@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,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model call facade — wraps LLM client with transcript integration.
|
|
3
|
+
*/
|
|
4
|
+
import type { LLMClientBase } from "../llm/client-base.js";
|
|
5
|
+
import type { Message, ToolDefinition, LLMResponse, StreamCallback } from "../types.js";
|
|
6
|
+
import { Transcript } from "../session/transcript.js";
|
|
7
|
+
export declare class ModelFacade {
|
|
8
|
+
private readonly client;
|
|
9
|
+
private readonly transcript;
|
|
10
|
+
constructor(client: LLMClientBase, transcript: Transcript);
|
|
11
|
+
call(systemPrompt: string, messages: Message[], tools: ToolDefinition[], onStream?: StreamCallback, signal?: AbortSignal): Promise<LLMResponse>;
|
|
12
|
+
/**
|
|
13
|
+
* Call without streaming — used as fallback when streaming fails.
|
|
14
|
+
*/
|
|
15
|
+
callWithoutStreaming(systemPrompt: string, messages: Message[], tools: ToolDefinition[], signal?: AbortSignal): Promise<LLMResponse>;
|
|
16
|
+
/** Record API timing and token usage to bootstrap state. */
|
|
17
|
+
private recordUsage;
|
|
18
|
+
/** Optional summarize function for tool use summaries. */
|
|
19
|
+
summarize?: (systemPrompt: string, userMessage: string) => Promise<string>;
|
|
20
|
+
/** Get cumulative output tokens (for token budget). */
|
|
21
|
+
getOutputTokens?(): number;
|
|
22
|
+
private recordResponse;
|
|
23
|
+
getUsage(): import("../llm/types.js").LLMUsageTracker;
|
|
24
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model call facade — wraps LLM client with transcript integration.
|
|
3
|
+
*/
|
|
4
|
+
import { logger, getCurrentSid } from "../logging/logger.js";
|
|
5
|
+
import { recordLLMError, recordLLMRequest, recordLLMResponse, } from "../logging/session-recorder.js";
|
|
6
|
+
import { sanitizeMessages } from "../logging/sanitize-messages.js";
|
|
7
|
+
import { addAPIDuration, addToModelUsage, addInputTokens, addOutputTokens } from "../state.js";
|
|
8
|
+
let _reqSeq = 0;
|
|
9
|
+
function nextReqId() {
|
|
10
|
+
_reqSeq += 1;
|
|
11
|
+
return `r${_reqSeq.toString(36)}`;
|
|
12
|
+
}
|
|
13
|
+
export class ModelFacade {
|
|
14
|
+
client;
|
|
15
|
+
transcript;
|
|
16
|
+
constructor(client, transcript) {
|
|
17
|
+
this.client = client;
|
|
18
|
+
this.transcript = transcript;
|
|
19
|
+
}
|
|
20
|
+
async call(systemPrompt, messages, tools, onStream, signal) {
|
|
21
|
+
const startMs = Date.now();
|
|
22
|
+
const msgCount = messages.length;
|
|
23
|
+
const sid = getCurrentSid();
|
|
24
|
+
const reqId = nextReqId();
|
|
25
|
+
recordLLMRequest(sid, {
|
|
26
|
+
provider: this.client.provider ?? "?",
|
|
27
|
+
model: this.client.model ?? "?",
|
|
28
|
+
stream: true,
|
|
29
|
+
// Image base64 payloads stay out of recorded prompts — see
|
|
30
|
+
// logging/sanitize-messages.ts. Transcripts keep the full bytes
|
|
31
|
+
// (needed for replay); logs do not.
|
|
32
|
+
messages: sanitizeMessages(messages),
|
|
33
|
+
tools,
|
|
34
|
+
systemPrompt,
|
|
35
|
+
}, reqId);
|
|
36
|
+
let response;
|
|
37
|
+
try {
|
|
38
|
+
response = await this.client.createMessage({
|
|
39
|
+
systemPrompt,
|
|
40
|
+
messages,
|
|
41
|
+
tools,
|
|
42
|
+
stream: true,
|
|
43
|
+
onChunk: (chunk) => {
|
|
44
|
+
if (!onStream)
|
|
45
|
+
return;
|
|
46
|
+
if (chunk.type === "text" && chunk.text) {
|
|
47
|
+
onStream({ type: "text_delta", text: chunk.text, tokens: chunk.tokens });
|
|
48
|
+
}
|
|
49
|
+
else if (chunk.type === "tool_use_start" && chunk.toolCall) {
|
|
50
|
+
// Forward tool_use_start immediately so the UI can show progress
|
|
51
|
+
// while JSON args are still streaming
|
|
52
|
+
onStream({
|
|
53
|
+
type: "tool_use_start",
|
|
54
|
+
toolCall: {
|
|
55
|
+
id: chunk.toolCall.id ?? "",
|
|
56
|
+
toolName: chunk.toolCall.toolName ?? "",
|
|
57
|
+
args: chunk.toolCall.args ?? {},
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
else if (chunk.type === "tool_use_delta" && chunk.toolCall?.id) {
|
|
62
|
+
onStream({
|
|
63
|
+
type: "tool_use_args_delta",
|
|
64
|
+
toolCallId: chunk.toolCall.id,
|
|
65
|
+
args: chunk.toolCall.args ?? {},
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
signal,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
recordLLMError(sid, reqId, err, Date.now() - startMs);
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
const latencyMs = Date.now() - startMs;
|
|
77
|
+
logger.info("llm.request", {
|
|
78
|
+
stream: true,
|
|
79
|
+
latencyMs,
|
|
80
|
+
msgCount,
|
|
81
|
+
stopReason: response.stopReason,
|
|
82
|
+
toolCalls: response.toolCalls.length,
|
|
83
|
+
textLen: response.text?.length ?? 0,
|
|
84
|
+
usage: response.usage,
|
|
85
|
+
});
|
|
86
|
+
recordLLMResponse(sid, {
|
|
87
|
+
text: response.text,
|
|
88
|
+
toolCalls: response.toolCalls,
|
|
89
|
+
stopReason: response.stopReason,
|
|
90
|
+
usage: response.usage,
|
|
91
|
+
durationMs: latencyMs,
|
|
92
|
+
}, reqId);
|
|
93
|
+
this.recordUsage(response, latencyMs);
|
|
94
|
+
this.recordResponse(response);
|
|
95
|
+
return response;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Call without streaming — used as fallback when streaming fails.
|
|
99
|
+
*/
|
|
100
|
+
async callWithoutStreaming(systemPrompt, messages, tools, signal) {
|
|
101
|
+
const startMs = Date.now();
|
|
102
|
+
const msgCount = messages.length;
|
|
103
|
+
const sid = getCurrentSid();
|
|
104
|
+
const reqId = nextReqId();
|
|
105
|
+
recordLLMRequest(sid, {
|
|
106
|
+
provider: this.client.provider ?? "?",
|
|
107
|
+
model: this.client.model ?? "?",
|
|
108
|
+
stream: false,
|
|
109
|
+
// Image base64 payloads stay out of recorded prompts — same rule
|
|
110
|
+
// as the streaming path above.
|
|
111
|
+
messages: sanitizeMessages(messages),
|
|
112
|
+
tools,
|
|
113
|
+
systemPrompt,
|
|
114
|
+
}, reqId);
|
|
115
|
+
let response;
|
|
116
|
+
try {
|
|
117
|
+
response = await this.client.createMessage({
|
|
118
|
+
systemPrompt,
|
|
119
|
+
messages,
|
|
120
|
+
tools,
|
|
121
|
+
stream: false,
|
|
122
|
+
signal,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
recordLLMError(sid, reqId, err, Date.now() - startMs);
|
|
127
|
+
throw err;
|
|
128
|
+
}
|
|
129
|
+
const latencyMs = Date.now() - startMs;
|
|
130
|
+
logger.info("llm.request", {
|
|
131
|
+
stream: false,
|
|
132
|
+
latencyMs,
|
|
133
|
+
msgCount,
|
|
134
|
+
stopReason: response.stopReason,
|
|
135
|
+
toolCalls: response.toolCalls.length,
|
|
136
|
+
textLen: response.text?.length ?? 0,
|
|
137
|
+
usage: response.usage,
|
|
138
|
+
});
|
|
139
|
+
recordLLMResponse(sid, {
|
|
140
|
+
text: response.text,
|
|
141
|
+
toolCalls: response.toolCalls,
|
|
142
|
+
stopReason: response.stopReason,
|
|
143
|
+
usage: response.usage,
|
|
144
|
+
durationMs: latencyMs,
|
|
145
|
+
}, reqId);
|
|
146
|
+
this.recordUsage(response, latencyMs);
|
|
147
|
+
this.recordResponse(response);
|
|
148
|
+
return response;
|
|
149
|
+
}
|
|
150
|
+
/** Record API timing and token usage to bootstrap state. */
|
|
151
|
+
recordUsage(response, latencyMs) {
|
|
152
|
+
addAPIDuration(latencyMs);
|
|
153
|
+
const u = response.usage;
|
|
154
|
+
if (u) {
|
|
155
|
+
addInputTokens(u.promptTokens ?? 0);
|
|
156
|
+
addOutputTokens(u.completionTokens ?? 0);
|
|
157
|
+
addToModelUsage(this.client.model ?? "unknown", u.promptTokens ?? 0, u.completionTokens ?? 0, u.cacheReadTokens ?? 0, u.cacheCreationTokens ?? 0);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/** Optional summarize function for tool use summaries. */
|
|
161
|
+
summarize;
|
|
162
|
+
recordResponse(response) {
|
|
163
|
+
if (response.text || response.toolCalls.length > 0 || response.reasoningContent) {
|
|
164
|
+
const contentBlocks = [];
|
|
165
|
+
// DeepSeek V4 thinking mode emits reasoning_content alongside the
|
|
166
|
+
// reply; we echo it back on the next turn so the model can resume
|
|
167
|
+
// its chain of thought. Persist as a dedicated block so transcript
|
|
168
|
+
// -> message round-tripping preserves it without mixing into
|
|
169
|
+
// displayable text. Goes first so it sits adjacent to the
|
|
170
|
+
// assistant turn it belongs to even after compaction.
|
|
171
|
+
if (response.reasoningContent) {
|
|
172
|
+
contentBlocks.push({
|
|
173
|
+
type: "reasoning",
|
|
174
|
+
reasoningContent: response.reasoningContent,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
if (response.text) {
|
|
178
|
+
contentBlocks.push({ type: "text", text: response.text });
|
|
179
|
+
}
|
|
180
|
+
for (const tc of response.toolCalls) {
|
|
181
|
+
contentBlocks.push({
|
|
182
|
+
type: "tool_use",
|
|
183
|
+
id: tc.id,
|
|
184
|
+
name: tc.toolName,
|
|
185
|
+
input: tc.args,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
this.transcript.appendMessage("assistant", contentBlocks);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
getUsage() {
|
|
192
|
+
return this.client.getUsage();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a single-string `task` for inline image attachments.
|
|
3
|
+
*
|
|
4
|
+
* Desktop's composer encodes images as `<codeshell-image>` blocks before
|
|
5
|
+
* sending — see `packages/desktop/src/renderer/chat/attachments.ts` —
|
|
6
|
+
* because the agent-server-stdio RPC schema only carries a `task: string`.
|
|
7
|
+
* The engine recovers the structured form here before handing the message
|
|
8
|
+
* to the LLM client.
|
|
9
|
+
*
|
|
10
|
+
* Wire format (one block per image):
|
|
11
|
+
*
|
|
12
|
+
* <codeshell-image mime="image/png" name="screenshot.png">
|
|
13
|
+
* data:image/png;base64,iVBORw0KGgo…
|
|
14
|
+
* </codeshell-image>
|
|
15
|
+
*
|
|
16
|
+
* Multiple blocks may appear interleaved with regular text — preserved
|
|
17
|
+
* order matters because some prompts reference "the second image".
|
|
18
|
+
*
|
|
19
|
+
* Pure / no I/O. Pure-text tasks (no `<codeshell-image>` substring) hit
|
|
20
|
+
* a single non-matching indexOf check and return immediately, so CLI / TUI
|
|
21
|
+
* callers pay essentially nothing.
|
|
22
|
+
*/
|
|
23
|
+
export interface ParsedImage {
|
|
24
|
+
/** MIME type as declared in the block opening tag. */
|
|
25
|
+
mime: string;
|
|
26
|
+
/** Original file name (may be empty). HTML-attr-escaped on the wire; unescaped here. */
|
|
27
|
+
name: string;
|
|
28
|
+
/** Full `data:<mime>;base64,<…>` URL — handy for OpenAI-compat clients. */
|
|
29
|
+
dataUrl: string;
|
|
30
|
+
/** Just the base64 payload, with the data-URL prefix stripped. */
|
|
31
|
+
base64: string;
|
|
32
|
+
}
|
|
33
|
+
export interface ParsedTask {
|
|
34
|
+
/** Remaining plain-text portion (image blocks removed, surrounding whitespace trimmed). */
|
|
35
|
+
text: string;
|
|
36
|
+
/** Images in the order they appeared in the source. */
|
|
37
|
+
images: ParsedImage[];
|
|
38
|
+
/** Convenience flag — true iff `images.length > 0`. */
|
|
39
|
+
hasImages: boolean;
|
|
40
|
+
}
|
|
41
|
+
export declare class ImageParseError extends Error {
|
|
42
|
+
constructor(message: string);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Parse `<codeshell-image>` blocks out of `task`.
|
|
46
|
+
*
|
|
47
|
+
* Behavior:
|
|
48
|
+
* - No marker substring → fast return, no allocations beyond the
|
|
49
|
+
* `ParsedTask` shell.
|
|
50
|
+
* - One or more well-formed blocks → blocks removed from `text`,
|
|
51
|
+
* surrounding whitespace collapsed, blocks accumulated in `images`
|
|
52
|
+
* in source order.
|
|
53
|
+
* - Malformed block (e.g. unclosed tag, missing data URL) → throws
|
|
54
|
+
* {@link ImageParseError}. Callers decide whether to drop or fail
|
|
55
|
+
* the run, but **silent fallback is intentionally not provided** —
|
|
56
|
+
* dropping image bytes on the floor was the failure mode this whole
|
|
57
|
+
* pipeline exists to prevent.
|
|
58
|
+
*/
|
|
59
|
+
export declare function parseTaskWithImages(task: string): ParsedTask;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a single-string `task` for inline image attachments.
|
|
3
|
+
*
|
|
4
|
+
* Desktop's composer encodes images as `<codeshell-image>` blocks before
|
|
5
|
+
* sending — see `packages/desktop/src/renderer/chat/attachments.ts` —
|
|
6
|
+
* because the agent-server-stdio RPC schema only carries a `task: string`.
|
|
7
|
+
* The engine recovers the structured form here before handing the message
|
|
8
|
+
* to the LLM client.
|
|
9
|
+
*
|
|
10
|
+
* Wire format (one block per image):
|
|
11
|
+
*
|
|
12
|
+
* <codeshell-image mime="image/png" name="screenshot.png">
|
|
13
|
+
* data:image/png;base64,iVBORw0KGgo…
|
|
14
|
+
* </codeshell-image>
|
|
15
|
+
*
|
|
16
|
+
* Multiple blocks may appear interleaved with regular text — preserved
|
|
17
|
+
* order matters because some prompts reference "the second image".
|
|
18
|
+
*
|
|
19
|
+
* Pure / no I/O. Pure-text tasks (no `<codeshell-image>` substring) hit
|
|
20
|
+
* a single non-matching indexOf check and return immediately, so CLI / TUI
|
|
21
|
+
* callers pay essentially nothing.
|
|
22
|
+
*/
|
|
23
|
+
export class ImageParseError extends Error {
|
|
24
|
+
constructor(message) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.name = "ImageParseError";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const IMAGE_BLOCK_MARKER = "<codeshell-image";
|
|
30
|
+
/**
|
|
31
|
+
* Pulled out so the regex compiles once. Captures:
|
|
32
|
+
* 1 = raw attribute string (everything between `<codeshell-image` and the
|
|
33
|
+
* closing `>` of the opening tag)
|
|
34
|
+
* 2 = body (everything between the opening tag and `</codeshell-image>`)
|
|
35
|
+
*
|
|
36
|
+
* Anchored loosely — we tolerate whitespace inside the opening tag and
|
|
37
|
+
* around the body, which is what the desktop encoder produces.
|
|
38
|
+
*/
|
|
39
|
+
const IMAGE_BLOCK_RE = /<codeshell-image\b([^>]*)>([\s\S]*?)<\/codeshell-image>/g;
|
|
40
|
+
const ATTR_RE = /(\w+)\s*=\s*"([^"]*)"/g;
|
|
41
|
+
/**
|
|
42
|
+
* Reverse of the desktop encoder's `escapeAttr` so file names with `&`
|
|
43
|
+
* or quotes round-trip cleanly.
|
|
44
|
+
*/
|
|
45
|
+
function unescapeAttr(s) {
|
|
46
|
+
return s
|
|
47
|
+
.replace(/"/g, '"')
|
|
48
|
+
.replace(/</g, "<")
|
|
49
|
+
.replace(/>/g, ">")
|
|
50
|
+
.replace(/&/g, "&");
|
|
51
|
+
}
|
|
52
|
+
function parseAttrs(raw) {
|
|
53
|
+
const out = {};
|
|
54
|
+
ATTR_RE.lastIndex = 0;
|
|
55
|
+
let m;
|
|
56
|
+
while ((m = ATTR_RE.exec(raw)) !== null) {
|
|
57
|
+
out[m[1].toLowerCase()] = unescapeAttr(m[2]);
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
const DATA_URL_RE = /^data:([^;,]+);base64,([A-Za-z0-9+/=\s]+)$/;
|
|
62
|
+
function parseDataUrl(body) {
|
|
63
|
+
const trimmed = body.trim();
|
|
64
|
+
const m = DATA_URL_RE.exec(trimmed);
|
|
65
|
+
if (!m) {
|
|
66
|
+
throw new ImageParseError("image block body is not a data URL of the form `data:<mime>;base64,<…>`");
|
|
67
|
+
}
|
|
68
|
+
const mime = m[1].trim();
|
|
69
|
+
// Strip ALL whitespace from the base64 portion — wire format may contain
|
|
70
|
+
// newlines inserted for readability. The base64 grammar tolerates none.
|
|
71
|
+
const base64 = m[2].replace(/\s+/g, "");
|
|
72
|
+
if (base64.length === 0) {
|
|
73
|
+
throw new ImageParseError("image block body has an empty base64 payload");
|
|
74
|
+
}
|
|
75
|
+
return { mime, base64 };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Parse `<codeshell-image>` blocks out of `task`.
|
|
79
|
+
*
|
|
80
|
+
* Behavior:
|
|
81
|
+
* - No marker substring → fast return, no allocations beyond the
|
|
82
|
+
* `ParsedTask` shell.
|
|
83
|
+
* - One or more well-formed blocks → blocks removed from `text`,
|
|
84
|
+
* surrounding whitespace collapsed, blocks accumulated in `images`
|
|
85
|
+
* in source order.
|
|
86
|
+
* - Malformed block (e.g. unclosed tag, missing data URL) → throws
|
|
87
|
+
* {@link ImageParseError}. Callers decide whether to drop or fail
|
|
88
|
+
* the run, but **silent fallback is intentionally not provided** —
|
|
89
|
+
* dropping image bytes on the floor was the failure mode this whole
|
|
90
|
+
* pipeline exists to prevent.
|
|
91
|
+
*/
|
|
92
|
+
export function parseTaskWithImages(task) {
|
|
93
|
+
if (typeof task !== "string" || task.indexOf(IMAGE_BLOCK_MARKER) === -1) {
|
|
94
|
+
return { text: task ?? "", images: [], hasImages: false };
|
|
95
|
+
}
|
|
96
|
+
// Defensively reject the orphaned-opening-tag case before delegating to
|
|
97
|
+
// the matcher: a `<codeshell-image …>` with no matching `</codeshell-image>`
|
|
98
|
+
// is exactly the "browser hung up mid-paste" failure mode this parser
|
|
99
|
+
// exists to surface, not swallow.
|
|
100
|
+
const openingMatches = task.match(/<codeshell-image\b/g) ?? [];
|
|
101
|
+
const closingMatches = task.match(/<\/codeshell-image>/g) ?? [];
|
|
102
|
+
if (openingMatches.length !== closingMatches.length) {
|
|
103
|
+
throw new ImageParseError(`unbalanced <codeshell-image> tags: ${openingMatches.length} opening vs ${closingMatches.length} closing`);
|
|
104
|
+
}
|
|
105
|
+
const images = [];
|
|
106
|
+
IMAGE_BLOCK_RE.lastIndex = 0;
|
|
107
|
+
const textWithoutImages = task.replace(IMAGE_BLOCK_RE, (_match, attrsRaw, body) => {
|
|
108
|
+
const attrs = parseAttrs(attrsRaw);
|
|
109
|
+
const { mime, base64 } = parseDataUrl(body);
|
|
110
|
+
const declaredMime = attrs.mime?.trim();
|
|
111
|
+
// Prefer the opening-tag attribute when it disagrees with the data URL's
|
|
112
|
+
// self-declared type — the attribute is what the desktop validator gated
|
|
113
|
+
// on, so it's the "source of truth" the rest of the pipeline expects.
|
|
114
|
+
const finalMime = declaredMime && declaredMime.length > 0 ? declaredMime : mime;
|
|
115
|
+
images.push({
|
|
116
|
+
mime: finalMime,
|
|
117
|
+
name: attrs.name ?? "",
|
|
118
|
+
dataUrl: `data:${finalMime};base64,${base64}`,
|
|
119
|
+
base64,
|
|
120
|
+
});
|
|
121
|
+
return "";
|
|
122
|
+
});
|
|
123
|
+
// Collapse the whitespace the removed blocks leave behind. Two passes:
|
|
124
|
+
// 1. Multiple blank lines (3+ newlines) → exactly two newlines, so the
|
|
125
|
+
// remaining prose retains paragraph breaks but doesn't look like a
|
|
126
|
+
// page of empty whitespace.
|
|
127
|
+
// 2. Trim leading/trailing whitespace introduced by a block at either
|
|
128
|
+
// end of the message.
|
|
129
|
+
const cleanedText = textWithoutImages.replace(/\n{3,}/g, "\n\n").trim();
|
|
130
|
+
return {
|
|
131
|
+
text: cleanedText,
|
|
132
|
+
images,
|
|
133
|
+
hasImages: images.length > 0,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* patchOrphanedToolUses — repair message sequences where an assistant
|
|
3
|
+
* `tool_use` block has no corresponding `tool_result`.
|
|
4
|
+
*
|
|
5
|
+
* Why this matters: OpenAI strictly enforces that every `tool_calls`
|
|
6
|
+
* entry on an assistant message is followed by a matching `role:"tool"`
|
|
7
|
+
* message (one per `tool_call_id`). An incomplete sequence triggers
|
|
8
|
+
* `400 An assistant message with 'tool_calls' must be followed by tool
|
|
9
|
+
* messages responding to each 'tool_call_id'`.
|
|
10
|
+
*
|
|
11
|
+
* The sequence can become incomplete in two ways:
|
|
12
|
+
* 1. The model called tools, the API call between turns failed before
|
|
13
|
+
* the executor wrote the results. TurnLoop already patches this
|
|
14
|
+
* mid-run (see turn-loop.ts), so the broken state only lives in
|
|
15
|
+
* memory.
|
|
16
|
+
* 2. The process crashed / was Ctrl+C'd after the assistant message
|
|
17
|
+
* was persisted to transcript.jsonl but before tool_result events
|
|
18
|
+
* were appended. On `/resume`, the loaded message array carries
|
|
19
|
+
* this gap into the next API call.
|
|
20
|
+
*
|
|
21
|
+
* This module is the resume-side counterpart: scan the entire loaded
|
|
22
|
+
* history (not just the tail), find every assistant→missing-result gap,
|
|
23
|
+
* inject a synthetic tool_result for each orphan in the correct
|
|
24
|
+
* position so the resulting sequence is valid for both Anthropic and
|
|
25
|
+
* OpenAI message shapes.
|
|
26
|
+
*
|
|
27
|
+
* Insertion strategy: we append the synthetic results as a NEW `user`
|
|
28
|
+
* message with `tool_result` blocks placed immediately after the
|
|
29
|
+
* assistant message that produced the orphan. This matches what the
|
|
30
|
+
* runtime would have written if execution had completed normally, and
|
|
31
|
+
* the OpenAI converter (providers/openai.ts) lifts each `tool_result`
|
|
32
|
+
* out to a separate `role:"tool"` message keyed by `tool_use_id` —
|
|
33
|
+
* exactly the shape the API requires.
|
|
34
|
+
*/
|
|
35
|
+
import type { Message } from "../types.js";
|
|
36
|
+
export interface PatchOrphanedSummary {
|
|
37
|
+
/** How many gaps were found across the whole history. */
|
|
38
|
+
gapsPatched: number;
|
|
39
|
+
/** Total synthetic tool_result blocks injected. */
|
|
40
|
+
toolResultsInjected: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Walk `messages` and, for every assistant message whose `tool_use`
|
|
44
|
+
* blocks lack corresponding `tool_result`s anywhere later in the array,
|
|
45
|
+
* splice a synthetic user→tool_result message right after it. Mutates
|
|
46
|
+
* `messages` in place and returns a summary so callers can log how
|
|
47
|
+
* much repair was needed.
|
|
48
|
+
*
|
|
49
|
+
* Idempotent: a second call on the same array is a no-op because the
|
|
50
|
+
* first pass already filled every gap.
|
|
51
|
+
*/
|
|
52
|
+
export declare function patchOrphanedToolUses(messages: Message[]): PatchOrphanedSummary;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* patchOrphanedToolUses — repair message sequences where an assistant
|
|
3
|
+
* `tool_use` block has no corresponding `tool_result`.
|
|
4
|
+
*
|
|
5
|
+
* Why this matters: OpenAI strictly enforces that every `tool_calls`
|
|
6
|
+
* entry on an assistant message is followed by a matching `role:"tool"`
|
|
7
|
+
* message (one per `tool_call_id`). An incomplete sequence triggers
|
|
8
|
+
* `400 An assistant message with 'tool_calls' must be followed by tool
|
|
9
|
+
* messages responding to each 'tool_call_id'`.
|
|
10
|
+
*
|
|
11
|
+
* The sequence can become incomplete in two ways:
|
|
12
|
+
* 1. The model called tools, the API call between turns failed before
|
|
13
|
+
* the executor wrote the results. TurnLoop already patches this
|
|
14
|
+
* mid-run (see turn-loop.ts), so the broken state only lives in
|
|
15
|
+
* memory.
|
|
16
|
+
* 2. The process crashed / was Ctrl+C'd after the assistant message
|
|
17
|
+
* was persisted to transcript.jsonl but before tool_result events
|
|
18
|
+
* were appended. On `/resume`, the loaded message array carries
|
|
19
|
+
* this gap into the next API call.
|
|
20
|
+
*
|
|
21
|
+
* This module is the resume-side counterpart: scan the entire loaded
|
|
22
|
+
* history (not just the tail), find every assistant→missing-result gap,
|
|
23
|
+
* inject a synthetic tool_result for each orphan in the correct
|
|
24
|
+
* position so the resulting sequence is valid for both Anthropic and
|
|
25
|
+
* OpenAI message shapes.
|
|
26
|
+
*
|
|
27
|
+
* Insertion strategy: we append the synthetic results as a NEW `user`
|
|
28
|
+
* message with `tool_result` blocks placed immediately after the
|
|
29
|
+
* assistant message that produced the orphan. This matches what the
|
|
30
|
+
* runtime would have written if execution had completed normally, and
|
|
31
|
+
* the OpenAI converter (providers/openai.ts) lifts each `tool_result`
|
|
32
|
+
* out to a separate `role:"tool"` message keyed by `tool_use_id` —
|
|
33
|
+
* exactly the shape the API requires.
|
|
34
|
+
*/
|
|
35
|
+
const SYNTHETIC_ERROR_TEXT = "Error: Tool execution did not complete (process interrupted or earlier API failure). " +
|
|
36
|
+
"This result was injected during session resume to keep the message sequence valid.";
|
|
37
|
+
/**
|
|
38
|
+
* Walk `messages` and, for every assistant message whose `tool_use`
|
|
39
|
+
* blocks lack corresponding `tool_result`s anywhere later in the array,
|
|
40
|
+
* splice a synthetic user→tool_result message right after it. Mutates
|
|
41
|
+
* `messages` in place and returns a summary so callers can log how
|
|
42
|
+
* much repair was needed.
|
|
43
|
+
*
|
|
44
|
+
* Idempotent: a second call on the same array is a no-op because the
|
|
45
|
+
* first pass already filled every gap.
|
|
46
|
+
*/
|
|
47
|
+
export function patchOrphanedToolUses(messages) {
|
|
48
|
+
const summary = { gapsPatched: 0, toolResultsInjected: 0 };
|
|
49
|
+
// Pre-compute the set of tool_result ids already answered anywhere in
|
|
50
|
+
// the history, then scan forward. Doing this in one pass avoids the
|
|
51
|
+
// O(n²) "for each assistant, scan tail" pattern in TurnLoop's
|
|
52
|
+
// single-shot version — resume sessions can be long.
|
|
53
|
+
const answeredIds = new Set();
|
|
54
|
+
for (const msg of messages) {
|
|
55
|
+
if (!Array.isArray(msg.content))
|
|
56
|
+
continue;
|
|
57
|
+
for (const block of msg.content) {
|
|
58
|
+
if (block.type === "tool_result" && block.tool_use_id) {
|
|
59
|
+
answeredIds.add(block.tool_use_id);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Walk left-to-right, splicing inserts immediately after the offending
|
|
64
|
+
// assistant message. We iterate by index and bump past the inserted
|
|
65
|
+
// message so we don't re-process it.
|
|
66
|
+
for (let i = 0; i < messages.length; i++) {
|
|
67
|
+
const msg = messages[i];
|
|
68
|
+
if (msg.role !== "assistant" || !Array.isArray(msg.content))
|
|
69
|
+
continue;
|
|
70
|
+
const orphanedIds = [];
|
|
71
|
+
for (const block of msg.content) {
|
|
72
|
+
if (block.type === "tool_use" && block.id && !answeredIds.has(block.id)) {
|
|
73
|
+
orphanedIds.push(block.id);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (orphanedIds.length === 0)
|
|
77
|
+
continue;
|
|
78
|
+
const errorBlocks = orphanedIds.map((id) => ({
|
|
79
|
+
type: "tool_result",
|
|
80
|
+
tool_use_id: id,
|
|
81
|
+
content: SYNTHETIC_ERROR_TEXT,
|
|
82
|
+
}));
|
|
83
|
+
messages.splice(i + 1, 0, { role: "user", content: errorBlocks });
|
|
84
|
+
// Mark these ids answered so a later assistant message referencing
|
|
85
|
+
// the same id (shouldn't happen with real id generation, but guards
|
|
86
|
+
// against bad transcripts) doesn't double-patch.
|
|
87
|
+
for (const id of orphanedIds)
|
|
88
|
+
answeredIds.add(id);
|
|
89
|
+
summary.gapsPatched += 1;
|
|
90
|
+
summary.toolResultsInjected += orphanedIds.length;
|
|
91
|
+
// Skip the synthetic message we just spliced in.
|
|
92
|
+
i += 1;
|
|
93
|
+
}
|
|
94
|
+
return summary;
|
|
95
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-level query API — async generator wrapping TurnLoop.
|
|
3
|
+
*
|
|
4
|
+
* Callers consume events via `for await (const event of query(params))`.
|
|
5
|
+
* This is the public entry point for running agentic queries; TurnLoop
|
|
6
|
+
* is the internal state machine.
|
|
7
|
+
*
|
|
8
|
+
* Adapted from restored-src/src/query.ts, simplified for Code Shell.
|
|
9
|
+
*/
|
|
10
|
+
import type { Message, StreamEvent, ToolDefinition, TerminalReason } from "../types.js";
|
|
11
|
+
import { type TurnLoopDeps } from "./turn-loop.js";
|
|
12
|
+
export interface QueryParams {
|
|
13
|
+
/** Initial message history (including the new user message). */
|
|
14
|
+
messages: Message[];
|
|
15
|
+
/** System prompt text. */
|
|
16
|
+
systemPrompt: string;
|
|
17
|
+
/** Available tool definitions. */
|
|
18
|
+
tools: ToolDefinition[];
|
|
19
|
+
/** Max turns before forced stop. */
|
|
20
|
+
maxTurns?: number;
|
|
21
|
+
/** Max tool calls per turn (default 20). */
|
|
22
|
+
maxToolCallsPerTurn?: number;
|
|
23
|
+
/** Abort signal for cancellation. */
|
|
24
|
+
signal?: AbortSignal;
|
|
25
|
+
/** Dependencies injected by the caller (engine). */
|
|
26
|
+
deps: QueryDeps;
|
|
27
|
+
}
|
|
28
|
+
export interface QueryDeps {
|
|
29
|
+
model: TurnLoopDeps["model"];
|
|
30
|
+
toolExecutor: TurnLoopDeps["toolExecutor"];
|
|
31
|
+
contextManager: TurnLoopDeps["contextManager"];
|
|
32
|
+
hooks: TurnLoopDeps["hooks"];
|
|
33
|
+
transcript: TurnLoopDeps["transcript"];
|
|
34
|
+
}
|
|
35
|
+
export interface QueryResult {
|
|
36
|
+
text: string;
|
|
37
|
+
reason: TerminalReason;
|
|
38
|
+
turnCount: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Run an agentic query and yield stream events as they occur.
|
|
42
|
+
*
|
|
43
|
+
* Usage:
|
|
44
|
+
* const events: StreamEvent[] = [];
|
|
45
|
+
* for await (const event of query(params)) {
|
|
46
|
+
* events.push(event);
|
|
47
|
+
* }
|
|
48
|
+
* // last event contains the final result
|
|
49
|
+
*/
|
|
50
|
+
export declare function query(params: QueryParams): AsyncGenerator<StreamEvent, QueryResult, undefined>;
|