@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,357 @@
1
+ /**
2
+ * Tests for `runBackgroundJob()`.
3
+ *
4
+ * Strategy: stub `bootstrapConversation`, `processMessage`, and
5
+ * `emitNotificationSignal` via `mock.module()` and inspect the recorded
6
+ * calls. We do NOT exercise the real conversation runtime here — the unit
7
+ * under test is the wrapper's contract:
8
+ * - bootstrap is called once
9
+ * - processMessage is awaited (or raced against a timeout)
10
+ * - failure paths emit `activity.failed` (unless suppressed)
11
+ * - the result is always a structured value, never a thrown error
12
+ */
13
+
14
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
15
+
16
+ import type { TrustContext } from "../../daemon/trust-context.js";
17
+
18
+ // ── Module mocks ─────────────────────────────────────────────────────
19
+
20
+ let bootstrapCalls = 0;
21
+ let bootstrapLastArgs: Record<string, unknown> | null = null;
22
+ const STUB_CONVERSATION_ID = "conv-test-1";
23
+
24
+ mock.module("../../memory/conversation-bootstrap.js", () => ({
25
+ bootstrapConversation: (opts: Record<string, unknown>) => {
26
+ bootstrapCalls += 1;
27
+ bootstrapLastArgs = opts;
28
+ return { id: STUB_CONVERSATION_ID };
29
+ },
30
+ }));
31
+
32
+ const addMessageCalls: Array<{
33
+ conversationId: string;
34
+ role: string;
35
+ content: string;
36
+ }> = [];
37
+
38
+ mock.module("../../memory/conversation-crud.js", () => ({
39
+ addMessage: async (conversationId: string, role: string, content: string) => {
40
+ addMessageCalls.push({ conversationId, role, content });
41
+ return { id: `msg-${addMessageCalls.length}` };
42
+ },
43
+ }));
44
+
45
+ let processMessageImpl: (
46
+ conversationId: string,
47
+ content: string,
48
+ attachmentIds: string[] | undefined,
49
+ options: Record<string, unknown> | undefined,
50
+ ) => Promise<{ messageId: string }> = async () => ({ messageId: "msg-1" });
51
+ const processMessageCalls: Array<{
52
+ conversationId: string;
53
+ content: string;
54
+ options: Record<string, unknown> | undefined;
55
+ }> = [];
56
+
57
+ mock.module("../../daemon/process-message.js", () => ({
58
+ processMessage: async (
59
+ conversationId: string,
60
+ content: string,
61
+ attachmentIds: string[] | undefined,
62
+ options: Record<string, unknown> | undefined,
63
+ ) => {
64
+ processMessageCalls.push({ conversationId, content, options });
65
+ return processMessageImpl(conversationId, content, attachmentIds, options);
66
+ },
67
+ }));
68
+
69
+ const emitCalls: Array<Record<string, unknown>> = [];
70
+ let emitImpl: (
71
+ params: Record<string, unknown>,
72
+ ) => Promise<unknown> = async () => ({
73
+ signalId: "sig-1",
74
+ deduplicated: false,
75
+ dispatched: true,
76
+ reason: "ok",
77
+ deliveryResults: [],
78
+ });
79
+
80
+ mock.module("../../notifications/emit-signal.js", () => ({
81
+ emitNotificationSignal: (params: Record<string, unknown>) => {
82
+ emitCalls.push(params);
83
+ return emitImpl(params);
84
+ },
85
+ }));
86
+
87
+ // Stub the pre-first-message gate. Default OPEN — every pre-existing
88
+ // test assumes a fully-onboarded daemon. The dedicated "gate closed"
89
+ // test flips this to false.
90
+ let preFirstMessageGateOpen = true;
91
+ mock.module("../pre-first-message-gate.js", () => ({
92
+ hasReceivedUserMessage: () => preFirstMessageGateOpen,
93
+ }));
94
+
95
+ // Import after mocks are in place.
96
+ const { runBackgroundJob } = await import("../background-job-runner.js");
97
+
98
+ // ── Shared fixtures ──────────────────────────────────────────────────
99
+
100
+ const TRUST_CONTEXT: TrustContext = {
101
+ sourceChannel: "vellum",
102
+ trustClass: "guardian",
103
+ };
104
+
105
+ function baseOpts(overrides: Record<string, unknown> = {}) {
106
+ return {
107
+ jobName: "test-job",
108
+ source: "test-source",
109
+ prompt: "do the test",
110
+ trustContext: TRUST_CONTEXT,
111
+ callSite: "heartbeatAgent" as const,
112
+ timeoutMs: 5_000,
113
+ origin: "heartbeat" as const,
114
+ ...overrides,
115
+ };
116
+ }
117
+
118
+ beforeEach(() => {
119
+ bootstrapCalls = 0;
120
+ bootstrapLastArgs = null;
121
+ processMessageCalls.length = 0;
122
+ emitCalls.length = 0;
123
+ addMessageCalls.length = 0;
124
+ preFirstMessageGateOpen = true;
125
+ processMessageImpl = async () => ({ messageId: "msg-1" });
126
+ emitImpl = async () => ({
127
+ signalId: "sig-1",
128
+ deduplicated: false,
129
+ dispatched: true,
130
+ reason: "ok",
131
+ deliveryResults: [],
132
+ });
133
+ });
134
+
135
+ // ── Tests ────────────────────────────────────────────────────────────
136
+
137
+ describe("runBackgroundJob", () => {
138
+ test("success path: returns ok=true and emits no notification", async () => {
139
+ processMessageImpl = async () => ({ messageId: "msg-success" });
140
+
141
+ const result = await runBackgroundJob(baseOpts());
142
+
143
+ expect(result.ok).toBe(true);
144
+ expect(result.conversationId).toBe(STUB_CONVERSATION_ID);
145
+ expect(result.error).toBeUndefined();
146
+ expect(result.errorKind).toBeUndefined();
147
+ expect(bootstrapCalls).toBe(1);
148
+ expect(bootstrapLastArgs).toMatchObject({
149
+ conversationType: "background",
150
+ source: "test-source",
151
+ origin: "heartbeat",
152
+ systemHint: "do the test",
153
+ groupId: "system:background",
154
+ });
155
+ expect(processMessageCalls).toHaveLength(1);
156
+ expect(processMessageCalls[0].options).toMatchObject({
157
+ trustContext: TRUST_CONTEXT,
158
+ callSite: "heartbeatAgent",
159
+ });
160
+ expect(emitCalls).toHaveLength(0);
161
+ });
162
+
163
+ test("generic exception: returns ok=false with errorKind=exception and emits activity.failed with dedupeKey", async () => {
164
+ processMessageImpl = async () => {
165
+ throw new Error("boom");
166
+ };
167
+
168
+ const result = await runBackgroundJob(baseOpts());
169
+
170
+ expect(result.ok).toBe(false);
171
+ expect(result.errorKind).toBe("exception");
172
+ expect(result.error).toBeInstanceOf(Error);
173
+ expect(result.error?.message).toBe("boom");
174
+ expect(result.conversationId).toBe(STUB_CONVERSATION_ID);
175
+
176
+ expect(emitCalls).toHaveLength(1);
177
+ const emitted = emitCalls[0];
178
+ expect(emitted.sourceEventName).toBe("activity.failed");
179
+ expect(emitted.sourceChannel).toBe("assistant_tool");
180
+ expect(emitted.sourceContextId).toBe(STUB_CONVERSATION_ID);
181
+ expect(emitted.contextPayload).toMatchObject({
182
+ jobName: "test-job",
183
+ errorMessage: "boom",
184
+ errorKind: "exception",
185
+ });
186
+ expect(emitted.attentionHints).toMatchObject({
187
+ requiresAction: false,
188
+ urgency: "medium",
189
+ isAsyncBackground: true,
190
+ visibleInSourceNow: false,
191
+ });
192
+ // Dedupe key collapses repeated failures of the same job per UTC day.
193
+ expect(typeof emitted.dedupeKey).toBe("string");
194
+ expect(emitted.dedupeKey as string).toMatch(
195
+ /^activity-failed:test-job:\d{4}-\d{2}-\d{2}$/,
196
+ );
197
+ });
198
+
199
+ test("timeout: returns ok=false with errorKind=timeout and emits activity.failed", async () => {
200
+ // Never resolve — force timeout to win the race.
201
+ processMessageImpl = () => new Promise(() => {});
202
+
203
+ const result = await runBackgroundJob(baseOpts({ timeoutMs: 50 }));
204
+
205
+ expect(result.ok).toBe(false);
206
+ expect(result.errorKind).toBe("timeout");
207
+ expect(result.error?.message).toContain("timed out after 50ms");
208
+ expect(emitCalls).toHaveLength(1);
209
+ expect(emitCalls[0].sourceEventName).toBe("activity.failed");
210
+ expect(
211
+ (emitCalls[0].contextPayload as { errorKind: string }).errorKind,
212
+ ).toBe("timeout");
213
+ });
214
+
215
+ test("suppressFailureNotifications: failure returns ok=false but emits nothing", async () => {
216
+ processMessageImpl = async () => {
217
+ throw new Error("suppressed");
218
+ };
219
+
220
+ const result = await runBackgroundJob(
221
+ baseOpts({ suppressFailureNotifications: true }),
222
+ );
223
+
224
+ expect(result.ok).toBe(false);
225
+ expect(result.errorKind).toBe("exception");
226
+ expect(result.error?.message).toBe("suppressed");
227
+ expect(emitCalls).toHaveLength(0);
228
+ });
229
+
230
+ test("onConversationCreated fires synchronously after bootstrap, BEFORE processMessage", async () => {
231
+ let processMessageStarted = false;
232
+ let callbackFiredBeforeProcessMessage = false;
233
+
234
+ processMessageImpl = async () => {
235
+ processMessageStarted = true;
236
+ // Delay completion so we can observe the ordering — even with the
237
+ // delay, the callback should already have fired.
238
+ await new Promise<void>((resolve) => setTimeout(resolve, 10));
239
+ return { messageId: "msg-after" };
240
+ };
241
+
242
+ const seenConversationIds: string[] = [];
243
+ const onConversationCreated = (conversationId: string) => {
244
+ seenConversationIds.push(conversationId);
245
+ callbackFiredBeforeProcessMessage = !processMessageStarted;
246
+ };
247
+
248
+ const result = await runBackgroundJob(baseOpts({ onConversationCreated }));
249
+
250
+ expect(result.ok).toBe(true);
251
+ expect(seenConversationIds).toEqual([STUB_CONVERSATION_ID]);
252
+ expect(callbackFiredBeforeProcessMessage).toBe(true);
253
+ });
254
+
255
+ test("onConversationCreated callback throws are swallowed and the job still runs", async () => {
256
+ const result = await runBackgroundJob(
257
+ baseOpts({
258
+ onConversationCreated: () => {
259
+ throw new Error("callback boom");
260
+ },
261
+ }),
262
+ );
263
+
264
+ expect(result.ok).toBe(true);
265
+ expect(processMessageCalls).toHaveLength(1);
266
+ });
267
+
268
+ test("conversationType=scheduled and scheduleJobId are propagated to bootstrapConversation", async () => {
269
+ await runBackgroundJob(
270
+ baseOpts({
271
+ conversationType: "scheduled",
272
+ scheduleJobId: "job-abc",
273
+ }),
274
+ );
275
+
276
+ expect(bootstrapLastArgs).toMatchObject({
277
+ conversationType: "scheduled",
278
+ scheduleJobId: "job-abc",
279
+ });
280
+ });
281
+
282
+ test("default conversationType is 'background' when not specified", async () => {
283
+ await runBackgroundJob(baseOpts());
284
+ expect(bootstrapLastArgs).toMatchObject({ conversationType: "background" });
285
+ // No scheduleJobId by default.
286
+ expect(bootstrapLastArgs).not.toHaveProperty("scheduleJobId");
287
+ });
288
+
289
+ test("assistantSandwich seeds three messages in user/assistant/user order, with sandwich written before processMessage runs", async () => {
290
+ let addMessageCountAtProcessMessageStart = -1;
291
+ processMessageImpl = async () => {
292
+ addMessageCountAtProcessMessageStart = addMessageCalls.length;
293
+ return { messageId: "msg-final" };
294
+ };
295
+
296
+ await runBackgroundJob(
297
+ baseOpts({
298
+ prompt: "",
299
+ assistantSandwich: {
300
+ preamble: "TRUSTED_PRE",
301
+ content: "UNTRUSTED_PAYLOAD",
302
+ postamble: "TRUSTED_POST",
303
+ },
304
+ }),
305
+ );
306
+
307
+ // All three sandwich addMessage calls happened.
308
+ expect(addMessageCalls).toHaveLength(3);
309
+ expect(addMessageCalls[0]).toMatchObject({
310
+ conversationId: STUB_CONVERSATION_ID,
311
+ role: "user",
312
+ content: "TRUSTED_PRE",
313
+ });
314
+ expect(addMessageCalls[1]).toMatchObject({
315
+ conversationId: STUB_CONVERSATION_ID,
316
+ role: "assistant",
317
+ content: "UNTRUSTED_PAYLOAD",
318
+ });
319
+ expect(addMessageCalls[2]).toMatchObject({
320
+ conversationId: STUB_CONVERSATION_ID,
321
+ role: "user",
322
+ content: "TRUSTED_POST",
323
+ });
324
+ expect(processMessageCalls).toHaveLength(1);
325
+ expect(processMessageCalls[0].content).toBe("");
326
+ // processMessage observed all 3 sandwich messages already in place.
327
+ expect(addMessageCountAtProcessMessageStart).toBe(3);
328
+ });
329
+
330
+ describe("pre-first-message gate", () => {
331
+ test("gate closed: no bootstrap, no processMessage, no notification — result reports skipReason", async () => {
332
+ preFirstMessageGateOpen = false;
333
+
334
+ const result = await runBackgroundJob(baseOpts());
335
+
336
+ expect(result.ok).toBe(true);
337
+ expect(result.skipReason).toBe("pre_first_user_message");
338
+ expect(result.conversationId).toBe("");
339
+ expect(bootstrapCalls).toBe(0);
340
+ expect(processMessageCalls).toHaveLength(0);
341
+ expect(emitCalls).toHaveLength(0);
342
+ });
343
+
344
+ test("gate closed but allowPreFirstUserMessage=true: runs normally", async () => {
345
+ preFirstMessageGateOpen = false;
346
+
347
+ const result = await runBackgroundJob(
348
+ baseOpts({ allowPreFirstUserMessage: true }),
349
+ );
350
+
351
+ expect(result.ok).toBe(true);
352
+ expect(result.skipReason).toBeUndefined();
353
+ expect(bootstrapCalls).toBe(1);
354
+ expect(processMessageCalls).toHaveLength(1);
355
+ });
356
+ });
357
+ });
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Tests for `hasReceivedUserMessage()` — the warm-pool background-job gate.
3
+ *
4
+ * Strategy: stub `rawGet` so we can simulate three states:
5
+ * 1. No user message in standard conversations → gate closed.
6
+ * 2. A user message exists → gate open, subsequent calls cached.
7
+ * 3. `rawGet` throws → gate stays closed (fail-conservative).
8
+ */
9
+
10
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
11
+
12
+ let rawGetImpl: () => unknown = () => null;
13
+ let rawGetCalls = 0;
14
+
15
+ mock.module("../../memory/raw-query.js", () => ({
16
+ rawGet: () => {
17
+ rawGetCalls += 1;
18
+ return rawGetImpl();
19
+ },
20
+ }));
21
+
22
+ // Import after mocks are wired so the module captures the mocked rawGet.
23
+ const { hasReceivedUserMessage, _resetPreFirstMessageGateCacheForTests } =
24
+ await import("../pre-first-message-gate.js");
25
+
26
+ beforeEach(() => {
27
+ _resetPreFirstMessageGateCacheForTests();
28
+ rawGetCalls = 0;
29
+ rawGetImpl = () => null;
30
+ });
31
+
32
+ describe("hasReceivedUserMessage", () => {
33
+ test("returns false when no user message exists in standard conversations", () => {
34
+ rawGetImpl = () => null;
35
+
36
+ expect(hasReceivedUserMessage()).toBe(false);
37
+ expect(rawGetCalls).toBe(1);
38
+ });
39
+
40
+ test("returns true when at least one user message exists", () => {
41
+ rawGetImpl = () => ({ one: 1 });
42
+
43
+ expect(hasReceivedUserMessage()).toBe(true);
44
+ expect(rawGetCalls).toBe(1);
45
+ });
46
+
47
+ test("caches `true` result — subsequent calls do not re-query", () => {
48
+ rawGetImpl = () => ({ one: 1 });
49
+
50
+ expect(hasReceivedUserMessage()).toBe(true);
51
+ expect(hasReceivedUserMessage()).toBe(true);
52
+ expect(hasReceivedUserMessage()).toBe(true);
53
+
54
+ // Only the first call hits the DB.
55
+ expect(rawGetCalls).toBe(1);
56
+ });
57
+
58
+ test("does NOT cache `false` result — re-queries each time so the gate opens once the user interacts", () => {
59
+ rawGetImpl = () => null;
60
+ expect(hasReceivedUserMessage()).toBe(false);
61
+ expect(hasReceivedUserMessage()).toBe(false);
62
+ expect(rawGetCalls).toBe(2);
63
+
64
+ // Simulate the user sending their first message — gate flips on next call.
65
+ rawGetImpl = () => ({ one: 1 });
66
+ expect(hasReceivedUserMessage()).toBe(true);
67
+ expect(rawGetCalls).toBe(3);
68
+
69
+ // And now the cache kicks in.
70
+ expect(hasReceivedUserMessage()).toBe(true);
71
+ expect(rawGetCalls).toBe(3);
72
+ });
73
+
74
+ test("returns false (and logs) when rawGet throws — fail-conservative so background work stays paused", () => {
75
+ rawGetImpl = () => {
76
+ throw new Error("schema not initialized");
77
+ };
78
+
79
+ expect(hasReceivedUserMessage()).toBe(false);
80
+ expect(rawGetCalls).toBe(1);
81
+ });
82
+ });
@@ -13,6 +13,7 @@
13
13
 
14
14
  import type { ChannelId } from "../channels/types.js";
15
15
  import {
16
+ findContactByAddress,
16
17
  findContactByChannelExternalId,
17
18
  findGuardianForChannel,
18
19
  } from "../contacts/contact-store.js";
@@ -205,40 +206,61 @@ export function resolveActorTrust(
205
206
  );
206
207
 
207
208
  // --- Member lookup via contacts ---
209
+ // Primary path: match by externalUserId (populated after channel verification
210
+ // completes, or for channels registered via the verification upsert path).
211
+ // Fallback path: match by address (covers channels registered by the inbound
212
+ // name-capture flow, where address is set but externalUserId remains NULL
213
+ // until the DTMF challenge succeeds). Mirrors the gateway's OR-based lookup
214
+ // in ContactStore.getContactByPhoneNumber so the runtime's unverified-caller
215
+ // guard fires for pre-verification channels the gateway passes through.
208
216
  let memberRecord: ActorTrustContext["memberRecord"] = null;
209
- const contactMatch = findContactByChannelExternalId(
217
+ const byExternalId = findContactByChannelExternalId(
210
218
  input.sourceChannel,
211
219
  canonicalSenderId,
212
220
  );
213
- if (contactMatch) {
214
- const matchingChannel = contactMatch.channels.find(
221
+ const byExternalIdChannel = byExternalId?.channels.find(
222
+ (ch) =>
223
+ ch.type === input.sourceChannel &&
224
+ ch.externalUserId === canonicalSenderId,
225
+ );
226
+
227
+ if (byExternalId && byExternalIdChannel) {
228
+ memberRecord = { contact: byExternalId, channel: byExternalIdChannel };
229
+ } else {
230
+ // Address fallback: catches channels where externalUserId is not yet set.
231
+ const byAddress = findContactByAddress(input.sourceChannel, canonicalSenderId);
232
+ const byAddressChannel = byAddress?.channels.find(
215
233
  (ch) =>
216
234
  ch.type === input.sourceChannel &&
217
- ch.externalUserId === canonicalSenderId,
235
+ ch.address?.toLowerCase() === canonicalSenderId.toLowerCase(),
218
236
  );
219
- if (matchingChannel) {
220
- memberRecord = { contact: contactMatch, channel: matchingChannel };
237
+ if (byAddress && byAddressChannel) {
238
+ memberRecord = { contact: byAddress, channel: byAddressChannel };
221
239
  }
222
240
  }
241
+
223
242
  log.debug(
224
243
  {
225
244
  channel: input.sourceChannel,
226
245
  canonicalSenderId,
227
246
  found: !!memberRecord,
247
+ via: memberRecord?.channel.externalUserId ? "externalUserId" : memberRecord ? "address" : "none",
228
248
  },
229
249
  "trust-resolver member lookup",
230
250
  );
231
251
 
232
- // Only use member metadata when the record's externalUserId matches the
252
+ // Only use member metadata when the record's channel identity matches the
233
253
  // current sender to avoid misidentification in group chats.
234
- // Canonicalize the stored member ID to handle formatting variance (e.g.
235
- // phone numbers stored without E.164 normalization).
254
+ // Primary check: externalUserId (canonicalized to handle E.164 variance).
255
+ // Fallback: address match for channels where externalUserId is NULL (e.g.
256
+ // name-capture registrations that haven't completed DTMF verification yet).
236
257
  const memberMatchesSender = memberRecord?.channel.externalUserId
237
258
  ? canonicalizeInboundIdentity(
238
259
  input.sourceChannel,
239
260
  memberRecord.channel.externalUserId,
240
261
  ) === canonicalSenderId
241
- : false;
262
+ : (memberRecord?.channel.address?.toLowerCase() ===
263
+ canonicalSenderId.toLowerCase());
242
264
 
243
265
  const memberDisplayName =
244
266
  memberMatchesSender &&
@@ -49,6 +49,7 @@ import type {
49
49
  import type { InterfaceId } from "../channels/types.js";
50
50
  import { resolveEffectiveContextWindow } from "../config/llm-context-resolution.js";
51
51
  import { getConfig } from "../config/loader.js";
52
+ import type { LLMCallSite } from "../config/schemas/llm.js";
52
53
  import { getDiskPressureStatus } from "../daemon/disk-pressure-guard.js";
53
54
  import {
54
55
  classifyDiskPressureTurnPolicy,
@@ -56,6 +57,7 @@ import {
56
57
  } from "../daemon/disk-pressure-policy.js";
57
58
  import type { TrustContext } from "../daemon/trust-context.js";
58
59
  import { getConversationOverrideProfile } from "../memory/conversation-crud.js";
60
+ import { recordRequestLog } from "../memory/llm-request-log-store.js";
59
61
  import type { TurnContext } from "../plugins/types.js";
60
62
  import type { Message } from "../providers/types.js";
61
63
  import { getLogger } from "../util/logger.js";
@@ -183,6 +185,13 @@ export interface WakeOptions {
183
185
  */
184
186
  sourceChannel?: TrustContext["sourceChannel"];
185
187
  sourceInterface?: InterfaceId | "vellum";
188
+ /**
189
+ * LLM call site to route this wake through. Defaults to `"mainAgent"` so
190
+ * conversation wakes share the user's chat-model selection. Background jobs
191
+ * (e.g. memory consolidation) pass their own call site so operators can
192
+ * tune the model/profile and observability bucket independently.
193
+ */
194
+ callSite?: LLMCallSite;
186
195
  }
187
196
 
188
197
  /**
@@ -539,6 +548,24 @@ export async function wakeAgentForOpportunity(
539
548
  }
540
549
  };
541
550
  const onEvent = (event: AgentEvent): void => {
551
+ // Replicates the recordRequestLog side-effect in `handleUsage` because
552
+ // wakes own their own onEvent and never reach `dispatchAgentEvent`.
553
+ if (event.type === "usage" && event.rawRequest && event.rawResponse) {
554
+ try {
555
+ recordRequestLog(
556
+ conversationId,
557
+ JSON.stringify(event.rawRequest),
558
+ JSON.stringify(event.rawResponse),
559
+ undefined,
560
+ event.actualProvider,
561
+ );
562
+ } catch (err) {
563
+ log.warn(
564
+ { err, conversationId, source },
565
+ "agent-wake: failed to persist LLM request log (non-fatal)",
566
+ );
567
+ }
568
+ }
542
569
  if (mode === "buffering") {
543
570
  buffered.push(event);
544
571
  return;
@@ -635,10 +662,11 @@ export async function wakeAgentForOpportunity(
635
662
  // `markProcessing(true)` so a thrown DB/config read can't strand the
636
663
  // processing flag.
637
664
  const overrideProfile = getConversationOverrideProfile(conversationId);
665
+ const callSite = opts.callSite ?? "mainAgent";
638
666
  const config = getConfig();
639
667
  const effectiveContextWindow = resolveEffectiveContextWindow({
640
668
  llm: config.llm,
641
- callSite: "mainAgent",
669
+ callSite,
642
670
  overrideProfile,
643
671
  });
644
672
 
@@ -676,12 +704,13 @@ export async function wakeAgentForOpportunity(
676
704
  undefined, // no external abort signal
677
705
  `wake:${source}`,
678
706
  onCheckpoint,
679
- // Route through `mainAgent` same as a normal user turn on this
680
- // conversation. Without an explicit callSite, the resolver in
707
+ // Route through the caller-supplied call site (defaults to
708
+ // `mainAgent` so a normal user-turn wake shares the user's chat
709
+ // selection). Without an explicit callSite, the resolver in
681
710
  // `RetryProvider` and the routing in `CallSiteRoutingProvider`
682
- // short-circuit and silently drop both `llm.callSites.mainAgent`
683
- // config and the pinned `overrideProfile` below.
684
- "mainAgent",
711
+ // short-circuit and silently drop both per-callsite config and the
712
+ // pinned `overrideProfile` below.
713
+ callSite,
685
714
  wakeTurnContext,
686
715
  overrideProfile,
687
716
  effectiveContextWindow.maxInputTokens,