@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
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
*/
|
|
33
33
|
import { spawn } from "node:child_process";
|
|
34
34
|
import { MAX_HOOK_OUTPUT_BYTES } from "../hooks/hook-output.js";
|
|
35
|
+
import { killChildTree } from "../runtime/spawn-common.js";
|
|
35
36
|
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
36
37
|
/**
|
|
37
38
|
* Extract the user-facing context string from a CC plugin's stdout JSON.
|
|
@@ -116,20 +117,8 @@ export async function runPluginCommandHook(spec, ctx) {
|
|
|
116
117
|
const timer = setTimeout(() => {
|
|
117
118
|
// eslint-disable-next-line no-console
|
|
118
119
|
console.warn(`[plugin-hook] ${spec.pluginKey} ${ctx.eventName} timed out after ${timeoutMs}ms`);
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
setTimeout(() => {
|
|
122
|
-
try {
|
|
123
|
-
child.kill("SIGKILL");
|
|
124
|
-
}
|
|
125
|
-
catch {
|
|
126
|
-
/* already exited */
|
|
127
|
-
}
|
|
128
|
-
}, 1000);
|
|
129
|
-
}
|
|
130
|
-
catch {
|
|
131
|
-
/* already exited */
|
|
132
|
-
}
|
|
120
|
+
// win32: taskkill /T reaps the tree; POSIX: SIGTERM → grace → SIGKILL.
|
|
121
|
+
killChildTree(child, 1000);
|
|
133
122
|
settle({});
|
|
134
123
|
}, timeoutMs);
|
|
135
124
|
child.stdout?.on("data", (chunk) => {
|
|
@@ -139,10 +128,7 @@ export async function runPluginCommandHook(spec, ctx) {
|
|
|
139
128
|
stdoutCapped = true;
|
|
140
129
|
// eslint-disable-next-line no-console
|
|
141
130
|
console.warn(`[plugin-hook] ${spec.pluginKey} ${ctx.eventName} stdout exceeded ${MAX_HOOK_OUTPUT_BYTES} bytes — killing`);
|
|
142
|
-
|
|
143
|
-
child.kill("SIGTERM");
|
|
144
|
-
}
|
|
145
|
-
catch { /* already exited */ }
|
|
131
|
+
killChildTree(child, 1000);
|
|
146
132
|
}
|
|
147
133
|
return;
|
|
148
134
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin content inventory (插件详情页) — enumerate everything one installed
|
|
3
|
+
* plugin contributes: skills, commands, agents, hooks, MCP servers. The
|
|
4
|
+
* plugins list only showed "N skills", so users couldn't see what a plugin
|
|
5
|
+
* actually installs (feedback#15). Read-only; reuses the same parsers the
|
|
6
|
+
* loaders use so the inventory can't drift from what actually loads.
|
|
7
|
+
*/
|
|
8
|
+
import { type PluginHookEntry } from "./loadPluginHooks.js";
|
|
9
|
+
export interface PluginContentInventory {
|
|
10
|
+
/** skills/<name>/SKILL.md — name + frontmatter description when present. */
|
|
11
|
+
skills: {
|
|
12
|
+
name: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
}[];
|
|
15
|
+
/** commands/<name>.md */
|
|
16
|
+
commands: string[];
|
|
17
|
+
/** agents/<name>.md */
|
|
18
|
+
agents: string[];
|
|
19
|
+
/** hooks/hooks.json entries (event + command), owner-filtered. */
|
|
20
|
+
hooks: PluginHookEntry[];
|
|
21
|
+
/** MCP server names as merged (keyed `<plugin>:<server>` — bare name here). */
|
|
22
|
+
mcpServers: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Inventory one plugin's contributions. `pluginName` is the bare name (no
|
|
26
|
+
* @marketplace); `installPath` its install dir. Hooks/MCP go through the same
|
|
27
|
+
* scanners the runtime loaders use (filtered to this plugin) so naming —
|
|
28
|
+
* e.g. MCP's `<plugin>:<server>` record keys — matches what users see live.
|
|
29
|
+
*/
|
|
30
|
+
export declare function describePluginContent(pluginName: string, installPath: string): PluginContentInventory;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin content inventory (插件详情页) — enumerate everything one installed
|
|
3
|
+
* plugin contributes: skills, commands, agents, hooks, MCP servers. The
|
|
4
|
+
* plugins list only showed "N skills", so users couldn't see what a plugin
|
|
5
|
+
* actually installs (feedback#15). Read-only; reuses the same parsers the
|
|
6
|
+
* loaders use so the inventory can't drift from what actually loads.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { parseFrontmatter } from "../skills/frontmatter.js";
|
|
11
|
+
import { listPluginHooks } from "./loadPluginHooks.js";
|
|
12
|
+
import { mergePluginMcpServers } from "./installer/loadPluginMcp.js";
|
|
13
|
+
function listMdNames(dir) {
|
|
14
|
+
if (!existsSync(dir))
|
|
15
|
+
return [];
|
|
16
|
+
try {
|
|
17
|
+
return readdirSync(dir)
|
|
18
|
+
.filter((f) => f.endsWith(".md"))
|
|
19
|
+
.map((f) => f.replace(/\.md$/, ""))
|
|
20
|
+
.sort();
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function listSkills(installPath) {
|
|
27
|
+
const dir = join(installPath, "skills");
|
|
28
|
+
if (!existsSync(dir))
|
|
29
|
+
return [];
|
|
30
|
+
const out = [];
|
|
31
|
+
try {
|
|
32
|
+
for (const entry of readdirSync(dir).sort()) {
|
|
33
|
+
const skillMd = join(dir, entry, "SKILL.md");
|
|
34
|
+
try {
|
|
35
|
+
if (!statSync(join(dir, entry)).isDirectory() || !existsSync(skillMd))
|
|
36
|
+
continue;
|
|
37
|
+
const { frontmatter } = parseFrontmatter(readFileSync(skillMd, "utf-8"));
|
|
38
|
+
const desc = typeof frontmatter.description === "string" ? frontmatter.description : undefined;
|
|
39
|
+
out.push({ name: entry, description: desc });
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// unreadable skill dir — skip, same as the loader would
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Inventory one plugin's contributions. `pluginName` is the bare name (no
|
|
53
|
+
* @marketplace); `installPath` its install dir. Hooks/MCP go through the same
|
|
54
|
+
* scanners the runtime loaders use (filtered to this plugin) so naming —
|
|
55
|
+
* e.g. MCP's `<plugin>:<server>` record keys — matches what users see live.
|
|
56
|
+
*/
|
|
57
|
+
export function describePluginContent(pluginName, installPath) {
|
|
58
|
+
const mcpPrefix = `${pluginName}:`;
|
|
59
|
+
let mcpServers = [];
|
|
60
|
+
try {
|
|
61
|
+
mcpServers = Object.keys(mergePluginMcpServers({}))
|
|
62
|
+
.filter((k) => k.startsWith(mcpPrefix))
|
|
63
|
+
.map((k) => k.slice(mcpPrefix.length))
|
|
64
|
+
.sort();
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
mcpServers = [];
|
|
68
|
+
}
|
|
69
|
+
let hooks = [];
|
|
70
|
+
try {
|
|
71
|
+
hooks = listPluginHooks().filter((h) => h.plugin === pluginName);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
hooks = [];
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
skills: listSkills(installPath),
|
|
78
|
+
commands: listMdNames(join(installPath, "commands")),
|
|
79
|
+
agents: listMdNames(join(installPath, "agents")),
|
|
80
|
+
hooks,
|
|
81
|
+
mcpServers,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -5,6 +5,19 @@
|
|
|
5
5
|
* sparse-checkout, no npm/pip.
|
|
6
6
|
*/
|
|
7
7
|
import type { PluginInstallEntry } from "./types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Compose the on-disk cache directory for a plugin version. Every path segment
|
|
10
|
+
* (marketplace / plugin / version) can originate from an attacker-controlled
|
|
11
|
+
* marketplace manifest, so each must be validated as a single safe path
|
|
12
|
+
* segment before it enters `join`. Without this a manifest entry named `..`
|
|
13
|
+
* (or containing a separator) would let the materialized plugin tree be
|
|
14
|
+
* written outside the plugin cache root — a supply-chain path traversal.
|
|
15
|
+
*
|
|
16
|
+
* Reuses `assertSafePluginName` (rejects empty / "." / ".." / separators /
|
|
17
|
+
* NUL). Exported so the segment-validation contract can be unit-tested
|
|
18
|
+
* directly.
|
|
19
|
+
*/
|
|
20
|
+
export declare function pluginCacheDir(marketplace: string, plugin: string, version: string): string;
|
|
8
21
|
/**
|
|
9
22
|
* Resolve a candidate `installPath` to a realpath and verify it lives strictly
|
|
10
23
|
* underneath the plugin cache root. Returns the resolved path on success, or
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* source types (path / git / github / git-subdir), no dependencies, no
|
|
5
5
|
* sparse-checkout, no npm/pip.
|
|
6
6
|
*/
|
|
7
|
-
import { existsSync, realpathSync, rmSync } from "node:fs";
|
|
7
|
+
import { existsSync, realpathSync, rmSync, rmdirSync } from "node:fs";
|
|
8
8
|
import { cp, mkdir, mkdtemp, rm } from "node:fs/promises";
|
|
9
9
|
import { dirname, isAbsolute, join, resolve, sep } from "node:path";
|
|
10
10
|
import { homedir, tmpdir } from "node:os";
|
|
@@ -13,13 +13,30 @@ import { loadMarketplace } from "./marketplaceManager.js";
|
|
|
13
13
|
import { readKnownMarketplaces } from "./knownMarketplaces.js";
|
|
14
14
|
import { appendInstallEntry, pluginInstallKey, readInstalledPlugins, removeInstallEntries, } from "./installedPlugins.js";
|
|
15
15
|
import { rewritePluginVars } from "./varRewrite.js";
|
|
16
|
+
import { assertSafePluginName } from "./installer/paths.js";
|
|
17
|
+
import { pruneDisabledSettingsForPlugin } from "./installer/pruneDisabled.js";
|
|
16
18
|
function userHome() {
|
|
17
19
|
return process.env.HOME ?? homedir();
|
|
18
20
|
}
|
|
19
21
|
function pluginCacheRoot() {
|
|
20
22
|
return join(userHome(), ".code-shell", "plugins", "cache");
|
|
21
23
|
}
|
|
22
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Compose the on-disk cache directory for a plugin version. Every path segment
|
|
26
|
+
* (marketplace / plugin / version) can originate from an attacker-controlled
|
|
27
|
+
* marketplace manifest, so each must be validated as a single safe path
|
|
28
|
+
* segment before it enters `join`. Without this a manifest entry named `..`
|
|
29
|
+
* (or containing a separator) would let the materialized plugin tree be
|
|
30
|
+
* written outside the plugin cache root — a supply-chain path traversal.
|
|
31
|
+
*
|
|
32
|
+
* Reuses `assertSafePluginName` (rejects empty / "." / ".." / separators /
|
|
33
|
+
* NUL). Exported so the segment-validation contract can be unit-tested
|
|
34
|
+
* directly.
|
|
35
|
+
*/
|
|
36
|
+
export function pluginCacheDir(marketplace, plugin, version) {
|
|
37
|
+
assertSafePluginName(marketplace);
|
|
38
|
+
assertSafePluginName(plugin);
|
|
39
|
+
assertSafePluginName(version);
|
|
23
40
|
return join(pluginCacheRoot(), marketplace, plugin, version);
|
|
24
41
|
}
|
|
25
42
|
/**
|
|
@@ -80,7 +97,7 @@ async function materializeGit(url, ref, cacheTarget) {
|
|
|
80
97
|
await mkdir(dirname(cacheTarget), { recursive: true });
|
|
81
98
|
if (existsSync(cacheTarget))
|
|
82
99
|
await rm(cacheTarget, { recursive: true, force: true });
|
|
83
|
-
const clone = await gitClone(url, cacheTarget, ref ? { ref } :
|
|
100
|
+
const clone = await gitClone(url, cacheTarget, { full: true, ...(ref ? { ref } : {}) });
|
|
84
101
|
if (!clone.ok)
|
|
85
102
|
return { ok: false, error: clone.error };
|
|
86
103
|
const head = await gitRevParseHead(cacheTarget);
|
|
@@ -92,7 +109,7 @@ async function materializeGitSubdir(url, subPath, ref, cacheTarget) {
|
|
|
92
109
|
// Clone to a tempdir, then copy the subdir over.
|
|
93
110
|
const tmp = await mkdtemp(join(tmpdir(), "plugin-clone-"));
|
|
94
111
|
try {
|
|
95
|
-
const clone = await gitClone(url, tmp + "/repo", ref ? { ref } :
|
|
112
|
+
const clone = await gitClone(url, tmp + "/repo", { full: true, ...(ref ? { ref } : {}) });
|
|
96
113
|
if (!clone.ok)
|
|
97
114
|
return { ok: false, error: clone.error };
|
|
98
115
|
const head = await gitRevParseHead(tmp + "/repo");
|
|
@@ -152,7 +169,11 @@ async function materialize(source, marketplaceInstallLocation, marketplace, plug
|
|
|
152
169
|
// present, so we ignore the result and let materializePath report a real
|
|
153
170
|
// missing-path error if the subdir truly isn't there.
|
|
154
171
|
if (!isAbsolute(source)) {
|
|
155
|
-
|
|
172
|
+
// Strip a leading "./" — in non-cone sparse mode the literal "./" prefix
|
|
173
|
+
// doesn't match repo paths (which are stored without it), so the
|
|
174
|
+
// expand would silently no-op and the tree would stay un-materialized.
|
|
175
|
+
const sparseRel = source.replace(/^\.\//, "");
|
|
176
|
+
await gitSparseCheckoutAdd(marketplaceInstallLocation, sparseRel);
|
|
156
177
|
}
|
|
157
178
|
const r = await materializePath(marketplaceInstallLocation, source, placeholder);
|
|
158
179
|
if (!r.ok)
|
|
@@ -244,7 +265,18 @@ export async function installPlugin(pluginName, marketplaceName) {
|
|
|
244
265
|
if (!entry) {
|
|
245
266
|
return { ok: false, error: `plugin "${pluginName}" not found in marketplace "${marketplaceName}".` };
|
|
246
267
|
}
|
|
247
|
-
|
|
268
|
+
// materialize() validates every cache path segment (marketplace / plugin /
|
|
269
|
+
// version) and throws a PluginInstallError on an unsafe one. Convert that to
|
|
270
|
+
// a clean failure result — every caller (bootstrap / marketplace-service /
|
|
271
|
+
// tui handler) consumes { ok, error } and must not be crashed by a hostile
|
|
272
|
+
// marketplace manifest.
|
|
273
|
+
let mat;
|
|
274
|
+
try {
|
|
275
|
+
mat = await materialize(entry.source, km.installLocation, marketplaceName, pluginName);
|
|
276
|
+
}
|
|
277
|
+
catch (e) {
|
|
278
|
+
return { ok: false, error: e.message };
|
|
279
|
+
}
|
|
248
280
|
if (!mat.ok)
|
|
249
281
|
return mat;
|
|
250
282
|
// Rewrite ${CLAUDE_PLUGIN_ROOT} → ${CODESHELL_PLUGIN_ROOT} across every
|
|
@@ -304,14 +336,16 @@ export function uninstallPlugin(pluginName, marketplaceName) {
|
|
|
304
336
|
const pluginParent = join(pluginCacheRoot(), marketplaceName, pluginName);
|
|
305
337
|
try {
|
|
306
338
|
// rmdir succeeds only when empty; ignore failures.
|
|
307
|
-
|
|
308
|
-
fs.rmdirSync(pluginParent);
|
|
339
|
+
rmdirSync(pluginParent);
|
|
309
340
|
}
|
|
310
341
|
catch {
|
|
311
342
|
// not empty or doesn't exist — fine
|
|
312
343
|
}
|
|
313
344
|
}
|
|
314
345
|
const removedFromManifest = removeInstallEntries(key);
|
|
346
|
+
// Clear orphaned disable flags (disabledSkills "name:skill" /
|
|
347
|
+
// disabledPlugins "name") so a removed plugin leaves no dangling entries.
|
|
348
|
+
pruneDisabledSettingsForPlugin(pluginName);
|
|
315
349
|
return { ok: removedFromManifest || removedFromDisk, removedFromManifest, removedFromDisk };
|
|
316
350
|
}
|
|
317
351
|
export function listInstalled() {
|
package/dist/plugins/schemas.js
CHANGED
|
@@ -123,6 +123,7 @@ export function validatePluginEntry(raw, index) {
|
|
|
123
123
|
category: typeof raw.category === "string" ? raw.category : undefined,
|
|
124
124
|
source: source.value,
|
|
125
125
|
homepage: typeof raw.homepage === "string" ? raw.homepage : undefined,
|
|
126
|
+
version: typeof raw.version === "string" ? raw.version : undefined,
|
|
126
127
|
},
|
|
127
128
|
};
|
|
128
129
|
}
|
package/dist/plugins/types.d.ts
CHANGED
|
@@ -48,6 +48,12 @@ export interface PluginMarketplaceEntry {
|
|
|
48
48
|
category?: string;
|
|
49
49
|
source: PluginEntrySource;
|
|
50
50
|
homepage?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Declared version from the marketplace manifest, when the author wrote
|
|
53
|
+
* one. CC's marketplace.json has no version convention, so this is often
|
|
54
|
+
* absent — the UI hides it rather than showing a placeholder.
|
|
55
|
+
*/
|
|
56
|
+
version?: string;
|
|
51
57
|
}
|
|
52
58
|
export interface PluginMarketplace {
|
|
53
59
|
name: string;
|
package/dist/preset/index.d.ts
CHANGED
|
@@ -51,8 +51,14 @@ export declare function listPresetNames(): string[];
|
|
|
51
51
|
export declare function resolveAgentPreset(name?: string): AgentPreset;
|
|
52
52
|
/**
|
|
53
53
|
* Build the full system prompt for a preset by loading and joining its sections.
|
|
54
|
+
*
|
|
55
|
+
* `activeToolNames` (the turn's effective tool set, post capability-override
|
|
56
|
+
* filtering) gates tool-coupled sections: the "browser" section is dropped when
|
|
57
|
+
* no browser tool is active, so the browser capability is a single on/off unit
|
|
58
|
+
* (tools + usage instructions disappear together). Omit `activeToolNames` to
|
|
59
|
+
* include all sections (e.g. when assembling a generic/preview prompt).
|
|
54
60
|
*/
|
|
55
|
-
export declare function buildPresetSystemPrompt(preset: AgentPreset): string;
|
|
61
|
+
export declare function buildPresetSystemPrompt(preset: AgentPreset, activeToolNames?: readonly string[]): string;
|
|
56
62
|
export declare function resolveBuiltinToolNames(options?: {
|
|
57
63
|
preset?: string;
|
|
58
64
|
enabledBuiltinTools?: string[];
|
package/dist/preset/index.js
CHANGED
|
@@ -18,9 +18,25 @@ const GENERAL_BUILTIN_TOOLS = [
|
|
|
18
18
|
"Glob",
|
|
19
19
|
"Grep",
|
|
20
20
|
"Bash",
|
|
21
|
+
// Bash(run_in_background=true) companions — without these in the preset
|
|
22
|
+
// whitelist, the registry skips them (registerBuiltins filters BUILTIN_TOOLS
|
|
23
|
+
// by the selected set), so a model that correctly calls BashOutput after
|
|
24
|
+
// launching a background shell hits "Tool not found" and the turn dies.
|
|
25
|
+
"BashOutput",
|
|
26
|
+
"KillShell",
|
|
27
|
+
"ListShells",
|
|
28
|
+
// Browser automation (drive the in-app webview) — 3 semantic tools. Same
|
|
29
|
+
// whitelist requirement as the BashOutput trio above: registerBuiltins filters
|
|
30
|
+
// BUILTIN_TOOLS by the preset set, so without these the model calling
|
|
31
|
+
// browser_observe/etc. hits "Tool not found". They self-degrade to a clear
|
|
32
|
+
// error when no browser panel is wired (headless), so listing is safe.
|
|
33
|
+
"browser_observe",
|
|
34
|
+
"browser_act",
|
|
35
|
+
"browser_navigate",
|
|
21
36
|
"WebSearch",
|
|
22
37
|
"WebFetch",
|
|
23
38
|
"GenerateImage",
|
|
39
|
+
"GenerateVideo",
|
|
24
40
|
"AskUserQuestion",
|
|
25
41
|
"Agent",
|
|
26
42
|
// AgentStatus removed: background agents now write to ~/.code-shell/agents/
|
|
@@ -36,11 +52,22 @@ const GENERAL_BUILTIN_TOOLS = [
|
|
|
36
52
|
"CronCreate",
|
|
37
53
|
"CronDelete",
|
|
38
54
|
"CronList",
|
|
55
|
+
// cc-orchestrator:驱动外部 claude CLI 跑一轮。同 BashOutput/UseCredential/
|
|
56
|
+
// EditModelCatalog 的 whitelist 要求:已在 BUILTIN_TOOLS 注册,但 registerBuiltins
|
|
57
|
+
// 按 preset 集过滤 → 名单里没有它,agent 就没有「指挥 Claude Code」的工具,只能幻觉
|
|
58
|
+
// RemoteTrigger / 兜底 Bash `claude -p`(用户实测「为什么驱动 cc 没作为工具」)。
|
|
59
|
+
// 定时/循环驱动统一走 CronCreate(到点跑一轮引擎,prompt 里调 DriveAgent);
|
|
60
|
+
// 无人值守审批由 DriveAgent 自身 bypass 解决,不需要定时层专门的 CC 调度工具。
|
|
61
|
+
// DriveAgent 是通用驱动(cli: claude|codex);DriveClaudeCode 保留为 cli:claude 的
|
|
62
|
+
// 别名(老 prompt/记忆兼容)。两个都要在白名单里,否则 registerBuiltins 滤掉。
|
|
63
|
+
"DriveAgent",
|
|
64
|
+
"DriveClaudeCode",
|
|
65
|
+
// 编排时读 CC/Codex 剩余额度做规划(开几个/等重置/换 provider)。
|
|
66
|
+
"CheckQuota",
|
|
39
67
|
"Skill",
|
|
40
68
|
"MCPTool",
|
|
41
69
|
"ListMcpResources",
|
|
42
70
|
"ReadMcpResource",
|
|
43
|
-
"RemoteTrigger",
|
|
44
71
|
"REPL",
|
|
45
72
|
"PowerShell",
|
|
46
73
|
// Persistent cross-session memory. Including these in the default preset is
|
|
@@ -54,6 +81,28 @@ const GENERAL_BUILTIN_TOOLS = [
|
|
|
54
81
|
"MemoryRead",
|
|
55
82
|
"MemorySave",
|
|
56
83
|
"MemoryDelete",
|
|
84
|
+
// AI 取用已存凭证(cookie/token/link)给 yt-dlp/curl 等。必须在 preset 白名单里
|
|
85
|
+
// 否则 registerBuiltins 滤掉它 → 即使存了凭证、注册了工具,AI 列表里也没有
|
|
86
|
+
// UseCredential(用户实测「找不到这个工具」的真因)。它带 isUseCredentialAvailable
|
|
87
|
+
// guard:cwd 凭证库为空时仍自动隐藏,所以无条件列入是安全的(空库不会冒出来)。
|
|
88
|
+
"UseCredential",
|
|
89
|
+
// 同理:把 cookie 凭证注入内置浏览器(恢复登录态后用 browser_* 工具)。带
|
|
90
|
+
// isInjectCredentialAvailable guard(无 cookie 凭证时自动隐藏),无条件列入安全。
|
|
91
|
+
"InjectCredential",
|
|
92
|
+
// AI 增/改模型 catalog(写 ~/.code-shell/model-catalog.user.json)。同 BashOutput/
|
|
93
|
+
// UseCredential 一样的 whitelist 要求:registerBuiltins 按 preset 集过滤 BUILTIN_TOOLS,
|
|
94
|
+
// 名单里没有它 → 即使工具已注册,AI 列表里也没有 → 用户实测「找不到这个工具」。
|
|
95
|
+
// permissionDefault: "ask",列入只是让 AI 看得到,调用仍走审批,无条件列入安全。
|
|
96
|
+
"EditModelCatalog",
|
|
97
|
+
// Goal-mode control tools. Same whitelist requirement as the rest:
|
|
98
|
+
// registerBuiltins filters BUILTIN_TOOLS by the preset set, so a goal tool
|
|
99
|
+
// absent here is registered-but-invisible — the model never sees it and can
|
|
100
|
+
// neither self-declare completion (complete_goal) nor honor a user's request
|
|
101
|
+
// to abandon the goal (cancel_goal), stranding a persistent goal that only a
|
|
102
|
+
// manual disk edit could clear. cancel_goal is the "strong intent" escape
|
|
103
|
+
// hatch (requires confirm+reason); the turn-loop enforces the guard.
|
|
104
|
+
"complete_goal",
|
|
105
|
+
"cancel_goal",
|
|
57
106
|
];
|
|
58
107
|
const TERMINAL_CODING_EXTRA_TOOLS = [
|
|
59
108
|
"EnterWorktree",
|
|
@@ -80,13 +129,31 @@ const GENERAL_PERMISSION_RULES = [
|
|
|
80
129
|
{ tool: "TodoWrite", decision: "allow" },
|
|
81
130
|
{ tool: "Sleep", decision: "allow" },
|
|
82
131
|
{ tool: "CronList", decision: "allow" },
|
|
132
|
+
{ tool: "CheckQuota", decision: "allow" },
|
|
83
133
|
{ tool: "Skill", decision: "allow" },
|
|
134
|
+
// ListMcpResources only enumerates resource names (and the executor filters
|
|
135
|
+
// the list to this session's enabled servers). ReadMcpResource pulls actual
|
|
136
|
+
// content and is intentionally NOT auto-allowed here — it falls back to its
|
|
137
|
+
// tool-level "ask" default so a default-mode session confirms the read.
|
|
84
138
|
{ tool: "ListMcpResources", decision: "allow" },
|
|
85
|
-
{ tool: "ReadMcpResource", decision: "allow" },
|
|
86
139
|
// Reading memory is always safe; writes (MemorySave/MemoryDelete) stay gated
|
|
87
140
|
// by the tools' own permissionDefault so the user confirms each change.
|
|
88
141
|
{ tool: "MemoryList", decision: "allow" },
|
|
89
142
|
{ tool: "MemoryRead", decision: "allow" },
|
|
143
|
+
// Browser automation (3 semantic tools). Rules are first-match-wins, ordered
|
|
144
|
+
// by specificity — so the action-gating rule for browser_act MUST come first:
|
|
145
|
+
// click/type/select mutate the page/form → "ask"; all other actions (hover/
|
|
146
|
+
// scroll/wait/press_key/list_tabs/switch_tab) fall through to browser_act's
|
|
147
|
+
// tool-level "allow". observe (read-only) and navigate auto-allow.
|
|
148
|
+
// (Main-side sensitive-action + domain-whitelist enforcement also applies.)
|
|
149
|
+
{
|
|
150
|
+
tool: "browser_act",
|
|
151
|
+
argsPattern: { action: "^(click|type|select)$" },
|
|
152
|
+
decision: "ask",
|
|
153
|
+
reason: "browser_act click/type/select mutate the page",
|
|
154
|
+
},
|
|
155
|
+
{ tool: "browser_observe", decision: "allow" },
|
|
156
|
+
{ tool: "browser_navigate", decision: "allow" },
|
|
90
157
|
];
|
|
91
158
|
// ─── Preset definitions ──────────────────────────────────────────
|
|
92
159
|
export const BUILTIN_AGENT_PRESETS = {
|
|
@@ -94,7 +161,7 @@ export const BUILTIN_AGENT_PRESETS = {
|
|
|
94
161
|
name: "general",
|
|
95
162
|
label: "General Orchestrator",
|
|
96
163
|
description: "Domain-agnostic orchestration for research, operations, automation, and long-running tasks.",
|
|
97
|
-
promptSections: ["base", "orchestration", "tone"],
|
|
164
|
+
promptSections: ["base", "orchestration", "browser", "tone"],
|
|
98
165
|
injectGitStatus: false,
|
|
99
166
|
builtinTools: [...GENERAL_BUILTIN_TOOLS],
|
|
100
167
|
defaultPermissionRules: GENERAL_PERMISSION_RULES,
|
|
@@ -103,7 +170,7 @@ export const BUILTIN_AGENT_PRESETS = {
|
|
|
103
170
|
name: "terminal-coding",
|
|
104
171
|
label: "Terminal Coding Assistant",
|
|
105
172
|
description: "General orchestration plus coding-focused guidance and code-navigation tools.",
|
|
106
|
-
promptSections: ["base", "orchestration", "coding", "tone"],
|
|
173
|
+
promptSections: ["base", "orchestration", "coding", "browser", "tone"],
|
|
107
174
|
injectGitStatus: true,
|
|
108
175
|
builtinTools: [...GENERAL_BUILTIN_TOOLS, ...TERMINAL_CODING_EXTRA_TOOLS],
|
|
109
176
|
defaultPermissionRules: [
|
|
@@ -156,11 +223,34 @@ export function resolveAgentPreset(name) {
|
|
|
156
223
|
const allowed = listPresetNames().join(", ");
|
|
157
224
|
throw new Error(`Unknown agent preset "${name}". Available presets: ${allowed}`);
|
|
158
225
|
}
|
|
226
|
+
/** Tool names that gate the "browser" prompt section — if NONE of these are in
|
|
227
|
+
* the active tool set (browser capability turned off), the section is dropped
|
|
228
|
+
* so the model isn't told how to use tools it can't see. Keep in sync with the
|
|
229
|
+
* browser tools registered in builtin/index.ts. */
|
|
230
|
+
const BROWSER_SECTION_TOOLS = ["browser_observe", "browser_act", "browser_navigate"];
|
|
231
|
+
/** Prompt sections whose inclusion is gated by an active tool being present. */
|
|
232
|
+
const TOOL_GATED_SECTIONS = {
|
|
233
|
+
browser: BROWSER_SECTION_TOOLS,
|
|
234
|
+
};
|
|
159
235
|
/**
|
|
160
236
|
* Build the full system prompt for a preset by loading and joining its sections.
|
|
237
|
+
*
|
|
238
|
+
* `activeToolNames` (the turn's effective tool set, post capability-override
|
|
239
|
+
* filtering) gates tool-coupled sections: the "browser" section is dropped when
|
|
240
|
+
* no browser tool is active, so the browser capability is a single on/off unit
|
|
241
|
+
* (tools + usage instructions disappear together). Omit `activeToolNames` to
|
|
242
|
+
* include all sections (e.g. when assembling a generic/preview prompt).
|
|
161
243
|
*/
|
|
162
|
-
export function buildPresetSystemPrompt(preset) {
|
|
163
|
-
|
|
244
|
+
export function buildPresetSystemPrompt(preset, activeToolNames) {
|
|
245
|
+
let sections = preset.promptSections;
|
|
246
|
+
if (activeToolNames) {
|
|
247
|
+
const active = new Set(activeToolNames);
|
|
248
|
+
sections = sections.filter((s) => {
|
|
249
|
+
const gate = TOOL_GATED_SECTIONS[s];
|
|
250
|
+
return !gate || gate.some((t) => active.has(t));
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
return loadSections(sections);
|
|
164
254
|
}
|
|
165
255
|
export function resolveBuiltinToolNames(options) {
|
|
166
256
|
const preset = resolveAgentPreset(options?.preset);
|
package/dist/product/types.d.ts
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
import type { PermissionRule, MCPServerConfig } from "../types.js";
|
|
22
22
|
import type { Evaluator } from "../run/Evaluator.js";
|
|
23
23
|
import type { RegisteredTool } from "../types.js";
|
|
24
|
-
import type { EngineHookConfig } from "../engine/
|
|
24
|
+
import type { EngineHookConfig } from "../engine/types.js";
|
|
25
25
|
export interface ProductPreset {
|
|
26
26
|
/** Unique name for this product's preset. */
|
|
27
27
|
name: string;
|
|
@@ -33,6 +33,20 @@ export interface ComposerOptions {
|
|
|
33
33
|
* `${pluginName}:` is filtered. See scanSkills(opts.disabledPlugins).
|
|
34
34
|
*/
|
|
35
35
|
disabledPlugins?: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Sub-agent skill allowlist (hard isolation). When set, only these skills
|
|
38
|
+
* appear in the LLM's skills listing — applied on top of the disabled
|
|
39
|
+
* lists. Undefined → the full (non-disabled) pool. Mirrors
|
|
40
|
+
* scanSkills(opts.skillAllowlist) so the prompt matches the Skill tool's
|
|
41
|
+
* dispatch gate.
|
|
42
|
+
*/
|
|
43
|
+
skillAllowlist?: string[];
|
|
44
|
+
/**
|
|
45
|
+
* settings.memories.maxAge (days). When > 0, memories whose file mtime is
|
|
46
|
+
* older than this are dropped from the injected memory context (TODO 8.1).
|
|
47
|
+
* Undefined/0 → inject all.
|
|
48
|
+
*/
|
|
49
|
+
memoriesMaxAgeDays?: number;
|
|
36
50
|
}
|
|
37
51
|
export declare class PromptComposer {
|
|
38
52
|
private readonly options;
|
|
@@ -52,6 +66,19 @@ export declare class PromptComposer {
|
|
|
52
66
|
* Only injects git status if the resolved preset opts in.
|
|
53
67
|
*/
|
|
54
68
|
buildSystemContext(): Promise<string>;
|
|
69
|
+
/**
|
|
70
|
+
* Per-turn dynamic context, delivered as a trailing <system-reminder> user
|
|
71
|
+
* message rather than baked into the system prefix.
|
|
72
|
+
*
|
|
73
|
+
* Holds the two things that change *within* a session — the skills listing
|
|
74
|
+
* (changes when a skill is installed/disabled) and the git-status snapshot
|
|
75
|
+
* (changes whenever the working tree changes). Keeping them out of the
|
|
76
|
+
* system prompt means installing a skill or editing a file no longer
|
|
77
|
+
* invalidates the cached system prefix. Placed at the END of the messages
|
|
78
|
+
* array (after the user task) so it sits past the conversation's cache
|
|
79
|
+
* breakpoint — a change here never re-bills the history prefix.
|
|
80
|
+
*/
|
|
81
|
+
buildDynamicContextMessage(): Promise<Message | null>;
|
|
55
82
|
invalidateCache(sectionName?: string): void;
|
|
56
83
|
private getSections;
|
|
57
84
|
private getInstructions;
|