mixdog 1.2.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/package.json +2 -1
- package/scripts/provider-pingpong-live.mjs +509 -0
- package/src/agents/advisor/AGENT.md +1 -1
- package/src/agents/advisor/agent.json +1 -1
- package/src/defaults/shipped-history.json +5 -0
- package/src/defaults/skills/setup/SKILL.md +6 -1
- package/src/defaults/skills/setup/references/actions.md +44 -22
- package/src/defaults/skills/setup/references/surfaces.md +10 -8
- package/src/headless-exec.mjs +15 -8
- package/src/lib/keychain-cjs.cjs +7 -4
- package/src/output-styles/common.md +11 -10
- package/src/rules/agent/AGENT.md +5 -5
- package/src/rules/lead/LEAD.md +5 -5
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
- package/src/runtime/agent/orchestrator/config.mjs +5 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +7 -6
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +29 -10
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +58 -7
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +16 -3
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +10 -61
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +12 -6
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +114 -72
- package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +37 -5
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +43 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +64 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +70 -6
- package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
- package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
- package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +25 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +87 -5
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +13 -13
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +355 -37
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +93 -47
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +55 -10
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +26 -8
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +246 -42
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
- package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +388 -0
- package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
- package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +48 -22
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +119 -18
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +33 -1
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +121 -61
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +37 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +47 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +151 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +42 -24
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +172 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +53 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +25 -4
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +71 -24
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -35
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +11 -3
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +170 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +75 -70
- package/src/runtime/agent/orchestrator/providers/openrouter.mjs +75 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +147 -8
- package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
- package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +157 -0
- package/src/runtime/agent/orchestrator/providers/wire-route.mjs +512 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +183 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +100 -0
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
- package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +14 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +176 -71
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +62 -10
- package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +14 -93
- package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +120 -0
- package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
- package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +91 -1
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
- package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +21 -10
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +132 -0
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +30 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +63 -20
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +150 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +208 -14
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +25 -3
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +19 -2
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/side-question.mjs +192 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +58 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +41 -28
- package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/store.mjs +19 -3
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +77 -0
- package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +14 -10
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +49 -34
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
- package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
- package/src/runtime/computer-bridge/action-schema.mjs +44 -21
- package/src/runtime/github/tool.mjs +92 -2
- package/src/runtime/memory/index.mjs +1 -0
- package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
- package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
- package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
- package/src/runtime/memory/lib/pg/process.mjs +31 -26
- package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +108 -3
- package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
- package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
- package/src/runtime/office/README.md +1 -1
- package/src/runtime/office/authoring/html-document-author.mjs +2 -0
- package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-measure.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +2 -0
- package/src/runtime/office/core/office-actions-read.mjs +3 -0
- package/src/runtime/office/core/office-render-preview.mjs +2 -0
- package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
- package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
- package/src/runtime/office/core/office-sessions.mjs +5 -0
- package/src/runtime/office/core/office-transactions.mjs +3 -0
- package/src/runtime/office/core/office-write-ledger.mjs +98 -0
- package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
- package/src/runtime/office/index.mjs +30 -0
- package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
- package/src/runtime/office/pdf/pdf-render.mjs +23 -7
- package/src/runtime/office/pdf/pdf-security.mjs +2 -0
- package/src/runtime/office/portable/portable-opc.mjs +4 -1
- package/src/runtime/office/quality/visual-diff.mjs +2 -0
- package/src/runtime/shared/bounded-file-read.mjs +13 -0
- package/src/runtime/shared/bounded-line-diff.mjs +182 -0
- package/src/runtime/shared/buffered-appender.mjs +18 -0
- package/src/runtime/shared/config.mjs +78 -18
- package/src/runtime/shared/err-text.mjs +6 -0
- package/src/runtime/shared/file-permissions.d.mts +6 -1
- package/src/runtime/shared/file-permissions.mjs +54 -6
- package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
- package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
- package/src/runtime/shared/loopback-listener.mjs +9 -0
- package/src/runtime/shared/provider-api-key.mjs +2 -0
- package/src/runtime/shared/review-diff.mjs +52 -0
- package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
- package/src/runtime/shared/session-sidebar-host.mjs +38 -0
- package/src/runtime/shared/slow-span.mjs +114 -0
- package/src/runtime/shared/statusline/statusline-segments.mjs +28 -4
- package/src/runtime/shared/tool-card-model/card-header.mjs +6 -1
- package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
- package/src/runtime/shared/tool-card-model.mjs +5 -2
- package/src/runtime/shared/tool-output-limit.mjs +4 -0
- package/src/runtime/shared/tool-primitives.mjs +13 -0
- package/src/runtime/shared/tool-result-summary.mjs +8 -1
- package/src/runtime/shared/tool-surface.mjs +18 -3
- package/src/runtime/shared/tool-work-units.mjs +40 -4
- package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
- package/src/runtime/shared/transcript-writer.mjs +10 -2
- package/src/runtime/shared/turn-changes.mjs +268 -100
- package/src/runtime/shared/turn-review-reply.mjs +8 -39
- package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
- package/src/runtime/shared/turn-snapshot.mjs +857 -683
- package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
- package/src/runtime/shared/user-data-guard.mjs +262 -49
- package/src/runtime/shared/worktrees/carry.mjs +531 -0
- package/src/runtime/shared/worktrees/contract.mjs +34 -0
- package/src/runtime/shared/worktrees/file-recovery.mjs +68 -0
- package/src/runtime/shared/worktrees/git-head.mjs +205 -0
- package/src/runtime/shared/worktrees/git.mjs +8 -3
- package/src/runtime/shared/worktrees/maintenance.mjs +1 -1
- package/src/runtime/shared/worktrees/manager.mjs +156 -8
- package/src/runtime/shared/worktrees/merge.mjs +31 -21
- package/src/runtime/shared/worktrees/paths.d.mts +6 -0
- package/src/runtime/terminal-bridge/client.mjs +44 -11
- package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
- package/src/runtime/tidy/apply.mjs +47 -2
- package/src/runtime/tidy/run-engines.mjs +11 -5
- package/src/session-runtime/agent-tool-routing.mjs +19 -13
- package/src/session-runtime/boot/apis.mjs +13 -5
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +6 -1
- package/src/session-runtime/boot/session.mjs +0 -1
- package/src/session-runtime/boot/tools.mjs +4 -1
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +65 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +11 -4
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +115 -18
- package/src/session-runtime/internal-tool-executor.mjs +6 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +188 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +29 -6
- package/src/session-runtime/lifecycle/teardown.mjs +72 -7
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/connect.mjs +17 -5
- package/src/session-runtime/model-route/set-route.mjs +2 -2
- package/src/session-runtime/native-web-search-usage.mjs +51 -0
- package/src/session-runtime/native-web-search.mjs +10 -1
- package/src/session-runtime/new-session-config.mjs +4 -2
- package/src/session-runtime/provider-auth/login.mjs +4 -0
- package/src/session-runtime/resource-scope-decorate.mjs +10 -3
- package/src/session-runtime/runtime-review-api.mjs +8 -2
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
- package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +73 -7
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +15 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
- package/src/session-runtime/services/agent-tool/worker-index.mjs +46 -7
- package/src/session-runtime/services/agent-tool.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +19 -3
- package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
- package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
- package/src/session-runtime/services/provider-admin.mjs +81 -15
- package/src/session-runtime/session-transcript-purge.mjs +32 -0
- package/src/session-runtime/session-turn-api.mjs +14 -5
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -0
- package/src/session-runtime/setup-tool/executor.mjs +36 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
- package/src/session-runtime/setup-tool/settings-contract.mjs +13 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +13 -4
- package/src/session-runtime/skills-api.mjs +3 -5
- package/src/session-runtime/tool-surface.mjs +5 -1
- package/src/session-runtime/turn/compaction-gate.mjs +25 -0
- package/src/session-runtime/turn/session-ops.mjs +7 -5
- package/src/session-runtime/turn/side-question-ops.mjs +22 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +5 -1
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +8 -3
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +10 -0
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +25 -9
- package/src/session-runtime/usage-stats-api.mjs +43 -11
- package/src/session-runtime/workspace/project-branches.mjs +7 -5
- package/src/session-runtime/workspace/transition-steps.mjs +129 -31
- package/src/session-runtime/workspace/transitions.mjs +190 -15
- package/src/standalone/daemon-agent-control.mjs +9 -1
- package/src/standalone/daemon-local-session-bridge.mjs +14 -1
- package/src/standalone/daemon-owner.mjs +17 -4
- package/src/standalone/daemon-pg-stop.mjs +51 -0
- package/src/standalone/daemon-stop-budget.d.mts +2 -0
- package/src/standalone/daemon-stop-budget.mjs +18 -0
- package/src/standalone/daemon-stored-session-views.mjs +2 -0
- package/src/standalone/daemon-telemetry.mjs +19 -0
- package/src/standalone/daemon.mjs +61 -1
- package/src/standalone/desktop-service-registry.mjs +5 -0
- package/src/standalone/local-session-runtime.mjs +70 -19
- package/src/standalone/session-client.mjs +42 -0
- package/src/standalone/session-protocol.mjs +7 -0
- package/src/standalone/session-proxy/projection.mjs +41 -4
- package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
- package/src/standalone/session-runtime-inline-host.mjs +1 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
- package/src/standalone/session-service-api.mjs +6 -1
- package/src/standalone/session-state-patch.d.mts +2 -1
- package/src/standalone/session-state-patch.mjs +41 -1
- package/src/tui/App.jsx +25 -0
- package/src/tui/app/app-view/floating-panel.jsx +26 -1
- package/src/tui/app/btw-controller.mjs +118 -0
- package/src/tui/app/create-app-pickers.mjs +2 -0
- package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
- package/src/tui/app/shell-layout/surfaces.mjs +3 -1
- package/src/tui/app/slash-commands.mjs +13 -3
- package/src/tui/app/slash-dispatch/session-commands.mjs +19 -6
- package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
- package/src/tui/app/use-global-key-input.mjs +5 -12
- package/src/tui/app/use-prompt-handlers.mjs +11 -0
- package/src/tui/components/BtwPanel.jsx +53 -0
- package/src/tui/components/QuestionPanel.jsx +275 -0
- package/src/tui/components/question-panel-model.mjs +156 -0
- package/src/tui/dist/index.mjs +2413 -1465
- package/src/tui/session/context-state.mjs +4 -2
- package/src/tui/session/session-api/commands.mjs +10 -0
- package/src/tui/session/session-api/controls.mjs +2 -2
- package/src/tui/session/session-api/integrations.mjs +9 -2
- package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle.mjs +2 -1
- package/src/tui/session/session-api/settings.mjs +6 -0
- package/src/tui/session/session-api.mjs +1 -0
- package/src/tui/session/tool-approval.mjs +10 -7
- package/src/tui/session/transcript-spill.mjs +14 -7
- package/src/tui/session/turn-stream.mjs +174 -31
- package/src/tui/session/turn.mjs +12 -5
- package/src/workflows/default/WORKFLOW.md +3 -1
|
@@ -26,7 +26,11 @@ import { createSdkStreamReader } from './gemini-sdk-stream/reader.mjs';
|
|
|
26
26
|
import { createRestStreamWatchdogs } from './gemini-rest-stream/watchdogs.mjs';
|
|
27
27
|
import { drainSseDataLines, sseDataPayload } from './gemini-rest-stream/sse-lines.mjs';
|
|
28
28
|
import { noteAbandonedUsage } from '../../../shared/llm/usage-context.mjs';
|
|
29
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
applyGeminiErrorContract,
|
|
31
|
+
assertNoGeminiInBandError,
|
|
32
|
+
geminiFinishReasonKind,
|
|
33
|
+
} from './gemini-error-contract.mjs';
|
|
30
34
|
|
|
31
35
|
export const GEMINI_FIRST_BYTE_TIMEOUT_MS = resolveTimeoutMs(
|
|
32
36
|
'MIXDOG_GEMINI_FIRST_BYTE_TIMEOUT_MS',
|
|
@@ -183,8 +187,10 @@ function stampGeminiStreamFailure(
|
|
|
183
187
|
const visible = visibleText.length > 0;
|
|
184
188
|
// Native functionCall chunks are only dispatched after successful stream
|
|
185
189
|
// completion in gemini.mjs. Until then a reconnect is safe. Text-leaked
|
|
186
|
-
// calls are dispatched while parsing and remain a hard replay boundary
|
|
187
|
-
|
|
190
|
+
// calls are dispatched while parsing and remain a hard replay boundary,
|
|
191
|
+
// unless the guard holds them back (`deferToolCalls`): a held call never
|
|
192
|
+
// runs when the stream fails, so a reconnect cannot double-execute it.
|
|
193
|
+
const pendingTool = leaked && textLeakGuard?.defersToolCalls !== true;
|
|
188
194
|
try {
|
|
189
195
|
if (visible) {
|
|
190
196
|
err.liveTextEmitted = true;
|
|
@@ -237,24 +243,31 @@ function aggregateGeminiStreamChunks(responses, label = 'Gemini stream') {
|
|
|
237
243
|
// An error envelope anywhere in the stream — including after STOP — fails
|
|
238
244
|
// the turn instead of aggregating into a success.
|
|
239
245
|
for (const response of responses) assertNoGeminiInBandError(response, label);
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
246
|
+
const aggregatedResponse = {};
|
|
247
|
+
// Candidates are keyed by their own `index`; chunks that omit it fall back
|
|
248
|
+
// to the position inside that chunk's candidate list.
|
|
249
|
+
const candidatesByIndex = new Map();
|
|
244
250
|
for (const response of responses) {
|
|
251
|
+
// Early block info must survive later chunks that carry none.
|
|
252
|
+
if (response?.promptFeedback) {
|
|
253
|
+
aggregatedResponse.promptFeedback = { ...aggregatedResponse.promptFeedback, ...response.promptFeedback };
|
|
254
|
+
}
|
|
245
255
|
if (response?.candidates) {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (!
|
|
249
|
-
|
|
250
|
-
|
|
256
|
+
response.candidates.forEach((candidate, position) => {
|
|
257
|
+
const candidateIndex = Number.isInteger(candidate?.index) ? candidate.index : position;
|
|
258
|
+
if (!candidatesByIndex.has(candidateIndex)) candidatesByIndex.set(candidateIndex, { index: candidateIndex });
|
|
259
|
+
const aggCand = candidatesByIndex.get(candidateIndex);
|
|
260
|
+
// A later chunk that omits a field never erases an earlier value.
|
|
261
|
+
if (candidate.citationMetadata !== undefined) {
|
|
262
|
+
aggCand.citationMetadata = mergeStreamMetadata(aggCand.citationMetadata, candidate.citationMetadata);
|
|
251
263
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
aggCand.finishReason = candidate.finishReason;
|
|
256
|
-
aggCand.finishMessage = candidate.finishMessage;
|
|
257
|
-
aggCand.safetyRatings = candidate.safetyRatings;
|
|
264
|
+
if (candidate.groundingMetadata !== undefined) {
|
|
265
|
+
aggCand.groundingMetadata = mergeStreamMetadata(aggCand.groundingMetadata, candidate.groundingMetadata);
|
|
266
|
+
}
|
|
267
|
+
if (geminiFinishReasonKind(candidate.finishReason) !== 'none') aggCand.finishReason = candidate.finishReason;
|
|
268
|
+
if (candidate.finishMessage !== undefined) aggCand.finishMessage = candidate.finishMessage;
|
|
269
|
+
if (candidate.safetyRatings !== undefined) aggCand.safetyRatings = candidate.safetyRatings;
|
|
270
|
+
if (candidate.continuationToken !== undefined) aggCand.continuationToken = candidate.continuationToken;
|
|
258
271
|
if (candidate.content?.parts) {
|
|
259
272
|
if (!aggCand.content) {
|
|
260
273
|
aggCand.content = {
|
|
@@ -273,36 +286,52 @@ function aggregateGeminiStreamChunks(responses, label = 'Gemini stream') {
|
|
|
273
286
|
aggCand.content.parts.push(newPart);
|
|
274
287
|
}
|
|
275
288
|
}
|
|
276
|
-
|
|
277
|
-
}
|
|
289
|
+
});
|
|
278
290
|
}
|
|
279
291
|
if (response?.usageMetadata) aggregatedResponse.usageMetadata = response.usageMetadata;
|
|
280
292
|
}
|
|
293
|
+
if (candidatesByIndex.size) {
|
|
294
|
+
aggregatedResponse.candidates = [...candidatesByIndex.values()].sort((a, b) => a.index - b.index);
|
|
295
|
+
}
|
|
281
296
|
return aggregatedResponse;
|
|
282
297
|
}
|
|
283
298
|
|
|
284
|
-
//
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
299
|
+
// GroundingMetadata / CitationMetadata arrive in pieces while streaming and
|
|
300
|
+
// are merged, not replaced: groundingChunks carry only the chunks not sent
|
|
301
|
+
// before (appended as-is, so groundingSupports indices stay valid); every
|
|
302
|
+
// other list is a de-duplicated union, nested objects merge, scalars take the
|
|
303
|
+
// latest value.
|
|
304
|
+
function mergeStreamMetadata(previous, next) {
|
|
305
|
+
if (!previous) return next;
|
|
306
|
+
if (!next || typeof next !== 'object') return previous;
|
|
307
|
+
const merged = { ...previous };
|
|
308
|
+
for (const [key, value] of Object.entries(next)) {
|
|
309
|
+
if (value === undefined || value === null) continue;
|
|
310
|
+
const before = previous[key];
|
|
311
|
+
if (Array.isArray(value)) {
|
|
312
|
+
if (key === 'groundingChunks') {
|
|
313
|
+
merged[key] = [...(before || []), ...value];
|
|
314
|
+
} else {
|
|
315
|
+
const seen = new Set((before || []).map((item) => JSON.stringify(item)));
|
|
316
|
+
merged[key] = [...(before || []), ...value.filter((item) => !seen.has(JSON.stringify(item)))];
|
|
317
|
+
}
|
|
318
|
+
} else if (typeof value === 'object' && before && typeof before === 'object') {
|
|
319
|
+
merged[key] = { ...before, ...value };
|
|
320
|
+
} else {
|
|
321
|
+
merged[key] = value;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return merged;
|
|
290
325
|
}
|
|
291
326
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
label,
|
|
297
|
-
acceptEmptyNoFinish = false,
|
|
298
|
-
aggregated = null,
|
|
299
|
-
}) {
|
|
327
|
+
// A stream that ends with no finishReason is unfinished, whatever it carried
|
|
328
|
+
// (thoughts only, an empty body, even right after a tool result); only a
|
|
329
|
+
// STOP that carries no text is a completed, empty answer.
|
|
330
|
+
function assertGeminiStreamCompleted({ sawStreamChunk, finishReason, promptBlockReason, label }) {
|
|
300
331
|
if (!sawStreamChunk) {
|
|
301
332
|
throw geminiTruncatedStreamError(`${label} truncated: empty stream`);
|
|
302
333
|
}
|
|
303
|
-
if (
|
|
304
|
-
// Right after a tool result the model may end with nothing at all.
|
|
305
|
-
if (acceptEmptyNoFinish && hasNoAnswerContent(aggregated)) return;
|
|
334
|
+
if (geminiFinishReasonKind(finishReason) === 'none' && geminiFinishReasonKind(promptBlockReason) === 'none') {
|
|
306
335
|
throw geminiTruncatedStreamError(`${label} truncated: no finishReason`);
|
|
307
336
|
}
|
|
308
337
|
}
|
|
@@ -344,13 +373,23 @@ function relayGeminiStreamText(t, { onTextDelta, textLeakGuard }) {
|
|
|
344
373
|
* `part.text` streams. Mirrors the Anthropic OAuth guard: suppress tags from
|
|
345
374
|
* visible text, synthesize known-tool calls, dispatch via onToolCall.
|
|
346
375
|
*/
|
|
347
|
-
export function createGeminiTextLeakGuard({
|
|
376
|
+
export function createGeminiTextLeakGuard({
|
|
377
|
+
knownToolNames,
|
|
378
|
+
onTextDelta,
|
|
379
|
+
onToolCall,
|
|
380
|
+
onStreamDelta,
|
|
381
|
+
deferToolCalls = false,
|
|
382
|
+
}) {
|
|
348
383
|
const _knownTools = knownToolNameSet(knownToolNames);
|
|
349
384
|
const _enabled = _knownTools.size > 0;
|
|
350
385
|
const _isKnownTool = (name) => _knownTools.has(name);
|
|
351
386
|
let leakBuffer = '';
|
|
352
387
|
let relayedText = '';
|
|
353
388
|
const leakedCalls = [];
|
|
389
|
+
// With `deferToolCalls`, recovered calls wait here until the caller has seen
|
|
390
|
+
// the response finish cleanly (releaseDeferredToolCalls); a failed response
|
|
391
|
+
// never runs them.
|
|
392
|
+
const deferredCalls = [];
|
|
354
393
|
const dispatchedFingerprints = new Set();
|
|
355
394
|
|
|
356
395
|
const dispatchLeakedCall = (recovered) => {
|
|
@@ -372,9 +411,12 @@ export function createGeminiTextLeakGuard({ knownToolNames, onTextDelta, onToolC
|
|
|
372
411
|
arguments: args,
|
|
373
412
|
};
|
|
374
413
|
leakedCalls.push(call);
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
414
|
+
if (deferToolCalls) deferredCalls.push(call);
|
|
415
|
+
else {
|
|
416
|
+
try {
|
|
417
|
+
onToolCall?.(call);
|
|
418
|
+
} catch {}
|
|
419
|
+
}
|
|
378
420
|
try {
|
|
379
421
|
onStreamDelta?.('tool');
|
|
380
422
|
} catch {}
|
|
@@ -401,6 +443,9 @@ export function createGeminiTextLeakGuard({ knownToolNames, onTextDelta, onToolC
|
|
|
401
443
|
get enabled() {
|
|
402
444
|
return _enabled;
|
|
403
445
|
},
|
|
446
|
+
get defersToolCalls() {
|
|
447
|
+
return deferToolCalls === true;
|
|
448
|
+
},
|
|
404
449
|
feedText(text) {
|
|
405
450
|
if (!text) return;
|
|
406
451
|
if (!_enabled) {
|
|
@@ -439,6 +484,13 @@ export function createGeminiTextLeakGuard({ knownToolNames, onTextDelta, onToolC
|
|
|
439
484
|
getLeakedToolCalls() {
|
|
440
485
|
return [...leakedCalls];
|
|
441
486
|
},
|
|
487
|
+
releaseDeferredToolCalls() {
|
|
488
|
+
for (const call of deferredCalls.splice(0)) {
|
|
489
|
+
try {
|
|
490
|
+
onToolCall?.(call);
|
|
491
|
+
} catch {}
|
|
492
|
+
}
|
|
493
|
+
},
|
|
442
494
|
getRelayedText() {
|
|
443
495
|
return relayedText;
|
|
444
496
|
},
|
|
@@ -473,7 +525,6 @@ export async function consumeGeminiRestStreamResponse(
|
|
|
473
525
|
unwrapChunk = null,
|
|
474
526
|
onChunk = null,
|
|
475
527
|
failureUsage = null,
|
|
476
|
-
acceptEmptyNoFinish = false,
|
|
477
528
|
}
|
|
478
529
|
) {
|
|
479
530
|
const unwrap =
|
|
@@ -613,8 +664,6 @@ export async function consumeGeminiRestStreamResponse(
|
|
|
613
664
|
finishReason,
|
|
614
665
|
promptBlockReason,
|
|
615
666
|
label,
|
|
616
|
-
acceptEmptyNoFinish,
|
|
617
|
-
aggregated,
|
|
618
667
|
});
|
|
619
668
|
} catch (err) {
|
|
620
669
|
throw stampGeminiStreamFailure(err, { relayedText, textLeakGuard, chunks: allChunks, failureUsage });
|
|
@@ -634,7 +683,6 @@ export async function consumeGeminiSdkStream(
|
|
|
634
683
|
firstByteTimeoutMs = GEMINI_FIRST_BYTE_TIMEOUT_MS,
|
|
635
684
|
cancellationGraceMs = 250,
|
|
636
685
|
failureUsage = null,
|
|
637
|
-
acceptEmptyNoFinish = false,
|
|
638
686
|
}
|
|
639
687
|
) {
|
|
640
688
|
let relayedText = '';
|
|
@@ -721,8 +769,6 @@ export async function consumeGeminiSdkStream(
|
|
|
721
769
|
finishReason,
|
|
722
770
|
promptBlockReason,
|
|
723
771
|
label,
|
|
724
|
-
acceptEmptyNoFinish,
|
|
725
|
-
aggregated: raw,
|
|
726
772
|
});
|
|
727
773
|
return raw;
|
|
728
774
|
} catch (err) {
|
|
@@ -15,14 +15,53 @@ function catalogThinkingLevels(model, provider) {
|
|
|
15
15
|
return declared.length ? [...new Set(declared)] : null;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
// Gemini 2.5 models take thinkingBudget only (thinkingLevel is unsupported).
|
|
19
|
+
// Documented ranges: 2.5 Pro 128–32768 (cannot disable), 2.5 Flash 0–24576,
|
|
20
|
+
// 2.5 Flash-Lite 0 or 512–24576; -1 is dynamic thinking for all of them.
|
|
21
|
+
function budgetSpec(model) {
|
|
22
|
+
const bare = String(model || '').replace(/^models\//i, '').toLowerCase();
|
|
23
|
+
if (!/^gemini-2\.5(?:-|$)/.test(bare)) return null;
|
|
24
|
+
if (/^gemini-2\.5-pro/.test(bare)) {
|
|
25
|
+
return { name: 'Gemini 2.5 Pro', min: 128, max: 32768, canDisable: false, efforts: { minimal: 128, low: 1024, medium: 8192, high: 32768 } };
|
|
26
|
+
}
|
|
27
|
+
if (/^gemini-2\.5-flash-lite/.test(bare)) {
|
|
28
|
+
return { name: 'Gemini 2.5 Flash-Lite', min: 512, max: 24576, canDisable: true, efforts: { minimal: 512, low: 1024, medium: 8192, high: 24576 } };
|
|
29
|
+
}
|
|
30
|
+
return { name: 'Gemini 2.5 Flash', min: 0, max: 24576, canDisable: true, efforts: { minimal: 0, low: 1024, medium: 8192, high: 24576 } };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Levels documented for models whose ladder differs from the generic wire
|
|
34
|
+
// vocabulary (a catalog ladder, when declared, still takes precedence).
|
|
35
|
+
function documentedThinkingLevels(model) {
|
|
36
|
+
const bare = String(model || '').replace(/^models\//i, '').toLowerCase();
|
|
37
|
+
if (bare === 'gemini-4-argon' || bare === 'gemini-3.8-flash') return ['low', 'medium', 'high'];
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function checkBudget(model, spec, budget) {
|
|
42
|
+
if (!Number.isInteger(budget) || budget < -1) {
|
|
43
|
+
throw new TypeError('thinkingBudget must be -1 (dynamic), 0, or a positive integer.');
|
|
44
|
+
}
|
|
45
|
+
if (!spec || budget === -1) return;
|
|
46
|
+
if (budget === 0 && !spec.canDisable) {
|
|
47
|
+
throw new TypeError(`${model} (${spec.name}) cannot disable thinking; thinkingBudget 0 is not allowed.`);
|
|
48
|
+
}
|
|
49
|
+
if (budget !== 0 && (budget < spec.min || budget > spec.max)) {
|
|
50
|
+
throw new TypeError(`${model} (${spec.name}) thinkingBudget must be -1, ${spec.canDisable ? '0, or ' : ''}${spec.min}–${spec.max}; received ${budget}.`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Only translate the public option names. Omitting settings preserves the
|
|
55
|
+
// provider's model default. Gemini 2.5 models use thinkingBudget (a generic
|
|
56
|
+
// effort maps to a budget; an explicit thinkingLevel is rejected locally and
|
|
57
|
+
// budgets are range-checked). Other models use thinkingLevel, checked against
|
|
58
|
+
// the catalog/documented ladder; unknown models pass values within the wire
|
|
59
|
+
// vocabulary and the server decides.
|
|
23
60
|
export function geminiThinkingConfig(model, opts = {}, { includeThoughts, provider = 'gemini' } = {}) {
|
|
24
61
|
const rawBudget = opts.thinkingBudget ?? opts.thinkingBudgetTokens;
|
|
25
62
|
const hasBudget = rawBudget !== undefined && rawBudget !== null && rawBudget !== '';
|
|
63
|
+
const spec = budgetSpec(model);
|
|
64
|
+
const explicitLevel = opts.thinkingLevel == null ? '' : String(opts.thinkingLevel).trim().toLowerCase();
|
|
26
65
|
const rawLevel = opts.thinkingLevel ?? (hasBudget ? undefined : opts.effort);
|
|
27
66
|
const level = rawLevel == null ? '' : String(rawLevel).trim().toLowerCase();
|
|
28
67
|
const config = {};
|
|
@@ -31,8 +70,16 @@ export function geminiThinkingConfig(model, opts = {}, { includeThoughts, provid
|
|
|
31
70
|
if (level && hasBudget) {
|
|
32
71
|
throw new TypeError('Choose thinkingLevel/effort or thinkingBudget, not both.');
|
|
33
72
|
}
|
|
34
|
-
if (
|
|
35
|
-
|
|
73
|
+
if (spec && explicitLevel) {
|
|
74
|
+
throw new TypeError(`${model} (${spec.name}) does not support thinkingLevel; use thinkingBudget.`);
|
|
75
|
+
}
|
|
76
|
+
if (spec && level) {
|
|
77
|
+
if (!Object.hasOwn(spec.efforts, level)) {
|
|
78
|
+
throw new TypeError(`${model} supports thinking levels ${Object.keys(spec.efforts).join(', ')}; received ${level}.`);
|
|
79
|
+
}
|
|
80
|
+
config.thinkingBudget = spec.efforts[level];
|
|
81
|
+
} else if (level) {
|
|
82
|
+
const supported = catalogThinkingLevels(model, provider) ?? documentedThinkingLevels(model) ?? LEVELS;
|
|
36
83
|
if (!supported.includes(level)) {
|
|
37
84
|
throw new TypeError(`${model} supports thinking levels ${supported.join(', ')}; received ${level}.`);
|
|
38
85
|
}
|
|
@@ -40,9 +87,7 @@ export function geminiThinkingConfig(model, opts = {}, { includeThoughts, provid
|
|
|
40
87
|
}
|
|
41
88
|
if (hasBudget) {
|
|
42
89
|
const budget = Number(rawBudget);
|
|
43
|
-
|
|
44
|
-
throw new TypeError('thinkingBudget must be -1 (dynamic), 0, or a positive integer.');
|
|
45
|
-
}
|
|
90
|
+
checkBudget(model, spec, budget);
|
|
46
91
|
config.thinkingBudget = budget;
|
|
47
92
|
}
|
|
48
93
|
return Object.keys(config).length ? config : undefined;
|
|
@@ -17,7 +17,12 @@ import {
|
|
|
17
17
|
} from '../stall-policy.mjs';
|
|
18
18
|
import { getLlmDispatcher, preconnect } from '../../../shared/llm/http-agent.mjs';
|
|
19
19
|
import { GEMINI_FIRST_BYTE_TIMEOUT_MS, consumeGeminiRestStreamResponse } from './gemini-stream.mjs';
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
applyGeminiErrorContract,
|
|
22
|
+
geminiContinuationUnsupportedError,
|
|
23
|
+
geminiFinishErrorFields,
|
|
24
|
+
geminiFinishReasonKind,
|
|
25
|
+
} from './gemini-error-contract.mjs';
|
|
21
26
|
import {
|
|
22
27
|
GEMINI_MIDSTREAM_MAX_ATTEMPTS,
|
|
23
28
|
geminiEndsWithFunctionResponse,
|
|
@@ -50,6 +55,7 @@ import {
|
|
|
50
55
|
import {
|
|
51
56
|
awaitSharedCreate,
|
|
52
57
|
dropRejectedGeminiCache,
|
|
58
|
+
geminiBareModelId,
|
|
53
59
|
geminiCacheCreateBody,
|
|
54
60
|
geminiCacheEntry,
|
|
55
61
|
geminiCachePrefixIdentity,
|
|
@@ -275,6 +281,10 @@ export class GeminiProvider {
|
|
|
275
281
|
if (decision.canReuseState) {
|
|
276
282
|
return state.cacheName;
|
|
277
283
|
}
|
|
284
|
+
// A request forked from a shared prefix (/btw: opts.sharedCachePrefixCount)
|
|
285
|
+
// only reads the session's live cache. Creating or refreshing one would
|
|
286
|
+
// store the fork's own suffix (the appended reply and question).
|
|
287
|
+
if (opts.sharedCachePrefixCount) return decision.canAttachState ? state.cacheName : null;
|
|
278
288
|
if (!apiKey || geminiExplicitCacheRefused(model)) return null;
|
|
279
289
|
const { canAttachState } = decision;
|
|
280
290
|
if (geminiPrefixBelowMinimum({ model, systemInstruction, geminiTools, contents, opts, currentIter })) {
|
|
@@ -584,10 +594,15 @@ export class GeminiProvider {
|
|
|
584
594
|
cachedContent,
|
|
585
595
|
});
|
|
586
596
|
const parsed = parseGeminiCandidate(response, textLeakGuard);
|
|
587
|
-
emitGeminiToolCalls(parsed.nativeToolCalls, callbacks.onToolCall);
|
|
588
597
|
const usage = resolveGeminiUsage(response, opts, cachedContent, useModel);
|
|
598
|
+
// Terminal status first: a failed candidate's calls are never dispatched.
|
|
589
599
|
const incomplete = geminiIncompleteError(response, parsed, useModel, usage);
|
|
590
600
|
if (incomplete) {
|
|
601
|
+
Object.assign(incomplete, geminiFinishErrorFields(response));
|
|
602
|
+
if (geminiFinishReasonKind(incomplete.finishReason) === 'continuation') {
|
|
603
|
+
// Direct Gemini only: surface the typed result with its token.
|
|
604
|
+
throw geminiContinuationUnsupportedError(incomplete, response);
|
|
605
|
+
}
|
|
591
606
|
// A malformed / unexpected tool call that survived the stream ladder
|
|
592
607
|
// (4 attempts) is spent; the loop must not multiply that budget.
|
|
593
608
|
if (
|
|
@@ -599,6 +614,8 @@ export class GeminiProvider {
|
|
|
599
614
|
}
|
|
600
615
|
throw incomplete;
|
|
601
616
|
}
|
|
617
|
+
textLeakGuard?.releaseDeferredToolCalls?.();
|
|
618
|
+
emitGeminiToolCalls(parsed.nativeToolCalls, callbacks.onToolCall);
|
|
602
619
|
return geminiSendResult(parsed, useModel, opts, usage);
|
|
603
620
|
}
|
|
604
621
|
|
|
@@ -626,7 +643,7 @@ export class GeminiProvider {
|
|
|
626
643
|
}
|
|
627
644
|
|
|
628
645
|
async _restGenerateContent(useModel, apiKey, body, fallbackSignal) {
|
|
629
|
-
const nonStreamUrl = `https://generativelanguage.googleapis.com/v1beta/models/${encodeURIComponent(useModel)}:generateContent?key=${encodeURIComponent(apiKey)}`;
|
|
646
|
+
const nonStreamUrl = `https://generativelanguage.googleapis.com/v1beta/models/${encodeURIComponent(geminiBareModelId(useModel))}:generateContent?key=${encodeURIComponent(apiKey)}`;
|
|
630
647
|
const res = await this._fetch(nonStreamUrl, {
|
|
631
648
|
method: 'POST',
|
|
632
649
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -650,10 +667,10 @@ export class GeminiProvider {
|
|
|
650
667
|
// { retryUncached: true } when the cache itself was rejected and the send
|
|
651
668
|
// must be replayed without it.
|
|
652
669
|
async _streamCachedViaRest(stream, internal) {
|
|
653
|
-
const { opts, signal, useModel, contents, generationConfig, cachedContent, callbacks } = stream;
|
|
670
|
+
const { opts, signal, useModel, contents, generationConfig, safetySettings, cachedContent, callbacks } = stream;
|
|
654
671
|
const apiKey = this._getApiKey();
|
|
655
|
-
const genUrl = `https://generativelanguage.googleapis.com/v1beta/models/${encodeURIComponent(useModel)}:streamGenerateContent?alt=sse&key=${encodeURIComponent(apiKey)}`;
|
|
656
|
-
const body = geminiCachedRestBody({ opts, contents, cachedContent, generationConfig });
|
|
672
|
+
const genUrl = `https://generativelanguage.googleapis.com/v1beta/models/${encodeURIComponent(geminiBareModelId(useModel))}:streamGenerateContent?alt=sse&key=${encodeURIComponent(apiKey)}`;
|
|
673
|
+
const body = geminiCachedRestBody({ opts, contents, cachedContent, generationConfig, safetySettings });
|
|
657
674
|
// cachedContent owns tools + toolConfig. The API rejects a
|
|
658
675
|
// generateContent request that repeats either field.
|
|
659
676
|
// Option A (mirror anthropic-oauth): no absolute wall-clock cap on a
|
|
@@ -679,7 +696,6 @@ export class GeminiProvider {
|
|
|
679
696
|
connected();
|
|
680
697
|
const textLeakGuard = geminiTextLeakGuardFor(stream);
|
|
681
698
|
const response = await consumeGeminiRestStreamResponse(res, {
|
|
682
|
-
acceptEmptyNoFinish: afterToolResult,
|
|
683
699
|
signal: attemptSignal,
|
|
684
700
|
onStreamDelta: callbacks.onStreamDelta,
|
|
685
701
|
onTextDelta: callbacks.onTextDelta,
|
|
@@ -715,13 +731,15 @@ export class GeminiProvider {
|
|
|
715
731
|
}
|
|
716
732
|
|
|
717
733
|
async _streamViaSdk(stream) {
|
|
718
|
-
const { opts, signal, useModel, systemInstruction, geminiTools, toolConfig, generationConfig, contents } =
|
|
734
|
+
const { opts, signal, useModel, systemInstruction, geminiTools, toolConfig, generationConfig, safetySettings, contents } =
|
|
735
|
+
stream;
|
|
719
736
|
const genModel = this._currentGenAI().getGenerativeModel({
|
|
720
737
|
model: useModel,
|
|
721
738
|
systemInstruction,
|
|
722
739
|
tools: geminiTools,
|
|
723
740
|
...(toolConfig ? { toolConfig } : {}),
|
|
724
741
|
...(generationConfig ? { generationConfig } : {}),
|
|
742
|
+
...(safetySettings ? { safetySettings } : {}),
|
|
725
743
|
});
|
|
726
744
|
// Option A (mirror anthropic-oauth): pure pass-through of the external
|
|
727
745
|
// signal, no absolute streaming total cap. See the REST path.
|
|
@@ -3,7 +3,7 @@ import { createNpmVersionSource, maxSemver } from './npm-cli-version.mjs';
|
|
|
3
3
|
// Grok CLI client version for the cli-chat-proxy version gate (HTTP 426).
|
|
4
4
|
// Effective = env override, else max(floor, learned-from-426, live npm latest
|
|
5
5
|
// of the official @xai-official/grok CLI).
|
|
6
|
-
export const GROK_CLI_VERSION_FLOOR = '1.0.
|
|
6
|
+
export const GROK_CLI_VERSION_FLOOR = '1.0.60';
|
|
7
7
|
export const GROK_CLI_NPM_PACKAGE = '@xai-official/grok';
|
|
8
8
|
|
|
9
9
|
const live = createNpmVersionSource(GROK_CLI_NPM_PACKAGE, { persistKey: 'grok-cli' });
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { mergeFlatSchemaProperty } from './flat-schema-merge.mjs';
|
|
2
|
+
|
|
1
3
|
// Preserve action-specific input rules when a provider needs a flat schema.
|
|
2
4
|
// Field definitions remain shared; only the per-action field names and differing
|
|
3
5
|
// enums/bounds are repeated, rather than copying every full schema branch.
|
|
@@ -34,3 +36,61 @@ export function actionInputContract(schema) {
|
|
|
34
36
|
});
|
|
35
37
|
return `Allowed input by action (* required): ${rows.join('; ')}.`;
|
|
36
38
|
}
|
|
39
|
+
|
|
40
|
+
// A per-action input union: the root's `action` enum and an `input` whose
|
|
41
|
+
// anyOf alternatives are object schemas, each titled with the one action it
|
|
42
|
+
// belongs to. Returns those alternatives as action/input branches, or null.
|
|
43
|
+
function actionInputBranches(schema) {
|
|
44
|
+
const actions = schema?.properties?.action?.enum;
|
|
45
|
+
const alternatives = schema?.properties?.input?.anyOf;
|
|
46
|
+
if (!Array.isArray(actions) || !Array.isArray(alternatives) || !alternatives.length) return null;
|
|
47
|
+
const branches = alternatives.map((alternative) =>
|
|
48
|
+
alternative?.properties && actions.includes(alternative.title)
|
|
49
|
+
? { properties: { action: { enum: [alternative.title] }, input: alternative } }
|
|
50
|
+
: null
|
|
51
|
+
);
|
|
52
|
+
return branches.every(Boolean) ? branches : null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** The flat projection of a per-action input union: `input` becomes the
|
|
56
|
+
* merged field set of every alternative, its description listing the fields
|
|
57
|
+
* per action. Any other schema is returned as is; the input is never mutated. */
|
|
58
|
+
export function flattenActionInputUnion(schema) {
|
|
59
|
+
const branches = actionInputBranches(schema);
|
|
60
|
+
if (!branches) return schema;
|
|
61
|
+
const { anyOf: _anyOf, description, ...base } = schema.properties.input;
|
|
62
|
+
const merged = branches
|
|
63
|
+
.map(({ properties }) => {
|
|
64
|
+
const { title: _title, description: _description, ...shape } = properties.input;
|
|
65
|
+
return shape;
|
|
66
|
+
})
|
|
67
|
+
.reduce((current, shape) => mergeFlatSchemaProperty(current, shape));
|
|
68
|
+
const contract = actionInputContract({ oneOf: branches });
|
|
69
|
+
return {
|
|
70
|
+
...schema,
|
|
71
|
+
properties: {
|
|
72
|
+
...schema.properties,
|
|
73
|
+
input: { ...base, ...merged, description: [description, contract].filter(Boolean).join(' ') },
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Nested per-action input unions keyed by their flat projection's JSON. A tool
|
|
79
|
+
// advertises the flat projection on every path; only provider paths verified
|
|
80
|
+
// to accept nested alternatives opt in through actionInputUnionFor. Keyed by
|
|
81
|
+
// content, so a request snapshot's clone still resolves.
|
|
82
|
+
const nestedByFlat = new Map();
|
|
83
|
+
|
|
84
|
+
/** Register `nested` (a per-action input union) and return the flat
|
|
85
|
+
* projection the tool advertises. */
|
|
86
|
+
export function advertiseActionInputUnion(nested) {
|
|
87
|
+
const flat = flattenActionInputUnion(nested);
|
|
88
|
+
nestedByFlat.set(JSON.stringify(flat), nested);
|
|
89
|
+
return flat;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** The registered nested union for an advertised flat schema, else `schema`. */
|
|
93
|
+
export function actionInputUnionFor(schema) {
|
|
94
|
+
if (!schema?.properties?.action || !schema.properties.input) return schema;
|
|
95
|
+
return nestedByFlat.get(JSON.stringify(schema)) ?? schema;
|
|
96
|
+
}
|
|
@@ -19,6 +19,7 @@ export const NATIVE_SERVER_TOOL_RESULT_BLOCK_TYPES = new Set([
|
|
|
19
19
|
'bash_code_execution_tool_result',
|
|
20
20
|
'text_editor_code_execution_tool_result',
|
|
21
21
|
'mcp_tool_result',
|
|
22
|
+
'tool_search_tool_result',
|
|
22
23
|
]);
|
|
23
24
|
|
|
24
25
|
export function isNativeServerToolBlockType(type) {
|