@vellumai/assistant 0.6.4 → 0.6.5

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 (717) hide show
  1. package/.prettierignore +5 -0
  2. package/ARCHITECTURE.md +32 -36
  3. package/Dockerfile +12 -0
  4. package/README.md +3 -4
  5. package/bun.lock +8 -3
  6. package/docs/architecture/integrations.md +1 -20
  7. package/docs/architecture/security.md +16 -16
  8. package/docs/error-handling.md +111 -0
  9. package/docs/skills.md +10 -10
  10. package/docs/stt-provider-onboarding.md +2 -1
  11. package/knip.json +9 -2
  12. package/node_modules/@vellumai/ces-contracts/package.json +2 -1
  13. package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +471 -0
  14. package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +398 -4
  15. package/node_modules/@vellumai/credential-storage/bun.lock +2 -2
  16. package/node_modules/@vellumai/credential-storage/package.json +2 -2
  17. package/node_modules/@vellumai/credential-storage/src/oauth-runtime.ts +20 -2
  18. package/node_modules/@vellumai/egress-proxy/bun.lock +2 -2
  19. package/node_modules/@vellumai/egress-proxy/package.json +2 -2
  20. package/openapi.yaml +123 -11
  21. package/package.json +6 -3
  22. package/scripts/generate-openapi.ts +50 -11
  23. package/src/__tests__/agent-loop-callsite-precedence.test.ts +318 -0
  24. package/src/__tests__/agent-loop-sentry-hygiene.test.ts +137 -0
  25. package/src/__tests__/agent-loop.test.ts +112 -1
  26. package/src/__tests__/anthropic-error-formatting.test.ts +98 -0
  27. package/src/__tests__/anthropic-provider.test.ts +171 -2
  28. package/src/__tests__/approval-cascade.test.ts +31 -10
  29. package/src/__tests__/approval-routes-http.test.ts +134 -10
  30. package/src/__tests__/assistant-attachments.test.ts +44 -0
  31. package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -0
  32. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  33. package/src/__tests__/browser-identifier-parity-guard.test.ts +53 -0
  34. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +23 -33
  35. package/src/__tests__/browser-skill-endstate.test.ts +51 -182
  36. package/src/__tests__/btw-routes.test.ts +47 -1
  37. package/src/__tests__/call-controller.test.ts +1 -2
  38. package/src/__tests__/call-site-routing-provider.test.ts +214 -0
  39. package/src/__tests__/catalog-cache.test.ts +27 -4
  40. package/src/__tests__/channel-approval-routes.test.ts +4 -4
  41. package/src/__tests__/channel-reply-delivery.test.ts +300 -2
  42. package/src/__tests__/checker.test.ts +428 -501
  43. package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
  44. package/src/__tests__/compaction-circuit-breaker.test.ts +336 -0
  45. package/src/__tests__/compaction.benchmark.test.ts +1 -1
  46. package/src/__tests__/config-analysis.test.ts +11 -28
  47. package/src/__tests__/config-loader-backfill.test.ts +174 -0
  48. package/src/__tests__/config-loader-corrupt.test.ts +183 -0
  49. package/src/__tests__/config-loader-quarantine-bulletin.test.ts +202 -0
  50. package/src/__tests__/config-schema-cmd.test.ts +11 -5
  51. package/src/__tests__/config-schema.test.ts +427 -114
  52. package/src/__tests__/config-watcher.test.ts +2 -2
  53. package/src/__tests__/contact-store-user-file.test.ts +72 -73
  54. package/src/__tests__/contacts-write.test.ts +4 -4
  55. package/src/__tests__/context-token-estimator.test.ts +191 -1
  56. package/src/__tests__/context-window-manager.test.ts +530 -2
  57. package/src/__tests__/conversation-abort-tool-results.test.ts +30 -16
  58. package/src/__tests__/conversation-agent-loop-overflow.test.ts +61 -17
  59. package/src/__tests__/conversation-agent-loop.test.ts +412 -82
  60. package/src/__tests__/conversation-attachments.test.ts +1 -1
  61. package/src/__tests__/conversation-confirmation-signals.test.ts +30 -9
  62. package/src/__tests__/conversation-error.test.ts +37 -6
  63. package/src/__tests__/conversation-history-web-search.test.ts +6 -0
  64. package/src/__tests__/conversation-init.benchmark.test.ts +36 -0
  65. package/src/__tests__/conversation-lifecycle.test.ts +336 -0
  66. package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
  67. package/src/__tests__/conversation-pre-run-repair.test.ts +30 -16
  68. package/src/__tests__/conversation-process-callsite.test.ts +306 -0
  69. package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -16
  70. package/src/__tests__/conversation-queue.test.ts +41 -26
  71. package/src/__tests__/conversation-routes-disk-view.test.ts +29 -1
  72. package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
  73. package/src/__tests__/conversation-runtime-assembly.test.ts +2735 -55
  74. package/src/__tests__/conversation-runtime-workspace.test.ts +12 -12
  75. package/src/__tests__/conversation-skill-tools.test.ts +12 -146
  76. package/src/__tests__/conversation-slash-queue.test.ts +34 -19
  77. package/src/__tests__/conversation-slash-unknown.test.ts +30 -16
  78. package/src/__tests__/conversation-speed-override.test.ts +30 -11
  79. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1035 -0
  80. package/src/__tests__/conversation-surfaces-standalone.test.ts +630 -0
  81. package/src/__tests__/conversation-title-service.test.ts +2 -2
  82. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +1 -1
  83. package/src/__tests__/conversation-unread-route.test.ts +2 -2
  84. package/src/__tests__/conversation-usage.test.ts +3 -1
  85. package/src/__tests__/conversation-workspace-cache-state.test.ts +31 -10
  86. package/src/__tests__/conversation-workspace-injection.test.ts +43 -15
  87. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +44 -16
  88. package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
  89. package/src/__tests__/credential-security-invariants.test.ts +3 -0
  90. package/src/__tests__/credential-storage-oauth-compat.test.ts +18 -0
  91. package/src/__tests__/credential-storage-static-compat.test.ts +28 -0
  92. package/src/__tests__/credential-vault-unit.test.ts +135 -19
  93. package/src/__tests__/credentials-cli.test.ts +1 -9
  94. package/src/__tests__/cross-provider-web-search.test.ts +84 -0
  95. package/src/__tests__/daemon-server-persist-and-process-callsite.test.ts +92 -0
  96. package/src/__tests__/delete-propagation.test.ts +437 -0
  97. package/src/__tests__/dm-backfill.test.ts +417 -0
  98. package/src/__tests__/dm-persistence.test.ts +227 -0
  99. package/src/__tests__/edit-propagation.test.ts +280 -0
  100. package/src/__tests__/ephemeral-permissions.test.ts +93 -3
  101. package/src/__tests__/estimator-calibration-integration.test.ts +208 -0
  102. package/src/__tests__/estimator-calibration.test.ts +213 -0
  103. package/src/__tests__/extension-id-sync-guard.test.ts +26 -7
  104. package/src/__tests__/file-write-tool.test.ts +151 -1
  105. package/src/__tests__/filing-service.test.ts +255 -0
  106. package/src/__tests__/gemini-provider.test.ts +0 -3
  107. package/src/__tests__/guardian-grant-minting.test.ts +8 -0
  108. package/src/__tests__/headless-browser-interactions.test.ts +1 -1
  109. package/src/__tests__/heartbeat-service.test.ts +96 -15
  110. package/src/__tests__/host-shell-tool.test.ts +124 -18
  111. package/src/__tests__/http-user-message-parity.test.ts +29 -1
  112. package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
  113. package/src/__tests__/intent-routing.test.ts +1 -40
  114. package/src/__tests__/llm-catalog-parity.test.ts +174 -0
  115. package/src/__tests__/llm-context-normalization.test.ts +121 -0
  116. package/src/__tests__/llm-resolver.test.ts +214 -0
  117. package/src/__tests__/llm-schema.test.ts +223 -0
  118. package/src/__tests__/managed-proxy-context.test.ts +6 -2
  119. package/src/__tests__/messaging-skill-split.test.ts +3 -34
  120. package/src/__tests__/migration-import-from-url.test.ts +684 -0
  121. package/src/__tests__/model-intents.test.ts +9 -83
  122. package/src/__tests__/notification-decision-fallback.test.ts +0 -10
  123. package/src/__tests__/notification-decision-identity.test.ts +0 -9
  124. package/src/__tests__/notification-decision-recipient-context.test.ts +0 -9
  125. package/src/__tests__/oauth-store.test.ts +10 -7
  126. package/src/__tests__/oauth2-gateway-transport.test.ts +8 -3
  127. package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
  128. package/src/__tests__/openai-provider.test.ts +7 -0
  129. package/src/__tests__/openai-responses-provider.test.ts +396 -0
  130. package/src/__tests__/openrouter-provider-only.test.ts +135 -0
  131. package/src/__tests__/outbound-slack-persistence.test.ts +293 -0
  132. package/src/__tests__/permission-checker-host-gate.test.ts +1 -1
  133. package/src/__tests__/permission-mode.test.ts +16 -0
  134. package/src/__tests__/permission-types.test.ts +0 -1
  135. package/src/__tests__/persona-resolver.test.ts +13 -13
  136. package/src/__tests__/pkb-autoinject.test.ts +37 -1
  137. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
  138. package/src/__tests__/pricing.test.ts +50 -3
  139. package/src/__tests__/profiler-routes.test.ts +1 -1
  140. package/src/__tests__/provider-commit-message-generator.test.ts +14 -84
  141. package/src/__tests__/provider-env-vars-scope.test.ts +52 -0
  142. package/src/__tests__/provider-error-scenarios.test.ts +135 -6
  143. package/src/__tests__/provider-managed-proxy-integration.test.ts +42 -11
  144. package/src/__tests__/provider-registry-ollama.test.ts +1 -2
  145. package/src/__tests__/proxy-approval-callback.test.ts +0 -1
  146. package/src/__tests__/reaction-persistence.test.ts +560 -0
  147. package/src/__tests__/relay-server.test.ts +1 -1
  148. package/src/__tests__/require-fresh-approval.test.ts +1 -1
  149. package/src/__tests__/retry-openrouter-only-normalization.test.ts +136 -0
  150. package/src/__tests__/retry-thinking-tool-choice.test.ts +226 -0
  151. package/src/__tests__/risk-classifier-parity.test.ts +230 -0
  152. package/src/__tests__/sanitize-config-for-transfer.test.ts +78 -1
  153. package/src/__tests__/secret-ingress-http.test.ts +28 -0
  154. package/src/__tests__/secret-prompter-channel-fallback.test.ts +125 -0
  155. package/src/__tests__/secret-routes-managed-proxy.test.ts +2 -3
  156. package/src/__tests__/secret-scanner-executor.test.ts +1 -1
  157. package/src/__tests__/send-endpoint-busy.test.ts +29 -1
  158. package/src/__tests__/server-history-render.test.ts +31 -0
  159. package/src/__tests__/shell-parser-property.test.ts +13 -13
  160. package/src/__tests__/skill-cache-store.test.ts +182 -0
  161. package/src/__tests__/skills.test.ts +19 -33
  162. package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
  163. package/src/__tests__/slack-skill.test.ts +3 -8
  164. package/src/__tests__/starter-bundle.test.ts +35 -0
  165. package/src/__tests__/subagent-call-site-routing.test.ts +280 -0
  166. package/src/__tests__/suggestion-routes.test.ts +160 -3
  167. package/src/__tests__/system-prompt.test.ts +22 -35
  168. package/src/__tests__/task-runner.test.ts +3 -1
  169. package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
  170. package/src/__tests__/terminal-tools.test.ts +8 -0
  171. package/src/__tests__/test-support/browser-skill-harness.ts +2 -52
  172. package/src/__tests__/thread-backfill.test.ts +941 -0
  173. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -2
  174. package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
  175. package/src/__tests__/tool-executor.test.ts +60 -94
  176. package/src/__tests__/trust-store.test.ts +442 -109
  177. package/src/__tests__/update-bulletin-job.test.ts +389 -0
  178. package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -1
  179. package/src/__tests__/verification-control-plane-policy.test.ts +1 -22
  180. package/src/__tests__/voice-session-bridge.test.ts +39 -0
  181. package/src/__tests__/volume-security-guard.test.ts +3 -2
  182. package/src/__tests__/web-search-history.test.ts +337 -0
  183. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +343 -0
  184. package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +202 -0
  185. package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +210 -0
  186. package/src/__tests__/workspace-migration-drop-user-md.test.ts +11 -11
  187. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
  188. package/src/__tests__/workspace-policy.test.ts +1 -13
  189. package/src/acp/client-handler.ts +1 -2
  190. package/src/agent/loop.ts +209 -17
  191. package/src/avatar/resvg-lazy.test.ts +136 -0
  192. package/src/avatar/resvg-lazy.ts +82 -9
  193. package/src/avatar/traits-png-sync.ts +21 -1
  194. package/src/browser/__tests__/operations.test.ts +163 -0
  195. package/src/browser/identifiers.ts +51 -0
  196. package/src/browser/operations.ts +660 -0
  197. package/src/browser/types.ts +81 -0
  198. package/src/calls/guardian-question-copy.ts +2 -2
  199. package/src/calls/telephony-stt-routing.ts +1 -1
  200. package/src/calls/voice-session-bridge.ts +1 -0
  201. package/src/cli/AGENTS.md +1 -1
  202. package/src/cli/commands/__tests__/attachment.test.ts +438 -0
  203. package/src/cli/commands/__tests__/browser.test.ts +554 -0
  204. package/src/cli/commands/__tests__/cache.test.ts +623 -0
  205. package/src/cli/commands/__tests__/email-list.test.ts +6 -0
  206. package/src/cli/commands/__tests__/email-send.test.ts +93 -1
  207. package/src/cli/commands/__tests__/image-generation.test.ts +666 -0
  208. package/src/cli/commands/__tests__/inference-send.test.ts +451 -0
  209. package/src/cli/commands/__tests__/stt-transcribe.test.ts +454 -0
  210. package/src/cli/commands/__tests__/task.test.ts +913 -0
  211. package/src/cli/commands/__tests__/tts-synthesize.test.ts +594 -0
  212. package/src/cli/commands/__tests__/ui-confirm.test.ts +650 -0
  213. package/src/cli/commands/__tests__/ui.test.ts +1215 -0
  214. package/src/cli/commands/__tests__/watchers.test.ts +716 -0
  215. package/src/cli/commands/attachment.ts +182 -0
  216. package/src/cli/commands/browser.ts +350 -0
  217. package/src/cli/commands/cache.ts +341 -0
  218. package/src/cli/commands/completions.ts +0 -3
  219. package/src/cli/commands/config.ts +6 -6
  220. package/src/cli/commands/conversations-import.ts +347 -0
  221. package/src/cli/commands/conversations.ts +14 -1
  222. package/src/cli/commands/email.ts +234 -194
  223. package/src/cli/commands/image-generation.ts +300 -0
  224. package/src/cli/commands/inference.ts +200 -0
  225. package/src/cli/commands/memory.ts +127 -17
  226. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
  227. package/src/cli/commands/platform/__tests__/connect.test.ts +0 -1
  228. package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -1
  229. package/src/cli/commands/platform/__tests__/status.test.ts +0 -1
  230. package/src/cli/commands/stt.ts +339 -0
  231. package/src/cli/commands/task.ts +795 -0
  232. package/src/cli/commands/trust.ts +50 -19
  233. package/src/cli/commands/tts.ts +273 -0
  234. package/src/cli/commands/ui.ts +670 -0
  235. package/src/cli/commands/watchers.ts +509 -0
  236. package/src/cli/lib/daemon-credential-client.ts +0 -19
  237. package/src/cli/program.ts +23 -4
  238. package/src/cli.ts +0 -37
  239. package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +23 -1
  240. package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
  241. package/src/config/bundled-skills/messaging/SKILL.md +2 -2
  242. package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
  243. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +8 -1
  244. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +15 -1
  245. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +21 -1
  246. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +11 -12
  247. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -8
  248. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  249. package/src/config/bundled-tool-registry.ts +0 -175
  250. package/src/config/env.ts +7 -2
  251. package/src/config/feature-flag-registry.json +25 -9
  252. package/src/config/llm-resolver.ts +128 -0
  253. package/src/config/loader.ts +194 -10
  254. package/src/config/raw-config-utils.ts +30 -2
  255. package/src/config/sanitize-for-transfer.ts +35 -0
  256. package/src/config/schema.ts +30 -41
  257. package/src/config/schemas/analysis.ts +3 -22
  258. package/src/config/schemas/calls.ts +0 -4
  259. package/src/config/schemas/filing.ts +2 -7
  260. package/src/config/schemas/heartbeat.ts +0 -5
  261. package/src/config/schemas/inference.ts +3 -23
  262. package/src/config/schemas/llm.ts +318 -0
  263. package/src/config/schemas/memory-processing.ts +1 -9
  264. package/src/config/schemas/notifications.ts +4 -11
  265. package/src/config/schemas/platform.ts +3 -9
  266. package/src/config/schemas/security.ts +33 -0
  267. package/src/config/schemas/services.ts +9 -4
  268. package/src/config/schemas/stt.ts +1 -0
  269. package/src/config/schemas/tts.ts +53 -0
  270. package/src/config/schemas/updates.ts +1 -1
  271. package/src/config/schemas/workspace-git.ts +3 -40
  272. package/src/config/skills.ts +2 -2
  273. package/src/context/__tests__/compact-prompt.test.ts +45 -0
  274. package/src/context/__tests__/microcompact.test.ts +805 -0
  275. package/src/context/estimator-calibration.ts +136 -0
  276. package/src/context/microcompact.ts +443 -0
  277. package/src/context/prompts/compact.md +12 -0
  278. package/src/context/token-estimator.ts +61 -3
  279. package/src/context/window-manager.ts +229 -25
  280. package/src/credential-execution/approval-bridge.ts +0 -1
  281. package/src/credential-execution/executable-discovery.ts +19 -8
  282. package/src/credential-execution/process-manager.test.ts +109 -0
  283. package/src/credential-execution/process-manager.ts +65 -2
  284. package/src/daemon/approval-generators.ts +29 -4
  285. package/src/daemon/assistant-attachments.ts +24 -13
  286. package/src/daemon/classifier.ts +2 -2
  287. package/src/daemon/config-watcher.ts +0 -1
  288. package/src/daemon/context-overflow-reducer.ts +4 -1
  289. package/src/daemon/conversation-agent-loop-handlers.ts +79 -12
  290. package/src/daemon/conversation-agent-loop.ts +462 -80
  291. package/src/daemon/conversation-attachments.ts +2 -6
  292. package/src/daemon/conversation-error.ts +36 -1
  293. package/src/daemon/conversation-lifecycle.ts +30 -6
  294. package/src/daemon/conversation-messaging.ts +73 -4
  295. package/src/daemon/conversation-process.ts +10 -4
  296. package/src/daemon/conversation-queue-manager.ts +3 -0
  297. package/src/daemon/conversation-runtime-assembly.ts +760 -29
  298. package/src/daemon/conversation-slash.ts +2 -2
  299. package/src/daemon/conversation-surfaces.ts +389 -1
  300. package/src/daemon/conversation-tool-setup.ts +10 -5
  301. package/src/daemon/conversation-usage.ts +1 -1
  302. package/src/daemon/conversation.ts +118 -30
  303. package/src/daemon/external-skills-bootstrap.ts +41 -0
  304. package/src/daemon/guardian-action-generators.ts +34 -14
  305. package/src/daemon/handlers/config-model.test.ts +86 -0
  306. package/src/daemon/handlers/config-model.ts +54 -12
  307. package/src/daemon/handlers/conversations.ts +9 -2
  308. package/src/daemon/handlers/shared.ts +39 -11
  309. package/src/daemon/handlers/skills.ts +2 -2
  310. package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
  311. package/src/daemon/lifecycle.ts +76 -14
  312. package/src/daemon/message-types/conversations.ts +14 -0
  313. package/src/daemon/message-types/messages.ts +9 -1
  314. package/src/daemon/message-types/trust.ts +0 -2
  315. package/src/daemon/parse-actual-tokens-from-error.test.ts +57 -1
  316. package/src/daemon/parse-actual-tokens-from-error.ts +66 -0
  317. package/src/daemon/pkb-context-tracker.test.ts +169 -0
  318. package/src/daemon/pkb-context-tracker.ts +125 -0
  319. package/src/daemon/pkb-reminder-builder.test.ts +70 -0
  320. package/src/daemon/pkb-reminder-builder.ts +31 -0
  321. package/src/daemon/providers-setup.ts +6 -0
  322. package/src/daemon/server.ts +117 -9
  323. package/src/daemon/tool-side-effects.ts +0 -9
  324. package/src/daemon/watch-handler.ts +4 -4
  325. package/src/daemon/web-search-history.ts +126 -0
  326. package/src/events/domain-events.ts +0 -1
  327. package/src/filing/filing-service.ts +9 -10
  328. package/src/heartbeat/heartbeat-service.ts +76 -28
  329. package/src/home/__tests__/feed-scheduler.test.ts +39 -11
  330. package/src/home/__tests__/rollup-producer.test.ts +44 -0
  331. package/src/home/assistant-feed-authoring.ts +4 -0
  332. package/src/home/emit-feed-event.ts +4 -0
  333. package/src/home/feed-scheduler.ts +20 -4
  334. package/src/home/feed-types.ts +56 -2
  335. package/src/home/relationship-state-writer.ts +2 -2
  336. package/src/home/rollup-producer.ts +34 -5
  337. package/src/home/suggested-prompts.ts +101 -0
  338. package/src/ipc/__tests__/attachment-ipc.test.ts +213 -0
  339. package/src/ipc/__tests__/browser-ipc.test.ts +339 -0
  340. package/src/ipc/__tests__/cache-ipc.test.ts +266 -0
  341. package/src/ipc/__tests__/socket-path.test.ts +73 -0
  342. package/src/ipc/__tests__/task-ipc.test.ts +577 -0
  343. package/src/ipc/__tests__/ui-request-route.test.ts +495 -0
  344. package/src/ipc/__tests__/watcher-ipc.test.ts +295 -0
  345. package/src/ipc/cli-client.ts +2 -1
  346. package/src/ipc/cli-server.ts +26 -8
  347. package/src/ipc/gateway-client.ts +4 -4
  348. package/src/ipc/routes/attachment.ts +114 -0
  349. package/src/ipc/routes/browser-context.ts +61 -0
  350. package/src/ipc/routes/browser.ts +96 -0
  351. package/src/ipc/routes/cache.ts +96 -0
  352. package/src/ipc/routes/index.ts +17 -1
  353. package/src/ipc/routes/task-queue.ts +226 -0
  354. package/src/ipc/routes/task.ts +173 -0
  355. package/src/ipc/routes/ui-request.ts +50 -0
  356. package/src/ipc/routes/watcher.ts +203 -0
  357. package/src/ipc/socket-path.ts +100 -0
  358. package/src/memory/__tests__/conversation-analyze-job.test.ts +9 -8
  359. package/src/memory/__tests__/conversation-group-migration.test.ts +99 -0
  360. package/src/memory/admin.ts +18 -0
  361. package/src/memory/conversation-analyze-job.ts +14 -13
  362. package/src/memory/conversation-attention-store.ts +13 -6
  363. package/src/memory/conversation-crud.ts +103 -3
  364. package/src/memory/conversation-group-migration.ts +38 -6
  365. package/src/memory/conversation-title-service.ts +7 -4
  366. package/src/memory/db-init.ts +2 -0
  367. package/src/memory/embedding-backend.ts +1 -1
  368. package/src/memory/graph/compaction.ts +299 -0
  369. package/src/memory/graph/consolidation.ts +4 -4
  370. package/src/memory/graph/conversation-graph-memory.ts +89 -29
  371. package/src/memory/graph/extraction.test.ts +272 -2
  372. package/src/memory/graph/extraction.ts +173 -51
  373. package/src/memory/graph/graph-search.test.ts +92 -0
  374. package/src/memory/graph/graph-search.ts +4 -1
  375. package/src/memory/graph/narrative.ts +2 -2
  376. package/src/memory/graph/pattern-scan.ts +2 -2
  377. package/src/memory/graph/retriever.test.ts +459 -0
  378. package/src/memory/graph/retriever.ts +230 -48
  379. package/src/memory/graph/store.ts +41 -0
  380. package/src/memory/graph/tool-handlers.ts +27 -0
  381. package/src/memory/graph/tools.ts +6 -1
  382. package/src/memory/indexer.ts +5 -5
  383. package/src/memory/job-handlers/conversation-starters.ts +23 -20
  384. package/src/memory/job-handlers/summarization.ts +2 -2
  385. package/src/memory/job-utils.ts +7 -1
  386. package/src/memory/jobs/embed-pkb-file.test.ts +168 -0
  387. package/src/memory/jobs/embed-pkb-file.ts +54 -0
  388. package/src/memory/jobs-store.ts +44 -3
  389. package/src/memory/jobs-worker.ts +4 -0
  390. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
  391. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +2 -2
  392. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +82 -0
  393. package/src/memory/migrations/index.ts +1 -0
  394. package/src/memory/pkb/pkb-index.test.ts +368 -0
  395. package/src/memory/pkb/pkb-index.ts +255 -0
  396. package/src/memory/pkb/pkb-reconcile.test.ts +251 -0
  397. package/src/memory/pkb/pkb-reconcile.ts +148 -0
  398. package/src/memory/pkb/pkb-search.test.ts +438 -0
  399. package/src/memory/pkb/pkb-search.ts +137 -0
  400. package/src/memory/pkb/types.ts +53 -0
  401. package/src/memory/qdrant-client.ts +122 -1
  402. package/src/memory/slack-thread-store.ts +37 -0
  403. package/src/messaging/providers/gmail/adapter.ts +6 -16
  404. package/src/messaging/providers/gmail/client.ts +22 -0
  405. package/src/messaging/providers/gmail/types.ts +7 -0
  406. package/src/messaging/providers/slack/adapter.ts +14 -2
  407. package/src/messaging/providers/slack/backfill.test.ts +257 -0
  408. package/src/messaging/providers/slack/backfill.ts +101 -0
  409. package/src/messaging/providers/slack/message-metadata.test.ts +316 -0
  410. package/src/messaging/providers/slack/message-metadata.ts +123 -0
  411. package/src/messaging/providers/slack/render-transcript.test.ts +1373 -0
  412. package/src/messaging/providers/slack/render-transcript.ts +443 -0
  413. package/src/messaging/style-analyzer.ts +5 -2
  414. package/src/notifications/README.md +9 -5
  415. package/src/notifications/decision-engine.ts +3 -9
  416. package/src/notifications/preference-extractor.ts +2 -6
  417. package/src/oauth/oauth-store.ts +1 -0
  418. package/src/oauth/platform-connection.test.ts +47 -0
  419. package/src/oauth/platform-connection.ts +15 -5
  420. package/src/oauth/seed-providers.ts +4 -2
  421. package/src/permissions/approval-policy.test.ts +948 -0
  422. package/src/permissions/approval-policy.ts +257 -0
  423. package/src/permissions/bash-risk-classifier.test.ts +1208 -0
  424. package/src/permissions/bash-risk-classifier.ts +707 -0
  425. package/src/permissions/checker.ts +217 -708
  426. package/src/permissions/command-registry.test.ts +535 -0
  427. package/src/permissions/command-registry.ts +825 -0
  428. package/src/permissions/defaults.ts +26 -78
  429. package/src/permissions/file-risk-classifier.test.ts +535 -0
  430. package/src/permissions/file-risk-classifier.ts +274 -0
  431. package/src/permissions/risk-types.ts +205 -0
  432. package/src/permissions/secret-prompter.ts +53 -2
  433. package/src/permissions/skill-risk-classifier.test.ts +311 -0
  434. package/src/permissions/skill-risk-classifier.ts +214 -0
  435. package/src/permissions/trust-client.ts +52 -25
  436. package/src/permissions/trust-store-interface.ts +1 -6
  437. package/src/permissions/trust-store.ts +161 -62
  438. package/src/permissions/types.ts +23 -14
  439. package/src/permissions/web-risk-classifier.test.ts +170 -0
  440. package/src/permissions/web-risk-classifier.ts +89 -0
  441. package/src/permissions/workspace-policy.ts +1 -16
  442. package/src/platform/client.ts +19 -1
  443. package/src/prompts/persona-resolver.ts +3 -3
  444. package/src/prompts/system-prompt.ts +19 -20
  445. package/src/prompts/templates/SOUL.md +2 -2
  446. package/src/prompts/update-bulletin-job.ts +190 -0
  447. package/src/providers/__tests__/context-overflow-error.test.ts +328 -0
  448. package/src/providers/__tests__/provider-env-vars.test.ts +102 -0
  449. package/src/providers/__tests__/retry-callsite.test.ts +424 -0
  450. package/src/providers/anthropic/client.ts +183 -14
  451. package/src/providers/call-site-routing.ts +71 -0
  452. package/src/providers/gemini/client.ts +65 -2
  453. package/src/providers/managed-proxy/constants.ts +2 -1
  454. package/src/providers/model-catalog.ts +501 -33
  455. package/src/providers/model-intents.ts +4 -4
  456. package/src/providers/openai/chat-completions-provider.ts +57 -1
  457. package/src/providers/openai/responses-provider.ts +86 -9
  458. package/src/providers/openrouter/client.ts +76 -9
  459. package/src/providers/provider-env-vars.ts +56 -0
  460. package/src/providers/provider-send-message.ts +22 -5
  461. package/src/providers/ratelimit.ts +4 -0
  462. package/src/providers/registry.ts +19 -8
  463. package/src/providers/retry.ts +174 -39
  464. package/src/providers/speech-to-text/__tests__/resolve.test.ts +55 -0
  465. package/src/providers/speech-to-text/google-gemini-live-stream.ts +4 -4
  466. package/src/providers/speech-to-text/provider-catalog.ts +17 -0
  467. package/src/providers/speech-to-text/resolve.ts +7 -0
  468. package/src/providers/speech-to-text/xai-realtime.test.ts +578 -0
  469. package/src/providers/speech-to-text/xai-realtime.ts +796 -0
  470. package/src/providers/speech-to-text/xai.test.ts +155 -0
  471. package/src/providers/speech-to-text/xai.ts +97 -0
  472. package/src/providers/types.ts +93 -3
  473. package/src/runtime/AGENTS.md +2 -2
  474. package/src/runtime/__tests__/agent-wake.test.ts +43 -2
  475. package/src/runtime/__tests__/interactive-ui.test.ts +673 -0
  476. package/src/runtime/agent-wake.ts +63 -22
  477. package/src/runtime/auth/route-policy.ts +4 -0
  478. package/src/runtime/btw-sidechain.ts +13 -3
  479. package/src/runtime/channel-reply-delivery.ts +106 -2
  480. package/src/runtime/decision-token.ts +116 -0
  481. package/src/runtime/gateway-client.ts +2 -2
  482. package/src/runtime/http-router.ts +32 -0
  483. package/src/runtime/http-server.ts +52 -1
  484. package/src/runtime/http-types.ts +23 -1
  485. package/src/runtime/interactive-ui.ts +362 -0
  486. package/src/runtime/invite-instruction-generator.ts +2 -2
  487. package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +176 -0
  488. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +390 -0
  489. package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +221 -0
  490. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +1540 -0
  491. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +453 -0
  492. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +222 -0
  493. package/src/runtime/migrations/gcs-signed-url.ts +162 -0
  494. package/src/runtime/migrations/vbundle-importer.ts +154 -9
  495. package/src/runtime/migrations/vbundle-metadata-merge.ts +124 -0
  496. package/src/runtime/migrations/vbundle-streaming-importer.ts +2522 -0
  497. package/src/runtime/migrations/vbundle-streaming-validator.ts +244 -0
  498. package/src/runtime/migrations/vbundle-tar-stream.ts +217 -0
  499. package/src/runtime/migrations/vbundle-validator.ts +15 -6
  500. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +111 -0
  501. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +114 -75
  502. package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +246 -0
  503. package/src/runtime/routes/approval-prompt-ts-tracker.ts +58 -0
  504. package/src/runtime/routes/approval-routes.ts +12 -17
  505. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +9 -0
  506. package/src/runtime/routes/avatar-routes.ts +20 -4
  507. package/src/runtime/routes/btw-routes.ts +1 -4
  508. package/src/runtime/routes/conversation-management-routes.ts +20 -2
  509. package/src/runtime/routes/conversation-routes.ts +133 -27
  510. package/src/runtime/routes/debug-routes.ts +1 -1
  511. package/src/runtime/routes/diagnostics-routes.ts +6 -4
  512. package/src/runtime/routes/events-routes.ts +16 -0
  513. package/src/runtime/routes/guardian-approval-interception.ts +33 -3
  514. package/src/runtime/routes/guardian-approval-prompt.ts +13 -3
  515. package/src/runtime/routes/home-feed-routes.ts +120 -2
  516. package/src/runtime/routes/inbound-message-handler.ts +912 -2
  517. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +113 -2
  518. package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -3
  519. package/src/runtime/routes/inbound-stages/edit-intercept.ts +129 -6
  520. package/src/runtime/routes/integrations/slack/channel.ts +25 -3
  521. package/src/runtime/routes/llm-context-normalization.ts +23 -1
  522. package/src/runtime/routes/migration-routes.ts +720 -124
  523. package/src/runtime/routes/settings-routes.ts +4 -2
  524. package/src/runtime/routes/trust-rules-routes.ts +30 -14
  525. package/src/runtime/routes/work-items-routes.test.ts +1 -1
  526. package/src/runtime/routes/work-items-routes.ts +3 -2
  527. package/src/runtime/services/__tests__/analyze-conversation.test.ts +25 -43
  528. package/src/runtime/services/analyze-conversation.ts +12 -16
  529. package/src/runtime/skill-route-registry.ts +28 -6
  530. package/src/schedule/scheduler.ts +8 -0
  531. package/src/security/__tests__/provider-key-env-fallback.test.ts +119 -0
  532. package/src/security/__tests__/untrusted-content.test.ts +109 -0
  533. package/src/security/oauth2.ts +98 -35
  534. package/src/security/secure-keys.ts +7 -8
  535. package/src/security/token-manager.ts +27 -13
  536. package/src/security/untrusted-content.ts +102 -0
  537. package/src/skills/catalog-cache.ts +26 -7
  538. package/src/skills/catalog-install.ts +31 -3
  539. package/src/skills/skill-cache-store.ts +97 -0
  540. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +76 -0
  541. package/src/stt/daemon-batch-transcriber.ts +33 -0
  542. package/src/stt/stt-stream-session.ts +8 -1
  543. package/src/stt/types.ts +5 -1
  544. package/src/subagent/manager.ts +41 -13
  545. package/src/tasks/ephemeral-permissions.ts +9 -4
  546. package/src/telemetry/usage-telemetry-reporter.ts +27 -5
  547. package/src/tools/browser/__tests__/browser-status.test.ts +45 -2
  548. package/src/tools/browser/browser-execution.ts +65 -38
  549. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +22 -0
  550. package/src/tools/credentials/tool-policy.ts +39 -5
  551. package/src/tools/credentials/vault.ts +9 -4
  552. package/src/tools/executor.ts +4 -0
  553. package/src/tools/filesystem/write.ts +52 -0
  554. package/src/tools/host-terminal/host-shell.ts +45 -5
  555. package/src/tools/memory/register.test.ts +185 -0
  556. package/src/tools/memory/register.ts +3 -1
  557. package/src/tools/network/web-fetch.ts +20 -10
  558. package/src/tools/network/web-search.ts +19 -4
  559. package/src/tools/permission-checker.ts +36 -15
  560. package/src/tools/policy-context.ts +25 -8
  561. package/src/tools/registry.ts +55 -3
  562. package/src/tools/side-effects.ts +0 -11
  563. package/src/tools/skills/execute.ts +2 -2
  564. package/src/tools/skills/sandbox-runner.ts +5 -2
  565. package/src/tools/terminal/backends/native.ts +51 -2
  566. package/src/tools/terminal/safe-env.ts +3 -2
  567. package/src/tools/terminal/shell.ts +1 -0
  568. package/src/tools/tool-manifest.ts +6 -21
  569. package/src/tools/types.ts +12 -3
  570. package/src/tools/verification-control-plane-policy.ts +1 -1
  571. package/src/tts/__tests__/provider-adapters.test.ts +240 -13
  572. package/src/tts/provider-catalog.ts +18 -0
  573. package/src/tts/providers/index.ts +2 -0
  574. package/src/tts/providers/xai-provider.ts +224 -0
  575. package/src/tts/types.ts +46 -0
  576. package/src/types/tar-stream.d.ts +66 -0
  577. package/src/util/json.ts +17 -0
  578. package/src/util/platform.ts +2 -2
  579. package/src/util/pricing.ts +15 -5
  580. package/src/watcher/engine.ts +1 -1
  581. package/src/watcher/providers/google-calendar.ts +134 -8
  582. package/src/watcher/providers/outlook-calendar.ts +42 -2
  583. package/src/workspace/git-service.ts +23 -4
  584. package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +516 -0
  585. package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +171 -0
  586. package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +154 -0
  587. package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +57 -0
  588. package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +70 -0
  589. package/src/workspace/migrations/043-release-notes-latex-rendering.ts +75 -0
  590. package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +51 -0
  591. package/src/workspace/migrations/045-release-notes-meet-avatar.ts +130 -0
  592. package/src/workspace/migrations/AGENTS.md +1 -1
  593. package/src/workspace/migrations/registry.ts +16 -0
  594. package/src/workspace/provider-commit-message-generator.ts +19 -38
  595. package/src/__tests__/gmail-archive-fallback.test.ts +0 -193
  596. package/src/__tests__/gmail-archive-gate.test.ts +0 -246
  597. package/src/__tests__/gmail-preferences.test.ts +0 -117
  598. package/src/__tests__/outlook-attachments.test.ts +0 -301
  599. package/src/__tests__/outlook-automation-tools.test.ts +0 -425
  600. package/src/__tests__/outlook-categories.test.ts +0 -212
  601. package/src/__tests__/outlook-compose-tools.test.ts +0 -325
  602. package/src/__tests__/outlook-declutter-tools.test.ts +0 -585
  603. package/src/__tests__/outlook-follow-up.test.ts +0 -196
  604. package/src/__tests__/outlook-trash.test.ts +0 -77
  605. package/src/__tests__/outlook-unsubscribe.test.ts +0 -279
  606. package/src/__tests__/update-bulletin-format.test.ts +0 -181
  607. package/src/__tests__/update-bulletin-state.test.ts +0 -135
  608. package/src/__tests__/update-bulletin.test.ts +0 -478
  609. package/src/__tests__/update-template-contract.test.ts +0 -29
  610. package/src/cli/commands/doctor.ts +0 -341
  611. package/src/config/bundled-skills/browser/SKILL.md +0 -88
  612. package/src/config/bundled-skills/browser/TOOLS.json +0 -516
  613. package/src/config/bundled-skills/browser/tools/browser-attach.ts +0 -12
  614. package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -12
  615. package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -12
  616. package/src/config/bundled-skills/browser/tools/browser-detach.ts +0 -12
  617. package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -12
  618. package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -12
  619. package/src/config/bundled-skills/browser/tools/browser-hover.ts +0 -12
  620. package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -12
  621. package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -12
  622. package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -12
  623. package/src/config/bundled-skills/browser/tools/browser-scroll.ts +0 -12
  624. package/src/config/bundled-skills/browser/tools/browser-select-option.ts +0 -12
  625. package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -12
  626. package/src/config/bundled-skills/browser/tools/browser-status.ts +0 -12
  627. package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -12
  628. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +0 -49
  629. package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -12
  630. package/src/config/bundled-skills/chatgpt-import/SKILL.md +0 -27
  631. package/src/config/bundled-skills/chatgpt-import/TOOLS.json +0 -27
  632. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +0 -378
  633. package/src/config/bundled-skills/gmail/SKILL.md +0 -221
  634. package/src/config/bundled-skills/gmail/TOOLS.json +0 -588
  635. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +0 -256
  636. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +0 -112
  637. package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +0 -44
  638. package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +0 -81
  639. package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +0 -108
  640. package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +0 -146
  641. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +0 -53
  642. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +0 -347
  643. package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +0 -59
  644. package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +0 -82
  645. package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +0 -26
  646. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +0 -347
  647. package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +0 -29
  648. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +0 -122
  649. package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +0 -67
  650. package/src/config/bundled-skills/gmail/tools/scan-result-store.ts +0 -100
  651. package/src/config/bundled-skills/gmail/tools/shared.ts +0 -47
  652. package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
  653. package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -226
  654. package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -223
  655. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -27
  656. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -48
  657. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -19
  658. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -36
  659. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -58
  660. package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -17
  661. package/src/config/bundled-skills/google-calendar/types.ts +0 -97
  662. package/src/config/bundled-skills/outlook/SKILL.md +0 -196
  663. package/src/config/bundled-skills/outlook/TOOLS.json +0 -530
  664. package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +0 -85
  665. package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +0 -77
  666. package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +0 -84
  667. package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +0 -94
  668. package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +0 -49
  669. package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +0 -237
  670. package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +0 -161
  671. package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +0 -32
  672. package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +0 -272
  673. package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +0 -29
  674. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +0 -129
  675. package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +0 -87
  676. package/src/config/bundled-skills/outlook/tools/shared.ts +0 -20
  677. package/src/config/bundled-skills/outlook-calendar/SKILL.md +0 -51
  678. package/src/config/bundled-skills/outlook-calendar/TOOLS.json +0 -221
  679. package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +0 -252
  680. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +0 -53
  681. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +0 -74
  682. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +0 -18
  683. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +0 -46
  684. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +0 -36
  685. package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +0 -17
  686. package/src/config/bundled-skills/outlook-calendar/types.ts +0 -120
  687. package/src/config/bundled-skills/slack/SKILL.md +0 -108
  688. package/src/config/bundled-skills/tasks/SKILL.md +0 -37
  689. package/src/config/bundled-skills/tasks/TOOLS.json +0 -353
  690. package/src/config/bundled-skills/tasks/icon.svg +0 -34
  691. package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -12
  692. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -12
  693. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -12
  694. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -12
  695. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -12
  696. package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -12
  697. package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -12
  698. package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -12
  699. package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -12
  700. package/src/config/bundled-skills/watcher/SKILL.md +0 -31
  701. package/src/config/bundled-skills/watcher/TOOLS.json +0 -167
  702. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -12
  703. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -12
  704. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -12
  705. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -12
  706. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -12
  707. package/src/prompts/templates/UPDATES.md +0 -50
  708. package/src/prompts/update-bulletin-format.ts +0 -85
  709. package/src/prompts/update-bulletin-state.ts +0 -58
  710. package/src/prompts/update-bulletin-template-path.ts +0 -13
  711. package/src/prompts/update-bulletin.ts +0 -139
  712. package/src/shared/provider-env-vars.ts +0 -19
  713. package/src/tools/watcher/create.ts +0 -86
  714. package/src/tools/watcher/delete.ts +0 -36
  715. package/src/tools/watcher/digest.ts +0 -54
  716. package/src/tools/watcher/list.ts +0 -83
  717. package/src/tools/watcher/update.ts +0 -71
@@ -14,6 +14,46 @@ import type {
14
14
  SendMessageOptions,
15
15
  ToolDefinition,
16
16
  } from "../types.js";
17
+ import {
18
+ ContextOverflowError,
19
+ extractOverflowTokensFromMessage,
20
+ } from "../types.js";
21
+
22
+ /**
23
+ * Detect OpenAI-compatible context-overflow signals on an `OpenAI.APIError`.
24
+ *
25
+ * OpenAI proper returns HTTP 400 with body
26
+ * `{ error: { code: "context_length_exceeded", message, ... } }`
27
+ * Other OpenAI-compatible providers (OpenRouter, Fireworks, Ollama, etc.)
28
+ * forward similar shapes; not all populate `code` so we also probe the
29
+ * message/param fields. Returns an object with any extractable token counts
30
+ * when the error matches, or `null` when it does not.
31
+ *
32
+ * Most OpenAI-compatible providers do not report `actualTokens`/`maxTokens`
33
+ * in the error body, but the typed wrapper is still valuable as a stable
34
+ * signal for the agent loop.
35
+ */
36
+ export function detectOpenAICompatibleContextOverflow(
37
+ error: InstanceType<typeof OpenAI.APIError>,
38
+ ): { actualTokens?: number; maxTokens?: number } | null {
39
+ // OpenAI-compatible providers use 400 (most) or 413 (rarer payload-too-large).
40
+ const status = error.status;
41
+ if (status !== 400 && status !== 413) return null;
42
+ const code = error.code;
43
+ const codeMatches =
44
+ typeof code === "string" &&
45
+ /context_length_exceeded|context_window_exceeded|input_too_long|prompt_too_long/i.test(
46
+ code,
47
+ );
48
+ const message = error.message ?? "";
49
+ const messageMatches =
50
+ /context.?length.?exceeded|context.?window.?exceeded|prompt.?is.?too.?long|prompt_too_long|input.?too.?long|too.?many.?(?:input.?)?tokens|maximum.?context/i.test(
51
+ message,
52
+ );
53
+ if (!codeMatches && !messageMatches) return null;
54
+ // OpenAI-compatible providers rarely report usable token counts; best-effort extract.
55
+ return extractOverflowTokensFromMessage(message);
56
+ }
17
57
 
18
58
  export interface OpenAIChatCompletionsProviderOptions {
19
59
  baseURL?: string;
@@ -24,7 +64,9 @@ export interface OpenAIChatCompletionsProviderOptions {
24
64
  extraCreateParams?: Record<string, unknown>;
25
65
  }
26
66
 
27
- /** Map our internal effort values to OpenAI's reasoning_effort parameter. */
67
+ /** Map our internal effort values to OpenAI's reasoning_effort parameter.
68
+ * OpenAI's reasoning_effort caps at "high", so "xhigh" and "max" both
69
+ * collapse to "high" on this transport. */
28
70
  const EFFORT_TO_REASONING_EFFORT: Record<
29
71
  string,
30
72
  NonNullable<
@@ -34,6 +76,7 @@ const EFFORT_TO_REASONING_EFFORT: Record<
34
76
  low: "low",
35
77
  medium: "medium",
36
78
  high: "high",
79
+ xhigh: "high",
37
80
  max: "high",
38
81
  };
39
82
 
@@ -256,6 +299,19 @@ export class OpenAIChatCompletionsProvider implements Provider {
256
299
  ? signal.reason
257
300
  : undefined;
258
301
  if (error instanceof OpenAI.APIError) {
302
+ const overflow = detectOpenAICompatibleContextOverflow(error);
303
+ if (overflow) {
304
+ throw new ContextOverflowError(
305
+ `${this.providerLabel} API error (${error.status}): ${error.message}`,
306
+ this.name,
307
+ {
308
+ actualTokens: overflow.actualTokens,
309
+ maxTokens: overflow.maxTokens,
310
+ statusCode: error.status,
311
+ cause: error,
312
+ },
313
+ );
314
+ }
259
315
  const retryAfterMs = extractRetryAfterMs(error.headers);
260
316
  const errorOptions: {
261
317
  retryAfterMs?: number;
@@ -14,19 +14,24 @@ import type {
14
14
  SendMessageOptions,
15
15
  ToolDefinition,
16
16
  } from "../types.js";
17
+ import { ContextOverflowError } from "../types.js";
18
+ import { detectOpenAICompatibleContextOverflow } from "./chat-completions-provider.js";
17
19
 
18
20
  export interface OpenAIResponsesProviderOptions {
19
21
  baseURL?: string;
20
22
  providerName?: string;
21
23
  providerLabel?: string;
22
24
  streamTimeoutMs?: number;
25
+ useNativeWebSearch?: boolean;
23
26
  }
24
27
 
25
- /** Map our internal effort values to the Responses API reasoning.effort parameter. */
28
+ /** Map our internal effort values to the Responses API reasoning.effort parameter.
29
+ * The Responses API caps at "high", so "xhigh" and "max" both collapse to "high". */
26
30
  const EFFORT_TO_REASONING_EFFORT: Record<string, "low" | "medium" | "high"> = {
27
31
  low: "low",
28
32
  medium: "medium",
29
33
  high: "high",
34
+ xhigh: "high",
30
35
  max: "high",
31
36
  };
32
37
 
@@ -75,6 +80,7 @@ export class OpenAIResponsesProvider implements Provider {
75
80
  private client: OpenAI;
76
81
  private model: string;
77
82
  private streamTimeoutMs: number;
83
+ private useNativeWebSearch: boolean;
78
84
 
79
85
  constructor(
80
86
  apiKey: string,
@@ -89,6 +95,7 @@ export class OpenAIResponsesProvider implements Provider {
89
95
  });
90
96
  this.model = model;
91
97
  this.streamTimeoutMs = options.streamTimeoutMs ?? 1_800_000;
98
+ this.useNativeWebSearch = options.useNativeWebSearch ?? false;
92
99
  }
93
100
 
94
101
  async sendMessage(
@@ -131,13 +138,31 @@ export class OpenAIResponsesProvider implements Provider {
131
138
  }
132
139
 
133
140
  if (tools && tools.length > 0) {
134
- params.tools = tools.map((t) => ({
135
- type: "function" as const,
136
- name: t.name,
137
- description: t.description,
138
- parameters: t.input_schema,
139
- strict: null,
140
- }));
141
+ if (
142
+ this.useNativeWebSearch &&
143
+ tools.some((t) => t.name === "web_search")
144
+ ) {
145
+ const otherTools = tools.filter((t) => t.name !== "web_search");
146
+ const mappedOther = otherTools.map((t) => ({
147
+ type: "function" as const,
148
+ name: t.name,
149
+ description: t.description,
150
+ parameters: t.input_schema,
151
+ strict: null,
152
+ }));
153
+ const webSearchTool = {
154
+ type: "web_search_preview" as const,
155
+ };
156
+ params.tools = [...mappedOther, webSearchTool];
157
+ } else {
158
+ params.tools = tools.map((t) => ({
159
+ type: "function" as const,
160
+ name: t.name,
161
+ description: t.description,
162
+ parameters: t.input_schema,
163
+ strict: null,
164
+ }));
165
+ }
141
166
  }
142
167
 
143
168
  const { signal: timeoutSignal, cleanup: cleanupTimeout } =
@@ -152,6 +177,8 @@ export class OpenAIResponsesProvider implements Provider {
152
177
  >();
153
178
  // Maps item_id → callId so we can look up tool calls from delta events.
154
179
  const itemIdToCallId = new Map<string, string>();
180
+ // Track web search call item IDs so we can emit server_tool_complete.
181
+ const webSearchCallIds: string[] = [];
155
182
  let finishReason = "unknown";
156
183
  let responseModel = modelOverride ?? this.model;
157
184
  let inputTokens = 0;
@@ -195,6 +222,15 @@ export class OpenAIResponsesProvider implements Provider {
195
222
  args: "",
196
223
  });
197
224
  itemIdToCallId.set(itemId, callId);
225
+ } else if (item?.type === "web_search_call") {
226
+ const toolUseId = item.id ?? "";
227
+ webSearchCallIds.push(toolUseId);
228
+ onEvent?.({
229
+ type: "server_tool_start",
230
+ name: "web_search",
231
+ toolUseId,
232
+ input: {},
233
+ });
198
234
  }
199
235
  break;
200
236
  }
@@ -248,6 +284,14 @@ export class OpenAIResponsesProvider implements Provider {
248
284
  }
249
285
  finishReason = response.status ?? "completed";
250
286
  }
287
+ // Emit server_tool_complete for any web search calls that were started.
288
+ for (const toolUseId of webSearchCallIds) {
289
+ onEvent?.({
290
+ type: "server_tool_complete",
291
+ toolUseId,
292
+ isError: false,
293
+ });
294
+ }
251
295
  break;
252
296
  }
253
297
  }
@@ -256,8 +300,28 @@ export class OpenAIResponsesProvider implements Provider {
256
300
  cleanupTimeout();
257
301
  }
258
302
 
259
- // Build content blocks
303
+ // Build content blocks.
304
+ // Inject server_tool_use + web_search_tool_result pairs before text so
305
+ // conversation history matches the shape Anthropic produces for native
306
+ // web search. The paired result block prevents repairHistory() from
307
+ // treating completed searches as interrupted (which would inject a
308
+ // synthetic web_search_tool_result_error and corrupt history). OpenAI
309
+ // weaves search results into the text output, so the result content is
310
+ // an empty array — the actual results are in the text block that follows.
260
311
  const content: ContentBlock[] = [];
312
+ for (const toolUseId of webSearchCallIds) {
313
+ content.push({
314
+ type: "server_tool_use",
315
+ id: toolUseId,
316
+ name: "web_search",
317
+ input: {},
318
+ });
319
+ content.push({
320
+ type: "web_search_tool_result",
321
+ tool_use_id: toolUseId,
322
+ content: [],
323
+ });
324
+ }
261
325
  if (contentText) {
262
326
  content.push({ type: "text", text: contentText });
263
327
  }
@@ -297,6 +361,19 @@ export class OpenAIResponsesProvider implements Provider {
297
361
  ? signal.reason
298
362
  : undefined;
299
363
  if (error instanceof OpenAI.APIError) {
364
+ const overflow = detectOpenAICompatibleContextOverflow(error);
365
+ if (overflow) {
366
+ throw new ContextOverflowError(
367
+ `${this.providerLabel} API error (${error.status}): ${error.message}`,
368
+ this.name,
369
+ {
370
+ actualTokens: overflow.actualTokens,
371
+ maxTokens: overflow.maxTokens,
372
+ statusCode: error.status,
373
+ cause: error,
374
+ },
375
+ );
376
+ }
300
377
  const retryAfterMs = extractRetryAfterMs(error.headers);
301
378
  const errorOptions: {
302
379
  retryAfterMs?: number;
@@ -6,11 +6,13 @@ import type {
6
6
  SendMessageOptions,
7
7
  ToolDefinition,
8
8
  } from "../types.js";
9
+ import { ContextOverflowError, isContextOverflowError } from "../types.js";
9
10
 
10
11
  export interface OpenRouterProviderOptions {
11
12
  apiKey?: string;
12
13
  baseURL?: string;
13
14
  streamTimeoutMs?: number;
15
+ useNativeWebSearch?: boolean;
14
16
  }
15
17
 
16
18
  const DEFAULT_OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
@@ -31,11 +33,51 @@ function toAnthropicMessagesBaseURL(openRouterBaseURL: string): string {
31
33
  return openRouterBaseURL.replace(/\/v1\/?$/, "");
32
34
  }
33
35
 
36
+ /**
37
+ * Extract the normalized `openrouter.only` list from a per-call config. Returns
38
+ * an empty array when the field is absent, empty, or contains no usable string
39
+ * entries, so callers can branch on `length > 0` to decide whether to emit the
40
+ * wire-format `provider: { only: [...] }` field. Exported for tests.
41
+ */
42
+ export function extractOnlyList(config: unknown): string[] {
43
+ const cfg = config as { openrouter?: { only?: unknown } } | undefined;
44
+ const only = cfg?.openrouter?.only;
45
+ if (!Array.isArray(only)) return [];
46
+ return only.filter((x): x is string => typeof x === "string" && x.length > 0);
47
+ }
48
+
49
+ /**
50
+ * Rewrite `options.config` for the Anthropic-compat path so OpenRouter's
51
+ * `provider: { only: [...] }` body field travels through `AnthropicProvider`'s
52
+ * `...restConfig` spread into `Anthropic.MessageStreamParams`. The `openrouter`
53
+ * key itself is removed because Anthropic's JSON parser doesn't know about it
54
+ * — only the translated `provider` field should reach the wire. Safe to inject
55
+ * here because `getAnthropicInner()` hardcodes OpenRouter's baseURL; the inner
56
+ * `AnthropicProvider` never talks to Anthropic directly. Exported for tests.
57
+ */
58
+ export function withOpenRouterBodyExtras(
59
+ options?: SendMessageOptions,
60
+ ): SendMessageOptions | undefined {
61
+ if (!options?.config) return options;
62
+ const only = extractOnlyList(options.config);
63
+ if (only.length === 0) return options;
64
+ const { openrouter: _openrouter, ...rest } = options.config as Record<
65
+ string,
66
+ unknown
67
+ >;
68
+ const existingProvider = (rest.provider ?? {}) as Record<string, unknown>;
69
+ return {
70
+ ...options,
71
+ config: { ...rest, provider: { ...existingProvider, only } },
72
+ };
73
+ }
74
+
34
75
  export class OpenRouterProvider extends OpenAIChatCompletionsProvider {
35
76
  private readonly openRouterApiKey: string;
36
77
  private readonly defaultModel: string;
37
78
  private readonly resolvedBaseURL: string;
38
79
  private readonly providerStreamTimeoutMs: number | undefined;
80
+ private readonly useNativeWebSearch: boolean;
39
81
  private anthropicInner: AnthropicProvider | undefined;
40
82
 
41
83
  constructor(
@@ -54,6 +96,7 @@ export class OpenRouterProvider extends OpenAIChatCompletionsProvider {
54
96
  this.defaultModel = model;
55
97
  this.resolvedBaseURL = baseURL;
56
98
  this.providerStreamTimeoutMs = options.streamTimeoutMs;
99
+ this.useNativeWebSearch = options.useNativeWebSearch ?? false;
57
100
  }
58
101
 
59
102
  // When routing to an `anthropic/*` model, actual API calls hit the Anthropic
@@ -72,15 +115,31 @@ export class OpenRouterProvider extends OpenAIChatCompletionsProvider {
72
115
  options?: SendMessageOptions,
73
116
  ): Promise<ProviderResponse> {
74
117
  const effectiveModel = this.resolveEffectiveModel(options);
75
- if (isAnthropicModel(effectiveModel)) {
76
- return this.getAnthropicInner().sendMessage(
77
- messages,
78
- tools,
79
- systemPrompt,
80
- options,
81
- );
118
+ try {
119
+ if (isAnthropicModel(effectiveModel)) {
120
+ return await this.getAnthropicInner().sendMessage(
121
+ messages,
122
+ tools,
123
+ systemPrompt,
124
+ withOpenRouterBodyExtras(options),
125
+ );
126
+ }
127
+ return await super.sendMessage(messages, tools, systemPrompt, options);
128
+ } catch (error) {
129
+ // Re-tag delegate-thrown ContextOverflowError so the outer provider name
130
+ // matches the configured provider ("openrouter"). This keeps downstream
131
+ // error reporting and metrics attribution accurate, while preserving the
132
+ // actualTokens/maxTokens extracted by the delegate.
133
+ if (isContextOverflowError(error) && error.provider !== this.name) {
134
+ throw new ContextOverflowError(error.message, this.name, {
135
+ actualTokens: error.actualTokens,
136
+ maxTokens: error.maxTokens,
137
+ statusCode: error.statusCode,
138
+ cause: error,
139
+ });
140
+ }
141
+ throw error;
82
142
  }
83
- return super.sendMessage(messages, tools, systemPrompt, options);
84
143
  }
85
144
 
86
145
  // OpenRouter's unified `reasoning` parameter controls extended thinking on
@@ -93,7 +152,14 @@ export class OpenRouterProvider extends OpenAIChatCompletionsProvider {
93
152
  ): Record<string, unknown> {
94
153
  const config = options?.config as Record<string, unknown> | undefined;
95
154
  const thinkingEnabled = config?.thinking !== undefined;
96
- return { reasoning: { enabled: thinkingEnabled } };
155
+ const extras: Record<string, unknown> = {
156
+ reasoning: { enabled: thinkingEnabled },
157
+ };
158
+ const only = extractOnlyList(config);
159
+ if (only.length > 0) {
160
+ extras.provider = { only };
161
+ }
162
+ return extras;
97
163
  }
98
164
 
99
165
  private resolveEffectiveModel(options?: SendMessageOptions): string {
@@ -114,6 +180,7 @@ export class OpenRouterProvider extends OpenAIChatCompletionsProvider {
114
180
  baseURL: toAnthropicMessagesBaseURL(this.resolvedBaseURL),
115
181
  streamTimeoutMs: this.providerStreamTimeoutMs,
116
182
  authToken: this.openRouterApiKey,
183
+ useNativeWebSearch: this.useNativeWebSearch,
117
184
  },
118
185
  );
119
186
  }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Provider env-var lookup helpers.
3
+ *
4
+ * Two sources of truth feed these helpers:
5
+ *
6
+ * 1. LLM providers — names come from `PROVIDER_CATALOG` in
7
+ * `model-catalog.ts`. `getLlmProviderEnvVar` consults the catalog
8
+ * directly.
9
+ * 2. Search providers — names mirror `meta/provider-env-vars.json`
10
+ * (the single source of truth for the macOS client bundle). The
11
+ * mirror is an inline constant here; parity is enforced by
12
+ * `assistant/src/providers/__tests__/provider-env-vars.test.ts`
13
+ * to prevent drift. We inline rather than read the JSON at runtime
14
+ * because the daemon is compiled to a binary and `meta/` is not
15
+ * reliably present at a known path on disk.
16
+ *
17
+ * Use `getLlmProviderEnvVar` when you're scoped to LLM providers,
18
+ * `getSearchProviderEnvVar` when you're scoped to search providers, and
19
+ * `getAnyProviderEnvVar` (LLM-first, then search) when you accept either
20
+ * kind — e.g. the generic `getProviderKeyAsync` env-var fallback.
21
+ *
22
+ * Each helper returns `undefined` for keyless providers (e.g. Ollama),
23
+ * unknown IDs, and providers outside the helper's scope.
24
+ */
25
+ import { PROVIDER_CATALOG } from "./model-catalog.js";
26
+
27
+ /**
28
+ * Search-provider env var names. Mirrors `meta/provider-env-vars.json`.
29
+ * Parity with the JSON file is enforced by `provider-env-vars.test.ts`.
30
+ */
31
+ export const SEARCH_PROVIDER_ENV_VAR_NAMES: Record<string, string> = {
32
+ brave: "BRAVE_API_KEY",
33
+ perplexity: "PERPLEXITY_API_KEY",
34
+ };
35
+
36
+ export function getLlmProviderEnvVar(providerId: string): string | undefined {
37
+ return PROVIDER_CATALOG.find((p) => p.id === providerId)?.envVar;
38
+ }
39
+
40
+ export function getSearchProviderEnvVar(
41
+ providerId: string,
42
+ ): string | undefined {
43
+ return SEARCH_PROVIDER_ENV_VAR_NAMES[providerId];
44
+ }
45
+
46
+ /**
47
+ * Resolve a provider env-var name from either source — LLM catalog first,
48
+ * then the search-provider mirror. Returns `undefined` when no provider
49
+ * scope declares an env var for the given ID (keyless LLM providers like
50
+ * Ollama, unknown IDs, etc.).
51
+ */
52
+ export function getAnyProviderEnvVar(providerId: string): string | undefined {
53
+ return (
54
+ getLlmProviderEnvVar(providerId) ?? getSearchProviderEnvVar(providerId)
55
+ );
56
+ }
@@ -4,7 +4,9 @@
4
4
  * and response extraction helpers.
5
5
  */
6
6
 
7
+ import { resolveCallSiteConfig } from "../config/llm-resolver.js";
7
8
  import { getConfig } from "../config/loader.js";
9
+ import type { LLMCallSite } from "../config/schemas/llm.js";
8
10
  import {
9
11
  getProvider,
10
12
  initializeProviders,
@@ -18,6 +20,10 @@ import type {
18
20
  ToolUseContent,
19
21
  } from "./types.js";
20
22
 
23
+ // Re-export the typed context-overflow error so callsites that dispatch on
24
+ // this category do not need to reach into `./types.js` directly.
25
+ export { ContextOverflowError, isContextOverflowError } from "./types.js";
26
+
21
27
  export interface ConfiguredProviderResult {
22
28
  provider: Provider;
23
29
  configuredProviderName: string;
@@ -36,9 +42,17 @@ let lazyInitPromise: Promise<void> | null = null;
36
42
  * If providers haven't been initialized yet (e.g. non-daemon code paths),
37
43
  * performs a one-shot `initializeProviders(getConfig())`.
38
44
  *
45
+ * The provider name is sourced from
46
+ * `resolveCallSiteConfig(callSite, config.llm).provider` — i.e. the unified
47
+ * `llm` block drives selection. The `callSite` argument is required so the
48
+ * resolver can layer per-call-site overrides; pass the closest matching
49
+ * call-site identifier from `LLMCallSiteEnum` when adding a new caller.
50
+ *
39
51
  * Returns `null` when no providers are available at all.
40
52
  */
41
- export async function resolveConfiguredProvider(): Promise<ConfiguredProviderResult | null> {
53
+ export async function resolveConfiguredProvider(
54
+ callSite: LLMCallSite,
55
+ ): Promise<ConfiguredProviderResult | null> {
42
56
  const config = getConfig();
43
57
 
44
58
  if (listProviders().length === 0) {
@@ -54,7 +68,7 @@ export async function resolveConfiguredProvider(): Promise<ConfiguredProviderRes
54
68
  }
55
69
  }
56
70
 
57
- const inferenceProvider = config.services.inference.provider;
71
+ const inferenceProvider = resolveCallSiteConfig(callSite, config.llm).provider;
58
72
 
59
73
  try {
60
74
  const provider = getProvider(inferenceProvider);
@@ -72,10 +86,13 @@ export async function resolveConfiguredProvider(): Promise<ConfiguredProviderRes
72
86
  * Thin wrapper around `resolveConfiguredProvider()` for callsites
73
87
  * that only need the Provider instance.
74
88
  *
75
- * Returns `null` when no providers are available.
89
+ * `callSite` is required see `resolveConfiguredProvider`. Returns `null`
90
+ * when no providers are available.
76
91
  */
77
- export async function getConfiguredProvider(): Promise<Provider | null> {
78
- const result = await resolveConfiguredProvider();
92
+ export async function getConfiguredProvider(
93
+ callSite: LLMCallSite,
94
+ ): Promise<Provider | null> {
95
+ const result = await resolveConfiguredProvider(callSite);
79
96
  return result?.provider ?? null;
80
97
  }
81
98
 
@@ -14,6 +14,10 @@ const log = getLogger("rate-limit");
14
14
  export class RateLimitProvider implements Provider {
15
15
  public readonly name: string;
16
16
 
17
+ get tokenEstimationProvider(): string | undefined {
18
+ return this.inner.tokenEstimationProvider;
19
+ }
20
+
17
21
  private requestTimestamps: number[];
18
22
 
19
23
  constructor(
@@ -7,6 +7,7 @@ import {
7
7
  buildManagedBaseUrl,
8
8
  resolveManagedProxyContext,
9
9
  } from "./managed-proxy/context.js";
10
+ import { isModelInCatalog } from "./model-catalog.js";
10
11
  import { getProviderDefaultModel } from "./model-intents.js";
11
12
  import { OllamaProvider } from "./ollama/client.js";
12
13
  import { OpenAIResponsesProvider } from "./openai/client.js";
@@ -51,8 +52,6 @@ export interface ProvidersConfig {
51
52
  services: {
52
53
  inference: {
53
54
  mode: "managed" | "your-own";
54
- provider: string;
55
- model: string;
56
55
  };
57
56
  "image-generation": {
58
57
  mode: "managed" | "your-own";
@@ -64,18 +63,28 @@ export interface ProvidersConfig {
64
63
  provider: string;
65
64
  };
66
65
  };
66
+ llm: {
67
+ default: {
68
+ provider: string;
69
+ model: string;
70
+ };
71
+ };
67
72
  timeouts?: { providerStreamTimeoutSec?: number };
68
73
  }
69
74
 
70
75
  function resolveModel(config: ProvidersConfig, providerName: string): string {
71
- const inferenceProvider = config.services.inference.provider;
72
- const inferenceModel = config.services.inference.model;
76
+ const inferenceProvider = config.llm.default.provider;
77
+ const inferenceModel = config.llm.default.model;
73
78
  if (inferenceProvider === providerName) {
74
- // If a non-Anthropic provider is selected with the untouched global default
75
- // model, use a provider-appropriate fallback instead.
79
+ // If a non-Anthropic provider is selected but the configured model is
80
+ // still an Anthropic catalog model (current or previous default), use a
81
+ // provider-appropriate fallback instead. Checking the full Anthropic
82
+ // catalog rather than only the current default prevents stale persisted
83
+ // defaults (e.g. claude-opus-4-6) from being sent to non-Anthropic APIs
84
+ // after the catalog default changes.
76
85
  if (
77
86
  providerName !== "anthropic" &&
78
- inferenceModel === getProviderDefaultModel("anthropic")
87
+ isModelInCatalog("anthropic", inferenceModel)
79
88
  ) {
80
89
  return getProviderDefaultModel(providerName);
81
90
  }
@@ -175,6 +184,7 @@ export async function initializeProviders(
175
184
  "openai",
176
185
  new RetryProvider(
177
186
  new OpenAIResponsesProvider(openaiCreds.apiKey, model, {
187
+ useNativeWebSearch,
178
188
  streamTimeoutMs,
179
189
  ...(openaiCreds.baseURL ? { baseURL: openaiCreds.baseURL } : {}),
180
190
  }),
@@ -203,7 +213,7 @@ export async function initializeProviders(
203
213
 
204
214
  // Ollama (keyless provider — always init when configured or key present)
205
215
  const ollamaKey = await getProviderKeyAsync("ollama");
206
- if (config.services.inference.provider === "ollama" || ollamaKey) {
216
+ if (config.llm.default.provider === "ollama" || ollamaKey) {
207
217
  const model = resolveModel(config, "ollama");
208
218
  registerProvider(
209
219
  "ollama",
@@ -240,6 +250,7 @@ export async function initializeProviders(
240
250
  "openrouter",
241
251
  new RetryProvider(
242
252
  new OpenRouterProvider(openrouterKey, model, {
253
+ useNativeWebSearch,
243
254
  streamTimeoutMs,
244
255
  }),
245
256
  ),