@cjhyy/code-shell-core 0.5.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +162 -0
- package/dist/agent/coordinator.d.ts +49 -0
- package/dist/agent/coordinator.js +77 -0
- package/dist/arena/arena.d.ts +43 -0
- package/dist/arena/arena.js +334 -0
- package/dist/arena/context/context-tools.d.ts +16 -0
- package/dist/arena/context/context-tools.js +231 -0
- package/dist/arena/detect-mode.d.ts +20 -0
- package/dist/arena/detect-mode.js +78 -0
- package/dist/arena/digest-builder.d.ts +25 -0
- package/dist/arena/digest-builder.js +120 -0
- package/dist/arena/index.d.ts +29 -0
- package/dist/arena/index.js +29 -0
- package/dist/arena/iterate/convergence.d.ts +25 -0
- package/dist/arena/iterate/convergence.js +103 -0
- package/dist/arena/iterate/formats/index.d.ts +22 -0
- package/dist/arena/iterate/formats/index.js +283 -0
- package/dist/arena/iterate/index.d.ts +11 -0
- package/dist/arena/iterate/index.js +9 -0
- package/dist/arena/iterate/iterative-arena.d.ts +23 -0
- package/dist/arena/iterate/iterative-arena.js +237 -0
- package/dist/arena/iterate/parse.d.ts +42 -0
- package/dist/arena/iterate/parse.js +123 -0
- package/dist/arena/iterate/phases/argue.d.ts +22 -0
- package/dist/arena/iterate/phases/argue.js +159 -0
- package/dist/arena/iterate/phases/revise.d.ts +16 -0
- package/dist/arena/iterate/phases/revise.js +62 -0
- package/dist/arena/iterate/phases/tournament.d.ts +34 -0
- package/dist/arena/iterate/phases/tournament.js +113 -0
- package/dist/arena/iterate/tools/web-tools.d.ts +13 -0
- package/dist/arena/iterate/tools/web-tools.js +54 -0
- package/dist/arena/iterate/types.d.ts +152 -0
- package/dist/arena/iterate/types.js +8 -0
- package/dist/arena/ledger.d.ts +47 -0
- package/dist/arena/ledger.js +151 -0
- package/dist/arena/lenses/architecture.d.ts +5 -0
- package/dist/arena/lenses/architecture.js +22 -0
- package/dist/arena/lenses/engineering.d.ts +5 -0
- package/dist/arena/lenses/engineering.js +22 -0
- package/dist/arena/lenses/general.d.ts +5 -0
- package/dist/arena/lenses/general.js +20 -0
- package/dist/arena/lenses/index.d.ts +16 -0
- package/dist/arena/lenses/index.js +47 -0
- package/dist/arena/lenses/product.d.ts +5 -0
- package/dist/arena/lenses/product.js +22 -0
- package/dist/arena/model-presets.d.ts +23 -0
- package/dist/arena/model-presets.js +44 -0
- package/dist/arena/phases/adjudication.d.ts +24 -0
- package/dist/arena/phases/adjudication.js +144 -0
- package/dist/arena/phases/build-consensus.d.ts +29 -0
- package/dist/arena/phases/build-consensus.js +86 -0
- package/dist/arena/phases/claim-registry.d.ts +26 -0
- package/dist/arena/phases/claim-registry.js +60 -0
- package/dist/arena/phases/cross-review.d.ts +45 -0
- package/dist/arena/phases/cross-review.js +224 -0
- package/dist/arena/phases/debate-rounds.d.ts +27 -0
- package/dist/arena/phases/debate-rounds.js +162 -0
- package/dist/arena/phases/participant-research.d.ts +38 -0
- package/dist/arena/phases/participant-research.js +317 -0
- package/dist/arena/phases/planning-detail-expansion.d.ts +38 -0
- package/dist/arena/phases/planning-detail-expansion.js +121 -0
- package/dist/arena/planner.d.ts +27 -0
- package/dist/arena/planner.js +312 -0
- package/dist/arena/providers/docs.d.ts +6 -0
- package/dist/arena/providers/docs.js +108 -0
- package/dist/arena/providers/git.d.ts +8 -0
- package/dist/arena/providers/git.js +174 -0
- package/dist/arena/providers/index.d.ts +32 -0
- package/dist/arena/providers/index.js +132 -0
- package/dist/arena/providers/none.d.ts +7 -0
- package/dist/arena/providers/none.js +11 -0
- package/dist/arena/providers/repo.d.ts +6 -0
- package/dist/arena/providers/repo.js +255 -0
- package/dist/arena/render/session.d.ts +17 -0
- package/dist/arena/render/session.js +190 -0
- package/dist/arena/render/terminal.d.ts +34 -0
- package/dist/arena/render/terminal.js +286 -0
- package/dist/arena/strategies/discussion.d.ts +25 -0
- package/dist/arena/strategies/discussion.js +143 -0
- package/dist/arena/strategies/index.d.ts +15 -0
- package/dist/arena/strategies/index.js +28 -0
- package/dist/arena/strategies/language-wrapper.d.ts +17 -0
- package/dist/arena/strategies/language-wrapper.js +102 -0
- package/dist/arena/strategies/lens-wrapper.d.ts +16 -0
- package/dist/arena/strategies/lens-wrapper.js +236 -0
- package/dist/arena/strategies/planning.d.ts +30 -0
- package/dist/arena/strategies/planning.js +225 -0
- package/dist/arena/strategies/review.d.ts +26 -0
- package/dist/arena/strategies/review.js +168 -0
- package/dist/arena/strategies/utils.d.ts +39 -0
- package/dist/arena/strategies/utils.js +647 -0
- package/dist/arena/tools/selector.d.ts +17 -0
- package/dist/arena/tools/selector.js +61 -0
- package/dist/arena/transitions.d.ts +48 -0
- package/dist/arena/transitions.js +92 -0
- package/dist/arena/types.d.ts +508 -0
- package/dist/arena/types.js +27 -0
- package/dist/cli/agent-server-stdio.d.ts +32 -0
- package/dist/cli/agent-server-stdio.js +116 -0
- package/dist/colorizer.d.ts +23 -0
- package/dist/colorizer.js +12 -0
- package/dist/context/compaction.d.ts +116 -0
- package/dist/context/compaction.js +534 -0
- package/dist/context/manager.d.ts +145 -0
- package/dist/context/manager.js +423 -0
- package/dist/context/token-counter.d.ts +27 -0
- package/dist/context/token-counter.js +91 -0
- package/dist/context/tool-result-storage.d.ts +96 -0
- package/dist/context/tool-result-storage.js +296 -0
- package/dist/cost-tracker.d.ts +64 -0
- package/dist/cost-tracker.js +314 -0
- package/dist/cron/scheduler.d.ts +34 -0
- package/dist/cron/scheduler.js +115 -0
- package/dist/data/deepseek-models.json +46 -0
- package/dist/data/gemini-models.json +67 -0
- package/dist/data/openai-models.json +175 -0
- package/dist/data/openrouter-models.d.ts +35 -0
- package/dist/data/openrouter-models.js +36 -0
- package/dist/data/openrouter-models.json +4626 -0
- package/dist/data/openrouter-sync.d.ts +16 -0
- package/dist/data/openrouter-sync.js +53 -0
- package/dist/data/static-catalogs.d.ts +25 -0
- package/dist/data/static-catalogs.js +26 -0
- package/dist/data/zai-models.json +56 -0
- package/dist/engine/cost-store.d.ts +22 -0
- package/dist/engine/cost-store.js +15 -0
- package/dist/engine/engine.d.ts +295 -0
- package/dist/engine/engine.js +1467 -0
- package/dist/engine/model-facade.d.ts +24 -0
- package/dist/engine/model-facade.js +194 -0
- package/dist/engine/parse-task.d.ts +59 -0
- package/dist/engine/parse-task.js +135 -0
- package/dist/engine/patch-orphaned-tools.d.ts +52 -0
- package/dist/engine/patch-orphaned-tools.js +95 -0
- package/dist/engine/query.d.ts +50 -0
- package/dist/engine/query.js +107 -0
- package/dist/engine/runtime.d.ts +50 -0
- package/dist/engine/runtime.js +59 -0
- package/dist/engine/streaming-tool-queue.d.ts +34 -0
- package/dist/engine/streaming-tool-queue.js +61 -0
- package/dist/engine/token-budget.d.ts +22 -0
- package/dist/engine/token-budget.js +40 -0
- package/dist/engine/tool-summary.d.ts +13 -0
- package/dist/engine/tool-summary.js +35 -0
- package/dist/engine/turn-loop.d.ts +122 -0
- package/dist/engine/turn-loop.js +602 -0
- package/dist/engine/turn-state.d.ts +20 -0
- package/dist/engine/turn-state.js +17 -0
- package/dist/exceptions.d.ts +61 -0
- package/dist/exceptions.js +116 -0
- package/dist/git/utils.d.ts +35 -0
- package/dist/git/utils.js +98 -0
- package/dist/git/worktree.d.ts +36 -0
- package/dist/git/worktree.js +139 -0
- package/dist/hooks/events.d.ts +114 -0
- package/dist/hooks/events.js +4 -0
- package/dist/hooks/inject.d.ts +19 -0
- package/dist/hooks/inject.js +29 -0
- package/dist/hooks/registry.d.ts +15 -0
- package/dist/hooks/registry.js +84 -0
- package/dist/hooks/shell-runner.d.ts +45 -0
- package/dist/hooks/shell-runner.js +173 -0
- package/dist/index.d.ts +117 -0
- package/dist/index.js +145 -0
- package/dist/llm/api-key-sanitize.d.ts +22 -0
- package/dist/llm/api-key-sanitize.js +81 -0
- package/dist/llm/capabilities/index.d.ts +20 -0
- package/dist/llm/capabilities/index.js +39 -0
- package/dist/llm/capabilities/rules.d.ts +26 -0
- package/dist/llm/capabilities/rules.js +215 -0
- package/dist/llm/capabilities/types.d.ts +114 -0
- package/dist/llm/capabilities/types.js +24 -0
- package/dist/llm/client-base.d.ts +29 -0
- package/dist/llm/client-base.js +137 -0
- package/dist/llm/client-factory.d.ts +10 -0
- package/dist/llm/client-factory.js +29 -0
- package/dist/llm/model-cache.d.ts +21 -0
- package/dist/llm/model-cache.js +46 -0
- package/dist/llm/model-fetcher.d.ts +29 -0
- package/dist/llm/model-fetcher.js +282 -0
- package/dist/llm/model-pool.d.ts +95 -0
- package/dist/llm/model-pool.js +246 -0
- package/dist/llm/provider-catalog.d.ts +32 -0
- package/dist/llm/provider-catalog.js +50 -0
- package/dist/llm/provider-kinds.d.ts +21 -0
- package/dist/llm/provider-kinds.js +132 -0
- package/dist/llm/providers/anthropic.d.ts +19 -0
- package/dist/llm/providers/anthropic.js +267 -0
- package/dist/llm/providers/openai.d.ts +64 -0
- package/dist/llm/providers/openai.js +606 -0
- package/dist/llm/retry.d.ts +12 -0
- package/dist/llm/retry.js +17 -0
- package/dist/llm/stream-watchdog.d.ts +42 -0
- package/dist/llm/stream-watchdog.js +70 -0
- package/dist/llm/token-counter.d.ts +17 -0
- package/dist/llm/token-counter.js +36 -0
- package/dist/llm/types.d.ts +37 -0
- package/dist/llm/types.js +4 -0
- package/dist/logging/logger.d.ts +109 -0
- package/dist/logging/logger.js +390 -0
- package/dist/logging/sanitize-messages.d.ts +42 -0
- package/dist/logging/sanitize-messages.js +150 -0
- package/dist/logging/session-recorder.d.ts +90 -0
- package/dist/logging/session-recorder.js +304 -0
- package/dist/lsp/client.d.ts +41 -0
- package/dist/lsp/client.js +166 -0
- package/dist/lsp/manager.d.ts +40 -0
- package/dist/lsp/manager.js +124 -0
- package/dist/lsp/servers.d.ts +16 -0
- package/dist/lsp/servers.js +60 -0
- package/dist/migrate-models.d.ts +45 -0
- package/dist/migrate-models.js +179 -0
- package/dist/onboarding.d.ts +189 -0
- package/dist/onboarding.js +625 -0
- package/dist/plugins/gitOps.d.ts +32 -0
- package/dist/plugins/gitOps.js +62 -0
- package/dist/plugins/installedPlugins.d.ts +15 -0
- package/dist/plugins/installedPlugins.js +56 -0
- package/dist/plugins/knownMarketplaces.d.ts +10 -0
- package/dist/plugins/knownMarketplaces.js +46 -0
- package/dist/plugins/loadPluginHooks.d.ts +52 -0
- package/dist/plugins/loadPluginHooks.js +162 -0
- package/dist/plugins/marketplaceManager.d.ts +49 -0
- package/dist/plugins/marketplaceManager.js +142 -0
- package/dist/plugins/parseMarketplaceInput.d.ts +16 -0
- package/dist/plugins/parseMarketplaceInput.js +73 -0
- package/dist/plugins/pluginCommandHook.d.ts +54 -0
- package/dist/plugins/pluginCommandHook.js +180 -0
- package/dist/plugins/pluginCommandsLoader.d.ts +25 -0
- package/dist/plugins/pluginCommandsLoader.js +114 -0
- package/dist/plugins/pluginInstaller.d.ts +36 -0
- package/dist/plugins/pluginInstaller.js +228 -0
- package/dist/plugins/schemas.d.ts +9 -0
- package/dist/plugins/schemas.js +136 -0
- package/dist/plugins/types.d.ts +75 -0
- package/dist/plugins/types.js +7 -0
- package/dist/plugins/varRewrite.d.ts +42 -0
- package/dist/plugins/varRewrite.js +129 -0
- package/dist/preset/index.d.ts +60 -0
- package/dist/preset/index.js +159 -0
- package/dist/product/define.d.ts +60 -0
- package/dist/product/define.js +123 -0
- package/dist/product/index.d.ts +5 -0
- package/dist/product/index.js +4 -0
- package/dist/product/types.d.ts +111 -0
- package/dist/product/types.js +21 -0
- package/dist/prompt/composer.d.ts +49 -0
- package/dist/prompt/composer.js +168 -0
- package/dist/prompt/instruction-scanner.d.ts +54 -0
- package/dist/prompt/instruction-scanner.js +187 -0
- package/dist/prompt/section-cache.d.ts +15 -0
- package/dist/prompt/section-cache.js +31 -0
- package/dist/prompt/section-loader.d.ts +26 -0
- package/dist/prompt/section-loader.js +53 -0
- package/dist/prompt/sections/base.md +35 -0
- package/dist/prompt/sections/coding.md +31 -0
- package/dist/prompt/sections/orchestration.md +16 -0
- package/dist/prompt/sections/tone.md +9 -0
- package/dist/protocol/chat-session-manager.d.ts +33 -0
- package/dist/protocol/chat-session-manager.js +65 -0
- package/dist/protocol/chat-session.d.ts +49 -0
- package/dist/protocol/chat-session.js +86 -0
- package/dist/protocol/client.d.ts +104 -0
- package/dist/protocol/client.js +260 -0
- package/dist/protocol/factories.d.ts +93 -0
- package/dist/protocol/factories.js +64 -0
- package/dist/protocol/helpers.d.ts +42 -0
- package/dist/protocol/helpers.js +55 -0
- package/dist/protocol/index.d.ts +4 -0
- package/dist/protocol/index.js +4 -0
- package/dist/protocol/server.d.ts +80 -0
- package/dist/protocol/server.js +855 -0
- package/dist/protocol/transport.d.ts +37 -0
- package/dist/protocol/transport.js +85 -0
- package/dist/protocol/types.d.ts +221 -0
- package/dist/protocol/types.js +61 -0
- package/dist/remote/bridge.d.ts +37 -0
- package/dist/remote/bridge.js +103 -0
- package/dist/run/ArtifactTracker.d.ts +38 -0
- package/dist/run/ArtifactTracker.js +132 -0
- package/dist/run/CheckpointWriter.d.ts +53 -0
- package/dist/run/CheckpointWriter.js +135 -0
- package/dist/run/EngineRunner.d.ts +72 -0
- package/dist/run/EngineRunner.js +119 -0
- package/dist/run/Evaluator.d.ts +56 -0
- package/dist/run/Evaluator.js +62 -0
- package/dist/run/FileRunStore.d.ts +39 -0
- package/dist/run/FileRunStore.js +176 -0
- package/dist/run/Heartbeat.d.ts +54 -0
- package/dist/run/Heartbeat.js +123 -0
- package/dist/run/RunApprovalBackend.d.ts +53 -0
- package/dist/run/RunApprovalBackend.js +85 -0
- package/dist/run/RunLock.d.ts +40 -0
- package/dist/run/RunLock.js +98 -0
- package/dist/run/RunManager.d.ts +82 -0
- package/dist/run/RunManager.js +587 -0
- package/dist/run/RunQueue.d.ts +27 -0
- package/dist/run/RunQueue.js +73 -0
- package/dist/run/RunStore.d.ts +25 -0
- package/dist/run/RunStore.js +9 -0
- package/dist/run/factory.d.ts +63 -0
- package/dist/run/factory.js +51 -0
- package/dist/run/index.d.ts +17 -0
- package/dist/run/index.js +23 -0
- package/dist/run/types.d.ts +136 -0
- package/dist/run/types.js +28 -0
- package/dist/runtime/safe-spawn.d.ts +118 -0
- package/dist/runtime/safe-spawn.js +268 -0
- package/dist/services/analytics.d.ts +29 -0
- package/dist/services/analytics.js +84 -0
- package/dist/services/auto-dream.d.ts +49 -0
- package/dist/services/auto-dream.js +124 -0
- package/dist/services/diagnostics.d.ts +41 -0
- package/dist/services/diagnostics.js +99 -0
- package/dist/services/extract-memories.d.ts +31 -0
- package/dist/services/extract-memories.js +71 -0
- package/dist/services/index.d.ts +11 -0
- package/dist/services/index.js +17 -0
- package/dist/services/memory-orchestrator.d.ts +60 -0
- package/dist/services/memory-orchestrator.js +133 -0
- package/dist/services/notifier.d.ts +25 -0
- package/dist/services/notifier.js +69 -0
- package/dist/services/oauth.d.ts +27 -0
- package/dist/services/oauth.js +153 -0
- package/dist/services/session-memory.d.ts +37 -0
- package/dist/services/session-memory.js +81 -0
- package/dist/session/file-history.d.ts +41 -0
- package/dist/session/file-history.js +115 -0
- package/dist/session/memory.d.ts +104 -0
- package/dist/session/memory.js +310 -0
- package/dist/session/session-manager.d.ts +41 -0
- package/dist/session/session-manager.js +261 -0
- package/dist/session/transcript.d.ts +39 -0
- package/dist/session/transcript.js +186 -0
- package/dist/settings/manager.d.ts +36 -0
- package/dist/settings/manager.js +187 -0
- package/dist/settings/schema.d.ts +1219 -0
- package/dist/settings/schema.js +246 -0
- package/dist/skills/frontmatter.d.ts +13 -0
- package/dist/skills/frontmatter.js +70 -0
- package/dist/skills/index.d.ts +7 -0
- package/dist/skills/index.js +6 -0
- package/dist/skills/scanner.d.ts +31 -0
- package/dist/skills/scanner.js +171 -0
- package/dist/state.d.ts +160 -0
- package/dist/state.js +267 -0
- package/dist/tool-system/builtin/agent-notifications.d.ts +84 -0
- package/dist/tool-system/builtin/agent-notifications.js +197 -0
- package/dist/tool-system/builtin/agent-registry.d.ts +67 -0
- package/dist/tool-system/builtin/agent-registry.js +126 -0
- package/dist/tool-system/builtin/agent-transcript-translator.d.ts +22 -0
- package/dist/tool-system/builtin/agent-transcript-translator.js +160 -0
- package/dist/tool-system/builtin/agent.d.ts +16 -0
- package/dist/tool-system/builtin/agent.js +364 -0
- package/dist/tool-system/builtin/apply-patch/applier.d.ts +26 -0
- package/dist/tool-system/builtin/apply-patch/applier.js +250 -0
- package/dist/tool-system/builtin/apply-patch/index.d.ts +20 -0
- package/dist/tool-system/builtin/apply-patch/index.js +101 -0
- package/dist/tool-system/builtin/apply-patch/parser.d.ts +17 -0
- package/dist/tool-system/builtin/apply-patch/parser.js +212 -0
- package/dist/tool-system/builtin/apply-patch/seek-sequence.d.ts +18 -0
- package/dist/tool-system/builtin/apply-patch/seek-sequence.js +123 -0
- package/dist/tool-system/builtin/apply-patch/types.d.ts +49 -0
- package/dist/tool-system/builtin/apply-patch/types.js +13 -0
- package/dist/tool-system/builtin/arena.d.ts +31 -0
- package/dist/tool-system/builtin/arena.js +416 -0
- package/dist/tool-system/builtin/ask-user.d.ts +20 -0
- package/dist/tool-system/builtin/ask-user.js +99 -0
- package/dist/tool-system/builtin/bash.d.ts +21 -0
- package/dist/tool-system/builtin/bash.js +149 -0
- package/dist/tool-system/builtin/brief.d.ts +6 -0
- package/dist/tool-system/builtin/brief.js +41 -0
- package/dist/tool-system/builtin/config.d.ts +6 -0
- package/dist/tool-system/builtin/config.js +67 -0
- package/dist/tool-system/builtin/cron.d.ts +10 -0
- package/dist/tool-system/builtin/cron.js +61 -0
- package/dist/tool-system/builtin/edit.d.ts +6 -0
- package/dist/tool-system/builtin/edit.js +100 -0
- package/dist/tool-system/builtin/file-cache.d.ts +11 -0
- package/dist/tool-system/builtin/file-cache.js +39 -0
- package/dist/tool-system/builtin/glob.d.ts +7 -0
- package/dist/tool-system/builtin/glob.js +76 -0
- package/dist/tool-system/builtin/grep.d.ts +7 -0
- package/dist/tool-system/builtin/grep.js +150 -0
- package/dist/tool-system/builtin/index.d.ts +20 -0
- package/dist/tool-system/builtin/index.js +449 -0
- package/dist/tool-system/builtin/lsp.d.ts +6 -0
- package/dist/tool-system/builtin/lsp.js +141 -0
- package/dist/tool-system/builtin/mcp-tools.d.ts +10 -0
- package/dist/tool-system/builtin/mcp-tools.js +102 -0
- package/dist/tool-system/builtin/memory.d.ts +26 -0
- package/dist/tool-system/builtin/memory.js +226 -0
- package/dist/tool-system/builtin/notebook-edit.d.ts +6 -0
- package/dist/tool-system/builtin/notebook-edit.js +124 -0
- package/dist/tool-system/builtin/plan.d.ts +15 -0
- package/dist/tool-system/builtin/plan.js +55 -0
- package/dist/tool-system/builtin/powershell.d.ts +11 -0
- package/dist/tool-system/builtin/powershell.js +64 -0
- package/dist/tool-system/builtin/read.d.ts +6 -0
- package/dist/tool-system/builtin/read.js +70 -0
- package/dist/tool-system/builtin/remote-trigger.d.ts +6 -0
- package/dist/tool-system/builtin/remote-trigger.js +54 -0
- package/dist/tool-system/builtin/repl.d.ts +11 -0
- package/dist/tool-system/builtin/repl.js +82 -0
- package/dist/tool-system/builtin/send-message.d.ts +6 -0
- package/dist/tool-system/builtin/send-message.js +47 -0
- package/dist/tool-system/builtin/skill-prompt.d.ts +20 -0
- package/dist/tool-system/builtin/skill-prompt.js +52 -0
- package/dist/tool-system/builtin/skill.d.ts +9 -0
- package/dist/tool-system/builtin/skill.js +55 -0
- package/dist/tool-system/builtin/sleep.d.ts +6 -0
- package/dist/tool-system/builtin/sleep.js +33 -0
- package/dist/tool-system/builtin/task.d.ts +48 -0
- package/dist/tool-system/builtin/task.js +139 -0
- package/dist/tool-system/builtin/tool-search.d.ts +11 -0
- package/dist/tool-system/builtin/tool-search.js +90 -0
- package/dist/tool-system/builtin/web-fetch.d.ts +10 -0
- package/dist/tool-system/builtin/web-fetch.js +328 -0
- package/dist/tool-system/builtin/web-search.d.ts +25 -0
- package/dist/tool-system/builtin/web-search.js +174 -0
- package/dist/tool-system/builtin/worktree.d.ts +10 -0
- package/dist/tool-system/builtin/worktree.js +95 -0
- package/dist/tool-system/builtin/write.d.ts +6 -0
- package/dist/tool-system/builtin/write.js +36 -0
- package/dist/tool-system/context.d.ts +165 -0
- package/dist/tool-system/context.js +18 -0
- package/dist/tool-system/executor.d.ts +49 -0
- package/dist/tool-system/executor.js +495 -0
- package/dist/tool-system/investigation-guard.d.ts +46 -0
- package/dist/tool-system/investigation-guard.js +155 -0
- package/dist/tool-system/mcp-manager.d.ts +67 -0
- package/dist/tool-system/mcp-manager.js +249 -0
- package/dist/tool-system/permission.d.ts +111 -0
- package/dist/tool-system/permission.js +774 -0
- package/dist/tool-system/registry.d.ts +32 -0
- package/dist/tool-system/registry.js +131 -0
- package/dist/tool-system/sandbox/bwrap.d.ts +13 -0
- package/dist/tool-system/sandbox/bwrap.js +63 -0
- package/dist/tool-system/sandbox/index.d.ts +78 -0
- package/dist/tool-system/sandbox/index.js +222 -0
- package/dist/tool-system/sandbox/off.d.ts +2 -0
- package/dist/tool-system/sandbox/off.js +8 -0
- package/dist/tool-system/sandbox/seatbelt.d.ts +18 -0
- package/dist/tool-system/sandbox/seatbelt.js +109 -0
- package/dist/tool-system/task-guard.d.ts +29 -0
- package/dist/tool-system/task-guard.js +70 -0
- package/dist/tool-system/validation.d.ts +5 -0
- package/dist/tool-system/validation.js +39 -0
- package/dist/types.d.ts +376 -0
- package/dist/types.js +4 -0
- package/dist/updater.d.ts +65 -0
- package/dist/updater.js +405 -0
- package/dist/utils/debug.d.ts +41 -0
- package/dist/utils/debug.js +110 -0
- package/dist/utils/earlyInput.d.ts +43 -0
- package/dist/utils/earlyInput.js +166 -0
- package/dist/utils/env.d.ts +24 -0
- package/dist/utils/env.js +104 -0
- package/dist/utils/envUtils.d.ts +51 -0
- package/dist/utils/envUtils.js +135 -0
- package/dist/utils/execFileNoThrow.d.ts +39 -0
- package/dist/utils/execFileNoThrow.js +74 -0
- package/dist/utils/format.d.ts +44 -0
- package/dist/utils/format.js +236 -0
- package/dist/utils/intl.d.ts +22 -0
- package/dist/utils/intl.js +83 -0
- package/dist/utils/lockfile.d.ts +15 -0
- package/dist/utils/lockfile.js +30 -0
- package/dist/utils/memoize.d.ts +19 -0
- package/dist/utils/memoize.js +14 -0
- package/dist/utils/semver.d.ts +6 -0
- package/dist/utils/semver.js +13 -0
- package/dist/utils/sliceAnsi.d.ts +12 -0
- package/dist/utils/sliceAnsi.js +62 -0
- package/dist/utils/systemTheme.d.ts +40 -0
- package/dist/utils/systemTheme.js +108 -0
- package/dist/utils/task-sanitizer.d.ts +6 -0
- package/dist/utils/task-sanitizer.js +24 -0
- package/dist/utils/theme.d.ts +93 -0
- package/dist/utils/theme.js +544 -0
- package/dist/utils/toolDisplay.d.ts +31 -0
- package/dist/utils/toolDisplay.js +188 -0
- package/package.json +72 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool-result persistence — write large tool_result content to disk and
|
|
3
|
+
* replace the in-context message with a reference + preview.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors Claude Code's services/compact/microcompact.ts + utils/toolResultStorage.ts
|
|
6
|
+
* approach, simplified for codeshell:
|
|
7
|
+
*
|
|
8
|
+
* • One file per tool_use_id (UUID), so the same id always maps to the
|
|
9
|
+
* same file — guarantees byte-identical preview on every turn.
|
|
10
|
+
* • Decision state (ContentReplacementState) is held by the caller and
|
|
11
|
+
* mutated in place. Once a result is "seen", its fate is frozen for
|
|
12
|
+
* the rest of the session (prevents flapping replacement choices that
|
|
13
|
+
* would constantly invalidate the prompt prefix).
|
|
14
|
+
* • No transcript persistence / no fork-subagent gap-fill. Resume just
|
|
15
|
+
* re-derives the seenIds set from the loaded messages.
|
|
16
|
+
*
|
|
17
|
+
* Strategy:
|
|
18
|
+
* • Per-result cap (DEFAULT_PERSIST_THRESHOLD): when a single tool_result
|
|
19
|
+
* exceeds it, persist + replace.
|
|
20
|
+
* • Per-message aggregate cap (PER_MESSAGE_AGGREGATE_CAP): when a single
|
|
21
|
+
* user message's tool_results together exceed it (e.g. a batch of
|
|
22
|
+
* parallel Read results), persist the largest ones first until under.
|
|
23
|
+
*/
|
|
24
|
+
import type { Message } from "../types.js";
|
|
25
|
+
/** Per-result threshold. Larger than this → persist + replace. */
|
|
26
|
+
export declare const DEFAULT_PERSIST_THRESHOLD = 50000;
|
|
27
|
+
/** Per-message aggregate cap (sum of tool_result content sizes in one user msg). */
|
|
28
|
+
export declare const PER_MESSAGE_AGGREGATE_CAP = 200000;
|
|
29
|
+
/** Preview length included in the replacement string. */
|
|
30
|
+
export declare const PREVIEW_SIZE = 2000;
|
|
31
|
+
/**
|
|
32
|
+
* Per-session decision state for tool-result persistence.
|
|
33
|
+
*
|
|
34
|
+
* seenIds — every tool_use_id we've evaluated; once seen, its fate
|
|
35
|
+
* (persisted or not) is fixed for the rest of the session.
|
|
36
|
+
* replacements — subset of seenIds that were persisted, mapped to the
|
|
37
|
+
* EXACT replacement string sent to the model. Re-applying
|
|
38
|
+
* is a Map lookup, never re-reads the file, guarantees
|
|
39
|
+
* byte-identical output.
|
|
40
|
+
*/
|
|
41
|
+
export interface ContentReplacementState {
|
|
42
|
+
seenIds: Set<string>;
|
|
43
|
+
replacements: Map<string, string>;
|
|
44
|
+
}
|
|
45
|
+
export declare function createContentReplacementState(): ContentReplacementState;
|
|
46
|
+
/**
|
|
47
|
+
* Rebuild a state object by walking the loaded message history.
|
|
48
|
+
* Used on resume so the budget makes the same decisions it made before.
|
|
49
|
+
* Replacements are taken from the messages themselves (we identify them
|
|
50
|
+
* by the PERSISTED_OPEN sentinel), so we don't need a side-channel log.
|
|
51
|
+
*/
|
|
52
|
+
export declare function reconstructContentReplacementState(messages: Message[]): ContentReplacementState;
|
|
53
|
+
/**
|
|
54
|
+
* Resolve the directory tool results are written to, given the engine's
|
|
55
|
+
* transcript path. Layout: <transcriptDir>/tool-results/
|
|
56
|
+
*/
|
|
57
|
+
export declare function resolveToolResultsDir(transcriptPath: string): string;
|
|
58
|
+
interface PersistOptions {
|
|
59
|
+
/** Per-result threshold; default DEFAULT_PERSIST_THRESHOLD. */
|
|
60
|
+
perResultThreshold?: number;
|
|
61
|
+
/** Per-message aggregate cap; default PER_MESSAGE_AGGREGATE_CAP. */
|
|
62
|
+
perMessageCap?: number;
|
|
63
|
+
/** Directory to write tool-result files to. Required. */
|
|
64
|
+
toolResultsDir: string;
|
|
65
|
+
/** Decision state, mutated in place. */
|
|
66
|
+
state: ContentReplacementState;
|
|
67
|
+
/** Optional callback fired when a result is freshly persisted. */
|
|
68
|
+
onPersist?: (info: {
|
|
69
|
+
toolUseId: string;
|
|
70
|
+
filepath: string;
|
|
71
|
+
originalSize: number;
|
|
72
|
+
reason: "per-result-cap" | "per-message-budget";
|
|
73
|
+
}) => void;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Walk each user message, decide which tool_result blocks should be
|
|
77
|
+
* persisted (per-result cap OR per-message aggregate), persist them,
|
|
78
|
+
* and return a new message array with those blocks replaced.
|
|
79
|
+
*
|
|
80
|
+
* Frozen decisions:
|
|
81
|
+
* - If a tool_use_id is already in state.replacements, that exact
|
|
82
|
+
* replacement is re-applied (no I/O).
|
|
83
|
+
* - If it's in state.seenIds but NOT replacements, it was decided
|
|
84
|
+
* "don't persist" on an earlier pass — leave it unreplaced even if
|
|
85
|
+
* it now exceeds the threshold (changing the decision mid-session
|
|
86
|
+
* would invalidate any model state built on the prior content).
|
|
87
|
+
*
|
|
88
|
+
* @returns the new messages array, with replacements applied.
|
|
89
|
+
*/
|
|
90
|
+
export declare function applyToolResultPersistence(messages: Message[], options: PersistOptions): Message[];
|
|
91
|
+
/**
|
|
92
|
+
* Public test helper: check whether content already wears the persisted
|
|
93
|
+
* sentinel. Used by tests to assert idempotency.
|
|
94
|
+
*/
|
|
95
|
+
export declare function isPersistedReplacement(s: string): boolean;
|
|
96
|
+
export {};
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool-result persistence — write large tool_result content to disk and
|
|
3
|
+
* replace the in-context message with a reference + preview.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors Claude Code's services/compact/microcompact.ts + utils/toolResultStorage.ts
|
|
6
|
+
* approach, simplified for codeshell:
|
|
7
|
+
*
|
|
8
|
+
* • One file per tool_use_id (UUID), so the same id always maps to the
|
|
9
|
+
* same file — guarantees byte-identical preview on every turn.
|
|
10
|
+
* • Decision state (ContentReplacementState) is held by the caller and
|
|
11
|
+
* mutated in place. Once a result is "seen", its fate is frozen for
|
|
12
|
+
* the rest of the session (prevents flapping replacement choices that
|
|
13
|
+
* would constantly invalidate the prompt prefix).
|
|
14
|
+
* • No transcript persistence / no fork-subagent gap-fill. Resume just
|
|
15
|
+
* re-derives the seenIds set from the loaded messages.
|
|
16
|
+
*
|
|
17
|
+
* Strategy:
|
|
18
|
+
* • Per-result cap (DEFAULT_PERSIST_THRESHOLD): when a single tool_result
|
|
19
|
+
* exceeds it, persist + replace.
|
|
20
|
+
* • Per-message aggregate cap (PER_MESSAGE_AGGREGATE_CAP): when a single
|
|
21
|
+
* user message's tool_results together exceed it (e.g. a batch of
|
|
22
|
+
* parallel Read results), persist the largest ones first until under.
|
|
23
|
+
*/
|
|
24
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
25
|
+
import { dirname, join } from "node:path";
|
|
26
|
+
import { logger } from "../logging/logger.js";
|
|
27
|
+
// ─── Tunables ───────────────────────────────────────────────────────
|
|
28
|
+
/** Per-result threshold. Larger than this → persist + replace. */
|
|
29
|
+
export const DEFAULT_PERSIST_THRESHOLD = 50_000;
|
|
30
|
+
/** Per-message aggregate cap (sum of tool_result content sizes in one user msg). */
|
|
31
|
+
export const PER_MESSAGE_AGGREGATE_CAP = 200_000;
|
|
32
|
+
/** Preview length included in the replacement string. */
|
|
33
|
+
export const PREVIEW_SIZE = 2_000;
|
|
34
|
+
/** Sentinel tags so re-runs detect "already-persisted" content. */
|
|
35
|
+
const PERSISTED_OPEN = "<persisted-output>";
|
|
36
|
+
const PERSISTED_CLOSE = "</persisted-output>";
|
|
37
|
+
const CLEARED_PREFIX = "[Old tool result cleared";
|
|
38
|
+
export function createContentReplacementState() {
|
|
39
|
+
return { seenIds: new Set(), replacements: new Map() };
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Rebuild a state object by walking the loaded message history.
|
|
43
|
+
* Used on resume so the budget makes the same decisions it made before.
|
|
44
|
+
* Replacements are taken from the messages themselves (we identify them
|
|
45
|
+
* by the PERSISTED_OPEN sentinel), so we don't need a side-channel log.
|
|
46
|
+
*/
|
|
47
|
+
export function reconstructContentReplacementState(messages) {
|
|
48
|
+
const state = createContentReplacementState();
|
|
49
|
+
for (const msg of messages) {
|
|
50
|
+
if (!Array.isArray(msg.content))
|
|
51
|
+
continue;
|
|
52
|
+
for (const block of msg.content) {
|
|
53
|
+
if (block.type !== "tool_result" || !block.tool_use_id)
|
|
54
|
+
continue;
|
|
55
|
+
state.seenIds.add(block.tool_use_id);
|
|
56
|
+
if (typeof block.content === "string" && block.content.startsWith(PERSISTED_OPEN)) {
|
|
57
|
+
state.replacements.set(block.tool_use_id, block.content);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return state;
|
|
62
|
+
}
|
|
63
|
+
// ─── Persistence ─────────────────────────────────────────────────────
|
|
64
|
+
/**
|
|
65
|
+
* Resolve the directory tool results are written to, given the engine's
|
|
66
|
+
* transcript path. Layout: <transcriptDir>/tool-results/
|
|
67
|
+
*/
|
|
68
|
+
export function resolveToolResultsDir(transcriptPath) {
|
|
69
|
+
return join(dirname(transcriptPath), "tool-results");
|
|
70
|
+
}
|
|
71
|
+
function ensureDir(dir) {
|
|
72
|
+
try {
|
|
73
|
+
mkdirSync(dir, { recursive: true });
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// Existing directory is fine.
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Write content to <dir>/<toolUseId>.txt. Idempotent: skips if the file
|
|
81
|
+
* already exists (tool_use_id is a UUID, content is deterministic per id).
|
|
82
|
+
*/
|
|
83
|
+
function persistToFile(dir, toolUseId, content) {
|
|
84
|
+
ensureDir(dir);
|
|
85
|
+
const filepath = join(dir, `${toolUseId}.txt`);
|
|
86
|
+
try {
|
|
87
|
+
// 'wx' = fail if exists. Skipping on collision is correct: same id =
|
|
88
|
+
// same content. Avoids re-writing the same bytes every turn.
|
|
89
|
+
writeFileSync(filepath, content, { encoding: "utf-8", flag: "wx" });
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
const code = err.code;
|
|
93
|
+
if (code !== "EEXIST") {
|
|
94
|
+
// Read-only FS (CI containers, ephemeral runtimes) hits EROFS/EACCES/
|
|
95
|
+
// ENOENT here on every large tool_result. The caller already catches
|
|
96
|
+
// and marks the id as seen so we don't re-attempt; degrade to debug
|
|
97
|
+
// so a headless run on a read-only FS doesn't flood the log with
|
|
98
|
+
// warnings. The block is left in-place untouched, which is the
|
|
99
|
+
// correct user-facing behavior.
|
|
100
|
+
logger.debug("tool_result.persist_failed", {
|
|
101
|
+
toolUseId,
|
|
102
|
+
code,
|
|
103
|
+
error: err.message,
|
|
104
|
+
});
|
|
105
|
+
throw err;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return filepath;
|
|
109
|
+
}
|
|
110
|
+
function buildReplacement(filepath, originalSize, content) {
|
|
111
|
+
const sizeKb = (originalSize / 1024).toFixed(1);
|
|
112
|
+
const previewRaw = content.slice(0, PREVIEW_SIZE);
|
|
113
|
+
// Cut at the last newline within the preview if there's one in the
|
|
114
|
+
// back half — avoids slicing mid-line which looks ugly to the model.
|
|
115
|
+
const lastNl = previewRaw.lastIndexOf("\n");
|
|
116
|
+
const preview = lastNl > PREVIEW_SIZE * 0.5 ? previewRaw.slice(0, lastNl) : previewRaw;
|
|
117
|
+
const hasMore = content.length > preview.length;
|
|
118
|
+
return (`${PERSISTED_OPEN}\n` +
|
|
119
|
+
`Output too large (${sizeKb} KB). Full output saved to: ${filepath}\n\n` +
|
|
120
|
+
`Preview (first ${preview.length} chars${hasMore ? ", truncated" : ""}):\n` +
|
|
121
|
+
preview +
|
|
122
|
+
(hasMore ? "\n..." : "") +
|
|
123
|
+
`\n${PERSISTED_CLOSE}`);
|
|
124
|
+
}
|
|
125
|
+
function collectCandidates(msg) {
|
|
126
|
+
if (!Array.isArray(msg.content))
|
|
127
|
+
return [];
|
|
128
|
+
const out = [];
|
|
129
|
+
for (const block of msg.content) {
|
|
130
|
+
if (block.type !== "tool_result" || !block.tool_use_id)
|
|
131
|
+
continue;
|
|
132
|
+
if (typeof block.content !== "string")
|
|
133
|
+
continue;
|
|
134
|
+
// Skip blocks already in a persisted/cleared sentinel — nothing to do
|
|
135
|
+
// and we must not re-persist (would change replacement strings →
|
|
136
|
+
// prompt cache miss).
|
|
137
|
+
if (block.content.startsWith(PERSISTED_OPEN) ||
|
|
138
|
+
block.content.startsWith(CLEARED_PREFIX))
|
|
139
|
+
continue;
|
|
140
|
+
out.push({
|
|
141
|
+
toolUseId: block.tool_use_id,
|
|
142
|
+
block,
|
|
143
|
+
content: block.content,
|
|
144
|
+
size: block.content.length,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
return out;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Walk each user message, decide which tool_result blocks should be
|
|
151
|
+
* persisted (per-result cap OR per-message aggregate), persist them,
|
|
152
|
+
* and return a new message array with those blocks replaced.
|
|
153
|
+
*
|
|
154
|
+
* Frozen decisions:
|
|
155
|
+
* - If a tool_use_id is already in state.replacements, that exact
|
|
156
|
+
* replacement is re-applied (no I/O).
|
|
157
|
+
* - If it's in state.seenIds but NOT replacements, it was decided
|
|
158
|
+
* "don't persist" on an earlier pass — leave it unreplaced even if
|
|
159
|
+
* it now exceeds the threshold (changing the decision mid-session
|
|
160
|
+
* would invalidate any model state built on the prior content).
|
|
161
|
+
*
|
|
162
|
+
* @returns the new messages array, with replacements applied.
|
|
163
|
+
*/
|
|
164
|
+
export function applyToolResultPersistence(messages, options) {
|
|
165
|
+
const { perResultThreshold = DEFAULT_PERSIST_THRESHOLD, perMessageCap = PER_MESSAGE_AGGREGATE_CAP, toolResultsDir, state, onPersist, } = options;
|
|
166
|
+
// Pass 1: figure out the replacement string for every block we need
|
|
167
|
+
// to change in this call. Walks each user msg independently — parallel
|
|
168
|
+
// tool results in different msgs don't combine for the aggregate cap.
|
|
169
|
+
const newReplacements = new Map();
|
|
170
|
+
for (const msg of messages) {
|
|
171
|
+
if (msg.role !== "user")
|
|
172
|
+
continue;
|
|
173
|
+
const candidates = collectCandidates(msg);
|
|
174
|
+
if (candidates.length === 0)
|
|
175
|
+
continue;
|
|
176
|
+
// Partition by prior decision.
|
|
177
|
+
const fresh = [];
|
|
178
|
+
for (const c of candidates) {
|
|
179
|
+
if (state.replacements.has(c.toolUseId)) {
|
|
180
|
+
// Already replaced — re-apply the cached string. (The block in
|
|
181
|
+
// `msg` might still hold the original content if we're seeing
|
|
182
|
+
// these messages for the first time this turn; the rewrite
|
|
183
|
+
// pass below picks up the cached replacement either way.)
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (state.seenIds.has(c.toolUseId)) {
|
|
187
|
+
// Seen and explicitly left alone before — frozen.
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
fresh.push(c);
|
|
191
|
+
}
|
|
192
|
+
if (fresh.length === 0)
|
|
193
|
+
continue;
|
|
194
|
+
// Per-result: anything individually over the threshold gets persisted.
|
|
195
|
+
const toPersist = new Set();
|
|
196
|
+
for (const c of fresh) {
|
|
197
|
+
if (c.size > perResultThreshold) {
|
|
198
|
+
toPersist.add(c.toolUseId);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Per-message: if the total (frozen + fresh) still exceeds the cap,
|
|
202
|
+
// pick more from the largest remaining fresh blocks until under.
|
|
203
|
+
const frozenSize = candidates
|
|
204
|
+
.filter((c) => state.seenIds.has(c.toolUseId) && !state.replacements.has(c.toolUseId))
|
|
205
|
+
.reduce((s, c) => s + c.size, 0);
|
|
206
|
+
let projected = frozenSize +
|
|
207
|
+
fresh.reduce((s, c) => s + (toPersist.has(c.toolUseId) ? 0 : c.size), 0);
|
|
208
|
+
if (projected > perMessageCap) {
|
|
209
|
+
const remaining = fresh
|
|
210
|
+
.filter((c) => !toPersist.has(c.toolUseId))
|
|
211
|
+
.sort((a, b) => b.size - a.size);
|
|
212
|
+
for (const c of remaining) {
|
|
213
|
+
if (projected <= perMessageCap)
|
|
214
|
+
break;
|
|
215
|
+
toPersist.add(c.toolUseId);
|
|
216
|
+
projected -= c.size;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// Persist + mark.
|
|
220
|
+
for (const c of fresh) {
|
|
221
|
+
if (toPersist.has(c.toolUseId)) {
|
|
222
|
+
try {
|
|
223
|
+
const filepath = persistToFile(toolResultsDir, c.toolUseId, c.content);
|
|
224
|
+
const replacement = buildReplacement(filepath, c.size, c.content);
|
|
225
|
+
state.replacements.set(c.toolUseId, replacement);
|
|
226
|
+
newReplacements.set(c.toolUseId, replacement);
|
|
227
|
+
state.seenIds.add(c.toolUseId);
|
|
228
|
+
onPersist?.({
|
|
229
|
+
toolUseId: c.toolUseId,
|
|
230
|
+
filepath,
|
|
231
|
+
originalSize: c.size,
|
|
232
|
+
reason: c.size > perResultThreshold ? "per-result-cap" : "per-message-budget",
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
// Persistence failed — leave block untouched, but mark seen so
|
|
237
|
+
// we don't try again next turn (and don't risk flapping if a
|
|
238
|
+
// transient FS issue clears up).
|
|
239
|
+
state.seenIds.add(c.toolUseId);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
// Decided "don't persist" → freeze that decision.
|
|
244
|
+
state.seenIds.add(c.toolUseId);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// Pass 2: rewrite messages. For every tool_result whose id is in
|
|
249
|
+
// state.replacements, swap content for the cached replacement string.
|
|
250
|
+
if (state.replacements.size === 0)
|
|
251
|
+
return messages;
|
|
252
|
+
let mutated = false;
|
|
253
|
+
const out = messages.map((msg) => {
|
|
254
|
+
if (msg.role !== "user" || !Array.isArray(msg.content))
|
|
255
|
+
return msg;
|
|
256
|
+
let blockChanged = false;
|
|
257
|
+
const newContent = msg.content.map((block) => {
|
|
258
|
+
if (block.type !== "tool_result" || !block.tool_use_id)
|
|
259
|
+
return block;
|
|
260
|
+
const replacement = state.replacements.get(block.tool_use_id);
|
|
261
|
+
if (replacement === undefined)
|
|
262
|
+
return block;
|
|
263
|
+
if (block.content === replacement)
|
|
264
|
+
return block;
|
|
265
|
+
// microcompact may have already cleared this block to a fingerprint.
|
|
266
|
+
// Don't roll it back — that would cause persistence and microcompact
|
|
267
|
+
// to overwrite each other every turn, doing 2 redundant rewrites on
|
|
268
|
+
// a stable end-state. The cleared fingerprint is the legitimate
|
|
269
|
+
// downstream form; leave it alone.
|
|
270
|
+
if (typeof block.content === "string" &&
|
|
271
|
+
block.content.startsWith(CLEARED_PREFIX)) {
|
|
272
|
+
return block;
|
|
273
|
+
}
|
|
274
|
+
blockChanged = true;
|
|
275
|
+
return { ...block, content: replacement };
|
|
276
|
+
});
|
|
277
|
+
if (!blockChanged)
|
|
278
|
+
return msg;
|
|
279
|
+
mutated = true;
|
|
280
|
+
return { ...msg, content: newContent };
|
|
281
|
+
});
|
|
282
|
+
if (mutated && newReplacements.size > 0) {
|
|
283
|
+
logger.info("tool_result.persisted", {
|
|
284
|
+
count: newReplacements.size,
|
|
285
|
+
ids: [...newReplacements.keys()],
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
return mutated ? out : messages;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Public test helper: check whether content already wears the persisted
|
|
292
|
+
* sentinel. Used by tests to assert idempotency.
|
|
293
|
+
*/
|
|
294
|
+
export function isPersistedReplacement(s) {
|
|
295
|
+
return s.startsWith(PERSISTED_OPEN);
|
|
296
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cost tracker — tracks token usage and calculates estimated costs.
|
|
3
|
+
*/
|
|
4
|
+
import { type Colorizer } from "./colorizer.js";
|
|
5
|
+
export interface UsageRecord {
|
|
6
|
+
model: string;
|
|
7
|
+
promptTokens: number;
|
|
8
|
+
completionTokens: number;
|
|
9
|
+
cacheReadTokens: number;
|
|
10
|
+
cacheWriteTokens: number;
|
|
11
|
+
totalTokens: number;
|
|
12
|
+
timestamp: number;
|
|
13
|
+
isSubAgent?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare class CostTracker {
|
|
16
|
+
private records;
|
|
17
|
+
private sessionStart;
|
|
18
|
+
private _hasUnknownModel;
|
|
19
|
+
record(model: string, promptTokens: number, completionTokens: number, isSubAgent?: boolean, cacheReadTokens?: number, cacheWriteTokens?: number): void;
|
|
20
|
+
getTotalTokens(): {
|
|
21
|
+
prompt: number;
|
|
22
|
+
completion: number;
|
|
23
|
+
total: number;
|
|
24
|
+
};
|
|
25
|
+
getEstimatedCost(): number;
|
|
26
|
+
getRequestCount(): number;
|
|
27
|
+
getSessionDuration(): number;
|
|
28
|
+
/** Estimate cost for a specific set of tokens without recording them. */
|
|
29
|
+
estimateForTokens(model: string, promptTokens: number, completionTokens: number, cacheReadTokens?: number, cacheWriteTokens?: number): number;
|
|
30
|
+
/**
|
|
31
|
+
* Get total cache token counts.
|
|
32
|
+
*/
|
|
33
|
+
getCacheTokens(): {
|
|
34
|
+
cacheRead: number;
|
|
35
|
+
cacheWrite: number;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Format a styled cost summary for terminal display.
|
|
39
|
+
*/
|
|
40
|
+
formatSummary(c?: Colorizer): string;
|
|
41
|
+
/**
|
|
42
|
+
* Format a compact one-line cost display for the prompt footer.
|
|
43
|
+
*/
|
|
44
|
+
formatCompact(c?: Colorizer): string;
|
|
45
|
+
reset(): void;
|
|
46
|
+
/** Serialize cost state for session persistence. */
|
|
47
|
+
serialize(): SessionCostState;
|
|
48
|
+
/** Restore cost state from a previous session. */
|
|
49
|
+
restore(state: SessionCostState): void;
|
|
50
|
+
}
|
|
51
|
+
export interface SessionCostState {
|
|
52
|
+
records: UsageRecord[];
|
|
53
|
+
sessionStart: number;
|
|
54
|
+
totalPromptTokens: number;
|
|
55
|
+
totalCompletionTokens: number;
|
|
56
|
+
estimatedCost: number;
|
|
57
|
+
}
|
|
58
|
+
export declare const costTracker: CostTracker;
|
|
59
|
+
/**
|
|
60
|
+
* Wire the LLM base-class usage hook into the singleton cost tracker.
|
|
61
|
+
* Called once from main.ts so every LLM call (REPL, run, arena, sub-agents)
|
|
62
|
+
* records into a single tracker without each call site having to remember.
|
|
63
|
+
*/
|
|
64
|
+
export declare function installCostTracking(): Promise<void>;
|