mixdog 1.1.2 → 1.2.1
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 +8 -5
- package/package.json +2 -1
- package/scripts/lib/run-node-tests.mjs +9 -0
- package/scripts/prune-desktop-runtime.mjs +3 -0
- package/scripts/test-direct.mjs +4 -2
- package/src/defaults/shipped-history.json +10 -0
- package/src/defaults/skills/pptx/SKILL.md +6 -6
- package/src/defaults/skills/pptx/references/review.md +6 -4
- package/src/defaults/skills/pptx/scripts/source-extract.mjs +1 -1
- package/src/defaults/skills/setup/references/actions.md +18 -5
- package/src/defaults/skills/visualize/SKILL.md +160 -0
- package/src/defaults/skills/visualize/references/craft.md +88 -0
- package/src/headless-command.mjs +56 -3
- package/src/headless-exec.mjs +17 -1
- package/src/help.mjs +2 -0
- package/src/rules/shared/60-verification.md +3 -1
- package/src/rules/shared/70-delivery.md +4 -2
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +2 -0
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
- package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +17 -11
- package/src/runtime/agent/orchestrator/config-storage.mjs +1 -0
- package/src/runtime/agent/orchestrator/config.mjs +19 -5
- package/src/runtime/agent/orchestrator/context/collect.mjs +2 -1
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +11 -5
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +74 -21
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +133 -15
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +55 -8
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +86 -8
- package/src/runtime/agent/orchestrator/mcp/client.mjs +474 -164
- package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
- package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
- package/src/runtime/agent/orchestrator/mcp/reconnect-singleflight.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +108 -17
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +15 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +32 -12
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +337 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs +159 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +444 -0
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +21 -6
- package/src/runtime/agent/orchestrator/providers/effort-rejection.mjs +244 -0
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +41 -28
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +8 -40
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +51 -12
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +37 -2
- package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +82 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +556 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +251 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +69 -102
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +15 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +15 -4
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog-store.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +4 -4
- package/src/runtime/agent/orchestrator/providers/registry.mjs +47 -7
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +10 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +36 -3
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -11
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +15 -55
- package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +15 -2
- package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +16 -1
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +278 -84
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +54 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +10 -3
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +268 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/sqlite-gate.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +628 -0
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +10 -3
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +24 -13
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +362 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +253 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +184 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +136 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +128 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +101 -0
- package/src/runtime/agent/orchestrator/session/explicit-skills.mjs +83 -5
- package/src/runtime/agent/orchestrator/session/imported-message.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/continuation.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/diagnostic.mjs +1 -7
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/refusal.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +7 -4
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +21 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +9 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +37 -16
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +17 -4
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +90 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +32 -3
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/message-ids.mjs +123 -0
- package/src/runtime/agent/orchestrator/session/message-ids.test-support.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +33 -22
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +10 -3
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +817 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +23 -12
- package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +158 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +202 -374
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +20 -3
- package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +48 -9
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +161 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -0
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +52 -2
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +32 -22
- package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +10 -3
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-cache-policy.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +203 -33
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +32 -35
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +11 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +9 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +83 -68
- package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +8 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +20 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +16 -7
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +137 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +11 -10
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +21 -11
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +13 -10
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +17 -12
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +56 -13
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +58 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/trusted-roots.mjs +25 -1
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +4 -4
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/route.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/read-redirects.mjs +34 -30
- package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +7 -7
- package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +78 -5
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
- package/src/runtime/attachments/store.d.mts +3 -0
- package/src/runtime/attachments/store.mjs +38 -0
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +1 -1
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +16 -4
- package/src/runtime/channels/lib/worker-main.mjs +17 -14
- package/src/runtime/computer-bridge/linux-readiness.mjs +0 -2
- package/src/runtime/effort-judge/judge-client.mjs +56 -18
- package/src/runtime/memory/lib/memory.mjs +1 -1
- package/src/runtime/memory/lib/session-ingest.mjs +2 -2
- package/src/runtime/shared/atomic-file.mjs +33 -6
- package/src/runtime/shared/best-effort-stderr.mjs +8 -0
- package/src/runtime/shared/code-graph-state.mjs +12 -0
- package/src/runtime/shared/defaults-separation.mjs +2 -0
- package/src/runtime/shared/extension-scopes.mjs +5 -3
- package/src/runtime/shared/file-lock.mjs +37 -11
- package/src/runtime/shared/git-runner-worker.mjs +3 -2
- package/src/runtime/shared/git-runner.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +14 -0
- package/src/runtime/shared/llm/default-context-window.mjs +6 -0
- package/src/runtime/shared/llm/model-catalog-projection.mjs +5 -4
- package/src/runtime/shared/llm/model-catalog.mjs +240 -130
- package/src/runtime/shared/llm/provider-catalog-cache.mjs +36 -28
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +162 -0
- package/src/runtime/shared/llm/provider-seed-rosters.mjs +130 -0
- package/src/runtime/shared/model-proxy-mode.d.mts +3 -0
- package/src/runtime/shared/model-proxy-mode.mjs +19 -0
- package/src/runtime/shared/plugin-manifest.mjs +18 -9
- package/src/runtime/shared/pristine-execution-contract.json +9 -2
- package/src/runtime/shared/pristine-execution.mjs +28 -4
- package/src/runtime/shared/provider-accounts.mjs +125 -21
- package/src/runtime/shared/provider-api-key.mjs +33 -1
- package/src/runtime/shared/schedule-model-ref.mjs +11 -2
- package/src/runtime/shared/session-usage-totals.mjs +19 -0
- package/src/runtime/shared/sharp-electron-linux.mjs +25 -0
- package/src/runtime/shared/shell-display.mjs +9 -3
- package/src/runtime/shared/singleton-owner.mjs +36 -6
- package/src/runtime/shared/skill-mentions.d.mts +10 -0
- package/src/runtime/shared/skill-mentions.mjs +133 -0
- package/src/runtime/shared/skill-script-runtime.mjs +264 -0
- package/src/runtime/shared/statusline/statusline-segments.mjs +68 -14
- package/src/runtime/shared/tool-primitives.mjs +35 -2
- package/src/runtime/shared/tool-surface.mjs +7 -0
- package/src/runtime/shared/tool-work-units.mjs +14 -0
- package/src/runtime/shared/transcript-metadata.mjs +17 -1
- package/src/runtime/shared/turn-changes.mjs +791 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +346 -12
- package/src/runtime/shared/turn-snapshot.mjs +690 -81
- package/src/runtime/shared/turn-worktree-snapshot.mjs +185 -15
- package/src/runtime/shared/worker-requests.mjs +15 -2
- package/src/runtime/shared/worktrees/cache-cleanups.mjs +52 -0
- package/src/runtime/shared/worktrees/contract.mjs +551 -0
- package/src/runtime/shared/worktrees/disk.mjs +57 -0
- package/src/runtime/shared/worktrees/git.mjs +247 -0
- package/src/runtime/shared/worktrees/include.mjs +480 -0
- package/src/runtime/shared/worktrees/lock.mjs +46 -0
- package/src/runtime/shared/worktrees/maintenance.mjs +96 -0
- package/src/runtime/shared/worktrees/manager.mjs +1215 -0
- package/src/runtime/shared/worktrees/merge.mjs +182 -0
- package/src/runtime/shared/worktrees/owner.mjs +46 -0
- package/src/runtime/shared/worktrees/paths.mjs +62 -0
- package/src/runtime/shared/worktrees/registry.mjs +110 -0
- package/src/runtime/shared/worktrees/settings.mjs +84 -0
- package/src/runtime/shared/worktrees/slug.mjs +62 -0
- package/src/runtime/shared/worktrees/test-support.mjs +96 -0
- package/src/runtime/visualize-bridge/client.mjs +181 -0
- package/src/runtime/visualize-bridge/tool-defs.mjs +97 -0
- package/src/session-runtime/automation-agents.mjs +8 -2
- package/src/session-runtime/boot/apis.mjs +90 -0
- package/src/session-runtime/boot/config.mjs +7 -2
- package/src/session-runtime/boot/facade.mjs +21 -0
- package/src/session-runtime/boot/infrastructure.mjs +30 -18
- package/src/session-runtime/boot/session.mjs +1 -0
- package/src/session-runtime/boot/tools.mjs +4 -0
- package/src/session-runtime/config-lifecycle.mjs +10 -1
- package/src/session-runtime/conversation-import/discovery.mjs +698 -0
- package/src/session-runtime/conversation-import/service.mjs +369 -0
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +21 -6
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
- package/src/session-runtime/global-extensions.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +27 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +32 -1
- package/src/session-runtime/internal-tool-executor.mjs +9 -1
- package/src/session-runtime/lifecycle/session-catalog.mjs +8 -1
- package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +5 -0
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +21 -3
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +16 -0
- package/src/session-runtime/mcp-glue/connect.mjs +68 -16
- package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +122 -33
- package/src/session-runtime/mcp-glue/server-input.mjs +29 -0
- package/src/session-runtime/mcp-glue.mjs +22 -2
- package/src/session-runtime/model-route/route-persist.mjs +3 -0
- package/src/session-runtime/model-route/set-route.mjs +15 -2
- package/src/session-runtime/new-session-config.mjs +3 -2
- package/src/session-runtime/notification-bus.mjs +18 -3
- package/src/session-runtime/provider-auth/accounts.mjs +33 -15
- package/src/session-runtime/provider-models/row-hydration.mjs +2 -0
- package/src/session-runtime/provider-models/web-search-catalog.mjs +5 -1
- package/src/session-runtime/provider-readiness.mjs +16 -10
- package/src/session-runtime/resource-extension-sync.mjs +45 -7
- package/src/session-runtime/resource-mcp-api.mjs +121 -84
- package/src/session-runtime/resource-plugins-api.mjs +29 -41
- package/src/session-runtime/resource-scope-decorate.mjs +6 -8
- package/src/session-runtime/resource-skills-api.mjs +23 -2
- package/src/session-runtime/route-resolution.mjs +10 -1
- package/src/session-runtime/route-state.mjs +16 -2
- package/src/session-runtime/runtime-core.mjs +5 -0
- package/src/session-runtime/runtime-facade.mjs +8 -0
- package/src/session-runtime/runtime-review-api.mjs +9 -0
- package/src/session-runtime/schedule-session-run.mjs +1 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +5 -0
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +3 -0
- package/src/session-runtime/services/agent-tool/job-views/job-lookup.mjs +1 -0
- package/src/session-runtime/services/agent-tool/job-views/spawn-meta.mjs +1 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +15 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +1 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +10 -2
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -7
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +2 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -0
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +1 -0
- package/src/session-runtime/services/agent-tool.mjs +1 -0
- package/src/session-runtime/services/channel-session-router.mjs +4 -1
- package/src/session-runtime/services/daemon-candidate.mjs +3 -2
- package/src/session-runtime/services/daemon-crash-capture/spawn-capture.mjs +55 -0
- package/src/session-runtime/services/hook-bus/command-handler.mjs +4 -1
- package/src/session-runtime/services/hook-bus/handlers.mjs +7 -3
- package/src/session-runtime/services/provider-admin.mjs +64 -18
- package/src/session-runtime/services/usage-dashboard-model.mjs +3 -0
- package/src/session-runtime/session-create/session-options.mjs +10 -1
- package/src/session-runtime/session-turn-api.mjs +1 -0
- package/src/session-runtime/settings-api.mjs +4 -2
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -2
- package/src/session-runtime/settings-worktree-api.mjs +17 -0
- package/src/session-runtime/setup-tool/executor.mjs +23 -5
- package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +4 -1
- package/src/session-runtime/setup-tool/tool-defs.mjs +38 -4
- package/src/session-runtime/skills-api.mjs +7 -3
- package/src/session-runtime/turn/agent-ops.mjs +12 -1
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +14 -3
- package/src/session-runtime/turn/turn-run/snapshot-tracker.mjs +20 -15
- package/src/session-runtime/turn/turn-run/turn-open.mjs +4 -5
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +29 -1
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +6 -1
- package/src/session-runtime/turn/turn-run.mjs +6 -7
- package/src/session-runtime/webhook-session-run.mjs +16 -4
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -3
- package/src/session-runtime/workspace/admission-gate.mjs +197 -0
- package/src/session-runtime/workspace/project-branches.mjs +136 -0
- package/src/session-runtime/workspace/transition-steps.mjs +364 -0
- package/src/session-runtime/workspace/transitions.mjs +651 -0
- package/src/session-runtime/workspace/workspace-state.mjs +112 -0
- package/src/skill-script-entry.mjs +36 -0
- package/src/standalone/channel-transport/http-routes.mjs +17 -0
- package/src/standalone/channel-transport.mjs +13 -1
- package/src/standalone/daemon-desktop-runtime.mjs +1 -0
- package/src/standalone/daemon-owner.mjs +372 -0
- package/src/standalone/daemon-stored-session-views.mjs +15 -4
- package/src/standalone/daemon.mjs +179 -8
- package/src/standalone/desktop-service-registry.mjs +20 -0
- package/src/standalone/local-session-runtime.mjs +11 -0
- package/src/standalone/session-client/attachment-calls.mjs +3 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +62 -0
- package/src/standalone/session-client/lease-heartbeat.mjs +47 -0
- package/src/standalone/session-client.mjs +104 -13
- package/src/standalone/session-protocol.mjs +21 -0
- package/src/standalone/session-proxy.mjs +3 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +4 -0
- package/src/standalone/session-service/agent-tree/agent-rehydrate.mjs +1 -0
- package/src/standalone/session-service/entries/lifecycle.mjs +6 -0
- package/src/standalone/session-service/projection/revisions.mjs +2 -0
- package/src/standalone/session-service/projection/transcript-window.mjs +149 -19
- package/src/standalone/session-service/projection/workspace.mjs +14 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +17 -4
- package/src/standalone/session-transport/call-route.mjs +13 -0
- package/src/standalone/session-transport/client-registry/client-grace.mjs +45 -3
- package/src/standalone/session-transport/client-registry/registration-replays.mjs +1 -0
- package/src/standalone/session-transport/client-registry.mjs +20 -3
- package/src/standalone/session-transport/routes.mjs +79 -2
- package/src/standalone/session-transport/stack.mjs +2 -0
- package/src/standalone/session-transport.mjs +24 -1
- package/src/tui/App.jsx +9 -1
- package/src/tui/app/app-view/floating-panel.jsx +9 -1
- package/src/tui/app/app-view.jsx +6 -0
- package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
- package/src/tui/app/message-selector.mjs +2 -1
- package/src/tui/app/model-options.mjs +37 -5
- package/src/tui/app/model-picker/provider-models-list.mjs +2 -2
- package/src/tui/app/model-picker.mjs +4 -2
- package/src/tui/app/skill-mention-palette.mjs +88 -0
- package/src/tui/app/slash-palette.mjs +23 -7
- package/src/tui/app/transcript-row-estimate.mjs +11 -3
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -2
- package/src/tui/app/use-prompt-state.mjs +5 -0
- package/src/tui/components/Message.jsx +22 -1
- package/src/tui/components/PromptInput.jsx +21 -3
- package/src/tui/components/SlashCommandPalette.jsx +12 -3
- package/src/tui/components/TranscriptItem.jsx +9 -1
- package/src/tui/components/prompt-input/key-handler.mjs +21 -8
- package/src/tui/components/user-message-skills.mjs +38 -0
- package/src/tui/dist/index.mjs +839 -207
- package/src/tui/index.jsx +10 -2
- package/src/tui/session/compaction-view.mjs +147 -0
- package/src/tui/session/context-state.mjs +6 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/queue-helpers.mjs +7 -2
- package/src/tui/session/quota-resume.mjs +2 -1
- package/src/tui/session/session-api/commands.mjs +10 -2
- package/src/tui/session/session-api/controls.mjs +4 -0
- package/src/tui/session/session-api/extensions.mjs +4 -2
- package/src/tui/session/session-api/intake/rewind.mjs +2 -1
- package/src/tui/session/session-api/integrations.mjs +17 -0
- package/src/tui/session/session-api/lifecycle/dispose.mjs +6 -1
- package/src/tui/session/session-api/lifecycle/inheritance.mjs +2 -0
- package/src/tui/session/session-api/lifecycle/resume.mjs +3 -0
- package/src/tui/session/session-api/routes.mjs +10 -1
- package/src/tui/session/session-api/settings.mjs +9 -0
- package/src/tui/session/session-api/worktree.mjs +60 -0
- package/src/tui/session/session-api.mjs +2 -0
- package/src/tui/session/session-flow/auto-clear.mjs +31 -12
- package/src/tui/session/session-flow/drain.mjs +27 -3
- package/src/tui/session/session-flow/session-reset.mjs +4 -3
- package/src/tui/session/session-flow.mjs +2 -0
- package/src/tui/session/transcript-intake.mjs +14 -5
- package/src/tui/session/tui-steering-persist.mjs +25 -9
- package/src/tui/session/turn-stream.mjs +32 -4
- package/src/tui/session/turn-tool-cards.mjs +10 -2
- package/src/tui/session/turn.mjs +56 -10
- package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
- package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
// Daemon-side stand-in for a provider in remote mode (MIXDOG_MODEL_PROXY=client).
|
|
2
|
+
// It holds no credentials and opens no model connection: every call is handed
|
|
3
|
+
// to the desktop client through the model proxy channel and executed by the
|
|
4
|
+
// PC's own provider of the same name. The registry still wraps it with
|
|
5
|
+
// admission scheduling and usage accounting, which then see the PC's result.
|
|
6
|
+
import {
|
|
7
|
+
getModelProxyChannel,
|
|
8
|
+
ModelProxyUnavailableError,
|
|
9
|
+
splitModelProxySendOptions,
|
|
10
|
+
stripModelProxySecrets,
|
|
11
|
+
} from './model-proxy-channel.mjs';
|
|
12
|
+
import {
|
|
13
|
+
isFinalizedProviderRequestTools,
|
|
14
|
+
providerNativeToolPrefixCount,
|
|
15
|
+
} from '../runtime-core/provider-request-tools.mjs';
|
|
16
|
+
import {
|
|
17
|
+
attachmentTextForPart,
|
|
18
|
+
isAttachmentReference,
|
|
19
|
+
isPermanentAttachmentError,
|
|
20
|
+
readAttachmentBuffer,
|
|
21
|
+
} from '../../../attachments/store.mjs';
|
|
22
|
+
import { MAX_ATTACHMENT_BLOB_BYTES } from '../../../attachments/limits.mjs';
|
|
23
|
+
|
|
24
|
+
/** Stored-attachment bytes one proxied call may carry inline: the store's own
|
|
25
|
+
* single-blob ceiling. Newer messages are inlined first; a reference past the
|
|
26
|
+
* budget stays a reference, which the PC lowers to its "unavailable" text. */
|
|
27
|
+
export const MODEL_PROXY_INLINE_MAX_BYTES = MAX_ATTACHMENT_BLOB_BYTES;
|
|
28
|
+
|
|
29
|
+
// A stored reference names a blob in THIS daemon's attachment store, which the
|
|
30
|
+
// PC running the call cannot read. Each one travels as the inline part it was
|
|
31
|
+
// stored from (image/file → base64 `data`, text → its text), so the PC lowers
|
|
32
|
+
// exactly what a local daemon would.
|
|
33
|
+
function inlineReference(part, budget) {
|
|
34
|
+
let buffer;
|
|
35
|
+
try {
|
|
36
|
+
buffer = readAttachmentBuffer(part);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (isPermanentAttachmentError(error)) return part;
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
if (buffer.length > budget.remaining) return part;
|
|
42
|
+
budget.remaining -= buffer.length;
|
|
43
|
+
const { attachmentRef: _ref, sizeBytes: _size, ...rest } = part;
|
|
44
|
+
if (part.type === 'text') {
|
|
45
|
+
const { textKind: _kind, filename: _name, mimeType: _mime, ...textRest } = rest;
|
|
46
|
+
return { ...textRest, type: 'text', text: attachmentTextForPart(part) };
|
|
47
|
+
}
|
|
48
|
+
return { ...rest, data: buffer.toString('base64') };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function inlinePart(part, budget) {
|
|
52
|
+
if (!part || typeof part !== 'object' || Array.isArray(part)) return part;
|
|
53
|
+
if (isAttachmentReference(part)) return inlineReference(part, budget);
|
|
54
|
+
if (Array.isArray(part.content)) {
|
|
55
|
+
const content = inlineParts(part.content, budget);
|
|
56
|
+
return content === part.content ? part : { ...part, content };
|
|
57
|
+
}
|
|
58
|
+
return part;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Newest last in a content list, so it is walked backwards for the budget. */
|
|
62
|
+
function inlineParts(parts, budget) {
|
|
63
|
+
let out = null;
|
|
64
|
+
for (let index = parts.length - 1; index >= 0; index -= 1) {
|
|
65
|
+
const next = inlinePart(parts[index], budget);
|
|
66
|
+
if (next === parts[index]) continue;
|
|
67
|
+
out ??= [...parts];
|
|
68
|
+
out[index] = next;
|
|
69
|
+
}
|
|
70
|
+
return out ?? parts;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** `messages` with every stored attachment reference replaced by its bytes. */
|
|
74
|
+
export function inlineModelProxyAttachments(messages, { maxBytes = MODEL_PROXY_INLINE_MAX_BYTES } = {}) {
|
|
75
|
+
if (!Array.isArray(messages)) return messages;
|
|
76
|
+
const budget = { remaining: maxBytes };
|
|
77
|
+
let out = null;
|
|
78
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
79
|
+
const message = messages[index];
|
|
80
|
+
if (!message || typeof message !== 'object' || message.content == null || typeof message.content === 'string') {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const content = Array.isArray(message.content)
|
|
84
|
+
? inlineParts(message.content, budget)
|
|
85
|
+
: inlinePart(message.content, budget);
|
|
86
|
+
if (content === message.content) continue;
|
|
87
|
+
out ??= [...messages];
|
|
88
|
+
out[index] = { ...message, content };
|
|
89
|
+
}
|
|
90
|
+
return out ?? messages;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export class ModelProxyProvider {
|
|
94
|
+
#channel;
|
|
95
|
+
#modelInfo = new Map();
|
|
96
|
+
|
|
97
|
+
constructor(name, config = {}, channel = getModelProxyChannel()) {
|
|
98
|
+
this.name = name;
|
|
99
|
+
this.config = config || {};
|
|
100
|
+
this.#channel = channel;
|
|
101
|
+
// Adapter traits are reported by the PC's real instance.
|
|
102
|
+
if (typeof this.config.modelProxy?.nativePdf === 'boolean') this.nativePdf = this.config.modelProxy.nativePdf;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
#call(method, fields = {}, options = {}) {
|
|
106
|
+
return this.#channel.request({ provider: this.name, method, ...fields }, options);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async send(messages, model, tools, sendOpts) {
|
|
110
|
+
const { options, callbacks } = splitModelProxySendOptions(sendOpts);
|
|
111
|
+
const finalized = isFinalizedProviderRequestTools(tools);
|
|
112
|
+
return this.#call(
|
|
113
|
+
'send',
|
|
114
|
+
{
|
|
115
|
+
model: model ?? null,
|
|
116
|
+
messages: inlineModelProxyAttachments(messages),
|
|
117
|
+
tools: Array.isArray(tools) ? tools : null,
|
|
118
|
+
toolsFinalized: finalized,
|
|
119
|
+
nativePrefixCount: finalized ? providerNativeToolPrefixCount(tools) : 0,
|
|
120
|
+
options,
|
|
121
|
+
},
|
|
122
|
+
{ signal: sendOpts?.signal || null, callbacks }
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
#adoptCatalog(catalog) {
|
|
127
|
+
const models = Array.isArray(catalog?.models) ? catalog.models : [];
|
|
128
|
+
const info = catalog?.modelInfo && typeof catalog.modelInfo === 'object' ? catalog.modelInfo : {};
|
|
129
|
+
this.#modelInfo = new Map(Object.entries(info));
|
|
130
|
+
return models;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async listModels() {
|
|
134
|
+
return this.#adoptCatalog(await this.#call('listModels'));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async _refreshModelCache() {
|
|
138
|
+
return this.#adoptCatalog(await this.#call('refreshModels'));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async isAvailable() {
|
|
142
|
+
return (await this.#call('isAvailable')) === true;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
getCachedModelInfo(model) {
|
|
146
|
+
return this.#modelInfo.get(String(model ?? '')) ?? null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** A proxy instance whose class carries the PC adapter's usage convention. */
|
|
151
|
+
export function createModelProxyProvider(name, config = {}, channel = getModelProxyChannel()) {
|
|
152
|
+
const inputExcludesCache = config?.modelProxy?.inputExcludesCache;
|
|
153
|
+
if (typeof inputExcludesCache !== 'boolean') return new ModelProxyProvider(name, config, channel);
|
|
154
|
+
class BoundModelProxyProvider extends ModelProxyProvider {
|
|
155
|
+
static inputExcludesCache = inputExcludesCache;
|
|
156
|
+
}
|
|
157
|
+
return new BoundModelProxyProvider(name, config, channel);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// The PC's provider set (availability + non-secret config) changes only on a
|
|
161
|
+
// PC-side sign-in or settings edit; a short cache keeps registry re-inits from
|
|
162
|
+
// paying a client round trip each. The cache belongs to one client generation:
|
|
163
|
+
// a reconnect (possibly from another PC) always asks again.
|
|
164
|
+
const PROVIDER_CONFIG_TTL_MS = 15_000;
|
|
165
|
+
/** How long a registry init waits for a client to connect and for its PC to
|
|
166
|
+
* answer with a loaded provider registry. */
|
|
167
|
+
export const MODEL_PROXY_CONFIG_WAIT_MS = 15_000;
|
|
168
|
+
const CONFIG_RETRY_FIRST_MS = 250;
|
|
169
|
+
const CONFIG_RETRY_MAX_MS = 2_000;
|
|
170
|
+
let _providerConfigCache = null;
|
|
171
|
+
let _providerConfigInFlight = null;
|
|
172
|
+
|
|
173
|
+
/** A reply the registry may act on: the PC says its registry is loaded, or it
|
|
174
|
+
* already names an enabled provider (a client that predates `ready`). An
|
|
175
|
+
* empty or unready answer is never read as "everything disabled". */
|
|
176
|
+
function providerConfigReady(reply, providers) {
|
|
177
|
+
// A loaded PC registry is authoritative, even when it has nothing enabled.
|
|
178
|
+
if (reply?.ready === true) return true;
|
|
179
|
+
if (reply?.ready === false) return false;
|
|
180
|
+
return Object.keys(providers).some((name) => providers[name]?.enabled === true);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const pause = (ms) =>
|
|
184
|
+
new Promise((resolve) => {
|
|
185
|
+
const timer = setTimeout(resolve, ms);
|
|
186
|
+
timer.unref?.();
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
export function loadModelProxyProviderConfig({
|
|
190
|
+
channel = getModelProxyChannel(),
|
|
191
|
+
now = Date.now,
|
|
192
|
+
waitMs = MODEL_PROXY_CONFIG_WAIT_MS,
|
|
193
|
+
} = {}) {
|
|
194
|
+
const generation = channel.generation;
|
|
195
|
+
const cached = _providerConfigCache;
|
|
196
|
+
if (
|
|
197
|
+
cached &&
|
|
198
|
+
cached.channel === channel &&
|
|
199
|
+
cached.generation === generation &&
|
|
200
|
+
now() - cached.at < PROVIDER_CONFIG_TTL_MS
|
|
201
|
+
) {
|
|
202
|
+
return Promise.resolve(cached.value);
|
|
203
|
+
}
|
|
204
|
+
const inFlight = _providerConfigInFlight;
|
|
205
|
+
if (inFlight && inFlight.channel === channel && inFlight.generation === generation) return inFlight.promise;
|
|
206
|
+
const promise = (async () => {
|
|
207
|
+
const deadline = Date.now() + waitMs;
|
|
208
|
+
let delay = CONFIG_RETRY_FIRST_MS;
|
|
209
|
+
let lastError = null;
|
|
210
|
+
for (;;) {
|
|
211
|
+
if (!channel.connected) {
|
|
212
|
+
const remaining = deadline - Date.now();
|
|
213
|
+
if (remaining <= 0 || !(await channel.whenConnected(remaining))) {
|
|
214
|
+
throw lastError ?? new ModelProxyUnavailableError('no desktop client is connected to run model calls');
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
try {
|
|
218
|
+
const reply = await channel.request({ provider: '', method: 'providerConfig' });
|
|
219
|
+
const raw = reply?.providers && typeof reply.providers === 'object' ? reply.providers : {};
|
|
220
|
+
// Defense in depth: the PC already strips secrets before sending.
|
|
221
|
+
const value = stripModelProxySecrets(raw);
|
|
222
|
+
if (providerConfigReady(reply, value)) {
|
|
223
|
+
if (channel.generation === generation) {
|
|
224
|
+
_providerConfigCache = { at: now(), value, channel, generation };
|
|
225
|
+
}
|
|
226
|
+
return value;
|
|
227
|
+
}
|
|
228
|
+
lastError = new ModelProxyUnavailableError('the desktop client has not loaded its model providers yet');
|
|
229
|
+
} catch (error) {
|
|
230
|
+
// Only "no client / no answer yet" is worth waiting out.
|
|
231
|
+
if (error?.code !== 'MODEL_PROXY_UNAVAILABLE') throw error;
|
|
232
|
+
lastError = error;
|
|
233
|
+
}
|
|
234
|
+
if (Date.now() + delay > deadline) throw lastError;
|
|
235
|
+
await pause(delay);
|
|
236
|
+
delay = Math.min(delay * 2, CONFIG_RETRY_MAX_MS);
|
|
237
|
+
}
|
|
238
|
+
})();
|
|
239
|
+
const entry = { channel, generation, promise };
|
|
240
|
+
_providerConfigInFlight = entry;
|
|
241
|
+
const clear = () => {
|
|
242
|
+
if (_providerConfigInFlight === entry) _providerConfigInFlight = null;
|
|
243
|
+
};
|
|
244
|
+
promise.then(clear, clear);
|
|
245
|
+
return promise;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export function _resetModelProxyProviderConfigForTest() {
|
|
249
|
+
_providerConfigCache = null;
|
|
250
|
+
_providerConfigInFlight = null;
|
|
251
|
+
}
|
|
@@ -10,6 +10,7 @@ import { writeJsonAtomicSync } from '../../../shared/atomic-file.mjs';
|
|
|
10
10
|
import { boundProviderAuthPath } from '../../../shared/provider-auth-binding.mjs';
|
|
11
11
|
import { getLlmDispatcher } from '../../../shared/llm/http-agent.mjs';
|
|
12
12
|
import { accountIdentityFields, scrubOAuthSecrets } from './lib/oauth-token-utils.mjs';
|
|
13
|
+
import { modelProxyClientMode } from '../../../shared/model-proxy-mode.mjs';
|
|
13
14
|
|
|
14
15
|
export const CLIENT_ID = '1031625952748946';
|
|
15
16
|
export const DEVICE_AUTH_URL = 'https://auth.meta.com/oidc/device/authorization/';
|
|
@@ -44,6 +45,7 @@ const nonEmptyString = (value) => typeof value === 'string' && value.trim() !==
|
|
|
44
45
|
export const isValidMuseCredentialDocument = (doc) => nonEmptyString(doc?.accessToken) && nonEmptyString(doc?.apiKey);
|
|
45
46
|
|
|
46
47
|
export function loadTokens() {
|
|
48
|
+
if (modelProxyClientMode()) return null;
|
|
47
49
|
const path = getOwnTokenPath();
|
|
48
50
|
if (!existsSync(path)) return null;
|
|
49
51
|
try {
|
|
@@ -10,6 +10,15 @@ import { createHash } from 'node:crypto';
|
|
|
10
10
|
import { noteErrorUsage } from './lib/note-error-usage.mjs';
|
|
11
11
|
import { fileMtimeMs } from './lib/oauth-token-utils.mjs';
|
|
12
12
|
import { OpenAICompatProvider, preloadOpenAICompatRuntime } from './openai-compat.mjs';
|
|
13
|
+
import { getModelMetadataSync } from './model-catalog.mjs';
|
|
14
|
+
import { makeModelCache } from './model-cache.mjs';
|
|
15
|
+
import { PRICING_RATE_KEYS } from '../../../shared/llm/model-pricing-rates.mjs';
|
|
16
|
+
import {
|
|
17
|
+
MUSE_DEFAULT_EFFORT_LEVELS as FIVE_LEVELS,
|
|
18
|
+
MUSE_SEED_IDS as SEED_MODELS,
|
|
19
|
+
MUSE_SPARK_MAX_OUTPUT as SPARK_MAX_OUTPUT,
|
|
20
|
+
museSeedRow,
|
|
21
|
+
} from '../../../shared/llm/provider-seed-rosters.mjs';
|
|
13
22
|
import {
|
|
14
23
|
API_VERSION,
|
|
15
24
|
MODEL_API_BASE_URL,
|
|
@@ -27,108 +36,63 @@ export {
|
|
|
27
36
|
export { beginOAuthLogin, loginOAuth } from './muse-code-oauth-login.mjs';
|
|
28
37
|
|
|
29
38
|
export const DEFAULT_MODEL = 'muse-spark-1.3';
|
|
30
|
-
const FIVE_LEVELS = Object.freeze(['minimal', 'low', 'medium', 'high', 'xhigh']);
|
|
31
|
-
const SIX_LEVELS = Object.freeze([...FIVE_LEVELS, 'max']);
|
|
32
39
|
const effortOptions = (levels) => [{ type: 'effort', values: [...levels] }];
|
|
33
40
|
// Image and voice generation ids are served by the same catalog but are not chat models.
|
|
34
41
|
const NON_CHAT_MODEL_RE = /^muse-(image|voice)-/i;
|
|
35
|
-
const SPARK_CONTEXT = 1_048_576;
|
|
36
|
-
const SPARK_MAX_OUTPUT = 131_072;
|
|
37
|
-
const STANDARD_COST = { inputCostPerM: 1.25, outputCostPerM: 4.25, cacheReadCostPerM: 0.15, cacheWriteCostPerM: 0 };
|
|
38
|
-
const CONTRIBUTOR_COST = { inputCostPerM: 0.1, outputCostPerM: 0.2, cacheReadCostPerM: 0.002, cacheWriteCostPerM: 0 };
|
|
39
|
-
|
|
40
|
-
// Seeded roster: the discovery endpoint lists bare ids, so limits, pricing and
|
|
41
|
-
// the effort ladder come from here. Only the 1.3 revisions accept `max`.
|
|
42
|
-
const SEEDS = Object.freeze({
|
|
43
|
-
'muse-spark-1.1': { name: 'Muse Spark 1.1', levels: FIVE_LEVELS, cost: STANDARD_COST },
|
|
44
|
-
'muse-spark-1.2': { name: 'Muse Spark 1.2', levels: FIVE_LEVELS, cost: STANDARD_COST },
|
|
45
|
-
'muse-spark-1.2-contributor': { name: 'Muse Spark 1.2 (C)', levels: FIVE_LEVELS, cost: CONTRIBUTOR_COST },
|
|
46
|
-
'muse-spark-1.3': { name: 'Muse Spark 1.3', levels: SIX_LEVELS, cost: STANDARD_COST },
|
|
47
|
-
'muse-spark-1.3-contributor': { name: 'Muse Spark 1.3 (C)', levels: SIX_LEVELS, cost: CONTRIBUTOR_COST },
|
|
48
|
-
});
|
|
49
|
-
const SEED_MODELS = Object.freeze(Object.keys(SEEDS));
|
|
50
|
-
|
|
51
|
-
function seedRow(id) {
|
|
52
|
-
const seed = SEEDS[id];
|
|
53
|
-
return {
|
|
54
|
-
id,
|
|
55
|
-
name: seed.name,
|
|
56
|
-
provider: 'muse-code-oauth',
|
|
57
|
-
family: 'muse-spark',
|
|
58
|
-
contextWindow: SPARK_CONTEXT,
|
|
59
|
-
outputTokens: SPARK_MAX_OUTPUT,
|
|
60
|
-
supportsReasoning: true,
|
|
61
|
-
supportsVision: true,
|
|
62
|
-
supportsFunctionCalling: true,
|
|
63
|
-
reasoningLevels: [...seed.levels],
|
|
64
|
-
reasoningOptions: effortOptions(seed.levels),
|
|
65
|
-
...seed.cost,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Revisioned Spark ids the seed does not list inherit the newest seeded
|
|
70
|
-
// revision of their tier (limits, vision, pricing) but take the five-level
|
|
71
|
-
// ladder: only reviewed seeds advertise `max`.
|
|
72
|
-
const SPARK_ID_RE = /^muse-spark-(\d+)\.(\d+)(?:\.(\d+))?(-contributor)?$/i;
|
|
73
42
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
43
|
+
// The discovered roster (fields /models returned, never seed values) is
|
|
44
|
+
// persisted so the shared sync lookup sees what listModels found.
|
|
45
|
+
const museModelCache = makeModelCache({
|
|
46
|
+
fileName: 'muse-code-oauth-models.json',
|
|
47
|
+
ttlMs: 24 * 60 * 60 * 1000,
|
|
48
|
+
version: 1,
|
|
49
|
+
});
|
|
78
50
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
51
|
+
// Row fields the shared metadata lookup resolves: live roster, models.dev
|
|
52
|
+
// `meta`, verified corrections, then the offline seed (provider-seed-rosters).
|
|
53
|
+
const LOOKUP_FIELDS = Object.freeze([
|
|
54
|
+
'contextWindow',
|
|
55
|
+
'outputTokens',
|
|
56
|
+
...PRICING_RATE_KEYS,
|
|
57
|
+
'supportsReasoning',
|
|
58
|
+
'supportsVision',
|
|
59
|
+
'supportsFunctionCalling',
|
|
60
|
+
'reasoningOptions',
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
// Labels compare without the trailing "(C)" tier marker, case or punctuation.
|
|
64
|
+
const nameKey = (name) =>
|
|
65
|
+
String(name || '')
|
|
66
|
+
.replace(/\s*\(c\)\s*$/i, '')
|
|
67
|
+
.toLowerCase()
|
|
68
|
+
.replace(/[^a-z0-9]+/g, '');
|
|
69
|
+
|
|
70
|
+
// A discovered or catalog label naming the seeded model keeps the seed's "(C)" marker.
|
|
71
|
+
function tierName(candidate, seedName) {
|
|
72
|
+
if (!candidate) return '';
|
|
73
|
+
return seedName && nameKey(candidate) === nameKey(seedName) ? seedName : candidate;
|
|
82
74
|
}
|
|
83
75
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
for (const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (!templateRevision || compareRevision(candidate, templateRevision) > 0) {
|
|
95
|
-
template = seedId;
|
|
96
|
-
templateRevision = candidate;
|
|
97
|
-
}
|
|
76
|
+
// Discovered fields win, then the shared lookup (fetched catalogs before
|
|
77
|
+
// seeds). Rows that report no effort ladder gain the default five levels
|
|
78
|
+
// unless a source declares the model non-reasoning.
|
|
79
|
+
function museRow(id, discovered = null) {
|
|
80
|
+
const meta = getModelMetadataSync(id, 'muse-code-oauth');
|
|
81
|
+
if (!meta && !discovered) return null;
|
|
82
|
+
const row = { id, provider: 'muse-code-oauth', family: 'muse-spark' };
|
|
83
|
+
for (const key of LOOKUP_FIELDS) {
|
|
84
|
+
const value = meta?.[key];
|
|
85
|
+
if (value != null && !(Array.isArray(value) && !value.length)) row[key] = value;
|
|
98
86
|
}
|
|
99
|
-
|
|
100
|
-
const revision =
|
|
101
|
-
match[3] && Number(match[3]) !== 0 ? `${match[1]}.${match[2]}.${match[3]}` : `${match[1]}.${match[2]}`;
|
|
102
|
-
return {
|
|
103
|
-
...seedRow(template),
|
|
104
|
-
id,
|
|
105
|
-
name: `Muse Spark ${revision}${contributor ? ' (C)' : ''}`,
|
|
106
|
-
reasoningLevels: [...FIVE_LEVELS],
|
|
107
|
-
reasoningOptions: effortOptions(FIVE_LEVELS),
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Seeds win for the ids they cover; lineage rows yield to discovered metadata.
|
|
112
|
-
// A name supplied by discovery is always kept. Other discovered rows keep
|
|
113
|
-
// their own metadata and only gain the default effort ladder when they report none.
|
|
114
|
-
function museRow(id, discovered) {
|
|
87
|
+
Object.assign(row, discovered || {});
|
|
115
88
|
const discoveredName =
|
|
116
89
|
typeof discovered?.name === 'string' && discovered.name && discovered.name !== id ? discovered.name : '';
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
family: 'muse-spark',
|
|
124
|
-
...(lineage || {}),
|
|
125
|
-
...(discovered || {}),
|
|
126
|
-
};
|
|
127
|
-
if (discoveredName) row.name = discoveredName;
|
|
128
|
-
else if (lineage) row.name = lineage.name;
|
|
129
|
-
if (!row.reasoningOptions?.length) {
|
|
130
|
-
row.reasoningOptions = effortOptions(FIVE_LEVELS);
|
|
131
|
-
row.reasoningLevels = [...FIVE_LEVELS];
|
|
90
|
+
row.name = tierName(discoveredName || meta?.displayName, museSeedRow(id)?.name) || id;
|
|
91
|
+
// A model declared non-reasoning gets no default ladder.
|
|
92
|
+
if (!row.reasoningOptions?.length)
|
|
93
|
+
row.reasoningOptions = row.supportsReasoning === false ? [] : effortOptions(FIVE_LEVELS);
|
|
94
|
+
if (!row.reasoningLevels?.length) {
|
|
95
|
+
row.reasoningLevels = [...(row.reasoningOptions.find((o) => o?.type === 'effort')?.values || [])];
|
|
132
96
|
}
|
|
133
97
|
return row;
|
|
134
98
|
}
|
|
@@ -414,12 +378,9 @@ export class MuseCodeOAuthProvider {
|
|
|
414
378
|
});
|
|
415
379
|
this._innerKey = apiKey;
|
|
416
380
|
// The Responses builder reads limits and the effort ladder from the inner
|
|
417
|
-
// provider's cached model row;
|
|
381
|
+
// provider's cached model row; the shared lookup fills what discovery omits.
|
|
418
382
|
const innerRow = this._inner.getCachedModelInfo.bind(this._inner);
|
|
419
|
-
this._inner.getCachedModelInfo = (model) =>
|
|
420
|
-
const discovered = innerRow(model);
|
|
421
|
-
return discovered || SEEDS[model] || lineageRow(model) ? museRow(model, discovered) : null;
|
|
422
|
-
};
|
|
383
|
+
this._inner.getCachedModelInfo = (model) => museRow(model, innerRow(model));
|
|
423
384
|
return this._inner;
|
|
424
385
|
}
|
|
425
386
|
|
|
@@ -452,6 +413,8 @@ export class MuseCodeOAuthProvider {
|
|
|
452
413
|
async listModels() {
|
|
453
414
|
const { apiKey } = await this.ensureAuth();
|
|
454
415
|
const inner = this._ensureInner(apiKey);
|
|
416
|
+
// Only the latest request, fetched with the still-active key, publishes.
|
|
417
|
+
const publish = museModelCache.beginSave(() => loadTokens()?.apiKey === apiKey);
|
|
455
418
|
let items;
|
|
456
419
|
try {
|
|
457
420
|
items = await inner._fetchModelItems();
|
|
@@ -460,25 +423,29 @@ export class MuseCodeOAuthProvider {
|
|
|
460
423
|
return SEED_MODELS.map((id) => museRow(id));
|
|
461
424
|
}
|
|
462
425
|
// A successful roster is authoritative, even when it holds no chat models.
|
|
463
|
-
const
|
|
426
|
+
const discovered = (Array.isArray(items) ? items : [])
|
|
464
427
|
.filter((m) => typeof m?.id === 'string' && m.id && !NON_CHAT_MODEL_RE.test(m.id))
|
|
465
428
|
.map((m) => {
|
|
466
429
|
const contextWindow = Number(m.context_window ?? m.max_context_window ?? m.context_length ?? 0);
|
|
467
430
|
const outputTokens = Number(m.max_output_tokens ?? m.output_tokens ?? 0);
|
|
468
431
|
const name = [m.name, m.display_name].find((v) => typeof v === 'string' && v.trim());
|
|
469
|
-
return
|
|
432
|
+
return {
|
|
433
|
+
id: m.id,
|
|
434
|
+
provider: 'muse-code-oauth',
|
|
470
435
|
...(name ? { name: name.trim() } : {}),
|
|
471
436
|
...(contextWindow > 0 ? { contextWindow } : {}),
|
|
472
437
|
...(outputTokens > 0 ? { outputTokens } : {}),
|
|
473
438
|
...(typeof m.created === 'number' ? { created: m.created } : {}),
|
|
474
|
-
}
|
|
439
|
+
};
|
|
475
440
|
});
|
|
476
|
-
|
|
441
|
+
const rows = discovered.map((row) => museRow(row.id, row));
|
|
442
|
+
// A superseded or other-credential response never replaces the live roster either.
|
|
443
|
+
if (publish(discovered)) inner._enrichedModels = rows;
|
|
477
444
|
return rows;
|
|
478
445
|
}
|
|
479
446
|
|
|
480
447
|
getCachedModelInfo(model) {
|
|
481
|
-
return this._inner?.getCachedModelInfo?.(model) ||
|
|
448
|
+
return this._inner?.getCachedModelInfo?.(model) || museRow(model);
|
|
482
449
|
}
|
|
483
450
|
|
|
484
451
|
/** Subscription window/weekly usage, read from the key endpoint without onboarding. */
|
|
@@ -6,6 +6,7 @@ import { boundProviderAuthPath } from '../../../shared/provider-auth-binding.mjs
|
|
|
6
6
|
import { cursorTokenExpiry } from './cursor-auth.mjs';
|
|
7
7
|
import { isValidMuseCredentialDocument } from './muse-code-oauth-tokens.mjs';
|
|
8
8
|
import { developerOptionEnabled, developerOptionForProvider } from '../../../shared/developer-options.mjs';
|
|
9
|
+
import { modelProxyClientMode } from '../../../shared/model-proxy-mode.mjs';
|
|
9
10
|
|
|
10
11
|
const ANTHROPIC_DEFAULT_CREDENTIALS_PATH = join(resolvePluginData(), 'anthropic-oauth-credentials.json');
|
|
11
12
|
|
|
@@ -100,6 +101,8 @@ function credentialPathsSignature(paths, extra = '') {
|
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
function memoProbe(key, paths, compute, extraSignature = '') {
|
|
104
|
+
// Remote mode: no credential file on this server is ever read.
|
|
105
|
+
if (modelProxyClientMode()) return 'absent';
|
|
103
106
|
const signature = credentialPathsSignature(paths, extraSignature);
|
|
104
107
|
const hit = _probeCache.get(key);
|
|
105
108
|
const now = Date.now();
|
|
@@ -178,6 +181,17 @@ function mimoOAuthState() {
|
|
|
178
181
|
);
|
|
179
182
|
}
|
|
180
183
|
|
|
184
|
+
function commandCodeOAuthState() {
|
|
185
|
+
const paths = [
|
|
186
|
+
boundProviderAuthPath('command-code-oauth') ||
|
|
187
|
+
process.env.COMMAND_CODE_OAUTH_CREDENTIALS_PATH ||
|
|
188
|
+
join(resolvePluginData(), 'command-code-oauth.json'),
|
|
189
|
+
];
|
|
190
|
+
return memoProbe('command-code-oauth', paths, () =>
|
|
191
|
+
resolveProbeState(paths, (docs) => docs.some((own) => typeof own?.apiKey === 'string' && !!own.apiKey.trim()))
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
181
195
|
function museCodeOAuthState() {
|
|
182
196
|
const paths = [
|
|
183
197
|
boundProviderAuthPath('muse-code-oauth') ||
|
|
@@ -252,6 +266,7 @@ const OAUTH_PROBE_STATES = new Map([
|
|
|
252
266
|
['openai-oauth', openAIOAuthState],
|
|
253
267
|
['grok-oauth', grokOAuthState],
|
|
254
268
|
['muse-code-oauth', museCodeOAuthState],
|
|
269
|
+
['command-code-oauth', commandCodeOAuthState],
|
|
255
270
|
['mimo-oauth', mimoOAuthState],
|
|
256
271
|
['cursor-oauth', cursorOAuthState],
|
|
257
272
|
['antigravity-oauth', antigravityOAuthState],
|
|
@@ -868,7 +868,8 @@ async function measureUsage(provider, providerObj, routeInfo) {
|
|
|
868
868
|
(provider === 'cursor-oauth' ||
|
|
869
869
|
provider === 'cursor-api' ||
|
|
870
870
|
provider === 'antigravity-oauth' ||
|
|
871
|
-
provider === 'muse-code-oauth'
|
|
871
|
+
provider === 'muse-code-oauth' ||
|
|
872
|
+
provider === 'command-code-oauth') &&
|
|
872
873
|
typeof providerObj?.getUsageSnapshot === 'function'
|
|
873
874
|
) {
|
|
874
875
|
return await providerObj.getUsageSnapshot();
|
|
@@ -893,12 +894,12 @@ async function measureUsageWithAuthRetry(provider, providerObj, routeInfo) {
|
|
|
893
894
|
// refresh cannot vouch for the reading it last produced: keeping a 100% meter
|
|
894
895
|
// earned by a dead token would hold the account out of the roster until its
|
|
895
896
|
// reset time, so the recorded quota goes with the credential.
|
|
896
|
-
function usageAfterFailure(err, provider, accountId, log) {
|
|
897
|
+
async function usageAfterFailure(err, provider, accountId, log) {
|
|
897
898
|
const snapshot = provider === 'anthropic-oauth' && accountId === 'default' ? latestClaudeStatuslineUsage() : null;
|
|
898
899
|
if (snapshot) return snapshot;
|
|
899
900
|
if (isUsageAuthRejection(err) && ACCOUNT_PROVIDERS.includes(provider)) {
|
|
900
901
|
try {
|
|
901
|
-
clearProviderAccountQuotaState(provider, accountId);
|
|
902
|
+
await clearProviderAccountQuotaState(provider, accountId);
|
|
902
903
|
} catch (error) {
|
|
903
904
|
log(`Account usage could not be cleared: ${error.message}`);
|
|
904
905
|
}
|
|
@@ -952,7 +953,7 @@ export async function fetchOAuthUsageSnapshot(routeInfo, providerObj, log = () =
|
|
|
952
953
|
try {
|
|
953
954
|
snapshot = await measureUsageWithAuthRetry(provider, providerObj, routeInfo);
|
|
954
955
|
} catch (err) {
|
|
955
|
-
snapshot = usageAfterFailure(err, provider, accountId, log);
|
|
956
|
+
snapshot = await usageAfterFailure(err, provider, accountId, log);
|
|
956
957
|
}
|
|
957
958
|
if (!isContentfulSnapshot(snapshot)) {
|
|
958
959
|
cacheNegative(key, 'empty');
|
|
@@ -961,7 +962,7 @@ export async function fetchOAuthUsageSnapshot(routeInfo, providerObj, log = () =
|
|
|
961
962
|
}
|
|
962
963
|
if (ACCOUNT_PROVIDERS.includes(provider)) {
|
|
963
964
|
try {
|
|
964
|
-
recordProviderAccountUsage(provider, accountId, snapshot);
|
|
965
|
+
await recordProviderAccountUsage(provider, accountId, snapshot);
|
|
965
966
|
} catch (error) {
|
|
966
967
|
log(`Account usage could not be saved: ${error.message}`);
|
|
967
968
|
}
|
|
@@ -38,7 +38,7 @@ export async function sendCompatChat(provider, messages, useModel, tools, opts)
|
|
|
38
38
|
// global catalog must not shape a user-defined endpoint's request.
|
|
39
39
|
let modelInfo = null;
|
|
40
40
|
if (isCustom) modelInfo = provider.getCachedModelInfo(useModel) || null;
|
|
41
|
-
else if (provider.name === 'opencode-go')
|
|
41
|
+
else if (provider.name === 'opencode-go' || provider.name === 'command-code-oauth')
|
|
42
42
|
modelInfo = provider.getCachedModelInfo(useModel) || getModelMetadataSync(useModel, provider.name);
|
|
43
43
|
else if (profile?.resolveModelInfo) modelInfo = profile.resolveModelInfo(provider, useModel) || null;
|
|
44
44
|
// Resolved before lowering: replay eligibility depends on the snapped level
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolveProviderApiKey } from '../../../shared/provider-api-key.mjs';
|
|
1
2
|
import { enrichModels } from './model-catalog.mjs';
|
|
2
3
|
import { sanitizeModelList } from './model-list-sanitize.mjs';
|
|
3
4
|
import { PROVIDER_GENERATE_TOTAL_TIMEOUT_MS, createTimeoutSignal, resolveTimeoutMs } from '../stall-policy.mjs';
|
|
@@ -10,12 +11,15 @@ const MODEL_LIST_TIMEOUT_MS = resolveTimeoutMs('MIXDOG_COMPAT_MODEL_LIST_TIMEOUT
|
|
|
10
11
|
// `keyless` omits the Authorization header entirely (keyless endpoints);
|
|
11
12
|
// `signal` aborts the request together with the list timeout.
|
|
12
13
|
export async function fetchCompatModelItems(provider, { signal = null, keyless = false } = {}) {
|
|
13
|
-
const
|
|
14
|
+
const name = provider.name;
|
|
15
|
+
const timeout = createTimeoutSignal(signal, MODEL_LIST_TIMEOUT_MS, `${name} model list`);
|
|
14
16
|
try {
|
|
15
17
|
const res = await fetch(`${String(provider.baseURL || '').replace(/\/+$/, '')}/models`, {
|
|
16
18
|
method: 'GET',
|
|
17
19
|
headers: {
|
|
18
|
-
...(keyless
|
|
20
|
+
...(keyless
|
|
21
|
+
? {}
|
|
22
|
+
: { Authorization: `Bearer ${resolveProviderApiKey(name, provider.config || provider) || 'no-key'}` }),
|
|
19
23
|
...(provider.defaultHeaders || {}),
|
|
20
24
|
},
|
|
21
25
|
signal: timeout.signal,
|
|
@@ -74,6 +74,17 @@ export function applyCompatProviderChatOptions(params, providerName, opts = {},
|
|
|
74
74
|
}
|
|
75
75
|
return params;
|
|
76
76
|
}
|
|
77
|
+
if (providerName === 'command-code-oauth') {
|
|
78
|
+
// The API's field is undocumented; mirror the common `reasoning_effort`
|
|
79
|
+
// (levels the catalog row declares, else low/medium/high).
|
|
80
|
+
const rawEffort = opts.effort ?? config?.reasoningEffort;
|
|
81
|
+
const declared = modelInfo?.reasoningOptions?.some((option) => option?.type === 'effort');
|
|
82
|
+
const effort = declared
|
|
83
|
+
? normalizeOpencodeGoReasoningEffort(rawEffort, modelInfo)
|
|
84
|
+
: normalizeReasoningEffort(rawEffort, ['low', 'medium', 'high']);
|
|
85
|
+
if (effort) params.reasoning_effort = effort;
|
|
86
|
+
return params;
|
|
87
|
+
}
|
|
77
88
|
if (providerName === 'opencode-go') {
|
|
78
89
|
const reasoningEffort = normalizeOpencodeGoReasoningEffort(opts.effort ?? config?.reasoningEffort, modelInfo);
|
|
79
90
|
// OpenCode Go's OpenAI-compatible contract exposes reasoning_effort,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolveProviderApiKey } from '../../../shared/provider-api-key.mjs';
|
|
1
2
|
import { markProviderRecoveryExhausted, withRetry } from './retry-classifier.mjs';
|
|
2
3
|
import { consumeCompatResponsesStream } from './openai-compat-stream.mjs';
|
|
3
4
|
import { PROVIDER_FIRST_BYTE_TIMEOUT_MS, createPassthroughSignal } from '../stall-policy.mjs';
|
|
@@ -158,7 +159,7 @@ export async function sendXaiResponsesWebSocket(provider, messages, useModel, to
|
|
|
158
159
|
const reason = signal.reason;
|
|
159
160
|
throw reason instanceof Error ? reason : new Error('xAI Responses WebSocket request aborted by session close');
|
|
160
161
|
}
|
|
161
|
-
const apiKey = provider.config
|
|
162
|
+
const apiKey = resolveProviderApiKey('xai', provider.config);
|
|
162
163
|
if (!apiKey) throw new Error('xAI API key not configured');
|
|
163
164
|
messages = await preparePdfTextForProvider(messages, provider);
|
|
164
165
|
const chatMessagesForTrace = toOpenAIMessages(messages, provider.name, { nativePdf: provider.nativePdf });
|