@vellumai/assistant 0.8.0 → 0.8.1

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 (692) hide show
  1. package/AGENTS.md +11 -0
  2. package/Dockerfile +5 -4
  3. package/README.md +2 -2
  4. package/docker-entrypoint.sh +16 -0
  5. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  6. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  7. package/eslint.config.mjs +12 -0
  8. package/knip.json +2 -1
  9. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  10. package/openapi.yaml +4847 -1698
  11. package/package.json +3 -1
  12. package/scripts/generate-openapi.ts +52 -4
  13. package/scripts/sync-llm-catalog.ts +165 -0
  14. package/scripts/sync-web-search-catalog.ts +107 -0
  15. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  16. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  17. package/src/__tests__/anthropic-provider.test.ts +92 -2
  18. package/src/__tests__/app-control-flow.test.ts +7 -0
  19. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  20. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  21. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  22. package/src/__tests__/btw-routes.test.ts +1 -0
  23. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  24. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  25. package/src/__tests__/channel-policy.test.ts +12 -0
  26. package/src/__tests__/checker.test.ts +89 -0
  27. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +35 -7
  28. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  29. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  30. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  31. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  32. package/src/__tests__/config-loader-platform-defaults.test.ts +77 -23
  33. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  34. package/src/__tests__/config-schema.test.ts +14 -3
  35. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  36. package/src/__tests__/config-set-route.test.ts +198 -0
  37. package/src/__tests__/config-watcher.test.ts +6 -0
  38. package/src/__tests__/contacts-tools.test.ts +51 -199
  39. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  40. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  41. package/src/__tests__/context-search-conversations-source.test.ts +42 -16
  42. package/src/__tests__/context-search-fanout.test.ts +20 -157
  43. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
  44. package/src/__tests__/context-search-types.test.ts +7 -2
  45. package/src/__tests__/context-window-manager.test.ts +389 -1
  46. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  47. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  48. package/src/__tests__/conversation-error.test.ts +38 -0
  49. package/src/__tests__/conversation-fork-crud.test.ts +241 -1
  50. package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
  51. package/src/__tests__/conversation-init.benchmark.test.ts +1 -0
  52. package/src/__tests__/conversation-lifecycle.test.ts +124 -0
  53. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  54. package/src/__tests__/conversation-process-callsite.test.ts +21 -1
  55. package/src/__tests__/conversation-runtime-assembly.test.ts +4 -4
  56. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  57. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  58. package/src/__tests__/credential-security-invariants.test.ts +5 -6
  59. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  60. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  61. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  62. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  63. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  64. package/src/__tests__/external-plugin-loader.test.ts +458 -0
  65. package/src/__tests__/filing-service.test.ts +23 -3
  66. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  67. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  68. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  69. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -8
  70. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  71. package/src/__tests__/heartbeat-service.test.ts +50 -233
  72. package/src/__tests__/history-repair.test.ts +89 -0
  73. package/src/__tests__/host-app-control-proxy.test.ts +109 -1
  74. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  75. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  76. package/src/__tests__/host-browser-routes.test.ts +325 -33
  77. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  78. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  79. package/src/__tests__/inference-profile-reaper.test.ts +154 -0
  80. package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
  81. package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
  82. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  83. package/src/__tests__/install-skill-routing.test.ts +2 -2
  84. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +15 -0
  85. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  86. package/src/__tests__/llm-catalog-parity.test.ts +146 -0
  87. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
  88. package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
  89. package/src/__tests__/llm-resolver.test.ts +46 -0
  90. package/src/__tests__/managed-profile-guard.test.ts +131 -2
  91. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  92. package/src/__tests__/mcp-cli.test.ts +182 -220
  93. package/src/__tests__/mcp-health-check.test.ts +56 -27
  94. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  95. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  96. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  97. package/src/__tests__/oauth-cli.test.ts +38 -2009
  98. package/src/__tests__/oauth-commands-routes.test.ts +711 -0
  99. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  100. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  101. package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
  102. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  103. package/src/__tests__/plugin-bootstrap.test.ts +31 -2
  104. package/src/__tests__/plugin-route-contribution.test.ts +31 -3
  105. package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
  106. package/src/__tests__/plugin-types.test.ts +13 -11
  107. package/src/__tests__/process-message-background-slack.test.ts +46 -0
  108. package/src/__tests__/profile-entry-status.test.ts +43 -0
  109. package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
  110. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  111. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  112. package/src/__tests__/relay-server.test.ts +118 -0
  113. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  114. package/src/__tests__/schedule-retry.test.ts +56 -4
  115. package/src/__tests__/schedule-routes.test.ts +104 -0
  116. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  117. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  118. package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
  119. package/src/__tests__/scheduler-wake.test.ts +0 -63
  120. package/src/__tests__/secret-allowlist.test.ts +1 -0
  121. package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
  122. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  123. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  124. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  125. package/src/__tests__/skill-load-tool.test.ts +2 -4
  126. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  127. package/src/__tests__/suggestion-routes.test.ts +3 -3
  128. package/src/__tests__/sync-message-contract.test.ts +63 -0
  129. package/src/__tests__/task-scheduler.test.ts +88 -23
  130. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  131. package/src/__tests__/usage-cli.test.ts +11 -73
  132. package/src/__tests__/user-plugin-loader.test.ts +145 -0
  133. package/src/__tests__/vercel-config.test.ts +168 -0
  134. package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
  135. package/src/__tests__/web-search.test.ts +303 -2
  136. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  137. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
  138. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +53 -20
  139. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
  140. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  141. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  142. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  143. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  144. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  145. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  146. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  147. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  148. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  149. package/src/acp/resolve-agent.test.ts +25 -0
  150. package/src/acp/resolve-agent.ts +13 -2
  151. package/src/acp/session-manager.ts +14 -0
  152. package/src/approvals/guardian-request-resolvers.ts +32 -87
  153. package/src/calls/relay-server.ts +35 -0
  154. package/src/calls/relay-setup-router.ts +36 -0
  155. package/src/calls/types.ts +1 -0
  156. package/src/calls/voice-session-bridge.ts +23 -4
  157. package/src/channels/config.ts +14 -1
  158. package/src/channels/types.ts +1 -0
  159. package/src/cli/AGENTS.md +164 -4
  160. package/src/cli/__tests__/notifications.test.ts +54 -0
  161. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  162. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  163. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  164. package/src/cli/commands/__tests__/changelog.test.ts +593 -0
  165. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  166. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  167. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  168. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  169. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  170. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  171. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  172. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  173. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  174. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  175. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  176. package/src/cli/commands/__tests__/status.test.ts +249 -0
  177. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  178. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  179. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  180. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  181. package/src/cli/commands/attachment.ts +8 -3
  182. package/src/cli/commands/audit.ts +95 -64
  183. package/src/cli/commands/auth.ts +61 -58
  184. package/src/cli/commands/avatar.ts +276 -390
  185. package/src/cli/commands/backup.ts +409 -505
  186. package/src/cli/commands/bash.ts +9 -5
  187. package/src/cli/commands/browser.ts +28 -9
  188. package/src/cli/commands/cache.ts +9 -4
  189. package/src/cli/commands/changelog.ts +414 -0
  190. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  191. package/src/cli/commands/clients.ts +8 -3
  192. package/src/cli/commands/completions.ts +9 -9
  193. package/src/cli/commands/config.ts +102 -72
  194. package/src/cli/commands/contacts.ts +575 -696
  195. package/src/cli/commands/conversations-defer.ts +17 -69
  196. package/src/cli/commands/conversations-import.ts +90 -253
  197. package/src/cli/commands/conversations.ts +346 -436
  198. package/src/cli/commands/credential-execution.ts +9 -6
  199. package/src/cli/commands/credentials.ts +456 -736
  200. package/src/cli/commands/domain.ts +128 -206
  201. package/src/cli/commands/email.ts +606 -794
  202. package/src/cli/commands/gateway.ts +8 -1
  203. package/src/cli/commands/image-generation.ts +157 -205
  204. package/src/cli/commands/inference-providers.ts +352 -0
  205. package/src/cli/commands/inference-session.ts +415 -0
  206. package/src/cli/commands/inference.ts +87 -65
  207. package/src/cli/commands/keys.ts +8 -3
  208. package/src/cli/commands/mcp.ts +103 -287
  209. package/src/cli/commands/memory-v2.ts +162 -516
  210. package/src/cli/commands/notifications.ts +33 -7
  211. package/src/cli/commands/oauth/apps.ts +292 -261
  212. package/src/cli/commands/oauth/connect.ts +176 -297
  213. package/src/cli/commands/oauth/disconnect.ts +16 -215
  214. package/src/cli/commands/oauth/index.ts +49 -45
  215. package/src/cli/commands/oauth/mode.ts +43 -199
  216. package/src/cli/commands/oauth/ping.ts +17 -125
  217. package/src/cli/commands/oauth/providers.ts +732 -921
  218. package/src/cli/commands/oauth/request.ts +60 -350
  219. package/src/cli/commands/oauth/shared.ts +11 -121
  220. package/src/cli/commands/oauth/status.ts +31 -121
  221. package/src/cli/commands/oauth/token.ts +13 -55
  222. package/src/cli/commands/pending.ts +19 -10
  223. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  224. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  225. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  226. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  227. package/src/cli/commands/platform/connect.ts +16 -80
  228. package/src/cli/commands/platform/disconnect.ts +14 -112
  229. package/src/cli/commands/platform/index.ts +177 -246
  230. package/src/cli/commands/routes.ts +153 -336
  231. package/src/cli/commands/sequence.ts +316 -360
  232. package/src/cli/commands/skills.ts +449 -671
  233. package/src/cli/commands/status.ts +58 -37
  234. package/src/cli/commands/stt.ts +94 -262
  235. package/src/cli/commands/task.ts +14 -40
  236. package/src/cli/commands/trust.ts +8 -3
  237. package/src/cli/commands/tts.ts +162 -167
  238. package/src/cli/commands/ui.ts +35 -42
  239. package/src/cli/commands/usage.ts +188 -126
  240. package/src/cli/commands/watchers.ts +8 -3
  241. package/src/cli/commands/webhooks.ts +99 -193
  242. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  243. package/src/cli/lib/daemon-credential-client.ts +4 -5
  244. package/src/cli/lib/nested-value.ts +44 -0
  245. package/src/cli/lib/open-browser.ts +36 -0
  246. package/src/cli/lib/register-command.ts +19 -0
  247. package/src/cli/lib/time-ago.ts +34 -0
  248. package/src/cli/program.ts +2 -4
  249. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  250. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  251. package/src/cli/utils/conversation-id.ts +30 -0
  252. package/src/cli/utils/parse-duration.ts +41 -0
  253. package/src/config/acp-defaults.test.ts +5 -1
  254. package/src/config/acp-defaults.ts +11 -4
  255. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  256. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  257. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  258. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  259. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  260. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  261. package/src/config/bundled-tool-registry.ts +0 -2
  262. package/src/config/feature-flag-registry.json +16 -0
  263. package/src/config/llm-resolver.ts +16 -1
  264. package/src/config/loader.ts +76 -14
  265. package/src/config/raw-config-utils.ts +2 -30
  266. package/src/config/schema.ts +4 -0
  267. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  268. package/src/config/schemas/call-site-catalog.ts +29 -7
  269. package/src/config/schemas/llm-request-logs.ts +57 -0
  270. package/src/config/schemas/llm.ts +52 -2
  271. package/src/config/schemas/memory-retrospective.ts +48 -0
  272. package/src/config/schemas/memory-v2.ts +32 -1
  273. package/src/config/schemas/memory.ts +4 -0
  274. package/src/config/schemas/services.ts +15 -12
  275. package/src/config/seed-inference-profiles.ts +195 -134
  276. package/src/contacts/contact-store.ts +0 -61
  277. package/src/context/window-manager.ts +191 -5
  278. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +79 -0
  279. package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
  280. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  281. package/src/daemon/approval-generators.ts +23 -29
  282. package/src/daemon/config-watcher.ts +2 -0
  283. package/src/daemon/conversation-agent-loop-handlers.ts +24 -0
  284. package/src/daemon/conversation-agent-loop.ts +127 -97
  285. package/src/daemon/conversation-error.ts +21 -0
  286. package/src/daemon/conversation-lifecycle.ts +46 -5
  287. package/src/daemon/conversation-process.ts +36 -19
  288. package/src/daemon/conversation-runtime-assembly.ts +14 -5
  289. package/src/daemon/conversation-slash.ts +175 -23
  290. package/src/daemon/conversation-store.ts +17 -10
  291. package/src/daemon/conversation-surfaces.ts +76 -12
  292. package/src/daemon/conversation-tool-setup.ts +24 -14
  293. package/src/daemon/conversation.ts +48 -9
  294. package/src/daemon/external-plugins-bootstrap.ts +18 -8
  295. package/src/daemon/guardian-action-generators.ts +7 -22
  296. package/src/daemon/handlers/config-model.ts +8 -126
  297. package/src/daemon/handlers/config-slack-channel.ts +10 -7
  298. package/src/daemon/handlers/config-vercel.ts +3 -1
  299. package/src/daemon/handlers/skills.ts +84 -5
  300. package/src/daemon/history-repair.ts +33 -6
  301. package/src/daemon/host-app-control-proxy.ts +44 -19
  302. package/src/daemon/host-bash-proxy.ts +85 -158
  303. package/src/daemon/host-browser-proxy.ts +96 -35
  304. package/src/daemon/host-proxy-base.ts +13 -1
  305. package/src/daemon/host-proxy-preactivation.ts +25 -1
  306. package/src/daemon/identity-helpers.ts +19 -0
  307. package/src/daemon/lifecycle.ts +42 -43
  308. package/src/daemon/meet-host-supervisor.ts +15 -15
  309. package/src/daemon/memory-v2-startup.ts +9 -2
  310. package/src/daemon/message-protocol.ts +6 -0
  311. package/src/daemon/message-types/bookmarks.ts +18 -0
  312. package/src/daemon/message-types/conversations.ts +12 -9
  313. package/src/daemon/message-types/messages.ts +9 -1
  314. package/src/daemon/message-types/sync.ts +60 -0
  315. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  316. package/src/daemon/pkb-reminder-builder.ts +21 -7
  317. package/src/daemon/process-message.ts +56 -23
  318. package/src/daemon/server.ts +23 -18
  319. package/src/daemon/shutdown-handlers.ts +0 -2
  320. package/src/daemon/tool-setup-types.ts +9 -0
  321. package/src/daemon/tool-side-effects.ts +6 -4
  322. package/src/daemon/wake-target-adapter.ts +11 -0
  323. package/src/export/transcript-formatter.ts +61 -2
  324. package/src/filing/filing-service.ts +40 -53
  325. package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
  326. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  327. package/src/heartbeat/heartbeat-service.ts +148 -127
  328. package/src/home/__tests__/feed-types.test.ts +63 -131
  329. package/src/home/__tests__/feed-writer.test.ts +77 -278
  330. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  331. package/src/home/feed-types.ts +19 -73
  332. package/src/home/feed-writer.ts +25 -156
  333. package/src/home/post-connect-feed.ts +1 -3
  334. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  335. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  336. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  337. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  338. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  339. package/src/ipc/assistant-server.ts +55 -6
  340. package/src/ipc/cli-client.ts +370 -50
  341. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  342. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  343. package/src/ipc/skill-routes/events.ts +30 -3
  344. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  345. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  346. package/src/live-voice/live-voice-session-manager.ts +11 -4
  347. package/src/live-voice/live-voice-session.ts +14 -6
  348. package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
  349. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  350. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  351. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  352. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  353. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  354. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
  355. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  356. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  357. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  358. package/src/memory/bookmark-crud.ts +179 -0
  359. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  360. package/src/memory/context-search/agent-protocol.ts +5 -1
  361. package/src/memory/context-search/agent-runner.ts +60 -85
  362. package/src/memory/context-search/limits.ts +1 -4
  363. package/src/memory/context-search/search.ts +23 -113
  364. package/src/memory/context-search/sources/conversations.ts +18 -6
  365. package/src/memory/context-search/sources/memory-v2.ts +39 -14
  366. package/src/memory/context-search/sources/memory.ts +7 -0
  367. package/src/memory/context-search/sources/workspace.ts +13 -10
  368. package/src/memory/context-search/types.ts +1 -1
  369. package/src/memory/conversation-bootstrap.ts +11 -0
  370. package/src/memory/conversation-crud.ts +312 -10
  371. package/src/memory/conversation-queries.ts +9 -5
  372. package/src/memory/conversation-title-service.ts +1 -0
  373. package/src/memory/conversation-types.ts +16 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +2 -1
  376. package/src/memory/embedding-runtime-manager.ts +1 -2
  377. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  378. package/src/memory/graph/conversation-graph-memory.ts +76 -5
  379. package/src/memory/graph/extraction.ts +4 -0
  380. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  381. package/src/memory/graph/tool-handlers.ts +17 -7
  382. package/src/memory/graph/tools.ts +44 -5
  383. package/src/memory/indexer.ts +17 -0
  384. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +13 -15
  385. package/src/memory/jobs/embed-concept-page.ts +45 -9
  386. package/src/memory/jobs-store.ts +51 -1
  387. package/src/memory/jobs-worker.ts +52 -3
  388. package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
  389. package/src/memory/llm-request-log-source-local.ts +26 -0
  390. package/src/memory/llm-request-log-source.ts +97 -0
  391. package/src/memory/llm-request-log-store.ts +1 -1
  392. package/src/memory/memory-retrospective-constants.ts +13 -0
  393. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  394. package/src/memory/memory-retrospective-job.ts +351 -0
  395. package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
  396. package/src/memory/memory-retrospective-state.ts +162 -0
  397. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  398. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  399. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  400. package/src/memory/message-content.ts +38 -1
  401. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  402. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  403. package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
  404. package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
  405. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  406. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  407. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  408. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  409. package/src/memory/migrations/243-provider-connections.ts +68 -0
  410. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  411. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  412. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  413. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  414. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  415. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  416. package/src/memory/migrations/index.ts +7 -0
  417. package/src/memory/published-pages-store.ts +16 -0
  418. package/src/memory/schema/bookmarks.ts +38 -0
  419. package/src/memory/schema/conversations.ts +2 -0
  420. package/src/memory/schema/index.ts +2 -0
  421. package/src/memory/schema/inference.ts +29 -0
  422. package/src/memory/schema/memory-core.ts +9 -0
  423. package/src/memory/search/semantic.ts +1 -4
  424. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  425. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  426. package/src/memory/v2/__tests__/activation.test.ts +11 -4
  427. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  428. package/src/memory/v2/__tests__/consolidation-job.test.ts +123 -135
  429. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  430. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  431. package/src/memory/v2/__tests__/injection.test.ts +628 -10
  432. package/src/memory/v2/__tests__/migration.test.ts +7 -3
  433. package/src/memory/v2/__tests__/page-index.test.ts +277 -0
  434. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  435. package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
  436. package/src/memory/v2/__tests__/qdrant.test.ts +72 -0
  437. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  438. package/src/memory/v2/__tests__/router.test.ts +516 -0
  439. package/src/memory/v2/__tests__/sim.test.ts +45 -1
  440. package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
  441. package/src/memory/v2/__tests__/static-context.test.ts +7 -22
  442. package/src/memory/v2/__tests__/sweep-job.test.ts +95 -0
  443. package/src/memory/v2/activation-store.ts +34 -5
  444. package/src/memory/v2/activation.ts +40 -27
  445. package/src/memory/v2/backfill-jobs.ts +17 -84
  446. package/src/memory/v2/consolidation-job.ts +85 -78
  447. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  448. package/src/memory/v2/injection.ts +440 -109
  449. package/src/memory/v2/migration.ts +117 -20
  450. package/src/memory/v2/page-index.ts +191 -0
  451. package/src/memory/v2/page-store.ts +3 -0
  452. package/src/memory/v2/prompts/consolidation.ts +9 -7
  453. package/src/memory/v2/prompts/router.ts +192 -0
  454. package/src/memory/v2/qdrant.ts +100 -87
  455. package/src/memory/v2/reranker.ts +14 -7
  456. package/src/memory/v2/router.ts +322 -0
  457. package/src/memory/v2/sim.ts +25 -12
  458. package/src/memory/v2/skill-store.ts +118 -29
  459. package/src/memory/v2/static-context.ts +16 -9
  460. package/src/memory/v2/sweep-job.ts +122 -96
  461. package/src/memory/v2/types.ts +10 -6
  462. package/src/memory/validation.ts +13 -0
  463. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  464. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  465. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  466. package/src/notifications/adapters/platform.ts +171 -0
  467. package/src/notifications/conversation-pairing.ts +2 -2
  468. package/src/notifications/copy-composer.ts +15 -0
  469. package/src/notifications/destination-resolver.ts +21 -0
  470. package/src/notifications/emit-signal.ts +28 -1
  471. package/src/notifications/home-feed-side-effect.ts +111 -0
  472. package/src/notifications/signal.ts +5 -0
  473. package/src/permissions/checker.ts +12 -0
  474. package/src/permissions/ipc-risk-types.ts +2 -0
  475. package/src/plugin-api/index.ts +13 -0
  476. package/src/plugin-api/package.json +12 -0
  477. package/src/plugin-api/types.ts +62 -0
  478. package/src/plugins/defaults/injectors.ts +19 -3
  479. package/src/plugins/external-plugin-loader.ts +294 -0
  480. package/src/plugins/types.ts +46 -30
  481. package/src/plugins/user-loader.ts +64 -41
  482. package/src/proactive-artifact/job.test.ts +12 -4
  483. package/src/proactive-artifact/job.ts +4 -0
  484. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  485. package/src/proactive-artifact/trigger-state.ts +4 -0
  486. package/src/prompts/__tests__/system-prompt.test.ts +105 -0
  487. package/src/prompts/system-prompt.ts +22 -1
  488. package/src/prompts/update-bulletin-job.ts +61 -73
  489. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  490. package/src/providers/__tests__/inference.test.ts +288 -0
  491. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  492. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  493. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  494. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  495. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  496. package/src/providers/anthropic/client.ts +95 -26
  497. package/src/providers/call-site-routing.ts +94 -16
  498. package/src/providers/connection-resolution.ts +163 -0
  499. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  500. package/src/providers/inference/adapter-factory.ts +173 -0
  501. package/src/providers/inference/auth.ts +112 -0
  502. package/src/providers/inference/backfill.ts +196 -0
  503. package/src/providers/inference/connections.ts +356 -0
  504. package/src/providers/inference/resolve-auth.ts +65 -0
  505. package/src/providers/model-catalog.ts +104 -6
  506. package/src/providers/openai/responses-provider.ts +4 -2
  507. package/src/providers/provider-env-vars.ts +17 -7
  508. package/src/providers/provider-secret-catalog.ts +49 -30
  509. package/src/providers/provider-send-message.ts +41 -20
  510. package/src/providers/registry.ts +143 -159
  511. package/src/providers/retry.ts +18 -10
  512. package/src/providers/search-provider-catalog.ts +121 -0
  513. package/src/runtime/AGENTS.md +18 -5
  514. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  515. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  516. package/src/runtime/actor-trust-resolver.ts +32 -10
  517. package/src/runtime/agent-wake.ts +35 -6
  518. package/src/runtime/assistant-event-hub.ts +3 -85
  519. package/src/runtime/auth/route-policy.ts +303 -8
  520. package/src/runtime/auth/same-actor.ts +2 -0
  521. package/src/runtime/background-job-runner.ts +339 -0
  522. package/src/runtime/btw-sidechain.ts +1 -0
  523. package/src/runtime/http-router.ts +36 -1
  524. package/src/runtime/http-server.ts +31 -5
  525. package/src/runtime/http-types.ts +2 -0
  526. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  527. package/src/runtime/middleware/request-logger.ts +62 -1
  528. package/src/runtime/pre-first-message-gate.ts +83 -0
  529. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  530. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
  531. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  532. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
  533. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
  534. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  535. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  536. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +4 -4
  537. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  538. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  539. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  540. package/src/runtime/routes/acp-routes.ts +10 -8
  541. package/src/runtime/routes/app-management-routes.ts +228 -3
  542. package/src/runtime/routes/approval-routes.ts +0 -18
  543. package/src/runtime/routes/audit-routes.ts +43 -0
  544. package/src/runtime/routes/auth-routes.ts +72 -0
  545. package/src/runtime/routes/avatar-routes.ts +273 -20
  546. package/src/runtime/routes/backup-routes.ts +406 -2
  547. package/src/runtime/routes/bookmark-routes.ts +154 -0
  548. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  549. package/src/runtime/routes/contact-routes.ts +0 -160
  550. package/src/runtime/routes/conversation-cli-routes.ts +192 -0
  551. package/src/runtime/routes/conversation-management-routes.ts +30 -43
  552. package/src/runtime/routes/conversation-query-routes.ts +334 -86
  553. package/src/runtime/routes/conversation-routes.ts +31 -10
  554. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  555. package/src/runtime/routes/credential-routes.ts +540 -0
  556. package/src/runtime/routes/debug-routes.ts +2 -2
  557. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  558. package/src/runtime/routes/domain-routes.ts +167 -0
  559. package/src/runtime/routes/email-routes.ts +603 -0
  560. package/src/runtime/routes/errors.ts +2 -2
  561. package/src/runtime/routes/events-routes.ts +192 -0
  562. package/src/runtime/routes/home-feed-routes.ts +6 -78
  563. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  564. package/src/runtime/routes/host-browser-routes.ts +103 -22
  565. package/src/runtime/routes/http-adapter.ts +2 -0
  566. package/src/runtime/routes/identity-routes.ts +5 -0
  567. package/src/runtime/routes/image-generation-routes.ts +99 -0
  568. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
  569. package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
  570. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  571. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -4
  572. package/src/runtime/routes/index.ts +36 -0
  573. package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
  574. package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
  575. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  576. package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
  577. package/src/runtime/routes/inference-send-routes.ts +115 -0
  578. package/src/runtime/routes/integrations/twilio.ts +1 -0
  579. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  580. package/src/runtime/routes/memory-v2-routes.ts +13 -398
  581. package/src/runtime/routes/notification-routes.ts +2 -0
  582. package/src/runtime/routes/oauth-apps.ts +112 -7
  583. package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
  584. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  585. package/src/runtime/routes/oauth-providers.ts +298 -8
  586. package/src/runtime/routes/platform-routes.ts +336 -0
  587. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  588. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  589. package/src/runtime/routes/playground/state.ts +2 -1
  590. package/src/runtime/routes/publish-routes.ts +221 -0
  591. package/src/runtime/routes/schedule-routes.ts +82 -0
  592. package/src/runtime/routes/sequence-routes.ts +291 -0
  593. package/src/runtime/routes/settings-routes.ts +2 -10
  594. package/src/runtime/routes/skills-routes.ts +31 -1
  595. package/src/runtime/routes/stt-routes.ts +240 -3
  596. package/src/runtime/routes/surface-action-routes.ts +43 -7
  597. package/src/runtime/routes/tts-routes.ts +67 -0
  598. package/src/runtime/routes/types.ts +32 -0
  599. package/src/runtime/routes/user-routes-cli.ts +243 -0
  600. package/src/runtime/routes/webhook-routes.ts +165 -0
  601. package/src/runtime/sync/resource-sync-events.ts +25 -0
  602. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  603. package/src/runtime/sync/sync-publisher.ts +21 -0
  604. package/src/schedule/scheduler.ts +200 -123
  605. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  606. package/src/security/secret-patterns.ts +3 -0
  607. package/src/sequence/engine.ts +38 -40
  608. package/src/subagent/manager.ts +20 -15
  609. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  610. package/src/tools/browser/browser-execution.ts +15 -4
  611. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  612. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  613. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  614. package/src/tools/browser/cdp-client/factory.ts +66 -5
  615. package/src/tools/browser/runtime-check.ts +77 -0
  616. package/src/tools/memory/register.test.ts +3 -3
  617. package/src/tools/memory/register.ts +9 -1
  618. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  619. package/src/tools/network/web-search.ts +280 -37
  620. package/src/tools/permission-checker.ts +13 -5
  621. package/src/tools/subagent/spawn.ts +3 -3
  622. package/src/tools/terminal/shell.ts +44 -0
  623. package/src/usage/attribution.ts +3 -2
  624. package/src/util/pricing.ts +86 -160
  625. package/src/watcher/__tests__/engine.test.ts +301 -0
  626. package/src/watcher/constants.ts +7 -0
  627. package/src/watcher/engine.ts +90 -90
  628. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  629. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  630. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
  631. package/src/workspace/migrations/069-seed-onboarding-threads.ts +8 -2
  632. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
  633. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
  634. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  635. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  636. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  637. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  638. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  639. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  640. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  641. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  642. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  643. package/src/workspace/migrations/registry.ts +22 -0
  644. package/src/workspace/migrations/runner.ts +13 -2
  645. package/src/workspace/migrations/types.ts +13 -3
  646. package/src/workspace/provider-commit-message-generator.ts +3 -2
  647. package/src/__tests__/context-search-pkb-source.test.ts +0 -498
  648. package/src/__tests__/credentials-cli.test.ts +0 -1225
  649. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  650. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  651. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  652. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  653. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  654. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  655. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  656. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  657. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  658. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  659. package/src/cli/commands/autonomy.ts +0 -365
  660. package/src/cli/commands/memory.ts +0 -424
  661. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -947
  662. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  663. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  664. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  665. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  666. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  667. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  668. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  669. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  670. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  671. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  672. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  673. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  674. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  675. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  676. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  677. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  678. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  679. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  680. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  681. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  682. package/src/home/assistant-feed-authoring.ts +0 -135
  683. package/src/home/emit-feed-event.ts +0 -169
  684. package/src/home/feed-scheduler.ts +0 -281
  685. package/src/home/platform-gmail-digest.ts +0 -163
  686. package/src/home/rewrite-command-preview.ts +0 -66
  687. package/src/home/rewrite-feed-title.ts +0 -58
  688. package/src/home/rollup-producer.ts +0 -426
  689. package/src/memory/admin.ts +0 -326
  690. package/src/memory/context-search/sources/pkb.ts +0 -476
  691. package/src/memory/graph/compaction.ts +0 -299
  692. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -0,0 +1,279 @@
1
+ /**
2
+ * Dispatcher gate test — proves that `resolveConfiguredProvider` routes
3
+ * through `resolveProviderFromConnection` for every dispatch when a profile
4
+ * names a `provider_connection`, AND that misconfigurations now fail loudly
5
+ * rather than silently rerouting to a legacy registry.
6
+ *
7
+ * Hard config errors (missing connection name, unknown connection,
8
+ * provider mismatch) throw `ConnectionResolutionError`. Soft credential
9
+ * failures (resolver returns null) still return null so callers can
10
+ * degrade gracefully.
11
+ *
12
+ * Hard gates:
13
+ * 1. Two profiles, same provider, different `provider_connection` →
14
+ * resolver called twice with the right connection each time, with
15
+ * auth bundles distinguishable per profile (mix-and-match goal #2
16
+ * of the design).
17
+ * 2. Profile WITHOUT `provider_connection` → throws
18
+ * `ConnectionResolutionError` (configuration bug; backfill should
19
+ * have populated it).
20
+ * 3. `provider_connection` set but unknown → throws (loud config error).
21
+ * 4. `provider_connection` set, found, but resolver returns null →
22
+ * returns null (soft credential failure; satellite caller decides
23
+ * what to do).
24
+ */
25
+
26
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
27
+
28
+ // ---------------------------------------------------------------------------
29
+ // Module mocks (must be declared before the import-under-test).
30
+ // ---------------------------------------------------------------------------
31
+
32
+ mock.module("../../util/logger.js", () => ({
33
+ getLogger: () =>
34
+ new Proxy({} as Record<string, unknown>, { get: () => () => {} }),
35
+ }));
36
+
37
+ // Test fixtures for the mocked config loader.
38
+ let mockLlmConfig: Record<string, unknown> = {};
39
+
40
+ mock.module("../../config/loader.js", () => ({
41
+ getConfig: () => ({
42
+ llm: mockLlmConfig,
43
+ services: { inference: { mode: "your-own" } },
44
+ }),
45
+ }));
46
+
47
+ // Mock the DB getter — we never actually hit SQLite since `getConnection` is
48
+ // also mocked. Returning a sentinel keeps the call signature satisfied.
49
+ const mockDbSentinel = { __mock: "db" };
50
+ mock.module("../../memory/db-connection.js", () => ({
51
+ getDb: () => mockDbSentinel,
52
+ }));
53
+
54
+ // Spy storage for the resolver — each test inspects what was passed in.
55
+ type Connection = {
56
+ name: string;
57
+ provider: string;
58
+ auth: { type: string; credential?: string };
59
+ };
60
+
61
+ const resolveProviderCalls: Connection[] = [];
62
+
63
+ // Each connection name maps to a distinct fake Provider instance. Returning
64
+ // distinguishable instances lets the test assert that two profiles with
65
+ // different connections route to different providers.
66
+ const fakeProviders = new Map<string, { name: string; tag: string }>();
67
+
68
+ // Connection registry the mocked `getConnection` reads from.
69
+ const fakeConnections = new Map<string, Connection>();
70
+
71
+ mock.module("../inference/connections.js", () => ({
72
+ getConnection: (_db: unknown, name: string) =>
73
+ fakeConnections.get(name) ?? null,
74
+ }));
75
+
76
+ mock.module("../registry.js", () => ({
77
+ // The dispatch path does not import getProvider.
78
+ // Kept here only because other test files share this mock module shape.
79
+ getProvider: (name: string) => {
80
+ throw new Error(`legacy getProvider should not be called: ${name}`);
81
+ },
82
+ initializeProviders: async () => {},
83
+ listProviders: () => Array.from(fakeProviders.values()),
84
+ // The function under test — wraps the dispatcher's connection-aware path.
85
+ resolveProviderFromConnection: async (connection: Connection) => {
86
+ resolveProviderCalls.push(connection);
87
+ return fakeProviders.get(`conn:${connection.name}`) ?? null;
88
+ },
89
+ }));
90
+
91
+ // ---------------------------------------------------------------------------
92
+ // Imports (after mocks).
93
+ // ---------------------------------------------------------------------------
94
+
95
+ import { ConnectionResolutionError } from "../connection-resolution.js";
96
+ import { getConfiguredProvider } from "../provider-send-message.js";
97
+
98
+ // ---------------------------------------------------------------------------
99
+ // Helpers
100
+ // ---------------------------------------------------------------------------
101
+
102
+ function setLlmConfig(c: Record<string, unknown>): void {
103
+ mockLlmConfig = c;
104
+ }
105
+
106
+ function registerConnection(
107
+ c: Connection,
108
+ providerStub: { name: string; tag: string },
109
+ ): void {
110
+ fakeConnections.set(c.name, c);
111
+ fakeProviders.set(`conn:${c.name}`, providerStub);
112
+ }
113
+
114
+ function reset(): void {
115
+ resolveProviderCalls.length = 0;
116
+ fakeConnections.clear();
117
+ fakeProviders.clear();
118
+ mockLlmConfig = {};
119
+ }
120
+
121
+ // ---------------------------------------------------------------------------
122
+ // Tests
123
+ // ---------------------------------------------------------------------------
124
+
125
+ describe("dispatch routes through provider_connection (Phase 1: connection-only)", () => {
126
+ beforeEach(reset);
127
+
128
+ test("two profiles, same provider, different connections → resolver called twice with the right connection each time", async () => {
129
+ // Same underlying provider impl, two distinguishable connection-bound
130
+ // Provider stubs.
131
+ registerConnection(
132
+ {
133
+ name: "anthropic-managed",
134
+ provider: "anthropic",
135
+ auth: { type: "platform" },
136
+ },
137
+ { name: "anthropic", tag: "managed-stub" },
138
+ );
139
+ registerConnection(
140
+ {
141
+ name: "anthropic-personal",
142
+ provider: "anthropic",
143
+ auth: {
144
+ type: "api_key",
145
+ credential: "credential/test/anthropic",
146
+ },
147
+ },
148
+ { name: "anthropic", tag: "personal-stub" },
149
+ );
150
+
151
+ setLlmConfig({
152
+ default: { provider: "anthropic", model: "claude-opus-4-7" },
153
+ profiles: {
154
+ "anthropic-managed-profile": {
155
+ provider: "anthropic",
156
+ provider_connection: "anthropic-managed",
157
+ },
158
+ "anthropic-personal-profile": {
159
+ provider: "anthropic",
160
+ provider_connection: "anthropic-personal",
161
+ },
162
+ },
163
+ });
164
+
165
+ const managedResult = await getConfiguredProvider("mainAgent", {
166
+ overrideProfile: "anthropic-managed-profile",
167
+ });
168
+ const personalResult = await getConfiguredProvider("mainAgent", {
169
+ overrideProfile: "anthropic-personal-profile",
170
+ });
171
+
172
+ // Hard gate #1: the resolver was called — at all.
173
+ expect(resolveProviderCalls.length).toBe(2);
174
+
175
+ // Hard gate #2: each call received the right connection by name.
176
+ expect(resolveProviderCalls[0].name).toBe("anthropic-managed");
177
+ expect(resolveProviderCalls[1].name).toBe("anthropic-personal");
178
+
179
+ // Hard gate #3: the auth bundle on the connection matches what we'd
180
+ // expect at adapter-call time. Different auth types per profile = mix-
181
+ // and-match works.
182
+ expect(resolveProviderCalls[0].auth.type).toBe("platform");
183
+ expect(resolveProviderCalls[1].auth.type).toBe("api_key");
184
+ expect(resolveProviderCalls[1].auth.credential).toBe(
185
+ "credential/test/anthropic",
186
+ );
187
+
188
+ // Sanity: dispatch returned non-null for both.
189
+ expect(managedResult).not.toBeNull();
190
+ expect(personalResult).not.toBeNull();
191
+ });
192
+
193
+ test("profile WITHOUT provider_connection returns null (graceful fallback)", async () => {
194
+ setLlmConfig({
195
+ default: { provider: "anthropic", model: "claude-opus-4-7" },
196
+ profiles: {
197
+ "legacy-profile": {
198
+ provider: "anthropic",
199
+ // no provider_connection — boot-time backfill is expected to
200
+ // populate this in production. When unset, the per-callsite
201
+ // resolver returns null so callsites with deterministic
202
+ // fallbacks (invite instructions, telegram resolution, etc.)
203
+ // keep working. Hard config errors (lookup failed, mismatch)
204
+ // still throw via tryResolveProviderForConnectionName.
205
+ },
206
+ },
207
+ });
208
+
209
+ const result = await getConfiguredProvider("mainAgent", {
210
+ overrideProfile: "legacy-profile",
211
+ });
212
+
213
+ expect(result).toBeNull();
214
+ // Resolver must NOT have been called — short-circuited before reaching it.
215
+ expect(resolveProviderCalls.length).toBe(0);
216
+ });
217
+
218
+ test("provider_connection set but unknown → throws ConnectionResolutionError(not_found)", async () => {
219
+ // No connection registered — the dispatcher should throw with reason
220
+ // 'not_found' rather than falling through to a legacy lookup.
221
+ setLlmConfig({
222
+ default: { provider: "anthropic", model: "claude-opus-4-7" },
223
+ profiles: {
224
+ broken: {
225
+ provider: "anthropic",
226
+ provider_connection: "does-not-exist",
227
+ },
228
+ },
229
+ });
230
+
231
+ let caught: unknown;
232
+ try {
233
+ await getConfiguredProvider("mainAgent", { overrideProfile: "broken" });
234
+ } catch (err) {
235
+ caught = err;
236
+ }
237
+
238
+ expect(caught).toBeInstanceOf(ConnectionResolutionError);
239
+ expect((caught as ConnectionResolutionError).reason).toBe("not_found");
240
+ expect((caught as ConnectionResolutionError).connectionName).toBe(
241
+ "does-not-exist",
242
+ );
243
+ // Resolver was NOT called (lookup failed before reaching it).
244
+ expect(resolveProviderCalls.length).toBe(0);
245
+ });
246
+
247
+ test("provider_connection set, connection found, but resolver returns null → returns null (soft credential failure)", async () => {
248
+ // Connection exists but resolver returns null (e.g., missing credential).
249
+ fakeConnections.set("anthropic-broken-personal", {
250
+ name: "anthropic-broken-personal",
251
+ provider: "anthropic",
252
+ auth: { type: "api_key", credential: "credential/missing" },
253
+ });
254
+ // Intentionally do NOT register a fakeProviders entry for
255
+ // `conn:anthropic-broken-personal` — resolver returns null.
256
+
257
+ setLlmConfig({
258
+ default: { provider: "anthropic", model: "claude-opus-4-7" },
259
+ profiles: {
260
+ "broken-creds": {
261
+ provider: "anthropic",
262
+ provider_connection: "anthropic-broken-personal",
263
+ },
264
+ },
265
+ });
266
+
267
+ const result = await getConfiguredProvider("mainAgent", {
268
+ overrideProfile: "broken-creds",
269
+ });
270
+
271
+ // Resolver WAS called — but returned null. No legacy fallback.
272
+ expect(resolveProviderCalls.length).toBe(1);
273
+ expect(resolveProviderCalls[0].name).toBe("anthropic-broken-personal");
274
+ // Soft credential failure → null result. Satellite callers handle null
275
+ // however they want (rollup producer skips, others throw a domain-
276
+ // specific error).
277
+ expect(result).toBeNull();
278
+ });
279
+ });
@@ -0,0 +1,288 @@
1
+ /**
2
+ * Tests for provider_connections: migration, CRUD, and
3
+ * mix-and-match E2E (two profiles, same provider, different connections).
4
+ */
5
+
6
+ import { Database } from "bun:sqlite";
7
+ import { describe, expect, test } from "bun:test";
8
+
9
+ import { drizzle } from "drizzle-orm/bun-sqlite";
10
+
11
+ import type { DrizzleDb } from "../../memory/db-connection.js";
12
+ import { getSqliteFrom } from "../../memory/db-connection.js";
13
+ import { migrateCreateProviderConnections } from "../../memory/migrations/243-provider-connections.js";
14
+ import { migrateProviderConnectionStatusLabel } from "../../memory/migrations/244-provider-connection-status-label.js";
15
+ import * as schema from "../../memory/schema.js";
16
+ import { AuthSchema } from "../inference/auth.js";
17
+ import {
18
+ createConnection,
19
+ deleteConnection,
20
+ getConnection,
21
+ listConnections,
22
+ seedCanonicalConnections,
23
+ updateConnection,
24
+ } from "../inference/connections.js";
25
+
26
+ // ---------------------------------------------------------------------------
27
+ // Setup — each test gets a fresh in-memory DB
28
+ // ---------------------------------------------------------------------------
29
+
30
+ function setupDb(): { db: DrizzleDb; raw: Database } {
31
+ const sqlite = new Database(":memory:");
32
+ sqlite.exec("PRAGMA journal_mode=WAL");
33
+ sqlite.exec("PRAGMA foreign_keys = ON");
34
+ const db = drizzle(sqlite, { schema });
35
+ const raw = getSqliteFrom(db);
36
+ migrateCreateProviderConnections(db);
37
+ migrateProviderConnectionStatusLabel(db);
38
+ return { db, raw };
39
+ }
40
+
41
+ // ---------------------------------------------------------------------------
42
+ // Migration idempotency
43
+ // ---------------------------------------------------------------------------
44
+
45
+ describe("migrateCreateProviderConnections", () => {
46
+ test("creates the provider_connections table", () => {
47
+ const { raw } = setupDb();
48
+ const rows = raw.query("SELECT name FROM provider_connections").all() as { name: string }[];
49
+ expect(Array.isArray(rows)).toBe(true);
50
+ });
51
+
52
+ test("seeds canonical connections on first run", () => {
53
+ const { db } = setupDb();
54
+ const canonicals = ["anthropic-managed", "openai-managed", "gemini-managed"];
55
+ for (const name of canonicals) {
56
+ const conn = getConnection(db, name);
57
+ expect(conn).not.toBeNull();
58
+ }
59
+ });
60
+
61
+ test("canonical connections have correct auth types", () => {
62
+ const { db } = setupDb();
63
+ expect(getConnection(db, "anthropic-managed")?.auth.type).toBe("platform");
64
+ expect(getConnection(db, "openai-managed")?.auth.type).toBe("platform");
65
+ expect(getConnection(db, "gemini-managed")?.auth.type).toBe("platform");
66
+ });
67
+
68
+ test("seedCanonicalConnections is idempotent", () => {
69
+ const { db } = setupDb();
70
+ // Run twice — should not throw or create duplicates
71
+ seedCanonicalConnections(db);
72
+ seedCanonicalConnections(db);
73
+ const managed = listConnections(db, { provider: "anthropic" });
74
+ expect(managed.filter((c) => c.name === "anthropic-managed").length).toBe(1);
75
+ });
76
+ });
77
+
78
+ // ---------------------------------------------------------------------------
79
+ // Connection CRUD
80
+ // ---------------------------------------------------------------------------
81
+
82
+ describe("Connection CRUD", () => {
83
+ test("createConnection — happy path", () => {
84
+ const { db } = setupDb();
85
+ const result = createConnection(db, {
86
+ name: "my-anthropic",
87
+ provider: "anthropic",
88
+ auth: { type: "api_key", credential: "credential/anthropic/api_key" },
89
+ });
90
+ expect(result.ok).toBe(true);
91
+ if (!result.ok) return;
92
+ expect(result.connection.name).toBe("my-anthropic");
93
+ expect(result.connection.provider).toBe("anthropic");
94
+ expect(result.connection.auth.type).toBe("api_key");
95
+ });
96
+
97
+ test("createConnection — rejects unknown provider", () => {
98
+ const { db } = setupDb();
99
+ const result = createConnection(db, {
100
+ name: "bad-conn",
101
+ provider: "unknown-llm" as never,
102
+ auth: { type: "none" },
103
+ });
104
+ expect(result.ok).toBe(false);
105
+ if (result.ok) return;
106
+ expect(result.error.code).toBe("invalid_provider");
107
+ });
108
+
109
+ test("createConnection — rejects duplicate name", () => {
110
+ const { db } = setupDb();
111
+ createConnection(db, {
112
+ name: "dup-conn",
113
+ provider: "openai",
114
+ auth: { type: "platform" },
115
+ });
116
+ const result = createConnection(db, {
117
+ name: "dup-conn",
118
+ provider: "openai",
119
+ auth: { type: "platform" },
120
+ });
121
+ expect(result.ok).toBe(false);
122
+ if (result.ok) return;
123
+ expect(result.error.code).toBe("already_exists");
124
+ });
125
+
126
+ test("getConnection — returns null for unknown name", () => {
127
+ const { db } = setupDb();
128
+ expect(getConnection(db, "nonexistent")).toBeNull();
129
+ });
130
+
131
+ test("listConnections — filters by provider", () => {
132
+ const { db } = setupDb();
133
+ createConnection(db, {
134
+ name: "test-openai",
135
+ provider: "openai",
136
+ auth: { type: "api_key", credential: "credential/openai/api_key" },
137
+ });
138
+ const openai = listConnections(db, { provider: "openai" });
139
+ expect(openai.every((c) => c.provider === "openai")).toBe(true);
140
+ });
141
+
142
+ test("updateConnection — happy path", () => {
143
+ const { db } = setupDb();
144
+ createConnection(db, {
145
+ name: "updatable",
146
+ provider: "anthropic",
147
+ auth: { type: "platform" },
148
+ });
149
+ const result = updateConnection(db, "updatable", {
150
+ auth: { type: "api_key", credential: "credential/anthropic/api_key" },
151
+ });
152
+ expect(result.ok).toBe(true);
153
+ if (!result.ok) return;
154
+ expect(result.connection.auth.type).toBe("api_key");
155
+ const fetched = getConnection(db, "updatable");
156
+ expect(fetched?.auth.type).toBe("api_key");
157
+ });
158
+
159
+ test("updateConnection — rejects unknown name", () => {
160
+ const { db } = setupDb();
161
+ const result = updateConnection(db, "ghost", { auth: { type: "none" } });
162
+ expect(result.ok).toBe(false);
163
+ if (result.ok) return;
164
+ expect(result.error.code).toBe("not_found");
165
+ });
166
+
167
+ test("deleteConnection — happy path", () => {
168
+ const { db } = setupDb();
169
+ createConnection(db, {
170
+ name: "to-delete",
171
+ provider: "gemini",
172
+ auth: { type: "platform" },
173
+ });
174
+ const result = deleteConnection(db, "to-delete");
175
+ expect(result.ok).toBe(true);
176
+ expect(getConnection(db, "to-delete")).toBeNull();
177
+ });
178
+
179
+ test("deleteConnection — rejects unknown name", () => {
180
+ const { db } = setupDb();
181
+ const result = deleteConnection(db, "ghost");
182
+ expect(result.ok).toBe(false);
183
+ if (result.ok) return;
184
+ expect(result.error.code).toBe("not_found");
185
+ });
186
+
187
+ test("deleteConnection — rejects when profiles reference it (no --force)", () => {
188
+ const { db } = setupDb();
189
+ createConnection(db, {
190
+ name: "referenced",
191
+ provider: "anthropic",
192
+ auth: { type: "platform" },
193
+ });
194
+ const result = deleteConnection(db, "referenced", {
195
+ force: false,
196
+ referencingProfiles: ["profile-a", "profile-b"],
197
+ });
198
+ expect(result.ok).toBe(false);
199
+ if (result.ok) return;
200
+ expect(result.error.code).toBe("has_references");
201
+ if (result.error.code !== "has_references") return;
202
+ expect(result.error.count).toBe(2);
203
+ });
204
+
205
+ test("deleteConnection --force removes even with references", () => {
206
+ const { db } = setupDb();
207
+ createConnection(db, {
208
+ name: "force-delete",
209
+ provider: "anthropic",
210
+ auth: { type: "platform" },
211
+ });
212
+ const result = deleteConnection(db, "force-delete", {
213
+ force: true,
214
+ referencingProfiles: ["some-profile"],
215
+ });
216
+ expect(result.ok).toBe(true);
217
+ expect(getConnection(db, "force-delete")).toBeNull();
218
+ });
219
+ });
220
+
221
+ // ---------------------------------------------------------------------------
222
+ // Auth schema validation
223
+ // ---------------------------------------------------------------------------
224
+
225
+ describe("AuthSchema", () => {
226
+ test("api_key variant requires credential", () => {
227
+ const ok = AuthSchema.safeParse({ type: "api_key", credential: "cred/foo/api_key" });
228
+ expect(ok.success).toBe(true);
229
+
230
+ const bad = AuthSchema.safeParse({ type: "api_key" }); // missing credential
231
+ expect(bad.success).toBe(false);
232
+ });
233
+
234
+ test("platform variant has no extra fields", () => {
235
+ const ok = AuthSchema.safeParse({ type: "platform" });
236
+ expect(ok.success).toBe(true);
237
+ });
238
+
239
+ test("none variant parses", () => {
240
+ const ok = AuthSchema.safeParse({ type: "none" });
241
+ expect(ok.success).toBe(true);
242
+ });
243
+
244
+ test("oauth_subscription and service_account parse (v2 variants, runtime-rejected)", () => {
245
+ expect(
246
+ AuthSchema.safeParse({ type: "oauth_subscription", credential: "x" }).success,
247
+ ).toBe(true);
248
+ expect(
249
+ AuthSchema.safeParse({ type: "service_account", credential: "x" }).success,
250
+ ).toBe(true);
251
+ });
252
+ });
253
+
254
+ // ---------------------------------------------------------------------------
255
+ // Mix-and-match correctness
256
+ // ---------------------------------------------------------------------------
257
+
258
+ describe("Mix-and-match: two profiles, same provider, different connections", () => {
259
+ test("getConnection returns the right auth for each connection name", () => {
260
+ const { db } = setupDb();
261
+
262
+ // anthropic-managed already exists (canonical seed) with platform auth.
263
+ const managedConn = getConnection(db, "anthropic-managed");
264
+ expect(managedConn?.auth.type).toBe("platform");
265
+
266
+ // Create a personal connection with api_key auth.
267
+ createConnection(db, {
268
+ name: "anthropic-personal",
269
+ provider: "anthropic",
270
+ auth: { type: "api_key", credential: "credential/anthropic/api_key" },
271
+ });
272
+
273
+ const personalConn = getConnection(db, "anthropic-personal");
274
+ expect(personalConn?.auth.type).toBe("api_key");
275
+
276
+ // Both connections exist for the same provider.
277
+ const anthropicConns = listConnections(db, { provider: "anthropic" });
278
+ const names = anthropicConns.map((c) => c.name);
279
+ expect(names).toContain("anthropic-managed");
280
+ expect(names).toContain("anthropic-personal");
281
+
282
+ // Auth is distinct per connection.
283
+ const managed = anthropicConns.find((c) => c.name === "anthropic-managed");
284
+ const personal = anthropicConns.find((c) => c.name === "anthropic-personal");
285
+ expect(managed?.auth.type).toBe("platform");
286
+ expect(personal?.auth.type).toBe("api_key");
287
+ });
288
+ });
@@ -34,6 +34,7 @@ describe("getLlmProviderEnvVar", () => {
34
34
  test("returns undefined for search providers (out of scope)", () => {
35
35
  expect(getLlmProviderEnvVar("brave")).toBeUndefined();
36
36
  expect(getLlmProviderEnvVar("perplexity")).toBeUndefined();
37
+ expect(getLlmProviderEnvVar("tavily")).toBeUndefined();
37
38
  });
38
39
 
39
40
  test("returns undefined for unknown provider", () => {
@@ -50,6 +51,10 @@ describe("getSearchProviderEnvVar", () => {
50
51
  expect(getSearchProviderEnvVar("perplexity")).toBe("PERPLEXITY_API_KEY");
51
52
  });
52
53
 
54
+ test("returns TAVILY_API_KEY for tavily", () => {
55
+ expect(getSearchProviderEnvVar("tavily")).toBe("TAVILY_API_KEY");
56
+ });
57
+
53
58
  test("returns undefined for LLM providers (out of scope)", () => {
54
59
  expect(getSearchProviderEnvVar("anthropic")).toBeUndefined();
55
60
  expect(getSearchProviderEnvVar("openai")).toBeUndefined();
@@ -69,6 +74,7 @@ describe("getAnyProviderEnvVar", () => {
69
74
  test("returns search env var for search providers", () => {
70
75
  expect(getAnyProviderEnvVar("brave")).toBe("BRAVE_API_KEY");
71
76
  expect(getAnyProviderEnvVar("perplexity")).toBe("PERPLEXITY_API_KEY");
77
+ expect(getAnyProviderEnvVar("tavily")).toBe("TAVILY_API_KEY");
72
78
  });
73
79
 
74
80
  test("returns undefined for ollama (keyless LLM provider)", () => {
@@ -39,4 +39,10 @@ describe("API_KEY_PROVIDERS", () => {
39
39
  expect(API_KEY_PROVIDERS).toContain("openai");
40
40
  expect(API_KEY_PROVIDERS).toContain("gemini");
41
41
  });
42
+
43
+ test("includes search providers", () => {
44
+ expect(API_KEY_PROVIDERS).toContain("brave");
45
+ expect(API_KEY_PROVIDERS).toContain("perplexity");
46
+ expect(API_KEY_PROVIDERS).toContain("tavily");
47
+ });
42
48
  });
@@ -38,7 +38,6 @@ mock.module("../registry.js", () => ({
38
38
  // ── Imports (after mocks) ───────────────────────────────────────────────────
39
39
 
40
40
  import { LLMSchema } from "../../config/schemas/llm.js";
41
- import { getConfiguredProvider } from "../provider-send-message.js";
42
41
  import { RetryProvider } from "../retry.js";
43
42
  import type {
44
43
  Message,
@@ -47,6 +46,13 @@ import type {
47
46
  SendMessageOptions,
48
47
  } from "../types.js";
49
48
 
49
+ // Side-effect import: ensures `provider-send-message.ts` (and its transitive
50
+ // `connection-resolution` + `registry`) are loaded in a deterministic order
51
+ // across the test suite. Without this, bun's module loader has produced
52
+ // "Export named 'clearConnectionProviderCache' not found" errors when this
53
+ // file runs before others that mock `registry.js`.
54
+ import "../provider-send-message.js";
55
+
50
56
  // ── Test fixtures ──────────────────────────────────────────────────────────
51
57
 
52
58
  const DUMMY_MESSAGES: Message[] = [
@@ -746,34 +752,10 @@ describe("RetryProvider — no callSite (pre-resolved config passes through)", (
746
752
  });
747
753
  });
748
754
 
749
- // ── getConfiguredProvider — call-site routing ──────────────────────────────
750
-
751
- describe("getConfiguredProvider callSite routing", () => {
752
- test("selects provider from llm.callSites[id].provider when callSite given", async () => {
753
- setLlmConfig({
754
- default: { provider: "anthropic", model: "claude-opus-4-7" },
755
- callSites: {
756
- heartbeatAgent: { provider: "openai", model: "gpt-5.4" },
757
- },
758
- });
759
- mockProviders.set("openai", { name: "openai" });
760
- mockProviders.set("anthropic", { name: "anthropic" });
761
-
762
- const provider = await getConfiguredProvider("heartbeatAgent");
763
- expect(provider?.name).toBe("openai");
764
- });
765
-
766
- test("falls back to llm.default.provider when callSite has no provider override", async () => {
767
- setLlmConfig({
768
- default: { provider: "anthropic", model: "claude-opus-4-7" },
769
- callSites: {
770
- // No provider field — default takes over.
771
- heartbeatAgent: { model: "claude-haiku-4-5-20251001" },
772
- },
773
- });
774
- mockProviders.set("anthropic", { name: "anthropic" });
775
-
776
- const provider = await getConfiguredProvider("heartbeatAgent");
777
- expect(provider?.name).toBe("anthropic");
778
- });
779
- });
755
+ // `getConfiguredProvider` — call-site routing coverage lives in
756
+ // `dispatch-connection-routing.test.ts`, where the connection lookup is
757
+ // fully mocked. Keeping those tests here would require mocking
758
+ // `inference/connections.js` and `memory/db-connection.js` at the file
759
+ // level, and bun's `mock.module` leaks across files in a single suite
760
+ // run that pollutes `inference.test.ts` (which exercises the real
761
+ // SQLite-backed `getConnection`).