@vellumai/assistant 0.11.3 → 0.11.4-dev.202608190019.b94dbf2
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/AGENTS.md +9 -3
- package/ARCHITECTURE.md +32 -10
- package/docs/architecture/memory.md +43 -5
- package/docs/architecture/security.md +96 -152
- package/docs/architecture/turn-actor.md +70 -0
- package/docs/browser-use-architecture-phase2.md +128 -56
- package/docs/flux-turn-detection-spike.md +248 -0
- package/docs/guardian-request-flow.md +35 -0
- package/docs/stt-provider-onboarding.md +3 -1
- package/knip.json +3 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +34 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +166 -1
- package/node_modules/@vellumai/gateway-client/src/index.ts +2 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
- package/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/openapi.yaml +289 -113
- package/package.json +1 -1
- package/scripts/voice-ttft-spike.ts +3 -3
- package/scripts/write-plugin-api-shim.ts +10 -0
- package/src/__tests__/app-compiler.test.ts +38 -3
- package/src/__tests__/app-control-flow.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +2 -2
- package/src/__tests__/assistant-feature-flag-guard.test.ts +25 -3
- package/src/__tests__/attachments-store.test.ts +21 -12
- package/src/__tests__/byok-default-profile-ensure.test.ts +17 -0
- package/src/__tests__/call-setup-flow-name-capture.test.ts +0 -1
- package/src/__tests__/call-site-routing-provider.test.ts +1 -1
- package/src/__tests__/channel-availability-routes.test.ts +14 -1
- package/src/__tests__/channel-capabilities-dedupe.test.ts +214 -0
- package/src/__tests__/channel-delivery-store.test.ts +14 -14
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +4 -4
- package/src/__tests__/channel-setup-panel-ack.test.ts +1 -1
- package/src/__tests__/checker.test.ts +20 -314
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +6 -2
- package/src/__tests__/compaction-events.test.ts +8 -10
- package/src/__tests__/config-loader-backfill.test.ts +3 -3
- package/src/__tests__/config-schema.test.ts +25 -10
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +8 -11
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +8 -11
- package/src/__tests__/conversation-agent-loop.test.ts +32 -21
- package/src/__tests__/conversation-attachments.test.ts +0 -1
- package/src/__tests__/conversation-attention-store.test.ts +63 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +112 -0
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -4
- package/src/__tests__/conversation-fork-crud.test.ts +69 -0
- package/src/__tests__/conversation-fork-referential.test.ts +67 -0
- package/src/__tests__/conversation-fork-retrospective.test.ts +24 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +209 -0
- package/src/__tests__/conversation-notifiers-provenance.test.ts +59 -0
- package/src/__tests__/conversation-queue.test.ts +154 -4
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +1 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +9 -9
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +1 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +187 -102
- package/src/__tests__/conversation-runtime-workspace.test.ts +14 -10
- package/src/__tests__/conversation-slash-queue.test.ts +3 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-app-open.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +21 -14
- package/src/__tests__/conversation-surfaces-queued-emit.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-state-update.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-table-action.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +1 -1
- package/src/__tests__/credential-prompt-route.test.ts +7 -10
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/cu-unified-flow.test.ts +1 -0
- package/src/__tests__/custom-profile-ensure.test.ts +5 -1
- package/src/__tests__/default-plugin-names-guard.test.ts +12 -1
- package/src/__tests__/discord-access-request-privacy.test.ts +5 -1
- package/src/__tests__/discord-requester-notice-privacy.test.ts +3 -3
- package/src/__tests__/document-append-idempotency.test.ts +233 -0
- package/src/__tests__/document-sync-tags.test.ts +0 -75
- package/src/__tests__/dynamic-skill-background-guard.test.ts +0 -2
- package/src/__tests__/edit-propagation.test.ts +107 -11
- package/src/__tests__/file-ops-service.test.ts +163 -30
- package/src/__tests__/filesystem-tools.test.ts +23 -24
- package/src/__tests__/gateway-only-guard.test.ts +2 -5
- package/src/__tests__/helpers/gateway-classify-mock.ts +27 -6
- package/src/__tests__/helpers/mock-actor-context.ts +49 -0
- package/src/__tests__/helpers/mock-conversation.ts +13 -1
- package/src/__tests__/host-file-read-tool.test.ts +16 -19
- package/src/__tests__/http-user-message-parity.test.ts +1 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +49 -0
- package/src/__tests__/injector-chain.test.ts +63 -41
- package/src/__tests__/injector-disk-pressure.test.ts +11 -23
- package/src/__tests__/inline-skill-load-permissions.test.ts +47 -36
- package/src/__tests__/llm-context-resolution.test.ts +73 -1
- package/src/__tests__/llm-schema.test.ts +5 -2
- package/src/__tests__/managed-skill-lifecycle.test.ts +7 -0
- package/src/__tests__/mcp-list-plugin-servers.test.ts +250 -0
- package/src/__tests__/media-generate-image.test.ts +131 -21
- package/src/__tests__/memory-retrieval-hook.test.ts +100 -7
- package/src/__tests__/messages-read-boundary-guard.test.ts +134 -0
- package/src/__tests__/mtime-cache.test.ts +3 -1
- package/src/__tests__/non-member-access-request.test.ts +0 -20
- package/src/__tests__/outbound-slack-persistence.test.ts +40 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +0 -4
- package/src/__tests__/plugin-api-store-credential.test.ts +261 -0
- package/src/__tests__/plugin-api-webhook-url.test.ts +10 -7
- package/src/__tests__/plugin-disabled-state.test.ts +2 -0
- package/src/__tests__/plugin-effective-enabled-set.test.ts +55 -3
- package/src/__tests__/plugin-execution-context.test.ts +73 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +5 -1
- package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +7 -4
- package/src/__tests__/plugin-secret-pattern-contribution.test.ts +1 -1
- package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +14 -7
- package/src/__tests__/provider-commit-message-generator.test.ts +20 -0
- package/src/__tests__/proxy-approval-callback.test.ts +1 -0
- package/src/__tests__/qdrant-manager.test.ts +14 -1
- package/src/__tests__/reaction-persistence.test.ts +200 -7
- package/src/__tests__/require-fresh-approval.test.ts +0 -4
- package/src/__tests__/risk-classification-boundary-guard.test.ts +115 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +460 -105
- package/src/__tests__/run-due-schedules.test.ts +21 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +187 -18
- package/src/__tests__/schedule-routes.test.ts +23 -0
- package/src/__tests__/schedule-store.test.ts +17 -0
- package/src/__tests__/scoped-approval-grants.test.ts +11 -6
- package/src/__tests__/secret-ingress-channel.test.ts +0 -1
- package/src/__tests__/secret-ingress-http.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +3 -3
- package/src/__tests__/skills.test.ts +32 -0
- package/src/__tests__/slack-edit-ordering-characterization.test.ts +0 -1
- package/src/__tests__/starter-task-flow.test.ts +5 -4
- package/src/__tests__/subagent-call-site-routing.test.ts +31 -19
- package/src/__tests__/subagent-fork-prompt-role.test.ts +1 -1
- package/src/__tests__/subagent-spawn-and-await.test.ts +18 -17
- package/src/__tests__/subagent-tool-gate-mode.test.ts +1 -1
- package/src/__tests__/subagent-tools.test.ts +81 -101
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +1 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +132 -5
- package/src/__tests__/tool-executor.test.ts +68 -39
- package/src/__tests__/turn-events-store.test.ts +43 -0
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +1 -1
- package/src/__tests__/ui-shape-teaching.test.ts +33 -0
- package/src/__tests__/ui-visual-surface.test.ts +1 -1
- package/src/__tests__/ui-voice-picker-surface.test.ts +128 -0
- package/src/__tests__/ui-work-result-surface.test.ts +1 -1
- package/src/__tests__/user-plugin-loader.test.ts +3 -1
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/visible-app-context.test.ts +16 -9
- package/src/__tests__/voice-config-update.test.ts +40 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +5 -3
- package/src/__tests__/voice-session-bridge.test.ts +85 -29
- package/src/__tests__/worker-entrypoint-guards.test.ts +54 -0
- package/src/__tests__/worker-plugin-surface.test.ts +77 -0
- package/src/__tests__/workspace-migration-142-consolidate-voice-front-door.test.ts +158 -0
- package/src/__tests__/workspace-migration-143-repair-deprecated-codex-model-id.test.ts +133 -0
- package/src/__tests__/workspace-migration-144-convert-stranded-subscription-openai-profiles.test.ts +316 -0
- package/src/__tests__/workspace-migration-145-collapse-profile-bindings-to-entries.test.ts +325 -0
- package/src/__tests__/workspace-migration-146-repair-retired-fireworks-deepseek-flash-model-id.test.ts +235 -0
- package/src/acp/__tests__/acp-claude-oauth.test.ts +10 -2
- package/src/acp/__tests__/auth-required.test.ts +161 -0
- package/src/acp/acp-claude-oauth.ts +19 -2
- package/src/acp/agent-process.test.ts +100 -0
- package/src/acp/agent-process.ts +29 -26
- package/src/acp/auth-required.ts +102 -0
- package/src/acp/session-manager.test.ts +119 -0
- package/src/acp/session-manager.ts +76 -3
- package/src/api/events/acp-auth-required.ts +55 -0
- package/src/api/events/host-file.ts +2 -2
- package/src/api/index.ts +7 -0
- package/src/api/surfaces.ts +12 -3
- package/src/apps/app-store.ts +3 -0
- package/src/bundler/package-resolver.ts +2 -30
- package/src/calls/__tests__/voice-session-bridge.test.ts +194 -11
- package/src/calls/__tests__/voice-triage-escalate.test.ts +102 -0
- package/src/calls/call-controller.ts +19 -3
- package/src/calls/call-setup-flow.ts +0 -1
- package/src/calls/media-stream-stt-session.ts +15 -0
- package/src/calls/voice-session-bridge.ts +115 -41
- package/src/calls/voice-triage-escalate.ts +105 -2
- package/src/channels/__tests__/plugin-channel-declarations.test.ts +161 -0
- package/src/channels/config.ts +13 -0
- package/src/channels/plugin-channel-declarations.ts +108 -0
- package/src/channels/types.ts +30 -0
- package/src/cli/AGENTS.md +5 -2
- package/src/cli/bundled-modules.ts +29 -0
- package/src/cli/commands/credentials.help.ts +2 -2
- package/src/cli/commands/db/repair.ts +4 -8
- package/src/cli/commands/domain.ts +6 -3
- package/src/cli/commands/email.ts +6 -3
- package/src/cli/commands/inference-providers.ts +1 -1
- package/src/cli/commands/keys.ts +8 -3
- package/src/cli/commands/mcp.help.ts +13 -4
- package/src/cli/commands/mcp.ts +9 -0
- package/src/cli/commands/memory/__tests__/memory-v2.test.ts +57 -7
- package/src/cli/commands/memory/__tests__/memory-v3.test.ts +128 -5
- package/src/cli/commands/memory/index.help.ts +84 -28
- package/src/cli/commands/memory/index.ts +2 -0
- package/src/cli/commands/memory/memory-v2.ts +58 -54
- package/src/cli/commands/memory/memory-v3.ts +64 -0
- package/src/cli/commands/memory/memory-validate.ts +18 -0
- package/src/cli/commands/plugins.ts +85 -36
- package/src/cli/commands/schedules.ts +35 -1
- package/src/cli/commands/stt.help.ts +27 -2
- package/src/cli/commands/trust.ts +3 -14
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +39 -0
- package/src/cli/lib/bundled-marketplace.json +14 -1
- package/src/cli/lib/upgrade-plugin.ts +42 -0
- package/src/config/__tests__/balanced-model-experiment.test.ts +278 -0
- package/src/config/__tests__/default-profile-catalog.test.ts +34 -2
- package/src/config/__tests__/default-provider.test.ts +6 -1
- package/src/config/__tests__/profile-materialization.test.ts +75 -19
- package/src/config/assistant-feature-flags.ts +36 -15
- package/src/config/balanced-model-experiment.ts +35 -0
- package/src/config/bundled-skills/acp/SKILL.md +6 -7
- package/src/config/bundled-skills/document-editor/SKILL.md +2 -2
- package/src/config/bundled-skills/document-editor/TOOLS.json +2 -2
- package/src/config/bundled-skills/image-studio/SKILL.md +5 -4
- package/src/config/bundled-skills/image-studio/TOOLS.json +1 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +101 -0
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +14 -4
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.test.ts +65 -0
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +7 -1
- package/src/config/bundled-skills/settings/tools/shared.ts +16 -0
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +19 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +9 -3
- package/src/config/bundled-skills/subagent/SKILL.md +17 -12
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -4
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +22 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +9 -2
- package/src/config/call-site-defaults.ts +11 -5
- package/src/config/default-profile-catalog.ts +179 -16
- package/src/config/default-profile-names.ts +4 -1
- package/src/config/default-provider-resolution.ts +4 -0
- package/src/config/feature-flag-registry.json +12 -12
- package/src/config/llm-context-resolution.ts +11 -3
- package/src/config/llm-resolver.ts +28 -1
- package/src/config/profile-materialization.ts +70 -22
- package/src/config/schemas/__tests__/live-voice.test.ts +107 -4
- package/src/config/schemas/call-site-catalog.ts +4 -4
- package/src/config/schemas/live-voice.ts +57 -23
- package/src/config/schemas/llm.ts +59 -32
- package/src/config/schemas/mcp.ts +23 -0
- package/src/config/schemas/plugin-updates.ts +6 -2
- package/src/config/schemas/stt.ts +1 -0
- package/src/config/skills.ts +9 -2
- package/src/context/outbound-sanitize.ts +96 -1
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +1 -1
- package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +82 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +15 -10
- package/src/daemon/conversation-agent-loop.ts +31 -19
- package/src/daemon/conversation-messaging.ts +5 -1
- package/src/daemon/conversation-notifiers.ts +20 -10
- package/src/daemon/conversation-process.ts +20 -6
- package/src/daemon/conversation-runtime-assembly.ts +12 -6
- package/src/daemon/conversation-store.ts +14 -4
- package/src/daemon/conversation-surfaces.ts +75 -26
- package/src/daemon/conversation-tool-setup.ts +3 -6
- package/src/daemon/conversation.ts +154 -51
- package/src/daemon/doordash-steps.ts +2 -2
- package/src/daemon/lifecycle.ts +14 -1
- package/src/daemon/mcp-reload-service.ts +36 -6
- package/src/daemon/process-message.ts +13 -26
- package/src/daemon/providers-setup.ts +6 -3
- package/src/daemon/trust-context-types.ts +29 -0
- package/src/daemon/trust-context.ts +12 -7
- package/src/daemon/wake-conversation-ops.ts +3 -2
- package/src/daemon/windows-compiled-entry.ts +4 -0
- package/src/documents/document-store.ts +143 -240
- package/src/hooks/hook-loader.ts +3 -3
- package/src/hooks/registry.ts +103 -45
- package/src/hooks/types.ts +5 -0
- package/src/inbound/__tests__/oauth-callback-url.test.ts +83 -0
- package/src/inbound/oauth-callback-url.ts +61 -0
- package/src/ipc/gateway-client.test.ts +1 -1
- package/src/ipc/gateway-client.ts +14 -21
- package/src/ipc/gateway-flag-listener.ts +17 -3
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +1 -104
- package/src/live-voice/__tests__/live-voice-events.test.ts +7 -8
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +1050 -0
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +115 -8
- package/src/live-voice/__tests__/live-voice-photo.test.ts +100 -0
- package/src/live-voice/__tests__/live-voice-progress.test.ts +60 -194
- package/src/live-voice/__tests__/live-voice-stt.test.ts +14 -0
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +29 -0
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +0 -483
- package/src/live-voice/__tests__/live-voice-vad.test.ts +0 -16
- package/src/live-voice/__tests__/progress-narration.test.ts +214 -0
- package/src/live-voice/live-voice-archive.ts +2 -0
- package/src/live-voice/live-voice-manager.ts +16 -3
- package/src/live-voice/live-voice-metrics.ts +57 -32
- package/src/live-voice/live-voice-photo.ts +1 -2
- package/src/live-voice/live-voice-session.ts +598 -323
- package/src/live-voice/progress-narration.ts +277 -0
- package/src/live-voice/protocol.ts +21 -1
- package/src/live-voice/windows-compiled-live-voice.ts +4 -0
- package/src/mcp/__tests__/effective-config.test.ts +238 -0
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
- package/src/mcp/__tests__/mcp-oauth-client-registration.test.ts +200 -0
- package/src/mcp/__tests__/mcp-oauth-provider.test.ts +9 -9
- package/src/mcp/__tests__/plugin-server-credential-isolation.test.ts +95 -0
- package/src/mcp/client.ts +16 -11
- package/src/mcp/effective-config.ts +113 -0
- package/src/mcp/manager.ts +11 -6
- package/src/mcp/mcp-auth-orchestrator.ts +13 -22
- package/src/mcp/mcp-oauth-provider.ts +205 -240
- package/src/monitoring/__tests__/plugin-auto-update.test.ts +166 -3
- package/src/monitoring/control.ts +1 -0
- package/src/monitoring/db-integrity-sample.ts +4 -5
- package/src/monitoring/plugin-auto-update.ts +128 -24
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/approval-card-data.ts +33 -0
- package/src/notifications/signal.ts +1 -0
- package/src/permissions/AGENTS.md +16 -0
- package/src/permissions/checker.test.ts +75 -122
- package/src/permissions/checker.ts +44 -560
- package/src/permissions/confirmation-guardian-request.test.ts +15 -11
- package/src/permissions/confirmation-guardian-request.ts +2 -2
- package/src/permissions/prompter.ts +1 -5
- package/src/permissions/question-guardian-request.test.ts +14 -6
- package/src/permissions/question-guardian-request.ts +1 -2
- package/src/persistence/attachments-store.ts +8 -1
- package/src/persistence/bookmark-crud.ts +3 -7
- package/src/persistence/conversation-attention-store.ts +16 -45
- package/src/persistence/conversation-crud.ts +33 -4
- package/src/persistence/conversation-lineage.ts +9 -0
- package/src/persistence/conversation-queries.ts +182 -52
- package/src/persistence/delivery-crud.ts +150 -36
- package/src/persistence/embeddings/qdrant-manager.ts +84 -49
- package/src/persistence/external-conversation-store.ts +32 -4
- package/src/persistence/llm-request-log-store.ts +4 -10
- package/src/persistence/llm-usage-store.ts +8 -3
- package/src/persistence/message-reads.test.ts +197 -0
- package/src/persistence/message-reads.ts +211 -0
- package/src/persistence/migrations/360-add-document-workspace-path.ts +5 -14
- package/src/persistence/migrations/366-chatgpt-subscription-row-identity.test.ts +120 -0
- package/src/persistence/migrations/366-chatgpt-subscription-row-identity.ts +62 -0
- package/src/persistence/real-user-turn-filter.ts +27 -3
- package/src/persistence/schema/documents.ts +4 -4
- package/src/persistence/steps.ts +9 -0
- package/src/plugin-api/__tests__/oauth-callback-url-export.test.ts +29 -0
- package/src/plugin-api/constants.ts +8 -0
- package/src/plugin-api/conversation-turn.ts +195 -5
- package/src/plugin-api/index.ts +38 -6
- package/src/plugin-api/resolve-credential.ts +3 -2
- package/src/plugin-api/store-credential.ts +146 -0
- package/src/plugin-api/vision-support.test.ts +1 -1
- package/src/plugin-api/webhook-url.ts +13 -11
- package/src/plugins/__tests__/mcp-servers.test.ts +371 -0
- package/src/plugins/defaults/main.ts +21 -7
- package/src/plugins/defaults/memory/AGENTS.md +15 -3
- package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +204 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +72 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +4 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +4 -1
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +0 -1
- package/src/plugins/defaults/memory/buffer-format.ts +165 -0
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +6 -0
- package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +77 -0
- package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +24 -6
- package/src/plugins/defaults/memory/graph/image-ref-utils.ts +3 -0
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +1 -30
- package/src/plugins/defaults/memory/graph-topology/pending-buffer.test.ts +34 -0
- package/src/plugins/defaults/memory/graph-topology/pending-buffer.ts +17 -24
- package/src/plugins/defaults/memory/hooks/post-compact.ts +1 -4
- package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +53 -5
- package/src/plugins/defaults/memory/indexer.ts +3 -1
- package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +19 -7
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +4 -4
- package/src/plugins/defaults/memory/src/__tests__/memory-v3-gate-stats.test.ts +281 -0
- package/src/plugins/defaults/memory/src/memory-v2-routes.ts +12 -10
- package/src/plugins/defaults/memory/src/memory-v3-routes.ts +207 -0
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +147 -0
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +8 -0
- package/src/plugins/defaults/memory/substrate/__tests__/edge-index.test.ts +0 -30
- package/src/plugins/defaults/memory/substrate/__tests__/ingest.test.ts +73 -1
- package/src/plugins/defaults/memory/substrate/__tests__/page-index.test.ts +37 -0
- package/src/plugins/defaults/memory/substrate/__tests__/page-links.test.ts +208 -0
- package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +158 -1
- package/src/plugins/defaults/memory/substrate/__tests__/static-context.test.ts +195 -58
- package/src/plugins/defaults/memory/substrate/consolidation-job.ts +93 -24
- package/src/plugins/defaults/memory/substrate/edge-index.ts +0 -31
- package/src/plugins/defaults/memory/substrate/ingest.ts +59 -0
- package/src/plugins/defaults/memory/substrate/page-index.ts +35 -8
- package/src/plugins/defaults/memory/substrate/page-links.ts +133 -0
- package/src/plugins/defaults/memory/substrate/page-store.ts +10 -0
- package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +124 -34
- package/src/plugins/defaults/memory/substrate/skill-content.ts +8 -1
- package/src/plugins/defaults/memory/substrate/static-context.ts +160 -33
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +2 -4
- package/src/plugins/defaults/memory/v1/graph/extraction.ts +3 -1
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +18 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +66 -1
- package/src/plugins/defaults/memory/v3/card.ts +9 -9
- package/src/plugins/defaults/memory/v3/core-set.test.ts +7 -0
- package/src/plugins/defaults/memory/v3/core-set.ts +5 -1
- package/src/plugins/defaults/memory/v3/edge.ts +13 -57
- package/src/plugins/defaults/memory/v3/injector.ts +8 -0
- package/src/plugins/defaults/memory/v3/prune.ts +2 -0
- package/src/plugins/defaults/memory/v3/selection-log-store.ts +2 -0
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +23 -9
- package/src/plugins/defaults/memory/worker-control.ts +1 -0
- package/src/plugins/defaults/memory/worker.ts +6 -3
- package/src/plugins/defaults/worker-entrypoints.ts +3 -0
- package/src/plugins/external-plugin-loader.ts +47 -0
- package/src/plugins/mcp-servers.ts +361 -0
- package/src/plugins/mtime-cache.ts +37 -46
- package/src/plugins/pipeline.ts +14 -7
- package/src/plugins/plugin-execution-context.ts +35 -11
- package/src/plugins/worker-plugin-surface.ts +33 -0
- package/src/prompts/templates/system-sections.ts +0 -7
- package/src/providers/__tests__/connection-model-compat.test.ts +1 -1
- package/src/providers/__tests__/context-overflow-error.test.ts +24 -0
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +214 -2
- package/src/providers/__tests__/preflight-resolved-config.test.ts +57 -0
- package/src/providers/__tests__/retry-callsite.test.ts +25 -2
- package/src/providers/anthropic/__tests__/pause-turn-continuation.test.ts +170 -0
- package/src/providers/anthropic/client.ts +332 -241
- package/src/providers/call-site-routing.ts +30 -3
- package/src/providers/connection-resolution.ts +194 -11
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +4 -0
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/inference/auth.ts +6 -0
- package/src/providers/inference/connection-availability.ts +24 -2
- package/src/providers/inference/connections.ts +2 -0
- package/src/providers/model-catalog.ts +3 -3
- package/src/providers/model-intents.ts +28 -8
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +163 -40
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +125 -2
- package/src/providers/openai/chat-completions-provider.ts +133 -36
- package/src/providers/openai/codex-models.ts +2 -1
- package/src/providers/provider-send-message.ts +32 -3
- package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +433 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +625 -0
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +34 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +285 -6
- package/src/providers/speech-to-text/deepgram-flux-frames.ts +395 -0
- package/src/providers/speech-to-text/deepgram-flux-realtime.ts +679 -0
- package/src/providers/speech-to-text/provider-catalog.ts +99 -8
- package/src/providers/speech-to-text/resolve.ts +25 -2
- package/src/routes/control.ts +1 -0
- package/src/routes/route-host-client.ts +1 -0
- package/src/routes/route-host-protocol.ts +7 -0
- package/src/routes/worker.ts +48 -15
- package/src/runtime/AGENTS.md +16 -17
- package/src/runtime/access-request-helper.ts +9 -12
- package/src/runtime/agent-wake.ts +18 -15
- package/src/runtime/effective-capabilities.test.ts +43 -0
- package/src/runtime/effective-capabilities.ts +27 -0
- package/src/runtime/guardian-reply-router.ts +6 -2
- package/src/runtime/pre-first-message-gate.ts +4 -0
- package/src/runtime/routes/__tests__/acp-claude-auth-routes.test.ts +12 -4
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +522 -2
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +52 -0
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +61 -0
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +44 -0
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +102 -1
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +132 -35
- package/src/runtime/routes/__tests__/schedule-routes-disarm-reason.test.ts +215 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +25 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +55 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher-host.test.ts +52 -1
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +133 -1
- package/src/runtime/routes/channel-availability-routes.ts +32 -14
- package/src/runtime/routes/channel-route-shared.ts +0 -6
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +6 -6
- package/src/runtime/routes/conversation-list-routes.ts +181 -23
- package/src/runtime/routes/conversation-management-routes.ts +17 -12
- package/src/runtime/routes/conversation-query-routes.ts +40 -27
- package/src/runtime/routes/conversation-routes.ts +43 -29
- package/src/runtime/routes/credential-prompt-routes.ts +4 -7
- package/src/runtime/routes/credential-routes.ts +26 -82
- package/src/runtime/routes/default-provider-routes.ts +15 -0
- package/src/runtime/routes/documents-routes.ts +3 -222
- package/src/runtime/routes/inbound-message-handler.ts +21 -45
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -9
- package/src/runtime/routes/inbound-stages/admission-policy.ts +1 -17
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +101 -79
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +12 -7
- package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +91 -8
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +72 -79
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +2 -3
- package/src/runtime/routes/inference-profiles-routes.ts +20 -11
- package/src/runtime/routes/inference-provider-connection-routes.ts +77 -15
- package/src/runtime/routes/log-export-routes.ts +3 -0
- package/src/runtime/routes/mcp-auth-routes.ts +148 -57
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +2 -0
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +3 -0
- package/src/runtime/routes/playground/inject-failures.ts +2 -2
- package/src/runtime/routes/playground/reset-circuit.ts +1 -1
- package/src/runtime/routes/plugins-routes.ts +38 -8
- package/src/runtime/routes/schedule-routes.ts +94 -7
- package/src/runtime/routes/settings-routes.ts +6 -6
- package/src/runtime/routes/stt-routes.ts +31 -25
- package/src/runtime/routes/surface-action-routes.ts +20 -19
- package/src/runtime/routes/surface-conversation-resolver.ts +3 -0
- package/src/runtime/routes/user-route-dispatcher.ts +69 -15
- package/src/runtime/routes/user-route-import.ts +108 -0
- package/src/runtime/routes/user-route-resolution.ts +18 -1
- package/src/runtime/routes/workspace-routes.ts +0 -9
- package/src/runtime/routes/workspace-utils.ts +3 -13
- package/src/runtime/services/conversation-serializer.ts +7 -2
- package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +68 -5
- package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +81 -0
- package/src/schedule/plugin-schedule-availability.ts +58 -0
- package/src/schedule/plugin-schedule-declarations.ts +23 -27
- package/src/schedule/plugin-schedule-reconciler.ts +12 -3
- package/src/schedule/schedule-store.ts +5 -1
- package/src/schedule/scheduler.ts +9 -4
- package/src/schedule/worker-control.ts +1 -0
- package/src/schedule/worker.ts +6 -0
- package/src/security/oauth2.ts +6 -22
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +22 -0
- package/src/stt/__tests__/types.test.ts +94 -0
- package/src/stt/daemon-batch-transcriber.ts +10 -0
- package/src/stt/stt-stream-session.ts +8 -4
- package/src/stt/types.ts +103 -0
- package/src/subagent/__tests__/consult-prompt.test.ts +26 -15
- package/src/subagent/consult-context.ts +11 -11
- package/src/subagent/consult-prompt.ts +26 -35
- package/src/subagent/manager.ts +21 -40
- package/src/subagent/notify.ts +7 -1
- package/src/subagent/types.ts +15 -12
- package/src/tools/__tests__/tool-input-schemas.test.ts +7 -7
- package/src/tools/acp/spawn.test.ts +97 -0
- package/src/tools/acp/spawn.ts +38 -4
- package/src/tools/credentials/ref-parse.ts +35 -0
- package/src/tools/credentials/resolve.ts +4 -10
- package/src/tools/credentials/store.ts +168 -0
- package/src/tools/document/document-tool.ts +12 -3
- package/src/tools/executor.ts +53 -15
- package/src/tools/filesystem/read.ts +27 -10
- package/src/tools/host-filesystem/read.ts +27 -15
- package/src/tools/network/url-safety.ts +9 -16
- package/src/tools/permission-checker.ts +43 -52
- package/src/tools/registry.ts +2 -1
- package/src/tools/shared/filesystem/file-ops-service.ts +63 -35
- package/src/tools/shared/filesystem/legacy-read-args.ts +22 -0
- package/src/tools/shared/filesystem/types.ts +5 -5
- package/src/tools/skills/scaffold-managed.ts +25 -7
- package/src/tools/subagent/spawn.ts +28 -88
- package/src/tools/tool-types.ts +26 -13
- package/src/tools/types.ts +6 -6
- package/src/tools/ui-surface/surface-shape-docs.ts +12 -1
- package/src/tools/workflows/run-workflow.ts +1 -2
- package/src/tts/__tests__/reasoning-tag-filter.test.ts +78 -0
- package/src/tts/reasoning-tag-filter.ts +89 -0
- package/src/util/__tests__/worker-process-command.test.ts +37 -0
- package/src/util/logger.ts +16 -0
- package/src/util/think-tag-stream.ts +95 -0
- package/src/util/worker-process.ts +37 -4
- package/src/windows-compiled-cli.ts +32 -0
- package/src/windows-compiled-entry.ts +4 -0
- package/src/windows-compiled-logger.ts +6 -0
- package/src/windows-compiled-worker-entry.ts +29 -0
- package/src/workspace/byok-default-profile-ensure.ts +76 -24
- package/src/workspace/custom-profile-ensure.ts +4 -24
- package/src/workspace/migrations/142-consolidate-voice-front-door.ts +70 -0
- package/src/workspace/migrations/143-repair-deprecated-codex-model-id.ts +134 -0
- package/src/workspace/migrations/144-convert-stranded-subscription-openai-profiles.ts +265 -0
- package/src/workspace/migrations/145-collapse-profile-bindings-to-entries.ts +328 -0
- package/src/workspace/migrations/146-repair-retired-fireworks-deepseek-flash-model-id.ts +195 -0
- package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +0 -10
- package/src/workspace/migrations/registry.ts +10 -0
- package/src/workspace/provider-commit-message-generator.ts +7 -5
- package/src/__tests__/document-workspace-file.test.ts +0 -467
- package/src/live-voice/__tests__/front-decision.test.ts +0 -645
- package/src/live-voice/front-decision.ts +0 -476
- package/src/permissions/ipc-risk-types.ts +0 -143
- package/src/permissions/risk-types.ts +0 -76
- package/src/subagent/__tests__/consult-transcript.test.ts +0 -184
- package/src/subagent/consult-transcript.ts +0 -90
|
@@ -45,9 +45,16 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
|
|
|
45
45
|
profile: "cost-optimized",
|
|
46
46
|
contextWindow: { maxInputTokens: 1000000 },
|
|
47
47
|
},
|
|
48
|
+
// Forced-tool selection over a numbered candidate pool: the model picks ids,
|
|
49
|
+
// it does not reason its way to an answer. `effort` has to be named here
|
|
50
|
+
// because a call-site tweak only overrides the fields it lists, so leaving it
|
|
51
|
+
// off inherits `balanced`'s `effort: "high"` (see default-profile-catalog).
|
|
52
|
+
// Low effort matches `recall`, the sibling site doing the same kind of
|
|
53
|
+
// bounded judgment, and keeps retrieval latency low on escalated voice turns.
|
|
48
54
|
memoryV3SelectL2: {
|
|
49
55
|
profile: "balanced",
|
|
50
56
|
temperature: 0,
|
|
57
|
+
effort: "low",
|
|
51
58
|
thinking: { enabled: false, streamThinking: false },
|
|
52
59
|
},
|
|
53
60
|
recall: {
|
|
@@ -121,22 +128,21 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
|
|
|
121
128
|
effort: "low",
|
|
122
129
|
thinking: { enabled: false },
|
|
123
130
|
},
|
|
124
|
-
//
|
|
125
|
-
// upstream cannot fit any usable decision budget (~1s+ per forced tool call).
|
|
131
|
+
// Progress narration only helps when it arrives before the next real output.
|
|
126
132
|
// `latency-optimized` is the latency-class profile (see
|
|
127
133
|
// default-profile-catalog.ts): managed installs get the pinned latency model,
|
|
128
134
|
// BYOK installs resolve their own provider's latency model through the intent
|
|
129
135
|
// table rather than a model id they may hold no credential for. The profile
|
|
130
136
|
// is user-facing ("Speed"), so a user edit to it moves this call site too.
|
|
131
|
-
|
|
137
|
+
voiceProgressNarration: {
|
|
132
138
|
profile: "latency-optimized",
|
|
133
139
|
effort: "low",
|
|
134
140
|
thinking: { enabled: false },
|
|
135
141
|
},
|
|
136
142
|
// The front-door leg fronts EVERY unified live-voice turn and its leading
|
|
137
143
|
// tokens ARE the endpointing/triage verdict, so both TTFT variance and
|
|
138
|
-
// judgment quality gate the whole call.
|
|
139
|
-
//
|
|
144
|
+
// judgment quality gate the whole call. Live drives showed the
|
|
145
|
+
// cost-optimized upstream with multi-second
|
|
140
146
|
// cross-session TTFT tails and over-escalation of small talk under open-task
|
|
141
147
|
// context pressure.
|
|
142
148
|
voiceFrontDoor: {
|
|
@@ -4,8 +4,10 @@ import {
|
|
|
4
4
|
isModelInCatalog,
|
|
5
5
|
} from "../providers/model-catalog.js";
|
|
6
6
|
import { resolveModelIntent } from "../providers/model-intents.js";
|
|
7
|
+
import { isCodexSubscriptionModel } from "../providers/openai/codex-models.js";
|
|
7
8
|
import type { ModelIntent } from "../providers/types.js";
|
|
8
9
|
import { getManagedUpstream } from "../providers/vellum-model-routing.js";
|
|
10
|
+
import { getBalancedModelExperimentArm } from "./balanced-model-experiment.js";
|
|
9
11
|
import {
|
|
10
12
|
DEFAULT_PROFILE_KEYS,
|
|
11
13
|
DEFAULT_PROFILE_PROVIDERS,
|
|
@@ -31,7 +33,8 @@ import {
|
|
|
31
33
|
* structured as an intent × provider matrix: each default profile is an
|
|
32
34
|
* intent, and each provider that can serve default profiles has a concrete
|
|
33
35
|
* implementation of that intent (model, token budget, effort, thinking).
|
|
34
|
-
* The `vellum` column is the platform-managed implementation
|
|
36
|
+
* The `vellum` column is the platform-managed implementation and the
|
|
37
|
+
* `chatgpt` column is the ChatGPT-subscription implementation; the other
|
|
35
38
|
* columns are the BYOK implementations resolved through `llm.defaultProvider`
|
|
36
39
|
* on off-platform installs.
|
|
37
40
|
*
|
|
@@ -96,7 +99,7 @@ const VELLUM_PROFILE_IMPLS: ProfileImpls = {
|
|
|
96
99
|
},
|
|
97
100
|
},
|
|
98
101
|
"cost-optimized": {
|
|
99
|
-
model: "accounts/fireworks/models/deepseek-v4-flash",
|
|
102
|
+
model: "accounts/fireworks/models/deepseek-v4-flash-0731",
|
|
100
103
|
provider: "vellum",
|
|
101
104
|
source: "managed",
|
|
102
105
|
label: "Cost",
|
|
@@ -147,6 +150,108 @@ const VELLUM_PROFILE_IMPLS: ProfileImpls = {
|
|
|
147
150
|
},
|
|
148
151
|
};
|
|
149
152
|
|
|
153
|
+
/**
|
|
154
|
+
* Arm to managed model pin for the `experiment-balanced-model-2026-08-06` A/B
|
|
155
|
+
* test (`balanced-model-experiment.ts` owns the flag read). An arm repoints
|
|
156
|
+
* the model of the managed (`vellum`) implementation of `balanced` and nothing
|
|
157
|
+
* else: effort, thinking, token budget, label and description all stay on the
|
|
158
|
+
* shipped body, and the `chatgpt` and BYOK columns are untouched because those
|
|
159
|
+
* installs run the provider their user chose and sit outside the experiment.
|
|
160
|
+
*
|
|
161
|
+
* `control` is absent by design. It, an arm this build does not know, and an
|
|
162
|
+
* unset flag all resolve to the shipped body, so no LaunchDarkly value can
|
|
163
|
+
* strand an install on a model that is not pinned here. A `Map` rather than an
|
|
164
|
+
* object literal keeps that true for every string LaunchDarkly can send: the
|
|
165
|
+
* arm is remote input, and an object lookup would resolve `constructor` or
|
|
166
|
+
* `toString` to an inherited `Object.prototype` member instead of missing.
|
|
167
|
+
*
|
|
168
|
+
* `glm-5p2` is text-only: Balanced does not pass `doesSupportVision` on that
|
|
169
|
+
* arm, so image input routes through the image-fallback captioning plugin.
|
|
170
|
+
*/
|
|
171
|
+
const BALANCED_EXPERIMENT_MODELS = new Map<string, string>([
|
|
172
|
+
["terra", "gpt-5.6-terra"],
|
|
173
|
+
["glm-5p2", "accounts/fireworks/models/glm-5p2"],
|
|
174
|
+
]);
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* The managed (`vellum`) implementation of a default profile, carrying the
|
|
178
|
+
* balanced-model experiment arm. Resolved per call rather than materialized
|
|
179
|
+
* once: the gateway pushes flag changes to a running daemon, so the arm can
|
|
180
|
+
* move under a live process.
|
|
181
|
+
*/
|
|
182
|
+
function managedProfileImpl(key: DefaultProfileKey): DefaultProfileTemplate {
|
|
183
|
+
const impl = VELLUM_PROFILE_IMPLS[key];
|
|
184
|
+
if (key !== "balanced") {
|
|
185
|
+
return impl;
|
|
186
|
+
}
|
|
187
|
+
const arm = getBalancedModelExperimentArm();
|
|
188
|
+
const model = arm == null ? undefined : BALANCED_EXPERIMENT_MODELS.get(arm);
|
|
189
|
+
return model == null ? impl : { ...impl, model };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* The `chatgpt` column: ChatGPT-subscription implementations, stamped
|
|
194
|
+
* `provider: "chatgpt"` so dispatch routes through the canonical
|
|
195
|
+
* `chatgpt-subscription` row via `resolveRoutingIdentity` with no pinned
|
|
196
|
+
* connection. Models are pinned (never intents): the intent tables are
|
|
197
|
+
* keyed by concrete dispatch providers, and the Codex endpoint serves only
|
|
198
|
+
* `CODEX_SUBSCRIPTION_MODEL_IDS`. Cost and Speed are identical
|
|
199
|
+
* implementations here: the subscription serves no tier cheaper or faster
|
|
200
|
+
* than luna, and both profiles advertise reasoning off.
|
|
201
|
+
*/
|
|
202
|
+
const CHATGPT_PROFILE_IMPLS: ProfileImpls = {
|
|
203
|
+
balanced: {
|
|
204
|
+
model: "gpt-5.6-luna",
|
|
205
|
+
provider: "chatgpt",
|
|
206
|
+
source: "managed",
|
|
207
|
+
label: "Balanced",
|
|
208
|
+
description: "Good balance of quality, cost, and speed",
|
|
209
|
+
// Matches the vellum column's Balanced (same model): the Codex path
|
|
210
|
+
// sends no max_output_tokens, so this only sizes internal budgeting.
|
|
211
|
+
maxTokens: 32000,
|
|
212
|
+
effort: "high",
|
|
213
|
+
thinking: { enabled: true, streamThinking: true },
|
|
214
|
+
contextWindow: { maxInputTokens: DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS },
|
|
215
|
+
},
|
|
216
|
+
"quality-optimized": {
|
|
217
|
+
model: "gpt-5.6-sol",
|
|
218
|
+
provider: "chatgpt",
|
|
219
|
+
source: "managed",
|
|
220
|
+
label: "Quality",
|
|
221
|
+
description: "Best results with the most capable model",
|
|
222
|
+
maxTokens: 32000,
|
|
223
|
+
effort: "high",
|
|
224
|
+
thinking: { enabled: true, streamThinking: true },
|
|
225
|
+
contextWindow: { maxInputTokens: DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS },
|
|
226
|
+
},
|
|
227
|
+
"cost-optimized": {
|
|
228
|
+
model: "gpt-5.6-luna",
|
|
229
|
+
provider: "chatgpt",
|
|
230
|
+
source: "managed",
|
|
231
|
+
label: "Cost",
|
|
232
|
+
description: "Cheapest responses, for high-volume work",
|
|
233
|
+
maxTokens: 8192,
|
|
234
|
+
effort: "none",
|
|
235
|
+
thinking: { enabled: false, streamThinking: false },
|
|
236
|
+
contextWindow: { maxInputTokens: DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS },
|
|
237
|
+
},
|
|
238
|
+
"latency-optimized": {
|
|
239
|
+
model: "gpt-5.6-luna",
|
|
240
|
+
provider: "chatgpt",
|
|
241
|
+
source: "managed",
|
|
242
|
+
label: "Speed",
|
|
243
|
+
description: "Fastest responses, with reasoning turned off",
|
|
244
|
+
maxTokens: 8192,
|
|
245
|
+
// Explicit reasoning opt-out, matching the other columns: this profile
|
|
246
|
+
// advertises reasoning as off, and OpenAI-compat APIs default reasoning
|
|
247
|
+
// to "medium" when the field is omitted, so the opt-out has to be stated
|
|
248
|
+
// rather than implied.
|
|
249
|
+
effort: "none",
|
|
250
|
+
thinking: { enabled: false, streamThinking: false },
|
|
251
|
+
contextWindow: { maxInputTokens: DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS },
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
|
|
150
255
|
/**
|
|
151
256
|
* The BYOK implementation of each default profile intent, shared by every
|
|
152
257
|
* non-vellum provider. The concrete model resolves per provider from the
|
|
@@ -219,7 +324,9 @@ export const PROFILE_IMPLS: Record<
|
|
|
219
324
|
provider,
|
|
220
325
|
provider === "vellum"
|
|
221
326
|
? VELLUM_PROFILE_IMPLS[key]
|
|
222
|
-
:
|
|
327
|
+
: provider === "chatgpt"
|
|
328
|
+
? CHATGPT_PROFILE_IMPLS[key]
|
|
329
|
+
: { ...BYOK_PROFILE_IMPLS[key], provider },
|
|
223
330
|
]),
|
|
224
331
|
) as Record<DefaultProfileProvider, DefaultProfileTemplate>,
|
|
225
332
|
]),
|
|
@@ -302,9 +409,9 @@ export const OS_BETA_PROFILE_TEMPLATE: DefaultProfileTemplate = {
|
|
|
302
409
|
/**
|
|
303
410
|
* Profiles whose body is code-owned outright: no workspace overlay, and no
|
|
304
411
|
* user-owned shadow. The shadow rule below lets a user replace a default they
|
|
305
|
-
* can select, but `latency-optimized`
|
|
306
|
-
* `
|
|
307
|
-
*
|
|
412
|
+
* can select, but `latency-optimized` serves `voiceFrontDoor` and
|
|
413
|
+
* `voiceProgressNarration`, where a model outside the latency envelope is
|
|
414
|
+
* audible dead air rather than a slow reply. A same-named
|
|
308
415
|
* workspace entry stays on disk and stays listed; it just never governs what
|
|
309
416
|
* this name resolves to.
|
|
310
417
|
*/
|
|
@@ -372,21 +479,23 @@ for (const key of DEFAULT_PROFILE_KEYS) {
|
|
|
372
479
|
`PROFILE_IMPLS[${key}][${provider}] must set exactly one of \`intent\` or \`model\`.`,
|
|
373
480
|
);
|
|
374
481
|
}
|
|
375
|
-
if (impl.provider
|
|
482
|
+
if (ROUTING_IDENTITY_PROVIDERS.has(impl.provider) && impl.model == null) {
|
|
376
483
|
throw new Error(
|
|
377
|
-
`PROFILE_IMPLS[${key}][${provider}] must pin a \`model\`:
|
|
378
|
-
`
|
|
484
|
+
`PROFILE_IMPLS[${key}][${provider}] must pin a \`model\`: routing ` +
|
|
485
|
+
`identities have no intent table, and the model selects the route.`,
|
|
379
486
|
);
|
|
380
487
|
}
|
|
381
488
|
if (impl.model != null) {
|
|
382
489
|
const routable =
|
|
383
490
|
impl.provider === "vellum"
|
|
384
491
|
? getManagedUpstream(impl.model) !== null
|
|
385
|
-
:
|
|
492
|
+
: impl.provider === "chatgpt"
|
|
493
|
+
? isCodexSubscriptionModel(impl.model)
|
|
494
|
+
: isModelInCatalog(impl.provider, impl.model);
|
|
386
495
|
if (!routable) {
|
|
387
496
|
throw new Error(
|
|
388
497
|
`PROFILE_IMPLS[${key}][${provider}] references model "${impl.model}" ` +
|
|
389
|
-
`which is not ${impl.provider === "vellum" ? "served by any managed upstream" : `in PROVIDER_CATALOG for provider "${impl.provider}"`}. ` +
|
|
498
|
+
`which is not ${impl.provider === "vellum" ? "served by any managed upstream" : impl.provider === "chatgpt" ? "in CODEX_SUBSCRIPTION_MODEL_IDS" : `in PROVIDER_CATALOG for provider "${impl.provider}"`}. ` +
|
|
390
499
|
`Update model-catalog.ts or default-profile-catalog.ts.`,
|
|
391
500
|
);
|
|
392
501
|
}
|
|
@@ -394,6 +503,19 @@ for (const key of DEFAULT_PROFILE_KEYS) {
|
|
|
394
503
|
}
|
|
395
504
|
}
|
|
396
505
|
|
|
506
|
+
// The experiment arms substitute into the managed column at request time, so
|
|
507
|
+
// they need the same routability guarantee as the pins validated above: a
|
|
508
|
+
// LaunchDarkly arm must never select a model no managed upstream serves.
|
|
509
|
+
for (const [arm, model] of BALANCED_EXPERIMENT_MODELS) {
|
|
510
|
+
if (getManagedUpstream(model) === null) {
|
|
511
|
+
throw new Error(
|
|
512
|
+
`BALANCED_EXPERIMENT_MODELS["${arm}"] references model "${model}" which ` +
|
|
513
|
+
`is not served by any managed upstream. ` +
|
|
514
|
+
`Update model-catalog.ts or default-profile-catalog.ts.`,
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
397
519
|
// Provider choices without a named column materialize from the shared BYOK
|
|
398
520
|
// templates; verify each one's resolved model lands in the catalog.
|
|
399
521
|
for (const provider of DEFAULT_PROVIDER_CHOICES) {
|
|
@@ -432,6 +554,14 @@ function buildDefaultProfileEntries(): Record<string, ProfileEntry> {
|
|
|
432
554
|
* The materialized code-default bodies keyed by profile name — the
|
|
433
555
|
* code-owned content a managed-source workspace entry resolves to. These are
|
|
434
556
|
* the `vellum` column (the managed implementations).
|
|
557
|
+
*
|
|
558
|
+
* Materialized once at module load, so this is the shipped catalog: the
|
|
559
|
+
* balanced-model experiment arm is applied by the provider-aware resolvers
|
|
560
|
+
* (`resolveDefaultProfileForProvider`, `getEffectiveProfilesForProvider`),
|
|
561
|
+
* which are what every runtime and client-facing reader of a default profile's
|
|
562
|
+
* content goes through. The name-only readers that serve from this record
|
|
563
|
+
* (`getEffectiveProfile`, `getEffectiveProfiles`) consume a profile's
|
|
564
|
+
* existence and status, never its model.
|
|
435
565
|
*/
|
|
436
566
|
export const CODE_DEFAULT_PROFILE_ENTRIES: Readonly<
|
|
437
567
|
Record<string, ProfileEntry>
|
|
@@ -517,7 +647,9 @@ function resolveAgainstBody(
|
|
|
517
647
|
* Non-obvious rules:
|
|
518
648
|
*
|
|
519
649
|
* - The `vellum` column stamps `provider: "vellum"` with no connection —
|
|
520
|
-
* dispatch derives the upstream from the model per-request.
|
|
650
|
+
* dispatch derives the upstream from the model per-request. The `chatgpt`
|
|
651
|
+
* column likewise stamps its routing identity with no connection;
|
|
652
|
+
* dispatch resolves the canonical subscription row per-request.
|
|
521
653
|
* - A default provider without a named matrix column materializes from the
|
|
522
654
|
* shared `BYOK_PROFILE_IMPLS` templates, with `resolveModelIntent`
|
|
523
655
|
* falling back to the provider's catalog `defaultModel`.
|
|
@@ -543,17 +675,48 @@ export function isDefaultProfileKey(name: string): name is DefaultProfileKey {
|
|
|
543
675
|
return (DEFAULT_PROFILE_KEYS as readonly string[]).includes(name);
|
|
544
676
|
}
|
|
545
677
|
|
|
678
|
+
/**
|
|
679
|
+
* The implementation of default profile `key` on `provider`: the named matrix
|
|
680
|
+
* column when the provider has one, the shared BYOK template otherwise. The
|
|
681
|
+
* managed column carries the balanced-model experiment arm, which is why the
|
|
682
|
+
* lookup runs through here rather than reading `PROFILE_IMPLS` directly.
|
|
683
|
+
*/
|
|
684
|
+
function defaultProfileImplForProvider(
|
|
685
|
+
key: DefaultProfileKey,
|
|
686
|
+
provider: NonNullable<ProfileEntry["provider"]>,
|
|
687
|
+
): DefaultProfileTemplate {
|
|
688
|
+
if (!isDefaultProfileProvider(provider)) {
|
|
689
|
+
return { ...BYOK_PROFILE_IMPLS[key], provider };
|
|
690
|
+
}
|
|
691
|
+
if (provider === "vellum") {
|
|
692
|
+
return managedProfileImpl(key);
|
|
693
|
+
}
|
|
694
|
+
return PROFILE_IMPLS[key][provider];
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* The code-owned body a default profile name resolves to under the given
|
|
699
|
+
* default provider. This is the single choke point where a default profile key
|
|
700
|
+
* becomes a concrete body, so every consumer (the runtime resolver through
|
|
701
|
+
* `resolveDefaultProfileForProvider`, the client-facing listing through
|
|
702
|
+
* `getEffectiveProfilesForProvider`) reports the same model the request runs
|
|
703
|
+
* on, experiment arm included.
|
|
704
|
+
*/
|
|
546
705
|
function defaultProfileBodyForProvider(
|
|
547
706
|
name: string,
|
|
548
707
|
defaultProvider: DefaultProviderConfig | null,
|
|
549
708
|
): ProfileEntry | undefined {
|
|
550
|
-
if (
|
|
709
|
+
if (!isDefaultProfileKey(name)) {
|
|
551
710
|
return CODE_DEFAULT_PROFILE_ENTRIES[name];
|
|
552
711
|
}
|
|
712
|
+
if (defaultProvider == null) {
|
|
713
|
+
// The frozen `CODE_DEFAULT_PROFILE_ENTRIES` body, re-materialized so an
|
|
714
|
+
// install that predates `llm.defaultProvider` still sees the arm.
|
|
715
|
+
const managed = managedProfileImpl(name);
|
|
716
|
+
return materializeProfile(managed, managed.provider);
|
|
717
|
+
}
|
|
553
718
|
const { provider } = defaultProvider;
|
|
554
|
-
const impl =
|
|
555
|
-
? PROFILE_IMPLS[name][provider]
|
|
556
|
-
: { ...BYOK_PROFILE_IMPLS[name], provider };
|
|
719
|
+
const impl = defaultProfileImplForProvider(name, provider);
|
|
557
720
|
return clampMaxTokensToModelCap({
|
|
558
721
|
...materializeProfile(
|
|
559
722
|
impl,
|
|
@@ -38,7 +38,9 @@ export const OS_BETA_PROFILE_KEY = "os-beta";
|
|
|
38
38
|
/**
|
|
39
39
|
* The named columns of the intent × provider matrix. `vellum` is the
|
|
40
40
|
* platform-managed column (routed through the single `vellum` connection to
|
|
41
|
-
* an underlying provider per profile)
|
|
41
|
+
* an underlying provider per profile) and `chatgpt` is the
|
|
42
|
+
* ChatGPT-subscription column (routed through the `chatgpt-subscription`
|
|
43
|
+
* connection to the Codex endpoint); the rest are BYOK columns whose
|
|
42
44
|
* models resolve per provider via `resolveModelIntent`. The full set of
|
|
43
45
|
* providers that can back `llm.defaultProvider` is wider, see
|
|
44
46
|
* `DEFAULT_PROVIDER_CHOICES` in `schemas/llm.ts`.
|
|
@@ -53,6 +55,7 @@ export const DEFAULT_PROFILE_PROVIDERS = [
|
|
|
53
55
|
"gemini",
|
|
54
56
|
"fireworks",
|
|
55
57
|
"openrouter",
|
|
58
|
+
"chatgpt",
|
|
56
59
|
"vellum",
|
|
57
60
|
] as const;
|
|
58
61
|
export type DefaultProfileProvider = (typeof DEFAULT_PROFILE_PROVIDERS)[number];
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* conveniences (`getDefaultProvider()` without an argument,
|
|
7
7
|
* `setDefaultProvider`) live in `default-provider.ts`.
|
|
8
8
|
*/
|
|
9
|
+
import { CHATGPT_SUBSCRIPTION_CONNECTION_NAME } from "../providers/inference/auth.js";
|
|
9
10
|
import { VELLUM_MANAGED_CONNECTION_NAME } from "../providers/vellum-model-routing.js";
|
|
10
11
|
import type { DefaultProviderConfig } from "./schemas/llm.js";
|
|
11
12
|
import type { AssistantConfig } from "./types.js";
|
|
@@ -29,5 +30,8 @@ export function resolveDefaultConnectionName(
|
|
|
29
30
|
if (dp.provider === "vellum") {
|
|
30
31
|
return VELLUM_MANAGED_CONNECTION_NAME;
|
|
31
32
|
}
|
|
33
|
+
if (dp.provider === "chatgpt") {
|
|
34
|
+
return CHATGPT_SUBSCRIPTION_CONNECTION_NAME;
|
|
35
|
+
}
|
|
32
36
|
return `${dp.provider}-personal`;
|
|
33
37
|
}
|
|
@@ -36,15 +36,6 @@
|
|
|
36
36
|
"defaultEnabled": "control",
|
|
37
37
|
"values": ["control", "variant-a", "personal-page"]
|
|
38
38
|
},
|
|
39
|
-
{
|
|
40
|
-
"id": "experiment-billing-cta-2026-07-23",
|
|
41
|
-
"scope": "client",
|
|
42
|
-
"key": "experiment-billing-cta-2026-07-23",
|
|
43
|
-
"label": "Experiment: Billing CTA 2026-07-23",
|
|
44
|
-
"description": "Credit paywall CTA experiment. control = single Add Credits CTA for everyone (opens Add Credits modal). upgrade-cta = FREE users (plan_id base) get a single Upgrade CTA (View Plans takeover) instead; PAID users still get Add Credits.",
|
|
45
|
-
"defaultEnabled": "control",
|
|
46
|
-
"values": ["control", "upgrade-cta"]
|
|
47
|
-
},
|
|
48
39
|
{
|
|
49
40
|
"id": "local-docker-enabled",
|
|
50
41
|
"scope": "client",
|
|
@@ -247,10 +238,10 @@
|
|
|
247
238
|
},
|
|
248
239
|
{
|
|
249
240
|
"id": "web-remote-ingress",
|
|
250
|
-
"scope": "
|
|
241
|
+
"scope": "client",
|
|
251
242
|
"key": "web-remote-ingress",
|
|
252
243
|
"label": "Web Remote Ingress",
|
|
253
|
-
"description": "
|
|
244
|
+
"description": "Show the pair-a-device card in web settings. Visibility only; pairing itself is always available.",
|
|
254
245
|
"defaultEnabled": false
|
|
255
246
|
},
|
|
256
247
|
{
|
|
@@ -371,7 +362,16 @@
|
|
|
371
362
|
"key": "plugin-schedules",
|
|
372
363
|
"label": "Plugin Schedules",
|
|
373
364
|
"description": "Plugins declare recurring schedules as files that register and run automatically",
|
|
374
|
-
"defaultEnabled":
|
|
365
|
+
"defaultEnabled": true
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
"id": "experiment-balanced-model-2026-08-06",
|
|
369
|
+
"scope": "assistant",
|
|
370
|
+
"key": "experiment-balanced-model-2026-08-06",
|
|
371
|
+
"label": "Experiment: Balanced Profile Model",
|
|
372
|
+
"description": "Multivariate experiment on the model the managed Balanced inference profile resolves to. control = gpt-5.6-luna (the shipped pin); terra = gpt-5.6-terra; glm-5p2 = accounts/fireworks/models/glm-5p2. Only the managed (vellum) implementation moves: ChatGPT-subscription and BYOK installs run the provider the user chose and are outside the experiment. Rollout and targeting are managed in the LaunchDarkly dashboard; any value that is not an arm name resolves to control.",
|
|
373
|
+
"defaultEnabled": "control",
|
|
374
|
+
"values": ["control", "terra", "glm-5p2"]
|
|
375
375
|
}
|
|
376
376
|
]
|
|
377
377
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolveEntryProviderKind } from "../providers/connection-resolution.js";
|
|
1
2
|
import { ROUTING_IDENTITY_PROVIDERS } from "../providers/inference/auth.js";
|
|
2
3
|
import {
|
|
3
4
|
getCatalogProviderForModel,
|
|
@@ -54,11 +55,18 @@ export function resolveEffectiveContextWindow({
|
|
|
54
55
|
forceOverrideProfile,
|
|
55
56
|
selectionSeed,
|
|
56
57
|
});
|
|
57
|
-
// Routing identities
|
|
58
|
-
// carries
|
|
58
|
+
// Routing identities dispatch built-in catalog models, so the model's
|
|
59
|
+
// catalog owner carries their limits. An entry-name provider resolves
|
|
60
|
+
// through its row's kind instead: a custom-endpoint kind has no catalog
|
|
61
|
+
// models, so its models keep the conservative default even when a model
|
|
62
|
+
// id collides with a built-in one (the custom endpoint's "gpt-5.5" is not
|
|
63
|
+
// OpenAI's). Labels with no row fall back to the model's catalog owner.
|
|
59
64
|
const catalogProviderId = ROUTING_IDENTITY_PROVIDERS.has(resolved.provider)
|
|
60
65
|
? getCatalogProviderForModel(resolved.model)
|
|
61
|
-
: resolved.provider
|
|
66
|
+
: PROVIDER_CATALOG.some((p) => p.id === resolved.provider)
|
|
67
|
+
? resolved.provider
|
|
68
|
+
: (resolveEntryProviderKind(resolved.provider, resolved.model) ??
|
|
69
|
+
getCatalogProviderForModel(resolved.model));
|
|
62
70
|
const catalogModel = PROVIDER_CATALOG.find(
|
|
63
71
|
(provider) => provider.id === catalogProviderId,
|
|
64
72
|
)?.models.find((model) => model.id === resolved.model);
|
|
@@ -76,6 +76,15 @@ import {
|
|
|
76
76
|
*/
|
|
77
77
|
export interface ResolveCallSiteOpts {
|
|
78
78
|
overrideProfile?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Whether a profile's provider value can actually dispatch: a known
|
|
81
|
+
* vendor, or a connection entry row. Selection is pure and DB-blind, so
|
|
82
|
+
* dispatch-side callers supply this (see `dispatchProviderResolvable` in
|
|
83
|
+
* `connection-resolution.ts`); a profile failing it is unusable and
|
|
84
|
+
* selection falls through to the next rung, keeping model and transport
|
|
85
|
+
* coherent. When absent, every provider is assumed resolvable.
|
|
86
|
+
*/
|
|
87
|
+
isResolvableProvider?: (provider: string) => boolean;
|
|
79
88
|
/**
|
|
80
89
|
* Float `overrideProfile` above the call-site layers for non-main-agent call
|
|
81
90
|
* sites. Retained for API compatibility; under single-winner selection the
|
|
@@ -112,7 +121,11 @@ export interface ResolveCallSiteOpts {
|
|
|
112
121
|
}) => void;
|
|
113
122
|
}
|
|
114
123
|
|
|
115
|
-
export type ResolutionFallbackReason =
|
|
124
|
+
export type ResolutionFallbackReason =
|
|
125
|
+
| "missing"
|
|
126
|
+
| "disabled"
|
|
127
|
+
| "incomplete"
|
|
128
|
+
| "unresolvable";
|
|
116
129
|
|
|
117
130
|
export interface ResolvedCallSiteConfig {
|
|
118
131
|
config: z.infer<typeof LLMConfigBase>;
|
|
@@ -313,6 +326,20 @@ function usableEntry(
|
|
|
313
326
|
report(name, "incomplete");
|
|
314
327
|
return undefined;
|
|
315
328
|
}
|
|
329
|
+
// A provider the caller cannot resolve (not a known vendor, not an entry
|
|
330
|
+
// row) makes the profile unusable, and selection falls through to the
|
|
331
|
+
// next rung the same way an incomplete profile does: the fallback keeps
|
|
332
|
+
// model and transport coherent, where a dispatch-time fallback would pair
|
|
333
|
+
// this profile's model with the default transport. Selection is DB-blind,
|
|
334
|
+
// so the predicate is supplied by dispatch-side callers; when absent,
|
|
335
|
+
// every provider is assumed resolvable.
|
|
336
|
+
if (
|
|
337
|
+
opts.isResolvableProvider != null &&
|
|
338
|
+
!opts.isResolvableProvider(entry.provider)
|
|
339
|
+
) {
|
|
340
|
+
report(name, "unresolvable");
|
|
341
|
+
return undefined;
|
|
342
|
+
}
|
|
316
343
|
return { name, entry };
|
|
317
344
|
}
|
|
318
345
|
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { getDb } from "../persistence/db-connection.js";
|
|
1
2
|
import { ROUTING_IDENTITY_PROVIDERS } from "../providers/inference/auth.js";
|
|
3
|
+
import { getConnection } from "../providers/inference/connections.js";
|
|
2
4
|
import {
|
|
3
5
|
getCatalogProviderForModel,
|
|
4
6
|
isModelInCatalog,
|
|
5
7
|
} from "../providers/model-catalog.js";
|
|
6
8
|
import {
|
|
9
|
+
getManagedUpstream,
|
|
7
10
|
MANAGED_ROUTABLE_PROVIDERS,
|
|
8
11
|
VELLUM_MANAGED_CONNECTION_NAME,
|
|
9
12
|
} from "../providers/vellum-model-routing.js";
|
|
@@ -97,35 +100,80 @@ export function completeCustomProfile(
|
|
|
97
100
|
}
|
|
98
101
|
}
|
|
99
102
|
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
// would
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
//
|
|
103
|
+
// Completion never stamps a `provider_connection`; an inherited binding
|
|
104
|
+
// would only re-introduce the collapsed field on disk. The default's
|
|
105
|
+
// explicit binding is instead inherited IN the provider value, the
|
|
106
|
+
// entries-model representation: the vellum binding becomes the routing
|
|
107
|
+
// identity (only when it can serve the model, or the read-path schema
|
|
108
|
+
// would strip the profile), and a same-vendor binding becomes the entry
|
|
109
|
+
// name, so a completed profile keeps signing with the credential the
|
|
110
|
+
// workspace default names rather than whatever auto-resolution finds
|
|
111
|
+
// first.
|
|
109
112
|
if (
|
|
110
113
|
completed.provider !== undefined &&
|
|
111
|
-
ROUTING_IDENTITY_PROVIDERS.has(completed.provider)
|
|
114
|
+
!ROUTING_IDENTITY_PROVIDERS.has(completed.provider) &&
|
|
115
|
+
profile.provider_connection === undefined &&
|
|
116
|
+
dflt.provider_connection !== undefined
|
|
112
117
|
) {
|
|
113
|
-
|
|
118
|
+
if (dflt.provider_connection === VELLUM_MANAGED_CONNECTION_NAME) {
|
|
119
|
+
// Only managed-servable pairs inherit the managed binding; anything
|
|
120
|
+
// else inherits nothing and lets dispatch auto-resolve by vendor,
|
|
121
|
+
// matching the pre-entries inheritance contract.
|
|
122
|
+
if (
|
|
123
|
+
MANAGED_ROUTABLE_PROVIDERS.has(completed.provider) &&
|
|
124
|
+
completed.model !== undefined &&
|
|
125
|
+
getManagedUpstream(completed.model) !== null
|
|
126
|
+
) {
|
|
127
|
+
completed.provider = "vellum";
|
|
128
|
+
}
|
|
129
|
+
} else if (completed.provider === dflt.provider) {
|
|
130
|
+
// Folding to the entry name is only safe against a verified row; a
|
|
131
|
+
// dangling or kind-disagreeing binding stays in the legacy field,
|
|
132
|
+
// where the collapse migration's recovery can judge it.
|
|
133
|
+
if (bindingRowKind(dflt.provider_connection) === completed.provider) {
|
|
134
|
+
completed.provider = dflt.provider_connection;
|
|
135
|
+
} else {
|
|
136
|
+
completed.provider_connection = dflt.provider_connection;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
114
139
|
}
|
|
140
|
+
return structuredClone(completed);
|
|
141
|
+
}
|
|
115
142
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
143
|
+
/**
|
|
144
|
+
* `{...raw, ...completed}` recursively: completed (schema-known) values win,
|
|
145
|
+
* raw keys the schema stripped survive at every depth. Used by boot
|
|
146
|
+
* materialization and the config write path so both preserve unknown keys
|
|
147
|
+
* the same way after `safeParse`.
|
|
148
|
+
*/
|
|
149
|
+
export function mergePreservingUnknownKeys(
|
|
150
|
+
raw: Record<string, unknown>,
|
|
151
|
+
completed: Record<string, unknown>,
|
|
152
|
+
): Record<string, unknown> {
|
|
153
|
+
const out: Record<string, unknown> = { ...raw, ...completed };
|
|
154
|
+
for (const [key, value] of Object.entries(completed)) {
|
|
155
|
+
const rawValue = raw[key];
|
|
156
|
+
if (isRecord(value) && isRecord(rawValue)) {
|
|
157
|
+
out[key] = mergePreservingUnknownKeys(rawValue, value);
|
|
158
|
+
}
|
|
126
159
|
}
|
|
160
|
+
return out;
|
|
161
|
+
}
|
|
127
162
|
|
|
128
|
-
|
|
163
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
164
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* The provider kind stored on a connection row, or null when the row is
|
|
169
|
+
* missing or the DB is unavailable (both mean "unverifiable" to callers).
|
|
170
|
+
*/
|
|
171
|
+
function bindingRowKind(name: string): string | null {
|
|
172
|
+
try {
|
|
173
|
+
return getConnection(getDb(), name)?.provider ?? null;
|
|
174
|
+
} catch {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
129
177
|
}
|
|
130
178
|
|
|
131
179
|
type PlainObject = Record<string, unknown>;
|