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
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// The phase a provider timeout names on its `timeoutPhase` field. A provider
|
|
2
|
+
// stamps it where the timer that fired is known; retry policy and error
|
|
3
|
+
// presentation read it instead of matching the timeout's message text.
|
|
4
|
+
export const TIMEOUT_PHASE = Object.freeze({
|
|
5
|
+
// The response headers did not arrive in the first-byte window.
|
|
6
|
+
HEADERS: 'headers',
|
|
7
|
+
// The headers arrived, the first chunk did not.
|
|
8
|
+
FIRST_CHUNK: 'first-chunk',
|
|
9
|
+
// A stream that already produced output went silent.
|
|
10
|
+
IDLE: 'idle',
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
/** A timeout before the model produced anything: headers or first chunk. */
|
|
14
|
+
export function isFirstByteTimeout(err) {
|
|
15
|
+
const phase = err?.timeoutPhase;
|
|
16
|
+
return phase === TIMEOUT_PHASE.HEADERS || phase === TIMEOUT_PHASE.FIRST_CHUNK;
|
|
17
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type QuietWaitKind = 'provider' | 'thinking' | 'model' | 'tool' | 'slot' | 'cancel' | '';
|
|
2
|
+
|
|
3
|
+
export const MODEL_THINKING_STAGE: 'model_thinking';
|
|
4
|
+
export function awaitingModelResponse(liveness: unknown): boolean;
|
|
5
|
+
export function displayProgressStage(liveness: unknown): string | null;
|
|
6
|
+
|
|
7
|
+
export interface QuietProgress {
|
|
8
|
+
since: number;
|
|
9
|
+
wait: QuietWaitKind;
|
|
10
|
+
tool?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface QuietProgressParts {
|
|
14
|
+
quietMs: number;
|
|
15
|
+
minutes: number;
|
|
16
|
+
wait: QuietWaitKind;
|
|
17
|
+
tool: string;
|
|
18
|
+
escalated: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const QUIET_PROGRESS_CUE_MS: number;
|
|
22
|
+
export function lastProgressAt(liveness: unknown): number;
|
|
23
|
+
export function quietWaitKind(stage: unknown): QuietWaitKind;
|
|
24
|
+
export function quietProgress(options: {
|
|
25
|
+
progressAt: unknown;
|
|
26
|
+
stage: unknown;
|
|
27
|
+
tool?: unknown;
|
|
28
|
+
now?: number;
|
|
29
|
+
}): QuietProgress | null;
|
|
30
|
+
export function quietProgressParts(
|
|
31
|
+
quiet: { since?: unknown; wait?: unknown; tool?: unknown } | null | undefined,
|
|
32
|
+
now: number,
|
|
33
|
+
warnMs?: unknown
|
|
34
|
+
): QuietProgressParts | null;
|
|
35
|
+
export function quietProgressLabel(parts: QuietProgressParts | null): string;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// Quiet-time cue for a running turn: how long it has gone without progress
|
|
2
|
+
// the stall watchdog counts, and what it is waiting on. Display only — the
|
|
3
|
+
// watchdog's abort policy lives in stall-policy.mjs and is never read or
|
|
4
|
+
// changed here. Shared by the TUI spinner, the desktop live status line and
|
|
5
|
+
// the desktop agent rows, so every surface says the same thing.
|
|
6
|
+
|
|
7
|
+
/** A running turn with no counted progress for this long reads "quiet".
|
|
8
|
+
* Lenient on purpose: effort-mode models can think for minutes without a
|
|
9
|
+
* single semantic delta (stall-policy.mjs, the semantic-idle notes), so the
|
|
10
|
+
* cue stays neutral text; only the watchdog's own warn point escalates it. */
|
|
11
|
+
export const QUIET_PROGRESS_CUE_MS = 120_000;
|
|
12
|
+
|
|
13
|
+
/** The newest progress stamp of a runtime liveness entry or progress
|
|
14
|
+
* snapshot: the same signals the stall watchdog counts (stage changes,
|
|
15
|
+
* semantic stream deltas, tool starts and tool heartbeats, the turn start). */
|
|
16
|
+
export function lastProgressAt(liveness) {
|
|
17
|
+
if (!liveness || typeof liveness !== 'object') return 0;
|
|
18
|
+
return Math.max(
|
|
19
|
+
Number(liveness.lastProgressAt) || 0,
|
|
20
|
+
Number(liveness.lastStreamDeltaAt) || 0,
|
|
21
|
+
Number(liveness.toolStartedAt) || 0,
|
|
22
|
+
Number(liveness.askStartedAt) || 0
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** The stage a provider reports once its request is on the wire and the
|
|
27
|
+
* response headers are still pending. The runtime keeps the turn in
|
|
28
|
+
* `requesting` and records the send time (`requestSentAt`); the display stage
|
|
29
|
+
* below reads "model thinking" from that record. */
|
|
30
|
+
export const MODEL_THINKING_STAGE = 'model_thinking';
|
|
31
|
+
|
|
32
|
+
/** Request sent, response headers (transport) not yet received — read from
|
|
33
|
+
* a runtime liveness entry or progress snapshot. */
|
|
34
|
+
export function awaitingModelResponse(liveness) {
|
|
35
|
+
if (!liveness || typeof liveness !== 'object' || liveness.stage !== 'requesting') return false;
|
|
36
|
+
const sentAt = Number(liveness.requestSentAt) || 0;
|
|
37
|
+
return sentAt > 0 && !((Number(liveness.lastTransportAt) || 0) >= sentAt);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** The stage a surface shows: `model_thinking` while the request waits for
|
|
41
|
+
* its headers, otherwise the runtime stage. */
|
|
42
|
+
export function displayProgressStage(liveness) {
|
|
43
|
+
if (awaitingModelResponse(liveness)) return MODEL_THINKING_STAGE;
|
|
44
|
+
return typeof liveness?.stage === 'string' ? liveness.stage : null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const WAIT_BY_STAGE = {
|
|
48
|
+
connecting: 'provider',
|
|
49
|
+
requesting: 'provider',
|
|
50
|
+
[MODEL_THINKING_STAGE]: 'thinking',
|
|
51
|
+
streaming: 'model',
|
|
52
|
+
tool_running: 'tool',
|
|
53
|
+
resource_wait: 'slot',
|
|
54
|
+
cancelling: 'cancel',
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/** What a quiet turn waits on, from its runtime stage ('' when unknown). */
|
|
58
|
+
export function quietWaitKind(stage) {
|
|
59
|
+
return WAIT_BY_STAGE[String(stage || '')] || '';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** The quiet state of a running turn at `now`, or null while it is not
|
|
63
|
+
* quiet. `since` is the frozen progress stamp, so the value stays identical
|
|
64
|
+
* for the whole silence and publishing it costs one update per silence. */
|
|
65
|
+
export function quietProgress({ progressAt, stage, tool = null, now = Date.now() }) {
|
|
66
|
+
const since = Number(progressAt) || 0;
|
|
67
|
+
if (!since || now - since < QUIET_PROGRESS_CUE_MS) return null;
|
|
68
|
+
const wait = quietWaitKind(stage);
|
|
69
|
+
return { since, wait, ...(wait === 'tool' && tool ? { tool: String(tool) } : {}) };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Display parts of a quiet state at `now`: whole quiet minutes, and whether
|
|
73
|
+
* the silence reached the watchdog's warn point (`warnMs`, 0 = none). */
|
|
74
|
+
export function quietProgressParts(quiet, now, warnMs = 0) {
|
|
75
|
+
const since = Number(quiet?.since) || 0;
|
|
76
|
+
if (!since) return null;
|
|
77
|
+
const quietMs = Math.max(0, now - since);
|
|
78
|
+
if (quietMs < QUIET_PROGRESS_CUE_MS) return null;
|
|
79
|
+
return {
|
|
80
|
+
quietMs,
|
|
81
|
+
minutes: Math.floor(quietMs / 60_000),
|
|
82
|
+
wait: String(quiet.wait || ''),
|
|
83
|
+
tool: typeof quiet.tool === 'string' ? quiet.tool : '',
|
|
84
|
+
escalated: Number(warnMs) > 0 && quietMs >= Number(warnMs),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const WAIT_TEXT = {
|
|
89
|
+
provider: 'waiting on provider',
|
|
90
|
+
thinking: 'model thinking',
|
|
91
|
+
model: 'waiting on model',
|
|
92
|
+
slot: 'waiting for a slot',
|
|
93
|
+
cancel: 'stopping',
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/** The TUI's lowercase English cue: `quiet for 2m · waiting on provider`. */
|
|
97
|
+
export function quietProgressLabel(parts) {
|
|
98
|
+
if (!parts) return '';
|
|
99
|
+
const wait = parts.wait === 'tool' ? `running ${parts.tool || 'a tool'}` : WAIT_TEXT[parts.wait] || '';
|
|
100
|
+
return [`quiet for ${parts.minutes}m`, wait].filter(Boolean).join(' · ');
|
|
101
|
+
}
|
|
@@ -131,6 +131,32 @@ export function listQuotaResumeEntries() {
|
|
|
131
131
|
return [...load().entries.values()];
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
/** Rekey a proven legacy execution and its Goal together; invalidate old fires. */
|
|
135
|
+
export function rekeyQuotaResumeTurn(sessionId, fromTurnKey, toTurnKey) {
|
|
136
|
+
const current = load();
|
|
137
|
+
const id = text(sessionId);
|
|
138
|
+
const from = text(fromTurnKey);
|
|
139
|
+
const to = text(toTurnKey);
|
|
140
|
+
if (!id || !from || !to || from === to) return false;
|
|
141
|
+
const entry = current.entries.get(id);
|
|
142
|
+
const suspension = current.suspensions.get(id);
|
|
143
|
+
const moveEntry = entry?.turnKey === from;
|
|
144
|
+
const moveGoal = suspension?.turnKey === from;
|
|
145
|
+
if (!moveEntry && !moveGoal) return false;
|
|
146
|
+
const next = {
|
|
147
|
+
...current,
|
|
148
|
+
generation: current.generation + Number(moveEntry),
|
|
149
|
+
entries: new Map(current.entries),
|
|
150
|
+
suspensions: new Map(current.suspensions),
|
|
151
|
+
};
|
|
152
|
+
if (moveEntry) next.entries.set(id, normalizeEntry({ ...entry, turnKey: to, generation: next.generation }));
|
|
153
|
+
if (moveGoal) next.suspensions.set(id, normalizeSuspension({ ...suspension, turnKey: to }));
|
|
154
|
+
persist(next);
|
|
155
|
+
state = next;
|
|
156
|
+
notify(id);
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
|
|
134
160
|
/** The session snapshot's `quotaResume` value for an entry (or null). */
|
|
135
161
|
export function publicQuotaResume(entry) {
|
|
136
162
|
if (!entry) return null;
|
|
@@ -244,7 +270,12 @@ export function isAgentOnlySession(session) {
|
|
|
244
270
|
const lower = (value) => text(value).toLowerCase();
|
|
245
271
|
if (lower(session.visibility) === 'agent-only') return true;
|
|
246
272
|
const parentId = text(session.parentSessionId || session.ownerSessionId);
|
|
247
|
-
return
|
|
273
|
+
return (
|
|
274
|
+
lower(session.owner) === 'agent' &&
|
|
275
|
+
lower(session.agent) !== 'lead' &&
|
|
276
|
+
parentId !== '' &&
|
|
277
|
+
parentId !== text(session.id)
|
|
278
|
+
);
|
|
248
279
|
}
|
|
249
280
|
|
|
250
281
|
/** Global setting, default on. */
|
|
@@ -61,3 +61,47 @@ export function readRowsForDisplay(text) {
|
|
|
61
61
|
}
|
|
62
62
|
return out.join('\n');
|
|
63
63
|
}
|
|
64
|
+
|
|
65
|
+
/** Decode one contiguous model-facing read window, never display metadata.
|
|
66
|
+
* Unknown or disjoint views are not safe substitutes for file text. Per-line
|
|
67
|
+
* clipping is not visible in the text: the read executor reports it
|
|
68
|
+
* structurally, never inferred from row content.
|
|
69
|
+
* The display format does not preserve original byte size or final newline.
|
|
70
|
+
*/
|
|
71
|
+
export function readSourceWindow(text) {
|
|
72
|
+
if (typeof text !== 'string') return null;
|
|
73
|
+
if (/^<system-reminder>File exists but has empty contents: [^\n]*<\/system-reminder>$/.test(text))
|
|
74
|
+
return { content: '', totalLines: 0, startLine: 1, endLine: 0, truncated: false };
|
|
75
|
+
const emptyRange = /^\(no lines in range; file has (\d+) lines\)$/.exec(text);
|
|
76
|
+
if (emptyRange)
|
|
77
|
+
return { content: '', totalLines: Number(emptyRange[1]), startLine: null, endLine: null, truncated: false };
|
|
78
|
+
if (!RUN_MARKER_RE.test(text.split('\n', 1)[0])) return null;
|
|
79
|
+
const rows = [];
|
|
80
|
+
let totalLines;
|
|
81
|
+
let footer = null;
|
|
82
|
+
for (const line of readRowsForDisplay(text).split('\n')) {
|
|
83
|
+
const row = /^(\d+)→([\s\S]*)$/.exec(line);
|
|
84
|
+
if (row) {
|
|
85
|
+
if (footer) return null;
|
|
86
|
+
const number = Number(row[1]);
|
|
87
|
+
if (rows.length && number !== rows.at(-1).number + 1) return null;
|
|
88
|
+
rows.push({ number, content: row[2] });
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const metadata = /^\[lines (\d+)-(\d+) of (\d+)(?:; pass offset:\d+ to continue)?\]$/.exec(line);
|
|
92
|
+
if (!metadata || footer) return null;
|
|
93
|
+
footer = metadata;
|
|
94
|
+
totalLines = Number(metadata[3]);
|
|
95
|
+
}
|
|
96
|
+
if (!rows.length) return null;
|
|
97
|
+
const startLine = rows[0].number;
|
|
98
|
+
const endLine = rows.at(-1).number;
|
|
99
|
+
if (footer && (Number(footer[1]) !== startLine || Number(footer[2]) !== endLine || totalLines < endLine)) return null;
|
|
100
|
+
return {
|
|
101
|
+
content: rows.map((row) => row.content).join('\n'),
|
|
102
|
+
...(totalLines === undefined ? {} : { totalLines }),
|
|
103
|
+
startLine,
|
|
104
|
+
endLine,
|
|
105
|
+
truncated: totalLines === undefined || endLine < totalLines,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
@@ -1,47 +1,7 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
// The daemon's channel transport OWNS this file (writes/clears it); everything
|
|
4
|
-
// else only asks one question: "which session is pinned to the channel?".
|
|
5
|
-
// That session reclaims its link on boot
|
|
6
|
-
// instead of waiting for a manual toggle — the reconnect path that used to
|
|
7
|
-
// look like the channel had silently unlinked itself.
|
|
8
|
-
import { readFileSync } from 'node:fs';
|
|
9
|
-
import { join, resolve } from 'node:path';
|
|
1
|
+
// Path of the durable channel-link record (channel-remote-intent.json).
|
|
2
|
+
import { join } from 'node:path';
|
|
10
3
|
import { resolveRuntimeRoot } from './runtime-root.mjs';
|
|
11
4
|
|
|
12
5
|
export function remoteIntentPath(root = resolveRuntimeRoot()) {
|
|
13
6
|
return join(root, 'channel-remote-intent.json');
|
|
14
7
|
}
|
|
15
|
-
|
|
16
|
-
export function readRemoteIntent(path = remoteIntentPath()) {
|
|
17
|
-
try {
|
|
18
|
-
const value = JSON.parse(readFileSync(path, 'utf8'));
|
|
19
|
-
const sessionId = String(value?.sessionId || '').trim();
|
|
20
|
-
const transcriptPath = String(value?.transcriptPath || '').trim();
|
|
21
|
-
if (!/^[A-Za-z0-9_-]+$/.test(sessionId) || !transcriptPath) return null;
|
|
22
|
-
return {
|
|
23
|
-
sessionId,
|
|
24
|
-
transcriptPath,
|
|
25
|
-
cwd: value?.cwd == null ? null : String(value.cwd),
|
|
26
|
-
};
|
|
27
|
-
} catch {
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// cwd is compared only when the record carries one: the intent is session
|
|
33
|
-
// pinned, and a resumed session keeps its id across restarts.
|
|
34
|
-
export function remoteIntentMatchesSession(sessionId, cwd = null, path = undefined) {
|
|
35
|
-
const id = String(sessionId || '').trim();
|
|
36
|
-
if (!id) return false;
|
|
37
|
-
const intent = readRemoteIntent(path);
|
|
38
|
-
if (!intent || intent.sessionId !== id) return false;
|
|
39
|
-
if (intent.cwd && cwd) {
|
|
40
|
-
try {
|
|
41
|
-
if (resolve(intent.cwd) !== resolve(cwd)) return false;
|
|
42
|
-
} catch {
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
const TRUNCATED = '… [diff truncated for display]';
|
|
2
2
|
|
|
3
|
+
// Review replies always list every changed file with its counts. Patch text
|
|
4
|
+
// is carried per file within these caps (UTF-8 bytes); a file past either one
|
|
5
|
+
// is listed `patchOmitted` with reason PATCH_TOO_LARGE and is read on its own,
|
|
6
|
+
// up to the larger "show anyway" cap, when it is opened.
|
|
7
|
+
/** Largest single-file patch a review reply carries inline. */
|
|
8
|
+
export const REVIEW_FILE_PATCH_MAX_BYTES = 1024 * 1024;
|
|
9
|
+
/** Largest total patch text a review reply carries. */
|
|
10
|
+
export const REVIEW_PATCH_MAX_BYTES = 2 * 1024 * 1024;
|
|
11
|
+
/** Largest single-file patch a file-patch read returns. */
|
|
12
|
+
export const REVIEW_FILE_PATCH_SHOW_MAX_BYTES = 8 * 1024 * 1024;
|
|
13
|
+
export const PATCH_TOO_LARGE = 'too_large';
|
|
14
|
+
|
|
15
|
+
/** A reply file listed with its counts but without its patch, for size. */
|
|
16
|
+
export function patchOmittedFile(file) {
|
|
17
|
+
return { ...file, patchOmitted: true, reason: PATCH_TOO_LARGE };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** A `diff --git` section (string or Buffer) whose hunks boundReviewPatch cut. */
|
|
21
|
+
export function reviewSectionTruncated(section) {
|
|
22
|
+
return section.includes(TRUNCATED);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Nothing of the reply's patch fit: no patch text, a file omitted for size. */
|
|
26
|
+
export function reviewDiffTooLarge(files, patch) {
|
|
27
|
+
return !patch && (files || []).some((file) => file?.patchOmitted === true && file.reason === PATCH_TOO_LARGE);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** The per-file and total caps of one reply. `admit(bytes)` takes a patch of
|
|
31
|
+
* that size from the remaining total, or refuses it. */
|
|
32
|
+
export function createReviewPatchBudget(total = REVIEW_PATCH_MAX_BYTES) {
|
|
33
|
+
let remaining = total;
|
|
34
|
+
return {
|
|
35
|
+
get remaining() {
|
|
36
|
+
return remaining;
|
|
37
|
+
},
|
|
38
|
+
admit(bytes) {
|
|
39
|
+
if (bytes > REVIEW_FILE_PATCH_MAX_BYTES || bytes > remaining) return false;
|
|
40
|
+
remaining -= bytes;
|
|
41
|
+
return true;
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** One file-patch read's reply: its patch, or none when past `maxBytes`. */
|
|
47
|
+
export function filePatchReply(path, patch, maxBytes = REVIEW_FILE_PATCH_SHOW_MAX_BYTES) {
|
|
48
|
+
const text = typeof patch === 'string' ? patch : '';
|
|
49
|
+
if (Buffer.byteLength(text, 'utf8') > maxBytes) {
|
|
50
|
+
return { supported: true, path, patch: '', patchOmitted: true, reason: PATCH_TOO_LARGE };
|
|
51
|
+
}
|
|
52
|
+
return { supported: true, path, patch: text };
|
|
53
|
+
}
|
|
54
|
+
|
|
3
55
|
/** Bound hunk bodies, never the inventory of changed files. Headers are kept
|
|
4
56
|
* even when the inventory itself exceeds the display budget. */
|
|
5
57
|
export function boundReviewPatch(patch, maxChars) {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type SessionSidebarChange = { favorite: boolean } | { archived: boolean };
|
|
2
|
+
export type SessionSidebarHost = (sessionId: unknown, change: unknown) => unknown;
|
|
3
|
+
export function registerSessionSidebarHost(host: SessionSidebarHost): () => void;
|
|
4
|
+
export function applySessionSidebarChange(sessionId: string, change: SessionSidebarChange): Promise<void>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Runtime → desktop request channel for a session's sidebar metadata
|
|
2
|
+
// (favorite, archive). That metadata belongs to the desktop
|
|
3
|
+
// service hosted in this daemon: it registers a host here, and the Lead's
|
|
4
|
+
// `session` tool applies a change through it, so the sidebar republishes live.
|
|
5
|
+
//
|
|
6
|
+
// Deliberately dependency-free: the desktop service bundle imports this file
|
|
7
|
+
// too, and both copies share one registry through a global symbol.
|
|
8
|
+
|
|
9
|
+
const HOSTS_KEY = Symbol.for('mixdog.sessionSidebarHosts.v1');
|
|
10
|
+
|
|
11
|
+
function hosts() {
|
|
12
|
+
globalThis[HOSTS_KEY] ??= [];
|
|
13
|
+
return globalThis[HOSTS_KEY];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Register a desktop host. `host(sessionId, change)` applies one change:
|
|
18
|
+
* `{ favorite: boolean }` or `{ archived: boolean }`.
|
|
19
|
+
* @returns {() => void} Unregister.
|
|
20
|
+
*/
|
|
21
|
+
export function registerSessionSidebarHost(host) {
|
|
22
|
+
const entry = { host };
|
|
23
|
+
hosts().push(entry);
|
|
24
|
+
return () => {
|
|
25
|
+
const list = hosts();
|
|
26
|
+
const index = list.indexOf(entry);
|
|
27
|
+
if (index >= 0) list.splice(index, 1);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Apply one change through exactly one host: the most recently registered
|
|
32
|
+
* (active) desktop service. Never broadcast — each service writes the shared
|
|
33
|
+
* metadata file, so a second write would be redundant at best. */
|
|
34
|
+
export async function applySessionSidebarChange(sessionId, change) {
|
|
35
|
+
const active = hosts().at(-1);
|
|
36
|
+
if (!active) throw new Error('no desktop app is attached to this runtime');
|
|
37
|
+
await active.host(sessionId, change);
|
|
38
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// slow-span.mjs
|
|
2
|
+
// Passive per-request timing spans. Every traced call is timed on the same
|
|
3
|
+
// monotonic clock the owner heartbeat uses (performance.now), completed spans
|
|
4
|
+
// over `minMs` land in a bounded ring, and spans over `slowMs` are logged as
|
|
5
|
+
// `[slow-op] <label> <ms>`. When the event loop stalls, `describe(from, to)`
|
|
6
|
+
// names the spans that overlapped the stall window. Spans carry labels, phase
|
|
7
|
+
// durations and sizes only — never payloads.
|
|
8
|
+
|
|
9
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
10
|
+
import { performance } from 'node:perf_hooks';
|
|
11
|
+
|
|
12
|
+
export const SPAN_RING_MIN_MS = 25;
|
|
13
|
+
export const SPAN_SLOW_MS = 1000;
|
|
14
|
+
export const SPAN_RING_CAPACITY = 64;
|
|
15
|
+
|
|
16
|
+
const current = new AsyncLocalStorage();
|
|
17
|
+
|
|
18
|
+
/** Short, log-safe id of a session id. */
|
|
19
|
+
export function shortId(id) {
|
|
20
|
+
const text = String(id ?? '');
|
|
21
|
+
return text ? text.slice(0, 8) : '';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Appends detail (e.g. the action name) to the label of the span the caller runs in. */
|
|
25
|
+
export function annotateSpan(detail) {
|
|
26
|
+
const span = current.getStore();
|
|
27
|
+
if (span && detail) span.label += `:${detail}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Closes the running phase of the caller's span at `now`, under `name`. */
|
|
31
|
+
export function markPhase(name) {
|
|
32
|
+
const span = current.getStore();
|
|
33
|
+
if (!span) return;
|
|
34
|
+
const t = span.now();
|
|
35
|
+
span.phases.push([name, t - span.mark]);
|
|
36
|
+
span.mark = t;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Records a size (count/bytes) on the caller's span. */
|
|
40
|
+
export function noteSpanSize(size) {
|
|
41
|
+
const span = current.getStore();
|
|
42
|
+
if (span && Number.isFinite(size)) span.size = size;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const round = (ms) => Math.round(ms);
|
|
46
|
+
|
|
47
|
+
function formatSpan(span) {
|
|
48
|
+
const phases = span.phases.map(([name, ms]) => `${name}=${round(ms)}`).join(' ');
|
|
49
|
+
const size = span.size === undefined ? '' : ` size=${span.size}`;
|
|
50
|
+
return `${span.label} ${round(span.ms)}ms${phases ? ` ${phases}` : ''}${size}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function createSlowSpans({
|
|
54
|
+
now = () => performance.now(),
|
|
55
|
+
capacity = SPAN_RING_CAPACITY,
|
|
56
|
+
minMs = SPAN_RING_MIN_MS,
|
|
57
|
+
slowMs = SPAN_SLOW_MS,
|
|
58
|
+
log = () => {},
|
|
59
|
+
} = {}) {
|
|
60
|
+
const ring = [];
|
|
61
|
+
let sink = log;
|
|
62
|
+
|
|
63
|
+
function complete(span) {
|
|
64
|
+
span.end = now();
|
|
65
|
+
span.ms = span.end - span.start;
|
|
66
|
+
if (span.ms >= minMs) {
|
|
67
|
+
ring.push({
|
|
68
|
+
label: span.label,
|
|
69
|
+
start: span.start,
|
|
70
|
+
end: span.end,
|
|
71
|
+
ms: span.ms,
|
|
72
|
+
phases: span.phases,
|
|
73
|
+
size: span.size,
|
|
74
|
+
});
|
|
75
|
+
if (ring.length > capacity) ring.shift();
|
|
76
|
+
}
|
|
77
|
+
if (span.ms >= slowMs) {
|
|
78
|
+
try {
|
|
79
|
+
sink(`[slow-op] ${formatSpan(span)}`);
|
|
80
|
+
} catch {
|
|
81
|
+
/* logging must not fail the call */
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
setLog(next) {
|
|
88
|
+
sink = typeof next === 'function' ? next : () => {};
|
|
89
|
+
},
|
|
90
|
+
/** Runs `fn` inside a span; markPhase/annotateSpan inside it attach to this span. */
|
|
91
|
+
async trace(label, fn) {
|
|
92
|
+
const start = now();
|
|
93
|
+
const span = { label: String(label), start, mark: start, now, phases: [], size: undefined };
|
|
94
|
+
try {
|
|
95
|
+
return await current.run(span, fn);
|
|
96
|
+
} finally {
|
|
97
|
+
complete(span);
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
/** Completed spans overlapping [from, to], longest overlap first. */
|
|
101
|
+
overlapping(from, to, limit = 3) {
|
|
102
|
+
return ring
|
|
103
|
+
.map((span) => ({ span, overlap: Math.min(span.end, to) - Math.max(span.start, from) }))
|
|
104
|
+
.filter((row) => row.overlap > 0)
|
|
105
|
+
.sort((a, b) => b.overlap - a.overlap || b.span.end - a.span.end)
|
|
106
|
+
.slice(0, limit)
|
|
107
|
+
.map((row) => row.span);
|
|
108
|
+
},
|
|
109
|
+
/** One-line description of the spans overlapping a stall window ('' when none). */
|
|
110
|
+
describe(from, to, limit = 3) {
|
|
111
|
+
const spans = this.overlapping(from, to, limit);
|
|
112
|
+
return spans.length ? `spans: ${spans.map((span) => formatSpan({ ...span })).join('; ')}` : '';
|
|
113
|
+
},
|
|
114
|
+
get recent() {
|
|
115
|
+
return ring.slice();
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Process-wide recorder; the daemon points its log at daemon.log. */
|
|
121
|
+
export const slowSpans = createSlowSpans();
|
|
@@ -15,6 +15,11 @@ import { join } from 'node:path';
|
|
|
15
15
|
import { formatElapsed } from './statusline-format.mjs';
|
|
16
16
|
import { positiveInt } from '../numbers.mjs';
|
|
17
17
|
import { isPidAlive } from '../pid-liveness.mjs';
|
|
18
|
+
import { workspaceSees } from '../worktrees/workspace-visibility.mjs';
|
|
19
|
+
|
|
20
|
+
/** Whether an orphaned held shell (`status.orphaned`) belongs in the list of a
|
|
21
|
+
* session working in `sessionCwd`. */
|
|
22
|
+
export const shellJobVisibleFrom = (job, sessionCwd) => workspaceSees(job?.cwd, sessionCwd);
|
|
18
23
|
|
|
19
24
|
const DEFAULT_MIXDOG_HOME = process.env.MIXDOG_HOME || join(homedir(), '.mixdog');
|
|
20
25
|
const DEFAULT_STANDALONE_DATA_DIR = join(DEFAULT_MIXDOG_HOME, 'data');
|
|
@@ -76,9 +81,38 @@ export function shellJobsStatus({ clientHostPid, sessionId } = {}) {
|
|
|
76
81
|
_shellJobsRefreshInFlight.delete(ownerPid);
|
|
77
82
|
});
|
|
78
83
|
}
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
const own = cached?.value || EMPTY_SHELL_JOBS;
|
|
85
|
+
// Session buckets are not pid-scoped, so they come from the freshest scan of
|
|
86
|
+
// ANY owner. Reading them from this owner's own slot made the list follow
|
|
87
|
+
// that slot's age: an owner polled again after its entry was evicted (or
|
|
88
|
+
// went stale) answered with "no sessions", and the finished shells vanished
|
|
89
|
+
// until the next poll brought them back.
|
|
90
|
+
const sessions = freshestShellJobsSessions() ?? own.sessions;
|
|
91
|
+
if (!scoped) return sessions === own.sessions ? own : { ...own, sessions };
|
|
92
|
+
return (scope && sessions?.[scope]) || EMPTY_SHELL_JOBS_SESSION;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Listed jobs held only because their termination is unconfirmed. */
|
|
96
|
+
export function unconfirmedShellCount(status) {
|
|
97
|
+
const jobs = Array.isArray(status?.jobs) ? status.jobs : [];
|
|
98
|
+
return jobs.filter((job) => job?.terminationUnconfirmed === true).length;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Awaited fresh scan for pollers that own their cadence (desktop): the result
|
|
102
|
+
// reflects the disk at call time instead of the previous poll. The CLI render
|
|
103
|
+
// path keeps using the cache-only shellJobsStatus.
|
|
104
|
+
export async function shellJobsStatusFresh({ clientHostPid } = {}) {
|
|
105
|
+
const ownerPid = positiveInt(clientHostPid);
|
|
106
|
+
if (!ownerPid) return EMPTY_SHELL_JOBS;
|
|
107
|
+
return refreshShellJobsStatus(ownerPid);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function freshestShellJobsSessions() {
|
|
111
|
+
let freshest = null;
|
|
112
|
+
for (const entry of _shellJobsSegmentCache.values()) {
|
|
113
|
+
if (!freshest || entry.at >= freshest.at) freshest = entry;
|
|
114
|
+
}
|
|
115
|
+
return freshest?.value.sessions;
|
|
82
116
|
}
|
|
83
117
|
|
|
84
118
|
// Memory cycle L2 segment source. The daemon-hosted memory runtime writes
|
|
@@ -142,12 +176,13 @@ async function refreshShellJobsStatus(ownerPid) {
|
|
|
142
176
|
names = await readdir(dir);
|
|
143
177
|
} catch {
|
|
144
178
|
rememberShellJobs(ownerPid, value);
|
|
145
|
-
return;
|
|
179
|
+
return value;
|
|
146
180
|
}
|
|
147
181
|
const { ids, ownerByJob, doneIds } = listOpenShellJobs(names);
|
|
148
182
|
let count = 0;
|
|
149
183
|
let oldestMs = Infinity;
|
|
150
184
|
const jobs = [];
|
|
185
|
+
const orphaned = [];
|
|
151
186
|
// sessionId -> { count, oldestMs, jobs }. Jobs with no session stamp (legacy
|
|
152
187
|
// records, plain CLI runs) still count toward the owner total but belong to
|
|
153
188
|
// no pane, so they never light up a session's indicator.
|
|
@@ -160,11 +195,16 @@ async function refreshShellJobsStatus(ownerPid) {
|
|
|
160
195
|
} catch {
|
|
161
196
|
continue;
|
|
162
197
|
}
|
|
163
|
-
|
|
198
|
+
// A killed command whose processes are not confirmed gone has already
|
|
199
|
+
// reported its result, so its tool card is closed: it is listed until
|
|
200
|
+
// its owner retires the record. Its root pid may be gone while a
|
|
201
|
+
// descendant lives, so the owner's liveness decides, not the root's.
|
|
202
|
+
const unconfirmed = detail?.terminationUnconfirmed === true;
|
|
203
|
+
if (unconfirmed ? !isPidAlive(ownerByJob.get(id) || 0) : !(await isShellJobAlive(detail, p, dir, id))) continue;
|
|
164
204
|
// A foreground command is awaited in its own tool card; listing it here
|
|
165
205
|
// made every short command flash in and out of the shell list. Only
|
|
166
206
|
// backgrounded jobs (including promoted ones) are background work.
|
|
167
|
-
if (detail?.foreground === true) continue;
|
|
207
|
+
if (detail?.foreground === true && !unconfirmed) continue;
|
|
168
208
|
// Owner-wide totals stay this process's own; session buckets take every
|
|
169
209
|
// live job regardless of which host published it.
|
|
170
210
|
const ownedByThisHost = ownerByJob.get(id) === ownerPid;
|
|
@@ -181,8 +221,12 @@ async function refreshShellJobsStatus(ownerPid) {
|
|
|
181
221
|
command: String(detail?.command || '').trim(),
|
|
182
222
|
cwd: String(detail?.cwd || '').trim(),
|
|
183
223
|
startedAt: detail?.startedAt || (Number.isFinite(jobMs) ? jobMs : null),
|
|
224
|
+
...(unconfirmed ? { terminationUnconfirmed: true } : {}),
|
|
184
225
|
};
|
|
185
226
|
if (ownedByThisHost) jobs.push(job);
|
|
227
|
+
// Held by a session that has closed: every session that sees its
|
|
228
|
+
// folder lists it (shellJobVisibleFrom), not only the closed owner.
|
|
229
|
+
if (unconfirmed && detail?.ownerSessionClosed === true) orphaned.push(job);
|
|
186
230
|
if (!owner) continue;
|
|
187
231
|
const bucket = bySession.get(owner) || { count: 0, oldestMs: Infinity, jobs: [], finished: [] };
|
|
188
232
|
bucket.count += 1;
|
|
@@ -221,10 +265,12 @@ async function refreshShellJobsStatus(ownerPid) {
|
|
|
221
265
|
// count stays 0 (its publisher is a shard, not this host), so an empty
|
|
222
266
|
// aggregate must NOT discard the session buckets.
|
|
223
267
|
if (count || bySession.size) value = summarizeShellJobs({ count, oldestMs, jobs, bySession });
|
|
268
|
+
if (orphaned.length) value = { ...value, orphaned };
|
|
224
269
|
} catch {
|
|
225
270
|
value = EMPTY_SHELL_JOBS;
|
|
226
271
|
}
|
|
227
272
|
rememberShellJobs(ownerPid, value);
|
|
273
|
+
return value;
|
|
228
274
|
}
|
|
229
275
|
|
|
230
276
|
// Newest-first, capped ids of job records with no `.done` marker, plus the
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
import { formatToolActionHeader, toolLoadingTargets } from '../tool-surface.mjs';
|
|
6
6
|
import { agentActionSummary, agentActionTitle, agentResponseTitle, isAgentTool } from './agent-surface.mjs';
|
|
7
7
|
import { backgroundTaskActionTitle, backgroundTaskResultTitle, taskControlTitle } from './background-task.mjs';
|
|
8
|
-
import { toolSearchLoadedSummary } from './generic-detail.mjs';
|
|
8
|
+
import { bridgeDescribedToolNames, toolSearchLoadedSummary } from './generic-detail.mjs';
|
|
9
|
+
import { displayToolSearchTarget } from '../tool-primitives.mjs';
|
|
9
10
|
import { safeInlineText } from './inline-text.mjs';
|
|
10
11
|
import { shellHeader } from './shell-surface.mjs';
|
|
11
12
|
|
|
@@ -20,6 +21,11 @@ function headerLabel(base, surface, display, status, detail) {
|
|
|
20
21
|
}
|
|
21
22
|
if (display.isBackgroundMetadataResult) return backgroundTaskActionTitle(normalizedName, display.backgroundMeta);
|
|
22
23
|
if (isShellSurface) return shellHeader(status.shellStatus, groupCount, parsedArgs?.verifyShell === true);
|
|
24
|
+
// Bridge load_tool describes definitions; it never loads a tool.
|
|
25
|
+
const described =
|
|
26
|
+
normalizedName === 'load_tool' && !headerPending ? bridgeDescribedToolNames(display.displayedResultText) : null;
|
|
27
|
+
if (described)
|
|
28
|
+
return described.length ? `Described ${described.map(displayToolSearchTarget).join(', ')}` : 'Described';
|
|
23
29
|
return (
|
|
24
30
|
(isAgentTool(normalizedName) ? agentActionTitle(parsedArgs, display.displayedResultText) : '') ||
|
|
25
31
|
formatToolActionHeader(name, args, {
|