@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
@@ -41,6 +41,49 @@ mock.module("../util/logger.js", () => ({
41
41
  }),
42
42
  }));
43
43
 
44
+ // ── Mock oauth-store so handleOAuthConnectStart can run without a seeded DB ──
45
+ type MockProviderRow = {
46
+ authorizeUrl?: string;
47
+ requiresClientSecret?: boolean;
48
+ [key: string]: unknown;
49
+ };
50
+
51
+ const DEFAULT_PROVIDER: MockProviderRow = {
52
+ authorizeUrl: "https://accounts.google.com/o/oauth2/auth",
53
+ requiresClientSecret: false,
54
+ };
55
+
56
+ let mockGetProvider: (service: string) => MockProviderRow | undefined = () =>
57
+ DEFAULT_PROVIDER;
58
+ let mockGetAppByProviderAndClientId: (
59
+ service: string,
60
+ clientId: string,
61
+ ) => Record<string, unknown> | undefined = (_service, clientId) => ({
62
+ id: "test-app-id",
63
+ provider: "google",
64
+ clientId,
65
+ });
66
+ let mockGetMostRecentAppByProvider: (
67
+ service: string,
68
+ ) => Record<string, unknown> | undefined = () => ({
69
+ id: "test-app-id",
70
+ provider: "google",
71
+ clientId: "default-client-id",
72
+ });
73
+ let mockGetAppClientSecret: (
74
+ row: Record<string, unknown>,
75
+ ) => Promise<string | undefined> = async () => undefined;
76
+
77
+ mock.module("../oauth/oauth-store.js", () => ({
78
+ getProvider: (service: string) => mockGetProvider(service),
79
+ getAppByProviderAndClientId: (service: string, clientId: string) =>
80
+ mockGetAppByProviderAndClientId(service, clientId),
81
+ getMostRecentAppByProvider: (service: string) =>
82
+ mockGetMostRecentAppByProvider(service),
83
+ getAppClientSecret: (row: Record<string, unknown>) =>
84
+ mockGetAppClientSecret(row),
85
+ }));
86
+
44
87
  // NOTE: Do NOT mock oauth-connect-state — use the real module so we can
45
88
  // verify state transitions via getOAuthConnectState.
46
89
 
@@ -65,6 +108,23 @@ function findRoute(operationId: string) {
65
108
  // ── Tests ──────────────────────────────────────────────────────────────────────
66
109
 
67
110
  describe("oauth-connect-routes", () => {
111
+ beforeEach(() => {
112
+ // Reset oauth-store mocks to permissive defaults so every test starts
113
+ // from a clean baseline regardless of what the previous test set.
114
+ mockGetProvider = () => DEFAULT_PROVIDER;
115
+ mockGetAppByProviderAndClientId = (_service, clientId) => ({
116
+ id: "test-app-id",
117
+ provider: "google",
118
+ clientId,
119
+ });
120
+ mockGetMostRecentAppByProvider = () => ({
121
+ id: "test-app-id",
122
+ provider: "google",
123
+ clientId: "default-client-id",
124
+ });
125
+ mockGetAppClientSecret = async () => undefined;
126
+ });
127
+
68
128
  describe("POST internal/oauth/connect/start", () => {
69
129
  beforeEach(() => {
70
130
  capturedOnDeferredComplete = undefined;
@@ -109,17 +169,6 @@ describe("oauth-connect-routes", () => {
109
169
  ).rejects.toBeInstanceOf(BadRequestError);
110
170
  });
111
171
 
112
- test("missing clientId throws BadRequestError", async () => {
113
- await expect(
114
- findRoute("internal_oauth_connect_start").handler({
115
- body: {
116
- service: "google",
117
- callbackTransport: "gateway",
118
- },
119
- }),
120
- ).rejects.toBeInstanceOf(BadRequestError);
121
- });
122
-
123
172
  test("missing service throws BadRequestError", async () => {
124
173
  await expect(
125
174
  findRoute("internal_oauth_connect_start").handler({
@@ -183,6 +232,120 @@ describe("oauth-connect-routes", () => {
183
232
  }),
184
233
  ).rejects.toBeInstanceOf(InternalError);
185
234
  });
235
+
236
+ test("unknown provider throws NotFoundError", async () => {
237
+ mockGetProvider = () => undefined;
238
+ await expect(
239
+ findRoute("internal_oauth_connect_start").handler({
240
+ body: {
241
+ service: "made-up-service",
242
+ clientId: "my-client-id",
243
+ callbackTransport: "gateway",
244
+ },
245
+ }),
246
+ ).rejects.toBeInstanceOf(NotFoundError);
247
+ });
248
+
249
+ test("manual-token provider rejected even when clientId is explicitly supplied", async () => {
250
+ // Codex/Devin finding on PR #30251: the manual-token check used to live
251
+ // inside `if (!clientId)`, so callers passing `--client-id` for a
252
+ // manual-token provider (e.g. slack_channel, telegram) bypassed it.
253
+ mockGetProvider = () => ({
254
+ authorizeUrl: "urn:manual-token",
255
+ requiresClientSecret: false,
256
+ });
257
+ await expect(
258
+ findRoute("internal_oauth_connect_start").handler({
259
+ body: {
260
+ service: "slack_channel",
261
+ clientId: "any-client-id",
262
+ callbackTransport: "gateway",
263
+ },
264
+ }),
265
+ ).rejects.toBeInstanceOf(BadRequestError);
266
+ });
267
+
268
+ test("manual-token provider rejected when no clientId is supplied", async () => {
269
+ mockGetProvider = () => ({
270
+ authorizeUrl: "urn:manual-token",
271
+ requiresClientSecret: false,
272
+ });
273
+ await expect(
274
+ findRoute("internal_oauth_connect_start").handler({
275
+ body: {
276
+ service: "slack_channel",
277
+ callbackTransport: "gateway",
278
+ },
279
+ }),
280
+ ).rejects.toBeInstanceOf(BadRequestError);
281
+ });
282
+
283
+ test("explicit clientId with no registered app throws NotFoundError", async () => {
284
+ // Devin finding on PR #30251: the explicit-clientId branch used to
285
+ // silently continue when getAppByProviderAndClientId returned null,
286
+ // letting orchestrateOAuthConnect fail later with a less helpful error.
287
+ mockGetAppByProviderAndClientId = () => undefined;
288
+ await expect(
289
+ findRoute("internal_oauth_connect_start").handler({
290
+ body: {
291
+ service: "google",
292
+ clientId: "unregistered-client-id",
293
+ callbackTransport: "gateway",
294
+ },
295
+ }),
296
+ ).rejects.toBeInstanceOf(NotFoundError);
297
+ });
298
+
299
+ test("no clientId and no registered app throws BadRequestError", async () => {
300
+ mockGetMostRecentAppByProvider = () => undefined;
301
+ await expect(
302
+ findRoute("internal_oauth_connect_start").handler({
303
+ body: {
304
+ service: "google",
305
+ callbackTransport: "gateway",
306
+ },
307
+ }),
308
+ ).rejects.toBeInstanceOf(BadRequestError);
309
+ });
310
+
311
+ test("missing client_secret when provider requiresClientSecret throws BadRequestError", async () => {
312
+ // Devin finding on PR #30251: requiresClientSecret was only checked
313
+ // inside the `!clientId` branch. Hoisting it ensures explicit-clientId
314
+ // callers also fail fast with an actionable error.
315
+ mockGetProvider = () => ({
316
+ authorizeUrl: "https://accounts.example.com/o/oauth2/auth",
317
+ requiresClientSecret: true,
318
+ });
319
+ mockGetAppClientSecret = async () => undefined;
320
+ await expect(
321
+ findRoute("internal_oauth_connect_start").handler({
322
+ body: {
323
+ service: "github",
324
+ clientId: "explicit-client-id",
325
+ callbackTransport: "gateway",
326
+ },
327
+ }),
328
+ ).rejects.toBeInstanceOf(BadRequestError);
329
+ });
330
+
331
+ test("explicit clientId + stored secret succeeds without caller-supplied secret", async () => {
332
+ mockGetProvider = () => ({
333
+ authorizeUrl: "https://accounts.example.com/o/oauth2/auth",
334
+ requiresClientSecret: true,
335
+ });
336
+ mockGetAppClientSecret = async () => "stored-secret-from-keyring";
337
+ const result = await findRoute("internal_oauth_connect_start").handler({
338
+ body: {
339
+ service: "github",
340
+ clientId: "explicit-client-id",
341
+ callbackTransport: "gateway",
342
+ },
343
+ });
344
+ expect(result).toMatchObject({
345
+ auth_url: "https://accounts.google.com/o/oauth2/auth?client_id=test",
346
+ state: "test-state-uuid-abc123",
347
+ });
348
+ });
186
349
  });
187
350
 
188
351
  describe("GET internal/oauth/connect/status/:state", () => {
@@ -245,22 +245,26 @@ describe("GET /v1/oauth/providers/:providerKey", () => {
245
245
  );
246
246
 
247
247
  expect(status).toBe(200);
248
+ // The GET-by-key endpoint uses `serializeProviderFull`, which intentionally
249
+ // emits camelCase keys (see provider-serializer.ts). The list endpoint
250
+ // uses `serializeProviderSummary` and emits snake_case — these are
251
+ // separate wire formats by design.
248
252
  const { provider } = body as {
249
253
  provider: {
250
- provider_key: string;
251
- display_name: string | null;
254
+ providerKey: string;
255
+ displayName: string | null;
252
256
  description: string | null;
253
- dashboard_url: string | null;
254
- client_id_placeholder: string | null;
255
- requires_client_secret: boolean;
256
- supports_managed_mode: boolean;
257
+ dashboardUrl: string | null;
258
+ clientIdPlaceholder: string | null;
259
+ requiresClientSecret: boolean;
260
+ supportsManagedMode: boolean;
257
261
  };
258
262
  };
259
263
 
260
- expect(provider.provider_key).toBe("google");
261
- expect(provider.display_name).toBe("Google");
262
- expect(provider.supports_managed_mode).toBe(true);
263
- expect(provider.requires_client_secret).toBe(true);
264
+ expect(provider.providerKey).toBe("google");
265
+ expect(provider.displayName).toBe("Google");
266
+ expect(provider.supportsManagedMode).toBe(true);
267
+ expect(provider.requiresClientSecret).toBe(true);
264
268
  });
265
269
 
266
270
  test("returns 404 for unknown provider", async () => {
@@ -13,8 +13,9 @@ import { describe, expect, test } from "bun:test";
13
13
  *
14
14
  * These guards fail CI if:
15
15
  * 1. The Responses provider file contains `chat.completions.create(` calls.
16
- * 2. The provider registry wires `openai` to anything other than
17
- * `OpenAIResponsesProvider`.
16
+ * 2. The adapter factory wires `openai` to anything other than
17
+ * `OpenAIResponsesProvider`. (Catalog-driven adapter construction lives
18
+ * in `inference/adapter-factory.ts`; `registry.ts` only orchestrates it.)
18
19
  * 3. A new file appears in `providers/openai/` that introduces
19
20
  * `chat.completions.create(` calls.
20
21
  *
@@ -40,6 +41,11 @@ import { describe, expect, test } from "bun:test";
40
41
 
41
42
  const PROVIDERS_DIR = join(import.meta.dir, "..", "providers");
42
43
  const OPENAI_PROVIDERS_DIR = join(PROVIDERS_DIR, "openai");
44
+ const ADAPTER_FACTORY_PATH = join(
45
+ PROVIDERS_DIR,
46
+ "inference",
47
+ "adapter-factory.ts",
48
+ );
43
49
 
44
50
  describe("OpenAI Responses API cutover guard", () => {
45
51
  test("responses-provider.ts does not contain chat.completions.create() calls", () => {
@@ -60,32 +66,34 @@ describe("OpenAI Responses API cutover guard", () => {
60
66
  ).toBe(false);
61
67
  });
62
68
 
63
- test("registry.ts wires the 'openai' provider to OpenAIResponsesProvider", () => {
64
- const source = readFileSync(join(PROVIDERS_DIR, "registry.ts"), "utf-8");
69
+ test("adapter-factory.ts wires the 'openai' provider to OpenAIResponsesProvider", () => {
70
+ // Catalog-driven adapter construction lives in `adapter-factory.ts`.
71
+ // `registry.ts` only orchestrates and wraps the adapter; the only place
72
+ // that names a provider class for the "openai" id is the factory table.
73
+ const source = readFileSync(ADAPTER_FACTORY_PATH, "utf-8");
65
74
 
66
- // The registry should import OpenAIResponsesProvider
75
+ // The factory must import OpenAIResponsesProvider.
67
76
  expect(
68
77
  source.includes("OpenAIResponsesProvider"),
69
- "registry.ts must import OpenAIResponsesProvider for the openai provider.",
78
+ "adapter-factory.ts must import OpenAIResponsesProvider for the openai provider.",
70
79
  ).toBe(true);
71
80
 
72
- // The registry should instantiate OpenAIResponsesProvider for the "openai" key.
73
- // Look for `new OpenAIResponsesProvider(` near the openai registration block.
81
+ // The factory must instantiate OpenAIResponsesProvider.
74
82
  const hasResponsesInstantiation = source.includes(
75
83
  "new OpenAIResponsesProvider(",
76
84
  );
77
85
  expect(
78
86
  hasResponsesInstantiation,
79
87
  [
80
- "registry.ts must instantiate OpenAIResponsesProvider for the 'openai' provider.",
88
+ "adapter-factory.ts must instantiate OpenAIResponsesProvider for the 'openai' provider.",
81
89
  "OpenAI inference uses the Responses API, not chat completions.",
82
90
  ].join("\n"),
83
91
  ).toBe(true);
84
92
 
85
- // The registry should NOT instantiate OpenAIChatCompletionsProvider or
93
+ // The factory must NOT instantiate OpenAIChatCompletionsProvider or
86
94
  // OpenAIProvider (the backward-compatible alias) for the "openai" key.
87
95
  // Chat-completions classes may appear in imports but should not be
88
- // instantiated in the openai registration block.
96
+ // instantiated in the openai factory entry.
89
97
  const chatCompletionsInstantiations = [
90
98
  ...source.matchAll(/new\s+OpenAIChatCompletionsProvider\s*\(/g),
91
99
  ...source.matchAll(/new\s+OpenAIProvider\s*\(/g),
@@ -93,10 +101,23 @@ describe("OpenAI Responses API cutover guard", () => {
93
101
  expect(
94
102
  chatCompletionsInstantiations.length,
95
103
  [
96
- "registry.ts must NOT instantiate OpenAIChatCompletionsProvider or",
104
+ "adapter-factory.ts must NOT instantiate OpenAIChatCompletionsProvider or",
97
105
  "OpenAIProvider (legacy alias). Use OpenAIResponsesProvider for openai.",
98
106
  ].join("\n"),
99
107
  ).toBe(0);
108
+
109
+ // The factory's "openai" entry must specifically map to OpenAIResponsesProvider.
110
+ // Match `openai:` followed (within ~400 chars) by `new OpenAIResponsesProvider(`
111
+ // to confirm wiring at the entry level, not just an unrelated reference.
112
+ const openaiEntryWiring =
113
+ /openai\s*:\s*\([^)]*\)\s*=>\s*[\s\S]{0,400}?new\s+OpenAIResponsesProvider\s*\(/;
114
+ expect(
115
+ openaiEntryWiring.test(source),
116
+ [
117
+ "adapter-factory.ts ADAPTER_FACTORIES['openai'] entry must construct",
118
+ "OpenAIResponsesProvider. If the factory shape changed, update this guard.",
119
+ ].join("\n"),
120
+ ).toBe(true);
100
121
  });
101
122
 
102
123
  test("no files in providers/openai/ introduce chat.completions.create() calls", () => {
@@ -677,6 +677,23 @@ describe("OpenAIResponsesProvider", () => {
677
677
  expect(lastStreamParams!.text).toEqual({ verbosity: "high" });
678
678
  });
679
679
 
680
+ test("verbosity is forwarded for GPT-5 fine-tune IDs", async () => {
681
+ const ftProvider = new OpenAIResponsesProvider(
682
+ "sk-test",
683
+ "ft:gpt-5.2:acme::abc123",
684
+ );
685
+ fakeStreamEvents = [textDeltaEvent("OK"), completedEvent(10, 2)];
686
+
687
+ await ftProvider.sendMessage(
688
+ [{ role: "user", content: [{ type: "text", text: "Hi" }] }],
689
+ undefined,
690
+ undefined,
691
+ { config: { verbosity: "low" } },
692
+ );
693
+
694
+ expect(lastStreamParams!.text).toEqual({ verbosity: "low" });
695
+ });
696
+
680
697
  // -----------------------------------------------------------------------
681
698
  // Model override
682
699
  // -----------------------------------------------------------------------
@@ -70,15 +70,43 @@ const fakeCtx: DaemonContext = {
70
70
  assistantVersion: "9.9.9-test",
71
71
  };
72
72
 
73
+ /**
74
+ * Test helper. Accepts the new `hooks` bag and ALSO legacy top-level
75
+ * `init` / `onShutdown` for ergonomics — the helper merges them into a
76
+ * single `hooks` field that matches the runtime Plugin shape. This keeps
77
+ * the test call sites compact without leaking the old contract.
78
+ */
73
79
  function buildPlugin(
74
80
  name: string,
75
- extras: Partial<Omit<Plugin, "manifest">> = {},
81
+ extras: Partial<Omit<Plugin, "manifest" | "hooks">> & {
82
+ hooks?: Plugin["hooks"];
83
+ init?: (ctx: PluginInitContext) => Promise<void>;
84
+ onShutdown?: () => Promise<void>;
85
+ } = {},
76
86
  options: {
77
87
  requires?: Record<string, string>;
78
88
  requiresCredential?: string[];
79
89
  requiresFlag?: string[];
80
90
  } = {},
81
91
  ): Plugin {
92
+ const {
93
+ init: legacyInit,
94
+ onShutdown: legacyOnShutdown,
95
+ hooks: explicitHooks,
96
+ ...rest
97
+ } = extras;
98
+ const mergedHooks: Plugin["hooks"] | undefined =
99
+ legacyInit !== undefined ||
100
+ legacyOnShutdown !== undefined ||
101
+ explicitHooks !== undefined
102
+ ? {
103
+ ...(explicitHooks ?? {}),
104
+ ...(legacyInit !== undefined ? { init: legacyInit } : {}),
105
+ ...(legacyOnShutdown !== undefined
106
+ ? { shutdown: legacyOnShutdown }
107
+ : {}),
108
+ }
109
+ : undefined;
82
110
  return {
83
111
  manifest: {
84
112
  name,
@@ -89,7 +117,8 @@ function buildPlugin(
89
117
  : {}),
90
118
  ...(options.requiresFlag ? { requiresFlag: options.requiresFlag } : {}),
91
119
  },
92
- ...extras,
120
+ ...rest,
121
+ ...(mergedHooks ? { hooks: mergedHooks } : {}),
93
122
  };
94
123
  }
95
124
 
@@ -53,7 +53,7 @@ import {
53
53
  registerPlugin,
54
54
  resetPluginRegistryForTests,
55
55
  } from "../plugins/registry.js";
56
- import type { Plugin } from "../plugins/types.js";
56
+ import type { Plugin, PluginInitContext } from "../plugins/types.js";
57
57
  import {
58
58
  matchSkillRoute,
59
59
  resetSkillRoutesForTests,
@@ -76,17 +76,45 @@ const fakeCtx: DaemonContext = {
76
76
  };
77
77
 
78
78
  /** Build a minimal valid plugin with optional route contributions. */
79
+ /**
80
+ * Test helper. Accepts the new `hooks` bag and ALSO legacy top-level
81
+ * `init` / `onShutdown` for ergonomics — the helper merges them into a
82
+ * single `hooks` field that matches the runtime Plugin shape.
83
+ */
79
84
  function buildPlugin(
80
85
  name: string,
81
- extras: Partial<Omit<Plugin, "manifest">> = {},
86
+ extras: Partial<Omit<Plugin, "manifest" | "hooks">> & {
87
+ hooks?: Plugin["hooks"];
88
+ init?: (ctx: PluginInitContext) => Promise<void>;
89
+ onShutdown?: () => Promise<void>;
90
+ } = {},
82
91
  ): Plugin {
92
+ const {
93
+ init: legacyInit,
94
+ onShutdown: legacyOnShutdown,
95
+ hooks: explicitHooks,
96
+ ...rest
97
+ } = extras;
98
+ const mergedHooks: Plugin["hooks"] | undefined =
99
+ legacyInit !== undefined ||
100
+ legacyOnShutdown !== undefined ||
101
+ explicitHooks !== undefined
102
+ ? {
103
+ ...(explicitHooks ?? {}),
104
+ ...(legacyInit !== undefined ? { init: legacyInit } : {}),
105
+ ...(legacyOnShutdown !== undefined
106
+ ? { shutdown: legacyOnShutdown }
107
+ : {}),
108
+ }
109
+ : undefined;
83
110
  return {
84
111
  manifest: {
85
112
  name,
86
113
  version: "0.0.1",
87
114
  requires: { pluginRuntime: "v1" },
88
115
  },
89
- ...extras,
116
+ ...rest,
117
+ ...(mergedHooks ? { hooks: mergedHooks } : {}),
90
118
  };
91
119
  }
92
120
 
@@ -48,7 +48,7 @@ import {
48
48
  registerPlugin,
49
49
  resetPluginRegistryForTests,
50
50
  } from "../plugins/registry.js";
51
- import type { Plugin } from "../plugins/types.js";
51
+ import type { Plugin, PluginInitContext } from "../plugins/types.js";
52
52
  import type { ToolDefinition } from "../providers/types.js";
53
53
  import {
54
54
  __clearRegistryForTesting,
@@ -99,17 +99,45 @@ function makeFakeTool(name: string, extras: Partial<Tool> = {}): Tool {
99
99
  };
100
100
  }
101
101
 
102
+ /**
103
+ * Test helper. Accepts the new `hooks` bag and ALSO legacy top-level
104
+ * `init` / `onShutdown` for ergonomics — the helper merges them into a
105
+ * single `hooks` field that matches the runtime Plugin shape.
106
+ */
102
107
  function buildPlugin(
103
108
  name: string,
104
- extras: Partial<Omit<Plugin, "manifest">> = {},
109
+ extras: Partial<Omit<Plugin, "manifest" | "hooks">> & {
110
+ hooks?: Plugin["hooks"];
111
+ init?: (ctx: PluginInitContext) => Promise<void>;
112
+ onShutdown?: () => Promise<void>;
113
+ } = {},
105
114
  ): Plugin {
115
+ const {
116
+ init: legacyInit,
117
+ onShutdown: legacyOnShutdown,
118
+ hooks: explicitHooks,
119
+ ...rest
120
+ } = extras;
121
+ const mergedHooks: Plugin["hooks"] | undefined =
122
+ legacyInit !== undefined ||
123
+ legacyOnShutdown !== undefined ||
124
+ explicitHooks !== undefined
125
+ ? {
126
+ ...(explicitHooks ?? {}),
127
+ ...(legacyInit !== undefined ? { init: legacyInit } : {}),
128
+ ...(legacyOnShutdown !== undefined
129
+ ? { shutdown: legacyOnShutdown }
130
+ : {}),
131
+ }
132
+ : undefined;
106
133
  return {
107
134
  manifest: {
108
135
  name,
109
136
  version: "0.0.1",
110
137
  requires: { pluginRuntime: "v1" },
111
138
  },
112
- ...extras,
139
+ ...rest,
140
+ ...(mergedHooks ? { hooks: mergedHooks } : {}),
113
141
  };
114
142
  }
115
143
 
@@ -228,17 +228,19 @@ describe("plugin core types", () => {
228
228
 
229
229
  const plugin = {
230
230
  manifest,
231
- async init(ctx: PluginInitContext) {
232
- // Touch every field so refactors that rename any of them break here.
233
- void ctx.config;
234
- void ctx.credentials;
235
- void ctx.logger;
236
- void ctx.pluginStorageDir;
237
- void ctx.assistantVersion;
238
- void ctx.apiVersions;
239
- },
240
- async onShutdown() {
241
- // no-op
231
+ hooks: {
232
+ async init(ctx: PluginInitContext) {
233
+ // Touch every field so refactors that rename any of them break here.
234
+ void ctx.config;
235
+ void ctx.credentials;
236
+ void ctx.logger;
237
+ void ctx.pluginStorageDir;
238
+ void ctx.assistantVersion;
239
+ void ctx.apiVersions;
240
+ },
241
+ async shutdown() {
242
+ // no-op
243
+ },
242
244
  },
243
245
  tools: [sampleTool],
244
246
  routes: [
@@ -30,6 +30,14 @@ mock.module("../memory/conversation-disk-view.js", () => ({
30
30
  updateMetaFile: () => {},
31
31
  }));
32
32
 
33
+ const broadcastMessages: unknown[] = [];
34
+
35
+ mock.module("../runtime/assistant-event-hub.js", () => ({
36
+ broadcastMessage: (msg: unknown) => {
37
+ broadcastMessages.push(msg);
38
+ },
39
+ }));
40
+
33
41
  mock.module("../runtime/confirmation-request-guardian-bridge.js", () => ({
34
42
  bridgeConfirmationRequestToGuardian: () => {},
35
43
  }));
@@ -240,6 +248,7 @@ describe("processMessageInBackground Slack option propagation", () => {
240
248
  beforeEach(() => {
241
249
  activeConversation = makeConversation();
242
250
  mergeConversationOptionsMock.mockClear();
251
+ broadcastMessages.length = 0;
243
252
  });
244
253
 
245
254
  test("passes Slack inbound metadata to persistence and exposes the runtime notice during the loop", async () => {
@@ -309,6 +318,43 @@ describe("processMessageInBackground Slack option propagation", () => {
309
318
  expect(activeConversation.__clientSenders).toHaveLength(2);
310
319
  });
311
320
 
321
+ test("observes live agent events without replacing the broadcast emitter", async () => {
322
+ const observedMessages: unknown[] = [];
323
+
324
+ const processing = processMessage(
325
+ "conv-background-slack",
326
+ "Reply from Slack",
327
+ undefined,
328
+ {
329
+ onEvent: (msg) => {
330
+ observedMessages.push(msg);
331
+ },
332
+ },
333
+ "slack",
334
+ "slack",
335
+ );
336
+
337
+ await waitForRunAgentLoopCall();
338
+
339
+ const loopOnEvent = activeConversation.runAgentLoop.mock.calls[0][2] as
340
+ | ((msg: unknown) => void)
341
+ | undefined;
342
+ const delta = {
343
+ type: "assistant_text_delta",
344
+ text: "Working on it.",
345
+ conversationId: "conv-background-slack",
346
+ };
347
+ loopOnEvent?.(delta);
348
+
349
+ expect(broadcastMessages).toEqual([delta]);
350
+ expect(observedMessages).toEqual([delta]);
351
+
352
+ activeConversation.__loopDeferred.resolve();
353
+ await expect(processing).resolves.toEqual({
354
+ messageId: "persisted-user-message-id",
355
+ });
356
+ });
357
+
312
358
  test("leaves non-Slack background persistence metadata absent", async () => {
313
359
  await processMessageInBackground(
314
360
  "conv-background-slack",
@@ -0,0 +1,43 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { ProfileEntry } from "../config/schemas/llm.js";
4
+
5
+ describe("ProfileEntry status field", () => {
6
+ test("parses a profile with status: disabled", () => {
7
+ const result = ProfileEntry.safeParse({
8
+ status: "disabled",
9
+ });
10
+ expect(result.success).toBe(true);
11
+ if (result.success) {
12
+ expect(result.data.status).toBe("disabled");
13
+ }
14
+ });
15
+
16
+ test("parses a profile without status — status is undefined (treated as active)", () => {
17
+ const result = ProfileEntry.safeParse({
18
+ provider: "anthropic",
19
+ model: "claude-opus-4-7",
20
+ });
21
+ expect(result.success).toBe(true);
22
+ if (result.success) {
23
+ expect(result.data.status).toBeUndefined();
24
+ }
25
+ });
26
+
27
+ test("parses a profile with status: active", () => {
28
+ const result = ProfileEntry.safeParse({
29
+ status: "active",
30
+ });
31
+ expect(result.success).toBe(true);
32
+ if (result.success) {
33
+ expect(result.data.status).toBe("active");
34
+ }
35
+ });
36
+
37
+ test("rejects an invalid status value", () => {
38
+ const result = ProfileEntry.safeParse({
39
+ status: "hidden",
40
+ });
41
+ expect(result.success).toBe(false);
42
+ });
43
+ });