@fifine/aim-studio 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +159 -0
- package/bin/aim.js +3 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +89 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/commands/init.d.ts +13 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +513 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/update.d.ts +27 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +1275 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/configurators/claude.d.ts +32 -0
- package/dist/configurators/claude.d.ts.map +1 -0
- package/dist/configurators/claude.js +98 -0
- package/dist/configurators/claude.js.map +1 -0
- package/dist/configurators/index.d.ts +51 -0
- package/dist/configurators/index.d.ts.map +1 -0
- package/dist/configurators/index.js +113 -0
- package/dist/configurators/index.js.map +1 -0
- package/dist/configurators/shared.d.ts +12 -0
- package/dist/configurators/shared.d.ts.map +1 -0
- package/dist/configurators/shared.js +21 -0
- package/dist/configurators/shared.js.map +1 -0
- package/dist/configurators/workflow.d.ts +28 -0
- package/dist/configurators/workflow.d.ts.map +1 -0
- package/dist/configurators/workflow.js +147 -0
- package/dist/configurators/workflow.js.map +1 -0
- package/dist/constants/paths.d.ts +68 -0
- package/dist/constants/paths.d.ts.map +1 -0
- package/dist/constants/paths.js +77 -0
- package/dist/constants/paths.js.map +1 -0
- package/dist/constants/version.d.ts +9 -0
- package/dist/constants/version.d.ts.map +1 -0
- package/dist/constants/version.js +15 -0
- package/dist/constants/version.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations/index.d.ts +54 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +160 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/migrations/manifests/0.0.1.json +9 -0
- package/dist/migrations/manifests/0.1.9.json +30 -0
- package/dist/migrations/manifests/0.2.0.json +49 -0
- package/dist/migrations/manifests/0.2.12.json +9 -0
- package/dist/migrations/manifests/0.2.13.json +9 -0
- package/dist/migrations/manifests/0.2.14.json +175 -0
- package/dist/migrations/manifests/0.2.15.json +33 -0
- package/dist/migrations/manifests/0.3.0-beta.0.json +278 -0
- package/dist/migrations/manifests/0.3.0-beta.1.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.10.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.11.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.12.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.13.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.14.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.15.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.16.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.2.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.3.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.4.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.5.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.6.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.7.json +11 -0
- package/dist/migrations/manifests/0.3.0-beta.8.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.9.json +9 -0
- package/dist/migrations/manifests/0.3.0-rc.0.json +9 -0
- package/dist/migrations/manifests/0.3.0-rc.1.json +9 -0
- package/dist/migrations/manifests/0.3.0-rc.2.json +9 -0
- package/dist/templates/CLAUDE.md +71 -0
- package/dist/templates/aim/gitignore.txt +29 -0
- package/dist/templates/aim/index.d.ts +49 -0
- package/dist/templates/aim/index.d.ts.map +1 -0
- package/dist/templates/aim/index.js +92 -0
- package/dist/templates/aim/index.js.map +1 -0
- package/dist/templates/aim/scripts/__init__.py +5 -0
- package/dist/templates/aim/scripts/add_session.py +392 -0
- package/dist/templates/aim/scripts/common/__init__.py +80 -0
- package/dist/templates/aim/scripts/common/cli_adapter.py +435 -0
- package/dist/templates/aim/scripts/common/developer.py +190 -0
- package/dist/templates/aim/scripts/common/git_context.py +383 -0
- package/dist/templates/aim/scripts/common/paths.py +347 -0
- package/dist/templates/aim/scripts/common/phase.py +253 -0
- package/dist/templates/aim/scripts/common/registry.py +366 -0
- package/dist/templates/aim/scripts/common/task_queue.py +255 -0
- package/dist/templates/aim/scripts/common/task_utils.py +178 -0
- package/dist/templates/aim/scripts/common/worktree.py +219 -0
- package/dist/templates/aim/scripts/create_bootstrap.py +290 -0
- package/dist/templates/aim/scripts/get_context.py +16 -0
- package/dist/templates/aim/scripts/get_developer.py +26 -0
- package/dist/templates/aim/scripts/init_developer.py +51 -0
- package/dist/templates/aim/scripts/multi_agent/__init__.py +5 -0
- package/dist/templates/aim/scripts/multi_agent/cleanup.py +403 -0
- package/dist/templates/aim/scripts/multi_agent/create_pr.py +329 -0
- package/dist/templates/aim/scripts/multi_agent/plan.py +233 -0
- package/dist/templates/aim/scripts/multi_agent/start.py +461 -0
- package/dist/templates/aim/scripts/multi_agent/status.py +817 -0
- package/dist/templates/aim/scripts/task.py +1068 -0
- package/dist/templates/aim/scripts-shell-archive/add-session.sh +384 -0
- package/dist/templates/aim/scripts-shell-archive/common/developer.sh +129 -0
- package/dist/templates/aim/scripts-shell-archive/common/git-context.sh +263 -0
- package/dist/templates/aim/scripts-shell-archive/common/paths.sh +208 -0
- package/dist/templates/aim/scripts-shell-archive/common/phase.sh +150 -0
- package/dist/templates/aim/scripts-shell-archive/common/registry.sh +247 -0
- package/dist/templates/aim/scripts-shell-archive/common/task-queue.sh +142 -0
- package/dist/templates/aim/scripts-shell-archive/common/task-utils.sh +151 -0
- package/dist/templates/aim/scripts-shell-archive/common/worktree.sh +128 -0
- package/dist/templates/aim/scripts-shell-archive/create-bootstrap.sh +299 -0
- package/dist/templates/aim/scripts-shell-archive/get-context.sh +7 -0
- package/dist/templates/aim/scripts-shell-archive/get-developer.sh +15 -0
- package/dist/templates/aim/scripts-shell-archive/init-developer.sh +34 -0
- package/dist/templates/aim/scripts-shell-archive/multi-agent/cleanup.sh +396 -0
- package/dist/templates/aim/scripts-shell-archive/multi-agent/create-pr.sh +241 -0
- package/dist/templates/aim/scripts-shell-archive/multi-agent/plan.sh +207 -0
- package/dist/templates/aim/scripts-shell-archive/multi-agent/start.sh +317 -0
- package/dist/templates/aim/scripts-shell-archive/multi-agent/status.sh +828 -0
- package/dist/templates/aim/scripts-shell-archive/task.sh +1204 -0
- package/dist/templates/aim/tasks/.gitkeep +0 -0
- package/dist/templates/aim/workflow.md +258 -0
- package/dist/templates/aim/worktree.yaml +47 -0
- package/dist/templates/claude/agents/check.md +122 -0
- package/dist/templates/claude/agents/debug.md +106 -0
- package/dist/templates/claude/agents/dispatch.md +230 -0
- package/dist/templates/claude/agents/implement.md +96 -0
- package/dist/templates/claude/agents/plan.md +396 -0
- package/dist/templates/claude/agents/research.md +120 -0
- package/dist/templates/claude/agents/story.md +53 -0
- package/dist/templates/claude/commands/aim/before-backend-dev.md +13 -0
- package/dist/templates/claude/commands/aim/before-frontend-dev.md +13 -0
- package/dist/templates/claude/commands/aim/break-loop.md +153 -0
- package/dist/templates/claude/commands/aim/check-backend.md +13 -0
- package/dist/templates/claude/commands/aim/check-cross-layer.md +153 -0
- package/dist/templates/claude/commands/aim/check-frontend.md +13 -0
- package/dist/templates/claude/commands/aim/check-story.md +59 -0
- package/dist/templates/claude/commands/aim/create-command.md +154 -0
- package/dist/templates/claude/commands/aim/export.md +187 -0
- package/dist/templates/claude/commands/aim/finish-work.md +104 -0
- package/dist/templates/claude/commands/aim/integrate-skill.md +219 -0
- package/dist/templates/claude/commands/aim/onboard.md +358 -0
- package/dist/templates/claude/commands/aim/parallel.md +217 -0
- package/dist/templates/claude/commands/aim/portrait.md +170 -0
- package/dist/templates/claude/commands/aim/record-session.md +92 -0
- package/dist/templates/claude/commands/aim/start.md +112 -0
- package/dist/templates/claude/commands/aim/story.md +140 -0
- package/dist/templates/claude/commands/aim/update-spec.md +285 -0
- package/dist/templates/claude/commands/aim/visualize.md +182 -0
- package/dist/templates/claude/commands/trellis/before-backend-dev.md +13 -0
- package/dist/templates/claude/commands/trellis/before-frontend-dev.md +13 -0
- package/dist/templates/claude/commands/trellis/break-loop.md +125 -0
- package/dist/templates/claude/commands/trellis/check-backend.md +13 -0
- package/dist/templates/claude/commands/trellis/check-cross-layer.md +153 -0
- package/dist/templates/claude/commands/trellis/check-frontend.md +13 -0
- package/dist/templates/claude/commands/trellis/create-command.md +154 -0
- package/dist/templates/claude/commands/trellis/finish-work.md +129 -0
- package/dist/templates/claude/commands/trellis/integrate-skill.md +219 -0
- package/dist/templates/claude/commands/trellis/onboard.md +358 -0
- package/dist/templates/claude/commands/trellis/parallel.md +193 -0
- package/dist/templates/claude/commands/trellis/record-session.md +62 -0
- package/dist/templates/claude/commands/trellis/start.md +280 -0
- package/dist/templates/claude/commands/trellis/update-spec.md +285 -0
- package/dist/templates/claude/hooks/inject-subagent-context.py +772 -0
- package/dist/templates/claude/hooks/ralph-loop.py +388 -0
- package/dist/templates/claude/hooks/session-start.py +142 -0
- package/dist/templates/claude/index.d.ts +54 -0
- package/dist/templates/claude/index.d.ts.map +1 -0
- package/dist/templates/claude/index.js +85 -0
- package/dist/templates/claude/index.js.map +1 -0
- package/dist/templates/claude/settings.json +41 -0
- package/dist/templates/extract.d.ts +68 -0
- package/dist/templates/extract.d.ts.map +1 -0
- package/dist/templates/extract.js +128 -0
- package/dist/templates/extract.js.map +1 -0
- package/dist/templates/markdown/agents.md +25 -0
- package/dist/templates/markdown/gitignore.txt +12 -0
- package/dist/templates/markdown/index.d.ts +32 -0
- package/dist/templates/markdown/index.d.ts.map +1 -0
- package/dist/templates/markdown/index.js +58 -0
- package/dist/templates/markdown/index.js.map +1 -0
- package/dist/templates/markdown/spec/backend/database-guidelines.md.txt +51 -0
- package/dist/templates/markdown/spec/backend/directory-structure.md.txt +54 -0
- package/dist/templates/markdown/spec/backend/error-handling.md.txt +51 -0
- package/dist/templates/markdown/spec/backend/index.md +40 -0
- package/dist/templates/markdown/spec/backend/index.md.txt +38 -0
- package/dist/templates/markdown/spec/backend/logging-guidelines.md.txt +51 -0
- package/dist/templates/markdown/spec/backend/quality-guidelines.md.txt +51 -0
- package/dist/templates/markdown/spec/backend/script-conventions.md +467 -0
- package/dist/templates/markdown/spec/frontend/component-guidelines.md.txt +59 -0
- package/dist/templates/markdown/spec/frontend/directory-structure.md.txt +54 -0
- package/dist/templates/markdown/spec/frontend/hook-guidelines.md.txt +51 -0
- package/dist/templates/markdown/spec/frontend/index.md.txt +39 -0
- package/dist/templates/markdown/spec/frontend/quality-guidelines.md.txt +51 -0
- package/dist/templates/markdown/spec/frontend/state-management.md.txt +51 -0
- package/dist/templates/markdown/spec/frontend/type-safety.md.txt +51 -0
- package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md +118 -0
- package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +92 -0
- package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +94 -0
- package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md +394 -0
- package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +319 -0
- package/dist/templates/markdown/spec/guides/index.md.txt +89 -0
- package/dist/templates/markdown/spec/story/character.md.txt +95 -0
- package/dist/templates/markdown/spec/story/index.md.txt +31 -0
- package/dist/templates/markdown/spec/story/script.md.txt +313 -0
- package/dist/templates/markdown/spec/story/world.md.txt +92 -0
- package/dist/templates/markdown/workspace-index.md +123 -0
- package/dist/templates/markdown/worktree.yaml.txt +58 -0
- package/dist/templates/trellis/gitignore.txt +29 -0
- package/dist/templates/trellis/index.d.ts +49 -0
- package/dist/templates/trellis/index.d.ts.map +1 -0
- package/dist/templates/trellis/index.js +92 -0
- package/dist/templates/trellis/index.js.map +1 -0
- package/dist/templates/trellis/scripts/__init__.py +5 -0
- package/dist/templates/trellis/scripts/add_session.py +392 -0
- package/dist/templates/trellis/scripts/common/__init__.py +80 -0
- package/dist/templates/trellis/scripts/common/cli_adapter.py +435 -0
- package/dist/templates/trellis/scripts/common/developer.py +190 -0
- package/dist/templates/trellis/scripts/common/git_context.py +383 -0
- package/dist/templates/trellis/scripts/common/paths.py +347 -0
- package/dist/templates/trellis/scripts/common/phase.py +253 -0
- package/dist/templates/trellis/scripts/common/registry.py +366 -0
- package/dist/templates/trellis/scripts/common/task_queue.py +255 -0
- package/dist/templates/trellis/scripts/common/task_utils.py +178 -0
- package/dist/templates/trellis/scripts/common/worktree.py +219 -0
- package/dist/templates/trellis/scripts/create_bootstrap.py +290 -0
- package/dist/templates/trellis/scripts/get_context.py +16 -0
- package/dist/templates/trellis/scripts/get_developer.py +26 -0
- package/dist/templates/trellis/scripts/init_developer.py +51 -0
- package/dist/templates/trellis/scripts/multi_agent/__init__.py +5 -0
- package/dist/templates/trellis/scripts/multi_agent/cleanup.py +403 -0
- package/dist/templates/trellis/scripts/multi_agent/create_pr.py +329 -0
- package/dist/templates/trellis/scripts/multi_agent/plan.py +233 -0
- package/dist/templates/trellis/scripts/multi_agent/start.py +461 -0
- package/dist/templates/trellis/scripts/multi_agent/status.py +817 -0
- package/dist/templates/trellis/scripts/task.py +1056 -0
- package/dist/templates/trellis/scripts-shell-archive/add-session.sh +384 -0
- package/dist/templates/trellis/scripts-shell-archive/common/developer.sh +129 -0
- package/dist/templates/trellis/scripts-shell-archive/common/git-context.sh +263 -0
- package/dist/templates/trellis/scripts-shell-archive/common/paths.sh +208 -0
- package/dist/templates/trellis/scripts-shell-archive/common/phase.sh +150 -0
- package/dist/templates/trellis/scripts-shell-archive/common/registry.sh +247 -0
- package/dist/templates/trellis/scripts-shell-archive/common/task-queue.sh +142 -0
- package/dist/templates/trellis/scripts-shell-archive/common/task-utils.sh +151 -0
- package/dist/templates/trellis/scripts-shell-archive/common/worktree.sh +128 -0
- package/dist/templates/trellis/scripts-shell-archive/create-bootstrap.sh +299 -0
- package/dist/templates/trellis/scripts-shell-archive/get-context.sh +7 -0
- package/dist/templates/trellis/scripts-shell-archive/get-developer.sh +15 -0
- package/dist/templates/trellis/scripts-shell-archive/init-developer.sh +34 -0
- package/dist/templates/trellis/scripts-shell-archive/multi-agent/cleanup.sh +396 -0
- package/dist/templates/trellis/scripts-shell-archive/multi-agent/create-pr.sh +241 -0
- package/dist/templates/trellis/scripts-shell-archive/multi-agent/plan.sh +207 -0
- package/dist/templates/trellis/scripts-shell-archive/multi-agent/start.sh +317 -0
- package/dist/templates/trellis/scripts-shell-archive/multi-agent/status.sh +828 -0
- package/dist/templates/trellis/scripts-shell-archive/task.sh +1204 -0
- package/dist/templates/trellis/tasks/.gitkeep +0 -0
- package/dist/templates/trellis/workflow.md +416 -0
- package/dist/templates/trellis/worktree.yaml +47 -0
- package/dist/types/ai-tools.d.ts +48 -0
- package/dist/types/ai-tools.d.ts.map +1 -0
- package/dist/types/ai-tools.js +32 -0
- package/dist/types/ai-tools.js.map +1 -0
- package/dist/types/migration.d.ts +86 -0
- package/dist/types/migration.d.ts.map +1 -0
- package/dist/types/migration.js +8 -0
- package/dist/types/migration.js.map +1 -0
- package/dist/utils/compare-versions.d.ts +12 -0
- package/dist/utils/compare-versions.d.ts.map +1 -0
- package/dist/utils/compare-versions.js +76 -0
- package/dist/utils/compare-versions.js.map +1 -0
- package/dist/utils/file-writer.d.ts +23 -0
- package/dist/utils/file-writer.d.ts.map +1 -0
- package/dist/utils/file-writer.js +140 -0
- package/dist/utils/file-writer.js.map +1 -0
- package/dist/utils/project-detector.d.ts +16 -0
- package/dist/utils/project-detector.d.ts.map +1 -0
- package/dist/utils/project-detector.js +188 -0
- package/dist/utils/project-detector.js.map +1 -0
- package/dist/utils/template-fetcher.d.ts +51 -0
- package/dist/utils/template-fetcher.d.ts.map +1 -0
- package/dist/utils/template-fetcher.js +174 -0
- package/dist/utils/template-fetcher.js.map +1 -0
- package/dist/utils/template-hash.d.ts +78 -0
- package/dist/utils/template-hash.d.ts.map +1 -0
- package/dist/utils/template-hash.js +239 -0
- package/dist/utils/template-hash.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI Adapter for Multi-Platform Support.
|
|
3
|
+
|
|
4
|
+
Abstracts differences between Claude Code, OpenCode, Cursor, iFlow, and Codex interfaces.
|
|
5
|
+
|
|
6
|
+
Supported platforms:
|
|
7
|
+
- claude: Claude Code (default)
|
|
8
|
+
- opencode: OpenCode
|
|
9
|
+
- cursor: Cursor IDE
|
|
10
|
+
- iflow: iFlow CLI
|
|
11
|
+
- codex: Codex CLI (skills-based)
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
from common.cli_adapter import CLIAdapter
|
|
15
|
+
|
|
16
|
+
adapter = CLIAdapter("opencode")
|
|
17
|
+
cmd = adapter.build_run_command(
|
|
18
|
+
agent="dispatch",
|
|
19
|
+
session_id="abc123",
|
|
20
|
+
prompt="Start the pipeline"
|
|
21
|
+
)
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
from dataclasses import dataclass
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
from typing import ClassVar, Literal
|
|
29
|
+
|
|
30
|
+
Platform = Literal["claude", "opencode", "cursor", "iflow", "codex"]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass
|
|
34
|
+
class CLIAdapter:
|
|
35
|
+
"""Adapter for different AI coding CLI tools."""
|
|
36
|
+
|
|
37
|
+
platform: Platform
|
|
38
|
+
|
|
39
|
+
# =========================================================================
|
|
40
|
+
# Agent Name Mapping
|
|
41
|
+
# =========================================================================
|
|
42
|
+
|
|
43
|
+
# OpenCode has built-in agents that cannot be overridden
|
|
44
|
+
# See: https://github.com/sst/opencode/issues/4271
|
|
45
|
+
# Note: Class-level constant, not a dataclass field
|
|
46
|
+
_AGENT_NAME_MAP: ClassVar[dict[Platform, dict[str, str]]] = {
|
|
47
|
+
"claude": {}, # No mapping needed
|
|
48
|
+
"opencode": {
|
|
49
|
+
"plan": "trellis-plan", # 'plan' is built-in in OpenCode
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
def get_agent_name(self, agent: str) -> str:
|
|
54
|
+
"""Get platform-specific agent name.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
agent: Original agent name (e.g., 'plan', 'dispatch')
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Platform-specific agent name (e.g., 'trellis-plan' for OpenCode)
|
|
61
|
+
"""
|
|
62
|
+
mapping = self._AGENT_NAME_MAP.get(self.platform, {})
|
|
63
|
+
return mapping.get(agent, agent)
|
|
64
|
+
|
|
65
|
+
# =========================================================================
|
|
66
|
+
# Agent Path
|
|
67
|
+
# =========================================================================
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def config_dir_name(self) -> str:
|
|
71
|
+
"""Get platform-specific config directory name.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Directory name ('.claude', '.opencode', '.cursor', '.iflow', or '.agents')
|
|
75
|
+
"""
|
|
76
|
+
if self.platform == "opencode":
|
|
77
|
+
return ".opencode"
|
|
78
|
+
elif self.platform == "cursor":
|
|
79
|
+
return ".cursor"
|
|
80
|
+
elif self.platform == "iflow":
|
|
81
|
+
return ".iflow"
|
|
82
|
+
elif self.platform == "codex":
|
|
83
|
+
return ".agents"
|
|
84
|
+
else:
|
|
85
|
+
return ".claude"
|
|
86
|
+
|
|
87
|
+
def get_config_dir(self, project_root: Path) -> Path:
|
|
88
|
+
"""Get platform-specific config directory.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
project_root: Project root directory
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Path to config directory (.claude, .opencode, .cursor, .iflow, or .agents)
|
|
95
|
+
"""
|
|
96
|
+
return project_root / self.config_dir_name
|
|
97
|
+
|
|
98
|
+
def get_agent_path(self, agent: str, project_root: Path) -> Path:
|
|
99
|
+
"""Get path to agent definition file.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
agent: Agent name (original, before mapping)
|
|
103
|
+
project_root: Project root directory
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
Path to agent .md file
|
|
107
|
+
"""
|
|
108
|
+
mapped_name = self.get_agent_name(agent)
|
|
109
|
+
return self.get_config_dir(project_root) / "agents" / f"{mapped_name}.md"
|
|
110
|
+
|
|
111
|
+
def get_commands_path(self, project_root: Path, *parts: str) -> Path:
|
|
112
|
+
"""Get path to commands directory or specific command file.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
project_root: Project root directory
|
|
116
|
+
*parts: Additional path parts (e.g., 'trellis', 'finish-work.md')
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
Path to commands directory or file
|
|
120
|
+
|
|
121
|
+
Note:
|
|
122
|
+
Cursor uses prefix naming: .cursor/commands/trellis-<name>.md
|
|
123
|
+
Claude/OpenCode use subdirectory: .claude/commands/trellis/<name>.md
|
|
124
|
+
"""
|
|
125
|
+
if not parts:
|
|
126
|
+
return self.get_config_dir(project_root) / "commands"
|
|
127
|
+
|
|
128
|
+
# Cursor uses prefix naming instead of subdirectory
|
|
129
|
+
if self.platform == "cursor" and len(parts) >= 2 and parts[0] == "trellis":
|
|
130
|
+
# Convert trellis/<name>.md to trellis-<name>.md
|
|
131
|
+
filename = parts[-1]
|
|
132
|
+
return self.get_config_dir(project_root) / "commands" / f"trellis-{filename}"
|
|
133
|
+
|
|
134
|
+
return self.get_config_dir(project_root) / "commands" / Path(*parts)
|
|
135
|
+
|
|
136
|
+
def get_trellis_command_path(self, name: str) -> str:
|
|
137
|
+
"""Get relative path to a trellis command file.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
name: Command name without extension (e.g., 'finish-work', 'check-backend')
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Relative path string for use in JSONL entries
|
|
144
|
+
|
|
145
|
+
Note:
|
|
146
|
+
Cursor: .cursor/commands/trellis-<name>.md
|
|
147
|
+
Codex: .agents/skills/<name>/SKILL.md
|
|
148
|
+
Others: .{platform}/commands/trellis/<name>.md
|
|
149
|
+
"""
|
|
150
|
+
if self.platform == "cursor":
|
|
151
|
+
return f".cursor/commands/trellis-{name}.md"
|
|
152
|
+
elif self.platform == "codex":
|
|
153
|
+
return f".agents/skills/{name}/SKILL.md"
|
|
154
|
+
else:
|
|
155
|
+
return f"{self.config_dir_name}/commands/trellis/{name}.md"
|
|
156
|
+
|
|
157
|
+
# =========================================================================
|
|
158
|
+
# Environment Variables
|
|
159
|
+
# =========================================================================
|
|
160
|
+
|
|
161
|
+
def get_non_interactive_env(self) -> dict[str, str]:
|
|
162
|
+
"""Get environment variables for non-interactive mode.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
Dict of environment variables to set
|
|
166
|
+
"""
|
|
167
|
+
if self.platform == "opencode":
|
|
168
|
+
return {"OPENCODE_NON_INTERACTIVE": "1"}
|
|
169
|
+
elif self.platform == "codex":
|
|
170
|
+
return {"CODEX_NON_INTERACTIVE": "1"}
|
|
171
|
+
else:
|
|
172
|
+
return {"CLAUDE_NON_INTERACTIVE": "1"}
|
|
173
|
+
|
|
174
|
+
# =========================================================================
|
|
175
|
+
# CLI Command Building
|
|
176
|
+
# =========================================================================
|
|
177
|
+
|
|
178
|
+
def build_run_command(
|
|
179
|
+
self,
|
|
180
|
+
agent: str,
|
|
181
|
+
prompt: str,
|
|
182
|
+
session_id: str | None = None,
|
|
183
|
+
skip_permissions: bool = True,
|
|
184
|
+
verbose: bool = True,
|
|
185
|
+
json_output: bool = True,
|
|
186
|
+
) -> list[str]:
|
|
187
|
+
"""Build CLI command for running an agent.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
agent: Agent name (will be mapped if needed)
|
|
191
|
+
prompt: Prompt to send to the agent
|
|
192
|
+
session_id: Optional session ID (Claude Code only for creation)
|
|
193
|
+
skip_permissions: Whether to skip permission prompts
|
|
194
|
+
verbose: Whether to enable verbose output
|
|
195
|
+
json_output: Whether to use JSON output format
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
List of command arguments
|
|
199
|
+
"""
|
|
200
|
+
mapped_agent = self.get_agent_name(agent)
|
|
201
|
+
|
|
202
|
+
if self.platform == "opencode":
|
|
203
|
+
cmd = ["opencode", "run"]
|
|
204
|
+
cmd.extend(["--agent", mapped_agent])
|
|
205
|
+
|
|
206
|
+
# Note: OpenCode 'run' mode is non-interactive by default
|
|
207
|
+
# No equivalent to Claude Code's --dangerously-skip-permissions
|
|
208
|
+
# See: https://github.com/anomalyco/opencode/issues/9070
|
|
209
|
+
|
|
210
|
+
if json_output:
|
|
211
|
+
cmd.extend(["--format", "json"])
|
|
212
|
+
|
|
213
|
+
if verbose:
|
|
214
|
+
cmd.extend(["--log-level", "DEBUG", "--print-logs"])
|
|
215
|
+
|
|
216
|
+
# Note: OpenCode doesn't support --session-id on creation
|
|
217
|
+
# Session ID must be extracted from logs after startup
|
|
218
|
+
|
|
219
|
+
cmd.append(prompt)
|
|
220
|
+
|
|
221
|
+
elif self.platform == "codex":
|
|
222
|
+
cmd = ["codex", "exec"]
|
|
223
|
+
cmd.append(prompt)
|
|
224
|
+
|
|
225
|
+
else: # claude
|
|
226
|
+
cmd = ["claude", "-p"]
|
|
227
|
+
cmd.extend(["--agent", mapped_agent])
|
|
228
|
+
|
|
229
|
+
if session_id:
|
|
230
|
+
cmd.extend(["--session-id", session_id])
|
|
231
|
+
|
|
232
|
+
if skip_permissions:
|
|
233
|
+
cmd.append("--dangerously-skip-permissions")
|
|
234
|
+
|
|
235
|
+
if json_output:
|
|
236
|
+
cmd.extend(["--output-format", "stream-json"])
|
|
237
|
+
|
|
238
|
+
if verbose:
|
|
239
|
+
cmd.append("--verbose")
|
|
240
|
+
|
|
241
|
+
cmd.append(prompt)
|
|
242
|
+
|
|
243
|
+
return cmd
|
|
244
|
+
|
|
245
|
+
def build_resume_command(self, session_id: str) -> list[str]:
|
|
246
|
+
"""Build CLI command for resuming a session.
|
|
247
|
+
|
|
248
|
+
Args:
|
|
249
|
+
session_id: Session ID to resume
|
|
250
|
+
|
|
251
|
+
Returns:
|
|
252
|
+
List of command arguments
|
|
253
|
+
"""
|
|
254
|
+
if self.platform == "opencode":
|
|
255
|
+
return ["opencode", "run", "--session", session_id]
|
|
256
|
+
elif self.platform == "codex":
|
|
257
|
+
return ["codex", "resume", session_id]
|
|
258
|
+
else:
|
|
259
|
+
return ["claude", "--resume", session_id]
|
|
260
|
+
|
|
261
|
+
def get_resume_command_str(self, session_id: str, cwd: str | None = None) -> str:
|
|
262
|
+
"""Get human-readable resume command string.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
session_id: Session ID to resume
|
|
266
|
+
cwd: Optional working directory to cd into
|
|
267
|
+
|
|
268
|
+
Returns:
|
|
269
|
+
Command string for display
|
|
270
|
+
"""
|
|
271
|
+
cmd = self.build_resume_command(session_id)
|
|
272
|
+
cmd_str = " ".join(cmd)
|
|
273
|
+
|
|
274
|
+
if cwd:
|
|
275
|
+
return f"cd {cwd} && {cmd_str}"
|
|
276
|
+
return cmd_str
|
|
277
|
+
|
|
278
|
+
# =========================================================================
|
|
279
|
+
# Platform Detection Helpers
|
|
280
|
+
# =========================================================================
|
|
281
|
+
|
|
282
|
+
@property
|
|
283
|
+
def is_opencode(self) -> bool:
|
|
284
|
+
"""Check if platform is OpenCode."""
|
|
285
|
+
return self.platform == "opencode"
|
|
286
|
+
|
|
287
|
+
@property
|
|
288
|
+
def is_claude(self) -> bool:
|
|
289
|
+
"""Check if platform is Claude Code."""
|
|
290
|
+
return self.platform == "claude"
|
|
291
|
+
|
|
292
|
+
@property
|
|
293
|
+
def is_cursor(self) -> bool:
|
|
294
|
+
"""Check if platform is Cursor."""
|
|
295
|
+
return self.platform == "cursor"
|
|
296
|
+
|
|
297
|
+
@property
|
|
298
|
+
def cli_name(self) -> str:
|
|
299
|
+
"""Get CLI executable name.
|
|
300
|
+
|
|
301
|
+
Note: Cursor doesn't have a CLI tool, returns None-like value.
|
|
302
|
+
"""
|
|
303
|
+
if self.is_opencode:
|
|
304
|
+
return "opencode"
|
|
305
|
+
elif self.is_cursor:
|
|
306
|
+
return "cursor" # Note: Cursor is IDE-only, no CLI
|
|
307
|
+
else:
|
|
308
|
+
return "claude"
|
|
309
|
+
|
|
310
|
+
@property
|
|
311
|
+
def supports_cli_agents(self) -> bool:
|
|
312
|
+
"""Check if platform supports running agents via CLI.
|
|
313
|
+
|
|
314
|
+
Claude Code and OpenCode support CLI agent execution.
|
|
315
|
+
Cursor is IDE-only and doesn't support CLI agents.
|
|
316
|
+
"""
|
|
317
|
+
return self.platform in ("claude", "opencode")
|
|
318
|
+
|
|
319
|
+
# =========================================================================
|
|
320
|
+
# Session ID Handling
|
|
321
|
+
# =========================================================================
|
|
322
|
+
|
|
323
|
+
@property
|
|
324
|
+
def supports_session_id_on_create(self) -> bool:
|
|
325
|
+
"""Check if platform supports specifying session ID on creation.
|
|
326
|
+
|
|
327
|
+
Claude Code: Yes (--session-id)
|
|
328
|
+
OpenCode: No (auto-generated, extract from logs)
|
|
329
|
+
"""
|
|
330
|
+
return self.platform == "claude"
|
|
331
|
+
|
|
332
|
+
def extract_session_id_from_log(self, log_content: str) -> str | None:
|
|
333
|
+
"""Extract session ID from log output (OpenCode only).
|
|
334
|
+
|
|
335
|
+
OpenCode generates session IDs in format: ses_xxx
|
|
336
|
+
|
|
337
|
+
Args:
|
|
338
|
+
log_content: Log file content
|
|
339
|
+
|
|
340
|
+
Returns:
|
|
341
|
+
Session ID if found, None otherwise
|
|
342
|
+
"""
|
|
343
|
+
import re
|
|
344
|
+
|
|
345
|
+
# OpenCode session ID pattern
|
|
346
|
+
match = re.search(r"ses_[a-zA-Z0-9]+", log_content)
|
|
347
|
+
if match:
|
|
348
|
+
return match.group(0)
|
|
349
|
+
return None
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
# =============================================================================
|
|
353
|
+
# Factory Function
|
|
354
|
+
# =============================================================================
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def get_cli_adapter(platform: str = "claude") -> CLIAdapter:
|
|
358
|
+
"""Get CLI adapter for the specified platform.
|
|
359
|
+
|
|
360
|
+
Args:
|
|
361
|
+
platform: Platform name ('claude', 'opencode', 'cursor', 'iflow', or 'codex')
|
|
362
|
+
|
|
363
|
+
Returns:
|
|
364
|
+
CLIAdapter instance
|
|
365
|
+
|
|
366
|
+
Raises:
|
|
367
|
+
ValueError: If platform is not supported
|
|
368
|
+
"""
|
|
369
|
+
if platform not in ("claude", "opencode", "cursor", "iflow", "codex"):
|
|
370
|
+
raise ValueError(f"Unsupported platform: {platform} (must be 'claude', 'opencode', 'cursor', 'iflow', or 'codex')")
|
|
371
|
+
|
|
372
|
+
return CLIAdapter(platform=platform) # type: ignore
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def detect_platform(project_root: Path) -> Platform:
|
|
376
|
+
"""Auto-detect platform based on existing config directories.
|
|
377
|
+
|
|
378
|
+
Detection order:
|
|
379
|
+
1. TRELLIS_PLATFORM environment variable (if set)
|
|
380
|
+
2. .opencode directory exists → opencode
|
|
381
|
+
3. .iflow directory exists → iflow
|
|
382
|
+
4. .cursor directory exists (without .claude) → cursor
|
|
383
|
+
5. .agents/skills exists and no other platform dirs → codex
|
|
384
|
+
6. Default → claude
|
|
385
|
+
|
|
386
|
+
Args:
|
|
387
|
+
project_root: Project root directory
|
|
388
|
+
|
|
389
|
+
Returns:
|
|
390
|
+
Detected platform ('claude', 'opencode', 'cursor', 'iflow', or 'codex')
|
|
391
|
+
"""
|
|
392
|
+
import os
|
|
393
|
+
|
|
394
|
+
# Check environment variable first
|
|
395
|
+
env_platform = os.environ.get("TRELLIS_PLATFORM", "").lower()
|
|
396
|
+
if env_platform in ("claude", "opencode", "cursor", "iflow", "codex"):
|
|
397
|
+
return env_platform # type: ignore
|
|
398
|
+
|
|
399
|
+
# Check for .opencode directory (OpenCode-specific)
|
|
400
|
+
# Note: .claude might exist in both platforms during migration
|
|
401
|
+
if (project_root / ".opencode").is_dir():
|
|
402
|
+
return "opencode"
|
|
403
|
+
|
|
404
|
+
# Check for .iflow directory (iFlow-specific)
|
|
405
|
+
# Note: .claude might exist in both platforms during migration
|
|
406
|
+
if (project_root / ".iflow").is_dir():
|
|
407
|
+
return "iflow"
|
|
408
|
+
|
|
409
|
+
# Check for .cursor directory (Cursor-specific)
|
|
410
|
+
# Only detect as cursor if .claude doesn't exist (to avoid confusion)
|
|
411
|
+
if (project_root / ".cursor").is_dir() and not (project_root / ".claude").is_dir():
|
|
412
|
+
return "cursor"
|
|
413
|
+
|
|
414
|
+
# Check for Codex skills directory only when no other platform config exists
|
|
415
|
+
other_platform_dirs = (".claude", ".cursor", ".iflow", ".opencode")
|
|
416
|
+
has_other_platform_config = any(
|
|
417
|
+
(project_root / directory).is_dir() for directory in other_platform_dirs
|
|
418
|
+
)
|
|
419
|
+
if (project_root / ".agents" / "skills").is_dir() and not has_other_platform_config:
|
|
420
|
+
return "codex"
|
|
421
|
+
|
|
422
|
+
return "claude"
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
def get_cli_adapter_auto(project_root: Path) -> CLIAdapter:
|
|
426
|
+
"""Get CLI adapter with auto-detected platform.
|
|
427
|
+
|
|
428
|
+
Args:
|
|
429
|
+
project_root: Project root directory
|
|
430
|
+
|
|
431
|
+
Returns:
|
|
432
|
+
CLIAdapter instance for detected platform
|
|
433
|
+
"""
|
|
434
|
+
platform = detect_platform(project_root)
|
|
435
|
+
return CLIAdapter(platform=platform)
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Developer management utilities.
|
|
4
|
+
|
|
5
|
+
Provides:
|
|
6
|
+
init_developer - Initialize developer
|
|
7
|
+
ensure_developer - Ensure developer is initialized (exit if not)
|
|
8
|
+
show_developer_info - Show developer information
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import sys
|
|
14
|
+
from datetime import datetime
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
from .paths import (
|
|
18
|
+
DIR_WORKFLOW,
|
|
19
|
+
DIR_WORKSPACE,
|
|
20
|
+
DIR_TASKS,
|
|
21
|
+
FILE_DEVELOPER,
|
|
22
|
+
FILE_JOURNAL_PREFIX,
|
|
23
|
+
get_repo_root,
|
|
24
|
+
get_developer,
|
|
25
|
+
check_developer,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# =============================================================================
|
|
30
|
+
# Developer Initialization
|
|
31
|
+
# =============================================================================
|
|
32
|
+
|
|
33
|
+
def init_developer(name: str, repo_root: Path | None = None) -> bool:
|
|
34
|
+
"""Initialize developer.
|
|
35
|
+
|
|
36
|
+
Creates:
|
|
37
|
+
- .trellis/.developer file with developer info
|
|
38
|
+
- .trellis/workspace/<name>/ directory structure
|
|
39
|
+
- Initial journal file and index.md
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
name: Developer name.
|
|
43
|
+
repo_root: Repository root path. Defaults to auto-detected.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
True on success, False on error.
|
|
47
|
+
"""
|
|
48
|
+
if not name:
|
|
49
|
+
print("Error: developer name is required", file=sys.stderr)
|
|
50
|
+
return False
|
|
51
|
+
|
|
52
|
+
if repo_root is None:
|
|
53
|
+
repo_root = get_repo_root()
|
|
54
|
+
|
|
55
|
+
dev_file = repo_root / DIR_WORKFLOW / FILE_DEVELOPER
|
|
56
|
+
workspace_dir = repo_root / DIR_WORKFLOW / DIR_WORKSPACE / name
|
|
57
|
+
|
|
58
|
+
# Create .developer file
|
|
59
|
+
initialized_at = datetime.now().isoformat()
|
|
60
|
+
try:
|
|
61
|
+
dev_file.write_text(
|
|
62
|
+
f"name={name}\ninitialized_at={initialized_at}\n",
|
|
63
|
+
encoding="utf-8"
|
|
64
|
+
)
|
|
65
|
+
except (OSError, IOError) as e:
|
|
66
|
+
print(f"Error: Failed to create .developer file: {e}", file=sys.stderr)
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
# Create workspace directory structure
|
|
70
|
+
try:
|
|
71
|
+
workspace_dir.mkdir(parents=True, exist_ok=True)
|
|
72
|
+
except (OSError, IOError) as e:
|
|
73
|
+
print(f"Error: Failed to create workspace directory: {e}", file=sys.stderr)
|
|
74
|
+
return False
|
|
75
|
+
|
|
76
|
+
# Create initial journal file
|
|
77
|
+
journal_file = workspace_dir / f"{FILE_JOURNAL_PREFIX}1.md"
|
|
78
|
+
if not journal_file.exists():
|
|
79
|
+
today = datetime.now().strftime("%Y-%m-%d")
|
|
80
|
+
journal_content = f"""# Journal - {name} (Part 1)
|
|
81
|
+
|
|
82
|
+
> AI development session journal
|
|
83
|
+
> Started: {today}
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
"""
|
|
88
|
+
try:
|
|
89
|
+
journal_file.write_text(journal_content, encoding="utf-8")
|
|
90
|
+
except (OSError, IOError) as e:
|
|
91
|
+
print(f"Error: Failed to create journal file: {e}", file=sys.stderr)
|
|
92
|
+
return False
|
|
93
|
+
|
|
94
|
+
# Create index.md with markers for auto-update
|
|
95
|
+
index_file = workspace_dir / "index.md"
|
|
96
|
+
if not index_file.exists():
|
|
97
|
+
index_content = f"""# Workspace Index - {name}
|
|
98
|
+
|
|
99
|
+
> Journal tracking for AI development sessions.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Current Status
|
|
104
|
+
|
|
105
|
+
<!-- @@@auto:current-status -->
|
|
106
|
+
- **Active File**: `journal-1.md`
|
|
107
|
+
- **Total Sessions**: 0
|
|
108
|
+
- **Last Active**: -
|
|
109
|
+
<!-- @@@/auto:current-status -->
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Active Documents
|
|
114
|
+
|
|
115
|
+
<!-- @@@auto:active-documents -->
|
|
116
|
+
| File | Lines | Status |
|
|
117
|
+
|------|-------|--------|
|
|
118
|
+
| `journal-1.md` | ~0 | Active |
|
|
119
|
+
<!-- @@@/auto:active-documents -->
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Session History
|
|
124
|
+
|
|
125
|
+
<!-- @@@auto:session-history -->
|
|
126
|
+
| # | Date | Title | Commits |
|
|
127
|
+
|---|------|-------|---------|
|
|
128
|
+
<!-- @@@/auto:session-history -->
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Notes
|
|
133
|
+
|
|
134
|
+
- Sessions are appended to journal files
|
|
135
|
+
- New journal file created when current exceeds 2000 lines
|
|
136
|
+
- Use `add_session.py` to record sessions
|
|
137
|
+
"""
|
|
138
|
+
try:
|
|
139
|
+
index_file.write_text(index_content, encoding="utf-8")
|
|
140
|
+
except (OSError, IOError) as e:
|
|
141
|
+
print(f"Error: Failed to create index.md: {e}", file=sys.stderr)
|
|
142
|
+
return False
|
|
143
|
+
|
|
144
|
+
print(f"Developer initialized: {name}")
|
|
145
|
+
print(f" .developer file: {dev_file}")
|
|
146
|
+
print(f" Workspace dir: {workspace_dir}")
|
|
147
|
+
|
|
148
|
+
return True
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def ensure_developer(repo_root: Path | None = None) -> None:
|
|
152
|
+
"""Ensure developer is initialized, exit if not.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
repo_root: Repository root path. Defaults to auto-detected.
|
|
156
|
+
"""
|
|
157
|
+
if repo_root is None:
|
|
158
|
+
repo_root = get_repo_root()
|
|
159
|
+
|
|
160
|
+
if not check_developer(repo_root):
|
|
161
|
+
print("Error: Developer not initialized.", file=sys.stderr)
|
|
162
|
+
print(f"Run: python3 ./{DIR_WORKFLOW}/scripts/init_developer.py <your-name>", file=sys.stderr)
|
|
163
|
+
sys.exit(1)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def show_developer_info(repo_root: Path | None = None) -> None:
|
|
167
|
+
"""Show developer information.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
repo_root: Repository root path. Defaults to auto-detected.
|
|
171
|
+
"""
|
|
172
|
+
if repo_root is None:
|
|
173
|
+
repo_root = get_repo_root()
|
|
174
|
+
|
|
175
|
+
developer = get_developer(repo_root)
|
|
176
|
+
|
|
177
|
+
if not developer:
|
|
178
|
+
print("Developer: (not initialized)")
|
|
179
|
+
else:
|
|
180
|
+
print(f"Developer: {developer}")
|
|
181
|
+
print(f"Workspace: {DIR_WORKFLOW}/{DIR_WORKSPACE}/{developer}/")
|
|
182
|
+
print(f"Tasks: {DIR_WORKFLOW}/{DIR_TASKS}/")
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
# =============================================================================
|
|
186
|
+
# Main Entry (for testing)
|
|
187
|
+
# =============================================================================
|
|
188
|
+
|
|
189
|
+
if __name__ == "__main__":
|
|
190
|
+
show_developer_info()
|