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
|
@@ -9,20 +9,34 @@
|
|
|
9
9
|
import { mediaError } from './lanes.mjs';
|
|
10
10
|
|
|
11
11
|
const CREDIT_HINTS = /credit|spending limit|billing|quota|insufficient|payment/i;
|
|
12
|
+
// Subscription usage caps (ChatGPT plan windows), as opposed to short-lived
|
|
13
|
+
// rate limiting: retrying in a moment does not help until the window resets.
|
|
14
|
+
const USAGE_LIMIT = /usage_?limit/i;
|
|
12
15
|
|
|
13
|
-
function
|
|
16
|
+
function parseJson(text) {
|
|
14
17
|
try {
|
|
15
|
-
|
|
16
|
-
const message = parsed?.error?.message || parsed?.error || parsed?.message;
|
|
17
|
-
return typeof message === 'string' ? message : '';
|
|
18
|
+
return JSON.parse(text);
|
|
18
19
|
} catch {
|
|
19
|
-
return
|
|
20
|
+
return null;
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
function reason(text) {
|
|
25
|
+
const parsed = parseJson(text);
|
|
26
|
+
const message = parsed?.error?.message || parsed?.error || parsed?.message;
|
|
27
|
+
return typeof message === 'string' ? message : '';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Raw bodies are only echoed when they are short plain text; HTML error pages
|
|
31
|
+
// and other markup never reach the Studio.
|
|
32
|
+
function rawDetail(text) {
|
|
33
|
+
const raw = String(text || '').trim();
|
|
34
|
+
return raw && !raw.startsWith('<') ? raw.slice(0, 300) : '';
|
|
35
|
+
}
|
|
36
|
+
|
|
23
37
|
/** Build the error a lane throws for a non-OK upstream response. */
|
|
24
38
|
export function upstreamError(label, status, text) {
|
|
25
|
-
const detail = reason(text) ||
|
|
39
|
+
const detail = reason(text) || rawDetail(text);
|
|
26
40
|
if (status === 401 || status === 403) {
|
|
27
41
|
if (CREDIT_HINTS.test(detail)) {
|
|
28
42
|
return mediaError(`${label}: account has no usable balance — ${detail}`, 'MEDIA_BILLING_BLOCKED', status);
|
|
@@ -41,3 +55,55 @@ export function upstreamError(label, status, text) {
|
|
|
41
55
|
}
|
|
42
56
|
return mediaError(`${label} failed (${status})${detail ? `: ${detail}` : ''}`, 'MEDIA_UPSTREAM_FAILED', status);
|
|
43
57
|
}
|
|
58
|
+
|
|
59
|
+
const header = (headers, name) => String(headers?.get?.(name) || '').trim();
|
|
60
|
+
const epochSeconds = (value) => (Number.isFinite(Number(value)) && Number(value) > 0 ? Math.trunc(Number(value)) : 0);
|
|
61
|
+
|
|
62
|
+
// Latest reset among the exhausted windows advertised in the rate-limit
|
|
63
|
+
// headers. The family is named after the active limit, with the plain codex
|
|
64
|
+
// family as the fallback the backend also sends.
|
|
65
|
+
function headerResetAt(headers, limitId) {
|
|
66
|
+
const families = new Set([limitId && `x-${limitId.toLowerCase().replace(/_/g, '-')}`, 'x-codex'].filter(Boolean));
|
|
67
|
+
let latest = 0;
|
|
68
|
+
for (const family of families) {
|
|
69
|
+
for (const window of ['primary', 'secondary']) {
|
|
70
|
+
const used = Number(header(headers, `${family}-${window}-used-percent`));
|
|
71
|
+
const resetAt = epochSeconds(header(headers, `${family}-${window}-reset-at`));
|
|
72
|
+
if (used >= 100 && resetAt > latest) latest = resetAt;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return latest || null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Recognize a subscription usage-limit failure. `error` is the upstream error
|
|
80
|
+
* object (`{ type, code, resets_at }`), from an HTTP body or a stream event.
|
|
81
|
+
* Returns `{ limitId, resetsAt }` (epoch seconds or null), or null when the
|
|
82
|
+
* failure is something else.
|
|
83
|
+
*/
|
|
84
|
+
export function usageLimitInfo(error, headers) {
|
|
85
|
+
const kinds = [error?.type, error?.code, header(headers, 'x-codex-rate-limit-reached-type')];
|
|
86
|
+
if (!kinds.some((kind) => typeof kind === 'string' && USAGE_LIMIT.test(kind))) return null;
|
|
87
|
+
const limitId = header(headers, 'x-codex-active-limit') || String(error?.limit_id || error?.metered_feature || '');
|
|
88
|
+
return { limitId, resetsAt: epochSeconds(error?.resets_at) || headerResetAt(headers, limitId) };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** usageLimitInfo for a non-OK HTTP response; only 429s are usage limits. */
|
|
92
|
+
export function usageLimitFromResponse(status, text, headers) {
|
|
93
|
+
if (status !== 429) return null;
|
|
94
|
+
const parsed = parseJson(text);
|
|
95
|
+
return usageLimitInfo(parsed?.error && typeof parsed.error === 'object' ? parsed.error : parsed, headers);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function formatResetAt(seconds) {
|
|
99
|
+
return `${new Date(seconds * 1000).toISOString().slice(0, 16).replace('T', ' ')} UTC`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** The error a lane throws when the subscription's usage window is exhausted. */
|
|
103
|
+
export function usageLimitError(label, { limitId = '', resetsAt = null } = {}) {
|
|
104
|
+
const what = /image/i.test(limitId) ? 'image generation usage limit reached' : 'usage limit reached';
|
|
105
|
+
const when = resetsAt ? `resets ${formatResetAt(resetsAt)}` : 'try again after the usage window resets';
|
|
106
|
+
const err = mediaError(`${label}: ${what} — ${when}`, 'MEDIA_USAGE_LIMIT', 429);
|
|
107
|
+
if (resetsAt) err.resetsAt = new Date(resetsAt * 1000).toISOString();
|
|
108
|
+
return err;
|
|
109
|
+
}
|
|
@@ -69,6 +69,7 @@ export function cwdFromTranscriptPath(fp) {
|
|
|
69
69
|
* prefix envelopes, drops synthetic reference-files/compaction/ack/
|
|
70
70
|
* internal-notification rows). */
|
|
71
71
|
export function transcriptRowFromLine(parsed) {
|
|
72
|
+
if (parsed.memoryEligible === false) return null;
|
|
72
73
|
const role =
|
|
73
74
|
parsed.message?.role ?? (parsed.type === 'user' || parsed.type === 'assistant' ? parsed.type : undefined);
|
|
74
75
|
if (role !== 'user' && role !== 'assistant') return null;
|
|
@@ -667,13 +667,11 @@ async function listPostmasterRows() {
|
|
|
667
667
|
}
|
|
668
668
|
const stdout = await execFileText('ps', ['-eo', 'pid=,etimes=,args='], { timeout: 15_000 });
|
|
669
669
|
if (stdout === null) return [];
|
|
670
|
-
return stdout
|
|
671
|
-
.
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
return [{ pid: Number(match[1]), uptimeSec: Number(match[2]), args: match[3] }];
|
|
676
|
-
});
|
|
670
|
+
return stdout.split(/\r?\n/).flatMap((line) => {
|
|
671
|
+
const match = line.match(/^\s*(\d+)\s+(\d+)\s+(.*postgres.*)$/);
|
|
672
|
+
if (!match) return [];
|
|
673
|
+
return [{ pid: Number(match[1]), uptimeSec: Number(match[2]), args: match[3] }];
|
|
674
|
+
});
|
|
677
675
|
}
|
|
678
676
|
|
|
679
677
|
const PRISTINE_ROOT_PREFIX = 'mixdog-headless-pristine-';
|
|
@@ -828,7 +828,10 @@ export function stopPgForShutdownSync() {
|
|
|
828
828
|
} catch {}
|
|
829
829
|
// The postmaster is gone, so drop its advert too (same guarded clear as the
|
|
830
830
|
// async path: never another live owner's); otherwise pg.json outlives the run.
|
|
831
|
-
patchActiveInstance(
|
|
831
|
+
patchActiveInstance(
|
|
832
|
+
{ pg_port: null, pg_started_at: null, pg_pgdata: null, pg_runtime_dir: null },
|
|
833
|
+
{ timeoutMs: 1000 }
|
|
834
|
+
);
|
|
832
835
|
}
|
|
833
836
|
|
|
834
837
|
// ── Owned-cluster shutdown (a host that starts PG through its stores) ────────
|
|
@@ -39,7 +39,7 @@ export async function runDocxHtmlAuthoring(html, output, { target, signal = null
|
|
|
39
39
|
const scratch = await mkdtemp(join(tmpdir(), 'mixdog-docx-captures-'));
|
|
40
40
|
let browser;
|
|
41
41
|
try {
|
|
42
|
-
browser = await launchHtmlBrowser('docx-html-browser');
|
|
42
|
+
browser = await launchHtmlBrowser('docx-html-browser', { signal });
|
|
43
43
|
} catch (error) {
|
|
44
44
|
await rm(scratch, { recursive: true, force: true }).catch(() => {});
|
|
45
45
|
return htmlFailure(error, startedAt);
|
|
@@ -2,17 +2,25 @@
|
|
|
2
2
|
// deadline and abort wiring around the layout work, the failure result, and the photographs of captured elements.
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
buildPuppeteerLaunchArgs,
|
|
7
|
+
launchPuppeteerBrowser,
|
|
8
|
+
resolveBrowserLaunchOptions,
|
|
9
|
+
} from '../../shared/browser-launch.mjs';
|
|
6
10
|
import { startChildGuardian } from '../../shared/child-guardian.mjs';
|
|
7
11
|
|
|
8
12
|
/** Launches the local browser the HTML is laid out in, under a guardian that reaps it with this process. */
|
|
9
|
-
export async function launchHtmlBrowser(label) {
|
|
13
|
+
export async function launchHtmlBrowser(label, { signal = null } = {}) {
|
|
10
14
|
const puppeteer = (await import('puppeteer-core')).default;
|
|
11
|
-
const browser = await
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
const browser = await launchPuppeteerBrowser(
|
|
16
|
+
puppeteer,
|
|
17
|
+
{
|
|
18
|
+
headless: true,
|
|
19
|
+
...resolveBrowserLaunchOptions(),
|
|
20
|
+
args: buildPuppeteerLaunchArgs(['--font-render-hinting=none']),
|
|
21
|
+
},
|
|
22
|
+
{ signal }
|
|
23
|
+
);
|
|
16
24
|
try {
|
|
17
25
|
startChildGuardian({ childPid: browser.process?.()?.pid, label });
|
|
18
26
|
} catch {}
|
|
@@ -22,7 +30,9 @@ export async function launchHtmlBrowser(label) {
|
|
|
22
30
|
/** Runs `work` against the browser under a deadline and an abort signal, and closes the browser afterwards. */
|
|
23
31
|
export async function runInBrowser(browser, { signal, timeoutMs }, work) {
|
|
24
32
|
const abort = () => browser.close().catch(() => {});
|
|
25
|
-
|
|
33
|
+
// A cancel that landed while the browser was launching closes it at once.
|
|
34
|
+
if (signal?.aborted) abort();
|
|
35
|
+
else signal?.addEventListener('abort', abort, { once: true });
|
|
26
36
|
let timer = null;
|
|
27
37
|
const running = work();
|
|
28
38
|
const timeout = new Promise((_, reject) => {
|
|
@@ -262,7 +262,7 @@ export async function printHtmlPdf(
|
|
|
262
262
|
await rm(output, { force: true });
|
|
263
263
|
let browser;
|
|
264
264
|
try {
|
|
265
|
-
browser = await launchHtmlBrowser('pdf-html-browser');
|
|
265
|
+
browser = await launchHtmlBrowser('pdf-html-browser', { signal });
|
|
266
266
|
} catch (error) {
|
|
267
267
|
return htmlFailure(error, startedAt);
|
|
268
268
|
}
|
|
@@ -559,7 +559,7 @@ export async function measureHtmlDeck(
|
|
|
559
559
|
{ sourcePath, shotPath, timeoutMs = 90_000, signal = null, prepare = null }
|
|
560
560
|
) {
|
|
561
561
|
await writeFile(sourcePath, html, 'utf8');
|
|
562
|
-
const browser = await launchHtmlBrowser('pptx-html-browser');
|
|
562
|
+
const browser = await launchHtmlBrowser('pptx-html-browser', { signal });
|
|
563
563
|
const work = async () => {
|
|
564
564
|
const page = await browser.newPage();
|
|
565
565
|
await page.setViewport(viewport(HTML_CANVAS, 1));
|
|
@@ -66,7 +66,7 @@ export async function runXlsxHtmlAuthoring(html, output, { target, signal = null
|
|
|
66
66
|
const scratch = await mkdtemp(join(tmpdir(), 'mixdog-xlsx-captures-'));
|
|
67
67
|
let browser;
|
|
68
68
|
try {
|
|
69
|
-
browser = await launchHtmlBrowser('xlsx-html-browser');
|
|
69
|
+
browser = await launchHtmlBrowser('xlsx-html-browser', { signal });
|
|
70
70
|
} catch (error) {
|
|
71
71
|
await rm(scratch, { recursive: true, force: true }).catch(() => {});
|
|
72
72
|
return htmlFailure(error, startedAt);
|
|
@@ -16,11 +16,7 @@ import { AsyncLocalStorage } from 'node:async_hooks';
|
|
|
16
16
|
import { statSync } from 'node:fs';
|
|
17
17
|
import { tmpdir } from 'node:os';
|
|
18
18
|
import { isAbsolute, relative, resolve } from 'node:path';
|
|
19
|
-
import {
|
|
20
|
-
PATCH_EDIT_BUDGET_BYTES,
|
|
21
|
-
createSnapshotBudget,
|
|
22
|
-
reviewFileContent,
|
|
23
|
-
} from '../../shared/bounded-file-read.mjs';
|
|
19
|
+
import { PATCH_EDIT_BUDGET_BYTES, createSnapshotBudget, reviewFileContent } from '../../shared/bounded-file-read.mjs';
|
|
24
20
|
|
|
25
21
|
const ledgers = new AsyncLocalStorage();
|
|
26
22
|
|
|
@@ -31,9 +31,8 @@ export async function executeOfficeTool(args = {}, context = {}) {
|
|
|
31
31
|
const sessionId = String(context.sessionId || '');
|
|
32
32
|
if (!sessionId) return await tracedOfficeTool(args, context);
|
|
33
33
|
const cwd = context.cwd || process.cwd();
|
|
34
|
-
const { ledger, run } = runWithOfficeWriteLedger(
|
|
35
|
-
|
|
36
|
-
() => tracedOfficeTool(args, context)
|
|
34
|
+
const { ledger, run } = runWithOfficeWriteLedger({ cwd, dataDir: context.dataDir || defaultOfficeDataDir() }, () =>
|
|
35
|
+
tracedOfficeTool(args, context)
|
|
37
36
|
);
|
|
38
37
|
try {
|
|
39
38
|
return await run;
|
|
@@ -261,74 +261,6 @@ export async function extractPdfTextLayout(
|
|
|
261
261
|
// so the adapter, the tool surface, and tests keep one import.
|
|
262
262
|
export { findPdfText } from './pdf-search.mjs';
|
|
263
263
|
|
|
264
|
-
// The text run at `index`, joined with the next run on the same line when only
|
|
265
|
-
// the joined text names a category (a label the PDF drew as two runs).
|
|
266
|
-
function categoryLabelAt(items, index, expected) {
|
|
267
|
-
const item = items[index];
|
|
268
|
-
const text = String(item?.text || '').trim();
|
|
269
|
-
if (!text || expected.includes(text)) return text;
|
|
270
|
-
let nextIndex = index + 1;
|
|
271
|
-
while (nextIndex < items.length && !String(items[nextIndex]?.text || '').trim()) nextIndex += 1;
|
|
272
|
-
const next = items[nextIndex];
|
|
273
|
-
if (!next || Math.abs(Number(next.top) - Number(item.top)) > 1) return text;
|
|
274
|
-
const joined = `${text}${String(next.text || '').trim()}`;
|
|
275
|
-
return expected.includes(joined) ? joined : text;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// Every line that carries category labels, keyed by page and baseline.
|
|
279
|
-
function categoryLabelRows(layout, expected) {
|
|
280
|
-
const rows = [];
|
|
281
|
-
for (const page of layout?.pages || []) {
|
|
282
|
-
const items = Array.isArray(page.items) ? page.items : [];
|
|
283
|
-
for (let index = 0; index < items.length; index += 1) {
|
|
284
|
-
const item = items[index];
|
|
285
|
-
const text = categoryLabelAt(items, index, expected);
|
|
286
|
-
if (!text || !expected.includes(text)) continue;
|
|
287
|
-
let row = rows.find((entry) => entry.page === page.page && Math.abs(entry.top - Number(item.top)) <= 1);
|
|
288
|
-
if (!row) {
|
|
289
|
-
row = { page: page.page, width: Number(page.width) || 0, top: Number(item.top), labels: [] };
|
|
290
|
-
rows.push(row);
|
|
291
|
-
}
|
|
292
|
-
if (!row.labels.some((entry) => entry.text === text)) {
|
|
293
|
-
row.labels.push({ text, x: Number(item.x) || 0 });
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
return rows;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
function categoryRowSpacing(row, expected) {
|
|
301
|
-
const labels = expected
|
|
302
|
-
.map((text) => row.labels.find((entry) => entry.text === text))
|
|
303
|
-
.sort((left, right) => left.x - right.x);
|
|
304
|
-
const gaps = labels.slice(1).map((entry, index) => entry.x - labels[index].x);
|
|
305
|
-
return {
|
|
306
|
-
...row,
|
|
307
|
-
labels,
|
|
308
|
-
span: labels.length > 1 ? labels.at(-1).x - labels[0].x : 0,
|
|
309
|
-
minimumGap: gaps.length ? Math.min(...gaps) : 0,
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
export function evaluatePowerPointCategorySpacing(layout, categories = []) {
|
|
314
|
-
const expected = [...new Set(categories.map((entry) => String(entry || '').trim()).filter(Boolean))];
|
|
315
|
-
const complete = categoryLabelRows(layout, expected)
|
|
316
|
-
.filter((row) => expected.every((text) => row.labels.some((entry) => entry.text === text)))
|
|
317
|
-
.map((row) => categoryRowSpacing(row, expected))
|
|
318
|
-
.sort((left, right) => right.span - left.span);
|
|
319
|
-
const best = complete[0] || null;
|
|
320
|
-
const requiredGap = best ? best.width * 0.1 : 0;
|
|
321
|
-
return {
|
|
322
|
-
ok: expected.length <= 1 || Boolean(best && best.minimumGap >= requiredGap),
|
|
323
|
-
categories: expected,
|
|
324
|
-
page: best?.page || 0,
|
|
325
|
-
labels: best?.labels || [],
|
|
326
|
-
span: Number((best?.span || 0).toFixed(2)),
|
|
327
|
-
minimumGap: Number((best?.minimumGap || 0).toFixed(2)),
|
|
328
|
-
requiredGap: Number(requiredGap.toFixed(2)),
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
|
|
332
264
|
// A PDF reports the runs it drew, not cells: a cell whose words were drawn as
|
|
333
265
|
// separate runs would count as several columns and break its row against the
|
|
334
266
|
// rows around it. Runs closer than half a line height are the same cell — the
|
|
@@ -58,7 +58,7 @@ export async function forgetSessionSearch(sessionId) {
|
|
|
58
58
|
|
|
59
59
|
async function loadStoreDeps() {
|
|
60
60
|
const [{ getStoreDir }, { _storedSessionFromFile, STORED_SESSION_UNREADABLE }] = await Promise.all([
|
|
61
|
-
import('../agent/orchestrator/session/store/paths
|
|
61
|
+
import('../agent/orchestrator/session/store/session-paths.mjs'),
|
|
62
62
|
import('../agent/orchestrator/session/store/serialize.mjs'),
|
|
63
63
|
]);
|
|
64
64
|
return {
|
|
@@ -3,6 +3,19 @@ import { positiveInt } from './numbers.mjs';
|
|
|
3
3
|
|
|
4
4
|
export const TAG_TOMBSTONE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
5
5
|
|
|
6
|
+
// How long a finished agent (completed, failed or cancelled child, or a Lead
|
|
7
|
+
// row) stays listed in the Agents pane, measured from its finish stamp. This is
|
|
8
|
+
// pane visibility only: session reuse and cache reaping keep their own windows
|
|
9
|
+
// (resolveAgentTerminalReapMs).
|
|
10
|
+
export const AGENT_PANE_VISIBLE_MS = 60 * 60 * 1000;
|
|
11
|
+
|
|
12
|
+
/** Whether a row finished at `finishedAtMs` is still inside the pane window.
|
|
13
|
+
* Index rows are always stamped; a row with no usable stamp has no provable
|
|
14
|
+
* age and stays listed rather than vanishing on a guess. */
|
|
15
|
+
export function agentPaneVisible(finishedAtMs, now) {
|
|
16
|
+
return !(finishedAtMs > 0) || now - finishedAtMs < AGENT_PANE_VISIBLE_MS;
|
|
17
|
+
}
|
|
18
|
+
|
|
6
19
|
export function stampMs(value) {
|
|
7
20
|
if (typeof value === 'number') return Number.isFinite(value) && value > 0 ? value : 0;
|
|
8
21
|
const text = clean(value);
|
|
@@ -23,5 +23,5 @@ export function writeJsonAtomicAsync(
|
|
|
23
23
|
export function withFileLock<T>(
|
|
24
24
|
lockPath: string,
|
|
25
25
|
task: () => T | Promise<T>,
|
|
26
|
-
options?: { timeoutMs?: number; staleMs?: number; secret?: boolean }
|
|
26
|
+
options?: { timeoutMs?: number; staleMs?: number; secret?: boolean; strictOwner?: boolean }
|
|
27
27
|
): Promise<T>;
|
|
@@ -330,13 +330,18 @@ export function settleCancelledBackgroundTask(taskId, { result } = {}) {
|
|
|
330
330
|
export function cancelBackgroundTasks(options = {}) {
|
|
331
331
|
const reason = clean(options.reason) || 'cancelled';
|
|
332
332
|
const wanted = clean(options.surface);
|
|
333
|
+
const executionSessionId = clean(options.executionSessionId);
|
|
333
334
|
let cancelled = 0;
|
|
334
335
|
for (const task of [...tasks.values()]) {
|
|
335
336
|
if (wanted && task.surface !== wanted) continue;
|
|
336
337
|
// Scoped teardown must be exact. Legacy tasks without ownership stay
|
|
337
338
|
// visible/recoverable, but may not be claimed by whichever session happens
|
|
338
339
|
// to close first.
|
|
339
|
-
if (
|
|
340
|
+
if (executionSessionId) {
|
|
341
|
+
// Delegated work executes in its bound session; before binding it still
|
|
342
|
+
// belongs to the registering session. Notification ownership is separate.
|
|
343
|
+
if ((clean(task.meta?.sessionId) || task.ownerSessionId) !== executionSessionId) continue;
|
|
344
|
+
} else if (!taskMatchesScope(task, options, { includeUnattributed: false })) continue;
|
|
340
345
|
if (TERMINAL_STATUSES.has(task.status)) {
|
|
341
346
|
if (options.notify === false) silenceCancelledNotification(task);
|
|
342
347
|
continue;
|
|
@@ -162,14 +162,23 @@ export function lineDiffHunks(oldText, newText, budget, sources = [oldText, newT
|
|
|
162
162
|
result ||= { hunks: replacementHunks(oldText, newText), exact: false };
|
|
163
163
|
if (key && repeatable) cacheSet(key, result, oldText.length + newText.length);
|
|
164
164
|
// Within its own operation it is final: the budget never grows back.
|
|
165
|
-
else if (key)
|
|
165
|
+
else if (key) {
|
|
166
|
+
budget.fallbacks ||= new Map();
|
|
167
|
+
budget.fallbacks.set(key, result);
|
|
168
|
+
}
|
|
166
169
|
return result;
|
|
167
170
|
}
|
|
168
171
|
|
|
169
172
|
/** The `--- `/`+++ ` headers and hunks of `hunks`, as jsdiff formats them,
|
|
170
173
|
* ending in exactly one newline. */
|
|
171
174
|
export function unifiedHunksBody(oldHeader, newHeader, hunks) {
|
|
172
|
-
const generated = formatPatch({
|
|
175
|
+
const generated = formatPatch({
|
|
176
|
+
oldFileName: oldHeader,
|
|
177
|
+
newFileName: newHeader,
|
|
178
|
+
oldHeader: '',
|
|
179
|
+
newHeader: '',
|
|
180
|
+
hunks,
|
|
181
|
+
});
|
|
173
182
|
let end = generated.length;
|
|
174
183
|
// Linear trim: a /\n*$/ regex rescans from every position of a large patch.
|
|
175
184
|
while (end > 0 && generated.charCodeAt(end - 1) === 10) end -= 1;
|
|
@@ -88,3 +88,18 @@ export function buildPuppeteerLaunchArgs(extra = []) {
|
|
|
88
88
|
if (puppeteerNoSandboxEnabled()) args.push('--no-sandbox');
|
|
89
89
|
return args;
|
|
90
90
|
}
|
|
91
|
+
|
|
92
|
+
// A healthy headless launch answers in a few seconds; the observed CI failures
|
|
93
|
+
// are launches that never print the DevTools endpoint and hit puppeteer's 30 s
|
|
94
|
+
// TimeoutError (Windows runner, Linux runner). Puppeteer closes that child
|
|
95
|
+
// itself, so one fresh attempt is the remedy; a longer wait would only delay
|
|
96
|
+
// the same hang. Any other launch error (missing executable, bad args), or a
|
|
97
|
+
// timeout after `signal` aborted, is not retried.
|
|
98
|
+
export async function launchPuppeteerBrowser(puppeteer, options, { signal = null } = {}) {
|
|
99
|
+
try {
|
|
100
|
+
return await puppeteer.launch(options);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
if (error?.name !== 'TimeoutError' || signal?.aborted) throw error;
|
|
103
|
+
return puppeteer.launch(options);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { transportErrorText } from './transport-error-text.mjs';
|
|
2
2
|
import { describeError, safeErrorDetails } from './error-presentation.mjs';
|
|
3
3
|
import { oneLine } from './clean.mjs';
|
|
4
|
+
import { TIMEOUT_PHASE, isFirstByteTimeout } from './provider-timeout-phase.mjs';
|
|
4
5
|
|
|
5
6
|
// HTTP status carried by a provider/transport error, or 0 when absent.
|
|
6
7
|
export function errorHttpStatus(err) {
|
|
@@ -185,7 +186,9 @@ export function isCancelLikeError(error) {
|
|
|
185
186
|
const KIND_LINES = {
|
|
186
187
|
overloaded: 'Provider is busy at capacity.',
|
|
187
188
|
rate_limited: ({ retryAfterMs }) =>
|
|
188
|
-
retryAfterMs
|
|
189
|
+
retryAfterMs
|
|
190
|
+
? `Provider is rate-limited (retry in ${formatDurationMs(retryAfterMs)}).`
|
|
191
|
+
: 'Provider is rate-limited.',
|
|
189
192
|
quota_exhausted: 'Provider usage limit reached.',
|
|
190
193
|
entitlement: 'Not included in your plan.',
|
|
191
194
|
billing: 'Out of credits or at spend limit.',
|
|
@@ -198,7 +201,38 @@ const KIND_LINES = {
|
|
|
198
201
|
// A bare message carries none, so its wording keeps the legacy text path.
|
|
199
202
|
function hasTypedEvidence(error) {
|
|
200
203
|
if (!error || typeof error !== 'object') return false;
|
|
201
|
-
return
|
|
204
|
+
return (
|
|
205
|
+
Boolean(error.errorKind?.kind) || errorHttpStatus(error) > 0 || Boolean(error.code) || Boolean(error.retryAfterMs)
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// The window a provider timeout names (providerTimeoutError's message), or 0.
|
|
210
|
+
const timedOutMs = (text) => Number(/timed out after (\d+)ms/i.exec(text)?.[1]) || 0;
|
|
211
|
+
|
|
212
|
+
// A provider timeout before the model produced anything (isFirstByteTimeout):
|
|
213
|
+
// the model is slow, not the connection.
|
|
214
|
+
function stillThinkingText(error, text) {
|
|
215
|
+
const ms = Number(error.waitedMs) || timedOutMs(text);
|
|
216
|
+
const provider =
|
|
217
|
+
typeof error.providerLabel === 'string' && error.providerLabel ? error.providerLabel : 'the provider';
|
|
218
|
+
const attempts = Number(error.attempts) > 0 ? `; attempts: ${Math.floor(Number(error.attempts))}` : '';
|
|
219
|
+
return `Model still thinking: no output in ${formatDurationMs(ms)}; ${provider} sent nothing yet${attempts}.`;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Stamped provider timeout phases and stream cuts. Null when the error names
|
|
223
|
+
// neither, so the text rules below decide.
|
|
224
|
+
function typedStreamFailureText(error, text) {
|
|
225
|
+
if (!error || typeof error !== 'object') return null;
|
|
226
|
+
if (isFirstByteTimeout(error)) return stillThinkingText(error, text);
|
|
227
|
+
if (error.timeoutPhase === TIMEOUT_PHASE.IDLE) {
|
|
228
|
+
const ms = timedOutMs(text);
|
|
229
|
+
return ms > 0 ? `No progress ${formatDurationMs(ms)}.` : 'No progress.';
|
|
230
|
+
}
|
|
231
|
+
// A stream that ended before its finish marker lost its connection.
|
|
232
|
+
if (error.code === 'TRUNCATED_STREAM' && error.streamCorruption !== true) {
|
|
233
|
+
return 'Connection to the provider was lost (TRUNCATED_STREAM).';
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
202
236
|
}
|
|
203
237
|
|
|
204
238
|
export function presentErrorText(error, options = {}) {
|
|
@@ -227,6 +261,8 @@ export function presentErrorText(error, options = {}) {
|
|
|
227
261
|
if (embeddedError) text = embeddedError;
|
|
228
262
|
text = oneLine(stripErrorPrefix(text));
|
|
229
263
|
if (!text) return 'Unknown error';
|
|
264
|
+
const streamFailure = typedStreamFailureText(error, text);
|
|
265
|
+
if (streamFailure) return streamFailure;
|
|
230
266
|
|
|
231
267
|
if (code === 'PROVIDER_PREFIX_MUTATION' || name === 'ProviderPrefixMutationError') {
|
|
232
268
|
return 'Session state changed unexpectedly.';
|
|
@@ -282,9 +318,10 @@ export function presentErrorText(error, options = {}) {
|
|
|
282
318
|
return Number.isFinite(ms) && ms > 0 ? `No first response ${formatDurationMs(ms)}.` : 'No first response.';
|
|
283
319
|
}
|
|
284
320
|
|
|
321
|
+
// The agent's own watchdog, worded apart from any provider timeout.
|
|
285
322
|
const firstTransport = /first (?:transport|semantic response) stale\s*\((\d+)ms\)/i.exec(text);
|
|
286
323
|
if (firstTransport) {
|
|
287
|
-
return `
|
|
324
|
+
return `Agent watchdog stopped the run: no model response in ${formatDurationMs(firstTransport[1])}.`;
|
|
288
325
|
}
|
|
289
326
|
|
|
290
327
|
const firstResponse = /(?:agent\s+)?first response stale\s*\((\d+)ms\)/i.exec(text);
|
|
@@ -363,7 +400,8 @@ export function backgroundTaskFailureStatusLabel(status, error, options = {}) {
|
|
|
363
400
|
/^timeout$/i.test(statusNorm) ||
|
|
364
401
|
watchdog?.kind === 'timeout' ||
|
|
365
402
|
/first response stale/i.test(raw) ||
|
|
366
|
-
/no first response from/i.test(presented)
|
|
403
|
+
/no first response from/i.test(presented) ||
|
|
404
|
+
/^(?:Model still thinking|Agent watchdog stopped the run):/.test(presented)
|
|
367
405
|
)
|
|
368
406
|
head = 'Timeout';
|
|
369
407
|
else if (
|
|
@@ -278,12 +278,13 @@ function* releaseReclaimGuard(reclaim) {
|
|
|
278
278
|
|
|
279
279
|
// A lock is reclaimable when its recorded owner is dead, or when it names no
|
|
280
280
|
// owner at all and has outlived the stale window.
|
|
281
|
-
function lockReclaimable(owner, stat, staleMs) {
|
|
281
|
+
function lockReclaimable(owner, stat, staleMs, strictOwner = false) {
|
|
282
282
|
if (owner.pid !== null) return !ownerIsLive(owner);
|
|
283
|
+
if (strictOwner) return false;
|
|
283
284
|
return Date.now() - (Number(stat.mtimeMs) || 0) >= Math.max(0, staleMs);
|
|
284
285
|
}
|
|
285
286
|
|
|
286
|
-
function* tryReclaimStaleLock(lockPath, staleMs) {
|
|
287
|
+
function* tryReclaimStaleLock(lockPath, staleMs, strictOwner = false) {
|
|
287
288
|
let initial;
|
|
288
289
|
try {
|
|
289
290
|
initial = yield ['stat', lockPath];
|
|
@@ -291,7 +292,7 @@ function* tryReclaimStaleLock(lockPath, staleMs) {
|
|
|
291
292
|
return false;
|
|
292
293
|
}
|
|
293
294
|
const owner = yield* readLockOwner(lockPath);
|
|
294
|
-
if (!lockReclaimable(owner, initial, staleMs)) return false;
|
|
295
|
+
if (!lockReclaimable(owner, initial, staleMs, strictOwner)) return false;
|
|
295
296
|
const reclaim = yield* tryAcquireReclaimGuard(lockPath);
|
|
296
297
|
if (reclaim === null) return false;
|
|
297
298
|
try {
|
|
@@ -303,7 +304,7 @@ function* tryReclaimStaleLock(lockPath, staleMs) {
|
|
|
303
304
|
}
|
|
304
305
|
const currentOwner = yield* readLockOwner(lockPath);
|
|
305
306
|
if (currentOwner.pid !== owner.pid || currentOwner.token !== owner.token) return false;
|
|
306
|
-
if (lockReclaimable(currentOwner, current, staleMs)) {
|
|
307
|
+
if (lockReclaimable(currentOwner, current, staleMs, strictOwner)) {
|
|
307
308
|
try {
|
|
308
309
|
yield ['unlink', lockPath];
|
|
309
310
|
return true;
|
|
@@ -429,7 +430,7 @@ function* acquireLock(lockPath, opts, mode, markHeld, timing = null) {
|
|
|
429
430
|
// The reclaim runs synchronously in both modes: it is a few metadata
|
|
430
431
|
// calls, and an await inside it would let a process exit strand its guard.
|
|
431
432
|
try {
|
|
432
|
-
if (runSync(tryReclaimStaleLock(lockPath, staleMs))) continue;
|
|
433
|
+
if (runSync(tryReclaimStaleLock(lockPath, staleMs, opts.strictOwner === true))) continue;
|
|
433
434
|
} catch {}
|
|
434
435
|
if (timeoutMs <= 0) throw contentionError(lockPath, error, yield* describeLockHolder(lockPath));
|
|
435
436
|
if (Date.now() >= deadline) break;
|
|
@@ -2,7 +2,6 @@ import { EFFORT_BETA_HEADER } from './anthropic-effort.mjs';
|
|
|
2
2
|
import { normalizeClaudeModelId } from './anthropic-thinking-contract.mjs';
|
|
3
3
|
import { getModelMetadataSync } from './model-catalog.mjs';
|
|
4
4
|
|
|
5
|
-
const EXTENDED_CACHE_TTL_BETA_HEADER = 'extended-cache-ttl-2025-04-11';
|
|
6
5
|
const INTERLEAVED_THINKING_BETA_HEADER = 'interleaved-thinking-2025-05-14';
|
|
7
6
|
const FAST_MODE_BETA_HEADER = 'fast-mode-2026-02-01';
|
|
8
7
|
const TOOL_SEARCH_BETA_HEADER = 'advanced-tool-use-2025-11-20';
|
|
@@ -23,7 +22,7 @@ export function supportsAnthropicFastMode(model) {
|
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
export function buildAnthropicBetaHeaders({
|
|
26
|
-
base =
|
|
25
|
+
base = INTERLEAVED_THINKING_BETA_HEADER,
|
|
27
26
|
fastMode = false,
|
|
28
27
|
toolSearch = false,
|
|
29
28
|
effort = false,
|
|
@@ -28,6 +28,7 @@ export const ANTIGRAVITY_MODELS = Object.freeze([
|
|
|
28
28
|
low: 'gemini-3.1-pro-low',
|
|
29
29
|
high: 'gemini-3.1-pro-high',
|
|
30
30
|
}),
|
|
31
|
+
fallbackModel('gemini-4-argon', 'Gemini 4 Argon', 'gemini-pro', 1048576, 'gemini-4-argon', ['low', 'medium', 'high']),
|
|
31
32
|
fallbackModel('claude-opus-4-6-thinking', 'Claude Opus 4.6 (Thinking)', null, 250000, 'claude-opus-4-6-thinking', [
|
|
32
33
|
'low',
|
|
33
34
|
'medium',
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function canonicalRouteProvider(value: unknown): string;
|
|
2
|
+
export function routeChain(route: Record<string, unknown>): Record<string, unknown>[];
|
|
3
|
+
export function validateRouteChainProviders(routes: Record<string, unknown>[]): void;
|
|
4
|
+
export function normalizeRouteChain(
|
|
5
|
+
route: Record<string, unknown>,
|
|
6
|
+
normalizeLeaf: (route: Record<string, unknown>, fallback: Record<string, unknown>) => Record<string, unknown> | null,
|
|
7
|
+
fallback?: Record<string, unknown>
|
|
8
|
+
): Record<string, unknown> | null;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const PROVIDER_ALIASES = Object.freeze({
|
|
2
|
+
'openai-api': 'openai',
|
|
3
|
+
'xai-api': 'xai',
|
|
4
|
+
'gemini-api': 'gemini',
|
|
5
|
+
'anthropic-api': 'anthropic',
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export function canonicalRouteProvider(value) {
|
|
9
|
+
const id = String(value || '').trim();
|
|
10
|
+
return PROVIDER_ALIASES[id] || id;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function routeChain(route) {
|
|
14
|
+
if (!route || typeof route !== 'object' || Array.isArray(route)) return [];
|
|
15
|
+
const { fallbacks = [], ...primary } = route;
|
|
16
|
+
if (!Array.isArray(fallbacks)) throw new Error('route.fallbacks must be an array');
|
|
17
|
+
for (const entry of fallbacks) {
|
|
18
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry) || Object.hasOwn(entry, 'fallbacks')) {
|
|
19
|
+
throw new Error('fallback routes must be leaf route objects');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return [primary, ...fallbacks];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function validateRouteChainProviders(routes) {
|
|
26
|
+
const providers = new Set();
|
|
27
|
+
for (const route of routes) {
|
|
28
|
+
const provider = canonicalRouteProvider(route.provider);
|
|
29
|
+
if (!provider || !String(route.model || '').trim()) throw new Error('route requires provider and model');
|
|
30
|
+
if (providers.has(provider)) throw new Error(`duplicate route provider "${provider}"`);
|
|
31
|
+
if (providers.size && provider === 'default') throw new Error('follow Main is only allowed as the primary route');
|
|
32
|
+
providers.add(provider);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function normalizeRouteChain(route, normalizeLeaf, fallback = {}) {
|
|
37
|
+
const raw = routeChain({ ...fallback, ...route });
|
|
38
|
+
const primary = normalizeLeaf(route, fallback);
|
|
39
|
+
if (!primary) return null;
|
|
40
|
+
const routes = raw.map((entry, index) => {
|
|
41
|
+
const normalized = index === 0 ? primary : normalizeLeaf(entry, {});
|
|
42
|
+
if (!normalized) throw new Error('fallback route requires provider and model');
|
|
43
|
+
return { ...normalized, provider: canonicalRouteProvider(normalized.provider) };
|
|
44
|
+
});
|
|
45
|
+
validateRouteChainProviders(routes);
|
|
46
|
+
const [first, ...rest] = routes;
|
|
47
|
+
return rest.length ? { ...first, fallbacks: rest } : first;
|
|
48
|
+
}
|