mixdog 1.2.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/package.json +2 -1
- package/scripts/provider-pingpong-live.mjs +509 -0
- package/src/agents/advisor/AGENT.md +1 -1
- package/src/agents/advisor/agent.json +1 -1
- package/src/defaults/shipped-history.json +5 -0
- package/src/defaults/skills/setup/SKILL.md +6 -1
- package/src/defaults/skills/setup/references/actions.md +44 -22
- package/src/defaults/skills/setup/references/surfaces.md +10 -8
- package/src/headless-exec.mjs +15 -8
- package/src/lib/keychain-cjs.cjs +7 -4
- package/src/output-styles/common.md +11 -10
- package/src/rules/agent/AGENT.md +5 -5
- package/src/rules/lead/LEAD.md +5 -5
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
- package/src/runtime/agent/orchestrator/config.mjs +5 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +7 -6
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +29 -10
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +58 -7
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +16 -3
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +10 -61
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +12 -6
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +114 -72
- package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +37 -5
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +43 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +64 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +70 -6
- package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
- package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
- package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +25 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +87 -5
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +13 -13
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +355 -37
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +93 -47
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +55 -10
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +26 -8
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +246 -42
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
- package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +388 -0
- package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
- package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +48 -22
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +119 -18
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +33 -1
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +121 -61
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +37 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +47 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +151 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +42 -24
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +172 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +53 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +25 -4
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +71 -24
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -35
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +11 -3
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +170 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +75 -70
- package/src/runtime/agent/orchestrator/providers/openrouter.mjs +75 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +147 -8
- package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
- package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +157 -0
- package/src/runtime/agent/orchestrator/providers/wire-route.mjs +512 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +183 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +100 -0
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
- package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +14 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +176 -71
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +62 -10
- package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +14 -93
- package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +120 -0
- package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
- package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +91 -1
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
- package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +21 -10
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +132 -0
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +30 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +63 -20
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +150 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +208 -14
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +25 -3
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +19 -2
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/side-question.mjs +192 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +58 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +41 -28
- package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/store.mjs +19 -3
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +77 -0
- package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +14 -10
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +49 -34
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
- package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
- package/src/runtime/computer-bridge/action-schema.mjs +44 -21
- package/src/runtime/github/tool.mjs +92 -2
- package/src/runtime/memory/index.mjs +1 -0
- package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
- package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
- package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
- package/src/runtime/memory/lib/pg/process.mjs +31 -26
- package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +108 -3
- package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
- package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
- package/src/runtime/office/README.md +1 -1
- package/src/runtime/office/authoring/html-document-author.mjs +2 -0
- package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-measure.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +2 -0
- package/src/runtime/office/core/office-actions-read.mjs +3 -0
- package/src/runtime/office/core/office-render-preview.mjs +2 -0
- package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
- package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
- package/src/runtime/office/core/office-sessions.mjs +5 -0
- package/src/runtime/office/core/office-transactions.mjs +3 -0
- package/src/runtime/office/core/office-write-ledger.mjs +98 -0
- package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
- package/src/runtime/office/index.mjs +30 -0
- package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
- package/src/runtime/office/pdf/pdf-render.mjs +23 -7
- package/src/runtime/office/pdf/pdf-security.mjs +2 -0
- package/src/runtime/office/portable/portable-opc.mjs +4 -1
- package/src/runtime/office/quality/visual-diff.mjs +2 -0
- package/src/runtime/shared/bounded-file-read.mjs +13 -0
- package/src/runtime/shared/bounded-line-diff.mjs +182 -0
- package/src/runtime/shared/buffered-appender.mjs +18 -0
- package/src/runtime/shared/config.mjs +78 -18
- package/src/runtime/shared/err-text.mjs +6 -0
- package/src/runtime/shared/file-permissions.d.mts +6 -1
- package/src/runtime/shared/file-permissions.mjs +54 -6
- package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
- package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
- package/src/runtime/shared/loopback-listener.mjs +9 -0
- package/src/runtime/shared/provider-api-key.mjs +2 -0
- package/src/runtime/shared/review-diff.mjs +52 -0
- package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
- package/src/runtime/shared/session-sidebar-host.mjs +38 -0
- package/src/runtime/shared/slow-span.mjs +114 -0
- package/src/runtime/shared/statusline/statusline-segments.mjs +28 -4
- package/src/runtime/shared/tool-card-model/card-header.mjs +6 -1
- package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
- package/src/runtime/shared/tool-card-model.mjs +5 -2
- package/src/runtime/shared/tool-output-limit.mjs +4 -0
- package/src/runtime/shared/tool-primitives.mjs +13 -0
- package/src/runtime/shared/tool-result-summary.mjs +8 -1
- package/src/runtime/shared/tool-surface.mjs +18 -3
- package/src/runtime/shared/tool-work-units.mjs +40 -4
- package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
- package/src/runtime/shared/transcript-writer.mjs +10 -2
- package/src/runtime/shared/turn-changes.mjs +268 -100
- package/src/runtime/shared/turn-review-reply.mjs +8 -39
- package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
- package/src/runtime/shared/turn-snapshot.mjs +857 -683
- package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
- package/src/runtime/shared/user-data-guard.mjs +262 -49
- package/src/runtime/shared/worktrees/carry.mjs +531 -0
- package/src/runtime/shared/worktrees/contract.mjs +34 -0
- package/src/runtime/shared/worktrees/file-recovery.mjs +68 -0
- package/src/runtime/shared/worktrees/git-head.mjs +205 -0
- package/src/runtime/shared/worktrees/git.mjs +8 -3
- package/src/runtime/shared/worktrees/maintenance.mjs +1 -1
- package/src/runtime/shared/worktrees/manager.mjs +156 -8
- package/src/runtime/shared/worktrees/merge.mjs +31 -21
- package/src/runtime/shared/worktrees/paths.d.mts +6 -0
- package/src/runtime/terminal-bridge/client.mjs +44 -11
- package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
- package/src/runtime/tidy/apply.mjs +47 -2
- package/src/runtime/tidy/run-engines.mjs +11 -5
- package/src/session-runtime/agent-tool-routing.mjs +19 -13
- package/src/session-runtime/boot/apis.mjs +13 -5
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +6 -1
- package/src/session-runtime/boot/session.mjs +0 -1
- package/src/session-runtime/boot/tools.mjs +4 -1
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +65 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +11 -4
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +115 -18
- package/src/session-runtime/internal-tool-executor.mjs +6 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +188 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +29 -6
- package/src/session-runtime/lifecycle/teardown.mjs +72 -7
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/connect.mjs +17 -5
- package/src/session-runtime/model-route/set-route.mjs +2 -2
- package/src/session-runtime/native-web-search-usage.mjs +51 -0
- package/src/session-runtime/native-web-search.mjs +10 -1
- package/src/session-runtime/new-session-config.mjs +4 -2
- package/src/session-runtime/provider-auth/login.mjs +4 -0
- package/src/session-runtime/resource-scope-decorate.mjs +10 -3
- package/src/session-runtime/runtime-review-api.mjs +8 -2
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
- package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +73 -7
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +15 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
- package/src/session-runtime/services/agent-tool/worker-index.mjs +46 -7
- package/src/session-runtime/services/agent-tool.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +19 -3
- package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
- package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
- package/src/session-runtime/services/provider-admin.mjs +81 -15
- package/src/session-runtime/session-transcript-purge.mjs +32 -0
- package/src/session-runtime/session-turn-api.mjs +14 -5
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -0
- package/src/session-runtime/setup-tool/executor.mjs +36 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
- package/src/session-runtime/setup-tool/settings-contract.mjs +13 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +13 -4
- package/src/session-runtime/skills-api.mjs +3 -5
- package/src/session-runtime/tool-surface.mjs +5 -1
- package/src/session-runtime/turn/compaction-gate.mjs +25 -0
- package/src/session-runtime/turn/session-ops.mjs +7 -5
- package/src/session-runtime/turn/side-question-ops.mjs +22 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +5 -1
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +8 -3
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +10 -0
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +25 -9
- package/src/session-runtime/usage-stats-api.mjs +43 -11
- package/src/session-runtime/workspace/project-branches.mjs +7 -5
- package/src/session-runtime/workspace/transition-steps.mjs +129 -31
- package/src/session-runtime/workspace/transitions.mjs +190 -15
- package/src/standalone/daemon-agent-control.mjs +9 -1
- package/src/standalone/daemon-local-session-bridge.mjs +14 -1
- package/src/standalone/daemon-owner.mjs +17 -4
- package/src/standalone/daemon-pg-stop.mjs +51 -0
- package/src/standalone/daemon-stop-budget.d.mts +2 -0
- package/src/standalone/daemon-stop-budget.mjs +18 -0
- package/src/standalone/daemon-stored-session-views.mjs +2 -0
- package/src/standalone/daemon-telemetry.mjs +19 -0
- package/src/standalone/daemon.mjs +61 -1
- package/src/standalone/desktop-service-registry.mjs +5 -0
- package/src/standalone/local-session-runtime.mjs +70 -19
- package/src/standalone/session-client.mjs +42 -0
- package/src/standalone/session-protocol.mjs +7 -0
- package/src/standalone/session-proxy/projection.mjs +41 -4
- package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
- package/src/standalone/session-runtime-inline-host.mjs +1 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
- package/src/standalone/session-service-api.mjs +6 -1
- package/src/standalone/session-state-patch.d.mts +2 -1
- package/src/standalone/session-state-patch.mjs +41 -1
- package/src/tui/App.jsx +25 -0
- package/src/tui/app/app-view/floating-panel.jsx +26 -1
- package/src/tui/app/btw-controller.mjs +118 -0
- package/src/tui/app/create-app-pickers.mjs +2 -0
- package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
- package/src/tui/app/shell-layout/surfaces.mjs +3 -1
- package/src/tui/app/slash-commands.mjs +13 -3
- package/src/tui/app/slash-dispatch/session-commands.mjs +19 -6
- package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
- package/src/tui/app/use-global-key-input.mjs +5 -12
- package/src/tui/app/use-prompt-handlers.mjs +11 -0
- package/src/tui/components/BtwPanel.jsx +53 -0
- package/src/tui/components/QuestionPanel.jsx +275 -0
- package/src/tui/components/question-panel-model.mjs +156 -0
- package/src/tui/dist/index.mjs +2413 -1465
- package/src/tui/session/context-state.mjs +4 -2
- package/src/tui/session/session-api/commands.mjs +10 -0
- package/src/tui/session/session-api/controls.mjs +2 -2
- package/src/tui/session/session-api/integrations.mjs +9 -2
- package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle.mjs +2 -1
- package/src/tui/session/session-api/settings.mjs +6 -0
- package/src/tui/session/session-api.mjs +1 -0
- package/src/tui/session/tool-approval.mjs +10 -7
- package/src/tui/session/transcript-spill.mjs +14 -7
- package/src/tui/session/turn-stream.mjs +174 -31
- package/src/tui/session/turn.mjs +12 -5
- package/src/workflows/default/WORKFLOW.md +3 -1
|
@@ -1,30 +1,49 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { AnthropicProvider } from './anthropic.mjs';
|
|
3
3
|
import { OpenAICompatProvider, OPENAI_COMPAT_PRESETS } from './openai-compat.mjs';
|
|
4
|
-
import { currentUsageContext } from '../../../shared/llm/usage-context.mjs';
|
|
5
4
|
import { getModelMetadataSync, getModelsDevRowSync } from './model-catalog.mjs';
|
|
5
|
+
import { toInclusiveUsage, withInclusiveUsage } from './lib/inclusive-usage.mjs';
|
|
6
|
+
import { providerOffersWire, resolveWireRoute, sendOnRoute } from './wire-route.mjs';
|
|
7
|
+
import { gatewayMessagesOpts } from './wire-gateway.mjs';
|
|
8
|
+
|
|
9
|
+
// The Go Anthropic route: the shared request builder gets the model's output
|
|
10
|
+
// ceiling (models.dev limit) through the gateway options.
|
|
11
|
+
class OpenCodeGoMessagesEngine extends AnthropicProvider {
|
|
12
|
+
_sendOnce(messages, model, tools, opts) {
|
|
13
|
+
return super._sendOnce(messages, model, tools, gatewayMessagesOpts(this.config, model, messages, opts));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
6
16
|
|
|
7
17
|
// OpenCode Go publishes OpenAI chat/completions, OpenAI Responses, and
|
|
8
18
|
// Anthropic Messages endpoints, and each upstream brand answers on only one
|
|
9
|
-
// of them (muse-spark / gpt / grok 500 on chat/completions; minimax
|
|
10
|
-
// Messages). models.dev names the SDK package per model, which
|
|
11
|
-
// authoritative wire selector;
|
|
12
|
-
|
|
13
|
-
|
|
19
|
+
// of them (muse-spark / gpt / grok 500 on chat/completions; minimax and
|
|
20
|
+
// Claude expect Messages). models.dev names the SDK package per model, which
|
|
21
|
+
// is the authoritative wire selector; wire-route.mjs holds the cold-catalog
|
|
22
|
+
// prefix fallback. `@ai-sdk/google` names the Gemini generateContent wire
|
|
23
|
+
// (opencode-go-gemini.mjs).
|
|
14
24
|
const WIRE_API_BY_NPM = Object.freeze({
|
|
15
25
|
'@ai-sdk/openai': 'responses',
|
|
16
26
|
'@ai-sdk/anthropic': 'messages',
|
|
17
27
|
'@ai-sdk/openai-compatible': 'chat',
|
|
28
|
+
'@ai-sdk/google': 'gemini',
|
|
18
29
|
});
|
|
19
30
|
|
|
31
|
+
function openCodeGoCatalogWire(model) {
|
|
32
|
+
const npm = getModelsDevRowSync(String(model || ''), 'opencode-go')?.npm;
|
|
33
|
+
return typeof npm === 'string' && Object.hasOwn(WIRE_API_BY_NPM, npm) ? WIRE_API_BY_NPM[npm] : null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function resolveOpenCodeGoWireRoute(model, ctx = {}) {
|
|
37
|
+
const catalogWire = openCodeGoCatalogWire(model);
|
|
38
|
+
// Each Go model answers on the one wire the catalog names: it narrows the
|
|
39
|
+
// offered endpoints, so an override cannot pick a wire the model lacks.
|
|
40
|
+
const endpoints = providerOffersWire('opencode-go', catalogWire) ? [catalogWire] : null;
|
|
41
|
+
return resolveWireRoute('opencode-go', model, { ...ctx, catalogWire, endpoints });
|
|
42
|
+
}
|
|
43
|
+
|
|
20
44
|
/** Wire API for a Go model: 'responses' | 'messages' | 'chat'. */
|
|
21
45
|
function openCodeGoWireApi(model) {
|
|
22
|
-
|
|
23
|
-
const npm = getModelsDevRowSync(String(model || ''), 'opencode-go')?.npm;
|
|
24
|
-
if (npm && WIRE_API_BY_NPM[npm]) return WIRE_API_BY_NPM[npm];
|
|
25
|
-
if (RESPONSES_MODEL_PREFIXES.some((prefix) => id.startsWith(prefix))) return 'responses';
|
|
26
|
-
if (ANTHROPIC_MODEL_PREFIXES.some((prefix) => id.startsWith(prefix))) return 'messages';
|
|
27
|
-
return 'chat';
|
|
46
|
+
return resolveOpenCodeGoWireRoute(model).wire;
|
|
28
47
|
}
|
|
29
48
|
|
|
30
49
|
export function isAnthropicGoModel(model) {
|
|
@@ -48,42 +67,8 @@ export function openCodeGoEndpointForModel(model, configuredBaseURL) {
|
|
|
48
67
|
return `${bases.openai}/chat/completions`;
|
|
49
68
|
}
|
|
50
69
|
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
// and one source object always converts to the same object, so an abandoned
|
|
54
|
-
// attempt and the error that later carries it stay one record.
|
|
55
|
-
const inclusiveUsage = new WeakSet();
|
|
56
|
-
const convertedUsage = new WeakMap();
|
|
57
|
-
|
|
58
|
-
export function toInclusiveOpenCodeGoUsage(usage) {
|
|
59
|
-
if (!usage || inclusiveUsage.has(usage)) return usage;
|
|
60
|
-
if (convertedUsage.has(usage)) return convertedUsage.get(usage);
|
|
61
|
-
const input = Number(usage.inputTokens) || 0;
|
|
62
|
-
const cached = Number(usage.cachedTokens) || 0;
|
|
63
|
-
const cacheWrite = Number(usage.cacheWriteTokens) || 0;
|
|
64
|
-
const inclusiveInput = input + cached + cacheWrite;
|
|
65
|
-
const converted = {
|
|
66
|
-
...usage,
|
|
67
|
-
inputTokens: inclusiveInput,
|
|
68
|
-
promptTokens: Math.max(Number(usage.promptTokens) || 0, inclusiveInput),
|
|
69
|
-
};
|
|
70
|
-
inclusiveUsage.add(converted);
|
|
71
|
-
convertedUsage.set(usage, converted);
|
|
72
|
-
return converted;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function normalizeOpenCodeGoResultUsage(result, anthropicRoute) {
|
|
76
|
-
if (!anthropicRoute || !result?.usage) return result;
|
|
77
|
-
return { ...result, usage: toInclusiveOpenCodeGoUsage(result.usage) };
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function normalizeOpenCodeGoError(error) {
|
|
81
|
-
if (error && typeof error === 'object') {
|
|
82
|
-
if (error.usage) error.usage = toInclusiveOpenCodeGoUsage(error.usage);
|
|
83
|
-
if (error.partialUsage) error.partialUsage = toInclusiveOpenCodeGoUsage(error.partialUsage);
|
|
84
|
-
}
|
|
85
|
-
return error;
|
|
86
|
-
}
|
|
70
|
+
// The Messages route reports usage in the provider's inclusive convention.
|
|
71
|
+
export const toInclusiveOpenCodeGoUsage = toInclusiveUsage;
|
|
87
72
|
|
|
88
73
|
function opencodeGoContextWindow(modelId, current = 0) {
|
|
89
74
|
const native = Number(current);
|
|
@@ -118,11 +103,15 @@ export class OpenCodeGoProvider {
|
|
|
118
103
|
const preset = OPENAI_COMPAT_PRESETS['opencode-go'];
|
|
119
104
|
const bases = resolveOpenCodeGoBaseURLs(config.baseURL || preset.baseURL);
|
|
120
105
|
this.openai = new OpenAICompatProvider('opencode-go', { ...config, baseURL: bases.openai });
|
|
121
|
-
this.anthropic = new
|
|
106
|
+
this.anthropic = new OpenCodeGoMessagesEngine({
|
|
122
107
|
...config,
|
|
123
108
|
name: 'opencode-go',
|
|
124
109
|
baseURL: bases.anthropic,
|
|
125
110
|
disableBetaHeaders: true,
|
|
111
|
+
// The preset's identifying headers (User-Agent) ride the Messages wire
|
|
112
|
+
// too; the user's own headers win.
|
|
113
|
+
extraHeaders: { ...(preset.extraHeaders || {}), ...(config.extraHeaders || {}) },
|
|
114
|
+
modelMaxOutputTokens: (model) => this.getCachedModelInfo(model)?.outputTokens,
|
|
126
115
|
});
|
|
127
116
|
// The Anthropic route answers for this provider: PDFs lower to text.
|
|
128
117
|
this.anthropic.nativePdf = this.nativePdf;
|
|
@@ -142,29 +131,45 @@ export class OpenCodeGoProvider {
|
|
|
142
131
|
'x-opencode-session': sessionId,
|
|
143
132
|
},
|
|
144
133
|
};
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
return
|
|
163
|
-
} catch (error) {
|
|
164
|
-
throw normalizeOpenCodeGoError(error);
|
|
134
|
+
// The session's pinned route, else this model's route (wire-route.mjs);
|
|
135
|
+
// the resolved route is the only wire authority (a caller's own wire
|
|
136
|
+
// switches never reach an engine), and one clear "unsupported" refusal
|
|
137
|
+
// moves the send to the next wire once.
|
|
138
|
+
return sendOnRoute(this, model, tools, sendOpts, messages, async (wire, history, opts) => {
|
|
139
|
+
if (wire === 'responses') {
|
|
140
|
+
// OpenAI-family brands on the gateway (Muse Spark, GPT, Grok)
|
|
141
|
+
// only answer on /responses; the compat transport switches wire
|
|
142
|
+
// shape per request via this flag.
|
|
143
|
+
return this.openai.send(history, model, tools, { ...opts, compatWireApi: 'responses' });
|
|
144
|
+
}
|
|
145
|
+
if (wire === 'messages') {
|
|
146
|
+
// The Anthropic-style Go endpoint reports cached read/write usage
|
|
147
|
+
// and accepts the standard message shape. Preserve the caller's
|
|
148
|
+
// cache strategy so the shared Anthropic live-tail marker advances
|
|
149
|
+
// through tool loops instead of forcing every request fully cold.
|
|
150
|
+
// Abandoned attempts noted by the inner provider use the same conversion.
|
|
151
|
+
return withInclusiveUsage(() => this.anthropic.send(history, model, tools, opts));
|
|
165
152
|
}
|
|
153
|
+
if (wire === 'gemini') return (await this._geminiEngine()).send(history, model, tools, opts);
|
|
154
|
+
return this.openai.send(history, model, tools, opts);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// The Gemini generateContent route; the Google SDK loads only when a Gemini model is used.
|
|
159
|
+
async _geminiEngine() {
|
|
160
|
+
if (!this.gemini) {
|
|
161
|
+
const { OpenCodeGoGeminiEngine } = await import('./opencode-go-gemini.mjs');
|
|
162
|
+
this.gemini = new OpenCodeGoGeminiEngine({
|
|
163
|
+
...this.config,
|
|
164
|
+
baseURL: this.openai.baseURL,
|
|
165
|
+
extraHeaders: { ...(OPENAI_COMPAT_PRESETS['opencode-go'].extraHeaders || {}), ...(this.config.extraHeaders || {}) },
|
|
166
|
+
});
|
|
166
167
|
}
|
|
167
|
-
return this.
|
|
168
|
+
return this.gemini;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
resolveWireRoute(model, ctx = {}) {
|
|
172
|
+
return resolveOpenCodeGoWireRoute(model, { ...ctx, override: this.config?.modelWires?.[model] ?? null });
|
|
168
173
|
}
|
|
169
174
|
|
|
170
175
|
async listModels() {
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenRouter: one API key, three wires. Claude (`anthropic/*`, `~anthropic/*`)
|
|
3
|
+
* goes through the Anthropic Messages engine at https://openrouter.ai/api (the
|
|
4
|
+
* SDK appends /v1/messages); OpenAI GPT / o-series (`openai/gpt-*`,
|
|
5
|
+
* `openai/o*`, `~openai/*`) through the OpenAI-compatible engine's Responses
|
|
6
|
+
* wire; openrouter/auto and every other model through Chat Completions.
|
|
7
|
+
* Account-level provider-routing preferences stay OpenRouter's: no request
|
|
8
|
+
* names a provider order.
|
|
9
|
+
*/
|
|
10
|
+
import { WireGatewayProvider, messagesBaseFromOpenAIBase } from './wire-gateway.mjs';
|
|
11
|
+
import { OPENAI_COMPAT_PRESETS } from './openai-compat-presets.mjs';
|
|
12
|
+
import { openRouterReasoning } from './openai-compat-options.mjs';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The Claude id a routing slug stands for: an alias (`~anthropic/claude-opus-latest`)
|
|
16
|
+
* reads its catalog `alias_target`, the vendor prefix and a `:variant` suffix
|
|
17
|
+
* drop. Capability lookup only — the request still names the routing slug.
|
|
18
|
+
*/
|
|
19
|
+
export function openRouterCapabilityModel(model, aliasTarget = null) {
|
|
20
|
+
return String(aliasTarget || model || '')
|
|
21
|
+
.replace(/^~/, '')
|
|
22
|
+
.replace(/^anthropic\//i, '')
|
|
23
|
+
.replace(/:[^/]*$/, '');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Responses requests carry the same reasoning control as Chat requests
|
|
27
|
+
// (`openRouterReasoningEffort`, else the turn effort, else the configured
|
|
28
|
+
// effort; `none` disables reasoning).
|
|
29
|
+
function openRouterResponsesParams(config) {
|
|
30
|
+
return (params, { opts }) => {
|
|
31
|
+
const reasoning = openRouterReasoning(opts, config);
|
|
32
|
+
if (reasoning) params.reasoning = reasoning;
|
|
33
|
+
else delete params.reasoning;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// The Messages route takes the same control: the effort to send ('none' = no
|
|
38
|
+
// thinking), or null to keep the engine's own handling.
|
|
39
|
+
function openRouterMessagesEffort(config) {
|
|
40
|
+
return (opts) => {
|
|
41
|
+
const reasoning = openRouterReasoning(opts, config);
|
|
42
|
+
if (!reasoning) return null;
|
|
43
|
+
return reasoning.enabled === false ? 'none' : reasoning.effort;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** A roster row carrying `top_provider.max_completion_tokens` as its output ceiling. */
|
|
48
|
+
export function withTopProviderOutputCeiling(item) {
|
|
49
|
+
const ceiling = Number(item?.top_provider?.max_completion_tokens);
|
|
50
|
+
if (!(ceiling > 0) || item.max_output_tokens !== undefined) return item;
|
|
51
|
+
return { ...item, max_output_tokens: ceiling };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export class OpenRouterProvider extends WireGatewayProvider {
|
|
55
|
+
constructor(config = {}) {
|
|
56
|
+
const baseURL = config.baseURL || OPENAI_COMPAT_PRESETS.openrouter.baseURL;
|
|
57
|
+
super(
|
|
58
|
+
'openrouter',
|
|
59
|
+
config,
|
|
60
|
+
{
|
|
61
|
+
baseURL: messagesBaseFromOpenAIBase(baseURL),
|
|
62
|
+
authScheme: 'bearer',
|
|
63
|
+
// OpenRouter Messages takes PDFs natively as document blocks.
|
|
64
|
+
nativePdf: true,
|
|
65
|
+
messagesEffort: openRouterMessagesEffort(config),
|
|
66
|
+
capabilityModel: (model) => openRouterCapabilityModel(model, this.getCachedModelInfo(model)?.aliasTarget),
|
|
67
|
+
},
|
|
68
|
+
{ responsesParamsHook: openRouterResponsesParams(config) }
|
|
69
|
+
);
|
|
70
|
+
// The roster's output ceiling is `top_provider.max_completion_tokens`.
|
|
71
|
+
const fetchItems = this.openai._fetchModelItems.bind(this.openai);
|
|
72
|
+
this.openai._fetchModelItems = async (options) =>
|
|
73
|
+
(await fetchItems(options)).map(withTopProviderOutputCeiling);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -37,6 +37,26 @@ export function boundedCauseChain(err) {
|
|
|
37
37
|
return chain;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
const TOOL_SURFACE_EXCEEDS_CONTEXT = 'TOOL_SURFACE_EXCEEDS_CONTEXT';
|
|
41
|
+
const TOOL_SURFACE_MARKER = `(${TOOL_SURFACE_EXCEEDS_CONTEXT})`;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The local fixed-overhead refusal (session/loop/context-overflow.mjs), bare,
|
|
45
|
+
* wrapped as a cause, or persisted as its text. Never a provider overflow:
|
|
46
|
+
* its diagnostic names tools, and a tool named like a provider error code
|
|
47
|
+
* must not turn it into one.
|
|
48
|
+
*/
|
|
49
|
+
export function isToolSurfaceExceedsContextError(err) {
|
|
50
|
+
if (!err || (typeof err !== 'string' && typeof err !== 'object' && typeof err !== 'function')) return false;
|
|
51
|
+
// Every node of the chain: an Error, or persisted failure text kept as a cause.
|
|
52
|
+
return boundedCauseChain(err).some((item) =>
|
|
53
|
+
typeof item === 'string'
|
|
54
|
+
? item.includes(TOOL_SURFACE_MARKER)
|
|
55
|
+
: item?.code === TOOL_SURFACE_EXCEEDS_CONTEXT ||
|
|
56
|
+
(typeof item?.message === 'string' && item.message.includes(TOOL_SURFACE_MARKER))
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
40
60
|
export function headerValue(headers, name) {
|
|
41
61
|
if (!headers) return null;
|
|
42
62
|
const lower = name.toLowerCase();
|
|
@@ -78,6 +98,8 @@ export function errorHeaderValue(err, name) {
|
|
|
78
98
|
|
|
79
99
|
export function typedErrorCode(err) {
|
|
80
100
|
const detail = wireDetail(err);
|
|
101
|
+
const canonical = err && typeof err === 'object' ? codeFields(err).canonical.find(Boolean) : null;
|
|
102
|
+
if (canonical) return canonical;
|
|
81
103
|
for (const field of [detail?.code, detail?.type, err?.providerErrorCode, err?.code, err?.error?.code]) {
|
|
82
104
|
if (typeof field === 'string' && field.trim()) return field.trim().toLowerCase();
|
|
83
105
|
}
|
|
@@ -375,9 +397,66 @@ const KIND_RANK = [
|
|
|
375
397
|
'invalid_request',
|
|
376
398
|
];
|
|
377
399
|
|
|
400
|
+
// OpenRouter's canonical `error_type` vocabulary, stable across its Chat,
|
|
401
|
+
// Responses and Messages skins (the native code beside it is lossy: on
|
|
402
|
+
// Responses an auth failure arrives as `server_error`, a context overflow as
|
|
403
|
+
// `invalid_prompt`), mapped onto the typed codes classified here.
|
|
404
|
+
const GATEWAY_ERROR_TYPE_CODES = Object.freeze({
|
|
405
|
+
authentication: 'authentication_error',
|
|
406
|
+
permission_denied: 'permission_denied',
|
|
407
|
+
payment_required: 'payment_required',
|
|
408
|
+
context_length_exceeded: 'context_length_exceeded',
|
|
409
|
+
payload_too_large: 'payload_too_large',
|
|
410
|
+
image_too_large: 'request_too_large',
|
|
411
|
+
rate_limit_exceeded: 'rate_limit_exceeded',
|
|
412
|
+
provider_overloaded: 'overloaded',
|
|
413
|
+
provider_unavailable: 'service_unavailable',
|
|
414
|
+
timeout: 'timeout',
|
|
415
|
+
server: 'server_error',
|
|
416
|
+
content_policy_violation: 'content_policy_violation',
|
|
417
|
+
refusal: 'content_policy_violation',
|
|
418
|
+
invalid_request: 'invalid_request',
|
|
419
|
+
invalid_prompt: 'invalid_request',
|
|
420
|
+
unprocessable: 'invalid_request',
|
|
421
|
+
not_found: 'not_found',
|
|
422
|
+
precondition_failed: 'failed_precondition',
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
/** The typed code a gateway `error_type` names, or null for an absent/unmapped one. */
|
|
426
|
+
export function gatewayErrorTypeCode(errorType) {
|
|
427
|
+
const key = typeof errorType === 'string' ? errorType.trim().toLowerCase() : '';
|
|
428
|
+
return key && Object.hasOwn(GATEWAY_ERROR_TYPE_CODES, key) ? GATEWAY_ERROR_TYPE_CODES[key] : null;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Pre-classification normalizer for a wire error detail: when the envelope
|
|
433
|
+
* (or the detail itself) carries a gateway `error_type`, its typed code
|
|
434
|
+
* replaces the lossy native code (kept as `native_code`). Any other detail is
|
|
435
|
+
* returned unchanged.
|
|
436
|
+
*/
|
|
437
|
+
export function normalizeGatewayErrorDetail(detail, envelope = null) {
|
|
438
|
+
const errorType =
|
|
439
|
+
envelope?.response?.error_type ?? envelope?.error_type ?? detail?.error_type ?? detail?.metadata?.error_type;
|
|
440
|
+
const code = gatewayErrorTypeCode(errorType);
|
|
441
|
+
if (!code) return detail;
|
|
442
|
+
const nativeCode = detail?.code;
|
|
443
|
+
return {
|
|
444
|
+
...(detail && typeof detail === 'object' ? detail : {}),
|
|
445
|
+
code,
|
|
446
|
+
error_type: errorType,
|
|
447
|
+
...(nativeCode != null && nativeCode !== code ? { native_code: nativeCode } : {}),
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
|
|
378
451
|
function codeFields(item) {
|
|
379
452
|
const detail = wireDetail(item);
|
|
380
|
-
|
|
453
|
+
const canonical = [
|
|
454
|
+
gatewayErrorTypeCode(detail?.error_type ?? detail?.metadata?.error_type),
|
|
455
|
+
gatewayErrorTypeCode(item?.error_type),
|
|
456
|
+
gatewayErrorTypeCode(item?.error?.error_type ?? item?.error?.metadata?.error_type),
|
|
457
|
+
gatewayErrorTypeCode(item?.error?.error?.error_type),
|
|
458
|
+
];
|
|
459
|
+
const native = [
|
|
381
460
|
detail?.code,
|
|
382
461
|
detail?.type,
|
|
383
462
|
detail?.status,
|
|
@@ -396,19 +475,25 @@ function codeFields(item) {
|
|
|
396
475
|
item?.geminiStatus,
|
|
397
476
|
item?.status,
|
|
398
477
|
];
|
|
478
|
+
return { canonical, native };
|
|
399
479
|
}
|
|
400
480
|
|
|
481
|
+
// A gateway's canonical `error_type` supersedes every native code in the chain.
|
|
401
482
|
function typedCodes(chain) {
|
|
402
|
-
const
|
|
483
|
+
const canonical = [];
|
|
484
|
+
const native = [];
|
|
485
|
+
const add = (codes, field) => {
|
|
486
|
+
if (typeof field !== 'string') return;
|
|
487
|
+
const code = field.trim().toLowerCase();
|
|
488
|
+
if (code && !codes.includes(code)) codes.push(code);
|
|
489
|
+
};
|
|
403
490
|
for (const item of chain) {
|
|
404
491
|
if (!item || typeof item !== 'object') continue;
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
if (code && !codes.includes(code)) codes.push(code);
|
|
409
|
-
}
|
|
492
|
+
const fields = codeFields(item);
|
|
493
|
+
for (const field of fields.canonical) add(canonical, field);
|
|
494
|
+
for (const field of fields.native) add(native, field);
|
|
410
495
|
}
|
|
411
|
-
return
|
|
496
|
+
return canonical.length ? canonical : native;
|
|
412
497
|
}
|
|
413
498
|
|
|
414
499
|
const VALID_STATUS = (n) => Number.isFinite(n) && n >= 100 && n <= 599;
|
|
@@ -421,6 +506,53 @@ function statusOf(err) {
|
|
|
421
506
|
return 0;
|
|
422
507
|
}
|
|
423
508
|
|
|
509
|
+
// OpenRouter answers a 402 with this marker when concurrent in-flight spend is
|
|
510
|
+
// capped; it clears as requests finish (Retry-After), unlike a spent balance.
|
|
511
|
+
const IN_FLIGHT_BUDGET = 'openrouter_in_flight_budget';
|
|
512
|
+
|
|
513
|
+
const IN_FLIGHT_BUDGET_MAX_WAIT_MS = 60_000;
|
|
514
|
+
|
|
515
|
+
// Retry-After advice for the budget exception: a valid `0` ("retry now") is
|
|
516
|
+
// advice here, although retryAfterMsFromError treats zero as none.
|
|
517
|
+
function inFlightAdviceMs(err) {
|
|
518
|
+
const advised = retryAfterMsFromError(err);
|
|
519
|
+
if (advised != null) return advised;
|
|
520
|
+
for (const [name, unitMs] of [['retry-after-ms', 1], ['retry-after', 1000]]) {
|
|
521
|
+
const value = errorHeaderValue(err, name);
|
|
522
|
+
const n = Number(value);
|
|
523
|
+
if (value != null && String(value).trim() !== '' && Number.isFinite(n) && n >= 0) return n * unitMs;
|
|
524
|
+
}
|
|
525
|
+
return null;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// Only a 402 that names the marker AND carries Retry-After advice of 0..60s
|
|
529
|
+
// inclusive is a wait; without advice (or with a long one) it stays billing.
|
|
530
|
+
function isInFlightBudget402(chain, status, adviceMs) {
|
|
531
|
+
if (status !== 402 || adviceMs == null || adviceMs > IN_FLIGHT_BUDGET_MAX_WAIT_MS) return false;
|
|
532
|
+
return chain.some((item) => {
|
|
533
|
+
if (!item || typeof item !== 'object') return false;
|
|
534
|
+
const detail = wireDetail(item);
|
|
535
|
+
return [
|
|
536
|
+
detail?.code,
|
|
537
|
+
detail?.type,
|
|
538
|
+
detail?.metadata?.code,
|
|
539
|
+
detail?.metadata?.type,
|
|
540
|
+
detail?.metadata?.reason,
|
|
541
|
+
detail?.metadata?.limit_source,
|
|
542
|
+
item.code,
|
|
543
|
+
item.type,
|
|
544
|
+
item.error?.code,
|
|
545
|
+
item.error?.type,
|
|
546
|
+
item.error?.metadata?.code,
|
|
547
|
+
item.error?.metadata?.type,
|
|
548
|
+
item.error?.metadata?.reason,
|
|
549
|
+
item.error?.metadata?.limit_source,
|
|
550
|
+
item.error?.error?.code,
|
|
551
|
+
item.error?.error?.type,
|
|
552
|
+
].some((value) => typeof value === 'string' && value.trim().toLowerCase() === IN_FLIGHT_BUDGET);
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
|
|
424
556
|
function kindFromStatus(status) {
|
|
425
557
|
if (status === 401) return 'auth';
|
|
426
558
|
if (status === 402) return 'billing';
|
|
@@ -513,10 +645,17 @@ export function providerErrorKind(err, options = {}) {
|
|
|
513
645
|
const codes = typedCodes(chain);
|
|
514
646
|
const describe = (kind, code = typedErrorCode(err)) => ({ kind, code: code || '', status, retryAfterMs, resetAt });
|
|
515
647
|
|
|
648
|
+
// A local fixed-overhead refusal is no provider kind, whatever its text names.
|
|
649
|
+
if (isToolSurfaceExceedsContextError(err)) return describe('unknown', TOOL_SURFACE_EXCEEDS_CONTEXT);
|
|
516
650
|
// Validated account-pool evidence and boundary-stamped re-auth decide first.
|
|
517
651
|
if (err.quotaExhausted && typeof err.quotaExhausted === 'object') return describe('quota_exhausted');
|
|
518
652
|
if (chain.some((item) => item?.reauthRequired === true)) return describe('auth');
|
|
519
653
|
|
|
654
|
+
if (isInFlightBudget402(chain, status, inFlightAdviceMs(err))) return describe('transient', IN_FLIGHT_BUDGET);
|
|
655
|
+
// Every other 402 is a billing refusal, whatever generic retryable code
|
|
656
|
+
// (server_error, rate_limit_exceeded) its body also carries.
|
|
657
|
+
if (status === 402) return describe('billing');
|
|
658
|
+
|
|
520
659
|
let { kind, code } = kindFromCodes(codes, scope);
|
|
521
660
|
// Explicit quota flags (Anthropic unified-status rejected headers) outrank a
|
|
522
661
|
// generic rate-limit code or status; they never turn an overload (or a more
|
|
@@ -179,6 +179,9 @@ const PROVIDER_MODULES = {
|
|
|
179
179
|
openai: ['./openai-ws.mjs', 'OpenAIDirectProvider'],
|
|
180
180
|
'mixdog-local': ['./mixdog-local.mjs', 'MixdogLocalProvider'],
|
|
181
181
|
'opencode-go': ['./opencode-go.mjs', 'OpenCodeGoProvider'],
|
|
182
|
+
// Multi-wire preset gateways (wire-route.mjs picks the wire per model).
|
|
183
|
+
openrouter: ['./openrouter.mjs', 'OpenRouterProvider'],
|
|
184
|
+
deepseek: ['./deepseek.mjs', 'DeepSeekProvider'],
|
|
182
185
|
};
|
|
183
186
|
|
|
184
187
|
// User-defined providers (cfg.type === 'custom') are keyed by a generated
|
|
@@ -209,7 +212,7 @@ async function instantiateProvider(name, Ctor, cfg, proxyChannel = null) {
|
|
|
209
212
|
return wrapProviderAdmission(createModelProxyProvider(name, cfg, proxyChannel ?? getModelProxyChannel()), name);
|
|
210
213
|
}
|
|
211
214
|
if (isCustomProviderConfig(name, cfg)) return wrapProviderAdmission(await Ctor(name, cfg), name);
|
|
212
|
-
if (Object.hasOwn(OPENAI_COMPAT_PRESETS, name) && name
|
|
215
|
+
if (Object.hasOwn(OPENAI_COMPAT_PRESETS, name) && !Object.hasOwn(PROVIDER_MODULES, name)) {
|
|
213
216
|
return wrapProviderAdmission(new Ctor(name, cfg), name);
|
|
214
217
|
}
|
|
215
218
|
return createAccountPoolProvider(name, () => wrapProviderAdmission(new Ctor(cfg), name));
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
TOKEN_CONTEXT_OVERFLOW_PATTERNS,
|
|
11
11
|
TRANSIENT_SDK_NAMES,
|
|
12
12
|
boundedCauseChain,
|
|
13
|
+
isToolSurfaceExceedsContextError,
|
|
13
14
|
isTransientErrorCode,
|
|
14
15
|
providerErrorKind,
|
|
15
16
|
typedCodeKind,
|
|
@@ -463,6 +464,10 @@ const REQUEST_TOO_LARGE_KIND = 'request_too_large';
|
|
|
463
464
|
*/
|
|
464
465
|
export function isContextOverflowError(err, _depth = 0) {
|
|
465
466
|
if (!err || _depth > 2) return false;
|
|
467
|
+
// A local fixed-overhead refusal (anywhere in the chain, at any recursion
|
|
468
|
+
// level) is never a provider overflow: compacting history cannot help it,
|
|
469
|
+
// whatever its text names.
|
|
470
|
+
if (isToolSurfaceExceedsContextError(err)) return false;
|
|
466
471
|
const code = typedErrorCode(err);
|
|
467
472
|
if (code && CONTEXT_OVERFLOW_CODES.has(code)) return true;
|
|
468
473
|
// A typed byte/media-size refusal (a size code, or HTTP 413 without a
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const TRANSPORT_SCOPE_DISPOSED: 'transport_scope_disposed';
|
|
2
|
+
export function forkTransportScope(sessionId: string, label?: string): string;
|
|
3
|
+
export function disposeTransportScope(
|
|
4
|
+
scope: string,
|
|
5
|
+
provider?: { releaseTransportScope?(scope: string): void } | null
|
|
6
|
+
): void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// transport-scope.mjs — a send's transport state scope, apart from its
|
|
2
|
+
// session identity. Providers key their session-scoped transport and
|
|
3
|
+
// continuation state (pooled sockets and their previous_response_id anchor,
|
|
4
|
+
// Codex turn-state routing tokens, sticky HTTP fallback, Cursor runs and
|
|
5
|
+
// conversations) by `opts.transportScope || opts.sessionId`, while prompt
|
|
6
|
+
// cache routing (prompt_cache_key, handshake session id) stays on
|
|
7
|
+
// `opts.sessionId`. A request forked from a session (/btw) runs in a scope of
|
|
8
|
+
// its own: it shares the session's prompt cache but reads and writes none of
|
|
9
|
+
// its transport state, and its scope is disposed once it is answered.
|
|
10
|
+
import { randomUUID } from 'node:crypto';
|
|
11
|
+
|
|
12
|
+
/** The reason a scope's provider connections are closed when it is disposed. */
|
|
13
|
+
export const TRANSPORT_SCOPE_DISPOSED = 'transport_scope_disposed';
|
|
14
|
+
|
|
15
|
+
/** A fresh transport scope for one request forked from `sessionId`. */
|
|
16
|
+
export function forkTransportScope(sessionId, label = 'fork') {
|
|
17
|
+
return `${sessionId}#${label}:${randomUUID()}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Close every connection and drop every transport record of `scope`. */
|
|
21
|
+
export function disposeTransportScope(scope, provider) {
|
|
22
|
+
if (!scope) return;
|
|
23
|
+
try {
|
|
24
|
+
globalThis.__mixdogCloseProviderConnectionsForSession?.(scope, TRANSPORT_SCOPE_DISPOSED);
|
|
25
|
+
} finally {
|
|
26
|
+
provider?.releaseTransportScope?.(scope);
|
|
27
|
+
}
|
|
28
|
+
}
|