mixdog 1.2.3 → 1.2.5
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/package.json +1 -1
- package/scripts/gate-local.mjs +6 -4
- package/scripts/lib/gate-scheduler.mjs +29 -11
- package/scripts/mobile-release.mjs +5 -4
- package/scripts/probe-provider-catalog.mjs +31 -0
- package/scripts/provider-pingpong-live.mjs +128 -38
- package/scripts/session-sweep.mjs +5 -25
- 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 +7 -1
- package/src/defaults/skills/image/SKILL.md +21 -23
- package/src/lib/keychain-cjs.cjs +13 -11
- package/src/output-styles/common.md +2 -1
- package/src/rules/agent/AGENT.md +7 -5
- package/src/rules/lead/LEAD.md +13 -13
- 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/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-error-contract.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -3
- 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 +2 -5
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +4 -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 +81 -10
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +109 -5
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +107 -37
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +3 -1
- 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 +41 -11
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +67 -5
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +14 -4
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +9 -6
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -2
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +26 -4
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +12 -6
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +14 -6
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +4 -4
- 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 +6 -1
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +22 -10
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +33 -7
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +11 -2
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +9 -5
- package/src/runtime/agent/orchestrator/providers/lib/request-compression.mjs +86 -0
- package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -5
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +60 -16
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +11 -13
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +30 -19
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +42 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +13 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +1 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +18 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +36 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +11 -1
- 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/terminal-frames.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +1 -4
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +0 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +7 -6
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +13 -2
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/openrouter.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +5 -4
- package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/wire-route.mjs +14 -4
- package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +15 -3
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +6 -2
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +4 -1
- 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/skill-tool-loading.mjs +3 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +10 -10
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +3 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +46 -8
- 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 +3 -11
- package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +28 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
- 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 +1 -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 +2 -4
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +0 -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 +4 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +1 -4
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +8 -9
- package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +1 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -4
- 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 +21 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +38 -13
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +19 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
- 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 +29 -8
- 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 +32 -14
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +17 -33
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -9
- package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/side-question.mjs +12 -7
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +5 -12
- 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/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 +5 -11
- 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 -32
- 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 +1 -1
- package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +160 -212
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +50 -116
- 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 +7 -8
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
- package/src/runtime/agent/orchestrator/session/store.mjs +3 -16
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +11 -12
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +37 -13
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
- package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +4 -2
- 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/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/external-tool-adapters.mjs +204 -10
- 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 +200 -17
- 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/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-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/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 +178 -178
- 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 +118 -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/lib/ingest/transcript-rows.mjs +1 -0
- package/src/runtime/memory/lib/pg/process.mjs +5 -7
- package/src/runtime/memory/lib/pg/supervisor.mjs +4 -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/pdf-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/pptx-html-measure.mjs +1 -1
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
- package/src/runtime/office/core/office-write-ledger.mjs +1 -5
- package/src/runtime/office/index.mjs +2 -3
- package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
- 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-line-diff.mjs +11 -2
- package/src/runtime/shared/browser-launch.mjs +15 -0
- package/src/runtime/shared/err-text.mjs +42 -4
- package/src/runtime/shared/file-lock.mjs +6 -5
- package/src/runtime/shared/llm/anthropic-betas.mjs +1 -2
- package/src/runtime/shared/llm/provider-model-identities.mjs +1 -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 +6 -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/slow-span.mjs +8 -1
- package/src/runtime/shared/statusline/statusline-segments.mjs +24 -2
- package/src/runtime/shared/tool-card-model/card-header.mjs +2 -1
- package/src/runtime/shared/tool-output-budget.mjs +2 -0
- package/src/runtime/shared/tool-result-summary.mjs +16 -2
- package/src/runtime/shared/tool-status.mjs +3 -2
- package/src/runtime/shared/tool-surface.mjs +2 -3
- package/src/runtime/shared/tool-work-units.mjs +22 -15
- 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/transcript-file.mjs +10 -1
- package/src/runtime/shared/transcript-writer.mjs +14 -4
- package/src/runtime/shared/turn-changes.mjs +2 -1
- package/src/runtime/shared/turn-snapshot.mjs +11 -3
- 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 +6 -4
- package/src/runtime/shared/worktrees/contract.mjs +27 -1
- package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
- package/src/runtime/shared/worktrees/file-recovery.mjs +29 -13
- package/src/runtime/shared/worktrees/git-head.mjs +22 -13
- 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 +378 -32
- package/src/runtime/shared/worktrees/owner.mjs +2 -1
- 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 +14 -10
- package/src/session-runtime/boot/apis.mjs +7 -1
- package/src/session-runtime/boot/config.mjs +2 -0
- package/src/session-runtime/boot/facade.mjs +3 -0
- package/src/session-runtime/boot/session.mjs +3 -2
- package/src/session-runtime/boot/tools.mjs +3 -0
- package/src/session-runtime/conversation-import/service.mjs +1 -1
- package/src/session-runtime/goal-facade-api.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +44 -18
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +4 -1
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +22 -8
- package/src/session-runtime/internal-tool-executor.mjs +2 -0
- package/src/session-runtime/lifecycle/cold-heir.mjs +0 -1
- package/src/session-runtime/lifecycle/session-catalog.mjs +14 -16
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +18 -53
- 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 +7 -16
- 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 +114 -34
- 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.mjs +9 -8
- 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/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/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/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/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 +9 -6
- 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 +3 -9
- 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.mjs +28 -8
- package/src/session-runtime/services/agent-tool.mjs +4 -0
- package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -0
- package/src/session-runtime/services/provider-admin.mjs +77 -0
- 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.mjs +4 -5
- package/src/session-runtime/session-turn-api.mjs +3 -9
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -6
- package/src/session-runtime/setup-tool/executor.mjs +23 -5
- package/src/session-runtime/setup-tool/extended-actions.mjs +6 -6
- package/src/session-runtime/setup-tool/settings-contract.mjs +7 -2
- package/src/session-runtime/setup-tool/tool-defs.mjs +13 -1
- package/src/session-runtime/tool-policy-refresh.mjs +83 -32
- package/src/session-runtime/turn/agent-ops.mjs +49 -2
- package/src/session-runtime/turn/side-question-ops.mjs +1 -4
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +2 -0
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +4 -0
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +8 -2
- package/src/session-runtime/turn/turn-run.mjs +1 -36
- package/src/session-runtime/usage-stats-api.mjs +4 -1
- 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 +28 -36
- package/src/session-runtime/workspace/transition-steps.mjs +96 -95
- package/src/session-runtime/workspace/transitions.mjs +248 -68
- package/src/standalone/channel-transport.mjs +3 -4
- package/src/standalone/daemon-desktop-runtime.mjs +32 -1
- package/src/standalone/daemon-pg-stop.mjs +1 -3
- package/src/standalone/daemon-session-control.mjs +88 -0
- package/src/standalone/daemon-stored-session-views.mjs +23 -3
- package/src/standalone/daemon.mjs +2 -0
- package/src/standalone/desktop-service-registry.mjs +32 -5
- package/src/standalone/local-session-runtime.mjs +11 -12
- package/src/standalone/session-protocol.mjs +7 -0
- package/src/standalone/session-runtime-inline-host.mjs +2 -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-turns.mjs +17 -6
- package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
- package/src/standalone/session-tool-output.mjs +82 -0
- package/src/tui/app/app-view.jsx +2 -1
- 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/slash-commands.mjs +6 -0
- package/src/tui/app/slash-dispatch/session-commands.mjs +49 -0
- package/src/tui/components/Spinner.jsx +4 -0
- package/src/tui/components/SpinnerByline.jsx +21 -2
- package/src/tui/components/status-line/local-line.mjs +10 -2
- package/src/tui/dist/index.mjs +529 -270
- package/src/tui/session/active-tool-summary.mjs +1 -1
- package/src/tui/session/context-state.mjs +0 -3
- 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 +4 -10
- package/src/tui/session/session-api/controls.mjs +12 -0
- package/src/tui/session/session-api/lifecycle/dispose.mjs +2 -9
- package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
- package/src/tui/session/session-api/lifecycle.mjs +13 -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 +3 -3
- package/src/tui/session/session-api/worktree.mjs +3 -2
- 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 +17 -8
- 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 +5 -1
- package/src/tui/session/turn.mjs +38 -31
- 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/ui/streaming-markdown-heal.mjs +70 -18
- 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 -302
- 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
|
@@ -38,8 +38,8 @@ export function createSendDispatch({ registry, defaultCwd, sendFlow, spawnFlow,
|
|
|
38
38
|
if (inherited.tombstone) registry.consumeTagTombstone(inherited.tombstone);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
//
|
|
42
|
-
//
|
|
41
|
+
// Dead-tag fallback: a same-scope follow-up can land after its session was
|
|
42
|
+
// closed or deleted. Instead of bouncing an
|
|
43
43
|
// error back to Lead (who would just re-issue the same content as a spawn),
|
|
44
44
|
// respawn a FRESH session under the same tag with the message as its brief.
|
|
45
45
|
// `respawned: true` in the result tells Lead the worker has no prior session
|
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
import { clean, rowMatchesContext } from './helpers.mjs';
|
|
2
|
+
import { resolveRequestedModel } from './model-select.mjs';
|
|
3
|
+
|
|
4
|
+
// What an explicit (already resolved) spawn asks a reused session to change:
|
|
5
|
+
// the model, the tuning, or both — only what it names, or null when it names
|
|
6
|
+
// nothing. It is a partial request: the session's route write completes it
|
|
7
|
+
// against the latest selected route (and drops it when nothing differs), so
|
|
8
|
+
// no descriptor snapshot decides what the other tuning becomes.
|
|
9
|
+
function requestedRoute(args) {
|
|
10
|
+
const model = clean(args.model);
|
|
11
|
+
const effort = clean(args.effort);
|
|
12
|
+
const route = {
|
|
13
|
+
...(model ? { provider: clean(args.provider), model } : {}),
|
|
14
|
+
...(effort ? { effort } : {}),
|
|
15
|
+
...(args.fast === undefined ? {} : { fast: args.fast === true }),
|
|
16
|
+
...(args.autoEffort === undefined ? {} : { autoEffort: args.autoEffort !== false }),
|
|
17
|
+
};
|
|
18
|
+
return Object.keys(route).length ? route : null;
|
|
19
|
+
}
|
|
2
20
|
|
|
3
21
|
// Spawn request dispatch: deciding what an explicitly tagged spawn means before
|
|
4
22
|
// a job is started, and starting it.
|
|
@@ -6,7 +24,14 @@ import { clean, rowMatchesContext } from './helpers.mjs';
|
|
|
6
24
|
// Inputs: `registry` (tag resolution, live sessions, tombstones),
|
|
7
25
|
// `terminalTrace`, `sendFlow` (reuse path), `spawnFlow`, and `spawnResult`
|
|
8
26
|
// (job -> rendered tool output). Output: { spawn }.
|
|
9
|
-
export function createSpawnDispatch({
|
|
27
|
+
export function createSpawnDispatch({
|
|
28
|
+
registry,
|
|
29
|
+
terminalTrace,
|
|
30
|
+
sendFlow,
|
|
31
|
+
spawnFlow,
|
|
32
|
+
spawnResult,
|
|
33
|
+
listProviderModels = null,
|
|
34
|
+
}) {
|
|
10
35
|
// Explicit-tag spawn priority (auto nextTag always creates a fresh session):
|
|
11
36
|
// 1) live + busy -> queue the prompt (reuse)
|
|
12
37
|
// 2) live + idle -> continue existing session (reuse)
|
|
@@ -26,7 +51,12 @@ export function createSpawnDispatch({ registry, terminalTrace, sendFlow, spawnFl
|
|
|
26
51
|
}
|
|
27
52
|
if (liveSessionId && registry.getLiveSession(liveSessionId)) {
|
|
28
53
|
const prepared = await sendFlow.prepareSend({ ...args, tag: explicitTag }, scopedContext);
|
|
29
|
-
|
|
54
|
+
const route = requestedRoute(args);
|
|
55
|
+
return {
|
|
56
|
+
reused: sendFlow.dispatchToExistingSession(route ? { ...prepared, route } : prepared, notifyContext, {
|
|
57
|
+
reused: true,
|
|
58
|
+
}),
|
|
59
|
+
};
|
|
30
60
|
}
|
|
31
61
|
if (terminalTrace.hasTerminalTrace(explicitTag, scopedContext)) {
|
|
32
62
|
terminalTrace.reapTerminalTraceForTag(explicitTag, scopedContext);
|
|
@@ -52,7 +82,10 @@ export function createSpawnDispatch({ registry, terminalTrace, sendFlow, spawnFl
|
|
|
52
82
|
return { spawnArgs: args, respawned: false };
|
|
53
83
|
}
|
|
54
84
|
|
|
55
|
-
async function spawn(
|
|
85
|
+
async function spawn(requestArgs, request) {
|
|
86
|
+
// Resolve a user-pinned model before deferring, so a miss or an ambiguous
|
|
87
|
+
// name answers this call instead of failing the background job.
|
|
88
|
+
const args = await resolveRequestedModel(requestArgs, listProviderModels);
|
|
56
89
|
const explicitTag = clean(args.tag);
|
|
57
90
|
let spawnArgs = args;
|
|
58
91
|
let respawned = false;
|
|
@@ -17,6 +17,7 @@ export function createAgentExecute({
|
|
|
17
17
|
sendFlow,
|
|
18
18
|
closeFlow,
|
|
19
19
|
terminalTrace,
|
|
20
|
+
listProviderModels = null,
|
|
20
21
|
}) {
|
|
21
22
|
const spawnResult = (job) => renderResult(views.renderJob(job, false));
|
|
22
23
|
|
|
@@ -30,7 +31,14 @@ export function createAgentExecute({
|
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
const { send } = createSendDispatch({ registry, defaultCwd, sendFlow, spawnFlow, spawnResult });
|
|
33
|
-
const { spawn } = createSpawnDispatch({
|
|
34
|
+
const { spawn } = createSpawnDispatch({
|
|
35
|
+
registry,
|
|
36
|
+
terminalTrace,
|
|
37
|
+
sendFlow,
|
|
38
|
+
spawnFlow,
|
|
39
|
+
spawnResult,
|
|
40
|
+
listProviderModels,
|
|
41
|
+
});
|
|
34
42
|
|
|
35
43
|
return async function execute(args = {}, context = {}) {
|
|
36
44
|
try {
|
|
@@ -316,29 +316,52 @@ function agentDefinitionFiles(cleanAgent, dataDir, standaloneSourceRoot) {
|
|
|
316
316
|
return candidates;
|
|
317
317
|
}
|
|
318
318
|
|
|
319
|
-
|
|
319
|
+
const _frontmatterFirstResponseCache = new Map(); // key -> { value, atMs }
|
|
320
|
+
|
|
321
|
+
// The first definition (in precedence order) whose frontmatter yields a value
|
|
322
|
+
// through `pick`, cached per agent for the frontmatter TTL.
|
|
323
|
+
function cachedFrontmatterValue(cache, agent, dataDir, standaloneSourceRoot, pick) {
|
|
320
324
|
const cleanAgent = clean(agent);
|
|
321
325
|
if (!cleanAgent) return null;
|
|
322
326
|
if (agentDeleted(cleanAgent, dataDir)) return null;
|
|
323
327
|
const cacheKey = `${dataDir || ''}\u0000${cleanAgent}`;
|
|
324
|
-
const cached =
|
|
328
|
+
const cached = cache.get(cacheKey);
|
|
325
329
|
if (cached && Date.now() - cached.atMs < FRONTMATTER_PERM_CACHE_TTL_MS) {
|
|
326
330
|
return cached.value;
|
|
327
331
|
}
|
|
328
332
|
let resolved = null;
|
|
329
333
|
for (const file of agentDefinitionFiles(cleanAgent, dataDir, standaloneSourceRoot)) {
|
|
330
334
|
if (!existsSync(file)) continue;
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
resolved = permission;
|
|
335
|
+
const value = pick(parseMarkdownFrontmatter(readFileSync(file, 'utf8')));
|
|
336
|
+
if (value != null) {
|
|
337
|
+
resolved = value;
|
|
335
338
|
break;
|
|
336
339
|
}
|
|
337
340
|
}
|
|
338
|
-
|
|
341
|
+
cache.set(cacheKey, { value: resolved, atMs: Date.now() });
|
|
339
342
|
return resolved;
|
|
340
343
|
}
|
|
341
344
|
|
|
345
|
+
export function readAgentFrontmatterPermission(agent, dataDir, standaloneSourceRoot) {
|
|
346
|
+
return cachedFrontmatterValue(
|
|
347
|
+
_frontmatterPermCache,
|
|
348
|
+
agent,
|
|
349
|
+
dataDir,
|
|
350
|
+
standaloneSourceRoot,
|
|
351
|
+
(fm) => normalizeAgentPermissionOrNone(fm.permission) || null
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** The agent definition's `firstResponseTimeoutMs` (a non-negative integer;
|
|
356
|
+
* 0 disables the first-response deadline), or null when it sets none. */
|
|
357
|
+
export function readAgentFirstResponseTimeoutMs(agent, dataDir, standaloneSourceRoot) {
|
|
358
|
+
return cachedFrontmatterValue(_frontmatterFirstResponseCache, agent, dataDir, standaloneSourceRoot, (fm) => {
|
|
359
|
+
const raw = String(fm.firstResponseTimeoutMs ?? '').trim();
|
|
360
|
+
const ms = Number(raw);
|
|
361
|
+
return raw && Number.isFinite(ms) && ms >= 0 ? Math.floor(ms) : null;
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
|
|
342
365
|
// Agents are global definitions (agents/<id>/ under the data dir or the
|
|
343
366
|
// shipped source root). A spawn of an id with no definition anywhere —
|
|
344
367
|
// typically a custom agent deleted in settings — must fail loudly instead of
|
|
@@ -57,13 +57,18 @@ export function terminalResultHook({ job, turnReview, completionValue, notifyEar
|
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
/** Watchdog stall that still recovered a partial handoff:
|
|
60
|
+
/** Watchdog stall that still recovered a partial handoff: the turn never
|
|
61
|
+
* finished, so the owner is told it FAILED (stalled), with the partial
|
|
62
|
+
* output it produced before the stop. */
|
|
63
|
+
export const WATCHDOG_STOP_ERROR = 'stalled: the progress watchdog stopped the turn';
|
|
64
|
+
|
|
61
65
|
export function reconcileJobWatchdogPartial(job, value) {
|
|
62
66
|
if (!job?.taskId) return;
|
|
63
67
|
try {
|
|
64
68
|
reconcileBackgroundTask(job.taskId, {
|
|
65
|
-
status: '
|
|
69
|
+
status: 'failed',
|
|
66
70
|
result: value,
|
|
71
|
+
error: WATCHDOG_STOP_ERROR,
|
|
67
72
|
terminalReason: 'agent-watchdog-partial',
|
|
68
73
|
});
|
|
69
74
|
} catch {}
|
|
@@ -38,7 +38,7 @@ export function terminalJobFrozenFields(status, now = Date.now()) {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/** A worker/job row as the published session state carries it. That state
|
|
41
|
-
* (statusline, desktop, phone
|
|
41
|
+
* (statusline, desktop, phone) re-reads agent status on a
|
|
42
42
|
* 2s pulse, and these fields are the agent card's diagnostics, derived from
|
|
43
43
|
* the read time or the last stream delta: they changed on every read while
|
|
44
44
|
* nothing a surface shows did, so each pulse re-sent both row lists. Surfaces
|
|
@@ -64,7 +64,10 @@ export function createSessionProgress({ mgr }) {
|
|
|
64
64
|
const runtime = mgr.getSessionRuntime?.(sessionId) || null;
|
|
65
65
|
const snapshot =
|
|
66
66
|
typeof mgr.getSessionProgressSnapshot === 'function' ? mgr.getSessionProgressSnapshot(sessionId) : null;
|
|
67
|
-
|
|
67
|
+
// The armed watchdog's own policy (agent definition and provider budget
|
|
68
|
+
// applied); the role default only when none is registered.
|
|
69
|
+
const watchdogState = getProgressWatchdogState(mgr, sessionId);
|
|
70
|
+
const policy = watchdogState.policy || (role ? resolveAgentWatchdogPolicy(role) : null);
|
|
68
71
|
const queuedFollowups =
|
|
69
72
|
typeof mgr.getSessionPendingMessageDepth === 'function' ? mgr.getSessionPendingMessageDepth(sessionId) : null;
|
|
70
73
|
return buildAgentTaskProgressFields({
|
|
@@ -74,7 +77,7 @@ export function createSessionProgress({ mgr }) {
|
|
|
74
77
|
snapshot,
|
|
75
78
|
runtime,
|
|
76
79
|
policy,
|
|
77
|
-
watchdogState
|
|
80
|
+
watchdogState,
|
|
78
81
|
queuedFollowups,
|
|
79
82
|
taskStatus,
|
|
80
83
|
lastToolCall: runtime?.lastToolCall || null,
|
|
@@ -6,10 +6,9 @@ import { leadPoolTag } from '../worker-rows.mjs';
|
|
|
6
6
|
export const ACTIVE_LEAD_STATUS =
|
|
7
7
|
/^(?:connecting|requesting|streaming|tool[-_\s]?running|running|queued|pending|starting|cancelling)$/i;
|
|
8
8
|
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// keep claiming work the panel has already stopped believing.
|
|
9
|
+
// Recovery's freshness window: an active row whose turn is not in flight in
|
|
10
|
+
// this daemon is only believed while its own stamp sits inside this window
|
|
11
|
+
// (it covers a row written just before its turn's runtime entry exists).
|
|
13
12
|
export const LEAD_POOL_FRESH_MS = 2 * 60 * 1000;
|
|
14
13
|
|
|
15
14
|
export const isActiveLeadRow = (row) => ACTIVE_LEAD_STATUS.test(clean(row?.status || row?.stage));
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
// One reap timer per settled Lead row: fires at the row's reapAt
|
|
2
|
-
// the row
|
|
1
|
+
// One reap timer per settled Lead row: fires at the row's reapAt — never
|
|
2
|
+
// before the row has been listed in the Agents pane for its full visibility
|
|
3
|
+
// window — and removes the row only when it still carries that same deadline.
|
|
4
|
+
import { AGENT_PANE_VISIBLE_MS } from '../../../../runtime/shared/agent-reap-state.mjs';
|
|
3
5
|
import { clean } from '../helpers.mjs';
|
|
4
6
|
|
|
5
7
|
export function createLeadReapTimers({ removeRow }) {
|
|
@@ -18,7 +20,11 @@ export function createLeadReapTimers({ removeRow }) {
|
|
|
18
20
|
const reapAt = clean(row?.reapAt);
|
|
19
21
|
if (!sessionId || !reapAt) return;
|
|
20
22
|
cancel(sessionId);
|
|
21
|
-
|
|
23
|
+
// The provider reap window may be shorter than the pane window; deleting
|
|
24
|
+
// the row then would drop a finished Lead the pane still has to show.
|
|
25
|
+
const finishedMs = Date.parse(clean(row.finishedAt)) || Date.parse(clean(row.updatedAt)) || 0;
|
|
26
|
+
const deadline = Math.max(Date.parse(reapAt) || 0, finishedMs + AGENT_PANE_VISIBLE_MS);
|
|
27
|
+
const delay = Math.max(0, deadline - Date.now());
|
|
22
28
|
const handle = setTimeout(() => {
|
|
23
29
|
reapTimers.delete(sessionId);
|
|
24
30
|
removeRow(sessionId, reapAt);
|
|
@@ -1,34 +1,23 @@
|
|
|
1
1
|
// When an active Lead row is no longer believable, and how it settles to idle:
|
|
2
|
-
// runtime liveness, the
|
|
3
|
-
// terminal reap deadline from config.
|
|
4
|
-
import { statSync } from 'node:fs';
|
|
5
|
-
import { resolve } from 'node:path';
|
|
2
|
+
// runtime liveness, the daemon's in-memory turn state, the stamp freshness
|
|
3
|
+
// window, and the terminal reap deadline from config.
|
|
6
4
|
import { clean, runtimeAlive } from '../helpers.mjs';
|
|
7
5
|
import { createRowLiveness } from '../worker-index/row-liveness.mjs';
|
|
8
6
|
import { isActiveLeadRow, LEAD_POOL_FRESH_MS } from './lead-rows.mjs';
|
|
9
7
|
|
|
10
|
-
|
|
8
|
+
/** `isSessionRunning(sessionId)`: whether that Lead's turn is in flight in
|
|
9
|
+
* this process (every session runs inline in the daemon). */
|
|
10
|
+
export function createRowSettlement({ cfgMod, isSessionRunning = () => false }) {
|
|
11
11
|
// Lead rows settle to idle exactly like worker rows: same stamps, same
|
|
12
12
|
// config-driven terminal reap deadline.
|
|
13
|
-
const { idleRow } = createRowLiveness({
|
|
14
|
-
|
|
15
|
-
function leadHeartbeatFresh(sessionId, now) {
|
|
16
|
-
const id = clean(sessionId);
|
|
17
|
-
if (!dataDir || !id) return false;
|
|
18
|
-
try {
|
|
19
|
-
const mtimeMs = statSync(resolve(dataDir, 'sessions', `${id}.hb`)).mtimeMs || 0;
|
|
20
|
-
return mtimeMs > 0 && now - mtimeMs <= LEAD_POOL_FRESH_MS;
|
|
21
|
-
} catch {
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
13
|
+
const { idleRow } = createRowLiveness({ cfgMod });
|
|
25
14
|
|
|
26
15
|
function staleActiveLeadRow(row, now) {
|
|
27
16
|
if (!isActiveLeadRow(row)) return false;
|
|
28
17
|
// The runtime that stamped the turn is gone: no wall-clock window can make
|
|
29
18
|
// that row true again, so the panel must not wait one out.
|
|
30
19
|
if (!runtimeAlive(row.runtimePid)) return true;
|
|
31
|
-
if (
|
|
20
|
+
if (isSessionRunning(clean(row.sessionId))) return false;
|
|
32
21
|
const updated = Date.parse(clean(row.updatedAt)) || 0;
|
|
33
22
|
return !(updated > 0 && now - updated <= LEAD_POOL_FRESH_MS);
|
|
34
23
|
}
|
|
@@ -17,11 +17,11 @@ import { createRowSettlement } from './lead-worker-index/row-settlement.mjs';
|
|
|
17
17
|
import { createLeadReapTimers } from './lead-worker-index/reap-timers.mjs';
|
|
18
18
|
import { createForgottenLeads } from './lead-worker-index/forgotten-leads.mjs';
|
|
19
19
|
|
|
20
|
-
export function createLeadWorkerIndex({ dataDir, cfgMod, workerRowFromSession }) {
|
|
20
|
+
export function createLeadWorkerIndex({ dataDir, cfgMod, workerRowFromSession, isSessionRunning }) {
|
|
21
21
|
const activeLeadSessions = new Set();
|
|
22
22
|
const index = createLeadIndexFile({ dataDir });
|
|
23
23
|
const forgotten = createForgottenLeads(dataDir);
|
|
24
|
-
const settlement = createRowSettlement({
|
|
24
|
+
const settlement = createRowSettlement({ cfgMod, isSessionRunning });
|
|
25
25
|
const reaps = createLeadReapTimers({ removeRow: (sessionId, reapAt) => removeLeadWorkerRow(sessionId, reapAt) });
|
|
26
26
|
|
|
27
27
|
function removeLeadWorkerRow(sessionId, expectedReapAt = '') {
|
|
@@ -73,8 +73,11 @@ export function createLeadWorkerIndex({ dataDir, cfgMod, workerRowFromSession })
|
|
|
73
73
|
updatedAt: new Date(now).toISOString(),
|
|
74
74
|
});
|
|
75
75
|
if (!row) return false;
|
|
76
|
+
const settled = !ACTIVE_LEAD_STATUS.test(status) && !ACTIVE_LEAD_STATUS.test(stage);
|
|
76
77
|
const normalized = {
|
|
77
78
|
...row,
|
|
79
|
+
// The pane lists a settled Lead for a fixed window from this stamp.
|
|
80
|
+
finishedAt: settled ? row.finishedAt || new Date(now).toISOString() : row.finishedAt,
|
|
78
81
|
// Liveness identity of the runtime that owns this status. A row stamped
|
|
79
82
|
// by a process that no longer exists is recovered on the next boot.
|
|
80
83
|
runtimePid: process.pid,
|
|
@@ -89,12 +92,12 @@ export function createLeadWorkerIndex({ dataDir, cfgMod, workerRowFromSession })
|
|
|
89
92
|
},
|
|
90
93
|
{ rerun: true }
|
|
91
94
|
);
|
|
92
|
-
if (
|
|
93
|
-
activeLeadSessions.add(session.id);
|
|
94
|
-
reaps.cancel(session.id);
|
|
95
|
-
} else {
|
|
95
|
+
if (settled) {
|
|
96
96
|
activeLeadSessions.delete(session.id);
|
|
97
97
|
reaps.schedule(normalized);
|
|
98
|
+
} else {
|
|
99
|
+
activeLeadSessions.add(session.id);
|
|
100
|
+
reaps.cancel(session.id);
|
|
98
101
|
}
|
|
99
102
|
return true;
|
|
100
103
|
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// One-off model selection for a spawn the user explicitly pinned to a model.
|
|
2
|
+
// The agent's preset route stays the default; this only runs when `model` is
|
|
3
|
+
// passed. The query is matched against the live provider catalog — exact id,
|
|
4
|
+
// then exact display name, then every query word — and a catalog miss retries
|
|
5
|
+
// once on a refreshed catalog. One match runs; several or none fail with
|
|
6
|
+
// candidates instead of substituting another model.
|
|
7
|
+
import { clean } from './helpers.mjs';
|
|
8
|
+
|
|
9
|
+
const CANDIDATE_LIMIT = 8;
|
|
10
|
+
|
|
11
|
+
const norm = (value) =>
|
|
12
|
+
String(value || '')
|
|
13
|
+
.toLowerCase()
|
|
14
|
+
.replace(/[^a-z0-9]+/g, '');
|
|
15
|
+
const terms = (value) =>
|
|
16
|
+
String(value || '')
|
|
17
|
+
.toLowerCase()
|
|
18
|
+
.split(/\s+/)
|
|
19
|
+
.map(norm)
|
|
20
|
+
.filter(Boolean);
|
|
21
|
+
const label = (row) => `${row.provider}/${row.id}`;
|
|
22
|
+
|
|
23
|
+
function providerRows(rows, provider) {
|
|
24
|
+
if (!provider) return rows;
|
|
25
|
+
const wanted = norm(provider);
|
|
26
|
+
const exact = rows.filter((row) => norm(row.provider) === wanted);
|
|
27
|
+
return exact.length ? exact : rows.filter((row) => norm(row.provider).includes(wanted));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function matchModels(rows, query) {
|
|
31
|
+
const wanted = norm(query);
|
|
32
|
+
const words = terms(query);
|
|
33
|
+
// Nothing to match on ("???"): `[].every` would accept every row.
|
|
34
|
+
if (!words.length) return [];
|
|
35
|
+
const tiers = [
|
|
36
|
+
(row) => norm(row.id) === wanted,
|
|
37
|
+
(row) => norm(row.display) === wanted,
|
|
38
|
+
(row) => words.every((word) => `${norm(row.id)} ${norm(row.display)}`.includes(word)),
|
|
39
|
+
];
|
|
40
|
+
for (const test of tiers) {
|
|
41
|
+
const hits = rows.filter(test);
|
|
42
|
+
if (hits.length) return hits;
|
|
43
|
+
}
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function candidates(rows) {
|
|
48
|
+
const shown = rows.slice(0, CANDIDATE_LIMIT).map(label).join(', ');
|
|
49
|
+
return rows.length > CANDIDATE_LIMIT ? `${shown}, … (${rows.length} total)` : shown;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Resolve args.provider/args.model to one exact catalog route. Without a
|
|
53
|
+
* catalog (headless/daemon surfaces) exact provider + model pass through. */
|
|
54
|
+
export async function resolveRequestedModel(args, listProviderModels) {
|
|
55
|
+
const model = clean(args.model);
|
|
56
|
+
const provider = clean(args.provider);
|
|
57
|
+
if (!model) {
|
|
58
|
+
if (provider) throw new Error('agent spawn: provider requires model');
|
|
59
|
+
return args;
|
|
60
|
+
}
|
|
61
|
+
if (typeof listProviderModels !== 'function') {
|
|
62
|
+
if (!provider) throw new Error('agent spawn: model requires provider on this surface');
|
|
63
|
+
// Punctuation alone names no model; the catalog path rejects it the same way.
|
|
64
|
+
if (!terms(model).length) throw new Error(`agent spawn: model "${model}" for provider "${provider}" not found`);
|
|
65
|
+
return args;
|
|
66
|
+
}
|
|
67
|
+
let pool = providerRows(await listProviderModels(), provider);
|
|
68
|
+
let hits = matchModels(pool, model);
|
|
69
|
+
if (!hits.length) {
|
|
70
|
+
pool = providerRows(await listProviderModels({ force: true }), provider);
|
|
71
|
+
hits = matchModels(pool, model);
|
|
72
|
+
}
|
|
73
|
+
if (hits.length === 1) return { ...args, provider: hits[0].provider, model: hits[0].id };
|
|
74
|
+
const scope = provider ? ` for provider "${provider}"` : '';
|
|
75
|
+
if (hits.length > 1) {
|
|
76
|
+
throw new Error(`agent spawn: model "${model}"${scope} is ambiguous: ${candidates(hits)}; pass the exact one`);
|
|
77
|
+
}
|
|
78
|
+
if (!pool.length) {
|
|
79
|
+
throw new Error(`agent spawn: provider "${provider}" has no available models`);
|
|
80
|
+
}
|
|
81
|
+
throw new Error(`agent spawn: model "${model}"${scope} not found; available: ${candidates(pool)}`);
|
|
82
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
isAgentProgressWatchdogAbortError,
|
|
2
3
|
resolveAgentWatchdogPolicy,
|
|
3
4
|
resolveHandoffMessageStartIndex,
|
|
4
5
|
turnPartialHandoff,
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
terminalResultHook,
|
|
16
17
|
} from './job-task-reconcile.mjs';
|
|
17
18
|
import { createTurnReviewCollector } from './turn-review.mjs';
|
|
19
|
+
import { settledWorkerStatus } from './worker-index/row-liveness.mjs';
|
|
18
20
|
|
|
19
21
|
// `send` to an existing worker: resolve the live session, run one follow-up
|
|
20
22
|
// turn under the progress watchdog, and reconcile the job/worker row. Busy
|
|
@@ -28,7 +30,6 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
|
|
|
28
30
|
if (!sessionId) throw new Error(`agent send: target "${target}" not found`);
|
|
29
31
|
const session = mgr.getSession(sessionId);
|
|
30
32
|
if (!session || session.closed) throw new Error(`agent send: session "${sessionId}" is closed`);
|
|
31
|
-
registry.cancelReap(sessionId);
|
|
32
33
|
const prompt = await resolvePrompt(args, session.cwd || defaultCwd);
|
|
33
34
|
return { args, session, sessionId, prompt };
|
|
34
35
|
}
|
|
@@ -82,13 +83,18 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
|
|
|
82
83
|
const tag = registry.tagForSession(sessionId);
|
|
83
84
|
// Queued sends run as follow-up turns inside this same askSession call;
|
|
84
85
|
// the watchdog sweep re-stamps turnStartedAt at each turn boundary.
|
|
85
|
-
const
|
|
86
|
+
const watchdogPolicy = resolveAgentWatchdogPolicy(
|
|
87
|
+
sendAgent,
|
|
88
|
+
spawnFlow.agentWatchdogOverrides({ agent: sendAgent, provider: session.provider, model: session.model })
|
|
89
|
+
);
|
|
90
|
+
const watchdog = spawnFlow.startProgressIdleWatchdog(sessionId, watchdogPolicy, sendAgent, {
|
|
86
91
|
onTurnStart: spawnFlow.turnStartStamper(session, tag),
|
|
87
92
|
onProgress: spawnFlow.progressStamper(session, tag),
|
|
88
93
|
});
|
|
89
94
|
const turnReview = createTurnReviewCollector(session, tag, sendAgent, notifyContext || {});
|
|
90
95
|
const completionValue = completionValueFor({ session, tag, sessionId, sendAgent });
|
|
91
96
|
let finalStatus = 'idle';
|
|
97
|
+
let stalled = false;
|
|
92
98
|
registry.upsertWorkerSessionDeferred(session, tag, {
|
|
93
99
|
status: 'running',
|
|
94
100
|
stage: 'running',
|
|
@@ -129,6 +135,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
|
|
|
129
135
|
settleCancelled(error);
|
|
130
136
|
throw error;
|
|
131
137
|
}
|
|
138
|
+
stalled = isAgentProgressWatchdogAbortError(error);
|
|
132
139
|
const partial = watchdogPartialHandoffFromError(error, mgr.getSession(sessionId), handoffMsgStart);
|
|
133
140
|
if (partial) {
|
|
134
141
|
finalStatus = 'idle';
|
|
@@ -152,12 +159,10 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
|
|
|
152
159
|
turnReview.complete();
|
|
153
160
|
watchdog?.stop?.();
|
|
154
161
|
registry.upsertWorkerSessionDeferred(session, tag, {
|
|
155
|
-
|
|
156
|
-
stage: finalStatus,
|
|
162
|
+
...settledWorkerStatus(finalStatus, stalled),
|
|
157
163
|
finishedAt: new Date().toISOString(),
|
|
158
164
|
});
|
|
159
165
|
reconcileJobFinally(job, finalStatus);
|
|
160
|
-
registry.scheduleReap(sessionId);
|
|
161
166
|
// Same lifecycle as a fresh spawn: the transcript/tag stays resumable,
|
|
162
167
|
// while heavy process-local runtime state is reclaimed immediately.
|
|
163
168
|
try {
|
|
@@ -166,11 +171,24 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
|
|
|
166
171
|
}
|
|
167
172
|
}
|
|
168
173
|
|
|
174
|
+
// An explicit model on a reused tag goes through the session's own route
|
|
175
|
+
// API, which saves it and applies it from the session's next turn: the
|
|
176
|
+
// dispatched prompt when the session is idle, a later one while it is busy.
|
|
177
|
+
async function applyRequestedRoute(prepared) {
|
|
178
|
+
const { session, sessionId, route } = prepared;
|
|
179
|
+
if (!canUseSessionSurface(session) || typeof sessionSurface.setRoute !== 'function') {
|
|
180
|
+
throw new Error(`agent spawn: this surface cannot change the model of reused session "${sessionId}"`);
|
|
181
|
+
}
|
|
182
|
+
await sessionSurface.setRoute({ session, route });
|
|
183
|
+
return { ...prepared, session: mgr.getSession(sessionId) || session };
|
|
184
|
+
}
|
|
185
|
+
|
|
169
186
|
// Shared send dispatch for an already-resolved live session. Used by the
|
|
170
187
|
// `send` branch AND by the `spawn` branch when an explicit tag maps to a
|
|
171
188
|
// live session (reuse path). Busy sessions queue the prompt; idle ones run a
|
|
172
189
|
// background send job that continues the existing session (context kept).
|
|
173
|
-
async function dispatchToExistingSession(
|
|
190
|
+
async function dispatchToExistingSession(requested, notifyContext, extras = {}) {
|
|
191
|
+
const prepared = requested.route ? await applyRequestedRoute(requested) : requested;
|
|
174
192
|
const { session, sessionId, prompt } = prepared;
|
|
175
193
|
const tag = registry.tagForSession(sessionId);
|
|
176
194
|
if (canUseSessionSurface(session) && views.isSessionBusy(sessionId)) {
|
|
@@ -53,7 +53,9 @@ export function createJobStarter({ mgr, notifyStatusChange, notifySessionComplet
|
|
|
53
53
|
const currentMeta = task?.meta || jobMeta;
|
|
54
54
|
if (currentMeta?.sessionId) {
|
|
55
55
|
try {
|
|
56
|
-
Promise.resolve(mgr.closeSession(currentMeta.sessionId, 'agent-task-cancel')).catch(
|
|
56
|
+
Promise.resolve(mgr.closeSession(currentMeta.sessionId, 'agent-task-cancel', { tombstone: false })).catch(
|
|
57
|
+
() => {}
|
|
58
|
+
);
|
|
57
59
|
} catch {}
|
|
58
60
|
}
|
|
59
61
|
setImmediate(notifyStatusChange);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* route, and the transport prewarm. The validated spawn plan and the session
|
|
5
5
|
* spec it produces live in ./spawn-plan.mjs.
|
|
6
6
|
*/
|
|
7
|
-
import { presetKey, writeAgentStatuslineRoute } from '../helpers.mjs';
|
|
7
|
+
import { presetKey, readAgentFirstResponseTimeoutMs, writeAgentStatuslineRoute } from '../helpers.mjs';
|
|
8
8
|
import { resolveAgentWatchdogPolicy } from '../../../../runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs';
|
|
9
9
|
import { prepareAgentSession } from '../../../../runtime/agent/orchestrator/agent-runtime/session-builder.mjs';
|
|
10
10
|
import { getProvider } from '../../../../runtime/agent/orchestrator/providers/registry.mjs';
|
|
@@ -55,7 +55,6 @@ export function createSpawnPreparer({
|
|
|
55
55
|
resolveTag,
|
|
56
56
|
wantsSessionScan,
|
|
57
57
|
bindTag,
|
|
58
|
-
cancelReap,
|
|
59
58
|
ensureProvider,
|
|
60
59
|
sessionSurface = null,
|
|
61
60
|
refreshTagsFromSessions,
|
|
@@ -71,6 +70,19 @@ export function createSpawnPreparer({
|
|
|
71
70
|
wantsSessionScan,
|
|
72
71
|
});
|
|
73
72
|
|
|
73
|
+
/** Watchdog inputs for one agent run: the agent definition's own
|
|
74
|
+
* first-response deadline and the provider's first-response budget for the
|
|
75
|
+
* routed model (headers, and first output), handed to
|
|
76
|
+
* resolveAgentWatchdogPolicy. A provider on the shared window names none. */
|
|
77
|
+
function agentWatchdogOverrides({ agent, provider, model }) {
|
|
78
|
+
const budget = getProvider(provider)?.firstResponseBudget?.(model);
|
|
79
|
+
return {
|
|
80
|
+
firstResponseTimeoutMs: readAgentFirstResponseTimeoutMs(agent, dataDir, STANDALONE_SOURCE_ROOT) ?? undefined,
|
|
81
|
+
providerFirstByteTimeoutMs: budget?.transportMs,
|
|
82
|
+
providerFirstOutputTimeoutMs: budget?.semanticMs,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
74
86
|
/** Shared post-create wiring. Lead sessions write a gateway-session route on
|
|
75
87
|
* create; agent sessions are built through prepareAgentSession()/the remote
|
|
76
88
|
* runtime, so mirror that registration here or the vendored L1/L2
|
|
@@ -79,7 +91,6 @@ export function createSpawnPreparer({
|
|
|
79
91
|
const { agent, presetName, preset, tag } = plan;
|
|
80
92
|
writeAgentStatuslineRoute(session.id, preset);
|
|
81
93
|
bindTag(tag, session, { ...presetDescriptor(agent, preset, presetName), status: 'idle', stage: 'idle' });
|
|
82
|
-
cancelReap(session.id);
|
|
83
94
|
}
|
|
84
95
|
|
|
85
96
|
async function createSpawnedSession(plan, spec, prepState) {
|
|
@@ -127,7 +138,10 @@ export function createSpawnPreparer({
|
|
|
127
138
|
presetName: plan.presetName,
|
|
128
139
|
workerCwd: effectiveCwd || plan.workerCwd,
|
|
129
140
|
prompt: plan.prompt,
|
|
130
|
-
watchdogPolicy: resolveAgentWatchdogPolicy(
|
|
141
|
+
watchdogPolicy: resolveAgentWatchdogPolicy(
|
|
142
|
+
plan.agent,
|
|
143
|
+
agentWatchdogOverrides({ agent: plan.agent, provider: plan.preset.provider, model: plan.preset.model })
|
|
144
|
+
),
|
|
131
145
|
};
|
|
132
146
|
}
|
|
133
147
|
|
|
@@ -136,5 +150,5 @@ export function createSpawnPreparer({
|
|
|
136
150
|
return prepareSpawnInProcess(args, callerCwd, context, prepState);
|
|
137
151
|
}
|
|
138
152
|
|
|
139
|
-
return { prepareSpawn, prepareSpawnInProcess, createSpawnedSession };
|
|
153
|
+
return { prepareSpawn, prepareSpawnInProcess, createSpawnedSession, agentWatchdogOverrides };
|
|
140
154
|
}
|
|
@@ -15,11 +15,13 @@ import {
|
|
|
15
15
|
import { abnormalEmptyFinishError } from '../render.mjs';
|
|
16
16
|
import { createProgressWatchdogRegistry } from '../../agent-watchdog-registry.mjs';
|
|
17
17
|
import {
|
|
18
|
+
isAgentProgressWatchdogAbortError,
|
|
18
19
|
resolveHandoffMessageStartIndex,
|
|
19
20
|
turnPartialHandoff,
|
|
20
21
|
watchdogPartialHandoffFromError,
|
|
21
22
|
watchdogStoppedHandoff,
|
|
22
23
|
} from '../../../../runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs';
|
|
24
|
+
import { settledWorkerStatus } from '../worker-index/row-liveness.mjs';
|
|
23
25
|
import { saveSessionAsync } from '../../../../runtime/agent/orchestrator/session/store.mjs';
|
|
24
26
|
import { presetDescriptor } from './spawn-prep.mjs';
|
|
25
27
|
import { workerStageForStatus } from '../worker-rows.mjs';
|
|
@@ -35,7 +37,6 @@ export function createSpawnRunner({
|
|
|
35
37
|
notifyStatusChange = () => {},
|
|
36
38
|
notifySessionCompletion,
|
|
37
39
|
emitSubagentEvent,
|
|
38
|
-
scheduleReap,
|
|
39
40
|
sessionSurface = null,
|
|
40
41
|
createTurnReviewCollector,
|
|
41
42
|
}) {
|
|
@@ -128,6 +129,7 @@ export function createSpawnRunner({
|
|
|
128
129
|
const turnReview = createTurnReviewCollector(session, tag, agent, notifyContext || {});
|
|
129
130
|
const completionValue = completionValueFor(prepared);
|
|
130
131
|
let finalStatus = 'idle';
|
|
132
|
+
let stalled = false;
|
|
131
133
|
// SubagentStart: a worker session is about to run its first turn.
|
|
132
134
|
emitSubagentEvent('start', agent, { session_id: session.id, tag });
|
|
133
135
|
upsertWorkerSessionDeferred(session, tag, {
|
|
@@ -189,6 +191,7 @@ export function createSpawnRunner({
|
|
|
189
191
|
settleCancelled(error);
|
|
190
192
|
throw error;
|
|
191
193
|
}
|
|
194
|
+
stalled = isAgentProgressWatchdogAbortError(error);
|
|
192
195
|
const partial = watchdogPartialHandoffFromError(error, mgr.getSession(session.id), handoffMsgStart);
|
|
193
196
|
if (partial) {
|
|
194
197
|
finalStatus = 'idle';
|
|
@@ -211,13 +214,11 @@ export function createSpawnRunner({
|
|
|
211
214
|
watchdog?.stop?.();
|
|
212
215
|
upsertWorkerSessionDeferred(session, tag, {
|
|
213
216
|
...presetDescriptor(agent, preset, presetName),
|
|
214
|
-
|
|
215
|
-
stage: finalStatus,
|
|
217
|
+
...settledWorkerStatus(finalStatus, stalled),
|
|
216
218
|
finishedAt: new Date().toISOString(),
|
|
217
219
|
});
|
|
218
220
|
setImmediate(notifyStatusChange);
|
|
219
221
|
reconcileJobFinally(job, finalStatus);
|
|
220
|
-
scheduleReap(session.id);
|
|
221
222
|
// SubagentStop: worker finished (terminal), regardless of outcome.
|
|
222
223
|
emitSubagentEvent('stop', agent, { session_id: session.id, tag, status: finalStatus });
|
|
223
224
|
// Keep the durable session/tag for same-tag follow-ups, but release every
|
|
@@ -14,7 +14,7 @@ export function createSpawnFlow(deps) {
|
|
|
14
14
|
notifyStatusChange: deps.notifyStatusChange ?? (() => {}),
|
|
15
15
|
notifySessionCompletion: deps.notifySessionCompletion,
|
|
16
16
|
});
|
|
17
|
-
const { prepareSpawn, prepareSpawnInProcess } = createSpawnPreparer(deps);
|
|
17
|
+
const { prepareSpawn, prepareSpawnInProcess, agentWatchdogOverrides } = createSpawnPreparer(deps);
|
|
18
18
|
const runner = createSpawnRunner(deps);
|
|
19
19
|
const { closePreparedSpawn, startDeferredSpawnJob } = createDeferredSpawn({
|
|
20
20
|
...deps,
|
|
@@ -35,6 +35,7 @@ export function createSpawnFlow(deps) {
|
|
|
35
35
|
progressStamper: runner.progressStamper,
|
|
36
36
|
prepareSpawn,
|
|
37
37
|
prepareSpawnInProcess,
|
|
38
|
+
agentWatchdogOverrides,
|
|
38
39
|
runSpawn: runner.runSpawn,
|
|
39
40
|
};
|
|
40
41
|
}
|