mixdog 1.2.1 → 1.2.3
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 +18 -0
- package/package.json +2 -1
- package/scripts/gate-local.mjs +19 -3
- package/scripts/model-catalog-audit.mjs +1 -15
- package/scripts/provider-pingpong-live.mjs +509 -0
- package/src/agents/advisor/AGENT.md +1 -1
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +3 -3
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +6 -0
- package/src/defaults/skills/setup/SKILL.md +6 -1
- package/src/defaults/skills/setup/references/actions.md +44 -22
- package/src/defaults/skills/setup/references/surfaces.md +10 -8
- package/src/headless-exec.mjs +15 -8
- package/src/lib/keychain-cjs.cjs +7 -4
- package/src/output-styles/common.md +11 -10
- package/src/repl/slash-commands.mjs +16 -1
- package/src/rules/agent/AGENT.md +5 -5
- package/src/rules/lead/LEAD.md +5 -5
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -4
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
- package/src/runtime/agent/orchestrator/config.mjs +5 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +36 -7
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +49 -10
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +40 -3
- package/src/runtime/agent/orchestrator/mcp/client.mjs +230 -96
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +103 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +150 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +111 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +87 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +95 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-request.mjs +122 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +9 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +229 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +188 -29
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +98 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +39 -18
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +55 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +48 -37
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +10 -7
- package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +18 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +13 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-midstream.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-recovery.mjs +23 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +46 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request.mjs +14 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +102 -45
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +69 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +40 -7
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +30 -9
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +88 -21
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +30 -10
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +106 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +10 -61
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +94 -15
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +117 -72
- package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +75 -10
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +97 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +103 -23
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +43 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +32 -6
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +27 -3
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +64 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +70 -6
- package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
- package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
- package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +80 -18
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +46 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +273 -0
- package/src/runtime/agent/orchestrator/providers/gemini-family.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/gemini-history-signatures.mjs +9 -4
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +180 -0
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +369 -112
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +140 -35
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +70 -24
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +80 -29
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +69 -19
- package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +246 -42
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
- package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +388 -0
- package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
- package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +48 -22
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +119 -18
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +33 -1
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +123 -61
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +27 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +37 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +50 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +47 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +151 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +64 -23
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +79 -33
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +172 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +144 -15
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +193 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +66 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +109 -26
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +27 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +34 -20
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +23 -4
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +37 -28
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +274 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +72 -32
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +43 -15
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +7 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +1 -3
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +37 -4
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +12 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +12 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +76 -33
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -16
- package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -35
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +25 -14
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
- package/src/runtime/agent/orchestrator/providers/openai-ws-terminal.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +41 -22
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +170 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +75 -70
- package/src/runtime/agent/orchestrator/providers/openrouter.mjs +75 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +720 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +123 -219
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +148 -45
- package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +81 -16
- package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
- package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +157 -0
- package/src/runtime/agent/orchestrator/providers/wire-route.mjs +512 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +183 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +100 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
- package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +0 -18
- package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +57 -28
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +19 -16
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -97
- package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +14 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +176 -71
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +62 -10
- package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +14 -93
- package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +120 -0
- package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
- package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +91 -1
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
- package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +21 -10
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +132 -0
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +30 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +67 -20
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +104 -19
- package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +150 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +30 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +57 -21
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +5 -10
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +208 -14
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +16 -4
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +25 -3
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +19 -2
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +168 -29
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/side-question.mjs +192 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +58 -2
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +41 -28
- package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +22 -10
- package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/store.mjs +19 -3
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +77 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +20 -1
- package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +14 -10
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +49 -34
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
- package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
- package/src/runtime/computer-bridge/action-schema.mjs +44 -21
- package/src/runtime/github/tool.mjs +92 -2
- package/src/runtime/memory/index.mjs +1 -0
- package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
- package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
- package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
- package/src/runtime/memory/lib/pg/process.mjs +65 -50
- package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +124 -16
- package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
- package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
- package/src/runtime/office/README.md +2 -2
- package/src/runtime/office/authoring/html-document-author.mjs +2 -0
- package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-measure.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +2 -0
- package/src/runtime/office/core/office-actions-read.mjs +3 -0
- package/src/runtime/office/core/office-render-preview.mjs +2 -0
- package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
- package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
- package/src/runtime/office/core/office-sessions.mjs +5 -0
- package/src/runtime/office/core/office-transactions.mjs +3 -0
- package/src/runtime/office/core/office-write-ledger.mjs +98 -0
- package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
- package/src/runtime/office/index.mjs +30 -0
- package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
- package/src/runtime/office/pdf/pdf-render.mjs +23 -7
- package/src/runtime/office/pdf/pdf-security.mjs +2 -0
- package/src/runtime/office/portable/portable-opc.mjs +4 -1
- package/src/runtime/office/quality/visual-diff.mjs +2 -0
- package/src/runtime/office/shared/values.mjs +0 -5
- package/src/runtime/shared/background-tasks.mjs +92 -14
- package/src/runtime/shared/bounded-file-read.mjs +13 -0
- package/src/runtime/shared/bounded-line-diff.mjs +182 -0
- package/src/runtime/shared/buffered-appender.mjs +18 -0
- package/src/runtime/shared/config.mjs +78 -18
- package/src/runtime/shared/err-text.mjs +31 -0
- package/src/runtime/shared/error-presentation.mjs +159 -19
- package/src/runtime/shared/file-permissions.d.mts +6 -1
- package/src/runtime/shared/file-permissions.mjs +54 -6
- package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +129 -134
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
- package/src/runtime/shared/llm/model-catalog.mjs +53 -40
- package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +11 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
- package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
- package/src/runtime/shared/loopback-listener.mjs +9 -0
- package/src/runtime/shared/model-display.mjs +13 -0
- package/src/runtime/shared/provider-api-key.mjs +2 -0
- package/src/runtime/shared/quota-resume-store.mjs +11 -0
- package/src/runtime/shared/review-diff.mjs +52 -0
- package/src/runtime/shared/session-baseline-store.mjs +960 -0
- package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
- package/src/runtime/shared/session-sidebar-host.mjs +38 -0
- package/src/runtime/shared/slow-span.mjs +114 -0
- package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
- package/src/runtime/shared/statusline/statusline-segments.mjs +28 -4
- package/src/runtime/shared/task-notification-envelope.mjs +2 -2
- package/src/runtime/shared/tool-card-model/card-header.mjs +6 -1
- package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
- package/src/runtime/shared/tool-card-model.mjs +5 -2
- package/src/runtime/shared/tool-output-limit.mjs +4 -0
- package/src/runtime/shared/tool-primitives.mjs +13 -0
- package/src/runtime/shared/tool-result-summary.mjs +8 -1
- package/src/runtime/shared/tool-surface.mjs +18 -3
- package/src/runtime/shared/tool-work-units.mjs +40 -4
- package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
- package/src/runtime/shared/transcript-writer.mjs +10 -2
- package/src/runtime/shared/turn-changes.mjs +670 -274
- package/src/runtime/shared/turn-review-reply.mjs +8 -39
- package/src/runtime/shared/turn-snapshot-store.mjs +94 -2
- package/src/runtime/shared/turn-snapshot.mjs +986 -690
- package/src/runtime/shared/turn-worktree-snapshot.mjs +279 -262
- package/src/runtime/shared/user-data-guard.mjs +262 -49
- package/src/runtime/shared/worktrees/carry.mjs +531 -0
- package/src/runtime/shared/worktrees/contract.mjs +34 -24
- package/src/runtime/shared/worktrees/file-recovery.mjs +68 -0
- package/src/runtime/shared/worktrees/git-head.mjs +205 -0
- package/src/runtime/shared/worktrees/git.mjs +8 -3
- package/src/runtime/shared/worktrees/maintenance.mjs +1 -1
- package/src/runtime/shared/worktrees/manager.mjs +156 -8
- package/src/runtime/shared/worktrees/merge.mjs +31 -21
- package/src/runtime/shared/worktrees/paths.d.mts +6 -0
- package/src/runtime/shared/worktrees/test-support.mjs +19 -4
- package/src/runtime/terminal-bridge/client.mjs +44 -11
- package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
- package/src/runtime/tidy/apply.mjs +47 -2
- package/src/runtime/tidy/run-engines.mjs +11 -5
- package/src/session-runtime/agent-tool-routing.mjs +19 -13
- package/src/session-runtime/boot/apis.mjs +19 -5
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +12 -1
- package/src/session-runtime/boot/session.mjs +0 -1
- package/src/session-runtime/boot/tools.mjs +4 -1
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +65 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +11 -4
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +115 -18
- package/src/session-runtime/internal-tool-executor.mjs +6 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +188 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
- package/src/session-runtime/lifecycle/session-catalog.mjs +14 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +29 -6
- package/src/session-runtime/lifecycle/teardown.mjs +73 -8
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/connect.mjs +46 -14
- package/src/session-runtime/mcp-glue/server-catalog.mjs +20 -3
- package/src/session-runtime/mcp-glue.mjs +3 -0
- package/src/session-runtime/mcp-oauth-login.mjs +174 -0
- package/src/session-runtime/model-route/model-switch-target.mjs +34 -0
- package/src/session-runtime/model-route/set-route.mjs +85 -17
- package/src/session-runtime/model-route/web-search-route.mjs +1 -1
- package/src/session-runtime/native-web-search/routes.mjs +22 -3
- package/src/session-runtime/native-web-search-usage.mjs +51 -0
- package/src/session-runtime/native-web-search.mjs +10 -1
- package/src/session-runtime/new-session-config.mjs +4 -2
- package/src/session-runtime/provider-auth/login.mjs +4 -0
- package/src/session-runtime/provider-models/model-meta.mjs +12 -3
- package/src/session-runtime/quick-model-rows/web-search-rows.mjs +13 -8
- package/src/session-runtime/quick-web-search-models.mjs +13 -38
- package/src/session-runtime/resource-extension-sync.mjs +4 -0
- package/src/session-runtime/resource-mcp-api.mjs +98 -2
- package/src/session-runtime/resource-scope-decorate.mjs +10 -3
- package/src/session-runtime/runtime-review-api.mjs +21 -2
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +13 -1
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +7 -2
- package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +73 -7
- package/src/session-runtime/services/agent-tool/send-flow.mjs +22 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +2 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +22 -5
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +15 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -2
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
- package/src/session-runtime/services/agent-tool/worker-index.mjs +46 -7
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +17 -0
- package/src/session-runtime/services/agent-tool.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +19 -3
- package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
- package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
- package/src/session-runtime/services/provider-admin.mjs +81 -15
- package/src/session-runtime/session-transcript-purge.mjs +32 -0
- package/src/session-runtime/session-turn-api.mjs +14 -5
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -0
- package/src/session-runtime/settings-compaction-api.mjs +1 -0
- package/src/session-runtime/setup-tool/executor.mjs +36 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
- package/src/session-runtime/setup-tool/settings-contract.mjs +13 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +13 -4
- package/src/session-runtime/skills-api.mjs +3 -5
- package/src/session-runtime/tool-surface.mjs +5 -1
- package/src/session-runtime/turn/compaction-gate.mjs +25 -0
- package/src/session-runtime/turn/session-ops.mjs +7 -5
- package/src/session-runtime/turn/side-question-ops.mjs +22 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +5 -1
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +8 -3
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +10 -0
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +25 -9
- package/src/session-runtime/usage-stats-api.mjs +43 -11
- package/src/session-runtime/workspace/project-branches.mjs +7 -5
- package/src/session-runtime/workspace/transition-steps.mjs +129 -31
- package/src/session-runtime/workspace/transitions.mjs +190 -15
- package/src/standalone/daemon-agent-control.mjs +9 -1
- package/src/standalone/daemon-drain-policy.mjs +8 -0
- package/src/standalone/daemon-local-session-bridge.mjs +14 -1
- package/src/standalone/daemon-owner.mjs +17 -4
- package/src/standalone/daemon-pg-stop.mjs +51 -0
- package/src/standalone/daemon-stop-budget.d.mts +2 -0
- package/src/standalone/daemon-stop-budget.mjs +18 -0
- package/src/standalone/daemon-stored-session-views.mjs +2 -0
- package/src/standalone/daemon-telemetry.mjs +74 -0
- package/src/standalone/daemon.mjs +64 -8
- package/src/standalone/desktop-service-registry.mjs +5 -0
- package/src/standalone/local-session-runtime.mjs +70 -19
- package/src/standalone/session-client.mjs +42 -0
- package/src/standalone/session-protocol.mjs +14 -0
- package/src/standalone/session-proxy/projection.mjs +41 -4
- package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
- package/src/standalone/session-runtime-inline-host.mjs +1 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +33 -2
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +26 -10
- package/src/standalone/session-service/agent-tree.mjs +12 -0
- package/src/standalone/session-service/quota-resume.mjs +8 -0
- package/src/standalone/session-service/retention/busy.mjs +15 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
- package/src/standalone/session-service-api.mjs +11 -1
- package/src/standalone/session-service.mjs +1 -0
- package/src/standalone/session-state-patch.d.mts +2 -1
- package/src/standalone/session-state-patch.mjs +41 -1
- package/src/tui/App.jsx +25 -0
- package/src/tui/app/app-view/floating-panel.jsx +26 -1
- package/src/tui/app/app-view.jsx +1 -0
- package/src/tui/app/btw-controller.mjs +118 -0
- package/src/tui/app/create-app-pickers.mjs +6 -0
- package/src/tui/app/extension-pickers/mcp-login.mjs +107 -0
- package/src/tui/app/extension-pickers/mcp-servers-picker.mjs +2 -1
- package/src/tui/app/extension-pickers.mjs +2 -1
- package/src/tui/app/model-options.mjs +11 -16
- package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
- package/src/tui/app/shell-layout/surfaces.mjs +3 -1
- package/src/tui/app/slash-commands.mjs +20 -5
- package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
- package/src/tui/app/slash-dispatch/session-commands.mjs +19 -6
- package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
- package/src/tui/app/use-global-key-input.mjs +5 -12
- package/src/tui/app/use-prompt-handlers.mjs +11 -0
- package/src/tui/components/BtwPanel.jsx +53 -0
- package/src/tui/components/QuestionPanel.jsx +275 -0
- package/src/tui/components/StatusLine.jsx +2 -0
- package/src/tui/components/question-panel-model.mjs +156 -0
- package/src/tui/components/status-line/local-line.mjs +5 -2
- package/src/tui/components/status-line/use-statusline-text.mjs +7 -1
- package/src/tui/dist/index.mjs +3221 -1500
- package/src/tui/session/context-state.mjs +4 -2
- package/src/tui/session/quota-resume.mjs +46 -14
- package/src/tui/session/session-api/commands.mjs +43 -24
- package/src/tui/session/session-api/controls.mjs +2 -2
- package/src/tui/session/session-api/extensions.mjs +22 -0
- package/src/tui/session/session-api/integrations.mjs +16 -2
- package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle.mjs +7 -2
- package/src/tui/session/session-api/routes.mjs +71 -7
- package/src/tui/session/session-api/settings.mjs +11 -14
- package/src/tui/session/session-api.mjs +1 -0
- package/src/tui/session/session-flow/drain.mjs +7 -1
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
- package/src/tui/session/tool-approval.mjs +10 -7
- package/src/tui/session/transcript-spill.mjs +14 -7
- package/src/tui/session/turn-stream.mjs +174 -31
- package/src/tui/session/turn.mjs +46 -16
- package/src/tui/statusline-ansi-bridge.mjs +1 -1
- package/src/ui/statusline-agents.mjs +15 -4
- package/src/ui/statusline.mjs +7 -3
- package/src/ui/streaming-markdown-heal.mjs +34 -3
- package/src/vendor/statusline/src/gateway/claude-current.mjs +14 -4
- package/src/workflows/default/WORKFLOW.md +3 -1
- package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
- package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
|
@@ -8,14 +8,15 @@
|
|
|
8
8
|
* later request rebuilds the same history and the prompt cache keeps hitting.
|
|
9
9
|
* A judge that is missing, slow or failing leaves the step at the effort in
|
|
10
10
|
* force (the turn's or the previous step's).
|
|
11
|
-
* A custom route
|
|
12
|
-
*
|
|
13
|
-
* turn's following requests
|
|
11
|
+
* A custom route snaps the judged effort onto the model's levels. Without a
|
|
12
|
+
* mid-conversation update (snapshot mode 'custom') it becomes the effort of
|
|
13
|
+
* the turn's following requests; a custom GPT-6+ Responses route (mode
|
|
14
|
+
* 'responses') also marks it as the update.
|
|
14
15
|
*/
|
|
15
16
|
import { resolveAutoEffort } from '../../providers/auto-effort.mjs';
|
|
16
|
-
import { resolveCustomReasoning } from '../../providers/custom-reasoning.mjs';
|
|
17
|
+
import { isCustomProviderName, resolveCustomReasoning } from '../../providers/custom-reasoning.mjs';
|
|
17
18
|
import { autoEffortModel, stepEffortConfiguration } from '../../providers/effort-configuration.mjs';
|
|
18
|
-
import { effortOptionsFor } from '../../runtime-core/effort.mjs';
|
|
19
|
+
import { effortOptionsFor, warnEmptyAutoEffortLadder } from '../../runtime-core/effort.mjs';
|
|
19
20
|
import { judgeTurn, recordEffortDecision } from '../../../../effort-judge/judge-client.mjs';
|
|
20
21
|
import { stepResultWindow } from '../../../../effort-judge/judge-input.mjs';
|
|
21
22
|
|
|
@@ -35,12 +36,58 @@ const argText = (args) =>
|
|
|
35
36
|
.slice(0, 600)
|
|
36
37
|
.join('');
|
|
37
38
|
|
|
39
|
+
// A judgment runs beside the next iteration instead of in front of it. Its
|
|
40
|
+
// record lives on the loop state (`state.stepEffort`), so it can only ever
|
|
41
|
+
// reach the turn that started it; its promise settles the record and touches
|
|
42
|
+
// nothing else, so an aborted loop is never mutated afterwards. The result
|
|
43
|
+
// lands on the batch's last tool result in one of two places:
|
|
44
|
+
// - resolved before the next request is projected: on that tool result, so
|
|
45
|
+
// the request carries it (applyStepEffort);
|
|
46
|
+
// - resolved later: the request already went out with the earlier effort and
|
|
47
|
+
// its history is never rewritten (that would break the prompt cache), so
|
|
48
|
+
// the result marks the last tool result of the next batch, and the
|
|
49
|
+
// following request carries it (markStepEffort).
|
|
50
|
+
function applyResult(state, target, result) {
|
|
51
|
+
if (result.level) state.opts.effort = result.level;
|
|
52
|
+
if (result.marked) target.meta = { ...target.meta, effortConfiguration: result.marked };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// How long a request waits for its step judgment (measured judge p90 ≈ 284 ms).
|
|
56
|
+
export const STEP_EFFORT_GRACE_MS = 300;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Before a provider request is projected: wait up to the grace for the pending
|
|
60
|
+
* judgment and apply it if it resolved. A slower one leaves this request at
|
|
61
|
+
* the effort in force and lands on the following request.
|
|
62
|
+
*/
|
|
63
|
+
export async function applyStepEffort(state) {
|
|
64
|
+
const pending = state.stepEffort;
|
|
65
|
+
if (!pending || pending.sent) return;
|
|
66
|
+
if (!pending.settled && !state.signal?.aborted) {
|
|
67
|
+
let timer;
|
|
68
|
+
await Promise.race([
|
|
69
|
+
pending.promise,
|
|
70
|
+
new Promise((resolve) => {
|
|
71
|
+
timer = setTimeout(resolve, STEP_EFFORT_GRACE_MS);
|
|
72
|
+
}),
|
|
73
|
+
]);
|
|
74
|
+
clearTimeout(timer);
|
|
75
|
+
// Another caller may have handled it while this one waited.
|
|
76
|
+
if (pending.sent) return;
|
|
77
|
+
}
|
|
78
|
+
pending.sent = true;
|
|
79
|
+
if (!pending.result || state.signal?.aborted || !state.messages.includes(pending.target)) return;
|
|
80
|
+
applyResult(state, pending.target, pending.result);
|
|
81
|
+
pending.applied = true;
|
|
82
|
+
}
|
|
83
|
+
|
|
38
84
|
/**
|
|
39
|
-
*
|
|
85
|
+
* Start judging the step after this batch (not awaited). The result applies to
|
|
86
|
+
* the next request if it is ready by then, else to the one after.
|
|
40
87
|
* `state.opts.stepAutoEffort` ({ request, base }) is set only when auto effort
|
|
41
88
|
* is on for this turn and the installed judge was trained on steps.
|
|
42
89
|
*/
|
|
43
|
-
export
|
|
90
|
+
export function markStepEffort(state, assistantTurnMsg) {
|
|
44
91
|
const auto = state.opts?.stepAutoEffort;
|
|
45
92
|
const snapshot = state.opts?.effortConfiguration;
|
|
46
93
|
if (!auto || !snapshot || state.signal?.aborted) return;
|
|
@@ -55,11 +102,27 @@ export async function markStepEffort(state, assistantTurnMsg) {
|
|
|
55
102
|
}
|
|
56
103
|
}
|
|
57
104
|
if (!last) return;
|
|
105
|
+
const previous = state.stepEffort;
|
|
106
|
+
if (previous) {
|
|
107
|
+
// It resolved after its request went out: this batch carries it. One still
|
|
108
|
+
// running is superseded: the newest step's judgment queues behind it and
|
|
109
|
+
// any judgment still waiting in between is skipped (latest wins), so the
|
|
110
|
+
// judge never has more than one running and one queued.
|
|
111
|
+
if (previous.settled) {
|
|
112
|
+
if (previous.result && !previous.applied) applyResult(state, last, previous.result);
|
|
113
|
+
} else {
|
|
114
|
+
previous.superseded = true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
58
117
|
state.autoEffortSteps = (state.autoEffortSteps || 0) + 1;
|
|
59
118
|
const step = state.autoEffortSteps;
|
|
60
119
|
const provider = state.sessionRef?.provider;
|
|
61
120
|
const model = state.model;
|
|
62
|
-
const
|
|
121
|
+
const pending = { target: last, sent: false, settled: false, applied: false, superseded: false, result: null };
|
|
122
|
+
const behind = previous && !previous.settled ? previous.promise : Promise.resolve();
|
|
123
|
+
state.stepEffort = pending;
|
|
124
|
+
const context = { auto, snapshot, step, provider, model, providerClient: state.provider, sessionId: state.sessionId };
|
|
125
|
+
const input = {
|
|
63
126
|
step: {
|
|
64
127
|
request: auto.request,
|
|
65
128
|
step,
|
|
@@ -70,11 +133,26 @@ export async function markStepEffort(state, assistantTurnMsg) {
|
|
|
70
133
|
result: stepResultWindow(textOf(results.get(call.id)?.content)),
|
|
71
134
|
})),
|
|
72
135
|
},
|
|
73
|
-
}
|
|
136
|
+
};
|
|
137
|
+
pending.promise = behind
|
|
138
|
+
.then(() => (pending.superseded ? null : judgeTurn(input)))
|
|
139
|
+
.then((judged) => (judged ? stepResult(context, judged) : null))
|
|
140
|
+
// A failed judgment leaves the step at the effort in force.
|
|
141
|
+
.catch(() => null)
|
|
142
|
+
.then((result) => {
|
|
143
|
+
// Only this record changes here; the loop reads it at its next boundary.
|
|
144
|
+
pending.result = result;
|
|
145
|
+
pending.settled = true;
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// What a resolved judgment sets: `{ marked, level }` (the tool result's effort
|
|
150
|
+
// configuration, and the per-request effort of a custom route), or null.
|
|
151
|
+
function stepResult({ auto, snapshot, step, provider, model, providerClient, sessionId }, judged) {
|
|
74
152
|
// `atStep` numbers the tool-result step; `step` in a resolved decision is the ladder move.
|
|
75
153
|
const record = {
|
|
76
154
|
at: new Date().toISOString(),
|
|
77
|
-
sessionId
|
|
155
|
+
sessionId,
|
|
78
156
|
provider,
|
|
79
157
|
model,
|
|
80
158
|
mode: 'on',
|
|
@@ -82,9 +160,9 @@ export async function markStepEffort(state, assistantTurnMsg) {
|
|
|
82
160
|
};
|
|
83
161
|
if (!judged.probs) {
|
|
84
162
|
recordEffortDecision({ ...record, skipped: judged.skipped });
|
|
85
|
-
return;
|
|
163
|
+
return null;
|
|
86
164
|
}
|
|
87
|
-
const modelMeta = autoEffortModel(provider,
|
|
165
|
+
const modelMeta = autoEffortModel(provider, providerClient, model);
|
|
88
166
|
const resolved = resolveAutoEffort({
|
|
89
167
|
base: auto.base,
|
|
90
168
|
options: effortOptionsFor(provider, modelMeta),
|
|
@@ -96,19 +174,26 @@ export async function markStepEffort(state, assistantTurnMsg) {
|
|
|
96
174
|
ms: judged.ms,
|
|
97
175
|
probs: judged.probs.map((value) => Number(value.toFixed(3))),
|
|
98
176
|
});
|
|
99
|
-
if (
|
|
177
|
+
if (!resolved) warnEmptyAutoEffortLadder(provider, model, auto.base);
|
|
178
|
+
if (isCustomProviderName(provider)) {
|
|
100
179
|
const level =
|
|
101
180
|
resolved &&
|
|
102
181
|
resolveCustomReasoning({
|
|
103
|
-
protocol:
|
|
182
|
+
protocol: providerClient?.customConfig?.protocol,
|
|
104
183
|
model: modelMeta,
|
|
105
184
|
effort: resolved.effort,
|
|
106
185
|
}).level;
|
|
107
|
-
if (!level) return;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return
|
|
186
|
+
if (!level) return null;
|
|
187
|
+
// The per-request effort also carries the step on an update route,
|
|
188
|
+
// where a rejected update replays the request with it.
|
|
189
|
+
return {
|
|
190
|
+
level,
|
|
191
|
+
marked:
|
|
192
|
+
snapshot.mode === 'custom'
|
|
193
|
+
? { ...snapshot, effort: level }
|
|
194
|
+
: stepEffortConfiguration(snapshot, provider, model, level),
|
|
195
|
+
};
|
|
111
196
|
}
|
|
112
197
|
const marked = resolved && stepEffortConfiguration(snapshot, provider, model, resolved.effort);
|
|
113
|
-
|
|
198
|
+
return marked ? { level: null, marked } : null;
|
|
114
199
|
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Execution-call projection for the fixed tool bridge. A wire call
|
|
2
|
+
// `call_tool {name: T, arguments: A}` (id X) becomes the execution call
|
|
3
|
+
// `{ id: X, name: T, arguments: A, wireCall }` before eager admission and
|
|
4
|
+
// classification, so every policy, ordering, cache, hook, approval and audit
|
|
5
|
+
// layer sees the target itself. The tool result still answers wire id X and
|
|
6
|
+
// the transcript keeps the original wire call (`wireCall`, an immutable copy).
|
|
7
|
+
// Non-bridge sessions and every other call pass through unchanged.
|
|
8
|
+
import { formatInvalidToolArgsResult, isInvalidToolArgsMarker } from '../../providers/lib/openai-tool-args.mjs';
|
|
9
|
+
import {
|
|
10
|
+
BRIDGE_CALL_TOOL_NAME,
|
|
11
|
+
bridgeErrorText,
|
|
12
|
+
isToolBridgeEnabled,
|
|
13
|
+
resolveBridgeTarget,
|
|
14
|
+
} from '../../runtime-core/tool-bridge.mjs';
|
|
15
|
+
|
|
16
|
+
const CALL_TOOL_KEYS = new Set(['name', 'arguments']);
|
|
17
|
+
|
|
18
|
+
const isPlainObject = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
|
|
19
|
+
|
|
20
|
+
function deepFreeze(value) {
|
|
21
|
+
if (value && typeof value === 'object' && !Object.isFrozen(value)) {
|
|
22
|
+
Object.freeze(value);
|
|
23
|
+
for (const key of Object.keys(value)) deepFreeze(value[key]);
|
|
24
|
+
}
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function projectionFailure(wireCall, wire, text) {
|
|
29
|
+
return { id: wireCall.id, name: wireCall.name, arguments: wireCall.arguments, wireCall: wire, bridgeError: text };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @returns the execution call for `wireCall`: the projected target call, a
|
|
34
|
+
* call carrying `bridgeError` (answered with that error, never executed),
|
|
35
|
+
* or `wireCall` itself when no projection applies. Idempotent.
|
|
36
|
+
*/
|
|
37
|
+
export function resolveExecutionToolCall(wireCall, session) {
|
|
38
|
+
if (!wireCall || wireCall.name !== BRIDGE_CALL_TOOL_NAME || wireCall.wireCall || !isToolBridgeEnabled(session)) {
|
|
39
|
+
return wireCall;
|
|
40
|
+
}
|
|
41
|
+
const wire = deepFreeze(structuredClone(wireCall));
|
|
42
|
+
const args = wireCall.arguments;
|
|
43
|
+
if (isInvalidToolArgsMarker(args)) return projectionFailure(wireCall, wire, formatInvalidToolArgsResult(wireCall));
|
|
44
|
+
if (!isPlainObject(args)) {
|
|
45
|
+
return projectionFailure(
|
|
46
|
+
wireCall,
|
|
47
|
+
wire,
|
|
48
|
+
bridgeErrorText('INVALID_ARGUMENTS', 'call_tool requires {name, arguments}.')
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
const extra = Object.keys(args).filter((key) => !CALL_TOOL_KEYS.has(key));
|
|
52
|
+
if (extra.length) {
|
|
53
|
+
return projectionFailure(
|
|
54
|
+
wireCall,
|
|
55
|
+
wire,
|
|
56
|
+
bridgeErrorText('INVALID_ARGUMENTS', `call_tool does not accept: ${extra.join(', ')}.`)
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
if (!isPlainObject(args.arguments)) {
|
|
60
|
+
return projectionFailure(
|
|
61
|
+
wireCall,
|
|
62
|
+
wire,
|
|
63
|
+
bridgeErrorText('INVALID_ARGUMENTS', 'call_tool arguments must be an object of the target tool arguments.')
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
const target = resolveBridgeTarget(session, args.name);
|
|
67
|
+
if (target.error) return projectionFailure(wireCall, wire, bridgeErrorText(target.error.code, target.error.message));
|
|
68
|
+
const call = { id: wireCall.id, name: target.name, arguments: structuredClone(args.arguments), wireCall: wire };
|
|
69
|
+
// The target definition drives read-only classification of the call; it is
|
|
70
|
+
// never serialized with the call.
|
|
71
|
+
Object.defineProperty(call, 'bridgeTool', { value: target.tool, enumerable: false });
|
|
72
|
+
return call;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function resolveExecutionToolCalls(calls, session) {
|
|
76
|
+
return Array.isArray(calls) ? calls.map((call) => resolveExecutionToolCall(call, session)) : calls;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The classification tool list for `calls`: `tools` plus the definitions of
|
|
81
|
+
* bridged targets that are not on it, so a bridged target is classified
|
|
82
|
+
* (read-only, dedup, stale-read invalidation) exactly like a direct call.
|
|
83
|
+
*/
|
|
84
|
+
export function bridgeClassificationTools(tools, calls) {
|
|
85
|
+
const base = Array.isArray(tools) ? tools : [];
|
|
86
|
+
const seen = new Set(base.map((tool) => tool?.name));
|
|
87
|
+
const extra = [];
|
|
88
|
+
for (const call of calls || []) {
|
|
89
|
+
const definition = call?.bridgeTool;
|
|
90
|
+
if (!definition || seen.has(definition.name)) continue;
|
|
91
|
+
seen.add(definition.name);
|
|
92
|
+
extra.push(definition);
|
|
93
|
+
}
|
|
94
|
+
return extra.length ? [...base, ...extra] : tools;
|
|
95
|
+
}
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { resolvePreToolAskApproval } from '../tool-helpers.mjs';
|
|
6
6
|
import { runAbortable, throwIfAborted } from '../../../../../shared/abort-race.mjs';
|
|
7
|
+
import { evaluateExecPolicy } from '../../../tools/bash-policy-scan.mjs';
|
|
7
8
|
import { beginSessionApprovalWait } from '../../manager/runtime-liveness.mjs';
|
|
8
9
|
|
|
9
10
|
const isArgsObject = (value) => value && typeof value === 'object' && !Array.isArray(value);
|
|
10
11
|
|
|
11
|
-
async function askApproval(call, { callerSessionId, executeOpts, toolApprovalHook, decision }) {
|
|
12
|
+
async function askApproval(call, { callerSessionId, executeOpts, toolApprovalHook, decision, keepArgs = false }) {
|
|
12
13
|
const askReason = String(decision?.reason || 'approval requested by hook').trim();
|
|
13
14
|
// While the user decides, the session is waiting on them, not working.
|
|
14
15
|
const releaseApprovalWait = beginSessionApprovalWait(callerSessionId);
|
|
@@ -30,10 +31,35 @@ async function askApproval(call, { callerSessionId, executeOpts, toolApprovalHoo
|
|
|
30
31
|
}
|
|
31
32
|
if (askOutcome.denial) return { denial: askOutcome.denial };
|
|
32
33
|
const approval = askOutcome.approval;
|
|
33
|
-
if (approval && typeof approval === 'object' && isArgsObject(approval.args)) call.args = approval.args;
|
|
34
|
+
if (!keepArgs && approval && typeof approval === 'object' && isArgsObject(approval.args)) call.args = approval.args;
|
|
34
35
|
return null;
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Approval gate for a shell call (or a terminal `run`) whose exec policy
|
|
40
|
+
* decision is 'ask' (elevated launch). Runs after the final call is known. The
|
|
41
|
+
* approval is granted for the exact command being asked about: an approval
|
|
42
|
+
* reply cannot rewrite the args.
|
|
43
|
+
* @returns {Promise<{ denial: string } | { elevationApproved: boolean }>}
|
|
44
|
+
*/
|
|
45
|
+
export async function applyShellElevationGate(call, { callerSessionId, executeOpts, toolApprovalHook }) {
|
|
46
|
+
const gated = call.name === 'shell' || (call.name === 'terminal' && call.args?.action === 'run');
|
|
47
|
+
if (!gated || !isArgsObject(call.args) || call.args.command == null) {
|
|
48
|
+
return { elevationApproved: false };
|
|
49
|
+
}
|
|
50
|
+
const decision = evaluateExecPolicy(String(call.args.command));
|
|
51
|
+
if (decision.decision !== 'ask') return { elevationApproved: false };
|
|
52
|
+
const denied = await askApproval(call, {
|
|
53
|
+
callerSessionId,
|
|
54
|
+
executeOpts,
|
|
55
|
+
toolApprovalHook,
|
|
56
|
+
decision,
|
|
57
|
+
keepArgs: true,
|
|
58
|
+
});
|
|
59
|
+
if (denied) return denied;
|
|
60
|
+
return { elevationApproved: true };
|
|
61
|
+
}
|
|
62
|
+
|
|
37
63
|
/**
|
|
38
64
|
* @returns {Promise<{ denial: string } | { name: string, args: any }>}
|
|
39
65
|
* the call as the hook left it, or the denial text to return instead
|
|
@@ -48,7 +74,8 @@ export async function applyBeforeToolHook({
|
|
|
48
74
|
toolApprovalHook,
|
|
49
75
|
}) {
|
|
50
76
|
const call = { name, args, cwd };
|
|
51
|
-
|
|
77
|
+
// ask_user is itself the user prompt; it never goes through the ordinary approval gate.
|
|
78
|
+
if (!beforeToolHook || name === 'ask_user') return call;
|
|
52
79
|
try {
|
|
53
80
|
const decision = await runAbortable(executeOpts.signal, () =>
|
|
54
81
|
beforeToolHook(
|
|
@@ -35,13 +35,19 @@ function dispatchMcp(name, args, { cwd, callerSessionId, sessionRef, executeOpts
|
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
function dispatchInternal(
|
|
38
|
+
function dispatchInternal(
|
|
39
|
+
name,
|
|
40
|
+
args,
|
|
41
|
+
{ cwd, callerSessionId, sessionRef, executeOpts, notifyFn, toolApprovalHook, elevationApproved }
|
|
42
|
+
) {
|
|
39
43
|
// callerSessionId propagates into server.mjs dispatchTool so that
|
|
40
44
|
// dispatchAiWrapped can detect and reject recursive calls from a
|
|
41
45
|
// hidden-role session (recall/search → self).
|
|
42
46
|
return executeInternalTool(name, args, {
|
|
43
47
|
scopeId: sessionRef?.mcpScopeId || null,
|
|
44
48
|
callerSessionId,
|
|
49
|
+
// The calling session itself: bridge tools answer within its scope.
|
|
50
|
+
callerSession: sessionRef || null,
|
|
45
51
|
callerCwd: cwd,
|
|
46
52
|
setCallerCwd: async (nextCwd) => {
|
|
47
53
|
const applyForCaller = sessionRef?._applyResolvedCwdForCaller;
|
|
@@ -58,6 +64,8 @@ function dispatchInternal(name, args, { cwd, callerSessionId, sessionRef, execut
|
|
|
58
64
|
notifyFn,
|
|
59
65
|
toolApprovalHook,
|
|
60
66
|
toolCallId: executeOpts.toolCallId || null,
|
|
67
|
+
// Runtime-granted for this call only (terminal run); never from model args.
|
|
68
|
+
elevationApproved: elevationApproved === true,
|
|
61
69
|
invocationSource: 'model-tool',
|
|
62
70
|
});
|
|
63
71
|
}
|
|
@@ -90,9 +98,12 @@ export function dispatchToolCall({ name, args }, ctx) {
|
|
|
90
98
|
// variants) adapt to a native execution inside executeBuiltinTool's default
|
|
91
99
|
// case; on a shape mismatch it falls back to the redirect guidance message.
|
|
92
100
|
if (name === 'shell' || isBuiltinTool(name) || isExternalAdapterTool(name)) {
|
|
93
|
-
const builtinOpts =
|
|
94
|
-
|
|
95
|
-
:
|
|
101
|
+
const builtinOpts = {
|
|
102
|
+
...completionToolOpts,
|
|
103
|
+
...(executeOpts.suppressReadUnchangedStub ? { suppressReadUnchangedStub: true } : {}),
|
|
104
|
+
// Runtime-granted only; any value inherited from executeOpts is overridden.
|
|
105
|
+
elevationApproved: ctx.elevationApproved === true,
|
|
106
|
+
};
|
|
96
107
|
return executeBuiltinTool(name, args, cwd, builtinOpts);
|
|
97
108
|
}
|
|
98
109
|
return formatUnknownBuiltinToolMessage(name, args, 'tool');
|
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
import { isMcpTool } from '../../mcp/client.mjs';
|
|
9
9
|
import { prepareDeferredToolCallThrough } from './deferred-call-through.mjs';
|
|
10
10
|
import { refreshDeferredMcpToolCatalog } from '../../runtime-core/tool-catalog.mjs';
|
|
11
|
+
import { bridgeTargetUnavailable } from '../../runtime-core/tool-bridge.mjs';
|
|
11
12
|
import { preDispatchDenyForSession, routeWebFetchCall } from './pre-dispatch-deny.mjs';
|
|
12
13
|
import { runWithToolExecutionOwner } from '../../../../shared/tool-execution-owner.mjs';
|
|
13
14
|
import { runWithLocalSearchTelemetry } from '../../tools/builtin/local-search-telemetry.mjs';
|
|
14
15
|
import { throwIfAborted } from '../../../../shared/abort-race.mjs';
|
|
15
16
|
import { prepareToolCall } from './tool-exec/call-prep.mjs';
|
|
16
|
-
import { applyBeforeToolHook } from './tool-exec/before-hook.mjs';
|
|
17
|
+
import { applyBeforeToolHook, applyShellElevationGate } from './tool-exec/before-hook.mjs';
|
|
17
18
|
import { dispatchToolCall } from './tool-exec/dispatch.mjs';
|
|
18
19
|
import { applyAfterToolHook } from './tool-exec/after-hook.mjs';
|
|
19
20
|
import { runReadOnlyIoWithDeadline } from './tool-exec/read-only-deadline.mjs';
|
|
@@ -65,6 +66,18 @@ async function executeToolOwned(name, args, cwd, callerSessionId, sessionRef, ex
|
|
|
65
66
|
if (isMcpTool(call.name)) refreshDeferredMcpToolCatalog(sessionRef);
|
|
66
67
|
const deferredPrep = prepareDeferredToolCallThrough(sessionRef, call.name);
|
|
67
68
|
if (deferredPrep?.deny) return deferredPrep.deny;
|
|
69
|
+
// A bridged target was resolved when its call_tool was projected; it must
|
|
70
|
+
// still be available in this session's scope (also after a hook rewrite).
|
|
71
|
+
// The authorized identity is the public tool name, not its transport
|
|
72
|
+
// (web_fetch routed to local_fetch/image_fetch stays web_fetch here).
|
|
73
|
+
if (executeOpts.bridgeWireCall) {
|
|
74
|
+
const unavailable = bridgeTargetUnavailable(sessionRef, finalCall.schemaName || finalCall.name);
|
|
75
|
+
if (unavailable) return unavailable;
|
|
76
|
+
}
|
|
77
|
+
// Elevated launches ask the user first; denied / no approval UI refuses the call.
|
|
78
|
+
const elevation = await applyShellElevationGate(call, { callerSessionId, executeOpts, toolApprovalHook });
|
|
79
|
+
if (elevation.denial) return elevation.denial;
|
|
80
|
+
throwIfAborted(executeOpts.signal);
|
|
68
81
|
const result = await runReadOnlyIoWithDeadline(call.name, executeOpts.signal || null, async (deadlineSignal) => {
|
|
69
82
|
let callOpts = executeOpts;
|
|
70
83
|
if (deadlineSignal !== executeOpts.signal) {
|
|
@@ -80,6 +93,7 @@ async function executeToolOwned(name, args, cwd, callerSessionId, sessionRef, ex
|
|
|
80
93
|
completionToolOpts,
|
|
81
94
|
notifyFn,
|
|
82
95
|
toolApprovalHook,
|
|
96
|
+
elevationApproved: elevation.elevationApproved === true,
|
|
83
97
|
});
|
|
84
98
|
});
|
|
85
99
|
return applyAfterToolHook(result, hookFrom(executeOpts, sessionRef, 'afterToolHook'), {
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// Tool-exposure migration (native ↔ bridge-v1, and pre-versioned fixed
|
|
2
|
+
// surfaces → bridge-v1). The surface itself is rebuilt by
|
|
3
|
+
// applyDeferredToolSurface; this module adds what a changed request prefix
|
|
4
|
+
// invalidates: provider state, the prefix guard, the context baseline and the
|
|
5
|
+
// cache-break tag. Historical tool calls are never rewritten.
|
|
6
|
+
import {
|
|
7
|
+
applyDeferredToolSurface,
|
|
8
|
+
rebuildDeferredToolSurfaceForProvider,
|
|
9
|
+
} from '../../runtime-core/tool-catalog.mjs';
|
|
10
|
+
import {
|
|
11
|
+
bridgeSurfaceOutdated,
|
|
12
|
+
sessionToolExposure,
|
|
13
|
+
TOOL_EXPOSURE_BRIDGE,
|
|
14
|
+
TOOL_SURFACE_MIGRATION_INTENT,
|
|
15
|
+
toolExposureMigrationNeeded,
|
|
16
|
+
toolExposureModeForProvider,
|
|
17
|
+
} from '../../runtime-core/tool-exposure.mjs';
|
|
18
|
+
import { applyInitialDeferredToolManifestToBp2 } from '../../context/collect.mjs';
|
|
19
|
+
import { isAgentOwner } from '../../agent-owner.mjs';
|
|
20
|
+
import { honoredSchemaAllowlist } from '../manager/session-tool-surface.mjs';
|
|
21
|
+
import { syncSystemPrefix } from '../manager/prompt-utils.mjs';
|
|
22
|
+
import { invalidateProviderContextBaseline } from './compact-policy.mjs';
|
|
23
|
+
|
|
24
|
+
/** Drop everything measured against the previous tool surface. */
|
|
25
|
+
function invalidateForToolSurfaceMigration(session) {
|
|
26
|
+
delete session.providerState;
|
|
27
|
+
delete session._providerPrefixGuardState;
|
|
28
|
+
invalidateProviderContextBaseline(session);
|
|
29
|
+
session.updatedAt = Date.now();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* After a surface re-apply outside a request (resume, provider switch)
|
|
34
|
+
* migrated the exposure: the first send of the next turn carries the tag.
|
|
35
|
+
*/
|
|
36
|
+
export function markToolSurfaceMigrated(session) {
|
|
37
|
+
invalidateForToolSurfaceMigration(session);
|
|
38
|
+
session.pendingCacheBreakIntent = TOOL_SURFACE_MIGRATION_INTENT;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Provider switch: rebuild the surface for `provider`, migrating bridge ↔ native. */
|
|
42
|
+
export function rebuildToolSurfaceForProviderWithMigration(session, provider) {
|
|
43
|
+
if (!session) return false;
|
|
44
|
+
const migrating = toolExposureMigrationNeeded(session, provider);
|
|
45
|
+
rebuildDeferredToolSurfaceForProvider(session, provider);
|
|
46
|
+
if (migrating) markToolSurfaceMigrated(session);
|
|
47
|
+
return migrating;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// The latest assistant tool turn still waits for a result: not a safe boundary.
|
|
51
|
+
function hasUnansweredToolCalls(messages) {
|
|
52
|
+
const list = Array.isArray(messages) ? messages : [];
|
|
53
|
+
const index = list.findLastIndex((message) => message?.role === 'assistant' && message.toolCalls?.length);
|
|
54
|
+
if (index < 0) return false;
|
|
55
|
+
const answered = new Set(
|
|
56
|
+
list.slice(index + 1).flatMap((message) => (message?.role === 'tool' ? [message.toolCallId] : []))
|
|
57
|
+
);
|
|
58
|
+
return list[index].toolCalls.some((call) => call?.id && !answered.has(call.id));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Request-boundary migration of a live session whose persisted exposure
|
|
63
|
+
* differs from its provider's. `messages` is the transcript the request is
|
|
64
|
+
* built from; the fixed-guidance rewrite lands there (and on the session).
|
|
65
|
+
* Returns true when the surface changed; the caller drops its frozen tool
|
|
66
|
+
* snapshot and provider state and tags the send.
|
|
67
|
+
*/
|
|
68
|
+
export function migrateToolExposureAtBoundary(session, messages) {
|
|
69
|
+
if (!session || !toolExposureMigrationNeeded(session) || hasUnansweredToolCalls(messages)) return false;
|
|
70
|
+
const stored = session.messages;
|
|
71
|
+
const working = Array.isArray(messages) ? messages : stored;
|
|
72
|
+
if (Array.isArray(working)) session.messages = working;
|
|
73
|
+
try {
|
|
74
|
+
applyDeferredToolSurface(session, session.deferredSurfaceMode || 'lead', [], {
|
|
75
|
+
provider: session.provider,
|
|
76
|
+
model: session.model,
|
|
77
|
+
});
|
|
78
|
+
} finally {
|
|
79
|
+
if (Array.isArray(working) && session.messages !== working) {
|
|
80
|
+
// The rewrite may drop an emptied system message: keep the request
|
|
81
|
+
// transcript array identity the loop holds.
|
|
82
|
+
working.splice(0, working.length, ...session.messages);
|
|
83
|
+
}
|
|
84
|
+
session.messages = stored;
|
|
85
|
+
}
|
|
86
|
+
// The rewritten prompt messages are fresh objects; the canonical transcript
|
|
87
|
+
// the save path persists takes them too, so the next save writes the new
|
|
88
|
+
// prompt together with the new exposure.
|
|
89
|
+
if (Array.isArray(stored) && Array.isArray(working) && stored !== working) syncSystemPrefix(stored, working);
|
|
90
|
+
invalidateForToolSurfaceMigration(session);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Bridge state an agent surface carries; dropped when it returns to the full array.
|
|
95
|
+
const AGENT_BRIDGE_FIELDS = [
|
|
96
|
+
'toolExposureMode',
|
|
97
|
+
'deferredProviderMode',
|
|
98
|
+
'deferredNativeTools',
|
|
99
|
+
'deferredSurfaceMode',
|
|
100
|
+
'deferredToolUsage',
|
|
101
|
+
'deferredDefaultTools',
|
|
102
|
+
'deferredSelectedTools',
|
|
103
|
+
'deferredDiscoveredTools',
|
|
104
|
+
'deferredCallableTools',
|
|
105
|
+
'deferredAnnouncedTools',
|
|
106
|
+
'deferredToolDeltaRevision',
|
|
107
|
+
'nativeDeferredDiscovery',
|
|
108
|
+
'mcpServerInstructions',
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Agent (worker) sessions. Call right after their tools were resolved
|
|
113
|
+
* (create, resume, route change): on a bridge provider the eager surface
|
|
114
|
+
* becomes the full-mode core plus the bridge, built only from those
|
|
115
|
+
* role/policy-filtered tools; a native provider keeps the full array. A
|
|
116
|
+
* session honouring its own schema allowlist (a hidden specialist role) is
|
|
117
|
+
* already a small explicit surface and keeps it. `existing`: the session had
|
|
118
|
+
* a surface before, so a changed exposure is a migration.
|
|
119
|
+
*/
|
|
120
|
+
export function applyAgentToolExposure(session, { existing = false } = {}) {
|
|
121
|
+
if (!session || !Array.isArray(session.tools) || !isAgentOwner(session)) return false;
|
|
122
|
+
const before = sessionToolExposure(session);
|
|
123
|
+
const allowlisted = honoredSchemaAllowlist(session.schemaAllowedTools, { ownerIsAgent: true, agent: session.agent });
|
|
124
|
+
const bridge =
|
|
125
|
+
!allowlisted && toolExposureModeForProvider(session.provider, session.wireRoute) === TOOL_EXPOSURE_BRIDGE;
|
|
126
|
+
if (!bridge && before === null) return false;
|
|
127
|
+
// A surface an earlier bridge revision built is rebuilt now.
|
|
128
|
+
const outdated = bridgeSurfaceOutdated(session);
|
|
129
|
+
// The tools just resolved are the whole authority: no earlier catalog, MCP
|
|
130
|
+
// availability snapshot or pending MCP delta survives. (A bridge surface
|
|
131
|
+
// re-takes the snapshot at its next request boundary; a native agent has no
|
|
132
|
+
// refresh, so a stale snapshot would hide a connected server's tools.)
|
|
133
|
+
delete session.deferredToolCatalog;
|
|
134
|
+
delete session.deferredLateToolCatalog;
|
|
135
|
+
delete session.deferredMcpToolNames;
|
|
136
|
+
delete session.pendingDeferredToolDelta;
|
|
137
|
+
if (bridge) {
|
|
138
|
+
// The resolved list may be shared (prepared-resume cache): rebuild a copy.
|
|
139
|
+
session.tools = session.tools.slice();
|
|
140
|
+
applyDeferredToolSurface(session, 'full', [], { provider: session.provider, model: session.model });
|
|
141
|
+
} else {
|
|
142
|
+
for (const field of AGENT_BRIDGE_FIELDS) delete session[field];
|
|
143
|
+
// Without bridge state the fixed slot composes empty: the guidance goes.
|
|
144
|
+
if (Array.isArray(session.messages)) applyInitialDeferredToolManifestToBp2(session, [], { rebuild: true });
|
|
145
|
+
delete session.deferredToolBp2Applied;
|
|
146
|
+
}
|
|
147
|
+
const changed = before !== sessionToolExposure(session) || outdated;
|
|
148
|
+
if (existing && changed) markToolSurfaceMigrated(session);
|
|
149
|
+
return changed;
|
|
150
|
+
}
|
|
@@ -8,6 +8,7 @@ import { traceLoopPhaseTiming } from './diagnostics.mjs';
|
|
|
8
8
|
import { processToolBatch } from '../tool-batch.mjs';
|
|
9
9
|
import { CROSS_TURN_CAP, REPEAT_FAIL_LIMIT } from './loop-state.mjs';
|
|
10
10
|
import { markStepEffort } from './step-auto-effort.mjs';
|
|
11
|
+
import { resolveExecutionToolCalls } from './tool-call-resolution.mjs';
|
|
11
12
|
|
|
12
13
|
function isSleepLikeToolCall(call) {
|
|
13
14
|
const name = String(call?.name || call?.toolName || call?.function?.name || '').toLowerCase();
|
|
@@ -34,7 +35,9 @@ export async function runToolPhase(state, round, sent, onToolCall) {
|
|
|
34
35
|
}
|
|
35
36
|
// Per-turn batch shape — one row per assistant turn so trace consumers can
|
|
36
37
|
// derive the multi-tool adoption ratio without scanning message bodies.
|
|
37
|
-
|
|
38
|
+
// Audit records what runs: a bridged call_tool is recorded as its target.
|
|
39
|
+
// The wire calls stay the transcript identity (assistant turn below).
|
|
40
|
+
const toolBatchId = recordToolBatch(sessionId, resolveExecutionToolCalls(calls, sessionRef), state.iterations);
|
|
38
41
|
await Promise.resolve(onToolCall?.(state.iterations, calls));
|
|
39
42
|
const assistantTurnMsg = buildToolCallAssistantMessage(response, { calls, suppressMidTurnText, opts });
|
|
40
43
|
commitAssistantMessage(messages, assistantTurnMsg, opts);
|
|
@@ -70,7 +73,9 @@ export async function runToolPhase(state, round, sent, onToolCall) {
|
|
|
70
73
|
// carries a runtime notice for the model, delivered after its results.
|
|
71
74
|
if (response.recoveryNotice) messages.push(response.recoveryNotice);
|
|
72
75
|
const toolsEndedAt = Date.now();
|
|
73
|
-
|
|
76
|
+
// Starts the step judgment; the next request uses it if it has resolved by
|
|
77
|
+
// then (send-phase.mjs applyStepEffort), else the one after.
|
|
78
|
+
markStepEffort(state, assistantTurnMsg);
|
|
74
79
|
try {
|
|
75
80
|
opts.onToolPhaseCompleted?.({
|
|
76
81
|
iteration: round.nextIteration,
|
|
@@ -54,6 +54,12 @@ export function createAskPromptQueue({ sessionId, promptSource }) {
|
|
|
54
54
|
// after each turn — keeps queued `agent type=send` messages in order.
|
|
55
55
|
const tail = [];
|
|
56
56
|
let initialPromptSource = initialPromptSourceFor(promptSource);
|
|
57
|
+
// Queue entries of the input nextTurn handed out that no turn owns yet.
|
|
58
|
+
// Once a turn starts, its failure path acks or releases them instead.
|
|
59
|
+
let unstartedEntries = [];
|
|
60
|
+
const release = (entries) => {
|
|
61
|
+
if (entries?.length > 0) releasePendingMessages(sessionId, entries);
|
|
62
|
+
};
|
|
57
63
|
|
|
58
64
|
/** The next turn's input — prompt, caller context, consumed queue entries
|
|
59
65
|
* and provenance — or null when nothing model-visible is left to run. */
|
|
@@ -83,7 +89,26 @@ export function createAskPromptQueue({ sessionId, promptSource }) {
|
|
|
83
89
|
tail.unshift(...groups.slice(1).map(tailTurnFor));
|
|
84
90
|
input = queuedTurnInput(tailTurnFor(first));
|
|
85
91
|
}
|
|
86
|
-
|
|
92
|
+
if (!hasModelVisiblePromptContent(input.prompt)) {
|
|
93
|
+
release(input.pendingEntries);
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
unstartedEntries = input.pendingEntries;
|
|
97
|
+
return input;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/** The turn for the last nextTurn input started: it now owns its entries. */
|
|
101
|
+
const markStarted = () => {
|
|
102
|
+
unstartedEntries = [];
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/** Hands every drained entry no turn started back to the pending queue —
|
|
106
|
+
* the waiting follow-up turns and an input whose turn never opened.
|
|
107
|
+
* Called once when the ask unwinds; each entry is released once. */
|
|
108
|
+
const releaseUnstarted = () => {
|
|
109
|
+
const entries = [...unstartedEntries, ...tail.splice(0).flatMap((turn) => turn.entries || [])];
|
|
110
|
+
unstartedEntries = [];
|
|
111
|
+
release(entries);
|
|
87
112
|
};
|
|
88
113
|
|
|
89
114
|
/** Queues drained pending-message entries as follow-up turns; true when
|
|
@@ -101,5 +126,8 @@ export function createAskPromptQueue({ sessionId, promptSource }) {
|
|
|
101
126
|
return true;
|
|
102
127
|
};
|
|
103
128
|
|
|
104
|
-
|
|
129
|
+
/** True while drained follow-up turns are still waiting to run. */
|
|
130
|
+
const hasQueuedTurns = () => tail.length > 0;
|
|
131
|
+
|
|
132
|
+
return { nextTurn, pushDrained, hasQueuedTurns, markStarted, releaseUnstarted };
|
|
105
133
|
}
|