mixdog 1.2.2 → 1.2.4
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 +6 -4
- package/scripts/lib/gate-scheduler.mjs +29 -11
- package/scripts/probe-provider-catalog.mjs +31 -0
- package/scripts/provider-pingpong-live.mjs +599 -0
- package/scripts/session-sweep.mjs +5 -25
- package/src/agents/advisor/AGENT.md +1 -1
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/maintainer/AGENT.md +1 -1
- package/src/agents/maintainer/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +2 -4
- package/src/agents/security/AGENT.md +1 -2
- package/src/agents/writer/AGENT.md +2 -3
- package/src/defaults/shipped-history.json +11 -1
- package/src/defaults/skills/image/SKILL.md +21 -23
- 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 +20 -15
- package/src/output-styles/common.md +11 -10
- package/src/rules/agent/AGENT.md +6 -4
- package/src/rules/lead/LEAD.md +7 -9
- package/src/rules/shared/45-destructive.md +4 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
- 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/child-tree.mjs +101 -23
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +9 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +31 -15
- 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 +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +131 -9
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +125 -8
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +12 -62
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +117 -41
- 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 +39 -5
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
- package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
- package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +42 -11
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +109 -6
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +17 -4
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -2
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +73 -7
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +75 -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 +29 -5
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +36 -13
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +101 -11
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +19 -14
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +371 -41
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +97 -49
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +81 -10
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +35 -8
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
- 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 +253 -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 +392 -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/request-compression.mjs +86 -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 +50 -22
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +133 -21
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -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 +92 -16
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -13
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +133 -62
- 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 +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +39 -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 +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +84 -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 +155 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +40 -24
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
- 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 +183 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +87 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +17 -2
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
- 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 +28 -5
- 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 +4 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +72 -24
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +50 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -19
- 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 -36
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
- 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.mjs +18 -9
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +181 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +78 -70
- package/src/runtime/agent/orchestrator/providers/openrouter.mjs +74 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +150 -10
- package/src/runtime/agent/orchestrator/providers/registry.mjs +13 -2
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +7 -1
- 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 +164 -0
- package/src/runtime/agent/orchestrator/providers/wire-route.mjs +522 -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 +195 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +104 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +24 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
- package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
- package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
- 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 +16 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
- 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 +178 -71
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +102 -12
- package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
- package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +5 -11
- package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +16 -93
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +148 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
- 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/conversation-import/claude.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +89 -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 -27
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +24 -10
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +135 -0
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +31 -4
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +67 -20
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +10 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -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 +29 -5
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +147 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +7 -5
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +23 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +54 -13
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
- 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 +11 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +22 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
- package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +231 -16
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
- package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +47 -17
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +26 -4
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +36 -35
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +4 -10
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +17 -1
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/side-question.mjs +197 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +22 -15
- package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
- package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
- package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +44 -37
- package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -21
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
- package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +136 -196
- package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +53 -115
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
- package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
- package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +17 -10
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
- package/src/runtime/agent/orchestrator/session/store.mjs +22 -19
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +12 -12
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +38 -14
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
- 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 +79 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
- package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
- package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
- package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +218 -20
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
- package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
- package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
- package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +247 -49
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
- 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/code-graph-prewarm-worker.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
- package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
- 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/attachments/store.d.mts +9 -0
- package/src/runtime/attachments/store.mjs +80 -9
- package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
- package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
- package/src/runtime/computer-bridge/action-schema.mjs +219 -196
- package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
- package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
- package/src/runtime/effort-judge/judge-client.mjs +21 -4
- package/src/runtime/effort-judge/judge-worker.mjs +4 -1
- package/src/runtime/github/tool.mjs +208 -17
- package/src/runtime/media/adapters/codex-image.mjs +140 -21
- package/src/runtime/media/catalog.mjs +4 -4
- package/src/runtime/media/chatgpt-usage.mjs +55 -0
- package/src/runtime/media/defaults.mjs +37 -0
- package/src/runtime/media/jobs.mjs +12 -2
- package/src/runtime/media/lanes.mjs +12 -0
- package/src/runtime/media/tool-defs.mjs +15 -4
- package/src/runtime/media/tool.mjs +41 -12
- package/src/runtime/media/upstream-error.mjs +72 -6
- 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/ingest/transcript-rows.mjs +1 -0
- package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
- package/src/runtime/memory/lib/pg/process.mjs +36 -33
- package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +112 -4
- 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 +1 -1
- package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/html-browser.mjs +18 -8
- package/src/runtime/office/authoring/html-document-author.mjs +2 -0
- package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-measure.mjs +3 -1
- package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +3 -1
- 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 +94 -0
- package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
- package/src/runtime/office/index.mjs +29 -0
- package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
- 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/session-search/session-search-ingest.mjs +1 -1
- package/src/runtime/shared/agent-reap-state.mjs +13 -0
- package/src/runtime/shared/atomic-file.d.mts +1 -1
- package/src/runtime/shared/background-tasks.mjs +6 -1
- package/src/runtime/shared/bounded-file-read.mjs +13 -0
- package/src/runtime/shared/bounded-line-diff.mjs +191 -0
- package/src/runtime/shared/browser-launch.mjs +15 -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 +48 -4
- package/src/runtime/shared/file-lock.mjs +6 -5
- 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 +1 -2
- package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
- 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/loopback-listener.mjs +9 -0
- package/src/runtime/shared/model-route-chain.d.mts +8 -0
- package/src/runtime/shared/model-route-chain.mjs +48 -0
- package/src/runtime/shared/model-route-fallback.mjs +22 -0
- package/src/runtime/shared/pid-liveness.mjs +12 -0
- package/src/runtime/shared/provider-api-key.mjs +8 -0
- package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
- package/src/runtime/shared/quiet-progress.d.mts +35 -0
- package/src/runtime/shared/quiet-progress.mjs +101 -0
- package/src/runtime/shared/quota-resume-store.mjs +32 -1
- package/src/runtime/shared/read-row-numbers.mjs +44 -0
- package/src/runtime/shared/remote-intent.mjs +2 -42
- package/src/runtime/shared/review-diff.mjs +52 -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 +121 -0
- package/src/runtime/shared/statusline/statusline-segments.mjs +52 -6
- package/src/runtime/shared/tool-card-model/card-header.mjs +7 -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-budget.mjs +2 -0
- 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 +22 -1
- package/src/runtime/shared/tool-status.mjs +3 -2
- package/src/runtime/shared/tool-surface.mjs +20 -6
- package/src/runtime/shared/tool-work-units.mjs +54 -11
- package/src/runtime/shared/transcript-metadata.mjs +49 -1
- package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
- package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
- package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
- package/src/runtime/shared/transcript-writer.mjs +24 -6
- package/src/runtime/shared/turn-changes.mjs +269 -100
- package/src/runtime/shared/turn-review-reply.mjs +8 -39
- package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
- package/src/runtime/shared/turn-snapshot.mjs +865 -683
- package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
- package/src/runtime/shared/user-data-guard.mjs +262 -49
- package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
- package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
- package/src/runtime/shared/worktrees/carry.mjs +533 -0
- package/src/runtime/shared/worktrees/contract.mjs +60 -0
- package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
- package/src/runtime/shared/worktrees/file-recovery.mjs +84 -0
- package/src/runtime/shared/worktrees/git-head.mjs +214 -0
- package/src/runtime/shared/worktrees/git.mjs +8 -3
- package/src/runtime/shared/worktrees/include.mjs +125 -7
- package/src/runtime/shared/worktrees/lock.mjs +1 -1
- package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
- package/src/runtime/shared/worktrees/manager.mjs +525 -31
- package/src/runtime/shared/worktrees/merge.mjs +31 -21
- package/src/runtime/shared/worktrees/owner.mjs +2 -1
- package/src/runtime/shared/worktrees/paths.d.mts +6 -0
- package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
- package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
- package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
- package/src/runtime/terminal-bridge/client.mjs +57 -20
- 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 +20 -6
- package/src/session-runtime/boot/config.mjs +2 -0
- package/src/session-runtime/boot/facade.mjs +4 -0
- package/src/session-runtime/boot/infrastructure.mjs +6 -1
- package/src/session-runtime/boot/session.mjs +3 -3
- package/src/session-runtime/boot/tools.mjs +7 -1
- package/src/session-runtime/conversation-import/service.mjs +1 -1
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
- package/src/session-runtime/goal-facade-api.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +91 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +15 -5
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +137 -26
- package/src/session-runtime/internal-tool-executor.mjs +8 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +187 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
- package/src/session-runtime/lifecycle/session-catalog.mjs +25 -18
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +36 -48
- package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
- package/src/session-runtime/lifecycle/shared.mjs +5 -6
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
- package/src/session-runtime/lifecycle/teardown.mjs +70 -14
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/connect.mjs +17 -5
- package/src/session-runtime/media-api.mjs +8 -0
- package/src/session-runtime/model-route/route-ownership.mjs +60 -0
- package/src/session-runtime/model-route/route-persist.mjs +3 -2
- package/src/session-runtime/model-route/set-route.mjs +116 -36
- package/src/session-runtime/model-route/web-search-route.mjs +7 -2
- package/src/session-runtime/model-route-api.mjs +4 -2
- package/src/session-runtime/native-web-search/routes.mjs +37 -24
- package/src/session-runtime/native-web-search-usage.mjs +51 -0
- package/src/session-runtime/native-web-search.mjs +19 -9
- 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-auth/setup.mjs +4 -0
- package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
- package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
- package/src/session-runtime/provider-models.mjs +1 -0
- package/src/session-runtime/provider-usage.mjs +4 -0
- package/src/session-runtime/resource-scope-decorate.mjs +10 -3
- package/src/session-runtime/route-resolution.mjs +3 -1
- package/src/session-runtime/runtime-core.mjs +4 -0
- package/src/session-runtime/runtime-facade.mjs +6 -0
- package/src/session-runtime/runtime-review-api.mjs +8 -2
- package/src/session-runtime/services/agent-task-status.mjs +2 -0
- package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
- package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
- package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
- package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
- package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
- 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/lead-rows.mjs +3 -4
- package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
- package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +82 -13
- package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
- package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
- package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
- package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +18 -10
- package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
- package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
- package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
- package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
- package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -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 +74 -15
- package/src/session-runtime/services/agent-tool.mjs +7 -0
- package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -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 +158 -15
- package/src/session-runtime/session-create/session-options.mjs +7 -5
- package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
- package/src/session-runtime/session-transcript-purge.mjs +32 -0
- package/src/session-runtime/session-transcript.mjs +4 -5
- package/src/session-runtime/session-turn-api.mjs +17 -14
- package/src/session-runtime/settings-builtin-tools-api.mjs +18 -6
- package/src/session-runtime/setup-tool/executor.mjs +57 -9
- package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
- package/src/session-runtime/setup-tool/settings-contract.mjs +18 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +25 -4
- package/src/session-runtime/skills-api.mjs +3 -5
- package/src/session-runtime/tool-policy-refresh.mjs +83 -32
- package/src/session-runtime/tool-surface.mjs +5 -1
- package/src/session-runtime/turn/agent-ops.mjs +49 -2
- 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 +19 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +7 -1
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +12 -3
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +18 -2
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +26 -45
- package/src/session-runtime/usage-stats-api.mjs +46 -11
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
- package/src/session-runtime/workspace/admission-gate.mjs +44 -15
- package/src/session-runtime/workspace/project-branches.mjs +35 -41
- package/src/session-runtime/workspace/transition-steps.mjs +215 -116
- package/src/session-runtime/workspace/transitions.mjs +428 -73
- package/src/standalone/channel-transport.mjs +3 -4
- package/src/standalone/daemon-agent-control.mjs +9 -1
- package/src/standalone/daemon-desktop-runtime.mjs +32 -1
- 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 +49 -0
- package/src/standalone/daemon-session-control.mjs +88 -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 +25 -3
- package/src/standalone/daemon-telemetry.mjs +19 -0
- package/src/standalone/daemon.mjs +63 -1
- package/src/standalone/desktop-service-registry.mjs +5 -0
- package/src/standalone/local-session-runtime.mjs +80 -30
- 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 +3 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
- package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
- package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
- package/src/standalone/session-service/agent-tree.mjs +28 -2
- package/src/standalone/session-service/entries/session-loads.mjs +16 -5
- package/src/standalone/session-service/entries.mjs +1 -0
- package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
- package/src/standalone/session-service/quota-resume.mjs +28 -13
- package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
- package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
- package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
- package/src/standalone/session-service-api.mjs +6 -1
- package/src/standalone/session-state-patch.d.mts +2 -1
- package/src/standalone/session-state-patch.mjs +41 -1
- package/src/standalone/session-tool-output.mjs +82 -0
- 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 +2 -1
- package/src/tui/app/btw-controller.mjs +118 -0
- package/src/tui/app/create-app-pickers.mjs +2 -0
- package/src/tui/app/provider-setup/provider-items.mjs +8 -0
- package/src/tui/app/provider-setup-picker.mjs +15 -3
- 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 +19 -3
- package/src/tui/app/slash-dispatch/session-commands.mjs +68 -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/Spinner.jsx +4 -0
- package/src/tui/components/SpinnerByline.jsx +21 -2
- package/src/tui/components/question-panel-model.mjs +156 -0
- package/src/tui/components/status-line/local-line.mjs +10 -2
- package/src/tui/dist/index.mjs +2897 -1722
- package/src/tui/session/active-tool-summary.mjs +1 -1
- package/src/tui/session/context-state.mjs +4 -5
- package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
- package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
- package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
- package/src/tui/session/quota-resume.mjs +140 -61
- package/src/tui/session/session-api/commands.mjs +14 -10
- package/src/tui/session/session-api/controls.mjs +14 -2
- package/src/tui/session/session-api/integrations.mjs +9 -2
- package/src/tui/session/session-api/lifecycle/dispose.mjs +3 -9
- package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
- package/src/tui/session/session-api/lifecycle.mjs +14 -11
- package/src/tui/session/session-api/media.mjs +2 -0
- package/src/tui/session/session-api/routes.mjs +81 -57
- package/src/tui/session/session-api/settings.mjs +9 -3
- package/src/tui/session/session-api/worktree.mjs +3 -2
- package/src/tui/session/session-api.mjs +1 -0
- package/src/tui/session/session-flow/auto-clear.mjs +1 -3
- package/src/tui/session/session-flow/drain.mjs +6 -4
- package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
- package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
- package/src/tui/session/session-flow/queue.mjs +1 -1
- package/src/tui/session/tool-approval.mjs +20 -8
- package/src/tui/session/transcript-spill.mjs +14 -7
- package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
- package/src/tui/session/tui-steering-persist.mjs +3 -5
- package/src/tui/session/turn-quiet.mjs +53 -0
- package/src/tui/session/turn-stream.mjs +179 -32
- package/src/tui/session/turn.mjs +50 -36
- package/src/tui/session/worktree-setup-notice.mjs +38 -0
- package/src/tui/spinner-meta.mjs +10 -0
- package/src/tui/spinner-verbs.mjs +3 -0
- package/src/ui/statusline.mjs +13 -3
- package/src/workflows/default/WORKFLOW.md +3 -1
- package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
- package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
- package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -246
- package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
- package/src/session-runtime/turn/share-ops.mjs +0 -77
- package/src/tui/session/cross-surface-share.mjs +0 -406
- package/src/tui/session/live-share/delta.mjs +0 -153
- package/src/tui/session/live-share/mirror.mjs +0 -106
- package/src/tui/session/live-share/owner.mjs +0 -254
- package/src/tui/session/live-share/retry.mjs +0 -54
- package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
- package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
- package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
- package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
- package/src/tui/session/live-share/viewer.mjs +0 -99
- package/src/tui/session/live-share/wire.mjs +0 -44
- package/src/tui/session/live-share.mjs +0 -154
- package/src/tui/session/shared-dir-watch.mjs +0 -69
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
// standby fast path, the spawn-burst gate around process creation, and the
|
|
3
3
|
// delayed live foreground record once the command has reached a shell.
|
|
4
4
|
import { acquire as acquireChildSpawnSlot } from '../../../../shared/child-spawn-gate.mjs';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
killShellJob,
|
|
7
|
+
publishForegroundShellRecord,
|
|
8
|
+
trackForegroundShellJob,
|
|
9
|
+
waitForShellJob,
|
|
10
|
+
} from '../builtin/shell-jobs.mjs';
|
|
6
11
|
import {
|
|
7
12
|
nativeSpawnFileCaptureReady,
|
|
8
13
|
nativeSpawnSupportsStdinPipe,
|
|
@@ -13,6 +18,11 @@ import { _maybeEncodePowerShellCommand } from '../shell-powershell.mjs';
|
|
|
13
18
|
import { spawnShellWithRetry as _spawnShellWithRetry } from './shell-spawn-retry.mjs';
|
|
14
19
|
import { STANDBY_ARGS, takeWarmShellStandby } from './shell-warm-standby.mjs';
|
|
15
20
|
import { SHELL_OUTPUT_DISK_CAP } from '../shell-exec-output.mjs';
|
|
21
|
+
import { admitWorkspaceActivity, tryAdmitWorkspaceActivity } from '../../../../shared/worktrees/activity-gate.mjs';
|
|
22
|
+
import { worktreeError } from '../../../../shared/worktrees/contract.mjs';
|
|
23
|
+
import { capturePreKill, registerForegroundOwnedTree, treeKillForceSettle } from './shell-run-state.mjs';
|
|
24
|
+
import { releaseAdmissionOnConfirmedTermination } from './shell-run-settle.mjs';
|
|
25
|
+
import { killAfterSnapshot } from './shell-descendants.mjs';
|
|
16
26
|
|
|
17
27
|
// Foreground visibility threshold. Every shell readout (CLI statusline,
|
|
18
28
|
// desktop island) scans the on-disk job records, so a foreground command is
|
|
@@ -148,7 +158,7 @@ async function gatedSpawn({
|
|
|
148
158
|
* the moment the command reached it. Throws on spawn failure; the caller
|
|
149
159
|
* turns that into the spawn-failed result.
|
|
150
160
|
*/
|
|
151
|
-
|
|
161
|
+
async function spawnAdmittedShellChild({
|
|
152
162
|
run,
|
|
153
163
|
shell,
|
|
154
164
|
shellArg,
|
|
@@ -163,6 +173,9 @@ export async function spawnShellChild({
|
|
|
163
173
|
clientHostPid,
|
|
164
174
|
}) {
|
|
165
175
|
const { useDirectArgv, spawnCommand, argv } = shapeArgv({ directArgv, shellArg, shellArgs, command, execScript });
|
|
176
|
+
// Set before any child exists: a startup that fails after the child is
|
|
177
|
+
// created still publishes a visible record and an owned termination hold.
|
|
178
|
+
run.foregroundRecordInput = { command, cwd, ownerSessionId, clientHostPid };
|
|
166
179
|
const onChildError = (err) => {
|
|
167
180
|
run.spawnError = run.spawnError || err;
|
|
168
181
|
run.failurePhase = 'tool';
|
|
@@ -209,10 +222,22 @@ export async function spawnShellChild({
|
|
|
209
222
|
clientHostPid,
|
|
210
223
|
}));
|
|
211
224
|
run.child = spawned.child;
|
|
225
|
+
registerForegroundOwnedTree(run, ownerSessionId);
|
|
226
|
+
const parentAdmission = run.workspaceAdmission;
|
|
227
|
+
const childAdmission = tryAdmitWorkspaceActivity(ownerSessionId || run.foregroundRecordId, cwd || process.cwd(), {
|
|
228
|
+
pid: Number(run.child.pid) || process.pid,
|
|
229
|
+
kind: 'command',
|
|
230
|
+
});
|
|
231
|
+
if (!childAdmission) throw worktreeError('WORKTREE_BUSY_JOBS', 'The command workspace changed during spawn.');
|
|
232
|
+
run.workspaceAdmission = () => {
|
|
233
|
+
childAdmission();
|
|
234
|
+
parentAdmission();
|
|
235
|
+
};
|
|
212
236
|
spawned.attachErrorHandler(onChildError);
|
|
213
237
|
// Feed the script only after the error handler is attached; server
|
|
214
238
|
// messages cannot be processed before this synchronous block yields.
|
|
215
239
|
// Single atomic write+EOF, as for the standby.
|
|
240
|
+
abortSignal?.throwIfAborted();
|
|
216
241
|
if (standby) standby.feed(spawnCommand, cwd);
|
|
217
242
|
else if (stdinScript !== null) spawned.child.writeStdin(stdinScript, { close: true });
|
|
218
243
|
// The command has now reached a shell. This is the start moment every
|
|
@@ -224,15 +249,56 @@ export async function spawnShellChild({
|
|
|
224
249
|
run.foregroundRecordTimer = null;
|
|
225
250
|
if (run.settled || run.autoBackgrounded || !run.child?.pid) return;
|
|
226
251
|
run.foregroundRecordPublished = true;
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
252
|
+
try {
|
|
253
|
+
publishForegroundShellRecord({
|
|
254
|
+
...run.foregroundRecordInput,
|
|
255
|
+
jobId: run.foregroundRecordId,
|
|
256
|
+
pid: run.child.pid,
|
|
257
|
+
startedAtMs: run.commandStartedAtMs,
|
|
258
|
+
});
|
|
259
|
+
} catch (error) {
|
|
260
|
+
run.spawnError = error;
|
|
261
|
+
run.failureReason = 'workspace publication failed';
|
|
262
|
+
treeKillForceSettle(run, 'workspace-publication-failed');
|
|
263
|
+
}
|
|
236
264
|
}, FOREGROUND_RECORD_DELAY_MS);
|
|
237
265
|
run.foregroundRecordTimer.unref?.();
|
|
238
266
|
}
|
|
267
|
+
|
|
268
|
+
/** Admission precedes both native process creation and feeding a warm shell. */
|
|
269
|
+
export async function spawnShellChild(input) {
|
|
270
|
+
input.run.workspaceAdmission = await admitWorkspaceActivity(
|
|
271
|
+
input.ownerSessionId || input.run.foregroundRecordId,
|
|
272
|
+
input.cwd || process.cwd(),
|
|
273
|
+
input.abortSignal,
|
|
274
|
+
{ kind: 'command' }
|
|
275
|
+
);
|
|
276
|
+
try {
|
|
277
|
+
input.abortSignal?.throwIfAborted();
|
|
278
|
+
return await spawnAdmittedShellChild(input);
|
|
279
|
+
} catch (error) {
|
|
280
|
+
if (!input.run.child) {
|
|
281
|
+
input.run.workspaceAdmission();
|
|
282
|
+
input.run.workspaceAdmission = null;
|
|
283
|
+
} else {
|
|
284
|
+
try {
|
|
285
|
+
// Identities first: the kill may break the parent chain.
|
|
286
|
+
// Bounded: the kill is sent even if the snapshot hangs or fails.
|
|
287
|
+
await killAfterSnapshot(capturePreKill(input.run), () => killShellJob(input.run.foregroundRecordId));
|
|
288
|
+
const detail = await waitForShellJob(input.run.foregroundRecordId);
|
|
289
|
+
if (!detail || !['completed', 'failed', 'cancelled'].includes(detail.nativeStatus)) {
|
|
290
|
+
throw new Error('The child termination could not be confirmed; workspace admission is retained.');
|
|
291
|
+
}
|
|
292
|
+
input.run.workspaceAdmission?.();
|
|
293
|
+
input.run.workspaceAdmission = null;
|
|
294
|
+
} catch (cleanupError) {
|
|
295
|
+
input.run.killUnconfirmed = true;
|
|
296
|
+
// No settle will ever run for this run; the reservation is released
|
|
297
|
+
// only once the child has exited and its descendants are gone.
|
|
298
|
+
releaseAdmissionOnConfirmedTermination(input.run);
|
|
299
|
+
throw new AggregateError([error, cleanupError], 'Shell startup failed and workspace cleanup remains blocked.');
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
@@ -4,8 +4,37 @@
|
|
|
4
4
|
// tree-kill. The spawn, settle and auto-background phases live in their own
|
|
5
5
|
// modules and read/write this one record.
|
|
6
6
|
import { randomUUID } from 'node:crypto';
|
|
7
|
-
import { retireForegroundShellRecord } from '../builtin/shell-jobs.mjs';
|
|
7
|
+
import { publishForegroundShellRecord, retireForegroundShellRecord } from '../builtin/shell-jobs.mjs';
|
|
8
8
|
import { ShellTextDecoder, TaskOutput, treeKill } from '../shell-exec-output.mjs';
|
|
9
|
+
import { createProcessTreeTracker, killAfterSnapshot } from './shell-descendants.mjs';
|
|
10
|
+
import { registerOwnedShellTree } from './owned-shell-trees.mjs';
|
|
11
|
+
|
|
12
|
+
/** One pre-kill identity read of the run's tree (every kill path shares it):
|
|
13
|
+
* resolves true once the capture is complete, false when it failed. */
|
|
14
|
+
export function capturePreKill(run) {
|
|
15
|
+
run.terminationTracker = run.terminationTracker || createProcessTreeTracker({ pid: run.child.pid });
|
|
16
|
+
const rootExited = run.child.exitCode != null || run.child.signalCode != null;
|
|
17
|
+
return run.terminationTracker.capture({ rootExited }).catch(() => false);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Session close cancels every tree its session owns. For a foreground run
|
|
21
|
+
* that cancel must snapshot the identities first, exactly like the run's own
|
|
22
|
+
* kill, and mark the run owner-cancelled so its settle completes on confirmed
|
|
23
|
+
* termination instead of on the root's exit. */
|
|
24
|
+
export function registerForegroundOwnedTree(run, ownerSessionId) {
|
|
25
|
+
if (!ownerSessionId) return;
|
|
26
|
+
run.ownedTree = {
|
|
27
|
+
ownerSessionId,
|
|
28
|
+
prepareKill: () => {
|
|
29
|
+
if (run.settled || run.autoBackgrounded || !run.child?.pid) return true;
|
|
30
|
+
run.killed = true;
|
|
31
|
+
run.ownerCancelled = true;
|
|
32
|
+
run.killCause = run.killCause || 'session-close';
|
|
33
|
+
return run.terminationTracker?.complete === true || capturePreKill(run);
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
registerOwnedShellTree(run.foregroundRecordId, run.ownedTree);
|
|
37
|
+
}
|
|
9
38
|
|
|
10
39
|
// Treekill + exit confirmation. treeKill alone leaves settle() pending on
|
|
11
40
|
// 'close'/'exit'; on Windows a taskkill miss or a grandchild holding stdio
|
|
@@ -85,6 +114,12 @@ export function createShellRun({ abortSignal, resolve, jobId = null }) {
|
|
|
85
114
|
foregroundRecordId: jobId || `job_${Date.now()}_${randomUUID().slice(0, 6)}`,
|
|
86
115
|
foregroundRecordTimer: null,
|
|
87
116
|
foregroundRecordPublished: false,
|
|
117
|
+
// Command/cwd/owner the live record is published with.
|
|
118
|
+
foregroundRecordInput: null,
|
|
119
|
+
// Process identities captured before a kill, and the stop() of the
|
|
120
|
+
// observation loop that holds the workspace until they are gone.
|
|
121
|
+
terminationTracker: null,
|
|
122
|
+
stopTerminationWatch: null,
|
|
88
123
|
};
|
|
89
124
|
}
|
|
90
125
|
|
|
@@ -149,6 +184,49 @@ export function clearForegroundRecord(run) {
|
|
|
149
184
|
// Runtime of the COMMAND (see startMs).
|
|
150
185
|
export const elapsedSinceStart = (run) => Math.max(0, Date.now() - (run.commandStartedAtMs || run.startMs));
|
|
151
186
|
|
|
187
|
+
/** The command's result is reported, but its processes are not confirmed
|
|
188
|
+
* gone: the live record stays — now marked unconfirmed — until the
|
|
189
|
+
* termination watch retires it. */
|
|
190
|
+
export function keepTerminationUnconfirmedRecord(run) {
|
|
191
|
+
if (run.foregroundRecordTimer) {
|
|
192
|
+
clearTimeout(run.foregroundRecordTimer);
|
|
193
|
+
run.foregroundRecordTimer = null;
|
|
194
|
+
}
|
|
195
|
+
if (!run.foregroundRecordInput || !run.child?.pid) return;
|
|
196
|
+
try {
|
|
197
|
+
publishForegroundShellRecord({
|
|
198
|
+
...run.foregroundRecordInput,
|
|
199
|
+
jobId: run.foregroundRecordId,
|
|
200
|
+
pid: run.child.pid,
|
|
201
|
+
startedAtMs: run.commandStartedAtMs,
|
|
202
|
+
terminationUnconfirmed: true,
|
|
203
|
+
});
|
|
204
|
+
run.foregroundRecordPublished = true;
|
|
205
|
+
} catch {
|
|
206
|
+
/* the record is presentation; the workspace admission stays held */
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Record the tree's identities while the root is still alive, THEN kill: once
|
|
211
|
+
// an intermediate dies its children's parent links dangle and a snapshot taken
|
|
212
|
+
// afterwards can no longer find them.
|
|
213
|
+
// The kill waits for the snapshot at most PROCESS_TABLE_READ_BOUND_MS and is
|
|
214
|
+
// sent whether the snapshot succeeded, failed or is still pending (a late
|
|
215
|
+
// snapshot is still absorbed; a missing one leaves the outcome unknown, so the
|
|
216
|
+
// workspace stays held under the observation loop). The confirmation deadline
|
|
217
|
+
// starts once the kill is actually issued.
|
|
218
|
+
function snapshotThenKill(run, afterKill) {
|
|
219
|
+
if (!run.child?.pid) {
|
|
220
|
+
treeKill(run.child);
|
|
221
|
+
afterKill();
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
void killAfterSnapshot(capturePreKill(run), () => {
|
|
225
|
+
treeKill(run.child);
|
|
226
|
+
afterKill();
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
152
230
|
export function treeKillForceSettle(run, cause) {
|
|
153
231
|
run.killed = true;
|
|
154
232
|
run.killCause = run.killCause || cause || 'runtime-guard';
|
|
@@ -161,8 +239,7 @@ export function treeKillForceSettle(run, cause) {
|
|
|
161
239
|
if (run.child?.exitCode != null || run.child?.signalCode != null) return;
|
|
162
240
|
attempts += 1;
|
|
163
241
|
if (attempts < KILL_CONFIRM_ATTEMPTS) {
|
|
164
|
-
|
|
165
|
-
armConfirmation();
|
|
242
|
+
snapshotThenKill(run, armConfirmation);
|
|
166
243
|
return;
|
|
167
244
|
}
|
|
168
245
|
run.partialOutput = true;
|
|
@@ -172,6 +249,5 @@ export function treeKillForceSettle(run, cause) {
|
|
|
172
249
|
}, KILL_CONFIRM_INTERVAL_MS);
|
|
173
250
|
if (deadline.unref) deadline.unref();
|
|
174
251
|
};
|
|
175
|
-
|
|
176
|
-
armConfirmation();
|
|
252
|
+
snapshotThenKill(run, armConfirmation);
|
|
177
253
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// UI-diff side channel: a committed apply_patch (or edit-tool write) records
|
|
2
2
|
// a turn-review change entry and a per-call diff the desktop/TUI tool cards
|
|
3
3
|
// pick up. Display only — never affects edit semantics.
|
|
4
|
-
import {
|
|
4
|
+
import { createLineDiffBudget, lineDiffHunks, unifiedHunksBody } from '../../../../shared/bounded-line-diff.mjs';
|
|
5
5
|
import { boundReviewPatch } from '../../../../shared/review-diff.mjs';
|
|
6
|
+
import { decodeText } from '../../../../shared/turn-changes.mjs';
|
|
6
7
|
import { recordTurnDiffChanges } from '../../../../shared/turn-snapshot.mjs';
|
|
7
8
|
import { pathKey, resolveV4AEntryPath } from './paths.mjs';
|
|
8
9
|
import { patchHeaderPathForResolved } from './read-redirects.mjs';
|
|
@@ -38,31 +39,21 @@ function headerPath(value) {
|
|
|
38
39
|
.replace(/\\/g, '/');
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
const DIFF_TIMEOUT_MS = 100;
|
|
42
|
-
|
|
43
|
-
const utf8 = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
|
|
44
|
-
|
|
45
42
|
function isOmitted(value) {
|
|
46
43
|
return Boolean(value) && typeof value === 'object' && !(value instanceof Uint8Array) && value.omitted === true;
|
|
47
44
|
}
|
|
48
45
|
|
|
49
|
-
// Text of one side: '' for an absent file, null when it is not UTF-8
|
|
46
|
+
// Text of one side: '' for an absent file, null when it is binary (not UTF-8
|
|
47
|
+
// or holding a NUL byte) — the same rule as the turn review's tracker diffs.
|
|
50
48
|
function sideText(value) {
|
|
51
|
-
if (value == null) return
|
|
52
|
-
if (typeof value === 'string') return value;
|
|
53
|
-
if (value instanceof Uint8Array) {
|
|
54
|
-
try {
|
|
55
|
-
return utf8.decode(value);
|
|
56
|
-
} catch {
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
49
|
+
if (value == null || typeof value === 'string' || value instanceof Uint8Array) return decodeText(value);
|
|
60
50
|
return null;
|
|
61
51
|
}
|
|
62
52
|
|
|
63
53
|
// One file's change, from the call's own before and after states: absent
|
|
64
54
|
// (null), bytes or text, or an omitted marker when the bytes were not kept.
|
|
65
|
-
|
|
55
|
+
// `budget` is the call's line-diff budget.
|
|
56
|
+
function renderCallChange({ displayPath, newDisplayPath, before, after }, budget) {
|
|
66
57
|
const oldName = headerPath(displayPath) || 'unknown file';
|
|
67
58
|
const newName = headerPath(newDisplayPath) || oldName;
|
|
68
59
|
const oldHeader = before == null ? '/dev/null' : `a/${oldName}`;
|
|
@@ -82,23 +73,46 @@ function renderCallChange({ displayPath, newDisplayPath, before, after }) {
|
|
|
82
73
|
return oldName === newName ? '' : `${head}similarity index 100%\nrename from ${oldName}\nrename to ${newName}\n`;
|
|
83
74
|
}
|
|
84
75
|
const rename = oldName === newName ? '' : `rename from ${oldName}\nrename to ${newName}\n`;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
76
|
+
const { hunks } = lineDiffHunks(oldText, newText, budget, [before ?? null, after ?? null]);
|
|
77
|
+
return `${head}${rename}${unifiedHunksBody(oldHeader, newHeader, hunks)}`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Added/deleted lines of one rendered change, counted in its hunks only.
|
|
81
|
+
function hunkLineCounts(patch) {
|
|
82
|
+
let additions = 0;
|
|
83
|
+
let deletions = 0;
|
|
84
|
+
let inHunk = false;
|
|
85
|
+
for (const line of patch.split('\n')) {
|
|
86
|
+
if (line.startsWith('@@')) inHunk = true;
|
|
87
|
+
else if (inHunk && line.startsWith('+')) additions += 1;
|
|
88
|
+
else if (inHunk && line.startsWith('-')) deletions += 1;
|
|
94
89
|
}
|
|
95
|
-
return
|
|
90
|
+
return { additions, deletions };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Each change with the line counts of its own unbounded diff (the turn review
|
|
94
|
+
// sums them per file), plus the call's whole diff, within the call's budget.
|
|
95
|
+
export function measureCallChanges(changes, budget = createLineDiffBudget()) {
|
|
96
|
+
const patches = (changes || []).map((change) => renderCallChange(change, budget));
|
|
97
|
+
return {
|
|
98
|
+
diff: patches.join(''),
|
|
99
|
+
changes: (changes || []).map((change, index) => ({ ...change, ...hunkLineCounts(patches[index]) })),
|
|
100
|
+
};
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
// A call's card shows the change that call made — its own before against its
|
|
99
104
|
// own after — never the turn's running total for the same files.
|
|
100
105
|
export function callUiDiff(changes) {
|
|
101
|
-
return (changes
|
|
106
|
+
return measureCallChanges(changes).diff;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Fold the call's measured changes into the turn review and publish its card
|
|
110
|
+
// diff. Both share one line-diff budget: the call is one operation.
|
|
111
|
+
function recordCallChanges(callId, sessionId, changes) {
|
|
112
|
+
const budget = createLineDiffBudget();
|
|
113
|
+
const measured = measureCallChanges(changes, budget);
|
|
114
|
+
recordTurnDiffChanges(sessionId, measured.changes, budget);
|
|
115
|
+
registerApplyPatchUiDiff(callId, measured.diff);
|
|
102
116
|
}
|
|
103
117
|
|
|
104
118
|
// Edit-tool UI diff: a successful single-file str-replace edit records the
|
|
@@ -108,21 +122,42 @@ export function callUiDiff(changes) {
|
|
|
108
122
|
export function registerEditToolUiDiff({ callId, sessionId, basePath, fullPath, before, after }) {
|
|
109
123
|
if (!callId || !sessionId || typeof fullPath !== 'string') return;
|
|
110
124
|
try {
|
|
111
|
-
|
|
112
|
-
{
|
|
113
|
-
path: fullPath,
|
|
114
|
-
displayPath: patchHeaderPathForResolved(basePath || '', fullPath),
|
|
115
|
-
before: before ?? null,
|
|
116
|
-
after: after ?? null,
|
|
117
|
-
},
|
|
118
|
-
];
|
|
119
|
-
recordTurnDiffChanges(sessionId, changes);
|
|
120
|
-
registerApplyPatchUiDiff(callId, callUiDiff(changes));
|
|
125
|
+
recordCallChanges(callId, sessionId, [toolFileChange(basePath, { fullPath, before, after })]);
|
|
121
126
|
} catch {
|
|
122
127
|
// best-effort display channel
|
|
123
128
|
}
|
|
124
129
|
}
|
|
125
130
|
|
|
131
|
+
function toolFileChange(basePath, { fullPath, before, after }) {
|
|
132
|
+
return {
|
|
133
|
+
path: fullPath,
|
|
134
|
+
displayPath: patchHeaderPathForResolved(basePath || '', fullPath),
|
|
135
|
+
before: before ?? null,
|
|
136
|
+
after: after ?? null,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Writes of a tool without a per-call card (tidy, office): each change
|
|
141
|
+
// `{ fullPath, before, after }` (null = absent, bytes, or an omitted marker)
|
|
142
|
+
// joins the turn review with its own line counts, like an edit-tool write.
|
|
143
|
+
// Side channel only — never affects the tool result.
|
|
144
|
+
export function recordToolFileChanges({ sessionId, basePath, changes }) {
|
|
145
|
+
if (!sessionId || !changes?.length) return;
|
|
146
|
+
try {
|
|
147
|
+
const budget = createLineDiffBudget();
|
|
148
|
+
recordTurnDiffChanges(
|
|
149
|
+
sessionId,
|
|
150
|
+
measureCallChanges(
|
|
151
|
+
changes.map((change) => toolFileChange(basePath, change)),
|
|
152
|
+
budget
|
|
153
|
+
).changes,
|
|
154
|
+
budget
|
|
155
|
+
);
|
|
156
|
+
} catch {
|
|
157
|
+
// best-effort review channel
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
126
161
|
// Review content of one snapshot: null when absent, the bytes when captured,
|
|
127
162
|
// and an explicit omitted marker (never empty bytes) when they were not.
|
|
128
163
|
function snapshotContent(snapshot) {
|
|
@@ -184,8 +219,7 @@ export function registerCommittedPatchUiDiff({
|
|
|
184
219
|
after: snapshotContent(after),
|
|
185
220
|
});
|
|
186
221
|
}
|
|
187
|
-
|
|
188
|
-
registerApplyPatchUiDiff(callId, callUiDiff(changes));
|
|
222
|
+
recordCallChanges(callId, sessionId, changes);
|
|
189
223
|
} catch {
|
|
190
224
|
// Review collection is a side channel and must never affect committed
|
|
191
225
|
// apply_patch success/failure semantics.
|
|
@@ -105,8 +105,25 @@ export function formatToolStartProgress(name, args = {}) {
|
|
|
105
105
|
// ── host_input / cwd ─────────────────────────────────────────────
|
|
106
106
|
case 'inject_input':
|
|
107
107
|
return 'injecting input';
|
|
108
|
-
case 'cwd':
|
|
108
|
+
case 'cwd': // legacy: old transcripts
|
|
109
109
|
return a.action === 'set' ? 'setting cwd' : 'resolving cwd';
|
|
110
|
+
case 'session':
|
|
111
|
+
switch (a.action) {
|
|
112
|
+
case 'set-project':
|
|
113
|
+
return 'setting project';
|
|
114
|
+
case 'rename':
|
|
115
|
+
return 'renaming session';
|
|
116
|
+
case 'compact':
|
|
117
|
+
return 'scheduling compaction';
|
|
118
|
+
case 'fork':
|
|
119
|
+
return 'forking into a new session';
|
|
120
|
+
case 'favorite':
|
|
121
|
+
return a.value === false ? 'unfavoriting session' : 'favoriting session';
|
|
122
|
+
case 'archive':
|
|
123
|
+
return a.value === false ? 'unarchiving session' : 'archiving session';
|
|
124
|
+
default:
|
|
125
|
+
return 'checking session';
|
|
126
|
+
}
|
|
110
127
|
|
|
111
128
|
default:
|
|
112
129
|
return `running ${name}`;
|
|
@@ -27,9 +27,9 @@ export {
|
|
|
27
27
|
} from './shell-powershell.mjs';
|
|
28
28
|
export { stripAnsi, ExecResult } from './shell-exec-output.mjs';
|
|
29
29
|
|
|
30
|
-
async function _execPolicyBlockMessage(command) {
|
|
30
|
+
async function _execPolicyBlockMessage(command, elevationApproved = false) {
|
|
31
31
|
const { checkExecPolicyMessage } = await import('./bash-policy-scan.mjs');
|
|
32
|
-
return checkExecPolicyMessage(command);
|
|
32
|
+
return checkExecPolicyMessage(command, { elevationApproved });
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
// Admission-wait ceiling. Without it a saturated shell lane (all leases held
|
|
@@ -233,7 +233,7 @@ const failedResult = (run, stderr, failureReason) =>
|
|
|
233
233
|
// Admission lease, policy preflight, then the spawn. Resolves the run with a
|
|
234
234
|
// tool-phase failure and returns false when the command never reaches a shell.
|
|
235
235
|
async function admitAndSpawn(run, params, { admissionWaitMs, onSaturated }) {
|
|
236
|
-
const { admission, command, ownerSessionId, abortSignal } = params;
|
|
236
|
+
const { admission, command, ownerSessionId, abortSignal, elevationApproved } = params;
|
|
237
237
|
try {
|
|
238
238
|
run.resourceLease = await acquireShellLeaseBounded(admission, {
|
|
239
239
|
abortSignal,
|
|
@@ -241,7 +241,7 @@ async function admitAndSpawn(run, params, { admissionWaitMs, onSaturated }) {
|
|
|
241
241
|
label: `[task_id: ${run.foregroundRecordId}] ${String(command || '').slice(0, 120)}`,
|
|
242
242
|
ownerKey: ownerSessionId,
|
|
243
243
|
});
|
|
244
|
-
const policyErr = await _execPolicyBlockMessage(command);
|
|
244
|
+
const policyErr = await _execPolicyBlockMessage(command, elevationApproved === true);
|
|
245
245
|
if (policyErr) {
|
|
246
246
|
await releaseResourceLease(run);
|
|
247
247
|
run.resolveResult(failedResult(run, policyErr, 'preflight failed'));
|
|
@@ -544,6 +544,8 @@ export function execShellCommand(options) {
|
|
|
544
544
|
// hands the script to the shell out-of-band — see the POSIX env+eval path in
|
|
545
545
|
// bash-tool.mjs, which keeps the command body out of the child's argv.
|
|
546
546
|
execScript = null,
|
|
547
|
+
// The user approved this call's elevation 'ask' decision (runtime-set).
|
|
548
|
+
elevationApproved = false,
|
|
547
549
|
} = options;
|
|
548
550
|
return new Promise(async (resolve) => {
|
|
549
551
|
const run = createShellRun({ abortSignal, resolve, jobId });
|
|
@@ -565,6 +567,7 @@ export function execShellCommand(options) {
|
|
|
565
567
|
abortSignal,
|
|
566
568
|
directArgv,
|
|
567
569
|
execScript,
|
|
570
|
+
elevationApproved,
|
|
568
571
|
ownerSessionId,
|
|
569
572
|
clientHostPid,
|
|
570
573
|
},
|
|
@@ -2,7 +2,7 @@ import { extractHeredocBodies, extractShellCInner, stripQuotedAndHeredoc } from
|
|
|
2
2
|
import { extractPowerShellCommandInner } from './shell-powershell.mjs';
|
|
3
3
|
import { decodePowerShellEncodedCommand, isBlockedCommand, WRAPPER_NAMES } from './shell-policy.mjs';
|
|
4
4
|
|
|
5
|
-
/** @typedef {'allow'|'deny'} ExecPolicyDecision */
|
|
5
|
+
/** @typedef {'allow'|'ask'|'deny'} ExecPolicyDecision */
|
|
6
6
|
|
|
7
7
|
const EXEC_POLICY_DENY_PATTERNS = [
|
|
8
8
|
/\b(curl|wget|fetch|Invoke-WebRequest|iwr)\b[^\n|&;]*\|[^\n|&;]*\b(sh|bash|zsh|dash|pwsh|powershell)(?:\.exe)?\b/i,
|
|
@@ -16,9 +16,28 @@ const EXEC_POLICY_DENY_PATTERNS = [
|
|
|
16
16
|
// lookahead instead of the previous bare `iex\s+`.
|
|
17
17
|
/\|\s*iex\b/i,
|
|
18
18
|
/\biex\s+[$("'@]/i,
|
|
19
|
-
/\bStart-Process\b[^\n]*\s-Verb\s+RunAs\b/i,
|
|
20
19
|
];
|
|
21
20
|
|
|
21
|
+
// Elevated launch: `Start-Process` (or its aliases `saps` / `start`) with
|
|
22
|
+
// `-Verb RunAs`. Not a hard deny — the user is asked (parity with Claude Code's
|
|
23
|
+
// "Command requests elevated privileges"). `-Verb` may be abbreviated to any
|
|
24
|
+
// prefix (`-v`, `-ve`, `-ver`) and take its value after a space or a colon.
|
|
25
|
+
// `Start-Process` matches anywhere (as the former deny rule did); the short
|
|
26
|
+
// aliases only at a command position so `npm start -v RunAs` stays allowed.
|
|
27
|
+
const ELEVATION_ASK_PATTERN =
|
|
28
|
+
/(?:\bStart-Process\b|(?:^|[;&|({=\n])\s*(?:&\s*)?(?:saps|start)(?![\w-]))[^\n]*?\s-v(?:e(?:rb?)?)?(?:\s*:\s*|\s+)RunAs\b/i;
|
|
29
|
+
const ELEVATION_ASK_REASON = 'Command requests elevated privileges';
|
|
30
|
+
|
|
31
|
+
// PowerShell spellings of the same token that the quote-stripping pass would
|
|
32
|
+
// otherwise hide or split: backtick line continuation, backtick-escaped
|
|
33
|
+
// letters (`-V`erb`), and a quoted `-Verb` value (`-Verb:'RunAs'`).
|
|
34
|
+
function _normalizeElevationSyntax(text) {
|
|
35
|
+
return String(text || '')
|
|
36
|
+
.replace(/`\r?\n/g, ' ')
|
|
37
|
+
.replace(/`([A-Za-z])/g, '$1')
|
|
38
|
+
.replace(/(\s-v\w*(?:\s*:\s*|\s+))(['"])\s*RunAs\s*\2/gi, '$1RunAs');
|
|
39
|
+
}
|
|
40
|
+
|
|
22
41
|
// Verbs with no non-destructive invocation. `dd` is deliberately ABSENT: the
|
|
23
42
|
// disk-destroying form (`of=/dev/<disk>`) is hard-blocked at every command
|
|
24
43
|
// position by shell-policy, while `dd if=/dev/zero of=file` is the ordinary
|
|
@@ -39,12 +58,44 @@ const EXEC_POLICY_DENY_COMMANDS = new Set([
|
|
|
39
58
|
'parted',
|
|
40
59
|
]);
|
|
41
60
|
|
|
42
|
-
const _POLICY_RANK = { allow: 0,
|
|
61
|
+
const _POLICY_RANK = { allow: 0, ask: 1, deny: 2 };
|
|
43
62
|
|
|
44
63
|
// EVERY command position, not just the first: a deny-listed verb after `&&`,
|
|
45
64
|
// `;`, `|` or a newline is still an execution request, and reading only
|
|
46
65
|
// segment 0 let `true && shutdown /s` through. Callers pass quote-stripped
|
|
47
66
|
// text, so prose inside a string ("graceful shutdown") never reaches here.
|
|
67
|
+
const _ELEVATION_WRAPPERS = new Set(['sudo', 'doas', 'pkexec', 'gsudo']);
|
|
68
|
+
const _bareName = (token) =>
|
|
69
|
+
token
|
|
70
|
+
.replace(/^.*[\\/]/, '')
|
|
71
|
+
.toLowerCase()
|
|
72
|
+
.replace(/\.(exe|cmd|bat|com)$/i, '');
|
|
73
|
+
|
|
74
|
+
// Returns the first privilege-escalation wrapper (sudo, doas, pkexec, gsudo,
|
|
75
|
+
// with or without path/extension) found at any command position, else null.
|
|
76
|
+
function _elevationWrapperAtPositions(command) {
|
|
77
|
+
for (const seg of String(command || '').split(/[;&|\n]+/)) {
|
|
78
|
+
const tokens = seg.trim().split(/\s+/).filter(Boolean);
|
|
79
|
+
let i = 0;
|
|
80
|
+
while (i < tokens.length) {
|
|
81
|
+
const t = tokens[i];
|
|
82
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(t)) {
|
|
83
|
+
i++;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const base = _bareName(t);
|
|
87
|
+
if (_ELEVATION_WRAPPERS.has(base)) return base;
|
|
88
|
+
if (WRAPPER_NAMES.has(base)) {
|
|
89
|
+
i++;
|
|
90
|
+
while (i < tokens.length && (/^[-+]/.test(tokens[i]) || /^\d+[smhd]?$/.test(tokens[i]))) i++;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
48
99
|
function _commandNamesAtPositions(command) {
|
|
49
100
|
const names = [];
|
|
50
101
|
for (const seg of String(command || '').split(/[;&|\n]+/)) {
|
|
@@ -56,7 +107,7 @@ function _commandNamesAtPositions(command) {
|
|
|
56
107
|
i++;
|
|
57
108
|
continue;
|
|
58
109
|
}
|
|
59
|
-
if (WRAPPER_NAMES.has(t
|
|
110
|
+
if (WRAPPER_NAMES.has(_bareName(t))) {
|
|
60
111
|
i++;
|
|
61
112
|
while (i < tokens.length && (/^[-+]/.test(tokens[i]) || /^\d+[smhd]?$/.test(tokens[i]))) i++;
|
|
62
113
|
continue;
|
|
@@ -74,14 +125,15 @@ function classifyExecPolicy(command) {
|
|
|
74
125
|
if (!text.trim()) return { decision: 'allow', reason: '' };
|
|
75
126
|
// Scan executable syntax, not quoted log/search text. Recursively preserve
|
|
76
127
|
// actual shell, PowerShell, heredoc, and encoded-command payload coverage.
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
...extractShellCInner(text)
|
|
80
|
-
...extractPowerShellCommandInner(text)
|
|
81
|
-
...extractHeredocBodies(text)
|
|
128
|
+
const rawTargets = [
|
|
129
|
+
text,
|
|
130
|
+
...extractShellCInner(text),
|
|
131
|
+
...extractPowerShellCommandInner(text),
|
|
132
|
+
...extractHeredocBodies(text),
|
|
82
133
|
];
|
|
83
134
|
const decodedPowerShell = decodePowerShellEncodedCommand(text);
|
|
84
|
-
if (decodedPowerShell)
|
|
135
|
+
if (decodedPowerShell) rawTargets.push(decodedPowerShell);
|
|
136
|
+
const executableTargets = rawTargets.map(stripQuotedAndHeredoc);
|
|
85
137
|
if (executableTargets.some((target) => isBlockedCommand(target))) {
|
|
86
138
|
return {
|
|
87
139
|
decision: 'deny',
|
|
@@ -115,6 +167,24 @@ function classifyExecPolicy(command) {
|
|
|
115
167
|
};
|
|
116
168
|
}
|
|
117
169
|
}
|
|
170
|
+
// Elevation asks only after every deny rule above has had its say.
|
|
171
|
+
for (const target of rawTargets) {
|
|
172
|
+
const hit = ELEVATION_ASK_PATTERN.exec(stripQuotedAndHeredoc(_normalizeElevationSyntax(target)));
|
|
173
|
+
if (hit) {
|
|
174
|
+
return {
|
|
175
|
+
decision: 'ask',
|
|
176
|
+
reason: ELEVATION_ASK_REASON,
|
|
177
|
+
rule: 'elevation',
|
|
178
|
+
match: hit[0].trim().slice(0, 80),
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
for (const target of executableTargets) {
|
|
183
|
+
const wrapper = _elevationWrapperAtPositions(target);
|
|
184
|
+
if (wrapper) {
|
|
185
|
+
return { decision: 'ask', reason: ELEVATION_ASK_REASON, rule: 'elevation', match: wrapper };
|
|
186
|
+
}
|
|
187
|
+
}
|
|
118
188
|
// Destructive-but-legitimate commands are NOT judged here. The caller
|
|
119
189
|
// computes that non-blocking warning once (getDedupedDestructiveWarnings)
|
|
120
190
|
// and prepends it to the result; deriving it again per scan target only
|
|
@@ -140,9 +210,15 @@ export function evaluateExecPolicyFromTargets(targets) {
|
|
|
140
210
|
return worst;
|
|
141
211
|
}
|
|
142
212
|
|
|
143
|
-
/** Pre-spawn block message
|
|
144
|
-
|
|
213
|
+
/** Pre-spawn block message. An 'ask' decision blocks unless the runtime
|
|
214
|
+
* already obtained the user's approval for this call (`elevationApproved`). */
|
|
215
|
+
export function formatExecPolicyBlockMessage(policyResult, { elevationApproved = false } = {}) {
|
|
145
216
|
const r = policyResult || { decision: 'allow' };
|
|
217
|
+
if (r.decision === 'ask') {
|
|
218
|
+
if (elevationApproved === true) return null;
|
|
219
|
+
const rule = r.rule ? ` [rule ${r.rule}${r.match ? `: "${r.match}"` : ''}]` : '';
|
|
220
|
+
return `Error: command requires user approval for elevation — ${r.reason || ELEVATION_ASK_REASON}${rule}; no approval was granted for this call`;
|
|
221
|
+
}
|
|
146
222
|
if (r.decision === 'deny') {
|
|
147
223
|
const rule = r.rule ? ` [rule ${r.rule}${r.match ? `: "${r.match}"` : ''}]` : '';
|
|
148
224
|
const alt = r.alternative ? `; instead: ${r.alternative}` : '';
|