@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
@@ -16,6 +16,63 @@ mock.module("../util/logger.js", () => ({
16
16
  truncateForLog: (value: string) => value,
17
17
  }));
18
18
 
19
+ // Mock the shared `runBackgroundJob` runner so the scheduler's fresh-bootstrap
20
+ // talk-mode path stays observable in unit tests. Each invocation creates a new
21
+ // conversation row (so `getLastScheduleConversationId` lookups reflect reality)
22
+ // and pushes onto a shared log mirrored by the per-test `processMessage`
23
+ // callback used for the reuse path — that way assertions don't have to know
24
+ // which path a given run took.
25
+ const processedMessages: { conversationId: string; message: string }[] = [];
26
+ const runBackgroundJobOptions: Array<{
27
+ conversationType?: string;
28
+ scheduleJobId?: string;
29
+ groupId?: string;
30
+ suppressFailureNotifications?: boolean;
31
+ onConversationCreated?: (id: string) => void;
32
+ }> = [];
33
+ let runBackgroundJobShouldFail = false;
34
+ mock.module("../runtime/background-job-runner.js", () => ({
35
+ runBackgroundJob: async (opts: {
36
+ prompt: string;
37
+ groupId?: string;
38
+ conversationType?: "background" | "scheduled";
39
+ scheduleJobId?: string;
40
+ suppressFailureNotifications?: boolean;
41
+ onConversationCreated?: (id: string) => void;
42
+ }) => {
43
+ const { createConversation } =
44
+ await import("../memory/conversation-crud.js");
45
+ const conv = createConversation({
46
+ title: "(test stub)",
47
+ conversationType: opts.conversationType ?? "background",
48
+ source: "schedule",
49
+ ...(opts.groupId ? { groupId: opts.groupId } : {}),
50
+ ...(opts.scheduleJobId ? { scheduleJobId: opts.scheduleJobId } : {}),
51
+ });
52
+ runBackgroundJobOptions.push({
53
+ conversationType: opts.conversationType,
54
+ scheduleJobId: opts.scheduleJobId,
55
+ groupId: opts.groupId,
56
+ suppressFailureNotifications: opts.suppressFailureNotifications,
57
+ onConversationCreated: opts.onConversationCreated,
58
+ });
59
+ // Mirror the real runner's contract: fire the SSE callback synchronously
60
+ // BEFORE the job's processMessage finishes, with the bootstrap-returned
61
+ // conversation id.
62
+ opts.onConversationCreated?.(conv.id);
63
+ processedMessages.push({ conversationId: conv.id, message: opts.prompt });
64
+ if (runBackgroundJobShouldFail) {
65
+ return {
66
+ conversationId: conv.id,
67
+ ok: false,
68
+ error: new Error("Simulated failure"),
69
+ errorKind: "exception" as const,
70
+ };
71
+ }
72
+ return { conversationId: conv.id, ok: true };
73
+ },
74
+ }));
75
+
19
76
  import { deleteConversation } from "../memory/conversation-crud.js";
20
77
  import { getDb } from "../memory/db-connection.js";
21
78
  import { initializeDb } from "../memory/db-init.js";
@@ -77,6 +134,9 @@ describe("scheduler conversation reuse", () => {
77
134
  db.run("DELETE FROM tasks");
78
135
  db.run("DELETE FROM messages");
79
136
  db.run("DELETE FROM conversations");
137
+ processedMessages.length = 0;
138
+ runBackgroundJobOptions.length = 0;
139
+ runBackgroundJobShouldFail = false;
80
140
  });
81
141
 
82
142
  test("recurring schedule with reuseConversation=true reuses conversation across runs", async () => {
@@ -99,7 +159,6 @@ describe("scheduler conversation reuse", () => {
99
159
  // WHEN the schedule fires for the first time
100
160
  forceScheduleDue(schedule.id);
101
161
 
102
- const processedMessages: { conversationId: string; message: string }[] = [];
103
162
  const processMessage = async (conversationId: string, message: string) => {
104
163
  processedMessages.push({ conversationId, message });
105
164
  };
@@ -156,7 +215,6 @@ describe("scheduler conversation reuse", () => {
156
215
  // WHEN the schedule fires for the first time
157
216
  forceScheduleDue(schedule.id);
158
217
 
159
- const processedMessages: { conversationId: string; message: string }[] = [];
160
218
  const processMessage = async (conversationId: string, message: string) => {
161
219
  processedMessages.push({ conversationId, message });
162
220
  };
@@ -200,7 +258,6 @@ describe("scheduler conversation reuse", () => {
200
258
 
201
259
  forceScheduleDue(schedule.id);
202
260
 
203
- const processedMessages: { conversationId: string; message: string }[] = [];
204
261
  const processMessage = async (conversationId: string, message: string) => {
205
262
  processedMessages.push({ conversationId, message });
206
263
  };
@@ -245,7 +302,6 @@ describe("scheduler conversation reuse", () => {
245
302
  });
246
303
 
247
304
  // WHEN the schedule fires
248
- const processedMessages: { conversationId: string; message: string }[] = [];
249
305
  const processMessage = async (conversationId: string, message: string) => {
250
306
  processedMessages.push({ conversationId, message });
251
307
  };
@@ -285,7 +341,6 @@ describe("scheduler conversation reuse", () => {
285
341
  forceScheduleDue(schedule.id);
286
342
 
287
343
  let shouldFail = false;
288
- const processedMessages: { conversationId: string; message: string }[] = [];
289
344
  const processMessage = async (conversationId: string, message: string) => {
290
345
  processedMessages.push({ conversationId, message });
291
346
  if (shouldFail) throw new Error("Simulated failure");
@@ -327,3 +382,104 @@ describe("scheduler conversation reuse", () => {
327
382
  expect(processedMessages[0].conversationId).toBe(successConversationId);
328
383
  });
329
384
  });
385
+
386
+ describe("scheduler talk-mode runner option propagation", () => {
387
+ beforeEach(() => {
388
+ const db = getDb();
389
+ db.run("DELETE FROM cron_runs");
390
+ db.run("DELETE FROM cron_jobs");
391
+ db.run("DELETE FROM messages");
392
+ db.run("DELETE FROM conversations");
393
+ processedMessages.length = 0;
394
+ runBackgroundJobOptions.length = 0;
395
+ runBackgroundJobShouldFail = false;
396
+ });
397
+
398
+ test("talk-mode propagates conversationType=scheduled, scheduleJobId, and quiet=>suppressFailureNotifications", async () => {
399
+ const rruleExpr = buildEveryMinuteRrule();
400
+ const schedule = createSchedule({
401
+ name: "Quiet Talk Mode",
402
+ cronExpression: rruleExpr,
403
+ message: "Background work",
404
+ syntax: "rrule",
405
+ expression: rruleExpr,
406
+ quiet: true,
407
+ });
408
+ forceScheduleDue(schedule.id);
409
+
410
+ const processMessage = async () => {};
411
+ const scheduler = startScheduler(processMessage, () => {});
412
+ await new Promise((resolve) => setTimeout(resolve, 500));
413
+ scheduler.stop();
414
+
415
+ expect(runBackgroundJobOptions).toHaveLength(1);
416
+ const opts = runBackgroundJobOptions[0]!;
417
+ expect(opts.conversationType).toBe("scheduled");
418
+ expect(opts.scheduleJobId).toBe(schedule.id);
419
+ expect(opts.groupId).toBe("system:scheduled");
420
+ expect(opts.suppressFailureNotifications).toBe(true);
421
+ });
422
+
423
+ test("talk-mode without quiet leaves suppressFailureNotifications=false", async () => {
424
+ const rruleExpr = buildEveryMinuteRrule();
425
+ const schedule = createSchedule({
426
+ name: "Loud Talk Mode",
427
+ cronExpression: rruleExpr,
428
+ message: "Background work",
429
+ syntax: "rrule",
430
+ expression: rruleExpr,
431
+ // quiet defaults to false
432
+ });
433
+ forceScheduleDue(schedule.id);
434
+
435
+ const processMessage = async () => {};
436
+ const scheduler = startScheduler(processMessage, () => {});
437
+ await new Promise((resolve) => setTimeout(resolve, 500));
438
+ scheduler.stop();
439
+
440
+ expect(runBackgroundJobOptions).toHaveLength(1);
441
+ expect(runBackgroundJobOptions[0]!.suppressFailureNotifications).toBe(
442
+ false,
443
+ );
444
+ });
445
+
446
+ test("talk-mode fires onScheduleConversationCreated synchronously via runner callback (BEFORE the runner returns)", async () => {
447
+ const rruleExpr = buildEveryMinuteRrule();
448
+ const schedule = createSchedule({
449
+ name: "SSE timing",
450
+ cronExpression: rruleExpr,
451
+ message: "x",
452
+ syntax: "rrule",
453
+ expression: rruleExpr,
454
+ });
455
+ forceScheduleDue(schedule.id);
456
+
457
+ const sseCalls: Array<{
458
+ conversationId: string;
459
+ scheduleJobId: string;
460
+ title: string;
461
+ }> = [];
462
+ const processMessage = async () => {};
463
+ const scheduler = startScheduler(
464
+ processMessage,
465
+ () => {},
466
+ undefined,
467
+ (info) => sseCalls.push(info),
468
+ );
469
+ await new Promise((resolve) => setTimeout(resolve, 500));
470
+ scheduler.stop();
471
+
472
+ expect(sseCalls).toHaveLength(1);
473
+ expect(sseCalls[0]).toMatchObject({
474
+ scheduleJobId: schedule.id,
475
+ title: "SSE timing",
476
+ });
477
+ // The mock runner fires the callback synchronously after creating the
478
+ // conversation row, so the conversationId must be the same id the runner
479
+ // ultimately reports.
480
+ expect(processedMessages).toHaveLength(1);
481
+ expect(sseCalls[0].conversationId).toBe(
482
+ processedMessages[0].conversationId,
483
+ );
484
+ });
485
+ });
@@ -27,11 +27,6 @@ mock.module("../runtime/agent-wake.js", () => ({
27
27
  wakeAgentForOpportunity: mockWakeAgentForOpportunity,
28
28
  }));
29
29
 
30
- const mockEmitFeedEvent = mock(() => Promise.resolve());
31
- mock.module("../home/emit-feed-event.js", () => ({
32
- emitFeedEvent: mockEmitFeedEvent,
33
- }));
34
-
35
30
  import { getDb } from "../memory/db-connection.js";
36
31
  import { initializeDb } from "../memory/db-init.js";
37
32
  import { createSchedule } from "../schedule/schedule-store.js";
@@ -82,7 +77,6 @@ describe("scheduler wake mode", () => {
82
77
  db.run("DELETE FROM messages");
83
78
  db.run("DELETE FROM conversations");
84
79
  mockWakeAgentForOpportunity.mockClear();
85
- mockEmitFeedEvent.mockClear();
86
80
  });
87
81
 
88
82
  test("wake schedule calls wakeAgentForOpportunity with correct args", async () => {
@@ -208,63 +202,6 @@ describe("scheduler wake mode", () => {
208
202
  expect(row?.status).toBe("active");
209
203
  });
210
204
 
211
- test("quiet: true suppresses feed event", async () => {
212
- // GIVEN a one-shot wake schedule with quiet: true
213
- const schedule = createSchedule({
214
- name: "Wake Quiet",
215
- message: "Quiet wake",
216
- mode: "wake",
217
- wakeConversationId: "conv-quiet",
218
- quiet: true,
219
- nextRunAt: Date.now() - 1000,
220
- });
221
- forceScheduleDue(schedule.id);
222
-
223
- // WHEN the scheduler fires
224
- const scheduler = startScheduler(
225
- mock(() => Promise.resolve()),
226
- () => {},
227
- );
228
- await new Promise((resolve) => setTimeout(resolve, 500));
229
- scheduler.stop();
230
-
231
- // THEN wakeAgentForOpportunity is called
232
- expect(mockWakeAgentForOpportunity).toHaveBeenCalledTimes(1);
233
-
234
- // AND no feed event is emitted
235
- expect(mockEmitFeedEvent).not.toHaveBeenCalled();
236
- });
237
-
238
- test("quiet: false emits feed event on success", async () => {
239
- // GIVEN a one-shot wake schedule with quiet: false (default)
240
- const schedule = createSchedule({
241
- name: "Wake Loud",
242
- message: "Loud wake",
243
- mode: "wake",
244
- wakeConversationId: "conv-loud",
245
- nextRunAt: Date.now() - 1000,
246
- });
247
- forceScheduleDue(schedule.id);
248
-
249
- // WHEN the scheduler fires
250
- const scheduler = startScheduler(
251
- mock(() => Promise.resolve()),
252
- () => {},
253
- );
254
- await new Promise((resolve) => setTimeout(resolve, 500));
255
- scheduler.stop();
256
-
257
- // THEN a feed event IS emitted
258
- expect(mockEmitFeedEvent).toHaveBeenCalledTimes(1);
259
- expect(mockEmitFeedEvent).toHaveBeenCalledWith(
260
- expect.objectContaining({
261
- source: "assistant",
262
- title: "Wake Loud",
263
- summary: "Deferred wake fired.",
264
- }),
265
- );
266
- });
267
-
268
205
  test("retries wake when wakeAgentForOpportunity returns timeout", async () => {
269
206
  // GIVEN wakeAgentForOpportunity returns timeout on first call, then succeeds
270
207
  mockWakeAgentForOpportunity
@@ -135,6 +135,7 @@ describe("secret-allowlist", () => {
135
135
 
136
136
  // -----------------------------------------------------------------------
137
137
  // Integration with scanText
138
+ // AKIAIOSFODNN7* keys below are fake — based on the AWS docs example prefix, not real credentials.
138
139
  // -----------------------------------------------------------------------
139
140
  test("[experimental] allowlisted values are suppressed by scanText", () => {
140
141
  const awsKey = "AKIAIOSFODNN7REALKEY";
@@ -1,5 +1,6 @@
1
1
  import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
+ import { LLMSchema } from "../config/schemas/llm.js";
3
4
  import { credentialKey } from "../security/credential-key.js";
4
5
 
5
6
  let lastGeminiConstructorOpts: Record<string, unknown> | null = null;
@@ -15,11 +16,11 @@ const MANAGED_PROVIDERS = ["anthropic", "openai", "gemini"] as const;
15
16
 
16
17
  let platformBaseUrlOverride: string | undefined;
17
18
 
19
+ const baseLlm = LLMSchema.parse({});
20
+
18
21
  const mockConfig = {
19
22
  services: {
20
- inference: {
21
- mode: "your-own" as const,
22
- },
23
+ inference: {},
23
24
  "image-generation": {
24
25
  mode: "your-own" as const,
25
26
  provider: "gemini",
@@ -30,7 +31,14 @@ const mockConfig = {
30
31
  provider: "inference-provider-native",
31
32
  },
32
33
  },
33
- llm: { default: { provider: "anthropic", model: "test-model" } },
34
+ llm: {
35
+ ...baseLlm,
36
+ default: {
37
+ ...baseLlm.default,
38
+ provider: "anthropic" as const,
39
+ model: "test-model",
40
+ },
41
+ },
34
42
  };
35
43
 
36
44
  mock.module("@google/genai", () => ({
@@ -93,6 +93,7 @@ afterAll(() => {
93
93
  describe("shell tool credential ref resolution", () => {
94
94
  test("service/field ref resolves to UUID and reaches session creation", async () => {
95
95
  const meta = upsertCredentialMetadata("fal", "api_key", {
96
+ allowedTools: ["bash"],
96
97
  injectionTemplates: [
97
98
  {
98
99
  hostPattern: "*.fal.ai",
@@ -120,7 +121,9 @@ describe("shell tool credential ref resolution", () => {
120
121
  });
121
122
 
122
123
  test("UUID ref remains supported", async () => {
123
- const meta = upsertCredentialMetadata("github", "token");
124
+ const meta = upsertCredentialMetadata("github", "token", {
125
+ allowedTools: ["bash"],
126
+ });
124
127
 
125
128
  await shellTool.execute(
126
129
  {
@@ -156,7 +159,9 @@ describe("shell tool credential ref resolution", () => {
156
159
  });
157
160
 
158
161
  test("mixed known+unknown refs fails fast (no partial execution)", async () => {
159
- upsertCredentialMetadata("fal", "api_key");
162
+ upsertCredentialMetadata("fal", "api_key", {
163
+ allowedTools: ["bash"],
164
+ });
160
165
 
161
166
  const result = await shellTool.execute(
162
167
  {
@@ -175,7 +180,9 @@ describe("shell tool credential ref resolution", () => {
175
180
  });
176
181
 
177
182
  test("duplicate refs are deduped", async () => {
178
- const meta = upsertCredentialMetadata("fal", "api_key");
183
+ const meta = upsertCredentialMetadata("fal", "api_key", {
184
+ allowedTools: ["bash"],
185
+ });
179
186
 
180
187
  await shellTool.execute(
181
188
  {
@@ -209,4 +216,89 @@ describe("shell tool credential ref resolution", () => {
209
216
  expect(result.isError).toBeFalsy();
210
217
  expect(mockGetOrStartSession).not.toHaveBeenCalled();
211
218
  });
219
+
220
+ test("credential with allowedTools excluding bash is denied for proxied shell", async () => {
221
+ upsertCredentialMetadata("vercel", "api_token", {
222
+ allowedTools: ["publish_page"],
223
+ injectionTemplates: [
224
+ {
225
+ hostPattern: "api.vercel.com",
226
+ injectionType: "header",
227
+ headerName: "Authorization",
228
+ valuePrefix: "Bearer ",
229
+ },
230
+ ],
231
+ });
232
+
233
+ const result = await shellTool.execute(
234
+ {
235
+ command: "curl https://api.vercel.com/v1/projects",
236
+ activity: "test",
237
+ network_mode: "proxied",
238
+ credential_ids: ["vercel/api_token"],
239
+ },
240
+ ctx,
241
+ );
242
+
243
+ expect(result.isError).toBe(true);
244
+ expect(result.content).toContain("credential tool policy denied");
245
+ expect(result.content).toContain("not bash");
246
+ // Must not call getOrStartSession — policy denial happens before session creation
247
+ expect(mockGetOrStartSession).not.toHaveBeenCalled();
248
+ });
249
+
250
+ test("credential with allowedTools including bash starts proxied session", async () => {
251
+ const meta = upsertCredentialMetadata("deploy_svc", "api_key", {
252
+ allowedTools: ["bash"],
253
+ injectionTemplates: [
254
+ {
255
+ hostPattern: "*.deploy-svc.io",
256
+ injectionType: "header",
257
+ headerName: "Authorization",
258
+ valuePrefix: "Bearer ",
259
+ },
260
+ ],
261
+ });
262
+
263
+ await shellTool.execute(
264
+ {
265
+ command: "echo deploy",
266
+ activity: "test",
267
+ network_mode: "proxied",
268
+ credential_ids: ["deploy_svc/api_key"],
269
+ },
270
+ ctx,
271
+ );
272
+
273
+ // Session should be created with the resolved credential ID
274
+ expect(mockGetOrStartSession).toHaveBeenCalledTimes(1);
275
+ const callArgs = mockGetOrStartSession.mock.calls[0];
276
+ expect(callArgs[1]).toEqual([meta.credentialId]);
277
+ });
278
+
279
+ test("mixed allowed and denied credentials fail the whole command before session creation", async () => {
280
+ upsertCredentialMetadata("allowed_svc", "token", {
281
+ allowedTools: ["bash"],
282
+ });
283
+ upsertCredentialMetadata("denied_svc", "token", {
284
+ allowedTools: ["publish_page"],
285
+ });
286
+
287
+ const result = await shellTool.execute(
288
+ {
289
+ command: "echo mixed",
290
+ activity: "test",
291
+ network_mode: "proxied",
292
+ credential_ids: ["allowed_svc/token", "denied_svc/token"],
293
+ },
294
+ ctx,
295
+ );
296
+
297
+ expect(result.isError).toBe(true);
298
+ expect(result.content).toContain("credential tool policy denied");
299
+ expect(result.content).toContain("denied_svc/token");
300
+ expect(result.content).toContain("not bash");
301
+ // Must not call getOrStartSession — even one denied credential blocks the whole command
302
+ expect(mockGetOrStartSession).not.toHaveBeenCalled();
303
+ });
212
304
  });
@@ -136,6 +136,20 @@ mock.module("../tools/credentials/resolve.js", () => ({
136
136
  resolveCredentialRef: (ref: string) => ({ credentialId: ref }),
137
137
  }));
138
138
 
139
+ mock.module("../tools/credentials/metadata-store.js", () => ({
140
+ getCredentialMetadataById: (id: string) => ({
141
+ service: "test",
142
+ field: id,
143
+ allowedTools: ["bash"],
144
+ allowedDomains: [],
145
+ }),
146
+ }));
147
+
148
+ mock.module("../tools/credentials/tool-policy.js", () => ({
149
+ isToolAllowed: (toolName: string, allowedTools: string[]) =>
150
+ Array.isArray(allowedTools) && allowedTools.includes(toolName),
151
+ }));
152
+
139
153
  mock.module("../tools/network/script-proxy/logging.js", () => ({
140
154
  buildCredentialRefTrace: (
141
155
  rawRefs: string[],
@@ -50,6 +50,7 @@ mock.module("../config/loader.js", () => ({
50
50
  "openrouter",
51
51
  "brave",
52
52
  "perplexity",
53
+ "tavily",
53
54
  ],
54
55
  }));
55
56
 
@@ -371,15 +371,13 @@ describe("skill_load tool", () => {
371
371
  expect(result.content).toContain("Skill: No Includes");
372
372
  });
373
373
 
374
- test("bundled app-builder loads when frontend-design is unavailable", async () => {
374
+ test("bundled app-builder loads without includes", async () => {
375
375
  const result = await executeSkillLoad({ skill: "app-builder" });
376
376
 
377
377
  expect(result.isError).toBe(false);
378
378
  expect(result.content).toContain("Skill: App Builder");
379
- expect(result.content).toContain("Suggested Included Skills (not loaded):");
380
- expect(result.content).toContain("frontend-design");
379
+ expect(result.content).toContain("Included Skills (immediate): none");
381
380
  expect(result.content).toContain('<loaded_skill id="app-builder"');
382
- expect(result.content).not.toContain('<loaded_skill id="frontend-design"');
383
381
  });
384
382
 
385
383
  test("bundled phone-calls loads when setup includes are unavailable", async () => {
@@ -110,16 +110,39 @@ mock.module("../prompts/system-prompt.js", () => ({
110
110
  buildSubagentSystemPrompt: () => "subagent system",
111
111
  }));
112
112
 
113
- // Provider registry return distinct stubs so we can verify the selection.
113
+ // Provider registry + connection resolver routing goes through
114
+ // `provider_connection` exclusively. `getProvider` is kept here purely
115
+ // because the registry module still exports it; the production code under
116
+ // test does not call it.
114
117
  const anthropicStub = { name: "anthropic" };
115
118
  const openaiStub = { name: "openai" };
116
119
 
117
120
  mock.module("../providers/registry.js", () => ({
118
121
  getProvider: (name: string) => {
119
- if (name === "anthropic") return anthropicStub;
120
- if (name === "openai") return openaiStub;
121
- throw new Error(`unknown provider: ${name}`);
122
+ throw new Error(`legacy getProvider should not be called: ${name}`);
122
123
  },
124
+ resolveProviderFromConnection: async (connection: { name: string }) => {
125
+ if (connection.name === "anthropic-conn") return anthropicStub;
126
+ if (connection.name === "openai-conn") return openaiStub;
127
+ return null;
128
+ },
129
+ clearConnectionProviderCache: () => {},
130
+ }));
131
+
132
+ // Connection lookup — feeds `resolveProviderFromConnection` above. The DB
133
+ // is stubbed; tests don't touch SQLite.
134
+ mock.module("../providers/inference/connections.js", () => ({
135
+ getConnection: (_db: unknown, name: string) => {
136
+ if (name === "anthropic-conn")
137
+ return { name: "anthropic-conn", provider: "anthropic", auth: { type: "platform" } };
138
+ if (name === "openai-conn")
139
+ return { name: "openai-conn", provider: "openai", auth: { type: "platform" } };
140
+ return null;
141
+ },
142
+ }));
143
+
144
+ mock.module("../memory/db-connection.js", () => ({
145
+ getDb: () => ({}),
123
146
  }));
124
147
 
125
148
  // Mutable LLM config — tests rewrite this per-case.
@@ -154,7 +177,11 @@ function setLlmConfig(raw: unknown): void {
154
177
  describe("SubagentManager — provider call-site routing", () => {
155
178
  test("wraps the default provider in CallSiteRoutingProvider", async () => {
156
179
  setLlmConfig({
157
- default: { provider: "anthropic", model: "claude-opus-4-7" },
180
+ default: {
181
+ provider: "anthropic",
182
+ provider_connection: "anthropic-conn",
183
+ model: "claude-opus-4-7",
184
+ },
158
185
  });
159
186
 
160
187
  capturedProvider = undefined;
@@ -172,10 +199,27 @@ describe("SubagentManager — provider call-site routing", () => {
172
199
  });
173
200
 
174
201
  test("the wrapped provider exposes the default provider's name (stable identity for outer wrappers)", async () => {
202
+ // Note: `provider_connection` lives on `ProfileEntry` and `LLMConfigBase`,
203
+ // NOT on `LLMCallSiteConfig` (which is `LLMConfigFragment.extend({
204
+ // profile })`). Setting `provider_connection` directly on a `callSites.*`
205
+ // entry would be silently stripped by Zod. The correct shape for an
206
+ // alternate-provider call-site override is a profile reference, defined
207
+ // here as `altOpenai`.
175
208
  setLlmConfig({
176
- default: { provider: "anthropic", model: "claude-opus-4-7" },
209
+ default: {
210
+ provider: "anthropic",
211
+ provider_connection: "anthropic-conn",
212
+ model: "claude-opus-4-7",
213
+ },
214
+ profiles: {
215
+ altOpenai: {
216
+ provider: "openai",
217
+ provider_connection: "openai-conn",
218
+ model: "gpt-5.4",
219
+ },
220
+ },
177
221
  callSites: {
178
- subagentSpawn: { provider: "openai", model: "gpt-5.4" },
222
+ subagentSpawn: { profile: "altOpenai" },
179
223
  },
180
224
  });
181
225
 
@@ -202,7 +246,11 @@ describe("SubagentManager — provider call-site routing", () => {
202
246
 
203
247
  test("falls back to default provider when subagentSpawn callSite is absent", async () => {
204
248
  setLlmConfig({
205
- default: { provider: "anthropic", model: "claude-opus-4-7" },
249
+ default: {
250
+ provider: "anthropic",
251
+ provider_connection: "anthropic-conn",
252
+ model: "claude-opus-4-7",
253
+ },
206
254
  // No subagentSpawn override.
207
255
  });
208
256
 
@@ -224,7 +272,11 @@ describe("SubagentManager — provider call-site routing", () => {
224
272
 
225
273
  test("copies parent guardian and auth context into spawned conversation", async () => {
226
274
  setLlmConfig({
227
- default: { provider: "anthropic", model: "claude-opus-4-7" },
275
+ default: {
276
+ provider: "anthropic",
277
+ provider_connection: "anthropic-conn",
278
+ model: "claude-opus-4-7",
279
+ },
228
280
  });
229
281
 
230
282
  const parentTrustContext = {
@@ -273,11 +325,18 @@ describe("SubagentManager — provider call-site routing", () => {
273
325
  // ── Direct unit test for CallSiteRoutingProvider's selection logic ─────────
274
326
 
275
327
  describe("CallSiteRoutingProvider — selectProvider behavior", () => {
276
- test("routes to the resolved provider when callSite.provider differs from default", async () => {
328
+ test("routes to the resolved provider when callSite resolves to a profile with provider_connection", async () => {
277
329
  setLlmConfig({
278
330
  default: { provider: "anthropic", model: "claude-opus-4-7" },
331
+ profiles: {
332
+ altOpenai: {
333
+ provider: "openai",
334
+ provider_connection: "openai-conn",
335
+ model: "gpt-5.4",
336
+ },
337
+ },
279
338
  callSites: {
280
- subagentSpawn: { provider: "openai", model: "gpt-5.4" },
339
+ subagentSpawn: { profile: "altOpenai" },
281
340
  },
282
341
  });
283
342
 
@@ -309,10 +368,13 @@ describe("CallSiteRoutingProvider — selectProvider behavior", () => {
309
368
  },
310
369
  };
311
370
 
312
- const wrapper = new CallSiteRoutingProvider(defaultProvider, (name) => {
313
- if (name === "openai") return altProvider;
314
- return undefined;
315
- });
371
+ const wrapper = new CallSiteRoutingProvider(
372
+ defaultProvider,
373
+ async (connectionName) => {
374
+ if (connectionName === "openai-conn") return altProvider;
375
+ return null;
376
+ },
377
+ );
316
378
 
317
379
  await wrapper.sendMessage([], undefined, undefined, {
318
380
  config: { callSite: "subagentSpawn" },
@@ -347,7 +409,7 @@ describe("CallSiteRoutingProvider — selectProvider behavior", () => {
347
409
 
348
410
  const wrapper = new CallSiteRoutingProvider(
349
411
  defaultProvider,
350
- () => undefined,
412
+ async () => null,
351
413
  );
352
414
 
353
415
  await wrapper.sendMessage([], undefined, undefined, {