@hiai-gg/hiai-opencode 0.1.1 → 0.1.3
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/.env.example +68 -57
- package/AGENTS.md +383 -281
- package/ARCHITECTURE.md +280 -281
- package/LICENSE.md +59 -59
- package/README.md +421 -301
- package/assets/mcp/mempalace.mjs +196 -153
- package/assets/mcp/playwright.mjs +76 -0
- package/assets/mcp/rag.mjs +236 -236
- package/assets/runtime/npm-package-runner.mjs +54 -54
- package/config/hiai-opencode.schema.json +82 -82
- package/config/opencode.json +4 -4
- package/dist/config/defaults.d.ts +3 -0
- package/dist/config/platform-schema.d.ts +2 -0
- package/dist/index.js +462 -417
- package/dist/mcp/registry.d.ts +14 -0
- package/dist/mcp/types.d.ts +6 -0
- package/hiai-opencode.json +58 -58
- package/package.json +86 -91
- package/skills/api-and-interface-design/SKILL.md +294 -294
- package/skills/brainstorming/SKILL.md +164 -164
- package/skills/brainstorming/scripts/frame-template.html +214 -214
- package/skills/brainstorming/scripts/helper.js +88 -88
- package/skills/brainstorming/scripts/server.cjs +354 -354
- package/skills/brainstorming/scripts/start-server.sh +148 -148
- package/skills/brainstorming/scripts/stop-server.sh +56 -56
- package/skills/brainstorming/spec-document-reviewer-prompt.md +49 -49
- package/skills/brainstorming/visual-companion.md +287 -287
- package/skills/browser-testing-with-devtools/SKILL.md +302 -302
- package/skills/ci-cd-and-automation/SKILL.md +390 -390
- package/skills/code-review-and-quality/SKILL.md +347 -347
- package/skills/code-simplification/SKILL.md +331 -331
- package/skills/context-engineering/SKILL.md +289 -289
- package/skills/deprecation-and-migration/SKILL.md +206 -206
- package/skills/dispatching-parallel-agents/SKILL.md +182 -182
- package/skills/documentation-and-adrs/SKILL.md +278 -278
- package/skills/executing-plans/SKILL.md +70 -70
- package/skills/finishing-a-development-branch/SKILL.md +200 -200
- package/skills/frontend-ui-engineering/SKILL.md +322 -322
- package/skills/git-workflow-and-versioning/SKILL.md +300 -300
- package/skills/incremental-implementation/SKILL.md +241 -241
- package/skills/performance-optimization/SKILL.md +350 -350
- package/skills/receiving-code-review/SKILL.md +213 -213
- package/skills/requesting-code-review/SKILL.md +105 -105
- package/skills/requesting-code-review/code-reviewer.md +146 -146
- package/skills/security-and-hardening/SKILL.md +349 -349
- package/skills/shipping-and-launch/SKILL.md +309 -309
- package/skills/source-driven-development/SKILL.md +194 -194
- package/skills/spec-driven-development/SKILL.md +200 -200
- package/skills/subagent-driven-development/SKILL.md +277 -277
- package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -26
- package/skills/subagent-driven-development/implementer-prompt.md +113 -113
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -61
- package/skills/systematic-debugging/CREATION-LOG.md +119 -119
- package/skills/systematic-debugging/SKILL.md +596 -596
- package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -158
- package/skills/systematic-debugging/condition-based-waiting.md +115 -115
- package/skills/systematic-debugging/defense-in-depth.md +122 -122
- package/skills/systematic-debugging/find-polluter.sh +63 -63
- package/skills/systematic-debugging/root-cause-tracing.md +169 -169
- package/skills/systematic-debugging/test-academic.md +14 -14
- package/skills/systematic-debugging/test-pressure-1.md +58 -58
- package/skills/systematic-debugging/test-pressure-2.md +68 -68
- package/skills/systematic-debugging/test-pressure-3.md +69 -69
- package/skills/test-driven-development/SKILL.md +379 -379
- package/skills/using-agent-skills/SKILL.md +174 -174
- package/skills/using-git-worktrees/SKILL.md +218 -218
- package/skills/using-superpowers/SKILL.md +117 -117
- package/skills/using-superpowers/references/codex-tools.md +100 -100
- package/skills/using-superpowers/references/copilot-tools.md +52 -52
- package/skills/using-superpowers/references/gemini-tools.md +33 -33
- package/skills/verification-before-completion/SKILL.md +139 -139
- package/skills/writing-plans/SKILL.md +152 -152
- package/skills/writing-plans/plan-document-reviewer-prompt.md +49 -49
- package/skills/writing-skills/SKILL.md +655 -655
- package/skills/writing-skills/anthropic-best-practices.md +1150 -1150
- package/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -189
- package/skills/writing-skills/graphviz-conventions.dot +171 -171
- package/skills/writing-skills/persuasion-principles.md +187 -187
- package/skills/writing-skills/render-graphs.js +168 -168
- package/skills/writing-skills/testing-skills-with-subagents.md +384 -384
- package/src/AGENTS.md +41 -41
- package/src/agents/AGENTS.md +74 -74
- package/src/agents/agent-builder.ts +50 -50
- package/src/agents/bob/AGENTS.md +29 -29
- package/src/agents/bob/default.ts +128 -128
- package/src/agents/bob/gemini.ts +237 -237
- package/src/agents/bob/gpt-pro.ts +430 -430
- package/src/agents/bob/index.ts +19 -19
- package/src/agents/bob.ts +528 -528
- package/src/agents/builtin-agents/agent-overrides.ts +75 -75
- package/src/agents/builtin-agents/available-skills.ts +35 -35
- package/src/agents/builtin-agents/bob-agent.ts +96 -96
- package/src/agents/builtin-agents/coder-agent.ts +98 -98
- package/src/agents/builtin-agents/environment-context.ts +16 -16
- package/src/agents/builtin-agents/general-agents.ts +122 -122
- package/src/agents/builtin-agents/guard-agent.ts +66 -66
- package/src/agents/builtin-agents/model-resolution.ts +31 -31
- package/src/agents/builtin-agents/resolve-file-uri.ts +42 -42
- package/src/agents/builtin-agents.ts +194 -194
- package/src/agents/coder/AGENTS.md +34 -34
- package/src/agents/coder/agent.ts +162 -162
- package/src/agents/coder/gpt-codex.ts +404 -404
- package/src/agents/coder/gpt-pro.ts +319 -319
- package/src/agents/coder/gpt.ts +253 -253
- package/src/agents/coder/index.ts +8 -8
- package/src/agents/critic/agent.ts +105 -105
- package/src/agents/custom-agent-summaries.ts +61 -61
- package/src/agents/dynamic-agent-category-skills-guide.ts +138 -138
- package/src/agents/dynamic-agent-core-sections.ts +237 -237
- package/src/agents/dynamic-agent-policy-sections.ts +182 -182
- package/src/agents/dynamic-agent-prompt-builder.ts +31 -31
- package/src/agents/dynamic-agent-prompt-types.ts +24 -24
- package/src/agents/dynamic-agent-tool-categorization.ts +45 -45
- package/src/agents/env-context.ts +16 -16
- package/src/agents/gpt-apply-patch-guard.ts +7 -7
- package/src/agents/guard/agent.ts +146 -146
- package/src/agents/guard/default-prompt-sections.ts +305 -305
- package/src/agents/guard/default.ts +22 -22
- package/src/agents/guard/gemini-prompt-sections.ts +293 -293
- package/src/agents/guard/gemini.ts +22 -22
- package/src/agents/guard/gpt-prompt-sections.ts +296 -296
- package/src/agents/guard/gpt.ts +22 -22
- package/src/agents/guard/index.ts +2 -2
- package/src/agents/guard/prompt-section-builder.ts +104 -104
- package/src/agents/guard/shared-prompt.ts +172 -172
- package/src/agents/index.ts +5 -5
- package/src/agents/platform-adapter.ts +236 -236
- package/src/agents/platform-manager.ts +57 -57
- package/src/agents/prompt-library/identity.ts +14 -14
- package/src/agents/prompt-library/index.ts +7 -7
- package/src/agents/prompt-library/intent-gate.ts +149 -149
- package/src/agents/prompt-library/orchestration.ts +60 -60
- package/src/agents/prompt-library/platform.ts +36 -36
- package/src/agents/prompt-library/specialized.ts +39 -39
- package/src/agents/prompt-library/strategy.ts +80 -80
- package/src/agents/prompt-library/todo-discipline.ts +22 -22
- package/src/agents/quality-guardian.ts +76 -76
- package/src/agents/researcher.ts +73 -73
- package/src/agents/strategist/AGENTS.md +37 -37
- package/src/agents/strategist/behavioral-summary.ts +79 -79
- package/src/agents/strategist/gemini.ts +333 -333
- package/src/agents/strategist/gpt.ts +460 -460
- package/src/agents/strategist/high-accuracy-mode.ts +78 -78
- package/src/agents/strategist/identity-constraints.ts +336 -336
- package/src/agents/strategist/index.ts +6 -6
- package/src/agents/strategist/interview-mode.ts +335 -335
- package/src/agents/strategist/plan-generation.ts +213 -213
- package/src/agents/strategist/plan-template.ts +325 -325
- package/src/agents/strategist/system-prompt.ts +68 -68
- package/src/agents/sub/agent.ts +141 -141
- package/src/agents/sub/default.ts +52 -52
- package/src/agents/sub/gemini.ts +194 -194
- package/src/agents/sub/gpt-codex.ts +156 -156
- package/src/agents/sub/gpt-pro.ts +161 -161
- package/src/agents/sub/gpt.ts +157 -157
- package/src/agents/sub/index.ts +13 -13
- package/src/agents/types.ts +144 -144
- package/src/agents/ui.ts +58 -58
- package/src/config/data/model-capabilities.json +40690 -40690
- package/src/config/defaults.ts +89 -146
- package/src/config/hiai-opencode.schema.json +12 -12
- package/src/config/index.ts +67 -67
- package/src/config/loader.test.ts +65 -65
- package/src/config/loader.ts +186 -183
- package/src/config/models.ts +32 -32
- package/src/config/platform-schema.ts +193 -192
- package/src/config/schema/agent-definitions.ts +5 -5
- package/src/config/schema/agent-names.ts +66 -66
- package/src/config/schema/agent-overrides.ts +95 -95
- package/src/config/schema/babysitting.ts +7 -7
- package/src/config/schema/background-task.ts +29 -29
- package/src/config/schema/bob-agent.ts +11 -11
- package/src/config/schema/bob.ts +17 -17
- package/src/config/schema/browser-automation.ts +24 -24
- package/src/config/schema/categories.ts +45 -45
- package/src/config/schema/claude-code.ts +13 -13
- package/src/config/schema/commands.ts +14 -14
- package/src/config/schema/comment-checker.ts +8 -8
- package/src/config/schema/dynamic-context-pruning.ts +53 -53
- package/src/config/schema/experimental.ts +27 -27
- package/src/config/schema/fallback-models.ts +31 -31
- package/src/config/schema/fast-apply.ts +14 -14
- package/src/config/schema/git-env-prefix.ts +28 -28
- package/src/config/schema/git-master.ts +14 -14
- package/src/config/schema/hooks.ts +61 -61
- package/src/config/schema/index.ts +52 -52
- package/src/config/schema/internal/permission.ts +20 -20
- package/src/config/schema/model-capabilities.ts +10 -10
- package/src/config/schema/notification.ts +8 -8
- package/src/config/schema/oh-my-opencode-config.ts +90 -90
- package/src/config/schema/openclaw.ts +50 -50
- package/src/config/schema/ralph-loop.ts +11 -11
- package/src/config/schema/runtime-fallback.ts +18 -18
- package/src/config/schema/skills.ts +39 -39
- package/src/config/schema/start-work.ts +7 -7
- package/src/config/schema/tmux.ts +28 -28
- package/src/config/schema/websearch.ts +15 -15
- package/src/config/types.ts +174 -174
- package/src/create-hooks.ts +93 -93
- package/src/create-managers.ts +116 -116
- package/src/create-runtime-tmux-config.ts +18 -18
- package/src/create-tools.ts +53 -53
- package/src/features/background-agent/AGENTS.md +56 -56
- package/src/features/background-agent/abort-with-timeout.ts +35 -35
- package/src/features/background-agent/background-task-notification-template.ts +74 -74
- package/src/features/background-agent/compaction-aware-message-resolver.ts +164 -164
- package/src/features/background-agent/concurrency.ts +137 -137
- package/src/features/background-agent/constants.ts +58 -58
- package/src/features/background-agent/duration-formatter.ts +14 -14
- package/src/features/background-agent/error-classifier.ts +83 -83
- package/src/features/background-agent/fallback-retry-handler.ts +134 -134
- package/src/features/background-agent/index.ts +2 -2
- package/src/features/background-agent/loop-detector.ts +102 -102
- package/src/features/background-agent/manager.ts +2220 -2220
- package/src/features/background-agent/opencode-client.ts +3 -3
- package/src/features/background-agent/process-cleanup.ts +98 -98
- package/src/features/background-agent/remove-task-toast-tracking.ts +8 -8
- package/src/features/background-agent/session-existence.ts +57 -57
- package/src/features/background-agent/session-idle-event-handler.ts +93 -93
- package/src/features/background-agent/session-status-classifier.ts +20 -20
- package/src/features/background-agent/spawner/parent-directory-resolver.ts +24 -24
- package/src/features/background-agent/spawner.ts +327 -327
- package/src/features/background-agent/state.ts +199 -199
- package/src/features/background-agent/subagent-spawn-limits.ts +97 -97
- package/src/features/background-agent/task-history.ts +79 -79
- package/src/features/background-agent/task-poller.ts +225 -225
- package/src/features/background-agent/types.ts +100 -100
- package/src/features/boulder-state/constants.ts +13 -13
- package/src/features/boulder-state/index.ts +4 -4
- package/src/features/boulder-state/storage.ts +336 -336
- package/src/features/boulder-state/top-level-task.ts +78 -78
- package/src/features/boulder-state/types.ts +61 -61
- package/src/features/builtin-commands/commands.ts +143 -143
- package/src/features/builtin-commands/index.ts +2 -2
- package/src/features/builtin-commands/templates/handoff.ts +177 -177
- package/src/features/builtin-commands/templates/init-deep.ts +305 -305
- package/src/features/builtin-commands/templates/ralph-loop.ts +66 -66
- package/src/features/builtin-commands/templates/refactor.ts +619 -619
- package/src/features/builtin-commands/templates/remove-ai-slops.ts +96 -96
- package/src/features/builtin-commands/templates/start-work.ts +128 -128
- package/src/features/builtin-commands/templates/stop-continuation.ts +13 -13
- package/src/features/builtin-commands/types.ts +9 -9
- package/src/features/builtin-skills/index.ts +2 -2
- package/src/features/builtin-skills/materialize.ts +338 -338
- package/src/features/builtin-skills/skills/ai-slop-remover.ts +145 -145
- package/src/features/builtin-skills/skills/dev-browser.ts +221 -221
- package/src/features/builtin-skills/skills/frontend-ui-ux.ts +79 -79
- package/src/features/builtin-skills/skills/git-master-sections/commit-workflow.ts +509 -509
- package/src/features/builtin-skills/skills/git-master-sections/history-search-workflow.ts +229 -229
- package/src/features/builtin-skills/skills/git-master-sections/overview.ts +64 -64
- package/src/features/builtin-skills/skills/git-master-sections/quick-reference.ts +86 -86
- package/src/features/builtin-skills/skills/git-master-sections/rebase-workflow.ts +181 -181
- package/src/features/builtin-skills/skills/git-master-skill-metadata.ts +4 -4
- package/src/features/builtin-skills/skills/git-master.ts +28 -28
- package/src/features/builtin-skills/skills/index.ts +7 -7
- package/src/features/builtin-skills/skills/playwright-cli.ts +268 -268
- package/src/features/builtin-skills/skills/playwright.ts +466 -466
- package/src/features/builtin-skills/skills/review-work.ts +536 -536
- package/src/features/builtin-skills/skills.ts +39 -39
- package/src/features/builtin-skills/types.ts +16 -16
- package/src/features/claude-code-agent-loader/agent-definitions-loader.ts +87 -87
- package/src/features/claude-code-agent-loader/claude-model-mapper.ts +53 -53
- package/src/features/claude-code-agent-loader/index.ts +5 -5
- package/src/features/claude-code-agent-loader/json-agent-loader.ts +53 -53
- package/src/features/claude-code-agent-loader/loader.ts +86 -86
- package/src/features/claude-code-agent-loader/opencode-config-agents-reader.ts +125 -125
- package/src/features/claude-code-agent-loader/types.ts +31 -31
- package/src/features/claude-code-command-loader/index.ts +2 -2
- package/src/features/claude-code-command-loader/loader.ts +169 -169
- package/src/features/claude-code-command-loader/types.ts +46 -46
- package/src/features/claude-code-mcp-loader/configure-allowed-env-vars.ts +48 -48
- package/src/features/claude-code-mcp-loader/env-expander.ts +51 -51
- package/src/features/claude-code-mcp-loader/index.ts +12 -12
- package/src/features/claude-code-mcp-loader/loader.ts +156 -156
- package/src/features/claude-code-mcp-loader/scope-filter.ts +17 -17
- package/src/features/claude-code-mcp-loader/transformer.ts +57 -57
- package/src/features/claude-code-mcp-loader/types.ts +51 -51
- package/src/features/claude-code-plugin-loader/agent-loader.ts +59 -59
- package/src/features/claude-code-plugin-loader/command-loader.ts +53 -53
- package/src/features/claude-code-plugin-loader/discovery.ts +251 -251
- package/src/features/claude-code-plugin-loader/hook-loader.ts +26 -26
- package/src/features/claude-code-plugin-loader/index.ts +10 -10
- package/src/features/claude-code-plugin-loader/loader.ts +134 -134
- package/src/features/claude-code-plugin-loader/mcp-server-loader.ts +59 -59
- package/src/features/claude-code-plugin-loader/plugin-path-resolver.ts +23 -23
- package/src/features/claude-code-plugin-loader/scope-filter.ts +29 -29
- package/src/features/claude-code-plugin-loader/skill-loader.ts +62 -62
- package/src/features/claude-code-plugin-loader/types.ts +255 -255
- package/src/features/claude-code-session-state/index.ts +1 -1
- package/src/features/claude-code-session-state/state.ts +154 -154
- package/src/features/claude-tasks/session-storage.ts +52 -52
- package/src/features/claude-tasks/storage.ts +169 -169
- package/src/features/claude-tasks/types.ts +20 -20
- package/src/features/context-injector/collector.ts +91 -91
- package/src/features/context-injector/index.ts +14 -14
- package/src/features/context-injector/injector.ts +167 -167
- package/src/features/context-injector/types.ts +91 -91
- package/src/features/hook-message-injector/constants.ts +1 -1
- package/src/features/hook-message-injector/index.ts +11 -11
- package/src/features/hook-message-injector/injector.ts +437 -437
- package/src/features/hook-message-injector/types.ts +49 -49
- package/src/features/mcp-oauth/AGENTS.md +54 -54
- package/src/features/mcp-oauth/callback-server.ts +106 -106
- package/src/features/mcp-oauth/dcr.ts +98 -98
- package/src/features/mcp-oauth/discovery.ts +134 -134
- package/src/features/mcp-oauth/oauth-authorization-flow.ts +150 -150
- package/src/features/mcp-oauth/provider.ts +215 -215
- package/src/features/mcp-oauth/refresh-mutex.ts +58 -58
- package/src/features/mcp-oauth/resource-indicator.ts +16 -16
- package/src/features/mcp-oauth/schema.ts +8 -8
- package/src/features/mcp-oauth/step-up.ts +79 -79
- package/src/features/mcp-oauth/storage.ts +155 -155
- package/src/features/opencode-skill-loader/AGENTS.md +59 -59
- package/src/features/opencode-skill-loader/allowed-tools-parser.ts +9 -9
- package/src/features/opencode-skill-loader/async-loader.ts +213 -213
- package/src/features/opencode-skill-loader/blocking.ts +62 -62
- package/src/features/opencode-skill-loader/config-source-discovery.ts +114 -114
- package/src/features/opencode-skill-loader/discover-worker.ts +56 -56
- package/src/features/opencode-skill-loader/git-master-template-injection.ts +150 -150
- package/src/features/opencode-skill-loader/index.ts +17 -17
- package/src/features/opencode-skill-loader/loaded-skill-from-path.ts +73 -73
- package/src/features/opencode-skill-loader/loaded-skill-template-extractor.ts +16 -16
- package/src/features/opencode-skill-loader/loader.ts +172 -172
- package/src/features/opencode-skill-loader/merger/builtin-skill-converter.ts +26 -26
- package/src/features/opencode-skill-loader/merger/config-skill-entry-loader.ts +117 -117
- package/src/features/opencode-skill-loader/merger/scope-priority.ts +10 -10
- package/src/features/opencode-skill-loader/merger/skill-definition-merger.ts +31 -31
- package/src/features/opencode-skill-loader/merger/skills-config-normalizer.ts +19 -19
- package/src/features/opencode-skill-loader/merger.ts +96 -96
- package/src/features/opencode-skill-loader/skill-content.ts +11 -11
- package/src/features/opencode-skill-loader/skill-deduplication.ts +13 -13
- package/src/features/opencode-skill-loader/skill-definition-record.ts +11 -11
- package/src/features/opencode-skill-loader/skill-directory-loader.ts +112 -112
- package/src/features/opencode-skill-loader/skill-discovery.ts +76 -76
- package/src/features/opencode-skill-loader/skill-mcp-config.ts +45 -45
- package/src/features/opencode-skill-loader/skill-resolution-options.ts +9 -9
- package/src/features/opencode-skill-loader/skill-template-resolver.ts +97 -97
- package/src/features/opencode-skill-loader/types.ts +38 -38
- package/src/features/run-continuation-state/constants.ts +1 -1
- package/src/features/run-continuation-state/index.ts +3 -3
- package/src/features/run-continuation-state/storage.ts +80 -80
- package/src/features/run-continuation-state/types.ts +15 -15
- package/src/features/skill-mcp-manager/AGENTS.md +111 -111
- package/src/features/skill-mcp-manager/cleanup.ts +153 -153
- package/src/features/skill-mcp-manager/connection-type.ts +26 -26
- package/src/features/skill-mcp-manager/connection.ts +146 -146
- package/src/features/skill-mcp-manager/env-cleaner.ts +59 -59
- package/src/features/skill-mcp-manager/error-redaction.ts +47 -47
- package/src/features/skill-mcp-manager/http-client.ts +126 -126
- package/src/features/skill-mcp-manager/index.ts +2 -2
- package/src/features/skill-mcp-manager/manager.ts +178 -178
- package/src/features/skill-mcp-manager/oauth-handler.ts +160 -160
- package/src/features/skill-mcp-manager/stdio-client.ts +112 -112
- package/src/features/skill-mcp-manager/types.ts +96 -96
- package/src/features/task-toast-manager/index.ts +2 -2
- package/src/features/task-toast-manager/manager.ts +251 -251
- package/src/features/task-toast-manager/types.ts +29 -29
- package/src/features/tmux-subagent/action-executor-core.ts +82 -82
- package/src/features/tmux-subagent/action-executor.ts +137 -137
- package/src/features/tmux-subagent/cleanup.ts +42 -42
- package/src/features/tmux-subagent/decision-engine.ts +22 -22
- package/src/features/tmux-subagent/event-handlers.ts +6 -6
- package/src/features/tmux-subagent/grid-planning.ts +137 -137
- package/src/features/tmux-subagent/index.ts +16 -16
- package/src/features/tmux-subagent/manager.ts +969 -969
- package/src/features/tmux-subagent/oldest-agent-pane.ts +37 -37
- package/src/features/tmux-subagent/pane-split-availability.ts +77 -77
- package/src/features/tmux-subagent/pane-state-parser.ts +135 -135
- package/src/features/tmux-subagent/pane-state-querier.ts +76 -76
- package/src/features/tmux-subagent/polling-constants.ts +6 -6
- package/src/features/tmux-subagent/polling-manager.ts +167 -167
- package/src/features/tmux-subagent/polling.ts +183 -183
- package/src/features/tmux-subagent/session-created-event.ts +44 -44
- package/src/features/tmux-subagent/session-created-handler.ts +175 -175
- package/src/features/tmux-subagent/session-deleted-handler.ts +50 -50
- package/src/features/tmux-subagent/session-message-count.ts +3 -3
- package/src/features/tmux-subagent/session-ready-waiter.ts +44 -44
- package/src/features/tmux-subagent/session-status-parser.ts +17 -17
- package/src/features/tmux-subagent/spawn-action-decider.ts +147 -147
- package/src/features/tmux-subagent/spawn-target-finder.ts +146 -146
- package/src/features/tmux-subagent/tmux-grid-constants.ts +57 -57
- package/src/features/tmux-subagent/tracked-session-state.ts +29 -29
- package/src/features/tmux-subagent/types.ts +54 -54
- package/src/features/tool-metadata-store/index.ts +7 -7
- package/src/features/tool-metadata-store/store.ts +84 -84
- package/src/hooks/agent-usage-reminder/constants.ts +52 -52
- package/src/hooks/agent-usage-reminder/hook.ts +134 -134
- package/src/hooks/agent-usage-reminder/index.ts +1 -1
- package/src/hooks/agent-usage-reminder/storage.ts +42 -42
- package/src/hooks/agent-usage-reminder/types.ts +6 -6
- package/src/hooks/anthropic-context-window-limit-recovery/AGENTS.md +49 -49
- package/src/hooks/anthropic-context-window-limit-recovery/aggressive-truncation-strategy.ts +87 -87
- package/src/hooks/anthropic-context-window-limit-recovery/client.ts +21 -21
- package/src/hooks/anthropic-context-window-limit-recovery/deduplication-recovery.ts +77 -77
- package/src/hooks/anthropic-context-window-limit-recovery/empty-content-recovery-sdk.ts +199 -199
- package/src/hooks/anthropic-context-window-limit-recovery/empty-content-recovery.ts +149 -149
- package/src/hooks/anthropic-context-window-limit-recovery/executor.ts +83 -83
- package/src/hooks/anthropic-context-window-limit-recovery/index.ts +8 -8
- package/src/hooks/anthropic-context-window-limit-recovery/message-builder.ts +190 -190
- package/src/hooks/anthropic-context-window-limit-recovery/message-storage-directory.ts +40 -40
- package/src/hooks/anthropic-context-window-limit-recovery/parser.ts +209 -209
- package/src/hooks/anthropic-context-window-limit-recovery/pruning-deduplication.ts +189 -189
- package/src/hooks/anthropic-context-window-limit-recovery/pruning-tool-output-truncation.ts +142 -142
- package/src/hooks/anthropic-context-window-limit-recovery/pruning-types.ts +44 -44
- package/src/hooks/anthropic-context-window-limit-recovery/recovery-hook.test-support.ts +119 -119
- package/src/hooks/anthropic-context-window-limit-recovery/recovery-hook.ts +193 -193
- package/src/hooks/anthropic-context-window-limit-recovery/recovery-strategy.ts +2 -2
- package/src/hooks/anthropic-context-window-limit-recovery/session-timeout-map.ts +20 -20
- package/src/hooks/anthropic-context-window-limit-recovery/state.ts +78 -78
- package/src/hooks/anthropic-context-window-limit-recovery/storage-paths.ts +6 -6
- package/src/hooks/anthropic-context-window-limit-recovery/storage.ts +18 -18
- package/src/hooks/anthropic-context-window-limit-recovery/summarize-retry-strategy.ts +218 -218
- package/src/hooks/anthropic-context-window-limit-recovery/target-token-truncation.ts +196 -196
- package/src/hooks/anthropic-context-window-limit-recovery/tool-part-types.ts +38 -38
- package/src/hooks/anthropic-context-window-limit-recovery/tool-result-storage-sdk.ts +123 -123
- package/src/hooks/anthropic-context-window-limit-recovery/tool-result-storage.ts +119 -119
- package/src/hooks/anthropic-context-window-limit-recovery/types.ts +44 -44
- package/src/hooks/anthropic-effort/hook.ts +93 -93
- package/src/hooks/anthropic-effort/index.ts +1 -1
- package/src/hooks/auto-slash-command/constants.ts +12 -12
- package/src/hooks/auto-slash-command/detector.ts +88 -88
- package/src/hooks/auto-slash-command/executor.ts +165 -165
- package/src/hooks/auto-slash-command/hook.ts +238 -238
- package/src/hooks/auto-slash-command/index.ts +7 -7
- package/src/hooks/auto-slash-command/processed-command-store.ts +74 -74
- package/src/hooks/auto-slash-command/types.ts +42 -42
- package/src/hooks/background-notification/hook.ts +54 -54
- package/src/hooks/background-notification/index.ts +2 -2
- package/src/hooks/background-notification/types.ts +5 -5
- package/src/hooks/bash-file-read-guard.ts +44 -44
- package/src/hooks/category-skill-reminder/formatter.ts +37 -37
- package/src/hooks/category-skill-reminder/hook.ts +142 -142
- package/src/hooks/category-skill-reminder/index.ts +1 -1
- package/src/hooks/claude-code-hooks/AGENTS.md +41 -41
- package/src/hooks/claude-code-hooks/claude-code-hooks-hook.ts +28 -28
- package/src/hooks/claude-code-hooks/config-loader.ts +151 -151
- package/src/hooks/claude-code-hooks/config.ts +147 -147
- package/src/hooks/claude-code-hooks/dispatch-hook.ts +27 -27
- package/src/hooks/claude-code-hooks/execute-http-hook.ts +116 -116
- package/src/hooks/claude-code-hooks/handlers/chat-message-handler.ts +140 -140
- package/src/hooks/claude-code-hooks/handlers/pre-compact-handler.ts +41 -41
- package/src/hooks/claude-code-hooks/handlers/session-event-handler.ts +137 -137
- package/src/hooks/claude-code-hooks/handlers/tool-execute-after-handler.ts +160 -160
- package/src/hooks/claude-code-hooks/handlers/tool-execute-before-handler.ts +93 -93
- package/src/hooks/claude-code-hooks/index.ts +1 -1
- package/src/hooks/claude-code-hooks/plugin-config.ts +12 -12
- package/src/hooks/claude-code-hooks/post-tool-use.ts +195 -195
- package/src/hooks/claude-code-hooks/pre-compact.ts +105 -105
- package/src/hooks/claude-code-hooks/pre-tool-use.ts +168 -168
- package/src/hooks/claude-code-hooks/session-hook-state.ts +17 -17
- package/src/hooks/claude-code-hooks/stop.ts +118 -118
- package/src/hooks/claude-code-hooks/todo.ts +76 -76
- package/src/hooks/claude-code-hooks/tool-input-cache.ts +82 -82
- package/src/hooks/claude-code-hooks/transcript.ts +248 -248
- package/src/hooks/claude-code-hooks/types.ts +214 -214
- package/src/hooks/claude-code-hooks/user-prompt-submit.ts +121 -121
- package/src/hooks/comment-checker/cli-runner.ts +127 -127
- package/src/hooks/comment-checker/cli.ts +269 -269
- package/src/hooks/comment-checker/downloader.ts +170 -170
- package/src/hooks/comment-checker/hook.ts +192 -192
- package/src/hooks/comment-checker/index.ts +1 -1
- package/src/hooks/comment-checker/pending-calls.ts +45 -45
- package/src/hooks/comment-checker/types.ts +33 -33
- package/src/hooks/compaction-context-injector/compaction-context-prompt.ts +56 -56
- package/src/hooks/compaction-context-injector/constants.ts +5 -5
- package/src/hooks/compaction-context-injector/hook.ts +164 -164
- package/src/hooks/compaction-context-injector/index.ts +1 -1
- package/src/hooks/compaction-context-injector/recovery-prompt-config.ts +77 -77
- package/src/hooks/compaction-context-injector/recovery.ts +163 -163
- package/src/hooks/compaction-context-injector/session-id.ts +8 -8
- package/src/hooks/compaction-context-injector/session-prompt-config-resolver.ts +120 -120
- package/src/hooks/compaction-context-injector/tail-monitor.ts +52 -52
- package/src/hooks/compaction-context-injector/types.ts +25 -25
- package/src/hooks/compaction-context-injector/validated-model.ts +47 -47
- package/src/hooks/compaction-todo-preserver/hook.ts +127 -127
- package/src/hooks/compaction-todo-preserver/index.ts +2 -2
- package/src/hooks/context-window-monitor.ts +113 -113
- package/src/hooks/delegate-task-retry/guidance.ts +45 -45
- package/src/hooks/delegate-task-retry/hook.ts +22 -22
- package/src/hooks/delegate-task-retry/index.ts +4 -4
- package/src/hooks/delegate-task-retry/patterns.ts +77 -77
- package/src/hooks/directory-agents-injector/constants.ts +7 -7
- package/src/hooks/directory-agents-injector/finder.ts +38 -38
- package/src/hooks/directory-agents-injector/hook.ts +80 -80
- package/src/hooks/directory-agents-injector/index.ts +1 -1
- package/src/hooks/directory-agents-injector/injector.ts +59 -59
- package/src/hooks/directory-agents-injector/storage.ts +8 -8
- package/src/hooks/directory-readme-injector/constants.ts +7 -7
- package/src/hooks/directory-readme-injector/finder.ts +33 -33
- package/src/hooks/directory-readme-injector/hook.ts +80 -80
- package/src/hooks/directory-readme-injector/index.ts +1 -1
- package/src/hooks/directory-readme-injector/injector.ts +59 -59
- package/src/hooks/directory-readme-injector/storage.ts +8 -8
- package/src/hooks/edit-error-recovery/hook.ts +58 -58
- package/src/hooks/edit-error-recovery/index.ts +5 -5
- package/src/hooks/empty-task-response-detector.ts +27 -27
- package/src/hooks/fast-apply/hook.ts +11 -11
- package/src/hooks/fast-apply/index.ts +1 -1
- package/src/hooks/fast-apply/ollama-client.ts +53 -53
- package/src/hooks/fast-apply/tool-execute-before-handler.ts +86 -86
- package/src/hooks/guard/AGENTS.md +64 -64
- package/src/hooks/guard/background-launch-session-tracking.ts +97 -97
- package/src/hooks/guard/bob-path.ts +8 -8
- package/src/hooks/guard/boulder-continuation-injector.ts +109 -109
- package/src/hooks/guard/boulder-session-lineage.ts +44 -44
- package/src/hooks/guard/event-handler.ts +104 -104
- package/src/hooks/guard/final-wave-approval-gate.ts +47 -47
- package/src/hooks/guard/final-wave-plan-state.ts +60 -60
- package/src/hooks/guard/guard-hook.ts +27 -27
- package/src/hooks/guard/hook-name.ts +1 -1
- package/src/hooks/guard/idle-event.ts +341 -341
- package/src/hooks/guard/index.ts +3 -3
- package/src/hooks/guard/is-abort-error.ts +20 -20
- package/src/hooks/guard/recent-model-resolver.ts +89 -89
- package/src/hooks/guard/resolve-active-boulder-session.ts +29 -29
- package/src/hooks/guard/session-last-agent.ts +153 -153
- package/src/hooks/guard/subagent-session-id.ts +54 -54
- package/src/hooks/guard/system-reminder-templates.ts +249 -249
- package/src/hooks/guard/task-context.ts +45 -45
- package/src/hooks/guard/tool-execute-after.ts +209 -209
- package/src/hooks/guard/tool-execute-before.ts +102 -102
- package/src/hooks/guard/tsconfig.json +9 -9
- package/src/hooks/guard/types.ts +45 -45
- package/src/hooks/guard/verification-reminders.ts +197 -197
- package/src/hooks/guard/write-edit-tool-policy.ts +5 -5
- package/src/hooks/hashline-edit-diff-enhancer/hook.ts +106 -106
- package/src/hooks/hashline-read-enhancer/hook.ts +193 -193
- package/src/hooks/hashline-read-enhancer/index.ts +1 -1
- package/src/hooks/index.ts +58 -58
- package/src/hooks/interactive-bash-session/constants.ts +13 -13
- package/src/hooks/interactive-bash-session/hook.ts +125 -125
- package/src/hooks/interactive-bash-session/index.ts +3 -3
- package/src/hooks/interactive-bash-session/interactive-bash-session-tracker.ts +119 -119
- package/src/hooks/interactive-bash-session/parser.ts +118 -118
- package/src/hooks/interactive-bash-session/state-manager.ts +35 -35
- package/src/hooks/interactive-bash-session/storage.ts +59 -59
- package/src/hooks/interactive-bash-session/tmux-command-parser.ts +125 -125
- package/src/hooks/interactive-bash-session/types.ts +11 -11
- package/src/hooks/json-error-recovery/hook.ts +58 -58
- package/src/hooks/json-error-recovery/index.ts +6 -6
- package/src/hooks/keyword-detector/AGENTS.md +57 -57
- package/src/hooks/keyword-detector/analyze/default.ts +28 -28
- package/src/hooks/keyword-detector/analyze/index.ts +1 -1
- package/src/hooks/keyword-detector/constants.ts +45 -45
- package/src/hooks/keyword-detector/detector.ts +53 -53
- package/src/hooks/keyword-detector/hook.ts +143 -143
- package/src/hooks/keyword-detector/index.ts +5 -5
- package/src/hooks/keyword-detector/search/default.ts +20 -20
- package/src/hooks/keyword-detector/search/index.ts +1 -1
- package/src/hooks/keyword-detector/types.ts +4 -4
- package/src/hooks/keyword-detector/ultrawork/default.ts +302 -302
- package/src/hooks/keyword-detector/ultrawork/gemini.ts +290 -290
- package/src/hooks/keyword-detector/ultrawork/gpt.ts +173 -173
- package/src/hooks/keyword-detector/ultrawork/index.ts +56 -56
- package/src/hooks/keyword-detector/ultrawork/planner.ts +140 -140
- package/src/hooks/keyword-detector/ultrawork/source-detector.ts +65 -65
- package/src/hooks/legacy-plugin-toast/auto-migrate-runner.ts +2 -2
- package/src/hooks/legacy-plugin-toast/auto-migrate.ts +64 -64
- package/src/hooks/legacy-plugin-toast/hook.ts +68 -68
- package/src/hooks/legacy-plugin-toast/index.ts +1 -1
- package/src/hooks/legacy-plugin-toast/plugin-entry-migrator.ts +1 -1
- package/src/hooks/model-fallback/chat-message-fallback-handler.ts +74 -74
- package/src/hooks/model-fallback/hook.ts +201 -201
- package/src/hooks/model-fallback/next-fallback.ts +84 -84
- package/src/hooks/no-bob-gpt/hook.ts +56 -56
- package/src/hooks/no-bob-gpt/index.ts +1 -1
- package/src/hooks/no-coder-non-gpt/hook.ts +67 -67
- package/src/hooks/no-coder-non-gpt/index.ts +1 -1
- package/src/hooks/non-interactive-env/constants.ts +70 -70
- package/src/hooks/non-interactive-env/detector.ts +19 -19
- package/src/hooks/non-interactive-env/index.ts +5 -5
- package/src/hooks/non-interactive-env/non-interactive-env-hook.ts +73 -73
- package/src/hooks/non-interactive-env/types.ts +3 -3
- package/src/hooks/preemptive-compaction-degradation-monitor.ts +212 -212
- package/src/hooks/preemptive-compaction-no-text-tail.ts +70 -70
- package/src/hooks/preemptive-compaction.ts +218 -218
- package/src/hooks/question-label-truncator/hook.ts +62 -62
- package/src/hooks/question-label-truncator/index.ts +1 -1
- package/src/hooks/ralph-loop/AGENTS.md +62 -62
- package/src/hooks/ralph-loop/command-arguments.ts +30 -30
- package/src/hooks/ralph-loop/completion-handler.ts +65 -65
- package/src/hooks/ralph-loop/completion-promise-detector-test-input.ts +23 -23
- package/src/hooks/ralph-loop/completion-promise-detector.ts +165 -165
- package/src/hooks/ralph-loop/constants.ts +7 -7
- package/src/hooks/ralph-loop/continuation-prompt-builder.ts +77 -77
- package/src/hooks/ralph-loop/continuation-prompt-injector.ts +91 -91
- package/src/hooks/ralph-loop/index.ts +6 -6
- package/src/hooks/ralph-loop/iteration-continuation.ts +64 -64
- package/src/hooks/ralph-loop/logician-verification-detector.ts +88 -88
- package/src/hooks/ralph-loop/loop-session-recovery.ts +33 -33
- package/src/hooks/ralph-loop/loop-state-controller.ts +178 -178
- package/src/hooks/ralph-loop/message-storage-directory.ts +1 -1
- package/src/hooks/ralph-loop/pending-verification-handler.ts +152 -152
- package/src/hooks/ralph-loop/ralph-loop-event-handler.ts +231 -231
- package/src/hooks/ralph-loop/ralph-loop-hook.ts +90 -90
- package/src/hooks/ralph-loop/session-event-handler.ts +56 -56
- package/src/hooks/ralph-loop/session-reset-strategy.ts +69 -69
- package/src/hooks/ralph-loop/storage.ts +164 -164
- package/src/hooks/ralph-loop/types.ts +25 -25
- package/src/hooks/ralph-loop/verification-failure-handler.ts +103 -103
- package/src/hooks/ralph-loop/with-timeout.ts +20 -20
- package/src/hooks/read-image-resizer/hook.ts +209 -209
- package/src/hooks/read-image-resizer/image-dimensions.ts +191 -191
- package/src/hooks/read-image-resizer/image-resizer.ts +191 -191
- package/src/hooks/read-image-resizer/index.ts +1 -1
- package/src/hooks/read-image-resizer/png-fallback-resizer.ts +359 -359
- package/src/hooks/read-image-resizer/types.ts +16 -16
- package/src/hooks/rules-injector/AGENTS.md +53 -53
- package/src/hooks/rules-injector/cache.ts +27 -27
- package/src/hooks/rules-injector/constants.ts +31 -31
- package/src/hooks/rules-injector/finder.ts +3 -3
- package/src/hooks/rules-injector/hook.ts +94 -94
- package/src/hooks/rules-injector/index.ts +2 -2
- package/src/hooks/rules-injector/injector.ts +189 -189
- package/src/hooks/rules-injector/matcher.ts +63 -63
- package/src/hooks/rules-injector/output-path.ts +22 -22
- package/src/hooks/rules-injector/parser.ts +211 -211
- package/src/hooks/rules-injector/project-root-finder.ts +36 -36
- package/src/hooks/rules-injector/rule-distance.ts +53 -53
- package/src/hooks/rules-injector/rule-file-finder.ts +139 -139
- package/src/hooks/rules-injector/rule-file-scanner.ts +55 -55
- package/src/hooks/rules-injector/storage.ts +59 -59
- package/src/hooks/rules-injector/types.ts +57 -57
- package/src/hooks/runtime-fallback/AGENTS.md +102 -102
- package/src/hooks/runtime-fallback/agent-resolver.ts +50 -50
- package/src/hooks/runtime-fallback/auto-retry-signal.ts +32 -32
- package/src/hooks/runtime-fallback/auto-retry.ts +228 -228
- package/src/hooks/runtime-fallback/chat-message-handler.ts +62 -62
- package/src/hooks/runtime-fallback/constants.ts +47 -47
- package/src/hooks/runtime-fallback/error-classifier.ts +183 -183
- package/src/hooks/runtime-fallback/event-handler.ts +213 -213
- package/src/hooks/runtime-fallback/fallback-bootstrap-model.ts +63 -63
- package/src/hooks/runtime-fallback/fallback-models.ts +86 -86
- package/src/hooks/runtime-fallback/fallback-retry-dispatcher.ts +55 -55
- package/src/hooks/runtime-fallback/fallback-state.ts +74 -74
- package/src/hooks/runtime-fallback/hook.ts +87 -87
- package/src/hooks/runtime-fallback/index.ts +2 -2
- package/src/hooks/runtime-fallback/last-user-retry-parts.ts +20 -20
- package/src/hooks/runtime-fallback/message-update-handler.ts +168 -168
- package/src/hooks/runtime-fallback/retry-model-payload.ts +30 -30
- package/src/hooks/runtime-fallback/session-messages.ts +38 -38
- package/src/hooks/runtime-fallback/session-status-handler.ts +126 -126
- package/src/hooks/runtime-fallback/types.ts +77 -77
- package/src/hooks/runtime-fallback/visible-assistant-response.ts +80 -80
- package/src/hooks/session-notification-content.ts +145 -145
- package/src/hooks/session-notification-formatting.ts +25 -25
- package/src/hooks/session-notification-scheduler.ts +188 -188
- package/src/hooks/session-notification-sender.ts +117 -117
- package/src/hooks/session-notification-utils.ts +80 -80
- package/src/hooks/session-notification.ts +219 -219
- package/src/hooks/session-recovery/AGENTS.md +59 -59
- package/src/hooks/session-recovery/constants.ts +5 -5
- package/src/hooks/session-recovery/detect-error-type.ts +102 -102
- package/src/hooks/session-recovery/hook.ts +166 -166
- package/src/hooks/session-recovery/index.ts +7 -7
- package/src/hooks/session-recovery/recover-empty-content-message-sdk.ts +201 -201
- package/src/hooks/session-recovery/recover-thinking-block-order.ts +137 -137
- package/src/hooks/session-recovery/recover-thinking-disabled-violation.ts +75 -75
- package/src/hooks/session-recovery/recover-tool-result-missing.ts +108 -108
- package/src/hooks/session-recovery/recover-unavailable-tool.ts +108 -108
- package/src/hooks/session-recovery/resume.ts +49 -49
- package/src/hooks/session-recovery/storage/empty-messages.ts +47 -47
- package/src/hooks/session-recovery/storage/empty-text.ts +118 -118
- package/src/hooks/session-recovery/storage/message-dir.ts +1 -1
- package/src/hooks/session-recovery/storage/messages-reader.ts +83 -83
- package/src/hooks/session-recovery/storage/orphan-thinking-search.ts +43 -43
- package/src/hooks/session-recovery/storage/part-content.ts +28 -28
- package/src/hooks/session-recovery/storage/part-id.ts +5 -5
- package/src/hooks/session-recovery/storage/parts-reader.ts +56 -56
- package/src/hooks/session-recovery/storage/text-part-injector.ts +63 -63
- package/src/hooks/session-recovery/storage/thinking-block-search.ts +42 -42
- package/src/hooks/session-recovery/storage/thinking-prepend.ts +223 -223
- package/src/hooks/session-recovery/storage/thinking-strip.ts +67 -67
- package/src/hooks/session-recovery/storage.ts +34 -34
- package/src/hooks/session-recovery/types.ts +101 -101
- package/src/hooks/session-todo-status.ts +20 -20
- package/src/hooks/shared/compaction-model-resolver.ts +34 -34
- package/src/hooks/shared/shared/compaction-model-resolver.ts +34 -34
- package/src/hooks/start-work/context-info-builder.ts +319 -319
- package/src/hooks/start-work/index.ts +4 -4
- package/src/hooks/start-work/parse-user-request.ts +32 -32
- package/src/hooks/start-work/start-work-hook.ts +135 -135
- package/src/hooks/start-work/worktree-block.ts +11 -11
- package/src/hooks/start-work/worktree-detector.ts +77 -77
- package/src/hooks/stop-continuation-guard/hook.ts +122 -122
- package/src/hooks/stop-continuation-guard/index.ts +2 -2
- package/src/hooks/strategist-md-only/agent-matcher.ts +5 -5
- package/src/hooks/strategist-md-only/agent-resolution.ts +70 -70
- package/src/hooks/strategist-md-only/constants.ts +78 -78
- package/src/hooks/strategist-md-only/hook.ts +82 -82
- package/src/hooks/strategist-md-only/index.ts +2 -2
- package/src/hooks/strategist-md-only/path-policy.ts +41 -41
- package/src/hooks/sub-notepad/constants.ts +29 -29
- package/src/hooks/sub-notepad/hook.ts +44 -44
- package/src/hooks/sub-notepad/index.ts +3 -3
- package/src/hooks/task-reminder/hook.ts +59 -59
- package/src/hooks/task-reminder/index.ts +1 -1
- package/src/hooks/task-resume-info/hook.ts +39 -39
- package/src/hooks/task-resume-info/index.ts +1 -1
- package/src/hooks/tasks-todowrite-disabler/constants.ts +30 -30
- package/src/hooks/tasks-todowrite-disabler/hook.ts +34 -34
- package/src/hooks/tasks-todowrite-disabler/index.ts +2 -2
- package/src/hooks/think-mode/detector.ts +59 -59
- package/src/hooks/think-mode/hook.ts +76 -76
- package/src/hooks/think-mode/index.ts +5 -5
- package/src/hooks/think-mode/switcher.ts +100 -100
- package/src/hooks/think-mode/types.ts +16 -16
- package/src/hooks/thinking-block-validator/hook.ts +181 -181
- package/src/hooks/thinking-block-validator/index.ts +1 -1
- package/src/hooks/todo-continuation-enforcer/AGENTS.md +65 -65
- package/src/hooks/todo-continuation-enforcer/abort-detection.ts +17 -17
- package/src/hooks/todo-continuation-enforcer/compaction-guard.ts +39 -39
- package/src/hooks/todo-continuation-enforcer/constants.ts +25 -25
- package/src/hooks/todo-continuation-enforcer/continuation-injection.ts +222 -222
- package/src/hooks/todo-continuation-enforcer/countdown.ts +86 -86
- package/src/hooks/todo-continuation-enforcer/handler.ts +99 -99
- package/src/hooks/todo-continuation-enforcer/idle-event.ts +225 -225
- package/src/hooks/todo-continuation-enforcer/index.ts +59 -59
- package/src/hooks/todo-continuation-enforcer/message-directory.ts +1 -1
- package/src/hooks/todo-continuation-enforcer/non-idle-events.ts +107 -107
- package/src/hooks/todo-continuation-enforcer/pending-question-detection.ts +40 -40
- package/src/hooks/todo-continuation-enforcer/resolve-message-info.ts +48 -48
- package/src/hooks/todo-continuation-enforcer/session-state.ts +283 -283
- package/src/hooks/todo-continuation-enforcer/stagnation-detection.ts +36 -36
- package/src/hooks/todo-continuation-enforcer/todo.ts +11 -11
- package/src/hooks/todo-continuation-enforcer/token-limit-detection.ts +38 -38
- package/src/hooks/todo-continuation-enforcer/types.ts +74 -74
- package/src/hooks/todo-description-override/description.ts +28 -28
- package/src/hooks/todo-description-override/hook.ts +14 -14
- package/src/hooks/todo-description-override/index.ts +1 -1
- package/src/hooks/tool-output-truncator.ts +66 -66
- package/src/hooks/tool-pair-validator/hook.ts +184 -184
- package/src/hooks/tool-pair-validator/index.ts +1 -1
- package/src/hooks/unstable-agent-babysitter/index.ts +9 -9
- package/src/hooks/unstable-agent-babysitter/task-message-analyzer.ts +110 -110
- package/src/hooks/unstable-agent-babysitter/unstable-agent-babysitter-hook.ts +238 -238
- package/src/hooks/webfetch-redirect-guard/constants.ts +11 -11
- package/src/hooks/webfetch-redirect-guard/hook.ts +123 -123
- package/src/hooks/webfetch-redirect-guard/index.ts +1 -1
- package/src/hooks/webfetch-redirect-guard/redirect-resolution.ts +89 -89
- package/src/hooks/write-existing-file-guard/hook.ts +108 -108
- package/src/hooks/write-existing-file-guard/index.ts +1 -1
- package/src/hooks/write-existing-file-guard/session-read-permissions.ts +36 -36
- package/src/hooks/write-existing-file-guard/tool-execute-before-handler.ts +176 -176
- package/src/index.ts +285 -284
- package/src/internals/plugins/pty/LICENSE +21 -21
- package/src/internals/plugins/pty/constants.ts +7 -7
- package/src/internals/plugins/pty/plugin.ts +28 -28
- package/src/internals/plugins/pty/pty/buffer.ts +75 -75
- package/src/internals/plugins/pty/pty/formatters.ts +22 -22
- package/src/internals/plugins/pty/pty/manager.ts +175 -175
- package/src/internals/plugins/pty/pty/notification-manager.ts +75 -75
- package/src/internals/plugins/pty/pty/output-manager.ts +29 -29
- package/src/internals/plugins/pty/pty/permissions.ts +115 -115
- package/src/internals/plugins/pty/pty/session-lifecycle.ts +161 -161
- package/src/internals/plugins/pty/pty/tools/kill.ts +41 -41
- package/src/internals/plugins/pty/pty/tools/kill.txt +25 -25
- package/src/internals/plugins/pty/pty/tools/list.ts +25 -25
- package/src/internals/plugins/pty/pty/tools/list.txt +22 -22
- package/src/internals/plugins/pty/pty/tools/read.ts +234 -234
- package/src/internals/plugins/pty/pty/tools/read.txt +39 -39
- package/src/internals/plugins/pty/pty/tools/spawn.ts +71 -71
- package/src/internals/plugins/pty/pty/tools/spawn.txt +47 -47
- package/src/internals/plugins/pty/pty/tools/write.ts +96 -96
- package/src/internals/plugins/pty/pty/tools/write.txt +28 -28
- package/src/internals/plugins/pty/pty/types.ts +67 -67
- package/src/internals/plugins/pty/pty/utils.ts +21 -21
- package/src/internals/plugins/pty/pty/wildcard.ts +62 -62
- package/src/internals/plugins/pty/shared/constants.ts +7 -7
- package/src/internals/plugins/pty/types.ts +7 -7
- package/src/internals/plugins/subtask2/LICENSE +128 -128
- package/src/internals/plugins/subtask2/commands/index.ts +7 -7
- package/src/internals/plugins/subtask2/commands/loader.ts +39 -39
- package/src/internals/plugins/subtask2/commands/manifest.ts +64 -64
- package/src/internals/plugins/subtask2/commands/resolver.ts +28 -28
- package/src/internals/plugins/subtask2/core/plugin.ts +52 -52
- package/src/internals/plugins/subtask2/core/state.ts +764 -764
- package/src/internals/plugins/subtask2/features/auto.ts +57 -57
- package/src/internals/plugins/subtask2/features/index.ts +9 -9
- package/src/internals/plugins/subtask2/features/inline-subtasks.ts +205 -205
- package/src/internals/plugins/subtask2/features/parallel.ts +148 -148
- package/src/internals/plugins/subtask2/features/results.ts +48 -48
- package/src/internals/plugins/subtask2/features/returns.ts +273 -273
- package/src/internals/plugins/subtask2/features/turns.ts +190 -190
- package/src/internals/plugins/subtask2/hooks/command-hooks.ts +283 -283
- package/src/internals/plugins/subtask2/hooks/message-hooks.ts +603 -603
- package/src/internals/plugins/subtask2/hooks/session-idle-hook.ts +358 -358
- package/src/internals/plugins/subtask2/hooks/tool-hooks.ts +309 -309
- package/src/internals/plugins/subtask2/loop.ts +122 -122
- package/src/internals/plugins/subtask2/parsing/auto.ts +33 -33
- package/src/internals/plugins/subtask2/parsing/commands.ts +154 -154
- package/src/internals/plugins/subtask2/parsing/frontmatter.ts +20 -20
- package/src/internals/plugins/subtask2/parsing/index.ts +10 -10
- package/src/internals/plugins/subtask2/parsing/overrides.ts +68 -68
- package/src/internals/plugins/subtask2/parsing/parallel.ts +88 -88
- package/src/internals/plugins/subtask2/parsing/turns.ts +78 -78
- package/src/internals/plugins/subtask2/types.ts +41 -41
- package/src/internals/plugins/subtask2/utils/config.ts +100 -100
- package/src/internals/plugins/subtask2/utils/index.ts +7 -7
- package/src/internals/plugins/subtask2/utils/logger.ts +67 -67
- package/src/internals/plugins/subtask2/utils/prompts.ts +117 -117
- package/src/internals/plugins/websearch-cited/LICENSE +214 -214
- package/src/internals/plugins/websearch-cited/codex_prompt.txt +79 -79
- package/src/internals/plugins/websearch-cited/google.ts +749 -749
- package/src/internals/plugins/websearch-cited/index.ts +301 -301
- package/src/internals/plugins/websearch-cited/openai.ts +407 -407
- package/src/internals/plugins/websearch-cited/openrouter.ts +190 -190
- package/src/internals/plugins/websearch-cited/types.ts +7 -7
- package/src/lsp/index.ts +15 -15
- package/src/mcp/context7.ts +9 -9
- package/src/mcp/grep-app.ts +6 -6
- package/src/mcp/index.ts +54 -87
- package/src/mcp/omo-mcp-index.ts +30 -35
- package/src/mcp/registry.ts +132 -0
- package/src/mcp/types.ts +19 -9
- package/src/mcp/websearch.ts +44 -44
- package/src/permissions/index.ts +25 -25
- package/src/plugin/AGENTS.md +54 -54
- package/src/plugin/available-categories.ts +24 -24
- package/src/plugin/chat-headers.ts +141 -141
- package/src/plugin/chat-message.ts +309 -309
- package/src/plugin/chat-params.ts +182 -182
- package/src/plugin/command-execute-before.ts +80 -80
- package/src/plugin/event.ts +639 -639
- package/src/plugin/hooks/create-continuation-hooks.ts +128 -128
- package/src/plugin/hooks/create-core-hooks.ts +47 -47
- package/src/plugin/hooks/create-session-hooks.ts +286 -286
- package/src/plugin/hooks/create-skill-hooks.ts +50 -50
- package/src/plugin/hooks/create-tool-guard-hooks.ts +159 -159
- package/src/plugin/hooks/create-transform-hooks.ts +85 -85
- package/src/plugin/messages-transform.ts +28 -28
- package/src/plugin/normalize-tool-arg-schemas.ts +75 -75
- package/src/plugin/recent-synthetic-idles.ts +20 -20
- package/src/plugin/session-agent-resolver.ts +37 -37
- package/src/plugin/session-status-normalizer.ts +22 -22
- package/src/plugin/skill-context.ts +132 -132
- package/src/plugin/system-transform.ts +6 -6
- package/src/plugin/tool-execute-after.ts +178 -178
- package/src/plugin/tool-execute-before.ts +222 -222
- package/src/plugin/tool-registry.ts +282 -282
- package/src/plugin/types.ts +26 -26
- package/src/plugin/ultrawork-db-model-override.ts +142 -142
- package/src/plugin/ultrawork-model-override.ts +196 -196
- package/src/plugin/ultrawork-variant-availability.ts +51 -51
- package/src/plugin/unstable-agent-babysitter.ts +41 -41
- package/src/plugin-config.ts +314 -314
- package/src/plugin-dispose.ts +51 -51
- package/src/plugin-handlers/AGENTS.md +92 -92
- package/src/plugin-handlers/agent-config-handler.ts +502 -502
- package/src/plugin-handlers/agent-key-remapper.ts +39 -39
- package/src/plugin-handlers/agent-override-protection.ts +38 -38
- package/src/plugin-handlers/agent-priority-order.ts +63 -63
- package/src/plugin-handlers/category-config-resolver.ts +9 -9
- package/src/plugin-handlers/command-config-handler.ts +105 -105
- package/src/plugin-handlers/config-handler.ts +61 -61
- package/src/plugin-handlers/index.ts +10 -10
- package/src/plugin-handlers/mcp-config-handler.ts +205 -205
- package/src/plugin-handlers/plan-model-inheritance.ts +27 -27
- package/src/plugin-handlers/plugin-components-loader.ts +70 -70
- package/src/plugin-handlers/provider-config-handler.ts +73 -73
- package/src/plugin-handlers/strategist-agent-config-builder.ts +128 -128
- package/src/plugin-handlers/tool-config-handler.ts +193 -193
- package/src/plugin-interface.ts +83 -83
- package/src/plugin-state.ts +18 -18
- package/src/shared/AGENTS.md +54 -54
- package/src/shared/agent-display-names.ts +182 -182
- package/src/shared/agent-tool-restrictions.ts +80 -80
- package/src/shared/agent-variant.ts +101 -101
- package/src/shared/agents-config-dir.ts +23 -23
- package/src/shared/archive-entry-validator.ts +83 -83
- package/src/shared/background-output-consumption.ts +69 -69
- package/src/shared/binary-downloader.ts +127 -127
- package/src/shared/claude-config-dir.ts +16 -16
- package/src/shared/closure-protocol.ts +53 -53
- package/src/shared/command-executor/embedded-commands.ts +26 -26
- package/src/shared/command-executor/execute-command.ts +28 -28
- package/src/shared/command-executor/execute-hook-command.ts +129 -129
- package/src/shared/command-executor/home-directory.ts +5 -5
- package/src/shared/command-executor/resolve-commands-in-text.ts +49 -49
- package/src/shared/command-executor/shell-path.ts +27 -27
- package/src/shared/command-executor.ts +5 -5
- package/src/shared/compaction-agent-config-checkpoint.ts +42 -42
- package/src/shared/compaction-marker.ts +61 -61
- package/src/shared/config-errors.ts +18 -18
- package/src/shared/connected-providers-cache.ts +215 -215
- package/src/shared/contains-path.ts +50 -50
- package/src/shared/context-limit-resolver.ts +42 -42
- package/src/shared/data-path.ts +64 -64
- package/src/shared/deep-merge.ts +53 -53
- package/src/shared/disabled-tools.ts +19 -19
- package/src/shared/dynamic-truncator.ts +222 -222
- package/src/shared/external-plugin-detector.ts +139 -139
- package/src/shared/fallback-chain-from-models.ts +124 -124
- package/src/shared/fallback-model-availability.ts +102 -102
- package/src/shared/file-reference-resolver.ts +99 -99
- package/src/shared/file-utils.ts +34 -34
- package/src/shared/first-message-variant.ts +28 -28
- package/src/shared/frontmatter.ts +31 -31
- package/src/shared/git-worktree/collect-git-diff-stats.ts +56 -56
- package/src/shared/git-worktree/format-file-changes.ts +46 -46
- package/src/shared/git-worktree/index.ts +7 -7
- package/src/shared/git-worktree/parse-diff-numstat.ts +27 -27
- package/src/shared/git-worktree/parse-status-porcelain-line.ts +27 -27
- package/src/shared/git-worktree/parse-status-porcelain.ts +15 -15
- package/src/shared/git-worktree/types.ts +8 -8
- package/src/shared/hook-disabled.ts +22 -22
- package/src/shared/index.ts +80 -80
- package/src/shared/internal-initiator-marker.ts +18 -18
- package/src/shared/is-abort-error.ts +20 -20
- package/src/shared/json-file-cache-store.ts +98 -98
- package/src/shared/jsonc-parser.ts +98 -98
- package/src/shared/known-variants.ts +16 -16
- package/src/shared/legacy-plugin-warning.ts +68 -68
- package/src/shared/load-opencode-plugins.ts +60 -60
- package/src/shared/log-legacy-plugin-startup-warning.ts +46 -46
- package/src/shared/logger.ts +48 -48
- package/src/shared/merge-categories.ts +18 -18
- package/src/shared/migrate-legacy-config-file.ts +66 -66
- package/src/shared/migrate-legacy-plugin-entry.ts +75 -75
- package/src/shared/migration/agent-category.ts +60 -60
- package/src/shared/migration/agent-names.ts +100 -100
- package/src/shared/migration/config-migration.ts +210 -210
- package/src/shared/migration/hook-names.ts +40 -40
- package/src/shared/migration/migrations-sidecar.ts +92 -92
- package/src/shared/migration/model-versions.ts +50 -50
- package/src/shared/migration.ts +5 -5
- package/src/shared/model-availability.ts +294 -294
- package/src/shared/model-capabilities/bundled-snapshot.ts +15 -15
- package/src/shared/model-capabilities/get-model-capabilities.ts +140 -140
- package/src/shared/model-capabilities/index.ts +9 -9
- package/src/shared/model-capabilities/runtime-model-readers.ts +190 -190
- package/src/shared/model-capabilities/types.ts +80 -80
- package/src/shared/model-capabilities-cache.ts +213 -213
- package/src/shared/model-capability-aliases.ts +108 -108
- package/src/shared/model-capability-guardrails.ts +149 -149
- package/src/shared/model-capability-heuristics.ts +32 -32
- package/src/shared/model-error-classifier.ts +214 -214
- package/src/shared/model-format-normalizer.ts +20 -20
- package/src/shared/model-normalization.ts +8 -8
- package/src/shared/model-requirements.ts +26 -26
- package/src/shared/model-resolution-pipeline.ts +216 -216
- package/src/shared/model-resolution-types.ts +41 -41
- package/src/shared/model-resolver.ts +106 -106
- package/src/shared/model-sanitizer.ts +12 -12
- package/src/shared/model-settings-compatibility.ts +200 -200
- package/src/shared/model-suggestion-retry.ts +182 -182
- package/src/shared/normalize-sdk-response.ts +36 -36
- package/src/shared/opencode-command-dirs.ts +36 -36
- package/src/shared/opencode-config-dir-types.ts +15 -15
- package/src/shared/opencode-config-dir.ts +135 -135
- package/src/shared/opencode-http-api.ts +139 -139
- package/src/shared/opencode-message-dir.ts +29 -29
- package/src/shared/opencode-server-auth.ts +190 -190
- package/src/shared/opencode-storage-detection.ts +33 -33
- package/src/shared/opencode-storage-paths.ts +6 -6
- package/src/shared/opencode-version.ts +80 -80
- package/src/shared/parse-tools-config.ts +25 -25
- package/src/shared/pattern-matcher.ts +46 -46
- package/src/shared/permission-compat.ts +86 -86
- package/src/shared/plugin-command-discovery.ts +28 -28
- package/src/shared/plugin-entry-migrator.ts +21 -21
- package/src/shared/plugin-identity.ts +8 -8
- package/src/shared/port-utils.ts +48 -48
- package/src/shared/project-discovery-dirs.ts +101 -101
- package/src/shared/prompt-timeout-context.ts +49 -49
- package/src/shared/prompt-tools.ts +35 -35
- package/src/shared/provider-model-id-transform.ts +58 -58
- package/src/shared/question-denied-session-permission.ts +9 -9
- package/src/shared/record-type-guard.ts +3 -3
- package/src/shared/resolve-agent-definition-paths.ts +22 -22
- package/src/shared/retry-status-utils.ts +19 -19
- package/src/shared/runtime-plugin-config.ts +98 -98
- package/src/shared/safe-create-hook.ts +24 -24
- package/src/shared/session-category-registry.ts +27 -27
- package/src/shared/session-cursor.ts +108 -108
- package/src/shared/session-directory-resolver.ts +41 -41
- package/src/shared/session-injected-paths.ts +59 -59
- package/src/shared/session-model-state.ts +15 -15
- package/src/shared/session-prompt-params-helpers.ts +31 -31
- package/src/shared/session-prompt-params-state.ts +37 -37
- package/src/shared/session-tools-store.ts +18 -18
- package/src/shared/session-utils.ts +25 -25
- package/src/shared/shell-env.ts +175 -175
- package/src/shared/skill-path-resolver.ts +26 -26
- package/src/shared/snake-case.ts +44 -44
- package/src/shared/spawn-with-windows-hide.ts +84 -84
- package/src/shared/system-directive.ts +67 -67
- package/src/shared/task-system-enabled.ts +9 -9
- package/src/shared/tmux/constants.ts +12 -12
- package/src/shared/tmux/index.ts +3 -3
- package/src/shared/tmux/tmux-utils/environment.ts +13 -13
- package/src/shared/tmux/tmux-utils/layout.ts +96 -96
- package/src/shared/tmux/tmux-utils/pane-close.ts +48 -48
- package/src/shared/tmux/tmux-utils/pane-dimensions.ts +28 -28
- package/src/shared/tmux/tmux-utils/pane-replace.ts +73 -73
- package/src/shared/tmux/tmux-utils/pane-spawn.ts +94 -94
- package/src/shared/tmux/tmux-utils/server-health.ts +62 -62
- package/src/shared/tmux/tmux-utils/session-spawn.ts +145 -145
- package/src/shared/tmux/tmux-utils/window-spawn.ts +93 -93
- package/src/shared/tmux/tmux-utils.ts +15 -15
- package/src/shared/tmux/types.ts +4 -4
- package/src/shared/tool-name.ts +27 -27
- package/src/shared/truncate-description.ts +11 -11
- package/src/shared/vision-capable-models-cache.ts +17 -17
- package/src/shared/write-file-atomically.ts +31 -31
- package/src/shared/zip-entry-listing/powershell-zip-entry-listing.ts +99 -99
- package/src/shared/zip-entry-listing/python-zip-entry-listing.ts +55 -55
- package/src/shared/zip-entry-listing/read-zip-symlink-target.ts +23 -23
- package/src/shared/zip-entry-listing/tar-zip-entry-listing.ts +93 -93
- package/src/shared/zip-entry-listing/zipinfo-zip-entry-listing.ts +72 -72
- package/src/shared/zip-entry-listing.ts +13 -13
- package/src/shared/zip-extractor.ts +118 -118
- package/src/skills/index.ts +56 -56
- package/src/testing/module-mock-lifecycle.ts +143 -143
- package/src/tools/AGENTS.md +108 -108
- package/src/tools/ast-grep/cli-binary-path-resolution.ts +60 -60
- package/src/tools/ast-grep/cli.ts +177 -177
- package/src/tools/ast-grep/constants.ts +5 -5
- package/src/tools/ast-grep/downloader.ts +119 -119
- package/src/tools/ast-grep/environment-check.ts +89 -89
- package/src/tools/ast-grep/index.ts +5 -5
- package/src/tools/ast-grep/language-support.ts +63 -63
- package/src/tools/ast-grep/process-output-timeout.ts +28 -28
- package/src/tools/ast-grep/result-formatter.ts +102 -102
- package/src/tools/ast-grep/sg-cli-path.ts +102 -102
- package/src/tools/ast-grep/sg-compact-json-output.ts +54 -54
- package/src/tools/ast-grep/tools.ts +117 -117
- package/src/tools/ast-grep/types.ts +61 -61
- package/src/tools/background-task/AGENTS.md +53 -53
- package/src/tools/background-task/clients.ts +32 -32
- package/src/tools/background-task/constants.ts +9 -9
- package/src/tools/background-task/create-background-cancel.ts +115 -115
- package/src/tools/background-task/create-background-output.ts +159 -159
- package/src/tools/background-task/create-background-task.ts +126 -126
- package/src/tools/background-task/delay.ts +3 -3
- package/src/tools/background-task/full-session-format.ts +148 -148
- package/src/tools/background-task/index.ts +8 -8
- package/src/tools/background-task/message-dir.ts +1 -1
- package/src/tools/background-task/session-messages.ts +22 -22
- package/src/tools/background-task/task-result-format.ts +113 -113
- package/src/tools/background-task/task-status-format.ts +72 -72
- package/src/tools/background-task/time-format.ts +30 -30
- package/src/tools/background-task/tools.ts +11 -11
- package/src/tools/background-task/truncate-text.ts +4 -4
- package/src/tools/background-task/types.ts +72 -72
- package/src/tools/call-omo-agent/AGENTS.md +51 -51
- package/src/tools/call-omo-agent/agent-resolver.ts +64 -64
- package/src/tools/call-omo-agent/background-agent-executor.ts +91 -91
- package/src/tools/call-omo-agent/background-executor.ts +98 -98
- package/src/tools/call-omo-agent/completion-poller.ts +65 -65
- package/src/tools/call-omo-agent/constants.ts +23 -23
- package/src/tools/call-omo-agent/index.ts +3 -3
- package/src/tools/call-omo-agent/message-dir.ts +1 -1
- package/src/tools/call-omo-agent/message-processor.ts +86 -86
- package/src/tools/call-omo-agent/message-storage-directory.ts +1 -1
- package/src/tools/call-omo-agent/session-creator.ts +70 -70
- package/src/tools/call-omo-agent/subagent-session-creator.ts +74 -74
- package/src/tools/call-omo-agent/sync-executor.ts +148 -148
- package/src/tools/call-omo-agent/tool-context-with-metadata.ts +10 -10
- package/src/tools/call-omo-agent/tools.ts +192 -192
- package/src/tools/call-omo-agent/types.ts +34 -34
- package/src/tools/delegate-task/AGENTS.md +58 -58
- package/src/tools/delegate-task/anthropic-categories.ts +62 -62
- package/src/tools/delegate-task/available-models.ts +64 -64
- package/src/tools/delegate-task/background-continuation.ts +68 -68
- package/src/tools/delegate-task/background-task.ts +165 -165
- package/src/tools/delegate-task/builtin-categories.ts +33 -33
- package/src/tools/delegate-task/builtin-category-definition.ts +8 -8
- package/src/tools/delegate-task/cancel-unstable-agent-task.ts +19 -19
- package/src/tools/delegate-task/categories.ts +77 -77
- package/src/tools/delegate-task/category-resolver.ts +310 -310
- package/src/tools/delegate-task/constants.ts +351 -351
- package/src/tools/delegate-task/delegated-model-config.ts +20 -20
- package/src/tools/delegate-task/error-formatting.ts +51 -51
- package/src/tools/delegate-task/executor-types.ts +39 -39
- package/src/tools/delegate-task/executor.ts +16 -16
- package/src/tools/delegate-task/fallback-entry-resolution.ts +27 -27
- package/src/tools/delegate-task/fallback-entry-settings.ts +20 -20
- package/src/tools/delegate-task/google-categories.ts +130 -130
- package/src/tools/delegate-task/index.ts +4 -4
- package/src/tools/delegate-task/kimi-categories.ts +40 -40
- package/src/tools/delegate-task/model-selection.ts +201 -201
- package/src/tools/delegate-task/model-string-parser.ts +63 -63
- package/src/tools/delegate-task/openai-categories.ts +128 -128
- package/src/tools/delegate-task/parent-context-resolver.ts +47 -47
- package/src/tools/delegate-task/prompt-builder.ts +107 -107
- package/src/tools/delegate-task/resolve-call-id.ts +5 -5
- package/src/tools/delegate-task/skill-resolver.ts +22 -22
- package/src/tools/delegate-task/sub-agent.ts +70 -70
- package/src/tools/delegate-task/subagent-discovery.ts +152 -152
- package/src/tools/delegate-task/subagent-resolver.ts +225 -225
- package/src/tools/delegate-task/sync-continuation-deps.ts +9 -9
- package/src/tools/delegate-task/sync-continuation.ts +149 -149
- package/src/tools/delegate-task/sync-prompt-sender.ts +137 -137
- package/src/tools/delegate-task/sync-result-fetcher.ts +60 -60
- package/src/tools/delegate-task/sync-session-creator.ts +29 -29
- package/src/tools/delegate-task/sync-session-poller.ts +188 -188
- package/src/tools/delegate-task/sync-task-deps.ts +13 -13
- package/src/tools/delegate-task/sync-task-fallback.ts +68 -68
- package/src/tools/delegate-task/sync-task.ts +243 -243
- package/src/tools/delegate-task/time-formatter.ts +13 -13
- package/src/tools/delegate-task/timing.ts +46 -46
- package/src/tools/delegate-task/token-limiter.ts +123 -123
- package/src/tools/delegate-task/tools.ts +259 -259
- package/src/tools/delegate-task/types.ts +89 -89
- package/src/tools/delegate-task/unstable-agent-task.ts +243 -243
- package/src/tools/glob/cli.ts +206 -206
- package/src/tools/glob/constants.ts +12 -12
- package/src/tools/glob/index.ts +1 -1
- package/src/tools/glob/result-formatter.ts +26 -26
- package/src/tools/glob/tools.ts +49 -49
- package/src/tools/glob/types.ts +23 -23
- package/src/tools/grep/cli.ts +279 -279
- package/src/tools/grep/constants.ts +141 -141
- package/src/tools/grep/downloader.ts +128 -128
- package/src/tools/grep/index.ts +1 -1
- package/src/tools/grep/result-formatter.ts +60 -60
- package/src/tools/grep/tools.ts +75 -75
- package/src/tools/grep/types.ts +42 -42
- package/src/tools/hashline-edit/AGENTS.md +92 -92
- package/src/tools/hashline-edit/autocorrect-replacement-lines.ts +179 -179
- package/src/tools/hashline-edit/constants.ts +10 -10
- package/src/tools/hashline-edit/diff-utils.ts +53 -53
- package/src/tools/hashline-edit/edit-deduplication.ts +43 -43
- package/src/tools/hashline-edit/edit-operation-primitives.ts +126 -126
- package/src/tools/hashline-edit/edit-operations.ts +103 -103
- package/src/tools/hashline-edit/edit-ordering.ts +56 -56
- package/src/tools/hashline-edit/edit-text-normalization.ts +111 -111
- package/src/tools/hashline-edit/file-text-canonicalization.ts +44 -44
- package/src/tools/hashline-edit/formatter-trigger.ts +132 -132
- package/src/tools/hashline-edit/hash-computation.ts +154 -154
- package/src/tools/hashline-edit/hashline-chunk-formatter.ts +52 -52
- package/src/tools/hashline-edit/hashline-edit-diff.ts +31 -31
- package/src/tools/hashline-edit/hashline-edit-executor.ts +197 -197
- package/src/tools/hashline-edit/index.ts +20 -20
- package/src/tools/hashline-edit/normalize-edits.ts +95 -95
- package/src/tools/hashline-edit/tool-description.ts +95 -95
- package/src/tools/hashline-edit/tools.ts +42 -42
- package/src/tools/hashline-edit/types.ts +20 -20
- package/src/tools/hashline-edit/validation.ts +181 -181
- package/src/tools/index.ts +64 -64
- package/src/tools/interactive-bash/constants.ts +18 -18
- package/src/tools/interactive-bash/index.ts +4 -4
- package/src/tools/interactive-bash/tmux-path-resolver.ts +71 -71
- package/src/tools/interactive-bash/tools.ts +136 -136
- package/src/tools/look-at/assistant-message-extractor.ts +67 -67
- package/src/tools/look-at/constants.ts +3 -3
- package/src/tools/look-at/image-converter.ts +164 -164
- package/src/tools/look-at/index.ts +3 -3
- package/src/tools/look-at/look-at-arguments.ts +34 -34
- package/src/tools/look-at/mime-type-inference.ts +94 -94
- package/src/tools/look-at/multimodal-agent-metadata.ts +166 -166
- package/src/tools/look-at/multimodal-fallback-chain.ts +66 -66
- package/src/tools/look-at/session-poller.ts +42 -42
- package/src/tools/look-at/tools.ts +245 -245
- package/src/tools/look-at/types.ts +5 -5
- package/src/tools/lsp/AGENTS.md +70 -70
- package/src/tools/lsp/client.ts +3 -3
- package/src/tools/lsp/config.ts +3 -3
- package/src/tools/lsp/constants.ts +7 -7
- package/src/tools/lsp/diagnostics-tool.ts +75 -75
- package/src/tools/lsp/directory-diagnostics.ts +163 -163
- package/src/tools/lsp/find-references-tool.ts +43 -43
- package/src/tools/lsp/goto-definition-tool.ts +42 -42
- package/src/tools/lsp/index.ts +9 -9
- package/src/tools/lsp/infer-extension.ts +65 -65
- package/src/tools/lsp/language-config.ts +5 -5
- package/src/tools/lsp/language-mappings.ts +171 -171
- package/src/tools/lsp/lsp-client-connection.ts +66 -66
- package/src/tools/lsp/lsp-client-transport.ts +210 -210
- package/src/tools/lsp/lsp-client-wrapper.ts +116 -116
- package/src/tools/lsp/lsp-client.ts +129 -129
- package/src/tools/lsp/lsp-formatters.ts +193 -193
- package/src/tools/lsp/lsp-manager-process-cleanup.ts +83 -83
- package/src/tools/lsp/lsp-manager-temp-directory-cleanup.ts +29 -29
- package/src/tools/lsp/lsp-process.ts +158 -158
- package/src/tools/lsp/lsp-server.ts +217 -217
- package/src/tools/lsp/rename-tools.ts +53 -53
- package/src/tools/lsp/server-config-loader.ts +116 -116
- package/src/tools/lsp/server-definitions.ts +91 -91
- package/src/tools/lsp/server-installation.ts +58 -58
- package/src/tools/lsp/server-path-bases.ts +16 -16
- package/src/tools/lsp/server-resolution.ts +109 -109
- package/src/tools/lsp/symbols-tool.ts +76 -76
- package/src/tools/lsp/tools.ts +5 -5
- package/src/tools/lsp/types.ts +124 -124
- package/src/tools/lsp/workspace-edit.ts +121 -121
- package/src/tools/session-manager/constants.ts +93 -93
- package/src/tools/session-manager/file-storage.ts +203 -203
- package/src/tools/session-manager/index.ts +3 -3
- package/src/tools/session-manager/sdk-storage.ts +135 -135
- package/src/tools/session-manager/sdk-unavailable.ts +43 -43
- package/src/tools/session-manager/session-formatter.ts +199 -199
- package/src/tools/session-manager/storage.ts +161 -161
- package/src/tools/session-manager/tools.ts +197 -197
- package/src/tools/session-manager/types.ts +99 -99
- package/src/tools/shared/semaphore.ts +32 -32
- package/src/tools/skill/constants.ts +14 -14
- package/src/tools/skill/description-formatter.ts +61 -61
- package/src/tools/skill/index.ts +3 -3
- package/src/tools/skill/mcp-capability-formatter.ts +97 -97
- package/src/tools/skill/native-skills.ts +62 -62
- package/src/tools/skill/scope-priority.ts +17 -17
- package/src/tools/skill/skill-body.ts +26 -26
- package/src/tools/skill/skill-matcher.ts +40 -40
- package/src/tools/skill/tools.ts +196 -196
- package/src/tools/skill/types.ts +48 -48
- package/src/tools/skill-mcp/constants.ts +9 -9
- package/src/tools/skill-mcp/index.ts +3 -3
- package/src/tools/skill-mcp/tools.ts +204 -204
- package/src/tools/skill-mcp/types.ts +8 -8
- package/src/tools/slashcommand/command-discovery.ts +161 -161
- package/src/tools/slashcommand/command-output-formatter.ts +75 -75
- package/src/tools/slashcommand/index.ts +2 -2
- package/src/tools/slashcommand/types.ts +21 -21
- package/src/tools/task/index.ts +7 -7
- package/src/tools/task/task-create.ts +113 -113
- package/src/tools/task/task-get.ts +47 -47
- package/src/tools/task/task-list.ts +79 -79
- package/src/tools/task/task-update.ts +152 -152
- package/src/tools/task/todo-sync.ts +205 -205
- package/src/tools/task/types.ts +77 -77
- package/scripts/check_docs.ts +0 -129
- package/scripts/doctor.ts +0 -522
- package/scripts/measure_prompts.ts +0 -193
- package/scripts/test_routing.ts +0 -294
|
@@ -1,603 +1,603 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getClient,
|
|
3
|
-
getReturnState,
|
|
4
|
-
deleteReturnState,
|
|
5
|
-
setReturnState,
|
|
6
|
-
getPluginConfig,
|
|
7
|
-
getAllPendingReturns,
|
|
8
|
-
deletePendingReturn,
|
|
9
|
-
hasReturnStack,
|
|
10
|
-
peekReturnStack,
|
|
11
|
-
shiftReturnStack,
|
|
12
|
-
getCurrentReturnChain,
|
|
13
|
-
popCurrentReturnChain,
|
|
14
|
-
setHasActiveSubtask,
|
|
15
|
-
getHasActiveSubtask,
|
|
16
|
-
OPENCODE_GENERIC,
|
|
17
|
-
getSubtaskParentSession,
|
|
18
|
-
consumePendingPromptReturn,
|
|
19
|
-
setPendingStackedPromptResponse,
|
|
20
|
-
hasProcessedS2Message,
|
|
21
|
-
addProcessedS2Message,
|
|
22
|
-
getConfigs,
|
|
23
|
-
} from "../core/state";
|
|
24
|
-
import { log } from "../utils/logger";
|
|
25
|
-
import { DEFAULT_PROMPT } from "../utils/config";
|
|
26
|
-
import { S2_INLINE_INSTRUCTION } from "../utils/prompts";
|
|
27
|
-
import { parseInlineSubtask } from "../parsing";
|
|
28
|
-
import { executeInlineSubtask } from "../features/inline-subtasks";
|
|
29
|
-
import { executeReturn } from "../features/returns";
|
|
30
|
-
import {
|
|
31
|
-
getAllPendingEvaluations,
|
|
32
|
-
createEvaluationPrompt,
|
|
33
|
-
createYieldPrompt,
|
|
34
|
-
} from "../loop";
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Update the synthetic part in the database to make it visible in TUI.
|
|
38
|
-
*
|
|
39
|
-
* The v1 SDK from OpenCode exposes an internal hey-api HTTP client at client.client
|
|
40
|
-
* which we use to PATCH the part. This is the only reliable way to update parts
|
|
41
|
-
* from a plugin since client.part.update() doesn't exist in v1.
|
|
42
|
-
*
|
|
43
|
-
* Note: OpenCode's plugin system passes a v1 client. When/if they upgrade to v2,
|
|
44
|
-
* we can use client.part.update() directly.
|
|
45
|
-
*/
|
|
46
|
-
async function makePartVisible(
|
|
47
|
-
part: any,
|
|
48
|
-
msg: any,
|
|
49
|
-
newText: string
|
|
50
|
-
): Promise<void> {
|
|
51
|
-
const client = getClient();
|
|
52
|
-
if (!client) {
|
|
53
|
-
log(`makePartVisible: no client available`);
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Extract IDs from the part and message
|
|
58
|
-
const partID = part.id;
|
|
59
|
-
const messageID = part.messageID || msg?.info?.id;
|
|
60
|
-
const sessionID = part.sessionID || msg?.info?.sessionID;
|
|
61
|
-
|
|
62
|
-
if (!partID || !messageID || !sessionID) {
|
|
63
|
-
log(
|
|
64
|
-
`makePartVisible: missing IDs - partID=${partID}, messageID=${messageID}, sessionID=${sessionID}`
|
|
65
|
-
);
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
log(
|
|
70
|
-
`makePartVisible: updating part ${partID} in DB to be visible with text: "${newText.substring(0, 50)}..."`
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
// Use the internal HTTP client from v1 SDK
|
|
74
|
-
try {
|
|
75
|
-
const httpClient = (client as any).client || (client as any)._client;
|
|
76
|
-
if (httpClient?.patch) {
|
|
77
|
-
await httpClient.patch({
|
|
78
|
-
url: `/session/${sessionID}/message/${messageID}/part/${partID}`,
|
|
79
|
-
body: {
|
|
80
|
-
id: partID,
|
|
81
|
-
messageID,
|
|
82
|
-
sessionID,
|
|
83
|
-
type: "text",
|
|
84
|
-
text: newText,
|
|
85
|
-
synthetic: false, // Make visible in TUI
|
|
86
|
-
},
|
|
87
|
-
});
|
|
88
|
-
log(`makePartVisible: success`);
|
|
89
|
-
} else {
|
|
90
|
-
log(
|
|
91
|
-
`makePartVisible: no internal HTTP client found - keys: ${Object.keys(client).join(", ")}`
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
} catch (e) {
|
|
95
|
-
log(`makePartVisible: failed - ${e}`);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Helper to replace a message part with a prompt and clear any stale assistant response
|
|
101
|
-
*/
|
|
102
|
-
function replaceAndClear(
|
|
103
|
-
part: any,
|
|
104
|
-
msg: any,
|
|
105
|
-
msgIndex: number,
|
|
106
|
-
newText: string,
|
|
107
|
-
outputMessages: any[]
|
|
108
|
-
) {
|
|
109
|
-
log(
|
|
110
|
-
`Replacing generic message at index ${msgIndex} with prompt: "${newText.substring(0, 50)}..."`
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
// Modify in place - don't create new objects (references matter)
|
|
114
|
-
part.text = newText;
|
|
115
|
-
delete part.synthetic;
|
|
116
|
-
|
|
117
|
-
// Update the DB to make the message visible in TUI
|
|
118
|
-
makePartVisible(part, msg, newText).catch(e =>
|
|
119
|
-
log(`makePartVisible failed: ${e}`)
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
// CRITICAL: Remove any assistant response that came after the replaced message
|
|
123
|
-
// The LLM may have already responded to "Summarize..." before this hook fired
|
|
124
|
-
const nextIndex = msgIndex + 1;
|
|
125
|
-
if (nextIndex < outputMessages.length) {
|
|
126
|
-
const nextMsg = outputMessages[nextIndex];
|
|
127
|
-
const role = nextMsg.info?.role ?? nextMsg.role;
|
|
128
|
-
if (role === "assistant") {
|
|
129
|
-
outputMessages.splice(nextIndex, 1);
|
|
130
|
-
log(`Removed stale LLM response at index ${nextIndex}`);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Hook: experimental.chat.messages.transform
|
|
137
|
-
* Handles /subtask {...} inline subtasks and return prompt injection
|
|
138
|
-
*/
|
|
139
|
-
export async function chatMessagesTransform(input: any, output: any) {
|
|
140
|
-
try {
|
|
141
|
-
// Log every invocation with message count and session info
|
|
142
|
-
const sessionIDs = [
|
|
143
|
-
...new Set(
|
|
144
|
-
output.messages.map((m: any) => m.info?.sessionID).filter(Boolean)
|
|
145
|
-
),
|
|
146
|
-
];
|
|
147
|
-
|
|
148
|
-
// Log message summary for debugging
|
|
149
|
-
const msgSummary = output.messages
|
|
150
|
-
.map((m: any, i: number) => {
|
|
151
|
-
const role = m.info?.role || m.role || "?";
|
|
152
|
-
const parts = (m.parts || [])
|
|
153
|
-
.map((p: any) => {
|
|
154
|
-
if (p.type === "text") {
|
|
155
|
-
const text = p.text?.substring(0, 40) || "";
|
|
156
|
-
return `text:"${text}${p.text?.length > 40 ? "..." : ""}"${p.synthetic ? "(syn)" : ""}`;
|
|
157
|
-
}
|
|
158
|
-
if (p.type === "tool") return `tool:${p.state?.status || "?"}`;
|
|
159
|
-
if (p.type === "subtask")
|
|
160
|
-
return `subtask:"${p.prompt?.substring(0, 30) || ""}..."`;
|
|
161
|
-
return p.type;
|
|
162
|
-
})
|
|
163
|
-
.join(", ");
|
|
164
|
-
return `[${i}]${role}: ${parts}`;
|
|
165
|
-
})
|
|
166
|
-
.join(" | ");
|
|
167
|
-
|
|
168
|
-
log(
|
|
169
|
-
`message-hooks: ENTRY msgCount=${output.messages.length}, sessions=${sessionIDs.join(",") || "none"}`
|
|
170
|
-
);
|
|
171
|
-
log(`message-hooks: MESSAGES: ${msgSummary}`);
|
|
172
|
-
|
|
173
|
-
// Check for /subtask in user messages
|
|
174
|
-
// With the placeholder command file, OpenCode routes /subtask to command hook
|
|
175
|
-
// This is a fallback for when no placeholder exists
|
|
176
|
-
for (const msg of output.messages) {
|
|
177
|
-
if (msg.info?.role !== "user") continue;
|
|
178
|
-
|
|
179
|
-
// Track processed messages by ID to avoid infinite loop
|
|
180
|
-
const msgId = (msg.info as any)?.id;
|
|
181
|
-
if (msgId && hasProcessedS2Message(msgId)) continue;
|
|
182
|
-
|
|
183
|
-
for (const part of msg.parts) {
|
|
184
|
-
if (part.type !== "text") continue;
|
|
185
|
-
const text = part.text.trim();
|
|
186
|
-
const textLower = text.toLowerCase();
|
|
187
|
-
|
|
188
|
-
// Match /subtask (with space) - the recommended syntax
|
|
189
|
-
if (textLower.startsWith("/subtask ")) {
|
|
190
|
-
// If /subtask command exists, defer to command hook for instant execution
|
|
191
|
-
const configs = getConfigs();
|
|
192
|
-
if (configs["subtask"]) {
|
|
193
|
-
log(
|
|
194
|
-
`/subtask detected but deferring to command hook (subtask command exists)`
|
|
195
|
-
);
|
|
196
|
-
continue;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Fallback: handle via message transform when no placeholder command exists
|
|
200
|
-
log(
|
|
201
|
-
`/subtask detected in message (no placeholder): "${text.substring(0, 60)}..."`
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
// Mark as processed BEFORE spawning
|
|
205
|
-
if (msgId) addProcessedS2Message(msgId);
|
|
206
|
-
|
|
207
|
-
// Parse: remove "/subtask " prefix
|
|
208
|
-
const toParse = text.substring("/subtask ".length);
|
|
209
|
-
// Wrap in {} if it doesn't start with { (plain prompt case)
|
|
210
|
-
const parseInput = toParse.startsWith("{")
|
|
211
|
-
? toParse
|
|
212
|
-
: `{} ${toParse}`;
|
|
213
|
-
const parsed = parseInlineSubtask(parseInput);
|
|
214
|
-
|
|
215
|
-
if (parsed) {
|
|
216
|
-
log(
|
|
217
|
-
`/subtask inline subtask: prompt="${parsed.prompt.substring(
|
|
218
|
-
0,
|
|
219
|
-
50
|
|
220
|
-
)}...", overrides=${JSON.stringify(parsed.overrides)}`
|
|
221
|
-
);
|
|
222
|
-
// Replace with instruction to say minimal response
|
|
223
|
-
part.text = S2_INLINE_INSTRUCTION;
|
|
224
|
-
// Spawn the subtask - get sessionID from message info
|
|
225
|
-
const sessionID =
|
|
226
|
-
(msg.info as any)?.sessionID || (input as any).sessionID;
|
|
227
|
-
log(`/subtask sessionID: ${sessionID}`);
|
|
228
|
-
if (sessionID) {
|
|
229
|
-
executeInlineSubtask(parsed, sessionID).catch(console.error);
|
|
230
|
-
} else {
|
|
231
|
-
log(`/subtask ERROR: no sessionID found`);
|
|
232
|
-
}
|
|
233
|
-
return;
|
|
234
|
-
} else {
|
|
235
|
-
log(`/subtask parse failed for: "${parseInput}"`);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Filter out summary leak messages from the assistant
|
|
242
|
-
// These are responses that summarize task tool output, which we don't want
|
|
243
|
-
const filteredMessages: any[] = [];
|
|
244
|
-
|
|
245
|
-
const isSummaryLeak = (msg: any): boolean => {
|
|
246
|
-
const parts = msg.parts || [];
|
|
247
|
-
return parts.some((p: any) => {
|
|
248
|
-
if (p.type !== "step-start") return false;
|
|
249
|
-
if (typeof p.text !== "string") return false;
|
|
250
|
-
return (
|
|
251
|
-
p.text.includes("Summary of Task Tool Output") ||
|
|
252
|
-
p.text.includes("My task was to summarize") ||
|
|
253
|
-
p.text.includes("The tool executed your command") ||
|
|
254
|
-
p.text.includes("The command was executed successfully") ||
|
|
255
|
-
p.text.includes("To complete your request")
|
|
256
|
-
);
|
|
257
|
-
});
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
for (let i = 0; i < output.messages.length; i++) {
|
|
261
|
-
const msg = output.messages[i];
|
|
262
|
-
const role = msg.info?.role ?? msg.role;
|
|
263
|
-
|
|
264
|
-
if (role === "assistant" && isSummaryLeak(msg)) {
|
|
265
|
-
log(`message-hooks: removing summary leak at index ${i}`);
|
|
266
|
-
continue;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
filteredMessages.push(msg);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
if (filteredMessages.length !== output.messages.length) {
|
|
273
|
-
log(
|
|
274
|
-
`message-hooks: filtered ${output.messages.length - filteredMessages.length} summary leak messages`
|
|
275
|
-
);
|
|
276
|
-
// CRITICAL: Must mutate the array IN PLACE, not reassign!
|
|
277
|
-
// Reassigning output.messages doesn't affect the original sessionMessages in OpenCode
|
|
278
|
-
output.messages.length = 0;
|
|
279
|
-
output.messages.push(...filteredMessages);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
log(`message-hooks: post-filter, msgCount=${output.messages.length}`);
|
|
283
|
-
|
|
284
|
-
// NOTE: We don't try to delete messages from DB - client.session.removeMessage doesn't exist
|
|
285
|
-
// The filtering above is sufficient - it affects the current LLM call
|
|
286
|
-
|
|
287
|
-
log(`message-hooks: about to search for OPENCODE_GENERIC`);
|
|
288
|
-
|
|
289
|
-
// Find the LAST message with OPENCODE_GENERIC
|
|
290
|
-
let lastGenericPart: any = null;
|
|
291
|
-
let lastGenericMsg: any = null;
|
|
292
|
-
let lastGenericMsgIndex: number = -1;
|
|
293
|
-
|
|
294
|
-
log(
|
|
295
|
-
`message-hooks: searching ${output.messages.length} messages for OPENCODE_GENERIC`
|
|
296
|
-
);
|
|
297
|
-
|
|
298
|
-
for (let i = 0; i < output.messages.length; i++) {
|
|
299
|
-
const msg = output.messages[i];
|
|
300
|
-
for (const part of msg.parts || []) {
|
|
301
|
-
if (part.type === "text") {
|
|
302
|
-
const isGeneric = part.text === OPENCODE_GENERIC;
|
|
303
|
-
if (part.synthetic) {
|
|
304
|
-
log(
|
|
305
|
-
`message-hooks: found synthetic text at [${i}]: "${part.text?.substring(0, 50)}..." matches=${isGeneric}`
|
|
306
|
-
);
|
|
307
|
-
}
|
|
308
|
-
if (isGeneric) {
|
|
309
|
-
lastGenericPart = part;
|
|
310
|
-
lastGenericMsg = msg;
|
|
311
|
-
lastGenericMsgIndex = i;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
log(
|
|
318
|
-
`message-hooks: generic search complete, found=${!!lastGenericPart}, index=${lastGenericMsgIndex}`
|
|
319
|
-
);
|
|
320
|
-
|
|
321
|
-
// If no generic part found, check for pending prompt returns from inline subtasks
|
|
322
|
-
// Inline subtasks don't get OPENCODE_GENERIC, so we inject the pending prompt directly
|
|
323
|
-
if (!lastGenericPart) {
|
|
324
|
-
log(
|
|
325
|
-
`message-hooks: no generic part found, checking for pending prompt return`
|
|
326
|
-
);
|
|
327
|
-
|
|
328
|
-
for (const sid of sessionIDs) {
|
|
329
|
-
const pendingPrompt = consumePendingPromptReturn(sid as string);
|
|
330
|
-
if (pendingPrompt) {
|
|
331
|
-
log(`message-hooks: found pendingPromptReturn for ${sid}, injecting`);
|
|
332
|
-
|
|
333
|
-
// Clone structure from an existing user message to ensure correct format
|
|
334
|
-
const existingUserMsg = output.messages.find(
|
|
335
|
-
(m: any) => (m.info?.role ?? m.role) === "user"
|
|
336
|
-
);
|
|
337
|
-
|
|
338
|
-
if (existingUserMsg) {
|
|
339
|
-
const newMsg = JSON.parse(JSON.stringify(existingUserMsg));
|
|
340
|
-
newMsg.parts = [{ type: "text", text: pendingPrompt }];
|
|
341
|
-
// Remove IDs so OpenCode doesn't get confused
|
|
342
|
-
if (newMsg.id) delete newMsg.id;
|
|
343
|
-
if (newMsg.info?.id) delete newMsg.info.id;
|
|
344
|
-
if (newMsg.info?.createdAt) delete newMsg.info.createdAt;
|
|
345
|
-
output.messages.push(newMsg);
|
|
346
|
-
log(
|
|
347
|
-
`message-hooks: injected pending prompt: "${pendingPrompt.substring(0, 40)}..."`
|
|
348
|
-
);
|
|
349
|
-
} else {
|
|
350
|
-
// Fallback: create minimal message
|
|
351
|
-
output.messages.push({
|
|
352
|
-
info: { role: "user" },
|
|
353
|
-
parts: [{ type: "text", text: pendingPrompt }],
|
|
354
|
-
});
|
|
355
|
-
log(
|
|
356
|
-
`message-hooks: injected pending prompt (fallback): "${pendingPrompt.substring(0, 40)}..."`
|
|
357
|
-
);
|
|
358
|
-
}
|
|
359
|
-
return; // Let the LLM respond to our injected message
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
if (hasReturnStack(sid as string)) {
|
|
363
|
-
log(
|
|
364
|
-
`message-hooks: session ${sid} HAS returnStack but no generic part!`
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
return; // Nothing to do without generic part
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// The generic message is in a subtask session, but returns are stored under the PARENT session
|
|
372
|
-
// We need to resolve the parent session to look up returns
|
|
373
|
-
const subtaskSessionID = lastGenericMsg?.info?.sessionID;
|
|
374
|
-
const resolvedParent = subtaskSessionID
|
|
375
|
-
? getSubtaskParentSession(subtaskSessionID)
|
|
376
|
-
: undefined;
|
|
377
|
-
const parentSessionID = resolvedParent || subtaskSessionID;
|
|
378
|
-
|
|
379
|
-
log(
|
|
380
|
-
`message-hooks: subtaskSession=${subtaskSessionID}, resolvedParent=${resolvedParent || "NOT FOUND"}, using=${parentSessionID}`
|
|
381
|
-
);
|
|
382
|
-
|
|
383
|
-
// Check for deferred prompt return from session.idle
|
|
384
|
-
// This handles prompt returns that were deferred to be substituted here
|
|
385
|
-
log(
|
|
386
|
-
`message-hooks: checking pendingPromptReturn for session ${parentSessionID}`
|
|
387
|
-
);
|
|
388
|
-
if (parentSessionID) {
|
|
389
|
-
const pendingPrompt = consumePendingPromptReturn(parentSessionID);
|
|
390
|
-
if (pendingPrompt) {
|
|
391
|
-
replaceAndClear(
|
|
392
|
-
lastGenericPart,
|
|
393
|
-
lastGenericMsg,
|
|
394
|
-
lastGenericMsgIndex,
|
|
395
|
-
pendingPrompt,
|
|
396
|
-
output.messages
|
|
397
|
-
);
|
|
398
|
-
|
|
399
|
-
// Mark that we're waiting for LLM response to this prompt
|
|
400
|
-
setPendingStackedPromptResponse(parentSessionID);
|
|
401
|
-
|
|
402
|
-
return;
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
// Check for pending loop evaluation first (orchestrator-decides pattern)
|
|
407
|
-
log(`message-hooks: checking loop evaluations`);
|
|
408
|
-
for (const [sessionID, retryState] of getAllPendingEvaluations()) {
|
|
409
|
-
// Check if this is an unconditional loop (no until condition)
|
|
410
|
-
if (!retryState.config.until) {
|
|
411
|
-
// Unconditional loop: inject yield prompt, no evaluation needed
|
|
412
|
-
const yieldPrompt = createYieldPrompt(
|
|
413
|
-
retryState.iteration,
|
|
414
|
-
retryState.config.max
|
|
415
|
-
);
|
|
416
|
-
// Unconditional loop: modify in place
|
|
417
|
-
lastGenericPart.text = yieldPrompt;
|
|
418
|
-
log(
|
|
419
|
-
`loop: injected yield prompt (unconditional loop ${retryState.iteration}/${retryState.config.max})`
|
|
420
|
-
);
|
|
421
|
-
} else {
|
|
422
|
-
// Conditional loop: inject evaluation prompt
|
|
423
|
-
const evalPrompt = createEvaluationPrompt(
|
|
424
|
-
retryState.config.until,
|
|
425
|
-
retryState.iteration,
|
|
426
|
-
retryState.config.max
|
|
427
|
-
);
|
|
428
|
-
// Modify in place
|
|
429
|
-
lastGenericPart.text = evalPrompt;
|
|
430
|
-
log(
|
|
431
|
-
`loop: injected evaluation prompt for "${retryState.config.until}"`
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
// Don't delete yet - we need it when parsing the response
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
// Check for pending return
|
|
439
|
-
const pendingReturnsEntries = [...getAllPendingReturns()];
|
|
440
|
-
log(
|
|
441
|
-
`message-hooks: checking pendingReturns, count=${pendingReturnsEntries.length}`
|
|
442
|
-
);
|
|
443
|
-
for (const [sessionID, returnPrompt] of pendingReturnsEntries) {
|
|
444
|
-
deletePendingReturn(sessionID);
|
|
445
|
-
setHasActiveSubtask(false);
|
|
446
|
-
|
|
447
|
-
// Also shift from returnState to keep them in sync
|
|
448
|
-
// This prevents session.idle from trying to re-execute the same return
|
|
449
|
-
const returnStateData = getReturnState(sessionID);
|
|
450
|
-
if (returnStateData?.length && returnStateData[0] === returnPrompt) {
|
|
451
|
-
returnStateData.shift();
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
if (returnPrompt.startsWith("/")) {
|
|
455
|
-
// Command return: remove the summarize message entirely from history
|
|
456
|
-
// and fire the command immediately at this moment
|
|
457
|
-
if (lastGenericMsgIndex >= 0) {
|
|
458
|
-
output.messages.splice(lastGenericMsgIndex, 1);
|
|
459
|
-
|
|
460
|
-
// Also delete from DB to prevent OpenCode from re-fetching and responding to it
|
|
461
|
-
const msgId = lastGenericMsg?.id;
|
|
462
|
-
const partId = lastGenericPart?.id;
|
|
463
|
-
if (msgId && partId) {
|
|
464
|
-
const client = getClient();
|
|
465
|
-
// Delete the part (this effectively removes the message content)
|
|
466
|
-
client.session
|
|
467
|
-
.deletePart({ path: { id: partId } })
|
|
468
|
-
.catch((e: Error) => {
|
|
469
|
-
log(`Failed to delete summarize part from DB: ${e.message}`);
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
log(
|
|
474
|
-
`Removed summarize message at index ${lastGenericMsgIndex} for command return`
|
|
475
|
-
);
|
|
476
|
-
}
|
|
477
|
-
executeReturn(returnPrompt, sessionID).catch(console.error);
|
|
478
|
-
} else {
|
|
479
|
-
// Plain prompt return: MODIFY the existing part directly (for LLM)
|
|
480
|
-
replaceAndClear(
|
|
481
|
-
lastGenericPart,
|
|
482
|
-
lastGenericMsg,
|
|
483
|
-
lastGenericMsgIndex,
|
|
484
|
-
returnPrompt,
|
|
485
|
-
output.messages
|
|
486
|
-
);
|
|
487
|
-
}
|
|
488
|
-
return;
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
// No pending return found, check returnState for remaining returns
|
|
492
|
-
// This handles returns after the first one (which used pendingReturns)
|
|
493
|
-
// Use parentSessionID (resolved earlier) since returns are stored under parent session
|
|
494
|
-
if (parentSessionID) {
|
|
495
|
-
const remaining = getReturnState(parentSessionID);
|
|
496
|
-
if (remaining?.length) {
|
|
497
|
-
const nextReturn = remaining[0];
|
|
498
|
-
setHasActiveSubtask(false);
|
|
499
|
-
|
|
500
|
-
if (nextReturn.startsWith("/")) {
|
|
501
|
-
// Command return: remove the summarize message, let session.idle execute
|
|
502
|
-
if (lastGenericMsgIndex >= 0) {
|
|
503
|
-
output.messages.splice(lastGenericMsgIndex, 1);
|
|
504
|
-
log(
|
|
505
|
-
`Removed summarize message - returnState command will be processed by session.idle`
|
|
506
|
-
);
|
|
507
|
-
}
|
|
508
|
-
} else {
|
|
509
|
-
// Prompt return: REPLACE the message so LLM responds to it
|
|
510
|
-
// NOTE: We must replace the entire message, not just modify the part text,
|
|
511
|
-
// because OpenCode may deep-copy messages before sending to LLM
|
|
512
|
-
// First, check if there are stacked returns from inline subtasks
|
|
513
|
-
// and transfer them to returnState so the chain continues
|
|
514
|
-
const stackedReturns = getCurrentReturnChain(parentSessionID);
|
|
515
|
-
if (stackedReturns?.length) {
|
|
516
|
-
remaining.push(...stackedReturns);
|
|
517
|
-
popCurrentReturnChain(parentSessionID);
|
|
518
|
-
log(
|
|
519
|
-
`Transferred ${stackedReturns.length} stacked returns to returnState for continued processing`
|
|
520
|
-
);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
// Shift from returnState since we're handling it here
|
|
524
|
-
remaining.shift();
|
|
525
|
-
|
|
526
|
-
replaceAndClear(
|
|
527
|
-
lastGenericPart,
|
|
528
|
-
lastGenericMsg,
|
|
529
|
-
lastGenericMsgIndex,
|
|
530
|
-
nextReturn,
|
|
531
|
-
output.messages
|
|
532
|
-
);
|
|
533
|
-
|
|
534
|
-
// Mark that we're waiting for LLM response to this prompt
|
|
535
|
-
// This prevents session.idle from processing the next return too early
|
|
536
|
-
setPendingStackedPromptResponse(parentSessionID);
|
|
537
|
-
}
|
|
538
|
-
return;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
// No returns found, use generic replacement if configured
|
|
543
|
-
// BUT skip if there are stacked returns (from inline subtasks with returns)
|
|
544
|
-
// Those will be processed by session.idle hook
|
|
545
|
-
const pluginConfig = getPluginConfig();
|
|
546
|
-
|
|
547
|
-
// Check if the parent session has stacked returns
|
|
548
|
-
// Use parentSessionID (resolved earlier) since stacked returns are stored under parent session
|
|
549
|
-
let stackedSessionID: string | null = null;
|
|
550
|
-
if (parentSessionID && hasReturnStack(parentSessionID)) {
|
|
551
|
-
stackedSessionID = parentSessionID;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
if (stackedSessionID) {
|
|
555
|
-
// Peek at the first stacked return to decide how to handle
|
|
556
|
-
const nextReturnArray = peekReturnStack(stackedSessionID);
|
|
557
|
-
const nextReturn = nextReturnArray?.[0];
|
|
558
|
-
|
|
559
|
-
if (nextReturn?.startsWith("/")) {
|
|
560
|
-
// Command return: remove the summarize message, let session.idle execute
|
|
561
|
-
if (lastGenericMsgIndex >= 0) {
|
|
562
|
-
output.messages.splice(lastGenericMsgIndex, 1);
|
|
563
|
-
log(
|
|
564
|
-
`Removed summarize message - stacked command return will be processed by session.idle`
|
|
565
|
-
);
|
|
566
|
-
}
|
|
567
|
-
} else if (nextReturn) {
|
|
568
|
-
// Prompt return: REPLACE the message so LLM responds to it
|
|
569
|
-
const returnPrompt = shiftReturnStack(stackedSessionID);
|
|
570
|
-
if (returnPrompt) {
|
|
571
|
-
replaceAndClear(
|
|
572
|
-
lastGenericPart,
|
|
573
|
-
lastGenericMsg,
|
|
574
|
-
lastGenericMsgIndex,
|
|
575
|
-
returnPrompt,
|
|
576
|
-
output.messages
|
|
577
|
-
);
|
|
578
|
-
|
|
579
|
-
// Mark that we're waiting for LLM response to this prompt
|
|
580
|
-
// This prevents session.idle from processing returnState too early
|
|
581
|
-
setPendingStackedPromptResponse(stackedSessionID);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
setHasActiveSubtask(false);
|
|
585
|
-
return;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
if (getHasActiveSubtask() && pluginConfig.replace_generic) {
|
|
589
|
-
const text = pluginConfig.generic_return ?? DEFAULT_PROMPT;
|
|
590
|
-
replaceAndClear(
|
|
591
|
-
lastGenericPart,
|
|
592
|
-
lastGenericMsg,
|
|
593
|
-
lastGenericMsgIndex,
|
|
594
|
-
text,
|
|
595
|
-
output.messages
|
|
596
|
-
);
|
|
597
|
-
setHasActiveSubtask(false);
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
} catch (err) {
|
|
601
|
-
log(`message-hooks: EXCEPTION: ${err}`);
|
|
602
|
-
}
|
|
603
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
getClient,
|
|
3
|
+
getReturnState,
|
|
4
|
+
deleteReturnState,
|
|
5
|
+
setReturnState,
|
|
6
|
+
getPluginConfig,
|
|
7
|
+
getAllPendingReturns,
|
|
8
|
+
deletePendingReturn,
|
|
9
|
+
hasReturnStack,
|
|
10
|
+
peekReturnStack,
|
|
11
|
+
shiftReturnStack,
|
|
12
|
+
getCurrentReturnChain,
|
|
13
|
+
popCurrentReturnChain,
|
|
14
|
+
setHasActiveSubtask,
|
|
15
|
+
getHasActiveSubtask,
|
|
16
|
+
OPENCODE_GENERIC,
|
|
17
|
+
getSubtaskParentSession,
|
|
18
|
+
consumePendingPromptReturn,
|
|
19
|
+
setPendingStackedPromptResponse,
|
|
20
|
+
hasProcessedS2Message,
|
|
21
|
+
addProcessedS2Message,
|
|
22
|
+
getConfigs,
|
|
23
|
+
} from "../core/state";
|
|
24
|
+
import { log } from "../utils/logger";
|
|
25
|
+
import { DEFAULT_PROMPT } from "../utils/config";
|
|
26
|
+
import { S2_INLINE_INSTRUCTION } from "../utils/prompts";
|
|
27
|
+
import { parseInlineSubtask } from "../parsing";
|
|
28
|
+
import { executeInlineSubtask } from "../features/inline-subtasks";
|
|
29
|
+
import { executeReturn } from "../features/returns";
|
|
30
|
+
import {
|
|
31
|
+
getAllPendingEvaluations,
|
|
32
|
+
createEvaluationPrompt,
|
|
33
|
+
createYieldPrompt,
|
|
34
|
+
} from "../loop";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Update the synthetic part in the database to make it visible in TUI.
|
|
38
|
+
*
|
|
39
|
+
* The v1 SDK from OpenCode exposes an internal hey-api HTTP client at client.client
|
|
40
|
+
* which we use to PATCH the part. This is the only reliable way to update parts
|
|
41
|
+
* from a plugin since client.part.update() doesn't exist in v1.
|
|
42
|
+
*
|
|
43
|
+
* Note: OpenCode's plugin system passes a v1 client. When/if they upgrade to v2,
|
|
44
|
+
* we can use client.part.update() directly.
|
|
45
|
+
*/
|
|
46
|
+
async function makePartVisible(
|
|
47
|
+
part: any,
|
|
48
|
+
msg: any,
|
|
49
|
+
newText: string
|
|
50
|
+
): Promise<void> {
|
|
51
|
+
const client = getClient();
|
|
52
|
+
if (!client) {
|
|
53
|
+
log(`makePartVisible: no client available`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Extract IDs from the part and message
|
|
58
|
+
const partID = part.id;
|
|
59
|
+
const messageID = part.messageID || msg?.info?.id;
|
|
60
|
+
const sessionID = part.sessionID || msg?.info?.sessionID;
|
|
61
|
+
|
|
62
|
+
if (!partID || !messageID || !sessionID) {
|
|
63
|
+
log(
|
|
64
|
+
`makePartVisible: missing IDs - partID=${partID}, messageID=${messageID}, sessionID=${sessionID}`
|
|
65
|
+
);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
log(
|
|
70
|
+
`makePartVisible: updating part ${partID} in DB to be visible with text: "${newText.substring(0, 50)}..."`
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
// Use the internal HTTP client from v1 SDK
|
|
74
|
+
try {
|
|
75
|
+
const httpClient = (client as any).client || (client as any)._client;
|
|
76
|
+
if (httpClient?.patch) {
|
|
77
|
+
await httpClient.patch({
|
|
78
|
+
url: `/session/${sessionID}/message/${messageID}/part/${partID}`,
|
|
79
|
+
body: {
|
|
80
|
+
id: partID,
|
|
81
|
+
messageID,
|
|
82
|
+
sessionID,
|
|
83
|
+
type: "text",
|
|
84
|
+
text: newText,
|
|
85
|
+
synthetic: false, // Make visible in TUI
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
log(`makePartVisible: success`);
|
|
89
|
+
} else {
|
|
90
|
+
log(
|
|
91
|
+
`makePartVisible: no internal HTTP client found - keys: ${Object.keys(client).join(", ")}`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
} catch (e) {
|
|
95
|
+
log(`makePartVisible: failed - ${e}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Helper to replace a message part with a prompt and clear any stale assistant response
|
|
101
|
+
*/
|
|
102
|
+
function replaceAndClear(
|
|
103
|
+
part: any,
|
|
104
|
+
msg: any,
|
|
105
|
+
msgIndex: number,
|
|
106
|
+
newText: string,
|
|
107
|
+
outputMessages: any[]
|
|
108
|
+
) {
|
|
109
|
+
log(
|
|
110
|
+
`Replacing generic message at index ${msgIndex} with prompt: "${newText.substring(0, 50)}..."`
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
// Modify in place - don't create new objects (references matter)
|
|
114
|
+
part.text = newText;
|
|
115
|
+
delete part.synthetic;
|
|
116
|
+
|
|
117
|
+
// Update the DB to make the message visible in TUI
|
|
118
|
+
makePartVisible(part, msg, newText).catch(e =>
|
|
119
|
+
log(`makePartVisible failed: ${e}`)
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
// CRITICAL: Remove any assistant response that came after the replaced message
|
|
123
|
+
// The LLM may have already responded to "Summarize..." before this hook fired
|
|
124
|
+
const nextIndex = msgIndex + 1;
|
|
125
|
+
if (nextIndex < outputMessages.length) {
|
|
126
|
+
const nextMsg = outputMessages[nextIndex];
|
|
127
|
+
const role = nextMsg.info?.role ?? nextMsg.role;
|
|
128
|
+
if (role === "assistant") {
|
|
129
|
+
outputMessages.splice(nextIndex, 1);
|
|
130
|
+
log(`Removed stale LLM response at index ${nextIndex}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Hook: experimental.chat.messages.transform
|
|
137
|
+
* Handles /subtask {...} inline subtasks and return prompt injection
|
|
138
|
+
*/
|
|
139
|
+
export async function chatMessagesTransform(input: any, output: any) {
|
|
140
|
+
try {
|
|
141
|
+
// Log every invocation with message count and session info
|
|
142
|
+
const sessionIDs = [
|
|
143
|
+
...new Set(
|
|
144
|
+
output.messages.map((m: any) => m.info?.sessionID).filter(Boolean)
|
|
145
|
+
),
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
// Log message summary for debugging
|
|
149
|
+
const msgSummary = output.messages
|
|
150
|
+
.map((m: any, i: number) => {
|
|
151
|
+
const role = m.info?.role || m.role || "?";
|
|
152
|
+
const parts = (m.parts || [])
|
|
153
|
+
.map((p: any) => {
|
|
154
|
+
if (p.type === "text") {
|
|
155
|
+
const text = p.text?.substring(0, 40) || "";
|
|
156
|
+
return `text:"${text}${p.text?.length > 40 ? "..." : ""}"${p.synthetic ? "(syn)" : ""}`;
|
|
157
|
+
}
|
|
158
|
+
if (p.type === "tool") return `tool:${p.state?.status || "?"}`;
|
|
159
|
+
if (p.type === "subtask")
|
|
160
|
+
return `subtask:"${p.prompt?.substring(0, 30) || ""}..."`;
|
|
161
|
+
return p.type;
|
|
162
|
+
})
|
|
163
|
+
.join(", ");
|
|
164
|
+
return `[${i}]${role}: ${parts}`;
|
|
165
|
+
})
|
|
166
|
+
.join(" | ");
|
|
167
|
+
|
|
168
|
+
log(
|
|
169
|
+
`message-hooks: ENTRY msgCount=${output.messages.length}, sessions=${sessionIDs.join(",") || "none"}`
|
|
170
|
+
);
|
|
171
|
+
log(`message-hooks: MESSAGES: ${msgSummary}`);
|
|
172
|
+
|
|
173
|
+
// Check for /subtask in user messages
|
|
174
|
+
// With the placeholder command file, OpenCode routes /subtask to command hook
|
|
175
|
+
// This is a fallback for when no placeholder exists
|
|
176
|
+
for (const msg of output.messages) {
|
|
177
|
+
if (msg.info?.role !== "user") continue;
|
|
178
|
+
|
|
179
|
+
// Track processed messages by ID to avoid infinite loop
|
|
180
|
+
const msgId = (msg.info as any)?.id;
|
|
181
|
+
if (msgId && hasProcessedS2Message(msgId)) continue;
|
|
182
|
+
|
|
183
|
+
for (const part of msg.parts) {
|
|
184
|
+
if (part.type !== "text") continue;
|
|
185
|
+
const text = part.text.trim();
|
|
186
|
+
const textLower = text.toLowerCase();
|
|
187
|
+
|
|
188
|
+
// Match /subtask (with space) - the recommended syntax
|
|
189
|
+
if (textLower.startsWith("/subtask ")) {
|
|
190
|
+
// If /subtask command exists, defer to command hook for instant execution
|
|
191
|
+
const configs = getConfigs();
|
|
192
|
+
if (configs["subtask"]) {
|
|
193
|
+
log(
|
|
194
|
+
`/subtask detected but deferring to command hook (subtask command exists)`
|
|
195
|
+
);
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Fallback: handle via message transform when no placeholder command exists
|
|
200
|
+
log(
|
|
201
|
+
`/subtask detected in message (no placeholder): "${text.substring(0, 60)}..."`
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
// Mark as processed BEFORE spawning
|
|
205
|
+
if (msgId) addProcessedS2Message(msgId);
|
|
206
|
+
|
|
207
|
+
// Parse: remove "/subtask " prefix
|
|
208
|
+
const toParse = text.substring("/subtask ".length);
|
|
209
|
+
// Wrap in {} if it doesn't start with { (plain prompt case)
|
|
210
|
+
const parseInput = toParse.startsWith("{")
|
|
211
|
+
? toParse
|
|
212
|
+
: `{} ${toParse}`;
|
|
213
|
+
const parsed = parseInlineSubtask(parseInput);
|
|
214
|
+
|
|
215
|
+
if (parsed) {
|
|
216
|
+
log(
|
|
217
|
+
`/subtask inline subtask: prompt="${parsed.prompt.substring(
|
|
218
|
+
0,
|
|
219
|
+
50
|
|
220
|
+
)}...", overrides=${JSON.stringify(parsed.overrides)}`
|
|
221
|
+
);
|
|
222
|
+
// Replace with instruction to say minimal response
|
|
223
|
+
part.text = S2_INLINE_INSTRUCTION;
|
|
224
|
+
// Spawn the subtask - get sessionID from message info
|
|
225
|
+
const sessionID =
|
|
226
|
+
(msg.info as any)?.sessionID || (input as any).sessionID;
|
|
227
|
+
log(`/subtask sessionID: ${sessionID}`);
|
|
228
|
+
if (sessionID) {
|
|
229
|
+
executeInlineSubtask(parsed, sessionID).catch(console.error);
|
|
230
|
+
} else {
|
|
231
|
+
log(`/subtask ERROR: no sessionID found`);
|
|
232
|
+
}
|
|
233
|
+
return;
|
|
234
|
+
} else {
|
|
235
|
+
log(`/subtask parse failed for: "${parseInput}"`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Filter out summary leak messages from the assistant
|
|
242
|
+
// These are responses that summarize task tool output, which we don't want
|
|
243
|
+
const filteredMessages: any[] = [];
|
|
244
|
+
|
|
245
|
+
const isSummaryLeak = (msg: any): boolean => {
|
|
246
|
+
const parts = msg.parts || [];
|
|
247
|
+
return parts.some((p: any) => {
|
|
248
|
+
if (p.type !== "step-start") return false;
|
|
249
|
+
if (typeof p.text !== "string") return false;
|
|
250
|
+
return (
|
|
251
|
+
p.text.includes("Summary of Task Tool Output") ||
|
|
252
|
+
p.text.includes("My task was to summarize") ||
|
|
253
|
+
p.text.includes("The tool executed your command") ||
|
|
254
|
+
p.text.includes("The command was executed successfully") ||
|
|
255
|
+
p.text.includes("To complete your request")
|
|
256
|
+
);
|
|
257
|
+
});
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
for (let i = 0; i < output.messages.length; i++) {
|
|
261
|
+
const msg = output.messages[i];
|
|
262
|
+
const role = msg.info?.role ?? msg.role;
|
|
263
|
+
|
|
264
|
+
if (role === "assistant" && isSummaryLeak(msg)) {
|
|
265
|
+
log(`message-hooks: removing summary leak at index ${i}`);
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
filteredMessages.push(msg);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (filteredMessages.length !== output.messages.length) {
|
|
273
|
+
log(
|
|
274
|
+
`message-hooks: filtered ${output.messages.length - filteredMessages.length} summary leak messages`
|
|
275
|
+
);
|
|
276
|
+
// CRITICAL: Must mutate the array IN PLACE, not reassign!
|
|
277
|
+
// Reassigning output.messages doesn't affect the original sessionMessages in OpenCode
|
|
278
|
+
output.messages.length = 0;
|
|
279
|
+
output.messages.push(...filteredMessages);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
log(`message-hooks: post-filter, msgCount=${output.messages.length}`);
|
|
283
|
+
|
|
284
|
+
// NOTE: We don't try to delete messages from DB - client.session.removeMessage doesn't exist
|
|
285
|
+
// The filtering above is sufficient - it affects the current LLM call
|
|
286
|
+
|
|
287
|
+
log(`message-hooks: about to search for OPENCODE_GENERIC`);
|
|
288
|
+
|
|
289
|
+
// Find the LAST message with OPENCODE_GENERIC
|
|
290
|
+
let lastGenericPart: any = null;
|
|
291
|
+
let lastGenericMsg: any = null;
|
|
292
|
+
let lastGenericMsgIndex: number = -1;
|
|
293
|
+
|
|
294
|
+
log(
|
|
295
|
+
`message-hooks: searching ${output.messages.length} messages for OPENCODE_GENERIC`
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
for (let i = 0; i < output.messages.length; i++) {
|
|
299
|
+
const msg = output.messages[i];
|
|
300
|
+
for (const part of msg.parts || []) {
|
|
301
|
+
if (part.type === "text") {
|
|
302
|
+
const isGeneric = part.text === OPENCODE_GENERIC;
|
|
303
|
+
if (part.synthetic) {
|
|
304
|
+
log(
|
|
305
|
+
`message-hooks: found synthetic text at [${i}]: "${part.text?.substring(0, 50)}..." matches=${isGeneric}`
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
if (isGeneric) {
|
|
309
|
+
lastGenericPart = part;
|
|
310
|
+
lastGenericMsg = msg;
|
|
311
|
+
lastGenericMsgIndex = i;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
log(
|
|
318
|
+
`message-hooks: generic search complete, found=${!!lastGenericPart}, index=${lastGenericMsgIndex}`
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
// If no generic part found, check for pending prompt returns from inline subtasks
|
|
322
|
+
// Inline subtasks don't get OPENCODE_GENERIC, so we inject the pending prompt directly
|
|
323
|
+
if (!lastGenericPart) {
|
|
324
|
+
log(
|
|
325
|
+
`message-hooks: no generic part found, checking for pending prompt return`
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
for (const sid of sessionIDs) {
|
|
329
|
+
const pendingPrompt = consumePendingPromptReturn(sid as string);
|
|
330
|
+
if (pendingPrompt) {
|
|
331
|
+
log(`message-hooks: found pendingPromptReturn for ${sid}, injecting`);
|
|
332
|
+
|
|
333
|
+
// Clone structure from an existing user message to ensure correct format
|
|
334
|
+
const existingUserMsg = output.messages.find(
|
|
335
|
+
(m: any) => (m.info?.role ?? m.role) === "user"
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
if (existingUserMsg) {
|
|
339
|
+
const newMsg = JSON.parse(JSON.stringify(existingUserMsg));
|
|
340
|
+
newMsg.parts = [{ type: "text", text: pendingPrompt }];
|
|
341
|
+
// Remove IDs so OpenCode doesn't get confused
|
|
342
|
+
if (newMsg.id) delete newMsg.id;
|
|
343
|
+
if (newMsg.info?.id) delete newMsg.info.id;
|
|
344
|
+
if (newMsg.info?.createdAt) delete newMsg.info.createdAt;
|
|
345
|
+
output.messages.push(newMsg);
|
|
346
|
+
log(
|
|
347
|
+
`message-hooks: injected pending prompt: "${pendingPrompt.substring(0, 40)}..."`
|
|
348
|
+
);
|
|
349
|
+
} else {
|
|
350
|
+
// Fallback: create minimal message
|
|
351
|
+
output.messages.push({
|
|
352
|
+
info: { role: "user" },
|
|
353
|
+
parts: [{ type: "text", text: pendingPrompt }],
|
|
354
|
+
});
|
|
355
|
+
log(
|
|
356
|
+
`message-hooks: injected pending prompt (fallback): "${pendingPrompt.substring(0, 40)}..."`
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
return; // Let the LLM respond to our injected message
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (hasReturnStack(sid as string)) {
|
|
363
|
+
log(
|
|
364
|
+
`message-hooks: session ${sid} HAS returnStack but no generic part!`
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return; // Nothing to do without generic part
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// The generic message is in a subtask session, but returns are stored under the PARENT session
|
|
372
|
+
// We need to resolve the parent session to look up returns
|
|
373
|
+
const subtaskSessionID = lastGenericMsg?.info?.sessionID;
|
|
374
|
+
const resolvedParent = subtaskSessionID
|
|
375
|
+
? getSubtaskParentSession(subtaskSessionID)
|
|
376
|
+
: undefined;
|
|
377
|
+
const parentSessionID = resolvedParent || subtaskSessionID;
|
|
378
|
+
|
|
379
|
+
log(
|
|
380
|
+
`message-hooks: subtaskSession=${subtaskSessionID}, resolvedParent=${resolvedParent || "NOT FOUND"}, using=${parentSessionID}`
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
// Check for deferred prompt return from session.idle
|
|
384
|
+
// This handles prompt returns that were deferred to be substituted here
|
|
385
|
+
log(
|
|
386
|
+
`message-hooks: checking pendingPromptReturn for session ${parentSessionID}`
|
|
387
|
+
);
|
|
388
|
+
if (parentSessionID) {
|
|
389
|
+
const pendingPrompt = consumePendingPromptReturn(parentSessionID);
|
|
390
|
+
if (pendingPrompt) {
|
|
391
|
+
replaceAndClear(
|
|
392
|
+
lastGenericPart,
|
|
393
|
+
lastGenericMsg,
|
|
394
|
+
lastGenericMsgIndex,
|
|
395
|
+
pendingPrompt,
|
|
396
|
+
output.messages
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
// Mark that we're waiting for LLM response to this prompt
|
|
400
|
+
setPendingStackedPromptResponse(parentSessionID);
|
|
401
|
+
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Check for pending loop evaluation first (orchestrator-decides pattern)
|
|
407
|
+
log(`message-hooks: checking loop evaluations`);
|
|
408
|
+
for (const [sessionID, retryState] of getAllPendingEvaluations()) {
|
|
409
|
+
// Check if this is an unconditional loop (no until condition)
|
|
410
|
+
if (!retryState.config.until) {
|
|
411
|
+
// Unconditional loop: inject yield prompt, no evaluation needed
|
|
412
|
+
const yieldPrompt = createYieldPrompt(
|
|
413
|
+
retryState.iteration,
|
|
414
|
+
retryState.config.max
|
|
415
|
+
);
|
|
416
|
+
// Unconditional loop: modify in place
|
|
417
|
+
lastGenericPart.text = yieldPrompt;
|
|
418
|
+
log(
|
|
419
|
+
`loop: injected yield prompt (unconditional loop ${retryState.iteration}/${retryState.config.max})`
|
|
420
|
+
);
|
|
421
|
+
} else {
|
|
422
|
+
// Conditional loop: inject evaluation prompt
|
|
423
|
+
const evalPrompt = createEvaluationPrompt(
|
|
424
|
+
retryState.config.until,
|
|
425
|
+
retryState.iteration,
|
|
426
|
+
retryState.config.max
|
|
427
|
+
);
|
|
428
|
+
// Modify in place
|
|
429
|
+
lastGenericPart.text = evalPrompt;
|
|
430
|
+
log(
|
|
431
|
+
`loop: injected evaluation prompt for "${retryState.config.until}"`
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
// Don't delete yet - we need it when parsing the response
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Check for pending return
|
|
439
|
+
const pendingReturnsEntries = [...getAllPendingReturns()];
|
|
440
|
+
log(
|
|
441
|
+
`message-hooks: checking pendingReturns, count=${pendingReturnsEntries.length}`
|
|
442
|
+
);
|
|
443
|
+
for (const [sessionID, returnPrompt] of pendingReturnsEntries) {
|
|
444
|
+
deletePendingReturn(sessionID);
|
|
445
|
+
setHasActiveSubtask(false);
|
|
446
|
+
|
|
447
|
+
// Also shift from returnState to keep them in sync
|
|
448
|
+
// This prevents session.idle from trying to re-execute the same return
|
|
449
|
+
const returnStateData = getReturnState(sessionID);
|
|
450
|
+
if (returnStateData?.length && returnStateData[0] === returnPrompt) {
|
|
451
|
+
returnStateData.shift();
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (returnPrompt.startsWith("/")) {
|
|
455
|
+
// Command return: remove the summarize message entirely from history
|
|
456
|
+
// and fire the command immediately at this moment
|
|
457
|
+
if (lastGenericMsgIndex >= 0) {
|
|
458
|
+
output.messages.splice(lastGenericMsgIndex, 1);
|
|
459
|
+
|
|
460
|
+
// Also delete from DB to prevent OpenCode from re-fetching and responding to it
|
|
461
|
+
const msgId = lastGenericMsg?.id;
|
|
462
|
+
const partId = lastGenericPart?.id;
|
|
463
|
+
if (msgId && partId) {
|
|
464
|
+
const client = getClient();
|
|
465
|
+
// Delete the part (this effectively removes the message content)
|
|
466
|
+
client.session
|
|
467
|
+
.deletePart({ path: { id: partId } })
|
|
468
|
+
.catch((e: Error) => {
|
|
469
|
+
log(`Failed to delete summarize part from DB: ${e.message}`);
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
log(
|
|
474
|
+
`Removed summarize message at index ${lastGenericMsgIndex} for command return`
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
executeReturn(returnPrompt, sessionID).catch(console.error);
|
|
478
|
+
} else {
|
|
479
|
+
// Plain prompt return: MODIFY the existing part directly (for LLM)
|
|
480
|
+
replaceAndClear(
|
|
481
|
+
lastGenericPart,
|
|
482
|
+
lastGenericMsg,
|
|
483
|
+
lastGenericMsgIndex,
|
|
484
|
+
returnPrompt,
|
|
485
|
+
output.messages
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// No pending return found, check returnState for remaining returns
|
|
492
|
+
// This handles returns after the first one (which used pendingReturns)
|
|
493
|
+
// Use parentSessionID (resolved earlier) since returns are stored under parent session
|
|
494
|
+
if (parentSessionID) {
|
|
495
|
+
const remaining = getReturnState(parentSessionID);
|
|
496
|
+
if (remaining?.length) {
|
|
497
|
+
const nextReturn = remaining[0];
|
|
498
|
+
setHasActiveSubtask(false);
|
|
499
|
+
|
|
500
|
+
if (nextReturn.startsWith("/")) {
|
|
501
|
+
// Command return: remove the summarize message, let session.idle execute
|
|
502
|
+
if (lastGenericMsgIndex >= 0) {
|
|
503
|
+
output.messages.splice(lastGenericMsgIndex, 1);
|
|
504
|
+
log(
|
|
505
|
+
`Removed summarize message - returnState command will be processed by session.idle`
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
} else {
|
|
509
|
+
// Prompt return: REPLACE the message so LLM responds to it
|
|
510
|
+
// NOTE: We must replace the entire message, not just modify the part text,
|
|
511
|
+
// because OpenCode may deep-copy messages before sending to LLM
|
|
512
|
+
// First, check if there are stacked returns from inline subtasks
|
|
513
|
+
// and transfer them to returnState so the chain continues
|
|
514
|
+
const stackedReturns = getCurrentReturnChain(parentSessionID);
|
|
515
|
+
if (stackedReturns?.length) {
|
|
516
|
+
remaining.push(...stackedReturns);
|
|
517
|
+
popCurrentReturnChain(parentSessionID);
|
|
518
|
+
log(
|
|
519
|
+
`Transferred ${stackedReturns.length} stacked returns to returnState for continued processing`
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Shift from returnState since we're handling it here
|
|
524
|
+
remaining.shift();
|
|
525
|
+
|
|
526
|
+
replaceAndClear(
|
|
527
|
+
lastGenericPart,
|
|
528
|
+
lastGenericMsg,
|
|
529
|
+
lastGenericMsgIndex,
|
|
530
|
+
nextReturn,
|
|
531
|
+
output.messages
|
|
532
|
+
);
|
|
533
|
+
|
|
534
|
+
// Mark that we're waiting for LLM response to this prompt
|
|
535
|
+
// This prevents session.idle from processing the next return too early
|
|
536
|
+
setPendingStackedPromptResponse(parentSessionID);
|
|
537
|
+
}
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// No returns found, use generic replacement if configured
|
|
543
|
+
// BUT skip if there are stacked returns (from inline subtasks with returns)
|
|
544
|
+
// Those will be processed by session.idle hook
|
|
545
|
+
const pluginConfig = getPluginConfig();
|
|
546
|
+
|
|
547
|
+
// Check if the parent session has stacked returns
|
|
548
|
+
// Use parentSessionID (resolved earlier) since stacked returns are stored under parent session
|
|
549
|
+
let stackedSessionID: string | null = null;
|
|
550
|
+
if (parentSessionID && hasReturnStack(parentSessionID)) {
|
|
551
|
+
stackedSessionID = parentSessionID;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
if (stackedSessionID) {
|
|
555
|
+
// Peek at the first stacked return to decide how to handle
|
|
556
|
+
const nextReturnArray = peekReturnStack(stackedSessionID);
|
|
557
|
+
const nextReturn = nextReturnArray?.[0];
|
|
558
|
+
|
|
559
|
+
if (nextReturn?.startsWith("/")) {
|
|
560
|
+
// Command return: remove the summarize message, let session.idle execute
|
|
561
|
+
if (lastGenericMsgIndex >= 0) {
|
|
562
|
+
output.messages.splice(lastGenericMsgIndex, 1);
|
|
563
|
+
log(
|
|
564
|
+
`Removed summarize message - stacked command return will be processed by session.idle`
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
} else if (nextReturn) {
|
|
568
|
+
// Prompt return: REPLACE the message so LLM responds to it
|
|
569
|
+
const returnPrompt = shiftReturnStack(stackedSessionID);
|
|
570
|
+
if (returnPrompt) {
|
|
571
|
+
replaceAndClear(
|
|
572
|
+
lastGenericPart,
|
|
573
|
+
lastGenericMsg,
|
|
574
|
+
lastGenericMsgIndex,
|
|
575
|
+
returnPrompt,
|
|
576
|
+
output.messages
|
|
577
|
+
);
|
|
578
|
+
|
|
579
|
+
// Mark that we're waiting for LLM response to this prompt
|
|
580
|
+
// This prevents session.idle from processing returnState too early
|
|
581
|
+
setPendingStackedPromptResponse(stackedSessionID);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
setHasActiveSubtask(false);
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
if (getHasActiveSubtask() && pluginConfig.replace_generic) {
|
|
589
|
+
const text = pluginConfig.generic_return ?? DEFAULT_PROMPT;
|
|
590
|
+
replaceAndClear(
|
|
591
|
+
lastGenericPart,
|
|
592
|
+
lastGenericMsg,
|
|
593
|
+
lastGenericMsgIndex,
|
|
594
|
+
text,
|
|
595
|
+
output.messages
|
|
596
|
+
);
|
|
597
|
+
setHasActiveSubtask(false);
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
} catch (err) {
|
|
601
|
+
log(`message-hooks: EXCEPTION: ${err}`);
|
|
602
|
+
}
|
|
603
|
+
}
|