@vellumai/assistant 0.12.1 → 0.12.2-staging.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (577) hide show
  1. package/AGENTS.md +4 -0
  2. package/ARCHITECTURE.md +20 -21
  3. package/docs/architecture/turn-actor.md +15 -8
  4. package/docs/guardian-request-flow.md +16 -0
  5. package/node_modules/@vellumai/slack-text/src/index.ts +13 -8
  6. package/node_modules/@vellumai/slack-text/src/label-resolution-entities.test.ts +95 -0
  7. package/openapi.yaml +360 -51
  8. package/package.json +3 -1
  9. package/scripts/smoke-desktop-window-theme.ts +186 -0
  10. package/src/__tests__/always-loaded-tools-guard.test.ts +18 -10
  11. package/src/__tests__/anthropic-provider.test.ts +0 -63
  12. package/src/__tests__/app-compiler.test.ts +6 -0
  13. package/src/__tests__/app-control-tool-schemas.test.ts +5 -2
  14. package/src/__tests__/app-dir-path-guard.test.ts +1 -3
  15. package/src/__tests__/assistant-event-hub-machine-name.test.ts +6 -7
  16. package/src/__tests__/assistant-event-hub.test.ts +44 -0
  17. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
  18. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +5 -2
  19. package/src/__tests__/computer-use-tools.test.ts +19 -7
  20. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  21. package/src/__tests__/config-schema.test.ts +28 -29
  22. package/src/__tests__/config-watcher.test.ts +23 -8
  23. package/src/__tests__/connection-model-compat.test.ts +2 -2
  24. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  25. package/src/__tests__/conversation-pairing.test.ts +26 -0
  26. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -10
  27. package/src/__tests__/conversation-queue.test.ts +48 -207
  28. package/src/__tests__/conversation-retry-discard.test.ts +54 -1
  29. package/src/__tests__/conversation-runtime-assembly.test.ts +28 -0
  30. package/src/__tests__/conversation-skill-tools.test.ts +27 -0
  31. package/src/__tests__/conversation-surfaces-app-control.test.ts +8 -3
  32. package/src/__tests__/conversation-surfaces-point-at-budget.test.ts +1 -0
  33. package/src/__tests__/conversation-surfaces-point-at-capability.test.ts +1 -0
  34. package/src/__tests__/conversation-surfaces-task-progress.test.ts +67 -0
  35. package/src/__tests__/conversation-title-service.test.ts +14 -10
  36. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +3 -5
  37. package/src/__tests__/conversation-tool-setup-attribution.test.ts +51 -0
  38. package/src/__tests__/credential-record-retire.test.ts +171 -1
  39. package/src/__tests__/credential-routes.test.ts +250 -3
  40. package/src/__tests__/credential-security-invariants.test.ts +5 -3
  41. package/src/__tests__/cu-unified-flow.test.ts +14 -4
  42. package/src/__tests__/document-sync-tags.test.ts +25 -0
  43. package/src/__tests__/drain-kick-guard.test.ts +0 -2
  44. package/src/__tests__/drain-requeue-on-contention.test.ts +0 -6
  45. package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
  46. package/src/__tests__/git-porcelain.test.ts +47 -0
  47. package/src/__tests__/heartbeat-service.test.ts +56 -40
  48. package/src/__tests__/helpers/set-workspace-mcp.ts +11 -0
  49. package/src/__tests__/host-bash-proxy.test.ts +26 -45
  50. package/src/__tests__/host-browser-proxy.test.ts +6 -17
  51. package/src/__tests__/host-cu-proxy.test.ts +596 -0
  52. package/src/__tests__/host-file-proxy-targeted.test.ts +23 -0
  53. package/src/__tests__/host-file-proxy.test.ts +11 -23
  54. package/src/__tests__/host-transfer-proxy-targeted.test.ts +30 -9
  55. package/src/__tests__/list-messages-camera-frame.test.ts +121 -0
  56. package/src/__tests__/llm-catalog-parity.test.ts +25 -0
  57. package/src/__tests__/mcp-auth-routes.test.ts +6 -9
  58. package/src/__tests__/mcp-config-secret-boundary.test.ts +78 -136
  59. package/src/__tests__/mcp-health-check.test.ts +8 -11
  60. package/src/__tests__/mcp-list-plugin-servers.test.ts +8 -10
  61. package/src/__tests__/message-deleted-hook-dispatch.test.ts +119 -0
  62. package/src/__tests__/messages-after-tiebreaker.test.ts +91 -0
  63. package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
  64. package/src/__tests__/messaging-send-tool.test.ts +355 -548
  65. package/src/__tests__/model-intents.test.ts +3 -0
  66. package/src/__tests__/notification-vellum-adapter.test.ts +85 -2
  67. package/src/__tests__/oauth-commands-routes.test.ts +168 -0
  68. package/src/__tests__/oauth-provider-profiles.test.ts +18 -0
  69. package/src/__tests__/oauth-provider-serializer.test.ts +22 -0
  70. package/src/__tests__/oauth-providers-routes.test.ts +1 -0
  71. package/src/__tests__/openai-provider.test.ts +1 -0
  72. package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
  73. package/src/__tests__/platform-callback-registration.test.ts +8 -16
  74. package/src/__tests__/platform-client-verify-credential.test.ts +2 -0
  75. package/src/__tests__/plugin-import-boundary-guard.test.ts +14 -0
  76. package/src/__tests__/qdrant-manager.test.ts +132 -0
  77. package/src/__tests__/resolve-app.test.ts +135 -0
  78. package/src/__tests__/scaffold-managed-skill-tool.test.ts +229 -6
  79. package/src/__tests__/script-proxy-certs.test.ts +35 -0
  80. package/src/__tests__/secret-routes-acp-guard.test.ts +59 -1
  81. package/src/__tests__/service-account-token.test.ts +247 -0
  82. package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
  83. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  84. package/src/__tests__/skills.test.ts +9 -4
  85. package/src/__tests__/source-fingerprint.test.ts +184 -0
  86. package/src/__tests__/subagent-tool-gate-mode.test.ts +70 -3
  87. package/src/__tests__/subagent-tools.test.ts +3 -2
  88. package/src/__tests__/telephony-tts-guard.test.ts +38 -3
  89. package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
  90. package/src/__tests__/ui-channel-variants.test.ts +1 -56
  91. package/src/__tests__/unicode.test.ts +13 -0
  92. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +4 -0
  93. package/src/__tests__/watch-retro-tool-availability.test.ts +8 -17
  94. package/src/__tests__/workspace-git-service.test.ts +26 -0
  95. package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +336 -0
  96. package/src/acp/__tests__/acp-claude-oauth.test.ts +257 -6
  97. package/src/acp/__tests__/acp-credentials.test.ts +13 -0
  98. package/src/acp/__tests__/agent-process.test.ts +258 -4
  99. package/src/acp/__tests__/auth-required.test.ts +96 -0
  100. package/src/acp/__tests__/claude-token-refresh.test.ts +257 -0
  101. package/src/acp/__tests__/client-handler.test.ts +90 -2
  102. package/src/acp/__tests__/helpers/acp-model-option.ts +51 -0
  103. package/src/acp/__tests__/prepare-agent-env.test.ts +60 -1
  104. package/src/acp/__tests__/session-manager-persistence.test.ts +5 -1
  105. package/src/acp/__tests__/session-manager-resume.test.ts +270 -6
  106. package/src/acp/__tests__/session-manager-usage.test.ts +4 -2
  107. package/src/acp/__tests__/session-manager.test.ts +895 -4
  108. package/src/acp/acp-claude-oauth.ts +328 -14
  109. package/src/acp/acp-credentials.ts +19 -0
  110. package/src/acp/agent-process.test.ts +4 -1
  111. package/src/acp/agent-process.ts +96 -10
  112. package/src/acp/auth-required.ts +50 -1
  113. package/src/acp/auto-install.test.ts +9 -7
  114. package/src/acp/claude-token-refresh.ts +150 -0
  115. package/src/acp/client-handler.ts +16 -3
  116. package/src/acp/model-config.test.ts +166 -0
  117. package/src/acp/model-config.ts +138 -0
  118. package/src/acp/prepare-agent-env.ts +21 -6
  119. package/src/acp/resolve-agent.test.ts +220 -6
  120. package/src/acp/resolve-agent.ts +88 -23
  121. package/src/acp/session-manager.test.ts +196 -3
  122. package/src/acp/session-manager.ts +441 -18
  123. package/src/acp/types.ts +50 -5
  124. package/src/agent/loop.ts +1 -0
  125. package/src/api/events/acp-session-model-update.test.ts +88 -0
  126. package/src/api/events/acp-session-model-update.ts +46 -0
  127. package/src/api/events/app-files-changed.ts +4 -3
  128. package/src/api/events/notification-intent.ts +2 -0
  129. package/src/api/events/user-message-echo.ts +7 -1
  130. package/src/api/index.ts +6 -0
  131. package/src/api/responses/conversation-message.ts +5 -0
  132. package/src/apps/app-store.ts +1 -1
  133. package/src/apps/resolve-app.ts +81 -0
  134. package/src/apps/source-fingerprint.ts +266 -0
  135. package/src/avatar/identity-avatar.ts +7 -2
  136. package/src/bundler/app-compiler.ts +15 -0
  137. package/src/calls/__tests__/barge-in-guard.test.ts +81 -0
  138. package/src/{__tests__ → calls/__tests__}/call-controller.test.ts +503 -82
  139. package/src/{__tests__ → calls/__tests__}/media-stream-audio-transcode.test.ts +1 -1
  140. package/src/{__tests__ → calls/__tests__}/media-stream-output.test.ts +37 -8
  141. package/src/{__tests__ → calls/__tests__}/media-stream-parser.test.ts +1 -1
  142. package/src/{__tests__ → calls/__tests__}/media-stream-server-integration.test.ts +150 -57
  143. package/src/{__tests__ → calls/__tests__}/media-stream-stt-session.test.ts +5 -5
  144. package/src/{__tests__ → calls/__tests__}/media-turn-detector.test.ts +1 -1
  145. package/src/{live-voice → calls}/__tests__/progress-narration.test.ts +4 -4
  146. package/src/{live-voice → calls}/__tests__/progress-phrases.test.ts +1 -1
  147. package/src/calls/__tests__/voice-control-protocol.test.ts +120 -25
  148. package/src/calls/__tests__/voice-leg-coordinator.test.ts +229 -0
  149. package/src/calls/__tests__/voice-progress-cadence.test.ts +274 -0
  150. package/src/{__tests__/voice-session-bridge.test.ts → calls/__tests__/voice-session-bridge-turn-flow.test.ts} +20 -12
  151. package/src/calls/__tests__/voice-session-bridge.test.ts +56 -1
  152. package/src/calls/__tests__/voice-triage-escalate.test.ts +105 -0
  153. package/src/calls/barge-in-guard.ts +118 -0
  154. package/src/calls/call-constants.ts +24 -4
  155. package/src/calls/call-controller.ts +499 -199
  156. package/src/calls/call-transport.ts +16 -0
  157. package/src/calls/media-stream-output.ts +32 -0
  158. package/src/calls/media-stream-server.ts +82 -30
  159. package/src/calls/media-stream-stt-session.ts +15 -0
  160. package/src/{live-voice → calls}/progress-narration.ts +2 -2
  161. package/src/calls/resolve-call-tts-provider.ts +33 -2
  162. package/src/calls/tts-call-strategy.ts +9 -5
  163. package/src/calls/types.ts +2 -0
  164. package/src/calls/voice-control-protocol.ts +155 -21
  165. package/src/calls/voice-leg-coordinator.ts +189 -0
  166. package/src/calls/voice-progress-cadence.ts +423 -0
  167. package/src/calls/voice-session-bridge.ts +92 -72
  168. package/src/calls/voice-triage-escalate.ts +178 -59
  169. package/src/cli/commands/__tests__/apps.test.ts +245 -0
  170. package/src/cli/commands/__tests__/bash.test.ts +53 -0
  171. package/src/cli/commands/__tests__/roadmap.help.test.ts +19 -0
  172. package/src/cli/commands/apps.help.ts +67 -13
  173. package/src/cli/commands/apps.ts +183 -0
  174. package/src/cli/commands/bash.help.ts +8 -13
  175. package/src/cli/commands/bash.ts +7 -25
  176. package/src/cli/commands/channels/__tests__/send.test.ts +218 -0
  177. package/src/cli/commands/channels/index.help.ts +70 -2
  178. package/src/cli/commands/channels/index.ts +16 -3
  179. package/src/cli/commands/channels/send.ts +128 -0
  180. package/src/cli/commands/credentials.help.ts +6 -2
  181. package/src/cli/commands/credentials.ts +2 -2
  182. package/src/cli/commands/mcp.help.ts +8 -8
  183. package/src/cli/commands/mcp.ts +1 -1
  184. package/src/cli/commands/oauth/status.ts +5 -0
  185. package/src/cli/commands/roadmap.help.ts +5 -1
  186. package/src/cli/commands/roadmap.ts +1 -1
  187. package/src/cli/lib/bundled-marketplace.json +103 -90
  188. package/src/config/__tests__/default-profile-catalog.test.ts +22 -0
  189. package/src/config/__tests__/memory-retrospective-schema.test.ts +15 -1
  190. package/src/config/__tests__/platform-identity.test.ts +255 -0
  191. package/src/config/__tests__/platform-rehydration.test.ts +99 -9
  192. package/src/config/acp-agent-write.ts +43 -0
  193. package/src/config/acp-defaults.test.ts +13 -3
  194. package/src/config/acp-defaults.ts +23 -6
  195. package/src/config/acp-schema.test.ts +81 -0
  196. package/src/config/acp-schema.ts +30 -2
  197. package/src/config/bundled-skills/acp/SKILL.md +22 -14
  198. package/src/config/bundled-skills/acp/TOOLS.json +5 -1
  199. package/src/config/bundled-skills/app-builder/SKILL.md +12 -9
  200. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
  201. package/src/config/bundled-skills/computer-use/SKILL.md +29 -2
  202. package/src/config/bundled-skills/computer-use/TOOLS.json +99 -0
  203. package/src/config/bundled-skills/computer-use/tools/computer-use-sequence.ts +12 -0
  204. package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -1
  205. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -1
  206. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -1
  207. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  208. package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
  209. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +67 -139
  210. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
  211. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -1
  212. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -1
  213. package/src/config/bundled-skills/schedule/SKILL.md +3 -4
  214. package/src/config/bundled-skills/screen-annotation/SKILL.md +8 -1
  215. package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +4 -1
  216. package/src/config/bundled-skills/skill-management/TOOLS.json +6 -2
  217. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +5 -2
  218. package/src/config/default-profile-catalog.ts +1 -1
  219. package/src/config/env.ts +2 -2
  220. package/src/config/feature-flag-registry.json +33 -13
  221. package/src/config/loader.ts +2 -0
  222. package/src/config/memory-v3-gate.test.ts +31 -0
  223. package/src/config/memory-v3-gate.ts +20 -16
  224. package/src/config/platform-identity.ts +201 -0
  225. package/src/config/platform-rehydration.ts +11 -27
  226. package/src/config/schema.ts +2 -2
  227. package/src/config/schemas/__tests__/live-voice.test.ts +8 -158
  228. package/src/config/schemas/__tests__/voice.test.ts +148 -0
  229. package/src/config/schemas/calls.ts +1 -28
  230. package/src/config/schemas/live-voice.ts +1 -173
  231. package/src/config/schemas/mcp.ts +1 -1
  232. package/src/config/schemas/memory-retrospective.ts +10 -0
  233. package/src/config/schemas/services.ts +18 -0
  234. package/src/config/schemas/skills.ts +0 -14
  235. package/src/config/schemas/voice.ts +150 -0
  236. package/src/credential-execution/process-manager.test.ts +18 -19
  237. package/src/credential-health/credential-health-service.ts +11 -17
  238. package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -121
  239. package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +4 -1
  240. package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +133 -0
  241. package/src/daemon/app-change-notify.ts +45 -0
  242. package/src/daemon/config-watcher.ts +13 -194
  243. package/src/daemon/conversation-error.ts +3 -2
  244. package/src/daemon/conversation-media-retry.ts +2 -1
  245. package/src/daemon/conversation-process.ts +35 -64
  246. package/src/daemon/conversation-runtime-assembly.ts +20 -7
  247. package/src/daemon/conversation-skill-tools.ts +13 -31
  248. package/src/daemon/conversation-store.ts +1 -1
  249. package/src/daemon/conversation-surfaces.ts +21 -10
  250. package/src/daemon/conversation-tool-setup.ts +45 -59
  251. package/src/daemon/conversation.ts +0 -3
  252. package/src/daemon/dictation-profile-store.ts +2 -1
  253. package/src/daemon/handlers/shared.ts +2 -1
  254. package/src/daemon/handlers/skills.ts +6 -3
  255. package/src/daemon/host-bash-proxy.ts +8 -12
  256. package/src/daemon/host-browser-proxy.ts +15 -1
  257. package/src/daemon/host-cu-proxy.ts +224 -19
  258. package/src/daemon/host-file-proxy.ts +8 -10
  259. package/src/daemon/host-proxy-preactivation.ts +2 -1
  260. package/src/daemon/host-transfer-proxy.ts +14 -18
  261. package/src/daemon/lifecycle.ts +0 -5
  262. package/src/daemon/mcp-reload-service.ts +5 -5
  263. package/src/daemon/message-types/sync.ts +1 -0
  264. package/src/daemon/orphan-reaper.ts +1 -1
  265. package/src/daemon/providers-setup.ts +1 -1
  266. package/src/daemon/reaction-history-render.ts +2 -1
  267. package/src/daemon/shutdown-handlers.ts +1 -9
  268. package/src/daemon/skill-memory-refresh.ts +64 -0
  269. package/src/daemon/tool-side-effects.ts +7 -18
  270. package/src/desktop/__tests__/fake-desktop.ts +122 -0
  271. package/src/desktop/desktop-chrome-policy.test.ts +79 -0
  272. package/src/desktop/desktop-chrome-policy.ts +47 -0
  273. package/src/desktop/desktop-chrome-session.ts +37 -0
  274. package/src/desktop/desktop-dependencies.test.ts +102 -0
  275. package/src/desktop/desktop-dependencies.ts +308 -0
  276. package/src/desktop/desktop-feature.test.ts +18 -0
  277. package/src/desktop/desktop-feature.ts +19 -0
  278. package/src/desktop/desktop-panel-config.test.ts +135 -0
  279. package/src/desktop/desktop-panel-config.ts +149 -0
  280. package/src/desktop/desktop-session-manager.test.ts +730 -0
  281. package/src/desktop/desktop-session-manager.ts +850 -0
  282. package/src/desktop/desktop-stream-bridge.test.ts +395 -0
  283. package/src/desktop/desktop-stream-bridge.ts +214 -0
  284. package/src/desktop/desktop-wallpaper.test.ts +191 -0
  285. package/src/desktop/desktop-wallpaper.ts +113 -0
  286. package/src/desktop/desktop-window-drag.ts +177 -0
  287. package/src/desktop/desktop-window-manager-config.test.ts +230 -0
  288. package/src/desktop/desktop-window-manager-config.ts +238 -0
  289. package/src/desktop/desktop-window-theme.ts +170 -0
  290. package/src/heartbeat/heartbeat-service.ts +21 -3
  291. package/src/home/__tests__/feed-writer.test.ts +22 -0
  292. package/src/home/feed-writer.ts +11 -2
  293. package/src/hooks/types.ts +33 -0
  294. package/src/i18n/AGENTS.md +22 -0
  295. package/src/i18n/__tests__/i18n.test.ts +108 -0
  296. package/src/i18n/index.ts +16 -0
  297. package/src/i18n/locales.ts +93 -0
  298. package/src/i18n/messages.ts +61 -0
  299. package/src/i18n/title.ts +25 -0
  300. package/src/inbound/platform-callback-registration.ts +4 -5
  301. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +121 -0
  302. package/src/live-voice/__tests__/live-voice-events.test.ts +8 -7
  303. package/src/live-voice/__tests__/live-voice-metrics.test.ts +0 -3
  304. package/src/live-voice/__tests__/live-voice-progress.test.ts +94 -15
  305. package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +238 -0
  306. package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
  307. package/src/live-voice/__tests__/protocol.test.ts +39 -0
  308. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +13 -69
  309. package/src/live-voice/__tests__/session-controls.test.ts +79 -0
  310. package/src/live-voice/live-voice-photo.ts +25 -6
  311. package/src/live-voice/live-voice-session.ts +297 -699
  312. package/src/live-voice/protocol.ts +60 -2
  313. package/src/live-voice/session-controls.ts +111 -0
  314. package/src/mcp/__tests__/effective-config.test.ts +2 -2
  315. package/src/mcp/__tests__/workspace-mcp-config.test.ts +135 -0
  316. package/src/mcp/effective-config.ts +3 -3
  317. package/src/mcp/mcp-header-store.ts +29 -45
  318. package/src/mcp/spec-schema.ts +111 -0
  319. package/src/mcp/startup.ts +8 -4
  320. package/src/mcp/workspace-mcp-config.ts +188 -0
  321. package/src/messaging/provider.ts +10 -3
  322. package/src/messaging/providers/__tests__/proactive-address.test.ts +95 -0
  323. package/src/messaging/providers/callback-routing.ts +18 -0
  324. package/src/messaging/providers/channel-transport.ts +56 -0
  325. package/src/messaging/providers/discord/transport.ts +17 -0
  326. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +6 -17
  327. package/src/messaging/providers/slack/adapter.ts +7 -44
  328. package/src/messaging/providers/slack/transport.ts +16 -0
  329. package/src/messaging/providers/telegram-bot/adapter.ts +1 -48
  330. package/src/messaging/providers/telegram-bot/client.ts +0 -26
  331. package/src/messaging/providers/telegram-bot/transport.ts +20 -0
  332. package/src/messaging/providers/whatsapp/adapter.ts +1 -48
  333. package/src/messaging/providers/whatsapp/transport.ts +18 -0
  334. package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +8 -0
  335. package/src/notifications/__tests__/assistant-reply-producer.test.ts +55 -0
  336. package/src/notifications/__tests__/guardian-feed-projection.test.ts +158 -2
  337. package/src/notifications/__tests__/home-feed-side-effect.test.ts +153 -3
  338. package/src/notifications/__tests__/schedule-result-producer.test.ts +99 -3
  339. package/src/notifications/adapters/macos.ts +3 -0
  340. package/src/notifications/assistant-reply-producer.ts +8 -3
  341. package/src/notifications/conversation-pairing.ts +36 -16
  342. package/src/notifications/delivered-post-record.ts +11 -1
  343. package/src/notifications/guardian-feed-projection.ts +125 -5
  344. package/src/notifications/home-feed-side-effect.ts +55 -7
  345. package/src/notifications/schedule-result-producer.ts +66 -22
  346. package/src/oauth/AGENTS.md +2 -0
  347. package/src/oauth/__tests__/seed-providers-managed.test.ts +149 -0
  348. package/src/oauth/byo-connection.test.ts +105 -0
  349. package/src/oauth/byo-connection.ts +36 -6
  350. package/src/oauth/connection-resolver.test.ts +100 -0
  351. package/src/oauth/connection-resolver.ts +120 -3
  352. package/src/oauth/provider-serializer.ts +9 -0
  353. package/src/oauth/scope-utils.ts +24 -0
  354. package/src/oauth/seed-providers.ts +314 -27
  355. package/src/outbound-proxy/certs.ts +3 -5
  356. package/src/permissions/checker.test.ts +11 -6
  357. package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
  358. package/src/persistence/conversation-crud.ts +71 -63
  359. package/src/persistence/conversation-lineage.ts +12 -4
  360. package/src/persistence/conversation-queries.ts +2 -2
  361. package/src/persistence/conversation-title-placeholders.ts +23 -0
  362. package/src/persistence/conversation-title-service.ts +9 -26
  363. package/src/persistence/embeddings/qdrant-manager.ts +163 -18
  364. package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
  365. package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
  366. package/src/persistence/message-cursor.ts +78 -0
  367. package/src/persistence/message-reads.ts +30 -0
  368. package/src/persistence/migrations/157-invite-contact-id.ts +18 -6
  369. package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +149 -0
  370. package/src/persistence/schema/memory-core.ts +5 -0
  371. package/src/platform/client.test.ts +4 -2
  372. package/src/platform/client.ts +2 -10
  373. package/src/plugin-api/constants.ts +2 -0
  374. package/src/plugin-api/index.ts +1 -0
  375. package/src/plugin-api/types.ts +2 -0
  376. package/src/plugins/defaults/index.ts +2 -0
  377. package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +46 -0
  378. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +118 -0
  379. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +83 -0
  380. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +9 -5
  381. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +20 -10
  382. package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +5 -0
  383. package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +219 -0
  384. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +31 -0
  385. package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +63 -0
  386. package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +4 -0
  387. package/src/plugins/defaults/memory/context-search/agent-runner.ts +3 -2
  388. package/src/plugins/defaults/memory/context-search/format.ts +3 -2
  389. package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +6 -3
  390. package/src/plugins/defaults/memory/context-search/sources/workspace.ts +3 -2
  391. package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -7
  392. package/src/plugins/defaults/memory/hooks/init.ts +10 -0
  393. package/src/plugins/defaults/memory/hooks/message-deleted.ts +21 -0
  394. package/src/plugins/defaults/memory/hooks/shutdown.ts +2 -0
  395. package/src/plugins/defaults/memory/host-utils.ts +10 -0
  396. package/src/plugins/defaults/memory/jobs-worker.ts +13 -0
  397. package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +34 -60
  398. package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +126 -0
  399. package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +79 -0
  400. package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +28 -0
  401. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +3 -5
  402. package/src/plugins/defaults/memory/memory-retrospective-job.ts +12 -3
  403. package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +1 -1
  404. package/src/plugins/defaults/memory/memory-retrospective-state.ts +312 -71
  405. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +2 -1
  406. package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +5 -3
  407. package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +9 -0
  408. package/src/plugins/defaults/memory/startup.ts +28 -2
  409. package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +7 -9
  410. package/src/plugins/defaults/memory/substrate/page-index.ts +6 -1
  411. package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
  412. package/src/plugins/defaults/memory/v1/graph/consolidation.ts +4 -2
  413. package/src/plugins/defaults/memory/v1/graph/extraction.ts +4 -2
  414. package/src/plugins/defaults/memory/v1/graph/retriever.ts +4 -1
  415. package/src/plugins/defaults/memory/v2/reranker.ts +6 -1
  416. package/src/plugins/defaults/memory/v3/__tests__/card.test.ts +24 -0
  417. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +125 -0
  418. package/src/plugins/defaults/memory/v3/__tests__/sections.test.ts +26 -0
  419. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +30 -0
  420. package/src/plugins/defaults/memory/v3/card.ts +3 -2
  421. package/src/plugins/defaults/memory/v3/pool-select.ts +5 -3
  422. package/src/plugins/defaults/memory/v3/sections.ts +9 -3
  423. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +5 -2
  424. package/src/plugins/defaults/memory/worker.ts +6 -0
  425. package/src/plugins/mcp-servers.ts +15 -75
  426. package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
  427. package/src/providers/__tests__/retry-callsite.test.ts +41 -0
  428. package/src/providers/__tests__/retry-outbound-sanitize.test.ts +176 -0
  429. package/src/providers/anthropic/client.ts +0 -47
  430. package/src/providers/gemini/client.ts +9 -23
  431. package/src/providers/gemini-thought-signature.test.ts +63 -0
  432. package/src/providers/gemini-thought-signature.ts +44 -0
  433. package/src/providers/inference/__tests__/endpoint-probe.test.ts +42 -3
  434. package/src/providers/inference/auth.ts +2 -3
  435. package/src/providers/inference/connection-availability.ts +27 -8
  436. package/src/providers/inference/endpoint-probe.ts +10 -1
  437. package/src/providers/inference/resolve-auth.ts +22 -4
  438. package/src/providers/inference/service-account-token.ts +248 -0
  439. package/src/providers/model-catalog.ts +34 -0
  440. package/src/providers/model-intents.ts +10 -5
  441. package/src/providers/openai/__tests__/chat-completions-output-token-limit.test.ts +141 -0
  442. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +146 -18
  443. package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +613 -0
  444. package/src/providers/openai/__tests__/google-thought-signature.test.ts +235 -0
  445. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +83 -1
  446. package/src/providers/openai/chat-completions-provider.ts +212 -79
  447. package/src/providers/openai/codex-models.ts +0 -4
  448. package/src/providers/openai/google-thought-signature.ts +320 -0
  449. package/src/providers/opencode/client.test.ts +73 -4
  450. package/src/providers/opencode/client.ts +60 -3
  451. package/src/providers/openrouter/client.ts +20 -0
  452. package/src/providers/outbound-request-sanitize.ts +96 -0
  453. package/src/providers/retry.ts +30 -19
  454. package/src/providers/unparseable-tool-args.ts +5 -1
  455. package/src/runtime/AGENTS.md +3 -1
  456. package/src/runtime/__tests__/channel-send.test.ts +443 -0
  457. package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +89 -0
  458. package/src/runtime/__tests__/host-observe.test.ts +40 -1
  459. package/src/runtime/__tests__/live-voice-upgrade.test.ts +58 -0
  460. package/src/runtime/__tests__/runtime-ws-test-utils.ts +72 -0
  461. package/src/runtime/__tests__/watch-stream-upgrade.test.ts +59 -0
  462. package/src/runtime/agent-wake.ts +2 -1
  463. package/src/runtime/assistant-event-hub.ts +21 -3
  464. package/src/runtime/auth/same-actor.ts +38 -3
  465. package/src/runtime/channel-send.ts +316 -0
  466. package/src/runtime/host-observe.ts +11 -1
  467. package/src/runtime/http-server.ts +160 -151
  468. package/src/runtime/routes/__tests__/acp-claude-auth-routes.test.ts +16 -5
  469. package/src/runtime/routes/__tests__/acp-routes.test.ts +159 -4
  470. package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +275 -0
  471. package/src/runtime/routes/__tests__/channel-send-routes.test.ts +127 -0
  472. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +108 -1
  473. package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
  474. package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +107 -0
  475. package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +16 -12
  476. package/src/runtime/routes/acp-claude-auth-routes.ts +11 -3
  477. package/src/runtime/routes/acp-routes.test.ts +15 -0
  478. package/src/runtime/routes/acp-routes.ts +72 -9
  479. package/src/runtime/routes/app-management-routes.ts +90 -2
  480. package/src/runtime/routes/app-routes.ts +1 -1
  481. package/src/runtime/routes/channel-send-routes.ts +85 -0
  482. package/src/runtime/routes/conversation-list-routes.ts +14 -3
  483. package/src/runtime/routes/conversation-query-routes.ts +40 -0
  484. package/src/runtime/routes/conversation-routes.ts +16 -3
  485. package/src/runtime/routes/credential-routes.ts +20 -14
  486. package/src/runtime/routes/desktop-setup-routes.test.ts +74 -0
  487. package/src/runtime/routes/desktop-setup-routes.ts +35 -0
  488. package/src/runtime/routes/diagnostics-routes.ts +61 -4
  489. package/src/runtime/routes/events-routes.ts +4 -0
  490. package/src/runtime/routes/host-cu-routes.ts +6 -0
  491. package/src/runtime/routes/index.ts +4 -2
  492. package/src/runtime/routes/log-export-routes.ts +2 -0
  493. package/src/runtime/routes/mcp-auth-routes.ts +39 -47
  494. package/src/runtime/routes/migration-routes.ts +6 -20
  495. package/src/runtime/routes/oauth-commands-routes.ts +50 -0
  496. package/src/runtime/routes/oauth-providers.ts +7 -0
  497. package/src/runtime/routes/platform-routes.ts +18 -15
  498. package/src/runtime/routes/workspace-routes.test.ts +55 -26
  499. package/src/runtime/routes/workspace-routes.ts +46 -63
  500. package/src/runtime/routes/workspace-tree-walk.test.ts +244 -0
  501. package/src/runtime/routes/workspace-tree-walk.ts +240 -0
  502. package/src/runtime/routes/workspace-utils.ts +17 -0
  503. package/src/runtime/services/__tests__/conversation-serializer.test.ts +28 -0
  504. package/src/runtime/services/conversation-serializer.ts +16 -3
  505. package/src/runtime/sync/resource-sync-events.ts +2 -1
  506. package/src/schedule/run-script.ts +2 -1
  507. package/src/schedule/schedule-store.ts +9 -2
  508. package/src/schedule/worker.ts +1 -1
  509. package/src/security/__tests__/ces-http-record-backend.test.ts +137 -0
  510. package/src/security/ces-http-record-backend.ts +120 -0
  511. package/src/security/ces-rpc-record-backend.ts +7 -0
  512. package/src/security/untrusted-content.ts +3 -1
  513. package/src/skills/__tests__/workspace-skill-md-signature.test.ts +60 -0
  514. package/src/skills/workspace-skill-md-signature.ts +50 -0
  515. package/src/subagent/consult-context.ts +12 -25
  516. package/src/tools/__tests__/side-effect-abort-guard.test.ts +1 -0
  517. package/src/tools/acp/list-agents.test.ts +3 -1
  518. package/src/tools/acp/spawn.test.ts +146 -11
  519. package/src/tools/acp/spawn.ts +21 -3
  520. package/src/tools/acp/status.test.ts +94 -0
  521. package/src/tools/acp/status.ts +40 -3
  522. package/src/tools/app-control/skill-proxy-bridge.ts +2 -1
  523. package/src/tools/browser/browser-execution.ts +1 -1
  524. package/src/tools/browser/cdp-client/accessibility-snapshot.ts +9 -3
  525. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +2 -1
  526. package/src/tools/browser/cdp-client/extension-cdp-client.ts +3 -2
  527. package/src/tools/browser/network-recorder.ts +2 -1
  528. package/src/tools/capability-offer.test.ts +22 -2
  529. package/src/tools/capability-offer.ts +16 -1
  530. package/src/tools/computer-use/definitions.ts +121 -2
  531. package/src/tools/computer-use/skill-proxy-bridge.ts +2 -1
  532. package/src/tools/credentials/metadata-store.ts +100 -0
  533. package/src/tools/filesystem/search.ts +2 -1
  534. package/src/tools/host-filesystem/edit.test.ts +2 -1
  535. package/src/tools/host-filesystem/edit.ts +2 -2
  536. package/src/tools/host-filesystem/read.test.ts +2 -1
  537. package/src/tools/host-filesystem/read.ts +2 -2
  538. package/src/tools/host-filesystem/transfer.test.ts +2 -1
  539. package/src/tools/host-filesystem/transfer.ts +2 -2
  540. package/src/tools/host-filesystem/write.test.ts +2 -1
  541. package/src/tools/host-filesystem/write.ts +2 -2
  542. package/src/tools/host-terminal/host-shell.test.ts +16 -0
  543. package/src/tools/host-terminal/host-shell.ts +4 -20
  544. package/src/tools/network/web-search.ts +6 -1
  545. package/src/tools/policy-context.ts +6 -7
  546. package/src/tools/skills/scaffold-managed.ts +61 -3
  547. package/src/tools/subagent/spawn.ts +5 -8
  548. package/src/tools/terminal/__tests__/sanitized-bash.test.ts +57 -0
  549. package/src/tools/terminal/sanitized-bash.ts +105 -0
  550. package/src/tools/ui-surface/channel-variants.ts +10 -59
  551. package/src/tools/watch/watch-retro-report.ts +0 -8
  552. package/src/types/host-capabilities.ts +5 -3
  553. package/src/util/__tests__/language-subtag.test.ts +23 -1
  554. package/src/util/ca-bundle.ts +13 -0
  555. package/src/util/language-subtag.ts +16 -0
  556. package/src/util/platform.ts +8 -0
  557. package/src/util/unicode.ts +15 -1
  558. package/src/watch/watch-retro.ts +6 -8
  559. package/src/watch/watch-timeline.ts +2 -2
  560. package/src/workflows/run-manager.ts +2 -1
  561. package/src/workspace/git-porcelain.ts +66 -0
  562. package/src/workspace/git-service.ts +6 -55
  563. package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +258 -0
  564. package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +78 -0
  565. package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +214 -0
  566. package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +102 -0
  567. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +199 -0
  568. package/src/workspace/migrations/registry.ts +6 -0
  569. package/src/__tests__/app-source-watcher.test.ts +0 -218
  570. package/src/__tests__/config-watcher-skill-reseed.test.ts +0 -359
  571. package/src/__tests__/speaker-identification.test.ts +0 -56
  572. package/src/calls/speaker-identification.ts +0 -233
  573. package/src/daemon/app-source-watcher.ts +0 -218
  574. package/src/messaging/providers/whatsapp/client.ts +0 -29
  575. package/src/runtime/routes/debug-bash-routes.ts +0 -173
  576. package/src/util/fs-watcher-error.ts +0 -36
  577. /package/src/{live-voice → calls}/progress-phrases.ts +0 -0
@@ -17,6 +17,7 @@ import {
17
17
  mediaSourceByteLength,
18
18
  resolveMediaReferences,
19
19
  } from "../media-resolve.js";
20
+ import { supportsForcedToolChoiceWithThinking } from "../model-catalog.js";
20
21
  import { PLACEHOLDER_EMPTY_TURN } from "../placeholder-sentinels.js";
21
22
  import { recordProviderRequestDiagnostics } from "../request-diagnostics.js";
22
23
  import { createStreamTimeout } from "../stream-timeout.js";
@@ -27,6 +28,7 @@ import type {
27
28
  Provider,
28
29
  ProviderResponse,
29
30
  SendMessageOptions,
31
+ ToolUseContent,
30
32
  } from "../types.js";
31
33
  import {
32
34
  ContextOverflowError,
@@ -51,6 +53,15 @@ import {
51
53
  coerceObjectParamsToJsonString,
52
54
  decodeCoercedObjectArgs,
53
55
  } from "./coerce-object-args.js";
56
+ import {
57
+ applyGemini3UnsignedToolCallFallback,
58
+ attachGoogleThoughtSignatureIfNeeded,
59
+ classifyGoogleThoughtSignatureRetry,
60
+ geminiThoughtSignaturesByToolCallId,
61
+ type GoogleToolCallExtraContent,
62
+ thoughtSignatureFromToolUseMetadata,
63
+ toolUseMetadataFromChatCompletionsDelta,
64
+ } from "./google-thought-signature.js";
54
65
  import {
55
66
  isOpenAICompatInlineAudio,
56
67
  OPENAI_COMPAT_MAX_INLINE_AUDIO_BYTES,
@@ -197,6 +208,12 @@ export interface OpenAIChatCompletionsProviderOptions {
197
208
  * (Fireworks, Together) keep sending `none` / forced choices. Enabled for
198
209
  * the generic `openai-compatible` adapter, whose upstream is unknown. */
199
210
  omitToolChoiceWhenReasoning?: boolean;
211
+ /** Wire field for the output-token limit. OpenAI and OpenAI-compatible
212
+ * backends use `max_completion_tokens`. OpenRouter defaults to
213
+ * `max_tokens` because its parameter router matches that key on
214
+ * `require_parameters` routes; see
215
+ * {@link OpenAIChatCompletionsProvider.resolveOutputTokenLimitField}. */
216
+ outputTokenLimitField?: "max_completion_tokens" | "max_tokens";
200
217
  }
201
218
 
202
219
  const log = getLogger("chat-completions");
@@ -204,7 +221,13 @@ const log = getLogger("chat-completions");
204
221
  /** Wire-level reasoning_effort values. The OpenAI SDK type doesn't include
205
222
  * `"max"`, but Fireworks accepts it for DeepSeek V4; the assignment to
206
223
  * `params.reasoning_effort` casts through this union. */
207
- export type ReasoningEffortWire = "none" | "low" | "medium" | "high" | "xhigh" | "max";
224
+ export type ReasoningEffortWire =
225
+ | "none"
226
+ | "low"
227
+ | "medium"
228
+ | "high"
229
+ | "xhigh"
230
+ | "max";
208
231
 
209
232
  const REASONING_EFFORT_RANK: Record<ReasoningEffortWire, number> = {
210
233
  none: 0,
@@ -388,9 +411,15 @@ export function isThinkingEnabledOnWire(params: unknown): boolean {
388
411
  * rejected it because thinking/reasoning mode forbids that parameter.
389
412
  * DeepSeek thinking mode 400s with `Thinking mode does not support this
390
413
  * tool_choice` for any explicit value, including `"auto"` and `"none"`.
391
- * One retry without `tool_choice` lets the same provider succeed instead of
392
- * failing over to a different backend.
414
+ * Kimi 400s with `tool_choice 'specified' is incompatible with thinking
415
+ * enabled`. One retry without `tool_choice` lets the same provider succeed
416
+ * instead of failing over to a different backend.
393
417
  */
418
+ const THINKING_MODE_TOOL_CHOICE_REJECTION_PATTERNS: RegExp[] = [
419
+ /does not support this tool_choice/i,
420
+ /tool_choice\s+'specified'\s+is incompatible with thinking/i,
421
+ ];
422
+
394
423
  function isThinkingModeToolChoiceRejection(
395
424
  error: unknown,
396
425
  params: unknown,
@@ -402,8 +431,9 @@ function isThinkingModeToolChoiceRejection(
402
431
  if (!isClientErrorStatus(error)) {
403
432
  return false;
404
433
  }
405
- return /does not support this tool_choice/i.test(
406
- openaiCompatErrorHaystack(error),
434
+ const haystack = openaiCompatErrorHaystack(error);
435
+ return THINKING_MODE_TOOL_CHOICE_REJECTION_PATTERNS.some((pattern) =>
436
+ pattern.test(haystack),
407
437
  );
408
438
  }
409
439
 
@@ -541,8 +571,10 @@ function isMissingReasoningContentRejection(
541
571
 
542
572
  /**
543
573
  * True when the request included an assistant `reasoning` / `reasoning_content`
544
- * extra and the provider rejected it as an unknown message property. One retry
545
- * without those extras lets a strict Chat Completions schema succeed.
574
+ * extra and the provider rejected it as an unknown or unsupported message
575
+ * property. One retry without those extras lets a strict Chat Completions
576
+ * schema succeed. Groq phrases this as
577
+ * `property 'reasoning_content' is unsupported`.
546
578
  */
547
579
  function isUnknownAssistantReasoningFieldRejection(
548
580
  error: unknown,
@@ -561,7 +593,7 @@ function isUnknownAssistantReasoningFieldRejection(
561
593
  if (!haystackNamesAssistantReasoningField(haystack)) {
562
594
  return false;
563
595
  }
564
- return /unknown|unexpected|unrecognized|additional propert|extra (?:field|property)|not (?:a )?valid|invalid (?:argument|parameter|field|property)/i.test(
596
+ return /unknown|unexpected|unrecognized|unsupported|not supported|additional propert|extra (?:field|property)|not (?:a )?valid|invalid (?:argument|parameter|field|property)/i.test(
565
597
  haystack,
566
598
  );
567
599
  }
@@ -634,6 +666,82 @@ function flattenContentPartsToStrings(params: unknown): boolean {
634
666
  return flattened;
635
667
  }
636
668
 
669
+ type OpenAICompatRetryKind =
670
+ | "reasoning-opt-out"
671
+ | "thinking-tool-choice"
672
+ | "missing-reasoning-content"
673
+ | "unknown-reasoning-field"
674
+ | "missing-thought-signature"
675
+ | "unknown-extra-content"
676
+ | "chat-template";
677
+
678
+ function classifyOpenAICompatRetry(
679
+ error: unknown,
680
+ params: OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming,
681
+ thoughtSignaturesByCallId: ReadonlyMap<string, string>,
682
+ ): { kind: OpenAICompatRetryKind; message: string; apply: () => void } | null {
683
+ if (isReasoningOptOutRejection(error, params)) {
684
+ return {
685
+ kind: "reasoning-opt-out",
686
+ message:
687
+ "Model rejected the explicit reasoning opt-out; retrying without reasoning params",
688
+ apply: () => {
689
+ delete params.reasoning_effort;
690
+ delete (params as unknown as Record<string, unknown>).reasoning;
691
+ },
692
+ };
693
+ }
694
+ if (isThinkingModeToolChoiceRejection(error, params)) {
695
+ return {
696
+ kind: "thinking-tool-choice",
697
+ message:
698
+ "Upstream rejected tool_choice in thinking mode; retrying without tool_choice",
699
+ apply: () => {
700
+ delete params.tool_choice;
701
+ },
702
+ };
703
+ }
704
+ if (isMissingReasoningContentRejection(error, params)) {
705
+ return {
706
+ kind: "missing-reasoning-content",
707
+ message:
708
+ "Upstream requires reasoning_content round-trip; retrying with empty field on assistant messages",
709
+ apply: () => {
710
+ backfillEmptyReasoningContent(params);
711
+ },
712
+ };
713
+ }
714
+ if (isUnknownAssistantReasoningFieldRejection(error, params)) {
715
+ return {
716
+ kind: "unknown-reasoning-field",
717
+ message:
718
+ "Upstream rejected assistant reasoning field; retrying without it",
719
+ apply: () => {
720
+ stripAssistantReasoningFields(params);
721
+ },
722
+ };
723
+ }
724
+ const thoughtSignatureRetry = classifyGoogleThoughtSignatureRetry(params, {
725
+ isClientError: isClientErrorStatus(error),
726
+ haystack: openaiCompatErrorHaystack(error),
727
+ capturedByCallId: thoughtSignaturesByCallId,
728
+ });
729
+ if (thoughtSignatureRetry) {
730
+ return thoughtSignatureRetry;
731
+ }
732
+ if (isChatTemplateRejection(error, params)) {
733
+ return {
734
+ kind: "chat-template",
735
+ message:
736
+ "Upstream chat template rejected structured message content; retrying with flattened plain-text content",
737
+ apply: () => {
738
+ flattenContentPartsToStrings(params);
739
+ },
740
+ };
741
+ }
742
+ return null;
743
+ }
744
+
637
745
  /**
638
746
  * Translate the neutral (Anthropic-shaped) `tool_choice` carried on the call
639
747
  * config into the OpenAI chat-completions wire format. Callers express
@@ -711,6 +819,7 @@ export class OpenAIChatCompletionsProvider implements Provider {
711
819
  private coerceObjectArgsToJsonString: boolean;
712
820
  private salvageXmlToolCalls: boolean;
713
821
  private omitToolChoiceWhenReasoning: boolean;
822
+ private outputTokenLimitField: "max_completion_tokens" | "max_tokens";
714
823
 
715
824
  constructor(
716
825
  apiKey: string,
@@ -742,6 +851,8 @@ export class OpenAIChatCompletionsProvider implements Provider {
742
851
  options.salvageXmlToolCalls ?? shouldSalvageXmlToolCalls(model);
743
852
  this.omitToolChoiceWhenReasoning =
744
853
  options.omitToolChoiceWhenReasoning ?? false;
854
+ this.outputTokenLimitField =
855
+ options.outputTokenLimitField ?? "max_completion_tokens";
745
856
  }
746
857
 
747
858
  get defaultModel(): string {
@@ -774,10 +885,13 @@ export class OpenAIChatCompletionsProvider implements Provider {
774
885
  const coercedObjectKeys = new Map<string, string[]>();
775
886
 
776
887
  try {
888
+ const thoughtSignaturesByCallId =
889
+ geminiThoughtSignaturesByToolCallId(messages);
777
890
  const openaiMessages = await this.toOpenAIMessages(
778
891
  messages,
779
892
  systemPrompt,
780
893
  requestSupportsInlineAudio(modelOverride ?? this.model),
894
+ modelOverride ?? this.model,
781
895
  );
782
896
 
783
897
  recordProviderRequestDiagnostics({
@@ -794,7 +908,8 @@ export class OpenAIChatCompletionsProvider implements Provider {
794
908
  };
795
909
 
796
910
  if (maxTokens) {
797
- params.max_completion_tokens = maxTokens;
911
+ params[this.resolveOutputTokenLimitField(modelOverride ?? this.model)] =
912
+ maxTokens;
798
913
  }
799
914
 
800
915
  // Profile-scoped token biasing (e.g. the `suppress-cjk` preset). Resolved
@@ -874,7 +989,18 @@ export class OpenAIChatCompletionsProvider implements Provider {
874
989
  const thinkingOn = isThinkingEnabledOnWire(params);
875
990
  const skipAutoDefault = thinkingOn && toolChoice === "auto";
876
991
  const skipAllChoices = thinkingOn && this.omitToolChoiceWhenReasoning;
877
- if (!skipAutoDefault && !skipAllChoices) {
992
+ const skipIncompatibleForcedChoice =
993
+ thinkingOn &&
994
+ !supportsForcedToolChoiceWithThinking(
995
+ this.name,
996
+ modelOverride ?? this.model,
997
+ ) &&
998
+ (toolChoice === "required" || typeof toolChoice === "object");
999
+ if (
1000
+ !skipAutoDefault &&
1001
+ !skipAllChoices &&
1002
+ !skipIncompatibleForcedChoice
1003
+ ) {
878
1004
  params.tool_choice = toolChoice;
879
1005
  }
880
1006
  }
@@ -973,7 +1099,12 @@ export class OpenAIChatCompletionsProvider implements Provider {
973
1099
 
974
1100
  const toolCallMap = new Map<
975
1101
  number,
976
- { id: string; name: string; args: string }
1102
+ {
1103
+ id: string;
1104
+ name: string;
1105
+ args: string;
1106
+ providerMetadata?: ToolUseContent["providerMetadata"];
1107
+ }
977
1108
  >();
978
1109
  const toolProgress = createToolProgressEmitter(onEvent);
979
1110
  let finishReason = "unknown";
@@ -1001,68 +1132,31 @@ export class OpenAIChatCompletionsProvider implements Provider {
1001
1132
  ? { headers: requestHeaders }
1002
1133
  : {}),
1003
1134
  });
1135
+ const attemptedCompatRetries = new Set<OpenAICompatRetryKind>();
1004
1136
  let stream: Awaited<ReturnType<typeof createStream>>;
1005
- try {
1006
- stream = await createStream();
1007
- } catch (error) {
1008
- if (isReasoningOptOutRejection(error, params)) {
1009
- log.warn(
1010
- {
1011
- provider: this.name,
1012
- model: modelOverride ?? this.model,
1013
- error: error instanceof Error ? error.message : String(error),
1014
- },
1015
- "Model rejected the explicit reasoning opt-out; retrying without reasoning params",
1016
- );
1017
- delete params.reasoning_effort;
1018
- delete (params as unknown as Record<string, unknown>).reasoning;
1019
- stream = await createStream();
1020
- } else if (isThinkingModeToolChoiceRejection(error, params)) {
1021
- log.warn(
1022
- {
1023
- provider: this.name,
1024
- model: modelOverride ?? this.model,
1025
- error: error instanceof Error ? error.message : String(error),
1026
- },
1027
- "Upstream rejected tool_choice in thinking mode; retrying without tool_choice",
1028
- );
1029
- delete params.tool_choice;
1137
+ for (;;) {
1138
+ try {
1030
1139
  stream = await createStream();
1031
- } else if (isMissingReasoningContentRejection(error, params)) {
1032
- log.warn(
1033
- {
1034
- provider: this.name,
1035
- model: modelOverride ?? this.model,
1036
- error: error instanceof Error ? error.message : String(error),
1037
- },
1038
- "Upstream requires reasoning_content round-trip; retrying with empty field on assistant messages",
1140
+ break;
1141
+ } catch (error) {
1142
+ const retry = classifyOpenAICompatRetry(
1143
+ error,
1144
+ params,
1145
+ thoughtSignaturesByCallId,
1039
1146
  );
1040
- backfillEmptyReasoningContent(params);
1041
- stream = await createStream();
1042
- } else if (isUnknownAssistantReasoningFieldRejection(error, params)) {
1043
- log.warn(
1044
- {
1045
- provider: this.name,
1046
- model: modelOverride ?? this.model,
1047
- error: error instanceof Error ? error.message : String(error),
1048
- },
1049
- "Upstream rejected assistant reasoning field; retrying without it",
1050
- );
1051
- stripAssistantReasoningFields(params);
1052
- stream = await createStream();
1053
- } else if (isChatTemplateRejection(error, params)) {
1147
+ if (!retry || attemptedCompatRetries.has(retry.kind)) {
1148
+ throw error;
1149
+ }
1150
+ attemptedCompatRetries.add(retry.kind);
1054
1151
  log.warn(
1055
1152
  {
1056
1153
  provider: this.name,
1057
1154
  model: modelOverride ?? this.model,
1058
1155
  error: error instanceof Error ? error.message : String(error),
1059
1156
  },
1060
- "Upstream chat template rejected structured message content; retrying with flattened plain-text content",
1157
+ retry.message,
1061
1158
  );
1062
- flattenContentPartsToStrings(params);
1063
- stream = await createStream();
1064
- } else {
1065
- throw error;
1159
+ retry.apply();
1066
1160
  }
1067
1161
  }
1068
1162
 
@@ -1150,6 +1244,14 @@ export class OpenAIChatCompletionsProvider implements Provider {
1150
1244
  entry.args,
1151
1245
  );
1152
1246
  }
1247
+ const providerMetadata =
1248
+ toolUseMetadataFromChatCompletionsDelta(tc);
1249
+ if (
1250
+ providerMetadata &&
1251
+ !thoughtSignatureFromToolUseMetadata(entry.providerMetadata)
1252
+ ) {
1253
+ entry.providerMetadata = providerMetadata;
1254
+ }
1153
1255
  }
1154
1256
  }
1155
1257
 
@@ -1271,6 +1373,9 @@ export class OpenAIChatCompletionsProvider implements Provider {
1271
1373
  id: tc.id,
1272
1374
  name: tc.name,
1273
1375
  input,
1376
+ ...(tc.providerMetadata
1377
+ ? { providerMetadata: tc.providerMetadata }
1378
+ : {}),
1274
1379
  });
1275
1380
  }
1276
1381
 
@@ -1284,11 +1389,19 @@ export class OpenAIChatCompletionsProvider implements Provider {
1284
1389
  content: contentText || null,
1285
1390
  tool_calls:
1286
1391
  toolCallMap.size > 0
1287
- ? Array.from(toolCallMap.values()).map((tc) => ({
1288
- id: tc.id,
1289
- type: "function",
1290
- function: { name: tc.name, arguments: tc.args },
1291
- }))
1392
+ ? Array.from(toolCallMap.values()).map((tc) =>
1393
+ attachGoogleThoughtSignatureIfNeeded(
1394
+ {
1395
+ id: tc.id,
1396
+ type: "function",
1397
+ function: { name: tc.name, arguments: tc.args },
1398
+ },
1399
+ thoughtSignatureFromToolUseMetadata(
1400
+ tc.providerMetadata,
1401
+ ),
1402
+ modelOverride ?? this.model,
1403
+ ),
1404
+ )
1292
1405
  : undefined,
1293
1406
  },
1294
1407
  finish_reason: finishReason,
@@ -1474,6 +1587,15 @@ export class OpenAIChatCompletionsProvider implements Provider {
1474
1587
  return this.maxReasoningEffort;
1475
1588
  }
1476
1589
 
1590
+ /** Per-request output-token-limit wire key. Defaults to the constructor
1591
+ * `outputTokenLimitField`. Subclasses override when support varies by
1592
+ * model. */
1593
+ protected resolveOutputTokenLimitField(
1594
+ _model: string,
1595
+ ): "max_completion_tokens" | "max_tokens" {
1596
+ return this.outputTokenLimitField;
1597
+ }
1598
+
1477
1599
  /**
1478
1600
  * Per-model sparse `reasoning_effort` support. Subclasses return the
1479
1601
  * accepted values for models that 4xx on in-between tiers (e.g. GLM 5.3's
@@ -1492,6 +1614,7 @@ export class OpenAIChatCompletionsProvider implements Provider {
1492
1614
  messages: Message[],
1493
1615
  systemPrompt?: string,
1494
1616
  audioInputEnabled = false,
1617
+ model = this.model,
1495
1618
  ): Promise<OpenAI.Chat.Completions.ChatCompletionMessageParam[]> {
1496
1619
  // Swap any persisted attachment references back to inline base64 before
1497
1620
  // serializing, so the block transforms below can read `source.data`.
@@ -1513,7 +1636,7 @@ export class OpenAIChatCompletionsProvider implements Provider {
1513
1636
  const emittedToolCallIds = new Set<string>();
1514
1637
  for (const msg of messages) {
1515
1638
  if (msg.role === "assistant") {
1516
- const assistantMessage = this.toOpenAIAssistantMessage(msg);
1639
+ const assistantMessage = this.toOpenAIAssistantMessage(msg, model);
1517
1640
  for (const toolCall of assistantMessage.tool_calls ?? []) {
1518
1641
  emittedToolCallIds.add(toolCall.id);
1519
1642
  }
@@ -1591,11 +1714,14 @@ export class OpenAIChatCompletionsProvider implements Provider {
1591
1714
  /** Convert an assistant message with text + tool_use blocks to OpenAI format. */
1592
1715
  private toOpenAIAssistantMessage(
1593
1716
  msg: Message,
1717
+ model: string,
1594
1718
  ): OpenAI.Chat.Completions.ChatCompletionAssistantMessageParam {
1595
1719
  const textParts: string[] = [];
1596
1720
  const reasoningParts: string[] = [];
1597
- const toolCalls: OpenAI.Chat.Completions.ChatCompletionMessageToolCall[] =
1598
- [];
1721
+ const toolCalls: Array<
1722
+ OpenAI.Chat.Completions.ChatCompletionMessageToolCall &
1723
+ GoogleToolCallExtraContent
1724
+ > = [];
1599
1725
 
1600
1726
  for (const block of msg.content) {
1601
1727
  switch (block.type) {
@@ -1609,14 +1735,20 @@ export class OpenAIChatCompletionsProvider implements Provider {
1609
1735
  }
1610
1736
  break;
1611
1737
  case "tool_use":
1612
- toolCalls.push({
1613
- id: block.id,
1614
- type: "function",
1615
- function: {
1616
- name: block.name,
1617
- arguments: JSON.stringify(block.input),
1618
- },
1619
- });
1738
+ toolCalls.push(
1739
+ attachGoogleThoughtSignatureIfNeeded(
1740
+ {
1741
+ id: block.id,
1742
+ type: "function",
1743
+ function: {
1744
+ name: block.name,
1745
+ arguments: JSON.stringify(block.input),
1746
+ },
1747
+ },
1748
+ thoughtSignatureFromToolUseMetadata(block.providerMetadata),
1749
+ model,
1750
+ ),
1751
+ );
1620
1752
  break;
1621
1753
  case "server_tool_use":
1622
1754
  textParts.push(`[Web search: ${block.name}]`);
@@ -1635,6 +1767,7 @@ export class OpenAIChatCompletionsProvider implements Provider {
1635
1767
  };
1636
1768
 
1637
1769
  if (toolCalls.length > 0) {
1770
+ applyGemini3UnsignedToolCallFallback(toolCalls, model);
1638
1771
  result.tool_calls = toolCalls;
1639
1772
  }
1640
1773
 
@@ -14,10 +14,6 @@ export const CODEX_SUBSCRIPTION_MODEL_IDS: ReadonlySet<string> = new Set([
14
14
  "gpt-5.6-terra",
15
15
  "gpt-5.6-luna",
16
16
  "gpt-5.5",
17
- // OpenAI retires these two from ChatGPT sign-in on 2026-08-31; API-key
18
- // auth is unaffected.
19
- "gpt-5.4",
20
- "gpt-5.4-mini",
21
17
  ]);
22
18
 
23
19
  /** True when `model` is allowlisted for Codex subscription routing. */