muonroi-cli 1.8.4 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +17 -5
- package/dist/packages/agent-harness-core/src/driver.d.ts +27 -1
- package/dist/packages/agent-harness-core/src/driver.js +46 -0
- package/dist/packages/agent-harness-core/src/event-filter.js +11 -0
- package/dist/packages/agent-harness-core/src/event-redact.js +7 -0
- package/dist/packages/agent-harness-core/src/event-tee.d.ts +64 -0
- package/dist/packages/agent-harness-core/src/event-tee.js +104 -0
- package/dist/packages/agent-harness-core/src/mcp-server.d.ts +25 -0
- package/dist/packages/agent-harness-core/src/mcp-server.js +169 -21
- package/dist/packages/agent-harness-core/src/predicate.d.ts +1 -1
- package/dist/packages/agent-harness-core/src/protocol.d.ts +90 -4
- package/dist/packages/agent-harness-core/src/protocol.js +15 -0
- package/dist/packages/agent-harness-core/src/visual-quality.d.ts +58 -0
- package/dist/packages/agent-harness-core/src/visual-quality.js +141 -0
- package/dist/packages/agent-harness-opentui/src/agent-mode.d.ts +6 -0
- package/dist/packages/agent-harness-opentui/src/agent-mode.js +14 -1
- package/dist/packages/agent-harness-opentui/src/input-bridge.d.ts +2 -10
- package/dist/packages/agent-harness-opentui/src/input-bridge.js +103 -16
- package/dist/packages/agent-harness-opentui/src/install.d.ts +8 -0
- package/dist/packages/agent-harness-opentui/src/install.js +10 -0
- package/dist/packages/agent-harness-opentui/src/semantic.js +12 -10
- package/dist/packages/agent-harness-opentui/src/visual-capture.d.ts +56 -0
- package/dist/packages/agent-harness-opentui/src/visual-capture.js +103 -0
- package/dist/src/agent-harness/mock-model.d.ts +38 -0
- package/dist/src/agent-harness/mock-model.js +69 -3
- package/dist/src/agent-harness/test-spawn.js +31 -0
- package/dist/src/chat/chat-keychain.d.ts +7 -12
- package/dist/src/chat/chat-keychain.js +19 -86
- package/dist/src/cli/config/screen-providers.js +1 -1
- package/dist/src/cli/cost-forensics.d.ts +10 -0
- package/dist/src/cli/cost-forensics.js +18 -3
- package/dist/src/cli/keys-bundle.d.ts +1 -1
- package/dist/src/cli/keys-bundle.js +1 -1
- package/dist/src/cli/keys.d.ts +10 -47
- package/dist/src/cli/keys.js +31 -399
- package/dist/src/council/clarifier.d.ts +31 -3
- package/dist/src/council/clarifier.js +220 -32
- package/dist/src/council/context.js +49 -15
- package/dist/src/council/debate-checkpoint.d.ts +129 -0
- package/dist/src/council/debate-checkpoint.js +176 -0
- package/dist/src/council/debate-planner.js +54 -5
- package/dist/src/council/debate-summary.d.ts +25 -0
- package/dist/src/council/debate-summary.js +85 -0
- package/dist/src/council/debate.d.ts +169 -2
- package/dist/src/council/debate.js +1265 -135
- package/dist/src/council/index.d.ts +108 -1
- package/dist/src/council/index.js +670 -197
- package/dist/src/council/leader.d.ts +26 -0
- package/dist/src/council/leader.js +150 -9
- package/dist/src/council/llm.d.ts +94 -0
- package/dist/src/council/llm.js +348 -55
- package/dist/src/council/panel-select.d.ts +30 -0
- package/dist/src/council/panel-select.js +82 -0
- package/dist/src/council/planner.js +40 -0
- package/dist/src/council/preflight.d.ts +17 -0
- package/dist/src/council/preflight.js +50 -2
- package/dist/src/council/prompts.d.ts +39 -4
- package/dist/src/council/prompts.js +256 -69
- package/dist/src/council/stance-recall.d.ts +42 -0
- package/dist/src/council/stance-recall.js +57 -0
- package/dist/src/council/strip-think.d.ts +17 -0
- package/dist/src/council/strip-think.js +33 -0
- package/dist/src/council/types.d.ts +138 -0
- package/dist/src/ee/artifact-cache.d.ts +16 -0
- package/dist/src/ee/artifact-cache.js +32 -0
- package/dist/src/ee/auth.d.ts +20 -0
- package/dist/src/ee/auth.js +54 -2
- package/dist/src/ee/bridge.d.ts +10 -0
- package/dist/src/ee/bridge.js +58 -0
- package/dist/src/ee/client.js +109 -21
- package/dist/src/ee/ee-onboarding.js +6 -26
- package/dist/src/ee/export-transcripts.d.ts +1 -0
- package/dist/src/ee/export-transcripts.js +8 -10
- package/dist/src/ee/extract-session.js +29 -0
- package/dist/src/ee/extract-style.d.ts +58 -0
- package/dist/src/ee/extract-style.js +270 -0
- package/dist/src/ee/recall-ledger.d.ts +9 -0
- package/dist/src/ee/recall-ledger.js +3 -0
- package/dist/src/ee/scope.d.ts +1 -0
- package/dist/src/ee/scope.js +26 -1
- package/dist/src/ee/search.d.ts +7 -0
- package/dist/src/ee/search.js +24 -0
- package/dist/src/ee/transcript-emit.js +2 -0
- package/dist/src/ee/types.d.ts +22 -0
- package/dist/src/ee/who-am-i-brain.d.ts +35 -0
- package/dist/src/ee/who-am-i-brain.js +220 -0
- package/dist/src/ee/who-am-i.d.ts +10 -3
- package/dist/src/ee/who-am-i.js +12 -0
- package/dist/src/ee/workflow-event.d.ts +48 -0
- package/dist/src/ee/workflow-event.js +81 -0
- package/dist/src/flow/compaction/compress.d.ts +3 -3
- package/dist/src/flow/compaction/compress.js +58 -8
- package/dist/src/flow/compaction/extract.d.ts +4 -7
- package/dist/src/flow/compaction/extract.js +50 -10
- package/dist/src/flow/compaction/index.d.ts +14 -1
- package/dist/src/flow/compaction/index.js +96 -3
- package/dist/src/flow/compaction/input-guard.d.ts +24 -0
- package/dist/src/flow/compaction/input-guard.js +43 -0
- package/dist/src/flow/compaction/progress.d.ts +35 -0
- package/dist/src/flow/compaction/progress.js +35 -0
- package/dist/src/flow/fold-planning.d.ts +36 -0
- package/dist/src/flow/fold-planning.js +83 -0
- package/dist/src/flow/hierarchy.d.ts +146 -0
- package/dist/src/flow/hierarchy.js +427 -0
- package/dist/src/flow/index.d.ts +1 -0
- package/dist/src/flow/index.js +2 -0
- package/dist/src/flow/run-artifacts.d.ts +102 -0
- package/dist/src/flow/run-artifacts.js +208 -0
- package/dist/src/generated/version.d.ts +1 -1
- package/dist/src/generated/version.js +1 -1
- package/dist/src/gsd/assessment-schema.d.ts +44 -0
- package/dist/src/gsd/assessment-schema.js +134 -0
- package/dist/src/gsd/capability-registry.d.ts +45 -0
- package/dist/src/gsd/capability-registry.js +337 -0
- package/dist/src/gsd/complexity-assessor.d.ts +39 -0
- package/dist/src/gsd/complexity-assessor.js +152 -0
- package/dist/src/gsd/config-bridge.d.ts +7 -0
- package/dist/src/gsd/config-bridge.js +114 -0
- package/dist/src/gsd/config-loader.d.ts +27 -0
- package/dist/src/gsd/config-loader.js +50 -0
- package/dist/src/gsd/council-context.d.ts +44 -0
- package/dist/src/gsd/council-context.js +114 -0
- package/dist/src/gsd/ee-closure.d.ts +28 -0
- package/dist/src/gsd/ee-closure.js +49 -0
- package/dist/src/gsd/flags.d.ts +66 -0
- package/dist/src/gsd/flags.js +102 -0
- package/dist/src/gsd/gsd-dispatch.d.ts +58 -0
- package/dist/src/gsd/gsd-dispatch.js +131 -0
- package/dist/src/gsd/gsd-runtime.d.ts +22 -0
- package/dist/src/gsd/gsd-runtime.js +37 -0
- package/dist/src/gsd/host-adapter.d.ts +11 -0
- package/dist/src/gsd/host-adapter.js +29 -0
- package/dist/src/gsd/index.d.ts +24 -1
- package/dist/src/gsd/index.js +27 -0
- package/dist/src/gsd/loop-host-contract.d.ts +21 -0
- package/dist/src/gsd/loop-host-contract.js +39 -0
- package/dist/src/gsd/loop-host.d.ts +69 -0
- package/dist/src/gsd/loop-host.js +245 -0
- package/dist/src/gsd/loop-resolver.d.ts +36 -0
- package/dist/src/gsd/loop-resolver.js +79 -0
- package/dist/src/gsd/model-tier.d.ts +13 -0
- package/dist/src/gsd/model-tier.js +45 -0
- package/dist/src/gsd/mutation-gate.d.ts +16 -0
- package/dist/src/gsd/mutation-gate.js +41 -0
- package/dist/src/gsd/native-roadmap.d.ts +89 -0
- package/dist/src/gsd/native-roadmap.js +343 -0
- package/dist/src/gsd/native-state.d.ts +47 -0
- package/dist/src/gsd/native-state.js +220 -0
- package/dist/src/gsd/paths.d.ts +23 -0
- package/dist/src/gsd/paths.js +66 -0
- package/dist/src/gsd/phase-dag.d.ts +12 -0
- package/dist/src/gsd/phase-dag.js +94 -0
- package/dist/src/gsd/phase-sync.d.ts +42 -0
- package/dist/src/gsd/phase-sync.js +321 -0
- package/dist/src/gsd/pil-gate-context.d.ts +13 -0
- package/dist/src/gsd/pil-gate-context.js +64 -0
- package/dist/src/gsd/pil-gate-critic.d.ts +19 -0
- package/dist/src/gsd/pil-gate-critic.js +74 -0
- package/dist/src/gsd/plan-council-prompts.d.ts +25 -0
- package/dist/src/gsd/plan-council-prompts.js +79 -0
- package/dist/src/gsd/plan-council.d.ts +44 -0
- package/dist/src/gsd/plan-council.js +283 -0
- package/dist/src/gsd/plan-gate-vocabulary.d.ts +40 -0
- package/dist/src/gsd/plan-gate-vocabulary.js +64 -0
- package/dist/src/gsd/product-workspace.d.ts +13 -0
- package/dist/src/gsd/product-workspace.js +124 -0
- package/dist/src/gsd/ship-bridge.d.ts +25 -0
- package/dist/src/gsd/ship-bridge.js +65 -0
- package/dist/src/gsd/state-document.d.ts +40 -0
- package/dist/src/gsd/state-document.js +163 -0
- package/dist/src/gsd/verdict-schema.d.ts +39 -0
- package/dist/src/gsd/verdict-schema.js +144 -0
- package/dist/src/gsd/verify-context.d.ts +22 -0
- package/dist/src/gsd/verify-context.js +27 -0
- package/dist/src/gsd/verify-council-prompts.d.ts +19 -0
- package/dist/src/gsd/verify-council-prompts.js +85 -0
- package/dist/src/gsd/verify-council.d.ts +25 -0
- package/dist/src/gsd/verify-council.js +119 -0
- package/dist/src/gsd/verify-gate-vocabulary.d.ts +25 -0
- package/dist/src/gsd/verify-gate-vocabulary.js +46 -0
- package/dist/src/gsd/workflow-engine.d.ts +60 -0
- package/dist/src/gsd/workflow-engine.js +207 -0
- package/dist/src/gsd/workflow-tools.d.ts +13 -0
- package/dist/src/gsd/workflow-tools.js +277 -0
- package/dist/src/headless/council-answers.js +4 -0
- package/dist/src/hooks/index.js +1 -1
- package/dist/src/index.js +172 -270
- package/dist/src/lsp/builtins.js +3 -1
- package/dist/src/lsp/manager.d.ts +5 -1
- package/dist/src/lsp/manager.js +249 -3
- package/dist/src/lsp/npm-cache.d.ts +11 -1
- package/dist/src/lsp/npm-cache.js +17 -1
- package/dist/src/lsp/runtime.d.ts +6 -1
- package/dist/src/lsp/runtime.js +17 -1
- package/dist/src/lsp/types.d.ts +83 -1
- package/dist/src/lsp/types.js +10 -0
- package/dist/src/maintain/pr-builder.js +23 -13
- package/dist/src/mcp/auto-setup.js +57 -32
- package/dist/src/mcp/client-pool.js +44 -16
- package/dist/src/mcp/lsp-tools.d.ts +5 -1
- package/dist/src/mcp/lsp-tools.js +93 -2
- package/dist/src/mcp/mcp-keychain.d.ts +3 -5
- package/dist/src/mcp/mcp-keychain.js +9 -49
- package/dist/src/mcp/research-onboarding.js +8 -7
- package/dist/src/mcp/runtime.js +34 -2
- package/dist/src/mcp/setup-guide-text.d.ts +1 -1
- package/dist/src/mcp/setup-guide-text.js +22 -2
- package/dist/src/mcp/tools-server.d.ts +10 -0
- package/dist/src/mcp/tools-server.js +10 -2
- package/dist/src/models/catalog-client.d.ts +87 -0
- package/dist/src/models/catalog-client.js +105 -38
- package/dist/src/models/catalog.json +528 -265
- package/dist/src/models/registry.d.ts +22 -7
- package/dist/src/models/registry.js +73 -10
- package/dist/src/ops/doctor.js +1 -1
- package/dist/src/orchestrator/ask-user.d.ts +61 -0
- package/dist/src/orchestrator/ask-user.js +65 -0
- package/dist/src/orchestrator/auto-commit.js +1 -1
- package/dist/src/orchestrator/batch-turn-runner.js +2 -2
- package/dist/src/orchestrator/cache-prefix.d.ts +67 -0
- package/dist/src/orchestrator/cache-prefix.js +83 -0
- package/dist/src/orchestrator/compact-request.d.ts +32 -0
- package/dist/src/orchestrator/compact-request.js +41 -0
- package/dist/src/orchestrator/compaction.d.ts +12 -3
- package/dist/src/orchestrator/compaction.js +35 -15
- package/dist/src/orchestrator/council-manager.d.ts +12 -3
- package/dist/src/orchestrator/council-manager.js +74 -32
- package/dist/src/orchestrator/council-request.d.ts +49 -0
- package/dist/src/orchestrator/council-request.js +62 -0
- package/dist/src/orchestrator/cross-turn-dedup.d.ts +6 -0
- package/dist/src/orchestrator/cross-turn-dedup.js +22 -1
- package/dist/src/orchestrator/error-utils.d.ts +29 -0
- package/dist/src/orchestrator/error-utils.js +132 -24
- package/dist/src/orchestrator/grounding-check.js +39 -1
- package/dist/src/orchestrator/interactive-pause.d.ts +26 -0
- package/dist/src/orchestrator/interactive-pause.js +36 -0
- package/dist/src/orchestrator/message-processor.d.ts +4 -0
- package/dist/src/orchestrator/message-processor.js +268 -41
- package/dist/src/orchestrator/orchestrator.d.ts +64 -3
- package/dist/src/orchestrator/orchestrator.js +823 -120
- package/dist/src/orchestrator/preprocessor.js +3 -3
- package/dist/src/orchestrator/proactive-compact-detector.d.ts +26 -0
- package/dist/src/orchestrator/proactive-compact-detector.js +36 -0
- package/dist/src/orchestrator/prompts.js +17 -17
- package/dist/src/orchestrator/reactive-delegation.d.ts +39 -0
- package/dist/src/orchestrator/reactive-delegation.js +59 -0
- package/dist/src/orchestrator/retry-classifier.d.ts +2 -1
- package/dist/src/orchestrator/retry-classifier.js +46 -2
- package/dist/src/orchestrator/safety-askcard.d.ts +1 -1
- package/dist/src/orchestrator/safety-askcard.js +5 -2
- package/dist/src/orchestrator/safety-intercept.d.ts +50 -0
- package/dist/src/orchestrator/safety-intercept.js +62 -0
- package/dist/src/orchestrator/scope-reminder.js +1 -1
- package/dist/src/orchestrator/session-experience.d.ts +2 -1
- package/dist/src/orchestrator/session-experience.js +2 -1
- package/dist/src/orchestrator/should-run-gate.d.ts +5 -0
- package/dist/src/orchestrator/should-run-gate.js +18 -0
- package/dist/src/orchestrator/stall-watchdog.d.ts +31 -3
- package/dist/src/orchestrator/stall-watchdog.js +65 -10
- package/dist/src/orchestrator/stream-runner.d.ts +13 -3
- package/dist/src/orchestrator/stream-runner.js +115 -49
- package/dist/src/orchestrator/sub-agent-cap.d.ts +13 -1
- package/dist/src/orchestrator/sub-agent-cap.js +16 -1
- package/dist/src/orchestrator/sub-agent-model-tier.d.ts +13 -1
- package/dist/src/orchestrator/sub-agent-model-tier.js +16 -2
- package/dist/src/orchestrator/subagent-compactor.d.ts +53 -1
- package/dist/src/orchestrator/subagent-compactor.js +126 -15
- package/dist/src/orchestrator/tool-engine.d.ts +41 -0
- package/dist/src/orchestrator/tool-engine.js +846 -66
- package/dist/src/orchestrator/tool-limit-auto-recover.d.ts +22 -0
- package/dist/src/orchestrator/tool-limit-auto-recover.js +30 -0
- package/dist/src/orchestrator/turn-runner-deps.d.ts +19 -0
- package/dist/src/orchestrator/turn-watchdog.d.ts +44 -0
- package/dist/src/orchestrator/turn-watchdog.js +84 -0
- package/dist/src/pil/agent-operating-contract.d.ts +1 -1
- package/dist/src/pil/agent-operating-contract.js +6 -4
- package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
- package/dist/src/pil/cheap-model-playbook.js +5 -1
- package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
- package/dist/src/pil/cheap-model-workbooks.js +1 -1
- package/dist/src/pil/discovery-types.d.ts +1 -0
- package/dist/src/pil/discovery.d.ts +1 -1
- package/dist/src/pil/discovery.js +18 -13
- package/dist/src/pil/layer1-intent.d.ts +18 -6
- package/dist/src/pil/layer1-intent.js +66 -757
- package/dist/src/pil/layer15-context-scan.js +15 -1
- package/dist/src/pil/layer1_5-complexity-size.d.ts +7 -0
- package/dist/src/pil/layer1_5-complexity-size.js +31 -5
- package/dist/src/pil/layer3-ee-injection.js +23 -8
- package/dist/src/pil/layer4-gsd.js +69 -16
- package/dist/src/pil/layer5-context.js +7 -3
- package/dist/src/pil/layer6-output.d.ts +23 -0
- package/dist/src/pil/layer6-output.js +5 -1
- package/dist/src/pil/llm-classify.d.ts +111 -5
- package/dist/src/pil/llm-classify.js +421 -189
- package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
- package/dist/src/pil/native-capabilities-workbook.js +8 -0
- package/dist/src/pil/pipeline.js +36 -2
- package/dist/src/pil/repo-grounding-probe.d.ts +15 -0
- package/dist/src/pil/repo-grounding-probe.js +136 -0
- package/dist/src/pil/repo-structure-hints.d.ts +7 -0
- package/dist/src/pil/repo-structure-hints.js +45 -0
- package/dist/src/pil/response-tools.js +5 -3
- package/dist/src/pil/schema.d.ts +1 -0
- package/dist/src/pil/schema.js +2 -0
- package/dist/src/pil/types.d.ts +18 -0
- package/dist/src/playbook/directives.d.ts +4 -0
- package/dist/src/playbook/directives.js +17 -5
- package/dist/src/product-loop/artifact-io.js +4 -0
- package/dist/src/product-loop/backlog-builder.d.ts +14 -1
- package/dist/src/product-loop/backlog-builder.js +30 -6
- package/dist/src/product-loop/criteria-seed.d.ts +51 -0
- package/dist/src/product-loop/criteria-seed.js +200 -0
- package/dist/src/product-loop/discovery-context-format.js +3 -1
- package/dist/src/product-loop/discovery-ecosystem.js +4 -1
- package/dist/src/product-loop/discovery-interview.d.ts +9 -0
- package/dist/src/product-loop/discovery-interview.js +60 -12
- package/dist/src/product-loop/discovery-recommender.js +2 -1
- package/dist/src/product-loop/discovery-schema.js +19 -2
- package/dist/src/product-loop/discovery-triage.d.ts +23 -0
- package/dist/src/product-loop/discovery-triage.js +109 -0
- package/dist/src/product-loop/gather.js +150 -2
- package/dist/src/product-loop/ideal-trace.d.ts +7 -0
- package/dist/src/product-loop/ideal-trace.js +64 -0
- package/dist/src/product-loop/index.d.ts +13 -1
- package/dist/src/product-loop/index.js +340 -52
- package/dist/src/product-loop/loop-driver.d.ts +7 -0
- package/dist/src/product-loop/loop-driver.js +330 -106
- package/dist/src/product-loop/phase-plan.d.ts +21 -0
- package/dist/src/product-loop/phase-plan.js +81 -6
- package/dist/src/product-loop/phase-rituals.d.ts +3 -0
- package/dist/src/product-loop/phase-rituals.js +8 -3
- package/dist/src/product-loop/phase-runner.js +39 -12
- package/dist/src/product-loop/plan-adherence-review.d.ts +26 -0
- package/dist/src/product-loop/plan-adherence-review.js +144 -0
- package/dist/src/product-loop/sprint-runner.d.ts +173 -0
- package/dist/src/product-loop/sprint-runner.js +863 -19
- package/dist/src/product-loop/types.d.ts +61 -5
- package/dist/src/providers/adapter.d.ts +1 -1
- package/dist/src/providers/adapter.js +3 -4
- package/dist/src/providers/anthropic.d.ts +9 -8
- package/dist/src/providers/anthropic.js +13 -47
- package/dist/src/providers/auth/browser-flow.d.ts +1 -1
- package/dist/src/providers/auth/browser-flow.js +1 -1
- package/dist/src/providers/auth/grok-oauth.d.ts +1 -0
- package/dist/src/providers/auth/grok-oauth.js +30 -5
- package/dist/src/providers/auth/openai-oauth.d.ts +1 -0
- package/dist/src/providers/auth/openai-oauth.js +15 -1
- package/dist/src/providers/auth/registry.js +0 -34
- package/dist/src/providers/auth/token-store.d.ts +9 -9
- package/dist/src/providers/auth/token-store.js +8 -67
- package/dist/src/providers/auth/types.d.ts +9 -1
- package/dist/src/providers/auth/types.js +1 -1
- package/dist/src/providers/capabilities.d.ts +24 -5
- package/dist/src/providers/capabilities.js +42 -24
- package/dist/src/providers/endpoints.d.ts +2 -2
- package/dist/src/providers/endpoints.js +11 -10
- package/dist/src/providers/env-store.d.ts +17 -0
- package/dist/src/providers/env-store.js +228 -0
- package/dist/src/providers/keychain.d.ts +22 -18
- package/dist/src/providers/keychain.js +127 -140
- package/dist/src/providers/mcp-vision-bridge.js +56 -146
- package/dist/src/providers/openai-compatible.js +8 -1
- package/dist/src/providers/pricing.d.ts +2 -2
- package/dist/src/providers/pricing.js +3 -13
- package/dist/src/providers/runtime.d.ts +43 -3
- package/dist/src/providers/runtime.js +88 -14
- package/dist/src/providers/strategies/base.strategy.d.ts +16 -0
- package/dist/src/providers/strategies/base.strategy.js +24 -1
- package/dist/src/providers/strategies/{siliconflow.strategy.d.ts → opencode-go.strategy.d.ts} +3 -3
- package/dist/src/providers/strategies/opencode-go.strategy.js +83 -0
- package/dist/src/providers/strategies/registry.js +4 -4
- package/dist/src/providers/strategies/thinking-mode.d.ts +109 -0
- package/dist/src/providers/strategies/thinking-mode.js +288 -1
- package/dist/src/providers/strategies/xai.strategy.js +27 -0
- package/dist/src/providers/strategies/zai.strategy.d.ts +14 -0
- package/dist/src/providers/strategies/zai.strategy.js +44 -0
- package/dist/src/providers/types.d.ts +5 -6
- package/dist/src/providers/types.js +2 -2
- package/dist/src/providers/vision-backend.d.ts +47 -0
- package/dist/src/providers/vision-backend.js +258 -0
- package/dist/src/providers/vision-proxy.d.ts +22 -9
- package/dist/src/providers/vision-proxy.js +63 -132
- package/dist/src/providers/warm.d.ts +65 -0
- package/dist/src/providers/warm.js +145 -0
- package/dist/src/providers/wire-debug.js +95 -0
- package/dist/src/router/decide.d.ts +13 -0
- package/dist/src/router/decide.js +138 -36
- package/dist/src/router/peak-hour.d.ts +38 -0
- package/dist/src/router/peak-hour.js +107 -0
- package/dist/src/router/step-router.js +3 -2
- package/dist/src/router/warm.js +4 -5
- package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
- package/dist/src/scaffold/continuation-prompt.js +26 -0
- package/dist/src/scaffold/point-to-existing.d.ts +21 -0
- package/dist/src/scaffold/point-to-existing.js +25 -0
- package/dist/src/self-qa/agentic-loop.js +6 -5
- package/dist/src/{ui/state → state}/active-run.d.ts +19 -0
- package/dist/src/{ui/state → state}/active-run.js +21 -0
- package/dist/src/{ui/status-bar/store.d.ts → state/status-bar-store.d.ts} +4 -1
- package/dist/src/{ui/status-bar/store.js → state/status-bar-store.js} +12 -9
- package/dist/src/state/turn-trace.d.ts +43 -0
- package/dist/src/state/turn-trace.js +32 -0
- package/dist/src/storage/db.js +2 -1
- package/dist/src/storage/index.d.ts +1 -1
- package/dist/src/storage/index.js +1 -1
- package/dist/src/storage/interaction-log.d.ts +1 -1
- package/dist/src/storage/migrations.js +71 -1
- package/dist/src/storage/sessions.d.ts +28 -10
- package/dist/src/storage/sessions.js +78 -21
- package/dist/src/storage/transcript-view.js +1 -1
- package/dist/src/storage/transcript.d.ts +51 -0
- package/dist/src/storage/transcript.js +340 -15
- package/dist/src/tools/file.d.ts +15 -0
- package/dist/src/tools/file.js +32 -0
- package/dist/src/tools/git-safety.d.ts +19 -0
- package/dist/src/tools/git-safety.js +168 -0
- package/dist/src/tools/native-tools.d.ts +1 -1
- package/dist/src/tools/native-tools.js +81 -1
- package/dist/src/tools/registry.d.ts +20 -0
- package/dist/src/tools/registry.js +576 -23
- package/dist/src/tools/research.d.ts +29 -0
- package/dist/src/tools/research.js +233 -0
- package/dist/src/types/index.d.ts +147 -4
- package/dist/src/ui/app.js +0 -0
- package/dist/src/ui/cards/product-status-card.js +1 -1
- package/dist/src/ui/components/agent-rail-activities.d.ts +26 -0
- package/dist/src/ui/components/agent-rail-activities.js +47 -0
- package/dist/src/ui/components/bubble-body-guard.d.ts +27 -0
- package/dist/src/ui/components/bubble-body-guard.js +50 -0
- package/dist/src/ui/components/compact-progress-card.d.ts +24 -0
- package/dist/src/ui/components/compact-progress-card.js +42 -0
- package/dist/src/ui/components/context-rail.d.ts +26 -0
- package/dist/src/ui/components/context-rail.js +33 -0
- package/dist/src/ui/components/council-conclusion-card.d.ts +73 -0
- package/dist/src/ui/components/council-conclusion-card.js +420 -0
- package/dist/src/ui/components/council-debate-pill.d.ts +36 -0
- package/dist/src/ui/components/council-debate-pill.js +34 -0
- package/dist/src/ui/components/council-info-card.js +2 -2
- package/dist/src/ui/components/council-leader-bubble.d.ts +10 -3
- package/dist/src/ui/components/council-leader-bubble.js +21 -11
- package/dist/src/ui/components/council-message-bubble.d.ts +15 -2
- package/dist/src/ui/components/council-message-bubble.js +16 -15
- package/dist/src/ui/components/council-phase-timeline.d.ts +9 -1
- package/dist/src/ui/components/council-phase-timeline.js +66 -17
- package/dist/src/ui/components/council-placeholder-bubble.d.ts +16 -9
- package/dist/src/ui/components/council-placeholder-bubble.js +32 -29
- package/dist/src/ui/components/council-question-card.js +13 -12
- package/dist/src/ui/components/council-rail-rounds.d.ts +26 -0
- package/dist/src/ui/components/council-rail-rounds.js +57 -0
- package/dist/src/ui/components/council-round-group.d.ts +38 -0
- package/dist/src/ui/components/council-round-group.js +88 -0
- package/dist/src/ui/components/council-status-list.d.ts +3 -1
- package/dist/src/ui/components/council-status-list.js +36 -24
- package/dist/src/ui/components/council-synthesis-banner.d.ts +7 -2
- package/dist/src/ui/components/council-synthesis-banner.js +20 -5
- package/dist/src/ui/components/halt-recovery-card.js +9 -5
- package/dist/src/ui/components/jump-to-latest-pill.d.ts +11 -0
- package/dist/src/ui/components/jump-to-latest-pill.js +14 -0
- package/dist/src/ui/components/message-view.d.ts +15 -0
- package/dist/src/ui/components/message-view.js +50 -1
- package/dist/src/ui/components/prompt-box.js +18 -16
- package/dist/src/ui/components/session-tree-card.d.ts +14 -0
- package/dist/src/ui/components/session-tree-card.js +46 -0
- package/dist/src/ui/components/slash-inline-menu.d.ts +12 -0
- package/dist/src/ui/components/slash-inline-menu.js +26 -5
- package/dist/src/ui/components/task-list-panel.d.ts +14 -1
- package/dist/src/ui/components/task-list-panel.js +22 -2
- package/dist/src/ui/components/tool-group.d.ts +15 -3
- package/dist/src/ui/components/tool-group.js +69 -11
- package/dist/src/ui/containers/modals-layer.d.ts +4 -2
- package/dist/src/ui/containers/modals-layer.js +2 -2
- package/dist/src/ui/council-harness-event.d.ts +57 -0
- package/dist/src/ui/council-harness-event.js +46 -0
- package/dist/src/ui/heartbeat-debug.d.ts +29 -0
- package/dist/src/ui/heartbeat-debug.js +45 -0
- package/dist/src/ui/hooks/use-session-picker.d.ts +3 -3
- package/dist/src/ui/mcp-modal.js +2 -4
- package/dist/src/ui/modals/api-key-modal.js +1 -1
- package/dist/src/ui/modals/connect-modal.js +4 -3
- package/dist/src/ui/modals/model-picker-modal.d.ts +8 -18
- package/dist/src/ui/modals/model-picker-modal.js +8 -10
- package/dist/src/ui/modals/session-picker-modal.d.ts +2 -2
- package/dist/src/ui/modals/session-picker-modal.js +3 -5
- package/dist/src/ui/picker-providers.d.ts +1 -1
- package/dist/src/ui/picker-providers.js +1 -1
- package/dist/src/ui/primitives/index.d.ts +1 -0
- package/dist/src/ui/primitives/index.js +2 -0
- package/dist/src/ui/primitives/semantic-primitives.d.ts +76 -0
- package/dist/src/ui/primitives/semantic-primitives.js +81 -0
- package/dist/src/ui/slash/compact.js +5 -7
- package/dist/src/ui/slash/cost.js +1 -1
- package/dist/src/ui/slash/council.js +19 -1
- package/dist/src/ui/slash/debug.d.ts +3 -31
- package/dist/src/ui/slash/debug.js +9 -20
- package/dist/src/ui/slash/ee.js +81 -0
- package/dist/src/ui/slash/ideal.d.ts +6 -2
- package/dist/src/ui/slash/ideal.js +97 -7
- package/dist/src/ui/slash/menu-items.d.ts +7 -0
- package/dist/src/ui/slash/menu-items.js +23 -20
- package/dist/src/ui/slash/registry.d.ts +2 -0
- package/dist/src/ui/slash/registry.js +4 -0
- package/dist/src/ui/status-bar/cache-hit.d.ts +6 -0
- package/dist/src/ui/status-bar/cache-hit.js +9 -0
- package/dist/src/ui/status-bar/index.d.ts +1 -1
- package/dist/src/ui/status-bar/index.js +7 -3
- package/dist/src/ui/status-bar/usd-meter.d.ts +5 -4
- package/dist/src/ui/status-bar/usd-meter.js +6 -4
- package/dist/src/ui/theme.d.ts +1 -0
- package/dist/src/ui/theme.js +2 -0
- package/dist/src/ui/types.d.ts +7 -0
- package/dist/src/ui/use-app-logic.js +0 -0
- package/dist/src/ui/utils/agent-activities.d.ts +39 -0
- package/dist/src/ui/utils/agent-activities.js +96 -0
- package/dist/src/ui/utils/format.d.ts +14 -0
- package/dist/src/ui/utils/format.js +23 -3
- package/dist/src/ui/utils/group-tool-entries.d.ts +26 -0
- package/dist/src/ui/utils/group-tool-entries.js +111 -0
- package/dist/src/ui/utils/tool-summary.d.ts +21 -0
- package/dist/src/ui/utils/tool-summary.js +91 -0
- package/dist/src/usage/downgrade.js +2 -2
- package/dist/src/usage/product-ledger.js +2 -2
- package/dist/src/utils/event-loop-monitor.d.ts +85 -0
- package/dist/src/utils/event-loop-monitor.js +107 -0
- package/dist/src/utils/install-manager.js +2 -1
- package/dist/src/utils/llm-deadline.d.ts +14 -0
- package/dist/src/utils/llm-deadline.js +19 -0
- package/dist/src/utils/logger.js +2 -2
- package/dist/src/utils/loop-profiler.d.ts +102 -0
- package/dist/src/utils/loop-profiler.js +202 -0
- package/dist/src/utils/permission-mode.js +5 -3
- package/dist/src/utils/redactor.js +1 -1
- package/dist/src/utils/settings.d.ts +180 -5
- package/dist/src/utils/settings.js +271 -31
- package/dist/src/utils/side-question.d.ts +1 -2
- package/dist/src/utils/side-question.js +2 -2
- package/dist/src/utils/visible-retry.d.ts +11 -0
- package/dist/src/utils/visible-retry.js +10 -1
- package/dist/src/verify/entrypoint.d.ts +1 -1
- package/dist/src/verify/entrypoint.js +52 -17
- package/dist/src/verify/orchestrator.d.ts +1 -1
- package/dist/src/verify/orchestrator.js +20 -3
- package/dist/src/verify/recipes.d.ts +13 -0
- package/dist/src/verify/recipes.js +15 -0
- package/package.json +134 -132
- package/dist/src/cli/bw-vault.d.ts +0 -55
- package/dist/src/cli/bw-vault.js +0 -133
- package/dist/src/mcp/ee-tools.d.ts +0 -46
- package/dist/src/mcp/ee-tools.js +0 -193
- package/dist/src/providers/auth/gcloud.d.ts +0 -28
- package/dist/src/providers/auth/gcloud.js +0 -102
- package/dist/src/providers/auth/gemini-oauth.d.ts +0 -82
- package/dist/src/providers/auth/gemini-oauth.js +0 -472
- package/dist/src/providers/gemini.d.ts +0 -11
- package/dist/src/providers/gemini.js +0 -45
- package/dist/src/providers/siliconflow-sse-repair.d.ts +0 -58
- package/dist/src/providers/siliconflow-sse-repair.js +0 -177
- package/dist/src/providers/strategies/google.strategy.d.ts +0 -22
- package/dist/src/providers/strategies/google.strategy.js +0 -174
- package/dist/src/providers/strategies/siliconflow.strategy.js +0 -29
- package/dist/src/ui/containers/chat-feed.d.ts +0 -40
- package/dist/src/ui/containers/chat-feed.js +0 -66
|
@@ -6,15 +6,20 @@
|
|
|
6
6
|
* is sent to the API for all providers (including DeepSeek, Gemini, etc.).
|
|
7
7
|
*/
|
|
8
8
|
import { dynamicTool, jsonSchema } from "ai";
|
|
9
|
+
import { registerGsdWorkflowTools } from "../gsd/workflow-tools.js";
|
|
10
|
+
import { requestProactiveCompact } from "../orchestrator/compact-request.js";
|
|
11
|
+
import { requestCouncilConvene } from "../orchestrator/council-request.js";
|
|
9
12
|
import { canonicalizeBashCommand } from "../orchestrator/tool-args-hash.js";
|
|
10
13
|
import { analyzeImageFromSource, askVisionProxy, listCachedImages } from "../providers/mcp-vision-bridge.js";
|
|
11
14
|
import { needsVisionProxy } from "../providers/vision-proxy.js";
|
|
15
|
+
import { loadMcpServers } from "../utils/settings.js";
|
|
12
16
|
import { getBashRun, sliceBashOutput } from "./bash-output-cache.js";
|
|
13
|
-
import { editFile, readFile, writeFile } from "./file.js";
|
|
17
|
+
import { editFile, readFile, readFiles, writeFile } from "./file.js";
|
|
14
18
|
import { FileTracker } from "./file-tracker.js";
|
|
15
|
-
import { analyzeGitCommand, checkPushGate, checkSensitiveStaging, commitBlockedMessage, pushBlockedMessage, recordCommandOutcome, } from "./git-safety.js";
|
|
19
|
+
import { analyzeGitCommand, checkDestructiveOp, checkPushGate, checkSensitiveStaging, commitBlockedMessage, pushBlockedMessage, recordCommandOutcome, } from "./git-safety.js";
|
|
16
20
|
import { executeGrep } from "./grep.js";
|
|
17
21
|
import { registerNativeMuonroiTools } from "./native-tools.js";
|
|
22
|
+
import { registerNativeResearchTools } from "./research.js";
|
|
18
23
|
import { VISION_TOOL_NAMES } from "./vision-gate.js";
|
|
19
24
|
function getSafetyApprovedMap() {
|
|
20
25
|
if (!globalThis.__muonroiSafetyApproved) {
|
|
@@ -84,20 +89,38 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
84
89
|
// One tracker per tool registry instance — shared across read/write/edit
|
|
85
90
|
// calls in the same session. Enforces "must read before edit/overwrite".
|
|
86
91
|
const fileTracker = new FileTracker();
|
|
92
|
+
// Native research tools (fetch_url, web_search) — always available.
|
|
93
|
+
// These are the in-process replacements for the old external MCP research servers.
|
|
94
|
+
registerNativeResearchTools(tools);
|
|
87
95
|
// read_file
|
|
88
96
|
tools.read_file = dynamicTool({
|
|
89
|
-
description: "Read file contents.
|
|
97
|
+
description: "Read file contents. To read SEVERAL files, pass them ALL in one call via file_paths (array) — STRONGLY PREFERRED over issuing separate read_file calls: each extra call re-sends the whole conversation as input, so N single reads cost O(N²) tokens while one batched read costs O(N). For a large SINGLE file, use start_line/end_line to extract only the needed section (start_line/end_line apply to file_path only; file_paths reads whole files). Use grep or lsp first to find line numbers.",
|
|
90
98
|
inputSchema: jsonSchema({
|
|
91
99
|
type: "object",
|
|
92
100
|
properties: {
|
|
93
|
-
file_path: { type: "string", description: "Path to
|
|
94
|
-
|
|
95
|
-
|
|
101
|
+
file_path: { type: "string", description: "Path to a single file to read (supports start_line/end_line)." },
|
|
102
|
+
file_paths: {
|
|
103
|
+
type: "array",
|
|
104
|
+
items: { type: "string" },
|
|
105
|
+
description: "Read MULTIPLE files in ONE call (preferred when you need 2+ files). Each is returned with its own header; each is capped independently so none is dropped. Best for small-to-medium files; for a large file use file_path + line range.",
|
|
106
|
+
},
|
|
107
|
+
start_line: { type: "number", description: "First line to read (1-based). Applies to file_path only." },
|
|
108
|
+
end_line: { type: "number", description: "Last line to read (1-based). Applies to file_path only." },
|
|
96
109
|
},
|
|
97
|
-
required: ["file_path"],
|
|
98
110
|
}),
|
|
99
111
|
execute: async (input) => {
|
|
100
|
-
const
|
|
112
|
+
const batch = Array.isArray(input.file_paths) && input.file_paths.length > 0
|
|
113
|
+
? input.file_paths.filter((p) => typeof p === "string" && p.trim() !== "")
|
|
114
|
+
: [];
|
|
115
|
+
if (batch.length > 1) {
|
|
116
|
+
// Per-file fair-share of the output cap so the concatenated result
|
|
117
|
+
// stays under MAX_TOOL_OUTPUT_CHARS and every file survives (no silent
|
|
118
|
+
// head/tail drop of whole files). Floor keeps each file legible.
|
|
119
|
+
const perFileCap = Math.max(4_000, Math.floor(MAX_TOOL_OUTPUT_CHARS / batch.length));
|
|
120
|
+
return formatResult(readFiles(batch, bash.getCwd(), fileTracker, perFileCap));
|
|
121
|
+
}
|
|
122
|
+
const single = batch.length === 1 ? batch[0] : input.file_path;
|
|
123
|
+
const result = readFile(single, bash.getCwd(), input.start_line, input.end_line, fileTracker);
|
|
101
124
|
return formatResult(result);
|
|
102
125
|
},
|
|
103
126
|
});
|
|
@@ -118,6 +141,137 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
118
141
|
return formatResult(result);
|
|
119
142
|
},
|
|
120
143
|
});
|
|
144
|
+
// compact — agent-initiated proactive context compaction. The model calls
|
|
145
|
+
// this to shed accumulated tool/conversation history mid-task (freeing
|
|
146
|
+
// context + resetting tool-call bloat) BEFORE it hits a tool-round limit,
|
|
147
|
+
// so a long task never gets interrupted. The request is queued here and
|
|
148
|
+
// consumed by the tool-engine's prepareStep boundary, which forces a
|
|
149
|
+
// compaction pass before the next LLM step, then the turn continues. A
|
|
150
|
+
// decisions/facts snapshot is preserved and high-value tool results stay
|
|
151
|
+
// rehydratable via ee_query "tool-artifact id=…". This is the proactive
|
|
152
|
+
// counterpart to the reactive tool-limit auto-recover.
|
|
153
|
+
tools.compact = dynamicTool({
|
|
154
|
+
description: "Proactively compress THIS turn's accumulated tool/conversation history to free context and reset tool-call bloat, then CONTINUE the task automatically. Call it after a read-heavy stretch (many read_file/grep/bash results) when context feels heavy and BEFORE you approach a tool-round limit — it prevents the 'reached tool limit' interruption entirely. The compaction runs before your next step; older tool results are summarized (a decisions/facts snapshot is kept) and remain rehydratable via ee_query \"tool-artifact id=…\". Do NOT stop after calling it — keep working toward the goal.",
|
|
155
|
+
inputSchema: jsonSchema({
|
|
156
|
+
type: "object",
|
|
157
|
+
properties: {
|
|
158
|
+
focus: {
|
|
159
|
+
type: "string",
|
|
160
|
+
description: "Short note on what to keep in mind / preserve after compaction (e.g. the current sub-task).",
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
}),
|
|
164
|
+
execute: async (input) => {
|
|
165
|
+
requestProactiveCompact(typeof input?.focus === "string" ? input.focus : null);
|
|
166
|
+
return formatResult({
|
|
167
|
+
success: true,
|
|
168
|
+
output: 'Context compaction scheduled — older tool history will be compressed before your next step; continue the task afterward. High-value results stay rehydratable via ee_query "tool-artifact id=…".',
|
|
169
|
+
});
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
// convene_council — agent-initiated multi-model council. The model calls this
|
|
173
|
+
// when THIS request genuinely warrants a cross-provider debate (conflicting
|
|
174
|
+
// design tradeoffs, high-stakes decision). The request is queued here; the
|
|
175
|
+
// tool-engine consumes it from the outer restart loop, runs runCouncilV2 with
|
|
176
|
+
// convenePath:true (which suppresses ALL hardcoded post-debate decision
|
|
177
|
+
// surface — no card, no continuation), splices the synthesis into THIS tool's
|
|
178
|
+
// tool_result, and restarts the step so the model reads the conclusion as the
|
|
179
|
+
// result and continues. Registered only when the council is usable so the
|
|
180
|
+
// model never calls a council that cannot convene.
|
|
181
|
+
if (opts?.councilConfigured) {
|
|
182
|
+
tools.convene_council = dynamicTool({
|
|
183
|
+
description: "Convene the multi-model council to debate THIS request. Use ONLY when the task has genuinely conflicting design tradeoffs, needs a cross-provider/second-opinion review, or is a high-stakes architecture/analysis decision where a single model's view is insufficient. It runs a real multi-role debate across several models and returns a synthesized conclusion AS THIS TOOL'S RESULT. Do NOT use it for routine or low-ambiguity work — it is expensive. After calling, read the returned conclusion and continue; nothing is auto-decided for you.",
|
|
184
|
+
inputSchema: jsonSchema({
|
|
185
|
+
type: "object",
|
|
186
|
+
properties: {
|
|
187
|
+
reason: {
|
|
188
|
+
type: "string",
|
|
189
|
+
description: "Why this task needs a multi-model debate (the specific tradeoff or decision at stake).",
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
}),
|
|
193
|
+
execute: async (input, execOpts) => {
|
|
194
|
+
const reason = input && typeof input === "object" && typeof input.reason === "string"
|
|
195
|
+
? input.reason
|
|
196
|
+
: null;
|
|
197
|
+
requestCouncilConvene(reason, execOpts?.toolCallId ?? null);
|
|
198
|
+
return formatResult({
|
|
199
|
+
success: true,
|
|
200
|
+
output: "Council convening — the multi-model debate runs now and its conclusion replaces this result before your next step. Read the conclusion, then continue.",
|
|
201
|
+
});
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
// ask_user — agent-initiated question to the human. The model calls this from
|
|
206
|
+
// its OWN judgment (e.g. after a convene_council conclusion, when it wants a
|
|
207
|
+
// go/no-go before implementing). The CLI does NOT synthesise options or decide
|
|
208
|
+
// the branch: question, options, and default all come from the model's input.
|
|
209
|
+
// execute() BLOCKS until the human answers; the answer becomes the tool result.
|
|
210
|
+
// Registered only when a UI answerer is wired (opts.askUser present).
|
|
211
|
+
if (opts?.askUser) {
|
|
212
|
+
const askUser = opts.askUser;
|
|
213
|
+
tools.ask_user = dynamicTool({
|
|
214
|
+
description: "Ask the human user a question and receive their answer AS THIS TOOL'S RESULT. Use when you need a decision, confirmation (e.g. 'proceed with implementation?'), or missing detail that only the user can provide — typically in an interactive discussion, or after a convene_council conclusion when you want a go/no-go before building. Supply the exact `question` and, optionally, `options` the user picks from (omit for a free-text answer). This BLOCKS until the user responds. Nothing is auto-decided: read their answer and continue from your own judgment. Do NOT use it to narrate or for rhetorical questions — only when you genuinely need input to proceed.",
|
|
215
|
+
inputSchema: jsonSchema({
|
|
216
|
+
type: "object",
|
|
217
|
+
properties: {
|
|
218
|
+
question: {
|
|
219
|
+
type: "string",
|
|
220
|
+
description: "The exact question to put to the user.",
|
|
221
|
+
},
|
|
222
|
+
context: {
|
|
223
|
+
type: "string",
|
|
224
|
+
description: "Optional short context shown under the question.",
|
|
225
|
+
},
|
|
226
|
+
options: {
|
|
227
|
+
type: "array",
|
|
228
|
+
description: "Optional choices the user picks from. Omit for a free-text answer. These are YOUR options — the CLI adds none.",
|
|
229
|
+
items: {
|
|
230
|
+
type: "object",
|
|
231
|
+
properties: {
|
|
232
|
+
label: { type: "string", description: "The choice shown to the user." },
|
|
233
|
+
description: { type: "string", description: "Optional one-line explanation of the choice." },
|
|
234
|
+
value: { type: "string", description: "Optional value returned when picked (defaults to the label)." },
|
|
235
|
+
},
|
|
236
|
+
required: ["label"],
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
defaultIndex: {
|
|
240
|
+
type: "number",
|
|
241
|
+
description: "Optional index into options for the pre-selected choice (defaults to 0 = first).",
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
required: ["question"],
|
|
245
|
+
}),
|
|
246
|
+
execute: async (input) => {
|
|
247
|
+
const obj = (input && typeof input === "object" ? input : {});
|
|
248
|
+
const question = typeof obj.question === "string" ? obj.question : "";
|
|
249
|
+
if (question.trim().length === 0) {
|
|
250
|
+
return formatResult({
|
|
251
|
+
success: false,
|
|
252
|
+
output: "ask_user requires a non-empty `question`.",
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
const rawOptions = Array.isArray(obj.options) ? obj.options : [];
|
|
256
|
+
const options = rawOptions
|
|
257
|
+
.filter((o) => !!o && typeof o === "object")
|
|
258
|
+
.map((o) => ({
|
|
259
|
+
label: typeof o.label === "string" ? o.label : String(o.label ?? ""),
|
|
260
|
+
description: typeof o.description === "string" ? o.description : undefined,
|
|
261
|
+
value: typeof o.value === "string" ? o.value : undefined,
|
|
262
|
+
}))
|
|
263
|
+
.filter((o) => o.label.length > 0);
|
|
264
|
+
const info = {
|
|
265
|
+
question,
|
|
266
|
+
context: typeof obj.context === "string" ? obj.context : undefined,
|
|
267
|
+
options: options.length > 0 ? options : undefined,
|
|
268
|
+
defaultIndex: typeof obj.defaultIndex === "number" ? obj.defaultIndex : undefined,
|
|
269
|
+
};
|
|
270
|
+
const answer = await askUser(info);
|
|
271
|
+
return formatResult({ success: true, output: answer });
|
|
272
|
+
},
|
|
273
|
+
});
|
|
274
|
+
}
|
|
121
275
|
// bash — every foreground call goes through here. We track the LAST
|
|
122
276
|
// canonical command + runId in SESSION-SCOPED state so we can inject a
|
|
123
277
|
// reminder when the model issues another bash call that canonicalizes to
|
|
@@ -215,6 +369,17 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
215
369
|
// motivation (session 18285908637a). gitSafetyKey is STABLE per process
|
|
216
370
|
// (or the real sessionId) — unlike repeatKey, whose anon fallback changes
|
|
217
371
|
// on every registry rebuild and would silently drop the gate across turns.
|
|
372
|
+
// Destructive-op guard (pre-execution, any permission mode): block a
|
|
373
|
+
// command that would irreversibly discard uncommitted work (git
|
|
374
|
+
// checkout --/restore/reset --hard/clean, git stash drop/clear, or rm of
|
|
375
|
+
// a tracked file) when there is actually work at risk. Routed as
|
|
376
|
+
// `destructive-revert` so the tool-engine shows the safety askcard
|
|
377
|
+
// interactively and hard-blocks headless (autonomous sub-agents) — the
|
|
378
|
+
// fix for the /ideal plan-adherence agent silently reverting user files.
|
|
379
|
+
const destructive = checkDestructiveOp(cmd, bash.getCwd());
|
|
380
|
+
if (destructive.blocked) {
|
|
381
|
+
return _prefixBlock("destructive-revert", destructive.message);
|
|
382
|
+
}
|
|
218
383
|
const gitShape = analyzeGitCommand(cmd);
|
|
219
384
|
// Hard-block broad staging when sensitive files are present.
|
|
220
385
|
// This runs PRE-EXECUTION (before bash.execute) regardless of permission mode.
|
|
@@ -253,7 +418,20 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
253
418
|
}
|
|
254
419
|
}
|
|
255
420
|
}
|
|
256
|
-
|
|
421
|
+
const isLongRunning = (c) => {
|
|
422
|
+
const lower = c.toLowerCase().trim();
|
|
423
|
+
return (/\bvite\b/.test(lower) ||
|
|
424
|
+
/\bnodemon\b/.test(lower) ||
|
|
425
|
+
/\bwebpack-dev-server\b/.test(lower) ||
|
|
426
|
+
/\bnext\s+dev\b/.test(lower) ||
|
|
427
|
+
/\bwatch\b/.test(lower) ||
|
|
428
|
+
/--watch\b/.test(lower) ||
|
|
429
|
+
/\b-w\b/.test(lower) ||
|
|
430
|
+
/\bdev-server\b/.test(lower) ||
|
|
431
|
+
/\blive-server\b/.test(lower) ||
|
|
432
|
+
/\bhttp-server\b/.test(lower));
|
|
433
|
+
};
|
|
434
|
+
if (input.background || isLongRunning(cmd)) {
|
|
257
435
|
const result = await bash.startBackground(input.command);
|
|
258
436
|
return formatResult(result);
|
|
259
437
|
}
|
|
@@ -378,6 +556,9 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
378
556
|
});
|
|
379
557
|
// Agent mode gets write/edit/task/delegate tools
|
|
380
558
|
if (mode === "agent") {
|
|
559
|
+
// Capture delegation functions for auto-routing logic below
|
|
560
|
+
const runTaskFn = opts?.runTask;
|
|
561
|
+
const runDelegationFn = opts?.runDelegation;
|
|
381
562
|
// write_file
|
|
382
563
|
tools.write_file = dynamicTool({
|
|
383
564
|
description: "Create a new file or overwrite an existing file with full content. SAFETY: overwriting an existing file requires you to call read_file on it first in the same session. New-file creation does not.",
|
|
@@ -390,6 +571,13 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
390
571
|
required: ["file_path", "content"],
|
|
391
572
|
}),
|
|
392
573
|
execute: async (input) => {
|
|
574
|
+
if (!input?.file_path?.trim() || input.content === undefined || input.content === null) {
|
|
575
|
+
return {
|
|
576
|
+
success: false,
|
|
577
|
+
output: 'BLOCKED (empty-write_file): write_file requires non-empty "file_path" and "content". ' +
|
|
578
|
+
'Example: {"file_path":"src/foo.ts","content":"export const x = 1;\\n"}',
|
|
579
|
+
};
|
|
580
|
+
}
|
|
393
581
|
const result = await writeFile(input.file_path, input.content, bash.getCwd(), fileTracker);
|
|
394
582
|
return {
|
|
395
583
|
success: result.success,
|
|
@@ -412,6 +600,17 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
412
600
|
required: ["file_path", "old_string", "new_string"],
|
|
413
601
|
}),
|
|
414
602
|
execute: async (input) => {
|
|
603
|
+
if (!input?.file_path?.trim() ||
|
|
604
|
+
input.old_string === undefined ||
|
|
605
|
+
input.old_string === null ||
|
|
606
|
+
input.new_string === undefined ||
|
|
607
|
+
input.new_string === null) {
|
|
608
|
+
return {
|
|
609
|
+
success: false,
|
|
610
|
+
output: "BLOCKED (empty-edit_file): edit_file requires file_path, old_string, and new_string. " +
|
|
611
|
+
'Example: {"file_path":"src/foo.ts","old_string":"a","new_string":"b"}',
|
|
612
|
+
};
|
|
613
|
+
}
|
|
415
614
|
const result = await editFile(input.file_path, input.old_string, input.new_string, bash.getCwd(), fileTracker);
|
|
416
615
|
return {
|
|
417
616
|
success: result.success,
|
|
@@ -475,9 +674,11 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
475
674
|
});
|
|
476
675
|
// task
|
|
477
676
|
if (opts?.runTask) {
|
|
478
|
-
const runTask = opts.runTask;
|
|
479
677
|
tools.task = dynamicTool({
|
|
480
|
-
description: "Delegate a
|
|
678
|
+
description: "Delegate a FOCUSED, SHORT foreground task to a sub-agent that blocks the current turn until complete. " +
|
|
679
|
+
"Use ONLY for quick edit/execute/verify work (default max ~12 rounds). " +
|
|
680
|
+
"For long research, exploration, or anything that may take many steps (explore agent), you MUST use the 'delegate' tool instead — it runs in true background and does not block. " +
|
|
681
|
+
"Using task for long work will cause stalls and timeouts.",
|
|
481
682
|
inputSchema: jsonSchema({
|
|
482
683
|
type: "object",
|
|
483
684
|
properties: {
|
|
@@ -489,13 +690,20 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
489
690
|
prompt: { type: "string", description: "Detailed instructions for the sub-agent" },
|
|
490
691
|
maxToolRounds: {
|
|
491
692
|
type: "number",
|
|
492
|
-
description: "Optional maximum tool execution rounds (default
|
|
693
|
+
description: "Optional maximum tool execution rounds. For research/explore use delegate + higher values (default 60); low values (≤20) only for task.",
|
|
493
694
|
},
|
|
494
695
|
},
|
|
495
696
|
required: ["agent", "description", "prompt"],
|
|
496
697
|
}),
|
|
497
698
|
execute: async (input) => {
|
|
498
|
-
|
|
699
|
+
// Auto-route long research (explore agent or high round count) to true background delegation
|
|
700
|
+
// to prevent blocking the main turn and causing stall timeouts.
|
|
701
|
+
const isLongResearch = input.agent === "explore" || (typeof input.maxToolRounds === "number" && input.maxToolRounds > 25);
|
|
702
|
+
const executor = isLongResearch && runDelegationFn ? runDelegationFn : runTaskFn;
|
|
703
|
+
if (!executor) {
|
|
704
|
+
return { success: false, output: "No delegation executor available." };
|
|
705
|
+
}
|
|
706
|
+
const result = await executor({
|
|
499
707
|
agent: input.agent,
|
|
500
708
|
description: input.description,
|
|
501
709
|
prompt: input.prompt,
|
|
@@ -530,7 +738,10 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
530
738
|
if (opts?.runDelegation) {
|
|
531
739
|
const runDelegation = opts.runDelegation;
|
|
532
740
|
tools.delegate = dynamicTool({
|
|
533
|
-
description: "Launch a read-only
|
|
741
|
+
description: "Launch a read-only BACKGROUND research agent (usually 'explore') that runs independently in a separate process. " +
|
|
742
|
+
"Use this for ANY long-running research, codebase exploration, analysis, or tasks with high maxToolRounds. " +
|
|
743
|
+
"Main session continues working immediately. Results are delivered later via notifications or delegation_read. " +
|
|
744
|
+
"This is the PREFERRED tool over 'task' for explore/research to avoid blocking and timeouts.",
|
|
534
745
|
inputSchema: jsonSchema({
|
|
535
746
|
type: "object",
|
|
536
747
|
properties: {
|
|
@@ -539,7 +750,7 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
539
750
|
prompt: { type: "string", description: "Detailed research instructions" },
|
|
540
751
|
maxToolRounds: {
|
|
541
752
|
type: "number",
|
|
542
|
-
description: "Optional maximum tool execution rounds (
|
|
753
|
+
description: "Optional maximum tool execution rounds (high values like 60+ expected for background research; do not use task for high values).",
|
|
543
754
|
},
|
|
544
755
|
},
|
|
545
756
|
required: ["agent", "description", "prompt"],
|
|
@@ -652,7 +863,7 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
652
863
|
// output in-process by toolCallId. For an exact "tool-artifact id=X"
|
|
653
864
|
// lookup this is the authoritative full content for THIS session and
|
|
654
865
|
// works even when EE is down — the failure window long sessions hit.
|
|
655
|
-
const { findArtifactByQuery, findArtifactOnDisk } = await import("../ee/artifact-cache.js");
|
|
866
|
+
const { findArtifactByQuery, findArtifactByHint, findArtifactOnDisk } = await import("../ee/artifact-cache.js");
|
|
656
867
|
// Lived-experience telemetry: record where the rehydrate came from so
|
|
657
868
|
// a "cảm nhận trong CLI" question (and the measure-first instrumentation)
|
|
658
869
|
// sees cache vs disk vs ee vs needed-but-unavailable.
|
|
@@ -664,6 +875,15 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
664
875
|
recordRehydration(mem ? "cache" : "disk");
|
|
665
876
|
return truncateOutput(`[tool-artifact id=${local.toolCallId} tool=${local.toolName} — rehydrated from ${src}]\n${local.content}`);
|
|
666
877
|
}
|
|
878
|
+
// B (cheap-model anti-mù) — the exact id missed locally. Cheap models
|
|
879
|
+
// often pass FILE PATHS instead of the opaque toolCallId, which
|
|
880
|
+
// extractArtifactId can't parse. Try a path match against the local
|
|
881
|
+
// cache before the EE round-trip so a botched id still recovers.
|
|
882
|
+
const fuzzy = findArtifactByHint(query);
|
|
883
|
+
if (fuzzy) {
|
|
884
|
+
recordRehydration("cache");
|
|
885
|
+
return truncateOutput(`[tool-artifact id=${fuzzy.toolCallId} tool=${fuzzy.toolName} — rehydrated by path match; your id was malformed (pass the exact id from the "[… elided id=X …]" stub next time)]\n${fuzzy.content}`);
|
|
886
|
+
}
|
|
667
887
|
// EE fallback (cross-session / post-restart) → raw /api/search exact lookup.
|
|
668
888
|
const { searchEE } = await import("../ee/search.js");
|
|
669
889
|
const resp = await searchEE(query, {
|
|
@@ -721,6 +941,204 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
721
941
|
}
|
|
722
942
|
},
|
|
723
943
|
});
|
|
944
|
+
tools.retrieve_tool_result = dynamicTool({
|
|
945
|
+
description: "Retrieve the full output of a previous tool call by its tool_call_id. " +
|
|
946
|
+
"Searches local cache, disk cache, database history (including parent sessions), and remote Experience Engine. " +
|
|
947
|
+
"Use this to rehydrate elided tool outputs. Optional max_chars and chunk_index allow paginated retrieval.",
|
|
948
|
+
inputSchema: jsonSchema({
|
|
949
|
+
type: "object",
|
|
950
|
+
properties: {
|
|
951
|
+
tool_call_id: { type: "string", description: "The unique ID of the tool call (e.g. 'call_123')." },
|
|
952
|
+
max_chars: {
|
|
953
|
+
type: "number",
|
|
954
|
+
description: "Optional character limit for the returned chunk (useful for very large outputs).",
|
|
955
|
+
},
|
|
956
|
+
chunk_index: {
|
|
957
|
+
type: "number",
|
|
958
|
+
description: "Optional chunk index if splitting the output by max_chars (0-based, default 0).",
|
|
959
|
+
},
|
|
960
|
+
},
|
|
961
|
+
required: ["tool_call_id"],
|
|
962
|
+
}),
|
|
963
|
+
execute: async (input) => {
|
|
964
|
+
const toolCallId = typeof input.tool_call_id === "string" ? input.tool_call_id.trim() : "";
|
|
965
|
+
if (!toolCallId) {
|
|
966
|
+
return "ERROR: tool_call_id is required.";
|
|
967
|
+
}
|
|
968
|
+
const maxChars = typeof input.max_chars === "number" ? input.max_chars : undefined;
|
|
969
|
+
const chunkIndex = typeof input.chunk_index === "number" ? input.chunk_index : 0;
|
|
970
|
+
let content = null;
|
|
971
|
+
let source = "";
|
|
972
|
+
// Tier 1: LRU cache
|
|
973
|
+
try {
|
|
974
|
+
const { getArtifact } = await import("../ee/artifact-cache.js");
|
|
975
|
+
const tier1 = getArtifact(toolCallId);
|
|
976
|
+
if (tier1) {
|
|
977
|
+
content = tier1.content;
|
|
978
|
+
source = "Tier 1 LRU cache";
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
catch (err) {
|
|
982
|
+
console.error(`[tools:retrieve_tool_result] Tier 1 LRU check failed: ${err.message}`);
|
|
983
|
+
}
|
|
984
|
+
// Tier 2: Disk cache
|
|
985
|
+
if (!content) {
|
|
986
|
+
try {
|
|
987
|
+
const { findArtifactOnDisk } = await import("../ee/artifact-cache.js");
|
|
988
|
+
const tier2 = await findArtifactOnDisk(`id=${toolCallId}`);
|
|
989
|
+
if (tier2) {
|
|
990
|
+
content = tier2.content;
|
|
991
|
+
source = "Tier 2 disk cache";
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
catch (err) {
|
|
995
|
+
console.error(`[tools:retrieve_tool_result] Tier 2 disk check failed: ${err.message}`);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
// Tier 3: SQLite database
|
|
999
|
+
if (!content && opts?.sessionId) {
|
|
1000
|
+
try {
|
|
1001
|
+
const { getSessionChain } = await import("../storage/index.js");
|
|
1002
|
+
const { getDatabase } = await import("../storage/db.js");
|
|
1003
|
+
const chain = getSessionChain(opts.sessionId);
|
|
1004
|
+
const db = getDatabase();
|
|
1005
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
1006
|
+
const row = db
|
|
1007
|
+
.prepare(`
|
|
1008
|
+
SELECT tr.output_json
|
|
1009
|
+
FROM tool_results tr
|
|
1010
|
+
JOIN tool_calls tc ON tc.id = tr.tool_call_row_id
|
|
1011
|
+
WHERE tc.tool_call_id = ? AND tc.session_id = ?
|
|
1012
|
+
LIMIT 1
|
|
1013
|
+
`)
|
|
1014
|
+
.get(toolCallId, chain[i]);
|
|
1015
|
+
if (row?.output_json) {
|
|
1016
|
+
const parsed = JSON.parse(row.output_json);
|
|
1017
|
+
if (parsed && typeof parsed === "object") {
|
|
1018
|
+
if ("output" in parsed && typeof parsed.output === "string") {
|
|
1019
|
+
content = parsed.output;
|
|
1020
|
+
}
|
|
1021
|
+
else if ("error" in parsed && typeof parsed.error === "string") {
|
|
1022
|
+
content = `ERROR: ${parsed.error}`;
|
|
1023
|
+
}
|
|
1024
|
+
else {
|
|
1025
|
+
content = JSON.stringify(parsed);
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
else {
|
|
1029
|
+
content = String(parsed);
|
|
1030
|
+
}
|
|
1031
|
+
source = `Tier 3 SQLite database (session ${chain[i]})`;
|
|
1032
|
+
break;
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
catch (err) {
|
|
1037
|
+
console.error(`[tools:retrieve_tool_result] Tier 3 DB check failed: ${err.message}`);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
// Tier 4: Remote EE (behavioral collection only)
|
|
1041
|
+
if (!content) {
|
|
1042
|
+
try {
|
|
1043
|
+
const { searchEE } = await import("../ee/search.js");
|
|
1044
|
+
const resp = await searchEE(`tool-artifact id=${toolCallId}`, {
|
|
1045
|
+
collections: ["experience-behavioral"],
|
|
1046
|
+
limit: 1,
|
|
1047
|
+
});
|
|
1048
|
+
const bestHit = resp?.points?.[0];
|
|
1049
|
+
if (bestHit?.text) {
|
|
1050
|
+
content = bestHit.text;
|
|
1051
|
+
source = "Tier 4 remote EE (behavioral collection)";
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
catch (err) {
|
|
1055
|
+
console.error(`[tools:retrieve_tool_result] Tier 4 EE check failed: ${err.message}`);
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
if (content === null) {
|
|
1059
|
+
return `ERROR: Tool result not found for tool_call_id: ${toolCallId} in any tier.`;
|
|
1060
|
+
}
|
|
1061
|
+
const totalLength = content.length;
|
|
1062
|
+
if (maxChars !== undefined && maxChars > 0) {
|
|
1063
|
+
const totalChunks = Math.ceil(totalLength / maxChars);
|
|
1064
|
+
const start = chunkIndex * maxChars;
|
|
1065
|
+
const end = Math.min(start + maxChars, totalLength);
|
|
1066
|
+
if (start >= totalLength) {
|
|
1067
|
+
return `ERROR: chunk_index ${chunkIndex} is out of bounds. Total chunks available: ${totalChunks} (max_chars: ${maxChars}, total length: ${totalLength}).`;
|
|
1068
|
+
}
|
|
1069
|
+
const chunk = content.slice(start, end);
|
|
1070
|
+
return JSON.stringify({
|
|
1071
|
+
tool_call_id: toolCallId,
|
|
1072
|
+
source,
|
|
1073
|
+
chunk_index: chunkIndex,
|
|
1074
|
+
total_chunks: totalChunks,
|
|
1075
|
+
chunk_length: chunk.length,
|
|
1076
|
+
total_length: totalLength,
|
|
1077
|
+
content: chunk,
|
|
1078
|
+
}, null, 2);
|
|
1079
|
+
}
|
|
1080
|
+
return JSON.stringify({
|
|
1081
|
+
tool_call_id: toolCallId,
|
|
1082
|
+
source,
|
|
1083
|
+
total_length: totalLength,
|
|
1084
|
+
content,
|
|
1085
|
+
}, null, 2);
|
|
1086
|
+
},
|
|
1087
|
+
});
|
|
1088
|
+
tools.search_session_history = dynamicTool({
|
|
1089
|
+
description: "Search the full message history across all sessions using an FTS5 MATCH expression. " +
|
|
1090
|
+
"Useful to locate past questions, answers, and context across the session lineage.",
|
|
1091
|
+
inputSchema: jsonSchema({
|
|
1092
|
+
type: "object",
|
|
1093
|
+
properties: {
|
|
1094
|
+
query: {
|
|
1095
|
+
type: "string",
|
|
1096
|
+
description: "FTS5 MATCH expression query (e.g. 'compaction AND error' or 'content:Vitest').",
|
|
1097
|
+
},
|
|
1098
|
+
},
|
|
1099
|
+
required: ["query"],
|
|
1100
|
+
}),
|
|
1101
|
+
execute: async (input) => {
|
|
1102
|
+
const query = typeof input.query === "string" ? input.query.trim() : "";
|
|
1103
|
+
if (!query) {
|
|
1104
|
+
return "ERROR: query MATCH expression is required.";
|
|
1105
|
+
}
|
|
1106
|
+
try {
|
|
1107
|
+
const { getDatabase } = await import("../storage/db.js");
|
|
1108
|
+
const db = getDatabase();
|
|
1109
|
+
// Wrap FTS search query execution in try-catch to prevent malformed FTS syntax crashes (fixing GAP-03)
|
|
1110
|
+
const rows = db
|
|
1111
|
+
.prepare(`
|
|
1112
|
+
SELECT session_id, seq, role, tool_name, content, tool_args, tool_output
|
|
1113
|
+
FROM session_history_fts
|
|
1114
|
+
WHERE session_history_fts MATCH ?
|
|
1115
|
+
ORDER BY rank
|
|
1116
|
+
LIMIT 50
|
|
1117
|
+
`)
|
|
1118
|
+
.all(query);
|
|
1119
|
+
if (rows.length === 0) {
|
|
1120
|
+
return `No session history matched the query: "${query}"`;
|
|
1121
|
+
}
|
|
1122
|
+
const results = rows.map((row) => ({
|
|
1123
|
+
session_id: row.session_id,
|
|
1124
|
+
seq: row.seq,
|
|
1125
|
+
role: row.role,
|
|
1126
|
+
tool_name: row.tool_name ?? undefined,
|
|
1127
|
+
content: row.content ?? undefined,
|
|
1128
|
+
tool_args: row.tool_args ?? undefined,
|
|
1129
|
+
tool_output: row.tool_output ?? undefined,
|
|
1130
|
+
}));
|
|
1131
|
+
return JSON.stringify({
|
|
1132
|
+
query,
|
|
1133
|
+
match_count: results.length,
|
|
1134
|
+
results,
|
|
1135
|
+
}, null, 2);
|
|
1136
|
+
}
|
|
1137
|
+
catch (err) {
|
|
1138
|
+
return `ERROR: FTS MATCH query failed. The FTS syntax might be malformed: ${err.message}`;
|
|
1139
|
+
}
|
|
1140
|
+
},
|
|
1141
|
+
});
|
|
724
1142
|
// Native muonroi-tools builtins — ee_health, ee_feedback, usage_forensics,
|
|
725
1143
|
// lsp_query, setup_guide, selfverify_*. These run IN-PROCESS; the CLI no
|
|
726
1144
|
// longer self-spawns itself as an MCP server to expose them to its own inner
|
|
@@ -728,16 +1146,25 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
728
1146
|
// and a seed-time bug once persisted a crashing vitest-worker command). The
|
|
729
1147
|
// muonroi-tools MCP server stays only for EXTERNAL agents. See native-tools.ts.
|
|
730
1148
|
registerNativeMuonroiTools(tools, { cwd: bash.getCwd() });
|
|
1149
|
+
registerGsdWorkflowTools(tools, {
|
|
1150
|
+
cwd: bash.getCwd(),
|
|
1151
|
+
sessionModelId: opts?.modelId ?? "unknown",
|
|
1152
|
+
sessionId: opts?.sessionId,
|
|
1153
|
+
depth: opts?.depthTier ?? "standard",
|
|
1154
|
+
runTask: opts?.runTask,
|
|
1155
|
+
runDebate: opts?.runDebate,
|
|
1156
|
+
});
|
|
731
1157
|
}
|
|
732
1158
|
// Vision proxy tools — only for text-only models (DeepSeek, etc.)
|
|
733
1159
|
if (opts?.modelId && needsVisionProxy(opts.modelId)) {
|
|
734
1160
|
const cwd = bash.getCwd();
|
|
735
1161
|
tools.analyze_image = dynamicTool({
|
|
736
|
-
description: "
|
|
737
|
-
"Use
|
|
738
|
-
"or when the user references an image.
|
|
1162
|
+
description: "Inspect an image and receive a <vision-observation> block — treat the result as your direct sight. " +
|
|
1163
|
+
"Use IMMEDIATELY when you encounter any image file (.png, .jpg, .gif, .webp, .svg, etc.) " +
|
|
1164
|
+
"or when the user references an image. Do not guess visual content. " +
|
|
739
1165
|
"Accepts file paths, data URIs, or base64 strings. " +
|
|
740
|
-
"Optionally provide a question to focus the analysis."
|
|
1166
|
+
"Optionally provide a question to focus the analysis (OCR, layout, specific UI element). " +
|
|
1167
|
+
"If details remain unclear, call ask_vision_proxy or ask the user for another screenshot.",
|
|
741
1168
|
inputSchema: jsonSchema({
|
|
742
1169
|
type: "object",
|
|
743
1170
|
properties: {
|
|
@@ -757,9 +1184,10 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
757
1184
|
},
|
|
758
1185
|
});
|
|
759
1186
|
tools.ask_vision_proxy = dynamicTool({
|
|
760
|
-
description: "Ask a follow-up
|
|
761
|
-
"
|
|
762
|
-
"
|
|
1187
|
+
description: "Ask a follow-up about an image you are viewing (cached ID) or analyze a new file with a specific question. " +
|
|
1188
|
+
"Returns a <vision-observation> — respond as if you saw it yourself. " +
|
|
1189
|
+
"Use when any detail in a prior observation is unclear: zoom on a region, read text, compare colors, verify UI state. " +
|
|
1190
|
+
"Reference a cached image by ID (from list_vision_cache) or provide a file path for a new image.",
|
|
763
1191
|
inputSchema: jsonSchema({
|
|
764
1192
|
type: "object",
|
|
765
1193
|
properties: {
|
|
@@ -854,6 +1282,131 @@ export function createBuiltinTools(bash, mode, opts) {
|
|
|
854
1282
|
for (const name of VISION_TOOL_NAMES)
|
|
855
1283
|
delete tools[name];
|
|
856
1284
|
}
|
|
1285
|
+
// ── Agent introspection tools: help the inner agent discover capabilities ──
|
|
1286
|
+
// These are always added last (after all filtering) so list_tools reflects reality.
|
|
1287
|
+
tools.list_mcp_servers = dynamicTool({
|
|
1288
|
+
description: "List every MCP server in the current user config (enabled or not). Returns id, label, enabled, transport, endpoint, and recommended_native (if any). " +
|
|
1289
|
+
"Use this to discover exactly what MCPs you have right now. For each MCP, see if there is a preferred native replacement (e.g. fetch_url instead of legacy fetch). " +
|
|
1290
|
+
"Memory, playwright, figma removed from defaults. Only enabled servers contribute tools this turn.",
|
|
1291
|
+
inputSchema: jsonSchema({
|
|
1292
|
+
type: "object",
|
|
1293
|
+
properties: {},
|
|
1294
|
+
additionalProperties: false,
|
|
1295
|
+
}),
|
|
1296
|
+
execute: async () => {
|
|
1297
|
+
const servers = loadMcpServers();
|
|
1298
|
+
// Native replacement recommendations (helps agent choose better tools)
|
|
1299
|
+
const RECOMMENDATIONS = {
|
|
1300
|
+
fetch: "Prefer native fetch_url (faster, always available, no external spawn).",
|
|
1301
|
+
tavily: "Prefer native web_search (direct Tavily API call, same results).",
|
|
1302
|
+
context7: "Consider keeping for library docs, or cache important docs into Experience Engine for offline use.",
|
|
1303
|
+
"muonroi-docs": null, // already our own controlled service
|
|
1304
|
+
playwright: "Use for full browser interaction/screenshots only; fetch_url sufficient for most content needs.",
|
|
1305
|
+
memory: "Use native ee_query / ee_write (Experience Engine) instead.",
|
|
1306
|
+
figma: "Add manually only if needed; no native equivalent yet.",
|
|
1307
|
+
};
|
|
1308
|
+
const summary = servers.map((s) => {
|
|
1309
|
+
const rec = RECOMMENDATIONS[s.id] ?? null;
|
|
1310
|
+
return {
|
|
1311
|
+
id: s.id,
|
|
1312
|
+
label: s.label,
|
|
1313
|
+
enabled: s.enabled,
|
|
1314
|
+
transport: s.transport,
|
|
1315
|
+
endpoint: s.url || (s.command ? `${s.command} ${(s.args || []).join(" ")}` : undefined),
|
|
1316
|
+
recommended_native: rec,
|
|
1317
|
+
};
|
|
1318
|
+
});
|
|
1319
|
+
return JSON.stringify({ count: summary.length, servers: summary }, null, 2);
|
|
1320
|
+
},
|
|
1321
|
+
});
|
|
1322
|
+
tools.list_tools = dynamicTool({
|
|
1323
|
+
description: "Compact grouped summary of every tool available this turn. " +
|
|
1324
|
+
"native = always-on builtins (fetch_url, web_search, bash, read_file, grep, ee_query, list_mcp_servers, list_tools, ...). " +
|
|
1325
|
+
"mcp = tools from your enabled MCP servers (prefixed mcp_<server-id>__). " +
|
|
1326
|
+
"Each line: name + short description (tells you purpose and rough usage). " +
|
|
1327
|
+
"Call list_mcp_servers() to see your MCP sources, then this to see concrete tools + how to use them. Full parameter schemas are in the system tool list this turn.",
|
|
1328
|
+
inputSchema: jsonSchema({
|
|
1329
|
+
type: "object",
|
|
1330
|
+
properties: {
|
|
1331
|
+
category: {
|
|
1332
|
+
type: "string",
|
|
1333
|
+
enum: ["all", "native", "mcp"],
|
|
1334
|
+
description: "Optional filter.",
|
|
1335
|
+
},
|
|
1336
|
+
},
|
|
1337
|
+
additionalProperties: false,
|
|
1338
|
+
}),
|
|
1339
|
+
execute: async (input) => {
|
|
1340
|
+
const cat = input?.category || "all";
|
|
1341
|
+
const grouped = { native: [], mcp: [] };
|
|
1342
|
+
for (const [name, tool] of Object.entries(tools)) {
|
|
1343
|
+
const t = tool;
|
|
1344
|
+
const shortDesc = (t.description || "").split("\n")[0].slice(0, 140);
|
|
1345
|
+
const entry = `${name}: ${shortDesc}`;
|
|
1346
|
+
if (name.startsWith("mcp_")) {
|
|
1347
|
+
if (cat === "all" || cat === "mcp")
|
|
1348
|
+
grouped.mcp.push(entry);
|
|
1349
|
+
}
|
|
1350
|
+
else {
|
|
1351
|
+
if (cat === "all" || cat === "native")
|
|
1352
|
+
grouped.native.push(entry);
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
grouped.native.sort();
|
|
1356
|
+
grouped.mcp.sort();
|
|
1357
|
+
return JSON.stringify({
|
|
1358
|
+
total: Object.keys(tools).length,
|
|
1359
|
+
native_count: grouped.native.length,
|
|
1360
|
+
mcp_count: grouped.mcp.length,
|
|
1361
|
+
...grouped,
|
|
1362
|
+
note: "Native tools are always preferred. MCP tools only from servers where enabled=true (see list_mcp_servers).",
|
|
1363
|
+
}, null, 2);
|
|
1364
|
+
},
|
|
1365
|
+
});
|
|
1366
|
+
tools.describe_tool = dynamicTool({
|
|
1367
|
+
description: "Get detailed usage information for a specific tool by name. Returns description, full input schema (parameters), and a short usage example or note. " +
|
|
1368
|
+
"Call this when you need precise 'how to use' details for a tool (e.g. describe_tool with name='fetch_url' or name='mcp_context7__something'). " +
|
|
1369
|
+
"This complements list_tools and list_mcp_servers.",
|
|
1370
|
+
inputSchema: jsonSchema({
|
|
1371
|
+
type: "object",
|
|
1372
|
+
properties: {
|
|
1373
|
+
name: {
|
|
1374
|
+
type: "string",
|
|
1375
|
+
description: "Exact tool name (e.g. 'fetch_url', 'web_search', 'mcp_context7__search' or any from list_tools)",
|
|
1376
|
+
},
|
|
1377
|
+
},
|
|
1378
|
+
required: ["name"],
|
|
1379
|
+
additionalProperties: false,
|
|
1380
|
+
}),
|
|
1381
|
+
execute: async (input) => {
|
|
1382
|
+
const name = typeof input?.name === "string" ? input.name.trim() : "";
|
|
1383
|
+
if (!name)
|
|
1384
|
+
return "ERROR: name is required";
|
|
1385
|
+
const tool = tools[name];
|
|
1386
|
+
if (!tool) {
|
|
1387
|
+
return JSON.stringify({
|
|
1388
|
+
name,
|
|
1389
|
+
error: "Tool not found in current tool set. Use list_tools to see available names.",
|
|
1390
|
+
}, null, 2);
|
|
1391
|
+
}
|
|
1392
|
+
const t = tool;
|
|
1393
|
+
const schema = t.inputSchema || tool.parameters || null;
|
|
1394
|
+
// Provide a minimal example note for common tools
|
|
1395
|
+
const examples = {
|
|
1396
|
+
fetch_url: 'Example: {"url": "https://example.com/docs", "format": "markdown"}',
|
|
1397
|
+
web_search: 'Example: {"query": "muonroi building block best practices", "maxResults": 5}',
|
|
1398
|
+
list_mcp_servers: "Call with no args: {}",
|
|
1399
|
+
list_tools: 'Example: {"category": "native"}',
|
|
1400
|
+
};
|
|
1401
|
+
return JSON.stringify({
|
|
1402
|
+
name,
|
|
1403
|
+
description: t.description,
|
|
1404
|
+
inputSchema: schema,
|
|
1405
|
+
example: examples[name] || "See inputSchema above. Call with correct parameters.",
|
|
1406
|
+
note: "Use the exact parameters from inputSchema when calling this tool.",
|
|
1407
|
+
}, null, 2);
|
|
1408
|
+
},
|
|
1409
|
+
});
|
|
857
1410
|
return tools;
|
|
858
1411
|
}
|
|
859
1412
|
//# sourceMappingURL=registry.js.map
|