mixdog 1.0.11 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +20 -0
- package/README.md +75 -181
- package/package.json +9 -4
- package/scripts/build-shipped-history.mjs +131 -0
- package/scripts/check-changelog-locales.mjs +203 -0
- package/scripts/computer-task-cost-report.mjs +0 -4
- package/scripts/lib/run-node-tests.mjs +235 -13
- package/scripts/lib/test-failure-records.mjs +5 -0
- package/scripts/lib/test-failure-summary.mjs +9 -3
- package/scripts/lib/test-spawn-ledger.mjs +19 -0
- package/scripts/prune-embedding-runtime.mjs +9 -5
- package/scripts/sync-client-version-floors.mjs +100 -0
- package/scripts/test-direct.mjs +16 -1
- package/src/agents/advisor/AGENT.md +38 -0
- package/src/agents/advisor/agent.json +6 -0
- package/src/agents/reviewer/AGENT.md +5 -2
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +381 -0
- package/src/defaults/skills/docx/SKILL.md +7 -5
- package/src/defaults/skills/docx/references/html.md +9 -8
- package/src/defaults/skills/docx/references/native-authoring.md +28 -18
- package/src/defaults/skills/goal-management/SKILL.md +11 -5
- package/src/defaults/skills/local-provider/SKILL.md +2 -1
- package/src/defaults/skills/pdf/SKILL.md +9 -6
- package/src/defaults/skills/pdf/references/html.md +17 -12
- package/src/defaults/skills/pptx/SKILL.md +8 -6
- package/src/defaults/skills/pptx/references/composition.md +4 -4
- package/src/defaults/skills/pptx/references/concepts.md +168 -0
- package/src/defaults/skills/pptx/references/direction.md +5 -4
- package/src/defaults/skills/pptx/references/html.md +6 -29
- package/src/defaults/skills/pptx/references/kit-index.md +11 -3
- package/src/defaults/skills/pptx/references/kit.md +27 -5
- package/src/defaults/skills/pptx/references/review.md +6 -5
- package/src/defaults/skills/setup/SKILL.md +5 -8
- package/src/defaults/skills/setup/references/actions.md +61 -31
- package/src/defaults/skills/setup/references/surfaces.md +12 -10
- package/src/defaults/skills/xlsx/SKILL.md +8 -6
- package/src/defaults/skills/xlsx/references/html.md +8 -4
- package/src/defaults/skills/xlsx/references/model-conventions.md +2 -0
- package/src/defaults/skills/xlsx/references/report-design.md +32 -16
- package/src/help.mjs +1 -1
- package/src/lib/rules-builder.cjs +1 -1
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +3 -1
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +4 -0
- package/src/runtime/agent/orchestrator/config-presets.d.mts +1 -0
- package/src/runtime/agent/orchestrator/config-presets.mjs +44 -0
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +9 -1
- package/src/runtime/agent/orchestrator/config.mjs +102 -21
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +90 -26
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +44 -14
- package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +4 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +79 -8
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +29 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +11 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +9 -5
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +30 -22
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +28 -10
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +14 -72
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +19 -3
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +20 -10
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-sink.mjs +36 -9
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +11 -17
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +388 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +92 -109
- package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +107 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +138 -30
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +32 -15
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +39 -5
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/lib/note-error-usage.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +57 -0
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +12 -5
- package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +20 -15
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +14 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +56 -11
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +28 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +27 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +7 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +23 -8
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +26 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +34 -15
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +12 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +0 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +0 -19
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +12 -43
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +39 -9
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +31 -9
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +13 -38
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +40 -9
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +7 -39
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +28 -101
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +8 -4
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +3 -6
- package/src/runtime/agent/orchestrator/providers/openai-service-tier.mjs +19 -0
- package/src/runtime/agent/orchestrator/providers/openai-startup-prewarm.mjs +5 -195
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +9 -18
- package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +4 -66
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +11 -5
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/acquire-attempt.mjs +3 -15
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/attempt-request.mjs +6 -56
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +1 -19
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure-stamps.mjs +0 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts.mjs +3 -5
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-outcome.mjs +10 -89
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-span.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-trace.mjs +0 -6
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +34 -11
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +0 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +3 -7
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +44 -19
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +40 -12
- package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +70 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +38 -3
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +11 -0
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +31 -41
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +5 -0
- package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +0 -17
- package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +0 -3
- package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +0 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +1 -2
- package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +18 -4
- package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +8 -1
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +7 -1
- package/src/runtime/agent/orchestrator/runtime-core/session-route-policy.mjs +16 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -2
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +7 -7
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +45 -2
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/eager-dispatch/entry.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +6 -13
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +114 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +5 -9
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +51 -18
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +7 -4
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +0 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +6 -9
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +63 -3
- package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +10 -28
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +4 -4
- package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +10 -19
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +1 -3
- package/src/runtime/agent/orchestrator/stall-policy.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +18 -8
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +19 -20
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +6 -11
- package/src/runtime/agent/orchestrator/tools/builtin/file-version-test-helpers.mjs +11 -0
- package/src/runtime/agent/orchestrator/tools/builtin/file-version.mjs +13 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-single-file-rescue.mjs +8 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +25 -12
- package/src/runtime/agent/orchestrator/tools/builtin/raw-content-publication.mjs +17 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +136 -76
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +15 -17
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +11 -10
- package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +30 -16
- package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/snapshot-helpers.mjs +4 -11
- package/src/runtime/agent/orchestrator/tools/builtin/snapshot-store.mjs +7 -3
- package/src/runtime/agent/orchestrator/tools/builtin/snapshot-validation.mjs +16 -19
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +14 -4
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +58 -8
- package/src/runtime/agent/orchestrator/tools/patch/content-guard.mjs +47 -0
- package/src/runtime/agent/orchestrator/tools/patch/delete-quarantine.mjs +155 -0
- package/src/runtime/agent/orchestrator/tools/patch/dispatch/native-proofs.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/patch/dispatch/native-snapshots.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +19 -16
- package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +13 -44
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/patch/post-patch-excerpts.mjs +5 -2
- package/src/runtime/agent/orchestrator/tools/patch/replay-capture.mjs +47 -7
- package/src/runtime/agent/orchestrator/tools/patch/rollback-state.mjs +72 -8
- package/src/runtime/agent/orchestrator/tools/patch/section-coalesce.mjs +3 -2
- package/src/runtime/agent/orchestrator/tools/patch/sequence/run.mjs +9 -1
- package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +9 -1
- package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +16 -4
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +35 -14
- package/src/runtime/agent/orchestrator/tools/patch/wave.mjs +42 -4
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/shell-codepage.mjs +296 -0
- package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +75 -24
- package/src/runtime/browser-bridge/tool-defs.mjs +1 -0
- package/src/runtime/channels/lib/config.mjs +3 -8
- package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +7 -3
- package/src/{tui → runtime/channels}/lib/voice-setup.mjs +38 -22
- package/src/runtime/channels/lib/webhook/request-handler.mjs +42 -8
- package/src/runtime/computer-bridge/actions.mjs +2 -0
- package/src/runtime/effort-judge/judge-client.mjs +125 -25
- package/src/runtime/effort-judge/judge-input.mjs +96 -0
- package/src/runtime/effort-judge/judge-worker.mjs +52 -20
- package/src/runtime/effort-judge/model-install.mjs +74 -0
- package/src/runtime/effort-judge/model-manifest.json +21 -0
- package/src/runtime/effort-judge/previous-human-request.mjs +162 -0
- package/src/runtime/effort-judge/verified-context-input.mjs +10 -0
- package/src/runtime/github/tool.mjs +214 -14
- package/src/runtime/local-provider/context-settings.mjs +15 -6
- package/src/runtime/local-provider/gguf-header.mjs +13 -5
- package/src/runtime/local-provider/hugging-face.mjs +27 -5
- package/src/runtime/local-provider/install-progress.mjs +7 -0
- package/src/runtime/local-provider/managed-runtime.mjs +2 -1
- package/src/runtime/local-provider/model-maintenance.mjs +15 -6
- package/src/runtime/local-provider/resumable-installations.mjs +40 -1
- package/src/runtime/local-provider/server.mjs +2 -0
- package/src/runtime/memory/lib/embedding-provider.mjs +12 -0
- package/src/runtime/memory/lib/http-router/session-routes.mjs +2 -1
- package/src/runtime/memory/lib/memory-config-flags.mjs +3 -2
- package/src/runtime/memory/lib/memory-embed.mjs +5 -0
- package/src/runtime/memory/lib/pg/process.mjs +57 -5
- package/src/runtime/office/README.md +13 -7
- package/src/runtime/office/authoring/docx-html-build.mjs +4 -4
- package/src/runtime/office/authoring/docx-html-measure.mjs +60 -0
- package/src/runtime/office/authoring/pdf-author-action.mjs +6 -1
- package/src/runtime/office/authoring/pptx-brief.mjs +40 -1
- package/src/runtime/office/authoring/pptx-html-build.mjs +1 -1
- package/src/runtime/office/authoring/pptx-html-measure.mjs +1 -1
- package/src/runtime/office/bench/deck-bench.mjs +1 -1
- package/src/runtime/office/com/office-com-host.ps1 +8 -0
- package/src/runtime/office/core/office-actions-render.mjs +2 -0
- package/src/runtime/office/design/design-art-direction.mjs +10 -2
- package/src/runtime/office/design/design-discipline.mjs +4 -5
- package/src/runtime/office/design/design-tokens.mjs +20 -1
- package/src/runtime/office/design/docx/design-docx/front-matter.mjs +7 -4
- package/src/runtime/office/design/docx/design-docx/section.mjs +3 -1
- package/src/runtime/office/design/docx/design-docx/writer.mjs +1 -0
- package/src/runtime/office/design/docx/design-docx-components.mjs +19 -15
- package/src/runtime/office/design/docx/design-docx.mjs +5 -6
- package/src/runtime/office/design/docx/document-typography.mjs +20 -6
- package/src/runtime/office/design/xlsx/design-xlsx.mjs +9 -2
- package/src/runtime/office/pdf/document-preview.mjs +133 -12
- package/src/runtime/office/pdf/pdf-writer.mjs +56 -22
- package/src/runtime/office/portable/portable-snapshot-docx.mjs +46 -3
- package/src/runtime/office/portable/portable-snapshot-shared.mjs +27 -1
- package/src/runtime/office/quality/assurance-rendered.mjs +21 -5
- package/src/runtime/office/quality/assurance-structure-docx.mjs +41 -9
- package/src/runtime/office/quality/design-aesthetics.mjs +4 -2
- package/src/runtime/office/quality/design-deck-diversity.mjs +15 -3
- package/src/runtime/office/quality/design-review.mjs +13 -5
- package/src/runtime/office/quality/document-brief.mjs +8 -2
- package/src/runtime/office/quality/forced-break-pages.mjs +203 -0
- package/src/runtime/office/quality/pptx-deck-rubric.mjs +21 -3
- package/src/runtime/office/quality/quality-pipeline.mjs +14 -17
- package/src/runtime/session-search/session-search-db.mjs +183 -0
- package/src/runtime/session-search/session-search-ingest.mjs +106 -0
- package/src/runtime/shared/agent-route-config.mjs +50 -2
- package/src/runtime/shared/bounded-file-read.mjs +166 -0
- package/src/runtime/shared/builtin-grandfathering.mjs +37 -0
- package/src/runtime/shared/config.mjs +24 -4
- package/src/runtime/shared/defaults-separation.mjs +263 -0
- package/src/runtime/shared/error-presentation.mjs +8 -1
- package/src/runtime/shared/llm/anthropic-effort.mjs +4 -0
- package/src/runtime/shared/llm/cost.mjs +4 -2
- package/src/runtime/shared/llm/model-catalog-projection.mjs +1 -1
- package/src/runtime/shared/llm/model-catalog.mjs +25 -0
- package/src/runtime/shared/llm/reasoning-usage.mjs +1 -2
- package/src/runtime/shared/llm/usage-accounting.mjs +14 -4
- package/src/runtime/shared/llm/usage-context.mjs +11 -1
- package/src/runtime/shared/llm/usage-ledger-repair.mjs +3 -1
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +105 -1
- package/src/runtime/shared/llm/usage-ledger-worker.mjs +2 -1
- package/src/runtime/shared/llm/usage-ledger.mjs +72 -5
- package/src/runtime/shared/onnx-runtime-support.mjs +6 -0
- package/src/runtime/shared/orchestration.mjs +14 -6
- package/src/runtime/shared/pristine-execution-contract.json +7 -2
- package/src/runtime/shared/projects.mjs +65 -48
- package/src/runtime/shared/provider-accounts.mjs +47 -6
- package/src/runtime/shared/quota-resume-store.mjs +255 -0
- package/src/runtime/shared/shipped-definitions.mjs +275 -0
- package/src/runtime/shared/tool-card-model/agent-surface.mjs +30 -9
- package/src/runtime/shared/tool-card-model/aggregate-card.mjs +7 -3
- package/src/runtime/shared/tool-card-model/background-task.mjs +17 -1
- package/src/runtime/shared/tool-card-model/card-detail.mjs +10 -4
- package/src/runtime/shared/tool-card-model/card-header.mjs +10 -4
- package/src/runtime/shared/tool-card-model/card-status.mjs +22 -5
- package/src/runtime/shared/tool-card-model/displayed-result.mjs +6 -1
- package/src/runtime/shared/tool-card-model/media-result.mjs +53 -0
- package/src/runtime/shared/tool-card-model/terminal-status.mjs +17 -1
- package/src/runtime/shared/tool-card-model.golden-cases.mjs +1 -1
- package/src/runtime/shared/tool-card-model.golden.json +75 -66
- package/src/runtime/shared/tool-card-model.mjs +1 -0
- package/src/runtime/shared/tool-output-limit.mjs +3 -0
- package/src/runtime/shared/tool-primitives.mjs +24 -18
- package/src/runtime/shared/tool-result-summary.mjs +128 -17
- package/src/runtime/shared/tool-status.mjs +20 -7
- package/src/runtime/shared/tool-surface.mjs +105 -28
- package/src/runtime/shared/tool-work-units.mjs +221 -18
- package/src/runtime/shared/transcript-metadata.mjs +2 -0
- package/src/runtime/shared/turn-review-reply.mjs +2 -0
- package/src/runtime/shared/turn-snapshot.mjs +65 -6
- package/src/runtime/shared/turn-worktree-snapshot.mjs +202 -22
- package/src/runtime/shared/worker-requests.mjs +14 -2
- package/src/runtime/terminal-bridge/client.mjs +311 -0
- package/src/runtime/terminal-bridge/tool-defs.mjs +36 -0
- package/src/runtime/web-search/lib/ssrf-guard.mjs +12 -56
- package/src/runtime/web-search/tool-defs.mjs +2 -0
- package/src/session-runtime/boot/apis.mjs +30 -5
- package/src/session-runtime/boot/config.mjs +4 -0
- package/src/session-runtime/boot/facade.mjs +4 -1
- package/src/session-runtime/boot/infrastructure.mjs +21 -2
- package/src/session-runtime/boot/session.mjs +5 -5
- package/src/session-runtime/boot/tools.mjs +2 -0
- package/src/session-runtime/builtin-features.d.mts +1 -0
- package/src/session-runtime/channel-config-api.mjs +5 -0
- package/src/session-runtime/config-lifecycle/config-writers.mjs +3 -0
- package/src/session-runtime/config-lifecycle.mjs +31 -6
- package/src/session-runtime/goal-facade-api.mjs +4 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +15 -3
- package/src/session-runtime/lifecycle/inheritance.mjs +28 -6
- package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +3 -0
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +7 -1
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +9 -0
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +14 -2
- package/src/session-runtime/lifecycle/teardown.mjs +5 -0
- package/src/session-runtime/local-provider-settings.mjs +10 -0
- package/src/session-runtime/media-api.mjs +32 -22
- package/src/session-runtime/model-recency.mjs +14 -0
- package/src/session-runtime/model-route/route-persist.mjs +17 -2
- package/src/session-runtime/model-route/route-tuning.mjs +16 -5
- package/src/session-runtime/model-route/set-route.mjs +55 -22
- package/src/session-runtime/model-route/web-search-route.mjs +2 -2
- package/src/session-runtime/model-route-api.mjs +2 -1
- package/src/session-runtime/notification-bus.mjs +31 -6
- package/src/session-runtime/provider-auth/login.mjs +6 -0
- package/src/session-runtime/provider-models/catalog-load.mjs +3 -1
- package/src/session-runtime/provider-models/row-hydration.mjs +36 -10
- package/src/session-runtime/quick-model-rows/model-meta.mjs +26 -0
- package/src/session-runtime/quick-model-rows/provider-rows.mjs +40 -14
- package/src/session-runtime/resource-api.mjs +8 -1
- package/src/session-runtime/route-state.mjs +9 -0
- package/src/session-runtime/runtime-core.mjs +4 -0
- package/src/session-runtime/runtime-facade.mjs +20 -1
- package/src/session-runtime/runtime-feature-gates.mjs +2 -0
- package/src/session-runtime/runtime-review-api.mjs +12 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +14 -1
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +10 -15
- package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +6 -1
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +20 -2
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +14 -6
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +2 -0
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +12 -1
- package/src/session-runtime/services/agent-tool/worker-index.mjs +17 -1
- package/src/session-runtime/services/agent-tool.mjs +1 -0
- package/src/session-runtime/services/channel-admin.mjs +87 -13
- package/src/session-runtime/services/provider-admin.mjs +306 -66
- package/src/session-runtime/services/seeds.mjs +73 -142
- package/src/session-runtime/services/usage-dashboard-model.mjs +29 -0
- package/src/session-runtime/services/usage-dashboard.mjs +7 -0
- package/src/session-runtime/session-address.mjs +125 -0
- package/src/session-runtime/session-create.mjs +57 -2
- package/src/session-runtime/settings-api.mjs +1 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +15 -10
- package/src/session-runtime/settings-compaction-api.mjs +13 -0
- package/src/session-runtime/setup-tool/executor.mjs +93 -40
- package/src/session-runtime/setup-tool/extended-actions.mjs +64 -5
- package/src/session-runtime/setup-tool/settings-contract.mjs +46 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +14 -6
- package/src/session-runtime/tool-surface.mjs +16 -9
- package/src/session-runtime/turn/session-ops.mjs +3 -0
- package/src/session-runtime/turn/share-ops.mjs +4 -1
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +6 -0
- package/src/session-runtime/usage-stats-api.mjs +43 -3
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +31 -5
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +6 -2
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +27 -7
- package/src/standalone/daemon-boot-coordinator.mjs +10 -0
- package/src/standalone/daemon-desktop-runtime.mjs +1 -0
- package/src/standalone/daemon-drain-policy.mjs +9 -0
- package/src/standalone/daemon-stored-session-views.mjs +7 -8
- package/src/standalone/daemon.mjs +36 -8
- package/src/standalone/local-session-runtime.mjs +11 -0
- package/src/standalone/session-client.mjs +52 -7
- package/src/standalone/session-protocol.mjs +9 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +2 -0
- package/src/standalone/session-service/entries/lifecycle.mjs +2 -0
- package/src/standalone/session-service/entries/session-loads.mjs +9 -0
- package/src/standalone/session-service/projection/revisions.mjs +28 -4
- package/src/standalone/session-service/projection.mjs +1 -0
- package/src/standalone/session-service/quota-resume.mjs +140 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +2 -2
- package/src/standalone/session-service/session-calls.mjs +10 -2
- package/src/standalone/session-service/stored-reader.mjs +26 -1
- package/src/standalone/session-service.mjs +21 -0
- package/src/standalone/session-transport/routes.mjs +2 -0
- package/src/tui/app/doctor.mjs +7 -11
- package/src/tui/app/maintenance-pickers/auto-clear-picker.mjs +3 -5
- package/src/tui/app/model-picker/model-footer.mjs +2 -2
- package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +21 -2
- package/src/tui/app/model-picker/route-selection.mjs +6 -1
- package/src/tui/app/settings-picker/settings-rows.mjs +4 -6
- package/src/tui/app/settings-picker/settings-toggles/store-toggles.mjs +1 -1
- package/src/tui/app/slash-commands.mjs +1 -1
- package/src/tui/app/slash-dispatch/route-commands.mjs +5 -3
- package/src/tui/app/transcript-row-estimate.mjs +17 -5
- package/src/tui/components/ContextPanel.jsx +5 -1
- package/src/tui/components/Spinner.jsx +34 -319
- package/src/tui/components/SpinnerByline.jsx +256 -0
- package/src/tui/components/tool-execution/aggregate-card.jsx +4 -2
- package/src/tui/components/tool-execution/text-format.mjs +1 -0
- package/src/tui/components/use-spinner-progress.mjs +113 -0
- package/src/tui/dist/index.mjs +15896 -14452
- package/src/tui/session/agent-job-feed/execution-delivery.mjs +13 -1
- package/src/tui/session/agent-job-feed/notification-router.mjs +3 -0
- package/src/tui/session/agent-job-feed/pending-resume.mjs +14 -1
- package/src/tui/session/agent-job-feed.mjs +4 -0
- package/src/tui/session/context-state.mjs +13 -1
- package/src/tui/session/initial-state.mjs +6 -0
- package/src/tui/session/quota-resume.mjs +263 -0
- package/src/tui/session/session-api/intake/abort.mjs +39 -35
- package/src/tui/session/session-api/intake/submission.mjs +13 -21
- package/src/tui/session/session-api/intake.mjs +3 -3
- package/src/tui/session/session-api/integrations.mjs +5 -1
- package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle/inheritance.mjs +2 -2
- package/src/tui/session/session-api/lifecycle/session-reset.mjs +4 -0
- package/src/tui/session/session-api/lifecycle.mjs +71 -2
- package/src/tui/session/session-api/media.mjs +2 -2
- package/src/tui/session/session-api/quota-resume.mjs +21 -0
- package/src/tui/session/session-api/routes.mjs +5 -2
- package/src/tui/session/session-api/settings.mjs +2 -0
- package/src/tui/session/session-api.mjs +2 -0
- package/src/tui/session/session-flow/auto-clear.mjs +14 -6
- package/src/tui/session/session-flow/drain.mjs +52 -5
- package/src/tui/session/session-flow/queue/take-entries.mjs +9 -4
- package/src/tui/session/session-flow/queue.mjs +4 -0
- package/src/tui/session/session-flow/steering.mjs +11 -0
- package/src/tui/session/session-flow.mjs +1 -0
- package/src/tui/session/tool-approval.mjs +7 -2
- package/src/tui/session/transcript-intake.mjs +1 -0
- package/src/tui/session/turn-tool-cards.mjs +4 -6
- package/src/tui/session/turn.mjs +40 -4
- package/src/vendor/statusline/bin/statusline-route.mjs +3 -2
- package/src/vendor/statusline/src/gateway/route-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-warmup.mjs +0 -165
|
@@ -21,6 +21,8 @@ export function createContextSwitch(deps, { ingestSessionIntoMemory, closeSurfac
|
|
|
21
21
|
} = deps;
|
|
22
22
|
|
|
23
23
|
async function switchContext({ cwd, desktopSession: nextDesktopSession, forResume = false } = {}) {
|
|
24
|
+
// Leaving the open conversation would re-key an addressed runtime.
|
|
25
|
+
deps.assertNotAddressed?.('switchContext');
|
|
24
26
|
clearRoutePreparation?.();
|
|
25
27
|
const session = getSession();
|
|
26
28
|
if (session?.id) {
|
|
@@ -55,6 +57,7 @@ export function createContextSwitch(deps, { ingestSessionIntoMemory, closeSurfac
|
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
async function newSession() {
|
|
60
|
+
deps.assertNotAddressed?.('newSession');
|
|
58
61
|
const session = getSession();
|
|
59
62
|
if (session?.id) {
|
|
60
63
|
void ingestSessionIntoMemory(session);
|
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { writeStatuslineRoute } from '../../statusline-route.mjs';
|
|
7
7
|
import { clean, hasOwn } from '../../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
toolSpecForMode,
|
|
10
|
+
deferredSurfaceModeForLead,
|
|
11
|
+
} from '../../../runtime/agent/orchestrator/runtime-core/effort.mjs';
|
|
9
12
|
import { isScratchConversation } from '../shared.mjs';
|
|
10
13
|
|
|
11
14
|
export function resolveResumeCwd(session, currentCwd) {
|
|
@@ -97,6 +100,9 @@ export function createSessionResume(deps, { ingestSessionIntoMemory, closeSurfac
|
|
|
97
100
|
}
|
|
98
101
|
|
|
99
102
|
async function resume(id) {
|
|
103
|
+
// An addressed runtime may only reopen its own conversation; checked
|
|
104
|
+
// before anything is retired or closed.
|
|
105
|
+
deps.assertResumeTarget?.(id);
|
|
100
106
|
clearRoutePreparation?.();
|
|
101
107
|
const prev = getSession();
|
|
102
108
|
// Captured before the manager reopens anything: the scratch decision for
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* owns (shared with the context switch).
|
|
5
5
|
*/
|
|
6
6
|
import { clean } from '../../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
7
|
+
import { forgetSessionSearch } from '../../../runtime/session-search/session-search-ingest.mjs';
|
|
7
8
|
import { listLeadSessions } from '../session-catalog.mjs';
|
|
8
9
|
import { SESSION_ID_PATTERN } from '../shared.mjs';
|
|
9
10
|
|
|
@@ -58,6 +59,7 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
|
|
|
58
59
|
if (current?.id !== sessionId) {
|
|
59
60
|
const deleted = mgr.deleteSession(sessionId) === true;
|
|
60
61
|
if (!deleted) return false;
|
|
62
|
+
void forgetSessionSearch(sessionId);
|
|
61
63
|
// The parent is already irreversibly gone, so child cleanup is
|
|
62
64
|
// best-effort and idempotent. Any vetoed child becomes sweep-eligible
|
|
63
65
|
// because its retained-parent proof disappeared with the parent.
|
|
@@ -74,6 +76,7 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
|
|
|
74
76
|
// immediately would let a late provider/save continuation resurrect the
|
|
75
77
|
// deleted conversation after the user has moved to its replacement.
|
|
76
78
|
if (mgr.closeSession(sessionId, cleanupReason, { tombstone: true }) !== true) return false;
|
|
79
|
+
void forgetSessionSearch(sessionId);
|
|
77
80
|
// Active parent deletion uses the same durable tombstone boundary for
|
|
78
81
|
// every linked child. Their files then mature with the parent instead of
|
|
79
82
|
// disappearing while the parent task is still retained.
|
|
@@ -85,6 +88,12 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
|
|
|
85
88
|
setSession(null);
|
|
86
89
|
invalidateContextStatusCache();
|
|
87
90
|
invalidatePreSessionToolSurface();
|
|
91
|
+
// An addressed runtime never mints a replacement under the deleted
|
|
92
|
+
// address: it becomes terminal and a new conversation needs a new entry.
|
|
93
|
+
if (deps.getAddressedSessionId?.()) {
|
|
94
|
+
deps.markAddressTerminal?.();
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
88
97
|
await createCurrentSession();
|
|
89
98
|
return true;
|
|
90
99
|
}
|
|
@@ -63,10 +63,22 @@ export function closeOwnSession(deps, closeSurfaceSession, reason) {
|
|
|
63
63
|
/** Plant the ordinary manager/store tombstone barrier for a canonical
|
|
64
64
|
* child session without running whole-process teardown. */
|
|
65
65
|
export function closeCanonicalSession(deps, reason = 'canonical-session-close') {
|
|
66
|
-
const { getSession, setSession, mgr, invalidateContextStatusCache } = deps;
|
|
66
|
+
const { getSession, setSession, mgr, invalidateContextStatusCache, beginCanonicalClose, finishCanonicalClose } = deps;
|
|
67
|
+
// Already terminal: closing is idempotent and keeps the address.
|
|
68
|
+
if (deps.isCanonicallyClosed?.() === true) return true;
|
|
67
69
|
const session = getSession?.();
|
|
68
70
|
if (!session?.id || session.remoteAttached === true) return false;
|
|
69
|
-
|
|
71
|
+
// Fence execution admission BEFORE the manager close: that close cancels the
|
|
72
|
+
// session's shells synchronously, and their completions must not be able to
|
|
73
|
+
// enqueue model work or create a conversation.
|
|
74
|
+
const fence = beginCanonicalClose?.(session.id);
|
|
75
|
+
let closed = false;
|
|
76
|
+
try {
|
|
77
|
+
closed = mgr.closeSession(session.id, reason, { tombstone: true }) === true;
|
|
78
|
+
} finally {
|
|
79
|
+
// Terminal after a durable close; admission restored when it failed.
|
|
80
|
+
finishCanonicalClose?.(fence, closed);
|
|
81
|
+
}
|
|
70
82
|
if (!closed) return false;
|
|
71
83
|
setSession?.(null);
|
|
72
84
|
invalidateContextStatusCache?.();
|
|
@@ -165,6 +165,11 @@ export function createTeardown(deps, { ingestSessionIntoMemory, closeSurfaceSess
|
|
|
165
165
|
agentTool.closeAll(reason, scope.scopedTeardown ? { callerSessionId: scope.closingSessionId } : {});
|
|
166
166
|
} catch {}
|
|
167
167
|
}
|
|
168
|
+
// Release the worker/lead index exit registrations (persists pending rows
|
|
169
|
+
// first). Idempotent, so repeated closes of one runtime dispose once.
|
|
170
|
+
try {
|
|
171
|
+
agentTool.dispose?.({ settle: scope.teardownReapsWork === true });
|
|
172
|
+
} catch {}
|
|
168
173
|
const { ok, stops } = await inOwnLoopTurn(() => {
|
|
169
174
|
const runtimeStops = startRuntimeStops(deps, reason, scope);
|
|
170
175
|
const closed = closeOwnSession(deps, closeSurfaceSession, reason);
|
|
@@ -10,6 +10,7 @@ export function createLocalProviderSettings({
|
|
|
10
10
|
prepareLocalProviderModel,
|
|
11
11
|
refreshLocalProviderCatalog,
|
|
12
12
|
cancelLocalProviderInstallation,
|
|
13
|
+
discardLocalProviderInstallation,
|
|
13
14
|
configureLocalProviderIdleTtl,
|
|
14
15
|
}) {
|
|
15
16
|
let commandError = null;
|
|
@@ -52,6 +53,15 @@ export function createLocalProviderSettings({
|
|
|
52
53
|
cancelLocalProviderInstallation(jobId);
|
|
53
54
|
return this.getToolModuleSettings();
|
|
54
55
|
},
|
|
56
|
+
discardLocalProviderInstallation(phase, modelId) {
|
|
57
|
+
if (!['runtime', 'model', 'verify', 'repair'].includes(phase))
|
|
58
|
+
throw new TypeError('phase must be runtime, model, verify or repair.');
|
|
59
|
+
if (phase !== 'runtime' && (typeof modelId !== 'string' || !modelId.trim()))
|
|
60
|
+
throw new TypeError('modelId is required.');
|
|
61
|
+
discardLocalProviderInstallation(phase, phase === 'runtime' ? null : modelId);
|
|
62
|
+
commandError = null;
|
|
63
|
+
return this.getToolModuleSettings();
|
|
64
|
+
},
|
|
55
65
|
setLocalProviderIdleTtl(seconds) {
|
|
56
66
|
const idleTtlSeconds = localIdleTtlSeconds(seconds);
|
|
57
67
|
const config = getConfig();
|
|
@@ -4,33 +4,43 @@
|
|
|
4
4
|
* The media graph (lane catalog, adapters, asset store) is imported on first
|
|
5
5
|
* use: a session that never opens the Studio must not pay for it at boot.
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
async
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async function jobs() {
|
|
17
|
-
jobModule ??= await import('../runtime/media/jobs.mjs');
|
|
18
|
-
return jobModule;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async function store() {
|
|
22
|
-
storeModule ??= await import('../runtime/media/store.mjs');
|
|
23
|
-
return storeModule;
|
|
7
|
+
// Each loader keeps its literal import() so bundlers can trace it; only a
|
|
8
|
+
// resolved module is cached, so a failed import is retried on the next call.
|
|
9
|
+
function lazy(load) {
|
|
10
|
+
let module = null;
|
|
11
|
+
return async () => {
|
|
12
|
+
module ??= await load();
|
|
13
|
+
return module;
|
|
14
|
+
};
|
|
24
15
|
}
|
|
25
16
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
17
|
+
const lanes = lazy(() => import('../runtime/media/lanes.mjs'));
|
|
18
|
+
const jobs = lazy(() => import('../runtime/media/jobs.mjs'));
|
|
19
|
+
const store = lazy(() => import('../runtime/media/store.mjs'));
|
|
20
|
+
const defaults = lazy(() => import('../runtime/media/defaults.mjs'));
|
|
21
|
+
const voice = lazy(() => import('../runtime/channels/lib/voice-setup.mjs'));
|
|
31
22
|
|
|
32
23
|
export function createMediaApi() {
|
|
33
24
|
return {
|
|
25
|
+
/** Read-only voice state: `voice.enabled` plus the managed whisper/ffmpeg
|
|
26
|
+
* runtime on disk. */
|
|
27
|
+
async getVoiceStatus() {
|
|
28
|
+
return (await voice()).getVoiceStatus();
|
|
29
|
+
},
|
|
30
|
+
/** Same toggle as the session `toggleVoice` action: enabling installs any
|
|
31
|
+
* missing whisper/ffmpeg component first. `error` carries the last
|
|
32
|
+
* warning or failure the toggle reported. */
|
|
33
|
+
async setVoiceEnabled(enabled) {
|
|
34
|
+
const module = await voice();
|
|
35
|
+
let error = null;
|
|
36
|
+
await module.toggleVoice({
|
|
37
|
+
enabled,
|
|
38
|
+
pushNotice: (text, level) => {
|
|
39
|
+
if (level === 'warn' || level === 'error') error = text;
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
return { status: await module.getVoiceStatus(), error };
|
|
43
|
+
},
|
|
34
44
|
async listMediaLanes() {
|
|
35
45
|
return (await lanes()).listMediaLanes();
|
|
36
46
|
},
|
|
@@ -3,6 +3,19 @@
|
|
|
3
3
|
// injected route provider (for sort priority) and webSearchCapableFor predicate.
|
|
4
4
|
import { clean } from '../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
5
5
|
import { contextWindowRange } from '../runtime/shared/llm/default-context-window.mjs';
|
|
6
|
+
import { isCustomProviderName } from '../runtime/agent/orchestrator/providers/custom-reasoning.mjs';
|
|
7
|
+
|
|
8
|
+
// A custom provider's effective row fields, carried when the row states them
|
|
9
|
+
// (explicit false included); first-party rows never carry them.
|
|
10
|
+
function customRowFields(name, m) {
|
|
11
|
+
if (!isCustomProviderName(name)) return {};
|
|
12
|
+
return {
|
|
13
|
+
...(typeof m.name === 'string' && m.name ? { name: m.name } : {}),
|
|
14
|
+
...(typeof m.hidden === 'boolean' ? { hidden: m.hidden } : {}),
|
|
15
|
+
...(typeof m.manual === 'boolean' ? { manual: m.manual } : {}),
|
|
16
|
+
...(m.customReasoning && typeof m.customReasoning === 'object' ? { customReasoning: m.customReasoning } : {}),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
6
19
|
|
|
7
20
|
function parsedProviderModelVersion(id) {
|
|
8
21
|
const text = clean(id).toLowerCase();
|
|
@@ -148,5 +161,6 @@ export function providerModelCacheRow(name, m, webSearchCapableFor) {
|
|
|
148
161
|
defaultFast: m.defaultFast === true,
|
|
149
162
|
supportsMaxMode: m.supportsMaxMode === true,
|
|
150
163
|
mode: m.mode || null,
|
|
164
|
+
...customRowFields(name, m),
|
|
151
165
|
};
|
|
152
166
|
}
|
|
@@ -7,6 +7,13 @@ import { saveModelSettings } from '../../runtime/agent/orchestrator/runtime-core
|
|
|
7
7
|
import { writeStatuslineRoute } from '../statusline-route.mjs';
|
|
8
8
|
import { sessionUsesRoute } from '../../runtime/agent/orchestrator/runtime-core/session-route-policy.mjs';
|
|
9
9
|
|
|
10
|
+
/** Re-tuning the live model (effort, Fast, context, or re-picking it) is not a
|
|
11
|
+
* main-model choice: new tasks keep their main model unless it is that model. */
|
|
12
|
+
function tunesNonMainModel(liveRoute, route, mainRoute) {
|
|
13
|
+
const sameModel = (other) => other?.provider === route.provider && other?.model === route.model;
|
|
14
|
+
return sameModel(liveRoute) && !sameModel(mainRoute);
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
export function createRoutePersistence(deps) {
|
|
11
18
|
const {
|
|
12
19
|
getConfig,
|
|
@@ -18,6 +25,7 @@ export function createRoutePersistence(deps) {
|
|
|
18
25
|
adoptConfig,
|
|
19
26
|
saveConfigAndAdopt,
|
|
20
27
|
persistLeadRoute,
|
|
28
|
+
resolveRoute,
|
|
21
29
|
invalidateContextStatusCache,
|
|
22
30
|
} = deps;
|
|
23
31
|
return {
|
|
@@ -27,11 +35,14 @@ export function createRoutePersistence(deps) {
|
|
|
27
35
|
hasSecrets: getConfigHasSecrets(),
|
|
28
36
|
});
|
|
29
37
|
},
|
|
30
|
-
persistAdoptedModelSettings(route) {
|
|
38
|
+
persistAdoptedModelSettings(route, { keepMainModel = false } = {}) {
|
|
31
39
|
// saveModelSettings is in-memory only. persistLeadRoute debounce-writes
|
|
32
40
|
// the adopted config (including modelSettings). If the lead preset cannot
|
|
33
41
|
// be normalized, still debounce-persist so effort/fast are not memory-only.
|
|
34
|
-
const leadRoute =
|
|
42
|
+
const leadRoute =
|
|
43
|
+
keepMainModel || tunesNonMainModel(getRoute(), route, resolveRoute(getConfig(), {}))
|
|
44
|
+
? null
|
|
45
|
+
: persistLeadRoute(route);
|
|
35
46
|
if (!leadRoute) saveConfigAndAdopt(getConfig());
|
|
36
47
|
return leadRoute;
|
|
37
48
|
},
|
|
@@ -42,6 +53,10 @@ export function createRoutePersistence(deps) {
|
|
|
42
53
|
if (!sessionUsesRoute(session, route)) return;
|
|
43
54
|
session.fast = route.fast === true;
|
|
44
55
|
session.effort = route.effectiveEffort || null;
|
|
56
|
+
// The request path reads session.modelParameters; keep only serviceTier in step.
|
|
57
|
+
const { serviceTier: _previous, ...otherParameters } = session.modelParameters || {};
|
|
58
|
+
const serviceTier = route.modelParameters?.serviceTier;
|
|
59
|
+
session.modelParameters = serviceTier ? { ...otherParameters, serviceTier } : otherParameters;
|
|
45
60
|
writeStatuslineRoute(statusRoutes, session, route);
|
|
46
61
|
invalidateContextStatusCache();
|
|
47
62
|
},
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* route-tuning.mjs — fast and effort changes on the current main route.
|
|
3
3
|
*/
|
|
4
4
|
import { normalizeEffortInput } from '../../runtime/agent/orchestrator/runtime-core/effort.mjs';
|
|
5
|
-
import {
|
|
5
|
+
import { selectionFastCapable } from '../route-state.mjs';
|
|
6
|
+
import { ultrafastCapableFor } from '../../runtime/agent/orchestrator/runtime-core/model-capabilities.mjs';
|
|
6
7
|
import { workflowPresetId } from '../../runtime/agent/orchestrator/runtime-core/workflow.mjs';
|
|
7
8
|
|
|
8
9
|
export function createRouteTuning(deps, persist) {
|
|
@@ -19,9 +20,19 @@ export function createRouteTuning(deps, persist) {
|
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
async function setFast(value) {
|
|
22
|
-
const
|
|
23
|
+
const ultra = value === 'ultrafast';
|
|
24
|
+
const enabled = value === true || ultra;
|
|
23
25
|
const modelMeta = await lookupModelMeta(getRoute().provider, getRoute().model);
|
|
24
|
-
|
|
26
|
+
// lookupModelMeta may answer with the provider's raw (unhydrated) model, so
|
|
27
|
+
// ask the capability directly instead of the row's serviceTier option.
|
|
28
|
+
if (ultra && !ultrafastCapableFor(getRoute().provider, modelMeta)) {
|
|
29
|
+
throw new Error(`ultrafast is not available for ${getRoute().provider}/${getRoute().model}`);
|
|
30
|
+
}
|
|
31
|
+
const { serviceTier: previousTier, ...otherParameters } = getRoute().modelParameters || {};
|
|
32
|
+
let modelParameters = getRoute().modelParameters;
|
|
33
|
+
if (ultra) modelParameters = { ...otherParameters, serviceTier: 'ultrafast' };
|
|
34
|
+
else if (previousTier === 'ultrafast') modelParameters = otherParameters;
|
|
35
|
+
const fastCapable = selectionFastCapable(
|
|
25
36
|
getRoute().provider,
|
|
26
37
|
modelMeta,
|
|
27
38
|
getRoute().effectiveEffort || getRoute().effort,
|
|
@@ -36,7 +47,7 @@ export function createRouteTuning(deps, persist) {
|
|
|
36
47
|
model: getRoute().model,
|
|
37
48
|
effort: getRoute().effort,
|
|
38
49
|
fast: fastCapable ? enabled : false,
|
|
39
|
-
modelParameters
|
|
50
|
+
modelParameters,
|
|
40
51
|
})
|
|
41
52
|
);
|
|
42
53
|
await commitRouteTuning(fastCapable, modelMeta);
|
|
@@ -52,7 +63,7 @@ export function createRouteTuning(deps, persist) {
|
|
|
52
63
|
const normalized = normalizeEffortInput(value);
|
|
53
64
|
setRouteState({ ...getRoute(), effort: normalized });
|
|
54
65
|
const modelMeta = await lookupModelMeta(getRoute().provider, getRoute().model);
|
|
55
|
-
const fastCapable =
|
|
66
|
+
const fastCapable = selectionFastCapable(getRoute().provider, modelMeta, normalized, getRoute().modelParameters);
|
|
56
67
|
await commitRouteTuning(fastCapable, modelMeta);
|
|
57
68
|
return getRoute();
|
|
58
69
|
},
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* (untouched, tuned, recreated, or updated in place when empty).
|
|
5
5
|
*/
|
|
6
6
|
import { clean, hasOwn } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
7
|
-
import { fastCapableFor } from '../../runtime/agent/orchestrator/runtime-core/model-capabilities.mjs';
|
|
8
7
|
import {
|
|
9
8
|
ensureProviderEnabled,
|
|
10
9
|
findPreset,
|
|
@@ -13,9 +12,13 @@ import {
|
|
|
13
12
|
} from '../../runtime/agent/orchestrator/runtime-core/config-helpers.mjs';
|
|
14
13
|
import { getModelMetadataSync } from '../../runtime/agent/orchestrator/providers/model-catalog.mjs';
|
|
15
14
|
import { workflowPresetId } from '../../runtime/agent/orchestrator/runtime-core/workflow.mjs';
|
|
16
|
-
import { resolveRouteContextState } from '../route-state.mjs';
|
|
15
|
+
import { resolveRouteContextState, selectionFastCapable } from '../route-state.mjs';
|
|
17
16
|
import { writeStatuslineRoute } from '../statusline-route.mjs';
|
|
18
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
sessionHasRouteHistory,
|
|
19
|
+
sessionRouteCommitted,
|
|
20
|
+
shouldRecreateEmptySessionForRouteChange,
|
|
21
|
+
} from '../../runtime/agent/orchestrator/runtime-core/session-route-policy.mjs';
|
|
19
22
|
import { rebuildDeferredToolSurfaceForProvider } from '../../runtime/agent/orchestrator/runtime-core/tool-catalog.mjs';
|
|
20
23
|
|
|
21
24
|
/** The request, completed from the live route where the caller left gaps. */
|
|
@@ -46,7 +49,7 @@ async function resolveSelectedRoute(deps, next) {
|
|
|
46
49
|
) {
|
|
47
50
|
throw new Error(`unknown model: ${selectedRoute.provider}/${selectedRoute.model}`);
|
|
48
51
|
}
|
|
49
|
-
const fastCapable =
|
|
52
|
+
const fastCapable = selectionFastCapable(
|
|
50
53
|
selectedRoute.provider,
|
|
51
54
|
modelMeta,
|
|
52
55
|
selectedRoute.effort,
|
|
@@ -82,7 +85,7 @@ async function recreateEmptySession(deps) {
|
|
|
82
85
|
}
|
|
83
86
|
|
|
84
87
|
/** Rewrite the addressed empty session to the route it was asked to run on. */
|
|
85
|
-
function
|
|
88
|
+
function updateSessionInPlace(deps, session, updateOptions) {
|
|
86
89
|
const { getRoute, getSession, setSession, mgr, statusRoutes } = deps;
|
|
87
90
|
const route = getRoute();
|
|
88
91
|
const fields = {
|
|
@@ -94,53 +97,83 @@ function updateEmptySessionInPlace(deps, session) {
|
|
|
94
97
|
contextPercent: route.contextPercent,
|
|
95
98
|
selectedContextWindow: route.selectedContextWindow || null,
|
|
96
99
|
};
|
|
97
|
-
const updated = mgr.updateSessionRoute?.(session.id, fields);
|
|
100
|
+
const updated = mgr.updateSessionRoute?.(session.id, fields, updateOptions);
|
|
98
101
|
if (updated) setSession(updated);
|
|
99
102
|
else Object.assign(session, fields);
|
|
100
103
|
rebuildDeferredToolSurfaceForProvider(getSession(), route.provider);
|
|
101
104
|
writeStatuslineRoute(statusRoutes, getSession(), route);
|
|
102
105
|
}
|
|
103
106
|
|
|
104
|
-
|
|
107
|
+
/** Validate, persist and adopt the requested route as the runtime's route. */
|
|
108
|
+
async function adoptRoute(deps, persist, next, options) {
|
|
105
109
|
const {
|
|
106
110
|
getConfig,
|
|
107
111
|
getRoute,
|
|
108
112
|
setRouteState,
|
|
109
|
-
getSession,
|
|
110
113
|
resolveRoute,
|
|
111
114
|
refreshRouteEffort,
|
|
112
115
|
refreshStatuslineUsageSnapshot,
|
|
113
116
|
scheduleStatuslineUsageRefresh,
|
|
114
|
-
invalidateContextStatusCache,
|
|
115
|
-
createCurrentSession,
|
|
116
117
|
} = deps;
|
|
118
|
+
const { selectedRoute, fastCapable, modelMeta } = await resolveSelectedRoute(deps, next);
|
|
119
|
+
persist.saveRouteModelSettings(selectedRoute, fastCapable);
|
|
120
|
+
// An heir opening on its source's model is not a main-model choice.
|
|
121
|
+
const leadRoute = persist.persistAdoptedModelSettings(selectedRoute, {
|
|
122
|
+
keepMainModel: options?.keepMainModel === true,
|
|
123
|
+
});
|
|
124
|
+
setRouteState(resolveRoute(getConfig(), leadRoute ? { model: workflowPresetId('lead') } : selectedRoute));
|
|
125
|
+
await refreshRouteEffort(modelMeta);
|
|
126
|
+
refreshStatuslineUsageSnapshot(getRoute());
|
|
127
|
+
scheduleStatuslineUsageRefresh();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Quota-exhaustion escape hatch: apply `next` to the addressed, ESTABLISHED
|
|
132
|
+
* session in place. The caller (session API) has already proven the latest
|
|
133
|
+
* settled turn failed on quota and that nothing is running. Starts no turn;
|
|
134
|
+
* the next turn's auto-compaction fits history to the new window.
|
|
135
|
+
*/
|
|
136
|
+
export function createContinueSessionInModel(deps, persist) {
|
|
137
|
+
const { getSession, invalidateContextStatusCache } = deps;
|
|
138
|
+
return async function continueSessionInModel(sessionId, next) {
|
|
139
|
+
const session = getSession();
|
|
140
|
+
if (!sessionId || !session?.id || session.id !== sessionId) {
|
|
141
|
+
throw new Error(`session ${sessionId || ''} is not the active session`);
|
|
142
|
+
}
|
|
143
|
+
await adoptRoute(deps, persist, next, {});
|
|
144
|
+
updateSessionInPlace(deps, session, { crossProvider: true });
|
|
145
|
+
invalidateContextStatusCache();
|
|
146
|
+
return true;
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function createSetRoute(deps, persist) {
|
|
151
|
+
const { getRoute, getSession, invalidateContextStatusCache, createCurrentSession } = deps;
|
|
117
152
|
|
|
118
153
|
return async function setRoute(next, options = {}) {
|
|
119
154
|
// Selection is for a new/inherited session. An explicit durable address
|
|
120
155
|
// permits initializing an EMPTY session, never rewriting an existing
|
|
121
156
|
// conversation's model, context boundary or provider cache.
|
|
122
157
|
const applyToCurrentSession = options?.applyToCurrentSession === true;
|
|
123
|
-
|
|
124
|
-
persist.saveRouteModelSettings(selectedRoute, fastCapable);
|
|
125
|
-
const leadRoute = persist.persistAdoptedModelSettings(selectedRoute);
|
|
126
|
-
setRouteState(resolveRoute(getConfig(), leadRoute ? { model: workflowPresetId('lead') } : selectedRoute));
|
|
127
|
-
await refreshRouteEffort(modelMeta);
|
|
128
|
-
refreshStatuslineUsageSnapshot(getRoute());
|
|
129
|
-
scheduleStatuslineUsageRefresh();
|
|
158
|
+
await adoptRoute(deps, persist, next, options);
|
|
130
159
|
const session = getSession();
|
|
131
160
|
// Model/provider changes are next-session-only for a session the user
|
|
132
161
|
// has already talked in or compacted (provider-keyed prompt cache). But
|
|
133
|
-
//
|
|
134
|
-
// first
|
|
135
|
-
//
|
|
136
|
-
|
|
162
|
+
// a current session with no model reply, no compaction summary and no
|
|
163
|
+
// in-flight first turn — empty, or holding only refused prompts — has no
|
|
164
|
+
// cache to protect, so /model takes effect live: route + statusline
|
|
165
|
+
// update immediately. Only a truly empty session is recreated below.
|
|
166
|
+
const currentSessionEmpty = !!session && !sessionRouteCommitted(session);
|
|
137
167
|
if (!currentSessionEmpty) {
|
|
138
168
|
// Some desktop effort changes travel as a same-model route update.
|
|
139
169
|
// Only effort/Fast may affect the source, starting with its next turn.
|
|
140
170
|
if (applyToCurrentSession) persist.applySessionTuning();
|
|
141
171
|
return getRoute();
|
|
142
172
|
}
|
|
173
|
+
// An addressed runtime keeps its durable id: the empty session is updated
|
|
174
|
+
// in place, never closed and replaced by a freshly minted one.
|
|
143
175
|
if (
|
|
176
|
+
!deps.getAddressedSessionId?.() &&
|
|
144
177
|
shouldRecreateEmptySessionForRouteChange(session, applyToCurrentSession) &&
|
|
145
178
|
session?.id &&
|
|
146
179
|
typeof createCurrentSession === 'function'
|
|
@@ -154,7 +187,7 @@ export function createSetRoute(deps, persist) {
|
|
|
154
187
|
// durable address. The caller asked to apply this route to THIS empty
|
|
155
188
|
// session, so update it in place instead of closing A and silently
|
|
156
189
|
// materializing B before the first prompt.
|
|
157
|
-
|
|
190
|
+
updateSessionInPlace(deps, session);
|
|
158
191
|
invalidateContextStatusCache();
|
|
159
192
|
}
|
|
160
193
|
return getRoute();
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { clean, hasOwn } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
6
6
|
import { coerceEffortFor } from '../../runtime/agent/orchestrator/runtime-core/effort.mjs';
|
|
7
|
-
import { fastCapableFor } from '../../runtime/agent/orchestrator/runtime-core/model-capabilities.mjs';
|
|
8
7
|
import { ensureProviderEnabled } from '../../runtime/agent/orchestrator/runtime-core/config-helpers.mjs';
|
|
8
|
+
import { selectionFastCapable } from '../route-state.mjs';
|
|
9
9
|
import {
|
|
10
10
|
isDefaultWebSearchRouteConfig,
|
|
11
11
|
isWebSearchCapableProvider,
|
|
@@ -71,7 +71,7 @@ export function createWebSearchRouteApi(deps) {
|
|
|
71
71
|
// bucket belongs to the MAIN route alone, so a web-search model pick that
|
|
72
72
|
// happens to match Main must not rewrite Main's saved effort/fast.
|
|
73
73
|
const effort = coerceEffortFor(selectedRoute.provider, modelMeta, selectedRoute.effort);
|
|
74
|
-
const fastCapable =
|
|
74
|
+
const fastCapable = selectionFastCapable(selectedRoute.provider, modelMeta, effort, selectedRoute.modelParameters);
|
|
75
75
|
return normalizeWebSearchRouteConfig({
|
|
76
76
|
...selectedRoute,
|
|
77
77
|
...(effort ? { effort } : {}),
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { createRoutePersistence } from './model-route/route-persist.mjs';
|
|
14
14
|
import { createWebSearchRouteApi } from './model-route/web-search-route.mjs';
|
|
15
|
-
import { createSetRoute } from './model-route/set-route.mjs';
|
|
15
|
+
import { createSetRoute, createContinueSessionInModel } from './model-route/set-route.mjs';
|
|
16
16
|
import { createRouteTuning } from './model-route/route-tuning.mjs';
|
|
17
17
|
|
|
18
18
|
export { shouldRecreateEmptySessionForRouteChange } from '../runtime/agent/orchestrator/runtime-core/session-route-policy.mjs';
|
|
@@ -22,6 +22,7 @@ export function createModelRouteApi(deps) {
|
|
|
22
22
|
return {
|
|
23
23
|
...createWebSearchRouteApi(deps),
|
|
24
24
|
setRoute: createSetRoute(deps, persist),
|
|
25
|
+
continueSessionInModel: createContinueSessionInModel(deps, persist),
|
|
25
26
|
...createRouteTuning(deps, persist),
|
|
26
27
|
};
|
|
27
28
|
}
|
|
@@ -29,7 +29,13 @@ function cleanSessionId(value) {
|
|
|
29
29
|
// the wake would leave its durable entry parked until the next user message.
|
|
30
30
|
// A completion whose owner is no longer the live session is still dropped (the
|
|
31
31
|
// durable queue carries it into that session's next turn).
|
|
32
|
-
export function createCompletionWakeScheduler({ getCurrentSessionId, getTurnApi }) {
|
|
32
|
+
export function createCompletionWakeScheduler({ getCurrentSessionId, getTurnApi, getOwnerLifecycle }) {
|
|
33
|
+
// A closing/terminal owner never starts inference from a completion; the
|
|
34
|
+
// check runs at request time and again inside the delayed callback.
|
|
35
|
+
const ownerOpen = (sessionId) => {
|
|
36
|
+
const life = getOwnerLifecycle?.(sessionId);
|
|
37
|
+
return !life || life.state === 'open';
|
|
38
|
+
};
|
|
33
39
|
// sessionId -> the oldest request suppressed while this session's wake is in
|
|
34
40
|
// flight, or null when nothing was suppressed. A present key means in flight.
|
|
35
41
|
const inFlight = new Map();
|
|
@@ -41,6 +47,7 @@ export function createCompletionWakeScheduler({ getCurrentSessionId, getTurnApi
|
|
|
41
47
|
try {
|
|
42
48
|
const turnApi = getTurnApi();
|
|
43
49
|
if (cleanSessionId(getCurrentSessionId()) !== ownerSessionId || !turnApi) return;
|
|
50
|
+
if (!ownerOpen(ownerSessionId)) return;
|
|
44
51
|
const delayMs = Math.max(0, Date.now() - queuedAt);
|
|
45
52
|
if (delayMs >= WAKE_DELAY_REPORT_MS) {
|
|
46
53
|
process.stderr.write(
|
|
@@ -70,7 +77,7 @@ export function createCompletionWakeScheduler({ getCurrentSessionId, getTurnApi
|
|
|
70
77
|
|
|
71
78
|
return function wakeQueuedCompletion({ sessionId, executionId, enqueuedAt } = {}) {
|
|
72
79
|
const ownerSessionId = cleanSessionId(sessionId);
|
|
73
|
-
if (!ownerSessionId) return false;
|
|
80
|
+
if (!ownerSessionId || !ownerOpen(ownerSessionId)) return false;
|
|
74
81
|
if (inFlight.has(ownerSessionId)) {
|
|
75
82
|
const suppressed = inFlight.get(ownerSessionId);
|
|
76
83
|
// Keep the oldest suppressed request so the replay reports the real wait.
|
|
@@ -99,10 +106,22 @@ function emitToListeners(source, content, meta = {}) {
|
|
|
99
106
|
return { handled, modelVisibleDelivered: event.modelVisibleDelivered === true };
|
|
100
107
|
}
|
|
101
108
|
|
|
102
|
-
export function createNotificationBus({ listeners, mgr, onCompletionQueued }) {
|
|
109
|
+
export function createNotificationBus({ listeners, mgr, onCompletionQueued, getOwnerLifecycle }) {
|
|
103
110
|
const boundSessionListeners = new Map();
|
|
104
111
|
const queuedCompletionIds = new Map();
|
|
105
112
|
|
|
113
|
+
// Owner identity + lifecycle generation. A closing/terminal owner (or a
|
|
114
|
+
// callback captured under an earlier generation) keeps its result for
|
|
115
|
+
// UI/history only: it is flagged `owner_closed`, never queued for the model
|
|
116
|
+
// and never wakes inference.
|
|
117
|
+
function ownerOpen(sessionId, capturedGeneration) {
|
|
118
|
+
const life = getOwnerLifecycle?.(sessionId);
|
|
119
|
+
if (!life) return true;
|
|
120
|
+
if (life.state !== 'open') return false;
|
|
121
|
+
return capturedGeneration === undefined || capturedGeneration === life.generation;
|
|
122
|
+
}
|
|
123
|
+
const closedMeta = (meta) => ({ ...(meta && typeof meta === 'object' ? meta : {}), owner_closed: true });
|
|
124
|
+
|
|
106
125
|
function emitRuntimeNotification(content, meta = {}) {
|
|
107
126
|
return emitToListeners(listeners, content, meta);
|
|
108
127
|
}
|
|
@@ -111,8 +130,10 @@ export function createNotificationBus({ listeners, mgr, onCompletionQueued }) {
|
|
|
111
130
|
const targetSessionId = cleanSessionId(sessionId);
|
|
112
131
|
if (!targetSessionId) return false;
|
|
113
132
|
const targetListeners = sessionNotificationListeners.get(targetSessionId) || [];
|
|
114
|
-
const
|
|
133
|
+
const open = ownerOpen(targetSessionId);
|
|
134
|
+
const { handled } = emitToListeners(targetListeners, content, open ? meta : closedMeta(meta));
|
|
115
135
|
if (handled) return true;
|
|
136
|
+
if (!open) return false;
|
|
116
137
|
if (typeof mgr.enqueuePendingMessage !== 'function') return false;
|
|
117
138
|
try {
|
|
118
139
|
return mgr.enqueuePendingMessage(targetSessionId, content) > 0;
|
|
@@ -168,13 +189,15 @@ export function createNotificationBus({ listeners, mgr, onCompletionQueued }) {
|
|
|
168
189
|
return true;
|
|
169
190
|
}
|
|
170
191
|
|
|
171
|
-
function notifySessionCompletion(sessionId, text, meta = {}) {
|
|
192
|
+
function notifySessionCompletion(sessionId, text, meta = {}, capturedGeneration = undefined) {
|
|
172
193
|
const targetSessionId = cleanSessionId(sessionId);
|
|
173
194
|
if (!targetSessionId) return false;
|
|
174
195
|
const targetListeners = sessionNotificationListeners.get(targetSessionId) || [];
|
|
196
|
+
const open = ownerOpen(targetSessionId, capturedGeneration);
|
|
175
197
|
const ownerMeta = {
|
|
176
198
|
...(meta && typeof meta === 'object' ? meta : {}),
|
|
177
199
|
caller_session_id: targetSessionId,
|
|
200
|
+
...(open ? {} : { owner_closed: true }),
|
|
178
201
|
};
|
|
179
202
|
delete ownerMeta.routing_session_id;
|
|
180
203
|
const { handled, modelVisibleDelivered } = emitToListeners(targetListeners, text, ownerMeta);
|
|
@@ -187,6 +210,7 @@ export function createNotificationBus({ listeners, mgr, onCompletionQueued }) {
|
|
|
187
210
|
handled,
|
|
188
211
|
mvd: modelVisibleDelivered,
|
|
189
212
|
});
|
|
213
|
+
if (!open) return handled;
|
|
190
214
|
if (modelVisibleDelivered) {
|
|
191
215
|
try {
|
|
192
216
|
recordDeliveredCompletion({
|
|
@@ -219,7 +243,8 @@ export function createNotificationBus({ listeners, mgr, onCompletionQueued }) {
|
|
|
219
243
|
|
|
220
244
|
function notifyFnForSession(callerSessionId) {
|
|
221
245
|
const ownerSessionId = cleanSessionId(callerSessionId);
|
|
222
|
-
|
|
246
|
+
const generation = getOwnerLifecycle?.(ownerSessionId)?.generation;
|
|
247
|
+
return (text, meta = {}) => notifySessionCompletion(ownerSessionId, text, meta, generation);
|
|
223
248
|
}
|
|
224
249
|
|
|
225
250
|
function bindListenerToSession(sessionId, listener) {
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
saveProviderApiKey,
|
|
11
11
|
saveCustomProvider,
|
|
12
12
|
removeCustomProvider,
|
|
13
|
+
updateCustomProviderModel,
|
|
13
14
|
testCustomProvider,
|
|
14
15
|
discoverCustomProviderModels,
|
|
15
16
|
} from '../services/provider-admin.mjs';
|
|
@@ -79,6 +80,11 @@ export function createLoginApi({ cfgMod, awaitKeychainPrewarm, reloadFullConfig,
|
|
|
79
80
|
refresh.afterCredentialChange();
|
|
80
81
|
return result;
|
|
81
82
|
},
|
|
83
|
+
async updateCustomProviderModel(providerId, modelId, patch) {
|
|
84
|
+
const result = await updateCustomProviderModel(cfgMod, providerId, modelId, patch);
|
|
85
|
+
refresh.afterCredentialChange();
|
|
86
|
+
return result;
|
|
87
|
+
},
|
|
82
88
|
async removeCustomProvider(providerId) {
|
|
83
89
|
await awaitKeychainPrewarm();
|
|
84
90
|
const result = removeCustomProvider(cfgMod, providerId);
|