@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.
Files changed (596) hide show
  1. package/AGENTS.md +9 -3
  2. package/ARCHITECTURE.md +32 -10
  3. package/docs/architecture/memory.md +43 -5
  4. package/docs/architecture/security.md +96 -152
  5. package/docs/architecture/turn-actor.md +70 -0
  6. package/docs/browser-use-architecture-phase2.md +128 -56
  7. package/docs/flux-turn-detection-spike.md +248 -0
  8. package/docs/guardian-request-flow.md +35 -0
  9. package/docs/stt-provider-onboarding.md +3 -1
  10. package/knip.json +3 -0
  11. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  12. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
  13. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
  14. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  15. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
  16. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
  17. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  18. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
  19. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
  20. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  21. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
  22. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
  23. package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +34 -0
  24. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +166 -1
  25. package/node_modules/@vellumai/gateway-client/src/index.ts +2 -0
  26. package/node_modules/@vellumai/service-contracts/package.json +1 -0
  27. package/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
  28. package/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
  29. package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  30. package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
  31. package/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
  32. package/openapi.yaml +289 -113
  33. package/package.json +1 -1
  34. package/scripts/voice-ttft-spike.ts +3 -3
  35. package/scripts/write-plugin-api-shim.ts +10 -0
  36. package/src/__tests__/app-compiler.test.ts +38 -3
  37. package/src/__tests__/app-control-flow.test.ts +1 -0
  38. package/src/__tests__/approval-routes-http.test.ts +2 -2
  39. package/src/__tests__/assistant-feature-flag-guard.test.ts +25 -3
  40. package/src/__tests__/attachments-store.test.ts +21 -12
  41. package/src/__tests__/byok-default-profile-ensure.test.ts +17 -0
  42. package/src/__tests__/call-setup-flow-name-capture.test.ts +0 -1
  43. package/src/__tests__/call-site-routing-provider.test.ts +1 -1
  44. package/src/__tests__/channel-availability-routes.test.ts +14 -1
  45. package/src/__tests__/channel-capabilities-dedupe.test.ts +214 -0
  46. package/src/__tests__/channel-delivery-store.test.ts +14 -14
  47. package/src/__tests__/channel-inbound-disk-pressure.test.ts +4 -4
  48. package/src/__tests__/channel-setup-panel-ack.test.ts +1 -1
  49. package/src/__tests__/checker.test.ts +20 -314
  50. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +6 -2
  51. package/src/__tests__/compaction-events.test.ts +8 -10
  52. package/src/__tests__/config-loader-backfill.test.ts +3 -3
  53. package/src/__tests__/config-schema.test.ts +25 -10
  54. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
  55. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +8 -11
  56. package/src/__tests__/conversation-agent-loop-overflow.test.ts +8 -11
  57. package/src/__tests__/conversation-agent-loop.test.ts +32 -21
  58. package/src/__tests__/conversation-attachments.test.ts +0 -1
  59. package/src/__tests__/conversation-attention-store.test.ts +63 -0
  60. package/src/__tests__/conversation-confirmation-signals.test.ts +112 -0
  61. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -4
  62. package/src/__tests__/conversation-fork-crud.test.ts +69 -0
  63. package/src/__tests__/conversation-fork-referential.test.ts +67 -0
  64. package/src/__tests__/conversation-fork-retrospective.test.ts +24 -0
  65. package/src/__tests__/conversation-load-history-repair.test.ts +209 -0
  66. package/src/__tests__/conversation-notifiers-provenance.test.ts +59 -0
  67. package/src/__tests__/conversation-queue.test.ts +154 -4
  68. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
  69. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +1 -1
  70. package/src/__tests__/conversation-routes-guardian-reply.test.ts +9 -9
  71. package/src/__tests__/conversation-routes-hidden-queue.test.ts +1 -1
  72. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -1
  73. package/src/__tests__/conversation-runtime-assembly.test.ts +187 -102
  74. package/src/__tests__/conversation-runtime-workspace.test.ts +14 -10
  75. package/src/__tests__/conversation-slash-queue.test.ts +3 -0
  76. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +1 -0
  77. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +1 -0
  78. package/src/__tests__/conversation-surfaces-app-control.test.ts +1 -0
  79. package/src/__tests__/conversation-surfaces-app-open.test.ts +1 -1
  80. package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -1
  81. package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +21 -14
  82. package/src/__tests__/conversation-surfaces-queued-emit.test.ts +1 -0
  83. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1 -0
  84. package/src/__tests__/conversation-surfaces-standalone.test.ts +1 -0
  85. package/src/__tests__/conversation-surfaces-state-update.test.ts +1 -1
  86. package/src/__tests__/conversation-surfaces-table-action.test.ts +1 -1
  87. package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -1
  88. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +1 -1
  89. package/src/__tests__/conversation-tool-setup-attribution.test.ts +1 -1
  90. package/src/__tests__/credential-prompt-route.test.ts +7 -10
  91. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  92. package/src/__tests__/cu-unified-flow.test.ts +1 -0
  93. package/src/__tests__/custom-profile-ensure.test.ts +5 -1
  94. package/src/__tests__/default-plugin-names-guard.test.ts +12 -1
  95. package/src/__tests__/discord-access-request-privacy.test.ts +5 -1
  96. package/src/__tests__/discord-requester-notice-privacy.test.ts +3 -3
  97. package/src/__tests__/document-append-idempotency.test.ts +233 -0
  98. package/src/__tests__/document-sync-tags.test.ts +0 -75
  99. package/src/__tests__/dynamic-skill-background-guard.test.ts +0 -2
  100. package/src/__tests__/edit-propagation.test.ts +107 -11
  101. package/src/__tests__/file-ops-service.test.ts +163 -30
  102. package/src/__tests__/filesystem-tools.test.ts +23 -24
  103. package/src/__tests__/gateway-only-guard.test.ts +2 -5
  104. package/src/__tests__/helpers/gateway-classify-mock.ts +27 -6
  105. package/src/__tests__/helpers/mock-actor-context.ts +49 -0
  106. package/src/__tests__/helpers/mock-conversation.ts +13 -1
  107. package/src/__tests__/host-file-read-tool.test.ts +16 -19
  108. package/src/__tests__/http-user-message-parity.test.ts +1 -1
  109. package/src/__tests__/init-feature-flag-overrides.test.ts +49 -0
  110. package/src/__tests__/injector-chain.test.ts +63 -41
  111. package/src/__tests__/injector-disk-pressure.test.ts +11 -23
  112. package/src/__tests__/inline-skill-load-permissions.test.ts +47 -36
  113. package/src/__tests__/llm-context-resolution.test.ts +73 -1
  114. package/src/__tests__/llm-schema.test.ts +5 -2
  115. package/src/__tests__/managed-skill-lifecycle.test.ts +7 -0
  116. package/src/__tests__/mcp-list-plugin-servers.test.ts +250 -0
  117. package/src/__tests__/media-generate-image.test.ts +131 -21
  118. package/src/__tests__/memory-retrieval-hook.test.ts +100 -7
  119. package/src/__tests__/messages-read-boundary-guard.test.ts +134 -0
  120. package/src/__tests__/mtime-cache.test.ts +3 -1
  121. package/src/__tests__/non-member-access-request.test.ts +0 -20
  122. package/src/__tests__/outbound-slack-persistence.test.ts +40 -1
  123. package/src/__tests__/platform-bash-auto-approve.test.ts +0 -4
  124. package/src/__tests__/plugin-api-store-credential.test.ts +261 -0
  125. package/src/__tests__/plugin-api-webhook-url.test.ts +10 -7
  126. package/src/__tests__/plugin-disabled-state.test.ts +2 -0
  127. package/src/__tests__/plugin-effective-enabled-set.test.ts +55 -3
  128. package/src/__tests__/plugin-execution-context.test.ts +73 -0
  129. package/src/__tests__/plugin-import-boundary-guard.test.ts +5 -1
  130. package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +7 -4
  131. package/src/__tests__/plugin-secret-pattern-contribution.test.ts +1 -1
  132. package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +14 -7
  133. package/src/__tests__/provider-commit-message-generator.test.ts +20 -0
  134. package/src/__tests__/proxy-approval-callback.test.ts +1 -0
  135. package/src/__tests__/qdrant-manager.test.ts +14 -1
  136. package/src/__tests__/reaction-persistence.test.ts +200 -7
  137. package/src/__tests__/require-fresh-approval.test.ts +0 -4
  138. package/src/__tests__/risk-classification-boundary-guard.test.ts +115 -0
  139. package/src/__tests__/run-conversation-turn-persistence.test.ts +460 -105
  140. package/src/__tests__/run-due-schedules.test.ts +21 -0
  141. package/src/__tests__/scaffold-managed-skill-tool.test.ts +187 -18
  142. package/src/__tests__/schedule-routes.test.ts +23 -0
  143. package/src/__tests__/schedule-store.test.ts +17 -0
  144. package/src/__tests__/scoped-approval-grants.test.ts +11 -6
  145. package/src/__tests__/secret-ingress-channel.test.ts +0 -1
  146. package/src/__tests__/secret-ingress-http.test.ts +1 -1
  147. package/src/__tests__/send-endpoint-busy.test.ts +3 -3
  148. package/src/__tests__/skills.test.ts +32 -0
  149. package/src/__tests__/slack-edit-ordering-characterization.test.ts +0 -1
  150. package/src/__tests__/starter-task-flow.test.ts +5 -4
  151. package/src/__tests__/subagent-call-site-routing.test.ts +31 -19
  152. package/src/__tests__/subagent-fork-prompt-role.test.ts +1 -1
  153. package/src/__tests__/subagent-spawn-and-await.test.ts +18 -17
  154. package/src/__tests__/subagent-tool-gate-mode.test.ts +1 -1
  155. package/src/__tests__/subagent-tools.test.ts +81 -101
  156. package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +1 -0
  157. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
  158. package/src/__tests__/tool-executor-lifecycle-events.test.ts +132 -5
  159. package/src/__tests__/tool-executor.test.ts +68 -39
  160. package/src/__tests__/turn-events-store.test.ts +43 -0
  161. package/src/__tests__/ui-choice-copy-surfaces.test.ts +1 -1
  162. package/src/__tests__/ui-shape-teaching.test.ts +33 -0
  163. package/src/__tests__/ui-visual-surface.test.ts +1 -1
  164. package/src/__tests__/ui-voice-picker-surface.test.ts +128 -0
  165. package/src/__tests__/ui-work-result-surface.test.ts +1 -1
  166. package/src/__tests__/user-plugin-loader.test.ts +3 -1
  167. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  168. package/src/__tests__/visible-app-context.test.ts +16 -9
  169. package/src/__tests__/voice-config-update.test.ts +40 -0
  170. package/src/__tests__/voice-scoped-grant-consumer.test.ts +5 -3
  171. package/src/__tests__/voice-session-bridge.test.ts +85 -29
  172. package/src/__tests__/worker-entrypoint-guards.test.ts +54 -0
  173. package/src/__tests__/worker-plugin-surface.test.ts +77 -0
  174. package/src/__tests__/workspace-migration-142-consolidate-voice-front-door.test.ts +158 -0
  175. package/src/__tests__/workspace-migration-143-repair-deprecated-codex-model-id.test.ts +133 -0
  176. package/src/__tests__/workspace-migration-144-convert-stranded-subscription-openai-profiles.test.ts +316 -0
  177. package/src/__tests__/workspace-migration-145-collapse-profile-bindings-to-entries.test.ts +325 -0
  178. package/src/__tests__/workspace-migration-146-repair-retired-fireworks-deepseek-flash-model-id.test.ts +235 -0
  179. package/src/acp/__tests__/acp-claude-oauth.test.ts +10 -2
  180. package/src/acp/__tests__/auth-required.test.ts +161 -0
  181. package/src/acp/acp-claude-oauth.ts +19 -2
  182. package/src/acp/agent-process.test.ts +100 -0
  183. package/src/acp/agent-process.ts +29 -26
  184. package/src/acp/auth-required.ts +102 -0
  185. package/src/acp/session-manager.test.ts +119 -0
  186. package/src/acp/session-manager.ts +76 -3
  187. package/src/api/events/acp-auth-required.ts +55 -0
  188. package/src/api/events/host-file.ts +2 -2
  189. package/src/api/index.ts +7 -0
  190. package/src/api/surfaces.ts +12 -3
  191. package/src/apps/app-store.ts +3 -0
  192. package/src/bundler/package-resolver.ts +2 -30
  193. package/src/calls/__tests__/voice-session-bridge.test.ts +194 -11
  194. package/src/calls/__tests__/voice-triage-escalate.test.ts +102 -0
  195. package/src/calls/call-controller.ts +19 -3
  196. package/src/calls/call-setup-flow.ts +0 -1
  197. package/src/calls/media-stream-stt-session.ts +15 -0
  198. package/src/calls/voice-session-bridge.ts +115 -41
  199. package/src/calls/voice-triage-escalate.ts +105 -2
  200. package/src/channels/__tests__/plugin-channel-declarations.test.ts +161 -0
  201. package/src/channels/config.ts +13 -0
  202. package/src/channels/plugin-channel-declarations.ts +108 -0
  203. package/src/channels/types.ts +30 -0
  204. package/src/cli/AGENTS.md +5 -2
  205. package/src/cli/bundled-modules.ts +29 -0
  206. package/src/cli/commands/credentials.help.ts +2 -2
  207. package/src/cli/commands/db/repair.ts +4 -8
  208. package/src/cli/commands/domain.ts +6 -3
  209. package/src/cli/commands/email.ts +6 -3
  210. package/src/cli/commands/inference-providers.ts +1 -1
  211. package/src/cli/commands/keys.ts +8 -3
  212. package/src/cli/commands/mcp.help.ts +13 -4
  213. package/src/cli/commands/mcp.ts +9 -0
  214. package/src/cli/commands/memory/__tests__/memory-v2.test.ts +57 -7
  215. package/src/cli/commands/memory/__tests__/memory-v3.test.ts +128 -5
  216. package/src/cli/commands/memory/index.help.ts +84 -28
  217. package/src/cli/commands/memory/index.ts +2 -0
  218. package/src/cli/commands/memory/memory-v2.ts +58 -54
  219. package/src/cli/commands/memory/memory-v3.ts +64 -0
  220. package/src/cli/commands/memory/memory-validate.ts +18 -0
  221. package/src/cli/commands/plugins.ts +85 -36
  222. package/src/cli/commands/schedules.ts +35 -1
  223. package/src/cli/commands/stt.help.ts +27 -2
  224. package/src/cli/commands/trust.ts +3 -14
  225. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +39 -0
  226. package/src/cli/lib/bundled-marketplace.json +14 -1
  227. package/src/cli/lib/upgrade-plugin.ts +42 -0
  228. package/src/config/__tests__/balanced-model-experiment.test.ts +278 -0
  229. package/src/config/__tests__/default-profile-catalog.test.ts +34 -2
  230. package/src/config/__tests__/default-provider.test.ts +6 -1
  231. package/src/config/__tests__/profile-materialization.test.ts +75 -19
  232. package/src/config/assistant-feature-flags.ts +36 -15
  233. package/src/config/balanced-model-experiment.ts +35 -0
  234. package/src/config/bundled-skills/acp/SKILL.md +6 -7
  235. package/src/config/bundled-skills/document-editor/SKILL.md +2 -2
  236. package/src/config/bundled-skills/document-editor/TOOLS.json +2 -2
  237. package/src/config/bundled-skills/image-studio/SKILL.md +5 -4
  238. package/src/config/bundled-skills/image-studio/TOOLS.json +1 -1
  239. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +101 -0
  240. package/src/config/bundled-skills/media-processing/services/preprocess.ts +14 -4
  241. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  242. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.test.ts +65 -0
  243. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +7 -1
  244. package/src/config/bundled-skills/settings/tools/shared.ts +16 -0
  245. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +19 -1
  246. package/src/config/bundled-skills/skill-management/TOOLS.json +9 -3
  247. package/src/config/bundled-skills/subagent/SKILL.md +17 -12
  248. package/src/config/bundled-skills/subagent/TOOLS.json +4 -4
  249. package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +22 -1
  250. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +9 -2
  251. package/src/config/call-site-defaults.ts +11 -5
  252. package/src/config/default-profile-catalog.ts +179 -16
  253. package/src/config/default-profile-names.ts +4 -1
  254. package/src/config/default-provider-resolution.ts +4 -0
  255. package/src/config/feature-flag-registry.json +12 -12
  256. package/src/config/llm-context-resolution.ts +11 -3
  257. package/src/config/llm-resolver.ts +28 -1
  258. package/src/config/profile-materialization.ts +70 -22
  259. package/src/config/schemas/__tests__/live-voice.test.ts +107 -4
  260. package/src/config/schemas/call-site-catalog.ts +4 -4
  261. package/src/config/schemas/live-voice.ts +57 -23
  262. package/src/config/schemas/llm.ts +59 -32
  263. package/src/config/schemas/mcp.ts +23 -0
  264. package/src/config/schemas/plugin-updates.ts +6 -2
  265. package/src/config/schemas/stt.ts +1 -0
  266. package/src/config/skills.ts +9 -2
  267. package/src/context/outbound-sanitize.ts +96 -1
  268. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +1 -1
  269. package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +82 -0
  270. package/src/daemon/conversation-agent-loop-handlers.ts +15 -10
  271. package/src/daemon/conversation-agent-loop.ts +31 -19
  272. package/src/daemon/conversation-messaging.ts +5 -1
  273. package/src/daemon/conversation-notifiers.ts +20 -10
  274. package/src/daemon/conversation-process.ts +20 -6
  275. package/src/daemon/conversation-runtime-assembly.ts +12 -6
  276. package/src/daemon/conversation-store.ts +14 -4
  277. package/src/daemon/conversation-surfaces.ts +75 -26
  278. package/src/daemon/conversation-tool-setup.ts +3 -6
  279. package/src/daemon/conversation.ts +154 -51
  280. package/src/daemon/doordash-steps.ts +2 -2
  281. package/src/daemon/lifecycle.ts +14 -1
  282. package/src/daemon/mcp-reload-service.ts +36 -6
  283. package/src/daemon/process-message.ts +13 -26
  284. package/src/daemon/providers-setup.ts +6 -3
  285. package/src/daemon/trust-context-types.ts +29 -0
  286. package/src/daemon/trust-context.ts +12 -7
  287. package/src/daemon/wake-conversation-ops.ts +3 -2
  288. package/src/daemon/windows-compiled-entry.ts +4 -0
  289. package/src/documents/document-store.ts +143 -240
  290. package/src/hooks/hook-loader.ts +3 -3
  291. package/src/hooks/registry.ts +103 -45
  292. package/src/hooks/types.ts +5 -0
  293. package/src/inbound/__tests__/oauth-callback-url.test.ts +83 -0
  294. package/src/inbound/oauth-callback-url.ts +61 -0
  295. package/src/ipc/gateway-client.test.ts +1 -1
  296. package/src/ipc/gateway-client.ts +14 -21
  297. package/src/ipc/gateway-flag-listener.ts +17 -3
  298. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +1 -104
  299. package/src/live-voice/__tests__/live-voice-events.test.ts +7 -8
  300. package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +1050 -0
  301. package/src/live-voice/__tests__/live-voice-metrics.test.ts +115 -8
  302. package/src/live-voice/__tests__/live-voice-photo.test.ts +100 -0
  303. package/src/live-voice/__tests__/live-voice-progress.test.ts +60 -194
  304. package/src/live-voice/__tests__/live-voice-stt.test.ts +14 -0
  305. package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +29 -0
  306. package/src/live-voice/__tests__/live-voice-tts-session.test.ts +0 -483
  307. package/src/live-voice/__tests__/live-voice-vad.test.ts +0 -16
  308. package/src/live-voice/__tests__/progress-narration.test.ts +214 -0
  309. package/src/live-voice/live-voice-archive.ts +2 -0
  310. package/src/live-voice/live-voice-manager.ts +16 -3
  311. package/src/live-voice/live-voice-metrics.ts +57 -32
  312. package/src/live-voice/live-voice-photo.ts +1 -2
  313. package/src/live-voice/live-voice-session.ts +598 -323
  314. package/src/live-voice/progress-narration.ts +277 -0
  315. package/src/live-voice/protocol.ts +21 -1
  316. package/src/live-voice/windows-compiled-live-voice.ts +4 -0
  317. package/src/mcp/__tests__/effective-config.test.ts +238 -0
  318. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
  319. package/src/mcp/__tests__/mcp-oauth-client-registration.test.ts +200 -0
  320. package/src/mcp/__tests__/mcp-oauth-provider.test.ts +9 -9
  321. package/src/mcp/__tests__/plugin-server-credential-isolation.test.ts +95 -0
  322. package/src/mcp/client.ts +16 -11
  323. package/src/mcp/effective-config.ts +113 -0
  324. package/src/mcp/manager.ts +11 -6
  325. package/src/mcp/mcp-auth-orchestrator.ts +13 -22
  326. package/src/mcp/mcp-oauth-provider.ts +205 -240
  327. package/src/monitoring/__tests__/plugin-auto-update.test.ts +166 -3
  328. package/src/monitoring/control.ts +1 -0
  329. package/src/monitoring/db-integrity-sample.ts +4 -5
  330. package/src/monitoring/plugin-auto-update.ts +128 -24
  331. package/src/notifications/AGENTS.md +2 -0
  332. package/src/notifications/approval-card-data.ts +33 -0
  333. package/src/notifications/signal.ts +1 -0
  334. package/src/permissions/AGENTS.md +16 -0
  335. package/src/permissions/checker.test.ts +75 -122
  336. package/src/permissions/checker.ts +44 -560
  337. package/src/permissions/confirmation-guardian-request.test.ts +15 -11
  338. package/src/permissions/confirmation-guardian-request.ts +2 -2
  339. package/src/permissions/prompter.ts +1 -5
  340. package/src/permissions/question-guardian-request.test.ts +14 -6
  341. package/src/permissions/question-guardian-request.ts +1 -2
  342. package/src/persistence/attachments-store.ts +8 -1
  343. package/src/persistence/bookmark-crud.ts +3 -7
  344. package/src/persistence/conversation-attention-store.ts +16 -45
  345. package/src/persistence/conversation-crud.ts +33 -4
  346. package/src/persistence/conversation-lineage.ts +9 -0
  347. package/src/persistence/conversation-queries.ts +182 -52
  348. package/src/persistence/delivery-crud.ts +150 -36
  349. package/src/persistence/embeddings/qdrant-manager.ts +84 -49
  350. package/src/persistence/external-conversation-store.ts +32 -4
  351. package/src/persistence/llm-request-log-store.ts +4 -10
  352. package/src/persistence/llm-usage-store.ts +8 -3
  353. package/src/persistence/message-reads.test.ts +197 -0
  354. package/src/persistence/message-reads.ts +211 -0
  355. package/src/persistence/migrations/360-add-document-workspace-path.ts +5 -14
  356. package/src/persistence/migrations/366-chatgpt-subscription-row-identity.test.ts +120 -0
  357. package/src/persistence/migrations/366-chatgpt-subscription-row-identity.ts +62 -0
  358. package/src/persistence/real-user-turn-filter.ts +27 -3
  359. package/src/persistence/schema/documents.ts +4 -4
  360. package/src/persistence/steps.ts +9 -0
  361. package/src/plugin-api/__tests__/oauth-callback-url-export.test.ts +29 -0
  362. package/src/plugin-api/constants.ts +8 -0
  363. package/src/plugin-api/conversation-turn.ts +195 -5
  364. package/src/plugin-api/index.ts +38 -6
  365. package/src/plugin-api/resolve-credential.ts +3 -2
  366. package/src/plugin-api/store-credential.ts +146 -0
  367. package/src/plugin-api/vision-support.test.ts +1 -1
  368. package/src/plugin-api/webhook-url.ts +13 -11
  369. package/src/plugins/__tests__/mcp-servers.test.ts +371 -0
  370. package/src/plugins/defaults/main.ts +21 -7
  371. package/src/plugins/defaults/memory/AGENTS.md +15 -3
  372. package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +204 -0
  373. package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +72 -0
  374. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +4 -1
  375. package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +4 -1
  376. package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +0 -1
  377. package/src/plugins/defaults/memory/buffer-format.ts +165 -0
  378. package/src/plugins/defaults/memory/context-search/sources/conversations.ts +6 -0
  379. package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +77 -0
  380. package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +24 -6
  381. package/src/plugins/defaults/memory/graph/image-ref-utils.ts +3 -0
  382. package/src/plugins/defaults/memory/graph/tool-handlers.ts +1 -30
  383. package/src/plugins/defaults/memory/graph-topology/pending-buffer.test.ts +34 -0
  384. package/src/plugins/defaults/memory/graph-topology/pending-buffer.ts +17 -24
  385. package/src/plugins/defaults/memory/hooks/post-compact.ts +1 -4
  386. package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +53 -5
  387. package/src/plugins/defaults/memory/indexer.ts +3 -1
  388. package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +19 -7
  389. package/src/plugins/defaults/memory/memory-retrospective-job.ts +4 -4
  390. package/src/plugins/defaults/memory/src/__tests__/memory-v3-gate-stats.test.ts +281 -0
  391. package/src/plugins/defaults/memory/src/memory-v2-routes.ts +12 -10
  392. package/src/plugins/defaults/memory/src/memory-v3-routes.ts +207 -0
  393. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +147 -0
  394. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +8 -0
  395. package/src/plugins/defaults/memory/substrate/__tests__/edge-index.test.ts +0 -30
  396. package/src/plugins/defaults/memory/substrate/__tests__/ingest.test.ts +73 -1
  397. package/src/plugins/defaults/memory/substrate/__tests__/page-index.test.ts +37 -0
  398. package/src/plugins/defaults/memory/substrate/__tests__/page-links.test.ts +208 -0
  399. package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +158 -1
  400. package/src/plugins/defaults/memory/substrate/__tests__/static-context.test.ts +195 -58
  401. package/src/plugins/defaults/memory/substrate/consolidation-job.ts +93 -24
  402. package/src/plugins/defaults/memory/substrate/edge-index.ts +0 -31
  403. package/src/plugins/defaults/memory/substrate/ingest.ts +59 -0
  404. package/src/plugins/defaults/memory/substrate/page-index.ts +35 -8
  405. package/src/plugins/defaults/memory/substrate/page-links.ts +133 -0
  406. package/src/plugins/defaults/memory/substrate/page-store.ts +10 -0
  407. package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +124 -34
  408. package/src/plugins/defaults/memory/substrate/skill-content.ts +8 -1
  409. package/src/plugins/defaults/memory/substrate/static-context.ts +160 -33
  410. package/src/plugins/defaults/memory/substrate/sweep-job.ts +2 -4
  411. package/src/plugins/defaults/memory/v1/graph/extraction.ts +3 -1
  412. package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +18 -0
  413. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +66 -1
  414. package/src/plugins/defaults/memory/v3/card.ts +9 -9
  415. package/src/plugins/defaults/memory/v3/core-set.test.ts +7 -0
  416. package/src/plugins/defaults/memory/v3/core-set.ts +5 -1
  417. package/src/plugins/defaults/memory/v3/edge.ts +13 -57
  418. package/src/plugins/defaults/memory/v3/injector.ts +8 -0
  419. package/src/plugins/defaults/memory/v3/prune.ts +2 -0
  420. package/src/plugins/defaults/memory/v3/selection-log-store.ts +2 -0
  421. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +23 -9
  422. package/src/plugins/defaults/memory/worker-control.ts +1 -0
  423. package/src/plugins/defaults/memory/worker.ts +6 -3
  424. package/src/plugins/defaults/worker-entrypoints.ts +3 -0
  425. package/src/plugins/external-plugin-loader.ts +47 -0
  426. package/src/plugins/mcp-servers.ts +361 -0
  427. package/src/plugins/mtime-cache.ts +37 -46
  428. package/src/plugins/pipeline.ts +14 -7
  429. package/src/plugins/plugin-execution-context.ts +35 -11
  430. package/src/plugins/worker-plugin-surface.ts +33 -0
  431. package/src/prompts/templates/system-sections.ts +0 -7
  432. package/src/providers/__tests__/connection-model-compat.test.ts +1 -1
  433. package/src/providers/__tests__/context-overflow-error.test.ts +24 -0
  434. package/src/providers/__tests__/dispatch-connection-routing.test.ts +214 -2
  435. package/src/providers/__tests__/preflight-resolved-config.test.ts +57 -0
  436. package/src/providers/__tests__/retry-callsite.test.ts +25 -2
  437. package/src/providers/anthropic/__tests__/pause-turn-continuation.test.ts +170 -0
  438. package/src/providers/anthropic/client.ts +332 -241
  439. package/src/providers/call-site-routing.ts +30 -3
  440. package/src/providers/connection-resolution.ts +194 -11
  441. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +4 -0
  442. package/src/providers/inference/adapter-factory.ts +3 -0
  443. package/src/providers/inference/auth.ts +6 -0
  444. package/src/providers/inference/connection-availability.ts +24 -2
  445. package/src/providers/inference/connections.ts +2 -0
  446. package/src/providers/model-catalog.ts +3 -3
  447. package/src/providers/model-intents.ts +28 -8
  448. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +163 -40
  449. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +125 -2
  450. package/src/providers/openai/chat-completions-provider.ts +133 -36
  451. package/src/providers/openai/codex-models.ts +2 -1
  452. package/src/providers/provider-send-message.ts +32 -3
  453. package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +433 -0
  454. package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +625 -0
  455. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +34 -0
  456. package/src/providers/speech-to-text/__tests__/resolve.test.ts +285 -6
  457. package/src/providers/speech-to-text/deepgram-flux-frames.ts +395 -0
  458. package/src/providers/speech-to-text/deepgram-flux-realtime.ts +679 -0
  459. package/src/providers/speech-to-text/provider-catalog.ts +99 -8
  460. package/src/providers/speech-to-text/resolve.ts +25 -2
  461. package/src/routes/control.ts +1 -0
  462. package/src/routes/route-host-client.ts +1 -0
  463. package/src/routes/route-host-protocol.ts +7 -0
  464. package/src/routes/worker.ts +48 -15
  465. package/src/runtime/AGENTS.md +16 -17
  466. package/src/runtime/access-request-helper.ts +9 -12
  467. package/src/runtime/agent-wake.ts +18 -15
  468. package/src/runtime/effective-capabilities.test.ts +43 -0
  469. package/src/runtime/effective-capabilities.ts +27 -0
  470. package/src/runtime/guardian-reply-router.ts +6 -2
  471. package/src/runtime/pre-first-message-gate.ts +4 -0
  472. package/src/runtime/routes/__tests__/acp-claude-auth-routes.test.ts +12 -4
  473. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +522 -2
  474. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +52 -0
  475. package/src/runtime/routes/__tests__/default-provider-routes.test.ts +61 -0
  476. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +44 -0
  477. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +102 -1
  478. package/src/runtime/routes/__tests__/plugins-routes.test.ts +132 -35
  479. package/src/runtime/routes/__tests__/schedule-routes-disarm-reason.test.ts +215 -0
  480. package/src/runtime/routes/__tests__/stt-routes.test.ts +25 -0
  481. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +55 -6
  482. package/src/runtime/routes/__tests__/user-route-dispatcher-host.test.ts +52 -1
  483. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +133 -1
  484. package/src/runtime/routes/channel-availability-routes.ts +32 -14
  485. package/src/runtime/routes/channel-route-shared.ts +0 -6
  486. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +6 -6
  487. package/src/runtime/routes/conversation-list-routes.ts +181 -23
  488. package/src/runtime/routes/conversation-management-routes.ts +17 -12
  489. package/src/runtime/routes/conversation-query-routes.ts +40 -27
  490. package/src/runtime/routes/conversation-routes.ts +43 -29
  491. package/src/runtime/routes/credential-prompt-routes.ts +4 -7
  492. package/src/runtime/routes/credential-routes.ts +26 -82
  493. package/src/runtime/routes/default-provider-routes.ts +15 -0
  494. package/src/runtime/routes/documents-routes.ts +3 -222
  495. package/src/runtime/routes/inbound-message-handler.ts +21 -45
  496. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +0 -1
  497. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -9
  498. package/src/runtime/routes/inbound-stages/admission-policy.ts +1 -17
  499. package/src/runtime/routes/inbound-stages/bootstrap-intercept.test.ts +0 -1
  500. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -3
  501. package/src/runtime/routes/inbound-stages/edit-intercept.ts +101 -79
  502. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +0 -1
  503. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +12 -7
  504. package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +91 -8
  505. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +72 -79
  506. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +2 -3
  507. package/src/runtime/routes/inference-profiles-routes.ts +20 -11
  508. package/src/runtime/routes/inference-provider-connection-routes.ts +77 -15
  509. package/src/runtime/routes/log-export-routes.ts +3 -0
  510. package/src/runtime/routes/mcp-auth-routes.ts +148 -57
  511. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +2 -0
  512. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +3 -0
  513. package/src/runtime/routes/playground/inject-failures.ts +2 -2
  514. package/src/runtime/routes/playground/reset-circuit.ts +1 -1
  515. package/src/runtime/routes/plugins-routes.ts +38 -8
  516. package/src/runtime/routes/schedule-routes.ts +94 -7
  517. package/src/runtime/routes/settings-routes.ts +6 -6
  518. package/src/runtime/routes/stt-routes.ts +31 -25
  519. package/src/runtime/routes/surface-action-routes.ts +20 -19
  520. package/src/runtime/routes/surface-conversation-resolver.ts +3 -0
  521. package/src/runtime/routes/user-route-dispatcher.ts +69 -15
  522. package/src/runtime/routes/user-route-import.ts +108 -0
  523. package/src/runtime/routes/user-route-resolution.ts +18 -1
  524. package/src/runtime/routes/workspace-routes.ts +0 -9
  525. package/src/runtime/routes/workspace-utils.ts +3 -13
  526. package/src/runtime/services/conversation-serializer.ts +7 -2
  527. package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +68 -5
  528. package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +81 -0
  529. package/src/schedule/plugin-schedule-availability.ts +58 -0
  530. package/src/schedule/plugin-schedule-declarations.ts +23 -27
  531. package/src/schedule/plugin-schedule-reconciler.ts +12 -3
  532. package/src/schedule/schedule-store.ts +5 -1
  533. package/src/schedule/scheduler.ts +9 -4
  534. package/src/schedule/worker-control.ts +1 -0
  535. package/src/schedule/worker.ts +6 -0
  536. package/src/security/oauth2.ts +6 -22
  537. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +22 -0
  538. package/src/stt/__tests__/types.test.ts +94 -0
  539. package/src/stt/daemon-batch-transcriber.ts +10 -0
  540. package/src/stt/stt-stream-session.ts +8 -4
  541. package/src/stt/types.ts +103 -0
  542. package/src/subagent/__tests__/consult-prompt.test.ts +26 -15
  543. package/src/subagent/consult-context.ts +11 -11
  544. package/src/subagent/consult-prompt.ts +26 -35
  545. package/src/subagent/manager.ts +21 -40
  546. package/src/subagent/notify.ts +7 -1
  547. package/src/subagent/types.ts +15 -12
  548. package/src/tools/__tests__/tool-input-schemas.test.ts +7 -7
  549. package/src/tools/acp/spawn.test.ts +97 -0
  550. package/src/tools/acp/spawn.ts +38 -4
  551. package/src/tools/credentials/ref-parse.ts +35 -0
  552. package/src/tools/credentials/resolve.ts +4 -10
  553. package/src/tools/credentials/store.ts +168 -0
  554. package/src/tools/document/document-tool.ts +12 -3
  555. package/src/tools/executor.ts +53 -15
  556. package/src/tools/filesystem/read.ts +27 -10
  557. package/src/tools/host-filesystem/read.ts +27 -15
  558. package/src/tools/network/url-safety.ts +9 -16
  559. package/src/tools/permission-checker.ts +43 -52
  560. package/src/tools/registry.ts +2 -1
  561. package/src/tools/shared/filesystem/file-ops-service.ts +63 -35
  562. package/src/tools/shared/filesystem/legacy-read-args.ts +22 -0
  563. package/src/tools/shared/filesystem/types.ts +5 -5
  564. package/src/tools/skills/scaffold-managed.ts +25 -7
  565. package/src/tools/subagent/spawn.ts +28 -88
  566. package/src/tools/tool-types.ts +26 -13
  567. package/src/tools/types.ts +6 -6
  568. package/src/tools/ui-surface/surface-shape-docs.ts +12 -1
  569. package/src/tools/workflows/run-workflow.ts +1 -2
  570. package/src/tts/__tests__/reasoning-tag-filter.test.ts +78 -0
  571. package/src/tts/reasoning-tag-filter.ts +89 -0
  572. package/src/util/__tests__/worker-process-command.test.ts +37 -0
  573. package/src/util/logger.ts +16 -0
  574. package/src/util/think-tag-stream.ts +95 -0
  575. package/src/util/worker-process.ts +37 -4
  576. package/src/windows-compiled-cli.ts +32 -0
  577. package/src/windows-compiled-entry.ts +4 -0
  578. package/src/windows-compiled-logger.ts +6 -0
  579. package/src/windows-compiled-worker-entry.ts +29 -0
  580. package/src/workspace/byok-default-profile-ensure.ts +76 -24
  581. package/src/workspace/custom-profile-ensure.ts +4 -24
  582. package/src/workspace/migrations/142-consolidate-voice-front-door.ts +70 -0
  583. package/src/workspace/migrations/143-repair-deprecated-codex-model-id.ts +134 -0
  584. package/src/workspace/migrations/144-convert-stranded-subscription-openai-profiles.ts +265 -0
  585. package/src/workspace/migrations/145-collapse-profile-bindings-to-entries.ts +328 -0
  586. package/src/workspace/migrations/146-repair-retired-fireworks-deepseek-flash-model-id.ts +195 -0
  587. package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +0 -10
  588. package/src/workspace/migrations/registry.ts +10 -0
  589. package/src/workspace/provider-commit-message-generator.ts +7 -5
  590. package/src/__tests__/document-workspace-file.test.ts +0 -467
  591. package/src/live-voice/__tests__/front-decision.test.ts +0 -645
  592. package/src/live-voice/front-decision.ts +0 -476
  593. package/src/permissions/ipc-risk-types.ts +0 -143
  594. package/src/permissions/risk-types.ts +0 -76
  595. package/src/subagent/__tests__/consult-transcript.test.ts +0 -184
  596. package/src/subagent/consult-transcript.ts +0 -90
@@ -37,8 +37,13 @@ import {
37
37
  isConnectionCompatibleWithModel,
38
38
  } from "./connection-model-compat.js";
39
39
  import {
40
+ connectionProviderKind,
40
41
  ConnectionResolutionError,
42
+ dispatchProviderResolvable,
43
+ expectedVendorProvider,
41
44
  isManagedConnectionRoute,
45
+ resolveEntryConnectionName,
46
+ resolveEntryProviderKind,
42
47
  resolveRoutingIdentity,
43
48
  tryResolveProviderForConnectionName,
44
49
  } from "./connection-resolution.js";
@@ -112,7 +117,7 @@ export class CallSiteRoutingProvider implements Provider {
112
117
  */
113
118
  private readonly resolveByConnection: (
114
119
  connectionName: string,
115
- expectedProvider: string,
120
+ expectedProvider: string | undefined,
116
121
  model: string | undefined,
117
122
  ) => Promise<Provider | null>,
118
123
  private readonly defaultRouteAttribution?: ProviderRouteAttribution,
@@ -203,9 +208,17 @@ export class CallSiteRoutingProvider implements Provider {
203
208
  forceOverrideProfile: options?.config?.forceOverrideProfile,
204
209
  selectionSeed: options?.config?.selectionSeed,
205
210
  });
211
+ // Capability follows the same row dispatch selects: an explicit
212
+ // provider_connection wins, then an entry-name label's row, then the
213
+ // resolved provider itself. Kept in this order so a label paired with a
214
+ // conflicting connection cannot enable a capability the dispatched
215
+ // transport lacks.
216
+ const routedKind = resolved.provider_connection
217
+ ? connectionProviderKind(resolved.provider_connection, resolved.model)
218
+ : resolveEntryProviderKind(resolved.provider, resolved.model);
206
219
  return shouldUseNativeWebSearch(
207
220
  getConfig(),
208
- resolved.provider,
221
+ routedKind ?? resolved.provider,
209
222
  resolved.model,
210
223
  );
211
224
  }
@@ -256,6 +269,7 @@ export class CallSiteRoutingProvider implements Provider {
256
269
  overrideProfile,
257
270
  forceOverrideProfile,
258
271
  selectionSeed,
272
+ isResolvableProvider: dispatchProviderResolvable,
259
273
  },
260
274
  );
261
275
 
@@ -273,6 +287,16 @@ export class CallSiteRoutingProvider implements Provider {
273
287
  )?.connectionName;
274
288
  }
275
289
 
290
+ // An entry-name provider IS the connection name: the label points at a
291
+ // row, and the row's own provider drives dispatch, so no expected
292
+ // provider is threaded (the label is not a vendor).
293
+ const entryRoute = connectionName
294
+ ? null
295
+ : resolveEntryConnectionName(resolved.provider);
296
+ if (entryRoute) {
297
+ connectionName = entryRoute;
298
+ }
299
+
276
300
  // When no connection is set, auto-resolve one for the resolved provider —
277
301
  // including when the provider matches the default's name. The default
278
302
  // transport may ride the managed (platform-billed) connection, so reusing
@@ -301,9 +325,12 @@ export class CallSiteRoutingProvider implements Provider {
301
325
  }
302
326
 
303
327
  if (connectionName) {
328
+ // The vendor guard covers both the entry route and a config carrying
329
+ // an entry label alongside an explicit provider_connection: a label
330
+ // that is not a vendor never threads into the row-equality check.
304
331
  const connectionProvider = await this.resolveByConnection(
305
332
  connectionName,
306
- resolved.provider,
333
+ expectedVendorProvider(resolved.provider, resolved.model),
307
334
  resolved.model,
308
335
  );
309
336
  if (connectionProvider) {
@@ -32,6 +32,7 @@ import {
32
32
  resolveCallSiteConfig,
33
33
  selectWinningProfile,
34
34
  } from "../config/llm-resolver.js";
35
+ import { unknownLlmProviderIssue } from "../config/schemas/llm.js";
35
36
  import { getDb } from "../persistence/db-connection.js";
36
37
  import { credentialKey } from "../security/credential-key.js";
37
38
  import { ProviderNotConfiguredError } from "../util/errors.js";
@@ -40,6 +41,7 @@ import {
40
41
  describeSubscriptionModelIncompatibility,
41
42
  isConnectionCompatibleWithModel,
42
43
  } from "./connection-model-compat.js";
44
+ import { VALID_CONNECTION_PROVIDERS } from "./inference/auth.js";
43
45
  import {
44
46
  canonicalVellumConnection,
45
47
  getConnection,
@@ -55,6 +57,7 @@ import {
55
57
  } from "./routing-identity.js";
56
58
  import type { Provider } from "./types.js";
57
59
  import {
60
+ getManagedUpstream,
58
61
  isVellumManagedConnection,
59
62
  MANAGED_ROUTABLE_PROVIDERS,
60
63
  VELLUM_MANAGED_CONNECTION_NAME,
@@ -64,6 +67,132 @@ export { ConnectionResolutionError, resolveRoutingIdentity };
64
67
 
65
68
  const log = getLogger("providers/connection-resolution");
66
69
 
70
+ /**
71
+ * Resolve a provider label that names a connection row (an entry) to that
72
+ * row's name. Returns null for catalog providers and routing identities
73
+ * (those translate through their own rules) and for labels naming no row.
74
+ *
75
+ * The write surfaces reject entry-name providers until the entries model
76
+ * enables them, so a config carrying one reaches dispatch only through a
77
+ * hand edit today and through the collapse migration later; translating
78
+ * here makes both route explainably instead of failing as an unknown
79
+ * provider.
80
+ */
81
+ export function resolveEntryConnectionName(
82
+ provider: string | undefined,
83
+ ): string | null {
84
+ if (!provider || VALID_CONNECTION_PROVIDERS.includes(provider)) {
85
+ return null;
86
+ }
87
+ try {
88
+ return getConnection(getDb(), provider) ? provider : null;
89
+ } catch {
90
+ return null;
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Write-surface membership for a PROFILE provider value: the known vendor
96
+ * and identity set, plus existing connection entry rows. Fail-closed on DB
97
+ * unavailability (an unverifiable entry name is rejected; the write is
98
+ * retryable), unlike the selection-time predicate below, which is
99
+ * fail-open so a DB blip never heals away a valid profile. Call-site
100
+ * fragments keep vendor-only membership: overrides become model-only with
101
+ * the entries demolition, so entries must not leak into them meanwhile.
102
+ */
103
+ export function writableProfileProviderIssue(provider: string): string | null {
104
+ const issue = unknownLlmProviderIssue(provider);
105
+ if (issue === null) {
106
+ return null;
107
+ }
108
+ try {
109
+ if (getConnection(getDb(), provider) != null) {
110
+ return null;
111
+ }
112
+ } catch {
113
+ // Unverifiable: fall through to the rejection.
114
+ }
115
+ return `Invalid provider "${provider}". Use a known provider or the name of an existing connection.`;
116
+ }
117
+
118
+ /**
119
+ * Selection-time predicate for `ResolveCallSiteOpts.isResolvableProvider`:
120
+ * a provider value dispatches when it is a known vendor/identity or names a
121
+ * connection entry row. Permissive on DB unavailability so a transient blip
122
+ * never heals away a valid entry profile; dispatch soft-fails on its own.
123
+ */
124
+ export function dispatchProviderResolvable(provider: string): boolean {
125
+ if (VALID_CONNECTION_PROVIDERS.includes(provider)) {
126
+ return true;
127
+ }
128
+ try {
129
+ return getConnection(getDb(), provider) != null;
130
+ } catch {
131
+ return true;
132
+ }
133
+ }
134
+
135
+ /**
136
+ * The vendor a resolved provider value expects its connection row to serve:
137
+ * catalog ids and routing identities pass through, and an entry-name label
138
+ * resolves to its row's dispatchable kind, so a config carrying both an
139
+ * entry label and a `provider_connection` is held to the label's kind by
140
+ * the row-equality check (a conflicting row mismatches explainably or
141
+ * auto-recovers to a matching one). A label naming no row yields undefined.
142
+ */
143
+ export function expectedVendorProvider(
144
+ provider: string | undefined,
145
+ model: string | undefined,
146
+ ): string | undefined {
147
+ if (!provider) {
148
+ return undefined;
149
+ }
150
+ if (VALID_CONNECTION_PROVIDERS.includes(provider)) {
151
+ return provider;
152
+ }
153
+ return resolveEntryProviderKind(provider, model) ?? undefined;
154
+ }
155
+
156
+ /**
157
+ * The dispatchable provider kind behind a connection row, or null when the
158
+ * row is missing or its kind cannot be derived. Identity-kind rows derive
159
+ * their upstream the way the identities themselves do. Sync and
160
+ * best-effort so capability probes can share dispatch's translation
161
+ * without replaying its async resolution.
162
+ */
163
+ export function connectionProviderKind(
164
+ connectionName: string,
165
+ model: string | undefined,
166
+ ): string | null {
167
+ try {
168
+ const row = getConnection(getDb(), connectionName);
169
+ if (!row) {
170
+ return null;
171
+ }
172
+ if (isVellumManagedConnection(row)) {
173
+ return model ? getManagedUpstream(model) : null;
174
+ }
175
+ if (row.provider === "chatgpt") {
176
+ return "openai";
177
+ }
178
+ return row.provider;
179
+ } catch {
180
+ return null;
181
+ }
182
+ }
183
+
184
+ /**
185
+ * The dispatchable provider kind behind an entry-name label, or null when
186
+ * the label is not an entry.
187
+ */
188
+ export function resolveEntryProviderKind(
189
+ provider: string | undefined,
190
+ model: string | undefined,
191
+ ): string | null {
192
+ const entryName = resolveEntryConnectionName(provider);
193
+ return entryName ? connectionProviderKind(entryName, model) : null;
194
+ }
195
+
67
196
  /**
68
197
  * Resolve a Provider through a named `provider_connection`.
69
198
  *
@@ -152,18 +281,36 @@ export async function tryResolveProviderForConnectionName(
152
281
  // fall back to the default provider.
153
282
  const isVellum = isVellumManagedConnection(connection);
154
283
  if (isVellum && !expectedProvider) {
155
- throw new ConnectionResolutionError(
156
- connectionName,
157
- "provider_mismatch",
158
- `provider_connection "${connectionName}" is the provider-agnostic Vellum-managed connection but the resolving profile declared no provider — set the profile's provider so the upstream can be selected`,
159
- );
284
+ // An entry-name route carries no declared provider (the label is the
285
+ // row's name, not a vendor); a vellum-kind row derives its upstream
286
+ // from the model, same as the vellum identity itself.
287
+ expectedProvider = model
288
+ ? (getManagedUpstream(model) ?? undefined)
289
+ : undefined;
290
+ if (!expectedProvider) {
291
+ throw new ConnectionResolutionError(
292
+ connectionName,
293
+ "provider_mismatch",
294
+ `provider_connection "${connectionName}" is the provider-agnostic Vellum-managed connection but the resolving profile declared no provider — set the profile's provider so the upstream can be selected`,
295
+ );
296
+ }
160
297
  }
161
298
  const isVellumRoute =
162
299
  isVellum &&
163
300
  !!expectedProvider &&
164
301
  MANAGED_ROUTABLE_PROVIDERS.has(expectedProvider);
302
+ // The ChatGPT-subscription row stores the "chatgpt" routing identity in
303
+ // its provider column, so the equality never holds for its openai
304
+ // upstream. The identity dispatches with the upstream threaded as
305
+ // `providerOverride`, mirroring the vellum sentinel; the upstream is
306
+ // always openai (`resolveRoutingIdentity`). Any other declared provider
307
+ // on a chatgpt row is a genuine mismatch and falls through below.
308
+ const isChatgptRoute =
309
+ connection.provider === "chatgpt" &&
310
+ (expectedProvider === undefined || expectedProvider === "openai");
165
311
  if (
166
312
  !isVellumRoute &&
313
+ !isChatgptRoute &&
167
314
  expectedProvider &&
168
315
  connection.provider !== expectedProvider
169
316
  ) {
@@ -225,7 +372,11 @@ export async function tryResolveProviderForConnectionName(
225
372
  try {
226
373
  const provider = await resolveProviderFromConnection(connection, config, {
227
374
  model,
228
- providerOverride: isVellumRoute ? expectedProvider : undefined,
375
+ providerOverride: isVellumRoute
376
+ ? expectedProvider
377
+ : isChatgptRoute
378
+ ? "openai"
379
+ : undefined,
229
380
  });
230
381
  return attachProviderRoute(provider, connection);
231
382
  } catch (err) {
@@ -324,7 +475,9 @@ async function resolveThroughPlatform(
324
475
  export async function resolveDefaultProvider(
325
476
  config: ProvidersConfig,
326
477
  ): Promise<Provider | null> {
327
- const resolved = resolveCallSiteConfig("mainAgent", config.llm);
478
+ const resolved = resolveCallSiteConfig("mainAgent", config.llm, {
479
+ isResolvableProvider: dispatchProviderResolvable,
480
+ });
328
481
  let connectionName = resolved.provider_connection;
329
482
  // A routing-identity provider names its own connection row; the
330
483
  // provider-keyed auto-resolve scan below cannot find it ("chatgpt" rows
@@ -335,6 +488,19 @@ export async function resolveDefaultProvider(
335
488
  resolved.model,
336
489
  )?.connectionName;
337
490
  }
491
+ // An entry-name provider IS the connection name: the label points at a
492
+ // row, and the row's own provider drives dispatch.
493
+ const entryName = connectionName
494
+ ? null
495
+ : resolveEntryConnectionName(resolved.provider);
496
+ if (entryName) {
497
+ return tryResolveProviderForConnectionName(
498
+ entryName,
499
+ config,
500
+ undefined,
501
+ resolved.model,
502
+ );
503
+ }
338
504
  if (!connectionName) {
339
505
  // The merged config has no provider_connection — the profile likely set
340
506
  // provider without a connection ("Any active" selection), and the merge
@@ -387,7 +553,7 @@ export async function resolveDefaultProvider(
387
553
  return tryResolveProviderForConnectionName(
388
554
  connectionName,
389
555
  config,
390
- resolved.provider,
556
+ expectedVendorProvider(resolved.provider, resolved.model),
391
557
  resolved.model,
392
558
  );
393
559
  }
@@ -423,9 +589,21 @@ export async function preflightResolvedConfig(
423
589
  // upstream; an unroutable vellum model throws here — it is statically
424
590
  // detectable, exactly what preflight exists to surface.
425
591
  const identity = resolveRoutingIdentity(resolved.provider, resolved.model);
426
- const provider = identity?.expectedProvider ?? resolved.provider;
592
+ // An entry-name provider IS the connection name, and the row's kind is
593
+ // what the checks below judge against (same translation dispatch uses).
594
+ // Precedence matches dispatch exactly: an explicit provider_connection
595
+ // wins over the entry name, so preflight judges the row the request
596
+ // actually uses rather than a healthy entry the request ignores.
597
+ const entryName = identity
598
+ ? null
599
+ : resolveEntryConnectionName(resolved.provider);
600
+ const provider = identity
601
+ ? identity.expectedProvider
602
+ : entryName
603
+ ? (connectionProviderKind(entryName, resolved.model) ?? resolved.provider)
604
+ : resolved.provider;
427
605
  const connectionName =
428
- identity?.connectionName ?? resolved.provider_connection;
606
+ identity?.connectionName ?? resolved.provider_connection ?? entryName;
429
607
  if (!connectionName) {
430
608
  return;
431
609
  }
@@ -512,7 +690,12 @@ export async function preflightResolvedConfig(
512
690
  }
513
691
  return;
514
692
  }
515
- if (connection.provider !== provider) {
693
+ // The ChatGPT-subscription row stores the "chatgpt" identity while its
694
+ // upstream is openai; the credential-presence switch below is the right
695
+ // preflight for it (the subscription token is its credential).
696
+ const isChatgptRow =
697
+ connection.provider === "chatgpt" && provider === "openai";
698
+ if (!isChatgptRow && connection.provider !== provider) {
516
699
  throw new ConnectionResolutionError(
517
700
  connectionName,
518
701
  "provider_mismatch",
@@ -43,6 +43,10 @@ describe("adapter factory", () => {
43
43
  useNativeWebSearch: false,
44
44
  });
45
45
  expect(adapter).toBeInstanceOf(OpenAIChatCompletionsProvider);
46
+ expect(
47
+ (adapter as unknown as { omitToolChoiceWhenReasoning: boolean })
48
+ .omitToolChoiceWhenReasoning,
49
+ ).toBe(true);
46
50
  });
47
51
 
48
52
  test("createAdapterFromConnection wires baseURL from ResolvedAuth", () => {
@@ -139,6 +139,9 @@ const ADAPTER_FACTORIES: Record<string, AdapterFactory> = {
139
139
  providerName: "openai-compatible",
140
140
  providerLabel: "OpenAI-compatible",
141
141
  streamTimeoutMs,
142
+ // Custom OpenAI-compatible endpoints may front strict reasoning
143
+ // models (DeepSeek thinking) that 400 on any explicit tool_choice.
144
+ omitToolChoiceWhenReasoning: true,
142
145
  ...(baseURL ? { baseURL } : {}),
143
146
  }),
144
147
  minimax: ({ apiKey, model, streamTimeoutMs }) =>
@@ -126,6 +126,12 @@ export const VALID_CONNECTION_PROVIDERS: readonly string[] = [
126
126
  // persisted `vellum` rows — the routing threaded in via `providerOverride`
127
127
  // never runs on a row that fails to load.
128
128
  VELLUM_MANAGED_PROVIDER,
129
+ // The ChatGPT-subscription row stores the "chatgpt" routing identity in its
130
+ // `provider` column for the same reason: the row IS the subscription route
131
+ // (auth modality = provider identity), and dispatch derives the openai
132
+ // upstream per-request. Allowlisted explicitly or the DB loaders would drop
133
+ // the persisted row.
134
+ "chatgpt",
129
135
  ];
130
136
 
131
137
  export type ConnectionProvider = string;
@@ -23,6 +23,10 @@ import {
23
23
  describeSubscriptionModelIncompatibility,
24
24
  isConnectionCompatibleWithModel,
25
25
  } from "../connection-model-compat.js";
26
+ import {
27
+ connectionProviderKind,
28
+ resolveEntryConnectionName,
29
+ } from "../connection-resolution.js";
26
30
  import { PROVIDER_CATALOG } from "../model-catalog.js";
27
31
  import { resolveManagedProxyContext } from "../platform-proxy/context.js";
28
32
  import {
@@ -161,7 +165,12 @@ export async function computeConnectionAvailability(
161
165
  if (resolvedConnectionName === VELLUM_MANAGED_CONNECTION_NAME) {
162
166
  return vellumConnectionAvailability();
163
167
  }
164
- if (connection.provider !== provider) {
168
+ // The ChatGPT-subscription row stores the "chatgpt" identity while its
169
+ // upstream is openai; the credential switch below is the right check for
170
+ // it (the subscription token is its credential).
171
+ const isChatgptRow =
172
+ connection.provider === "chatgpt" && provider === "openai";
173
+ if (!isChatgptRow && connection.provider !== provider) {
165
174
  return {
166
175
  status: "provider_mismatch",
167
176
  message: `Connection "${resolvedConnectionName}" is for provider "${connection.provider}", but the requested provider is "${provider}". Pick a connection for "${provider}" ${SETTINGS_HINT}.`,
@@ -326,9 +335,22 @@ export async function computeProfileAvailability(
326
335
  }
327
336
  }
328
337
 
338
+ // Precedence matches dispatch: an explicit provider_connection wins over
339
+ // an entry-name provider, and the vendor judged is the entry's
340
+ // dispatchable kind either way (the same translation dispatch uses).
341
+ const entryName = resolveEntryConnectionName(provider);
342
+ const entryKind =
343
+ entryName !== null
344
+ ? (connectionProviderKind(entryName, model) ?? provider)
345
+ : provider;
346
+
329
347
  const pinned = entry.provider_connection;
330
348
  if (typeof pinned === "string") {
331
- return computeConnectionAvailability(provider, pinned);
349
+ return computeConnectionAvailability(entryKind, pinned);
350
+ }
351
+
352
+ if (entryName !== null) {
353
+ return computeConnectionAvailability(entryKind, entryName);
332
354
  }
333
355
 
334
356
  // Mirror the dispatch-time auto-resolve (`resolveConfiguredProvider`): with
@@ -348,10 +348,12 @@ export function updateConnection(
348
348
  connection: {
349
349
  ...existing,
350
350
  auth,
351
+ provider: nextProvider,
351
352
  label: input.label !== undefined ? input.label : existing.label,
352
353
  baseUrl: nextBaseUrl,
353
354
  models: nextModels,
354
355
  updatedAt: now,
356
+ isManaged: isManagedRow({ name, provider: nextProvider, auth }),
355
357
  },
356
358
  };
357
359
  }
@@ -939,7 +939,7 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
939
939
  pricing: { inputPer1mTokens: 1.74, outputPer1mTokens: 3.48 },
940
940
  },
941
941
  {
942
- id: "accounts/fireworks/models/deepseek-v4-flash",
942
+ id: "accounts/fireworks/models/deepseek-v4-flash-0731",
943
943
  displayName: "DeepSeek V4 Flash",
944
944
  contextWindowTokens: 1040000,
945
945
  maxOutputTokens: 131072,
@@ -951,11 +951,11 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
951
951
  pricing: {
952
952
  inputPer1mTokens: 0.14,
953
953
  outputPer1mTokens: 0.28,
954
- cacheReadPer1mTokens: 0.03,
954
+ cacheReadPer1mTokens: 0.028,
955
955
  },
956
956
  },
957
957
  ],
958
- defaultModel: "accounts/fireworks/models/deepseek-v4-flash",
958
+ defaultModel: "accounts/fireworks/models/deepseek-v4-flash-0731",
959
959
  apiKeyUrl: "https://fireworks.ai/account/api-keys",
960
960
  apiKeyPlaceholder: "fw_...",
961
961
  },
@@ -1,4 +1,5 @@
1
1
  import { isModelInCatalog, PROVIDER_CATALOG } from "./model-catalog.js";
2
+ import { isCodexSubscriptionModel } from "./openai/codex-models.js";
2
3
  import type { ModelIntent } from "./types.js";
3
4
 
4
5
  /**
@@ -10,8 +11,10 @@ const PROVIDER_DEFAULT_MODELS: Record<string, string> = Object.fromEntries(
10
11
  );
11
12
 
12
13
  // `cost-optimized` is the cheapest model a provider serves, `latency-optimized`
13
- // the fastest to first token. On anthropic, ollama and fireworks the same model
14
- // is both, so those columns repeat by construction rather than by oversight.
14
+ // the fastest to first token. On anthropic, ollama, fireworks and openai the
15
+ // same model is both, so those columns repeat by construction rather than by
16
+ // oversight (openai's balanced repeats it too: the default-profile templates
17
+ // split those tiers by reasoning effort, not model).
15
18
  const PROVIDER_MODEL_INTENTS: Record<string, Record<ModelIntent, string>> = {
16
19
  anthropic: {
17
20
  balanced: "claude-sonnet-4-6",
@@ -21,11 +24,11 @@ const PROVIDER_MODEL_INTENTS: Record<string, Record<ModelIntent, string>> = {
21
24
  "vision-optimized": "claude-opus-4-6",
22
25
  },
23
26
  openai: {
24
- balanced: "gpt-5.4-mini",
25
- "cost-optimized": "gpt-5.4-nano",
27
+ balanced: "gpt-5.6-luna",
28
+ "cost-optimized": "gpt-5.6-luna",
26
29
  "latency-optimized": "gpt-5.6-luna",
27
- "quality-optimized": "gpt-5.4",
28
- "vision-optimized": "gpt-5.4",
30
+ "quality-optimized": "gpt-5.6-sol",
31
+ "vision-optimized": "gpt-5.6-terra",
29
32
  },
30
33
  gemini: {
31
34
  balanced: "gemini-3-flash-preview",
@@ -43,8 +46,8 @@ const PROVIDER_MODEL_INTENTS: Record<string, Record<ModelIntent, string>> = {
43
46
  },
44
47
  fireworks: {
45
48
  balanced: "accounts/fireworks/models/minimax-m3",
46
- "cost-optimized": "accounts/fireworks/models/deepseek-v4-flash",
47
- "latency-optimized": "accounts/fireworks/models/deepseek-v4-flash",
49
+ "cost-optimized": "accounts/fireworks/models/deepseek-v4-flash-0731",
50
+ "latency-optimized": "accounts/fireworks/models/deepseek-v4-flash-0731",
48
51
  "quality-optimized": "accounts/fireworks/models/kimi-k2p6",
49
52
  "vision-optimized": "accounts/fireworks/models/kimi-k2p6",
50
53
  },
@@ -89,6 +92,23 @@ for (const [provider, intents] of Object.entries(PROVIDER_MODEL_INTENTS)) {
89
92
  }
90
93
  }
91
94
 
95
+ // The openai column must additionally stay inside the ChatGPT Codex
96
+ // subscription set: the subscription default provider is stored as
97
+ // `llm.defaultProvider = { provider: "openai", connectionName:
98
+ // "chatgpt-subscription" }`, so the materialized default profiles resolve
99
+ // through this column while pinning the subscription connection, which
100
+ // bypasses the auto-resolution compat gate and hard-routes to the Codex
101
+ // endpoint, where a non-Codex model 400s on every request.
102
+ for (const [intent, modelId] of Object.entries(PROVIDER_MODEL_INTENTS.openai)) {
103
+ if (!isCodexSubscriptionModel(modelId)) {
104
+ throw new Error(
105
+ `PROVIDER_MODEL_INTENTS[openai][${intent}] references model "${modelId}" ` +
106
+ `which the ChatGPT subscription cannot serve. Pick a model from ` +
107
+ `CODEX_SUBSCRIPTION_MODEL_IDS in openai/codex-models.ts.`,
108
+ );
109
+ }
110
+ }
111
+
92
112
  export function isModelIntent(value: unknown): value is ModelIntent {
93
113
  return typeof value === "string" && MODEL_INTENTS.has(value as ModelIntent);
94
114
  }