@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
|
@@ -10,10 +10,34 @@ export declare class Transcript {
|
|
|
10
10
|
getFilePath(): string;
|
|
11
11
|
constructor(filePath: string);
|
|
12
12
|
append(type: TranscriptEventType, data: Record<string, unknown>): TranscriptEvent;
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Append a chat message to the transcript.
|
|
15
|
+
*
|
|
16
|
+
* `injected` marks a synthetic system-reminder turn (e.g. a background-job
|
|
17
|
+
* completion notification) that is submitted to the model as `role:"user"`
|
|
18
|
+
* but is NOT the user's own input. The disk reader uses this flag to skip
|
|
19
|
+
* rendering it as a user bubble on replay (matching the live UI, which never
|
|
20
|
+
* shows it as a bubble — only the assistant's reply). Real user input and
|
|
21
|
+
* step-gap steering messages are left unmarked so they render normally.
|
|
22
|
+
*/
|
|
23
|
+
appendMessage(role: string, content: string | ContentBlock[], opts?: {
|
|
24
|
+
injected?: boolean;
|
|
25
|
+
}): TranscriptEvent;
|
|
14
26
|
appendToolUse(toolName: string, toolCallId: string, args: Record<string, unknown>): TranscriptEvent;
|
|
15
27
|
appendToolResult(toolCallId: string, toolName: string, result?: string, error?: string): TranscriptEvent;
|
|
28
|
+
/** Anchor for a spawned sub-agent (see TranscriptEventType "subagent").
|
|
29
|
+
* Written at spawn time so replay can rebuild the sub-agent's card from
|
|
30
|
+
* sessions/<agentId>/ — agentId === the sub-agent's session id. */
|
|
31
|
+
appendSubagent(agentId: string, name: string | undefined, description: string): TranscriptEvent;
|
|
16
32
|
appendTurnBoundary(): TranscriptEvent;
|
|
33
|
+
/**
|
|
34
|
+
* Mark the in-flight turn as user-interrupted (Stop). Persisted so a resume
|
|
35
|
+
* rebuilds the renderer's "stopped" marker (foldTranscript) — otherwise the
|
|
36
|
+
* interrupted turn folds behind the process-card header on reload.
|
|
37
|
+
* Idempotent: a no-op if the last event is already a turn_stopped (the loop
|
|
38
|
+
* can hit more than one abort return for a single Stop).
|
|
39
|
+
*/
|
|
40
|
+
appendTurnStopped(): TranscriptEvent | undefined;
|
|
17
41
|
appendSummary(summary: string, compactedRange: {
|
|
18
42
|
fromTurn: number;
|
|
19
43
|
toTurn: number;
|
|
@@ -29,8 +29,22 @@ export class Transcript {
|
|
|
29
29
|
this.flush(event);
|
|
30
30
|
return event;
|
|
31
31
|
}
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Append a chat message to the transcript.
|
|
34
|
+
*
|
|
35
|
+
* `injected` marks a synthetic system-reminder turn (e.g. a background-job
|
|
36
|
+
* completion notification) that is submitted to the model as `role:"user"`
|
|
37
|
+
* but is NOT the user's own input. The disk reader uses this flag to skip
|
|
38
|
+
* rendering it as a user bubble on replay (matching the live UI, which never
|
|
39
|
+
* shows it as a bubble — only the assistant's reply). Real user input and
|
|
40
|
+
* step-gap steering messages are left unmarked so they render normally.
|
|
41
|
+
*/
|
|
42
|
+
appendMessage(role, content, opts) {
|
|
43
|
+
return this.append("message", {
|
|
44
|
+
role,
|
|
45
|
+
content,
|
|
46
|
+
...(opts?.injected ? { injected: true } : {}),
|
|
47
|
+
});
|
|
34
48
|
}
|
|
35
49
|
appendToolUse(toolName, toolCallId, args) {
|
|
36
50
|
return this.append("tool_use", { toolName, toolCallId, args });
|
|
@@ -38,10 +52,29 @@ export class Transcript {
|
|
|
38
52
|
appendToolResult(toolCallId, toolName, result, error) {
|
|
39
53
|
return this.append("tool_result", { toolCallId, toolName, result, error });
|
|
40
54
|
}
|
|
55
|
+
/** Anchor for a spawned sub-agent (see TranscriptEventType "subagent").
|
|
56
|
+
* Written at spawn time so replay can rebuild the sub-agent's card from
|
|
57
|
+
* sessions/<agentId>/ — agentId === the sub-agent's session id. */
|
|
58
|
+
appendSubagent(agentId, name, description) {
|
|
59
|
+
return this.append("subagent", { agentId, name, description });
|
|
60
|
+
}
|
|
41
61
|
appendTurnBoundary() {
|
|
42
62
|
this.currentTurn++;
|
|
43
63
|
return this.append("turn_boundary", { turnNumber: this.currentTurn });
|
|
44
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Mark the in-flight turn as user-interrupted (Stop). Persisted so a resume
|
|
67
|
+
* rebuilds the renderer's "stopped" marker (foldTranscript) — otherwise the
|
|
68
|
+
* interrupted turn folds behind the process-card header on reload.
|
|
69
|
+
* Idempotent: a no-op if the last event is already a turn_stopped (the loop
|
|
70
|
+
* can hit more than one abort return for a single Stop).
|
|
71
|
+
*/
|
|
72
|
+
appendTurnStopped() {
|
|
73
|
+
const last = this.events[this.events.length - 1];
|
|
74
|
+
if (last && last.type === "turn_stopped")
|
|
75
|
+
return undefined;
|
|
76
|
+
return this.append("turn_stopped", {});
|
|
77
|
+
}
|
|
45
78
|
appendSummary(summary, compactedRange) {
|
|
46
79
|
return this.append("summary", {
|
|
47
80
|
summary,
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure selection of the "most recent file modification" to undo, given a
|
|
3
|
+
* FileHistory snapshot list. Kept fs-free so the "what does /undo target"
|
|
4
|
+
* decision is unit-testable and shared between the TUI command and any future
|
|
5
|
+
* desktop entry point.
|
|
6
|
+
*
|
|
7
|
+
* A snapshot is the *pre-modification* backup of a file (see file-history.ts:
|
|
8
|
+
* saveSnapshot runs before Write/Edit/ApplyPatch). So the newest snapshot's
|
|
9
|
+
* backup is the content to restore for a single-step undo: it is the state the
|
|
10
|
+
* file had immediately before the last edit.
|
|
11
|
+
*/
|
|
12
|
+
import type { FileSnapshot, RedoRecord } from "./file-history.js";
|
|
13
|
+
/**
|
|
14
|
+
* The snapshot for the most recent modification. Returns the entry with the
|
|
15
|
+
* greatest `timestamp`; on a tie (same-millisecond snapshots of different
|
|
16
|
+
* files) the LAST such entry in array order wins — saveSnapshot pushes in
|
|
17
|
+
* chronological order, so the last pushed is the most recently recorded, which
|
|
18
|
+
* is the stable, predictable choice. Returns null for an empty history.
|
|
19
|
+
*/
|
|
20
|
+
export declare function latestUndoTarget(snapshots: FileSnapshot[]): FileSnapshot | null;
|
|
21
|
+
/**
|
|
22
|
+
* For "/undo all": each tracked file's EARLIEST snapshot — its content before
|
|
23
|
+
* the *first* AI edit this session. Restoring all of these reverts the whole
|
|
24
|
+
* session's file changes (vs. latestUndoTarget, which is the single last step).
|
|
25
|
+
*
|
|
26
|
+
* Returns one snapshot per file path, ordered by that file's first-edit time
|
|
27
|
+
* (oldest first) so a preview reads chronologically. On a same-millisecond tie
|
|
28
|
+
* for a given file, the FIRST array entry wins (earliest recorded).
|
|
29
|
+
*/
|
|
30
|
+
export declare function earliestSnapshotsPerFile(snapshots: FileSnapshot[]): FileSnapshot[];
|
|
31
|
+
/**
|
|
32
|
+
* For turn-level "/undo": the snapshots needed to revert just the MOST RECENT
|
|
33
|
+
* conversation turn (one user message = one turn, see SessionState.turnSeq).
|
|
34
|
+
*
|
|
35
|
+
* The latest turn = the greatest `turnSeq` present. A turn boundary is defined
|
|
36
|
+
* by turnSeq, NOT wall-clock — a clock skew must not move the boundary. Within
|
|
37
|
+
* that turn, each touched file is restored to its EARLIEST snapshot of the turn
|
|
38
|
+
* (its content before the *first* edit that turn), so re-editing a file twice
|
|
39
|
+
* in one turn still reverts to the pre-turn baseline — and edits from *earlier*
|
|
40
|
+
* turns are left intact (that's the whole point vs. earliestSnapshotsPerFile,
|
|
41
|
+
* which spans the whole session).
|
|
42
|
+
*
|
|
43
|
+
* Backward compatibility: snapshots written before this feature have no
|
|
44
|
+
* `turnSeq`. They share the `undefined` bucket. `undefined` sorts as the
|
|
45
|
+
* smallest "turn", so any real (tagged) turn supersedes the legacy bucket; a
|
|
46
|
+
* history that is ALL-legacy degrades to whole-session behaviour (each file's
|
|
47
|
+
* earliest) rather than throwing.
|
|
48
|
+
*
|
|
49
|
+
* Returns one snapshot per file, ordered by that file's first-edit time within
|
|
50
|
+
* the turn (oldest first) so a preview reads chronologically. Empty → [].
|
|
51
|
+
*/
|
|
52
|
+
export declare function latestTurnUndoTargets(snapshots: FileSnapshot[]): FileSnapshot[];
|
|
53
|
+
/**
|
|
54
|
+
* For "/redo": the RedoRecord[] of the MOST RECENT undone turn — the turn that
|
|
55
|
+
* `redoLatestTurn` should re-apply — but ONLY when that turn is still the latest
|
|
56
|
+
* undone state (i.e. nothing newer happened since the undo). Otherwise [].
|
|
57
|
+
*
|
|
58
|
+
* Rule: let R = the greatest turnSeq present in `redoRecords` (a RedoRecord
|
|
59
|
+
* exists only for a turn that was undone and not yet redone). R is redoable iff
|
|
60
|
+
* NO snapshot belongs to a strictly newer LIVE (non-undone) turn — a fresh edit
|
|
61
|
+
* after the undo supersedes the redo and invalidates it (spec: "新轮使 redo
|
|
62
|
+
* 失效"). Created-only turns have no pre-turn snapshot, so the RedoRecord itself
|
|
63
|
+
* is the sole evidence and is honoured as long as nothing newer superseded it.
|
|
64
|
+
*
|
|
65
|
+
* Empty `redoRecords` → []. fs-free so /redo's target decision is unit-testable.
|
|
66
|
+
*/
|
|
67
|
+
export declare function latestRedoTargets(redoRecords: RedoRecord[], snapshots: FileSnapshot[]): RedoRecord[];
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure selection of the "most recent file modification" to undo, given a
|
|
3
|
+
* FileHistory snapshot list. Kept fs-free so the "what does /undo target"
|
|
4
|
+
* decision is unit-testable and shared between the TUI command and any future
|
|
5
|
+
* desktop entry point.
|
|
6
|
+
*
|
|
7
|
+
* A snapshot is the *pre-modification* backup of a file (see file-history.ts:
|
|
8
|
+
* saveSnapshot runs before Write/Edit/ApplyPatch). So the newest snapshot's
|
|
9
|
+
* backup is the content to restore for a single-step undo: it is the state the
|
|
10
|
+
* file had immediately before the last edit.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* The snapshot for the most recent modification. Returns the entry with the
|
|
14
|
+
* greatest `timestamp`; on a tie (same-millisecond snapshots of different
|
|
15
|
+
* files) the LAST such entry in array order wins — saveSnapshot pushes in
|
|
16
|
+
* chronological order, so the last pushed is the most recently recorded, which
|
|
17
|
+
* is the stable, predictable choice. Returns null for an empty history.
|
|
18
|
+
*/
|
|
19
|
+
export function latestUndoTarget(snapshots) {
|
|
20
|
+
let best = null;
|
|
21
|
+
for (const s of snapshots) {
|
|
22
|
+
// `>=` so a later array entry with an equal timestamp supersedes an
|
|
23
|
+
// earlier one (last-pushed wins on a tie).
|
|
24
|
+
if (best === null || s.timestamp >= best.timestamp)
|
|
25
|
+
best = s;
|
|
26
|
+
}
|
|
27
|
+
return best;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* For "/undo all": each tracked file's EARLIEST snapshot — its content before
|
|
31
|
+
* the *first* AI edit this session. Restoring all of these reverts the whole
|
|
32
|
+
* session's file changes (vs. latestUndoTarget, which is the single last step).
|
|
33
|
+
*
|
|
34
|
+
* Returns one snapshot per file path, ordered by that file's first-edit time
|
|
35
|
+
* (oldest first) so a preview reads chronologically. On a same-millisecond tie
|
|
36
|
+
* for a given file, the FIRST array entry wins (earliest recorded).
|
|
37
|
+
*/
|
|
38
|
+
export function earliestSnapshotsPerFile(snapshots) {
|
|
39
|
+
const earliest = new Map();
|
|
40
|
+
for (const s of snapshots) {
|
|
41
|
+
// Undone snapshots belong to a reverted turn: their content is no longer on
|
|
42
|
+
// disk and they are not the session baseline, so skip them — otherwise an
|
|
43
|
+
// undone (earlier) snapshot could win the baseline and `/undo all` would
|
|
44
|
+
// restore stale content.
|
|
45
|
+
if (s.undone)
|
|
46
|
+
continue;
|
|
47
|
+
const cur = earliest.get(s.filePath);
|
|
48
|
+
// strict `<` so the first-seen entry wins on a tie (earliest recorded).
|
|
49
|
+
if (!cur || s.timestamp < cur.timestamp)
|
|
50
|
+
earliest.set(s.filePath, s);
|
|
51
|
+
}
|
|
52
|
+
return [...earliest.values()].sort((a, b) => a.timestamp - b.timestamp);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* For turn-level "/undo": the snapshots needed to revert just the MOST RECENT
|
|
56
|
+
* conversation turn (one user message = one turn, see SessionState.turnSeq).
|
|
57
|
+
*
|
|
58
|
+
* The latest turn = the greatest `turnSeq` present. A turn boundary is defined
|
|
59
|
+
* by turnSeq, NOT wall-clock — a clock skew must not move the boundary. Within
|
|
60
|
+
* that turn, each touched file is restored to its EARLIEST snapshot of the turn
|
|
61
|
+
* (its content before the *first* edit that turn), so re-editing a file twice
|
|
62
|
+
* in one turn still reverts to the pre-turn baseline — and edits from *earlier*
|
|
63
|
+
* turns are left intact (that's the whole point vs. earliestSnapshotsPerFile,
|
|
64
|
+
* which spans the whole session).
|
|
65
|
+
*
|
|
66
|
+
* Backward compatibility: snapshots written before this feature have no
|
|
67
|
+
* `turnSeq`. They share the `undefined` bucket. `undefined` sorts as the
|
|
68
|
+
* smallest "turn", so any real (tagged) turn supersedes the legacy bucket; a
|
|
69
|
+
* history that is ALL-legacy degrades to whole-session behaviour (each file's
|
|
70
|
+
* earliest) rather than throwing.
|
|
71
|
+
*
|
|
72
|
+
* Returns one snapshot per file, ordered by that file's first-edit time within
|
|
73
|
+
* the turn (oldest first) so a preview reads chronologically. Empty → [].
|
|
74
|
+
*/
|
|
75
|
+
export function latestTurnUndoTargets(snapshots) {
|
|
76
|
+
if (snapshots.length === 0)
|
|
77
|
+
return [];
|
|
78
|
+
// Find the latest turn, SKIPPING undone turns: once a turn is undone (marked,
|
|
79
|
+
// not deleted) its snapshots stay on disk for redo but must not be re-selected
|
|
80
|
+
// by undo — so the next /undo peels the prior live turn ("onion" behaviour).
|
|
81
|
+
// undefined (legacy) is treated as the smallest turn so it loses to any tagged
|
|
82
|
+
// turn; a key of `-Infinity` models that ordering.
|
|
83
|
+
const turnKey = (s) => s.turnSeq ?? -Infinity;
|
|
84
|
+
let maxTurn = -Infinity;
|
|
85
|
+
let found = false;
|
|
86
|
+
for (const s of snapshots) {
|
|
87
|
+
if (s.undone)
|
|
88
|
+
continue;
|
|
89
|
+
const k = turnKey(s);
|
|
90
|
+
if (k > maxTurn)
|
|
91
|
+
maxTurn = k;
|
|
92
|
+
found = true;
|
|
93
|
+
}
|
|
94
|
+
if (!found)
|
|
95
|
+
return [];
|
|
96
|
+
// Within the latest live turn, each file's earliest snapshot = its pre-turn
|
|
97
|
+
// state. Undone snapshots are skipped here too (defensive: they share neither
|
|
98
|
+
// the selected turn nor the baseline).
|
|
99
|
+
const earliest = new Map();
|
|
100
|
+
for (const s of snapshots) {
|
|
101
|
+
if (s.undone)
|
|
102
|
+
continue;
|
|
103
|
+
if (turnKey(s) !== maxTurn)
|
|
104
|
+
continue;
|
|
105
|
+
const cur = earliest.get(s.filePath);
|
|
106
|
+
// strict `<` so the first-seen entry wins on a same-ms tie (earliest).
|
|
107
|
+
if (!cur || s.timestamp < cur.timestamp)
|
|
108
|
+
earliest.set(s.filePath, s);
|
|
109
|
+
}
|
|
110
|
+
return [...earliest.values()].sort((a, b) => a.timestamp - b.timestamp);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* For "/redo": the RedoRecord[] of the MOST RECENT undone turn — the turn that
|
|
114
|
+
* `redoLatestTurn` should re-apply — but ONLY when that turn is still the latest
|
|
115
|
+
* undone state (i.e. nothing newer happened since the undo). Otherwise [].
|
|
116
|
+
*
|
|
117
|
+
* Rule: let R = the greatest turnSeq present in `redoRecords` (a RedoRecord
|
|
118
|
+
* exists only for a turn that was undone and not yet redone). R is redoable iff
|
|
119
|
+
* NO snapshot belongs to a strictly newer LIVE (non-undone) turn — a fresh edit
|
|
120
|
+
* after the undo supersedes the redo and invalidates it (spec: "新轮使 redo
|
|
121
|
+
* 失效"). Created-only turns have no pre-turn snapshot, so the RedoRecord itself
|
|
122
|
+
* is the sole evidence and is honoured as long as nothing newer superseded it.
|
|
123
|
+
*
|
|
124
|
+
* Empty `redoRecords` → []. fs-free so /redo's target decision is unit-testable.
|
|
125
|
+
*/
|
|
126
|
+
export function latestRedoTargets(redoRecords, snapshots) {
|
|
127
|
+
if (redoRecords.length === 0)
|
|
128
|
+
return [];
|
|
129
|
+
let maxRedoTurn = -Infinity;
|
|
130
|
+
for (const r of redoRecords) {
|
|
131
|
+
if (r.turnSeq > maxRedoTurn)
|
|
132
|
+
maxRedoTurn = r.turnSeq;
|
|
133
|
+
}
|
|
134
|
+
// If any LIVE snapshot belongs to a strictly newer turn, the redo turn is no
|
|
135
|
+
// longer the latest undone state → not redoable.
|
|
136
|
+
for (const s of snapshots) {
|
|
137
|
+
if (s.undone)
|
|
138
|
+
continue;
|
|
139
|
+
const k = s.turnSeq ?? -Infinity;
|
|
140
|
+
if (k > maxRedoTurn)
|
|
141
|
+
return [];
|
|
142
|
+
}
|
|
143
|
+
return redoRecords.filter((r) => r.turnSeq === maxRedoTurn);
|
|
144
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ValidatedSettings } from "./schema.js";
|
|
2
|
-
import type { EngineConfig } from "../engine/
|
|
2
|
+
import type { EngineConfig } from "../engine/types.js";
|
|
3
3
|
/**
|
|
4
4
|
* The subset of EngineConfig the config hot-reload ("layer 2") pushes onto an
|
|
5
5
|
* already-running session's `this.config`. These are the "disk-default" fields:
|
|
@@ -32,4 +32,11 @@ export type DiskDefaultPatch = Pick<EngineConfig, "preset" | "customSystemPrompt
|
|
|
32
32
|
* config (no divergence). It reuses `personalizationFrom` for the three
|
|
33
33
|
* personalization fields rather than duplicating the mapping.
|
|
34
34
|
*/
|
|
35
|
-
export declare function diskDefaultsFrom(settings: ValidatedSettings
|
|
35
|
+
export declare function diskDefaultsFrom(settings: ValidatedSettings,
|
|
36
|
+
/**
|
|
37
|
+
* EFFECTIVE disabled plugins for the target session — the caller should
|
|
38
|
+
* pass `engine.getEffectiveDisabledLists().disabledPlugins` so the merge
|
|
39
|
+
* honors project capabilityOverrides (能力总览 project "on" overrides the
|
|
40
|
+
* global list). Omitted → falls back to the raw global list (legacy).
|
|
41
|
+
*/
|
|
42
|
+
effectiveDisabledPlugins?: string[]): DiskDefaultPatch;
|
|
@@ -9,7 +9,14 @@ import { mergePluginMcpServers } from "../plugins/installer/loadPluginMcp.js";
|
|
|
9
9
|
* config (no divergence). It reuses `personalizationFrom` for the three
|
|
10
10
|
* personalization fields rather than duplicating the mapping.
|
|
11
11
|
*/
|
|
12
|
-
export function diskDefaultsFrom(settings
|
|
12
|
+
export function diskDefaultsFrom(settings,
|
|
13
|
+
/**
|
|
14
|
+
* EFFECTIVE disabled plugins for the target session — the caller should
|
|
15
|
+
* pass `engine.getEffectiveDisabledLists().disabledPlugins` so the merge
|
|
16
|
+
* honors project capabilityOverrides (能力总览 project "on" overrides the
|
|
17
|
+
* global list). Omitted → falls back to the raw global list (legacy).
|
|
18
|
+
*/
|
|
19
|
+
effectiveDisabledPlugins) {
|
|
13
20
|
const agent = settings.agent ?? {};
|
|
14
21
|
return {
|
|
15
22
|
preset: agent.preset,
|
|
@@ -19,6 +26,8 @@ export function diskDefaultsFrom(settings) {
|
|
|
19
26
|
// Same merge engineFactory uses: user-configured servers + enabled
|
|
20
27
|
// plugins' servers. Plugin servers a disabled plugin would contribute are
|
|
21
28
|
// skipped, matching new-session construction.
|
|
22
|
-
mcpServers: mergePluginMcpServers(settings.mcpServers ?? {},
|
|
29
|
+
mcpServers: mergePluginMcpServers(settings.mcpServers ?? {}, effectiveDisabledPlugins ??
|
|
30
|
+
settings.disabledPlugins ??
|
|
31
|
+
[], settings.mcpServerOverrides ?? {}),
|
|
23
32
|
};
|
|
24
33
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature Flags — a small, central on/off registry for opt-in or
|
|
3
|
+
* experimental behavior.
|
|
4
|
+
*
|
|
5
|
+
* Design goals:
|
|
6
|
+
* - One source of truth for flag NAMES + their DEFAULT state, so a flag
|
|
7
|
+
* can't be checked under a typo (the known set is a const).
|
|
8
|
+
* - Settings-driven: `settings.featureFlags` is a `{ [name]: boolean }`
|
|
9
|
+
* overlay over the defaults. Project settings override user settings the
|
|
10
|
+
* same way every other settings field does (the SettingsManager merge),
|
|
11
|
+
* so a flag can be flipped per-workspace.
|
|
12
|
+
* - Forgiving read: `isFeatureEnabled` falls back to the default when a
|
|
13
|
+
* flag is absent from settings, and ignores unknown flag names from
|
|
14
|
+
* settings (forward-compat with older binaries).
|
|
15
|
+
*
|
|
16
|
+
* This is the knob layer only — each consumer still has to CHECK its flag.
|
|
17
|
+
* The `/features` command (CLI) reads/writes this same map.
|
|
18
|
+
*/
|
|
19
|
+
/** Canonical flag names. Add new flags here so checks stay typo-safe. */
|
|
20
|
+
export declare const FEATURE_FLAGS: {
|
|
21
|
+
/** Web search tool availability (also gated by a configured provider). */
|
|
22
|
+
readonly web_search: {
|
|
23
|
+
readonly default: true;
|
|
24
|
+
readonly description: "Enable the WebSearch tool";
|
|
25
|
+
};
|
|
26
|
+
/** The Bash/shell tool. Off → the model cannot run shell commands. */
|
|
27
|
+
readonly shell_tool: {
|
|
28
|
+
readonly default: true;
|
|
29
|
+
readonly description: "Enable the Bash/shell tool";
|
|
30
|
+
};
|
|
31
|
+
/** Fast-output mode for supported models. */
|
|
32
|
+
readonly fast_mode: {
|
|
33
|
+
readonly default: false;
|
|
34
|
+
readonly description: "Faster streaming output on supported models";
|
|
35
|
+
};
|
|
36
|
+
/** Undo system (file-operation backups + /undo). */
|
|
37
|
+
readonly undo: {
|
|
38
|
+
readonly default: false;
|
|
39
|
+
readonly description: "Per-session file undo (/undo)";
|
|
40
|
+
};
|
|
41
|
+
/** Shell snapshot: capture full stdout/stderr of commands. */
|
|
42
|
+
readonly shell_snapshot: {
|
|
43
|
+
readonly default: false;
|
|
44
|
+
readonly description: "Capture full command stdout/stderr snapshots";
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
export type FeatureFlagName = keyof typeof FEATURE_FLAGS;
|
|
48
|
+
/** The settings overlay shape: a partial map of known flags → boolean. */
|
|
49
|
+
export type FeatureFlagOverrides = Partial<Record<FeatureFlagName, boolean>>;
|
|
50
|
+
/** All known flag names, for iteration (e.g. the /features listing). */
|
|
51
|
+
export declare function featureFlagNames(): FeatureFlagName[];
|
|
52
|
+
/** True when `name` is a recognized flag (narrows an arbitrary string). */
|
|
53
|
+
export declare function isKnownFeatureFlag(name: string): name is FeatureFlagName;
|
|
54
|
+
/**
|
|
55
|
+
* Resolve a flag's effective state: the settings overlay value when present
|
|
56
|
+
* and boolean, else the flag's compiled-in default. Unknown names → false
|
|
57
|
+
* (a check for a flag that doesn't exist is never "enabled").
|
|
58
|
+
*/
|
|
59
|
+
export declare function isFeatureEnabled(overrides: FeatureFlagOverrides | undefined, name: FeatureFlagName): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Resolve the full effective flag map (defaults merged with overrides).
|
|
62
|
+
* Used by `/features` to show the current state of every flag.
|
|
63
|
+
*/
|
|
64
|
+
export declare function resolveFeatureFlags(overrides: FeatureFlagOverrides | undefined): Record<FeatureFlagName, boolean>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature Flags — a small, central on/off registry for opt-in or
|
|
3
|
+
* experimental behavior.
|
|
4
|
+
*
|
|
5
|
+
* Design goals:
|
|
6
|
+
* - One source of truth for flag NAMES + their DEFAULT state, so a flag
|
|
7
|
+
* can't be checked under a typo (the known set is a const).
|
|
8
|
+
* - Settings-driven: `settings.featureFlags` is a `{ [name]: boolean }`
|
|
9
|
+
* overlay over the defaults. Project settings override user settings the
|
|
10
|
+
* same way every other settings field does (the SettingsManager merge),
|
|
11
|
+
* so a flag can be flipped per-workspace.
|
|
12
|
+
* - Forgiving read: `isFeatureEnabled` falls back to the default when a
|
|
13
|
+
* flag is absent from settings, and ignores unknown flag names from
|
|
14
|
+
* settings (forward-compat with older binaries).
|
|
15
|
+
*
|
|
16
|
+
* This is the knob layer only — each consumer still has to CHECK its flag.
|
|
17
|
+
* The `/features` command (CLI) reads/writes this same map.
|
|
18
|
+
*/
|
|
19
|
+
/** Canonical flag names. Add new flags here so checks stay typo-safe. */
|
|
20
|
+
export const FEATURE_FLAGS = {
|
|
21
|
+
/** Web search tool availability (also gated by a configured provider). */
|
|
22
|
+
web_search: { default: true, description: "Enable the WebSearch tool" },
|
|
23
|
+
/** The Bash/shell tool. Off → the model cannot run shell commands. */
|
|
24
|
+
shell_tool: { default: true, description: "Enable the Bash/shell tool" },
|
|
25
|
+
/** Fast-output mode for supported models. */
|
|
26
|
+
fast_mode: { default: false, description: "Faster streaming output on supported models" },
|
|
27
|
+
/** Undo system (file-operation backups + /undo). */
|
|
28
|
+
undo: { default: false, description: "Per-session file undo (/undo)" },
|
|
29
|
+
/** Shell snapshot: capture full stdout/stderr of commands. */
|
|
30
|
+
shell_snapshot: { default: false, description: "Capture full command stdout/stderr snapshots" },
|
|
31
|
+
};
|
|
32
|
+
/** All known flag names, for iteration (e.g. the /features listing). */
|
|
33
|
+
export function featureFlagNames() {
|
|
34
|
+
return Object.keys(FEATURE_FLAGS);
|
|
35
|
+
}
|
|
36
|
+
/** True when `name` is a recognized flag (narrows an arbitrary string). */
|
|
37
|
+
export function isKnownFeatureFlag(name) {
|
|
38
|
+
return Object.prototype.hasOwnProperty.call(FEATURE_FLAGS, name);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Resolve a flag's effective state: the settings overlay value when present
|
|
42
|
+
* and boolean, else the flag's compiled-in default. Unknown names → false
|
|
43
|
+
* (a check for a flag that doesn't exist is never "enabled").
|
|
44
|
+
*/
|
|
45
|
+
export function isFeatureEnabled(overrides, name) {
|
|
46
|
+
const override = overrides?.[name];
|
|
47
|
+
if (typeof override === "boolean")
|
|
48
|
+
return override;
|
|
49
|
+
return FEATURE_FLAGS[name].default;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Resolve the full effective flag map (defaults merged with overrides).
|
|
53
|
+
* Used by `/features` to show the current state of every flag.
|
|
54
|
+
*/
|
|
55
|
+
export function resolveFeatureFlags(overrides) {
|
|
56
|
+
const out = {};
|
|
57
|
+
for (const name of featureFlagNames()) {
|
|
58
|
+
out[name] = isFeatureEnabled(overrides, name);
|
|
59
|
+
}
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
@@ -12,7 +12,38 @@ import { type ValidatedSettings } from "./schema.js";
|
|
|
12
12
|
* `process.env.HOME` mutations.
|
|
13
13
|
*/
|
|
14
14
|
export declare function userHome(): string;
|
|
15
|
+
/**
|
|
16
|
+
* True if `key` (a dotted path like "permissions.rules" or just "env") targets a
|
|
17
|
+
* protected trust-root field. Matches on the FIRST segment so nested writes
|
|
18
|
+
* ("permissions.defaultMode", "env.FOO") are caught too.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isProtectedSettingKey(key: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* The fixed cwd used for "no-repo" pure-chat conversations (a chat not bound to
|
|
23
|
+
* any code project). Same location as desktop's `resolveNoRepoCwd`
|
|
24
|
+
* (`join(homedir(), ".code-shell", "no-repo")`), but built from {@link userHome}
|
|
25
|
+
* so tests can isolate it by overriding `$HOME`. The engine compares
|
|
26
|
+
* `config.cwd === noRepoDir()` to flip skill/plugin filtering to whitelist mode.
|
|
27
|
+
*/
|
|
28
|
+
export declare function noRepoDir(): string;
|
|
15
29
|
export type SettingsSourceName = "managed" | "user" | "project" | "local" | "flag";
|
|
30
|
+
/**
|
|
31
|
+
* Top-level settings fields that can influence code execution and are therefore
|
|
32
|
+
* stripped from an UNTRUSTED project's disk layers (project + local) before
|
|
33
|
+
* merge. A repo commits these into its `.code-shell/settings.json`, so an
|
|
34
|
+
* untrusted clone must not have them take effect:
|
|
35
|
+
* - permissions — `rules` can self-authorize (allow Bash …); `defaultMode`
|
|
36
|
+
* can set bypassPermissions.
|
|
37
|
+
* - env — injected into Bash child env unfiltered (BASH_ENV,
|
|
38
|
+
* LD_PRELOAD, PATH → arbitrary code on next command).
|
|
39
|
+
* - localEnvironment — same, as the env floor.
|
|
40
|
+
* - hooks — arbitrary commands on lifecycle events.
|
|
41
|
+
* - mcpServers — auto-connect to attacker-controlled MCP servers.
|
|
42
|
+
* Only project-scoped layers are filtered; user/managed/flag are trusted.
|
|
43
|
+
* Mirrors Claude Code's TRUSTED_SETTING_SOURCES model (project sources excluded
|
|
44
|
+
* from dangerous env application until trust is granted).
|
|
45
|
+
*/
|
|
46
|
+
export declare const DANGEROUS_PROJECT_FIELDS: readonly ["permissions", "env", "localEnvironment", "hooks", "mcpServers"];
|
|
16
47
|
/**
|
|
17
48
|
* Which disk layers a SettingsManager is allowed to read.
|
|
18
49
|
* 'full' — managed + user (~/.code-shell) + project + local (host terminal entrypoints)
|
|
@@ -26,13 +57,49 @@ export type SettingsScope = "isolated" | "project" | "full";
|
|
|
26
57
|
export declare class SettingsManager {
|
|
27
58
|
private readonly cwd;
|
|
28
59
|
private readonly scope;
|
|
60
|
+
/**
|
|
61
|
+
* Workspace trust for the project directory. When false, dangerous fields
|
|
62
|
+
* committed into the project's own `.code-shell/settings.{json,local.json}`
|
|
63
|
+
* ({@link DANGEROUS_PROJECT_FIELDS}) are stripped before merge, so a cloned
|
|
64
|
+
* malicious repo can't self-authorize permission rules, inject `env`
|
|
65
|
+
* (BASH_ENV/LD_PRELOAD/…), register hooks, or connect MCP servers. Safe
|
|
66
|
+
* fields (model choice, UI prefs, …) still merge. The user/managed/flag
|
|
67
|
+
* layers are never gated — the user put those there deliberately.
|
|
68
|
+
*
|
|
69
|
+
* Defaults to `true` so existing embedders/tests keep their behavior; the
|
|
70
|
+
* host (desktop) passes the real trust decision from its trust-store.
|
|
71
|
+
*/
|
|
72
|
+
private readonly projectTrusted;
|
|
29
73
|
private sources;
|
|
30
74
|
private merged;
|
|
31
|
-
constructor(cwd?: string, scope?: SettingsScope
|
|
75
|
+
constructor(cwd?: string, scope?: SettingsScope,
|
|
76
|
+
/**
|
|
77
|
+
* Workspace trust for the project directory. When false, dangerous fields
|
|
78
|
+
* committed into the project's own `.code-shell/settings.{json,local.json}`
|
|
79
|
+
* ({@link DANGEROUS_PROJECT_FIELDS}) are stripped before merge, so a cloned
|
|
80
|
+
* malicious repo can't self-authorize permission rules, inject `env`
|
|
81
|
+
* (BASH_ENV/LD_PRELOAD/…), register hooks, or connect MCP servers. Safe
|
|
82
|
+
* fields (model choice, UI prefs, …) still merge. The user/managed/flag
|
|
83
|
+
* layers are never gated — the user put those there deliberately.
|
|
84
|
+
*
|
|
85
|
+
* Defaults to `true` so existing embedders/tests keep their behavior; the
|
|
86
|
+
* host (desktop) passes the real trust decision from its trust-store.
|
|
87
|
+
*/
|
|
88
|
+
projectTrusted?: boolean);
|
|
32
89
|
/**
|
|
33
90
|
* Load settings from all sources.
|
|
34
91
|
*/
|
|
35
92
|
load(flagOverrides?: Record<string, unknown>): ValidatedSettings;
|
|
93
|
+
/**
|
|
94
|
+
* Run the version-based migrations (migrate-config.ts MIGRATIONS) against a
|
|
95
|
+
* single physical settings file. Best-effort: any read/parse/write error
|
|
96
|
+
* falls through silently and the original source data is used as-is.
|
|
97
|
+
* Writes back (with a .bak, like the models[] migration above) ONLY when a
|
|
98
|
+
* step changed actual content — the configVersion stamp alone doesn't
|
|
99
|
+
* justify touching the file. On write-back the in-memory source is updated
|
|
100
|
+
* so this load() already sees the migrated shape.
|
|
101
|
+
*/
|
|
102
|
+
private applyConfigMigration;
|
|
36
103
|
/**
|
|
37
104
|
* Get current effective settings.
|
|
38
105
|
*/
|