-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy path__init__.py
More file actions
93 lines (83 loc) · 4.03 KB
/
Copy path__init__.py
File metadata and controls
93 lines (83 loc) · 4.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
"""OpenSpec plugin — registers CLI-backed spec workflow tools and bundled skills."""
from __future__ import annotations
import logging
from pathlib import Path
try:
from . import schemas
from . import tools
except ImportError: # pragma: no cover - pytest may import the repo root as a top-level module
import schemas # type: ignore
import tools # type: ignore
logger = logging.getLogger(__name__)
_PLUGIN_DIR = Path(__file__).parent
_TOOLS = (
("openspec_list", schemas.OPENSPEC_LIST, tools.openspec_list, "📋"),
("openspec_show", schemas.OPENSPEC_SHOW, tools.openspec_show, "📖"),
("openspec_validate", schemas.OPENSPEC_VALIDATE, tools.openspec_validate, "✅"),
("openspec_status", schemas.OPENSPEC_STATUS, tools.openspec_status, "📊"),
("openspec_instructions", schemas.OPENSPEC_INSTRUCTIONS, tools.openspec_instructions, "🧭"),
)
_WRITE_TOOLS = (
("openspec_idea_create", schemas.OPENSPEC_IDEA_CREATE, tools.openspec_idea_create, "💡"),
("openspec_idea_enrich", schemas.OPENSPEC_IDEA_ENRICH, tools.openspec_idea_enrich, "🔎"),
("openspec_idea_promote", schemas.OPENSPEC_IDEA_PROMOTE, tools.openspec_idea_promote, "🚀"),
("openspec_task_list", schemas.OPENSPEC_TASK_LIST, tools.openspec_task_list, "☑️"),
("openspec_change_sequence_set", schemas.OPENSPEC_CHANGE_SEQUENCE_SET, tools.openspec_change_sequence_set, "🔢"),
("openspec_task_set_status", schemas.OPENSPEC_TASK_SET_STATUS, tools.openspec_task_set_status, "✅"),
("openspec_change_create", schemas.OPENSPEC_CHANGE_CREATE, tools.openspec_change_create, "📝"),
("openspec_change_promote", schemas.OPENSPEC_CHANGE_PROMOTE, tools.openspec_change_promote, "➡️"),
("openspec_change_archive", schemas.OPENSPEC_CHANGE_ARCHIVE, tools.openspec_change_archive, "📦"),
("openspec_change_unarchive", schemas.OPENSPEC_CHANGE_UNARCHIVE, tools.openspec_change_unarchive, "♻️"),
("openspec_spec_diff", schemas.OPENSPEC_SPEC_DIFF, tools.openspec_spec_diff, "🔍"),
("openspec_spec_create", schemas.OPENSPEC_SPEC_CREATE, tools.openspec_spec_create, "✏️"),
("openspec_spec_show", schemas.OPENSPEC_SPEC_SHOW, tools.openspec_spec_show, "📄"),
("openspec_spec_list", schemas.OPENSPEC_SPEC_LIST, tools.openspec_spec_list, "📋"),
)
def _check_openspec_available() -> bool:
return tools._openspec_bin() is not None
def register(ctx) -> None:
# openspec_context only reads the registry DB + files on disk, so it is
# available even when the openspec CLI binary is not installed. It is the
# entry point for resolving copyable 'os_' identifiers.
ctx.register_tool(
name="openspec_context",
toolset="openspec",
schema=schemas.OPENSPEC_CONTEXT,
handler=tools.openspec_context,
emoji="🔖",
)
for name, schema, handler, emoji in _TOOLS:
ctx.register_tool(
name=name,
toolset="openspec",
schema=schema,
handler=handler,
check_fn=_check_openspec_available,
emoji=emoji,
)
for name, schema, handler, emoji in _WRITE_TOOLS:
ctx.register_tool(
name=name,
toolset="openspec",
schema=schema,
handler=handler,
emoji=emoji,
)
# CLI passthrough tool — gated on openspec binary availability
ctx.register_tool(
name="openspec_cli",
toolset="openspec",
schema=schemas.OPENSPEC_CLI,
handler=tools.openspec_cli,
check_fn=_check_openspec_available,
emoji="🖥️",
)
# Register bundled upstream workflow skills (openspec-propose, openspec-apply-change, etc.)
skills_dir = _PLUGIN_DIR / "skills"
for child in sorted(skills_dir.iterdir()) if skills_dir.is_dir() else []:
skill_md = child / "SKILL.md"
if child.is_dir() and skill_md.exists():
try:
ctx.register_skill(child.name, skill_md)
except Exception:
logger.warning("Failed to register skill %s", child.name, exc_info=True)