mixdog 1.3.5 → 1.4.0
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/NOTICE.md +2 -2
- package/README.md +2 -2
- package/package.json +2 -11
- package/scripts/daemon-stub.mjs +1 -1
- package/scripts/gate-local.mjs +4 -2
- package/scripts/native-release-status.mjs +2 -2
- package/scripts/recall-history-cases.json +1 -1
- package/scripts/suite-health.mjs +10 -1
- package/scripts/test.mjs +7 -11
- package/src/agents/reviewer/AGENT.md +7 -11
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +17 -1
- package/src/defaults/skills/browser-use/SKILL.md +59 -11
- package/src/defaults/skills/code-tidy/SKILL.md +142 -270
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
- package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
- package/src/defaults/skills/computer-use/SKILL.md +33 -9
- package/src/defaults/skills/setup/SKILL.md +22 -0
- package/src/defaults/skills/setup/references/actions.md +39 -5
- package/src/defaults/skills/setup/references/surfaces.md +11 -2
- package/src/defaults/skills/visualize/SKILL.md +2 -1
- package/src/lib/rules-builder.cjs +10 -8
- package/src/rules/agent/AGENT.md +6 -6
- package/src/rules/lead/LEAD.md +18 -20
- package/src/rules/shared/05-tool-calls.md +5 -6
- package/src/rules/shared/10-tool-workflow.md +2 -0
- package/src/rules/shared/60-verification.md +7 -5
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
- package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
- package/src/runtime/agent/orchestrator/config.mjs +17 -1
- package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +72 -67
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +54 -1
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +176 -72
- package/src/runtime/agent/orchestrator/mcp/client.mjs +19 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +181 -133
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +42 -6
- package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +145 -66
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +64 -33
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +123 -102
- package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -13
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
- package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
- package/src/runtime/agent/orchestrator/providers/registry.mjs +26 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
- package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +12 -7
- package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +792 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +133 -22
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +0 -2
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +18 -22
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +32 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +12 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +23 -13
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +129 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +20 -2
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +18 -5
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +19 -8
- package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +36 -9
- package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
- package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
- package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +8 -6
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -14
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +84 -3
- package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
- package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +18 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +65 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
- package/src/runtime/browser-bridge/action-schema.mjs +13 -2
- package/src/runtime/browser-bridge/client.mjs +73 -8
- package/src/runtime/browser-bridge/input-fields.mjs +8 -9
- package/src/runtime/browser-bridge/mail-links.mjs +107 -0
- package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
- package/src/runtime/channels/lib/config.mjs +6 -61
- package/src/runtime/channels/lib/crash-log.mjs +1 -1
- package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
- package/src/runtime/channels/lib/event-queue.mjs +3 -18
- package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
- package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
- package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
- package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
- package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
- package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
- package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
- package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
- package/src/runtime/channels/lib/scheduler.mjs +33 -147
- package/src/runtime/channels/lib/schedules-db.mjs +34 -11
- package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
- package/src/runtime/channels/lib/tool-dispatch.mjs +1 -2
- package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
- package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
- package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
- package/src/runtime/channels/lib/worker-main.mjs +10 -34
- package/src/runtime/computer-bridge/action-schema.mjs +42 -1
- package/src/runtime/computer-bridge/actions.mjs +9 -1
- package/src/runtime/computer-bridge/client.mjs +180 -8
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +27 -2
- package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
- package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
- package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
- package/src/runtime/connectors/gmail-app-password.mjs +172 -39
- package/src/runtime/connectors/google-mcp.mjs +10 -12
- package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
- package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
- package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
- package/src/runtime/session-search/session-search-db.mjs +73 -9
- package/src/runtime/session-search/session-search-ingest.mjs +110 -20
- package/src/runtime/shared/abort-race.mjs +89 -0
- package/src/runtime/shared/agent-avatar.d.mts +0 -1
- package/src/runtime/shared/agent-kind.mjs +4 -3
- package/src/runtime/shared/bounded-download.mjs +8 -3
- package/src/runtime/shared/config.mjs +2 -13
- package/src/runtime/shared/connector-accounts.mjs +20 -10
- package/src/runtime/shared/connector-catalog.d.mts +29 -0
- package/src/runtime/shared/connector-catalog.mjs +150 -0
- package/src/runtime/shared/connector-triggers.mjs +22 -19
- package/src/runtime/shared/defaults-separation.mjs +2 -14
- package/src/runtime/shared/delegated-approval-host.mjs +103 -11
- package/src/runtime/shared/err-text.mjs +24 -15
- package/src/runtime/shared/file-permissions.d.mts +0 -8
- package/src/runtime/shared/file-permissions.mjs +0 -11
- package/src/runtime/shared/git-direct.test-support.mjs +19 -0
- package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
- package/src/runtime/shared/heartbeat-interval.mjs +19 -0
- package/src/runtime/shared/idle-auto-clear-gate.mjs +104 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
- package/src/runtime/shared/mixy-presence.mjs +22 -0
- package/src/runtime/shared/orchestration.d.mts +2 -0
- package/src/runtime/shared/pg-schema-db.mjs +27 -16
- package/src/runtime/shared/profile-config.cjs +1 -1
- package/src/runtime/shared/prompt-origin.d.mts +4 -0
- package/src/runtime/shared/prompt-origin.mjs +21 -0
- package/src/runtime/shared/provider-accounts.mjs +7 -1
- package/src/runtime/shared/provider-display-name.mjs +29 -0
- package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
- package/src/runtime/shared/routine-trigger.d.mts +2 -0
- package/src/runtime/shared/routine-trigger.mjs +10 -0
- package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
- package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
- package/src/runtime/shared/session-activity-signal.mjs +34 -1
- package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
- package/src/runtime/shared/session-sidebar-host.mjs +7 -3
- package/src/runtime/shared/session-turn-prelude.mjs +18 -0
- package/src/runtime/shared/tool-result-summary.mjs +1 -14
- package/src/runtime/shared/worktrees/test-support.mjs +9 -4
- package/src/runtime/terminal-bridge/client.mjs +10 -1
- package/src/runtime/visualize-bridge/client.mjs +27 -8
- package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
- package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
- package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
- package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
- package/src/session-runtime/agent-home-delivery.mjs +448 -185
- package/src/session-runtime/agent-task-sessions.mjs +329 -180
- package/src/session-runtime/boot/apis.mjs +9 -0
- package/src/session-runtime/boot/infrastructure.mjs +4 -0
- package/src/session-runtime/boot/providers.mjs +3 -0
- package/src/session-runtime/boot/tools.mjs +6 -1
- package/src/session-runtime/config-lifecycle.mjs +6 -0
- package/src/session-runtime/connector-merge-migration.mjs +305 -0
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +132 -28
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +2 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
- package/src/session-runtime/lifecycle/session-catalog.mjs +3 -1
- package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
- package/src/session-runtime/lifecycle/teardown.mjs +23 -5
- package/src/session-runtime/mcp-glue/server-catalog.mjs +55 -3
- package/src/session-runtime/mcp-oauth-login.mjs +5 -3
- package/src/session-runtime/mixy-heartbeat.mjs +153 -33
- package/src/session-runtime/notification-bus.mjs +31 -117
- package/src/session-runtime/notification-completion-queue.mjs +54 -0
- package/src/session-runtime/notification-listeners.mjs +76 -0
- package/src/session-runtime/owned-automation-run.mjs +2 -1
- package/src/session-runtime/prewarm/channel-start.mjs +3 -7
- package/src/session-runtime/resource-mcp-api.mjs +143 -224
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
- package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
- package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
- package/src/session-runtime/resource-mcp-servers.mjs +78 -0
- package/src/session-runtime/resource-mcp-store.mjs +49 -0
- package/src/session-runtime/routine-owner.mjs +40 -9
- package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +7 -2
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
- package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
- package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
- package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
- package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
- package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +7 -13
- package/src/session-runtime/services/channel-session-router.mjs +4 -2
- package/src/session-runtime/services/seeds.mjs +0 -28
- package/src/session-runtime/session-compaction-sync.mjs +27 -0
- package/src/session-runtime/session-create/session-options.mjs +1 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
- package/src/session-runtime/settings-compaction-api.mjs +2 -40
- package/src/session-runtime/settings-system-api.mjs +13 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
- package/src/session-runtime/setup-tool/executor.mjs +145 -22
- package/src/session-runtime/setup-tool/extended-actions.mjs +8 -3
- package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +4 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +64 -5
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
- package/src/session-runtime/tool-policy/policy-stage.mjs +16 -2
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
- package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
- package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
- package/src/standalone/channel-transport/client-registry.mjs +24 -163
- package/src/standalone/channel-transport.mjs +1 -1
- package/src/standalone/daemon-channels-loader.mjs +10 -8
- package/src/standalone/daemon-session-control/list-page.mjs +72 -0
- package/src/standalone/daemon-session-control/request.mjs +51 -0
- package/src/standalone/daemon-session-control/room-host.mjs +57 -0
- package/src/standalone/daemon-session-control/route-control.mjs +48 -0
- package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
- package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
- package/src/standalone/daemon-session-control.mjs +124 -188
- package/src/standalone/daemon.mjs +26 -3
- package/src/standalone/session-client.mjs +7 -3
- package/src/standalone/session-protocol.mjs +5 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
- package/src/standalone/session-service/quota-resume.mjs +3 -0
- package/src/standalone/session-service/retention/busy.mjs +65 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +23 -2
- package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
- package/src/standalone/session-tool-output.mjs +15 -7
- package/src/tui/app/model-options.mjs +3 -28
- package/src/tui/dist/index.mjs +58 -64
- package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/notice-surface.mjs +7 -1
- package/src/tui/session/queue-helpers.mjs +3 -42
- package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
- package/src/tui/session/session-api/routes-write.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +17 -1
- package/src/tui/session/session-flow/auto-clear.mjs +4 -33
- package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
- package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
- package/src/tui/session/session-flow/drain-retry.mjs +35 -0
- package/src/tui/session/session-flow/drain.mjs +118 -149
- package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
- package/src/tui/session/session-flow/queue/take-entries.mjs +5 -2
- package/src/tui/session/tool-approval-delegation.mjs +64 -0
- package/src/tui/session/tool-approval-request.mjs +39 -0
- package/src/tui/session/tool-approval-settle.mjs +62 -0
- package/src/tui/session/tool-approval.mjs +69 -115
- package/src/tui/session/tui-steering-persist.mjs +8 -1
- package/src/tui/session/turn-stream.mjs +19 -2
- package/src/tui/session/turn.mjs +1 -0
- package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
- package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
- package/scripts/code-graph-description-contract.mjs +0 -188
- package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
|
@@ -12,7 +12,9 @@ import { sendGzipCompressed } from '../lib/request-compression.mjs';
|
|
|
12
12
|
const API_URL = 'https://api.anthropic.com/v1/messages';
|
|
13
13
|
export { ANTHROPIC_VERSION };
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
// `plain`: exactly one uncompressed POST (a cache warm), so no compression
|
|
16
|
+
// rejection resend can follow.
|
|
17
|
+
export async function postMessages({ accessToken, requestBody, betaHeaders, signal, compress, plain = false }) {
|
|
16
18
|
const headers = {
|
|
17
19
|
Authorization: `Bearer ${accessToken}`,
|
|
18
20
|
'anthropic-version': ANTHROPIC_VERSION,
|
|
@@ -22,17 +24,15 @@ export async function postMessages({ accessToken, requestBody, betaHeaders, sign
|
|
|
22
24
|
'x-app': 'cli',
|
|
23
25
|
'Content-Type': 'application/json',
|
|
24
26
|
};
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}),
|
|
37
|
-
});
|
|
27
|
+
const raw = Buffer.from(JSON.stringify(requestBody));
|
|
28
|
+
const send = (body, sendHeaders) =>
|
|
29
|
+
fetch(API_URL, {
|
|
30
|
+
method: 'POST',
|
|
31
|
+
headers: sendHeaders,
|
|
32
|
+
body,
|
|
33
|
+
signal,
|
|
34
|
+
dispatcher: getLlmDispatcher(),
|
|
35
|
+
});
|
|
36
|
+
if (plain) return send(raw, headers);
|
|
37
|
+
return sendGzipCompressed({ raw, headers, compress, send });
|
|
38
38
|
}
|
|
@@ -43,16 +43,17 @@ import {
|
|
|
43
43
|
} from './anthropic-oauth-credentials.mjs';
|
|
44
44
|
import { claudeCliUserAgent, learnRequiredCliVersion, warmCliVersion } from './anthropic-oauth-client-version.mjs';
|
|
45
45
|
import { createPassthroughSignal } from '../stall-policy.mjs';
|
|
46
|
-
import { AnthropicFallbackTriggeredError } from './retry-classifier.mjs';
|
|
47
46
|
import { ANTHROPIC_MAX_MIDSTREAM_RETRIES, parseSSEStream, _classifyMidstreamError } from './anthropic-sse.mjs';
|
|
48
47
|
import { buildAnthropicBetaHeaders, supportsAnthropicFastMode } from './anthropic-betas.mjs';
|
|
49
48
|
import { applyAnthropicServerFallback } from './anthropic-server-fallback.mjs';
|
|
50
49
|
import { fastModeAvailable, fastModeDowngraded, noteFastModeCapacityError } from './anthropic-fast-mode.mjs';
|
|
51
50
|
import { ANTHROPIC_VERSION, anthropicQuotaError, createAnthropicOAuthRequest } from './anthropic-oauth-request.mjs';
|
|
52
51
|
import { isRefreshableAuthRejection } from './anthropic-oauth-request/initial-status.mjs';
|
|
52
|
+
import { postMessages } from './anthropic-oauth-request/gzip-post.mjs';
|
|
53
|
+
import { sendAnthropicCacheWarm } from './anthropic-cache-warm.mjs';
|
|
53
54
|
import { applyAnthropicErrorContract } from './anthropic-error-contract.mjs';
|
|
54
55
|
import { adjustMaxTokensForContextOverflow } from './anthropic-max-tokens-recovery.mjs';
|
|
55
|
-
import {
|
|
56
|
+
import { createAnthropicOverloadTracker, takeAnthropicModelFallback } from './anthropic-overload-fallback.mjs';
|
|
56
57
|
import { createAnthropicOAuthRecovery } from './anthropic-oauth-recovery.mjs';
|
|
57
58
|
import { createMidState, createMidstreamRecovery } from './anthropic-oauth-midstream.mjs';
|
|
58
59
|
import { assertAnthropicStreamNotEmpty } from './anthropic-midstream-recovery.mjs';
|
|
@@ -302,6 +303,28 @@ function buildRequestBody(requestMessages, model, tools, sendOpts) {
|
|
|
302
303
|
return markAnthropicEffortBody(body, effortProjection);
|
|
303
304
|
}
|
|
304
305
|
|
|
306
|
+
// Known tool names for the leaked-tool-call guard in parseSSEStream:
|
|
307
|
+
// recovered leaked calls are only synthesized when they name a tool
|
|
308
|
+
// actually offered to this request (native + lowered). Derived from the
|
|
309
|
+
// final request body so it matches exactly what the model was given.
|
|
310
|
+
function requestToolNames(body) {
|
|
311
|
+
return new Set(
|
|
312
|
+
(Array.isArray(body.tools) ? body.tools : [])
|
|
313
|
+
.map((t) => (t && typeof t.name === 'string' ? t.name : null))
|
|
314
|
+
.filter(Boolean)
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// The number of mid-stream retries a streamed turn took, as a hidden field of
|
|
319
|
+
// the result.
|
|
320
|
+
function tagMidstreamRetries(result, attemptIndex) {
|
|
321
|
+
try {
|
|
322
|
+
Object.defineProperty(result, '__midstreamRetries', { value: attemptIndex, enumerable: false });
|
|
323
|
+
} catch {
|
|
324
|
+
/* ignore non-extensible result */
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
305
328
|
export function _buildRequestBodyForCacheSmoke(messages, model, tools = [], sendOpts = {}) {
|
|
306
329
|
return buildRequestBody(messages, model, tools, sendOpts);
|
|
307
330
|
}
|
|
@@ -466,6 +489,41 @@ export class AnthropicOAuthProvider {
|
|
|
466
489
|
);
|
|
467
490
|
}
|
|
468
491
|
|
|
492
|
+
/**
|
|
493
|
+
* Cache-warm mode (anthropic-cache-warm.mjs): the body `send` would build
|
|
494
|
+
* for these arguments, POSTed once — no retry, credential replay, fallback
|
|
495
|
+
* model or re-send — and cut at the first content block. `onUsage` receives
|
|
496
|
+
* the reported usage as it arrives; resolves the final usage.
|
|
497
|
+
*/
|
|
498
|
+
async sendCacheWarm(messages, model, tools, sendOpts = {}, { onUsage, accountId = '' } = {}) {
|
|
499
|
+
await warmCliVersion();
|
|
500
|
+
const opts = sendOpts || {};
|
|
501
|
+
const creds = await this.ensureAuth();
|
|
502
|
+
const body = buildRequestBody(sanitizeToolPairs(messages), model, tools, opts);
|
|
503
|
+
body.messages = await prepareAnthropicImages(body.messages, { signal: opts.signal });
|
|
504
|
+
return sendAnthropicCacheWarm({
|
|
505
|
+
providerName: this.name,
|
|
506
|
+
instance: this,
|
|
507
|
+
accountId,
|
|
508
|
+
model,
|
|
509
|
+
opts,
|
|
510
|
+
onUsage,
|
|
511
|
+
post: (signal) =>
|
|
512
|
+
postMessages({
|
|
513
|
+
accessToken: creds.accessToken,
|
|
514
|
+
requestBody: body,
|
|
515
|
+
betaHeaders: buildOAuthBetaHeaders(body, {
|
|
516
|
+
fastMode: this.fastModeBetaHeaderLatched,
|
|
517
|
+
toolSearch: Array.isArray(body.tools) && body.tools.some((t) => t?.defer_loading === true),
|
|
518
|
+
model,
|
|
519
|
+
opts,
|
|
520
|
+
}),
|
|
521
|
+
signal,
|
|
522
|
+
plain: true,
|
|
523
|
+
}),
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
|
|
469
527
|
async _sendOnce(messages, model, tools, sendOpts) {
|
|
470
528
|
await warmCliVersion();
|
|
471
529
|
// Re-warm the kept-alive socket before the turn. preconnect() is a
|
|
@@ -505,15 +563,7 @@ export class AnthropicOAuthProvider {
|
|
|
505
563
|
// actually carries deferred (defer_loading) tools — gate the header on
|
|
506
564
|
// that instead of sending it unconditionally on every request.
|
|
507
565
|
const hasDeferredTools = Array.isArray(body.tools) && body.tools.some((t) => t && t.defer_loading === true);
|
|
508
|
-
|
|
509
|
-
// recovered leaked calls are only synthesized when they name a tool
|
|
510
|
-
// actually offered to this request (native + lowered). Derived from the
|
|
511
|
-
// final request body so it matches exactly what the model was given.
|
|
512
|
-
const knownToolNames = new Set(
|
|
513
|
-
(Array.isArray(body.tools) ? body.tools : [])
|
|
514
|
-
.map((t) => (t && typeof t.name === 'string' ? t.name : null))
|
|
515
|
-
.filter(Boolean)
|
|
516
|
-
);
|
|
566
|
+
const knownToolNames = requestToolNames(body);
|
|
517
567
|
const sessionId = opts.sessionId || null;
|
|
518
568
|
const iteration = Number.isFinite(Number(opts.iteration)) ? Number(opts.iteration) : null;
|
|
519
569
|
// Option A: no absolute wall-clock cap on streaming generation. A stream
|
|
@@ -530,51 +580,17 @@ export class AnthropicOAuthProvider {
|
|
|
530
580
|
// totalSignal is therefore a pure pass-through of externalSignal with no timer.
|
|
531
581
|
const totalTimeout = createPassthroughSignal(externalSignal);
|
|
532
582
|
const totalSignal = totalTimeout.signal;
|
|
533
|
-
|
|
534
|
-
// limit the configured fallback model takes over the whole send.
|
|
535
|
-
const overload = createAnthropicOverloadTracker({
|
|
536
|
-
model: useModel,
|
|
537
|
-
fallbackModel: opts._fallbackTriggered ? undefined : opts.fallbackModel,
|
|
538
|
-
});
|
|
539
|
-
const { requestWithRetry, cleanupCancelHandler } = createAnthropicOAuthRequest({
|
|
540
|
-
provider: this,
|
|
583
|
+
const { requestWithRetry, cleanupCancelHandler, midstream } = this._createSendRecovery({
|
|
541
584
|
opts,
|
|
542
585
|
body,
|
|
543
586
|
useModel,
|
|
544
587
|
sessionId,
|
|
545
|
-
totalSignal,
|
|
546
|
-
overload,
|
|
547
|
-
betaHeadersFor: (requestBody) =>
|
|
548
|
-
buildOAuthBetaHeaders(requestBody, {
|
|
549
|
-
fastMode: this.fastModeBetaHeaderLatched,
|
|
550
|
-
toolSearch: hasDeferredTools,
|
|
551
|
-
model: useModel,
|
|
552
|
-
opts,
|
|
553
|
-
}),
|
|
554
|
-
onStageChange,
|
|
555
|
-
});
|
|
556
|
-
const recovery = createAnthropicOAuthRecovery({
|
|
557
|
-
provider: this,
|
|
558
|
-
opts,
|
|
559
|
-
body,
|
|
560
|
-
useModel,
|
|
561
588
|
auth,
|
|
562
589
|
totalSignal,
|
|
563
|
-
|
|
564
|
-
cleanupCancelHandler,
|
|
590
|
+
hasDeferredTools,
|
|
565
591
|
onStageChange,
|
|
566
592
|
onTextReset,
|
|
567
593
|
});
|
|
568
|
-
// Bounded mid-stream retries for transient stream loss; jittered backoff
|
|
569
|
-
// between attempts (anthropic-oauth-midstream.mjs).
|
|
570
|
-
const midstream = createMidstreamRecovery({
|
|
571
|
-
maxRetries: ANTHROPIC_MAX_MIDSTREAM_RETRIES,
|
|
572
|
-
totalSignal,
|
|
573
|
-
recovery,
|
|
574
|
-
onStageChange,
|
|
575
|
-
retry529: opts.retry529 !== false,
|
|
576
|
-
overload,
|
|
577
|
-
});
|
|
578
594
|
|
|
579
595
|
let maxTokensAdjusted = false;
|
|
580
596
|
try {
|
|
@@ -605,7 +621,9 @@ export class AnthropicOAuthProvider {
|
|
|
605
621
|
if (SSE_VERBOSE) process.stderr.write(`[anthropic-oauth] Response ${response.status}, parsing SSE...\n`);
|
|
606
622
|
try {
|
|
607
623
|
onStageChange?.('streaming');
|
|
608
|
-
} catch {
|
|
624
|
+
} catch {
|
|
625
|
+
// the stage observer is advisory
|
|
626
|
+
}
|
|
609
627
|
|
|
610
628
|
const midState = createMidState(attemptIndex);
|
|
611
629
|
try {
|
|
@@ -623,7 +641,9 @@ export class AnthropicOAuthProvider {
|
|
|
623
641
|
);
|
|
624
642
|
try {
|
|
625
643
|
controller?.abort?.('Anthropic SSE complete');
|
|
626
|
-
} catch {
|
|
644
|
+
} catch {
|
|
645
|
+
// the stream is complete; the controller may already be aborted
|
|
646
|
+
}
|
|
627
647
|
this._settleStreamedTurn({
|
|
628
648
|
result,
|
|
629
649
|
midState,
|
|
@@ -633,11 +653,7 @@ export class AnthropicOAuthProvider {
|
|
|
633
653
|
useModel,
|
|
634
654
|
requestKind: opts.requestKind || null,
|
|
635
655
|
});
|
|
636
|
-
|
|
637
|
-
Object.defineProperty(result, '__midstreamRetries', { value: attemptIndex, enumerable: false });
|
|
638
|
-
} catch {
|
|
639
|
-
/* ignore non-extensible result */
|
|
640
|
-
}
|
|
656
|
+
tagMidstreamRetries(result, attemptIndex);
|
|
641
657
|
return result;
|
|
642
658
|
} catch (err) {
|
|
643
659
|
const decision = await midstream.onStreamError({ err, midState, controller, response, attemptIndex });
|
|
@@ -649,22 +665,81 @@ export class AnthropicOAuthProvider {
|
|
|
649
665
|
}
|
|
650
666
|
throw midstream.exhaustedError();
|
|
651
667
|
} catch (err) {
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
return await this.send(messages, err.fallbackModel, tools, {
|
|
659
|
-
...opts,
|
|
660
|
-
fallbackModel: undefined,
|
|
661
|
-
_fallbackTriggered: true,
|
|
668
|
+
const fallbackOpts = takeAnthropicModelFallback(err, {
|
|
669
|
+
tag: 'anthropic-oauth',
|
|
670
|
+
model: useModel,
|
|
671
|
+
opts,
|
|
672
|
+
onStageChange,
|
|
673
|
+
displayModel: _displayModel,
|
|
662
674
|
});
|
|
675
|
+
return await this.send(messages, err.fallbackModel, tools, fallbackOpts);
|
|
663
676
|
} finally {
|
|
664
677
|
totalTimeout.cleanup();
|
|
665
678
|
}
|
|
666
679
|
}
|
|
667
680
|
|
|
681
|
+
// The request and recovery pipeline of one send over its fixed body: the
|
|
682
|
+
// shared overload counter, the retried request with its per-request beta
|
|
683
|
+
// headers, the non-streaming recovery and the bounded mid-stream retries.
|
|
684
|
+
_createSendRecovery({
|
|
685
|
+
opts,
|
|
686
|
+
body,
|
|
687
|
+
useModel,
|
|
688
|
+
sessionId,
|
|
689
|
+
auth,
|
|
690
|
+
totalSignal,
|
|
691
|
+
hasDeferredTools,
|
|
692
|
+
onStageChange,
|
|
693
|
+
onTextReset,
|
|
694
|
+
}) {
|
|
695
|
+
// Request-loop 529s and SSE overload events share one counter; at the
|
|
696
|
+
// limit the configured fallback model takes over the whole send.
|
|
697
|
+
const overload = createAnthropicOverloadTracker({
|
|
698
|
+
model: useModel,
|
|
699
|
+
fallbackModel: opts._fallbackTriggered ? undefined : opts.fallbackModel,
|
|
700
|
+
});
|
|
701
|
+
const { requestWithRetry, cleanupCancelHandler } = createAnthropicOAuthRequest({
|
|
702
|
+
provider: this,
|
|
703
|
+
opts,
|
|
704
|
+
body,
|
|
705
|
+
useModel,
|
|
706
|
+
sessionId,
|
|
707
|
+
totalSignal,
|
|
708
|
+
overload,
|
|
709
|
+
betaHeadersFor: (requestBody) =>
|
|
710
|
+
buildOAuthBetaHeaders(requestBody, {
|
|
711
|
+
fastMode: this.fastModeBetaHeaderLatched,
|
|
712
|
+
toolSearch: hasDeferredTools,
|
|
713
|
+
model: useModel,
|
|
714
|
+
opts,
|
|
715
|
+
}),
|
|
716
|
+
onStageChange,
|
|
717
|
+
});
|
|
718
|
+
const recovery = createAnthropicOAuthRecovery({
|
|
719
|
+
provider: this,
|
|
720
|
+
opts,
|
|
721
|
+
body,
|
|
722
|
+
useModel,
|
|
723
|
+
auth,
|
|
724
|
+
totalSignal,
|
|
725
|
+
requestWithRetry,
|
|
726
|
+
cleanupCancelHandler,
|
|
727
|
+
onStageChange,
|
|
728
|
+
onTextReset,
|
|
729
|
+
});
|
|
730
|
+
// Bounded mid-stream retries for transient stream loss; jittered backoff
|
|
731
|
+
// between attempts (anthropic-oauth-midstream.mjs).
|
|
732
|
+
const midstream = createMidstreamRecovery({
|
|
733
|
+
maxRetries: ANTHROPIC_MAX_MIDSTREAM_RETRIES,
|
|
734
|
+
totalSignal,
|
|
735
|
+
recovery,
|
|
736
|
+
onStageChange,
|
|
737
|
+
retry529: opts.retry529 !== false,
|
|
738
|
+
overload,
|
|
739
|
+
});
|
|
740
|
+
return { requestWithRetry, cleanupCancelHandler, midstream };
|
|
741
|
+
}
|
|
742
|
+
|
|
668
743
|
// One attempt's initial response: a 401 (or Anthropic's exact revoked-token
|
|
669
744
|
// 403) refreshes the credentials in `auth` and replays once; a context
|
|
670
745
|
// overflow 400 shrinks `body.max_tokens` and replays once per send
|
|
@@ -687,7 +762,9 @@ export class AnthropicOAuthProvider {
|
|
|
687
762
|
// resources before the credential-refresh replay.
|
|
688
763
|
try {
|
|
689
764
|
controller?.abort?.();
|
|
690
|
-
} catch {
|
|
765
|
+
} catch {
|
|
766
|
+
// the controller may already be aborted before the credential-refresh replay
|
|
767
|
+
}
|
|
691
768
|
auth.creds = await this.ensureAuth({ forceRefresh: true, reason: String(response.status) });
|
|
692
769
|
({ response, controller, cancelHandler } = await requestWithRetry(auth.creds.accessToken));
|
|
693
770
|
rejectedAuthBody = null;
|
|
@@ -702,7 +779,9 @@ export class AnthropicOAuthProvider {
|
|
|
702
779
|
cleanupCancelHandler(cancelHandler);
|
|
703
780
|
try {
|
|
704
781
|
controller?.abort?.();
|
|
705
|
-
} catch {
|
|
782
|
+
} catch {
|
|
783
|
+
// the controller may already be aborted before the max-tokens replay
|
|
784
|
+
}
|
|
706
785
|
({ response, controller, cancelHandler } = await requestWithRetry(auth.creds.accessToken));
|
|
707
786
|
rejectedAuthBody = null;
|
|
708
787
|
}
|
|
@@ -12,11 +12,15 @@
|
|
|
12
12
|
import { ANTHROPIC_MAX_CONSECUTIVE_529 } from './retry-backoff.mjs';
|
|
13
13
|
import { AnthropicFallbackTriggeredError } from './retry-classifier.mjs';
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
const OVERLOADED_ERROR_CODE = 'overloaded_error';
|
|
16
16
|
|
|
17
17
|
/** Consecutive 529s end the request only for API-key (non-subscriber) first-party Opus. */
|
|
18
18
|
export function isTerminalOverloadModel(model) {
|
|
19
|
-
return /^claude-opus-/.test(
|
|
19
|
+
return /^claude-opus-/.test(
|
|
20
|
+
String(model || '')
|
|
21
|
+
.trim()
|
|
22
|
+
.toLowerCase()
|
|
23
|
+
);
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
export function isAnthropicOverloadError(err) {
|
|
@@ -56,8 +60,26 @@ export function createAnthropicOverloadTracker({ model, fallbackModel, terminalA
|
|
|
56
60
|
};
|
|
57
61
|
}
|
|
58
62
|
|
|
63
|
+
/**
|
|
64
|
+
* The catch around a whole Anthropic send. The fallback trigger can surface
|
|
65
|
+
* from the request loop, a mid-stream overload, or the non-streaming
|
|
66
|
+
* recovery; any other error is rethrown unchanged. For the trigger it logs,
|
|
67
|
+
* announces the model switch, and returns the options of the single re-send
|
|
68
|
+
* on `err.fallbackModel` (no second hop).
|
|
69
|
+
*/
|
|
70
|
+
export function takeAnthropicModelFallback(err, { tag, model, opts, onStageChange, displayModel = (id) => id }) {
|
|
71
|
+
if (!(err instanceof AnthropicFallbackTriggeredError)) throw err;
|
|
72
|
+
process.stderr.write(`[${tag}] ${err.message}\n`);
|
|
73
|
+
announceAnthropicModelFallback(onStageChange, displayModel(model), displayModel(err.fallbackModel));
|
|
74
|
+
return {
|
|
75
|
+
...opts,
|
|
76
|
+
fallbackModel: undefined,
|
|
77
|
+
_fallbackTriggered: true,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
59
81
|
/** Visible model-switch notice on the existing display-only stage channel. */
|
|
60
|
-
|
|
82
|
+
function announceAnthropicModelFallback(onStageChange, fromLabel, toLabel) {
|
|
61
83
|
if (typeof onStageChange !== 'function') return;
|
|
62
84
|
try {
|
|
63
85
|
onStageChange('reconnecting', {
|
|
@@ -97,7 +97,7 @@ function _statusForAnthropicSseError(event, payload) {
|
|
|
97
97
|
return 0;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
function _anthropicSseError(event, labels) {
|
|
100
|
+
export function _anthropicSseError(event, labels) {
|
|
101
101
|
const payload = event?.error && typeof event.error === 'object' ? event.error : event;
|
|
102
102
|
const type = payload?.type || event?.type || 'error';
|
|
103
103
|
const message = payload?.message || 'Anthropic SSE error';
|
|
@@ -198,7 +198,9 @@ export async function parseSSEStream(
|
|
|
198
198
|
const progress = (kind) => {
|
|
199
199
|
try {
|
|
200
200
|
onStreamDelta?.(kind);
|
|
201
|
-
} catch {
|
|
201
|
+
} catch {
|
|
202
|
+
// the stream-delta observer is advisory
|
|
203
|
+
}
|
|
202
204
|
};
|
|
203
205
|
const turn = createAnthropicSseTurn({
|
|
204
206
|
state,
|
|
@@ -222,12 +224,7 @@ export async function parseSSEStream(
|
|
|
222
224
|
_captureMidstreamAbort(state, signal.reason);
|
|
223
225
|
return signal.reason instanceof Error ? signal.reason : new Error(`${labels.display} SSE stream aborted`);
|
|
224
226
|
};
|
|
225
|
-
const onAbort = () =>
|
|
226
|
-
try {
|
|
227
|
-
const _c = reader.cancel('SSE aborted');
|
|
228
|
-
if (_c && typeof _c.catch === 'function') _c.catch(() => {});
|
|
229
|
-
} catch {}
|
|
230
|
-
};
|
|
227
|
+
const onAbort = () => cancelReaderOnAbort(reader);
|
|
231
228
|
let buffer = '';
|
|
232
229
|
let currentEvent = '';
|
|
233
230
|
retainProviderSseStream(streamKey);
|
|
@@ -239,24 +236,12 @@ export async function parseSSEStream(
|
|
|
239
236
|
signal.addEventListener('abort', onAbort, { once: true });
|
|
240
237
|
}
|
|
241
238
|
watchdogs.armFirstMessageTimer();
|
|
242
|
-
|
|
239
|
+
while (true) {
|
|
243
240
|
let chunk;
|
|
244
241
|
try {
|
|
245
242
|
chunk = await watchdogs.read();
|
|
246
243
|
} catch (err) {
|
|
247
|
-
|
|
248
|
-
if (stopped) {
|
|
249
|
-
// The caller's cancellation reason may be shared: never stamp this
|
|
250
|
-
// request's usage on it; the usage reported so far goes to this send.
|
|
251
|
-
if (signal?.aborted && state?.sawMessageStart) {
|
|
252
|
-
const reported = turn.reportedUsage();
|
|
253
|
-
noteAbandonedUsage(reported.usage, reported.model);
|
|
254
|
-
}
|
|
255
|
-
throw stopped;
|
|
256
|
-
}
|
|
257
|
-
// The connection dropped mid-body: carry what this turn completed so
|
|
258
|
-
// the loop can continue from finished tool calls instead of failing.
|
|
259
|
-
throw state?.sawMessageStart ? turn.attachTransportPartial(err) : err;
|
|
244
|
+
throw readFailureError(err, { watchdogs, signal, state, turn, abortedError });
|
|
260
245
|
}
|
|
261
246
|
const { done, value } = chunk;
|
|
262
247
|
if (done) break;
|
|
@@ -277,10 +262,7 @@ export async function parseSSEStream(
|
|
|
277
262
|
const framed = frameProviderSseChunk(region, { currentEvent, streamKey });
|
|
278
263
|
const framedChunk = typeof framed?.then === 'function' ? await framed : framed;
|
|
279
264
|
currentEvent = framedChunk.currentEvent;
|
|
280
|
-
|
|
281
|
-
if (framedEvent.error) continue;
|
|
282
|
-
if (applyAnthropicSseEvent(framedEvent, { turn, watchdogs, state, progress, labels })) break streamLoop;
|
|
283
|
-
}
|
|
265
|
+
if (applyAnthropicSseChunk(framedChunk.events, { turn, watchdogs, state, progress, labels })) break;
|
|
284
266
|
}
|
|
285
267
|
turn.flushLeak();
|
|
286
268
|
if (state?.sawMessageStart && !state?.sawCompleted) throw turn.truncatedError();
|
|
@@ -289,20 +271,69 @@ export async function parseSSEStream(
|
|
|
289
271
|
watchdogs.dispose();
|
|
290
272
|
try {
|
|
291
273
|
releaseProviderSseStream(streamKey);
|
|
292
|
-
} catch {
|
|
274
|
+
} catch {
|
|
275
|
+
// releasing the stream registration is bookkeeping only
|
|
276
|
+
}
|
|
293
277
|
if (signal) signal.removeEventListener('abort', onAbort);
|
|
294
278
|
// message_stop deliberately exits before EOF because Anthropic may keep
|
|
295
279
|
// sending pings. Cancel the reader so the successful response body and
|
|
296
280
|
// underlying keep-alive connection are not stranded.
|
|
297
281
|
try {
|
|
298
282
|
await reader.cancel('Anthropic SSE complete');
|
|
299
|
-
} catch {
|
|
283
|
+
} catch {
|
|
284
|
+
// the reader may already be closed after the stream ended
|
|
285
|
+
}
|
|
286
|
+
releaseReaderLock(reader, labels);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Caller cancellation of a live stream: cancel the reader without awaiting it.
|
|
291
|
+
function cancelReaderOnAbort(reader) {
|
|
292
|
+
try {
|
|
293
|
+
const _c = reader.cancel('SSE aborted');
|
|
294
|
+
if (_c && typeof _c.catch === 'function') _c.catch(() => {});
|
|
295
|
+
} catch {
|
|
296
|
+
// the reader may already be closed or released
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// The error a failed reader.read() ends the stream with: a watchdog stop or the
|
|
301
|
+
// caller's abort as-is, otherwise the transport failure carrying the partial
|
|
302
|
+
// turn once the message started.
|
|
303
|
+
function readFailureError(err, { watchdogs, signal, state, turn, abortedError }) {
|
|
304
|
+
const stopped = watchdogs.readFailure() ?? (signal?.aborted ? abortedError() : null);
|
|
305
|
+
if (stopped) {
|
|
306
|
+
// The caller's cancellation reason may be shared: never stamp this
|
|
307
|
+
// request's usage on it; the usage reported so far goes to this send.
|
|
308
|
+
if (signal?.aborted && state?.sawMessageStart) {
|
|
309
|
+
const reported = turn.reportedUsage();
|
|
310
|
+
noteAbandonedUsage(reported.usage, reported.model);
|
|
311
|
+
}
|
|
312
|
+
return stopped;
|
|
313
|
+
}
|
|
314
|
+
// The connection dropped mid-body: carry what this turn completed so
|
|
315
|
+
// the loop can continue from finished tool calls instead of failing.
|
|
316
|
+
return state?.sawMessageStart ? turn.attachTransportPartial(err) : err;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Fold one network chunk's framed records into the turn, in order. Returns true
|
|
320
|
+
// once a terminal record ends the stream; a framing error skips its record.
|
|
321
|
+
function applyAnthropicSseChunk(events, context) {
|
|
322
|
+
for (const framedEvent of events) {
|
|
323
|
+
if (framedEvent.error) continue;
|
|
324
|
+
if (applyAnthropicSseEvent(framedEvent, context)) return true;
|
|
325
|
+
}
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function releaseReaderLock(reader, labels) {
|
|
330
|
+
try {
|
|
331
|
+
reader.releaseLock();
|
|
332
|
+
} catch (err) {
|
|
300
333
|
try {
|
|
301
|
-
reader
|
|
302
|
-
} catch
|
|
303
|
-
|
|
304
|
-
process.stderr.write(`[${labels.tag}] reader releaseLock failed: ${err?.message ?? String(err)}\n`);
|
|
305
|
-
} catch {}
|
|
334
|
+
process.stderr.write(`[${labels.tag}] reader releaseLock failed: ${err?.message ?? String(err)}\n`);
|
|
335
|
+
} catch {
|
|
336
|
+
// stderr may be closed; the releaseLock failure is only reported
|
|
306
337
|
}
|
|
307
338
|
}
|
|
308
339
|
}
|