mixdog 1.2.0 → 1.2.2
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 +7 -5
- package/package.json +1 -1
- package/scripts/gate-local.mjs +19 -3
- package/scripts/model-catalog-audit.mjs +1 -15
- package/src/agents/reviewer/AGENT.md +3 -3
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +5 -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 +13 -3
- package/src/defaults/skills/visualize/SKILL.md +12 -9
- package/src/repl/slash-commands.mjs +16 -1
- 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-progress-watchdog.mjs +29 -4
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
- package/src/runtime/agent/orchestrator/config.mjs +10 -4
- 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 +122 -15
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +54 -11
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +104 -9
- package/src/runtime/agent/orchestrator/mcp/client.mjs +358 -140
- package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +103 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +150 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +111 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +87 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +95 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-request.mjs +122 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +9 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +229 -0
- package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +294 -44
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +96 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +39 -18
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +55 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +25 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +18 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +13 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-midstream.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-recovery.mjs +23 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +46 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request.mjs +14 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +73 -35
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +69 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +8 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +53 -18
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +30 -9
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +30 -14
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +82 -9
- 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 +447 -0
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +38 -5
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +97 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +102 -23
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +29 -6
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +18 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +86 -19
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +29 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +191 -0
- package/src/runtime/agent/orchestrator/providers/gemini-family.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/gemini-history-signatures.mjs +9 -4
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +180 -0
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +21 -82
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -12
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +21 -20
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +97 -51
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +68 -19
- package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +15 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +35 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +22 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +50 -0
- 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-response-normalization.mjs +23 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +94 -13
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +193 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +66 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +23 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +26 -6
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +42 -25
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +274 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +72 -32
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +2 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +1 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +34 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +5 -9
- package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +25 -14
- package/src/runtime/agent/orchestrator/providers/openai-ws-terminal.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +35 -24
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +581 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +35 -9
- package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +118 -219
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +148 -45
- package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +81 -16
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +3 -0
- 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/goal-reminder.mjs +0 -18
- package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +57 -28
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +19 -16
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +268 -181
- 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/session/catalog-db/index.mjs +284 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +270 -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/messages.mjs +6 -2
- 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.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -4
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +102 -18
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +42 -5
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +14 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +20 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +50 -23
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +22 -14
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
- package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +155 -29
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +22 -10
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +819 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +22 -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 +183 -374
- 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 +41 -3
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +38 -17
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
- 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/builtin-tools.mjs +5 -5
- 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-range-index.mjs +173 -22
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +15 -2
- 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/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/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/shell-snapshot.mjs +4 -0
- package/src/runtime/attachments/store.d.mts +3 -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/pg/process.mjs +34 -24
- package/src/runtime/memory/lib/pg/supervisor.mjs +16 -13
- package/src/runtime/memory/lib/session-ingest.mjs +2 -2
- package/src/runtime/office/README.md +1 -1
- package/src/runtime/office/shared/values.mjs +0 -5
- package/src/runtime/shared/atomic-file.mjs +25 -4
- package/src/runtime/shared/background-tasks.mjs +92 -14
- package/src/runtime/shared/err-text.mjs +25 -0
- package/src/runtime/shared/error-presentation.mjs +159 -19
- package/src/runtime/shared/extension-scopes.mjs +5 -3
- package/src/runtime/shared/file-lock.mjs +37 -11
- package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +134 -131
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
- package/src/runtime/shared/llm/model-catalog.mjs +53 -52
- package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +17 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
- package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
- package/src/runtime/shared/model-display.mjs +13 -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 +124 -20
- package/src/runtime/shared/provider-api-key.mjs +12 -0
- package/src/runtime/shared/quota-resume-store.mjs +11 -0
- package/src/runtime/shared/session-baseline-store.mjs +960 -0
- package/src/runtime/shared/shell-display.mjs +9 -3
- 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-format.mjs +4 -4
- package/src/runtime/shared/task-notification-envelope.mjs +2 -2
- package/src/runtime/shared/tool-primitives.mjs +35 -2
- package/src/runtime/shared/turn-changes.mjs +447 -219
- package/src/runtime/shared/turn-snapshot-store.mjs +182 -1
- package/src/runtime/shared/turn-snapshot.mjs +170 -48
- package/src/runtime/shared/turn-worktree-snapshot.mjs +160 -51
- package/src/runtime/shared/worker-requests.mjs +15 -2
- package/src/runtime/shared/worktrees/contract.mjs +0 -24
- package/src/runtime/shared/worktrees/test-support.mjs +19 -4
- package/src/session-runtime/automation-agents.mjs +8 -2
- package/src/session-runtime/boot/apis.mjs +61 -0
- package/src/session-runtime/boot/config.mjs +5 -2
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +35 -18
- 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 +10 -5
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
- package/src/session-runtime/lifecycle/session-catalog.mjs +2 -0
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/mcp-glue/connect.mjs +83 -16
- package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +135 -33
- package/src/session-runtime/mcp-glue.mjs +25 -2
- package/src/session-runtime/mcp-oauth-login.mjs +174 -0
- package/src/session-runtime/model-route/model-switch-target.mjs +34 -0
- package/src/session-runtime/model-route/set-route.mjs +83 -15
- package/src/session-runtime/model-route/web-search-route.mjs +1 -1
- package/src/session-runtime/native-web-search/routes.mjs +22 -3
- package/src/session-runtime/new-session-config.mjs +3 -2
- package/src/session-runtime/notification-bus.mjs +9 -2
- package/src/session-runtime/provider-auth/accounts.mjs +33 -15
- package/src/session-runtime/provider-models/model-meta.mjs +12 -3
- 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/quick-model-rows/web-search-rows.mjs +13 -8
- package/src/session-runtime/quick-web-search-models.mjs +13 -38
- package/src/session-runtime/resource-extension-sync.mjs +24 -5
- package/src/session-runtime/resource-mcp-api.mjs +198 -78
- 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/runtime-review-api.mjs +13 -0
- package/src/session-runtime/schedule-session-run.mjs +1 -1
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +13 -1
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +7 -2
- package/src/session-runtime/services/agent-tool/send-flow.mjs +22 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +2 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +22 -5
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -2
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +17 -0
- package/src/session-runtime/services/channel-session-router.mjs +4 -1
- 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/settings-compaction-api.mjs +1 -0
- package/src/session-runtime/setup-tool/executor.mjs +12 -1
- package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +1 -0
- package/src/session-runtime/setup-tool/tool-defs.mjs +7 -1
- package/src/session-runtime/skills-api.mjs +7 -3
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/webhook-session-run.mjs +16 -4
- package/src/skill-script-entry.mjs +36 -0
- package/src/standalone/daemon-drain-policy.mjs +8 -0
- package/src/standalone/daemon-stored-session-views.mjs +11 -3
- package/src/standalone/daemon-telemetry.mjs +55 -0
- package/src/standalone/daemon.mjs +44 -11
- package/src/standalone/session-protocol.mjs +12 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +33 -2
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +26 -10
- package/src/standalone/session-service/agent-tree.mjs +12 -0
- package/src/standalone/session-service/quota-resume.mjs +8 -0
- package/src/standalone/session-service/retention/busy.mjs +15 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +6 -1
- package/src/standalone/session-service-api.mjs +5 -0
- package/src/standalone/session-service.mjs +1 -0
- 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 +7 -0
- package/src/tui/app/create-app-pickers.mjs +4 -0
- package/src/tui/app/extension-pickers/mcp-login.mjs +107 -0
- package/src/tui/app/extension-pickers/mcp-servers-picker.mjs +2 -1
- package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
- package/src/tui/app/extension-pickers.mjs +2 -1
- package/src/tui/app/model-options.mjs +13 -16
- package/src/tui/app/skill-mention-palette.mjs +88 -0
- package/src/tui/app/slash-commands.mjs +7 -2
- package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
- 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/StatusLine.jsx +2 -0
- package/src/tui/components/TranscriptItem.jsx +9 -1
- package/src/tui/components/prompt-input/key-handler.mjs +21 -8
- package/src/tui/components/status-line/local-line.mjs +5 -2
- package/src/tui/components/status-line/use-statusline-text.mjs +7 -1
- package/src/tui/components/user-message-skills.mjs +38 -0
- package/src/tui/dist/index.mjs +1323 -214
- package/src/tui/session/queue-helpers.mjs +7 -2
- package/src/tui/session/quota-resume.mjs +46 -14
- package/src/tui/session/session-api/commands.mjs +33 -24
- package/src/tui/session/session-api/extensions.mjs +26 -2
- package/src/tui/session/session-api/integrations.mjs +7 -0
- package/src/tui/session/session-api/lifecycle.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +71 -7
- package/src/tui/session/session-api/settings.mjs +12 -14
- package/src/tui/session/session-flow/drain.mjs +21 -5
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
- package/src/tui/session/tui-steering-persist.mjs +25 -9
- package/src/tui/session/turn.mjs +55 -15
- package/src/tui/statusline-ansi-bridge.mjs +1 -1
- package/src/ui/statusline-agents.mjs +15 -4
- package/src/ui/statusline.mjs +7 -3
- package/src/ui/streaming-markdown-heal.mjs +34 -3
- package/src/vendor/statusline/src/gateway/claude-current.mjs +14 -4
- package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
- package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
- package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
- package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { normalizeAnthropicEffortInput } from './anthropic-effort.mjs';
|
|
1
|
+
import { anthropicEffortLevelsFor, normalizeAnthropicEffortInput } from './anthropic-effort.mjs';
|
|
2
2
|
import { CUSTOM_EFFORT_LEVELS, customEffortLevels, isCustomProviderName } from './custom-reasoning.mjs';
|
|
3
3
|
import { codexModelSupportsEffortUpdates } from './openai-oauth-catalog.mjs';
|
|
4
4
|
|
|
@@ -7,6 +7,9 @@ export const EFFORT_CONFIGURATION_BETA = 'mid-conversation-output-config-2026-07
|
|
|
7
7
|
// first version checked on the wire (update accepted, prompt cache kept), and
|
|
8
8
|
// every later version of that family. A model that turns out to reject the
|
|
9
9
|
// update is switched off at runtime (markEffortConfigurationUnsupported).
|
|
10
|
+
// The Anthropic catalogs publish no per-model flag for it, so a measured
|
|
11
|
+
// floor is kept for the families already checked: below it the rejection is
|
|
12
|
+
// certain, and every request would pay a failed attempt first.
|
|
10
13
|
const ANTHROPIC_MIN_VERSION = Object.freeze({
|
|
11
14
|
opus: [5, 0],
|
|
12
15
|
sonnet: [5, 5],
|
|
@@ -14,6 +17,10 @@ const ANTHROPIC_MIN_VERSION = Object.freeze({
|
|
|
14
17
|
fable: [5, 1],
|
|
15
18
|
mythos: [5, 1],
|
|
16
19
|
});
|
|
20
|
+
// A family not measured yet starts at the earliest checked major, on the
|
|
21
|
+
// routes that replay a rejected update (the rest cannot recover from one).
|
|
22
|
+
const ANTHROPIC_FIRST_MAJOR = Math.min(...Object.values(ANTHROPIC_MIN_VERSION).map(([major]) => major));
|
|
23
|
+
const ANTHROPIC_REPLAYING_PROVIDERS = new Set(['anthropic-oauth']);
|
|
17
24
|
// https://developers.openai.com/api/docs/guides/reasoning#change-reasoning-mid-conversation
|
|
18
25
|
// — GPT-6 and later, standard single-agent mode. The public API publishes no
|
|
19
26
|
// per-model flag, so the version is its whole answer; the OAuth backend's
|
|
@@ -25,14 +32,19 @@ function versionAtLeast([major, minor], [minMajor, minMinor]) {
|
|
|
25
32
|
return major > minMajor || (major === minMajor && minor >= minMinor);
|
|
26
33
|
}
|
|
27
34
|
|
|
28
|
-
function anthropicVersionSupported(id) {
|
|
35
|
+
function anthropicVersionSupported(provider, id) {
|
|
29
36
|
const m = id.match(/^claude-([a-z]+)-(\d+)(?:-(\d{1,2}))?$/);
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
if (!m) return false;
|
|
38
|
+
const version = [Number(m[2]), Number(m[3] || 0)];
|
|
39
|
+
const floor = ANTHROPIC_MIN_VERSION[m[1]];
|
|
40
|
+
if (floor) return versionAtLeast(version, floor);
|
|
41
|
+
return ANTHROPIC_REPLAYING_PROVIDERS.has(provider) && version[0] >= ANTHROPIC_FIRST_MAJOR;
|
|
32
42
|
}
|
|
33
43
|
|
|
44
|
+
// Any `gpt-<major>` id, whatever follows the major (tier names, minors,
|
|
45
|
+
// snapshots), so a later naming scheme needs no edit.
|
|
34
46
|
function openAiVersionSupported(id) {
|
|
35
|
-
const m = id.match(/^gpt-(\d+)(
|
|
47
|
+
const m = id.match(/^gpt-(\d+)(?:-|$)/);
|
|
36
48
|
return Boolean(m) && Number(m[1]) >= OPENAI_MIN_MAJOR;
|
|
37
49
|
}
|
|
38
50
|
|
|
@@ -110,11 +122,25 @@ function openAiSupportsEffortUpdates(provider, model, id) {
|
|
|
110
122
|
return declared ?? openAiVersionSupported(id);
|
|
111
123
|
}
|
|
112
124
|
|
|
125
|
+
// A custom route on the Responses wire (`opts.protocol`) serving GPT-6 or
|
|
126
|
+
// later takes the same update as the official routes. The version is read
|
|
127
|
+
// from the id's last `/` segment, so gateway ids like `openai/gpt-6.1-sol` count.
|
|
128
|
+
function customResponsesSupportsEffortUpdates(provider, opts, id) {
|
|
129
|
+
return (
|
|
130
|
+
isCustomProviderName(provider) &&
|
|
131
|
+
opts.protocol === 'openai-responses' &&
|
|
132
|
+
openAiVersionSupported(id.slice(id.lastIndexOf('/') + 1))
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
113
136
|
export function effortConfigurationMode(provider, model, opts = {}) {
|
|
114
137
|
const id = modelKey(model);
|
|
115
138
|
if (opts.effortConfigurationEnabled === false || Number(opts.thinkingBudgetTokens) > 0) return null;
|
|
116
139
|
if (unsupportedModels.has(`${provider}:${id}`)) return null;
|
|
117
|
-
if (
|
|
140
|
+
if (
|
|
141
|
+
(OPENAI_PROVIDERS.has(provider) && openAiSupportsEffortUpdates(provider, model, id)) ||
|
|
142
|
+
customResponsesSupportsEffortUpdates(provider, opts, id)
|
|
143
|
+
) {
|
|
118
144
|
const parameters = opts.modelParameters || {};
|
|
119
145
|
const mode = opts.reasoning?.mode ?? parameters.reasoning_mode ?? parameters.mode ?? 'standard';
|
|
120
146
|
if (mode !== 'standard' || opts.multiAgent === true || parameters.multi_agent === true) return null;
|
|
@@ -122,7 +148,7 @@ export function effortConfigurationMode(provider, model, opts = {}) {
|
|
|
122
148
|
}
|
|
123
149
|
if (
|
|
124
150
|
ANTHROPIC_PROVIDERS.has(provider) &&
|
|
125
|
-
anthropicVersionSupported(id) &&
|
|
151
|
+
anthropicVersionSupported(provider, id) &&
|
|
126
152
|
opts.disableBetaHeaders !== true &&
|
|
127
153
|
(!opts.baseURL || /^https:\/\/api\.anthropic\.com(?:\/|$)/.test(opts.baseURL))
|
|
128
154
|
)
|
|
@@ -132,7 +158,8 @@ export function effortConfigurationMode(provider, model, opts = {}) {
|
|
|
132
158
|
|
|
133
159
|
// Custom providers on the Chat and Responses wires take a fresh effort with
|
|
134
160
|
// every request, so auto effort sends a turn's or step's effort as that
|
|
135
|
-
// request's own effort: no mid-conversation update, no beta header
|
|
161
|
+
// request's own effort: no mid-conversation update, no beta header (except a
|
|
162
|
+
// Responses-wire GPT-6+ model, which takes the 'responses' update). A custom
|
|
136
163
|
// Anthropic-wire provider keeps auto effort off.
|
|
137
164
|
const CUSTOM_AUTO_EFFORT_PROTOCOLS = new Set(['openai-chat', 'openai-responses']);
|
|
138
165
|
|
|
@@ -147,24 +174,38 @@ export function customAutoEffortCapable(provider, protocol, model) {
|
|
|
147
174
|
}
|
|
148
175
|
|
|
149
176
|
/** The model auto effort reads its effort options from: a custom provider's
|
|
150
|
-
* effective row (its declared levels)
|
|
177
|
+
* effective row (its declared levels); an Anthropic route's id with the
|
|
178
|
+
* levels the wire builder accepts (provider rows ignored); the bare id for every other route. */
|
|
151
179
|
export function autoEffortModel(providerName, providerImpl, model) {
|
|
180
|
+
if (ANTHROPIC_PROVIDERS.has(providerName)) {
|
|
181
|
+
// The wire builder ignores provider rows on first-party routes, so the
|
|
182
|
+
// ladder is exactly what it accepts. `customReasoning` keeps an empty
|
|
183
|
+
// list from falling back to a family ladder.
|
|
184
|
+
return { id: model, reasoningLevels: anthropicEffortLevelsFor(model), customReasoning: true };
|
|
185
|
+
}
|
|
152
186
|
if (!isCustomProviderName(providerName)) return { id: model };
|
|
153
187
|
return { ...(providerImpl?.getCachedModelInfo?.(model) || {}), id: model };
|
|
154
188
|
}
|
|
155
189
|
|
|
156
190
|
/** The effort-change mode of a session's route: 'responses' / 'anthropic'
|
|
157
|
-
* (mid-conversation update), 'custom' (per-request effort), or null.
|
|
191
|
+
* (mid-conversation update), 'custom' (per-request effort), or null. A
|
|
192
|
+
* custom route takes an update mode only when its model declares levels. */
|
|
158
193
|
export function turnEffortConfigurationMode(session, provider) {
|
|
159
|
-
const
|
|
194
|
+
const protocol = provider?.customConfig?.protocol;
|
|
195
|
+
const opts = { ...(provider?.config || {}), modelParameters: session.modelParameters || {}, protocol };
|
|
196
|
+
const custom = customAutoEffortCapable(
|
|
197
|
+
session.provider,
|
|
198
|
+
protocol,
|
|
199
|
+
autoEffortModel(session.provider, provider, session.model)
|
|
200
|
+
);
|
|
160
201
|
const mode = effortConfigurationMode(session.provider, session.model, opts);
|
|
161
|
-
if (mode) return mode;
|
|
162
|
-
|
|
163
|
-
return customAutoEffortCapable(session.provider, provider?.customConfig?.protocol, model) ? 'custom' : null;
|
|
202
|
+
if (mode && (custom || !isCustomProviderName(session.provider))) return mode;
|
|
203
|
+
return custom ? 'custom' : null;
|
|
164
204
|
}
|
|
165
205
|
|
|
166
206
|
const CUSTOM_EFFORTS = new Set(CUSTOM_EFFORT_LEVELS);
|
|
167
|
-
|
|
207
|
+
// A custom route keeps its own levels (including `none`) in either mode.
|
|
208
|
+
const effortsFor = (mode, provider) => (mode === 'custom' || isCustomProviderName(provider) ? CUSTOM_EFFORTS : EFFORTS);
|
|
168
209
|
|
|
169
210
|
function normalizedEffort(provider, model, effort) {
|
|
170
211
|
if (ANTHROPIC_PROVIDERS.has(provider)) return normalizeAnthropicEffortInput(effort, model) || null;
|
|
@@ -180,8 +221,8 @@ function validSnapshot(value, provider, model, mode) {
|
|
|
180
221
|
value.provider === provider &&
|
|
181
222
|
value.model === modelKey(model) &&
|
|
182
223
|
value.mode === mode &&
|
|
183
|
-
effortsFor(mode).has(value.initialEffort) &&
|
|
184
|
-
effortsFor(mode).has(value.effort)
|
|
224
|
+
effortsFor(mode, provider).has(value.initialEffort) &&
|
|
225
|
+
effortsFor(mode, provider).has(value.effort)
|
|
185
226
|
);
|
|
186
227
|
}
|
|
187
228
|
|
|
@@ -192,7 +233,7 @@ function validSnapshot(value, provider, model, mode) {
|
|
|
192
233
|
export function prepareTurnEffortConfiguration(session, provider, turnEffort) {
|
|
193
234
|
const mode = turnEffortConfigurationMode(session, provider);
|
|
194
235
|
const effort = normalizedEffort(session.provider, session.model, turnEffort ?? session.effort);
|
|
195
|
-
if (!mode || !effortsFor(mode).has(effort)) return null;
|
|
236
|
+
if (!mode || !effortsFor(mode, session.provider).has(effort)) return null;
|
|
196
237
|
const first = (session.messages || []).find((message) =>
|
|
197
238
|
validSnapshot(message?.meta?.[META_KEY], session.provider, session.model, mode)
|
|
198
239
|
)?.meta?.[META_KEY];
|
|
@@ -214,7 +255,7 @@ export function prepareTurnEffortConfiguration(session, provider, turnEffort) {
|
|
|
214
255
|
// step), or null when that effort is not valid for the model.
|
|
215
256
|
export function stepEffortConfiguration(snapshot, provider, model, effort) {
|
|
216
257
|
const value = normalizedEffort(provider, model, effort);
|
|
217
|
-
if (!snapshot || !
|
|
258
|
+
if (!snapshot || !effortsFor(snapshot.mode, provider).has(value)) return null;
|
|
218
259
|
return { ...snapshot, effort: value };
|
|
219
260
|
}
|
|
220
261
|
|
|
@@ -249,6 +290,32 @@ export function projectEffortConfiguration(messages, provider, model, opts = {})
|
|
|
249
290
|
return { mode, initialEffort: seed.initialEffort, effort: current, updates };
|
|
250
291
|
}
|
|
251
292
|
|
|
293
|
+
/**
|
|
294
|
+
* Responses-wire placement of a projection's updates while a history is
|
|
295
|
+
* lowered in order: `before(message)` gives the items to emit ahead of a
|
|
296
|
+
* message, `end()` those after the last one. An update on a tool result
|
|
297
|
+
* applies after its whole batch; one on a user message before it. Adjacent
|
|
298
|
+
* updates are rejected, so a batch update that a user message directly
|
|
299
|
+
* follows yields to that message's own.
|
|
300
|
+
*/
|
|
301
|
+
export function responsesEffortUpdates(projection) {
|
|
302
|
+
let afterBatch = null;
|
|
303
|
+
const items = (effort) => (effort ? [{ type: 'configuration_update', reasoning: { effort } }] : []);
|
|
304
|
+
return {
|
|
305
|
+
before(message) {
|
|
306
|
+
const effort = projection?.updates.get(message);
|
|
307
|
+
if (message.role === 'tool') {
|
|
308
|
+
if (effort) afterBatch = effort;
|
|
309
|
+
return [];
|
|
310
|
+
}
|
|
311
|
+
const value = effort || afterBatch;
|
|
312
|
+
afterBatch = null;
|
|
313
|
+
return items(value);
|
|
314
|
+
},
|
|
315
|
+
end: () => items(afterBatch),
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
252
319
|
// Split only before a user message or after a whole tool-result batch.
|
|
253
320
|
// Sanitizing each segment before inserting the trusted empty system control
|
|
254
321
|
// avoids losing it as empty text, and never separates a tool call from its
|
|
@@ -252,7 +252,7 @@ export function dropRejectedGeminiCache(cachedContent, opts) {
|
|
|
252
252
|
// the model-specific minimum. Skip the POST entirely when the estimate
|
|
253
253
|
// is under threshold so we don't spam 400 responses turn-after-turn.
|
|
254
254
|
export function geminiPrefixBelowMinimum({ model, systemInstruction, geminiTools, contents, opts, currentIter }) {
|
|
255
|
-
const minTokens = _geminiCacheMinTokens(
|
|
255
|
+
const minTokens = _geminiCacheMinTokens();
|
|
256
256
|
const estimatedTokens = _estimateGeminiCacheTokens(systemInstruction, geminiTools, contents);
|
|
257
257
|
if (estimatedTokens >= minTokens) return false;
|
|
258
258
|
traceGeminiCache(opts, currentIter, 'gemini_cache_skip', {
|
|
@@ -43,12 +43,11 @@ function summarizeTraceContents(contents) {
|
|
|
43
43
|
return [...summaries.slice(0, 8), { omittedTurns: summaries.length - 12 }, ...summaries.slice(-4)];
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
// Gemini cachedContents API rejects prefixes below
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
// is harmless (we
|
|
51
|
-
// is harmless (we skip, fall back to implicit cache).
|
|
46
|
+
// Gemini cachedContents API rejects prefixes below a model-specific minimum
|
|
47
|
+
// with HTTP 400 "Cached content is too small". Estimating chars/4 ≈ tokens
|
|
48
|
+
// lets us skip the roundtrip when the prefix cannot satisfy the invariant.
|
|
49
|
+
// Estimate undercount is harmless (we attempt and get the same 400 we would
|
|
50
|
+
// have skipped); overcount is harmless (we skip, fall back to implicit cache).
|
|
52
51
|
export function _estimateGeminiCacheTokens(systemInstruction, geminiTools, contents) {
|
|
53
52
|
let chars = 0;
|
|
54
53
|
if (typeof systemInstruction === 'string') chars += systemInstruction.length;
|
|
@@ -67,8 +66,15 @@ export function _estimateGeminiCacheTokens(systemInstruction, geminiTools, conte
|
|
|
67
66
|
return Math.ceil(chars / 4);
|
|
68
67
|
}
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
// No catalog publishes the cachedContents floor and the published minimums
|
|
70
|
+
// differ per model and change between releases, so one floor serves every id:
|
|
71
|
+
// the highest published minimum. Skipping a small prefix only falls back to the
|
|
72
|
+
// implicit cache, whereas a floor that is too low would POST a create that the
|
|
73
|
+
// server rejects on every turn.
|
|
74
|
+
const GEMINI_CACHE_MIN_TOKENS = 4096;
|
|
75
|
+
|
|
76
|
+
export function _geminiCacheMinTokens() {
|
|
77
|
+
return GEMINI_CACHE_MIN_TOKENS;
|
|
72
78
|
}
|
|
73
79
|
|
|
74
80
|
export function _geminiCachePrefixCount(contents) {
|
|
@@ -110,6 +116,21 @@ const GEMINI_GLOBAL_CACHE_MAX_ENTRIES = 128;
|
|
|
110
116
|
export const GEMINI_GLOBAL_CACHE_DELETE_GRACE_MS = 2 * 60 * 1000;
|
|
111
117
|
const geminiGlobalCaches = new Map();
|
|
112
118
|
export const geminiGlobalCacheCreates = new Map();
|
|
119
|
+
// Models whose cachedContents.create the server refused as unsupported (not
|
|
120
|
+
// a prefix or quota failure). No catalog publishes explicit-cache support, so
|
|
121
|
+
// the server's own answer decides, once per process.
|
|
122
|
+
const geminiExplicitCacheRefusedModels = new Set();
|
|
123
|
+
|
|
124
|
+
export function markGeminiExplicitCacheRefused(model, err) {
|
|
125
|
+
if (err?.status !== 400) return false;
|
|
126
|
+
if (!/explicit caching is not supported/i.test(String(err?.message || ''))) return false;
|
|
127
|
+
geminiExplicitCacheRefusedModels.add(String(model || ''));
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function geminiExplicitCacheRefused(model) {
|
|
132
|
+
return geminiExplicitCacheRefusedModels.has(String(model || ''));
|
|
133
|
+
}
|
|
113
134
|
|
|
114
135
|
export function _geminiCredentialFingerprint(apiKey) {
|
|
115
136
|
return traceHash(String(apiKey || ''));
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gemini-error-contract.mjs — Google RPC error details → the provider error
|
|
3
|
+
* contract shared by Gemini (REST + SDK) and Antigravity:
|
|
4
|
+
* status, code (lowercased), retryAfterMs (uncapped), resetAt (epoch ms),
|
|
5
|
+
* quotaScope ('minute' | 'day' | undefined).
|
|
6
|
+
*
|
|
7
|
+
* Details come from `error.details` (REST body) or `errorDetails` (SDK
|
|
8
|
+
* GoogleGenerativeAIFetchError). Entries are google.rpc.RetryInfo,
|
|
9
|
+
* QuotaFailure and ErrorInfo.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const DURATION_RE = /^(?:\d+(?:\.\d+)?(?:ms|s|m|h))+$/;
|
|
13
|
+
const DURATION_PART_RE = /(\d+(?:\.\d+)?)(ms|s|m|h)/g;
|
|
14
|
+
const DURATION_UNIT_MS = { ms: 1, s: 1000, m: 60_000, h: 3_600_000 };
|
|
15
|
+
const BARE_SECONDS_RE = /^\d+(?:\.\d+)?$/;
|
|
16
|
+
|
|
17
|
+
// Google error classification: a per-minute quota with no RetryInfo is
|
|
18
|
+
// retried after one quota window.
|
|
19
|
+
export const GEMINI_PER_MINUTE_RETRY_MS = 60_000;
|
|
20
|
+
|
|
21
|
+
// "Please retry in 34.07s" (Gemini API) / "reset after 2h1m1s" (Cloud Code).
|
|
22
|
+
const MESSAGE_DELAY_RE = /(?:please retry in|reset after)\s+((?:\d+(?:\.\d+)?(?:ms|h|m|s))+)/i;
|
|
23
|
+
const LIMIT_ZERO_RE = /limit:\s*0(?!\d|\.\d)/i;
|
|
24
|
+
const CAPACITY_MESSAGE_RE = /exhausted your capacity|capacity exceeded|model_capacity_exhausted/i;
|
|
25
|
+
// ErrorInfo reasons that name a spent quota with no window of its own.
|
|
26
|
+
const TERMINAL_REASONS = new Set(['quota_exhausted', 'insufficient_g1_credits_balance']);
|
|
27
|
+
const CAPACITY_REASONS = new Set(['model_capacity_exhausted', 'model_capacity_exceeded']);
|
|
28
|
+
|
|
29
|
+
const GOOGLE_STATUS_HTTP = {
|
|
30
|
+
INVALID_ARGUMENT: 400,
|
|
31
|
+
UNAUTHENTICATED: 401,
|
|
32
|
+
PERMISSION_DENIED: 403,
|
|
33
|
+
NOT_FOUND: 404,
|
|
34
|
+
RESOURCE_EXHAUSTED: 429,
|
|
35
|
+
INTERNAL: 500,
|
|
36
|
+
UNAVAILABLE: 503,
|
|
37
|
+
DEADLINE_EXCEEDED: 504,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
function detailType(entry) {
|
|
41
|
+
return typeof entry?.['@type'] === 'string' ? entry['@type'] : '';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function durationMs(value) {
|
|
45
|
+
if (typeof value === 'string') {
|
|
46
|
+
const text = value.trim();
|
|
47
|
+
if (BARE_SECONDS_RE.test(text)) return Math.ceil(Number(text) * 1000);
|
|
48
|
+
if (!DURATION_RE.test(text)) return null;
|
|
49
|
+
let total = 0;
|
|
50
|
+
for (const [, amount, unit] of text.matchAll(DURATION_PART_RE)) total += Number(amount) * DURATION_UNIT_MS[unit];
|
|
51
|
+
return Math.ceil(total);
|
|
52
|
+
}
|
|
53
|
+
if (value && typeof value === 'object') {
|
|
54
|
+
const ms = Number(value.seconds || 0) * 1000 + Number(value.nanos || 0) / 1_000_000;
|
|
55
|
+
return Number.isFinite(ms) && ms >= 0 ? Math.ceil(ms) : null;
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// A zero wait is no advice: the caller's normal backoff (or the per-minute
|
|
61
|
+
// window) applies instead of an immediate re-issue.
|
|
62
|
+
function adviceMs(value) {
|
|
63
|
+
const ms = durationMs(value);
|
|
64
|
+
return ms > 0 ? ms : undefined;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function scopeOf(text) {
|
|
68
|
+
if (/per[\s_-]?day|daily/i.test(text)) return 'day';
|
|
69
|
+
if (/per[\s_-]?minute/i.test(text)) return 'minute';
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* `quotaScope` is 'minute' / 'day' from the typed quota ids only (never from
|
|
75
|
+
* the length of the server's wait); 'plan' marks a spent
|
|
76
|
+
* quota with no window (ErrorInfo QUOTA_EXHAUSTED, or a QuotaFailure
|
|
77
|
+
* violation with a zero limit; message prose alone never counts). Capacity
|
|
78
|
+
* (MODEL_CAPACITY_EXHAUSTED / "exhausted your capacity") is an overload of the
|
|
79
|
+
* shared pool: code `model_capacity_exhausted`, never a quota scope.
|
|
80
|
+
* @param {{ details?: unknown, errorDetails?: unknown, googleStatus?: string, message?: string }} input
|
|
81
|
+
* @returns {{ code?: string, retryAfterMs?: number, resetAt?: number, quotaScope?: 'minute'|'day'|'plan' }}
|
|
82
|
+
*/
|
|
83
|
+
export function geminiErrorContract({ details, errorDetails, googleStatus, message } = {}) {
|
|
84
|
+
const list = [details, errorDetails].flatMap((entry) => (Array.isArray(entry) ? entry : []));
|
|
85
|
+
let reason = '';
|
|
86
|
+
let retryAfterMs;
|
|
87
|
+
let resetAt;
|
|
88
|
+
const scopes = new Set();
|
|
89
|
+
let zeroLimit = false;
|
|
90
|
+
for (const entry of list) {
|
|
91
|
+
const type = detailType(entry);
|
|
92
|
+
if (type.endsWith('.RetryInfo') || entry?.retryDelay !== undefined) {
|
|
93
|
+
retryAfterMs ??= adviceMs(entry.retryDelay);
|
|
94
|
+
}
|
|
95
|
+
if (type.endsWith('.QuotaFailure') || Array.isArray(entry?.violations)) {
|
|
96
|
+
for (const violation of entry.violations || []) {
|
|
97
|
+
const scope = scopeOf(String(violation?.quotaId || ''));
|
|
98
|
+
if (scope) scopes.add(scope);
|
|
99
|
+
// A spent allowance is named by the typed violation, not by prose.
|
|
100
|
+
if (String(violation?.quotaValue ?? '').trim() === '0' || LIMIT_ZERO_RE.test(String(violation?.description || ''))) {
|
|
101
|
+
zeroLimit = true;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (type.endsWith('.ErrorInfo') || typeof entry?.reason === 'string') {
|
|
106
|
+
if (!reason && typeof entry.reason === 'string') reason = entry.reason.trim().toLowerCase();
|
|
107
|
+
const metadata = entry.metadata && typeof entry.metadata === 'object' ? entry.metadata : {};
|
|
108
|
+
retryAfterMs ??= adviceMs(metadata.quotaResetDelay);
|
|
109
|
+
const stamp = Date.parse(String(metadata.quotaResetTimeStamp || ''));
|
|
110
|
+
if (resetAt === undefined && Number.isFinite(stamp)) resetAt = stamp;
|
|
111
|
+
const scope = scopeOf(
|
|
112
|
+
[metadata.quotaId, metadata.quota_limit, metadata.quota_metric, entry.reason].filter(Boolean).join(' ')
|
|
113
|
+
);
|
|
114
|
+
if (scope) scopes.add(scope);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const text = typeof message === 'string' ? message : '';
|
|
118
|
+
// The message names capacity only when nothing typed said otherwise (a
|
|
119
|
+
// reason, a quota id or RetryInfo outranks it, as in classifyGoogleError).
|
|
120
|
+
const capacity =
|
|
121
|
+
CAPACITY_REASONS.has(reason) ||
|
|
122
|
+
(!reason && scopes.size === 0 && retryAfterMs === undefined && CAPACITY_MESSAGE_RE.test(text));
|
|
123
|
+
// A per-day violation outlasts any per-minute one reported with it.
|
|
124
|
+
let quotaScope = scopes.has('day') ? 'day' : scopes.has('minute') ? 'minute' : undefined;
|
|
125
|
+
if (retryAfterMs === undefined) {
|
|
126
|
+
const named = MESSAGE_DELAY_RE.exec(text);
|
|
127
|
+
if (named) retryAfterMs = adviceMs(named[1]);
|
|
128
|
+
}
|
|
129
|
+
// Per-minute quota with no RetryInfo: wait one quota window.
|
|
130
|
+
if (retryAfterMs === undefined && quotaScope === 'minute' && !capacity) retryAfterMs = GEMINI_PER_MINUTE_RETRY_MS;
|
|
131
|
+
if (resetAt === undefined && retryAfterMs !== undefined) resetAt = Date.now() + retryAfterMs;
|
|
132
|
+
if (!capacity && !quotaScope && (TERMINAL_REASONS.has(reason) || zeroLimit)) quotaScope = 'plan';
|
|
133
|
+
const status = typeof googleStatus === 'string' ? googleStatus.trim().toLowerCase() : '';
|
|
134
|
+
const code = capacity ? 'model_capacity_exhausted' : reason || status;
|
|
135
|
+
return {
|
|
136
|
+
...(code ? { code } : {}),
|
|
137
|
+
...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
|
|
138
|
+
...(resetAt !== undefined ? { resetAt } : {}),
|
|
139
|
+
...(quotaScope ? { quotaScope } : {}),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Copy the contract fields onto `err`; an already-typed `code` is kept. */
|
|
144
|
+
export function applyGeminiErrorContract(err, input) {
|
|
145
|
+
const { code, ...rest } = geminiErrorContract(input);
|
|
146
|
+
Object.assign(err, rest);
|
|
147
|
+
if (code && !(typeof err.code === 'string' && err.code)) err.code = code;
|
|
148
|
+
return err;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* The `{ error: {...} }` envelope a Gemini/Cloud Code stream carries in-band
|
|
153
|
+
* instead of an HTTP error status. Returns the typed error, or null when the
|
|
154
|
+
* chunk is an ordinary payload.
|
|
155
|
+
*/
|
|
156
|
+
export function geminiInBandError(chunk, label) {
|
|
157
|
+
const detail = chunk && typeof chunk === 'object' ? chunk.error : null;
|
|
158
|
+
if (!detail || (typeof detail !== 'object' && typeof detail !== 'string')) return null;
|
|
159
|
+
const body = typeof detail === 'object' ? detail : { message: detail };
|
|
160
|
+
const googleStatus = typeof body.status === 'string' ? body.status : '';
|
|
161
|
+
const status = Number.isFinite(Number(body.code)) && Number(body.code) > 0
|
|
162
|
+
? Number(body.code)
|
|
163
|
+
: GOOGLE_STATUS_HTTP[googleStatus.toUpperCase()];
|
|
164
|
+
const err = new Error(`${label} in-band error${status ? ` ${status}` : ''}: ${String(body.message || googleStatus || 'unknown').slice(0, 300)}`);
|
|
165
|
+
err.name = 'GeminiInBandError';
|
|
166
|
+
if (status) {
|
|
167
|
+
err.status = status;
|
|
168
|
+
err.httpStatus = status;
|
|
169
|
+
}
|
|
170
|
+
if (googleStatus) err.geminiStatus = googleStatus.toUpperCase();
|
|
171
|
+
err.error = body;
|
|
172
|
+
const details = body.details ?? body.errorDetails;
|
|
173
|
+
if (Array.isArray(details)) err.details = details;
|
|
174
|
+
return applyGeminiErrorContract(err, { details, googleStatus, message: body.message });
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Throw the typed in-band error when `chunk` is an error envelope. */
|
|
178
|
+
export function assertNoGeminiInBandError(chunk, label) {
|
|
179
|
+
const err = geminiInBandError(chunk, label);
|
|
180
|
+
if (err) throw err;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const SAFETY_FINISH = /^(?:PROMPT_)?(?:SAFETY|IMAGE_SAFETY|BLOCKLIST|PROHIBITED_CONTENT|SPII|IMAGE_PROHIBITED_CONTENT)$/;
|
|
184
|
+
|
|
185
|
+
/** Policy-refusal code for a finishReason, or null for any other reason. */
|
|
186
|
+
export function geminiPolicyFinishCode(finishReason) {
|
|
187
|
+
const reason = String(finishReason || '').replace(/^FINISH_REASON_/, '');
|
|
188
|
+
if (SAFETY_FINISH.test(reason)) return 'safety';
|
|
189
|
+
if (/^(?:PROMPT_)?RECITATION$/.test(reason)) return 'recitation';
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// True for an id in the Gemini wire family ("gemini-4-argon", "models/gemini-3.1-pro",
|
|
2
|
+
// "gemini-pro-agent"). It names the family only, never a generation: it separates
|
|
3
|
+
// Gemini from the other model families an Antigravity gateway serves (Claude,
|
|
4
|
+
// GPT-OSS), which reject Gemini-only request fields outright.
|
|
5
|
+
const GEMINI_FAMILY = /(?:^|\/)gemini-/i;
|
|
6
|
+
|
|
7
|
+
export function isGeminiFamilyModel(model) {
|
|
8
|
+
return GEMINI_FAMILY.test(String(model || ''));
|
|
9
|
+
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import { isGeminiFamilyModel } from './gemini-family.mjs';
|
|
2
|
+
|
|
1
3
|
const SYNTHETIC_TOOL_SIGNATURE = 'skip_thought_signature_validator';
|
|
2
4
|
|
|
3
|
-
// Gemini
|
|
4
|
-
// Foreign/interrupted histories may not have
|
|
5
|
-
//
|
|
5
|
+
// Gemini models that validate thought signatures check the first functionCall
|
|
6
|
+
// in every step of the current turn. Foreign/interrupted histories may not have
|
|
7
|
+
// a native signature for that call. Preserve real signatures and unsigned
|
|
8
|
+
// siblings of a signed parallel batch. The validator-bypass token is a Gemini
|
|
9
|
+
// wire token: it is only fabricated for the Gemini family, because the other
|
|
10
|
+
// families an Antigravity gateway serves reject it.
|
|
6
11
|
export function ensureGeminiToolCallSignatures(contents, model) {
|
|
7
|
-
if (
|
|
12
|
+
if (!isGeminiFamilyModel(model)) return contents;
|
|
8
13
|
let activeTurnStart = 0;
|
|
9
14
|
for (let index = contents.length - 1; index >= 0; index -= 1) {
|
|
10
15
|
const content = contents[index];
|
|
@@ -14,6 +14,7 @@ import { createProviderReplay } from './lib/provider-replay.mjs';
|
|
|
14
14
|
import { collectGeminiGroundingSources, parseGeminiTextPartMetadata, parseToolCalls } from './gemini-schema.mjs';
|
|
15
15
|
import { _resolveGeminiCacheUsage } from './gemini-cache.mjs';
|
|
16
16
|
import { traceGeminiCache } from './gemini-cache-policy.mjs';
|
|
17
|
+
import { geminiPolicyFinishCode } from './gemini-error-contract.mjs';
|
|
17
18
|
|
|
18
19
|
// Candidate text and tool calls after the text-leak guard: leaked
|
|
19
20
|
// (text-embedded) tool calls are appended to the native ones and empty the
|
|
@@ -64,7 +65,8 @@ export function geminiIncompleteError(response, parsed, useModel, usage = null)
|
|
|
64
65
|
if (!finishReason || normalizedFinishReason === 'STOP') return null;
|
|
65
66
|
return Object.assign(new Error(`Gemini response incomplete: finishReason=${finishReason}`), {
|
|
66
67
|
name: 'ProviderIncompleteError',
|
|
67
|
-
|
|
68
|
+
// Safety/recitation are policy refusals the core presents as such.
|
|
69
|
+
code: geminiPolicyFinishCode(finishReason) || 'PROVIDER_INCOMPLETE',
|
|
68
70
|
providerIncomplete: true,
|
|
69
71
|
finishReason,
|
|
70
72
|
partialContent: parsed.content,
|