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
|
@@ -2,23 +2,25 @@
|
|
|
2
2
|
* Command Code provider (commandcode.ai Provider API).
|
|
3
3
|
*
|
|
4
4
|
* Credentials are a Studio-issued API key (command-code-oauth-tokens.mjs).
|
|
5
|
-
* Each model is served on
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Command Code API host. The key never expires and
|
|
9
|
-
* 401 means the user must sign in again.
|
|
5
|
+
* Each model is served on a wire its /models row declares (wire-route.mjs
|
|
6
|
+
* picks among them): Chat Completions and Responses through the
|
|
7
|
+
* OpenAI-compatible engine, Messages through the Anthropic engine. Both
|
|
8
|
+
* clients are pinned to the Command Code API host. The key never expires and
|
|
9
|
+
* has no refresh grant: a 401 means the user must sign in again.
|
|
10
10
|
*/
|
|
11
11
|
import { noteErrorUsage } from './lib/note-error-usage.mjs';
|
|
12
12
|
import { fileMtimeMs, normalizeExpiresAtMs, scrubOAuthSecrets } from './lib/oauth-token-utils.mjs';
|
|
13
|
+
import { originBoundFetch } from './lib/origin-bound-fetch.mjs';
|
|
14
|
+
import { withInclusiveUsage } from './lib/inclusive-usage.mjs';
|
|
13
15
|
import { OpenAICompatProvider, preloadOpenAICompatRuntime } from './openai-compat.mjs';
|
|
14
16
|
import { COMPAT_RETRY_POLICY } from './openai-compat-retry-profile.mjs';
|
|
15
17
|
import { listCompatModels } from './openai-compat-models.mjs';
|
|
16
18
|
import { AnthropicProvider } from './anthropic.mjs';
|
|
17
|
-
import { toInclusiveOpenCodeGoUsage as toInclusiveUsage } from './opencode-go.mjs';
|
|
18
19
|
import { sanitizeToolPairs } from '../session/context-utils.mjs';
|
|
19
20
|
import { preparePdfTextForProvider } from './media-normalization.mjs';
|
|
20
|
-
import { currentUsageContext } from '../../../shared/llm/usage-context.mjs';
|
|
21
21
|
import { makeModelCache } from './model-cache.mjs';
|
|
22
|
+
import { resolveWireRoute, sendOnRoute } from './wire-route.mjs';
|
|
23
|
+
import { gatewayMessagesOpts } from './wire-gateway.mjs';
|
|
22
24
|
import {
|
|
23
25
|
API_ORIGIN,
|
|
24
26
|
CREDITS_URL,
|
|
@@ -38,8 +40,11 @@ export {
|
|
|
38
40
|
export { beginOAuthLogin, loginOAuth } from './command-code-oauth-login.mjs';
|
|
39
41
|
|
|
40
42
|
export const DEFAULT_MODEL = 'deepseek/deepseek-v4-flash';
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
+
const ENDPOINT_WIRES = Object.freeze({
|
|
44
|
+
'/chat/completions': 'chat',
|
|
45
|
+
'/messages': 'messages',
|
|
46
|
+
'/responses': 'responses',
|
|
47
|
+
});
|
|
43
48
|
// The Anthropic SDK appends /v1/messages itself.
|
|
44
49
|
const MESSAGES_BASE_URL = `${API_ORIGIN}/provider`;
|
|
45
50
|
const FIVE_HOURS_MS = 5 * 60 * 60 * 1000;
|
|
@@ -56,35 +61,42 @@ const commandCodeModelCache = makeModelCache({
|
|
|
56
61
|
});
|
|
57
62
|
|
|
58
63
|
/**
|
|
59
|
-
* The
|
|
60
|
-
*
|
|
61
|
-
|
|
64
|
+
* The wires a /models row declares (`supported_endpoints`), or null when it
|
|
65
|
+
* declares none — such a row is served on Chat Completions by convention.
|
|
66
|
+
*/
|
|
67
|
+
export function modelEndpoints(item) {
|
|
68
|
+
const declared = item?.supported_endpoints;
|
|
69
|
+
if (!Array.isArray(declared)) return null;
|
|
70
|
+
const wires = [];
|
|
71
|
+
for (const endpoint of declared) {
|
|
72
|
+
const path = String(endpoint).replace(/^\/?(?:provider\/)?(?:v1\/)?/, '/');
|
|
73
|
+
const wire = Object.hasOwn(ENDPOINT_WIRES, path) ? ENDPOINT_WIRES[path] : null;
|
|
74
|
+
if (wire && !wires.includes(wire)) wires.push(wire);
|
|
75
|
+
}
|
|
76
|
+
return wires;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// The route for a model with these declared endpoints (null: undeclared, Chat).
|
|
80
|
+
// `undefined`: nothing describes the model, so no wire is ruled out.
|
|
81
|
+
function commandCodeRoute(model, endpoints, ctx = {}) {
|
|
82
|
+
return resolveWireRoute(PROVIDER_ID, model, { ...ctx, endpoints: endpoints === undefined ? null : (endpoints ?? ['chat']) });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The wire a /models row is served on (wire-route.mjs over its declared
|
|
87
|
+
* endpoints): Responses for GPT / Muse / Grok when advertised, otherwise Chat
|
|
88
|
+
* when declared or undeclared, Messages when it is the only one, Responses
|
|
89
|
+
* for a Responses-only row; null when it declares none of them.
|
|
62
90
|
*/
|
|
63
91
|
export function modelWire(item) {
|
|
64
92
|
if (typeof item?.id !== 'string' || !item.id) return null;
|
|
65
|
-
|
|
66
|
-
if (!Array.isArray(endpoints)) return 'chat';
|
|
67
|
-
const declared = endpoints.map((endpoint) => String(endpoint).replace(/^\/?(?:provider\/)?(?:v1\/)?/, '/'));
|
|
68
|
-
if (declared.includes(CHAT_ENDPOINT)) return 'chat';
|
|
69
|
-
if (declared.includes(MESSAGES_ENDPOINT)) return 'messages';
|
|
70
|
-
return null;
|
|
93
|
+
return commandCodeRoute(item.id, modelEndpoints(item))?.wire || null;
|
|
71
94
|
}
|
|
72
95
|
|
|
73
|
-
// Every request either engine makes goes through this fetch:
|
|
74
|
-
//
|
|
75
|
-
// and redirects are never followed (any 3xx is an error).
|
|
96
|
+
// Every request either engine makes goes through this fetch: only the Command
|
|
97
|
+
// Code API origin, never a redirect.
|
|
76
98
|
function apiOnlyFetch(fetchImpl) {
|
|
77
|
-
return
|
|
78
|
-
const url = new URL(String(input?.url ?? input));
|
|
79
|
-
if (url.origin !== API_ORIGIN) {
|
|
80
|
-
throw new Error(`[command-code-oauth] refusing to send the API key to ${url.host}`);
|
|
81
|
-
}
|
|
82
|
-
const res = await (fetchImpl || globalThis.fetch)(input, { ...init, redirect: 'manual' });
|
|
83
|
-
if (res.status >= 300 && res.status < 400) {
|
|
84
|
-
throw new Error(`[command-code-oauth] refusing to follow a redirect from ${url.host}`);
|
|
85
|
-
}
|
|
86
|
-
return res;
|
|
87
|
-
};
|
|
99
|
+
return originBoundFetch(API_ORIGIN, fetchImpl, PROVIDER_ID);
|
|
88
100
|
}
|
|
89
101
|
|
|
90
102
|
// Anthropic engine bound to this credential: only the Command Code key is
|
|
@@ -98,15 +110,11 @@ class CommandCodeMessagesEngine extends AnthropicProvider {
|
|
|
98
110
|
client.fetch = apiOnlyFetch(this.config.fetchImpl);
|
|
99
111
|
return client;
|
|
100
112
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (err && typeof err === 'object') {
|
|
105
|
-
if (err.usage) err.usage = toInclusiveUsage(err.usage);
|
|
106
|
-
if (err.partialUsage) err.partialUsage = toInclusiveUsage(err.partialUsage);
|
|
113
|
+
// The roster's output ceiling reaches the shared request builder.
|
|
114
|
+
_sendOnce(messages, model, tools, opts) {
|
|
115
|
+
return super._sendOnce(messages, model, tools, gatewayMessagesOpts(this.config, model, messages, opts));
|
|
107
116
|
}
|
|
108
|
-
|
|
109
|
-
};
|
|
117
|
+
}
|
|
110
118
|
|
|
111
119
|
function rosterRow(item) {
|
|
112
120
|
const contextWindow = Number(item.context_window ?? item.max_context_window ?? item.context_length ?? 0);
|
|
@@ -118,6 +126,11 @@ function rosterRow(item) {
|
|
|
118
126
|
...(name ? { name: name.trim() } : {}),
|
|
119
127
|
...(contextWindow > 0 ? { contextWindow } : {}),
|
|
120
128
|
...(outputTokens > 0 ? { outputTokens } : {}),
|
|
129
|
+
// The full declared endpoint set: the cached route metadata a later
|
|
130
|
+
// send falls back on when the live roster cannot be read.
|
|
131
|
+
...(Array.isArray(item.supported_endpoints)
|
|
132
|
+
? { supportedEndpoints: item.supported_endpoints.map((endpoint) => String(endpoint)) }
|
|
133
|
+
: {}),
|
|
121
134
|
};
|
|
122
135
|
}
|
|
123
136
|
|
|
@@ -147,11 +160,16 @@ function scrubErrorSecrets(err, apiKey) {
|
|
|
147
160
|
}
|
|
148
161
|
|
|
149
162
|
// Redact where the transport first surfaces errors (request open and stream
|
|
150
|
-
// iteration)
|
|
163
|
+
// iteration) on the Chat and Responses endpoints, so the shared retry
|
|
164
|
+
// reporter never logs the key.
|
|
151
165
|
function redactClientErrors(client, apiKey) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
166
|
+
redactCreateErrors(client?.chat?.completions, apiKey);
|
|
167
|
+
redactCreateErrors(client?.responses, apiKey);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function redactCreateErrors(endpoint, apiKey) {
|
|
171
|
+
if (!endpoint || !apiKey || endpoint.create?.commandCodeRedacting === apiKey) return;
|
|
172
|
+
const create = endpoint.create.bind(endpoint);
|
|
155
173
|
const wrapped = async (...args) => {
|
|
156
174
|
try {
|
|
157
175
|
const stream = await create(...args);
|
|
@@ -177,7 +195,7 @@ function redactClientErrors(client, apiKey) {
|
|
|
177
195
|
}
|
|
178
196
|
};
|
|
179
197
|
wrapped.commandCodeRedacting = apiKey;
|
|
180
|
-
|
|
198
|
+
endpoint.create = wrapped;
|
|
181
199
|
}
|
|
182
200
|
|
|
183
201
|
// Same for the Anthropic client's streaming request (read through
|
|
@@ -253,8 +271,9 @@ export class CommandCodeOAuthProvider {
|
|
|
253
271
|
_defaultModelKey = null;
|
|
254
272
|
_messages = null;
|
|
255
273
|
_messagesKey = null;
|
|
256
|
-
// Model id →
|
|
257
|
-
|
|
274
|
+
// Model id → declared endpoint wires (null: undeclared) from the roster
|
|
275
|
+
// fetched with `_wiresKey`.
|
|
276
|
+
_endpoints = new Map();
|
|
258
277
|
_wiresKey = null;
|
|
259
278
|
|
|
260
279
|
constructor(config) {
|
|
@@ -315,6 +334,8 @@ export class CommandCodeOAuthProvider {
|
|
|
315
334
|
apiKey,
|
|
316
335
|
baseURL: MESSAGES_BASE_URL,
|
|
317
336
|
disableBetaHeaders: true,
|
|
337
|
+
modelMaxOutputTokens: (model) =>
|
|
338
|
+
commandCodeModelCache.loadSync({ allowStale: true })?.find((row) => row?.id === model)?.outputTokens,
|
|
318
339
|
// x-api-key from the SDK plus the bearer form of the same key.
|
|
319
340
|
extraHeaders: { Authorization: `Bearer ${apiKey}` },
|
|
320
341
|
});
|
|
@@ -324,8 +345,9 @@ export class CommandCodeOAuthProvider {
|
|
|
324
345
|
return engine;
|
|
325
346
|
}
|
|
326
347
|
|
|
327
|
-
// Servable rows from /models
|
|
328
|
-
//
|
|
348
|
+
// Servable rows from /models (any declared Chat, Messages or Responses
|
|
349
|
+
// endpoint, or none declared); only the latest fetch with the still-active
|
|
350
|
+
// key publishes the roster and the per-model endpoint map.
|
|
329
351
|
async _fetchRoster(apiKey, signal = null) {
|
|
330
352
|
const publish = commandCodeModelCache.beginSave(() => loadTokens()?.apiKey === apiKey);
|
|
331
353
|
const body = await requestCommandCodeJson(`${PROVIDER_BASE_URL}/models`, apiKey, {
|
|
@@ -338,16 +360,30 @@ export class CommandCodeOAuthProvider {
|
|
|
338
360
|
const items = list.filter((item) => modelWire(item));
|
|
339
361
|
publish(items.map(rosterRow));
|
|
340
362
|
if (this.tokens?.apiKey === apiKey) {
|
|
341
|
-
|
|
363
|
+
// Rows accumulate for one key: a later roster that misses a model
|
|
364
|
+
// leaves the endpoints it was last listed with.
|
|
365
|
+
const known = this._wiresKey === apiKey ? this._endpoints : new Map();
|
|
366
|
+
for (const item of items) known.set(item.id, modelEndpoints(item));
|
|
367
|
+
this._endpoints = known;
|
|
342
368
|
this._wiresKey = apiKey;
|
|
343
369
|
}
|
|
344
370
|
return items;
|
|
345
371
|
}
|
|
346
372
|
|
|
347
|
-
//
|
|
348
|
-
//
|
|
349
|
-
//
|
|
350
|
-
|
|
373
|
+
// A model's declared endpoints: what this credential's rosters listed,
|
|
374
|
+
// then the persisted roster (a roster miss or a roster that cannot be read
|
|
375
|
+
// right now must not move a known Messages-only model to Chat). null is a
|
|
376
|
+
// row declaring none (Chat); undefined is a model nothing describes.
|
|
377
|
+
_endpointsFor(apiKey, model) {
|
|
378
|
+
if (this._wiresKey === apiKey && this._endpoints.has(model)) return this._endpoints.get(model);
|
|
379
|
+
const cached = commandCodeModelCache.loadSync({ allowStale: true })?.find((row) => row?.id === model);
|
|
380
|
+
return cached ? modelEndpoints({ supported_endpoints: cached.supportedEndpoints }) : undefined;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// This credential's route for a model (the roster is fetched once when
|
|
384
|
+
// missing; a roster that cannot be read falls back on the persisted rows);
|
|
385
|
+
// a rejected key is surfaced.
|
|
386
|
+
async _routeFor(inner, model, ctx = {}) {
|
|
351
387
|
if (this._wiresKey !== inner.apiKey) {
|
|
352
388
|
try {
|
|
353
389
|
await listCompatModels(inner, { throwOnError: true });
|
|
@@ -355,7 +391,16 @@ export class CommandCodeOAuthProvider {
|
|
|
355
391
|
if (isUnauthorized(err)) throw err;
|
|
356
392
|
}
|
|
357
393
|
}
|
|
358
|
-
|
|
394
|
+
const endpoints = this._endpointsFor(inner.apiKey, model);
|
|
395
|
+
return commandCodeRoute(model, endpoints, {
|
|
396
|
+
...ctx,
|
|
397
|
+
override: this.config?.modelWires?.[model] ?? null,
|
|
398
|
+
known: endpoints !== undefined,
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
resolveWireRoute(model, ctx = {}) {
|
|
403
|
+
return this._routeFor(this._ensureInner(), model, ctx);
|
|
359
404
|
}
|
|
360
405
|
|
|
361
406
|
// A rejected key needs a fresh sign-in; the gateway's own detail stays attached.
|
|
@@ -382,17 +427,21 @@ export class CommandCodeOAuthProvider {
|
|
|
382
427
|
throw this._shapeError(err, this.tokens?.apiKey);
|
|
383
428
|
}
|
|
384
429
|
const apiKey = this._innerKey;
|
|
385
|
-
// The model's
|
|
386
|
-
//
|
|
387
|
-
const { compatWireApi: _wire, responsesTransport: _transport, ...
|
|
430
|
+
// The model's route (the session's pinned one, else its declared
|
|
431
|
+
// endpoints) picks the wire; a caller's compat wire flag cannot move it.
|
|
432
|
+
const { compatWireApi: _wire, responsesTransport: _transport, ...callerOpts } = sendOpts || {};
|
|
388
433
|
try {
|
|
389
434
|
const useModel = model || (await this._pickDefaultModel(inner));
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
435
|
+
// One clear "unsupported" refusal moves the send to the next wire once.
|
|
436
|
+
return await sendOnRoute(this, useModel, tools, callerOpts, messages, (wire, history, opts) => {
|
|
437
|
+
if (wire === 'messages') return this._sendMessages(apiKey, history, useModel, tools, opts);
|
|
438
|
+
// _doSend directly: the compat wrapper's 401 handler reloads a static
|
|
439
|
+
// config key, which does not apply to this credential.
|
|
440
|
+
if (wire === 'responses') {
|
|
441
|
+
return inner._doSend(history, useModel, tools, { ...opts, compatWireApi: 'responses' });
|
|
442
|
+
}
|
|
443
|
+
return inner._doSend(history, useModel, tools, opts);
|
|
444
|
+
});
|
|
396
445
|
} catch (err) {
|
|
397
446
|
throw this._shapeError(err, apiKey);
|
|
398
447
|
}
|
|
@@ -405,14 +454,7 @@ export class CommandCodeOAuthProvider {
|
|
|
405
454
|
async _sendMessages(apiKey, messages, model, tools, opts) {
|
|
406
455
|
const engine = this._ensureMessages(apiKey);
|
|
407
456
|
const prepared = await preparePdfTextForProvider(sanitizeToolPairs(messages), engine);
|
|
408
|
-
|
|
409
|
-
if (identity) identity.normalizeAbandonedUsage = toInclusiveUsage;
|
|
410
|
-
try {
|
|
411
|
-
const result = await engine._doSend(prepared, model, tools, opts);
|
|
412
|
-
return result?.usage ? { ...result, usage: toInclusiveUsage(result.usage) } : result;
|
|
413
|
-
} catch (err) {
|
|
414
|
-
throw normalizeUsageError(err);
|
|
415
|
-
}
|
|
457
|
+
return withInclusiveUsage(() => engine._doSend(prepared, model, tools, opts));
|
|
416
458
|
}
|
|
417
459
|
|
|
418
460
|
async listModels() {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Shared request controls for Chat Completions and Responses gateways.
|
|
2
2
|
import { emitProviderRetryStage, retryDelayLabel } from './retry-classifier.mjs';
|
|
3
|
+
import { isTogetherBaseURL } from './openai-compat-reasoning-field.mjs';
|
|
3
4
|
|
|
4
5
|
// withRetry onRetry for the compat stream sends: one stderr line plus a
|
|
5
6
|
// display-only 'reconnecting' stage for the UI.
|
|
@@ -13,8 +14,83 @@ export function compatStreamRetryReporter(label, opts) {
|
|
|
13
14
|
};
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
// Providers whose docs accept `required` / named tool_choice, and the subset
|
|
18
|
+
// that also documents `parallel_tool_calls`. DeepSeek documents no
|
|
19
|
+
// parallel_tool_calls, and rejects forced choices in thinking mode.
|
|
20
|
+
const FORCED_CHOICE_PROVIDERS = new Set([
|
|
21
|
+
'xai',
|
|
22
|
+
'deepseek',
|
|
23
|
+
'openrouter',
|
|
24
|
+
'mistral',
|
|
25
|
+
'groq',
|
|
26
|
+
'fireworks',
|
|
27
|
+
'together',
|
|
28
|
+
'command-code-oauth',
|
|
29
|
+
]);
|
|
30
|
+
const PARALLEL_CALLS_PROVIDERS = new Set([
|
|
31
|
+
'xai',
|
|
32
|
+
'openrouter',
|
|
33
|
+
'mistral',
|
|
34
|
+
'groq',
|
|
35
|
+
'fireworks',
|
|
36
|
+
'together',
|
|
37
|
+
'command-code-oauth',
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
function hostMatches(baseURL, domain) {
|
|
41
|
+
try {
|
|
42
|
+
const host = new URL(String(baseURL || '')).hostname.toLowerCase();
|
|
43
|
+
return host === domain || host.endsWith(`.${domain}`);
|
|
44
|
+
} catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function compatToolFamily(provider, baseURL) {
|
|
50
|
+
if (FORCED_CHOICE_PROVIDERS.has(provider)) return provider;
|
|
51
|
+
if (isTogetherBaseURL(baseURL)) return 'together';
|
|
52
|
+
if (hostMatches(baseURL, 'fireworks.ai')) return 'fireworks';
|
|
53
|
+
if (hostMatches(baseURL, 'mistral.ai')) return 'mistral';
|
|
54
|
+
if (hostMatches(baseURL, 'groq.com')) return 'groq';
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function forcedToolChoice(choice, wire) {
|
|
59
|
+
if (choice === 'required') return 'required';
|
|
60
|
+
if (!choice || typeof choice !== 'object') return null;
|
|
61
|
+
const name = choice.function?.name || choice.name;
|
|
62
|
+
if (typeof name !== 'string' || !name) return null;
|
|
63
|
+
return wire === 'responses' ? { type: 'function', name } : { type: 'function', function: { name } };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Tool-choice controls. `none` is universal. With `ctx` ({ provider, baseURL,
|
|
68
|
+
* wire: 'chat'|'responses', thinking: 'enabled'|'disabled'|null }) the
|
|
69
|
+
* documented providers also get explicit `required` / named tool_choice and an
|
|
70
|
+
* explicit boolean `opts.parallelToolCalls`; without it only `none` applies.
|
|
71
|
+
* DeepSeek rejects forced choices while thinking is explicitly enabled and
|
|
72
|
+
* keeps omitting them when thinking is left to the server default.
|
|
73
|
+
*/
|
|
74
|
+
export function applyCompatToolChoice(body, opts = {}, ctx = null) {
|
|
75
|
+
if (!(body.tools?.length > 0)) return body;
|
|
76
|
+
if (opts.toolChoice === 'none') body.tool_choice = 'none';
|
|
77
|
+
const family = ctx?.provider ? compatToolFamily(ctx.provider, ctx.baseURL) : null;
|
|
78
|
+
if (!family) return body;
|
|
79
|
+
const forced = forcedToolChoice(opts.toolChoice, ctx.wire);
|
|
80
|
+
if (forced) {
|
|
81
|
+
if (family === 'deepseek' && ctx.thinking === 'enabled') {
|
|
82
|
+
throw Object.assign(
|
|
83
|
+
new Error(
|
|
84
|
+
'[deepseek] tool_choice "required" or a named tool is not supported in thinking mode; disable thinking (effort none) to force a tool call'
|
|
85
|
+
),
|
|
86
|
+
{ code: 'unsupported_tool_choice' }
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
if (family !== 'deepseek' || ctx.thinking === 'disabled') body.tool_choice = forced;
|
|
90
|
+
}
|
|
91
|
+
if (typeof opts.parallelToolCalls === 'boolean' && PARALLEL_CALLS_PROVIDERS.has(family)) {
|
|
92
|
+
body.parallel_tool_calls = opts.parallelToolCalls;
|
|
93
|
+
}
|
|
18
94
|
return body;
|
|
19
95
|
}
|
|
20
96
|
|
|
@@ -130,7 +130,7 @@ function saveCredentials(tokens) {
|
|
|
130
130
|
|
|
131
131
|
export function hasCursorOAuthCredentials() {
|
|
132
132
|
const tokens = loadStoredCredentials();
|
|
133
|
-
if (!tokens?.access_token) return false;
|
|
133
|
+
if (!tokens?.access_token || tokens.reauth_required === true) return false;
|
|
134
134
|
const expiresAt = Number(tokens.expires_at) || 0;
|
|
135
135
|
return expiresAt === 0 || expiresAt > Date.now() || Boolean(tokens.refresh_token);
|
|
136
136
|
}
|
|
@@ -147,6 +147,18 @@ export function describeCursorOAuthCredentials() {
|
|
|
147
147
|
detail: 'Mixdog token store or CURSOR_ACCESS_TOKEN',
|
|
148
148
|
};
|
|
149
149
|
}
|
|
150
|
+
if (tokens.reauth_required === true) {
|
|
151
|
+
return {
|
|
152
|
+
authenticated: false,
|
|
153
|
+
usable: false,
|
|
154
|
+
refreshable: false,
|
|
155
|
+
reauthRequired: true,
|
|
156
|
+
status: 'Reauth Required',
|
|
157
|
+
detail: tokens.source || 'Cursor OAuth',
|
|
158
|
+
expiresAt: Number(tokens.expires_at) || null,
|
|
159
|
+
...accountIdentityFields(tokens.identity),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
150
162
|
const expiresAt = Number(tokens.expires_at) || 0;
|
|
151
163
|
const expired = expiresAt > 0 && expiresAt <= Date.now();
|
|
152
164
|
const expiring = expiresAt > 0 && expiresAt <= Date.now() + REFRESH_SKEW_MS;
|
|
@@ -336,10 +348,30 @@ export async function resolveCursorOAuthAccessToken({ forceRefresh = false, fetc
|
|
|
336
348
|
// (turn cancel / session close) kill it would fail the refresh for
|
|
337
349
|
// all of them and leave the process without a usable token. Its own
|
|
338
350
|
// timeout bounds the request instead.
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
351
|
+
let next;
|
|
352
|
+
try {
|
|
353
|
+
next = await exchangeCursorToken(latest.refresh_token, {
|
|
354
|
+
fetchFn,
|
|
355
|
+
signal: AbortSignal.timeout(REFRESH_TIMEOUT_MS),
|
|
356
|
+
});
|
|
357
|
+
} catch (error) {
|
|
358
|
+
if (error?.reauthRequired !== true) throw error;
|
|
359
|
+
// Mark the account dead only if no other process replaced the
|
|
360
|
+
// refresh token meanwhile. Non-destructive: tokens stay intact and
|
|
361
|
+
// a new sign-in rewrites the file without this marker.
|
|
362
|
+
if (!process.env.CURSOR_ACCESS_TOKEN || boundProviderAuthPath('cursor-oauth')) {
|
|
363
|
+
const current = loadStoredCredentials();
|
|
364
|
+
if (current?.refresh_token && current.refresh_token === latest.refresh_token) {
|
|
365
|
+
const { source: _source, ...persisted } = current;
|
|
366
|
+
try {
|
|
367
|
+
saveCredentials({ ...persisted, reauth_required: true });
|
|
368
|
+
} catch (saveError) {
|
|
369
|
+
process.stderr.write(`[cursor-oauth] dead-account mark failed: ${String(saveError?.message || saveError).slice(0, 200)}\n`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
throw error;
|
|
374
|
+
}
|
|
343
375
|
if (!process.env.CURSOR_ACCESS_TOKEN || boundProviderAuthPath('cursor-oauth')) {
|
|
344
376
|
saveCredentials(next);
|
|
345
377
|
}
|
|
@@ -4,7 +4,7 @@ import { createRemoteVersionSource } from './npm-cli-version.mjs';
|
|
|
4
4
|
// documented version endpoint; the official installer script embeds the
|
|
5
5
|
// current build (…/lab/<build>/…), parsed best-effort. Any format change or
|
|
6
6
|
// failure falls back to the floor.
|
|
7
|
-
export const CURSOR_CLIENT_VERSION_FLOOR = 'cli-2026.10.14-
|
|
7
|
+
export const CURSOR_CLIENT_VERSION_FLOOR = 'cli-2026.10.14-941492e';
|
|
8
8
|
const BUILD_PATTERN = /downloads\.cursor\.com\/lab\/(\d{4}\.\d{2}\.\d{2}-[0-9a-f]{6,40})\//;
|
|
9
9
|
export const CURSOR_INSTALL_URL = 'https://cursor.com/install';
|
|
10
10
|
|
|
@@ -207,6 +207,7 @@ export function createBridgeController(ctx) {
|
|
|
207
207
|
conversation: run.conversation,
|
|
208
208
|
tools: run.tools,
|
|
209
209
|
cloudRule: run.cloudRule,
|
|
210
|
+
sessionId: run.sessionId,
|
|
210
211
|
};
|
|
211
212
|
const frameParser = createFrameParser(
|
|
212
213
|
// Server requests answer on whichever bridge is live when they arrive.
|
|
@@ -3,12 +3,46 @@
|
|
|
3
3
|
* to the shared stream state and relayed to the SSE sink. Returns the
|
|
4
4
|
* message's forward-progress kind for the watchdog.
|
|
5
5
|
*/
|
|
6
|
+
import { appendAgentTrace } from '../agent-trace.mjs';
|
|
6
7
|
import { decodeMessage } from './cursor-wire-protobuf.mjs';
|
|
7
8
|
import { MAX_CHECKPOINT_BYTES, cursorInteractionProgress } from './cursor-wire-guards.mjs';
|
|
8
9
|
import { buildCursorInteractionResponse } from './cursor-wire-interactions.mjs';
|
|
9
10
|
import { cursorError } from './cursor-wire-transport.mjs';
|
|
10
11
|
import { handleExecMessage, handleKvMessage, sendClientMessage } from './cursor-wire-exec.mjs';
|
|
11
12
|
|
|
13
|
+
// Unknown fields seen on every live frame: AgentServerMessage field 8 (timing
|
|
14
|
+
// doubles) and InteractionUpdate field 25 (epoch-ms timestamp). Never traced.
|
|
15
|
+
const NOISE_SERVER_FIELDS = new Set([8]);
|
|
16
|
+
const NOISE_UPDATE_FIELDS = new Set([25]);
|
|
17
|
+
const TRACE_MAX_FIELDS = 8;
|
|
18
|
+
const TRACE_PREVIEW_BYTES = 48;
|
|
19
|
+
|
|
20
|
+
// Records undecoded fields (number, wire type, bounded hex of the raw field)
|
|
21
|
+
// so a new server event such as a mid-turn model fallback can be inspected.
|
|
22
|
+
function traceUnknownFields(trace, sessionId, scope, unknown, noise) {
|
|
23
|
+
const fields = unknown?.filter((field) => !noise.has(field.no));
|
|
24
|
+
if (!fields?.length) return;
|
|
25
|
+
try {
|
|
26
|
+
trace({
|
|
27
|
+
sessionId,
|
|
28
|
+
kind: 'cursor_unknown_field',
|
|
29
|
+
provider: 'cursor',
|
|
30
|
+
payload: {
|
|
31
|
+
scope,
|
|
32
|
+
count: fields.length,
|
|
33
|
+
fields: fields.slice(0, TRACE_MAX_FIELDS).map((field) => ({
|
|
34
|
+
no: field.no,
|
|
35
|
+
wire_type: field.wireType,
|
|
36
|
+
bytes: field.data.byteLength,
|
|
37
|
+
preview_hex: Buffer.from(field.data.subarray(0, TRACE_PREVIEW_BYTES)).toString('hex'),
|
|
38
|
+
})),
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
} catch {
|
|
42
|
+
/* best-effort */
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
12
46
|
// Relays one interaction update to the SSE stream and returns its progress.
|
|
13
47
|
function applyInteractionUpdate(update, state, filter, emit) {
|
|
14
48
|
if (update.textDelta?.text) {
|
|
@@ -62,11 +96,18 @@ function announcePendingToolCall(state, pending, emit) {
|
|
|
62
96
|
|
|
63
97
|
/**
|
|
64
98
|
* @param {Uint8Array} bytes one Connect frame payload
|
|
65
|
-
* @param {object} ctx { state, filter, emit, conversation, tools, cloudRule, bridge }
|
|
99
|
+
* @param {object} ctx { state, filter, emit, conversation, tools, cloudRule, bridge, sessionId?, trace? }
|
|
66
100
|
* @returns {'work'|'park'|'none'|string} progress kind for the watchdog
|
|
67
101
|
*/
|
|
68
|
-
export function processServerMessage(
|
|
102
|
+
export function processServerMessage(
|
|
103
|
+
bytes,
|
|
104
|
+
{ state, filter, emit, conversation, tools, cloudRule, bridge, sessionId = '', trace = appendAgentTrace }
|
|
105
|
+
) {
|
|
69
106
|
const message = decodeMessage('AgentServerMessage', bytes);
|
|
107
|
+
traceUnknownFields(trace, sessionId, 'agent_server_message', message.$unknown, NOISE_SERVER_FIELDS);
|
|
108
|
+
if (message.interactionUpdate) {
|
|
109
|
+
traceUnknownFields(trace, sessionId, 'interaction_update', message.interactionUpdate.$unknown, NOISE_UPDATE_FIELDS);
|
|
110
|
+
}
|
|
70
111
|
if (message.interactionUpdate) return applyInteractionUpdate(message.interactionUpdate, state, filter, emit);
|
|
71
112
|
if (message.kvServerMessage) {
|
|
72
113
|
handleKvMessage(bridge, message.kvServerMessage, conversation);
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
import { handleExecMessage, heartbeatFrame, sendToolResult } from './cursor-wire-exec.mjs';
|
|
43
43
|
import { completionChunk, createStreamSink } from './cursor-wire-stream-sink.mjs';
|
|
44
44
|
import { createBridgeController } from './cursor-wire-stream-bridge.mjs';
|
|
45
|
+
import { TRANSPORT_SCOPE_DISPOSED } from './transport-scope.mjs';
|
|
45
46
|
|
|
46
47
|
export { clearModelCache, getCursorModels, getCursorUsage } from './cursor-wire-models.mjs';
|
|
47
48
|
|
|
@@ -117,6 +118,8 @@ globalThis.__mixdogCloseProviderConnectionsForSession = (sessionId, reason) => {
|
|
|
117
118
|
_priorCursorSessionCloseHook?.(sessionId, reason);
|
|
118
119
|
} finally {
|
|
119
120
|
closeCursorRunsForSession(sessionId, reason);
|
|
121
|
+
// A disposed transport scope never sends again: drop its conversation.
|
|
122
|
+
if (reason === TRANSPORT_SCOPE_DISPOSED && sessionId) conversations.delete(conversationKey([], sessionId));
|
|
120
123
|
}
|
|
121
124
|
};
|
|
122
125
|
const _priorCursorDrainHook = globalThis.__mixdogDrainProviderConnections;
|
|
@@ -12,6 +12,7 @@ import { preparePdfTextForProvider } from './media-normalization.mjs';
|
|
|
12
12
|
import { consumeCompatChatCompletionStream } from './openai-compat-stream.mjs';
|
|
13
13
|
import { retryAfterMsFromError } from './retry-classifier.mjs';
|
|
14
14
|
import { ensureChatToolPairs } from './lib/wire-pairing.mjs';
|
|
15
|
+
import { acceptedWireTools } from './lib/claude-bridge-schema.mjs';
|
|
15
16
|
import { cursorTokenExpiry, exchangeCursorToken, resolveCursorOAuthAccessToken } from './cursor-auth.mjs';
|
|
16
17
|
import {
|
|
17
18
|
canonicalCursorModelId,
|
|
@@ -693,10 +694,16 @@ class CursorProviderBase {
|
|
|
693
694
|
const runtime = await this._runtime();
|
|
694
695
|
let accessToken = await this._accessToken({ signal });
|
|
695
696
|
let cursorSelection = await this._resolveCursorModel(model, sendOpts, runtime, accessToken);
|
|
697
|
+
// The Cursor run and conversation (checkpoint, pending tool batch) live
|
|
698
|
+
// under this scope; a forked request keeps its own (transport-scope.mjs).
|
|
696
699
|
const sessionScope = String(
|
|
697
|
-
sendOpts.
|
|
700
|
+
sendOpts.transportScope ||
|
|
701
|
+
sendOpts.sessionId ||
|
|
702
|
+
sendOpts.providerCacheKey || sendOpts.promptCacheKey || `cursor-call:${randomUUID()}`
|
|
698
703
|
);
|
|
699
|
-
const openAiTools = tools?.length
|
|
704
|
+
const openAiTools = tools?.length
|
|
705
|
+
? toOpenAITools(acceptedWireTools(tools, 'openai', sendOpts.onToolExcluded, '[cursor] tool'))
|
|
706
|
+
: undefined;
|
|
700
707
|
const dispatch = async () => {
|
|
701
708
|
noteRequestServiceTier(cursorSelectionIsFast(cursorSelection) ? 'fast' : '');
|
|
702
709
|
// Every attempt (retries included) prepares right before it lowers.
|