@cjhyy/code-shell-core 0.7.1 → 0.8.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/README.md +36 -23
- package/dist/agent/agent-definition-registry.d.ts +2 -2
- package/dist/agent/agent-definition-registry.js +47 -10
- package/dist/agent/agent-definition.d.ts +5 -0
- package/dist/agent/agent-definition.js +14 -0
- package/dist/automation/index.d.ts +7 -4
- package/dist/automation/index.js +4 -2
- package/dist/automation/runner.js +3 -1
- package/dist/automation/scheduler.d.ts +57 -1
- package/dist/automation/scheduler.js +123 -23
- package/dist/automation/store.d.ts +6 -2
- package/dist/automation/store.js +7 -3
- package/dist/capabilities/index.d.ts +109 -0
- package/dist/capabilities/index.js +80 -0
- package/dist/capability-control/disabled-lists.d.ts +2 -1
- package/dist/capability-control/disabled-lists.js +3 -5
- package/dist/capability-control/overlay.d.ts +14 -1
- package/dist/capability-control/overlay.js +40 -0
- package/dist/capability-control/service.js +6 -4
- package/dist/cli/agent-server-stdio.d.ts +1 -1
- package/dist/cli/agent-server-stdio.js +66 -6
- package/dist/cli/agent-server-tcp.js +7 -3
- package/dist/context/compaction.d.ts +39 -3
- package/dist/context/compaction.js +151 -39
- package/dist/context/manager.d.ts +17 -1
- package/dist/context/manager.js +36 -1
- package/dist/credentials/access.d.ts +3 -1
- package/dist/credentials/access.js +24 -3
- package/dist/credentials/index.d.ts +1 -1
- package/dist/credentials/index.js +1 -1
- package/dist/credentials/oauth.d.ts +4 -1
- package/dist/credentials/oauth.js +14 -0
- package/dist/credentials/store.d.ts +15 -1
- package/dist/credentials/store.js +17 -4
- package/dist/credentials/types.d.ts +24 -0
- package/dist/credentials/use-credential-tool.js +15 -1
- package/dist/engine/auxiliary-pipeline.d.ts +40 -0
- package/dist/engine/auxiliary-pipeline.js +181 -0
- package/dist/{settings → engine}/disk-defaults.d.ts +2 -2
- package/dist/{settings → engine}/disk-defaults.js +5 -2
- package/dist/engine/dynamic-tool-defs.d.ts +4 -0
- package/dist/engine/dynamic-tool-defs.js +4 -0
- package/dist/engine/engine.d.ts +254 -195
- package/dist/engine/engine.js +1812 -2041
- package/dist/engine/file-history-hook.d.ts +11 -0
- package/dist/engine/file-history-hook.js +31 -0
- package/dist/engine/goal-judge-context.d.ts +9 -0
- package/dist/engine/goal-judge-context.js +234 -0
- package/dist/engine/injected-context-cache.d.ts +6 -0
- package/dist/engine/injected-context-cache.js +13 -0
- package/dist/engine/input-attachments.d.ts +1 -1
- package/dist/engine/model-facade.d.ts +3 -3
- package/dist/engine/model-facade.js +15 -14
- package/dist/engine/permission-controller.d.ts +55 -0
- package/dist/engine/permission-controller.js +148 -0
- package/dist/engine/prompt-cache-diagnostics.d.ts +58 -0
- package/dist/engine/prompt-cache-diagnostics.js +178 -0
- package/dist/engine/run-accounting.d.ts +41 -0
- package/dist/engine/run-accounting.js +126 -0
- package/dist/engine/run-context.d.ts +44 -0
- package/dist/engine/run-context.js +88 -0
- package/dist/engine/run-environment.d.ts +30 -0
- package/dist/engine/run-environment.js +77 -0
- package/dist/engine/run-finalize.d.ts +58 -0
- package/dist/engine/run-finalize.js +245 -0
- package/dist/engine/run-goal.d.ts +58 -0
- package/dist/engine/run-goal.js +188 -0
- package/dist/engine/run-image-input.d.ts +1 -1
- package/dist/engine/run-image-input.js +5 -3
- package/dist/engine/run-session-open.d.ts +41 -0
- package/dist/engine/run-session-open.js +186 -0
- package/dist/engine/run-setup.d.ts +42 -0
- package/dist/engine/run-setup.js +58 -0
- package/dist/engine/run-tooling.d.ts +125 -0
- package/dist/engine/run-tooling.js +283 -0
- package/dist/engine/run-types.d.ts +139 -0
- package/dist/engine/run-types.js +12 -0
- package/dist/engine/run-workspace.d.ts +50 -0
- package/dist/engine/run-workspace.js +114 -0
- package/dist/engine/steer-queue.d.ts +1 -1
- package/dist/engine/subagent-spawner.d.ts +32 -0
- package/dist/engine/subagent-spawner.js +287 -0
- package/dist/engine/tool-summary.d.ts +2 -2
- package/dist/engine/tool-summary.js +2 -2
- package/dist/engine/turn-loop.d.ts +49 -10
- package/dist/engine/turn-loop.js +370 -104
- package/dist/engine/types.d.ts +30 -3
- package/dist/engine/types.js +1 -1
- package/dist/{engine/goal.d.ts → goal/lifecycle.d.ts} +76 -4
- package/dist/goal/lifecycle.js +482 -0
- package/dist/hooks/events.d.ts +24 -10
- package/dist/hooks/goal-stop-hook.d.ts +17 -28
- package/dist/hooks/goal-stop-hook.js +110 -465
- package/dist/hooks/registry.js +1 -1
- package/dist/index.d.ts +48 -108
- package/dist/index.extension.d.ts +51 -0
- package/dist/index.extension.js +39 -0
- package/dist/index.internal.d.ts +86 -0
- package/dist/index.internal.js +92 -0
- package/dist/index.js +34 -123
- package/dist/links/cli.d.ts +48 -0
- package/dist/links/cli.js +617 -0
- package/dist/links/http.d.ts +40 -0
- package/dist/links/http.js +166 -0
- package/dist/links/index.d.ts +4 -0
- package/dist/links/index.js +3 -0
- package/dist/links/link-action-tool.d.ts +5 -0
- package/dist/links/link-action-tool.js +241 -0
- package/dist/links/providers.d.ts +8 -0
- package/dist/links/providers.js +665 -0
- package/dist/links/types.d.ts +44 -0
- package/dist/llm/client-base.d.ts +7 -0
- package/dist/llm/client-base.js +60 -0
- package/dist/llm/model-pool.d.ts +1 -1
- package/dist/llm/model-pool.js +1 -1
- package/dist/llm/providers/anthropic.d.ts +1 -0
- package/dist/llm/providers/anthropic.js +9 -0
- package/dist/llm/providers/openai.d.ts +1 -0
- package/dist/llm/providers/openai.js +17 -0
- package/dist/model-catalog/index.js +15 -2
- package/dist/model-catalog/resolve.d.ts +13 -1
- package/dist/model-catalog/resolve.js +37 -2
- package/dist/model-catalog/types.d.ts +74 -48
- package/dist/model-catalog/types.js +16 -5
- package/dist/model-catalog/upsert.d.ts +3 -1
- package/dist/model-catalog/upsert.js +9 -0
- package/dist/onboarding.d.ts +0 -1
- package/dist/onboarding.js +1 -22
- package/dist/panel-apps/bindings.d.ts +24 -0
- package/dist/panel-apps/bindings.js +69 -0
- package/dist/panel-apps/github-archive.d.ts +21 -0
- package/dist/panel-apps/github-archive.js +98 -0
- package/dist/panel-apps/index.d.ts +4 -0
- package/dist/panel-apps/index.js +4 -0
- package/dist/panel-apps/installer.d.ts +68 -0
- package/dist/panel-apps/installer.js +622 -0
- package/dist/panel-apps/manifest.d.ts +364 -0
- package/dist/panel-apps/manifest.js +189 -0
- package/dist/panel-apps/paths.d.ts +13 -0
- package/dist/panel-apps/paths.js +38 -0
- package/dist/panel-apps/registry.d.ts +51 -0
- package/dist/panel-apps/registry.js +99 -0
- package/dist/panel-apps/runtime.d.ts +80 -0
- package/dist/panel-apps/runtime.js +154 -0
- package/dist/plugins/gitOps.js +8 -1
- package/dist/plugins/installedPlugins.d.ts +2 -1
- package/dist/plugins/installedPlugins.js +146 -8
- package/dist/plugins/installer/codex/convertAgents.d.ts +4 -1
- package/dist/plugins/installer/codex/convertAgents.js +62 -8
- package/dist/plugins/installer/codex/convertCommands.d.ts +5 -5
- package/dist/plugins/installer/codex/convertCommands.js +35 -12
- package/dist/plugins/installer/codex/convertHooks.d.ts +10 -0
- package/dist/plugins/installer/codex/convertHooks.js +82 -0
- package/dist/plugins/installer/codex/convertSkills.js +41 -6
- package/dist/plugins/installer/install.d.ts +7 -1
- package/dist/plugins/installer/install.js +21 -87
- package/dist/plugins/installer/installFromArchive.d.ts +26 -4
- package/dist/plugins/installer/installFromArchive.js +44 -27
- package/dist/plugins/installer/installFromNpm.d.ts +31 -0
- package/dist/plugins/installer/installFromNpm.js +273 -0
- package/dist/plugins/installer/loadPluginAgents.js +17 -4
- package/dist/plugins/installer/loadPluginMcp.d.ts +14 -0
- package/dist/plugins/installer/loadPluginMcp.js +245 -35
- package/dist/plugins/installer/normalizeManifest.d.ts +13 -0
- package/dist/plugins/installer/normalizeManifest.js +306 -0
- package/dist/plugins/installer/npmTar.d.ts +13 -0
- package/dist/plugins/installer/npmTar.js +321 -0
- package/dist/plugins/installer/parseSource.d.ts +11 -0
- package/dist/plugins/installer/parseSource.js +48 -0
- package/dist/plugins/installer/preview.d.ts +101 -0
- package/dist/plugins/installer/preview.js +336 -0
- package/dist/plugins/installer/projectPluginSource.d.ts +14 -0
- package/dist/plugins/installer/projectPluginSource.js +140 -0
- package/dist/plugins/installer/types.d.ts +775 -0
- package/dist/plugins/installer/types.js +100 -0
- package/dist/plugins/installer/unzip.d.ts +11 -0
- package/dist/plugins/installer/unzip.js +123 -9
- package/dist/plugins/installer/update.d.ts +2 -2
- package/dist/plugins/installer/update.js +43 -4
- package/dist/plugins/loadPluginHooks.d.ts +19 -2
- package/dist/plugins/loadPluginHooks.js +97 -86
- package/dist/plugins/pluginAutomationTemplates.d.ts +18 -0
- package/dist/plugins/pluginAutomationTemplates.js +50 -0
- package/dist/plugins/pluginCatalog.d.ts +45 -0
- package/dist/plugins/pluginCatalog.js +87 -0
- package/dist/plugins/pluginCommandHook.d.ts +6 -0
- package/dist/plugins/pluginCommandHook.js +25 -8
- package/dist/plugins/pluginCommandsLoader.d.ts +19 -0
- package/dist/plugins/pluginCommandsLoader.js +181 -7
- package/dist/plugins/pluginContent.d.ts +10 -1
- package/dist/plugins/pluginContent.js +87 -30
- package/dist/plugins/pluginHookApproval.d.ts +30 -0
- package/dist/plugins/pluginHookApproval.js +160 -0
- package/dist/plugins/pluginHookIntegrity.d.ts +69 -0
- package/dist/plugins/pluginHookIntegrity.js +361 -0
- package/dist/plugins/pluginInstaller.js +71 -12
- package/dist/plugins/pluginMcpApproval.d.ts +19 -0
- package/dist/plugins/pluginMcpApproval.js +110 -0
- package/dist/plugins/pluginMcpIntegrity.d.ts +21 -0
- package/dist/plugins/pluginMcpIntegrity.js +74 -0
- package/dist/plugins/types.d.ts +30 -0
- package/dist/plugins/varRewrite.d.ts +9 -5
- package/dist/plugins/varRewrite.js +26 -17
- package/dist/preset/index.d.ts +11 -8
- package/dist/preset/index.js +62 -203
- package/dist/product/define.js +9 -3
- package/dist/product/types.d.ts +0 -2
- package/dist/profile/activation.d.ts +36 -0
- package/dist/profile/activation.js +57 -0
- package/dist/profile/catalog-store.d.ts +77 -0
- package/dist/profile/catalog-store.js +346 -0
- package/dist/profile/catalog.d.ts +54 -0
- package/dist/profile/catalog.js +152 -0
- package/dist/profile/index.d.ts +7 -0
- package/dist/profile/index.js +7 -0
- package/dist/profile/requirements.d.ts +76 -0
- package/dist/profile/requirements.js +117 -0
- package/dist/profile/resolve.d.ts +11 -0
- package/dist/profile/resolve.js +41 -0
- package/dist/profile/store.d.ts +17 -0
- package/dist/profile/store.js +167 -0
- package/dist/profile/types.d.ts +321 -0
- package/dist/profile/types.js +104 -0
- package/dist/prompt/composer.d.ts +46 -7
- package/dist/prompt/composer.js +78 -48
- package/dist/prompt/instruction-scanner.d.ts +6 -5
- package/dist/prompt/instruction-scanner.js +8 -23
- package/dist/prompt/section-loader.d.ts +2 -2
- package/dist/prompt/section-loader.js +7 -4
- package/dist/prompt/sections/browser.md +10 -9
- package/dist/prompt/sections/harness-base.md +9 -0
- package/dist/protocol/chat-session-manager.d.ts +64 -1
- package/dist/protocol/chat-session-manager.js +104 -0
- package/dist/protocol/chat-session.d.ts +61 -10
- package/dist/protocol/chat-session.js +135 -25
- package/dist/protocol/client.d.ts +33 -3
- package/dist/protocol/client.js +96 -5
- package/dist/protocol/index.d.ts +2 -2
- package/dist/protocol/index.js +2 -2
- package/dist/protocol/mobile-remote-types.d.ts +406 -0
- package/dist/protocol/mobile-remote-types.js +1 -0
- package/dist/protocol/server.d.ts +127 -3
- package/dist/protocol/server.js +1309 -182
- package/dist/protocol/types.d.ts +152 -34
- package/dist/protocol/types.js +16 -0
- package/dist/run/ArtifactTracker.d.ts +6 -1
- package/dist/run/ArtifactTracker.js +29 -21
- package/dist/run/EngineRunner.d.ts +2 -0
- package/dist/run/EngineRunner.js +1 -0
- package/dist/run/RunManager.d.ts +26 -0
- package/dist/run/RunManager.js +82 -11
- package/dist/run/factory.d.ts +3 -0
- package/dist/run/factory.js +2 -0
- package/dist/runtime/safe-spawn.d.ts +6 -0
- package/dist/runtime/safe-spawn.js +8 -13
- package/dist/services/auto-dream.d.ts +13 -1
- package/dist/services/auto-dream.js +56 -8
- package/dist/services/dream-consolidation.js +10 -1
- package/dist/services/memory-orchestrator.js +6 -2
- package/dist/services/oauth.js +4 -1
- package/dist/services/session-memory.d.ts +4 -4
- package/dist/services/session-memory.js +13 -10
- package/dist/session/memory.d.ts +26 -7
- package/dist/session/memory.js +79 -21
- package/dist/session/session-manager.d.ts +182 -28
- package/dist/session/session-manager.js +910 -130
- package/dist/session/session-message.d.ts +22 -0
- package/dist/session/session-message.js +1 -0
- package/dist/session/transcript.d.ts +46 -5
- package/dist/session/transcript.js +159 -3
- package/dist/settings/feature-flags.d.ts +40 -0
- package/dist/settings/feature-flags.js +40 -0
- package/dist/settings/manager.d.ts +39 -1
- package/dist/settings/manager.js +102 -41
- package/dist/settings/migrate-config.js +4 -2
- package/dist/settings/schema.d.ts +511 -177
- package/dist/settings/schema.js +98 -25
- package/dist/skills/scanner.d.ts +6 -2
- package/dist/skills/scanner.js +160 -9
- package/dist/sources/adapter.d.ts +14 -0
- package/dist/sources/adapter.js +7 -0
- package/dist/sources/adapters/local-files.d.ts +10 -0
- package/dist/sources/adapters/local-files.js +127 -0
- package/dist/sources/adapters/mcp-resource.d.ts +17 -0
- package/dist/sources/adapters/mcp-resource.js +41 -0
- package/dist/sources/adapters/mock.d.ts +3 -0
- package/dist/sources/adapters/mock.js +29 -0
- package/dist/sources/binding.d.ts +6 -0
- package/dist/sources/binding.js +24 -0
- package/dist/sources/catalog.d.ts +6 -0
- package/dist/sources/catalog.js +64 -0
- package/dist/sources/context-summary.d.ts +8 -0
- package/dist/sources/context-summary.js +13 -0
- package/dist/sources/credential-status.d.ts +2 -0
- package/dist/sources/credential-status.js +13 -0
- package/dist/sources/index.d.ts +10 -0
- package/dist/sources/index.js +10 -0
- package/dist/sources/resolve.d.ts +28 -0
- package/dist/sources/resolve.js +47 -0
- package/dist/sources/truncate-utf8.d.ts +7 -0
- package/dist/sources/truncate-utf8.js +18 -0
- package/dist/sources/types.d.ts +71 -0
- package/dist/sources/types.js +26 -0
- package/dist/testing/fetch-stub.d.ts +32 -0
- package/dist/testing/fetch-stub.js +24 -0
- package/dist/themes/image.d.ts +18 -0
- package/dist/themes/image.js +117 -0
- package/dist/themes/index.d.ts +4 -0
- package/dist/themes/index.js +4 -0
- package/dist/themes/installer.d.ts +50 -0
- package/dist/themes/installer.js +290 -0
- package/dist/themes/manifest.d.ts +102 -0
- package/dist/themes/manifest.js +86 -0
- package/dist/themes/paths.d.ts +14 -0
- package/dist/themes/paths.js +33 -0
- package/dist/tool-system/browser-bridge.d.ts +53 -11
- package/dist/tool-system/browser-bridge.js +8 -9
- package/dist/tool-system/builtin/agent-heartbeat.d.ts +2 -2
- package/dist/tool-system/builtin/agent-heartbeat.js +20 -6
- package/dist/tool-system/builtin/agent-notifications.d.ts +127 -72
- package/dist/tool-system/builtin/agent-notifications.js +291 -101
- package/dist/tool-system/builtin/agent-output-file.js +1 -3
- package/dist/tool-system/builtin/agent-progress.d.ts +6 -0
- package/dist/tool-system/builtin/agent-progress.js +83 -0
- package/dist/tool-system/builtin/agent-registry.d.ts +38 -2
- package/dist/tool-system/builtin/agent-registry.js +178 -9
- package/dist/tool-system/builtin/agent-transcript-translator.js +1 -1
- package/dist/tool-system/builtin/agent.d.ts +2 -0
- package/dist/tool-system/builtin/agent.js +274 -33
- package/dist/tool-system/builtin/background-jobs.d.ts +55 -2
- package/dist/tool-system/builtin/background-jobs.js +96 -4
- package/dist/tool-system/builtin/background-work.d.ts +6 -0
- package/dist/tool-system/builtin/background-work.js +8 -1
- package/dist/tool-system/builtin/bash.js +5 -2
- package/dist/tool-system/builtin/browser-tools.d.ts +6 -3
- package/dist/tool-system/builtin/browser-tools.js +89 -23
- package/dist/tool-system/builtin/edit-model-catalog.d.ts +6 -0
- package/dist/tool-system/builtin/edit-model-catalog.js +172 -12
- package/dist/tool-system/builtin/edit.js +2 -6
- package/dist/tool-system/builtin/file-cache.d.ts +2 -0
- package/dist/tool-system/builtin/file-cache.js +4 -0
- package/dist/tool-system/builtin/generate-image.js +17 -10
- package/dist/tool-system/builtin/generate-video.js +26 -7
- package/dist/tool-system/builtin/grep.js +2 -2
- package/dist/tool-system/builtin/image-uploader.js +7 -1
- package/dist/tool-system/builtin/index.d.ts +32 -7
- package/dist/tool-system/builtin/index.js +237 -167
- package/dist/tool-system/builtin/memory.d.ts +6 -0
- package/dist/tool-system/builtin/memory.js +36 -15
- package/dist/tool-system/builtin/panel.d.ts +9 -0
- package/dist/tool-system/builtin/panel.js +314 -0
- package/dist/tool-system/builtin/read.js +5 -1
- package/dist/tool-system/builtin/send-message-to-session.d.ts +6 -0
- package/dist/tool-system/builtin/send-message-to-session.js +67 -0
- package/dist/tool-system/builtin/sources.d.ts +8 -0
- package/dist/tool-system/builtin/sources.js +137 -0
- package/dist/tool-system/builtin/tool-search.js +7 -2
- package/dist/tool-system/builtin/update-automation-memory.js +2 -0
- package/dist/tool-system/builtin/web-fetch.js +17 -13
- package/dist/tool-system/builtin/web-search.js +1 -3
- package/dist/tool-system/capability-module.d.ts +93 -0
- package/dist/tool-system/capability-module.js +53 -0
- package/dist/tool-system/context.d.ts +77 -19
- package/dist/tool-system/executor.js +75 -50
- package/dist/tool-system/external-tool-exposure.d.ts +60 -0
- package/dist/tool-system/external-tool-exposure.js +304 -0
- package/dist/tool-system/mcp-manager.d.ts +11 -1
- package/dist/tool-system/mcp-manager.js +19 -4
- package/dist/tool-system/mcp-tool-policy.d.ts +9 -0
- package/dist/tool-system/mcp-tool-policy.js +34 -0
- package/dist/tool-system/panel-bridge.d.ts +53 -0
- package/dist/tool-system/panel-bridge.js +1 -0
- package/dist/tool-system/permission.d.ts +26 -0
- package/dist/tool-system/permission.js +46 -0
- package/dist/tool-system/registry.d.ts +12 -1
- package/dist/tool-system/registry.js +31 -7
- package/dist/tool-system/sandbox/index.js +3 -8
- package/dist/tool-system/sandbox/seatbelt.js +2 -6
- package/dist/tool-system/session-tool-host.d.ts +139 -0
- package/dist/tool-system/session-tool-host.js +167 -0
- package/dist/tool-system/testing/tool-registry-harness.d.ts +31 -0
- package/dist/tool-system/testing/tool-registry-harness.js +51 -0
- package/dist/tool-system/validation.d.ts +14 -7
- package/dist/tool-system/validation.js +701 -7
- package/dist/types.d.ts +186 -20
- package/dist/{cc-orchestrator → utils}/cwd-normalize.d.ts +1 -0
- package/dist/{cc-orchestrator → utils}/cwd-normalize.js +1 -0
- package/dist/utils/file-mutex.d.ts +65 -0
- package/dist/utils/file-mutex.js +145 -0
- package/dist/utils/json.d.ts +2 -4
- package/dist/utils/json.js +2 -4
- package/dist/utils/lockfile.d.ts +30 -1
- package/dist/utils/lockfile.js +2 -2
- package/dist/utils/secret-scrubber.d.ts +8 -0
- package/dist/utils/secret-scrubber.js +227 -0
- package/dist/utils/toolDisplay.js +1 -1
- package/package.json +20 -5
- package/THIRD_PARTY_NOTICES.md +0 -206
- package/dist/arena/arena.d.ts +0 -45
- package/dist/arena/arena.js +0 -362
- package/dist/arena/context/context-tools.d.ts +0 -16
- package/dist/arena/context/context-tools.js +0 -272
- package/dist/arena/context/within-root.d.ts +0 -7
- package/dist/arena/context/within-root.js +0 -15
- package/dist/arena/detect-mode.d.ts +0 -20
- package/dist/arena/detect-mode.js +0 -78
- package/dist/arena/digest-builder.d.ts +0 -25
- package/dist/arena/digest-builder.js +0 -120
- package/dist/arena/index.d.ts +0 -29
- package/dist/arena/index.js +0 -29
- package/dist/arena/iterate/convergence.d.ts +0 -25
- package/dist/arena/iterate/convergence.js +0 -103
- package/dist/arena/iterate/formats/index.d.ts +0 -22
- package/dist/arena/iterate/formats/index.js +0 -283
- package/dist/arena/iterate/index.d.ts +0 -11
- package/dist/arena/iterate/index.js +0 -9
- package/dist/arena/iterate/iterative-arena.d.ts +0 -23
- package/dist/arena/iterate/iterative-arena.js +0 -237
- package/dist/arena/iterate/parse.d.ts +0 -42
- package/dist/arena/iterate/parse.js +0 -123
- package/dist/arena/iterate/phases/argue.d.ts +0 -22
- package/dist/arena/iterate/phases/argue.js +0 -165
- package/dist/arena/iterate/phases/revise.d.ts +0 -16
- package/dist/arena/iterate/phases/revise.js +0 -62
- package/dist/arena/iterate/phases/tournament.d.ts +0 -34
- package/dist/arena/iterate/phases/tournament.js +0 -113
- package/dist/arena/iterate/tools/web-tools.d.ts +0 -13
- package/dist/arena/iterate/tools/web-tools.js +0 -54
- package/dist/arena/iterate/types.d.ts +0 -152
- package/dist/arena/iterate/types.js +0 -8
- package/dist/arena/ledger.d.ts +0 -47
- package/dist/arena/ledger.js +0 -159
- package/dist/arena/lenses/architecture.d.ts +0 -5
- package/dist/arena/lenses/architecture.js +0 -22
- package/dist/arena/lenses/engineering.d.ts +0 -5
- package/dist/arena/lenses/engineering.js +0 -22
- package/dist/arena/lenses/general.d.ts +0 -5
- package/dist/arena/lenses/general.js +0 -20
- package/dist/arena/lenses/index.d.ts +0 -16
- package/dist/arena/lenses/index.js +0 -47
- package/dist/arena/lenses/product.d.ts +0 -5
- package/dist/arena/lenses/product.js +0 -22
- package/dist/arena/model-presets.d.ts +0 -23
- package/dist/arena/model-presets.js +0 -44
- package/dist/arena/phases/adjudication.d.ts +0 -25
- package/dist/arena/phases/adjudication.js +0 -142
- package/dist/arena/phases/build-consensus.d.ts +0 -30
- package/dist/arena/phases/build-consensus.js +0 -85
- package/dist/arena/phases/claim-registry.d.ts +0 -26
- package/dist/arena/phases/claim-registry.js +0 -60
- package/dist/arena/phases/cross-review.d.ts +0 -47
- package/dist/arena/phases/cross-review.js +0 -224
- package/dist/arena/phases/debate-rounds.d.ts +0 -28
- package/dist/arena/phases/debate-rounds.js +0 -161
- package/dist/arena/phases/participant-research.d.ts +0 -39
- package/dist/arena/phases/participant-research.js +0 -316
- package/dist/arena/phases/planning-detail-expansion.d.ts +0 -39
- package/dist/arena/phases/planning-detail-expansion.js +0 -120
- package/dist/arena/planner.d.ts +0 -28
- package/dist/arena/planner.js +0 -312
- package/dist/arena/providers/docs.d.ts +0 -7
- package/dist/arena/providers/docs.js +0 -111
- package/dist/arena/providers/git.d.ts +0 -8
- package/dist/arena/providers/git.js +0 -174
- package/dist/arena/providers/index.d.ts +0 -32
- package/dist/arena/providers/index.js +0 -132
- package/dist/arena/providers/none.d.ts +0 -7
- package/dist/arena/providers/none.js +0 -11
- package/dist/arena/providers/repo.d.ts +0 -7
- package/dist/arena/providers/repo.js +0 -258
- package/dist/arena/render/session.d.ts +0 -17
- package/dist/arena/render/session.js +0 -190
- package/dist/arena/render/terminal.d.ts +0 -34
- package/dist/arena/render/terminal.js +0 -286
- package/dist/arena/strategies/discussion.d.ts +0 -25
- package/dist/arena/strategies/discussion.js +0 -143
- package/dist/arena/strategies/index.d.ts +0 -15
- package/dist/arena/strategies/index.js +0 -28
- package/dist/arena/strategies/language-wrapper.d.ts +0 -17
- package/dist/arena/strategies/language-wrapper.js +0 -102
- package/dist/arena/strategies/lens-wrapper.d.ts +0 -16
- package/dist/arena/strategies/lens-wrapper.js +0 -236
- package/dist/arena/strategies/planning.d.ts +0 -30
- package/dist/arena/strategies/planning.js +0 -225
- package/dist/arena/strategies/review.d.ts +0 -26
- package/dist/arena/strategies/review.js +0 -168
- package/dist/arena/strategies/utils.d.ts +0 -36
- package/dist/arena/strategies/utils.js +0 -603
- package/dist/arena/tools/selector.d.ts +0 -17
- package/dist/arena/tools/selector.js +0 -61
- package/dist/arena/transitions.d.ts +0 -53
- package/dist/arena/transitions.js +0 -97
- package/dist/arena/types.d.ts +0 -518
- package/dist/arena/types.js +0 -27
- package/dist/cc-orchestrator/agent-adapter.d.ts +0 -54
- package/dist/cc-orchestrator/agent-adapter.js +0 -143
- package/dist/cc-orchestrator/cc-capability.d.ts +0 -19
- package/dist/cc-orchestrator/cc-capability.js +0 -53
- package/dist/cc-orchestrator/codex-session-discovery.d.ts +0 -24
- package/dist/cc-orchestrator/codex-session-discovery.js +0 -191
- package/dist/cc-orchestrator/codex-session-history.d.ts +0 -38
- package/dist/cc-orchestrator/codex-session-history.js +0 -247
- package/dist/cc-orchestrator/external-agent-bindings.d.ts +0 -27
- package/dist/cc-orchestrator/external-agent-bindings.js +0 -150
- package/dist/cc-orchestrator/external-agent-changes.d.ts +0 -19
- package/dist/cc-orchestrator/external-agent-changes.js +0 -231
- package/dist/cc-orchestrator/external-agent-driver.d.ts +0 -19
- package/dist/cc-orchestrator/external-agent-driver.js +0 -284
- package/dist/cc-orchestrator/external-agent-session-store.d.ts +0 -23
- package/dist/cc-orchestrator/external-agent-session-store.js +0 -146
- package/dist/cc-orchestrator/index.d.ts +0 -8
- package/dist/cc-orchestrator/index.js +0 -8
- package/dist/cc-orchestrator/relevance-judge.d.ts +0 -15
- package/dist/cc-orchestrator/relevance-judge.js +0 -29
- package/dist/cc-orchestrator/session-discovery.d.ts +0 -46
- package/dist/cc-orchestrator/session-discovery.js +0 -125
- package/dist/cc-orchestrator/session-history.d.ts +0 -54
- package/dist/cc-orchestrator/session-history.js +0 -150
- package/dist/cron/cron-runtime.d.ts +0 -2
- package/dist/cron/cron-runtime.js +0 -2
- package/dist/cron/cron-store.d.ts +0 -2
- package/dist/cron/cron-store.js +0 -2
- package/dist/cron/scheduler.d.ts +0 -7
- package/dist/cron/scheduler.js +0 -7
- package/dist/engine/goal.js +0 -206
- package/dist/external-agents/config.d.ts +0 -2
- package/dist/external-agents/config.js +0 -15
- package/dist/external-agents/types.d.ts +0 -31
- package/dist/git/parse-log.d.ts +0 -13
- package/dist/git/parse-log.js +0 -21
- package/dist/git/utils.d.ts +0 -49
- package/dist/git/utils.js +0 -161
- package/dist/git/worktree/crud.d.ts +0 -72
- package/dist/git/worktree/crud.js +0 -235
- package/dist/git/worktree/diff.d.ts +0 -14
- package/dist/git/worktree/diff.js +0 -82
- package/dist/git/worktree/git-exec.d.ts +0 -7
- package/dist/git/worktree/git-exec.js +0 -87
- package/dist/git/worktree/index.d.ts +0 -5
- package/dist/git/worktree/index.js +0 -5
- package/dist/git/worktree/query.d.ts +0 -43
- package/dist/git/worktree/query.js +0 -128
- package/dist/git/worktree/slug.d.ts +0 -11
- package/dist/git/worktree/slug.js +0 -58
- package/dist/git/worktree.d.ts +0 -1
- package/dist/git/worktree.js +0 -5
- package/dist/lsp/client.d.ts +0 -41
- package/dist/lsp/client.js +0 -186
- package/dist/lsp/manager.d.ts +0 -40
- package/dist/lsp/manager.js +0 -155
- package/dist/lsp/root-path.d.ts +0 -9
- package/dist/lsp/root-path.js +0 -12
- package/dist/lsp/servers.d.ts +0 -16
- package/dist/lsp/servers.js +0 -60
- package/dist/prompt/sections/coding.md +0 -35
- package/dist/quota/credentials.d.ts +0 -3
- package/dist/quota/credentials.js +0 -80
- package/dist/quota/index.d.ts +0 -36
- package/dist/quota/index.js +0 -155
- package/dist/quota/types.d.ts +0 -48
- package/dist/quota/types.js +0 -13
- package/dist/review/review-prompt.d.ts +0 -28
- package/dist/review/review-prompt.js +0 -81
- package/dist/state.d.ts +0 -160
- package/dist/state.js +0 -267
- package/dist/tool-system/builtin/apply-patch/applier.d.ts +0 -26
- package/dist/tool-system/builtin/apply-patch/applier.js +0 -308
- package/dist/tool-system/builtin/apply-patch/backup-targets.d.ts +0 -10
- package/dist/tool-system/builtin/apply-patch/backup-targets.js +0 -30
- package/dist/tool-system/builtin/apply-patch/index.d.ts +0 -20
- package/dist/tool-system/builtin/apply-patch/index.js +0 -105
- package/dist/tool-system/builtin/apply-patch/parser.d.ts +0 -17
- package/dist/tool-system/builtin/apply-patch/parser.js +0 -212
- package/dist/tool-system/builtin/apply-patch/seek-sequence.d.ts +0 -18
- package/dist/tool-system/builtin/apply-patch/seek-sequence.js +0 -123
- package/dist/tool-system/builtin/apply-patch/types.d.ts +0 -49
- package/dist/tool-system/builtin/apply-patch/types.js +0 -13
- package/dist/tool-system/builtin/arena.d.ts +0 -31
- package/dist/tool-system/builtin/arena.js +0 -416
- package/dist/tool-system/builtin/brief.d.ts +0 -6
- package/dist/tool-system/builtin/brief.js +0 -41
- package/dist/tool-system/builtin/check-quota.d.ts +0 -15
- package/dist/tool-system/builtin/check-quota.js +0 -34
- package/dist/tool-system/builtin/drive-claude-code.d.ts +0 -51
- package/dist/tool-system/builtin/drive-claude-code.js +0 -698
- package/dist/tool-system/builtin/lsp.d.ts +0 -7
- package/dist/tool-system/builtin/lsp.js +0 -144
- package/dist/tool-system/builtin/notebook-edit.d.ts +0 -7
- package/dist/tool-system/builtin/notebook-edit.js +0 -127
- package/dist/tool-system/builtin/worktree.d.ts +0 -11
- package/dist/tool-system/builtin/worktree.js +0 -363
- /package/dist/{external-agents → links}/types.js +0 -0
- /package/dist/{engine/session-usage.d.ts → session/usage.d.ts} +0 -0
- /package/dist/{engine/session-usage.js → session/usage.js} +0 -0
package/dist/engine/turn-loop.js
CHANGED
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
* Following Claude Code's po_() pattern:
|
|
5
5
|
* pre_check → model_call → post_check → tool_exec → context_mgmt → hook_notify → next turn
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { randomUUID } from "node:crypto";
|
|
8
|
+
import { buildAgentDirectionMessage } from "../tool-system/builtin/agent-notifications.js";
|
|
9
|
+
import { newTurnId } from "./turn-state.js";
|
|
8
10
|
import { formatFriendlyError } from "./friendly-error.js";
|
|
9
|
-
import {
|
|
11
|
+
import { buildGoalJudgeRuntimeContext } from "./goal-judge-context.js";
|
|
10
12
|
import { wrapHookMessages } from "../hooks/inject.js";
|
|
11
13
|
import { ContextLimitError } from "../exceptions.js";
|
|
12
14
|
import { logger } from "../logging/logger.js";
|
|
@@ -18,9 +20,9 @@ import { isAbortError } from "../llm/client-base.js";
|
|
|
18
20
|
import { crossedReactiveThreshold } from "./reactive-threshold.js";
|
|
19
21
|
import { COMPLETE_GOAL_TOOL_NAME } from "../tool-system/builtin/complete-goal.js";
|
|
20
22
|
import { CANCEL_GOAL_TOOL_NAME } from "../tool-system/builtin/cancel-goal.js";
|
|
21
|
-
import { redactSensitiveToolResultsInMessages, toolResultForDisplay, toolResultTranscriptText, toolResultsForDisplay, } from "../tool-system/tool-result-redaction.js";
|
|
22
|
-
import { addTokenUsage, cacheHitRateFromUsage, cumulativeCacheHitRate, } from "
|
|
23
|
-
import { createGoalBudgetTracker, recordGoalUsage, goalBudgetTerminationReason, applyGoalExtension, limitProximity, GOAL_DEFAULT_MAX_STOP_BLOCKS, } from "
|
|
23
|
+
import { redactSensitiveToolResultsInMessages, SENSITIVE_TOOL_RESULT_PLACEHOLDER, toolResultForDisplay, toolResultTranscriptText, toolResultsForDisplay, } from "../tool-system/tool-result-redaction.js";
|
|
24
|
+
import { addTokenUsage, cacheHitRateFromUsage, cumulativeCacheHitRate, } from "../session/usage.js";
|
|
25
|
+
import { createGoalBudgetTracker, recordGoalUsage, goalBudgetTerminationReason, applyGoalExtension, limitProximity, isSameGoalVersion, normalizeGoal, GOAL_DEFAULT_MAX_STOP_BLOCKS, } from "../goal/lifecycle.js";
|
|
24
26
|
/**
|
|
25
27
|
* 把一个 ToolResult 映射成发给 LLM 的 tool_result ContentBlock。
|
|
26
28
|
* 有 contentBlocks(view_image 的图片块)就原样用作 content;否则
|
|
@@ -87,6 +89,57 @@ export class TurnLoop {
|
|
|
87
89
|
* being re-emitted every turn while still within the approach threshold.
|
|
88
90
|
*/
|
|
89
91
|
approachAnnounced = false;
|
|
92
|
+
/** Latest coalesced Goal edit/resume reminder, consumed at a safe point. */
|
|
93
|
+
pendingGoalControlMessage = null;
|
|
94
|
+
/** Pause/delete requested while a Goal run is in flight. The current
|
|
95
|
+
* model/tool step is allowed to settle, then the loop stops before starting
|
|
96
|
+
* another model request. */
|
|
97
|
+
goalControlStopRequested = false;
|
|
98
|
+
/** Auxiliary tool-summary calls started by this loop and revoked by Goal pause/delete. */
|
|
99
|
+
activeToolSummaryControllers = new Set();
|
|
100
|
+
/**
|
|
101
|
+
* Apply a user goal edit/pause/resume to the live loop. Passing undefined
|
|
102
|
+
* pauses goal-driving at the next step boundary; a goal value resumes it.
|
|
103
|
+
* Usage accumulated before an edit is retained, while a pause/resume starts
|
|
104
|
+
* a fresh run-scoped budget window (matching a later persisted resume).
|
|
105
|
+
*/
|
|
106
|
+
updateGoal(goal, controlMessage, limits) {
|
|
107
|
+
const normalized = normalizeGoal(goal);
|
|
108
|
+
if (!normalized) {
|
|
109
|
+
this.config = { ...this.config, goal: undefined };
|
|
110
|
+
this.goalTracker = null;
|
|
111
|
+
this.pendingGoalControlMessage = null;
|
|
112
|
+
this.goalControlStopRequested = true;
|
|
113
|
+
for (const controller of this.activeToolSummaryControllers)
|
|
114
|
+
controller.abort();
|
|
115
|
+
this.activeToolSummaryControllers.clear();
|
|
116
|
+
this.stopBlockCount = 0;
|
|
117
|
+
this.approachAnnounced = false;
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const next = { ...normalized, goalId: normalized.goalId ?? randomUUID() };
|
|
121
|
+
const wasPaused = !this.config.goal;
|
|
122
|
+
this.config = {
|
|
123
|
+
...this.config,
|
|
124
|
+
goal: next,
|
|
125
|
+
...(typeof limits?.maxTurns === "number" && limits.maxTurns > 0
|
|
126
|
+
? { maxTurns: Math.max(this.config.maxTurns, Math.floor(limits.maxTurns)) }
|
|
127
|
+
: {}),
|
|
128
|
+
...(typeof limits?.maxStopBlocks === "number" && limits.maxStopBlocks > 0
|
|
129
|
+
? { maxStopBlocks: Math.floor(limits.maxStopBlocks) }
|
|
130
|
+
: {}),
|
|
131
|
+
};
|
|
132
|
+
this.goalControlStopRequested = false;
|
|
133
|
+
this.pendingGoalControlMessage = controlMessage?.trim()
|
|
134
|
+
? { goalId: next.goalId, revision: next.revision, text: controlMessage.trim() }
|
|
135
|
+
: null;
|
|
136
|
+
if (this.goalTracker && !wasPaused)
|
|
137
|
+
this.goalTracker.goal = next;
|
|
138
|
+
else
|
|
139
|
+
this.goalTracker = createGoalBudgetTracker(next, Date.now());
|
|
140
|
+
this.stopBlockCount = 0;
|
|
141
|
+
this.approachAnnounced = false;
|
|
142
|
+
}
|
|
90
143
|
/**
|
|
91
144
|
* Extend the in-flight run's limits (TODO 3.1 — 运行中续轮/加预算). Mutates
|
|
92
145
|
* the maxTurns ceiling, the maxStopBlocks cap, and/or the live goal budgets;
|
|
@@ -163,6 +216,8 @@ export class TurnLoop {
|
|
|
163
216
|
this.approachAnnounced = true;
|
|
164
217
|
this.config.onStream?.({
|
|
165
218
|
type: "goal_progress",
|
|
219
|
+
goalId: this.config.goal.goalId,
|
|
220
|
+
revision: this.config.goal.revision,
|
|
166
221
|
status: "approaching_limit",
|
|
167
222
|
round: this.stopBlockCount,
|
|
168
223
|
turnsRemaining: prox.turnsRemaining,
|
|
@@ -177,6 +232,16 @@ export class TurnLoop {
|
|
|
177
232
|
config) {
|
|
178
233
|
this.deps = deps;
|
|
179
234
|
this.config = config;
|
|
235
|
+
const normalizedGoal = normalizeGoal(this.config.goal);
|
|
236
|
+
if (normalizedGoal) {
|
|
237
|
+
this.config = {
|
|
238
|
+
...this.config,
|
|
239
|
+
goal: { ...normalizedGoal, goalId: normalizedGoal.goalId ?? randomUUID() },
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
else if (this.config.goal !== undefined) {
|
|
243
|
+
this.config = { ...this.config, goal: undefined };
|
|
244
|
+
}
|
|
180
245
|
for (const msg of this.config.freshImageMessages ?? []) {
|
|
181
246
|
this.pendingImageMessages.add(msg);
|
|
182
247
|
}
|
|
@@ -359,10 +424,17 @@ export class TurnLoop {
|
|
|
359
424
|
promptTokensConfidence: overhead > 0 ? "medium" : "low",
|
|
360
425
|
});
|
|
361
426
|
}
|
|
362
|
-
recordResponseUsage(usage) {
|
|
427
|
+
recordResponseUsage(usage, requestKind = "primary", recordCacheDiagnostics = true) {
|
|
363
428
|
this.currentTurnUsage = addTokenUsage(this.currentTurnUsage, usage);
|
|
429
|
+
this.deps.onAgentUsage?.(usage);
|
|
364
430
|
this.currentCumulativeUsage = this.deps.recordCumulativeUsage?.(usage);
|
|
365
|
-
this.deps.recordCacheReadDiagnostics
|
|
431
|
+
if (recordCacheDiagnostics && this.deps.recordCacheReadDiagnostics) {
|
|
432
|
+
this.deps.recordCacheReadDiagnostics({
|
|
433
|
+
usage,
|
|
434
|
+
requestKind,
|
|
435
|
+
fingerprint: this.deps.model.getPromptPrefixFingerprint(this.deps.systemPrompt, this.deps.tools),
|
|
436
|
+
});
|
|
437
|
+
}
|
|
366
438
|
}
|
|
367
439
|
emitCtxFromUsage(usage, messages) {
|
|
368
440
|
if (!this.config.onStream)
|
|
@@ -429,16 +501,18 @@ export class TurnLoop {
|
|
|
429
501
|
*/
|
|
430
502
|
async run(initialMessages) {
|
|
431
503
|
const result = await this.runUnredacted(initialMessages);
|
|
432
|
-
return {
|
|
504
|
+
return {
|
|
505
|
+
...result,
|
|
506
|
+
...(result.reason === "completed" && this.goalControlStopRequested
|
|
507
|
+
? { completionKind: "goal_control_stop" }
|
|
508
|
+
: {}),
|
|
509
|
+
messages: this.redactConsumedSensitiveToolResults(result.messages),
|
|
510
|
+
};
|
|
433
511
|
}
|
|
434
512
|
async runUnredacted(initialMessages) {
|
|
435
513
|
let messages = [...initialMessages];
|
|
436
514
|
let finalText = "";
|
|
437
515
|
const budgetTracker = createBudgetTracker();
|
|
438
|
-
// Recent execution evidence for the built-in Goal judge. Values enter this
|
|
439
|
-
// window only after irreversible sensitive-data removal, non-text omission,
|
|
440
|
-
// and per-item truncation at the current-round ToolResult boundary.
|
|
441
|
-
const goalToolResults = [];
|
|
442
516
|
const sensitiveGoalResultTools = this.config.goal
|
|
443
517
|
? new Set(this.deps.tools.filter((tool) => tool.sensitiveResult).map((tool) => tool.name))
|
|
444
518
|
: undefined;
|
|
@@ -449,7 +523,6 @@ export class TurnLoop {
|
|
|
449
523
|
if (!this.goalTracker && this.config.goal) {
|
|
450
524
|
this.goalTracker = createGoalBudgetTracker(this.config.goal, Date.now());
|
|
451
525
|
}
|
|
452
|
-
const goalTracker = this.goalTracker;
|
|
453
526
|
// Fresh run: re-arm the approaching-limit announcement.
|
|
454
527
|
this.approachAnnounced = false;
|
|
455
528
|
// run() must never reject: the engine's post-run bookkeeping (saveState
|
|
@@ -461,8 +534,12 @@ export class TurnLoop {
|
|
|
461
534
|
// hook emits, guards) and surfaces them as a model_error result.
|
|
462
535
|
try {
|
|
463
536
|
while (this.turnCount < this.config.maxTurns) {
|
|
464
|
-
|
|
465
|
-
|
|
537
|
+
if (this.goalControlStopRequested) {
|
|
538
|
+
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
539
|
+
return { text: finalText, reason: "completed", messages };
|
|
540
|
+
}
|
|
541
|
+
const preTurnGoalTermination = this.goalTracker
|
|
542
|
+
? goalBudgetTerminationReason(this.goalTracker, Date.now())
|
|
466
543
|
: undefined;
|
|
467
544
|
if (preTurnGoalTermination) {
|
|
468
545
|
this.config.onStream?.({
|
|
@@ -478,6 +555,7 @@ export class TurnLoop {
|
|
|
478
555
|
reason: "goal_budget_exhausted",
|
|
479
556
|
messages,
|
|
480
557
|
goalTermination: preTurnGoalTermination,
|
|
558
|
+
goalTerminationRound: this.stopBlockCount,
|
|
481
559
|
};
|
|
482
560
|
}
|
|
483
561
|
this.turnCount++;
|
|
@@ -507,8 +585,18 @@ export class TurnLoop {
|
|
|
507
585
|
// they join THIS step's request — no abort, no lost in-flight work. Same
|
|
508
586
|
// loop-top user-push pattern as turnStartInjection / turn-limit warnings
|
|
509
587
|
// below. Push to transcript too so they persist + survive resume.
|
|
588
|
+
// Bind self-reported Goal terminal tools to the revision that was
|
|
589
|
+
// actually visible when this model step began. An edit/pause/delete can
|
|
590
|
+
// arrive while context management, the model request, or its tool batch
|
|
591
|
+
// is in flight; a late complete_goal/cancel_goal from that old prompt
|
|
592
|
+
// must never terminate the newer revision.
|
|
593
|
+
const requestedGoalVersion = this.config.goal ? { ...this.config.goal } : undefined;
|
|
510
594
|
await this.consumeQueuedSteer(messages, "normal_step");
|
|
511
|
-
|
|
595
|
+
if (this.goalControlStopRequested) {
|
|
596
|
+
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
597
|
+
return { text: finalText, reason: "completed", messages };
|
|
598
|
+
}
|
|
599
|
+
this.deps.onAgentControlState?.("model");
|
|
512
600
|
// Per-turn correlation ID. Every log written through `tlog` (or any
|
|
513
601
|
// child derived from it) is stamped with `turn` + `turnId`, so
|
|
514
602
|
// `jq 'select(.turnId == "...")'` reconstructs one turn's timeline.
|
|
@@ -523,11 +611,6 @@ export class TurnLoop {
|
|
|
523
611
|
tlog.info("turn.start", { cat: "turn", messageCount: messages.length });
|
|
524
612
|
// Tag downstream tool-exec / permission lines with this turn's IDs.
|
|
525
613
|
this.deps.toolExecutor.setLogger(tlog);
|
|
526
|
-
this.config.onStream?.({
|
|
527
|
-
type: "stream_request_start",
|
|
528
|
-
turnNumber: this.turnCount,
|
|
529
|
-
messageId: assistantMessageId,
|
|
530
|
-
});
|
|
531
614
|
const turnStartHook = await this.emitHook("on_turn_start", {
|
|
532
615
|
turnNumber: this.turnCount,
|
|
533
616
|
});
|
|
@@ -535,6 +618,10 @@ export class TurnLoop {
|
|
|
535
618
|
if (turnStartInjection) {
|
|
536
619
|
messages.push(turnStartInjection);
|
|
537
620
|
}
|
|
621
|
+
if (this.goalControlStopRequested) {
|
|
622
|
+
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
623
|
+
return { text: finalText, reason: "completed", messages };
|
|
624
|
+
}
|
|
538
625
|
// Approaching max turns: inject a warning so the model can wrap up.
|
|
539
626
|
// (Model-facing only — the user-facing "再续" marker is handled by
|
|
540
627
|
// maybeAnnounceApproachingLimit below, which also watches the stop-block
|
|
@@ -587,6 +674,10 @@ export class TurnLoop {
|
|
|
587
674
|
this.markStopped();
|
|
588
675
|
return { text: finalText, reason: "aborted_streaming", messages };
|
|
589
676
|
}
|
|
677
|
+
if (this.goalControlStopRequested) {
|
|
678
|
+
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
679
|
+
return { text: finalText, reason: "completed", messages };
|
|
680
|
+
}
|
|
590
681
|
}
|
|
591
682
|
// No pre-llm ctx emit here: the messages-only estimate would be ~16k
|
|
592
683
|
// smaller than the real prompt (system + tools not included), making
|
|
@@ -614,8 +705,17 @@ export class TurnLoop {
|
|
|
614
705
|
messages.push(compactInjection);
|
|
615
706
|
}
|
|
616
707
|
}
|
|
708
|
+
if (this.goalControlStopRequested) {
|
|
709
|
+
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
710
|
+
return { text: finalText, reason: "completed", messages };
|
|
711
|
+
}
|
|
617
712
|
messages = this.appendVolatileContextMessages(messages);
|
|
618
713
|
// Model call (with streaming fallback and max_output_tokens continuation)
|
|
714
|
+
this.config.onStream?.({
|
|
715
|
+
type: "stream_request_start",
|
|
716
|
+
turnNumber: this.turnCount,
|
|
717
|
+
messageId: assistantMessageId,
|
|
718
|
+
});
|
|
619
719
|
// Track tool IDs streamed during this turn to avoid duplicate UI events
|
|
620
720
|
this.streamedToolIds.clear();
|
|
621
721
|
// Tool queue is created before the call, but enqueue happens only after
|
|
@@ -627,10 +727,18 @@ export class TurnLoop {
|
|
|
627
727
|
}
|
|
628
728
|
catch (err) {
|
|
629
729
|
if (err instanceof ContextLimitError) {
|
|
730
|
+
if (this.goalControlStopRequested) {
|
|
731
|
+
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
732
|
+
return { text: finalText, reason: "completed", messages };
|
|
733
|
+
}
|
|
630
734
|
// Progressive recovery: drop oldest API rounds, up to 3 retries
|
|
631
735
|
const { dropOldestRounds } = await import("../context/compaction.js");
|
|
632
736
|
let recovered = false;
|
|
633
737
|
for (let retry = 1; retry <= 3; retry++) {
|
|
738
|
+
if (this.goalControlStopRequested) {
|
|
739
|
+
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
740
|
+
return { text: finalText, reason: "completed", messages };
|
|
741
|
+
}
|
|
634
742
|
tlog.warn("turn.ptl_recovery", { cat: "turn", retry, roundsToDrop: retry });
|
|
635
743
|
messages = dropOldestRounds(messages, retry);
|
|
636
744
|
try {
|
|
@@ -685,12 +793,12 @@ export class TurnLoop {
|
|
|
685
793
|
}
|
|
686
794
|
// Charge every provider response to the run-scoped Goal budget before
|
|
687
795
|
// any truncation path can retry or continue the outer turn loop.
|
|
688
|
-
if (goalTracker && response.usage) {
|
|
796
|
+
if (this.goalTracker && response.usage) {
|
|
689
797
|
const used = (response.usage.promptTokens ?? 0) + (response.usage.completionTokens ?? 0);
|
|
690
|
-
recordGoalUsage(goalTracker, used);
|
|
798
|
+
recordGoalUsage(this.goalTracker, used);
|
|
691
799
|
}
|
|
692
|
-
let budgetTermination = goalTracker
|
|
693
|
-
? goalBudgetTerminationReason(goalTracker, Date.now())
|
|
800
|
+
let budgetTermination = this.goalTracker
|
|
801
|
+
? goalBudgetTerminationReason(this.goalTracker, Date.now())
|
|
694
802
|
: undefined;
|
|
695
803
|
// Feed actual token usage back to the context manager so subsequent
|
|
696
804
|
// compaction decisions use hybrid (actual + delta) estimation rather than
|
|
@@ -748,10 +856,10 @@ export class TurnLoop {
|
|
|
748
856
|
// Don't fire another continuation call if the user cancelled — without
|
|
749
857
|
// this an abort during a truncated response could still issue up to 3
|
|
750
858
|
// more model calls, emitting text after Stop.
|
|
751
|
-
if (this.config.signal?.aborted)
|
|
859
|
+
if (this.config.signal?.aborted || this.goalControlStopRequested)
|
|
752
860
|
break;
|
|
753
|
-
budgetTermination = goalTracker
|
|
754
|
-
? goalBudgetTerminationReason(goalTracker, Date.now())
|
|
861
|
+
budgetTermination = this.goalTracker
|
|
862
|
+
? goalBudgetTerminationReason(this.goalTracker, Date.now())
|
|
755
863
|
: undefined;
|
|
756
864
|
if (budgetTermination)
|
|
757
865
|
break;
|
|
@@ -772,16 +880,16 @@ export class TurnLoop {
|
|
|
772
880
|
this.stopBlockCount = 0;
|
|
773
881
|
}
|
|
774
882
|
if (contResponse.usage?.promptTokens !== undefined) {
|
|
775
|
-
this.recordResponseUsage(contResponse.usage);
|
|
883
|
+
this.recordResponseUsage(contResponse.usage, "continuation");
|
|
776
884
|
continuedResponse = true;
|
|
777
885
|
}
|
|
778
|
-
if (goalTracker && contResponse.usage) {
|
|
886
|
+
if (this.goalTracker && contResponse.usage) {
|
|
779
887
|
const used = (contResponse.usage.promptTokens ?? 0) +
|
|
780
888
|
(contResponse.usage.completionTokens ?? 0);
|
|
781
|
-
recordGoalUsage(goalTracker, used);
|
|
889
|
+
recordGoalUsage(this.goalTracker, used);
|
|
782
890
|
}
|
|
783
|
-
budgetTermination = goalTracker
|
|
784
|
-
? goalBudgetTerminationReason(goalTracker, Date.now())
|
|
891
|
+
budgetTermination = this.goalTracker
|
|
892
|
+
? goalBudgetTerminationReason(this.goalTracker, Date.now())
|
|
785
893
|
: undefined;
|
|
786
894
|
combinedText += contResponse.text;
|
|
787
895
|
if (budgetTermination ||
|
|
@@ -821,13 +929,13 @@ export class TurnLoop {
|
|
|
821
929
|
// is force-stopped regardless of what the model wants to do next (stop OR
|
|
822
930
|
// continue with tool calls). This is the unattended-safety backstop, so
|
|
823
931
|
// it sits BEFORE the "tool calls?" branch — both paths pass the gate.
|
|
824
|
-
budgetTermination = goalTracker
|
|
825
|
-
? (budgetTermination ?? goalBudgetTerminationReason(goalTracker, Date.now()))
|
|
932
|
+
budgetTermination = this.goalTracker
|
|
933
|
+
? (budgetTermination ?? goalBudgetTerminationReason(this.goalTracker, Date.now()))
|
|
826
934
|
: undefined;
|
|
827
|
-
if (goalTracker && budgetTermination) {
|
|
935
|
+
if (this.goalTracker && budgetTermination) {
|
|
828
936
|
tlog.info("turn.goal_budget_exhausted", {
|
|
829
937
|
cat: "goal",
|
|
830
|
-
tokensUsed: goalTracker.tokensUsed,
|
|
938
|
+
tokensUsed: this.goalTracker.tokensUsed,
|
|
831
939
|
tokenBudget: this.config.goal?.tokenBudget,
|
|
832
940
|
timeBudgetMs: this.config.goal?.timeBudgetMs,
|
|
833
941
|
});
|
|
@@ -845,6 +953,7 @@ export class TurnLoop {
|
|
|
845
953
|
reason: "goal_budget_exhausted",
|
|
846
954
|
messages,
|
|
847
955
|
goalTermination: budgetTermination,
|
|
956
|
+
goalTerminationRound: this.stopBlockCount,
|
|
848
957
|
};
|
|
849
958
|
}
|
|
850
959
|
// Post-check: tool calls?
|
|
@@ -864,28 +973,31 @@ export class TurnLoop {
|
|
|
864
973
|
if (await this.consumeQueuedSteer(messages, "finalize_backfill")) {
|
|
865
974
|
continue;
|
|
866
975
|
}
|
|
976
|
+
// A steer accepted while an async tool was launching must be
|
|
977
|
+
// answered before parking the run. Keep the tool's yield request
|
|
978
|
+
// pending across that extra model round, then park once the model
|
|
979
|
+
// has replied and there is still no background result to consume.
|
|
980
|
+
if (this.deps.consumeToolRunYield?.() === "background_notification") {
|
|
981
|
+
tlog.info("turn.background_notification_wait_after_steer", { cat: "turn" });
|
|
982
|
+
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
983
|
+
return {
|
|
984
|
+
text: finalText,
|
|
985
|
+
reason: "completed",
|
|
986
|
+
messages,
|
|
987
|
+
completionKind: "background_wait",
|
|
988
|
+
};
|
|
989
|
+
}
|
|
867
990
|
// on_stop seam: the model wants to stop. Give handlers (Goal mode)
|
|
868
991
|
// a chance to BLOCK termination and keep the agent working. A
|
|
869
992
|
// handler returning continueSession=true injects its messages and
|
|
870
993
|
// we run another turn instead of returning. Bounded by
|
|
871
994
|
// maxStopBlocks (consecutive) and the outer maxTurns ceiling.
|
|
872
995
|
const maxStopBlocks = this.config.maxStopBlocks ?? GOAL_DEFAULT_MAX_STOP_BLOCKS;
|
|
873
|
-
if (goalTracker) {
|
|
874
|
-
this.
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
progress: {
|
|
879
|
-
turnCount: this.turnCount,
|
|
880
|
-
stopRound: this.stopBlockCount + 1,
|
|
881
|
-
elapsedMs: Math.max(0, Date.now() - goalTracker.startedAtMs),
|
|
882
|
-
tokensUsed: goalTracker.tokensUsed,
|
|
883
|
-
tokenBudget: goalTracker.goal.tokenBudget,
|
|
884
|
-
timeBudgetMs: goalTracker.goal.timeBudgetMs,
|
|
885
|
-
maxTurns: this.config.maxTurns,
|
|
886
|
-
maxStopBlocks,
|
|
887
|
-
},
|
|
888
|
-
});
|
|
996
|
+
if (this.goalTracker) {
|
|
997
|
+
const judgeMessages = this.stripVolatileContextMessages(messages);
|
|
998
|
+
this.deps.publishGoalJudgeContext?.(buildGoalJudgeRuntimeContext(judgeMessages, {
|
|
999
|
+
sensitiveToolResultRedactions: this.sensitiveToolResultRedactions,
|
|
1000
|
+
}));
|
|
889
1001
|
}
|
|
890
1002
|
const stopHook = await this.emitHook("on_stop", {
|
|
891
1003
|
goal: this.config.goal,
|
|
@@ -900,16 +1012,16 @@ export class TurnLoop {
|
|
|
900
1012
|
hookGoalTermination === "time_budget_exhausted"
|
|
901
1013
|
? hookGoalTermination
|
|
902
1014
|
: undefined;
|
|
903
|
-
const postJudgeBudgetTermination = goalTracker
|
|
904
|
-
? (hookBudgetTermination ?? goalBudgetTerminationReason(goalTracker, Date.now()))
|
|
1015
|
+
const postJudgeBudgetTermination = this.goalTracker
|
|
1016
|
+
? (hookBudgetTermination ?? goalBudgetTerminationReason(this.goalTracker, Date.now()))
|
|
905
1017
|
: undefined;
|
|
906
|
-
if (goalTracker && postJudgeBudgetTermination) {
|
|
1018
|
+
if (this.goalTracker && postJudgeBudgetTermination) {
|
|
907
1019
|
tlog.info("turn.goal_budget_exhausted_after_judge", {
|
|
908
1020
|
cat: "goal",
|
|
909
1021
|
reason: postJudgeBudgetTermination,
|
|
910
|
-
tokensUsed: goalTracker.tokensUsed,
|
|
911
|
-
tokenBudget: goalTracker.goal.tokenBudget,
|
|
912
|
-
timeBudgetMs: goalTracker.goal.timeBudgetMs,
|
|
1022
|
+
tokensUsed: this.goalTracker.tokensUsed,
|
|
1023
|
+
tokenBudget: this.goalTracker.goal.tokenBudget,
|
|
1024
|
+
timeBudgetMs: this.goalTracker.goal.timeBudgetMs,
|
|
913
1025
|
});
|
|
914
1026
|
this.config.onStream?.({
|
|
915
1027
|
type: "assistant_message",
|
|
@@ -924,9 +1036,10 @@ export class TurnLoop {
|
|
|
924
1036
|
reason: "goal_budget_exhausted",
|
|
925
1037
|
messages,
|
|
926
1038
|
goalTermination: postJudgeBudgetTermination,
|
|
1039
|
+
goalTerminationRound: this.stopBlockCount,
|
|
927
1040
|
};
|
|
928
1041
|
}
|
|
929
|
-
if (goalTracker && hookGoalTermination === "judge_prompt_too_large") {
|
|
1042
|
+
if (this.goalTracker && hookGoalTermination === "judge_prompt_too_large") {
|
|
930
1043
|
tlog.warn("turn.goal_judge_prompt_too_large", { cat: "goal" });
|
|
931
1044
|
this.config.onStream?.({
|
|
932
1045
|
type: "assistant_message",
|
|
@@ -953,6 +1066,8 @@ export class TurnLoop {
|
|
|
953
1066
|
// up with stopBlockCount so the UI can show "第 N 轮".
|
|
954
1067
|
this.config.onStream?.({
|
|
955
1068
|
type: "goal_progress",
|
|
1069
|
+
goalId: this.config.goal?.goalId,
|
|
1070
|
+
revision: this.config.goal?.revision,
|
|
956
1071
|
status: "not_met",
|
|
957
1072
|
round: this.stopBlockCount,
|
|
958
1073
|
gaps: goalVerdict?.gaps || undefined,
|
|
@@ -991,11 +1106,6 @@ export class TurnLoop {
|
|
|
991
1106
|
stopBlockCount: this.stopBlockCount,
|
|
992
1107
|
maxStopBlocks,
|
|
993
1108
|
});
|
|
994
|
-
this.config.onStream?.({
|
|
995
|
-
type: "goal_progress",
|
|
996
|
-
status: "exhausted",
|
|
997
|
-
round: this.stopBlockCount,
|
|
998
|
-
});
|
|
999
1109
|
goalTermination = "stop_blocks_exhausted";
|
|
1000
1110
|
this.config.onStream?.({
|
|
1001
1111
|
type: "assistant_message",
|
|
@@ -1011,18 +1121,28 @@ export class TurnLoop {
|
|
|
1011
1121
|
// rounds = prior blocks + this accepted final round.
|
|
1012
1122
|
this.config.onStream?.({
|
|
1013
1123
|
type: "goal_progress",
|
|
1124
|
+
goalId: this.config.goal.goalId,
|
|
1125
|
+
revision: this.config.goal.revision,
|
|
1014
1126
|
status: "met",
|
|
1015
1127
|
round: this.stopBlockCount + 1,
|
|
1016
1128
|
});
|
|
1017
1129
|
}
|
|
1130
|
+
const goalTerminationRound = goalTermination ? this.stopBlockCount : undefined;
|
|
1018
1131
|
this.stopBlockCount = 0;
|
|
1019
1132
|
if (await this.consumeQueuedSteer(messages, "finalize_backfill")) {
|
|
1020
1133
|
continue;
|
|
1021
1134
|
}
|
|
1022
1135
|
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
1023
|
-
return {
|
|
1136
|
+
return {
|
|
1137
|
+
text: finalText,
|
|
1138
|
+
reason: "completed",
|
|
1139
|
+
messages,
|
|
1140
|
+
goalTermination,
|
|
1141
|
+
goalTerminationRound,
|
|
1142
|
+
};
|
|
1024
1143
|
}
|
|
1025
1144
|
// Tool execution phase
|
|
1145
|
+
this.deps.onAgentControlState?.("tool-batch");
|
|
1026
1146
|
tlog.info("turn.tool_use", {
|
|
1027
1147
|
cat: "turn",
|
|
1028
1148
|
tools: response.toolCalls.map((t) => t.toolName),
|
|
@@ -1063,20 +1183,13 @@ export class TurnLoop {
|
|
|
1063
1183
|
// Record results in transcript and stream
|
|
1064
1184
|
const resultBlocks = [];
|
|
1065
1185
|
for (const result of results) {
|
|
1066
|
-
if (goalTracker) {
|
|
1067
|
-
goalToolResults.push(projectGoalJudgeToolResult(result, this.turnCount, sensitiveGoalResultTools?.has(result.toolName) === true));
|
|
1068
|
-
// Never evict the front of one legal batch: the default executor may
|
|
1069
|
-
// return 25 results in a turn. Keep at least maxToolCallsPerTurn so
|
|
1070
|
-
// the judge renderer can preserve metadata for the entire newest batch.
|
|
1071
|
-
const residencyLimit = Math.max(20, this.config.maxToolCallsPerTurn);
|
|
1072
|
-
if (goalToolResults.length > residencyLimit) {
|
|
1073
|
-
goalToolResults.splice(0, goalToolResults.length - residencyLimit);
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
1186
|
resultBlocks.push(toolResultToBlock(result));
|
|
1077
1187
|
const streamResult = toolResultForDisplay(result);
|
|
1078
|
-
const
|
|
1079
|
-
|
|
1188
|
+
const sensitiveByMetadata = sensitiveGoalResultTools?.has(result.toolName) === true;
|
|
1189
|
+
const transcriptResult = sensitiveByMetadata
|
|
1190
|
+
? SENSITIVE_TOOL_RESULT_PLACEHOLDER
|
|
1191
|
+
: toolResultTranscriptText(result);
|
|
1192
|
+
if ((result.sensitive || sensitiveByMetadata) && transcriptResult !== undefined) {
|
|
1080
1193
|
this.sensitiveToolResultRedactions.set(result.id, transcriptResult);
|
|
1081
1194
|
}
|
|
1082
1195
|
this.deps.transcript.appendToolResult(result.id, result.toolName, transcriptResult, result.error, result.sensitive ? undefined : result.contentBlocks);
|
|
@@ -1086,13 +1199,15 @@ export class TurnLoop {
|
|
|
1086
1199
|
// best-effort observability — a thrown onStream handler, a failed dynamic
|
|
1087
1200
|
// import, or a rejecting summarize must never surface as an unhandled
|
|
1088
1201
|
// rejection (Node can treat those as fatal). Swallow at the tail. (B-2)
|
|
1089
|
-
if (this.config.onStream) {
|
|
1202
|
+
if (this.config.onStream && this.deps.model.summarize && !this.goalControlStopRequested) {
|
|
1203
|
+
const summaryController = new AbortController();
|
|
1204
|
+
this.activeToolSummaryControllers.add(summaryController);
|
|
1090
1205
|
void import("./tool-summary.js")
|
|
1091
1206
|
.then(({ generateToolUseSummary }) => {
|
|
1092
|
-
if (
|
|
1207
|
+
if (this.goalControlStopRequested || summaryController.signal.aborted)
|
|
1093
1208
|
return;
|
|
1094
|
-
return generateToolUseSummary(toolCalls, toolResultsForDisplay(results), this.deps.model.summarize).then((summary) => {
|
|
1095
|
-
if (summary) {
|
|
1209
|
+
return generateToolUseSummary(toolCalls, toolResultsForDisplay(results), this.deps.model.summarize, summaryController.signal).then((summary) => {
|
|
1210
|
+
if (summary && !summaryController.signal.aborted) {
|
|
1096
1211
|
this.config.onStream?.({
|
|
1097
1212
|
type: "tool_summary",
|
|
1098
1213
|
summary,
|
|
@@ -1106,6 +1221,9 @@ export class TurnLoop {
|
|
|
1106
1221
|
cat: "turn",
|
|
1107
1222
|
error: err.message,
|
|
1108
1223
|
});
|
|
1224
|
+
})
|
|
1225
|
+
.finally(() => {
|
|
1226
|
+
this.activeToolSummaryControllers.delete(summaryController);
|
|
1109
1227
|
});
|
|
1110
1228
|
}
|
|
1111
1229
|
const toolResultMessage = { role: "user", content: resultBlocks };
|
|
@@ -1136,6 +1254,31 @@ export class TurnLoop {
|
|
|
1136
1254
|
// Tool results just pushed; recompute ctx so the bar updates *before*
|
|
1137
1255
|
// the next model round-trip — large tool outputs can move it sharply.
|
|
1138
1256
|
this.emitCtxFromMessages(messages);
|
|
1257
|
+
// A trusted tool launched asynchronous work whose completion is routed
|
|
1258
|
+
// back into this Session. End this run at the tool boundary instead of
|
|
1259
|
+
// asking the model for another step with no new evidence; the queued
|
|
1260
|
+
// completion notification will wake the Session and continue normally.
|
|
1261
|
+
// This precedes complete_goal so a single batch cannot launch unfinished
|
|
1262
|
+
// background work and simultaneously claim the enclosing Goal is done.
|
|
1263
|
+
if (this.deps.peekToolRunYield?.() === "background_notification") {
|
|
1264
|
+
// Close the current model turn before a queued steer re-drives it;
|
|
1265
|
+
// interrupt-and-redrive swaps the turn signal at this boundary.
|
|
1266
|
+
this.finalizeModelTurn();
|
|
1267
|
+
if (await this.consumeQueuedSteer(messages, "finalize_backfill")) {
|
|
1268
|
+
continue;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
if (this.deps.peekToolRunYield?.() === "background_notification" &&
|
|
1272
|
+
this.deps.consumeToolRunYield?.() === "background_notification") {
|
|
1273
|
+
tlog.info("turn.background_notification_wait", { cat: "turn" });
|
|
1274
|
+
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
1275
|
+
return {
|
|
1276
|
+
text: finalText,
|
|
1277
|
+
reason: "completed",
|
|
1278
|
+
messages,
|
|
1279
|
+
completionKind: "background_wait",
|
|
1280
|
+
};
|
|
1281
|
+
}
|
|
1139
1282
|
// Goal mode P0: explicit completion. If the model called complete_goal,
|
|
1140
1283
|
// it has DECLARED the goal done — short-circuit to "completed" WITHOUT
|
|
1141
1284
|
// running the judge hook. The tool's result is already in `messages`
|
|
@@ -1145,16 +1288,33 @@ export class TurnLoop {
|
|
|
1145
1288
|
// the model just declared finished (the judge's onMet does this when IT
|
|
1146
1289
|
// decides; a self-report must do the same, else the goal outlives its
|
|
1147
1290
|
// completion and re-arms every follow-up turn).
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
this.
|
|
1153
|
-
if (
|
|
1154
|
-
|
|
1291
|
+
const completeGoalRequested = !!this.goalTracker &&
|
|
1292
|
+
isSameGoalVersion(requestedGoalVersion, this.config.goal) &&
|
|
1293
|
+
toolCalls.some((tc) => tc.toolName === COMPLETE_GOAL_TOOL_NAME);
|
|
1294
|
+
if (completeGoalRequested) {
|
|
1295
|
+
const persisted = this.deps.clearPersistedGoal?.("completed") !== false;
|
|
1296
|
+
if (persisted) {
|
|
1297
|
+
tlog.info("turn.goal_self_reported_complete", { cat: "goal" });
|
|
1298
|
+
this.config.onStream?.({
|
|
1299
|
+
type: "goal_progress",
|
|
1300
|
+
goalId: this.config.goal?.goalId,
|
|
1301
|
+
revision: this.config.goal?.revision,
|
|
1302
|
+
status: "met",
|
|
1303
|
+
round: this.stopBlockCount + 1,
|
|
1304
|
+
});
|
|
1305
|
+
this.stopBlockCount = 0;
|
|
1306
|
+
this.finalizeModelTurn();
|
|
1307
|
+
if (await this.consumeQueuedSteer(messages, "finalize_backfill")) {
|
|
1308
|
+
continue;
|
|
1309
|
+
}
|
|
1310
|
+
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
1311
|
+
return { text: finalText, reason: "completed", messages };
|
|
1155
1312
|
}
|
|
1156
|
-
|
|
1157
|
-
|
|
1313
|
+
tlog.warn("turn.goal_self_reported_complete_persist_failed", { cat: "goal" });
|
|
1314
|
+
messages.push({
|
|
1315
|
+
role: "user",
|
|
1316
|
+
content: "<system-reminder>complete_goal 未能持久化完成状态;目标仍处于活动状态。请不要宣称已经结束,并在会话状态恢复可写后重试。</system-reminder>",
|
|
1317
|
+
});
|
|
1158
1318
|
}
|
|
1159
1319
|
// Goal mode: user-initiated cancellation. cancel_goal is the "strong
|
|
1160
1320
|
// intent" escape hatch — honor it ONLY when confirm===true (the guard the
|
|
@@ -1162,15 +1322,35 @@ export class TurnLoop {
|
|
|
1162
1322
|
// persisted goal so it never re-arms; an unconfirmed call is a no-op here
|
|
1163
1323
|
// (the tool's own result string already told the model it was ignored).
|
|
1164
1324
|
const confirmedCancel = toolCalls.some((tc) => tc.toolName === CANCEL_GOAL_TOOL_NAME && tc.args?.confirm === true);
|
|
1165
|
-
if (goalTracker &&
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
this.
|
|
1170
|
-
if (
|
|
1171
|
-
|
|
1325
|
+
if (this.goalTracker &&
|
|
1326
|
+
isSameGoalVersion(requestedGoalVersion, this.config.goal) &&
|
|
1327
|
+
confirmedCancel &&
|
|
1328
|
+
!completeGoalRequested) {
|
|
1329
|
+
const persisted = this.deps.clearPersistedGoal?.("cancelled") !== false;
|
|
1330
|
+
if (persisted) {
|
|
1331
|
+
tlog.info("turn.goal_user_cancelled", { cat: "goal" });
|
|
1332
|
+
this.stopBlockCount = 0;
|
|
1333
|
+
this.config.onStream?.({
|
|
1334
|
+
type: "goal_cleared",
|
|
1335
|
+
goalId: this.config.goal?.goalId,
|
|
1336
|
+
revision: this.config.goal?.revision,
|
|
1337
|
+
});
|
|
1338
|
+
this.finalizeModelTurn();
|
|
1339
|
+
if (await this.consumeQueuedSteer(messages, "finalize_backfill")) {
|
|
1340
|
+
continue;
|
|
1341
|
+
}
|
|
1342
|
+
return {
|
|
1343
|
+
text: finalText,
|
|
1344
|
+
reason: "completed",
|
|
1345
|
+
messages,
|
|
1346
|
+
completionKind: "goal_control_stop",
|
|
1347
|
+
};
|
|
1172
1348
|
}
|
|
1173
|
-
|
|
1349
|
+
tlog.warn("turn.goal_user_cancelled_persist_failed", { cat: "goal" });
|
|
1350
|
+
messages.push({
|
|
1351
|
+
role: "user",
|
|
1352
|
+
content: "<system-reminder>cancel_goal 未能持久化删除状态;目标仍处于活动状态。请在会话状态恢复可写后重试。</system-reminder>",
|
|
1353
|
+
});
|
|
1174
1354
|
}
|
|
1175
1355
|
// Token budget check
|
|
1176
1356
|
const totalOutputTokens = this.deps.model.getOutputTokens?.() ?? 0;
|
|
@@ -1192,7 +1372,12 @@ export class TurnLoop {
|
|
|
1192
1372
|
continue;
|
|
1193
1373
|
}
|
|
1194
1374
|
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
1195
|
-
return {
|
|
1375
|
+
return {
|
|
1376
|
+
text: finalText,
|
|
1377
|
+
reason: "completed",
|
|
1378
|
+
messages,
|
|
1379
|
+
completionKind: "limit_stop",
|
|
1380
|
+
};
|
|
1196
1381
|
}
|
|
1197
1382
|
if (budgetDecision === "nudge") {
|
|
1198
1383
|
messages.push({
|
|
@@ -1265,6 +1450,12 @@ export class TurnLoop {
|
|
|
1265
1450
|
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
1266
1451
|
return { text: finalText, reason: "model_error", messages };
|
|
1267
1452
|
}
|
|
1453
|
+
// Pause/delete may have landed while the final allowed tool batch was
|
|
1454
|
+
// draining. Do not cross that safe boundary into an extra summary request.
|
|
1455
|
+
if (this.goalControlStopRequested) {
|
|
1456
|
+
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
1457
|
+
return { text: finalText, reason: "completed", messages };
|
|
1458
|
+
}
|
|
1268
1459
|
// Max turns reached — do one final summarization call (no tools)
|
|
1269
1460
|
logger.warn("turn.max_turns_reached", {
|
|
1270
1461
|
cat: "turn",
|
|
@@ -1272,6 +1463,11 @@ export class TurnLoop {
|
|
|
1272
1463
|
turnCount: this.turnCount,
|
|
1273
1464
|
});
|
|
1274
1465
|
await this.consumeQueuedSteer(messages, "finalize_backfill");
|
|
1466
|
+
if (this.goalControlStopRequested) {
|
|
1467
|
+
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
1468
|
+
return { text: finalText, reason: "completed", messages };
|
|
1469
|
+
}
|
|
1470
|
+
this.deps.onAgentControlState?.("model");
|
|
1275
1471
|
const hasPendingSensitiveToolResults = this.sensitiveToolResultRedactions.size > 0;
|
|
1276
1472
|
messages = this.prepareMessagesForModel(messages);
|
|
1277
1473
|
if (hasPendingSensitiveToolResults) {
|
|
@@ -1284,19 +1480,27 @@ export class TurnLoop {
|
|
|
1284
1480
|
else {
|
|
1285
1481
|
messages = this.deps.contextManager.manage(messages);
|
|
1286
1482
|
}
|
|
1483
|
+
if (this.goalControlStopRequested) {
|
|
1484
|
+
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
1485
|
+
return { text: finalText, reason: "completed", messages };
|
|
1486
|
+
}
|
|
1287
1487
|
messages.push({
|
|
1288
1488
|
role: "user",
|
|
1289
1489
|
content: "<system-reminder>Turn limit reached. Provide a final summary of what you accomplished and what remains to be done. Do NOT call any tools.</system-reminder>",
|
|
1290
1490
|
});
|
|
1291
1491
|
this.emitCtxFromMessages(messages);
|
|
1292
1492
|
try {
|
|
1493
|
+
if (this.goalControlStopRequested) {
|
|
1494
|
+
messages = this.redactConsumedSensitiveToolResults(messages);
|
|
1495
|
+
return { text: finalText, reason: "completed", messages };
|
|
1496
|
+
}
|
|
1293
1497
|
const summaryResponse = await this.deps.model.call(this.deps.systemPrompt, this.prepareMessagesForModel(messages), [], // No tools available for summary turn
|
|
1294
1498
|
this.config.onStream, this.config.signal, this.modelCallRecordingOptions());
|
|
1295
1499
|
if (summaryResponse.usage?.promptTokens !== undefined) {
|
|
1296
|
-
this.recordResponseUsage(summaryResponse.usage);
|
|
1500
|
+
this.recordResponseUsage(summaryResponse.usage, "primary", false);
|
|
1297
1501
|
}
|
|
1298
|
-
if (goalTracker && summaryResponse.usage) {
|
|
1299
|
-
recordGoalUsage(goalTracker, (summaryResponse.usage.promptTokens ?? 0) + (summaryResponse.usage.completionTokens ?? 0));
|
|
1502
|
+
if (this.goalTracker && summaryResponse.usage) {
|
|
1503
|
+
recordGoalUsage(this.goalTracker, (summaryResponse.usage.promptTokens ?? 0) + (summaryResponse.usage.completionTokens ?? 0));
|
|
1300
1504
|
}
|
|
1301
1505
|
if (this.config.signal?.aborted) {
|
|
1302
1506
|
this.markStopped();
|
|
@@ -1330,6 +1534,7 @@ export class TurnLoop {
|
|
|
1330
1534
|
reason: "max_turns",
|
|
1331
1535
|
messages,
|
|
1332
1536
|
...(this.config.goal ? { goalTermination: "max_turns_exhausted" } : {}),
|
|
1537
|
+
...(this.config.goal ? { goalTerminationRound: this.stopBlockCount } : {}),
|
|
1333
1538
|
};
|
|
1334
1539
|
}
|
|
1335
1540
|
/**
|
|
@@ -1388,6 +1593,14 @@ export class TurnLoop {
|
|
|
1388
1593
|
// really just a cancel. The signal is the authoritative cancel source.
|
|
1389
1594
|
if (isAbortError(err) || this.config.signal?.aborted)
|
|
1390
1595
|
throw err;
|
|
1596
|
+
// Pause/delete arrived while the streaming attempt was in flight. A
|
|
1597
|
+
// non-streaming fallback would be a brand-new provider request after the
|
|
1598
|
+
// promised safe boundary, so revoke any partial stream and synthesize an
|
|
1599
|
+
// empty settled step instead.
|
|
1600
|
+
if (this.goalControlStopRequested) {
|
|
1601
|
+
this.config.onStream?.({ type: "tombstone", messageId: assistantMessageId });
|
|
1602
|
+
return { text: "", toolCalls: [], stopReason: "stop" };
|
|
1603
|
+
}
|
|
1391
1604
|
// Sensitive tool results are model-facing exactly once. A streaming
|
|
1392
1605
|
// fallback would re-send the same pending plaintext in a second request,
|
|
1393
1606
|
// so fail the turn and let the unified exit redact returned history.
|
|
@@ -1413,8 +1626,25 @@ export class TurnLoop {
|
|
|
1413
1626
|
return this.turnCount;
|
|
1414
1627
|
}
|
|
1415
1628
|
async consumeQueuedSteer(messages, source) {
|
|
1416
|
-
const steered = this.deps.consumeSteer?.(source) ?? [];
|
|
1417
1629
|
let consumed = false;
|
|
1630
|
+
const goalControl = this.pendingGoalControlMessage;
|
|
1631
|
+
this.pendingGoalControlMessage = null;
|
|
1632
|
+
if (goalControl &&
|
|
1633
|
+
this.config.goal?.paused !== true &&
|
|
1634
|
+
this.config.goal?.goalId === goalControl.goalId &&
|
|
1635
|
+
(this.config.goal?.revision ?? 1) === (goalControl.revision ?? 1)) {
|
|
1636
|
+
const content = `<system-reminder>\n${goalControl.text}\n</system-reminder>`;
|
|
1637
|
+
const message = { role: "user", content };
|
|
1638
|
+
messages.push(message);
|
|
1639
|
+
this.deps.transcript.appendMessage("user", content, {
|
|
1640
|
+
injected: true,
|
|
1641
|
+
source: "goal-control",
|
|
1642
|
+
});
|
|
1643
|
+
consumed = true;
|
|
1644
|
+
}
|
|
1645
|
+
const directionConsumed = await this.consumeQueuedAgentDirections(messages, source);
|
|
1646
|
+
const steered = this.deps.consumeSteer?.(source) ?? [];
|
|
1647
|
+
consumed ||= directionConsumed;
|
|
1418
1648
|
for (let index = 0; index < steered.length; index++) {
|
|
1419
1649
|
const item = steered[index];
|
|
1420
1650
|
const { id, text, clientMessageId } = item;
|
|
@@ -1460,6 +1690,42 @@ export class TurnLoop {
|
|
|
1460
1690
|
}
|
|
1461
1691
|
return consumed;
|
|
1462
1692
|
}
|
|
1693
|
+
async consumeQueuedAgentDirections(messages, source) {
|
|
1694
|
+
if (!this.deps.consumeAgentDirections)
|
|
1695
|
+
return false;
|
|
1696
|
+
this.deps.onAgentControlState?.("safe-point");
|
|
1697
|
+
const directions = this.deps.consumeAgentDirections();
|
|
1698
|
+
if (directions.length === 0)
|
|
1699
|
+
return false;
|
|
1700
|
+
directions.sort((left, right) => left.sequence - right.sequence);
|
|
1701
|
+
const content = buildAgentDirectionMessage(directions);
|
|
1702
|
+
const envelopeIds = directions.map((item) => item.id);
|
|
1703
|
+
const correlationIds = directions
|
|
1704
|
+
.map((item) => item.correlationId)
|
|
1705
|
+
.filter((value) => value !== undefined);
|
|
1706
|
+
const hook = await this.emitHook("agent_direction_submit", {
|
|
1707
|
+
source: "agent-direction",
|
|
1708
|
+
authority: "agent",
|
|
1709
|
+
prompt: directions.map((item) => item.payload.prompt).join("\n"),
|
|
1710
|
+
envelopeIds,
|
|
1711
|
+
correlationIds,
|
|
1712
|
+
safePoint: source,
|
|
1713
|
+
});
|
|
1714
|
+
const message = { role: "user", content };
|
|
1715
|
+
messages.push(message);
|
|
1716
|
+
this.deps.transcript.appendMessage("user", content, {
|
|
1717
|
+
injected: true,
|
|
1718
|
+
authority: "agent",
|
|
1719
|
+
source: "agent-direction",
|
|
1720
|
+
envelopeIds,
|
|
1721
|
+
correlationIds,
|
|
1722
|
+
});
|
|
1723
|
+
this.deps.onAgentDirectionsDelivered?.(envelopeIds);
|
|
1724
|
+
const hookInjection = wrapHookMessages(hook.messages);
|
|
1725
|
+
if (hookInjection)
|
|
1726
|
+
messages.push(hookInjection);
|
|
1727
|
+
return true;
|
|
1728
|
+
}
|
|
1463
1729
|
/**
|
|
1464
1730
|
* Generate synthetic error tool_results for any dangling tool_use blocks
|
|
1465
1731
|
* that never received results (e.g. because the API call failed).
|