@cjhyy/code-shell-core 0.5.0-rc.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 +21 -0
- package/README.md +162 -0
- package/dist/agent/coordinator.d.ts +49 -0
- package/dist/agent/coordinator.js +77 -0
- package/dist/arena/arena.d.ts +43 -0
- package/dist/arena/arena.js +334 -0
- package/dist/arena/context/context-tools.d.ts +16 -0
- package/dist/arena/context/context-tools.js +231 -0
- package/dist/arena/detect-mode.d.ts +20 -0
- package/dist/arena/detect-mode.js +78 -0
- package/dist/arena/digest-builder.d.ts +25 -0
- package/dist/arena/digest-builder.js +120 -0
- package/dist/arena/index.d.ts +29 -0
- package/dist/arena/index.js +29 -0
- package/dist/arena/iterate/convergence.d.ts +25 -0
- package/dist/arena/iterate/convergence.js +103 -0
- package/dist/arena/iterate/formats/index.d.ts +22 -0
- package/dist/arena/iterate/formats/index.js +283 -0
- package/dist/arena/iterate/index.d.ts +11 -0
- package/dist/arena/iterate/index.js +9 -0
- package/dist/arena/iterate/iterative-arena.d.ts +23 -0
- package/dist/arena/iterate/iterative-arena.js +237 -0
- package/dist/arena/iterate/parse.d.ts +42 -0
- package/dist/arena/iterate/parse.js +123 -0
- package/dist/arena/iterate/phases/argue.d.ts +22 -0
- package/dist/arena/iterate/phases/argue.js +159 -0
- package/dist/arena/iterate/phases/revise.d.ts +16 -0
- package/dist/arena/iterate/phases/revise.js +62 -0
- package/dist/arena/iterate/phases/tournament.d.ts +34 -0
- package/dist/arena/iterate/phases/tournament.js +113 -0
- package/dist/arena/iterate/tools/web-tools.d.ts +13 -0
- package/dist/arena/iterate/tools/web-tools.js +54 -0
- package/dist/arena/iterate/types.d.ts +152 -0
- package/dist/arena/iterate/types.js +8 -0
- package/dist/arena/ledger.d.ts +47 -0
- package/dist/arena/ledger.js +151 -0
- package/dist/arena/lenses/architecture.d.ts +5 -0
- package/dist/arena/lenses/architecture.js +22 -0
- package/dist/arena/lenses/engineering.d.ts +5 -0
- package/dist/arena/lenses/engineering.js +22 -0
- package/dist/arena/lenses/general.d.ts +5 -0
- package/dist/arena/lenses/general.js +20 -0
- package/dist/arena/lenses/index.d.ts +16 -0
- package/dist/arena/lenses/index.js +47 -0
- package/dist/arena/lenses/product.d.ts +5 -0
- package/dist/arena/lenses/product.js +22 -0
- package/dist/arena/model-presets.d.ts +23 -0
- package/dist/arena/model-presets.js +44 -0
- package/dist/arena/phases/adjudication.d.ts +24 -0
- package/dist/arena/phases/adjudication.js +144 -0
- package/dist/arena/phases/build-consensus.d.ts +29 -0
- package/dist/arena/phases/build-consensus.js +86 -0
- package/dist/arena/phases/claim-registry.d.ts +26 -0
- package/dist/arena/phases/claim-registry.js +60 -0
- package/dist/arena/phases/cross-review.d.ts +45 -0
- package/dist/arena/phases/cross-review.js +224 -0
- package/dist/arena/phases/debate-rounds.d.ts +27 -0
- package/dist/arena/phases/debate-rounds.js +162 -0
- package/dist/arena/phases/participant-research.d.ts +38 -0
- package/dist/arena/phases/participant-research.js +317 -0
- package/dist/arena/phases/planning-detail-expansion.d.ts +38 -0
- package/dist/arena/phases/planning-detail-expansion.js +121 -0
- package/dist/arena/planner.d.ts +27 -0
- package/dist/arena/planner.js +312 -0
- package/dist/arena/providers/docs.d.ts +6 -0
- package/dist/arena/providers/docs.js +108 -0
- package/dist/arena/providers/git.d.ts +8 -0
- package/dist/arena/providers/git.js +174 -0
- package/dist/arena/providers/index.d.ts +32 -0
- package/dist/arena/providers/index.js +132 -0
- package/dist/arena/providers/none.d.ts +7 -0
- package/dist/arena/providers/none.js +11 -0
- package/dist/arena/providers/repo.d.ts +6 -0
- package/dist/arena/providers/repo.js +255 -0
- package/dist/arena/render/session.d.ts +17 -0
- package/dist/arena/render/session.js +190 -0
- package/dist/arena/render/terminal.d.ts +34 -0
- package/dist/arena/render/terminal.js +286 -0
- package/dist/arena/strategies/discussion.d.ts +25 -0
- package/dist/arena/strategies/discussion.js +143 -0
- package/dist/arena/strategies/index.d.ts +15 -0
- package/dist/arena/strategies/index.js +28 -0
- package/dist/arena/strategies/language-wrapper.d.ts +17 -0
- package/dist/arena/strategies/language-wrapper.js +102 -0
- package/dist/arena/strategies/lens-wrapper.d.ts +16 -0
- package/dist/arena/strategies/lens-wrapper.js +236 -0
- package/dist/arena/strategies/planning.d.ts +30 -0
- package/dist/arena/strategies/planning.js +225 -0
- package/dist/arena/strategies/review.d.ts +26 -0
- package/dist/arena/strategies/review.js +168 -0
- package/dist/arena/strategies/utils.d.ts +39 -0
- package/dist/arena/strategies/utils.js +647 -0
- package/dist/arena/tools/selector.d.ts +17 -0
- package/dist/arena/tools/selector.js +61 -0
- package/dist/arena/transitions.d.ts +48 -0
- package/dist/arena/transitions.js +92 -0
- package/dist/arena/types.d.ts +508 -0
- package/dist/arena/types.js +27 -0
- package/dist/cli/agent-server-stdio.d.ts +32 -0
- package/dist/cli/agent-server-stdio.js +116 -0
- package/dist/colorizer.d.ts +23 -0
- package/dist/colorizer.js +12 -0
- package/dist/context/compaction.d.ts +116 -0
- package/dist/context/compaction.js +534 -0
- package/dist/context/manager.d.ts +145 -0
- package/dist/context/manager.js +423 -0
- package/dist/context/token-counter.d.ts +27 -0
- package/dist/context/token-counter.js +91 -0
- package/dist/context/tool-result-storage.d.ts +96 -0
- package/dist/context/tool-result-storage.js +296 -0
- package/dist/cost-tracker.d.ts +64 -0
- package/dist/cost-tracker.js +314 -0
- package/dist/cron/scheduler.d.ts +34 -0
- package/dist/cron/scheduler.js +115 -0
- package/dist/data/deepseek-models.json +46 -0
- package/dist/data/gemini-models.json +67 -0
- package/dist/data/openai-models.json +175 -0
- package/dist/data/openrouter-models.d.ts +35 -0
- package/dist/data/openrouter-models.js +36 -0
- package/dist/data/openrouter-models.json +4626 -0
- package/dist/data/openrouter-sync.d.ts +16 -0
- package/dist/data/openrouter-sync.js +53 -0
- package/dist/data/static-catalogs.d.ts +25 -0
- package/dist/data/static-catalogs.js +26 -0
- package/dist/data/zai-models.json +56 -0
- package/dist/engine/cost-store.d.ts +22 -0
- package/dist/engine/cost-store.js +15 -0
- package/dist/engine/engine.d.ts +295 -0
- package/dist/engine/engine.js +1467 -0
- package/dist/engine/model-facade.d.ts +24 -0
- package/dist/engine/model-facade.js +194 -0
- package/dist/engine/parse-task.d.ts +59 -0
- package/dist/engine/parse-task.js +135 -0
- package/dist/engine/patch-orphaned-tools.d.ts +52 -0
- package/dist/engine/patch-orphaned-tools.js +95 -0
- package/dist/engine/query.d.ts +50 -0
- package/dist/engine/query.js +107 -0
- package/dist/engine/runtime.d.ts +50 -0
- package/dist/engine/runtime.js +59 -0
- package/dist/engine/streaming-tool-queue.d.ts +34 -0
- package/dist/engine/streaming-tool-queue.js +61 -0
- package/dist/engine/token-budget.d.ts +22 -0
- package/dist/engine/token-budget.js +40 -0
- package/dist/engine/tool-summary.d.ts +13 -0
- package/dist/engine/tool-summary.js +35 -0
- package/dist/engine/turn-loop.d.ts +122 -0
- package/dist/engine/turn-loop.js +602 -0
- package/dist/engine/turn-state.d.ts +20 -0
- package/dist/engine/turn-state.js +17 -0
- package/dist/exceptions.d.ts +61 -0
- package/dist/exceptions.js +116 -0
- package/dist/git/utils.d.ts +35 -0
- package/dist/git/utils.js +98 -0
- package/dist/git/worktree.d.ts +36 -0
- package/dist/git/worktree.js +139 -0
- package/dist/hooks/events.d.ts +114 -0
- package/dist/hooks/events.js +4 -0
- package/dist/hooks/inject.d.ts +19 -0
- package/dist/hooks/inject.js +29 -0
- package/dist/hooks/registry.d.ts +15 -0
- package/dist/hooks/registry.js +84 -0
- package/dist/hooks/shell-runner.d.ts +45 -0
- package/dist/hooks/shell-runner.js +173 -0
- package/dist/index.d.ts +117 -0
- package/dist/index.js +145 -0
- package/dist/llm/api-key-sanitize.d.ts +22 -0
- package/dist/llm/api-key-sanitize.js +81 -0
- package/dist/llm/capabilities/index.d.ts +20 -0
- package/dist/llm/capabilities/index.js +39 -0
- package/dist/llm/capabilities/rules.d.ts +26 -0
- package/dist/llm/capabilities/rules.js +215 -0
- package/dist/llm/capabilities/types.d.ts +114 -0
- package/dist/llm/capabilities/types.js +24 -0
- package/dist/llm/client-base.d.ts +29 -0
- package/dist/llm/client-base.js +137 -0
- package/dist/llm/client-factory.d.ts +10 -0
- package/dist/llm/client-factory.js +29 -0
- package/dist/llm/model-cache.d.ts +21 -0
- package/dist/llm/model-cache.js +46 -0
- package/dist/llm/model-fetcher.d.ts +29 -0
- package/dist/llm/model-fetcher.js +282 -0
- package/dist/llm/model-pool.d.ts +95 -0
- package/dist/llm/model-pool.js +246 -0
- package/dist/llm/provider-catalog.d.ts +32 -0
- package/dist/llm/provider-catalog.js +50 -0
- package/dist/llm/provider-kinds.d.ts +21 -0
- package/dist/llm/provider-kinds.js +132 -0
- package/dist/llm/providers/anthropic.d.ts +19 -0
- package/dist/llm/providers/anthropic.js +267 -0
- package/dist/llm/providers/openai.d.ts +64 -0
- package/dist/llm/providers/openai.js +606 -0
- package/dist/llm/retry.d.ts +12 -0
- package/dist/llm/retry.js +17 -0
- package/dist/llm/stream-watchdog.d.ts +42 -0
- package/dist/llm/stream-watchdog.js +70 -0
- package/dist/llm/token-counter.d.ts +17 -0
- package/dist/llm/token-counter.js +36 -0
- package/dist/llm/types.d.ts +37 -0
- package/dist/llm/types.js +4 -0
- package/dist/logging/logger.d.ts +109 -0
- package/dist/logging/logger.js +390 -0
- package/dist/logging/sanitize-messages.d.ts +42 -0
- package/dist/logging/sanitize-messages.js +150 -0
- package/dist/logging/session-recorder.d.ts +90 -0
- package/dist/logging/session-recorder.js +304 -0
- package/dist/lsp/client.d.ts +41 -0
- package/dist/lsp/client.js +166 -0
- package/dist/lsp/manager.d.ts +40 -0
- package/dist/lsp/manager.js +124 -0
- package/dist/lsp/servers.d.ts +16 -0
- package/dist/lsp/servers.js +60 -0
- package/dist/migrate-models.d.ts +45 -0
- package/dist/migrate-models.js +179 -0
- package/dist/onboarding.d.ts +189 -0
- package/dist/onboarding.js +625 -0
- package/dist/plugins/gitOps.d.ts +32 -0
- package/dist/plugins/gitOps.js +62 -0
- package/dist/plugins/installedPlugins.d.ts +15 -0
- package/dist/plugins/installedPlugins.js +56 -0
- package/dist/plugins/knownMarketplaces.d.ts +10 -0
- package/dist/plugins/knownMarketplaces.js +46 -0
- package/dist/plugins/loadPluginHooks.d.ts +52 -0
- package/dist/plugins/loadPluginHooks.js +162 -0
- package/dist/plugins/marketplaceManager.d.ts +49 -0
- package/dist/plugins/marketplaceManager.js +142 -0
- package/dist/plugins/parseMarketplaceInput.d.ts +16 -0
- package/dist/plugins/parseMarketplaceInput.js +73 -0
- package/dist/plugins/pluginCommandHook.d.ts +54 -0
- package/dist/plugins/pluginCommandHook.js +180 -0
- package/dist/plugins/pluginCommandsLoader.d.ts +25 -0
- package/dist/plugins/pluginCommandsLoader.js +114 -0
- package/dist/plugins/pluginInstaller.d.ts +36 -0
- package/dist/plugins/pluginInstaller.js +228 -0
- package/dist/plugins/schemas.d.ts +9 -0
- package/dist/plugins/schemas.js +136 -0
- package/dist/plugins/types.d.ts +75 -0
- package/dist/plugins/types.js +7 -0
- package/dist/plugins/varRewrite.d.ts +42 -0
- package/dist/plugins/varRewrite.js +129 -0
- package/dist/preset/index.d.ts +60 -0
- package/dist/preset/index.js +159 -0
- package/dist/product/define.d.ts +60 -0
- package/dist/product/define.js +123 -0
- package/dist/product/index.d.ts +5 -0
- package/dist/product/index.js +4 -0
- package/dist/product/types.d.ts +111 -0
- package/dist/product/types.js +21 -0
- package/dist/prompt/composer.d.ts +49 -0
- package/dist/prompt/composer.js +168 -0
- package/dist/prompt/instruction-scanner.d.ts +54 -0
- package/dist/prompt/instruction-scanner.js +187 -0
- package/dist/prompt/section-cache.d.ts +15 -0
- package/dist/prompt/section-cache.js +31 -0
- package/dist/prompt/section-loader.d.ts +26 -0
- package/dist/prompt/section-loader.js +53 -0
- package/dist/prompt/sections/base.md +35 -0
- package/dist/prompt/sections/coding.md +31 -0
- package/dist/prompt/sections/orchestration.md +16 -0
- package/dist/prompt/sections/tone.md +9 -0
- package/dist/protocol/chat-session-manager.d.ts +33 -0
- package/dist/protocol/chat-session-manager.js +65 -0
- package/dist/protocol/chat-session.d.ts +49 -0
- package/dist/protocol/chat-session.js +86 -0
- package/dist/protocol/client.d.ts +104 -0
- package/dist/protocol/client.js +260 -0
- package/dist/protocol/factories.d.ts +93 -0
- package/dist/protocol/factories.js +64 -0
- package/dist/protocol/helpers.d.ts +42 -0
- package/dist/protocol/helpers.js +55 -0
- package/dist/protocol/index.d.ts +4 -0
- package/dist/protocol/index.js +4 -0
- package/dist/protocol/server.d.ts +80 -0
- package/dist/protocol/server.js +855 -0
- package/dist/protocol/transport.d.ts +37 -0
- package/dist/protocol/transport.js +85 -0
- package/dist/protocol/types.d.ts +221 -0
- package/dist/protocol/types.js +61 -0
- package/dist/remote/bridge.d.ts +37 -0
- package/dist/remote/bridge.js +103 -0
- package/dist/run/ArtifactTracker.d.ts +38 -0
- package/dist/run/ArtifactTracker.js +132 -0
- package/dist/run/CheckpointWriter.d.ts +53 -0
- package/dist/run/CheckpointWriter.js +135 -0
- package/dist/run/EngineRunner.d.ts +72 -0
- package/dist/run/EngineRunner.js +119 -0
- package/dist/run/Evaluator.d.ts +56 -0
- package/dist/run/Evaluator.js +62 -0
- package/dist/run/FileRunStore.d.ts +39 -0
- package/dist/run/FileRunStore.js +176 -0
- package/dist/run/Heartbeat.d.ts +54 -0
- package/dist/run/Heartbeat.js +123 -0
- package/dist/run/RunApprovalBackend.d.ts +53 -0
- package/dist/run/RunApprovalBackend.js +85 -0
- package/dist/run/RunLock.d.ts +40 -0
- package/dist/run/RunLock.js +98 -0
- package/dist/run/RunManager.d.ts +82 -0
- package/dist/run/RunManager.js +587 -0
- package/dist/run/RunQueue.d.ts +27 -0
- package/dist/run/RunQueue.js +73 -0
- package/dist/run/RunStore.d.ts +25 -0
- package/dist/run/RunStore.js +9 -0
- package/dist/run/factory.d.ts +63 -0
- package/dist/run/factory.js +51 -0
- package/dist/run/index.d.ts +17 -0
- package/dist/run/index.js +23 -0
- package/dist/run/types.d.ts +136 -0
- package/dist/run/types.js +28 -0
- package/dist/runtime/safe-spawn.d.ts +118 -0
- package/dist/runtime/safe-spawn.js +268 -0
- package/dist/services/analytics.d.ts +29 -0
- package/dist/services/analytics.js +84 -0
- package/dist/services/auto-dream.d.ts +49 -0
- package/dist/services/auto-dream.js +124 -0
- package/dist/services/diagnostics.d.ts +41 -0
- package/dist/services/diagnostics.js +99 -0
- package/dist/services/extract-memories.d.ts +31 -0
- package/dist/services/extract-memories.js +71 -0
- package/dist/services/index.d.ts +11 -0
- package/dist/services/index.js +17 -0
- package/dist/services/memory-orchestrator.d.ts +60 -0
- package/dist/services/memory-orchestrator.js +133 -0
- package/dist/services/notifier.d.ts +25 -0
- package/dist/services/notifier.js +69 -0
- package/dist/services/oauth.d.ts +27 -0
- package/dist/services/oauth.js +153 -0
- package/dist/services/session-memory.d.ts +37 -0
- package/dist/services/session-memory.js +81 -0
- package/dist/session/file-history.d.ts +41 -0
- package/dist/session/file-history.js +115 -0
- package/dist/session/memory.d.ts +104 -0
- package/dist/session/memory.js +310 -0
- package/dist/session/session-manager.d.ts +41 -0
- package/dist/session/session-manager.js +261 -0
- package/dist/session/transcript.d.ts +39 -0
- package/dist/session/transcript.js +186 -0
- package/dist/settings/manager.d.ts +36 -0
- package/dist/settings/manager.js +187 -0
- package/dist/settings/schema.d.ts +1219 -0
- package/dist/settings/schema.js +246 -0
- package/dist/skills/frontmatter.d.ts +13 -0
- package/dist/skills/frontmatter.js +70 -0
- package/dist/skills/index.d.ts +7 -0
- package/dist/skills/index.js +6 -0
- package/dist/skills/scanner.d.ts +31 -0
- package/dist/skills/scanner.js +171 -0
- package/dist/state.d.ts +160 -0
- package/dist/state.js +267 -0
- package/dist/tool-system/builtin/agent-notifications.d.ts +84 -0
- package/dist/tool-system/builtin/agent-notifications.js +197 -0
- package/dist/tool-system/builtin/agent-registry.d.ts +67 -0
- package/dist/tool-system/builtin/agent-registry.js +126 -0
- package/dist/tool-system/builtin/agent-transcript-translator.d.ts +22 -0
- package/dist/tool-system/builtin/agent-transcript-translator.js +160 -0
- package/dist/tool-system/builtin/agent.d.ts +16 -0
- package/dist/tool-system/builtin/agent.js +364 -0
- package/dist/tool-system/builtin/apply-patch/applier.d.ts +26 -0
- package/dist/tool-system/builtin/apply-patch/applier.js +250 -0
- package/dist/tool-system/builtin/apply-patch/index.d.ts +20 -0
- package/dist/tool-system/builtin/apply-patch/index.js +101 -0
- package/dist/tool-system/builtin/apply-patch/parser.d.ts +17 -0
- package/dist/tool-system/builtin/apply-patch/parser.js +212 -0
- package/dist/tool-system/builtin/apply-patch/seek-sequence.d.ts +18 -0
- package/dist/tool-system/builtin/apply-patch/seek-sequence.js +123 -0
- package/dist/tool-system/builtin/apply-patch/types.d.ts +49 -0
- package/dist/tool-system/builtin/apply-patch/types.js +13 -0
- package/dist/tool-system/builtin/arena.d.ts +31 -0
- package/dist/tool-system/builtin/arena.js +416 -0
- package/dist/tool-system/builtin/ask-user.d.ts +20 -0
- package/dist/tool-system/builtin/ask-user.js +99 -0
- package/dist/tool-system/builtin/bash.d.ts +21 -0
- package/dist/tool-system/builtin/bash.js +149 -0
- package/dist/tool-system/builtin/brief.d.ts +6 -0
- package/dist/tool-system/builtin/brief.js +41 -0
- package/dist/tool-system/builtin/config.d.ts +6 -0
- package/dist/tool-system/builtin/config.js +67 -0
- package/dist/tool-system/builtin/cron.d.ts +10 -0
- package/dist/tool-system/builtin/cron.js +61 -0
- package/dist/tool-system/builtin/edit.d.ts +6 -0
- package/dist/tool-system/builtin/edit.js +100 -0
- package/dist/tool-system/builtin/file-cache.d.ts +11 -0
- package/dist/tool-system/builtin/file-cache.js +39 -0
- package/dist/tool-system/builtin/glob.d.ts +7 -0
- package/dist/tool-system/builtin/glob.js +76 -0
- package/dist/tool-system/builtin/grep.d.ts +7 -0
- package/dist/tool-system/builtin/grep.js +150 -0
- package/dist/tool-system/builtin/index.d.ts +20 -0
- package/dist/tool-system/builtin/index.js +449 -0
- package/dist/tool-system/builtin/lsp.d.ts +6 -0
- package/dist/tool-system/builtin/lsp.js +141 -0
- package/dist/tool-system/builtin/mcp-tools.d.ts +10 -0
- package/dist/tool-system/builtin/mcp-tools.js +102 -0
- package/dist/tool-system/builtin/memory.d.ts +26 -0
- package/dist/tool-system/builtin/memory.js +226 -0
- package/dist/tool-system/builtin/notebook-edit.d.ts +6 -0
- package/dist/tool-system/builtin/notebook-edit.js +124 -0
- package/dist/tool-system/builtin/plan.d.ts +15 -0
- package/dist/tool-system/builtin/plan.js +55 -0
- package/dist/tool-system/builtin/powershell.d.ts +11 -0
- package/dist/tool-system/builtin/powershell.js +64 -0
- package/dist/tool-system/builtin/read.d.ts +6 -0
- package/dist/tool-system/builtin/read.js +70 -0
- package/dist/tool-system/builtin/remote-trigger.d.ts +6 -0
- package/dist/tool-system/builtin/remote-trigger.js +54 -0
- package/dist/tool-system/builtin/repl.d.ts +11 -0
- package/dist/tool-system/builtin/repl.js +82 -0
- package/dist/tool-system/builtin/send-message.d.ts +6 -0
- package/dist/tool-system/builtin/send-message.js +47 -0
- package/dist/tool-system/builtin/skill-prompt.d.ts +20 -0
- package/dist/tool-system/builtin/skill-prompt.js +52 -0
- package/dist/tool-system/builtin/skill.d.ts +9 -0
- package/dist/tool-system/builtin/skill.js +55 -0
- package/dist/tool-system/builtin/sleep.d.ts +6 -0
- package/dist/tool-system/builtin/sleep.js +33 -0
- package/dist/tool-system/builtin/task.d.ts +48 -0
- package/dist/tool-system/builtin/task.js +139 -0
- package/dist/tool-system/builtin/tool-search.d.ts +11 -0
- package/dist/tool-system/builtin/tool-search.js +90 -0
- package/dist/tool-system/builtin/web-fetch.d.ts +10 -0
- package/dist/tool-system/builtin/web-fetch.js +328 -0
- package/dist/tool-system/builtin/web-search.d.ts +25 -0
- package/dist/tool-system/builtin/web-search.js +174 -0
- package/dist/tool-system/builtin/worktree.d.ts +10 -0
- package/dist/tool-system/builtin/worktree.js +95 -0
- package/dist/tool-system/builtin/write.d.ts +6 -0
- package/dist/tool-system/builtin/write.js +36 -0
- package/dist/tool-system/context.d.ts +165 -0
- package/dist/tool-system/context.js +18 -0
- package/dist/tool-system/executor.d.ts +49 -0
- package/dist/tool-system/executor.js +495 -0
- package/dist/tool-system/investigation-guard.d.ts +46 -0
- package/dist/tool-system/investigation-guard.js +155 -0
- package/dist/tool-system/mcp-manager.d.ts +67 -0
- package/dist/tool-system/mcp-manager.js +249 -0
- package/dist/tool-system/permission.d.ts +111 -0
- package/dist/tool-system/permission.js +774 -0
- package/dist/tool-system/registry.d.ts +32 -0
- package/dist/tool-system/registry.js +131 -0
- package/dist/tool-system/sandbox/bwrap.d.ts +13 -0
- package/dist/tool-system/sandbox/bwrap.js +63 -0
- package/dist/tool-system/sandbox/index.d.ts +78 -0
- package/dist/tool-system/sandbox/index.js +222 -0
- package/dist/tool-system/sandbox/off.d.ts +2 -0
- package/dist/tool-system/sandbox/off.js +8 -0
- package/dist/tool-system/sandbox/seatbelt.d.ts +18 -0
- package/dist/tool-system/sandbox/seatbelt.js +109 -0
- package/dist/tool-system/task-guard.d.ts +29 -0
- package/dist/tool-system/task-guard.js +70 -0
- package/dist/tool-system/validation.d.ts +5 -0
- package/dist/tool-system/validation.js +39 -0
- package/dist/types.d.ts +376 -0
- package/dist/types.js +4 -0
- package/dist/updater.d.ts +65 -0
- package/dist/updater.js +405 -0
- package/dist/utils/debug.d.ts +41 -0
- package/dist/utils/debug.js +110 -0
- package/dist/utils/earlyInput.d.ts +43 -0
- package/dist/utils/earlyInput.js +166 -0
- package/dist/utils/env.d.ts +24 -0
- package/dist/utils/env.js +104 -0
- package/dist/utils/envUtils.d.ts +51 -0
- package/dist/utils/envUtils.js +135 -0
- package/dist/utils/execFileNoThrow.d.ts +39 -0
- package/dist/utils/execFileNoThrow.js +74 -0
- package/dist/utils/format.d.ts +44 -0
- package/dist/utils/format.js +236 -0
- package/dist/utils/intl.d.ts +22 -0
- package/dist/utils/intl.js +83 -0
- package/dist/utils/lockfile.d.ts +15 -0
- package/dist/utils/lockfile.js +30 -0
- package/dist/utils/memoize.d.ts +19 -0
- package/dist/utils/memoize.js +14 -0
- package/dist/utils/semver.d.ts +6 -0
- package/dist/utils/semver.js +13 -0
- package/dist/utils/sliceAnsi.d.ts +12 -0
- package/dist/utils/sliceAnsi.js +62 -0
- package/dist/utils/systemTheme.d.ts +40 -0
- package/dist/utils/systemTheme.js +108 -0
- package/dist/utils/task-sanitizer.d.ts +6 -0
- package/dist/utils/task-sanitizer.js +24 -0
- package/dist/utils/theme.d.ts +93 -0
- package/dist/utils/theme.js +544 -0
- package/dist/utils/toolDisplay.d.ts +31 -0
- package/dist/utils/toolDisplay.js +188 -0
- package/package.json +72 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Investigation Guard — runtime enforcement of read budgets.
|
|
3
|
+
*
|
|
4
|
+
* Background: prompt rules in coding.md ("never re-read the same file",
|
|
5
|
+
* "after ~3 read-only calls, change strategy") describe a behavior the model
|
|
6
|
+
* frequently violates under context pressure. This module turns those soft
|
|
7
|
+
* rules into in-loop reminders/blocks delivered through tool results.
|
|
8
|
+
*
|
|
9
|
+
* Three independent counters share one guard instance per Engine:
|
|
10
|
+
* A) dedupe — same Read offset hit ≥2 times → reminder; ≥3 times → block
|
|
11
|
+
* B) read-budget — N consecutive read-only tools with no side-effecting
|
|
12
|
+
* tool in between → reminder on the next read
|
|
13
|
+
* C) silent turns — N consecutive turns of only read-only tools with no
|
|
14
|
+
* text output → injected into the *next* turn's user
|
|
15
|
+
* message by turn-loop (the guard just tracks state).
|
|
16
|
+
*
|
|
17
|
+
* Everything decays naturally on any write/Bash/AskUser tool (state reset).
|
|
18
|
+
*/
|
|
19
|
+
const READ_ONLY_TOOLS = new Set(["Read", "Grep", "Glob", "WebFetch", "WebSearch", "ToolSearch"]);
|
|
20
|
+
const READ_BUDGET = 3;
|
|
21
|
+
const SILENT_TURN_BUDGET = 3;
|
|
22
|
+
const DEDUPE_OFFSET_BUCKET = 50;
|
|
23
|
+
// Cap readHistory so a long-running session can't grow it unbounded.
|
|
24
|
+
// 512 distinct read signatures is far above what any real investigation
|
|
25
|
+
// touches; once exceeded, evict oldest insertion-order entries.
|
|
26
|
+
const READ_HISTORY_MAX = 512;
|
|
27
|
+
export class InvestigationGuard {
|
|
28
|
+
readHistory = new Map();
|
|
29
|
+
consecutiveReads = 0;
|
|
30
|
+
silentTurns = 0;
|
|
31
|
+
turnHasText = false;
|
|
32
|
+
turnHasSideEffect = false;
|
|
33
|
+
lastReminderSilent = -1;
|
|
34
|
+
/**
|
|
35
|
+
* Soft mode replaces hard blocks (3rd-read dedupe) with a stronger
|
|
36
|
+
* reminder. Used in headless runs (`code-shell run …`) where there is
|
|
37
|
+
* no human to retry the task, so an unattended automation should not
|
|
38
|
+
* be killed by the guard — it should still get the signal to change
|
|
39
|
+
* strategy, but the tool call goes through.
|
|
40
|
+
*/
|
|
41
|
+
softMode = false;
|
|
42
|
+
setSoftMode(soft) {
|
|
43
|
+
this.softMode = soft;
|
|
44
|
+
}
|
|
45
|
+
preToolCheck(call) {
|
|
46
|
+
const tool = call.toolName;
|
|
47
|
+
if (!READ_ONLY_TOOLS.has(tool)) {
|
|
48
|
+
if (this.isMutatingTool(tool)) {
|
|
49
|
+
this.consecutiveReads = 0;
|
|
50
|
+
this.turnHasSideEffect = true;
|
|
51
|
+
}
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
const key = this.buildKey(call);
|
|
55
|
+
if (!key)
|
|
56
|
+
return undefined;
|
|
57
|
+
const hits = (this.readHistory.get(key.signature) ?? 0) + 1;
|
|
58
|
+
this.readHistory.set(key.signature, hits);
|
|
59
|
+
if (this.readHistory.size > READ_HISTORY_MAX) {
|
|
60
|
+
const oldest = this.readHistory.keys().next().value;
|
|
61
|
+
if (oldest !== undefined)
|
|
62
|
+
this.readHistory.delete(oldest);
|
|
63
|
+
}
|
|
64
|
+
this.consecutiveReads += 1;
|
|
65
|
+
const prependParts = [];
|
|
66
|
+
if (hits >= 3) {
|
|
67
|
+
const message = `Investigation guard: ${tool} on this exact target has been called ${hits} times in this session. ` +
|
|
68
|
+
`Re-reading the same content will not produce new information. ` +
|
|
69
|
+
`Switch strategy: run a command with side effects (Bash, debug log, repro), make a code change, or ask the user a specific question. ` +
|
|
70
|
+
`If you genuinely need this content, summarize what you already know about it from prior reads instead of re-fetching.`;
|
|
71
|
+
if (this.softMode) {
|
|
72
|
+
// Soft mode (headless): deliver the same signal as a prepend so the
|
|
73
|
+
// model still sees it, but allow the tool call to proceed. Hard-
|
|
74
|
+
// blocking an unattended `code-shell run …` would dead-end the task
|
|
75
|
+
// with no human to retry.
|
|
76
|
+
prependParts.push(`<system-reminder>${message}</system-reminder>`);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
return { block: message };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (hits === 2) {
|
|
83
|
+
prependParts.push(`<system-reminder>Investigation guard: you already read this target once in this session. ` +
|
|
84
|
+
`Re-reading rarely yields new information. After this result, change strategy (Bash side-effect, edit, or ask user) rather than reading further.</system-reminder>`);
|
|
85
|
+
}
|
|
86
|
+
if (this.consecutiveReads > READ_BUDGET) {
|
|
87
|
+
prependParts.push(`<system-reminder>Investigation guard: ${this.consecutiveReads} consecutive read-only calls with no action taken. ` +
|
|
88
|
+
`Per coding.md, change strategy now — make a code change, run a command with side effects, or ask the user.</system-reminder>`);
|
|
89
|
+
}
|
|
90
|
+
return prependParts.length ? { prepend: prependParts.join("\n") } : undefined;
|
|
91
|
+
}
|
|
92
|
+
noteText(text) {
|
|
93
|
+
if (text && text.trim().length > 0)
|
|
94
|
+
this.turnHasText = true;
|
|
95
|
+
}
|
|
96
|
+
noteToolResult(_call, _result) { }
|
|
97
|
+
turnEnded(turnNumber) {
|
|
98
|
+
if (!this.turnHasText && !this.turnHasSideEffect) {
|
|
99
|
+
this.silentTurns += 1;
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
this.silentTurns = 0;
|
|
103
|
+
}
|
|
104
|
+
const wasSilent = this.silentTurns;
|
|
105
|
+
this.turnHasText = false;
|
|
106
|
+
this.turnHasSideEffect = false;
|
|
107
|
+
if (wasSilent >= SILENT_TURN_BUDGET && turnNumber !== this.lastReminderSilent) {
|
|
108
|
+
this.lastReminderSilent = turnNumber;
|
|
109
|
+
return (`<system-reminder>Investigation guard: you have taken ${wasSilent} consecutive turns of read-only investigation ` +
|
|
110
|
+
`without any text update to the user or side-effecting action. ` +
|
|
111
|
+
`Either surface a status update (what have you ruled out, what's your current hypothesis?), ` +
|
|
112
|
+
`or change tactic — verify at runtime (logs, repro, Bash) instead of reading further.</system-reminder>`);
|
|
113
|
+
}
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
isMutatingTool(name) {
|
|
117
|
+
if (name === "Bash")
|
|
118
|
+
return true;
|
|
119
|
+
if (name === "Edit" || name === "Write" || name === "NotebookEdit")
|
|
120
|
+
return true;
|
|
121
|
+
if (name === "AskUserQuestion")
|
|
122
|
+
return true;
|
|
123
|
+
if (name === "TodoWrite")
|
|
124
|
+
return false;
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
buildKey(call) {
|
|
128
|
+
const tool = call.toolName;
|
|
129
|
+
const args = (call.args ?? {});
|
|
130
|
+
if (tool === "Read") {
|
|
131
|
+
const fp = typeof args.file_path === "string" ? args.file_path : "";
|
|
132
|
+
if (!fp)
|
|
133
|
+
return undefined;
|
|
134
|
+
const off = typeof args.offset === "number" ? args.offset : 0;
|
|
135
|
+
const bucket = Math.floor(off / DEDUPE_OFFSET_BUCKET);
|
|
136
|
+
return { tool, signature: `Read::${fp}::${bucket}` };
|
|
137
|
+
}
|
|
138
|
+
if (tool === "Grep") {
|
|
139
|
+
const pat = typeof args.pattern === "string" ? args.pattern : "";
|
|
140
|
+
const path = typeof args.path === "string" ? args.path : "";
|
|
141
|
+
const glob = typeof args.glob === "string" ? args.glob : "";
|
|
142
|
+
if (!pat)
|
|
143
|
+
return undefined;
|
|
144
|
+
return { tool, signature: `Grep::${pat}::${path}::${glob}` };
|
|
145
|
+
}
|
|
146
|
+
if (tool === "Glob") {
|
|
147
|
+
const pat = typeof args.pattern === "string" ? args.pattern : "";
|
|
148
|
+
const path = typeof args.path === "string" ? args.path : "";
|
|
149
|
+
if (!pat)
|
|
150
|
+
return undefined;
|
|
151
|
+
return { tool, signature: `Glob::${pat}::${path}` };
|
|
152
|
+
}
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Manager — connects to external MCP servers and registers their tools.
|
|
3
|
+
*
|
|
4
|
+
* Supports stdio and streamable-http transports.
|
|
5
|
+
*/
|
|
6
|
+
import type { Tool as McpTool } from "@modelcontextprotocol/sdk/types.js";
|
|
7
|
+
import type { MCPServerConfig, RegisteredTool } from "../types.js";
|
|
8
|
+
import { ToolRegistry } from "./registry.js";
|
|
9
|
+
/**
|
|
10
|
+
* Build the static metadata for a discovered MCP tool.
|
|
11
|
+
*
|
|
12
|
+
* Policy (Gate 2 / Standard §S3):
|
|
13
|
+
* - Default: isConcurrencySafe=false, isReadOnly=false — conservative
|
|
14
|
+
* safe-by-default for unknown servers that may hold mutable state.
|
|
15
|
+
* - Opt-in: when the MCP server explicitly declares
|
|
16
|
+
* `annotations.readOnlyHint === true` per the MCP spec, we honour
|
|
17
|
+
* that hint and set BOTH isConcurrencySafe and isReadOnly to true,
|
|
18
|
+
* enabling parallel execution for provably read-only tools.
|
|
19
|
+
* - Anything other than the boolean literal `true`
|
|
20
|
+
* (undefined, null, false, "true", missing annotations) stays false.
|
|
21
|
+
*
|
|
22
|
+
* @internal exported for unit testing without spinning up a real transport.
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildRegisteredTool(serverName: string, tool: McpTool): RegisteredTool;
|
|
25
|
+
export declare class MCPManager {
|
|
26
|
+
private readonly toolRegistry;
|
|
27
|
+
private static instance;
|
|
28
|
+
private connections;
|
|
29
|
+
constructor(toolRegistry: ToolRegistry);
|
|
30
|
+
static getInstance(): MCPManager;
|
|
31
|
+
/**
|
|
32
|
+
* Connect to all configured MCP servers and register their tools.
|
|
33
|
+
*/
|
|
34
|
+
connectAll(servers: Record<string, MCPServerConfig>): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Connect to a single MCP server.
|
|
37
|
+
*/
|
|
38
|
+
connect(name: string, config: MCPServerConfig): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Discover tools from an MCP server and register them.
|
|
41
|
+
*/
|
|
42
|
+
private discoverTools;
|
|
43
|
+
/**
|
|
44
|
+
* Disconnect all MCP servers.
|
|
45
|
+
*/
|
|
46
|
+
disconnectAll(): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* List connected servers.
|
|
49
|
+
*/
|
|
50
|
+
listServers(): string[];
|
|
51
|
+
/**
|
|
52
|
+
* Call a tool on a specific MCP server.
|
|
53
|
+
*/
|
|
54
|
+
callTool(serverName: string, toolName: string, args: Record<string, unknown>): Promise<unknown>;
|
|
55
|
+
/**
|
|
56
|
+
* List resources from MCP servers.
|
|
57
|
+
*/
|
|
58
|
+
listResources(serverName?: string): Promise<Array<{
|
|
59
|
+
uri: string;
|
|
60
|
+
name: string;
|
|
61
|
+
description?: string;
|
|
62
|
+
}>>;
|
|
63
|
+
/**
|
|
64
|
+
* Read a resource from an MCP server.
|
|
65
|
+
*/
|
|
66
|
+
readResource(serverName: string, uri: string): Promise<string>;
|
|
67
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Manager — connects to external MCP servers and registers their tools.
|
|
3
|
+
*
|
|
4
|
+
* Supports stdio and streamable-http transports.
|
|
5
|
+
*/
|
|
6
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
7
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
8
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
9
|
+
import { logger } from "../logging/logger.js";
|
|
10
|
+
/**
|
|
11
|
+
* Build the static metadata for a discovered MCP tool.
|
|
12
|
+
*
|
|
13
|
+
* Policy (Gate 2 / Standard §S3):
|
|
14
|
+
* - Default: isConcurrencySafe=false, isReadOnly=false — conservative
|
|
15
|
+
* safe-by-default for unknown servers that may hold mutable state.
|
|
16
|
+
* - Opt-in: when the MCP server explicitly declares
|
|
17
|
+
* `annotations.readOnlyHint === true` per the MCP spec, we honour
|
|
18
|
+
* that hint and set BOTH isConcurrencySafe and isReadOnly to true,
|
|
19
|
+
* enabling parallel execution for provably read-only tools.
|
|
20
|
+
* - Anything other than the boolean literal `true`
|
|
21
|
+
* (undefined, null, false, "true", missing annotations) stays false.
|
|
22
|
+
*
|
|
23
|
+
* @internal exported for unit testing without spinning up a real transport.
|
|
24
|
+
*/
|
|
25
|
+
export function buildRegisteredTool(serverName, tool) {
|
|
26
|
+
const readOnly = tool.annotations?.readOnlyHint === true;
|
|
27
|
+
return {
|
|
28
|
+
name: `mcp_${serverName}_${tool.name}`,
|
|
29
|
+
description: `[${serverName}] ${tool.description ?? tool.name}`,
|
|
30
|
+
inputSchema: tool.inputSchema ?? { type: "object", properties: {} },
|
|
31
|
+
source: "mcp",
|
|
32
|
+
serverName,
|
|
33
|
+
permissionDefault: "ask",
|
|
34
|
+
isConcurrencySafe: readOnly,
|
|
35
|
+
isReadOnly: readOnly,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export class MCPManager {
|
|
39
|
+
toolRegistry;
|
|
40
|
+
static instance = null;
|
|
41
|
+
connections = new Map();
|
|
42
|
+
constructor(toolRegistry) {
|
|
43
|
+
this.toolRegistry = toolRegistry;
|
|
44
|
+
MCPManager.instance = this;
|
|
45
|
+
}
|
|
46
|
+
static getInstance() {
|
|
47
|
+
if (!MCPManager.instance) {
|
|
48
|
+
throw new Error("MCPManager not initialized. Connect to servers first.");
|
|
49
|
+
}
|
|
50
|
+
return MCPManager.instance;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Connect to all configured MCP servers and register their tools.
|
|
54
|
+
*/
|
|
55
|
+
async connectAll(servers) {
|
|
56
|
+
const entries = Object.entries(servers);
|
|
57
|
+
if (entries.length === 0)
|
|
58
|
+
return;
|
|
59
|
+
const results = await Promise.allSettled(entries.map(([name, config]) => this.connect(name, config)));
|
|
60
|
+
for (let i = 0; i < results.length; i++) {
|
|
61
|
+
const result = results[i];
|
|
62
|
+
if (result.status === "rejected") {
|
|
63
|
+
logger.warn("mcp.connect_failed", {
|
|
64
|
+
server: entries[i][0],
|
|
65
|
+
error: result.reason.message,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Connect to a single MCP server.
|
|
72
|
+
*/
|
|
73
|
+
async connect(name, config) {
|
|
74
|
+
if (this.connections.has(name)) {
|
|
75
|
+
logger.info("mcp.already_connected", { server: name });
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
logger.info("mcp.connecting", { server: name, transport: config.transport ?? "stdio" });
|
|
79
|
+
const client = new Client({ name: "code-shell", version: "0.1.0" }, { capabilities: {} });
|
|
80
|
+
let transport;
|
|
81
|
+
const transportType = config.transport ?? "stdio";
|
|
82
|
+
if (transportType === "stdio") {
|
|
83
|
+
if (!config.command) {
|
|
84
|
+
throw new Error(`MCP server "${name}": command is required for stdio transport`);
|
|
85
|
+
}
|
|
86
|
+
transport = new StdioClientTransport({
|
|
87
|
+
command: config.command,
|
|
88
|
+
args: config.args,
|
|
89
|
+
env: config.env ? { ...process.env, ...config.env } : undefined,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
else if (transportType === "streamable-http" || transportType === "sse") {
|
|
93
|
+
if (!config.url) {
|
|
94
|
+
throw new Error(`MCP server "${name}": url is required for ${transportType} transport`);
|
|
95
|
+
}
|
|
96
|
+
transport = new StreamableHTTPClientTransport(new URL(config.url), {
|
|
97
|
+
requestInit: config.headers ? { headers: config.headers } : undefined,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
throw new Error(`MCP server "${name}": unsupported transport "${transportType}"`);
|
|
102
|
+
}
|
|
103
|
+
// Prevent a misbehaving MCP server from hanging `connectAll()` forever.
|
|
104
|
+
// On timeout, best-effort close the transport so we don't leak the stdio
|
|
105
|
+
// child / socket when connect() is still pending in the background.
|
|
106
|
+
const CONNECT_TIMEOUT_MS = 15_000;
|
|
107
|
+
let timeoutHandle;
|
|
108
|
+
try {
|
|
109
|
+
await new Promise((resolve, reject) => {
|
|
110
|
+
timeoutHandle = setTimeout(() => {
|
|
111
|
+
reject(new Error(`MCP server "${name}" connect timed out after ${CONNECT_TIMEOUT_MS}ms`));
|
|
112
|
+
}, CONNECT_TIMEOUT_MS);
|
|
113
|
+
client.connect(transport).then(() => resolve(), (err) => reject(err));
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
try {
|
|
118
|
+
await transport.close?.();
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// ignore cleanup errors
|
|
122
|
+
}
|
|
123
|
+
throw err;
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
if (timeoutHandle)
|
|
127
|
+
clearTimeout(timeoutHandle);
|
|
128
|
+
}
|
|
129
|
+
this.connections.set(name, { client, serverName: name, transport });
|
|
130
|
+
// Discover and register tools
|
|
131
|
+
await this.discoverTools(name, client);
|
|
132
|
+
logger.info("mcp.connected", { server: name });
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Discover tools from an MCP server and register them.
|
|
136
|
+
*/
|
|
137
|
+
async discoverTools(serverName, client) {
|
|
138
|
+
const result = await client.listTools();
|
|
139
|
+
for (const tool of result.tools) {
|
|
140
|
+
const registered = buildRegisteredTool(serverName, tool);
|
|
141
|
+
// Register with an executor that calls the MCP server
|
|
142
|
+
this.toolRegistry.registerTool(registered, async (args) => {
|
|
143
|
+
const callResult = await client.callTool({ name: tool.name, arguments: args });
|
|
144
|
+
// Extract text from content array
|
|
145
|
+
const parts = [];
|
|
146
|
+
if (Array.isArray(callResult.content)) {
|
|
147
|
+
for (const item of callResult.content) {
|
|
148
|
+
if (typeof item === "object" && item !== null && "text" in item) {
|
|
149
|
+
parts.push(String(item.text));
|
|
150
|
+
}
|
|
151
|
+
else if (typeof item === "string") {
|
|
152
|
+
parts.push(item);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return parts.join("\n") || "(no output)";
|
|
157
|
+
});
|
|
158
|
+
logger.info("mcp.tool_registered", { server: serverName, tool: registered.name });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Disconnect all MCP servers.
|
|
163
|
+
*/
|
|
164
|
+
async disconnectAll() {
|
|
165
|
+
for (const [name, conn] of this.connections) {
|
|
166
|
+
try {
|
|
167
|
+
await conn.client.close();
|
|
168
|
+
logger.info("mcp.disconnected", { server: name });
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
logger.warn("mcp.disconnect_error", { server: name, error: err.message });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
this.connections.clear();
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* List connected servers.
|
|
178
|
+
*/
|
|
179
|
+
listServers() {
|
|
180
|
+
return [...this.connections.keys()];
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Call a tool on a specific MCP server.
|
|
184
|
+
*/
|
|
185
|
+
async callTool(serverName, toolName, args) {
|
|
186
|
+
const conn = this.connections.get(serverName);
|
|
187
|
+
if (!conn) {
|
|
188
|
+
throw new Error(`MCP server "${serverName}" is not connected.`);
|
|
189
|
+
}
|
|
190
|
+
const result = await conn.client.callTool({ name: toolName, arguments: args });
|
|
191
|
+
const parts = [];
|
|
192
|
+
if (Array.isArray(result.content)) {
|
|
193
|
+
for (const item of result.content) {
|
|
194
|
+
if (typeof item === "object" && item !== null && "text" in item) {
|
|
195
|
+
parts.push(String(item.text));
|
|
196
|
+
}
|
|
197
|
+
else if (typeof item === "string") {
|
|
198
|
+
parts.push(item);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return parts.join("\n") || "(no output)";
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* List resources from MCP servers.
|
|
206
|
+
*/
|
|
207
|
+
async listResources(serverName) {
|
|
208
|
+
const results = [];
|
|
209
|
+
const servers = serverName ? [serverName] : [...this.connections.keys()];
|
|
210
|
+
for (const name of servers) {
|
|
211
|
+
const conn = this.connections.get(name);
|
|
212
|
+
if (!conn)
|
|
213
|
+
continue;
|
|
214
|
+
try {
|
|
215
|
+
const res = await conn.client.listResources();
|
|
216
|
+
for (const r of res.resources) {
|
|
217
|
+
results.push({
|
|
218
|
+
uri: r.uri,
|
|
219
|
+
name: r.name ?? r.uri,
|
|
220
|
+
description: r.description,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
// Server may not support resources
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return results;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Read a resource from an MCP server.
|
|
232
|
+
*/
|
|
233
|
+
async readResource(serverName, uri) {
|
|
234
|
+
const conn = this.connections.get(serverName);
|
|
235
|
+
if (!conn) {
|
|
236
|
+
throw new Error(`MCP server "${serverName}" is not connected.`);
|
|
237
|
+
}
|
|
238
|
+
const result = await conn.client.readResource({ uri });
|
|
239
|
+
const parts = [];
|
|
240
|
+
if (Array.isArray(result.contents)) {
|
|
241
|
+
for (const item of result.contents) {
|
|
242
|
+
if (typeof item === "object" && item !== null && "text" in item) {
|
|
243
|
+
parts.push(String(item.text));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return parts.join("\n") || "(no content)";
|
|
248
|
+
}
|
|
249
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permission system — classifier + approval backend.
|
|
3
|
+
*/
|
|
4
|
+
import type { PermissionDecision, PermissionMode, PermissionRule, ApprovalRequest, ApprovalResult } from "../types.js";
|
|
5
|
+
import { logger as rootPermLogger } from "../logging/logger.js";
|
|
6
|
+
export interface ApprovalBackend {
|
|
7
|
+
requestApproval(request: ApprovalRequest): Promise<ApprovalResult>;
|
|
8
|
+
}
|
|
9
|
+
export declare class HeadlessApprovalBackend implements ApprovalBackend {
|
|
10
|
+
private readonly mode;
|
|
11
|
+
constructor(mode: "approve-all" | "deny-all" | "approve-read-only");
|
|
12
|
+
requestApproval(req: ApprovalRequest): Promise<ApprovalResult>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Auto approval backend — uses fast-path heuristics to auto-approve safe operations.
|
|
16
|
+
* Falls back to a delegate backend for uncertain cases.
|
|
17
|
+
*/
|
|
18
|
+
export declare class AutoApprovalBackend implements ApprovalBackend {
|
|
19
|
+
private readonly delegate?;
|
|
20
|
+
constructor(delegate?: ApprovalBackend | undefined);
|
|
21
|
+
requestApproval(req: ApprovalRequest): Promise<ApprovalResult>;
|
|
22
|
+
private isSafeOperation;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Interactive approval backend — prompts the user via a callback.
|
|
26
|
+
*
|
|
27
|
+
* Stores "always allow" decisions at two scopes:
|
|
28
|
+
* - session: in-memory map, lost when the process exits
|
|
29
|
+
* - project: persisted to <cwd>/.code-shell/settings.local.json so the
|
|
30
|
+
* same project remembers the rule across REPL restarts
|
|
31
|
+
*
|
|
32
|
+
* The classifier reads project rules from settings on session start (see
|
|
33
|
+
* Engine.buildPermissionConfig), so persisted rules become "auto-allow"
|
|
34
|
+
* the next time the user opens the project.
|
|
35
|
+
*/
|
|
36
|
+
export declare class InteractiveApprovalBackend implements ApprovalBackend {
|
|
37
|
+
private sessionRules;
|
|
38
|
+
private promptFn;
|
|
39
|
+
private cwd;
|
|
40
|
+
private savedProjectRules;
|
|
41
|
+
private onProjectRules;
|
|
42
|
+
setPromptFn(fn: (request: ApprovalRequest) => Promise<ApprovalResult>): void;
|
|
43
|
+
/**
|
|
44
|
+
* Has someone installed a real prompt callback? Engine consults this
|
|
45
|
+
* to decide whether to use the interactive backend (= talk to a UI)
|
|
46
|
+
* or fall back to HeadlessApprovalBackend (= deny-all). Without it,
|
|
47
|
+
* the agent-server-stdio entry — which wires setInteractiveApprovalFn
|
|
48
|
+
* during server boot — would still fall through to deny-all because
|
|
49
|
+
* the engine couldn't tell the difference. */
|
|
50
|
+
hasPromptFn(): boolean;
|
|
51
|
+
/** Inject the project root so persistence writes to the right settings file. */
|
|
52
|
+
setCwd(cwd: string): void;
|
|
53
|
+
/**
|
|
54
|
+
* Inject a callback fired when the user approves "for this project". The
|
|
55
|
+
* callback receives the *full* accumulated list of project rules saved in
|
|
56
|
+
* this session, so the classifier can be reconfigured without losing
|
|
57
|
+
* earlier approvals.
|
|
58
|
+
*/
|
|
59
|
+
setOnProjectRules(fn: (rules: PermissionRule[]) => void): void;
|
|
60
|
+
requestApproval(req: ApprovalRequest): Promise<ApprovalResult>;
|
|
61
|
+
}
|
|
62
|
+
export declare function getInteractiveApprovalBackend(): InteractiveApprovalBackend;
|
|
63
|
+
export declare function setInteractiveApprovalFn(fn: (request: ApprovalRequest) => Promise<ApprovalResult>): void;
|
|
64
|
+
type BashSafetyLevel = "safe-read" | "safe-write" | "unsafe" | "dangerous";
|
|
65
|
+
export declare function classifyBashCommand(command: string): BashSafetyLevel;
|
|
66
|
+
export declare class DenialTracker {
|
|
67
|
+
private denials;
|
|
68
|
+
private readonly periodMs;
|
|
69
|
+
private readonly maxDenials;
|
|
70
|
+
constructor(opts?: {
|
|
71
|
+
periodMs?: number;
|
|
72
|
+
maxDenials?: number;
|
|
73
|
+
});
|
|
74
|
+
record(toolName: string): void;
|
|
75
|
+
recordSuccess(toolName: string): void;
|
|
76
|
+
shouldWarn(toolName: string): boolean;
|
|
77
|
+
getWarningMessage(toolName: string): string;
|
|
78
|
+
clear(): void;
|
|
79
|
+
}
|
|
80
|
+
export declare const ACCEPT_EDITS_ALLOWLIST: ReadonlySet<string>;
|
|
81
|
+
export declare class PermissionClassifier {
|
|
82
|
+
private rules;
|
|
83
|
+
private defaultMode;
|
|
84
|
+
private approvalBackend;
|
|
85
|
+
private denialTracker;
|
|
86
|
+
/**
|
|
87
|
+
* Turn-scoped logger so permission events (ask/decision/auto-deny) are
|
|
88
|
+
* tagged with the current turn/turnId. Falls back to the root logger so
|
|
89
|
+
* tests and ad-hoc usages still write log lines.
|
|
90
|
+
*/
|
|
91
|
+
private log;
|
|
92
|
+
constructor(rules: PermissionRule[], defaultMode?: PermissionMode, approvalBackend?: ApprovalBackend);
|
|
93
|
+
setLogger(log: typeof rootPermLogger): void;
|
|
94
|
+
/** Replace mode + backend in place so live tool execution sees the change. */
|
|
95
|
+
reconfigure(mode: PermissionMode, approvalBackend: ApprovalBackend, rules?: PermissionRule[]): void;
|
|
96
|
+
getMode(): PermissionMode;
|
|
97
|
+
classify(toolName: string, args: Record<string, unknown>): PermissionDecision;
|
|
98
|
+
handleAsk(toolName: string, args: Record<string, unknown>, reason?: string): Promise<boolean>;
|
|
99
|
+
/** Get denial warning message if the model keeps getting denied. */
|
|
100
|
+
getDenialWarning(toolName: string): string | undefined;
|
|
101
|
+
private matchesRule;
|
|
102
|
+
private isDangerousCommand;
|
|
103
|
+
private assessRisk;
|
|
104
|
+
/**
|
|
105
|
+
* Short, human-friendly subtitle. The UI shows this under the tool title;
|
|
106
|
+
* full args (command bodies, diffs, etc.) come from the args field, so this
|
|
107
|
+
* stays compact — no truncation here, just a label.
|
|
108
|
+
*/
|
|
109
|
+
private describeToolCall;
|
|
110
|
+
}
|
|
111
|
+
export {};
|