mixdog 1.0.11 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +20 -0
- package/README.md +75 -181
- package/package.json +9 -4
- package/scripts/build-shipped-history.mjs +131 -0
- package/scripts/check-changelog-locales.mjs +203 -0
- package/scripts/computer-task-cost-report.mjs +0 -4
- package/scripts/lib/run-node-tests.mjs +235 -13
- package/scripts/lib/test-failure-records.mjs +5 -0
- package/scripts/lib/test-failure-summary.mjs +9 -3
- package/scripts/lib/test-spawn-ledger.mjs +19 -0
- package/scripts/prune-embedding-runtime.mjs +9 -5
- package/scripts/sync-client-version-floors.mjs +100 -0
- package/scripts/test-direct.mjs +16 -1
- package/src/agents/advisor/AGENT.md +38 -0
- package/src/agents/advisor/agent.json +6 -0
- package/src/agents/reviewer/AGENT.md +5 -2
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +381 -0
- package/src/defaults/skills/docx/SKILL.md +7 -5
- package/src/defaults/skills/docx/references/html.md +9 -8
- package/src/defaults/skills/docx/references/native-authoring.md +28 -18
- package/src/defaults/skills/goal-management/SKILL.md +11 -5
- package/src/defaults/skills/local-provider/SKILL.md +2 -1
- package/src/defaults/skills/pdf/SKILL.md +9 -6
- package/src/defaults/skills/pdf/references/html.md +17 -12
- package/src/defaults/skills/pptx/SKILL.md +8 -6
- package/src/defaults/skills/pptx/references/composition.md +4 -4
- package/src/defaults/skills/pptx/references/concepts.md +168 -0
- package/src/defaults/skills/pptx/references/direction.md +5 -4
- package/src/defaults/skills/pptx/references/html.md +6 -29
- package/src/defaults/skills/pptx/references/kit-index.md +11 -3
- package/src/defaults/skills/pptx/references/kit.md +27 -5
- package/src/defaults/skills/pptx/references/review.md +6 -5
- package/src/defaults/skills/setup/SKILL.md +5 -8
- package/src/defaults/skills/setup/references/actions.md +61 -31
- package/src/defaults/skills/setup/references/surfaces.md +12 -10
- package/src/defaults/skills/xlsx/SKILL.md +8 -6
- package/src/defaults/skills/xlsx/references/html.md +8 -4
- package/src/defaults/skills/xlsx/references/model-conventions.md +2 -0
- package/src/defaults/skills/xlsx/references/report-design.md +32 -16
- package/src/help.mjs +1 -1
- package/src/lib/rules-builder.cjs +1 -1
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +3 -1
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +4 -0
- package/src/runtime/agent/orchestrator/config-presets.d.mts +1 -0
- package/src/runtime/agent/orchestrator/config-presets.mjs +44 -0
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +9 -1
- package/src/runtime/agent/orchestrator/config.mjs +102 -21
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +90 -26
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +44 -14
- package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +4 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +79 -8
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +29 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +11 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +9 -5
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +30 -22
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +28 -10
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +14 -72
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +19 -3
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +20 -10
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-sink.mjs +36 -9
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +11 -17
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +388 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +92 -109
- package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +107 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +138 -30
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +32 -15
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +39 -5
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/lib/note-error-usage.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +57 -0
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +12 -5
- package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +20 -15
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +14 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +56 -11
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +28 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +27 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +7 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +23 -8
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +26 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +34 -15
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +12 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +0 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +0 -19
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +12 -43
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +39 -9
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +31 -9
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +13 -38
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +40 -9
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +7 -39
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +28 -101
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +8 -4
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +3 -6
- package/src/runtime/agent/orchestrator/providers/openai-service-tier.mjs +19 -0
- package/src/runtime/agent/orchestrator/providers/openai-startup-prewarm.mjs +5 -195
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +9 -18
- package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +4 -66
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +11 -5
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/acquire-attempt.mjs +3 -15
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/attempt-request.mjs +6 -56
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +1 -19
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure-stamps.mjs +0 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts.mjs +3 -5
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-outcome.mjs +10 -89
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-span.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-trace.mjs +0 -6
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +34 -11
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +0 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +3 -7
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +44 -19
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +40 -12
- package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +70 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +38 -3
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +11 -0
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +31 -41
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +5 -0
- package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +0 -17
- package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +0 -3
- package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +0 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +1 -2
- package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +18 -4
- package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +8 -1
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +7 -1
- package/src/runtime/agent/orchestrator/runtime-core/session-route-policy.mjs +16 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -2
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +7 -7
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +45 -2
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/eager-dispatch/entry.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +6 -13
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +114 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +5 -9
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +51 -18
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +7 -4
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +0 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +6 -9
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +63 -3
- package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +10 -28
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +4 -4
- package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +10 -19
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +1 -3
- package/src/runtime/agent/orchestrator/stall-policy.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +18 -8
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +19 -20
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +6 -11
- package/src/runtime/agent/orchestrator/tools/builtin/file-version-test-helpers.mjs +11 -0
- package/src/runtime/agent/orchestrator/tools/builtin/file-version.mjs +13 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-single-file-rescue.mjs +8 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +25 -12
- package/src/runtime/agent/orchestrator/tools/builtin/raw-content-publication.mjs +17 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +136 -76
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +15 -17
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +11 -10
- package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +30 -16
- package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/snapshot-helpers.mjs +4 -11
- package/src/runtime/agent/orchestrator/tools/builtin/snapshot-store.mjs +7 -3
- package/src/runtime/agent/orchestrator/tools/builtin/snapshot-validation.mjs +16 -19
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +14 -4
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +58 -8
- package/src/runtime/agent/orchestrator/tools/patch/content-guard.mjs +47 -0
- package/src/runtime/agent/orchestrator/tools/patch/delete-quarantine.mjs +155 -0
- package/src/runtime/agent/orchestrator/tools/patch/dispatch/native-proofs.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/patch/dispatch/native-snapshots.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +19 -16
- package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +13 -44
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/patch/post-patch-excerpts.mjs +5 -2
- package/src/runtime/agent/orchestrator/tools/patch/replay-capture.mjs +47 -7
- package/src/runtime/agent/orchestrator/tools/patch/rollback-state.mjs +72 -8
- package/src/runtime/agent/orchestrator/tools/patch/section-coalesce.mjs +3 -2
- package/src/runtime/agent/orchestrator/tools/patch/sequence/run.mjs +9 -1
- package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +9 -1
- package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +16 -4
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +35 -14
- package/src/runtime/agent/orchestrator/tools/patch/wave.mjs +42 -4
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/shell-codepage.mjs +296 -0
- package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +75 -24
- package/src/runtime/browser-bridge/tool-defs.mjs +1 -0
- package/src/runtime/channels/lib/config.mjs +3 -8
- package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +7 -3
- package/src/{tui → runtime/channels}/lib/voice-setup.mjs +38 -22
- package/src/runtime/channels/lib/webhook/request-handler.mjs +42 -8
- package/src/runtime/computer-bridge/actions.mjs +2 -0
- package/src/runtime/effort-judge/judge-client.mjs +125 -25
- package/src/runtime/effort-judge/judge-input.mjs +96 -0
- package/src/runtime/effort-judge/judge-worker.mjs +52 -20
- package/src/runtime/effort-judge/model-install.mjs +74 -0
- package/src/runtime/effort-judge/model-manifest.json +21 -0
- package/src/runtime/effort-judge/previous-human-request.mjs +162 -0
- package/src/runtime/effort-judge/verified-context-input.mjs +10 -0
- package/src/runtime/github/tool.mjs +214 -14
- package/src/runtime/local-provider/context-settings.mjs +15 -6
- package/src/runtime/local-provider/gguf-header.mjs +13 -5
- package/src/runtime/local-provider/hugging-face.mjs +27 -5
- package/src/runtime/local-provider/install-progress.mjs +7 -0
- package/src/runtime/local-provider/managed-runtime.mjs +2 -1
- package/src/runtime/local-provider/model-maintenance.mjs +15 -6
- package/src/runtime/local-provider/resumable-installations.mjs +40 -1
- package/src/runtime/local-provider/server.mjs +2 -0
- package/src/runtime/memory/lib/embedding-provider.mjs +12 -0
- package/src/runtime/memory/lib/http-router/session-routes.mjs +2 -1
- package/src/runtime/memory/lib/memory-config-flags.mjs +3 -2
- package/src/runtime/memory/lib/memory-embed.mjs +5 -0
- package/src/runtime/memory/lib/pg/process.mjs +57 -5
- package/src/runtime/office/README.md +13 -7
- package/src/runtime/office/authoring/docx-html-build.mjs +4 -4
- package/src/runtime/office/authoring/docx-html-measure.mjs +60 -0
- package/src/runtime/office/authoring/pdf-author-action.mjs +6 -1
- package/src/runtime/office/authoring/pptx-brief.mjs +40 -1
- package/src/runtime/office/authoring/pptx-html-build.mjs +1 -1
- package/src/runtime/office/authoring/pptx-html-measure.mjs +1 -1
- package/src/runtime/office/bench/deck-bench.mjs +1 -1
- package/src/runtime/office/com/office-com-host.ps1 +8 -0
- package/src/runtime/office/core/office-actions-render.mjs +2 -0
- package/src/runtime/office/design/design-art-direction.mjs +10 -2
- package/src/runtime/office/design/design-discipline.mjs +4 -5
- package/src/runtime/office/design/design-tokens.mjs +20 -1
- package/src/runtime/office/design/docx/design-docx/front-matter.mjs +7 -4
- package/src/runtime/office/design/docx/design-docx/section.mjs +3 -1
- package/src/runtime/office/design/docx/design-docx/writer.mjs +1 -0
- package/src/runtime/office/design/docx/design-docx-components.mjs +19 -15
- package/src/runtime/office/design/docx/design-docx.mjs +5 -6
- package/src/runtime/office/design/docx/document-typography.mjs +20 -6
- package/src/runtime/office/design/xlsx/design-xlsx.mjs +9 -2
- package/src/runtime/office/pdf/document-preview.mjs +133 -12
- package/src/runtime/office/pdf/pdf-writer.mjs +56 -22
- package/src/runtime/office/portable/portable-snapshot-docx.mjs +46 -3
- package/src/runtime/office/portable/portable-snapshot-shared.mjs +27 -1
- package/src/runtime/office/quality/assurance-rendered.mjs +21 -5
- package/src/runtime/office/quality/assurance-structure-docx.mjs +41 -9
- package/src/runtime/office/quality/design-aesthetics.mjs +4 -2
- package/src/runtime/office/quality/design-deck-diversity.mjs +15 -3
- package/src/runtime/office/quality/design-review.mjs +13 -5
- package/src/runtime/office/quality/document-brief.mjs +8 -2
- package/src/runtime/office/quality/forced-break-pages.mjs +203 -0
- package/src/runtime/office/quality/pptx-deck-rubric.mjs +21 -3
- package/src/runtime/office/quality/quality-pipeline.mjs +14 -17
- package/src/runtime/session-search/session-search-db.mjs +183 -0
- package/src/runtime/session-search/session-search-ingest.mjs +106 -0
- package/src/runtime/shared/agent-route-config.mjs +50 -2
- package/src/runtime/shared/bounded-file-read.mjs +166 -0
- package/src/runtime/shared/builtin-grandfathering.mjs +37 -0
- package/src/runtime/shared/config.mjs +24 -4
- package/src/runtime/shared/defaults-separation.mjs +263 -0
- package/src/runtime/shared/error-presentation.mjs +8 -1
- package/src/runtime/shared/llm/anthropic-effort.mjs +4 -0
- package/src/runtime/shared/llm/cost.mjs +4 -2
- package/src/runtime/shared/llm/model-catalog-projection.mjs +1 -1
- package/src/runtime/shared/llm/model-catalog.mjs +25 -0
- package/src/runtime/shared/llm/reasoning-usage.mjs +1 -2
- package/src/runtime/shared/llm/usage-accounting.mjs +14 -4
- package/src/runtime/shared/llm/usage-context.mjs +11 -1
- package/src/runtime/shared/llm/usage-ledger-repair.mjs +3 -1
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +105 -1
- package/src/runtime/shared/llm/usage-ledger-worker.mjs +2 -1
- package/src/runtime/shared/llm/usage-ledger.mjs +72 -5
- package/src/runtime/shared/onnx-runtime-support.mjs +6 -0
- package/src/runtime/shared/orchestration.mjs +14 -6
- package/src/runtime/shared/pristine-execution-contract.json +7 -2
- package/src/runtime/shared/projects.mjs +65 -48
- package/src/runtime/shared/provider-accounts.mjs +47 -6
- package/src/runtime/shared/quota-resume-store.mjs +255 -0
- package/src/runtime/shared/shipped-definitions.mjs +275 -0
- package/src/runtime/shared/tool-card-model/agent-surface.mjs +30 -9
- package/src/runtime/shared/tool-card-model/aggregate-card.mjs +7 -3
- package/src/runtime/shared/tool-card-model/background-task.mjs +17 -1
- package/src/runtime/shared/tool-card-model/card-detail.mjs +10 -4
- package/src/runtime/shared/tool-card-model/card-header.mjs +10 -4
- package/src/runtime/shared/tool-card-model/card-status.mjs +22 -5
- package/src/runtime/shared/tool-card-model/displayed-result.mjs +6 -1
- package/src/runtime/shared/tool-card-model/media-result.mjs +53 -0
- package/src/runtime/shared/tool-card-model/terminal-status.mjs +17 -1
- package/src/runtime/shared/tool-card-model.golden-cases.mjs +1 -1
- package/src/runtime/shared/tool-card-model.golden.json +75 -66
- package/src/runtime/shared/tool-card-model.mjs +1 -0
- package/src/runtime/shared/tool-output-limit.mjs +3 -0
- package/src/runtime/shared/tool-primitives.mjs +24 -18
- package/src/runtime/shared/tool-result-summary.mjs +128 -17
- package/src/runtime/shared/tool-status.mjs +20 -7
- package/src/runtime/shared/tool-surface.mjs +105 -28
- package/src/runtime/shared/tool-work-units.mjs +221 -18
- package/src/runtime/shared/transcript-metadata.mjs +2 -0
- package/src/runtime/shared/turn-review-reply.mjs +2 -0
- package/src/runtime/shared/turn-snapshot.mjs +65 -6
- package/src/runtime/shared/turn-worktree-snapshot.mjs +202 -22
- package/src/runtime/shared/worker-requests.mjs +14 -2
- package/src/runtime/terminal-bridge/client.mjs +311 -0
- package/src/runtime/terminal-bridge/tool-defs.mjs +36 -0
- package/src/runtime/web-search/lib/ssrf-guard.mjs +12 -56
- package/src/runtime/web-search/tool-defs.mjs +2 -0
- package/src/session-runtime/boot/apis.mjs +30 -5
- package/src/session-runtime/boot/config.mjs +4 -0
- package/src/session-runtime/boot/facade.mjs +4 -1
- package/src/session-runtime/boot/infrastructure.mjs +21 -2
- package/src/session-runtime/boot/session.mjs +5 -5
- package/src/session-runtime/boot/tools.mjs +2 -0
- package/src/session-runtime/builtin-features.d.mts +1 -0
- package/src/session-runtime/channel-config-api.mjs +5 -0
- package/src/session-runtime/config-lifecycle/config-writers.mjs +3 -0
- package/src/session-runtime/config-lifecycle.mjs +31 -6
- package/src/session-runtime/goal-facade-api.mjs +4 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +15 -3
- package/src/session-runtime/lifecycle/inheritance.mjs +28 -6
- package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +3 -0
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +7 -1
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +9 -0
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +14 -2
- package/src/session-runtime/lifecycle/teardown.mjs +5 -0
- package/src/session-runtime/local-provider-settings.mjs +10 -0
- package/src/session-runtime/media-api.mjs +32 -22
- package/src/session-runtime/model-recency.mjs +14 -0
- package/src/session-runtime/model-route/route-persist.mjs +17 -2
- package/src/session-runtime/model-route/route-tuning.mjs +16 -5
- package/src/session-runtime/model-route/set-route.mjs +55 -22
- package/src/session-runtime/model-route/web-search-route.mjs +2 -2
- package/src/session-runtime/model-route-api.mjs +2 -1
- package/src/session-runtime/notification-bus.mjs +31 -6
- package/src/session-runtime/provider-auth/login.mjs +6 -0
- package/src/session-runtime/provider-models/catalog-load.mjs +3 -1
- package/src/session-runtime/provider-models/row-hydration.mjs +36 -10
- package/src/session-runtime/quick-model-rows/model-meta.mjs +26 -0
- package/src/session-runtime/quick-model-rows/provider-rows.mjs +40 -14
- package/src/session-runtime/resource-api.mjs +8 -1
- package/src/session-runtime/route-state.mjs +9 -0
- package/src/session-runtime/runtime-core.mjs +4 -0
- package/src/session-runtime/runtime-facade.mjs +20 -1
- package/src/session-runtime/runtime-feature-gates.mjs +2 -0
- package/src/session-runtime/runtime-review-api.mjs +12 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +14 -1
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +10 -15
- package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +6 -1
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +20 -2
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +14 -6
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +2 -0
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +12 -1
- package/src/session-runtime/services/agent-tool/worker-index.mjs +17 -1
- package/src/session-runtime/services/agent-tool.mjs +1 -0
- package/src/session-runtime/services/channel-admin.mjs +87 -13
- package/src/session-runtime/services/provider-admin.mjs +306 -66
- package/src/session-runtime/services/seeds.mjs +73 -142
- package/src/session-runtime/services/usage-dashboard-model.mjs +29 -0
- package/src/session-runtime/services/usage-dashboard.mjs +7 -0
- package/src/session-runtime/session-address.mjs +125 -0
- package/src/session-runtime/session-create.mjs +57 -2
- package/src/session-runtime/settings-api.mjs +1 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +15 -10
- package/src/session-runtime/settings-compaction-api.mjs +13 -0
- package/src/session-runtime/setup-tool/executor.mjs +93 -40
- package/src/session-runtime/setup-tool/extended-actions.mjs +64 -5
- package/src/session-runtime/setup-tool/settings-contract.mjs +46 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +14 -6
- package/src/session-runtime/tool-surface.mjs +16 -9
- package/src/session-runtime/turn/session-ops.mjs +3 -0
- package/src/session-runtime/turn/share-ops.mjs +4 -1
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +6 -0
- package/src/session-runtime/usage-stats-api.mjs +43 -3
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +31 -5
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +6 -2
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +27 -7
- package/src/standalone/daemon-boot-coordinator.mjs +10 -0
- package/src/standalone/daemon-desktop-runtime.mjs +1 -0
- package/src/standalone/daemon-drain-policy.mjs +9 -0
- package/src/standalone/daemon-stored-session-views.mjs +7 -8
- package/src/standalone/daemon.mjs +36 -8
- package/src/standalone/local-session-runtime.mjs +11 -0
- package/src/standalone/session-client.mjs +52 -7
- package/src/standalone/session-protocol.mjs +9 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +2 -0
- package/src/standalone/session-service/entries/lifecycle.mjs +2 -0
- package/src/standalone/session-service/entries/session-loads.mjs +9 -0
- package/src/standalone/session-service/projection/revisions.mjs +28 -4
- package/src/standalone/session-service/projection.mjs +1 -0
- package/src/standalone/session-service/quota-resume.mjs +140 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +2 -2
- package/src/standalone/session-service/session-calls.mjs +10 -2
- package/src/standalone/session-service/stored-reader.mjs +26 -1
- package/src/standalone/session-service.mjs +21 -0
- package/src/standalone/session-transport/routes.mjs +2 -0
- package/src/tui/app/doctor.mjs +7 -11
- package/src/tui/app/maintenance-pickers/auto-clear-picker.mjs +3 -5
- package/src/tui/app/model-picker/model-footer.mjs +2 -2
- package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +21 -2
- package/src/tui/app/model-picker/route-selection.mjs +6 -1
- package/src/tui/app/settings-picker/settings-rows.mjs +4 -6
- package/src/tui/app/settings-picker/settings-toggles/store-toggles.mjs +1 -1
- package/src/tui/app/slash-commands.mjs +1 -1
- package/src/tui/app/slash-dispatch/route-commands.mjs +5 -3
- package/src/tui/app/transcript-row-estimate.mjs +17 -5
- package/src/tui/components/ContextPanel.jsx +5 -1
- package/src/tui/components/Spinner.jsx +34 -319
- package/src/tui/components/SpinnerByline.jsx +256 -0
- package/src/tui/components/tool-execution/aggregate-card.jsx +4 -2
- package/src/tui/components/tool-execution/text-format.mjs +1 -0
- package/src/tui/components/use-spinner-progress.mjs +113 -0
- package/src/tui/dist/index.mjs +15896 -14452
- package/src/tui/session/agent-job-feed/execution-delivery.mjs +13 -1
- package/src/tui/session/agent-job-feed/notification-router.mjs +3 -0
- package/src/tui/session/agent-job-feed/pending-resume.mjs +14 -1
- package/src/tui/session/agent-job-feed.mjs +4 -0
- package/src/tui/session/context-state.mjs +13 -1
- package/src/tui/session/initial-state.mjs +6 -0
- package/src/tui/session/quota-resume.mjs +263 -0
- package/src/tui/session/session-api/intake/abort.mjs +39 -35
- package/src/tui/session/session-api/intake/submission.mjs +13 -21
- package/src/tui/session/session-api/intake.mjs +3 -3
- package/src/tui/session/session-api/integrations.mjs +5 -1
- package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle/inheritance.mjs +2 -2
- package/src/tui/session/session-api/lifecycle/session-reset.mjs +4 -0
- package/src/tui/session/session-api/lifecycle.mjs +71 -2
- package/src/tui/session/session-api/media.mjs +2 -2
- package/src/tui/session/session-api/quota-resume.mjs +21 -0
- package/src/tui/session/session-api/routes.mjs +5 -2
- package/src/tui/session/session-api/settings.mjs +2 -0
- package/src/tui/session/session-api.mjs +2 -0
- package/src/tui/session/session-flow/auto-clear.mjs +14 -6
- package/src/tui/session/session-flow/drain.mjs +52 -5
- package/src/tui/session/session-flow/queue/take-entries.mjs +9 -4
- package/src/tui/session/session-flow/queue.mjs +4 -0
- package/src/tui/session/session-flow/steering.mjs +11 -0
- package/src/tui/session/session-flow.mjs +1 -0
- package/src/tui/session/tool-approval.mjs +7 -2
- package/src/tui/session/transcript-intake.mjs +1 -0
- package/src/tui/session/turn-tool-cards.mjs +4 -6
- package/src/tui/session/turn.mjs +40 -4
- package/src/vendor/statusline/bin/statusline-route.mjs +3 -2
- package/src/vendor/statusline/src/gateway/route-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-warmup.mjs +0 -165
|
@@ -15,9 +15,18 @@ import { boundProviderAuthPath } from '../../../shared/provider-auth-binding.mjs
|
|
|
15
15
|
import { resolvePluginData } from '../../../shared/plugin-paths.mjs';
|
|
16
16
|
import { getLlmDispatcher } from '../../../shared/llm/http-agent.mjs';
|
|
17
17
|
import { claudeCliUserAgent, resolveCliVersion } from './anthropic-oauth-client-version.mjs';
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
accountIdentityFields,
|
|
20
|
+
expiryFromAccessToken,
|
|
21
|
+
isDefinitiveOAuthFailure,
|
|
22
|
+
normalizeAccountIdentity,
|
|
23
|
+
oauthCredentialStatus,
|
|
24
|
+
scrubOAuthSecrets,
|
|
25
|
+
} from './lib/oauth-token-utils.mjs';
|
|
19
26
|
import { createOAuthPkce, parseOAuthCodeInput } from './lib/oauth-pkce.mjs';
|
|
20
27
|
|
|
28
|
+
const SIGN_IN_EXPIRED_PREFIX = 'Anthropic sign-in expired. Sign in again from Providers.';
|
|
29
|
+
|
|
21
30
|
// SSRF guard for the OAuth token endpoint override. Env-supplied URLs must be
|
|
22
31
|
// https with a valid http(s) URL shape; reject file:/data:/ftp:/etc. and any
|
|
23
32
|
// http override so a hostile env cannot redirect refresh-token requests.
|
|
@@ -88,15 +97,26 @@ function _loadCredentialsFile(path) {
|
|
|
88
97
|
mtimeMs: stat.mtimeMs,
|
|
89
98
|
accessToken: oauth.accessToken,
|
|
90
99
|
refreshToken: oauth.refreshToken || null,
|
|
100
|
+
reauthRequired: oauth.reauthRequired === true,
|
|
91
101
|
expiresAt: _normalizeExpiresAt(oauth.expiresAt ?? oauth.expires_at) || expiryFromAccessToken(oauth.accessToken),
|
|
92
102
|
scopes: Array.isArray(oauth.scopes) ? oauth.scopes : [],
|
|
93
103
|
subscriptionType: oauth.subscriptionType || null,
|
|
104
|
+
identity: normalizeAccountIdentity(oauth.identity),
|
|
94
105
|
};
|
|
95
106
|
} catch {
|
|
96
107
|
return null;
|
|
97
108
|
}
|
|
98
109
|
}
|
|
99
110
|
|
|
111
|
+
// The token endpoint names the signed-in account next to the tokens.
|
|
112
|
+
export function identityFromTokenResponse(json) {
|
|
113
|
+
return normalizeAccountIdentity({
|
|
114
|
+
id: json?.account?.uuid,
|
|
115
|
+
email: json?.account?.email_address,
|
|
116
|
+
organizationId: json?.organization?.uuid,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
100
120
|
// Cross-process safe credential save. Lockfile (O_EXCL) prevents two Mixdog
|
|
101
121
|
// refreshers from clobbering each other; atomic rename guarantees readers see
|
|
102
122
|
// either the old or new file, never a half-written one. Used so refresh_token
|
|
@@ -174,7 +194,21 @@ export function describeAnthropicOAuthCredentials() {
|
|
|
174
194
|
expiresAt,
|
|
175
195
|
};
|
|
176
196
|
}
|
|
177
|
-
|
|
197
|
+
if (creds.reauthRequired) {
|
|
198
|
+
return {
|
|
199
|
+
authenticated: false,
|
|
200
|
+
usable: false,
|
|
201
|
+
refreshable: false,
|
|
202
|
+
reauthRequired: true,
|
|
203
|
+
status: 'Reauth Required',
|
|
204
|
+
detail,
|
|
205
|
+
expiresAt,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
...oauthCredentialStatus({ hasRefresh, expiresAt, detail, refreshSkewMs: TOKEN_REFRESH_SKEW_MS }),
|
|
210
|
+
...accountIdentityFields(creds.identity),
|
|
211
|
+
};
|
|
178
212
|
} catch (err) {
|
|
179
213
|
return {
|
|
180
214
|
authenticated: false,
|
|
@@ -289,10 +323,14 @@ async function _refreshOAuthCredentialsUnlocked(creds) {
|
|
|
289
323
|
}
|
|
290
324
|
if (!res.ok) {
|
|
291
325
|
const isInvalidGrant = text.includes('invalid_grant') || json?.error === 'invalid_grant';
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
{
|
|
295
|
-
|
|
326
|
+
const failure = _tokenEndpointError('token refresh', res.status, text, [creds.refreshToken, creds.accessToken]);
|
|
327
|
+
if (isDefinitiveOAuthFailure(text, res.status)) {
|
|
328
|
+
throw Object.assign(new Error(`${SIGN_IN_EXPIRED_PREFIX} ${failure.message}`), {
|
|
329
|
+
isInvalidGrant: true,
|
|
330
|
+
reauthRequired: true,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
throw Object.assign(failure, { isInvalidGrant });
|
|
296
334
|
}
|
|
297
335
|
|
|
298
336
|
const accessToken = json?.access_token || json?.accessToken;
|
|
@@ -305,6 +343,7 @@ async function _refreshOAuthCredentialsUnlocked(creds) {
|
|
|
305
343
|
expiresAt,
|
|
306
344
|
scopes: Array.isArray(json?.scope) ? json.scope : creds.scopes,
|
|
307
345
|
subscriptionType: creds.subscriptionType,
|
|
346
|
+
identity: identityFromTokenResponse(json) || creds.identity || null,
|
|
308
347
|
};
|
|
309
348
|
// Persist rotated tokens back so any other Mixdog reader of the same
|
|
310
349
|
// credentials file picks up the new refresh_token. Without this, a
|
|
@@ -320,6 +359,8 @@ async function _refreshOAuthCredentialsUnlocked(creds) {
|
|
|
320
359
|
refreshToken: refreshed.refreshToken,
|
|
321
360
|
expiresAt: refreshed.expiresAt,
|
|
322
361
|
scopes: refreshed.scopes,
|
|
362
|
+
reauthRequired: undefined,
|
|
363
|
+
...(refreshed.identity ? { identity: refreshed.identity } : {}),
|
|
323
364
|
},
|
|
324
365
|
}));
|
|
325
366
|
} catch (err) {
|
|
@@ -364,7 +405,31 @@ export async function refreshOAuthCredentials(creds) {
|
|
|
364
405
|
) {
|
|
365
406
|
return disk;
|
|
366
407
|
}
|
|
367
|
-
|
|
408
|
+
const attempt = disk || { ...creds, path: credentialPath };
|
|
409
|
+
try {
|
|
410
|
+
return await _refreshOAuthCredentialsUnlocked(attempt);
|
|
411
|
+
} catch (err) {
|
|
412
|
+
if (err?.reauthRequired !== true) throw err;
|
|
413
|
+
const latest = _loadCredentialsFile(credentialPath);
|
|
414
|
+
if (latest?.refreshToken && latest.refreshToken !== attempt.refreshToken) {
|
|
415
|
+
if (!latest.expiresAt || latest.expiresAt > Date.now()) return latest;
|
|
416
|
+
return _refreshOAuthCredentialsUnlocked(latest);
|
|
417
|
+
}
|
|
418
|
+
try {
|
|
419
|
+
_updateCredentialsFile(credentialPath, (raw) => {
|
|
420
|
+
const oauth = raw?.claudeAiOauth;
|
|
421
|
+
if (!oauth || oauth.refreshToken !== attempt.refreshToken) return undefined;
|
|
422
|
+
// Non-destructive: tokens stay intact; a new sign-in or a
|
|
423
|
+
// successful refresh rewrites the entry without this marker.
|
|
424
|
+
return { ...raw, claudeAiOauth: { ...oauth, reauthRequired: true } };
|
|
425
|
+
});
|
|
426
|
+
} catch (saveErr) {
|
|
427
|
+
process.stderr.write(
|
|
428
|
+
`[anthropic-oauth] dead-account mark failed: ${_scrubTokens(saveErr?.message || String(saveErr)).slice(0, 200)}\n`
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
throw err;
|
|
432
|
+
}
|
|
368
433
|
},
|
|
369
434
|
{
|
|
370
435
|
timeoutMs: 120_000,
|
|
@@ -536,6 +601,7 @@ async function exchangeAuthorizationCode({ pkce, code, state, redirectUri }) {
|
|
|
536
601
|
}
|
|
537
602
|
const expiresAt = expiresAtFromTokenResponse(json);
|
|
538
603
|
const scopes = _oauthParseScopeField(json?.scope);
|
|
604
|
+
const identity = identityFromTokenResponse(json);
|
|
539
605
|
const credPath = _oauthCredentialsWritePath();
|
|
540
606
|
const raw = _updateCredentialsFile(credPath, (current) => {
|
|
541
607
|
const base = current && typeof current === 'object' ? current : {};
|
|
@@ -548,7 +614,10 @@ async function exchangeAuthorizationCode({ pkce, code, state, redirectUri }) {
|
|
|
548
614
|
refreshToken,
|
|
549
615
|
expiresAt,
|
|
550
616
|
scopes,
|
|
617
|
+
reauthRequired: undefined,
|
|
551
618
|
subscriptionType: existingOauth.subscriptionType ?? null,
|
|
619
|
+
// A fresh sign-in replaces the account: never keep the previous identity.
|
|
620
|
+
identity: identity || undefined,
|
|
552
621
|
},
|
|
553
622
|
};
|
|
554
623
|
});
|
|
@@ -559,10 +628,11 @@ async function exchangeAuthorizationCode({ pkce, code, state, redirectUri }) {
|
|
|
559
628
|
expiresAt,
|
|
560
629
|
scopes,
|
|
561
630
|
subscriptionType: raw.claudeAiOauth.subscriptionType,
|
|
631
|
+
identity,
|
|
562
632
|
};
|
|
563
633
|
}
|
|
564
634
|
|
|
565
|
-
export async function beginOAuthLogin({ openBrowserFn = null } = {}) {
|
|
635
|
+
export async function beginOAuthLogin({ openBrowserFn = null, openBrowser = true } = {}) {
|
|
566
636
|
const pkce = createOAuthPkce();
|
|
567
637
|
const state = randomBytes(32).toString('base64url');
|
|
568
638
|
const buildUrl = (redirectUri) => {
|
|
@@ -580,6 +650,7 @@ export async function beginOAuthLogin({ openBrowserFn = null } = {}) {
|
|
|
580
650
|
const url = buildUrl(OAUTH_REDIRECT_URI);
|
|
581
651
|
const manualUrl = buildUrl(OAUTH_MANUAL_REDIRECT_URI);
|
|
582
652
|
const openLoginUrl = async (targetUrl, label = 'login') => {
|
|
653
|
+
if (!openBrowser) return;
|
|
583
654
|
try {
|
|
584
655
|
const openInBrowser = openBrowserFn || (await import('../../../shared/open-url.mjs')).openInBrowser;
|
|
585
656
|
await openInBrowser(targetUrl.toString());
|
|
@@ -62,6 +62,8 @@ import {
|
|
|
62
62
|
} from './lib/anthropic-request-utils.mjs';
|
|
63
63
|
import {
|
|
64
64
|
EFFORT_CONFIGURATION_BETA,
|
|
65
|
+
isEffortConfigurationRejection,
|
|
66
|
+
markEffortConfigurationUnsupported,
|
|
65
67
|
projectEffortConfiguration,
|
|
66
68
|
lowerAnthropicEffortHistory,
|
|
67
69
|
markAnthropicEffortBody,
|
|
@@ -293,7 +295,9 @@ export class AnthropicOAuthProvider {
|
|
|
293
295
|
this.credentials = loadCredentials();
|
|
294
296
|
}
|
|
295
297
|
if (!this.credentials) {
|
|
296
|
-
throw new Error('Anthropic OAuth credentials not found. Open /providers in mixdog to sign in.')
|
|
298
|
+
throw Object.assign(new Error('Anthropic OAuth credentials not found. Open /providers in mixdog to sign in.'), {
|
|
299
|
+
reauthRequired: true,
|
|
300
|
+
});
|
|
297
301
|
}
|
|
298
302
|
|
|
299
303
|
// Pick up Mixdog-updated tokens the moment the credentials file is
|
|
@@ -359,12 +363,20 @@ export class AnthropicOAuthProvider {
|
|
|
359
363
|
return latest;
|
|
360
364
|
}
|
|
361
365
|
|
|
362
|
-
if (!latest?.refreshToken) {
|
|
366
|
+
if (!latest?.refreshToken || latest.reauthRequired) {
|
|
363
367
|
if (!force && latest?.accessToken && (!latest.expiresAt || latest.expiresAt > Date.now())) {
|
|
364
|
-
logQuiet('WARNING: token expiring but no refresh token; using current token until expiry');
|
|
368
|
+
logQuiet('WARNING: token expiring but no usable refresh token; using current token until expiry');
|
|
365
369
|
return latest;
|
|
366
370
|
}
|
|
367
|
-
|
|
371
|
+
if (latest?.reauthRequired) {
|
|
372
|
+
throw Object.assign(new Error('Anthropic sign-in expired. Sign in again from Providers.'), {
|
|
373
|
+
reauthRequired: true,
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
throw Object.assign(
|
|
377
|
+
new Error('Anthropic OAuth refresh token not available. Open /providers in mixdog to sign in again.'),
|
|
378
|
+
{ reauthRequired: true }
|
|
379
|
+
);
|
|
368
380
|
}
|
|
369
381
|
|
|
370
382
|
try {
|
|
@@ -608,6 +620,19 @@ export class AnthropicOAuthProvider {
|
|
|
608
620
|
throw anthropicQuotaError(response.status, response.headers, safeText);
|
|
609
621
|
}
|
|
610
622
|
|
|
623
|
+
// A newer model that rejects the mid-conversation effort update: switch
|
|
624
|
+
// the updates off for it in this process and replay the turn once
|
|
625
|
+
// without them (the request keeps its turn effort).
|
|
626
|
+
if (isEffortConfigurationRejection(response.status, scrubbedText) && !opts._effortConfigurationRetry) {
|
|
627
|
+
markEffortConfigurationUnsupported('anthropic-oauth', useModel);
|
|
628
|
+
process.stderr.write(`[anthropic-oauth] ${useModel} rejected the mid-conversation effort update; retrying once without it\n`);
|
|
629
|
+
return this.send(messages, useModel, tools, {
|
|
630
|
+
...opts,
|
|
631
|
+
effortConfigurationEnabled: false,
|
|
632
|
+
_effortConfigurationRetry: true,
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
|
|
611
636
|
// Anthropic can gate a newly launched model on a newer Claude
|
|
612
637
|
// Code client identity. Learn only the exact minimum-version
|
|
613
638
|
// rejection, persist the raised floor, and replay this untouched
|
|
@@ -71,6 +71,9 @@ export function createAnthropicSseTurn({
|
|
|
71
71
|
...events,
|
|
72
72
|
// Stream ended: flush any held-back leaked-tool-call buffer.
|
|
73
73
|
flushLeak: leak.flush,
|
|
74
|
+
// Usage the provider reported so far, in the success result's shape (a
|
|
75
|
+
// cancelled turn hands it to its send's accounting).
|
|
76
|
+
reportedUsage: () => ({ usage: turn.usage, model: turn.model || undefined }),
|
|
74
77
|
...outcome,
|
|
75
78
|
};
|
|
76
79
|
}
|
|
@@ -16,6 +16,7 @@ import { OAUTH_STREAM_LABELS } from './lib/anthropic-stream-labels.mjs';
|
|
|
16
16
|
import { stampStreamOutcome, STREAM_TRANSPORTS, STREAM_OUTCOME_VERSION } from './lib/stream-outcome.mjs';
|
|
17
17
|
import { createAnthropicSseTurn } from './anthropic-sse-turn.mjs';
|
|
18
18
|
import { createAnthropicSseWatchdogs } from './anthropic-sse-watchdogs.mjs';
|
|
19
|
+
import { noteAbandonedUsage } from '../../../shared/llm/usage-context.mjs';
|
|
19
20
|
|
|
20
21
|
/** Bounded mid-stream SSE retries (transient stream loss); shared with anthropic.mjs.
|
|
21
22
|
* Sourced from the single shared retry-budget table (MIDSTREAM_RETRY_POLICY.sse). */
|
|
@@ -234,7 +235,15 @@ export async function parseSSEStream(
|
|
|
234
235
|
chunk = await watchdogs.read();
|
|
235
236
|
} catch (err) {
|
|
236
237
|
const stopped = watchdogs.readFailure() ?? (signal?.aborted ? abortedError() : null);
|
|
237
|
-
if (stopped)
|
|
238
|
+
if (stopped) {
|
|
239
|
+
// The caller's cancellation reason may be shared: never stamp this
|
|
240
|
+
// request's usage on it; the usage reported so far goes to this send.
|
|
241
|
+
if (signal?.aborted && state?.sawMessageStart) {
|
|
242
|
+
const reported = turn.reportedUsage();
|
|
243
|
+
noteAbandonedUsage(reported.usage, reported.model);
|
|
244
|
+
}
|
|
245
|
+
throw stopped;
|
|
246
|
+
}
|
|
238
247
|
// The connection dropped mid-body: carry what this turn completed so
|
|
239
248
|
// the loop can continue from finished tool calls instead of failing.
|
|
240
249
|
throw state?.sawMessageStart ? turn.attachTransportPartial(err) : err;
|
|
@@ -7,6 +7,7 @@ import { createAbortController } from '../../../shared/abort-controller.mjs';
|
|
|
7
7
|
import { ANTHROPIC_MAX_MIDSTREAM_RETRIES, parseSSEStream } from './anthropic-sse.mjs';
|
|
8
8
|
import { buildAnthropicBetaHeaders } from './anthropic-betas.mjs';
|
|
9
9
|
import { buildAnthropicApiRequest } from './anthropic-api-request.mjs';
|
|
10
|
+
import { isCustomProviderName } from './custom-reasoning.mjs';
|
|
10
11
|
import { armFirstByteWatchdog, createAnthropicApiTransport } from './anthropic-api-transport.mjs';
|
|
11
12
|
import { createAnthropicApiRecovery } from './anthropic-api-recovery.mjs';
|
|
12
13
|
import { buildAnthropicTurnResult } from './anthropic-turn-result.mjs';
|
|
@@ -47,12 +48,18 @@ export class AnthropicProvider {
|
|
|
47
48
|
// off the client defaults and add it only on turns that actually serialize
|
|
48
49
|
// defer_loading tools.
|
|
49
50
|
_createClient(apiKey) {
|
|
50
|
-
|
|
51
|
+
// A custom gateway gets no first-party default betas and only its own
|
|
52
|
+
// credential: never the SDK's env/credential-file fallbacks, and none at
|
|
53
|
+
// all when keyless (config.keyless).
|
|
54
|
+
const custom = isCustomProviderName(this.name);
|
|
55
|
+
const keyless = custom && this.config.keyless === true;
|
|
56
|
+
const betaHeaders = this.config.disableBetaHeaders || custom ? null : buildAnthropicBetaHeaders();
|
|
51
57
|
return new (loadAnthropic())({
|
|
52
|
-
apiKey,
|
|
58
|
+
...(custom ? { apiKey: keyless ? '' : apiKey || '', authToken: null } : { apiKey }),
|
|
53
59
|
...(this.config.baseURL ? { baseURL: this.config.baseURL } : {}),
|
|
54
60
|
defaultHeaders: {
|
|
55
61
|
...(betaHeaders ? { 'anthropic-beta': betaHeaders } : {}),
|
|
62
|
+
...(keyless ? { 'x-api-key': null, authorization: null } : {}),
|
|
56
63
|
...(this.config.extraHeaders || {}),
|
|
57
64
|
},
|
|
58
65
|
maxRetries: 0,
|
|
@@ -114,6 +121,8 @@ export class AnthropicProvider {
|
|
|
114
121
|
tools,
|
|
115
122
|
opts,
|
|
116
123
|
fastModeLatched: this.fastModeBetaHeaderLatched,
|
|
124
|
+
// Custom providers carry per-model reasoning settings on their own rows.
|
|
125
|
+
modelInfo: isCustomProviderName(this.name) ? this.getCachedModelInfo?.(useModel) || null : null,
|
|
117
126
|
});
|
|
118
127
|
this.fastModeBetaHeaderLatched = fastModeLatched;
|
|
119
128
|
|
|
@@ -103,19 +103,20 @@ async function requestCodeAssist(action, body, context, timeoutMs = PROJECT_TIME
|
|
|
103
103
|
return payload;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
// The userinfo response carries the Google account's email and stable user id.
|
|
107
|
+
async function fetchAccountInfo(accessToken, { fetchFn = fetch, signal = null } = {}) {
|
|
107
108
|
try {
|
|
108
109
|
const res = await fetchFn(USERINFO_URL, {
|
|
109
110
|
headers: { Authorization: `Bearer ${accessToken}` },
|
|
110
111
|
redirect: 'error',
|
|
111
112
|
signal: withTimeoutSignal(signal, TOKEN_TIMEOUT_MS),
|
|
112
113
|
});
|
|
113
|
-
if (!res.ok) return '';
|
|
114
|
+
if (!res.ok) return { email: '', userId: '' };
|
|
114
115
|
const json = await res.json();
|
|
115
|
-
return String(json?.email || '');
|
|
116
|
+
return { email: String(json?.email || ''), userId: String(json?.id || json?.sub || '') };
|
|
116
117
|
} catch {
|
|
117
118
|
signal?.throwIfAborted();
|
|
118
|
-
return '';
|
|
119
|
+
return { email: '', userId: '' };
|
|
119
120
|
}
|
|
120
121
|
}
|
|
121
122
|
|
|
@@ -266,7 +267,7 @@ export async function exchangeAuthorizationCode({ code, verifier, fetchFn = fetc
|
|
|
266
267
|
if (!json?.access_token || !json?.refresh_token) {
|
|
267
268
|
throw new Error('[antigravity-oauth] token exchange response missing access_token or refresh_token');
|
|
268
269
|
}
|
|
269
|
-
const email = await
|
|
270
|
+
const { email, userId } = await fetchAccountInfo(json.access_token, { fetchFn, signal });
|
|
270
271
|
const projectId = await discoverProject(json.access_token, { fetchFn, onProgress, signal, email });
|
|
271
272
|
const tokens = {
|
|
272
273
|
access_token: json.access_token,
|
|
@@ -274,6 +275,7 @@ export async function exchangeAuthorizationCode({ code, verifier, fetchFn = fetc
|
|
|
274
275
|
expires_at: typeof json.expires_in === 'number' ? Date.now() + json.expires_in * 1000 : 0,
|
|
275
276
|
project_id: projectId,
|
|
276
277
|
email,
|
|
278
|
+
user_id: userId,
|
|
277
279
|
};
|
|
278
280
|
signal?.throwIfAborted();
|
|
279
281
|
saveTokens(tokens);
|
|
@@ -285,6 +287,7 @@ export async function beginOAuthLogin({
|
|
|
285
287
|
onProgress = null,
|
|
286
288
|
createServerFn = createServer,
|
|
287
289
|
openBrowserFn = null,
|
|
290
|
+
openBrowser = true,
|
|
288
291
|
} = {}) {
|
|
289
292
|
const controller = new AbortController();
|
|
290
293
|
const pkce = createOAuthPkce();
|
|
@@ -396,6 +399,7 @@ export async function beginOAuthLogin({
|
|
|
396
399
|
server.listen(CALLBACK_PORT, CALLBACK_HOST, async () => {
|
|
397
400
|
if (settled) return;
|
|
398
401
|
process.stderr.write(`\n[antigravity-oauth] Open this URL to log in:\n${url.toString()}\n\n`);
|
|
402
|
+
if (!openBrowser) return;
|
|
399
403
|
try {
|
|
400
404
|
if (openBrowserFn) await openBrowserFn(url.toString());
|
|
401
405
|
else {
|
|
@@ -18,7 +18,11 @@ import { join, resolve } from 'node:path';
|
|
|
18
18
|
import { getPluginData } from '../config.mjs';
|
|
19
19
|
import { writeJsonAtomicSync } from '../../../shared/atomic-file.mjs';
|
|
20
20
|
import { boundProviderAuthPath } from '../../../shared/provider-auth-binding.mjs';
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
accountIdentityFields,
|
|
23
|
+
normalizeExpiresAtMs as _normalizeExpiresAt,
|
|
24
|
+
scrubOAuthSecrets,
|
|
25
|
+
} from './lib/oauth-token-utils.mjs';
|
|
22
26
|
import { ANTIGRAVITY_MODELS } from '../../../shared/llm/provider-model-identities.mjs';
|
|
23
27
|
import { readLastKnownVersion, rememberLastKnownVersion } from './client-version-store.mjs';
|
|
24
28
|
import { maxSemver } from './npm-cli-version.mjs';
|
|
@@ -199,6 +203,7 @@ export function loadTokens() {
|
|
|
199
203
|
expires_at: _normalizeExpiresAt(raw.expires_at ?? raw.expiresAt),
|
|
200
204
|
project_id: String(raw.project_id || raw.projectId || ''),
|
|
201
205
|
email: String(raw.email || ''),
|
|
206
|
+
user_id: String(raw.user_id || raw.userId || ''),
|
|
202
207
|
source: 'own',
|
|
203
208
|
mtimeMs: mtimeMs(path),
|
|
204
209
|
};
|
|
@@ -216,6 +221,7 @@ export function saveTokens(tokens) {
|
|
|
216
221
|
expires_at: tokens.expires_at || 0,
|
|
217
222
|
project_id: tokens.project_id || tokens.projectId || '',
|
|
218
223
|
email: tokens.email || '',
|
|
224
|
+
user_id: tokens.user_id || tokens.userId || '',
|
|
219
225
|
},
|
|
220
226
|
{ lock: true, fsyncDir: true, mode: 0o600, secret: true }
|
|
221
227
|
);
|
|
@@ -263,6 +269,7 @@ export function describeAntigravityOAuthCredentials() {
|
|
|
263
269
|
reauthRequired: !usable,
|
|
264
270
|
status: usable ? 'Signed In' : 'Reauth Required',
|
|
265
271
|
detail,
|
|
272
|
+
...accountIdentityFields({ id: tokens.user_id, email: tokens.email }),
|
|
266
273
|
email: tokens.email || '',
|
|
267
274
|
projectId: tokens.project_id || '',
|
|
268
275
|
};
|
|
@@ -332,6 +339,7 @@ export function refreshTokens({ fetchFn = fetch } = {}) {
|
|
|
332
339
|
expires_at: typeof json.expires_in === 'number' ? Date.now() + json.expires_in * 1000 : 0,
|
|
333
340
|
project_id: current.project_id,
|
|
334
341
|
email: current.email,
|
|
342
|
+
user_id: current.user_id,
|
|
335
343
|
};
|
|
336
344
|
saveTokens(next);
|
|
337
345
|
return next;
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* Auth, endpoints, and headers live in antigravity-oauth-tokens.mjs.
|
|
13
13
|
*/
|
|
14
14
|
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
15
|
+
import { noteErrorUsage } from './lib/note-error-usage.mjs';
|
|
15
16
|
import { join } from 'node:path';
|
|
16
17
|
import { buildAntigravityRequest, isAntigravityClaude as isClaudeModel } from './antigravity-request.mjs';
|
|
17
18
|
import { createPassthroughSignal } from '../stall-policy.mjs';
|
|
@@ -167,6 +168,7 @@ export class AntigravityOAuthProvider {
|
|
|
167
168
|
response = await requestOnce();
|
|
168
169
|
} catch (err) {
|
|
169
170
|
lastErr = err;
|
|
171
|
+
noteErrorUsage(err);
|
|
170
172
|
const status = Number(err?.status || err?.httpStatus || 0);
|
|
171
173
|
const emitted = err?.unsafeToRetry === true || err?.liveTextEmitted === true || err?.emittedToolCall === true;
|
|
172
174
|
// A typed 401 says THIS access token is no longer accepted.
|
|
@@ -10,6 +10,17 @@ import { traceAgentUsage } from '../agent-trace.mjs';
|
|
|
10
10
|
import { createProviderReplay } from './lib/provider-replay.mjs';
|
|
11
11
|
import { parseToolCalls, collectGeminiGroundingSources, parseGeminiTextPartMetadata } from './gemini-schema.mjs';
|
|
12
12
|
|
|
13
|
+
// Pure usageMetadata normalization shared by the success path and a failed
|
|
14
|
+
// stream's partialUsage.
|
|
15
|
+
export function normalizeAntigravityUsage(um) {
|
|
16
|
+
const inputTokens = um.promptTokenCount || um.prompt_token_count || 0;
|
|
17
|
+
const cachedTokens = um.cachedContentTokenCount || um.cached_content_token_count || 0;
|
|
18
|
+
const outputTokens =
|
|
19
|
+
(um.candidatesTokenCount || um.candidates_token_count || 0) +
|
|
20
|
+
(um.thoughtsTokenCount || um.thoughts_token_count || 0);
|
|
21
|
+
return { inputTokens, outputTokens, cachedTokens, promptTokens: inputTokens, raw: um };
|
|
22
|
+
}
|
|
23
|
+
|
|
13
24
|
/**
|
|
14
25
|
* @param {object} deps
|
|
15
26
|
* @param {object} deps.response final unwrapped Gemini-shaped payload
|
|
@@ -48,31 +59,11 @@ export function finalizeAntigravityTurn({ response, collector, useModel, opts, o
|
|
|
48
59
|
const finishReason =
|
|
49
60
|
collector.terminalFailure || candidate?.finishReason || (promptBlockReason ? `PROMPT_${promptBlockReason}` : null);
|
|
50
61
|
const normalizedFinish = String(finishReason || '').replace(/^FINISH_REASON_/, '');
|
|
51
|
-
if (finishReason && normalizedFinish !== 'STOP') {
|
|
52
|
-
throw Object.assign(new Error(`Antigravity response incomplete: finishReason=${finishReason}`), {
|
|
53
|
-
name: 'ProviderIncompleteError',
|
|
54
|
-
code: 'PROVIDER_INCOMPLETE',
|
|
55
|
-
providerIncomplete: true,
|
|
56
|
-
finishReason,
|
|
57
|
-
partialContent: content,
|
|
58
|
-
partialToolCalls: toolCalls,
|
|
59
|
-
partialProviderReplay: providerReplay,
|
|
60
|
-
providerMetadata,
|
|
61
|
-
model: useModel,
|
|
62
|
-
rawUsage: response.usageMetadata || null,
|
|
63
|
-
...(collector.emittedToolCount ? { emittedToolCall: true, unsafeToRetry: true } : {}),
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
|
|
67
62
|
const um = response.usageMetadata || null;
|
|
68
63
|
let usage;
|
|
69
64
|
if (um) {
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
const outputTokens =
|
|
73
|
-
(um.candidatesTokenCount || um.candidates_token_count || 0) +
|
|
74
|
-
(um.thoughtsTokenCount || um.thoughts_token_count || 0);
|
|
75
|
-
usage = { inputTokens, outputTokens, cachedTokens, promptTokens: inputTokens, raw: um };
|
|
65
|
+
usage = normalizeAntigravityUsage(um);
|
|
66
|
+
const { inputTokens, outputTokens, cachedTokens } = usage;
|
|
76
67
|
traceAgentUsage({
|
|
77
68
|
sessionId: opts.sessionId || opts.session?.id || null,
|
|
78
69
|
iteration: Number.isFinite(Number(opts.iteration)) ? Number(opts.iteration) : null,
|
|
@@ -88,6 +79,23 @@ export function finalizeAntigravityTurn({ response, collector, useModel, opts, o
|
|
|
88
79
|
});
|
|
89
80
|
}
|
|
90
81
|
|
|
82
|
+
if (finishReason && normalizedFinish !== 'STOP') {
|
|
83
|
+
throw Object.assign(new Error(`Antigravity response incomplete: finishReason=${finishReason}`), {
|
|
84
|
+
name: 'ProviderIncompleteError',
|
|
85
|
+
code: 'PROVIDER_INCOMPLETE',
|
|
86
|
+
providerIncomplete: true,
|
|
87
|
+
finishReason,
|
|
88
|
+
partialContent: content,
|
|
89
|
+
partialToolCalls: toolCalls,
|
|
90
|
+
partialProviderReplay: providerReplay,
|
|
91
|
+
providerMetadata,
|
|
92
|
+
model: useModel,
|
|
93
|
+
rawUsage: response.usageMetadata || null,
|
|
94
|
+
...(usage ? { partialUsage: usage, partialModel: useModel } : {}),
|
|
95
|
+
...(collector.emittedToolCount ? { emittedToolCall: true, unsafeToRetry: true } : {}),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
91
99
|
return {
|
|
92
100
|
content,
|
|
93
101
|
model: useModel,
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { createProviderReplay } from './lib/provider-replay.mjs';
|
|
14
14
|
import { createGeminiTextLeakGuard, consumeGeminiRestStreamResponse } from './gemini-stream.mjs';
|
|
15
15
|
import { parseToolCalls, emitGeminiToolCalls } from './gemini-schema.mjs';
|
|
16
|
+
import { normalizeAntigravityUsage } from './antigravity-response.mjs';
|
|
16
17
|
|
|
17
18
|
// A retired wire id answers with one plain-text notice and no finishReason.
|
|
18
19
|
// That is a terminal answer about the model, not a truncated stream.
|
|
@@ -118,6 +119,7 @@ export function createAntigravityStreamCollector({ tools, useModel, onToolCall,
|
|
|
118
119
|
onChunk,
|
|
119
120
|
textLeakGuard,
|
|
120
121
|
label: 'Antigravity streamGenerateContent',
|
|
122
|
+
failureUsage: { model: useModel, normalize: normalizeAntigravityUsage },
|
|
121
123
|
// Cloud Code Assist nests the Gemini payload under
|
|
122
124
|
// `response`; in-band error events stay top level.
|
|
123
125
|
unwrapChunk: (chunk) => (chunk && typeof chunk === 'object' && chunk.response ? chunk.response : chunk),
|
|
@@ -25,18 +25,36 @@ export function autoEffortBase(chosen) {
|
|
|
25
25
|
|
|
26
26
|
export const AUTO_EFFORT_MODES = Object.freeze(['off', 'observe', 'on']);
|
|
27
27
|
|
|
28
|
-
// Below this top-class probability the judge is unsure and the default stays.
|
|
29
|
-
export const AUTO_EFFORT_MIN_CONFIDENCE = 0.4;
|
|
30
|
-
// xhigh costs far more than high, so "very hard" needs a firmer judge;
|
|
31
|
-
// below this it is treated as "hard". 0.65 minimised the eval cost with a
|
|
32
|
-
// false xhigh weighted three times a missed one.
|
|
33
|
-
export const AUTO_EFFORT_VERY_HARD_CONFIDENCE = 0.65;
|
|
34
|
-
|
|
35
28
|
// The judge rates four levels, each one ladder step from the base: easy -1
|
|
36
29
|
// (low), normal 0 (medium), hard +1 (high), very hard +2 (xhigh).
|
|
37
30
|
export const AUTO_EFFORT_LEVELS = Object.freeze(['easy', 'normal', 'hard', 'very hard']);
|
|
38
31
|
const STEP_OF_LEVEL = [-1, 0, 1, 2];
|
|
39
32
|
|
|
33
|
+
// The chosen level minimises the expected cost under the judge distribution.
|
|
34
|
+
// A miss costs one per level, plus extra for an opposite call and for a
|
|
35
|
+
// needless "very hard" (xhigh). Opposite calls are asymmetric: "easy" for a
|
|
36
|
+
// hard turn degrades the answer, "hard" for an easy turn only costs tokens.
|
|
37
|
+
// On the held-out test splits the heavier under-call cost cut hard-as-easy
|
|
38
|
+
// calls by a third (20 -> 13 of 7,180) for -0.2 points of exact accuracy.
|
|
39
|
+
export const AUTO_EFFORT_UNDER_OPPOSITE_COST = 3;
|
|
40
|
+
export const AUTO_EFFORT_OVER_OPPOSITE_COST = 1;
|
|
41
|
+
export const AUTO_EFFORT_FALSE_VERY_HARD_COST = 1;
|
|
42
|
+
// Ties keep the default first, then the cheaper side.
|
|
43
|
+
const TIE_ORDER = [1, 0, 2, 3];
|
|
44
|
+
|
|
45
|
+
function expectedCost(values, level) {
|
|
46
|
+
let cost = 0;
|
|
47
|
+
values.forEach((p, actual) => {
|
|
48
|
+
cost +=
|
|
49
|
+
p *
|
|
50
|
+
(Math.abs(level - actual) +
|
|
51
|
+
(level === 0 && actual >= 2 ? AUTO_EFFORT_UNDER_OPPOSITE_COST : 0) +
|
|
52
|
+
(actual === 0 && level >= 2 ? AUTO_EFFORT_OVER_OPPOSITE_COST : 0) +
|
|
53
|
+
(level === 3 && actual < 3 ? AUTO_EFFORT_FALSE_VERY_HARD_COST : 0));
|
|
54
|
+
});
|
|
55
|
+
return cost;
|
|
56
|
+
}
|
|
57
|
+
|
|
40
58
|
export function normalizeAutoEffortMode(value) {
|
|
41
59
|
const mode = String(value ?? '')
|
|
42
60
|
.trim()
|
|
@@ -57,9 +75,9 @@ export function judgedStep(probs) {
|
|
|
57
75
|
const values = Array.isArray(probs) && probs.length === AUTO_EFFORT_LEVELS.length ? probs.map(Number) : null;
|
|
58
76
|
if (!values || values.some((value) => !Number.isFinite(value))) return { step: 0, level: null, confidence: 0 };
|
|
59
77
|
const confidence = Math.max(...values);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
78
|
+
let level = TIE_ORDER[0];
|
|
79
|
+
for (const candidate of TIE_ORDER)
|
|
80
|
+
if (expectedCost(values, candidate) < expectedCost(values, level) - 1e-12) level = candidate;
|
|
63
81
|
return { step: STEP_OF_LEVEL[level], level, confidence };
|
|
64
82
|
}
|
|
65
83
|
|