opencode-repos 0.2.0 → 0.3.0
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/AGENTS.md +180 -0
- package/README.md +103 -3
- package/TODO.md +3 -0
- package/index.ts +1590 -158
- package/oh-my-opencode/.github/FUNDING.yml +15 -0
- package/oh-my-opencode/.github/ISSUE_TEMPLATE/bug_report.yml +129 -0
- package/oh-my-opencode/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/oh-my-opencode/.github/ISSUE_TEMPLATE/feature_request.yml +100 -0
- package/oh-my-opencode/.github/ISSUE_TEMPLATE/general.yml +83 -0
- package/oh-my-opencode/.github/assets/google.jpg +0 -0
- package/oh-my-opencode/.github/assets/hero.jpg +0 -0
- package/oh-my-opencode/.github/assets/indent.jpg +0 -0
- package/oh-my-opencode/.github/assets/microsoft.jpg +0 -0
- package/oh-my-opencode/.github/assets/omo.png +0 -0
- package/oh-my-opencode/.github/assets/orchestrator-atlas.png +0 -0
- package/oh-my-opencode/.github/assets/sisyphus.png +0 -0
- package/oh-my-opencode/.github/assets/sisyphuslabs.png +0 -0
- package/oh-my-opencode/.github/pull_request_template.md +34 -0
- package/oh-my-opencode/.github/workflows/ci.yml +138 -0
- package/oh-my-opencode/.github/workflows/cla.yml +41 -0
- package/oh-my-opencode/.github/workflows/lint-workflows.yml +22 -0
- package/oh-my-opencode/.github/workflows/publish.yml +165 -0
- package/oh-my-opencode/.github/workflows/sisyphus-agent.yml +500 -0
- package/oh-my-opencode/.opencode/background-tasks.json +27 -0
- package/oh-my-opencode/.opencode/command/get-unpublished-changes.md +84 -0
- package/oh-my-opencode/.opencode/command/omomomo.md +37 -0
- package/oh-my-opencode/.opencode/command/publish.md +257 -0
- package/oh-my-opencode/AGENTS.md +179 -0
- package/oh-my-opencode/CLA.md +58 -0
- package/oh-my-opencode/CONTRIBUTING.md +268 -0
- package/oh-my-opencode/LICENSE.md +82 -0
- package/oh-my-opencode/README.ja.md +370 -0
- package/oh-my-opencode/README.md +376 -0
- package/oh-my-opencode/README.zh-cn.md +380 -0
- package/oh-my-opencode/assets/oh-my-opencode.schema.json +2171 -0
- package/oh-my-opencode/bin/oh-my-opencode.js +80 -0
- package/oh-my-opencode/bin/platform.js +38 -0
- package/oh-my-opencode/bin/platform.test.ts +148 -0
- package/oh-my-opencode/bun.lock +314 -0
- package/oh-my-opencode/bunfig.toml +2 -0
- package/oh-my-opencode/docs/category-skill-guide.md +200 -0
- package/oh-my-opencode/docs/cli-guide.md +272 -0
- package/oh-my-opencode/docs/configurations.md +654 -0
- package/oh-my-opencode/docs/features.md +550 -0
- package/oh-my-opencode/docs/guide/installation.md +288 -0
- package/oh-my-opencode/docs/guide/overview.md +97 -0
- package/oh-my-opencode/docs/guide/understanding-orchestration-system.md +445 -0
- package/oh-my-opencode/docs/orchestration-guide.md +152 -0
- package/oh-my-opencode/docs/ultrawork-manifesto.md +197 -0
- package/oh-my-opencode/package.json +89 -0
- package/oh-my-opencode/packages/darwin-arm64/bin/.gitkeep +0 -0
- package/oh-my-opencode/packages/darwin-arm64/package.json +22 -0
- package/oh-my-opencode/packages/darwin-x64/bin/.gitkeep +0 -0
- package/oh-my-opencode/packages/darwin-x64/package.json +22 -0
- package/oh-my-opencode/packages/linux-arm64/bin/.gitkeep +0 -0
- package/oh-my-opencode/packages/linux-arm64/package.json +25 -0
- package/oh-my-opencode/packages/linux-arm64-musl/bin/.gitkeep +0 -0
- package/oh-my-opencode/packages/linux-arm64-musl/package.json +25 -0
- package/oh-my-opencode/packages/linux-x64/bin/.gitkeep +0 -0
- package/oh-my-opencode/packages/linux-x64/package.json +25 -0
- package/oh-my-opencode/packages/linux-x64-musl/bin/.gitkeep +0 -0
- package/oh-my-opencode/packages/linux-x64-musl/package.json +25 -0
- package/oh-my-opencode/packages/windows-x64/bin/.gitkeep +0 -0
- package/oh-my-opencode/packages/windows-x64/package.json +22 -0
- package/oh-my-opencode/postinstall.mjs +43 -0
- package/oh-my-opencode/script/build-binaries.ts +103 -0
- package/oh-my-opencode/script/build-schema.ts +28 -0
- package/oh-my-opencode/script/generate-changelog.ts +92 -0
- package/oh-my-opencode/script/publish.ts +344 -0
- package/oh-my-opencode/signatures/cla.json +676 -0
- package/oh-my-opencode/src/agents/AGENTS.md +67 -0
- package/oh-my-opencode/src/agents/atlas.ts +1383 -0
- package/oh-my-opencode/src/agents/dynamic-agent-prompt-builder.ts +400 -0
- package/oh-my-opencode/src/agents/explore.ts +122 -0
- package/oh-my-opencode/src/agents/index.ts +13 -0
- package/oh-my-opencode/src/agents/librarian.ts +326 -0
- package/oh-my-opencode/src/agents/metis.ts +315 -0
- package/oh-my-opencode/src/agents/momus.test.ts +57 -0
- package/oh-my-opencode/src/agents/momus.ts +444 -0
- package/oh-my-opencode/src/agents/multimodal-looker.ts +56 -0
- package/oh-my-opencode/src/agents/oracle.ts +122 -0
- package/oh-my-opencode/src/agents/prometheus-prompt.test.ts +22 -0
- package/oh-my-opencode/src/agents/prometheus-prompt.ts +1196 -0
- package/oh-my-opencode/src/agents/sisyphus-junior.test.ts +232 -0
- package/oh-my-opencode/src/agents/sisyphus-junior.ts +134 -0
- package/oh-my-opencode/src/agents/sisyphus.ts +633 -0
- package/oh-my-opencode/src/agents/types.ts +80 -0
- package/oh-my-opencode/src/agents/utils.test.ts +311 -0
- package/oh-my-opencode/src/agents/utils.ts +240 -0
- package/oh-my-opencode/src/cli/AGENTS.md +91 -0
- package/oh-my-opencode/src/cli/config-manager.test.ts +364 -0
- package/oh-my-opencode/src/cli/config-manager.ts +641 -0
- package/oh-my-opencode/src/cli/doctor/checks/auth.test.ts +114 -0
- package/oh-my-opencode/src/cli/doctor/checks/auth.ts +115 -0
- package/oh-my-opencode/src/cli/doctor/checks/config.test.ts +103 -0
- package/oh-my-opencode/src/cli/doctor/checks/config.ts +123 -0
- package/oh-my-opencode/src/cli/doctor/checks/dependencies.test.ts +152 -0
- package/oh-my-opencode/src/cli/doctor/checks/dependencies.ts +163 -0
- package/oh-my-opencode/src/cli/doctor/checks/gh.test.ts +151 -0
- package/oh-my-opencode/src/cli/doctor/checks/gh.ts +171 -0
- package/oh-my-opencode/src/cli/doctor/checks/index.ts +34 -0
- package/oh-my-opencode/src/cli/doctor/checks/lsp.test.ts +134 -0
- package/oh-my-opencode/src/cli/doctor/checks/lsp.ts +77 -0
- package/oh-my-opencode/src/cli/doctor/checks/mcp.test.ts +115 -0
- package/oh-my-opencode/src/cli/doctor/checks/mcp.ts +128 -0
- package/oh-my-opencode/src/cli/doctor/checks/opencode.test.ts +227 -0
- package/oh-my-opencode/src/cli/doctor/checks/opencode.ts +178 -0
- package/oh-my-opencode/src/cli/doctor/checks/plugin.test.ts +109 -0
- package/oh-my-opencode/src/cli/doctor/checks/plugin.ts +124 -0
- package/oh-my-opencode/src/cli/doctor/checks/version.test.ts +148 -0
- package/oh-my-opencode/src/cli/doctor/checks/version.ts +135 -0
- package/oh-my-opencode/src/cli/doctor/constants.ts +72 -0
- package/oh-my-opencode/src/cli/doctor/formatter.test.ts +218 -0
- package/oh-my-opencode/src/cli/doctor/formatter.ts +140 -0
- package/oh-my-opencode/src/cli/doctor/index.ts +11 -0
- package/oh-my-opencode/src/cli/doctor/runner.test.ts +153 -0
- package/oh-my-opencode/src/cli/doctor/runner.ts +132 -0
- package/oh-my-opencode/src/cli/doctor/types.ts +113 -0
- package/oh-my-opencode/src/cli/get-local-version/formatter.ts +66 -0
- package/oh-my-opencode/src/cli/get-local-version/index.ts +106 -0
- package/oh-my-opencode/src/cli/get-local-version/types.ts +14 -0
- package/oh-my-opencode/src/cli/index.ts +153 -0
- package/oh-my-opencode/src/cli/install.ts +523 -0
- package/oh-my-opencode/src/cli/model-fallback.ts +246 -0
- package/oh-my-opencode/src/cli/run/completion.test.ts +170 -0
- package/oh-my-opencode/src/cli/run/completion.ts +79 -0
- package/oh-my-opencode/src/cli/run/events.test.ts +155 -0
- package/oh-my-opencode/src/cli/run/events.ts +325 -0
- package/oh-my-opencode/src/cli/run/index.ts +2 -0
- package/oh-my-opencode/src/cli/run/runner.ts +159 -0
- package/oh-my-opencode/src/cli/run/types.ts +76 -0
- package/oh-my-opencode/src/cli/types.ts +40 -0
- package/oh-my-opencode/src/config/index.ts +26 -0
- package/oh-my-opencode/src/config/schema.test.ts +444 -0
- package/oh-my-opencode/src/config/schema.ts +339 -0
- package/oh-my-opencode/src/features/AGENTS.md +77 -0
- package/oh-my-opencode/src/features/background-agent/concurrency.test.ts +418 -0
- package/oh-my-opencode/src/features/background-agent/concurrency.ts +137 -0
- package/oh-my-opencode/src/features/background-agent/index.ts +3 -0
- package/oh-my-opencode/src/features/background-agent/manager.test.ts +1928 -0
- package/oh-my-opencode/src/features/background-agent/manager.ts +1335 -0
- package/oh-my-opencode/src/features/background-agent/types.ts +66 -0
- package/oh-my-opencode/src/features/boulder-state/constants.ts +13 -0
- package/oh-my-opencode/src/features/boulder-state/index.ts +3 -0
- package/oh-my-opencode/src/features/boulder-state/storage.test.ts +250 -0
- package/oh-my-opencode/src/features/boulder-state/storage.ts +150 -0
- package/oh-my-opencode/src/features/boulder-state/types.ts +26 -0
- package/oh-my-opencode/src/features/builtin-commands/commands.ts +89 -0
- package/oh-my-opencode/src/features/builtin-commands/index.ts +2 -0
- package/oh-my-opencode/src/features/builtin-commands/templates/init-deep.ts +300 -0
- package/oh-my-opencode/src/features/builtin-commands/templates/ralph-loop.ts +38 -0
- package/oh-my-opencode/src/features/builtin-commands/templates/refactor.ts +619 -0
- package/oh-my-opencode/src/features/builtin-commands/templates/start-work.ts +72 -0
- package/oh-my-opencode/src/features/builtin-commands/types.ts +9 -0
- package/oh-my-opencode/src/features/builtin-skills/frontend-ui-ux/SKILL.md +78 -0
- package/oh-my-opencode/src/features/builtin-skills/git-master/SKILL.md +1105 -0
- package/oh-my-opencode/src/features/builtin-skills/index.ts +2 -0
- package/oh-my-opencode/src/features/builtin-skills/skills.ts +1203 -0
- package/oh-my-opencode/src/features/builtin-skills/types.ts +16 -0
- package/oh-my-opencode/src/features/claude-code-agent-loader/index.ts +2 -0
- package/oh-my-opencode/src/features/claude-code-agent-loader/loader.ts +90 -0
- package/oh-my-opencode/src/features/claude-code-agent-loader/types.ts +17 -0
- package/oh-my-opencode/src/features/claude-code-command-loader/index.ts +2 -0
- package/oh-my-opencode/src/features/claude-code-command-loader/loader.ts +144 -0
- package/oh-my-opencode/src/features/claude-code-command-loader/types.ts +46 -0
- package/oh-my-opencode/src/features/claude-code-mcp-loader/env-expander.ts +27 -0
- package/oh-my-opencode/src/features/claude-code-mcp-loader/index.ts +11 -0
- package/oh-my-opencode/src/features/claude-code-mcp-loader/loader.test.ts +162 -0
- package/oh-my-opencode/src/features/claude-code-mcp-loader/loader.ts +113 -0
- package/oh-my-opencode/src/features/claude-code-mcp-loader/transformer.ts +53 -0
- package/oh-my-opencode/src/features/claude-code-mcp-loader/types.ts +42 -0
- package/oh-my-opencode/src/features/claude-code-plugin-loader/index.ts +3 -0
- package/oh-my-opencode/src/features/claude-code-plugin-loader/loader.ts +486 -0
- package/oh-my-opencode/src/features/claude-code-plugin-loader/types.ts +210 -0
- package/oh-my-opencode/src/features/claude-code-session-state/index.ts +1 -0
- package/oh-my-opencode/src/features/claude-code-session-state/state.test.ts +126 -0
- package/oh-my-opencode/src/features/claude-code-session-state/state.ts +37 -0
- package/oh-my-opencode/src/features/context-injector/collector.test.ts +330 -0
- package/oh-my-opencode/src/features/context-injector/collector.ts +85 -0
- package/oh-my-opencode/src/features/context-injector/index.ts +14 -0
- package/oh-my-opencode/src/features/context-injector/injector.test.ts +122 -0
- package/oh-my-opencode/src/features/context-injector/injector.ts +167 -0
- package/oh-my-opencode/src/features/context-injector/types.ts +91 -0
- package/oh-my-opencode/src/features/hook-message-injector/constants.ts +6 -0
- package/oh-my-opencode/src/features/hook-message-injector/index.ts +4 -0
- package/oh-my-opencode/src/features/hook-message-injector/injector.ts +195 -0
- package/oh-my-opencode/src/features/hook-message-injector/types.ts +47 -0
- package/oh-my-opencode/src/features/opencode-skill-loader/async-loader.test.ts +448 -0
- package/oh-my-opencode/src/features/opencode-skill-loader/async-loader.ts +180 -0
- package/oh-my-opencode/src/features/opencode-skill-loader/blocking.test.ts +210 -0
- package/oh-my-opencode/src/features/opencode-skill-loader/blocking.ts +62 -0
- package/oh-my-opencode/src/features/opencode-skill-loader/discover-worker.ts +59 -0
- package/oh-my-opencode/src/features/opencode-skill-loader/index.ts +4 -0
- package/oh-my-opencode/src/features/opencode-skill-loader/loader.test.ts +273 -0
- package/oh-my-opencode/src/features/opencode-skill-loader/loader.ts +259 -0
- package/oh-my-opencode/src/features/opencode-skill-loader/merger.ts +267 -0
- package/oh-my-opencode/src/features/opencode-skill-loader/skill-content.test.ts +267 -0
- package/oh-my-opencode/src/features/opencode-skill-loader/skill-content.ts +206 -0
- package/oh-my-opencode/src/features/opencode-skill-loader/types.ts +38 -0
- package/oh-my-opencode/src/features/skill-mcp-manager/env-cleaner.test.ts +201 -0
- package/oh-my-opencode/src/features/skill-mcp-manager/env-cleaner.ts +27 -0
- package/oh-my-opencode/src/features/skill-mcp-manager/index.ts +2 -0
- package/oh-my-opencode/src/features/skill-mcp-manager/manager.test.ts +611 -0
- package/oh-my-opencode/src/features/skill-mcp-manager/manager.ts +520 -0
- package/oh-my-opencode/src/features/skill-mcp-manager/types.ts +14 -0
- package/oh-my-opencode/src/features/task-toast-manager/index.ts +2 -0
- package/oh-my-opencode/src/features/task-toast-manager/manager.test.ts +249 -0
- package/oh-my-opencode/src/features/task-toast-manager/manager.ts +215 -0
- package/oh-my-opencode/src/features/task-toast-manager/types.ts +24 -0
- package/oh-my-opencode/src/hooks/AGENTS.md +73 -0
- package/oh-my-opencode/src/hooks/agent-usage-reminder/constants.ts +54 -0
- package/oh-my-opencode/src/hooks/agent-usage-reminder/index.ts +109 -0
- package/oh-my-opencode/src/hooks/agent-usage-reminder/storage.ts +42 -0
- package/oh-my-opencode/src/hooks/agent-usage-reminder/types.ts +6 -0
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/executor.test.ts +307 -0
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/executor.ts +485 -0
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/index.ts +151 -0
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/parser.ts +201 -0
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/pruning-deduplication.test.ts +33 -0
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/pruning-deduplication.ts +184 -0
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/pruning-types.ts +44 -0
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/storage.test.ts +77 -0
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/storage.ts +250 -0
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/types.ts +42 -0
- package/oh-my-opencode/src/hooks/atlas/index.test.ts +953 -0
- package/oh-my-opencode/src/hooks/atlas/index.ts +771 -0
- package/oh-my-opencode/src/hooks/auto-slash-command/constants.ts +12 -0
- package/oh-my-opencode/src/hooks/auto-slash-command/detector.test.ts +296 -0
- package/oh-my-opencode/src/hooks/auto-slash-command/detector.ts +65 -0
- package/oh-my-opencode/src/hooks/auto-slash-command/executor.ts +205 -0
- package/oh-my-opencode/src/hooks/auto-slash-command/index.test.ts +254 -0
- package/oh-my-opencode/src/hooks/auto-slash-command/index.ts +89 -0
- package/oh-my-opencode/src/hooks/auto-slash-command/types.ts +23 -0
- package/oh-my-opencode/src/hooks/auto-update-checker/cache.ts +93 -0
- package/oh-my-opencode/src/hooks/auto-update-checker/checker.test.ts +24 -0
- package/oh-my-opencode/src/hooks/auto-update-checker/checker.ts +284 -0
- package/oh-my-opencode/src/hooks/auto-update-checker/constants.ts +64 -0
- package/oh-my-opencode/src/hooks/auto-update-checker/index.test.ts +254 -0
- package/oh-my-opencode/src/hooks/auto-update-checker/index.ts +260 -0
- package/oh-my-opencode/src/hooks/auto-update-checker/types.ts +29 -0
- package/oh-my-opencode/src/hooks/background-compaction/index.ts +87 -0
- package/oh-my-opencode/src/hooks/background-notification/index.ts +28 -0
- package/oh-my-opencode/src/hooks/background-notification/types.ts +5 -0
- package/oh-my-opencode/src/hooks/claude-code-hooks/AGENTS.md +70 -0
- package/oh-my-opencode/src/hooks/claude-code-hooks/config-loader.ts +107 -0
- package/oh-my-opencode/src/hooks/claude-code-hooks/config.ts +103 -0
- package/oh-my-opencode/src/hooks/claude-code-hooks/index.ts +401 -0
- package/oh-my-opencode/src/hooks/claude-code-hooks/plugin-config.ts +12 -0
- package/oh-my-opencode/src/hooks/claude-code-hooks/post-tool-use.ts +199 -0
- package/oh-my-opencode/src/hooks/claude-code-hooks/pre-compact.ts +109 -0
- package/oh-my-opencode/src/hooks/claude-code-hooks/pre-tool-use.ts +172 -0
- package/oh-my-opencode/src/hooks/claude-code-hooks/stop.ts +118 -0
- package/oh-my-opencode/src/hooks/claude-code-hooks/todo.ts +76 -0
- package/oh-my-opencode/src/hooks/claude-code-hooks/tool-input-cache.ts +47 -0
- package/oh-my-opencode/src/hooks/claude-code-hooks/transcript.ts +252 -0
- package/oh-my-opencode/src/hooks/claude-code-hooks/types.ts +204 -0
- package/oh-my-opencode/src/hooks/claude-code-hooks/user-prompt-submit.ts +117 -0
- package/oh-my-opencode/src/hooks/comment-checker/cli.test.ts +68 -0
- package/oh-my-opencode/src/hooks/comment-checker/cli.ts +221 -0
- package/oh-my-opencode/src/hooks/comment-checker/downloader.ts +196 -0
- package/oh-my-opencode/src/hooks/comment-checker/index.ts +171 -0
- package/oh-my-opencode/src/hooks/comment-checker/types.ts +33 -0
- package/oh-my-opencode/src/hooks/compaction-context-injector/index.ts +61 -0
- package/oh-my-opencode/src/hooks/context-window-monitor.ts +99 -0
- package/oh-my-opencode/src/hooks/delegate-task-retry/index.test.ts +119 -0
- package/oh-my-opencode/src/hooks/delegate-task-retry/index.ts +136 -0
- package/oh-my-opencode/src/hooks/directory-agents-injector/constants.ts +9 -0
- package/oh-my-opencode/src/hooks/directory-agents-injector/index.ts +182 -0
- package/oh-my-opencode/src/hooks/directory-agents-injector/storage.ts +48 -0
- package/oh-my-opencode/src/hooks/directory-agents-injector/types.ts +5 -0
- package/oh-my-opencode/src/hooks/directory-readme-injector/constants.ts +9 -0
- package/oh-my-opencode/src/hooks/directory-readme-injector/index.ts +177 -0
- package/oh-my-opencode/src/hooks/directory-readme-injector/storage.ts +48 -0
- package/oh-my-opencode/src/hooks/directory-readme-injector/types.ts +5 -0
- package/oh-my-opencode/src/hooks/edit-error-recovery/index.test.ts +126 -0
- package/oh-my-opencode/src/hooks/edit-error-recovery/index.ts +57 -0
- package/oh-my-opencode/src/hooks/empty-task-response-detector.ts +27 -0
- package/oh-my-opencode/src/hooks/index.ts +32 -0
- package/oh-my-opencode/src/hooks/interactive-bash-session/constants.ts +15 -0
- package/oh-my-opencode/src/hooks/interactive-bash-session/index.ts +262 -0
- package/oh-my-opencode/src/hooks/interactive-bash-session/storage.ts +59 -0
- package/oh-my-opencode/src/hooks/interactive-bash-session/types.ts +11 -0
- package/oh-my-opencode/src/hooks/keyword-detector/constants.ts +300 -0
- package/oh-my-opencode/src/hooks/keyword-detector/detector.ts +52 -0
- package/oh-my-opencode/src/hooks/keyword-detector/index.test.ts +529 -0
- package/oh-my-opencode/src/hooks/keyword-detector/index.ts +100 -0
- package/oh-my-opencode/src/hooks/keyword-detector/types.ts +4 -0
- package/oh-my-opencode/src/hooks/non-interactive-env/constants.ts +70 -0
- package/oh-my-opencode/src/hooks/non-interactive-env/detector.ts +19 -0
- package/oh-my-opencode/src/hooks/non-interactive-env/index.test.ts +323 -0
- package/oh-my-opencode/src/hooks/non-interactive-env/index.ts +63 -0
- package/oh-my-opencode/src/hooks/non-interactive-env/types.ts +3 -0
- package/oh-my-opencode/src/hooks/prometheus-md-only/constants.ts +32 -0
- package/oh-my-opencode/src/hooks/prometheus-md-only/index.test.ts +488 -0
- package/oh-my-opencode/src/hooks/prometheus-md-only/index.ts +136 -0
- package/oh-my-opencode/src/hooks/ralph-loop/constants.ts +5 -0
- package/oh-my-opencode/src/hooks/ralph-loop/index.test.ts +835 -0
- package/oh-my-opencode/src/hooks/ralph-loop/index.ts +417 -0
- package/oh-my-opencode/src/hooks/ralph-loop/storage.ts +115 -0
- package/oh-my-opencode/src/hooks/ralph-loop/types.ts +19 -0
- package/oh-my-opencode/src/hooks/rules-injector/constants.ts +30 -0
- package/oh-my-opencode/src/hooks/rules-injector/finder.test.ts +381 -0
- package/oh-my-opencode/src/hooks/rules-injector/finder.ts +263 -0
- package/oh-my-opencode/src/hooks/rules-injector/index.ts +223 -0
- package/oh-my-opencode/src/hooks/rules-injector/matcher.ts +63 -0
- package/oh-my-opencode/src/hooks/rules-injector/parser.test.ts +226 -0
- package/oh-my-opencode/src/hooks/rules-injector/parser.ts +211 -0
- package/oh-my-opencode/src/hooks/rules-injector/storage.ts +59 -0
- package/oh-my-opencode/src/hooks/rules-injector/types.ts +57 -0
- package/oh-my-opencode/src/hooks/session-notification-utils.ts +140 -0
- package/oh-my-opencode/src/hooks/session-notification.test.ts +361 -0
- package/oh-my-opencode/src/hooks/session-notification.ts +330 -0
- package/oh-my-opencode/src/hooks/session-recovery/constants.ts +10 -0
- package/oh-my-opencode/src/hooks/session-recovery/index.test.ts +223 -0
- package/oh-my-opencode/src/hooks/session-recovery/index.ts +435 -0
- package/oh-my-opencode/src/hooks/session-recovery/storage.ts +390 -0
- package/oh-my-opencode/src/hooks/session-recovery/types.ts +98 -0
- package/oh-my-opencode/src/hooks/start-work/index.test.ts +402 -0
- package/oh-my-opencode/src/hooks/start-work/index.ts +242 -0
- package/oh-my-opencode/src/hooks/task-resume-info/index.ts +36 -0
- package/oh-my-opencode/src/hooks/think-mode/detector.ts +57 -0
- package/oh-my-opencode/src/hooks/think-mode/index.test.ts +353 -0
- package/oh-my-opencode/src/hooks/think-mode/index.ts +89 -0
- package/oh-my-opencode/src/hooks/think-mode/switcher.test.ts +461 -0
- package/oh-my-opencode/src/hooks/think-mode/switcher.ts +222 -0
- package/oh-my-opencode/src/hooks/think-mode/types.ts +21 -0
- package/oh-my-opencode/src/hooks/thinking-block-validator/index.ts +171 -0
- package/oh-my-opencode/src/hooks/todo-continuation-enforcer.test.ts +876 -0
- package/oh-my-opencode/src/hooks/todo-continuation-enforcer.ts +480 -0
- package/oh-my-opencode/src/hooks/tool-output-truncator.test.ts +168 -0
- package/oh-my-opencode/src/hooks/tool-output-truncator.ts +61 -0
- package/oh-my-opencode/src/index.ts +589 -0
- package/oh-my-opencode/src/mcp/AGENTS.md +70 -0
- package/oh-my-opencode/src/mcp/context7.ts +6 -0
- package/oh-my-opencode/src/mcp/grep-app.ts +6 -0
- package/oh-my-opencode/src/mcp/index.test.ts +86 -0
- package/oh-my-opencode/src/mcp/index.ts +32 -0
- package/oh-my-opencode/src/mcp/types.ts +9 -0
- package/oh-my-opencode/src/mcp/websearch.ts +10 -0
- package/oh-my-opencode/src/plugin-config.test.ts +119 -0
- package/oh-my-opencode/src/plugin-config.ts +135 -0
- package/oh-my-opencode/src/plugin-handlers/config-handler.test.ts +103 -0
- package/oh-my-opencode/src/plugin-handlers/config-handler.ts +399 -0
- package/oh-my-opencode/src/plugin-handlers/index.ts +1 -0
- package/oh-my-opencode/src/plugin-state.ts +30 -0
- package/oh-my-opencode/src/shared/AGENTS.md +63 -0
- package/oh-my-opencode/src/shared/agent-tool-restrictions.ts +44 -0
- package/oh-my-opencode/src/shared/agent-variant.test.ts +83 -0
- package/oh-my-opencode/src/shared/agent-variant.ts +40 -0
- package/oh-my-opencode/src/shared/claude-config-dir.test.ts +60 -0
- package/oh-my-opencode/src/shared/claude-config-dir.ts +11 -0
- package/oh-my-opencode/src/shared/command-executor.ts +225 -0
- package/oh-my-opencode/src/shared/config-errors.ts +18 -0
- package/oh-my-opencode/src/shared/config-path.ts +47 -0
- package/oh-my-opencode/src/shared/data-path.ts +22 -0
- package/oh-my-opencode/src/shared/deep-merge.test.ts +336 -0
- package/oh-my-opencode/src/shared/deep-merge.ts +53 -0
- package/oh-my-opencode/src/shared/dynamic-truncator.ts +193 -0
- package/oh-my-opencode/src/shared/external-plugin-detector.test.ts +133 -0
- package/oh-my-opencode/src/shared/external-plugin-detector.ts +132 -0
- package/oh-my-opencode/src/shared/file-reference-resolver.ts +85 -0
- package/oh-my-opencode/src/shared/file-utils.ts +40 -0
- package/oh-my-opencode/src/shared/first-message-variant.test.ts +32 -0
- package/oh-my-opencode/src/shared/first-message-variant.ts +28 -0
- package/oh-my-opencode/src/shared/frontmatter.test.ts +262 -0
- package/oh-my-opencode/src/shared/frontmatter.ts +31 -0
- package/oh-my-opencode/src/shared/hook-disabled.ts +22 -0
- package/oh-my-opencode/src/shared/index.ts +29 -0
- package/oh-my-opencode/src/shared/jsonc-parser.test.ts +266 -0
- package/oh-my-opencode/src/shared/jsonc-parser.ts +66 -0
- package/oh-my-opencode/src/shared/logger.ts +20 -0
- package/oh-my-opencode/src/shared/migration.test.ts +602 -0
- package/oh-my-opencode/src/shared/migration.ts +191 -0
- package/oh-my-opencode/src/shared/model-resolver.test.ts +101 -0
- package/oh-my-opencode/src/shared/model-resolver.ts +35 -0
- package/oh-my-opencode/src/shared/model-sanitizer.ts +12 -0
- package/oh-my-opencode/src/shared/opencode-config-dir.test.ts +318 -0
- package/oh-my-opencode/src/shared/opencode-config-dir.ts +142 -0
- package/oh-my-opencode/src/shared/opencode-version.test.ts +223 -0
- package/oh-my-opencode/src/shared/opencode-version.ts +72 -0
- package/oh-my-opencode/src/shared/pattern-matcher.ts +29 -0
- package/oh-my-opencode/src/shared/permission-compat.test.ts +134 -0
- package/oh-my-opencode/src/shared/permission-compat.ts +77 -0
- package/oh-my-opencode/src/shared/session-cursor.test.ts +66 -0
- package/oh-my-opencode/src/shared/session-cursor.ts +85 -0
- package/oh-my-opencode/src/shared/shell-env.test.ts +278 -0
- package/oh-my-opencode/src/shared/shell-env.ts +111 -0
- package/oh-my-opencode/src/shared/snake-case.ts +49 -0
- package/oh-my-opencode/src/shared/system-directive.ts +40 -0
- package/oh-my-opencode/src/shared/tool-name.ts +26 -0
- package/oh-my-opencode/src/shared/zip-extractor.ts +83 -0
- package/oh-my-opencode/src/tools/AGENTS.md +74 -0
- package/oh-my-opencode/src/tools/ast-grep/cli.ts +230 -0
- package/oh-my-opencode/src/tools/ast-grep/constants.ts +261 -0
- package/oh-my-opencode/src/tools/ast-grep/downloader.ts +128 -0
- package/oh-my-opencode/src/tools/ast-grep/index.ts +13 -0
- package/oh-my-opencode/src/tools/ast-grep/tools.ts +112 -0
- package/oh-my-opencode/src/tools/ast-grep/types.ts +61 -0
- package/oh-my-opencode/src/tools/ast-grep/utils.ts +102 -0
- package/oh-my-opencode/src/tools/background-task/constants.ts +7 -0
- package/oh-my-opencode/src/tools/background-task/index.ts +7 -0
- package/oh-my-opencode/src/tools/background-task/tools.ts +479 -0
- package/oh-my-opencode/src/tools/background-task/types.ts +16 -0
- package/oh-my-opencode/src/tools/call-omo-agent/constants.ts +7 -0
- package/oh-my-opencode/src/tools/call-omo-agent/index.ts +3 -0
- package/oh-my-opencode/src/tools/call-omo-agent/tools.ts +338 -0
- package/oh-my-opencode/src/tools/call-omo-agent/types.ts +27 -0
- package/oh-my-opencode/src/tools/delegate-task/constants.ts +205 -0
- package/oh-my-opencode/src/tools/delegate-task/index.ts +3 -0
- package/oh-my-opencode/src/tools/delegate-task/tools.test.ts +1575 -0
- package/oh-my-opencode/src/tools/delegate-task/tools.ts +885 -0
- package/oh-my-opencode/src/tools/delegate-task/types.ts +9 -0
- package/oh-my-opencode/src/tools/glob/cli.test.ts +158 -0
- package/oh-my-opencode/src/tools/glob/cli.ts +191 -0
- package/oh-my-opencode/src/tools/glob/constants.ts +12 -0
- package/oh-my-opencode/src/tools/glob/index.ts +3 -0
- package/oh-my-opencode/src/tools/glob/tools.ts +41 -0
- package/oh-my-opencode/src/tools/glob/types.ts +22 -0
- package/oh-my-opencode/src/tools/glob/utils.ts +26 -0
- package/oh-my-opencode/src/tools/grep/cli.ts +229 -0
- package/oh-my-opencode/src/tools/grep/constants.ts +127 -0
- package/oh-my-opencode/src/tools/grep/downloader.test.ts +103 -0
- package/oh-my-opencode/src/tools/grep/downloader.ts +145 -0
- package/oh-my-opencode/src/tools/grep/index.ts +3 -0
- package/oh-my-opencode/src/tools/grep/tools.ts +40 -0
- package/oh-my-opencode/src/tools/grep/types.ts +39 -0
- package/oh-my-opencode/src/tools/grep/utils.ts +53 -0
- package/oh-my-opencode/src/tools/index.ts +72 -0
- package/oh-my-opencode/src/tools/interactive-bash/constants.ts +18 -0
- package/oh-my-opencode/src/tools/interactive-bash/index.ts +4 -0
- package/oh-my-opencode/src/tools/interactive-bash/tools.ts +126 -0
- package/oh-my-opencode/src/tools/interactive-bash/utils.ts +71 -0
- package/oh-my-opencode/src/tools/look-at/constants.ts +3 -0
- package/oh-my-opencode/src/tools/look-at/index.ts +3 -0
- package/oh-my-opencode/src/tools/look-at/tools.test.ts +73 -0
- package/oh-my-opencode/src/tools/look-at/tools.ts +173 -0
- package/oh-my-opencode/src/tools/look-at/types.ts +4 -0
- package/oh-my-opencode/src/tools/lsp/client.ts +596 -0
- package/oh-my-opencode/src/tools/lsp/config.test.ts +130 -0
- package/oh-my-opencode/src/tools/lsp/config.ts +285 -0
- package/oh-my-opencode/src/tools/lsp/constants.ts +390 -0
- package/oh-my-opencode/src/tools/lsp/index.ts +7 -0
- package/oh-my-opencode/src/tools/lsp/tools.ts +261 -0
- package/oh-my-opencode/src/tools/lsp/types.ts +124 -0
- package/oh-my-opencode/src/tools/lsp/utils.ts +406 -0
- package/oh-my-opencode/src/tools/session-manager/constants.ts +97 -0
- package/oh-my-opencode/src/tools/session-manager/index.ts +3 -0
- package/oh-my-opencode/src/tools/session-manager/storage.test.ts +315 -0
- package/oh-my-opencode/src/tools/session-manager/storage.ts +238 -0
- package/oh-my-opencode/src/tools/session-manager/tools.test.ts +124 -0
- package/oh-my-opencode/src/tools/session-manager/tools.ts +146 -0
- package/oh-my-opencode/src/tools/session-manager/types.ts +99 -0
- package/oh-my-opencode/src/tools/session-manager/utils.test.ts +160 -0
- package/oh-my-opencode/src/tools/session-manager/utils.ts +199 -0
- package/oh-my-opencode/src/tools/skill/constants.ts +8 -0
- package/oh-my-opencode/src/tools/skill/index.ts +3 -0
- package/oh-my-opencode/src/tools/skill/tools.test.ts +239 -0
- package/oh-my-opencode/src/tools/skill/tools.ts +200 -0
- package/oh-my-opencode/src/tools/skill/types.ts +31 -0
- package/oh-my-opencode/src/tools/skill-mcp/constants.ts +3 -0
- package/oh-my-opencode/src/tools/skill-mcp/index.ts +3 -0
- package/oh-my-opencode/src/tools/skill-mcp/tools.test.ts +215 -0
- package/oh-my-opencode/src/tools/skill-mcp/tools.ts +172 -0
- package/oh-my-opencode/src/tools/skill-mcp/types.ts +8 -0
- package/oh-my-opencode/src/tools/slashcommand/index.ts +2 -0
- package/oh-my-opencode/src/tools/slashcommand/tools.ts +252 -0
- package/oh-my-opencode/src/tools/slashcommand/types.ts +28 -0
- package/oh-my-opencode/test-setup.ts +6 -0
- package/oh-my-opencode/tsconfig.json +20 -0
- package/package.json +1 -1
- package/src/__tests__/git.test.ts +7 -2
- package/src/__tests__/manifest.test.ts +5 -5
- package/src/agents/repo-explorer.ts +2 -1
- package/src/git.ts +18 -3
- package/src/manifest.ts +22 -15
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { join } from "path"
|
|
2
|
+
import { mkdirSync, appendFileSync, existsSync, writeFileSync, unlinkSync } from "fs"
|
|
3
|
+
import { tmpdir } from "os"
|
|
4
|
+
import { randomUUID } from "crypto"
|
|
5
|
+
import type { TranscriptEntry } from "./types"
|
|
6
|
+
import { transformToolName } from "../../shared/tool-name"
|
|
7
|
+
import { getClaudeConfigDir } from "../../shared"
|
|
8
|
+
|
|
9
|
+
const TRANSCRIPT_DIR = join(getClaudeConfigDir(), "transcripts")
|
|
10
|
+
|
|
11
|
+
export function getTranscriptPath(sessionId: string): string {
|
|
12
|
+
return join(TRANSCRIPT_DIR, `${sessionId}.jsonl`)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function ensureTranscriptDir(): void {
|
|
16
|
+
if (!existsSync(TRANSCRIPT_DIR)) {
|
|
17
|
+
mkdirSync(TRANSCRIPT_DIR, { recursive: true })
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function appendTranscriptEntry(
|
|
22
|
+
sessionId: string,
|
|
23
|
+
entry: TranscriptEntry
|
|
24
|
+
): void {
|
|
25
|
+
ensureTranscriptDir()
|
|
26
|
+
const path = getTranscriptPath(sessionId)
|
|
27
|
+
const line = JSON.stringify(entry) + "\n"
|
|
28
|
+
appendFileSync(path, line)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function recordToolUse(
|
|
32
|
+
sessionId: string,
|
|
33
|
+
toolName: string,
|
|
34
|
+
toolInput: Record<string, unknown>
|
|
35
|
+
): void {
|
|
36
|
+
appendTranscriptEntry(sessionId, {
|
|
37
|
+
type: "tool_use",
|
|
38
|
+
timestamp: new Date().toISOString(),
|
|
39
|
+
tool_name: toolName,
|
|
40
|
+
tool_input: toolInput,
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function recordToolResult(
|
|
45
|
+
sessionId: string,
|
|
46
|
+
toolName: string,
|
|
47
|
+
toolInput: Record<string, unknown>,
|
|
48
|
+
toolOutput: Record<string, unknown>
|
|
49
|
+
): void {
|
|
50
|
+
appendTranscriptEntry(sessionId, {
|
|
51
|
+
type: "tool_result",
|
|
52
|
+
timestamp: new Date().toISOString(),
|
|
53
|
+
tool_name: toolName,
|
|
54
|
+
tool_input: toolInput,
|
|
55
|
+
tool_output: toolOutput,
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function recordUserMessage(
|
|
60
|
+
sessionId: string,
|
|
61
|
+
content: string
|
|
62
|
+
): void {
|
|
63
|
+
appendTranscriptEntry(sessionId, {
|
|
64
|
+
type: "user",
|
|
65
|
+
timestamp: new Date().toISOString(),
|
|
66
|
+
content,
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function recordAssistantMessage(
|
|
71
|
+
sessionId: string,
|
|
72
|
+
content: string
|
|
73
|
+
): void {
|
|
74
|
+
appendTranscriptEntry(sessionId, {
|
|
75
|
+
type: "assistant",
|
|
76
|
+
timestamp: new Date().toISOString(),
|
|
77
|
+
content,
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ============================================================================
|
|
82
|
+
// Claude Code Compatible Transcript Builder (PORT FROM DISABLED)
|
|
83
|
+
// ============================================================================
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* OpenCode API response type (loosely typed)
|
|
87
|
+
*/
|
|
88
|
+
interface OpenCodeMessagePart {
|
|
89
|
+
type: string
|
|
90
|
+
tool?: string
|
|
91
|
+
state?: {
|
|
92
|
+
status?: string
|
|
93
|
+
input?: Record<string, unknown>
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
interface OpenCodeMessage {
|
|
98
|
+
info?: {
|
|
99
|
+
role?: string
|
|
100
|
+
}
|
|
101
|
+
parts?: OpenCodeMessagePart[]
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Claude Code compatible transcript entry (from disabled file)
|
|
106
|
+
*/
|
|
107
|
+
interface DisabledTranscriptEntry {
|
|
108
|
+
type: "assistant"
|
|
109
|
+
message: {
|
|
110
|
+
role: "assistant"
|
|
111
|
+
content: Array<{
|
|
112
|
+
type: "tool_use"
|
|
113
|
+
name: string
|
|
114
|
+
input: Record<string, unknown>
|
|
115
|
+
}>
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Build Claude Code compatible transcript from session messages
|
|
121
|
+
*
|
|
122
|
+
* PORT FROM DISABLED: This calls client.session.messages() API to fetch
|
|
123
|
+
* the full session history and builds a JSONL file in Claude Code format.
|
|
124
|
+
*
|
|
125
|
+
* @param client OpenCode client instance
|
|
126
|
+
* @param sessionId Session ID
|
|
127
|
+
* @param directory Working directory
|
|
128
|
+
* @param currentToolName Current tool being executed (added as last entry)
|
|
129
|
+
* @param currentToolInput Current tool input
|
|
130
|
+
* @returns Temp file path (caller must call deleteTempTranscript!)
|
|
131
|
+
*/
|
|
132
|
+
export async function buildTranscriptFromSession(
|
|
133
|
+
client: {
|
|
134
|
+
session: {
|
|
135
|
+
messages: (opts: { path: { id: string }; query?: { directory: string } }) => Promise<unknown>
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
sessionId: string,
|
|
139
|
+
directory: string,
|
|
140
|
+
currentToolName: string,
|
|
141
|
+
currentToolInput: Record<string, unknown>
|
|
142
|
+
): Promise<string | null> {
|
|
143
|
+
try {
|
|
144
|
+
const response = await client.session.messages({
|
|
145
|
+
path: { id: sessionId },
|
|
146
|
+
query: { directory },
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
// Handle various response formats
|
|
150
|
+
const messages = (response as { "200"?: unknown[]; data?: unknown[] })["200"]
|
|
151
|
+
?? (response as { data?: unknown[] }).data
|
|
152
|
+
?? (Array.isArray(response) ? response : [])
|
|
153
|
+
|
|
154
|
+
const entries: string[] = []
|
|
155
|
+
|
|
156
|
+
if (Array.isArray(messages)) {
|
|
157
|
+
for (const msg of messages as OpenCodeMessage[]) {
|
|
158
|
+
if (msg.info?.role !== "assistant") continue
|
|
159
|
+
|
|
160
|
+
for (const part of msg.parts || []) {
|
|
161
|
+
if (part.type !== "tool") continue
|
|
162
|
+
if (part.state?.status !== "completed") continue
|
|
163
|
+
if (!part.state?.input) continue
|
|
164
|
+
|
|
165
|
+
const rawToolName = part.tool as string
|
|
166
|
+
const toolName = transformToolName(rawToolName)
|
|
167
|
+
|
|
168
|
+
const entry: DisabledTranscriptEntry = {
|
|
169
|
+
type: "assistant",
|
|
170
|
+
message: {
|
|
171
|
+
role: "assistant",
|
|
172
|
+
content: [
|
|
173
|
+
{
|
|
174
|
+
type: "tool_use",
|
|
175
|
+
name: toolName,
|
|
176
|
+
input: part.state.input,
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
},
|
|
180
|
+
}
|
|
181
|
+
entries.push(JSON.stringify(entry))
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Always add current tool call as the last entry
|
|
187
|
+
const currentEntry: DisabledTranscriptEntry = {
|
|
188
|
+
type: "assistant",
|
|
189
|
+
message: {
|
|
190
|
+
role: "assistant",
|
|
191
|
+
content: [
|
|
192
|
+
{
|
|
193
|
+
type: "tool_use",
|
|
194
|
+
name: transformToolName(currentToolName),
|
|
195
|
+
input: currentToolInput,
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
},
|
|
199
|
+
}
|
|
200
|
+
entries.push(JSON.stringify(currentEntry))
|
|
201
|
+
|
|
202
|
+
// Write to temp file
|
|
203
|
+
const tempPath = join(
|
|
204
|
+
tmpdir(),
|
|
205
|
+
`opencode-transcript-${sessionId}-${randomUUID()}.jsonl`
|
|
206
|
+
)
|
|
207
|
+
writeFileSync(tempPath, entries.join("\n") + "\n")
|
|
208
|
+
|
|
209
|
+
return tempPath
|
|
210
|
+
} catch {
|
|
211
|
+
// CRITICAL FIX: Even on API failure, create file with current tool entry only
|
|
212
|
+
// (matching original disabled behavior - never return null with incompatible format)
|
|
213
|
+
try {
|
|
214
|
+
const currentEntry: DisabledTranscriptEntry = {
|
|
215
|
+
type: "assistant",
|
|
216
|
+
message: {
|
|
217
|
+
role: "assistant",
|
|
218
|
+
content: [
|
|
219
|
+
{
|
|
220
|
+
type: "tool_use",
|
|
221
|
+
name: transformToolName(currentToolName),
|
|
222
|
+
input: currentToolInput,
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
},
|
|
226
|
+
}
|
|
227
|
+
const tempPath = join(
|
|
228
|
+
tmpdir(),
|
|
229
|
+
`opencode-transcript-${sessionId}-${randomUUID()}.jsonl`
|
|
230
|
+
)
|
|
231
|
+
writeFileSync(tempPath, JSON.stringify(currentEntry) + "\n")
|
|
232
|
+
return tempPath
|
|
233
|
+
} catch {
|
|
234
|
+
// If even this fails, return null (truly catastrophic failure)
|
|
235
|
+
return null
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Delete temp transcript file (call in finally block)
|
|
242
|
+
*
|
|
243
|
+
* PORT FROM DISABLED: Cleanup mechanism to avoid disk accumulation
|
|
244
|
+
*/
|
|
245
|
+
export function deleteTempTranscript(path: string | null): void {
|
|
246
|
+
if (!path) return
|
|
247
|
+
try {
|
|
248
|
+
unlinkSync(path)
|
|
249
|
+
} catch {
|
|
250
|
+
// Ignore deletion errors
|
|
251
|
+
}
|
|
252
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Hooks Type Definitions
|
|
3
|
+
* Maps Claude Code hook concepts to OpenCode plugin events
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type ClaudeHookEvent =
|
|
7
|
+
| "PreToolUse"
|
|
8
|
+
| "PostToolUse"
|
|
9
|
+
| "UserPromptSubmit"
|
|
10
|
+
| "Stop"
|
|
11
|
+
| "PreCompact"
|
|
12
|
+
|
|
13
|
+
export interface HookMatcher {
|
|
14
|
+
matcher: string
|
|
15
|
+
hooks: HookCommand[]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface HookCommand {
|
|
19
|
+
type: "command"
|
|
20
|
+
command: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ClaudeHooksConfig {
|
|
24
|
+
PreToolUse?: HookMatcher[]
|
|
25
|
+
PostToolUse?: HookMatcher[]
|
|
26
|
+
UserPromptSubmit?: HookMatcher[]
|
|
27
|
+
Stop?: HookMatcher[]
|
|
28
|
+
PreCompact?: HookMatcher[]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface PreToolUseInput {
|
|
32
|
+
session_id: string
|
|
33
|
+
transcript_path?: string
|
|
34
|
+
cwd: string
|
|
35
|
+
permission_mode?: PermissionMode
|
|
36
|
+
hook_event_name: "PreToolUse"
|
|
37
|
+
tool_name: string
|
|
38
|
+
tool_input: Record<string, unknown>
|
|
39
|
+
tool_use_id?: string
|
|
40
|
+
hook_source?: HookSource
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface PostToolUseInput {
|
|
44
|
+
session_id: string
|
|
45
|
+
transcript_path?: string
|
|
46
|
+
cwd: string
|
|
47
|
+
permission_mode?: PermissionMode
|
|
48
|
+
hook_event_name: "PostToolUse"
|
|
49
|
+
tool_name: string
|
|
50
|
+
tool_input: Record<string, unknown>
|
|
51
|
+
tool_response: {
|
|
52
|
+
title?: string
|
|
53
|
+
output?: string
|
|
54
|
+
[key: string]: unknown
|
|
55
|
+
}
|
|
56
|
+
tool_use_id?: string
|
|
57
|
+
hook_source?: HookSource
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface UserPromptSubmitInput {
|
|
61
|
+
session_id: string
|
|
62
|
+
cwd: string
|
|
63
|
+
permission_mode?: PermissionMode
|
|
64
|
+
hook_event_name: "UserPromptSubmit"
|
|
65
|
+
prompt: string
|
|
66
|
+
session?: {
|
|
67
|
+
id: string
|
|
68
|
+
}
|
|
69
|
+
hook_source?: HookSource
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type PermissionMode = "default" | "plan" | "acceptEdits" | "bypassPermissions"
|
|
73
|
+
|
|
74
|
+
export type HookSource = "opencode-plugin"
|
|
75
|
+
|
|
76
|
+
export interface StopInput {
|
|
77
|
+
session_id: string
|
|
78
|
+
transcript_path?: string
|
|
79
|
+
cwd: string
|
|
80
|
+
permission_mode?: PermissionMode
|
|
81
|
+
hook_event_name: "Stop"
|
|
82
|
+
stop_hook_active: boolean
|
|
83
|
+
todo_path?: string
|
|
84
|
+
hook_source?: HookSource
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface PreCompactInput {
|
|
88
|
+
session_id: string
|
|
89
|
+
cwd: string
|
|
90
|
+
hook_event_name: "PreCompact"
|
|
91
|
+
hook_source?: HookSource
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export type PermissionDecision = "allow" | "deny" | "ask"
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Common JSON fields for all hook outputs (Claude Code spec)
|
|
98
|
+
*/
|
|
99
|
+
export interface HookCommonOutput {
|
|
100
|
+
/** If false, Claude stops entirely */
|
|
101
|
+
continue?: boolean
|
|
102
|
+
/** Message shown to user when continue=false */
|
|
103
|
+
stopReason?: string
|
|
104
|
+
/** Suppress output from transcript */
|
|
105
|
+
suppressOutput?: boolean
|
|
106
|
+
/** Warning/message displayed to user */
|
|
107
|
+
systemMessage?: string
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface PreToolUseOutput extends HookCommonOutput {
|
|
111
|
+
/** Deprecated: use hookSpecificOutput.permissionDecision instead */
|
|
112
|
+
decision?: "allow" | "deny" | "approve" | "block" | "ask"
|
|
113
|
+
/** Deprecated: use hookSpecificOutput.permissionDecisionReason instead */
|
|
114
|
+
reason?: string
|
|
115
|
+
hookSpecificOutput?: {
|
|
116
|
+
hookEventName: "PreToolUse"
|
|
117
|
+
permissionDecision: PermissionDecision
|
|
118
|
+
permissionDecisionReason?: string
|
|
119
|
+
updatedInput?: Record<string, unknown>
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface PostToolUseOutput extends HookCommonOutput {
|
|
124
|
+
decision?: "block"
|
|
125
|
+
reason?: string
|
|
126
|
+
hookSpecificOutput?: {
|
|
127
|
+
hookEventName: "PostToolUse"
|
|
128
|
+
/** Additional context to provide to Claude */
|
|
129
|
+
additionalContext?: string
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface HookResult {
|
|
134
|
+
exitCode: number
|
|
135
|
+
stdout?: string
|
|
136
|
+
stderr?: string
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface TranscriptEntry {
|
|
140
|
+
type: "tool_use" | "tool_result" | "user" | "assistant"
|
|
141
|
+
timestamp: string
|
|
142
|
+
tool_name?: string
|
|
143
|
+
tool_input?: Record<string, unknown>
|
|
144
|
+
tool_output?: Record<string, unknown>
|
|
145
|
+
content?: string
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface TodoItem {
|
|
149
|
+
id: string
|
|
150
|
+
content: string
|
|
151
|
+
status: "pending" | "in_progress" | "completed" | "cancelled"
|
|
152
|
+
priority?: "low" | "medium" | "high"
|
|
153
|
+
created_at: string
|
|
154
|
+
updated_at?: string
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface ClaudeCodeTodoItem {
|
|
158
|
+
content: string
|
|
159
|
+
status: string // "pending" | "in_progress" | "completed"
|
|
160
|
+
activeForm: string
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export interface TodoFile {
|
|
164
|
+
session_id: string
|
|
165
|
+
items: TodoItem[]
|
|
166
|
+
created_at: string
|
|
167
|
+
updated_at: string
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface StopOutput {
|
|
171
|
+
decision?: "block" | "continue"
|
|
172
|
+
reason?: string
|
|
173
|
+
stop_hook_active?: boolean
|
|
174
|
+
permission_mode?: PermissionMode
|
|
175
|
+
inject_prompt?: string
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export interface PreCompactOutput extends HookCommonOutput {
|
|
179
|
+
/** Additional context to inject into compaction prompt */
|
|
180
|
+
context?: string[]
|
|
181
|
+
hookSpecificOutput?: {
|
|
182
|
+
hookEventName: "PreCompact"
|
|
183
|
+
/** Additional context strings to inject */
|
|
184
|
+
additionalContext?: string[]
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export type ClaudeCodeContent =
|
|
189
|
+
| { type: "text"; text: string }
|
|
190
|
+
| { type: "tool_use"; id: string; name: string; input: Record<string, unknown> }
|
|
191
|
+
| { type: "tool_result"; tool_use_id: string; content: string }
|
|
192
|
+
|
|
193
|
+
export interface ClaudeCodeMessage {
|
|
194
|
+
type: "user" | "assistant"
|
|
195
|
+
message: {
|
|
196
|
+
role: "user" | "assistant"
|
|
197
|
+
content: ClaudeCodeContent[]
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export interface PluginConfig {
|
|
202
|
+
disabledHooks?: boolean | ClaudeHookEvent[]
|
|
203
|
+
keywordDetectorDisabled?: boolean
|
|
204
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
UserPromptSubmitInput,
|
|
3
|
+
PostToolUseOutput,
|
|
4
|
+
ClaudeHooksConfig,
|
|
5
|
+
} from "./types"
|
|
6
|
+
import { findMatchingHooks, executeHookCommand, log } from "../../shared"
|
|
7
|
+
import { DEFAULT_CONFIG } from "./plugin-config"
|
|
8
|
+
import { isHookCommandDisabled, type PluginExtendedConfig } from "./config-loader"
|
|
9
|
+
|
|
10
|
+
const USER_PROMPT_SUBMIT_TAG_OPEN = "<user-prompt-submit-hook>"
|
|
11
|
+
const USER_PROMPT_SUBMIT_TAG_CLOSE = "</user-prompt-submit-hook>"
|
|
12
|
+
|
|
13
|
+
export interface MessagePart {
|
|
14
|
+
type: "text" | "tool_use" | "tool_result"
|
|
15
|
+
text?: string
|
|
16
|
+
[key: string]: unknown
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface UserPromptSubmitContext {
|
|
20
|
+
sessionId: string
|
|
21
|
+
parentSessionId?: string
|
|
22
|
+
prompt: string
|
|
23
|
+
parts: MessagePart[]
|
|
24
|
+
cwd: string
|
|
25
|
+
permissionMode?: "default" | "acceptEdits" | "bypassPermissions"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface UserPromptSubmitResult {
|
|
29
|
+
block: boolean
|
|
30
|
+
reason?: string
|
|
31
|
+
modifiedParts: MessagePart[]
|
|
32
|
+
messages: string[]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function executeUserPromptSubmitHooks(
|
|
36
|
+
ctx: UserPromptSubmitContext,
|
|
37
|
+
config: ClaudeHooksConfig | null,
|
|
38
|
+
extendedConfig?: PluginExtendedConfig | null
|
|
39
|
+
): Promise<UserPromptSubmitResult> {
|
|
40
|
+
const modifiedParts = ctx.parts
|
|
41
|
+
const messages: string[] = []
|
|
42
|
+
|
|
43
|
+
if (ctx.parentSessionId) {
|
|
44
|
+
return { block: false, modifiedParts, messages }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (
|
|
48
|
+
ctx.prompt.includes(USER_PROMPT_SUBMIT_TAG_OPEN) &&
|
|
49
|
+
ctx.prompt.includes(USER_PROMPT_SUBMIT_TAG_CLOSE)
|
|
50
|
+
) {
|
|
51
|
+
return { block: false, modifiedParts, messages }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!config) {
|
|
55
|
+
return { block: false, modifiedParts, messages }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const matchers = findMatchingHooks(config, "UserPromptSubmit")
|
|
59
|
+
if (matchers.length === 0) {
|
|
60
|
+
return { block: false, modifiedParts, messages }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const stdinData: UserPromptSubmitInput = {
|
|
64
|
+
session_id: ctx.sessionId,
|
|
65
|
+
cwd: ctx.cwd,
|
|
66
|
+
permission_mode: ctx.permissionMode ?? "bypassPermissions",
|
|
67
|
+
hook_event_name: "UserPromptSubmit",
|
|
68
|
+
prompt: ctx.prompt,
|
|
69
|
+
session: { id: ctx.sessionId },
|
|
70
|
+
hook_source: "opencode-plugin",
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
for (const matcher of matchers) {
|
|
74
|
+
for (const hook of matcher.hooks) {
|
|
75
|
+
if (hook.type !== "command") continue
|
|
76
|
+
|
|
77
|
+
if (isHookCommandDisabled("UserPromptSubmit", hook.command, extendedConfig ?? null)) {
|
|
78
|
+
log("UserPromptSubmit hook command skipped (disabled by config)", { command: hook.command })
|
|
79
|
+
continue
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const result = await executeHookCommand(
|
|
83
|
+
hook.command,
|
|
84
|
+
JSON.stringify(stdinData),
|
|
85
|
+
ctx.cwd,
|
|
86
|
+
{ forceZsh: DEFAULT_CONFIG.forceZsh, zshPath: DEFAULT_CONFIG.zshPath }
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
if (result.stdout) {
|
|
90
|
+
const output = result.stdout.trim()
|
|
91
|
+
if (output.startsWith(USER_PROMPT_SUBMIT_TAG_OPEN)) {
|
|
92
|
+
messages.push(output)
|
|
93
|
+
} else {
|
|
94
|
+
messages.push(`${USER_PROMPT_SUBMIT_TAG_OPEN}\n${output}\n${USER_PROMPT_SUBMIT_TAG_CLOSE}`)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (result.exitCode !== 0) {
|
|
99
|
+
try {
|
|
100
|
+
const output = JSON.parse(result.stdout || "{}") as PostToolUseOutput
|
|
101
|
+
if (output.decision === "block") {
|
|
102
|
+
return {
|
|
103
|
+
block: true,
|
|
104
|
+
reason: output.reason || result.stderr,
|
|
105
|
+
modifiedParts,
|
|
106
|
+
messages,
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
} catch {
|
|
110
|
+
// Ignore JSON parse errors
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return { block: false, modifiedParts, messages }
|
|
117
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { describe, test, expect, beforeEach, mock } from "bun:test"
|
|
2
|
+
|
|
3
|
+
describe("comment-checker CLI path resolution", () => {
|
|
4
|
+
describe("lazy initialization", () => {
|
|
5
|
+
// #given module is imported
|
|
6
|
+
// #when COMMENT_CHECKER_CLI_PATH is accessed
|
|
7
|
+
// #then findCommentCheckerPathSync should NOT have been called during import
|
|
8
|
+
|
|
9
|
+
test("getCommentCheckerPathSync should be lazy - not called on module import", async () => {
|
|
10
|
+
// #given a fresh module import
|
|
11
|
+
// We need to verify that importing the module doesn't immediately call findCommentCheckerPathSync
|
|
12
|
+
|
|
13
|
+
// #when we import the module
|
|
14
|
+
const cliModule = await import("./cli")
|
|
15
|
+
|
|
16
|
+
// #then getCommentCheckerPathSync should exist and be callable
|
|
17
|
+
expect(typeof cliModule.getCommentCheckerPathSync).toBe("function")
|
|
18
|
+
|
|
19
|
+
// The key test: calling getCommentCheckerPathSync should work
|
|
20
|
+
// (we can't easily test that it wasn't called on import without mocking,
|
|
21
|
+
// but we can verify the function exists and returns expected types)
|
|
22
|
+
const result = cliModule.getCommentCheckerPathSync()
|
|
23
|
+
expect(result === null || typeof result === "string").toBe(true)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test("getCommentCheckerPathSync should cache result after first call", async () => {
|
|
27
|
+
// #given getCommentCheckerPathSync is called once
|
|
28
|
+
const cliModule = await import("./cli")
|
|
29
|
+
const firstResult = cliModule.getCommentCheckerPathSync()
|
|
30
|
+
|
|
31
|
+
// #when called again
|
|
32
|
+
const secondResult = cliModule.getCommentCheckerPathSync()
|
|
33
|
+
|
|
34
|
+
// #then should return same cached result
|
|
35
|
+
expect(secondResult).toBe(firstResult)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test("COMMENT_CHECKER_CLI_PATH export should not exist (removed for lazy loading)", async () => {
|
|
39
|
+
// #given the cli module
|
|
40
|
+
const cliModule = await import("./cli")
|
|
41
|
+
|
|
42
|
+
// #when checking for COMMENT_CHECKER_CLI_PATH
|
|
43
|
+
// #then it should not exist (replaced with lazy getter)
|
|
44
|
+
expect("COMMENT_CHECKER_CLI_PATH" in cliModule).toBe(false)
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
describe("runCommentChecker", () => {
|
|
49
|
+
test("should use getCommentCheckerPathSync for fallback path resolution", async () => {
|
|
50
|
+
// #given runCommentChecker is called without explicit path
|
|
51
|
+
const { runCommentChecker } = await import("./cli")
|
|
52
|
+
|
|
53
|
+
// #when called with input containing no comments
|
|
54
|
+
const result = await runCommentChecker({
|
|
55
|
+
session_id: "test",
|
|
56
|
+
tool_name: "Write",
|
|
57
|
+
transcript_path: "",
|
|
58
|
+
cwd: "/tmp",
|
|
59
|
+
hook_event_name: "PostToolUse",
|
|
60
|
+
tool_input: { file_path: "/tmp/test.ts", content: "const x = 1" },
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
// #then should return CheckResult type (binary may or may not exist)
|
|
64
|
+
expect(typeof result.hasComments).toBe("boolean")
|
|
65
|
+
expect(typeof result.message).toBe("string")
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
})
|