@vellumai/assistant 0.10.2-dev.202606250318.5e7cfb0 → 0.10.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 (430) hide show
  1. package/bun.lock +0 -20
  2. package/docs/workspace-tools.md +33 -42
  3. package/eslint-rules/cli-no-daemon-internals.js +0 -6
  4. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +0 -31
  5. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +0 -44
  6. package/node_modules/@vellumai/gateway-client/src/index.ts +0 -14
  7. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +0 -17
  8. package/node_modules/@vellumai/service-contracts/package.json +0 -1
  9. package/node_modules/@vellumai/service-contracts/src/index.ts +0 -1
  10. package/openapi.yaml +0 -155
  11. package/package.json +1 -4
  12. package/scripts/test.sh +15 -36
  13. package/src/__tests__/actor-token-service.test.ts +14 -36
  14. package/src/__tests__/agent-loop-override-profile.test.ts +0 -1
  15. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -2
  16. package/src/__tests__/agent-wake-override-profile.test.ts +0 -2
  17. package/src/__tests__/annotate-activity-metadata.test.ts +0 -2
  18. package/src/__tests__/annotate-risk-options.test.ts +0 -2
  19. package/src/__tests__/approval-cascade.test.ts +0 -2
  20. package/src/__tests__/assistant-attachments.test.ts +0 -42
  21. package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
  22. package/src/__tests__/btw-routes.test.ts +0 -2
  23. package/src/__tests__/build-persisted-content.test.ts +0 -2
  24. package/src/__tests__/call-controller.test.ts +0 -19
  25. package/src/__tests__/channel-guardian.test.ts +58 -94
  26. package/src/__tests__/channel-reply-delivery.test.ts +0 -2
  27. package/src/__tests__/compaction-events.test.ts +0 -2
  28. package/src/__tests__/compaction.benchmark.test.ts +0 -2
  29. package/src/__tests__/compactor-call-site-logging.test.ts +0 -2
  30. package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -2
  31. package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -2
  32. package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -2
  33. package/src/__tests__/compactor-web-search-strip.test.ts +0 -2
  34. package/src/__tests__/config-loader-backfill.test.ts +10 -123
  35. package/src/__tests__/config-schema.test.ts +0 -1
  36. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -31
  37. package/src/__tests__/contacts-relay-reads.test.ts +15 -13
  38. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -2
  39. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +0 -2
  40. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +0 -2
  41. package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
  42. package/src/__tests__/conversation-agent-loop.test.ts +0 -134
  43. package/src/__tests__/conversation-analysis-routes.test.ts +0 -2
  44. package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -2
  45. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -2
  46. package/src/__tests__/conversation-history-web-search.test.ts +0 -2
  47. package/src/__tests__/conversation-load-history-repair.test.ts +0 -2
  48. package/src/__tests__/conversation-load-history-stripped.test.ts +0 -2
  49. package/src/__tests__/conversation-pairing.test.ts +0 -2
  50. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -2
  51. package/src/__tests__/conversation-process-callsite.test.ts +0 -2
  52. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -2
  53. package/src/__tests__/conversation-queue.test.ts +0 -91
  54. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -14
  55. package/src/__tests__/conversation-routes-slash-commands.test.ts +0 -14
  56. package/src/__tests__/conversation-slash-queue.test.ts +0 -2
  57. package/src/__tests__/conversation-slash-unknown.test.ts +0 -2
  58. package/src/__tests__/conversation-speed-override.test.ts +0 -2
  59. package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -29
  60. package/src/__tests__/conversation-title-service.test.ts +0 -2
  61. package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -47
  62. package/src/__tests__/conversation-usage.test.ts +0 -2
  63. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -2
  64. package/src/__tests__/conversation-workspace-injection.test.ts +0 -2
  65. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -2
  66. package/src/__tests__/credential-security-invariants.test.ts +1 -1
  67. package/src/__tests__/db-migration-rollback.test.ts +171 -205
  68. package/src/__tests__/db-test-helpers.ts +4 -5
  69. package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -4
  70. package/src/__tests__/disk-pressure-guard.test.ts +0 -41
  71. package/src/__tests__/dm-persistence.test.ts +0 -2
  72. package/src/__tests__/emit-signal-routing-intent.test.ts +5 -10
  73. package/src/__tests__/events-dev-bypass-actor.test.ts +1 -7
  74. package/src/__tests__/exploration-drift-hook.test.ts +2 -3
  75. package/src/__tests__/filing-service.test.ts +0 -2
  76. package/src/__tests__/guardian-binding-drift-heal.test.ts +10 -75
  77. package/src/__tests__/guardian-dispatch.test.ts +1 -95
  78. package/src/__tests__/guardian-outbound-http.test.ts +0 -13
  79. package/src/__tests__/heartbeat-disk-pressure.test.ts +0 -2
  80. package/src/__tests__/heartbeat-service.test.ts +0 -2
  81. package/src/__tests__/helpers/channel-test-adapter.ts +7 -1
  82. package/src/__tests__/host-app-control-routes.test.ts +30 -24
  83. package/src/__tests__/host-bash-routes.test.ts +41 -31
  84. package/src/__tests__/host-browser-routes.test.ts +32 -26
  85. package/src/__tests__/host-cu-routes-targeted.test.ts +33 -25
  86. package/src/__tests__/host-file-routes-targeted.test.ts +52 -40
  87. package/src/__tests__/host-transfer-routes-targeted.test.ts +43 -31
  88. package/src/__tests__/http-user-message-parity.test.ts +8 -290
  89. package/src/__tests__/inbound-invite-redemption.test.ts +0 -28
  90. package/src/__tests__/inbound-slack-persistence.test.ts +0 -2
  91. package/src/__tests__/invite-redemption-service.test.ts +0 -198
  92. package/src/__tests__/llm-context-normalization.test.ts +0 -105
  93. package/src/__tests__/llm-request-log-error-payload.test.ts +9 -71
  94. package/src/__tests__/llm-usage-store.test.ts +0 -25
  95. package/src/__tests__/mcp-health-check.test.ts +1 -2
  96. package/src/__tests__/media-stream-server-integration.test.ts +0 -127
  97. package/src/__tests__/memory-retrieval-hook.test.ts +0 -2
  98. package/src/__tests__/messaging-send-tool.test.ts +0 -2
  99. package/src/__tests__/migration-import-from-url.test.ts +2 -2
  100. package/src/__tests__/mtime-cache.test.ts +5 -146
  101. package/src/__tests__/native-web-search.test.ts +0 -2
  102. package/src/__tests__/non-member-access-request.test.ts +17 -189
  103. package/src/__tests__/notification-broadcaster.test.ts +0 -4
  104. package/src/__tests__/notification-decision-recipient-context.test.ts +32 -33
  105. package/src/__tests__/notification-deep-link.test.ts +0 -6
  106. package/src/__tests__/notification-guardian-path.test.ts +0 -19
  107. package/src/__tests__/openai-provider.test.ts +12 -22
  108. package/src/__tests__/openai-responses-provider.test.ts +2 -12
  109. package/src/__tests__/outbound-slack-persistence.test.ts +0 -2
  110. package/src/__tests__/pending-interactions-resolved-event.test.ts +4 -7
  111. package/src/__tests__/persistence-secret-redaction.test.ts +0 -2
  112. package/src/__tests__/plugin-bootstrap.test.ts +73 -3
  113. package/src/__tests__/plugin-route-contribution.test.ts +17 -4
  114. package/src/__tests__/plugin-tool-contribution.test.ts +18 -3
  115. package/src/__tests__/plugin-types.test.ts +2 -0
  116. package/src/__tests__/process-message-background-slack.test.ts +0 -2
  117. package/src/__tests__/process-message-display-content.test.ts +0 -2
  118. package/src/__tests__/provider-error-scenarios.test.ts +4 -5
  119. package/src/__tests__/provider-usage-tracking.test.ts +0 -39
  120. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -2
  121. package/src/__tests__/registry.test.ts +1 -4
  122. package/src/__tests__/relay-server.test.ts +25 -694
  123. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -0
  124. package/src/__tests__/secret-ingress-http.test.ts +0 -14
  125. package/src/__tests__/send-endpoint-busy.test.ts +8 -30
  126. package/src/__tests__/skills.test.ts +0 -44
  127. package/src/__tests__/slack-inbound-verification.test.ts +2 -47
  128. package/src/__tests__/stt-hints.test.ts +13 -44
  129. package/src/__tests__/subagent-detail.test.ts +0 -27
  130. package/src/__tests__/subagent-disposal.test.ts +0 -65
  131. package/src/__tests__/subagent-notify-parent.test.ts +0 -2
  132. package/src/__tests__/subagent-role-registry.test.ts +2 -7
  133. package/src/__tests__/subagent-spawn-tool-fork.test.ts +0 -2
  134. package/src/__tests__/subagent-tools.test.ts +0 -2
  135. package/src/__tests__/suggestion-routes.test.ts +0 -2
  136. package/src/__tests__/title-generate-hook.test.ts +0 -2
  137. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -2
  138. package/src/__tests__/tool-executor.test.ts +11 -16
  139. package/src/__tests__/tool-preview-lifecycle.test.ts +0 -2
  140. package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -2
  141. package/src/__tests__/tool-start-timestamp.test.ts +0 -2
  142. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +10 -10
  143. package/src/__tests__/twilio-routes.test.ts +0 -96
  144. package/src/__tests__/ui-file-upload-surface.test.ts +0 -86
  145. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  146. package/src/__tests__/voice-invite-redemption.test.ts +0 -33
  147. package/src/__tests__/web-search-backend-failure.test.ts +0 -2
  148. package/src/__tests__/workspace-migration-remove-hooks.test.ts +35 -14
  149. package/src/__tests__/workspace-tool-loader.test.ts +2 -195
  150. package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
  151. package/src/agent/loop.ts +0 -56
  152. package/src/api/index.ts +1 -19
  153. package/src/api/responses/llm-request-log-entry.ts +0 -29
  154. package/src/api/responses/subagent-detail.ts +0 -17
  155. package/src/api/surfaces.ts +3 -39
  156. package/src/approvals/guardian-request-resolvers.ts +11 -1
  157. package/src/calls/__tests__/relay-setup-router.test.ts +4 -262
  158. package/src/calls/call-domain.ts +3 -3
  159. package/src/calls/guardian-dispatch.ts +8 -10
  160. package/src/calls/inbound-trust-reader.ts +1 -17
  161. package/src/calls/media-stream-server.ts +0 -21
  162. package/src/calls/relay-server.ts +50 -167
  163. package/src/calls/relay-setup-router.ts +7 -37
  164. package/src/calls/relay-verification.ts +4 -4
  165. package/src/calls/stt-hints.ts +12 -9
  166. package/src/calls/twilio-routes.ts +4 -14
  167. package/src/channels/types.ts +20 -10
  168. package/src/cli/commands/__tests__/cache.test.ts +1 -8
  169. package/src/cli/commands/cache.ts +181 -194
  170. package/src/cli/commands/db/__tests__/repair.test.ts +5 -6
  171. package/src/cli/commands/db/status.ts +1 -37
  172. package/src/cli/commands/mcp.ts +218 -252
  173. package/src/cli/commands/memory/index.ts +0 -2
  174. package/src/cli/commands/plugins.ts +3 -75
  175. package/src/cli/lib/__tests__/install-from-github.test.ts +0 -102
  176. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +1 -160
  177. package/src/cli/lib/list-installed-plugins.ts +1 -179
  178. package/src/config/__tests__/sync-gated-profiles.test.ts +3 -11
  179. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +17 -27
  180. package/src/config/bundled-skills/contacts/tools/contact-search.ts +3 -13
  181. package/src/config/bundled-skills/subagent/SKILL.md +1 -1
  182. package/src/config/bundled-skills/subagent/TOOLS.json +1 -1
  183. package/src/config/feature-flag-registry.json +13 -5
  184. package/src/config/loader.ts +5 -38
  185. package/src/config/schemas/__tests__/memory-v3.test.ts +0 -1
  186. package/src/config/schemas/memory-lifecycle.ts +0 -12
  187. package/src/config/schemas/memory-v3.ts +0 -7
  188. package/src/config/schemas/memory.ts +0 -4
  189. package/src/config/schemas/timeouts.ts +0 -8
  190. package/src/config/seed-inference-profiles.ts +11 -21
  191. package/src/config/skills.ts +5 -27
  192. package/src/config/sync-gated-profiles.ts +13 -12
  193. package/src/contacts/contacts-write.ts +0 -3
  194. package/src/daemon/assistant-attachments.ts +4 -27
  195. package/src/daemon/conversation-agent-loop.ts +0 -28
  196. package/src/daemon/conversation-process.ts +16 -35
  197. package/src/daemon/conversation-surfaces.ts +38 -111
  198. package/src/daemon/conversation-tool-setup.ts +16 -50
  199. package/src/daemon/conversation.ts +1 -13
  200. package/src/daemon/disk-pressure-guard.ts +2 -12
  201. package/src/daemon/event-loop-watchdog.ts +1 -28
  202. package/src/daemon/external-plugins-bootstrap.ts +34 -4
  203. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -25
  204. package/src/daemon/handlers/config-a2a.ts +14 -6
  205. package/src/daemon/handlers/config-channels.ts +22 -78
  206. package/src/daemon/handlers/conversations.ts +0 -77
  207. package/src/daemon/lifecycle.ts +0 -4
  208. package/src/daemon/mcp-reload-service.ts +0 -10
  209. package/src/daemon/memory-v2-startup.test.ts +0 -72
  210. package/src/daemon/memory-v2-startup.ts +19 -87
  211. package/src/daemon/message-types/conversations.ts +0 -2
  212. package/src/daemon/message-types/surfaces.ts +12 -12
  213. package/src/daemon/server.ts +4 -0
  214. package/src/daemon/shutdown-handlers.ts +0 -20
  215. package/src/daemon/tool-setup-types.ts +0 -9
  216. package/src/daemon/workspace-tools-watcher.ts +328 -0
  217. package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
  218. package/src/ipc/assistant-server.ts +2 -2
  219. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
  220. package/src/mcp/client.ts +1 -15
  221. package/src/mcp/mcp-auth-orchestrator.ts +1 -6
  222. package/src/mcp/mcp-oauth-provider.ts +8 -19
  223. package/src/memory/__tests__/memory-retrospective-job.test.ts +0 -8
  224. package/src/memory/conversation-crud.ts +0 -38
  225. package/src/memory/db-connection.ts +3 -22
  226. package/src/memory/db-init.ts +502 -36
  227. package/src/memory/db-singleton.ts +4 -6
  228. package/src/memory/jobs-worker.ts +0 -58
  229. package/src/memory/llm-request-log-store.ts +1 -26
  230. package/src/memory/llm-usage-store.ts +20 -48
  231. package/src/memory/memory-retrospective-job.ts +8 -9
  232. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +56 -130
  233. package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
  234. package/src/memory/migrations/registry.ts +573 -0
  235. package/src/memory/migrations/run-migrations.ts +6 -90
  236. package/src/memory/migrations/validate-migration-state.ts +66 -101
  237. package/src/memory/schema/conversations.ts +0 -9
  238. package/src/memory/schema/infrastructure.ts +0 -20
  239. package/src/memory/v2/__tests__/cli-command-store.test.ts +0 -25
  240. package/src/memory/v2/__tests__/skill-store.test.ts +0 -80
  241. package/src/memory/v2/cli-command-store.ts +38 -75
  242. package/src/memory/v2/prompts/consolidation.ts +82 -13
  243. package/src/memory/v2/prompts/router.ts +93 -21
  244. package/src/memory/v2/skill-store.ts +31 -68
  245. package/src/notifications/__tests__/broadcaster.test.ts +8 -16
  246. package/src/notifications/__tests__/decision-engine.test.ts +9 -78
  247. package/src/notifications/broadcaster.ts +1 -8
  248. package/src/notifications/decision-engine.ts +7 -15
  249. package/src/notifications/destination-resolver.ts +24 -68
  250. package/src/notifications/emit-signal.ts +14 -39
  251. package/src/permissions/question-prompter.test.ts +1 -1
  252. package/src/permissions/question-prompter.ts +4 -7
  253. package/src/plugin-api/index.ts +6 -6
  254. package/src/plugin-api/types.ts +5 -3
  255. package/src/plugin-api/vision-support.test.ts +4 -28
  256. package/src/plugin-api/vision-support.ts +31 -66
  257. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -161
  258. package/src/plugins/defaults/advisor/consult.ts +6 -110
  259. package/src/plugins/defaults/advisor/steering.ts +2 -14
  260. package/src/plugins/defaults/advisor/tools/advisor.ts +5 -32
  261. package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +1 -2
  262. package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +7 -47
  263. package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +11 -10
  264. package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +20 -12
  265. package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +11 -42
  266. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +3 -33
  267. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +4 -48
  268. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +8 -4
  269. package/src/plugins/defaults/memory-v3-shadow/injector.ts +15 -43
  270. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +2 -11
  271. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +13 -77
  272. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +11 -12
  273. package/src/plugins/mtime-cache.ts +291 -76
  274. package/src/plugins/pipeline.ts +13 -111
  275. package/src/plugins/types.ts +2 -0
  276. package/src/providers/anthropic/client.ts +0 -5
  277. package/src/providers/call-site-routing.ts +0 -4
  278. package/src/providers/model-catalog.ts +0 -16
  279. package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
  280. package/src/providers/openai/chat-completions-provider.ts +83 -37
  281. package/src/providers/openai/responses-provider.ts +46 -50
  282. package/src/providers/openrouter/client.ts +0 -5
  283. package/src/providers/provider-send-message.ts +0 -4
  284. package/src/providers/ratelimit.ts +0 -4
  285. package/src/providers/retry.ts +0 -4
  286. package/src/providers/types.ts +0 -9
  287. package/src/providers/usage-tracking.ts +0 -4
  288. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +3 -335
  289. package/src/runtime/access-request-helper.ts +39 -19
  290. package/src/runtime/actor-trust-resolver.ts +2 -2
  291. package/src/runtime/assistant-event-hub.ts +1 -1
  292. package/src/runtime/assistant-stream-state.ts +2 -9
  293. package/src/runtime/auth/require-bound-guardian.ts +11 -21
  294. package/src/runtime/channel-verification-service.ts +31 -56
  295. package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
  296. package/src/runtime/guardian-vellum-migration.ts +7 -66
  297. package/src/runtime/invite-redemption-service.ts +187 -198
  298. package/src/runtime/local-actor-identity.ts +11 -76
  299. package/src/runtime/pending-interactions.ts +1 -11
  300. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +5 -56
  301. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
  302. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +0 -187
  303. package/src/runtime/routes/browser-routes.ts +1 -1
  304. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -13
  305. package/src/runtime/routes/channel-verification-routes.ts +3 -3
  306. package/src/runtime/routes/contact-routes.ts +32 -8
  307. package/src/runtime/routes/conversation-cli-routes.ts +5 -4
  308. package/src/runtime/routes/conversation-list-routes.ts +7 -4
  309. package/src/runtime/routes/conversation-query-routes.ts +0 -72
  310. package/src/runtime/routes/conversation-routes.ts +85 -84
  311. package/src/runtime/routes/events-routes.ts +2 -2
  312. package/src/runtime/routes/global-search-routes.ts +1 -3
  313. package/src/runtime/routes/guardian-action-routes.ts +5 -4
  314. package/src/runtime/routes/host-app-control-routes.ts +4 -5
  315. package/src/runtime/routes/host-bash-routes.ts +4 -5
  316. package/src/runtime/routes/host-browser-routes.ts +11 -9
  317. package/src/runtime/routes/host-cu-routes.ts +4 -5
  318. package/src/runtime/routes/host-file-routes.ts +4 -5
  319. package/src/runtime/routes/host-transfer-routes.ts +6 -6
  320. package/src/runtime/routes/http-adapter.ts +1 -1
  321. package/src/runtime/routes/identity-routes.ts +2 -3
  322. package/src/runtime/routes/inbound-message-handler.ts +5 -5
  323. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +5 -97
  324. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +49 -61
  325. package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -16
  326. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
  327. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +8 -21
  328. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +3 -14
  329. package/src/runtime/routes/index.ts +0 -2
  330. package/src/runtime/routes/llm-context-normalization.ts +0 -83
  331. package/src/runtime/routes/mcp-auth-routes.ts +19 -171
  332. package/src/runtime/routes/migration-rollback-routes.ts +3 -4
  333. package/src/runtime/routes/migration-routes.ts +1 -4
  334. package/src/runtime/routes/subagents-routes.ts +0 -5
  335. package/src/runtime/routes/surface-action-routes.ts +56 -42
  336. package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -1
  337. package/src/runtime/services/conversation-serializer.ts +9 -7
  338. package/src/runtime/tool-grant-request-helper.ts +3 -3
  339. package/src/runtime/trust-verdict-consumer.ts +9 -85
  340. package/src/runtime/verification-outbound-actions.ts +18 -18
  341. package/src/signals/user-message.ts +0 -16
  342. package/src/subagent/manager.ts +0 -9
  343. package/src/subagent/types.ts +3 -3
  344. package/src/telemetry/types.ts +1 -34
  345. package/src/telemetry/usage-telemetry-reporter.test.ts +2 -3
  346. package/src/telemetry/usage-telemetry-reporter.ts +3 -87
  347. package/src/tools/ask-question/ask-question-tool.test.ts +0 -29
  348. package/src/tools/ask-question/ask-question-tool.ts +0 -13
  349. package/src/tools/executor.ts +4 -4
  350. package/src/tools/registry.ts +0 -18
  351. package/src/tools/shared/filesystem/path-policy.ts +5 -12
  352. package/src/tools/tool-approval-handler.ts +1 -1
  353. package/src/tools/tool-defaults.ts +2 -9
  354. package/src/tools/tool-manifest.ts +0 -3
  355. package/src/tools/types.ts +2 -17
  356. package/src/tools/workspace-tools/loader.ts +244 -348
  357. package/src/util/errors.ts +1 -26
  358. package/src/util/platform.ts +0 -5
  359. package/src/workflows/library.test.ts +0 -140
  360. package/src/workflows/library.ts +28 -82
  361. package/src/workspace/migrations/017-seed-persona-dirs.ts +34 -3
  362. package/src/workspace/migrations/019-scope-journal-to-guardian.ts +24 -3
  363. package/src/workspace/migrations/048-remove-workspace-hooks.ts +66 -14
  364. package/src/workspace/migrations/registry.ts +0 -2
  365. package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +0 -91
  366. package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +0 -48
  367. package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +0 -28
  368. package/node_modules/@vellumai/service-contracts/src/channels.ts +0 -41
  369. package/src/__tests__/code-search-tool.test.ts +0 -585
  370. package/src/__tests__/guardian-expiry-notifier.test.ts +0 -282
  371. package/src/__tests__/mcp-config-secret-boundary.test.ts +0 -390
  372. package/src/__tests__/plugin-pipeline.test.ts +0 -96
  373. package/src/__tests__/sse-actor-principal-guardian-source.test.ts +0 -102
  374. package/src/__tests__/steer-on-enqueue-question.test.ts +0 -181
  375. package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +0 -208
  376. package/src/agent/loop-exclusive-tool.test.ts +0 -150
  377. package/src/api/constants/sse-replay.ts +0 -41
  378. package/src/api/events/conversation-notice.ts +0 -26
  379. package/src/approvals/guardian-channel-delivery.ts +0 -30
  380. package/src/approvals/guardian-expiry-notifier.ts +0 -148
  381. package/src/cli/commands/memory/__tests__/worker.test.ts +0 -302
  382. package/src/cli/commands/memory/worker.ts +0 -175
  383. package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -143
  384. package/src/config/prune-seeded-callsite-defaults.ts +0 -110
  385. package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -129
  386. package/src/contacts/__tests__/guardian-delivery-reader.test.ts +0 -312
  387. package/src/contacts/__tests__/member-write-relay.test.ts +0 -202
  388. package/src/contacts/guardian-delivery-reader.ts +0 -223
  389. package/src/contacts/member-write-relay.ts +0 -189
  390. package/src/daemon/conversation-notices.ts +0 -60
  391. package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -225
  392. package/src/hooks/hook-loader.ts +0 -341
  393. package/src/mcp/mcp-header-store.ts +0 -134
  394. package/src/memory/__tests__/301-create-watchdog-events.test.ts +0 -110
  395. package/src/memory/__tests__/prompt-override.test.ts +0 -192
  396. package/src/memory/__tests__/watchdog-events-store.test.ts +0 -161
  397. package/src/memory/migrations/300-add-processing-started-at.ts +0 -30
  398. package/src/memory/migrations/301-create-watchdog-events.ts +0 -45
  399. package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +0 -224
  400. package/src/memory/prompt-override.ts +0 -129
  401. package/src/memory/steps.ts +0 -573
  402. package/src/memory/watchdog-events-store.ts +0 -87
  403. package/src/memory/worker-control.ts +0 -118
  404. package/src/memory/worker-process.ts +0 -72
  405. package/src/notifications/__tests__/connected-channels.test.ts +0 -114
  406. package/src/notifications/__tests__/destination-resolver.test.ts +0 -256
  407. package/src/onboarding/checkin-event.test.ts +0 -222
  408. package/src/onboarding/checkin-event.ts +0 -321
  409. package/src/onboarding/schedule-checkin.ts +0 -190
  410. package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +0 -106
  411. package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +0 -60
  412. package/src/plugins/defaults/advisor/context-pack.ts +0 -288
  413. package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +0 -146
  414. package/src/plugins/surface-import.ts +0 -121
  415. package/src/providers/openai/__tests__/api-error-normalization.test.ts +0 -321
  416. package/src/providers/openai/api-error-normalization.ts +0 -270
  417. package/src/runtime/__tests__/channel-verification-service.test.ts +0 -133
  418. package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -181
  419. package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +0 -66
  420. package/src/runtime/__tests__/local-principal-trust.test.ts +0 -164
  421. package/src/runtime/anchored-guardian.test.ts +0 -156
  422. package/src/runtime/anchored-guardian.ts +0 -135
  423. package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +0 -99
  424. package/src/runtime/local-principal-trust.ts +0 -52
  425. package/src/runtime/routes/__tests__/contact-routes.test.ts +0 -212
  426. package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -93
  427. package/src/runtime/routes/onboarding-checkin-routes.ts +0 -86
  428. package/src/tools/filesystem/search.ts +0 -543
  429. package/src/util/telemetry-db-path.ts +0 -24
  430. package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +0 -134
@@ -786,11 +786,6 @@ export class AnthropicProvider implements Provider {
786
786
  this.useNativeWebSearch = options.useNativeWebSearch ?? false;
787
787
  }
788
788
 
789
- /** See {@link Provider.supportsNativeWebSearch}. */
790
- get supportsNativeWebSearch(): boolean {
791
- return this.useNativeWebSearch;
792
- }
793
-
794
789
  async sendMessage(
795
790
  messages: Message[],
796
791
  options?: SendMessageOptions,
@@ -43,9 +43,6 @@ import type {
43
43
 
44
44
  export class CallSiteRoutingProvider implements Provider {
45
45
  public readonly tokenEstimationProvider?: string;
46
- // Forward native web-search capability so it survives the wrapper chain
47
- // (callers like the advisor consult gate on it). Fixed at construction.
48
- public readonly supportsNativeWebSearch?: boolean;
49
46
 
50
47
  // Per-call async context that tracks which provider is currently executing.
51
48
  // Using AsyncLocalStorage instead of a plain instance field means concurrent
@@ -97,7 +94,6 @@ export class CallSiteRoutingProvider implements Provider {
97
94
  ) => Promise<Provider | null>,
98
95
  ) {
99
96
  this.tokenEstimationProvider = defaultProvider.tokenEstimationProvider;
100
- this.supportsNativeWebSearch = defaultProvider.supportsNativeWebSearch;
101
97
  if (defaultProvider.countInputTokens) {
102
98
  this.countInputTokens =
103
99
  defaultProvider.countInputTokens.bind(defaultProvider);
@@ -760,22 +760,6 @@ const RAW_PROVIDER_CATALOG: ProviderCatalogEntry[] = [
760
760
  maxEffort: "max",
761
761
  pricing: { inputPer1mTokens: 1.74, outputPer1mTokens: 3.48 },
762
762
  },
763
- {
764
- id: "accounts/fireworks/models/deepseek-v4-flash",
765
- displayName: "DeepSeek V4 Flash",
766
- contextWindowTokens: 1040000,
767
- maxOutputTokens: 131072,
768
- supportsThinking: true,
769
- supportsCaching: true,
770
- supportsVision: false,
771
- supportsToolUse: true,
772
- maxEffort: "max",
773
- pricing: {
774
- inputPer1mTokens: 0.14,
775
- outputPer1mTokens: 0.28,
776
- cacheReadPer1mTokens: 0.03,
777
- },
778
- },
779
763
  ],
780
764
  defaultModel: "accounts/fireworks/models/kimi-k2p5",
781
765
  apiKeyUrl: "https://fireworks.ai/account/api-keys",
@@ -0,0 +1,120 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import OpenAI from "openai";
4
+
5
+ import { extractApiErrorDetail } from "../chat-completions-provider.js";
6
+
7
+ /**
8
+ * Construct a real `OpenAI.APIError` so production code paths that use
9
+ * `instanceof OpenAI.APIError` and SDK-defined getters keep matching.
10
+ */
11
+ function buildApiError(
12
+ status: number,
13
+ body: unknown,
14
+ headers?: Headers,
15
+ ): InstanceType<typeof OpenAI.APIError> {
16
+ return new OpenAI.APIError(
17
+ status,
18
+ body as Record<string, unknown>,
19
+ undefined,
20
+ headers ?? new Headers(),
21
+ );
22
+ }
23
+
24
+ describe("extractApiErrorDetail", () => {
25
+ test("serializes a structured body so logs show the upstream error", () => {
26
+ // This is the canonical OpenRouter shape that motivated the helper:
27
+ // the SDK's `error.message` collapses to "400 Provider returned error"
28
+ // and the real detail lives nested under `error.metadata.raw`.
29
+ const err = buildApiError(400, {
30
+ error: {
31
+ code: 400,
32
+ message: "Provider returned error",
33
+ metadata: {
34
+ raw: "messages.4: tool_use_id must reference a prior tool_use block",
35
+ provider_name: "Anthropic",
36
+ },
37
+ },
38
+ });
39
+ const { detail, requestId } = extractApiErrorDetail(err);
40
+ expect(detail).toContain("Provider returned error");
41
+ expect(detail).toContain("tool_use_id must reference a prior tool_use");
42
+ expect(detail).toContain("Anthropic");
43
+ expect(requestId).toBeUndefined();
44
+ });
45
+
46
+ test("surfaces the upstream request id when present in headers", () => {
47
+ const headers = new Headers({ "x-request-id": "req_abc123" });
48
+ const err = buildApiError(
49
+ 400,
50
+ { error: { message: "Provider returned error" } },
51
+ headers,
52
+ );
53
+ const { requestId } = extractApiErrorDetail(err);
54
+ expect(requestId).toBe("req_abc123");
55
+ });
56
+
57
+ test("falls back to x-openrouter-request-id when x-request-id is absent", () => {
58
+ const headers = new Headers({
59
+ "x-openrouter-request-id": "gen-or-xyz",
60
+ });
61
+ const err = buildApiError(
62
+ 400,
63
+ { error: { message: "Provider returned error" } },
64
+ headers,
65
+ );
66
+ const { requestId } = extractApiErrorDetail(err);
67
+ expect(requestId).toBe("gen-or-xyz");
68
+ });
69
+
70
+ test("returns empty detail when the body is missing", () => {
71
+ // The SDK constructs an APIError even when the upstream response had
72
+ // no JSON body (e.g. network-layer 5xx). The helper must degrade
73
+ // gracefully rather than emit `undefined` or `null` strings.
74
+ const err = buildApiError(500, undefined);
75
+ const { detail, requestId } = extractApiErrorDetail(err);
76
+ expect(detail).toBe("");
77
+ expect(requestId).toBeUndefined();
78
+ });
79
+
80
+ test("returns empty detail when the body serializes to an empty object", () => {
81
+ // `{}` carries zero signal and just adds noise to log lines.
82
+ const err = buildApiError(429, {});
83
+ const { detail } = extractApiErrorDetail(err);
84
+ expect(detail).toBe("");
85
+ });
86
+
87
+ test("truncates very long bodies with an ellipsis", () => {
88
+ const huge = "X".repeat(5000);
89
+ const err = buildApiError(400, { error: { message: huge } });
90
+ const { detail } = extractApiErrorDetail(err);
91
+ // Cap is 2000 chars; the helper appends a single-char ellipsis when truncating.
92
+ expect(detail.length).toBeLessThanOrEqual(2001);
93
+ expect(detail.endsWith("…")).toBe(true);
94
+ });
95
+
96
+ test("preserves string bodies verbatim (no double-encoding)", () => {
97
+ // Some providers return a non-JSON body (HTML error page, plain text).
98
+ // The SDK stores it on `error.error` as a string in that case.
99
+ const err = buildApiError(502, "upstream timeout");
100
+ const { detail } = extractApiErrorDetail(err);
101
+ expect(detail).toBe("upstream timeout");
102
+ });
103
+
104
+ test("returns empty detail when JSON.stringify throws (cyclic body)", () => {
105
+ // Pathological body — should not propagate the TypeError to callers.
106
+ // OpenAI's `APIError` constructor itself JSON.stringifies the body to
107
+ // build its own `.message`, so we can't get to this branch via the SDK
108
+ // constructor; build a structural stand-in instead.
109
+ const cyclic: Record<string, unknown> = {};
110
+ cyclic.self = cyclic;
111
+ const stub = {
112
+ status: 400,
113
+ message: "synthetic",
114
+ headers: new Headers(),
115
+ error: cyclic,
116
+ } as unknown as InstanceType<typeof OpenAI.APIError>;
117
+ const { detail } = extractApiErrorDetail(stub);
118
+ expect(detail).toBe("");
119
+ });
120
+ });
@@ -22,11 +22,6 @@ import {
22
22
  isUnparseableToolArgs,
23
23
  wrapUnparseableToolArgs,
24
24
  } from "../unparseable-tool-args.js";
25
- import {
26
- captureRawErrorBodyFetch,
27
- formatNormalizedOpenAIAPIError,
28
- normalizeOpenAIAPIError,
29
- } from "./api-error-normalization.js";
30
25
  import {
31
26
  coerceObjectParamsToJsonString,
32
27
  decodeCoercedObjectArgs,
@@ -48,7 +43,6 @@ import {
48
43
  */
49
44
  export function detectOpenAICompatibleContextOverflow(
50
45
  error: InstanceType<typeof OpenAI.APIError>,
51
- extraMessage?: string,
52
46
  ): { actualTokens?: number; maxTokens?: number } | null {
53
47
  // OpenAI-compatible providers use 400 (most) or 413 (rarer payload-too-large).
54
48
  const status = error.status;
@@ -59,9 +53,7 @@ export function detectOpenAICompatibleContextOverflow(
59
53
  /context_length_exceeded|context_window_exceeded|input_too_long|prompt_too_long/i.test(
60
54
  code,
61
55
  );
62
- // Include the normalized upstream message: the SDK's `error.message` is often
63
- // generic ("400 Provider returned error") while the real signal is in the body.
64
- const message = `${error.message ?? ""} ${extraMessage ?? ""}`;
56
+ const message = error.message ?? "";
65
57
  const messageMatches =
66
58
  /context.?length.?exceeded|context.?window.?exceeded|prompt.?is.?too.?long|prompt_too_long|input.?too.?long|too.?many.?(?:input.?)?tokens|maximum.?context/i.test(
67
59
  message,
@@ -71,6 +63,53 @@ export function detectOpenAICompatibleContextOverflow(
71
63
  return extractOverflowTokensFromMessage(message);
72
64
  }
73
65
 
66
+ /**
67
+ * Build the human-readable error string surfaced from an
68
+ * `OpenAI.APIError`. The SDK's `error.message` is typically a one-line
69
+ * summary like `"400 Provider returned error"` — useless when the
70
+ * upstream is OpenRouter (which wraps the real downstream error on
71
+ * `error.error.metadata.raw`) or any provider that returns nested
72
+ * structured details.
73
+ *
74
+ * Returns `{ detail, requestId }` where `detail` includes the JSON body
75
+ * (truncated) and `requestId` is the upstream correlation header when
76
+ * present. Callers fold these into the thrown `ProviderError` so log
77
+ * lines actually identify the failure without re-running the request.
78
+ *
79
+ * Exported for tests.
80
+ */
81
+ export function extractApiErrorDetail(
82
+ error: InstanceType<typeof OpenAI.APIError>,
83
+ ): { detail: string; requestId: string | undefined } {
84
+ const body = (error as { error?: unknown }).error;
85
+ let detail = "";
86
+ if (body !== undefined && body !== null) {
87
+ try {
88
+ const serialized = typeof body === "string" ? body : JSON.stringify(body);
89
+ if (serialized && serialized !== "{}") {
90
+ detail =
91
+ serialized.length > MAX_API_ERROR_DETAIL_CHARS
92
+ ? `${serialized.slice(0, MAX_API_ERROR_DETAIL_CHARS)}…`
93
+ : serialized;
94
+ }
95
+ } catch {
96
+ // Body had a cycle or threw on toJSON — fall through with empty detail.
97
+ }
98
+ }
99
+ const requestId = readHeader(error.headers, [
100
+ "x-request-id",
101
+ "x-openrouter-request-id",
102
+ "openai-request-id",
103
+ "x-amzn-requestid",
104
+ ]);
105
+ return { detail, requestId };
106
+ }
107
+
108
+ /** Cap on the inline-rendered body to keep log lines readable while still
109
+ * surfacing the meaningful upstream payload. Tuned to comfortably hold
110
+ * OpenRouter's `error.metadata.raw` strings, which are typically <1KB. */
111
+ const MAX_API_ERROR_DETAIL_CHARS = 2000;
112
+
74
113
  const VISION_NOT_SUPPORTED_PATTERNS = [
75
114
  /no endpoints found that support image input/i,
76
115
  /does not support image/i,
@@ -82,9 +121,8 @@ const VISION_NOT_SUPPORTED_PATTERNS = [
82
121
 
83
122
  export function detectVisionNotSupported(
84
123
  error: InstanceType<typeof OpenAI.APIError>,
85
- extraMessage?: string,
86
124
  ): boolean {
87
- const haystack = `${error.message} ${extraMessage ?? ""} ${JSON.stringify((error as { error?: unknown }).error ?? "")}`;
125
+ const haystack = `${error.message} ${JSON.stringify((error as { error?: unknown }).error ?? "")}`;
88
126
  return VISION_NOT_SUPPORTED_PATTERNS.some((re) => re.test(haystack));
89
127
  }
90
128
 
@@ -108,6 +146,34 @@ export function detectVisionNotSupported(
108
146
  */
109
147
  export const EMPTY_ASSISTANT_TURN_PLACEHOLDER = PLACEHOLDER_EMPTY_TURN.slice(1);
110
148
 
149
+ /**
150
+ * Read the first matching header from an SDK error's headers object,
151
+ * tolerating both Map-like (`Headers.get()`) and plain-object shapes.
152
+ * Mirrors the shape-tolerance already in `extractRetryAfterMs`.
153
+ */
154
+ function readHeader(
155
+ headers: unknown,
156
+ names: readonly string[],
157
+ ): string | undefined {
158
+ if (!headers) return undefined;
159
+ const getter =
160
+ typeof (headers as { get?: unknown }).get === "function"
161
+ ? (headers as { get(name: string): string | null }).get.bind(headers)
162
+ : undefined;
163
+ for (const name of names) {
164
+ let value: string | null | undefined;
165
+ if (getter) {
166
+ value = getter(name);
167
+ } else if (typeof headers === "object") {
168
+ const record = headers as Record<string, unknown>;
169
+ const raw = record[name] ?? record[name.toLowerCase()];
170
+ value = typeof raw === "string" ? raw : undefined;
171
+ }
172
+ if (typeof value === "string" && value.length > 0) return value;
173
+ }
174
+ return undefined;
175
+ }
176
+
111
177
  export interface OpenAIChatCompletionsProviderOptions {
112
178
  baseURL?: string;
113
179
  providerName?: string;
@@ -276,8 +342,6 @@ export class OpenAIChatCompletionsProvider implements Provider {
276
342
  apiKey,
277
343
  baseURL: options.baseURL,
278
344
  timeout: sdkTimeoutMs,
279
- // Capture the raw non-2xx body before the SDK parses (and drops) it.
280
- fetch: captureRawErrorBodyFetch,
281
345
  });
282
346
  this.model = model;
283
347
  this.extraCreateParams = options.extraCreateParams ?? {};
@@ -699,16 +763,11 @@ export class OpenAIChatCompletionsProvider implements Provider {
699
763
  ? signal.reason
700
764
  : undefined;
701
765
  if (error instanceof OpenAI.APIError) {
702
- const normalized = normalizeOpenAIAPIError(error);
703
- const formattedMessage = formatNormalizedOpenAIAPIError(
704
- this.providerLabel,
705
- error.status,
706
- normalized,
707
- );
708
- const overflow = detectOpenAICompatibleContextOverflow(
709
- error,
710
- normalized.message,
711
- );
766
+ const { detail, requestId } = extractApiErrorDetail(error);
767
+ const detailSuffix = detail ? ` ${detail}` : "";
768
+ const requestIdSuffix = requestId ? ` [request_id=${requestId}]` : "";
769
+ const formattedMessage = `${this.providerLabel} API error (${error.status}): ${error.message}${detailSuffix}${requestIdSuffix}`;
770
+ const overflow = detectOpenAICompatibleContextOverflow(error);
712
771
  if (overflow) {
713
772
  throw new ContextOverflowError(formattedMessage, this.name, {
714
773
  actualTokens: overflow.actualTokens,
@@ -717,7 +776,7 @@ export class OpenAIChatCompletionsProvider implements Provider {
717
776
  cause: error,
718
777
  });
719
778
  }
720
- if (detectVisionNotSupported(error, normalized.message)) {
779
+ if (detectVisionNotSupported(error)) {
721
780
  const model = modelOverride ?? this.model;
722
781
  throw new ProviderError(
723
782
  `This model (${model}) doesn't support image input. Remove the image or switch to a vision-capable model.`,
@@ -730,23 +789,10 @@ export class OpenAIChatCompletionsProvider implements Provider {
730
789
  const errorOptions: {
731
790
  retryAfterMs?: number;
732
791
  abortReason?: unknown;
733
- apiErrorCode?: string;
734
- apiErrorType?: string;
735
- apiErrorParam?: string;
736
- requestId?: string;
737
- rawBody?: string;
738
792
  } = {};
739
793
  if (retryAfterMs !== undefined)
740
794
  errorOptions.retryAfterMs = retryAfterMs;
741
795
  if (abortReason) errorOptions.abortReason = abortReason;
742
- if (normalized.apiErrorCode)
743
- errorOptions.apiErrorCode = normalized.apiErrorCode;
744
- if (normalized.apiErrorType)
745
- errorOptions.apiErrorType = normalized.apiErrorType;
746
- if (normalized.apiErrorParam)
747
- errorOptions.apiErrorParam = normalized.apiErrorParam;
748
- if (normalized.requestId) errorOptions.requestId = normalized.requestId;
749
- if (normalized.rawBody) errorOptions.rawBody = normalized.rawBody;
750
796
  throw new ProviderError(
751
797
  formattedMessage,
752
798
  this.name,
@@ -16,11 +16,6 @@ import type {
16
16
  } from "../types.js";
17
17
  import { ContextOverflowError } from "../types.js";
18
18
  import { wrapUnparseableToolArgs } from "../unparseable-tool-args.js";
19
- import {
20
- captureRawErrorBodyFetch,
21
- formatNormalizedOpenAIAPIError,
22
- normalizeOpenAIAPIError,
23
- } from "./api-error-normalization.js";
24
19
  import { detectOpenAICompatibleContextOverflow } from "./chat-completions-provider.js";
25
20
 
26
21
  const log = getLogger("openai-responses");
@@ -153,6 +148,7 @@ export class OpenAIResponsesProvider implements Provider {
153
148
  private streamTimeoutMs: number;
154
149
  private useNativeWebSearch: boolean;
155
150
  private codexSubscription: boolean;
151
+ private lastCodexErrorBody: string | undefined;
156
152
 
157
153
  constructor(
158
154
  apiKey: string,
@@ -172,18 +168,32 @@ export class OpenAIResponsesProvider implements Provider {
172
168
  ? "https://chatgpt.com/backend-api/codex"
173
169
  : options.baseURL,
174
170
  timeout: sdkTimeoutMs,
175
- // Capture the raw non-2xx body before the SDK parses (and drops) it.
176
- fetch: captureRawErrorBodyFetch,
171
+ ...(this.codexSubscription
172
+ ? {
173
+ fetch: async (url: RequestInfo | URL, init?: RequestInit) => {
174
+ const res = await globalThis.fetch(url, init);
175
+ if (!res.ok) {
176
+ const body = await res.text();
177
+ this.lastCodexErrorBody = body;
178
+ log.warn(
179
+ { status: res.status, body, url: String(url) },
180
+ "Codex endpoint raw error response",
181
+ );
182
+ return new Response(body, {
183
+ status: res.status,
184
+ statusText: res.statusText,
185
+ headers: res.headers,
186
+ });
187
+ }
188
+ return res;
189
+ },
190
+ }
191
+ : {}),
177
192
  });
178
193
  this.model = model;
179
194
  this.useNativeWebSearch = options.useNativeWebSearch ?? false;
180
195
  }
181
196
 
182
- /** See {@link Provider.supportsNativeWebSearch}. */
183
- get supportsNativeWebSearch(): boolean {
184
- return this.useNativeWebSearch;
185
- }
186
-
187
197
  async sendMessage(
188
198
  messages: Message[],
189
199
  options?: SendMessageOptions,
@@ -500,57 +510,43 @@ export class OpenAIResponsesProvider implements Provider {
500
510
  ? signal.reason
501
511
  : undefined;
502
512
  if (error instanceof OpenAI.APIError) {
503
- const normalized = normalizeOpenAIAPIError(error);
504
- if (this.codexSubscription) {
505
- log.warn(
513
+ const overflow = detectOpenAICompatibleContextOverflow(error);
514
+ if (overflow) {
515
+ throw new ContextOverflowError(
516
+ `${this.providerLabel} API error (${error.status}): ${error.message}`,
517
+ this.name,
506
518
  {
507
- status: error.status,
508
- message: normalized.message,
509
- requestId: normalized.requestId,
519
+ actualTokens: overflow.actualTokens,
520
+ maxTokens: overflow.maxTokens,
521
+ statusCode: error.status,
522
+ cause: error,
510
523
  },
511
- "Codex endpoint raw error response",
512
524
  );
513
525
  }
514
- const formattedMessage = formatNormalizedOpenAIAPIError(
515
- this.providerLabel,
516
- error.status,
517
- normalized,
518
- );
519
- const overflow = detectOpenAICompatibleContextOverflow(
520
- error,
521
- normalized.message,
522
- );
523
- if (overflow) {
524
- throw new ContextOverflowError(formattedMessage, this.name, {
525
- actualTokens: overflow.actualTokens,
526
- maxTokens: overflow.maxTokens,
527
- statusCode: error.status,
528
- cause: error,
529
- });
530
- }
531
526
  const retryAfterMs = extractRetryAfterMs(error.headers);
532
527
  const errorOptions: {
533
528
  retryAfterMs?: number;
534
529
  abortReason?: unknown;
535
- apiErrorCode?: string;
536
- apiErrorType?: string;
537
- apiErrorParam?: string;
538
- requestId?: string;
539
- rawBody?: string;
540
530
  } = {};
541
531
  if (retryAfterMs !== undefined)
542
532
  errorOptions.retryAfterMs = retryAfterMs;
543
533
  if (abortReason) errorOptions.abortReason = abortReason;
544
- if (normalized.apiErrorCode)
545
- errorOptions.apiErrorCode = normalized.apiErrorCode;
546
- if (normalized.apiErrorType)
547
- errorOptions.apiErrorType = normalized.apiErrorType;
548
- if (normalized.apiErrorParam)
549
- errorOptions.apiErrorParam = normalized.apiErrorParam;
550
- if (normalized.requestId) errorOptions.requestId = normalized.requestId;
551
- if (normalized.rawBody) errorOptions.rawBody = normalized.rawBody;
534
+ let errorDetail = error.message;
535
+ if (this.lastCodexErrorBody) {
536
+ try {
537
+ const parsed = JSON.parse(this.lastCodexErrorBody);
538
+ if (parsed.detail) errorDetail = parsed.detail;
539
+ } catch {
540
+ errorDetail = this.lastCodexErrorBody.slice(0, 200);
541
+ }
542
+ this.lastCodexErrorBody = undefined;
543
+ }
544
+ const extras = [error.code, error.type, error.param]
545
+ .filter(Boolean)
546
+ .join(", ");
547
+ const extraSuffix = extras ? ` [${extras}]` : "";
552
548
  throw new ProviderError(
553
- formattedMessage,
549
+ `${this.providerLabel} API error (${error.status}): ${errorDetail}${extraSuffix}`,
554
550
  this.name,
555
551
  error.status,
556
552
  Object.keys(errorOptions).length > 0 ? errorOptions : undefined,
@@ -140,11 +140,6 @@ export class OpenRouterProvider extends OpenAIChatCompletionsProvider {
140
140
  return isAnthropicModel(this.defaultModel) ? "anthropic" : this.name;
141
141
  }
142
142
 
143
- /** See {@link Provider.supportsNativeWebSearch}. Set per model at construction. */
144
- get supportsNativeWebSearch(): boolean {
145
- return this.useNativeWebSearch;
146
- }
147
-
148
143
  override async sendMessage(
149
144
  messages: Message[],
150
145
  options?: SendMessageOptions,
@@ -43,9 +43,6 @@ let lazyInitPromise: Promise<void> | null = null;
43
43
  export class CallSiteConfiguredProvider implements Provider {
44
44
  public readonly name: string;
45
45
  public readonly tokenEstimationProvider?: string;
46
- // Forward native web-search capability so it survives the wrapper chain
47
- // (callers like the advisor consult gate on it). Fixed at construction.
48
- public readonly supportsNativeWebSearch?: boolean;
49
46
 
50
47
  constructor(
51
48
  private readonly inner: Provider,
@@ -55,7 +52,6 @@ export class CallSiteConfiguredProvider implements Provider {
55
52
  ) {
56
53
  this.name = inner.name;
57
54
  this.tokenEstimationProvider = inner.tokenEstimationProvider;
58
- this.supportsNativeWebSearch = inner.supportsNativeWebSearch;
59
55
  }
60
56
 
61
57
  sendMessage(
@@ -23,10 +23,6 @@ export class RateLimitProvider implements Provider {
23
23
  return this.inner.tokenEstimationProvider;
24
24
  }
25
25
 
26
- get supportsNativeWebSearch(): boolean | undefined {
27
- return this.inner.supportsNativeWebSearch;
28
- }
29
-
30
26
  private requestTimestamps: number[];
31
27
 
32
28
  // Forward the optional token-counting endpoint so the capability survives
@@ -618,10 +618,6 @@ export class RetryProvider implements Provider {
618
618
  return this.inner.tokenEstimationProvider;
619
619
  }
620
620
 
621
- get supportsNativeWebSearch(): boolean | undefined {
622
- return this.inner.supportsNativeWebSearch;
623
- }
624
-
625
621
  // Forward the optional token-counting endpoint so the capability survives
626
622
  // the wrapper chain (callers gate on its presence). Bound straight to the
627
623
  // inner provider — count_tokens is a cheap separate endpoint and its caller
@@ -265,15 +265,6 @@ export interface Provider {
265
265
  * Falls back to `name` when unset.
266
266
  */
267
267
  tokenEstimationProvider?: string;
268
- /**
269
- * True when this provider instance was constructed to run web search
270
- * server-side (provider-native). The native search only activates when a
271
- * `web_search`-named tool is passed in the request, so callers that want to
272
- * enable web search on a one-shot completion (e.g. the advisor consult) check
273
- * this first — passing the tool to a non-native instance would surface an
274
- * unexecutable client tool call. Absent/false on providers without it.
275
- */
276
- supportsNativeWebSearch?: boolean;
277
268
  sendMessage(
278
269
  messages: Message[],
279
270
  options?: SendMessageOptions,
@@ -18,9 +18,6 @@ const log = getLogger("provider-usage-tracking");
18
18
  export class UsageTrackingProvider implements Provider {
19
19
  public readonly name: string;
20
20
  public readonly tokenEstimationProvider?: string;
21
- // Forward native web-search capability so it survives the wrapper chain
22
- // (callers like the advisor consult gate on it). Fixed at construction.
23
- public readonly supportsNativeWebSearch?: boolean;
24
21
  // Forward the optional token-counting endpoint so the capability survives
25
22
  // the wrapper chain. Bound straight to the inner provider — count_tokens is
26
23
  // not billed, so there's no usage to track.
@@ -29,7 +26,6 @@ export class UsageTrackingProvider implements Provider {
29
26
  constructor(private readonly inner: Provider) {
30
27
  this.name = inner.name;
31
28
  this.tokenEstimationProvider = inner.tokenEstimationProvider;
32
- this.supportsNativeWebSearch = inner.supportsNativeWebSearch;
33
29
  if (inner.countInputTokens) {
34
30
  this.countInputTokens = inner.countInputTokens.bind(inner);
35
31
  }