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
|
@@ -71,8 +71,10 @@ export function createContextState({
|
|
|
71
71
|
// Lead workspace record (worktrees/contract.mjs SessionWorkspace): the
|
|
72
72
|
// registered Project, the execution root, the worktree binding and its
|
|
73
73
|
// revision. Null while the session has never left its project folder.
|
|
74
|
-
// Identity-stable until a transition commits.
|
|
75
|
-
|
|
74
|
+
// Identity-stable until a transition commits. A project-folder session in a
|
|
75
|
+
// git repository publishes the folder's branch / detached commit too
|
|
76
|
+
// (getLiveWorkspace reads HEAD without spawning git).
|
|
77
|
+
workspace: runtime.getLiveWorkspace?.() ?? runtime.getWorkspace?.() ?? null,
|
|
76
78
|
systemShell: runtime.systemShell || { source: 'auto', command: '', effective: '' },
|
|
77
79
|
webSearchRoute: runtime.getWebSearchRoute?.() || runtime.webSearchRoute || null,
|
|
78
80
|
autoClear: autoClearState(),
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import {
|
|
12
12
|
cancelQuotaResumeEntry,
|
|
13
13
|
forgetQuotaSuspendedGoal,
|
|
14
|
+
isAgentOnlySession,
|
|
14
15
|
noteQuotaSuspendedGoal,
|
|
15
16
|
publicQuotaResume,
|
|
16
17
|
quotaAutoResumeEnabled,
|
|
@@ -73,6 +74,20 @@ export function latestQuotaFailure(items) {
|
|
|
73
74
|
return null;
|
|
74
75
|
}
|
|
75
76
|
|
|
77
|
+
/** The turn key of the failed turndone that ends the transcript, when no
|
|
78
|
+
* later turn has begun; '' otherwise. */
|
|
79
|
+
export function latestFailedTurnKey(items) {
|
|
80
|
+
const transcript = Array.isArray(items) ? items : [];
|
|
81
|
+
for (let index = transcript.length - 1; index >= 0; index -= 1) {
|
|
82
|
+
const item = transcript[index];
|
|
83
|
+
if (item?.kind === 'user' || item?.archived === true) return '';
|
|
84
|
+
if (item?.kind !== 'turndone') continue;
|
|
85
|
+
if (String(item.status || '').toLowerCase() !== 'failed') return '';
|
|
86
|
+
return transcriptTurnKeys(transcript)[index] || '';
|
|
87
|
+
}
|
|
88
|
+
return '';
|
|
89
|
+
}
|
|
90
|
+
|
|
76
91
|
/** What retrying the turn submits: its prompt when it produced no output, the
|
|
77
92
|
* continuation instruction when it did, null when the prompt carried no text
|
|
78
93
|
* (a media/attachment-only prompt cannot be replayed). */
|
|
@@ -125,6 +140,8 @@ export function createQuotaResumeLane(bag) {
|
|
|
125
140
|
routeProvider: String(runtime.sessionProvider ?? runtime.provider ?? ''),
|
|
126
141
|
routeModel: String(runtime.sessionModel ?? runtime.model ?? ''),
|
|
127
142
|
});
|
|
143
|
+
// A delegated agent child never owns a resume: the Lead decides its retries.
|
|
144
|
+
const agentOnly = () => isAgentOnlySession({ id: currentId(), ...runtime.session });
|
|
128
145
|
const queueResume = (sessionId, failure) =>
|
|
129
146
|
scheduleQuotaResumeEntry({ sessionId, turnKey: failure.turnKey, ...failure.quota, ...sessionRoute() });
|
|
130
147
|
|
|
@@ -141,6 +158,21 @@ export function createQuotaResumeLane(bag) {
|
|
|
141
158
|
forgetQuotaSuspendedGoal(sessionId);
|
|
142
159
|
};
|
|
143
160
|
|
|
161
|
+
// Anything running, settling, closing or queued owns the session first.
|
|
162
|
+
const retryBlocked = () => {
|
|
163
|
+
const state = getState();
|
|
164
|
+
return (
|
|
165
|
+
flags.disposed ||
|
|
166
|
+
settlement !== null ||
|
|
167
|
+
(flags.admission || 'open') !== 'open' ||
|
|
168
|
+
state.busy ||
|
|
169
|
+
state.commandBusy ||
|
|
170
|
+
flags.autoClearRunning ||
|
|
171
|
+
flags.draining ||
|
|
172
|
+
pending.length > 0
|
|
173
|
+
);
|
|
174
|
+
};
|
|
175
|
+
|
|
144
176
|
/** The one retry operation. `automatic` is the scheduler's resume: it
|
|
145
177
|
* enqueues directly, because the hours it waited must not trigger the idle
|
|
146
178
|
* auto-clear a user submission starts. */
|
|
@@ -166,7 +198,7 @@ export function createQuotaResumeLane(bag) {
|
|
|
166
198
|
settlement = null;
|
|
167
199
|
if (!id || !failure) return null;
|
|
168
200
|
settlement = { sessionId: id, turnKey: failure.turnKey, epoch: cancelEpoch };
|
|
169
|
-
if (failure.quota.resetAt === null || !quotaAutoResumeEnabled()) return null;
|
|
201
|
+
if (failure.quota.resetAt === null || !quotaAutoResumeEnabled() || agentOnly()) return null;
|
|
170
202
|
return queueResume(id, failure);
|
|
171
203
|
},
|
|
172
204
|
|
|
@@ -188,6 +220,7 @@ export function createQuotaResumeLane(bag) {
|
|
|
188
220
|
/** Explicit request to auto-resume the latest quota-failed turn. */
|
|
189
221
|
scheduleQuotaResume(sessionId) {
|
|
190
222
|
requireAddressed(sessionId);
|
|
223
|
+
if (agentOnly()) throw new Error('agent sessions do not auto-resume; the Lead decides retries');
|
|
191
224
|
const failure = latestQuotaFailure(getState().items);
|
|
192
225
|
if (!failure || failure.quota.resetAt === null) {
|
|
193
226
|
throw new Error('latest turn did not fail on exhausted provider quota with a known reset time');
|
|
@@ -207,9 +240,15 @@ export function createQuotaResumeLane(bag) {
|
|
|
207
240
|
if (sessionId) cancelFor(String(sessionId));
|
|
208
241
|
},
|
|
209
242
|
|
|
243
|
+
/** A deferred retry request (the desktop's switch-model flow): checked
|
|
244
|
+
* against the session's own state when it arrives, so it runs only while
|
|
245
|
+
* `turnKey` is still the latest failed turn and nothing is running,
|
|
246
|
+
* settling or queued. False when refused. */
|
|
210
247
|
async retryFailedTurn(sessionId, turnKey) {
|
|
211
248
|
requireAddressed(sessionId);
|
|
212
|
-
|
|
249
|
+
const key = String(turnKey || '');
|
|
250
|
+
if (!key || retryBlocked() || latestFailedTurnKey(getState().items) !== key) return false;
|
|
251
|
+
return (await retryFailedTurn(key)) === true;
|
|
213
252
|
},
|
|
214
253
|
|
|
215
254
|
/** Scheduler fire for the entry of `generation`, after a usable reading.
|
|
@@ -219,19 +258,12 @@ export function createQuotaResumeLane(bag) {
|
|
|
219
258
|
const id = currentId();
|
|
220
259
|
const entry = quotaResumeEntry(id);
|
|
221
260
|
if (!id || !entry || entry.generation !== generation) return 'stale';
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
settlement !== null ||
|
|
226
|
-
(flags.admission || 'open') !== 'open' ||
|
|
227
|
-
state.busy ||
|
|
228
|
-
state.commandBusy ||
|
|
229
|
-
flags.autoClearRunning ||
|
|
230
|
-
flags.draining ||
|
|
231
|
-
pending.length > 0
|
|
232
|
-
) {
|
|
233
|
-
return 'busy';
|
|
261
|
+
if (agentOnly()) {
|
|
262
|
+
cancelQuotaResumeEntry(id, { generation });
|
|
263
|
+
return 'agent-session';
|
|
234
264
|
}
|
|
265
|
+
const state = getState();
|
|
266
|
+
if (retryBlocked()) return 'busy';
|
|
235
267
|
const failure = latestQuotaFailure(state.items);
|
|
236
268
|
if (!failure || failure.turnKey !== entry.turnKey) {
|
|
237
269
|
cancelQuotaResumeEntry(id, { generation });
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* commands.mjs — the session object's long-running slash commands: memory
|
|
3
3
|
* control, recall, doctor, and manual compaction (scheduled for turn end when
|
|
4
4
|
* a turn is running). Each shows a command status while it holds the lock.
|
|
5
|
+
* /btw side questions (askSide/cancelSide) run beside them, lock-free.
|
|
5
6
|
*/
|
|
6
7
|
import { compactEventDetail } from '../labels.mjs';
|
|
7
8
|
import { archiveItemsForCompaction, compactionArchivedRows } from '../compaction-view.mjs';
|
|
@@ -92,34 +93,43 @@ export function createSessionCommandsApi(bag) {
|
|
|
92
93
|
};
|
|
93
94
|
};
|
|
94
95
|
|
|
96
|
+
// The compaction pass itself, under a lock its caller holds. `quiet` (the
|
|
97
|
+
// model switch's pre-compaction) asks the compactor to skip a pass that
|
|
98
|
+
// would not reduce anything and then adds no row for it.
|
|
99
|
+
async function runCompaction(startedAt, { quiet = false } = {}) {
|
|
100
|
+
// Give Ink one event-loop turn to paint the compacting spinner before
|
|
101
|
+
// runtime.compact() starts synchronous session/transcript work (same
|
|
102
|
+
// yield as the auto-clear path; without it /compact looks frozen with
|
|
103
|
+
// no spinner until the compact already finished).
|
|
104
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
105
|
+
const result = await runtime.compact({ recoverAgent: true, ...(quiet ? { requireReduction: true } : {}) });
|
|
106
|
+
const compactChanged = Boolean(result && !result.error && result.changed !== false);
|
|
107
|
+
syncContextStats({
|
|
108
|
+
allowEstimated: true,
|
|
109
|
+
invalidateExact: compactChanged,
|
|
110
|
+
});
|
|
111
|
+
set({ ...routeState(), stats: { ...getState().stats } });
|
|
112
|
+
if (compactChanged) {
|
|
113
|
+
// The compacted rows stay visible (archived) above the divider.
|
|
114
|
+
const { items } = archiveItemsForCompaction(getState().items, compactDoneItem(result, startedAt), null, {
|
|
115
|
+
archived: compactionArchivedRows(result),
|
|
116
|
+
});
|
|
117
|
+
set({ items: replaceItems(items, { preserveSpill: true }) });
|
|
118
|
+
} else if (!quiet || result?.error) {
|
|
119
|
+
pushItem(compactDoneItem(result, startedAt));
|
|
120
|
+
}
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// An in-place model switch compacts first on the current model (routes.mjs
|
|
125
|
+
// holds the command lock and shows the compacting status meanwhile).
|
|
126
|
+
bag.compactBeforeModelSwitch = () => runCompaction(Date.now(), { quiet: true });
|
|
127
|
+
|
|
95
128
|
async function compactCommand() {
|
|
96
129
|
if (getState().commandBusy) return null;
|
|
97
130
|
if (getState().busy) return scheduleCompactForTurnEnd(compactCommand);
|
|
98
131
|
try {
|
|
99
|
-
return await withCommandStatus('Compacting conversation', 'compacting',
|
|
100
|
-
// Give Ink one event-loop turn to paint the compacting spinner before
|
|
101
|
-
// runtime.compact() starts synchronous session/transcript work (same
|
|
102
|
-
// yield as the auto-clear path; without it /compact looks frozen with
|
|
103
|
-
// no spinner until the compact already finished).
|
|
104
|
-
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
105
|
-
const result = await runtime.compact({ recoverAgent: true });
|
|
106
|
-
const compactChanged = Boolean(result && !result.error && result.changed !== false);
|
|
107
|
-
syncContextStats({
|
|
108
|
-
allowEstimated: true,
|
|
109
|
-
invalidateExact: compactChanged,
|
|
110
|
-
});
|
|
111
|
-
set({ ...routeState(), stats: { ...getState().stats } });
|
|
112
|
-
if (compactChanged) {
|
|
113
|
-
// The compacted rows stay visible (archived) above the divider.
|
|
114
|
-
const { items } = archiveItemsForCompaction(getState().items, compactDoneItem(result, startedAt), null, {
|
|
115
|
-
archived: compactionArchivedRows(result),
|
|
116
|
-
});
|
|
117
|
-
set({ items: replaceItems(items, { preserveSpill: true }) });
|
|
118
|
-
} else {
|
|
119
|
-
pushItem(compactDoneItem(result, startedAt));
|
|
120
|
-
}
|
|
121
|
-
return result;
|
|
122
|
-
});
|
|
132
|
+
return await withCommandStatus('Compacting conversation', 'compacting', (startedAt) => runCompaction(startedAt));
|
|
123
133
|
} finally {
|
|
124
134
|
// A command reply reads the published snapshot, not the draft. Commit
|
|
125
135
|
// completion before the awaiting service constructs that reply.
|
|
@@ -166,5 +176,14 @@ export function createSessionCommandsApi(bag) {
|
|
|
166
176
|
});
|
|
167
177
|
},
|
|
168
178
|
compact: compactCommand,
|
|
179
|
+
// /btw: answered from the conversation so far while a turn keeps running.
|
|
180
|
+
// No command lock and no transcript row: the answer is only returned.
|
|
181
|
+
askSide: (question) => runtime.askSide(question),
|
|
182
|
+
// `sessionId` names the session the side question was asked in (it may
|
|
183
|
+
// no longer be the current one after a switch); omitted, the current one.
|
|
184
|
+
cancelSide: (sessionId) => {
|
|
185
|
+
if (typeof sessionId === 'string' && sessionId) runtime.cancelSide(sessionId);
|
|
186
|
+
else runtime.cancelSide();
|
|
187
|
+
},
|
|
169
188
|
};
|
|
170
189
|
}
|
|
@@ -91,8 +91,8 @@ export function createSessionControlsApi(bag) {
|
|
|
91
91
|
);
|
|
92
92
|
return result;
|
|
93
93
|
},
|
|
94
|
-
setCwd: (path, options = {}) => {
|
|
95
|
-
const next = runtime.setCwd(path);
|
|
94
|
+
setCwd: async (path, options = {}) => {
|
|
95
|
+
const next = await runtime.setCwd(path);
|
|
96
96
|
// Republish up-arrow history for the NEW project: current session prompts
|
|
97
97
|
// merged with the cwd-scoped persisted store for the new cwd.
|
|
98
98
|
const sessionList = recomputePromptHistory(getState().items);
|
|
@@ -28,6 +28,13 @@ export function createSessionExtensionsApi(bag) {
|
|
|
28
28
|
{ busyError: 'Another command is still running; try again when it finishes.' }
|
|
29
29
|
);
|
|
30
30
|
const pluginLabel = (result, plugin) => result?.plugin?.title || result?.plugin?.name || plugin?.name || plugin;
|
|
31
|
+
// MCP OAuth sign-in methods the runtime must implement (no silent fallback).
|
|
32
|
+
const mcpOAuth =
|
|
33
|
+
(name) =>
|
|
34
|
+
(...args) => {
|
|
35
|
+
if (typeof runtime[name] !== 'function') throw new Error('MCP sign-in is unavailable');
|
|
36
|
+
return runtime[name](...args);
|
|
37
|
+
};
|
|
31
38
|
|
|
32
39
|
return {
|
|
33
40
|
mcpStatus: () => {
|
|
@@ -55,6 +62,19 @@ export function createSessionExtensionsApi(bag) {
|
|
|
55
62
|
(name) => runtime.removeMcpServer?.(name),
|
|
56
63
|
(_status, name) => [`mcp removed: ${name}`]
|
|
57
64
|
),
|
|
65
|
+
// Explicit OAuth sign-in: no command lock, the flow runs on the server's
|
|
66
|
+
// own connect lane and the caller polls its status. The caller (TUI app)
|
|
67
|
+
// owns the sign-in completion notice; the store never posts one.
|
|
68
|
+
beginMcpOAuthLogin: async (name, options) => {
|
|
69
|
+
const result = await mcpOAuth('beginMcpOAuthLogin')(name, options);
|
|
70
|
+
if (result?.state === 'pending') pushNotice(`mcp sign-in started: ${name}`, 'info');
|
|
71
|
+
return result;
|
|
72
|
+
},
|
|
73
|
+
getMcpOAuthLoginStatus: mcpOAuth('getMcpOAuthLoginStatus'),
|
|
74
|
+
cancelMcpOAuthLogin: mcpOAuth('cancelMcpOAuthLogin'),
|
|
75
|
+
completeMcpOAuthLogin: mcpOAuth('completeMcpOAuthLogin'),
|
|
76
|
+
signOutMcpServer: lockedChange(mcpOAuth('signOutMcpServer'), (_status, name) => [`mcp signed out: ${name}`]),
|
|
77
|
+
probeMcpServerAuth: mcpOAuth('probeMcpServerAuth'),
|
|
58
78
|
setMcpServerEnabled: async (name, enabled) => {
|
|
59
79
|
// No global commandBusy: the runtime adopts config synchronously and
|
|
60
80
|
// serializes the heavy connect/close/recreate per server name, so rapid
|
|
@@ -70,6 +90,8 @@ export function createSessionExtensionsApi(bag) {
|
|
|
70
90
|
const row = status?.servers?.find((s) => s.name === name);
|
|
71
91
|
if (enabled && row && (row.status === 'failed' || row.error)) {
|
|
72
92
|
pushNotice(`mcp enable failed: ${name}${row.error ? ` — ${row.error}` : ''}`, 'error');
|
|
93
|
+
} else if (enabled && row?.authRequired) {
|
|
94
|
+
pushNotice(`mcp enabled: ${name} — sign-in required`, 'warn');
|
|
73
95
|
} else {
|
|
74
96
|
pushNotice(`mcp ${enabled ? 'enabled' : 'disabled'}: ${name}`, 'info');
|
|
75
97
|
}
|
|
@@ -38,8 +38,8 @@ export function createSessionIntegrationsApi(bag, { oauthFlows }) {
|
|
|
38
38
|
getQuotaHistory: async (options = {}) => {
|
|
39
39
|
return await runtime.getQuotaHistory?.(options);
|
|
40
40
|
},
|
|
41
|
-
getSessionUsage: async () => {
|
|
42
|
-
return await runtime.getSessionUsage?.();
|
|
41
|
+
getSessionUsage: async (options = {}) => {
|
|
42
|
+
return await runtime.getSessionUsage?.(options);
|
|
43
43
|
},
|
|
44
44
|
consumeCodexRateLimitResetCredit: async (options = {}) => {
|
|
45
45
|
// Desktop capability parity: without this delegation the session runtime
|
|
@@ -52,6 +52,12 @@ export function createSessionIntegrationsApi(bag, { oauthFlows }) {
|
|
|
52
52
|
getSessionReviewDiff: async () => {
|
|
53
53
|
return (await runtime.getSessionReviewDiff?.()) ?? { supported: false, files: [], patch: '' };
|
|
54
54
|
},
|
|
55
|
+
getSessionReviewFilePatch: async (file, oldPath) => {
|
|
56
|
+
return (await runtime.getSessionReviewFilePatch?.(file, oldPath)) ?? { supported: false, patch: '' };
|
|
57
|
+
},
|
|
58
|
+
getTurnReviewFilePatch: async (file) => {
|
|
59
|
+
return (await runtime.getTurnReviewFilePatch?.(file)) ?? { supported: false, patch: '' };
|
|
60
|
+
},
|
|
55
61
|
revertTurnReview: async (checkpointId) => {
|
|
56
62
|
return await requireRuntimeMethod('revertTurnReview', 'Turn review revert is unavailable')(checkpointId);
|
|
57
63
|
},
|
|
@@ -78,6 +84,13 @@ export function createSessionIntegrationsApi(bag, { oauthFlows }) {
|
|
|
78
84
|
revision
|
|
79
85
|
);
|
|
80
86
|
},
|
|
87
|
+
clearSessionChangeHistory: async () => {
|
|
88
|
+
// A queued or running prompt/command may still be about to record changes.
|
|
89
|
+
if (getState().busy || getState().commandBusy) {
|
|
90
|
+
throw new Error('Change history cannot be deleted while this session is running a turn');
|
|
91
|
+
}
|
|
92
|
+
return await requireRuntimeMethod('clearSessionChangeHistory', 'Change history deletion is unavailable')();
|
|
93
|
+
},
|
|
81
94
|
getOnboardingStatus: () => {
|
|
82
95
|
return runtime.getOnboardingStatus?.() || { completed: true, workflowRoutes: {} };
|
|
83
96
|
},
|
|
@@ -133,6 +146,7 @@ export function createSessionIntegrationsApi(bag, { oauthFlows }) {
|
|
|
133
146
|
return result;
|
|
134
147
|
},
|
|
135
148
|
testCustomProvider: (input) => runtime.testCustomProvider(input),
|
|
149
|
+
checkCustomProviderKeyEnv: (name) => runtime.checkCustomProviderKeyEnv(name),
|
|
136
150
|
discoverCustomProviderModels: (input) => runtime.discoverCustomProviderModels(input),
|
|
137
151
|
saveOpenCodeGoUsageAuth: async (opts) => {
|
|
138
152
|
await runtime.saveOpenCodeGoUsageAuth(opts);
|
|
@@ -8,6 +8,7 @@ import { createSessionResetActions } from './lifecycle/session-reset.mjs';
|
|
|
8
8
|
import { createInheritanceActions } from './lifecycle/inheritance.mjs';
|
|
9
9
|
import { createResumeAction } from './lifecycle/resume.mjs';
|
|
10
10
|
import { createDisposeAction } from './lifecycle/dispose.mjs';
|
|
11
|
+
import { publishModelSwitch } from './routes.mjs';
|
|
11
12
|
|
|
12
13
|
export function createSessionLifecycleApi(bag, { restoreTranscriptItems, oauthFlows }) {
|
|
13
14
|
const { runtime, pushNotice, removeNotice, setProgressHint, finishToolApproval } = bag;
|
|
@@ -55,7 +56,8 @@ export function createSessionLifecycleApi(bag, { restoreTranscriptItems, oauthFl
|
|
|
55
56
|
id,
|
|
56
57
|
approved,
|
|
57
58
|
decision?.reason || (approved ? 'approved by user' : 'denied by user'),
|
|
58
|
-
typeof decision?.device === 'string' ? decision.device : ''
|
|
59
|
+
typeof decision?.device === 'string' ? decision.device : '',
|
|
60
|
+
decision?.answers
|
|
59
61
|
);
|
|
60
62
|
},
|
|
61
63
|
pushNotice,
|
|
@@ -85,9 +87,12 @@ export function createSessionLifecycleApi(bag, { restoreTranscriptItems, oauthFl
|
|
|
85
87
|
bag.supersedeQuotaResume?.(sessionId);
|
|
86
88
|
bag.set({ commandBusy: true });
|
|
87
89
|
try {
|
|
88
|
-
await runtime.continueSessionInModel(sessionId, route);
|
|
90
|
+
const result = await runtime.continueSessionInModel(sessionId, route);
|
|
89
91
|
bag.set({ ...bag.routeState(), stats: { ...bag.getState().stats } });
|
|
90
92
|
bag.syncContextStats?.({ allowEstimated: true });
|
|
93
|
+
// The same live divider as a picker switch; IPC and remote callers
|
|
94
|
+
// see it through the published snapshot.
|
|
95
|
+
publishModelSwitch(bag, result?.modelSwitch);
|
|
91
96
|
return true;
|
|
92
97
|
} finally {
|
|
93
98
|
bag.set({ commandBusy: false });
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
* the serialized optimistic setRoute, web-search route, workflows, agent
|
|
4
4
|
* definitions, output style and orchestration mode.
|
|
5
5
|
*/
|
|
6
|
+
import { modelSwitchItem } from '../../../runtime/agent/orchestrator/session/transcript-restore/restore.mjs';
|
|
7
|
+
import { selectedModel, switchesSessionModel } from '../../../session-runtime/model-route/model-switch-target.mjs';
|
|
8
|
+
import { latestQuotaFailure } from '../quota-resume.mjs';
|
|
6
9
|
import { createApiHelpers } from './shared.mjs';
|
|
7
10
|
|
|
8
11
|
// Optimistic route preview: the requested provider/model/effort/fast are
|
|
@@ -47,6 +50,12 @@ function optimisticRoutePatch(requested = {}, current = {}) {
|
|
|
47
50
|
return patch;
|
|
48
51
|
}
|
|
49
52
|
|
|
53
|
+
/** The live divider of an in-place model switch (restored from message meta
|
|
54
|
+
* after a reload); every switch path publishes it the same way. */
|
|
55
|
+
export function publishModelSwitch(bag, modelSwitch) {
|
|
56
|
+
if (modelSwitch) bag.pushItem(modelSwitchItem(bag.nextId(), modelSwitch));
|
|
57
|
+
}
|
|
58
|
+
|
|
50
59
|
export function createSessionRouteApi(bag) {
|
|
51
60
|
const {
|
|
52
61
|
runtime,
|
|
@@ -68,32 +77,84 @@ export function createSessionRouteApi(bag) {
|
|
|
68
77
|
let routeWrite = null;
|
|
69
78
|
let routeSequence = 0;
|
|
70
79
|
|
|
80
|
+
// A preset selector previews as the preset's model, never as its id.
|
|
81
|
+
const previewedRequest = (routeOpts) => {
|
|
82
|
+
if (routeOpts.provider || !routeOpts.model) return routeOpts;
|
|
83
|
+
const target = selectedModel(runtime, routeOpts, '', '');
|
|
84
|
+
return target.provider ? { ...routeOpts, ...target } : routeOpts;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Auto-compact on model change (default on): compact on the CURRENT model,
|
|
88
|
+
// whose cache and window still hold the history, before the switch. A model
|
|
89
|
+
// stopped on its quota cannot run it; the next turn's auto-compaction on the
|
|
90
|
+
// new model fits the history instead. A failure never blocks the switch.
|
|
91
|
+
const compactBeforeModelSwitch = async () => {
|
|
92
|
+
if (runtime.getCompactionSettings?.()?.onModelChange === false) return;
|
|
93
|
+
if (latestQuotaFailure(getState().items)) return;
|
|
94
|
+
if (typeof bag.compactBeforeModelSwitch !== 'function') return;
|
|
95
|
+
set({
|
|
96
|
+
commandStatus: { active: true, verb: 'Compacting conversation', startedAt: Date.now(), mode: 'compacting' },
|
|
97
|
+
});
|
|
98
|
+
flushEmitImmediate();
|
|
99
|
+
try {
|
|
100
|
+
await bag.compactBeforeModelSwitch();
|
|
101
|
+
} catch {
|
|
102
|
+
/* the switch goes ahead; next-turn auto-compaction fits the window */
|
|
103
|
+
} finally {
|
|
104
|
+
set({ commandStatus: null });
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
71
108
|
const setRoute = async (opts) => {
|
|
72
109
|
if (getState().commandBusy && !routeWrite) return false;
|
|
110
|
+
const routeOpts = opts && typeof opts === 'object' ? opts : {};
|
|
111
|
+
// Every user model choice on this surface (composer picker, /model,
|
|
112
|
+
// presets, the TUI picker) switches the conversation itself in place.
|
|
113
|
+
const switchesModel = switchesSessionModel(runtime, routeOpts);
|
|
114
|
+
// A running turn keeps the route it started on.
|
|
115
|
+
if (switchesModel && getState().busy) {
|
|
116
|
+
throw new Error('The model cannot change while a response is running. Try again when it finishes.');
|
|
117
|
+
}
|
|
73
118
|
// Any route change supersedes waiting for the old route's quota reset.
|
|
74
119
|
bag.supersedeQuotaResume?.(getState().sessionId);
|
|
75
120
|
const token = ++routeSequence;
|
|
76
121
|
const previousWrite = routeWrite;
|
|
77
|
-
const
|
|
78
|
-
const preview = optimisticRoutePatch(routeOpts, getState());
|
|
122
|
+
const preview = optimisticRoutePatch(previewedRequest(routeOpts), getState());
|
|
79
123
|
// Preview immediately, serialize persistence without dropping a later
|
|
80
124
|
// click. Earlier completions cannot replace the newest visible choice.
|
|
81
|
-
|
|
125
|
+
// A model switch previews once its pre-compaction (which republishes the
|
|
126
|
+
// current route) is done.
|
|
127
|
+
set({ commandBusy: true, ...(switchesModel ? {} : preview || {}) });
|
|
82
128
|
flushEmitImmediate();
|
|
83
129
|
const write = (async () => {
|
|
84
130
|
if (previousWrite) await previousWrite.catch(() => {});
|
|
85
131
|
const previousRoute = routeState();
|
|
86
132
|
try {
|
|
87
|
-
// Explicit addressing
|
|
88
|
-
//
|
|
133
|
+
// Explicit addressing applies the route to this session: an empty
|
|
134
|
+
// one is initialized in place. Either way an established
|
|
135
|
+
// conversation follows the user's choice in place.
|
|
89
136
|
const applyToCurrentSession = routeOpts.applyToCurrentSession === true;
|
|
90
137
|
const keepMainModel = routeOpts.keepMainModel === true;
|
|
91
138
|
const { applyToCurrentSession: _drop, keepMainModel: _keep, ...nextRoute } = routeOpts;
|
|
92
|
-
|
|
139
|
+
if (switchesModel) {
|
|
140
|
+
// The destination must be accepted before the history is compacted.
|
|
141
|
+
await runtime.setRoute(nextRoute, { validateOnly: true });
|
|
142
|
+
await compactBeforeModelSwitch();
|
|
143
|
+
if (token === routeSequence && preview) {
|
|
144
|
+
set(preview);
|
|
145
|
+
flushEmitImmediate();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const resolvedRoute = await runtime.setRoute(nextRoute, {
|
|
149
|
+
applyToCurrentSession,
|
|
150
|
+
keepMainModel,
|
|
151
|
+
switchEstablished: true,
|
|
152
|
+
});
|
|
93
153
|
if (token === routeSequence) {
|
|
94
|
-
if (applyToCurrentSession) syncContextStats({ allowEstimated: true });
|
|
154
|
+
if (applyToCurrentSession || resolvedRoute?.modelSwitch) syncContextStats({ allowEstimated: true });
|
|
95
155
|
publishRoute();
|
|
96
156
|
}
|
|
157
|
+
publishModelSwitch(bag, resolvedRoute?.modelSwitch);
|
|
97
158
|
return resolvedRoute;
|
|
98
159
|
} catch (error) {
|
|
99
160
|
if (token === routeSequence && preview) {
|
|
@@ -116,6 +177,9 @@ export function createSessionRouteApi(bag) {
|
|
|
116
177
|
if (routeWrite === write) routeWrite = null;
|
|
117
178
|
}
|
|
118
179
|
};
|
|
180
|
+
// The settings surface's setModel (/model, presets) is the same user
|
|
181
|
+
// model choice and runs through this one path.
|
|
182
|
+
bag.setSessionRoute = setRoute;
|
|
119
183
|
|
|
120
184
|
const setWebSearchRoute = async (opts) => {
|
|
121
185
|
if (getState().commandBusy) return null;
|
|
@@ -28,20 +28,11 @@ export function createSessionSettingsApi(bag) {
|
|
|
28
28
|
const lockedRuntimeCall = (call) => withCommandLock(async (...args) => await call(...args));
|
|
29
29
|
|
|
30
30
|
return {
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
setModel: withCommandLock(
|
|
37
|
-
async (m) => {
|
|
38
|
-
bag.supersedeQuotaResume?.(getState().sessionId);
|
|
39
|
-
await runtime.setRoute({ model: m });
|
|
40
|
-
publishRoute();
|
|
41
|
-
return true;
|
|
42
|
-
},
|
|
43
|
-
{ busyResult: false, onRelease: flushEmitImmediate }
|
|
44
|
-
),
|
|
31
|
+
// A model selector (/model, a preset) is the user's model choice like any
|
|
32
|
+
// picker selection: the route surface switches an established
|
|
33
|
+
// conversation in place (pre-compaction, busy refusal, divider). False
|
|
34
|
+
// while another command holds the lock.
|
|
35
|
+
setModel: async (m) => (await bag.setSessionRoute({ model: m })) !== false,
|
|
45
36
|
setEffort: withCommandLock(
|
|
46
37
|
async (value) => {
|
|
47
38
|
await runtime.setEffort(value);
|
|
@@ -115,6 +106,12 @@ export function createSessionSettingsApi(bag) {
|
|
|
115
106
|
deferStatsRefresh();
|
|
116
107
|
return next;
|
|
117
108
|
}),
|
|
109
|
+
getSessionTitleSettings: () => {
|
|
110
|
+
return runtime.getSessionTitleSettings?.() || { aiSessionTitles: true };
|
|
111
|
+
},
|
|
112
|
+
setAiSessionTitles: withCommandLock(async (enabled) => {
|
|
113
|
+
return await runtime.setAiSessionTitles?.(enabled);
|
|
114
|
+
}),
|
|
118
115
|
getToolModuleSettings: () => {
|
|
119
116
|
return (
|
|
120
117
|
runtime.getToolModuleSettings?.() || {
|
|
@@ -33,6 +33,7 @@ export function createSessionApi(bag) {
|
|
|
33
33
|
autoClear: await read(api.getAutoClear),
|
|
34
34
|
compaction: await read(api.getCompactionSettings),
|
|
35
35
|
recap: await read(api.getRecapSettings),
|
|
36
|
+
sessionTitles: await read(api.getSessionTitleSettings),
|
|
36
37
|
toolModules: await read(api.getToolModuleSettings),
|
|
37
38
|
channels: await read(api.getChannelSettings, { includeStatus: false }),
|
|
38
39
|
systemShell: await read(api.getSystemShell),
|
|
@@ -248,6 +248,12 @@ export function createDrainLoop(
|
|
|
248
248
|
while (pending.length > 0) {
|
|
249
249
|
if (flags.drainEpoch !== drainEpoch) return;
|
|
250
250
|
if (admission() !== 'open') return;
|
|
251
|
+
// Admission is rechecked before every batch: a command that took the
|
|
252
|
+
// lock while the previous turn settled (an in-place model switch and
|
|
253
|
+
// its pre-compaction, a reset) runs before the next turn starts. The
|
|
254
|
+
// finally below re-enters drain(), which waits on the same gate, and
|
|
255
|
+
// the commandBusy release re-kicks the queue.
|
|
256
|
+
if (flags.autoClearRunning || getState().commandBusy) return;
|
|
251
257
|
// Drain one priority/mode bucket at a time (unified command queue):
|
|
252
258
|
// prompt steering stays editable and task notifications stay
|
|
253
259
|
// non-editable but model-visible.
|
|
@@ -267,7 +273,7 @@ export function createDrainLoop(
|
|
|
267
273
|
// after a long idle is compacted first; the wake runs regardless.
|
|
268
274
|
if (autoClearBeforeWake && batch.every((entry) => COMPLETION_WAKE_MODES.has(entry.mode))) {
|
|
269
275
|
await autoClearBeforeWake();
|
|
270
|
-
if (flags.drainEpoch !== drainEpoch || admission() !== 'open') {
|
|
276
|
+
if (flags.drainEpoch !== drainEpoch || admission() !== 'open' || getState().commandBusy) {
|
|
271
277
|
queue.requeueEntriesFront(batch);
|
|
272
278
|
return;
|
|
273
279
|
}
|
|
@@ -5,8 +5,12 @@
|
|
|
5
5
|
// prompt, so a continuation prompt or a merged batch never removes rows.
|
|
6
6
|
const TURN_CHROME_KINDS = new Set(['user', 'turndone', 'notice']);
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
// An in-place model switch made after the stop (the quota "switch model"
|
|
9
|
+
// path) is not the failed turn's output and outlives its rewind.
|
|
10
|
+
const isModelSwitchDivider = (item) => item?.kind === 'statusdone' && item.status === 'model-switched';
|
|
11
|
+
|
|
12
|
+
/** The items with the trailing failed, output-less turn removed (a later
|
|
13
|
+
* model switch divider kept), or null when nothing qualifies. */
|
|
10
14
|
export function rewoundFailedTurnItems(items, text) {
|
|
11
15
|
const list = Array.isArray(items) ? items : [];
|
|
12
16
|
const resubmitted = String(text || '').trim();
|
|
@@ -16,6 +20,8 @@ export function rewoundFailedTurnItems(items, text) {
|
|
|
16
20
|
const tail = list.slice(start + 1);
|
|
17
21
|
const failed = tail.some((item) => item?.kind === 'turndone' && String(item.status || '').toLowerCase() === 'failed');
|
|
18
22
|
if (!failed) return null;
|
|
19
|
-
if (tail.some((item) => !TURN_CHROME_KINDS.has(String(item?.kind || ''))))
|
|
20
|
-
|
|
23
|
+
if (tail.some((item) => !TURN_CHROME_KINDS.has(String(item?.kind || '')) && !isModelSwitchDivider(item))) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
return [...list.slice(0, start), ...tail.filter(isModelSwitchDivider)];
|
|
21
27
|
}
|
|
@@ -12,17 +12,20 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
|
|
|
12
12
|
|
|
13
13
|
function normalizeToolApprovalRequest(input = {}, id = nextId()) {
|
|
14
14
|
const now = Date.now();
|
|
15
|
+
const requestTimeoutMs =
|
|
16
|
+
Number.isFinite(Number(input?.timeoutMs)) && Number(input.timeoutMs) > 0 ? Number(input.timeoutMs) : timeoutMs;
|
|
15
17
|
return {
|
|
16
18
|
id,
|
|
17
19
|
name: String(input?.name || input?.tool_name || 'tool'),
|
|
20
|
+
kind: typeof input?.kind === 'string' ? input.kind : '',
|
|
18
21
|
args: input?.args ?? input?.tool_input ?? null,
|
|
19
22
|
cwd: input?.cwd || null,
|
|
20
23
|
sessionId: input?.sessionId || input?.session_id || null,
|
|
21
24
|
toolCallId: input?.toolCallId || input?.tool_use_id || null,
|
|
22
25
|
reason: String(input?.reason || input?.message || 'approval requested by hook').trim(),
|
|
23
26
|
requestedAt: now,
|
|
24
|
-
timeoutMs,
|
|
25
|
-
expiresAt: now +
|
|
27
|
+
timeoutMs: requestTimeoutMs,
|
|
28
|
+
expiresAt: now + requestTimeoutMs,
|
|
26
29
|
};
|
|
27
30
|
}
|
|
28
31
|
// Every request expires from ITS OWN requestedAt, queued or active. Arming
|
|
@@ -39,10 +42,10 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
|
|
|
39
42
|
// Settle one entry: drop its timeout, then hand the waiter its answer. The
|
|
40
43
|
// resolve stays guarded — a waiter whose caller already went away must never
|
|
41
44
|
// take the rest of the queue down with it.
|
|
42
|
-
function settleToolApproval(entry, approved, reason) {
|
|
45
|
+
function settleToolApproval(entry, approved, reason, answers) {
|
|
43
46
|
if (entry?.timer) clearTimeout(entry.timer);
|
|
44
47
|
try {
|
|
45
|
-
entry.resolve({ approved, reason });
|
|
48
|
+
entry.resolve(answers === undefined ? { approved, reason } : { approved, reason, answers });
|
|
46
49
|
} catch {}
|
|
47
50
|
}
|
|
48
51
|
function presentNextToolApproval() {
|
|
@@ -56,7 +59,7 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
|
|
|
56
59
|
armToolApprovalTimeout(entry);
|
|
57
60
|
set({ toolApproval: entry.request });
|
|
58
61
|
}
|
|
59
|
-
function finishToolApproval(id, approved, reason = '', device = '') {
|
|
62
|
+
function finishToolApproval(id, approved, reason = '', device = '', answers = undefined) {
|
|
60
63
|
const targetId = String(id || '');
|
|
61
64
|
if (activeToolApproval && activeToolApproval.id === targetId) {
|
|
62
65
|
const entry = activeToolApproval;
|
|
@@ -67,14 +70,14 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
|
|
|
67
70
|
? { id: targetId, approved: approved === true, device: String(device), at: Date.now() }
|
|
68
71
|
: null;
|
|
69
72
|
set({ toolApproval: null, toolApprovalResult });
|
|
70
|
-
settleToolApproval(entry, approved === true, String(reason || ''));
|
|
73
|
+
settleToolApproval(entry, approved === true, String(reason || ''), answers);
|
|
71
74
|
presentNextToolApproval();
|
|
72
75
|
return true;
|
|
73
76
|
}
|
|
74
77
|
const index = toolApprovalQueue.findIndex((entry) => entry.id === targetId);
|
|
75
78
|
if (index >= 0) {
|
|
76
79
|
const [entry] = toolApprovalQueue.splice(index, 1);
|
|
77
|
-
settleToolApproval(entry, approved === true, String(reason || ''));
|
|
80
|
+
settleToolApproval(entry, approved === true, String(reason || ''), answers);
|
|
78
81
|
return true;
|
|
79
82
|
}
|
|
80
83
|
return false;
|