@cjhyy/code-shell-core 0.5.0-rc.2 → 0.6.0-rc.1
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
|
@@ -23,6 +23,7 @@ import { ChatSessionManager } from "../protocol/chat-session-manager.js";
|
|
|
23
23
|
import { AgentServer } from "../protocol/server.js";
|
|
24
24
|
import { listenTcp } from "../protocol/tcp-transport.js";
|
|
25
25
|
import { SettingsManager } from "../settings/manager.js";
|
|
26
|
+
import { computeEffectiveDisabledLists } from "../capability-control/disabled-lists.js";
|
|
26
27
|
import { personalizationFrom } from "../settings/personalization.js";
|
|
27
28
|
import { MCPManager } from "../tool-system/mcp-manager.js";
|
|
28
29
|
import { mergePluginMcpServers } from "../plugins/installer/loadPluginMcp.js";
|
|
@@ -31,18 +32,24 @@ import { HeadlessApprovalBackend } from "../tool-system/permission.js";
|
|
|
31
32
|
import { createRunManager } from "../run/factory.js";
|
|
32
33
|
import { startAutomation } from "../automation/index.js";
|
|
33
34
|
import { CronStore, defaultCronStorePath } from "../automation/store.js";
|
|
35
|
+
import { resolveLLMConfigForTag } from "../engine/resolve-llm-config.js";
|
|
34
36
|
const cwd = process.env.AGENT_CWD ?? process.cwd();
|
|
35
37
|
const port = Number(process.env.AGENT_TCP_PORT ?? "4321");
|
|
36
38
|
const host = process.env.AGENT_TCP_HOST ?? "127.0.0.1";
|
|
37
39
|
const settingsManager = new SettingsManager(cwd, "full");
|
|
40
|
+
// Read once at startup and reuse for every session (see engineFactory below).
|
|
41
|
+
// This is intentional for the TCP host: it's a headless long-running server,
|
|
42
|
+
// so config changes — including `mcpServers` — take effect on restart, not
|
|
43
|
+
// mid-session. (The stdio host re-reads per session via freshSettings(); the
|
|
44
|
+
// difference is by design, not a bug. Assessment §4.8.)
|
|
38
45
|
const settings = settingsManager.get();
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
const seedLlm = resolveLLMConfigForTag(settings, "text", settings.defaults?.text);
|
|
47
|
+
if (!seedLlm) {
|
|
48
|
+
console.error(`[agent-server] 没有可用的文本模型连接(defaults.text=${settings.defaults?.text ?? "未设置"})。` +
|
|
49
|
+
`请在「连接」页添加并填写凭证。`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
const llmConfig = seedLlm;
|
|
46
53
|
// ── Shared runtime (same bootstrap as stdio) ─────────────────────
|
|
47
54
|
const seedEngine = new Engine({ llm: llmConfig, cwd, settingsScope: "full" });
|
|
48
55
|
const modelPool = seedEngine.getModelPool();
|
|
@@ -60,25 +67,32 @@ const runtime = new EngineRuntime({
|
|
|
60
67
|
});
|
|
61
68
|
const chatManager = new ChatSessionManager({
|
|
62
69
|
runtime,
|
|
63
|
-
engineFactory: (slice) =>
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
70
|
+
engineFactory: (slice) => {
|
|
71
|
+
// Fold project capabilityOverrides over the global disabledPlugins for
|
|
72
|
+
// the MCP merge (能力总览 project "on" must override global off) — same
|
|
73
|
+
// contract as the stdio host's factory.
|
|
74
|
+
const sessionCwd = slice.cwd ?? cwd;
|
|
75
|
+
const { disabledPlugins } = computeEffectiveDisabledLists(new SettingsManager(sessionCwd, "full"), sessionCwd);
|
|
76
|
+
return new Engine({
|
|
77
|
+
llm: runtime.modelPool.resolveLLMConfig() ?? resolvedLlmConfig,
|
|
78
|
+
clientDefaults: resolvedClientDefaults,
|
|
79
|
+
cwd,
|
|
80
|
+
runtime,
|
|
81
|
+
settingsScope: "full",
|
|
82
|
+
mcpServers: mergePluginMcpServers(settings.mcpServers ?? {}, disabledPlugins, settings.mcpServerOverrides ?? {}),
|
|
83
|
+
permissionMode: slice.permissionMode,
|
|
84
|
+
preset: slice.preset,
|
|
85
|
+
customSystemPrompt: slice.customSystemPrompt,
|
|
86
|
+
appendSystemPrompt: slice.appendSystemPrompt,
|
|
87
|
+
// Personalization + instruction compat come from disk settings only
|
|
88
|
+
// (not per-request slice overrides) — same disk-only contract as the
|
|
89
|
+
// stdio host. Shared helper keeps the three fields wired identically.
|
|
90
|
+
...personalizationFrom(settings.agent),
|
|
91
|
+
maxTurns: slice.maxTurns,
|
|
92
|
+
maxContextTokens: slice.maxContextTokens,
|
|
93
|
+
...(slice.cwd ? { cwd: slice.cwd } : {}),
|
|
94
|
+
});
|
|
95
|
+
},
|
|
82
96
|
maxSessions: 16,
|
|
83
97
|
idleTtlMs: 30 * 60 * 1000,
|
|
84
98
|
});
|
|
@@ -16,6 +16,25 @@ import type { Message } from "../types.js";
|
|
|
16
16
|
* Uses per-block-type estimation with 33% overhead padding.
|
|
17
17
|
*/
|
|
18
18
|
export declare function estimateTokens(messages: Message[]): number;
|
|
19
|
+
/**
|
|
20
|
+
* Reconcile user-supplied compaction ratios into a safe ordering.
|
|
21
|
+
*
|
|
22
|
+
* The three tiers must satisfy `floor < compact < summarize` or the manager
|
|
23
|
+
* fires them in the wrong order (e.g. an emergency window-compact before the
|
|
24
|
+
* cheaper summary). Users edit these freely in settings.json, so we clamp
|
|
25
|
+
* rather than trust: summarize is pulled up to at least compact, floor is
|
|
26
|
+
* pushed down to at most compact. Absent fields are left undefined so the
|
|
27
|
+
* ContextManager keeps its own default for them.
|
|
28
|
+
*/
|
|
29
|
+
export declare function clampContextRatios(input: {
|
|
30
|
+
compactAtRatio?: number;
|
|
31
|
+
summarizeAtRatio?: number;
|
|
32
|
+
microcompactFloorRatio?: number;
|
|
33
|
+
}): {
|
|
34
|
+
compactAtRatio?: number;
|
|
35
|
+
summarizeAtRatio?: number;
|
|
36
|
+
microcompactFloorRatio?: number;
|
|
37
|
+
};
|
|
19
38
|
/**
|
|
20
39
|
* Expand a slice start-index backwards so that every tool_result in the
|
|
21
40
|
* kept range has its corresponding tool_use in the kept range too.
|
|
@@ -74,6 +93,43 @@ export interface MicrocompactOptions {
|
|
|
74
93
|
* forced into blind re-Reads (which then trip the Investigation guard).
|
|
75
94
|
*/
|
|
76
95
|
export declare function microcompact(messages: Message[], options?: MicrocompactOptions): Message[];
|
|
96
|
+
export interface DedupeFileReadsResult {
|
|
97
|
+
messages: Message[];
|
|
98
|
+
/** How many stale Read results were cleared. */
|
|
99
|
+
clearedCount: number;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Content-aware dedup: when the SAME file is Read more than once, every Read
|
|
103
|
+
* result except the most recent is stale — the file's current state is in the
|
|
104
|
+
* latest read. Clear the older ones (replace with a fingerprint pointing at
|
|
105
|
+
* the newer read) regardless of the recency window or pressure floor, because
|
|
106
|
+
* this is pure waste removal, not lossy compaction: the model never needs two
|
|
107
|
+
* copies of the same file.
|
|
108
|
+
*
|
|
109
|
+
* Distinct from microcompact (which is recency-gated and pressure-gated): a
|
|
110
|
+
* file Read 3 times in the last 3 turns keeps 3 full copies under microcompact
|
|
111
|
+
* but only the newest under this pass. Zero-cost and always safe to run, so the
|
|
112
|
+
* ContextManager calls it as an early tier.
|
|
113
|
+
*
|
|
114
|
+
* Only `Read` is deduped (its result is exactly the file content). Edit/Write
|
|
115
|
+
* results are diffs/confirmations, not full snapshots, so they're left alone.
|
|
116
|
+
*/
|
|
117
|
+
export declare function dedupeFileReads(messages: Message[]): DedupeFileReadsResult;
|
|
118
|
+
/**
|
|
119
|
+
* Observation masking for browser_observe(snapshot) results (the research's
|
|
120
|
+
* highest-leverage browser-token saving: a page snapshot is large and only the
|
|
121
|
+
* LATEST one matters for the next decision; older ones are stale element lists).
|
|
122
|
+
* Keep the most recent snapshot result verbatim; replace every earlier one with
|
|
123
|
+
* a one-line placeholder. Deterministic — no LLM summarization needed.
|
|
124
|
+
*
|
|
125
|
+
* Keyed on the snapshot OBSERVATION (browser_observe with mode snapshot) — read/
|
|
126
|
+
* extract observations and act results are left untouched. Renamed from
|
|
127
|
+
* maskOldBrowserSnapshots when the 9 browser_* tools collapsed into 3.
|
|
128
|
+
*/
|
|
129
|
+
export declare function maskOldObservations(messages: Message[]): {
|
|
130
|
+
messages: Message[];
|
|
131
|
+
maskedCount: number;
|
|
132
|
+
};
|
|
77
133
|
/**
|
|
78
134
|
* Apply aggregate per-message tool result budget.
|
|
79
135
|
* When total tool_result content in a single message exceeds maxTotalChars,
|
|
@@ -18,6 +18,30 @@ import { estimateMessagesTokens } from "./token-counter.js";
|
|
|
18
18
|
export function estimateTokens(messages) {
|
|
19
19
|
return Math.ceil(estimateMessagesTokens(messages) * (4 / 3));
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Reconcile user-supplied compaction ratios into a safe ordering.
|
|
23
|
+
*
|
|
24
|
+
* The three tiers must satisfy `floor < compact < summarize` or the manager
|
|
25
|
+
* fires them in the wrong order (e.g. an emergency window-compact before the
|
|
26
|
+
* cheaper summary). Users edit these freely in settings.json, so we clamp
|
|
27
|
+
* rather than trust: summarize is pulled up to at least compact, floor is
|
|
28
|
+
* pushed down to at most compact. Absent fields are left undefined so the
|
|
29
|
+
* ContextManager keeps its own default for them.
|
|
30
|
+
*/
|
|
31
|
+
export function clampContextRatios(input) {
|
|
32
|
+
const compact = input.compactAtRatio;
|
|
33
|
+
const summarize = input.summarizeAtRatio !== undefined && compact !== undefined
|
|
34
|
+
? Math.max(input.summarizeAtRatio, compact)
|
|
35
|
+
: input.summarizeAtRatio;
|
|
36
|
+
const floor = input.microcompactFloorRatio !== undefined && compact !== undefined
|
|
37
|
+
? Math.min(input.microcompactFloorRatio, compact)
|
|
38
|
+
: input.microcompactFloorRatio;
|
|
39
|
+
return {
|
|
40
|
+
compactAtRatio: compact,
|
|
41
|
+
summarizeAtRatio: summarize,
|
|
42
|
+
microcompactFloorRatio: floor,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
21
45
|
// ─── Tool Use / Result Pair Protection ──────────────────────────────
|
|
22
46
|
/**
|
|
23
47
|
* Expand a slice start-index backwards so that every tool_result in the
|
|
@@ -275,6 +299,168 @@ export function microcompact(messages, options = {}) {
|
|
|
275
299
|
}
|
|
276
300
|
return result;
|
|
277
301
|
}
|
|
302
|
+
/** Tools whose result is the content of a single file, keyed by path. */
|
|
303
|
+
const FILE_READ_TOOLS = new Set(["Read"]);
|
|
304
|
+
/**
|
|
305
|
+
* Content-aware dedup: when the SAME file is Read more than once, every Read
|
|
306
|
+
* result except the most recent is stale — the file's current state is in the
|
|
307
|
+
* latest read. Clear the older ones (replace with a fingerprint pointing at
|
|
308
|
+
* the newer read) regardless of the recency window or pressure floor, because
|
|
309
|
+
* this is pure waste removal, not lossy compaction: the model never needs two
|
|
310
|
+
* copies of the same file.
|
|
311
|
+
*
|
|
312
|
+
* Distinct from microcompact (which is recency-gated and pressure-gated): a
|
|
313
|
+
* file Read 3 times in the last 3 turns keeps 3 full copies under microcompact
|
|
314
|
+
* but only the newest under this pass. Zero-cost and always safe to run, so the
|
|
315
|
+
* ContextManager calls it as an early tier.
|
|
316
|
+
*
|
|
317
|
+
* Only `Read` is deduped (its result is exactly the file content). Edit/Write
|
|
318
|
+
* results are diffs/confirmations, not full snapshots, so they're left alone.
|
|
319
|
+
*/
|
|
320
|
+
export function dedupeFileReads(messages) {
|
|
321
|
+
const idToName = buildToolUseIdToNameMap(messages);
|
|
322
|
+
const idToInput = new Map();
|
|
323
|
+
for (const msg of messages) {
|
|
324
|
+
if (!Array.isArray(msg.content))
|
|
325
|
+
continue;
|
|
326
|
+
for (const block of msg.content) {
|
|
327
|
+
if (block.type === "tool_use" && block.id)
|
|
328
|
+
idToInput.set(block.id, block.input);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
// Resolve a Read tool_use_id to its file_path arg (the dedup key).
|
|
332
|
+
const pathOf = (toolUseId) => {
|
|
333
|
+
const input = idToInput.get(toolUseId);
|
|
334
|
+
const p = input?.file_path ?? input?.path;
|
|
335
|
+
return typeof p === "string" && p.length > 0 ? p : undefined;
|
|
336
|
+
};
|
|
337
|
+
// Collect, per file path, the message indices + block positions of every
|
|
338
|
+
// non-cleared Read result. Walk forward so "last" is the newest.
|
|
339
|
+
const byPath = new Map();
|
|
340
|
+
for (let i = 0; i < messages.length; i++) {
|
|
341
|
+
const msg = messages[i];
|
|
342
|
+
if (!Array.isArray(msg.content))
|
|
343
|
+
continue;
|
|
344
|
+
for (const block of msg.content) {
|
|
345
|
+
if (block.type !== "tool_result" || !block.tool_use_id)
|
|
346
|
+
continue;
|
|
347
|
+
if (!FILE_READ_TOOLS.has(idToName.get(block.tool_use_id) ?? ""))
|
|
348
|
+
continue;
|
|
349
|
+
if (typeof block.content !== "string")
|
|
350
|
+
continue;
|
|
351
|
+
if (block.content.startsWith("[Old tool result cleared"))
|
|
352
|
+
continue;
|
|
353
|
+
const path = pathOf(block.tool_use_id);
|
|
354
|
+
if (!path)
|
|
355
|
+
continue;
|
|
356
|
+
const list = byPath.get(path) ?? [];
|
|
357
|
+
list.push({ msgIdx: i, toolUseId: block.tool_use_id });
|
|
358
|
+
byPath.set(path, list);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
// For each path read more than once, mark all-but-last for clearing.
|
|
362
|
+
const clearIds = new Set();
|
|
363
|
+
for (const [, reads] of byPath) {
|
|
364
|
+
if (reads.length < 2)
|
|
365
|
+
continue;
|
|
366
|
+
for (let k = 0; k < reads.length - 1; k++)
|
|
367
|
+
clearIds.add(reads[k].toolUseId);
|
|
368
|
+
}
|
|
369
|
+
if (clearIds.size === 0)
|
|
370
|
+
return { messages, clearedCount: 0 };
|
|
371
|
+
let clearedCount = 0;
|
|
372
|
+
const result = messages.map((msg) => {
|
|
373
|
+
if (!Array.isArray(msg.content))
|
|
374
|
+
return msg;
|
|
375
|
+
return {
|
|
376
|
+
...msg,
|
|
377
|
+
content: msg.content.map((block) => {
|
|
378
|
+
if (block.type !== "tool_result" || !block.tool_use_id)
|
|
379
|
+
return block;
|
|
380
|
+
if (!clearIds.has(block.tool_use_id))
|
|
381
|
+
return block;
|
|
382
|
+
const argsSummary = summarizeToolCallArgs("Read", idToInput.get(block.tool_use_id));
|
|
383
|
+
clearedCount++;
|
|
384
|
+
return {
|
|
385
|
+
...block,
|
|
386
|
+
content: `[Old tool result cleared — superseded by a newer Read${argsSummary ? ` of ${argsSummary}` : ""}]`,
|
|
387
|
+
};
|
|
388
|
+
}),
|
|
389
|
+
};
|
|
390
|
+
});
|
|
391
|
+
return { messages: result, clearedCount };
|
|
392
|
+
}
|
|
393
|
+
/** Build id → true for tool_use blocks that are a browser snapshot observation,
|
|
394
|
+
* i.e. `browser_observe` with mode "snapshot" (the default when mode omitted).
|
|
395
|
+
* Only snapshots produce large, supersede-able element lists worth masking. */
|
|
396
|
+
function buildSnapshotObserveIdSet(messages) {
|
|
397
|
+
const ids = new Set();
|
|
398
|
+
for (const msg of messages) {
|
|
399
|
+
if (!Array.isArray(msg.content))
|
|
400
|
+
continue;
|
|
401
|
+
for (const block of msg.content) {
|
|
402
|
+
if (block.type !== "tool_use" || !block.id || block.name !== "browser_observe")
|
|
403
|
+
continue;
|
|
404
|
+
const mode = block.input?.mode;
|
|
405
|
+
if (mode === undefined || mode === "snapshot")
|
|
406
|
+
ids.add(block.id);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return ids;
|
|
410
|
+
}
|
|
411
|
+
const OLD_SNAPSHOT_PLACEHOLDER = "[Old browser snapshot collapsed — superseded by a newer browser_observe(snapshot). " +
|
|
412
|
+
"Re-run browser_observe for the current page's elements.]";
|
|
413
|
+
/**
|
|
414
|
+
* Observation masking for browser_observe(snapshot) results (the research's
|
|
415
|
+
* highest-leverage browser-token saving: a page snapshot is large and only the
|
|
416
|
+
* LATEST one matters for the next decision; older ones are stale element lists).
|
|
417
|
+
* Keep the most recent snapshot result verbatim; replace every earlier one with
|
|
418
|
+
* a one-line placeholder. Deterministic — no LLM summarization needed.
|
|
419
|
+
*
|
|
420
|
+
* Keyed on the snapshot OBSERVATION (browser_observe with mode snapshot) — read/
|
|
421
|
+
* extract observations and act results are left untouched. Renamed from
|
|
422
|
+
* maskOldBrowserSnapshots when the 9 browser_* tools collapsed into 3.
|
|
423
|
+
*/
|
|
424
|
+
export function maskOldObservations(messages) {
|
|
425
|
+
const snapshotIds = buildSnapshotObserveIdSet(messages);
|
|
426
|
+
const snapResults = [];
|
|
427
|
+
for (const msg of messages) {
|
|
428
|
+
if (!Array.isArray(msg.content))
|
|
429
|
+
continue;
|
|
430
|
+
for (const block of msg.content) {
|
|
431
|
+
if (block.type !== "tool_result" || !block.tool_use_id)
|
|
432
|
+
continue;
|
|
433
|
+
if (!snapshotIds.has(block.tool_use_id))
|
|
434
|
+
continue;
|
|
435
|
+
if (typeof block.content !== "string")
|
|
436
|
+
continue;
|
|
437
|
+
if (block.content.startsWith("[Old browser snapshot collapsed"))
|
|
438
|
+
continue;
|
|
439
|
+
snapResults.push(block.tool_use_id);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
if (snapResults.length < 2)
|
|
443
|
+
return { messages, maskedCount: 0 };
|
|
444
|
+
// Mask all but the last (newest walked-forward).
|
|
445
|
+
const maskIds = new Set(snapResults.slice(0, -1));
|
|
446
|
+
let maskedCount = 0;
|
|
447
|
+
const result = messages.map((msg) => {
|
|
448
|
+
if (!Array.isArray(msg.content))
|
|
449
|
+
return msg;
|
|
450
|
+
return {
|
|
451
|
+
...msg,
|
|
452
|
+
content: msg.content.map((block) => {
|
|
453
|
+
if (block.type !== "tool_result" || !block.tool_use_id)
|
|
454
|
+
return block;
|
|
455
|
+
if (!maskIds.has(block.tool_use_id))
|
|
456
|
+
return block;
|
|
457
|
+
maskedCount++;
|
|
458
|
+
return { ...block, content: OLD_SNAPSHOT_PLACEHOLDER };
|
|
459
|
+
}),
|
|
460
|
+
};
|
|
461
|
+
});
|
|
462
|
+
return { messages: result, maskedCount };
|
|
463
|
+
}
|
|
278
464
|
/**
|
|
279
465
|
* Apply aggregate per-message tool result budget.
|
|
280
466
|
* When total tool_result content in a single message exceeds maxTotalChars,
|
package/dist/context/manager.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Tier 2: LLM summary (async) — generate summary of older messages via model call
|
|
6
6
|
* Tier 3: window compact (sync, emergency) — aggressive truncation fallback
|
|
7
7
|
*/
|
|
8
|
-
import { estimateTokens, microcompact, snipCompact, windowCompact, truncateToolResult, buildSummarizationPrompt, applySummaryCompaction, applyToolResultBudget, extractAnchoredSummary, } from "./compaction.js";
|
|
8
|
+
import { estimateTokens, microcompact, dedupeFileReads, maskOldObservations, snipCompact, windowCompact, truncateToolResult, buildSummarizationPrompt, applySummaryCompaction, applyToolResultBudget, extractAnchoredSummary, } from "./compaction.js";
|
|
9
9
|
import { applyToolResultPersistence, createContentReplacementState, reconstructContentReplacementState, resolveToolResultsDir, } from "./tool-result-storage.js";
|
|
10
10
|
import { logger } from "../logging/logger.js";
|
|
11
11
|
const DEFAULT_CONFIG = {
|
|
@@ -127,6 +127,25 @@ export class ContextManager {
|
|
|
127
127
|
// Tier 0c: Aggregate tool result budget (per-message) — char-level
|
|
128
128
|
// backstop for messages still over the limit after persistence.
|
|
129
129
|
result = applyToolResultBudget(result);
|
|
130
|
+
// Tier 0d: dedup repeated Reads of the same file — keep only the latest
|
|
131
|
+
// copy (older ones are stale). Always-on + zero-cost: it's pure waste
|
|
132
|
+
// removal (the model never needs two snapshots of one file), unlike the
|
|
133
|
+
// pressure-/recency-gated tiers below. Runs before microcompact so an
|
|
134
|
+
// already-deduped result isn't double-counted toward the keep-recent window.
|
|
135
|
+
const dedup = dedupeFileReads(result);
|
|
136
|
+
if (dedup.clearedCount > 0) {
|
|
137
|
+
result = dedup.messages;
|
|
138
|
+
logger.info("context.dedupe_file_reads", { cleared: dedup.clearedCount });
|
|
139
|
+
}
|
|
140
|
+
// Tier 0d': browser observation masking — keep only the latest
|
|
141
|
+
// browser_snapshot, collapse older ones (stale element lists, often large).
|
|
142
|
+
// Same always-on waste-removal class as dedupeFileReads. The research's
|
|
143
|
+
// top browser-token lever (folding old observations beats LLM summarizing).
|
|
144
|
+
const masked = maskOldObservations(result);
|
|
145
|
+
if (masked.maskedCount > 0) {
|
|
146
|
+
result = masked.messages;
|
|
147
|
+
logger.info("context.mask_browser_snapshots", { masked: masked.maskedCount });
|
|
148
|
+
}
|
|
130
149
|
// Tier 1: microcompact — fingerprint old whitelisted tool_results.
|
|
131
150
|
// Only runs above the floor ratio: under-pressure context keeps full
|
|
132
151
|
// detail so the model isn't forced to re-Read files it just looked at.
|
|
@@ -341,20 +360,22 @@ export class ContextManager {
|
|
|
341
360
|
*/
|
|
342
361
|
truncateToolResults(messages) {
|
|
343
362
|
const maxChars = this.config.maxToolResultChars;
|
|
344
|
-
let modified = false;
|
|
345
363
|
const result = messages.map((msg) => {
|
|
346
364
|
if (!Array.isArray(msg.content))
|
|
347
365
|
return msg;
|
|
366
|
+
// Per-message flag: a truncation in an earlier message must not force
|
|
367
|
+
// later, unchanged messages to be spread-copied.
|
|
368
|
+
let messageModified = false;
|
|
348
369
|
const newContent = msg.content.map((block) => {
|
|
349
370
|
if (block.type === "tool_result" && typeof block.content === "string") {
|
|
350
371
|
if (block.content.length > maxChars) {
|
|
351
|
-
|
|
372
|
+
messageModified = true;
|
|
352
373
|
return { ...block, content: truncateToolResult(block.content, maxChars) };
|
|
353
374
|
}
|
|
354
375
|
}
|
|
355
376
|
return block;
|
|
356
377
|
});
|
|
357
|
-
return
|
|
378
|
+
return messageModified ? { ...msg, content: newContent } : msg;
|
|
358
379
|
});
|
|
359
380
|
return result;
|
|
360
381
|
}
|
package/dist/cost-tracker.js
CHANGED
|
@@ -3,67 +3,11 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { NOOP_COLORIZER } from "./colorizer.js";
|
|
5
5
|
import { findOpenRouterModel } from "./data/openrouter-models.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// Anthropic (per 1M tokens, USD)
|
|
12
|
-
"claude-opus-4.6": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
|
|
13
|
-
"claude-opus-4-6": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 }, // alias
|
|
14
|
-
"claude-opus-4.5": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
|
|
15
|
-
"claude-opus-4.1": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
|
|
16
|
-
"claude-opus-4": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
|
|
17
|
-
"claude-sonnet-4.6": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
18
|
-
"claude-sonnet-4-6": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 }, // alias
|
|
19
|
-
"claude-sonnet-4.5": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
20
|
-
"claude-sonnet-4": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
21
|
-
"claude-3.7-sonnet": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
22
|
-
"claude-3-7-sonnet": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
23
|
-
"claude-3.5-haiku": { input: 0.8, output: 4, cacheRead: 0.08, cacheWrite: 1 },
|
|
24
|
-
"claude-haiku-4.5": { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 },
|
|
25
|
-
"claude-haiku-4-5": { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 }, // alias
|
|
26
|
-
// OpenAI
|
|
27
|
-
"gpt-5.4": pricing(5, 20),
|
|
28
|
-
"gpt-5.4-mini": pricing(1.5, 6),
|
|
29
|
-
"gpt-5.4-pro": pricing(10, 40),
|
|
30
|
-
"gpt-5": pricing(5, 20),
|
|
31
|
-
"gpt-4o": pricing(2.5, 10),
|
|
32
|
-
"gpt-4o-mini": pricing(0.15, 0.6),
|
|
33
|
-
"gpt-4.1": pricing(2, 8),
|
|
34
|
-
"gpt-4.1-mini": pricing(0.4, 1.6),
|
|
35
|
-
"o4-mini": pricing(1.1, 4.4),
|
|
36
|
-
"o3": pricing(10, 40),
|
|
37
|
-
"o3-mini": pricing(1.1, 4.4),
|
|
38
|
-
// Google
|
|
39
|
-
"gemini-2.5-pro": pricing(1.25, 10),
|
|
40
|
-
"gemini-2.5-pro-preview": pricing(1.25, 10),
|
|
41
|
-
"gemini-2.5-flash": pricing(0.15, 0.6),
|
|
42
|
-
"gemini-3.1-pro-preview": pricing(2, 10),
|
|
43
|
-
"gemini-3-flash-preview": pricing(0.15, 0.6),
|
|
44
|
-
"gemini-2.0-flash": pricing(0.1, 0.4),
|
|
45
|
-
// DeepSeek
|
|
46
|
-
"deepseek-v4-flash": pricing(0.126, 0.252),
|
|
47
|
-
"deepseek-v4-pro": pricing(0.5, 2),
|
|
48
|
-
"deepseek-v3.2": pricing(0.14, 0.28),
|
|
49
|
-
"deepseek-chat": pricing(0.14, 0.28),
|
|
50
|
-
"deepseek-r1": pricing(0.55, 2.19),
|
|
51
|
-
"deepseek-reasoner": pricing(0.55, 2.19),
|
|
52
|
-
// Qwen
|
|
53
|
-
"qwen3-coder": pricing(0.3, 0.6),
|
|
54
|
-
"qwen3-235b-a22b": pricing(0.3, 1.2),
|
|
55
|
-
"qwen3-30b-a3b": pricing(0.1, 0.3),
|
|
56
|
-
"qwen3-max": pricing(0.5, 2),
|
|
57
|
-
// Meta
|
|
58
|
-
"llama-4-maverick": pricing(0.2, 0.8),
|
|
59
|
-
"llama-4-scout": pricing(0.15, 0.4),
|
|
60
|
-
// Mistral
|
|
61
|
-
"devstral-medium": pricing(0.5, 1.5),
|
|
62
|
-
"mistral-large": pricing(2, 6),
|
|
63
|
-
"devstral-small": pricing(0.1, 0.3),
|
|
64
|
-
};
|
|
65
|
-
// Default fallback pricing
|
|
66
|
-
const DEFAULT_PRICING = pricing(3, 15);
|
|
6
|
+
import { MODEL_PRICING, DEFAULT_PRICING, } from "./data/model-metadata.js";
|
|
7
|
+
// Pricing per 1M tokens (USD). The MODEL_PRICING table + DEFAULT_PRICING now
|
|
8
|
+
// live in data/model-metadata.json (loaded by data/model-metadata.ts) so a
|
|
9
|
+
// price change is a data edit, not a code change. cacheRead/cacheWrite are
|
|
10
|
+
// derived there: read = 10% of input, write = 125% of input.
|
|
67
11
|
/** Build a ModelPricing from an OpenRouter snapshot entry. */
|
|
68
12
|
function openRouterPricing(hit) {
|
|
69
13
|
const input = hit.inputPricePerMillion;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential encryption boundary.
|
|
3
|
+
*
|
|
4
|
+
* The core has no business owning a platform encryption key — on the desktop
|
|
5
|
+
* the only safe key lives behind Electron `safeStorage`, which is in the main
|
|
6
|
+
* process, not in this worker. So core defines an INTERFACE and the host feeds
|
|
7
|
+
* an implementation: desktop main injects a safeStorage-backed cipher; the
|
|
8
|
+
* headless CLI / SDK inject {@link PlaintextCipher}. This keeps `safeStorage`
|
|
9
|
+
* out of `packages/core` entirely (`grep -R safeStorage packages/core/src`
|
|
10
|
+
* must stay empty) and puts secret crypto where the key actually is.
|
|
11
|
+
*
|
|
12
|
+
* The stored field is a tagged string so a store written by one cipher can be
|
|
13
|
+
* read (or rejected) by another:
|
|
14
|
+
* - `plain:<secret>` — PlaintextCipher, or any pre-cipher legacy value
|
|
15
|
+
* that has no recognized prefix (treated as plain).
|
|
16
|
+
* - `enc:<scheme>:<base64>` — an encrypting cipher; `<scheme>` lets a cipher
|
|
17
|
+
* recognize its own ciphertext via canDecrypt().
|
|
18
|
+
*/
|
|
19
|
+
export interface EncryptionCipher {
|
|
20
|
+
/** Encrypt a plaintext secret into its stored (tagged) form. */
|
|
21
|
+
encrypt(plaintext: string): string;
|
|
22
|
+
/** Decrypt a stored value back to plaintext. Must accept this cipher's own
|
|
23
|
+
* output and legacy un-prefixed plaintext; may throw if a value is
|
|
24
|
+
* recognizably foreign and undecryptable. */
|
|
25
|
+
decrypt(stored: string): string;
|
|
26
|
+
/** True when this cipher can decrypt `stored`. Used by the store to decide
|
|
27
|
+
* whether to migrate (re-encrypt on next save) a value written by a
|
|
28
|
+
* different cipher / left as legacy plaintext. */
|
|
29
|
+
canDecrypt?(stored: string): boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The no-encryption strategy — chosen explicitly, not a no-op. Headless and
|
|
33
|
+
* SDK hosts have no safe key store, so they keep credentials as owner-only
|
|
34
|
+
* (0o600) plaintext, exactly as before this boundary existed. Named so the
|
|
35
|
+
* choice reads honestly in host wiring: `new CredentialStore(cwd, new
|
|
36
|
+
* PlaintextCipher())` says "plaintext on purpose", not "forgot to encrypt".
|
|
37
|
+
*/
|
|
38
|
+
export declare class PlaintextCipher implements EncryptionCipher {
|
|
39
|
+
encrypt(plaintext: string): string;
|
|
40
|
+
decrypt(stored: string): string;
|
|
41
|
+
canDecrypt(stored: string): boolean;
|
|
42
|
+
}
|
|
43
|
+
/** Reads a value that may be tagged (`plain:`) or legacy bare plaintext. */
|
|
44
|
+
export declare function readPlaintext(stored: string): string;
|
|
45
|
+
/** Host startup hook: install the process-wide credential cipher (desktop main
|
|
46
|
+
* passes a safeStorage-backed implementation). Idempotent; last call wins. */
|
|
47
|
+
export declare function setDefaultCredentialCipher(cipher: EncryptionCipher): void;
|
|
48
|
+
/** The current process-default cipher (PlaintextCipher unless a host set one). */
|
|
49
|
+
export declare function getDefaultCredentialCipher(): EncryptionCipher;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const PLAIN_PREFIX = "plain:";
|
|
2
|
+
/**
|
|
3
|
+
* The no-encryption strategy — chosen explicitly, not a no-op. Headless and
|
|
4
|
+
* SDK hosts have no safe key store, so they keep credentials as owner-only
|
|
5
|
+
* (0o600) plaintext, exactly as before this boundary existed. Named so the
|
|
6
|
+
* choice reads honestly in host wiring: `new CredentialStore(cwd, new
|
|
7
|
+
* PlaintextCipher())` says "plaintext on purpose", not "forgot to encrypt".
|
|
8
|
+
*/
|
|
9
|
+
export class PlaintextCipher {
|
|
10
|
+
encrypt(plaintext) {
|
|
11
|
+
return `${PLAIN_PREFIX}${plaintext}`;
|
|
12
|
+
}
|
|
13
|
+
decrypt(stored) {
|
|
14
|
+
// Accept our own tag, and treat any un-tagged legacy value as plaintext.
|
|
15
|
+
if (stored.startsWith(PLAIN_PREFIX))
|
|
16
|
+
return stored.slice(PLAIN_PREFIX.length);
|
|
17
|
+
if (stored.startsWith("enc:")) {
|
|
18
|
+
throw new Error("PlaintextCipher cannot decrypt an encrypted credential");
|
|
19
|
+
}
|
|
20
|
+
return stored;
|
|
21
|
+
}
|
|
22
|
+
canDecrypt(stored) {
|
|
23
|
+
return !stored.startsWith("enc:");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Reads a value that may be tagged (`plain:`) or legacy bare plaintext. */
|
|
27
|
+
export function readPlaintext(stored) {
|
|
28
|
+
return stored.startsWith(PLAIN_PREFIX) ? stored.slice(PLAIN_PREFIX.length) : stored;
|
|
29
|
+
}
|
|
30
|
+
// ─── Process-default cipher ──────────────────────────────────────
|
|
31
|
+
// CredentialStore is constructed at ~12 call sites (core + desktop) as
|
|
32
|
+
// `new CredentialStore(cwd)`. Rather than thread a cipher through every one,
|
|
33
|
+
// the host sets the process default ONCE at startup; stores pick it up unless
|
|
34
|
+
// a cipher is passed explicitly. Defaults to PlaintextCipher so any host that
|
|
35
|
+
// never calls the setter behaves exactly as before.
|
|
36
|
+
let defaultCipher = new PlaintextCipher();
|
|
37
|
+
/** Host startup hook: install the process-wide credential cipher (desktop main
|
|
38
|
+
* passes a safeStorage-backed implementation). Idempotent; last call wins. */
|
|
39
|
+
export function setDefaultCredentialCipher(cipher) {
|
|
40
|
+
defaultCipher = cipher;
|
|
41
|
+
}
|
|
42
|
+
/** The current process-default cipher (PlaintextCipher unless a host set one). */
|
|
43
|
+
export function getDefaultCredentialCipher() {
|
|
44
|
+
return defaultCipher;
|
|
45
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cookie jar 工具(凭证模块第二期):core 侧的纯函数,把存进 CredentialStore 的
|
|
3
|
+
* cookie 凭证(序列化的 jar)转成 yt-dlp/curl/wget/aria2 都吃的 Netscape cookies.txt。
|
|
4
|
+
*
|
|
5
|
+
* 形态与 desktop/src/main/credentials-service.ts 的 `formatNetscapeCookies` 一致
|
|
6
|
+
* (desktop 在拓取那一刻用,core 在取用那一刻用)。core 不能 import desktop,故各持一份
|
|
7
|
+
* 同语义的纯实现 —— 都无 Electron 依赖、可单测。
|
|
8
|
+
*/
|
|
9
|
+
/** 与 Electron Cookie 对齐的最小子集(jar 里存的就是这个)。 */
|
|
10
|
+
export interface CookieLike {
|
|
11
|
+
domain?: string;
|
|
12
|
+
hostOnly?: boolean;
|
|
13
|
+
path?: string;
|
|
14
|
+
secure?: boolean;
|
|
15
|
+
expirationDate?: number;
|
|
16
|
+
name: string;
|
|
17
|
+
value: string;
|
|
18
|
+
}
|
|
19
|
+
/** Cookie[] → Netscape cookies.txt 字符串。跳过含 TAB/换行的脏 cookie。 */
|
|
20
|
+
export declare function formatNetscapeCookies(cookies: CookieLike[]): string;
|
|
21
|
+
/**
|
|
22
|
+
* 解析 cookie 凭证的 `secret`(序列化 jar)。容错:非数组/坏 JSON → 空数组。
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseCookieJar(secret: string | undefined): CookieLike[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cookie jar 工具(凭证模块第二期):core 侧的纯函数,把存进 CredentialStore 的
|
|
3
|
+
* cookie 凭证(序列化的 jar)转成 yt-dlp/curl/wget/aria2 都吃的 Netscape cookies.txt。
|
|
4
|
+
*
|
|
5
|
+
* 形态与 desktop/src/main/credentials-service.ts 的 `formatNetscapeCookies` 一致
|
|
6
|
+
* (desktop 在拓取那一刻用,core 在取用那一刻用)。core 不能 import desktop,故各持一份
|
|
7
|
+
* 同语义的纯实现 —— 都无 Electron 依赖、可单测。
|
|
8
|
+
*/
|
|
9
|
+
function bad(s) {
|
|
10
|
+
return s.includes("\t") || s.includes("\n") || s.includes("\r");
|
|
11
|
+
}
|
|
12
|
+
/** Cookie[] → Netscape cookies.txt 字符串。跳过含 TAB/换行的脏 cookie。 */
|
|
13
|
+
export function formatNetscapeCookies(cookies) {
|
|
14
|
+
const lines = ["# Netscape HTTP Cookie File"];
|
|
15
|
+
for (const c of cookies) {
|
|
16
|
+
if (bad(c.name) || bad(c.value) || (c.domain && bad(c.domain)))
|
|
17
|
+
continue;
|
|
18
|
+
const domain = c.domain ?? "";
|
|
19
|
+
const includeSub = c.hostOnly === true ? "FALSE" : "TRUE";
|
|
20
|
+
const path = c.path ?? "/";
|
|
21
|
+
const secure = c.secure ? "TRUE" : "FALSE";
|
|
22
|
+
const expiry = typeof c.expirationDate === "number" ? String(Math.floor(c.expirationDate)) : "0";
|
|
23
|
+
lines.push([domain, includeSub, path, secure, expiry, c.name, c.value].join("\t"));
|
|
24
|
+
}
|
|
25
|
+
return lines.join("\n") + "\n";
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 解析 cookie 凭证的 `secret`(序列化 jar)。容错:非数组/坏 JSON → 空数组。
|
|
29
|
+
*/
|
|
30
|
+
export function parseCookieJar(secret) {
|
|
31
|
+
if (!secret)
|
|
32
|
+
return [];
|
|
33
|
+
try {
|
|
34
|
+
const parsed = JSON.parse(secret);
|
|
35
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
}
|