@qduc/term2 0.22.1 → 0.23.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/dist/agent.d.ts +1 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +18 -10
- package/dist/agent.js.map +1 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +19 -1
- package/dist/app.js.map +1 -1
- package/dist/cli.js +26 -0
- package/dist/cli.js.map +1 -1
- package/dist/components/input/ApplicationInputSurface.js +1 -1
- package/dist/components/input/ApplicationInputSurface.js.map +1 -1
- package/dist/components/input/SettingsMenuSession.d.ts.map +1 -1
- package/dist/components/input/SettingsMenuSession.js +8 -5
- package/dist/components/input/SettingsMenuSession.js.map +1 -1
- package/dist/components/input/SubagentPoolMenuSession.d.ts +9 -0
- package/dist/components/input/SubagentPoolMenuSession.d.ts.map +1 -0
- package/dist/components/input/{MentorPoolMenuSession.js → SubagentPoolMenuSession.js} +17 -10
- package/dist/components/input/SubagentPoolMenuSession.js.map +1 -0
- package/dist/components/input/menu-controller.d.ts.map +1 -1
- package/dist/components/input/menu-controller.js +4 -3
- package/dist/components/input/menu-controller.js.map +1 -1
- package/dist/components/input/menu-registry.js +2 -2
- package/dist/components/input/menu-registry.js.map +1 -1
- package/dist/components/input/menu-types.d.ts +5 -1
- package/dist/components/input/menu-types.d.ts.map +1 -1
- package/dist/components/input/triggers.d.ts.map +1 -1
- package/dist/components/input/triggers.js +10 -7
- package/dist/components/input/triggers.js.map +1 -1
- package/dist/components/layout/Banner.d.ts.map +1 -1
- package/dist/components/layout/Banner.js +4 -1
- package/dist/components/layout/Banner.js.map +1 -1
- package/dist/components/layout/StatusBar.d.ts.map +1 -1
- package/dist/components/layout/StatusBar.js +10 -17
- package/dist/components/layout/StatusBar.js.map +1 -1
- package/dist/components/menu/SettingsSelectionMenu.d.ts.map +1 -1
- package/dist/components/menu/SettingsSelectionMenu.js +3 -1
- package/dist/components/menu/SettingsSelectionMenu.js.map +1 -1
- package/dist/components/menu/SubagentPoolSelectionMenu.d.ts +19 -0
- package/dist/components/menu/SubagentPoolSelectionMenu.d.ts.map +1 -0
- package/dist/components/menu/{MentorPoolSelectionMenu.js → SubagentPoolSelectionMenu.js} +29 -15
- package/dist/components/menu/SubagentPoolSelectionMenu.js.map +1 -0
- package/dist/context/InputContext.d.ts +1 -1
- package/dist/context/InputContext.d.ts.map +1 -1
- package/dist/context/InputContext.js +2 -2
- package/dist/context/InputContext.js.map +1 -1
- package/dist/contracts/conversation-items.d.ts +4 -0
- package/dist/contracts/conversation-items.d.ts.map +1 -1
- package/dist/contracts/provider-input.d.ts +2 -0
- package/dist/contracts/provider-input.d.ts.map +1 -1
- package/dist/contracts/provider-input.js.map +1 -1
- package/dist/gateway/assertion.d.ts +1 -1
- package/dist/gateway/assertion.d.ts.map +1 -1
- package/dist/gateway/contracts.d.ts +13 -3
- package/dist/gateway/contracts.d.ts.map +1 -1
- package/dist/gateway/contracts.js +56 -0
- package/dist/gateway/contracts.js.map +1 -1
- package/dist/gateway/gateway.d.ts +40 -1
- package/dist/gateway/gateway.d.ts.map +1 -1
- package/dist/gateway/gateway.js +1319 -76
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/persistence/admission-persistence.d.ts +3 -3
- package/dist/gateway/persistence/admission-persistence.d.ts.map +1 -1
- package/dist/gateway/persistence/admission-persistence.js +25 -11
- package/dist/gateway/persistence/admission-persistence.js.map +1 -1
- package/dist/gateway/persistence/contracts.d.ts +5 -3
- package/dist/gateway/persistence/contracts.d.ts.map +1 -1
- package/dist/gateway/persistence/contracts.js +13 -0
- package/dist/gateway/persistence/contracts.js.map +1 -1
- package/dist/gateway/persistence/interaction-checkpoint.d.ts +5 -0
- package/dist/gateway/persistence/interaction-checkpoint.d.ts.map +1 -1
- package/dist/gateway/persistence/interaction-checkpoint.js +22 -0
- package/dist/gateway/persistence/interaction-checkpoint.js.map +1 -1
- package/dist/gateway/persistence/projection.d.ts.map +1 -1
- package/dist/gateway/persistence/projection.js +4 -1
- package/dist/gateway/persistence/projection.js.map +1 -1
- package/dist/gateway/persistence/session-index.d.ts +1 -1
- package/dist/gateway/persistence/session-index.d.ts.map +1 -1
- package/dist/gateway/persistence/session-index.js +2 -2
- package/dist/gateway/persistence/session-index.js.map +1 -1
- package/dist/gateway/persistence/session-snapshot.d.ts +32 -0
- package/dist/gateway/persistence/session-snapshot.d.ts.map +1 -0
- package/dist/gateway/persistence/session-snapshot.js +50 -0
- package/dist/gateway/persistence/session-snapshot.js.map +1 -0
- package/dist/gateway/runtime-factory.d.ts +37 -1
- package/dist/gateway/runtime-factory.d.ts.map +1 -1
- package/dist/gateway/runtime-factory.js +155 -24
- package/dist/gateway/runtime-factory.js.map +1 -1
- package/dist/gateway/safe-log.d.ts +1 -1
- package/dist/gateway/safe-log.d.ts.map +1 -1
- package/dist/gateway/safe-log.js +5 -46
- package/dist/gateway/safe-log.js.map +1 -1
- package/dist/gateway/serve-args.d.ts +53 -0
- package/dist/gateway/serve-args.d.ts.map +1 -0
- package/dist/gateway/serve-args.js +172 -0
- package/dist/gateway/serve-args.js.map +1 -0
- package/dist/gateway/serve.d.ts +79 -0
- package/dist/gateway/serve.d.ts.map +1 -0
- package/dist/gateway/serve.js +375 -0
- package/dist/gateway/serve.js.map +1 -0
- package/dist/gateway/server-session.d.ts +9 -0
- package/dist/gateway/server-session.d.ts.map +1 -1
- package/dist/gateway/server-session.js +142 -26
- package/dist/gateway/server-session.js.map +1 -1
- package/dist/gateway/server.d.ts.map +1 -1
- package/dist/gateway/server.js +13 -2
- package/dist/gateway/server.js.map +1 -1
- package/dist/hooks/use-subagent-pool-selection.d.ts +115 -0
- package/dist/hooks/use-subagent-pool-selection.d.ts.map +1 -0
- package/dist/hooks/{use-mentor-pool-selection.js → use-subagent-pool-selection.js} +110 -54
- package/dist/hooks/use-subagent-pool-selection.js.map +1 -0
- package/dist/lib/agent-client.d.ts +3 -0
- package/dist/lib/agent-client.d.ts.map +1 -1
- package/dist/lib/agent-client.js +7 -0
- package/dist/lib/agent-client.js.map +1 -1
- package/dist/lib/agent-configuration.d.ts +1 -0
- package/dist/lib/agent-configuration.d.ts.map +1 -1
- package/dist/lib/agent-configuration.js +3 -0
- package/dist/lib/agent-configuration.js.map +1 -1
- package/dist/lib/agent-factory.d.ts +2 -0
- package/dist/lib/agent-factory.d.ts.map +1 -1
- package/dist/lib/agent-factory.js +5 -0
- package/dist/lib/agent-factory.js.map +1 -1
- package/dist/lib/subagent-bridge.d.ts +5 -0
- package/dist/lib/subagent-bridge.d.ts.map +1 -1
- package/dist/lib/subagent-bridge.js +5 -0
- package/dist/lib/subagent-bridge.js.map +1 -1
- package/dist/lib/tool-selection-policy.d.ts +2 -0
- package/dist/lib/tool-selection-policy.d.ts.map +1 -1
- package/dist/lib/tool-selection-policy.js +6 -1
- package/dist/lib/tool-selection-policy.js.map +1 -1
- package/dist/prompts/explorer-delegation-contract.test.ts +1 -1
- package/dist/prompts/prompt-constructor.d.ts.map +1 -1
- package/dist/prompts/prompt-constructor.js +1 -0
- package/dist/prompts/prompt-constructor.js.map +1 -1
- package/dist/prompts/prompt-constructor.test.ts +3 -0
- package/dist/prompts/prompt-constructor.ts +1 -0
- package/dist/prompts/prompt-profiles.d.ts.map +1 -1
- package/dist/prompts/prompt-profiles.js +3 -2
- package/dist/prompts/prompt-profiles.js.map +1 -1
- package/dist/prompts/prompt-profiles.ts +4 -2
- package/dist/prompts/subagent-delegation.d.ts +2 -1
- package/dist/prompts/subagent-delegation.d.ts.map +1 -1
- package/dist/prompts/subagent-delegation.js +10 -5
- package/dist/prompts/subagent-delegation.js.map +1 -1
- package/dist/prompts/subagent-delegation.test.ts +10 -3
- package/dist/prompts/subagent-delegation.ts +16 -4
- package/dist/prompts/subagents/librarian.md +26 -21
- package/dist/prompts/subagents/reviewer.md +33 -0
- package/dist/services/agent-runtime/application-run-loop.d.ts.map +1 -1
- package/dist/services/agent-runtime/application-run-loop.js +10 -5
- package/dist/services/agent-runtime/application-run-loop.js.map +1 -1
- package/dist/services/agent-runtime/context-compaction/local-context-compactor.d.ts +9 -0
- package/dist/services/agent-runtime/context-compaction/local-context-compactor.d.ts.map +1 -1
- package/dist/services/agent-runtime/context-compaction/local-context-compactor.js +6 -0
- package/dist/services/agent-runtime/context-compaction/local-context-compactor.js.map +1 -1
- package/dist/services/agent-runtime/model-resolver.d.ts +6 -0
- package/dist/services/agent-runtime/model-resolver.d.ts.map +1 -1
- package/dist/services/agent-runtime/model-resolver.js +18 -4
- package/dist/services/agent-runtime/model-resolver.js.map +1 -1
- package/dist/services/approval/non-interactive-approval-policy.d.ts.map +1 -1
- package/dist/services/approval/non-interactive-approval-policy.js +2 -1
- package/dist/services/approval/non-interactive-approval-policy.js.map +1 -1
- package/dist/services/approval/shell-auto-approval-evaluator.js +2 -2
- package/dist/services/approval/shell-auto-approval-evaluator.js.map +1 -1
- package/dist/services/conversation/conversation-service.d.ts +28 -0
- package/dist/services/conversation/conversation-service.d.ts.map +1 -1
- package/dist/services/conversation/conversation-service.js +95 -27
- package/dist/services/conversation/conversation-service.js.map +1 -1
- package/dist/services/conversation/run-item-normalizer.d.ts.map +1 -1
- package/dist/services/conversation/run-item-normalizer.js +3 -0
- package/dist/services/conversation/run-item-normalizer.js.map +1 -1
- package/dist/services/conversation/session-browser.d.ts +5 -0
- package/dist/services/conversation/session-browser.d.ts.map +1 -1
- package/dist/services/conversation/session-browser.js +94 -31
- package/dist/services/conversation/session-browser.js.map +1 -1
- package/dist/services/conversation/session-index/session-index-database.d.ts +1 -0
- package/dist/services/conversation/session-index/session-index-database.d.ts.map +1 -1
- package/dist/services/conversation/session-index/session-index-database.js +6 -4
- package/dist/services/conversation/session-index/session-index-database.js.map +1 -1
- package/dist/services/conversation/session-index/session-index-schema.d.ts +1 -1
- package/dist/services/conversation/session-index/session-index-schema.d.ts.map +1 -1
- package/dist/services/conversation/session-index/session-index-schema.js +2 -1
- package/dist/services/conversation/session-index/session-index-schema.js.map +1 -1
- package/dist/services/conversation-agent-client.d.ts +3 -0
- package/dist/services/conversation-agent-client.d.ts.map +1 -1
- package/dist/services/memory/memory-capabilities.d.ts.map +1 -1
- package/dist/services/memory/memory-capabilities.js +2 -5
- package/dist/services/memory/memory-capabilities.js.map +1 -1
- package/dist/services/plan-mode-interceptor.js +2 -2
- package/dist/services/plan-mode-interceptor.js.map +1 -1
- package/dist/services/sandboxed-code-host/host-types.d.ts +12 -1
- package/dist/services/sandboxed-code-host/host-types.d.ts.map +1 -1
- package/dist/services/sandboxed-code-host/host-types.js.map +1 -1
- package/dist/services/sandboxed-code-host/host-worker.d.ts.map +1 -1
- package/dist/services/sandboxed-code-host/host-worker.js +146 -31
- package/dist/services/sandboxed-code-host/host-worker.js.map +1 -1
- package/dist/services/sandboxed-code-host/sandbox.d.ts +6 -1
- package/dist/services/sandboxed-code-host/sandbox.d.ts.map +1 -1
- package/dist/services/sandboxed-code-host/sandbox.js +5 -0
- package/dist/services/sandboxed-code-host/sandbox.js.map +1 -1
- package/dist/services/sandboxed-code-host/sandboxed-code-host.d.ts +3 -3
- package/dist/services/sandboxed-code-host/sandboxed-code-host.d.ts.map +1 -1
- package/dist/services/sandboxed-code-host/sandboxed-code-host.js +173 -22
- package/dist/services/sandboxed-code-host/sandboxed-code-host.js.map +1 -1
- package/dist/services/session/session-access-state.d.ts +5 -1
- package/dist/services/session/session-access-state.d.ts.map +1 -1
- package/dist/services/session/session-access-state.js +8 -1
- package/dist/services/session/session-access-state.js.map +1 -1
- package/dist/services/session/session-client-factory.d.ts +1 -0
- package/dist/services/session/session-client-factory.d.ts.map +1 -1
- package/dist/services/session/session-client-factory.js +1 -1
- package/dist/services/session/session-client-factory.js.map +1 -1
- package/dist/services/session/session-composition.d.ts +22 -4
- package/dist/services/session/session-composition.d.ts.map +1 -1
- package/dist/services/session/session-composition.js +9 -5
- package/dist/services/session/session-composition.js.map +1 -1
- package/dist/services/settings/ancillary-settings-migration.d.ts.map +1 -1
- package/dist/services/settings/ancillary-settings-migration.js +8 -1
- package/dist/services/settings/ancillary-settings-migration.js.map +1 -1
- package/dist/services/settings/settings-schema.d.ts +12 -40
- package/dist/services/settings/settings-schema.d.ts.map +1 -1
- package/dist/services/settings/settings-schema.js +27 -53
- package/dist/services/settings/settings-schema.js.map +1 -1
- package/dist/services/settings/settings-sources.d.ts +0 -3
- package/dist/services/settings/settings-sources.d.ts.map +1 -1
- package/dist/services/settings/settings-sources.js +0 -3
- package/dist/services/settings/settings-sources.js.map +1 -1
- package/dist/services/settings/settings-ui-metadata.d.ts.map +1 -1
- package/dist/services/settings/settings-ui-metadata.js +3 -3
- package/dist/services/settings/settings-ui-metadata.js.map +1 -1
- package/dist/services/settings/test-helpers/settings-consumer-inventory.d.ts +1 -1
- package/dist/services/settings/test-helpers/settings-consumer-inventory.d.ts.map +1 -1
- package/dist/services/settings/test-helpers/settings-consumer-inventory.js +5 -8
- package/dist/services/settings/test-helpers/settings-consumer-inventory.js.map +1 -1
- package/dist/services/subagents/nested-runner.d.ts +3 -0
- package/dist/services/subagents/nested-runner.d.ts.map +1 -1
- package/dist/services/subagents/nested-runner.js +31 -4
- package/dist/services/subagents/nested-runner.js.map +1 -1
- package/dist/services/subagents/role-loader.d.ts.map +1 -1
- package/dist/services/subagents/role-loader.js +7 -12
- package/dist/services/subagents/role-loader.js.map +1 -1
- package/dist/services/subagents/runtime.d.ts +3 -0
- package/dist/services/subagents/runtime.d.ts.map +1 -1
- package/dist/services/subagents/runtime.js +35 -3
- package/dist/services/subagents/runtime.js.map +1 -1
- package/dist/services/subagents/subagent-async-registry.d.ts +10 -1
- package/dist/services/subagents/subagent-async-registry.d.ts.map +1 -1
- package/dist/services/subagents/subagent-async-registry.js +21 -4
- package/dist/services/subagents/subagent-async-registry.js.map +1 -1
- package/dist/services/subagents/subagent-manager.d.ts +3 -0
- package/dist/services/subagents/subagent-manager.d.ts.map +1 -1
- package/dist/services/subagents/subagent-manager.js.map +1 -1
- package/dist/services/subagents/subagent-pool-config.d.ts +39 -0
- package/dist/services/subagents/subagent-pool-config.d.ts.map +1 -0
- package/dist/services/subagents/subagent-pool-config.js +84 -0
- package/dist/services/subagents/subagent-pool-config.js.map +1 -0
- package/dist/services/subagents/subagent-role-pool-selector.d.ts +29 -0
- package/dist/services/subagents/subagent-role-pool-selector.d.ts.map +1 -0
- package/dist/services/subagents/subagent-role-pool-selector.js +56 -0
- package/dist/services/subagents/subagent-role-pool-selector.js.map +1 -0
- package/dist/services/subagents/tool-policy.d.ts +13 -0
- package/dist/services/subagents/tool-policy.d.ts.map +1 -1
- package/dist/services/subagents/tool-policy.js +36 -4
- package/dist/services/subagents/tool-policy.js.map +1 -1
- package/dist/services/subagents/types.d.ts +1 -1
- package/dist/services/subagents/types.d.ts.map +1 -1
- package/dist/services/subagents/types.js +1 -1
- package/dist/services/subagents/types.js.map +1 -1
- package/dist/test-helpers/outside-sandbox-temp-dir.d.ts +2 -0
- package/dist/test-helpers/outside-sandbox-temp-dir.d.ts.map +1 -0
- package/dist/test-helpers/outside-sandbox-temp-dir.js +38 -0
- package/dist/test-helpers/outside-sandbox-temp-dir.js.map +1 -0
- package/dist/tools/agent/configure-task-check-in.d.ts +2 -0
- package/dist/tools/agent/configure-task-check-in.d.ts.map +1 -1
- package/dist/tools/agent/configure-task-check-in.js +3 -0
- package/dist/tools/agent/configure-task-check-in.js.map +1 -1
- package/dist/tools/agent/run-explorer.d.ts +6 -0
- package/dist/tools/agent/run-explorer.d.ts.map +1 -0
- package/dist/tools/agent/run-explorer.js +58 -0
- package/dist/tools/agent/run-explorer.js.map +1 -0
- package/dist/tools/agent/run-subagent-async.d.ts +2 -0
- package/dist/tools/agent/run-subagent-async.d.ts.map +1 -1
- package/dist/tools/agent/run-subagent-async.js +3 -3
- package/dist/tools/agent/run-subagent-async.js.map +1 -1
- package/dist/tools/agent/run-subagent.d.ts +2 -2
- package/dist/tools/agent/run-subagent.d.ts.map +1 -1
- package/dist/tools/agent/run-subagent.js +8 -6
- package/dist/tools/agent/run-subagent.js.map +1 -1
- package/dist/tools/file/apply-patch.d.ts.map +1 -1
- package/dist/tools/file/apply-patch.js +7 -2
- package/dist/tools/file/apply-patch.js.map +1 -1
- package/dist/tools/file/create-file.d.ts.map +1 -1
- package/dist/tools/file/create-file.js +4 -0
- package/dist/tools/file/create-file.js.map +1 -1
- package/dist/tools/file/glob.d.ts.map +1 -1
- package/dist/tools/file/glob.js +6 -0
- package/dist/tools/file/glob.js.map +1 -1
- package/dist/tools/file/search-replace.d.ts.map +1 -1
- package/dist/tools/file/search-replace.js +6 -2
- package/dist/tools/file/search-replace.js.map +1 -1
- package/dist/tools/format-helpers.d.ts +5 -0
- package/dist/tools/format-helpers.d.ts.map +1 -1
- package/dist/tools/format-helpers.js.map +1 -1
- package/dist/tools/memory/memory-tools.d.ts +0 -1
- package/dist/tools/memory/memory-tools.d.ts.map +1 -1
- package/dist/tools/memory/memory-tools.js +1 -116
- package/dist/tools/memory/memory-tools.js.map +1 -1
- package/dist/tools/scripted-return-contract.d.ts +24 -0
- package/dist/tools/scripted-return-contract.d.ts.map +1 -0
- package/dist/tools/scripted-return-contract.js +36 -0
- package/dist/tools/scripted-return-contract.js.map +1 -0
- package/dist/tools/session-browser/session-browser-tools.d.ts.map +1 -1
- package/dist/tools/session-browser/session-browser-tools.js +21 -8
- package/dist/tools/session-browser/session-browser-tools.js.map +1 -1
- package/dist/tools/system/run-code/index.d.ts +3 -0
- package/dist/tools/system/run-code/index.d.ts.map +1 -1
- package/dist/tools/system/run-code/index.js +3 -0
- package/dist/tools/system/run-code/index.js.map +1 -1
- package/dist/tools/system/run-code/run-code-execution.d.ts +56 -0
- package/dist/tools/system/run-code/run-code-execution.d.ts.map +1 -0
- package/dist/tools/system/run-code/run-code-execution.js +68 -0
- package/dist/tools/system/run-code/run-code-execution.js.map +1 -0
- package/dist/tools/system/run-code/run-code-runtime-contract.d.ts +20 -0
- package/dist/tools/system/run-code/run-code-runtime-contract.d.ts.map +1 -0
- package/dist/tools/system/run-code/run-code-runtime-contract.js +2 -0
- package/dist/tools/system/run-code/run-code-runtime-contract.js.map +1 -0
- package/dist/tools/system/run-code/run-code-runtime.d.ts +99 -0
- package/dist/tools/system/run-code/run-code-runtime.d.ts.map +1 -0
- package/dist/tools/system/run-code/run-code-runtime.js +719 -0
- package/dist/tools/system/run-code/run-code-runtime.js.map +1 -0
- package/dist/tools/system/run-code/run-code-telemetry.d.ts +12 -10
- package/dist/tools/system/run-code/run-code-telemetry.d.ts.map +1 -1
- package/dist/tools/system/run-code/run-code-telemetry.js +48 -72
- package/dist/tools/system/run-code/run-code-telemetry.js.map +1 -1
- package/dist/tools/system/run-code/run-code.d.ts +22 -59
- package/dist/tools/system/run-code/run-code.d.ts.map +1 -1
- package/dist/tools/system/run-code/run-code.js +118 -784
- package/dist/tools/system/run-code/run-code.js.map +1 -1
- package/dist/tools/system/run-code/tools-header.d.ts +16 -4
- package/dist/tools/system/run-code/tools-header.d.ts.map +1 -1
- package/dist/tools/system/run-code/tools-header.js +32 -16
- package/dist/tools/system/run-code/tools-header.js.map +1 -1
- package/dist/tools/system/shell.d.ts +3 -0
- package/dist/tools/system/shell.d.ts.map +1 -1
- package/dist/tools/system/shell.js +13 -3
- package/dist/tools/system/shell.js.map +1 -1
- package/dist/tools/types.d.ts +12 -4
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js.map +1 -1
- package/dist/utils/ai/model-settings.d.ts +6 -0
- package/dist/utils/ai/model-settings.d.ts.map +1 -1
- package/dist/utils/ai/model-settings.js +7 -1
- package/dist/utils/ai/model-settings.js.map +1 -1
- package/dist/utils/ai/token-usage.d.ts +4 -5
- package/dist/utils/ai/token-usage.d.ts.map +1 -1
- package/dist/utils/ai/token-usage.js +3 -3
- package/dist/utils/ai/token-usage.js.map +1 -1
- package/dist/utils/conversation/conversation-utils.d.ts.map +1 -1
- package/dist/utils/conversation/conversation-utils.js +3 -0
- package/dist/utils/conversation/conversation-utils.js.map +1 -1
- package/dist/utils/settings-command.d.ts.map +1 -1
- package/dist/utils/settings-command.js +2 -1
- package/dist/utils/settings-command.js.map +1 -1
- package/dist/utils/shell/sandbox/sandbox-policy.d.ts +2 -0
- package/dist/utils/shell/sandbox/sandbox-policy.d.ts.map +1 -1
- package/dist/utils/shell/sandbox/sandbox-policy.js +1 -1
- package/dist/utils/shell/sandbox/sandbox-policy.js.map +1 -1
- package/dist/utils/streaming/streaming-session-factory.d.ts.map +1 -1
- package/dist/utils/streaming/streaming-session-factory.js +22 -22
- package/dist/utils/streaming/streaming-session-factory.js.map +1 -1
- package/package.json +1 -1
- package/dist/components/input/MentorPoolMenuSession.d.ts +0 -9
- package/dist/components/input/MentorPoolMenuSession.d.ts.map +0 -1
- package/dist/components/input/MentorPoolMenuSession.js.map +0 -1
- package/dist/components/menu/MentorPoolSelectionMenu.d.ts +0 -13
- package/dist/components/menu/MentorPoolSelectionMenu.d.ts.map +0 -1
- package/dist/components/menu/MentorPoolSelectionMenu.js.map +0 -1
- package/dist/hooks/use-mentor-pool-selection.d.ts +0 -105
- package/dist/hooks/use-mentor-pool-selection.d.ts.map +0 -1
- package/dist/hooks/use-mentor-pool-selection.js.map +0 -1
|
@@ -0,0 +1,719 @@
|
|
|
1
|
+
import { appendFileSync } from 'node:fs';
|
|
2
|
+
import { lstat } from 'node:fs/promises';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { SandboxedCodeHostImpl } from '../../../services/sandboxed-code-host/sandboxed-code-host.js';
|
|
6
|
+
import { applyApprovalGrant } from '../../../services/approval/approval-grant-executor.js';
|
|
7
|
+
import { resolveOutsideWorkspaceEdit } from '../../../services/approval/approval-descriptor.js';
|
|
8
|
+
import { normalizeToolParameters } from '../../../lib/tool-invoke.js';
|
|
9
|
+
import { isZodToolParameterSchema } from '../../types.js';
|
|
10
|
+
import { renderCompactSignature } from './tools-header.js';
|
|
11
|
+
import { getScriptedReturnContract, scriptedReturnContractJsonSchema, validateScriptedReturn, } from '../../scripted-return-contract.js';
|
|
12
|
+
import { WORKFLOW_PROHIBITED_TOOLS } from '../../../services/agent-runtime/workflow/workflow-evaluator.js';
|
|
13
|
+
import { resolveWorkspacePath, resolveWorkspacePathPhysically } from '../../utils.js';
|
|
14
|
+
import { parseUpstreamApplyPatch } from '../../file/upstream-apply-patch.js';
|
|
15
|
+
import { saveOutputArtifact } from '../../../utils/shell/shell-output.js';
|
|
16
|
+
import { getRunCodeExecutionResult } from './run-code-execution.js';
|
|
17
|
+
export const TOOL_NAME_RUN_CODE = 'run_code';
|
|
18
|
+
export const TOOL_NAME_DESCRIBE = 'describe';
|
|
19
|
+
/** Limits governing one script invocation. */
|
|
20
|
+
export const RUN_CODE_LIMITS = {
|
|
21
|
+
maxCalls: 200,
|
|
22
|
+
maxConcurrency: 8,
|
|
23
|
+
maxResultChars: 100_000,
|
|
24
|
+
maxMediaBytes: 8 * 1024 * 1024,
|
|
25
|
+
maxMediaTotalBytes: 32 * 1024 * 1024,
|
|
26
|
+
maxMediaAttachments: 32,
|
|
27
|
+
maxCodeBytes: 65_536,
|
|
28
|
+
maxOutputBytes: 262_144,
|
|
29
|
+
maxConsoleBytes: 262_144,
|
|
30
|
+
};
|
|
31
|
+
/** Tools that are structurally unavailable from a script. */
|
|
32
|
+
export const RUN_CODE_PROHIBITED_TOOLS = new Set([
|
|
33
|
+
...WORKFLOW_PROHIBITED_TOOLS,
|
|
34
|
+
TOOL_NAME_RUN_CODE,
|
|
35
|
+
'ask_mentor',
|
|
36
|
+
'session_rollover',
|
|
37
|
+
'shell',
|
|
38
|
+
'bash',
|
|
39
|
+
'enter_worktree',
|
|
40
|
+
'exit_worktree',
|
|
41
|
+
]);
|
|
42
|
+
/** Static semantic adapters for action tools whose result contract is known. */
|
|
43
|
+
export const ACTION_SEMANTICS = {
|
|
44
|
+
configure_task_check_in: (raw) => {
|
|
45
|
+
const parsed = parseActionPayload(raw);
|
|
46
|
+
if (!isRecord(parsed) || typeof parsed.ok !== 'boolean')
|
|
47
|
+
return { outcome: 'unknown', reason: 'unrecognized action result shape' };
|
|
48
|
+
if (parsed.ok === true)
|
|
49
|
+
return { outcome: 'applied' };
|
|
50
|
+
return {
|
|
51
|
+
outcome: 'not_applied',
|
|
52
|
+
reason: typeof parsed.error === 'string' && parsed.error ? parsed.error : 'action reported ok:false',
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
cancel_run: (raw) => {
|
|
56
|
+
const parsed = parseActionPayload(raw);
|
|
57
|
+
if (!isRecord(parsed) || typeof parsed.ok !== 'boolean')
|
|
58
|
+
return { outcome: 'unknown', reason: 'unrecognized action result shape' };
|
|
59
|
+
if (parsed.ok === true &&
|
|
60
|
+
typeof parsed.runId === 'string' &&
|
|
61
|
+
parsed.runId.length > 0 &&
|
|
62
|
+
parsed.status === 'cancelling') {
|
|
63
|
+
return { outcome: 'applied', reason: 'cancellation requested and accepted; settlement is reported separately' };
|
|
64
|
+
}
|
|
65
|
+
if (parsed.ok === false &&
|
|
66
|
+
parsed.code === 'not_active' &&
|
|
67
|
+
typeof parsed.target === 'string' &&
|
|
68
|
+
parsed.target.length > 0) {
|
|
69
|
+
return { outcome: 'not_applied', reason: `not_active (target: ${parsed.target})` };
|
|
70
|
+
}
|
|
71
|
+
return { outcome: 'unknown', reason: 'unrecognized action result shape' };
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
export const isActionTool = (name) => ACTION_SEMANTICS[name] !== undefined;
|
|
75
|
+
const parseActionPayload = (raw) => {
|
|
76
|
+
if (typeof raw !== 'string')
|
|
77
|
+
return raw;
|
|
78
|
+
try {
|
|
79
|
+
return JSON.parse(raw);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return raw;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const MAX_RECEIPT_REASON_CHARS = 280;
|
|
86
|
+
export const clipReason = (reason) => reason.length <= MAX_RECEIPT_REASON_CHARS ? reason : `${reason.slice(0, MAX_RECEIPT_REASON_CHARS)}…`;
|
|
87
|
+
export function isDirectlyCallable(tool) {
|
|
88
|
+
return RUN_CODE_PROHIBITED_TOOLS.has(tool.name);
|
|
89
|
+
}
|
|
90
|
+
export function describeTool(tool) {
|
|
91
|
+
let parameters;
|
|
92
|
+
const targetSchema = tool.canonicalParameters ?? tool.parameters;
|
|
93
|
+
if (isZodToolParameterSchema(targetSchema)) {
|
|
94
|
+
try {
|
|
95
|
+
parameters = z.toJSONSchema(targetSchema, { io: 'input' });
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
parameters = { unconvertible: true };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (targetSchema && typeof targetSchema === 'object') {
|
|
102
|
+
parameters = targetSchema;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
parameters = { unconvertible: true };
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
name: tool.name,
|
|
109
|
+
description: tool.description,
|
|
110
|
+
parameters,
|
|
111
|
+
scriptedReturnContract: scriptedReturnContractJsonSchema(getScriptedReturnContract(tool)),
|
|
112
|
+
...(typeof tool.scriptedReturnShape === 'string' && tool.scriptedReturnShape
|
|
113
|
+
? { scriptedReturnShape: tool.scriptedReturnShape }
|
|
114
|
+
: {}),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const isRecord = (value) => typeof value === 'object' && value !== null;
|
|
118
|
+
const isMediaContentPart = (value) => isRecord(value) && ((value.type === 'image' && 'image' in value) || (value.type === 'file' && 'file' in value));
|
|
119
|
+
const mediaBytes = (value) => {
|
|
120
|
+
const payload = value.type === 'image' ? value.image : value.type === 'file' ? value.file : undefined;
|
|
121
|
+
if (isRecord(payload) && typeof payload.data === 'string') {
|
|
122
|
+
try {
|
|
123
|
+
return Buffer.from(payload.data, 'base64').byteLength;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return Buffer.byteLength(payload.data, 'utf8');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
return Buffer.byteLength(JSON.stringify(payload) ?? '', 'utf8');
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return Number.POSITIVE_INFINITY;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const MEDIA_REFERENCE_KEY = '__term2_run_code_media_reference__';
|
|
137
|
+
const isMediaReference = (value) => isRecord(value) && typeof value[MEDIA_REFERENCE_KEY] === 'string' && Object.keys(value).length === 1;
|
|
138
|
+
export function createMediaReferenceStore() {
|
|
139
|
+
const attachments = new Map();
|
|
140
|
+
const byValue = new WeakMap();
|
|
141
|
+
let totalBytes = 0;
|
|
142
|
+
const capture = (value) => {
|
|
143
|
+
if (isMediaContentPart(value)) {
|
|
144
|
+
const existing = byValue.get(value);
|
|
145
|
+
if (existing !== undefined)
|
|
146
|
+
return existing ? { [MEDIA_REFERENCE_KEY]: existing } : '[media content omitted]';
|
|
147
|
+
const size = mediaBytes(value);
|
|
148
|
+
if (!Number.isFinite(size) ||
|
|
149
|
+
size > RUN_CODE_LIMITS.maxMediaBytes ||
|
|
150
|
+
attachments.size >= RUN_CODE_LIMITS.maxMediaAttachments ||
|
|
151
|
+
totalBytes + size > RUN_CODE_LIMITS.maxMediaTotalBytes) {
|
|
152
|
+
byValue.set(value, null);
|
|
153
|
+
return `[media content omitted: attachment exceeds the ${RUN_CODE_LIMITS.maxMediaBytes}-byte per-image or ${RUN_CODE_LIMITS.maxMediaTotalBytes}-byte per-run limit]`;
|
|
154
|
+
}
|
|
155
|
+
const token = `run_code_media_${randomUUID()}`;
|
|
156
|
+
byValue.set(value, token);
|
|
157
|
+
attachments.set(token, value);
|
|
158
|
+
totalBytes += size;
|
|
159
|
+
return { [MEDIA_REFERENCE_KEY]: token };
|
|
160
|
+
}
|
|
161
|
+
if (Array.isArray(value))
|
|
162
|
+
return value.map(capture);
|
|
163
|
+
if (isRecord(value))
|
|
164
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, capture(entry)]));
|
|
165
|
+
return value;
|
|
166
|
+
};
|
|
167
|
+
const resolve = (value) => {
|
|
168
|
+
if (isMediaReference(value))
|
|
169
|
+
return attachments.get(value[MEDIA_REFERENCE_KEY]) ?? value;
|
|
170
|
+
if (Array.isArray(value))
|
|
171
|
+
return value.map(resolve);
|
|
172
|
+
if (isRecord(value))
|
|
173
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, resolve(entry)]));
|
|
174
|
+
return value;
|
|
175
|
+
};
|
|
176
|
+
return { capture, resolve };
|
|
177
|
+
}
|
|
178
|
+
const containsMediaContent = (value, ancestors = new Set()) => {
|
|
179
|
+
if (isMediaContentPart(value))
|
|
180
|
+
return true;
|
|
181
|
+
if (!isRecord(value) && !Array.isArray(value))
|
|
182
|
+
return false;
|
|
183
|
+
if (ancestors.has(value))
|
|
184
|
+
return false;
|
|
185
|
+
ancestors.add(value);
|
|
186
|
+
const found = Array.isArray(value)
|
|
187
|
+
? value.some((entry) => containsMediaContent(entry, ancestors))
|
|
188
|
+
: Object.values(value).some((entry) => containsMediaContent(entry, ancestors));
|
|
189
|
+
ancestors.delete(value);
|
|
190
|
+
return found;
|
|
191
|
+
};
|
|
192
|
+
const truncate = (text, limit) => {
|
|
193
|
+
if (text.length <= limit)
|
|
194
|
+
return text;
|
|
195
|
+
let prefix = text.slice(0, limit);
|
|
196
|
+
if (/[\uD800-\uDBFF]$/.test(prefix))
|
|
197
|
+
prefix = prefix.slice(0, -1);
|
|
198
|
+
return `${prefix}\n[truncated: result exceeded ${limit} characters]`;
|
|
199
|
+
};
|
|
200
|
+
export const serializeResult = async (result, limit, toolName, callsCompleted) => {
|
|
201
|
+
const execution = getRunCodeExecutionResult(result);
|
|
202
|
+
if (execution && result instanceof String)
|
|
203
|
+
result = String(result);
|
|
204
|
+
if (typeof result === 'string')
|
|
205
|
+
return { ok: true, result: truncate(result, limit) };
|
|
206
|
+
try {
|
|
207
|
+
const encoded = JSON.stringify(result);
|
|
208
|
+
if (encoded === undefined)
|
|
209
|
+
return { ok: true, result: null };
|
|
210
|
+
if (encoded.length <= limit)
|
|
211
|
+
return { ok: true, result: result };
|
|
212
|
+
if (containsMediaContent(result))
|
|
213
|
+
return { ok: true, result: `[truncated: media result exceeded ${limit} characters; media content omitted]` };
|
|
214
|
+
let retrieval = '';
|
|
215
|
+
try {
|
|
216
|
+
const artifactPath = await saveOutputArtifact(encoded, { filenamePrefix: 'tool-overflow' });
|
|
217
|
+
retrieval = `Full output saved to: ${artifactPath}. `;
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
retrieval = 'Full output could not be saved; the omitted result is unavailable. ';
|
|
221
|
+
}
|
|
222
|
+
const callUnit = callsCompleted === 1 ? 'call' : 'calls';
|
|
223
|
+
return {
|
|
224
|
+
ok: false,
|
|
225
|
+
error: `Tool "${toolName}" result exceeded ${limit} characters and could not be delivered to script. ${retrieval}${callsCompleted} nested tool ${callUnit} completed — inspect state before retrying; tool effects have already completed.`,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
return { ok: true, result: truncate(String(result), limit) };
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
export function getConversationSessionId(context) {
|
|
233
|
+
if (!context || typeof context !== 'object')
|
|
234
|
+
return undefined;
|
|
235
|
+
const runContext = context.context;
|
|
236
|
+
if (!runContext || typeof runContext !== 'object')
|
|
237
|
+
return undefined;
|
|
238
|
+
const sessionId = runContext.sessionId;
|
|
239
|
+
return typeof sessionId === 'string' && sessionId.length > 0 ? sessionId : undefined;
|
|
240
|
+
}
|
|
241
|
+
export function writeNestedCallRecord(tool, sessionId, outcome) {
|
|
242
|
+
const logPath = process.env.TERM2_NESTED_CALL_LOG;
|
|
243
|
+
if (!logPath || !sessionId)
|
|
244
|
+
return;
|
|
245
|
+
try {
|
|
246
|
+
appendFileSync(logPath, `${JSON.stringify({ tool, sessionId, timestamp: new Date().toISOString(), outcome })}\n`, 'utf8');
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
// Experiment-only logging must never affect tool execution.
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
const PATH_TOOLS = new Set([
|
|
253
|
+
'read_file',
|
|
254
|
+
'create_file',
|
|
255
|
+
'search_replace',
|
|
256
|
+
'apply_patch',
|
|
257
|
+
'grep',
|
|
258
|
+
'glob',
|
|
259
|
+
'read_code_outline',
|
|
260
|
+
'code_context_search',
|
|
261
|
+
]);
|
|
262
|
+
export async function bindPreparedAuthority(toolName, params, cwd, executionContext) {
|
|
263
|
+
const isRemote = executionContext?.isRemote() ?? false;
|
|
264
|
+
if (isRemote && PATH_TOOLS.has(toolName))
|
|
265
|
+
return { kind: 'denied', message: 'Cannot establish remote physical path authority for a nested tool call.' };
|
|
266
|
+
try {
|
|
267
|
+
const physicalRoot = isRemote ? cwd : await requirePhysicalPath(cwd, cwd);
|
|
268
|
+
return { kind: 'bound', physicalRoot, params: await bindPreparedArguments(toolName, params, cwd) };
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
return {
|
|
272
|
+
kind: 'denied',
|
|
273
|
+
message: `Cannot establish physical path authority: ${error instanceof Error ? error.message : String(error)}`,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
async function requirePhysicalPath(value, cwd, semantics = 'referent') {
|
|
278
|
+
const physicalPath = await resolveWorkspacePathPhysically(value, cwd);
|
|
279
|
+
if (physicalPath === undefined)
|
|
280
|
+
throw new Error(`Unresolved path: ${value}`);
|
|
281
|
+
if (semantics === 'unlink-source') {
|
|
282
|
+
const lexicalPath = resolveWorkspacePath(value, cwd, { allowOutsideWorkspace: true });
|
|
283
|
+
const stats = await lstat(lexicalPath);
|
|
284
|
+
if (stats.isSymbolicLink())
|
|
285
|
+
throw new Error(`Symlink unlink source is unsupported: ${value}`);
|
|
286
|
+
}
|
|
287
|
+
return physicalPath;
|
|
288
|
+
}
|
|
289
|
+
async function bindPreparedArguments(toolName, params, cwd) {
|
|
290
|
+
if (!params || typeof params !== 'object' || Array.isArray(params) || !PATH_TOOLS.has(toolName))
|
|
291
|
+
return params;
|
|
292
|
+
const record = params;
|
|
293
|
+
const bindPath = async (value, semantics = 'referent') => typeof value === 'string' ? requirePhysicalPath(value, cwd, semantics) : value;
|
|
294
|
+
if (toolName === 'apply_patch' && typeof record.patch === 'string')
|
|
295
|
+
return { ...record, patch: await bindPatchPaths(record.patch, bindPath) };
|
|
296
|
+
return 'path' in record ? { ...record, path: await bindPath(record.path) } : params;
|
|
297
|
+
}
|
|
298
|
+
async function bindPatchPaths(patch, bindPath) {
|
|
299
|
+
let parsed;
|
|
300
|
+
try {
|
|
301
|
+
parsed = parseUpstreamApplyPatch(patch);
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
return patch;
|
|
305
|
+
}
|
|
306
|
+
const targets = parsed.operations.flatMap((operation) => {
|
|
307
|
+
const moveTo = 'moveTo' in operation ? operation.moveTo : undefined;
|
|
308
|
+
const semantics = operation.type === 'delete_file' || moveTo ? 'unlink-source' : 'referent';
|
|
309
|
+
return [{ path: operation.path, semantics }, ...(moveTo ? [{ path: moveTo, semantics: 'referent' }] : [])];
|
|
310
|
+
});
|
|
311
|
+
let targetIndex = 0;
|
|
312
|
+
const lines = patch.replace(/\r\n?/g, '\n').split('\n');
|
|
313
|
+
const prefixes = ['*** Add File: ', '*** Update File: ', '*** Delete File: ', '*** Move to: '];
|
|
314
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
315
|
+
const prefix = prefixes.find((candidate) => lines[index].startsWith(candidate));
|
|
316
|
+
if (!prefix)
|
|
317
|
+
continue;
|
|
318
|
+
const target = targets[targetIndex++];
|
|
319
|
+
const bound = await bindPath(target.path, target.semantics);
|
|
320
|
+
lines[index] = prefix + String(bound);
|
|
321
|
+
}
|
|
322
|
+
return lines.join('\n');
|
|
323
|
+
}
|
|
324
|
+
export function withAbortSignal(context, signal, extra = {}) {
|
|
325
|
+
return context && typeof context === 'object'
|
|
326
|
+
? { ...context, signal, ...extra }
|
|
327
|
+
: { signal, ...extra };
|
|
328
|
+
}
|
|
329
|
+
export function mergeAbortSignals(callerSignal, hostSignal) {
|
|
330
|
+
if (!callerSignal || callerSignal === hostSignal)
|
|
331
|
+
return callerSignal ?? hostSignal;
|
|
332
|
+
const controller = new AbortController();
|
|
333
|
+
const abort = () => {
|
|
334
|
+
callerSignal.removeEventListener('abort', abort);
|
|
335
|
+
hostSignal.removeEventListener('abort', abort);
|
|
336
|
+
controller.abort();
|
|
337
|
+
};
|
|
338
|
+
if (callerSignal.aborted || hostSignal.aborted) {
|
|
339
|
+
controller.abort();
|
|
340
|
+
return controller.signal;
|
|
341
|
+
}
|
|
342
|
+
callerSignal.addEventListener('abort', abort, { once: true });
|
|
343
|
+
hostSignal.addEventListener('abort', abort, { once: true });
|
|
344
|
+
return controller.signal;
|
|
345
|
+
}
|
|
346
|
+
export async function isParallelSafe(tool, params, context) {
|
|
347
|
+
const declared = tool.parallelSafe;
|
|
348
|
+
if (declared === undefined || declared === false)
|
|
349
|
+
return false;
|
|
350
|
+
if (declared === true)
|
|
351
|
+
return true;
|
|
352
|
+
try {
|
|
353
|
+
return (await declared(params, context)) === true;
|
|
354
|
+
}
|
|
355
|
+
catch {
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
import { createRunCodeExecution, } from './run-code-execution.js';
|
|
360
|
+
import { emitRunCodeCompletionTelemetry } from './run-code-telemetry.js';
|
|
361
|
+
const createBridgeRunId = (() => {
|
|
362
|
+
let next = 0;
|
|
363
|
+
return () => `run_code_bridge_${++next}`;
|
|
364
|
+
})();
|
|
365
|
+
/**
|
|
366
|
+
* Product-specific runtime for one final wrapped registry snapshot.
|
|
367
|
+
*
|
|
368
|
+
* The host remains deliberately product-neutral. This module owns the other
|
|
369
|
+
* half of the seam: discovery of scriptable members, nested admission and
|
|
370
|
+
* approval, call/action ledgers, attachment references, normalization, and
|
|
371
|
+
* completion telemetry. Consequently a caller cannot accidentally execute
|
|
372
|
+
* only half of the lifecycle (for example, admit calls without finalizing
|
|
373
|
+
* receipts) by assembling the pieces itself.
|
|
374
|
+
*/
|
|
375
|
+
export function createRunCodeRuntime(options) {
|
|
376
|
+
// Snapshot and filter once. Discovery and dispatch therefore cannot drift
|
|
377
|
+
// if a caller mutates its registry while an invocation is in flight.
|
|
378
|
+
const registry = options.registry.filter((tool) => !RUN_CODE_PROHIBITED_TOOLS.has(tool.name));
|
|
379
|
+
const discovery = () => registry;
|
|
380
|
+
const execute = async (input) => {
|
|
381
|
+
const { loggingService } = options;
|
|
382
|
+
const approvalRegistry = options.approvalPolicyRegistry;
|
|
383
|
+
// The owner is session-scoped while the registry is rebuilt with an agent.
|
|
384
|
+
// Reassert the complete wrapped graph at the execution seam so an owner
|
|
385
|
+
// attached after construction observes the same graph as this invocation.
|
|
386
|
+
if (options.nestedApprovalOwner && options.graphIdentity) {
|
|
387
|
+
options.nestedApprovalOwner.bindGraph(options.graphIdentity);
|
|
388
|
+
}
|
|
389
|
+
const callerSignal = input.context?.signal ?? input.signal;
|
|
390
|
+
const bridgeRunId = createBridgeRunId();
|
|
391
|
+
const startedAt = Date.now();
|
|
392
|
+
const calls = [];
|
|
393
|
+
const receipts = [];
|
|
394
|
+
const pendingReceiptByCallId = new Map();
|
|
395
|
+
const abortedCallIds = new Set();
|
|
396
|
+
let rejectedSeq = 0;
|
|
397
|
+
const output = [];
|
|
398
|
+
const consoleValues = [];
|
|
399
|
+
const sessionId = getConversationSessionId(input.context);
|
|
400
|
+
const mediaReferences = createMediaReferenceStore();
|
|
401
|
+
const record = (tool, outcome, started, directlyCallable, callId, diagnostic) => {
|
|
402
|
+
calls.push({
|
|
403
|
+
tool,
|
|
404
|
+
outcome,
|
|
405
|
+
durationMs: Date.now() - started,
|
|
406
|
+
directlyCallable,
|
|
407
|
+
...(callId ? { callId } : {}),
|
|
408
|
+
...(diagnostic ? { diagnostic } : {}),
|
|
409
|
+
});
|
|
410
|
+
if (outcome !== 'describe') {
|
|
411
|
+
writeNestedCallRecord(tool, sessionId, outcome === 'ok' ? 'success' : outcome === 'approval_required' ? 'denied-by-approval' : 'failure');
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
const failed = (message) => ({
|
|
415
|
+
kind: 'result',
|
|
416
|
+
result: { ok: false, error: message },
|
|
417
|
+
});
|
|
418
|
+
const recordReceipt = (callId, tool, outcome, reason) => {
|
|
419
|
+
if (abortedCallIds.has(callId))
|
|
420
|
+
return;
|
|
421
|
+
const pendingIndex = pendingReceiptByCallId.get(callId);
|
|
422
|
+
const value = { callId, tool, outcome, ...(reason ? { reason: clipReason(reason) } : {}) };
|
|
423
|
+
if (pendingIndex !== undefined) {
|
|
424
|
+
receipts[pendingIndex] = value;
|
|
425
|
+
pendingReceiptByCallId.delete(callId);
|
|
426
|
+
}
|
|
427
|
+
else
|
|
428
|
+
receipts.push(value);
|
|
429
|
+
};
|
|
430
|
+
const tools = {
|
|
431
|
+
binding: {
|
|
432
|
+
name: 'tools',
|
|
433
|
+
kind: 'namespace',
|
|
434
|
+
members: [...new Set([...registry.map((tool) => tool.name), TOOL_NAME_DESCRIBE])],
|
|
435
|
+
},
|
|
436
|
+
limits: {
|
|
437
|
+
maxCalls: RUN_CODE_LIMITS.maxCalls,
|
|
438
|
+
maxConcurrency: RUN_CODE_LIMITS.maxConcurrency,
|
|
439
|
+
limitExceededMessage: `Tool call limit reached (${RUN_CODE_LIMITS.maxCalls} calls per script run).`,
|
|
440
|
+
},
|
|
441
|
+
overBudget: ({ usedCalls, maxCalls }, rejected) => {
|
|
442
|
+
record(rejected.tool.name, 'unknown', rejected.started, undefined, undefined, 'call_budget');
|
|
443
|
+
if (isActionTool(rejected.tool.name)) {
|
|
444
|
+
rejectedSeq += 1;
|
|
445
|
+
recordReceipt(`${bridgeRunId}:rejected-${rejectedSeq}`, rejected.tool.name, 'unknown', 'call budget exhausted before dispatch');
|
|
446
|
+
}
|
|
447
|
+
return failed(`Tool call limit reached (${maxCalls} calls per script run; ${usedCalls} calls admitted, ${Math.max(0, maxCalls - usedCalls)} remaining). Return the partial results you collected and start another run_code call only for unattempted work; Do not repeat completed tool effects.`);
|
|
448
|
+
},
|
|
449
|
+
onAdmitted: (prepared, context) => {
|
|
450
|
+
if (!isActionTool(prepared.tool.name))
|
|
451
|
+
return;
|
|
452
|
+
const callId = `${bridgeRunId}:${context.callId}`;
|
|
453
|
+
pendingReceiptByCallId.set(callId, receipts.length);
|
|
454
|
+
receipts.push({ callId, tool: prepared.tool.name, outcome: 'unknown' });
|
|
455
|
+
},
|
|
456
|
+
onAborted: (prepared, context, reason) => {
|
|
457
|
+
const callId = `${bridgeRunId}:${context.callId}`;
|
|
458
|
+
abortedCallIds.add(callId);
|
|
459
|
+
record(prepared.tool.name, 'unknown', prepared.started, undefined, callId);
|
|
460
|
+
if (isActionTool(prepared.tool.name))
|
|
461
|
+
recordReceipt(callId, prepared.tool.name, 'unknown', reason);
|
|
462
|
+
},
|
|
463
|
+
prepare: async (payload) => {
|
|
464
|
+
const started = Date.now();
|
|
465
|
+
const name = typeof payload.member === 'string' ? payload.member : '';
|
|
466
|
+
const tool = registry.find((candidate) => candidate.name === name);
|
|
467
|
+
if (name === TOOL_NAME_DESCRIBE && typeof payload.params === 'string') {
|
|
468
|
+
const described = registry.find((candidate) => candidate.name === payload.params);
|
|
469
|
+
if (!described)
|
|
470
|
+
return failed(`Unknown tool "${payload.params}". Available: ${registry.map((entry) => entry.name).join(', ')}`);
|
|
471
|
+
record(name, 'describe', started);
|
|
472
|
+
return { kind: 'result', result: { ok: true, result: describeTool(described) } };
|
|
473
|
+
}
|
|
474
|
+
if (!tool) {
|
|
475
|
+
record(name || '(unnamed)', 'unknown_tool', started, undefined, undefined, 'unknown_tool');
|
|
476
|
+
if (isActionTool(name)) {
|
|
477
|
+
rejectedSeq += 1;
|
|
478
|
+
recordReceipt(`${bridgeRunId}:rejected-${rejectedSeq}`, name, 'failed', `Unknown tool "${name}"`);
|
|
479
|
+
}
|
|
480
|
+
return failed(`Unknown tool "${name}". Available: ${registry.map((entry) => entry.name).join(', ')}`);
|
|
481
|
+
}
|
|
482
|
+
const targetSchema = tool.canonicalParameters ?? tool.parameters;
|
|
483
|
+
let normalized = payload.params ?? {};
|
|
484
|
+
try {
|
|
485
|
+
normalized = normalizeToolParameters(normalized, targetSchema);
|
|
486
|
+
}
|
|
487
|
+
catch {
|
|
488
|
+
normalized = payload.params ?? {};
|
|
489
|
+
}
|
|
490
|
+
if (isZodToolParameterSchema(targetSchema)) {
|
|
491
|
+
const parsed = targetSchema.safeParse(normalized);
|
|
492
|
+
if (!parsed.success) {
|
|
493
|
+
record(name, 'invalid_params', started, undefined, undefined, 'invalid_nested_input');
|
|
494
|
+
const issues = parsed.error?.issues.map((issue) => `${issue.path.join('.') || '(root)'}: ${issue.message}`).join('; ') ??
|
|
495
|
+
'invalid parameters';
|
|
496
|
+
if (isActionTool(name)) {
|
|
497
|
+
rejectedSeq += 1;
|
|
498
|
+
recordReceipt(`${bridgeRunId}:rejected-${rejectedSeq}`, name, 'failed', `Invalid parameters: ${issues}`);
|
|
499
|
+
}
|
|
500
|
+
return failed(`Invalid parameters for "${name}": ${issues}\nSignature: ${renderCompactSignature(tool)}`);
|
|
501
|
+
}
|
|
502
|
+
normalized = parsed.data;
|
|
503
|
+
}
|
|
504
|
+
const authorityRoot = options.getCwd();
|
|
505
|
+
const authority = await bindPreparedAuthority(name, normalized, authorityRoot, options.executionContext);
|
|
506
|
+
if (authority.kind === 'denied') {
|
|
507
|
+
record(name, 'approval_required', started, isDirectlyCallable(tool));
|
|
508
|
+
if (isActionTool(name)) {
|
|
509
|
+
rejectedSeq += 1;
|
|
510
|
+
recordReceipt(`${bridgeRunId}:rejected-${rejectedSeq}`, name, 'not_applied', authority.message);
|
|
511
|
+
}
|
|
512
|
+
return failed(authority.message);
|
|
513
|
+
}
|
|
514
|
+
return {
|
|
515
|
+
tool,
|
|
516
|
+
params: authority.params,
|
|
517
|
+
originalParams: normalized,
|
|
518
|
+
authorityRoot,
|
|
519
|
+
authorityMeaning: JSON.stringify(authority),
|
|
520
|
+
parallelSafe: await isParallelSafe(tool, normalized, input.context),
|
|
521
|
+
started,
|
|
522
|
+
};
|
|
523
|
+
},
|
|
524
|
+
lane: (prepared) => (prepared.parallelSafe ? 'default' : 'serial'),
|
|
525
|
+
invoke: async (prepared, callContext) => {
|
|
526
|
+
const callId = `${bridgeRunId}:${callContext.callId}`;
|
|
527
|
+
const decision = await approvalRegistry.evaluate({
|
|
528
|
+
toolName: prepared.tool.name,
|
|
529
|
+
args: prepared.params,
|
|
530
|
+
context: input.context,
|
|
531
|
+
});
|
|
532
|
+
if (decision.kind !== 'auto_approve') {
|
|
533
|
+
if (decision.kind === 'prompt' && options.nestedApprovalOwner) {
|
|
534
|
+
const nestedContext = withAbortSignal(input.context, mergeAbortSignals(callerSignal, callContext.signal), {
|
|
535
|
+
scripted: true,
|
|
536
|
+
});
|
|
537
|
+
tools.onWaiting?.(callContext);
|
|
538
|
+
try {
|
|
539
|
+
const resolution = await options.nestedApprovalOwner.request({
|
|
540
|
+
requestId: callId,
|
|
541
|
+
sessionId: sessionId ?? 'unknown',
|
|
542
|
+
graphIdentity: options.graphIdentity ?? options.registry,
|
|
543
|
+
outerRunId: bridgeRunId,
|
|
544
|
+
nestedCallId: callId,
|
|
545
|
+
toolName: prepared.tool.name,
|
|
546
|
+
preparedArguments: prepared.params,
|
|
547
|
+
authorityContext: input.context,
|
|
548
|
+
approval: {
|
|
549
|
+
agentName: 'Nested run_code',
|
|
550
|
+
toolName: prepared.tool.name,
|
|
551
|
+
argumentsText: JSON.stringify(prepared.params),
|
|
552
|
+
rawInterruption: null,
|
|
553
|
+
callId,
|
|
554
|
+
outsideWorkspaceEdit: resolveOutsideWorkspaceEdit(prepared.tool.name, prepared.params, prepared.authorityRoot),
|
|
555
|
+
},
|
|
556
|
+
signal: nestedContext.signal,
|
|
557
|
+
revalidateAuthority: async () => {
|
|
558
|
+
const currentRoot = options.getCwd();
|
|
559
|
+
const authority = await bindPreparedAuthority(prepared.tool.name, prepared.originalParams, currentRoot, options.executionContext);
|
|
560
|
+
return (authority.kind === 'bound' &&
|
|
561
|
+
currentRoot === prepared.authorityRoot &&
|
|
562
|
+
JSON.stringify(authority) === prepared.authorityMeaning);
|
|
563
|
+
},
|
|
564
|
+
revalidate: async () => (await approvalRegistry.evaluate({
|
|
565
|
+
toolName: prepared.tool.name,
|
|
566
|
+
args: prepared.params,
|
|
567
|
+
context: input.context,
|
|
568
|
+
})).kind,
|
|
569
|
+
grant: (nestedDecision) => {
|
|
570
|
+
if (callContext.signal.aborted)
|
|
571
|
+
throw new Error('Tool execution was not approved.');
|
|
572
|
+
const applied = applyApprovalGrant({
|
|
573
|
+
sessionId: sessionId ?? 'unknown',
|
|
574
|
+
sessionAccess: options.sessionAccess,
|
|
575
|
+
nestedCompatibility: options.nestedCompatibility,
|
|
576
|
+
logger: loggingService,
|
|
577
|
+
}, {
|
|
578
|
+
answer: nestedDecision.answer,
|
|
579
|
+
toolName: prepared.tool.name,
|
|
580
|
+
rawArguments: prepared.params,
|
|
581
|
+
callId,
|
|
582
|
+
});
|
|
583
|
+
if (!applied.isApproved)
|
|
584
|
+
throw new Error('Tool execution was not approved.');
|
|
585
|
+
},
|
|
586
|
+
dispatch: async () => prepared.tool.execute(prepared.params, nestedContext, { toolCall: { callId } }),
|
|
587
|
+
});
|
|
588
|
+
if (resolution.kind === 'approved')
|
|
589
|
+
return settleResolved(prepared, resolution.result, callId);
|
|
590
|
+
const message = 'message' in resolution ? resolution.message : String(resolution.error);
|
|
591
|
+
record(prepared.tool.name, 'approval_required', prepared.started, isDirectlyCallable(prepared.tool), callId);
|
|
592
|
+
if (isActionTool(prepared.tool.name))
|
|
593
|
+
recordReceipt(callId, prepared.tool.name, 'not_applied', message);
|
|
594
|
+
return failed(message);
|
|
595
|
+
}
|
|
596
|
+
finally {
|
|
597
|
+
tools.onResumed?.(callContext);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
const outcome = decision.kind === 'unknown'
|
|
601
|
+
? 'unknown_policy'
|
|
602
|
+
: decision.kind === 'error'
|
|
603
|
+
? 'policy_error'
|
|
604
|
+
: decision.kind === 'interceptor_denied'
|
|
605
|
+
? 'interceptor_denied'
|
|
606
|
+
: 'approval_required';
|
|
607
|
+
record(prepared.tool.name, outcome, prepared.started, isDirectlyCallable(prepared.tool), callId);
|
|
608
|
+
const message = decision.kind === 'unknown'
|
|
609
|
+
? `"${prepared.tool.name}" has no registered approval policy and is unavailable from inside a script.`
|
|
610
|
+
: decision.kind === 'interceptor_denied'
|
|
611
|
+
? `"${prepared.tool.name}" was refused by an approval interceptor and is unavailable from inside a script.`
|
|
612
|
+
: decision.kind === 'error'
|
|
613
|
+
? `"${prepared.tool.name}" approval policy failed and is unavailable from inside a script.`
|
|
614
|
+
: `"${prepared.tool.name}" requires approval and is unavailable from inside a script.`;
|
|
615
|
+
if (isActionTool(prepared.tool.name))
|
|
616
|
+
recordReceipt(callId, prepared.tool.name, 'not_applied', message);
|
|
617
|
+
return failed(message);
|
|
618
|
+
}
|
|
619
|
+
try {
|
|
620
|
+
return settleResolved(prepared, await prepared.tool.execute(prepared.params, withAbortSignal(input.context, mergeAbortSignals(callerSignal, callContext.signal), { scripted: true }), { toolCall: { callId } }), callId);
|
|
621
|
+
}
|
|
622
|
+
catch (error) {
|
|
623
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
624
|
+
record(prepared.tool.name, 'error', prepared.started, undefined, callId, 'nested_tool_failure');
|
|
625
|
+
if (isActionTool(prepared.tool.name))
|
|
626
|
+
recordReceipt(callId, prepared.tool.name, 'failed', message);
|
|
627
|
+
return failed(message);
|
|
628
|
+
}
|
|
629
|
+
},
|
|
630
|
+
};
|
|
631
|
+
const settleResolved = async (prepared, raw, callId) => {
|
|
632
|
+
try {
|
|
633
|
+
if (isActionTool(prepared.tool.name)) {
|
|
634
|
+
const semantic = ACTION_SEMANTICS[prepared.tool.name](raw);
|
|
635
|
+
recordReceipt(callId, prepared.tool.name, semantic.outcome, semantic.reason);
|
|
636
|
+
}
|
|
637
|
+
const serialized = await serializeResult(mediaReferences.capture(raw), RUN_CODE_LIMITS.maxResultChars, prepared.tool.name, calls.filter((call) => call.outcome !== 'describe').length + 1);
|
|
638
|
+
if (!serialized.ok) {
|
|
639
|
+
record(prepared.tool.name, 'error', prepared.started, undefined, callId, 'invalid_nested_output');
|
|
640
|
+
return { kind: 'result', result: serialized };
|
|
641
|
+
}
|
|
642
|
+
const contract = validateScriptedReturn(prepared.tool, serialized.result);
|
|
643
|
+
if (!contract.ok) {
|
|
644
|
+
record(prepared.tool.name, 'error', prepared.started, undefined, callId, 'invalid_tool_output');
|
|
645
|
+
return {
|
|
646
|
+
kind: 'fail',
|
|
647
|
+
code: 'invalid_output',
|
|
648
|
+
detail: 'invalid_tool_output',
|
|
649
|
+
message: `Tool "${prepared.tool.name}" returned a value that violates its scripted output contract: ${contract.message}`,
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
record(prepared.tool.name, 'ok', prepared.started, undefined, callId);
|
|
653
|
+
return { kind: 'result', result: { ok: true, result: contract.value } };
|
|
654
|
+
}
|
|
655
|
+
catch (error) {
|
|
656
|
+
record(prepared.tool.name, 'error', prepared.started, undefined, callId, 'nested_tool_failure');
|
|
657
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
658
|
+
if (isActionTool(prepared.tool.name))
|
|
659
|
+
recordReceipt(callId, prepared.tool.name, 'failed', message);
|
|
660
|
+
return failed(message);
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
loggingService.debug('run_code execution started', {
|
|
664
|
+
cwd: options.getCwd(),
|
|
665
|
+
timeout: input.timeout,
|
|
666
|
+
exposedTools: registry.length,
|
|
667
|
+
description: input.description,
|
|
668
|
+
});
|
|
669
|
+
const result = await new SandboxedCodeHostImpl().run({
|
|
670
|
+
code: input.code,
|
|
671
|
+
inputData: input.inputs,
|
|
672
|
+
capabilities: { tools },
|
|
673
|
+
limits: {
|
|
674
|
+
timeoutMs: input.timeout,
|
|
675
|
+
maxCodeBytes: RUN_CODE_LIMITS.maxCodeBytes,
|
|
676
|
+
maxOutputBytes: RUN_CODE_LIMITS.maxOutputBytes,
|
|
677
|
+
maxConsoleBytes: RUN_CODE_LIMITS.maxConsoleBytes,
|
|
678
|
+
},
|
|
679
|
+
subject: 'Script',
|
|
680
|
+
allowVoidOutput: true,
|
|
681
|
+
signal: callerSignal,
|
|
682
|
+
onConsole: (values) => {
|
|
683
|
+
consoleValues.push(values);
|
|
684
|
+
output.push(values.map((value) => (typeof value === 'string' ? value : JSON.stringify(value))).join(' '));
|
|
685
|
+
},
|
|
686
|
+
});
|
|
687
|
+
for (const [callId, index] of pendingReceiptByCallId) {
|
|
688
|
+
receipts[index] = {
|
|
689
|
+
...receipts[index],
|
|
690
|
+
outcome: 'unknown',
|
|
691
|
+
reason: 'did not settle before the script run ended',
|
|
692
|
+
};
|
|
693
|
+
pendingReceiptByCallId.delete(callId);
|
|
694
|
+
}
|
|
695
|
+
const resolvedResult = result.ok && !result.voidOutput
|
|
696
|
+
? { ...result, output: mediaReferences.resolve(result.output) }
|
|
697
|
+
: result;
|
|
698
|
+
const attachments = [];
|
|
699
|
+
const execution = createRunCodeExecution(resolvedResult, calls, receipts, consoleValues, attachments);
|
|
700
|
+
emitRunCodeCompletionTelemetry(loggingService, {
|
|
701
|
+
code: input.code,
|
|
702
|
+
execution,
|
|
703
|
+
durationMs: Date.now() - startedAt,
|
|
704
|
+
timeoutMs: input.timeout,
|
|
705
|
+
sessionId,
|
|
706
|
+
runId: bridgeRunId,
|
|
707
|
+
calls,
|
|
708
|
+
receipts,
|
|
709
|
+
});
|
|
710
|
+
loggingService.debug('run_code execution finished', {
|
|
711
|
+
ok: result.ok,
|
|
712
|
+
toolCalls: calls.filter((call) => call.outcome !== 'describe').length,
|
|
713
|
+
schemaLookups: calls.filter((call) => call.outcome === 'describe').length,
|
|
714
|
+
});
|
|
715
|
+
return { execution, output };
|
|
716
|
+
};
|
|
717
|
+
return { discovery, execute };
|
|
718
|
+
}
|
|
719
|
+
//# sourceMappingURL=run-code-runtime.js.map
|