@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
@@ -208,9 +208,11 @@ describe("Invariant 2: no generic plaintext secret read API", () => {
208
208
  "config/bundled-skills/image-studio/tools/media-generate-image.ts", // image generation tool API key lookup
209
209
  "config/bundled-skills/media-processing/tools/analyze-keyframes.ts", // keyframe analysis tool API key lookup
210
210
  "providers/registry.ts", // provider registry API key lookup for initialization
211
+ "providers/inference/resolve-auth.ts", // provider_connection auth resolver (api_key path reads vault, mirrors registry.ts)
211
212
  "providers/provider-availability.ts", // provider availability API key check
212
213
  "media/image-credentials.ts", // shared image-gen credential resolver (provider API key lookup)
213
214
  "memory/embedding-backend.ts", // embedding backend API key lookup
215
+ "memory/llm-request-log-source-clickhouse.ts", // ClickHouse read source — lazy lookup of clickhouse:url + clickhouse:password + vellum:platform_assistant_id for self-scoped mirror reads
214
216
  "daemon/providers-setup.ts", // provider initialization API key lookup
215
217
  "workspace/migrations/006-services-config.ts", // services config migration reads provider API keys
216
218
  "workspace/migrations/018-rekey-compound-credential-keys.ts", // re-key compound credential storage keys
@@ -220,22 +222,19 @@ describe("Invariant 2: no generic plaintext secret read API", () => {
220
222
  "daemon/lifecycle.ts", // CES client injection into secure-keys at startup
221
223
  "daemon/daemon-skill-host.ts", // SkillHost secureKeys facet adapter (delegates to getProviderKeyAsync)
222
224
  "runtime/routes/credential-prompt-routes.ts", // Route for secure credential prompt (stores secret via setSecureKeyAsync)
225
+ "runtime/routes/credential-routes.ts", // CLI credential management routes (CLI-migrated to IPC)
226
+ "runtime/routes/platform-routes.ts", // CLI platform connect/disconnect/status routes (CLI-migrated to IPC)
223
227
  "ipc/skill-routes/providers.ts", // host.providers.secureKeys.getProviderKey IPC route (out-of-process SkillHost companion)
224
228
  "daemon/external-plugins-bootstrap.ts", // reads credentials at plugin init (manifest.requiresCredential) via the CES-mediated getSecureKeyAsync path
225
229
  "inbound/platform-callback-registration.ts", // managed credential lookup for platform base URL, assistant ID, and API key
226
230
  "tts/providers/elevenlabs-provider.ts", // ElevenLabs TTS API key lookup
227
231
  "tts/providers/deepgram-provider.ts", // Deepgram TTS API key lookup
228
232
  "tts/providers/xai-provider.ts", // xAI TTS API key lookup
229
- "meet/session-manager.ts", // Meet bot container provisioning (provider API key lookup for Deepgram/TTS)
230
233
  "credential-health/credential-health-service.ts", // credential health check reads access tokens for liveness pings
231
234
  "ipc/skill-routes/providers.ts", // skill IPC route exposes provider key lookup to hosted skills
232
- "cli/commands/avatar.ts", // CLI avatar command credential lookup
233
- "cli/commands/credentials.ts", // CLI credential management commands
235
+ "runtime/routes/avatar-routes.ts", // avatar generate route reads platform_base_url from credential store
234
236
  "cli/commands/keys.ts", // CLI provider key management
235
237
  "cli/commands/oauth/connect.ts", // CLI OAuth connect stored-secret verification
236
- "cli/commands/platform/connect.ts", // CLI platform connect credential check
237
- "cli/commands/platform/disconnect.ts", // CLI platform disconnect credential lookup
238
- "cli/commands/platform/index.ts", // CLI platform status credential check
239
238
  ]);
240
239
 
241
240
  const thisDir = dirname(fileURLToPath(import.meta.url));
@@ -13,8 +13,13 @@ let _ipcResponse: { ok: boolean; result?: unknown; error?: string } = {
13
13
  error: "Could not connect to assistant daemon. Is it running?",
14
14
  };
15
15
 
16
+ let _lastIpcCall: { method: string; params: unknown } | null = null;
17
+
16
18
  mock.module("../ipc/cli-client.js", () => ({
17
- cliIpcCall: async () => _ipcResponse,
19
+ cliIpcCall: async (method: string, params: unknown) => {
20
+ _lastIpcCall = { method, params };
21
+ return _ipcResponse;
22
+ },
18
23
  }));
19
24
 
20
25
  mock.module("../util/logger.js", () => ({
@@ -120,4 +125,54 @@ describe("daemon credential client", () => {
120
125
  expect(result.error).toBeUndefined();
121
126
  });
122
127
  });
128
+
129
+ // Regression: the IPC server registers route handlers by `operationId`
130
+ // (e.g. `secrets_add`, `secrets_delete`) and unwraps params from
131
+ // `{ body: ... }`. Earlier versions called `secrets/write` and
132
+ // `secrets/delete` with un-wrapped params, which the IPC server rejected
133
+ // with "Unknown method". These tests pin the wire format so it cannot
134
+ // silently drift again.
135
+ describe("IPC wire format", () => {
136
+ test("set uses secrets_add with body-wrapped params", async () => {
137
+ _ipcResponse = { ok: true, result: { success: true } };
138
+ _lastIpcCall = null;
139
+
140
+ await setSecureKeyViaDaemon(
141
+ "credential",
142
+ "github-app:pem",
143
+ "secret-pem-value",
144
+ );
145
+
146
+ const captured = _lastIpcCall as {
147
+ method: string;
148
+ params: unknown;
149
+ } | null;
150
+ expect(captured).not.toBeNull();
151
+ expect(captured?.method).toBe("secrets_add");
152
+ expect(captured?.params).toEqual({
153
+ body: {
154
+ type: "credential",
155
+ name: "github-app:pem",
156
+ value: "secret-pem-value",
157
+ },
158
+ });
159
+ });
160
+
161
+ test("delete uses secrets_delete with body-wrapped params", async () => {
162
+ _ipcResponse = { ok: true, result: { success: true } };
163
+ _lastIpcCall = null;
164
+
165
+ await deleteSecureKeyViaDaemon("credential", "github-app:pem");
166
+
167
+ const captured = _lastIpcCall as {
168
+ method: string;
169
+ params: unknown;
170
+ } | null;
171
+ expect(captured).not.toBeNull();
172
+ expect(captured?.method).toBe("secrets_delete");
173
+ expect(captured?.params).toEqual({
174
+ body: { type: "credential", name: "github-app:pem" },
175
+ });
176
+ });
177
+ });
123
178
  });
@@ -0,0 +1,132 @@
1
+ import { Database } from "bun:sqlite";
2
+ import { describe, expect, test } from "bun:test";
3
+
4
+ import { drizzle } from "drizzle-orm/bun-sqlite";
5
+
6
+ import { getSqliteFrom } from "../memory/db-connection.js";
7
+ import { migrateActivationState } from "../memory/migrations/232-activation-state.js";
8
+ import { migrateActivationStateFkCascade } from "../memory/migrations/241-activation-state-fk-cascade.js";
9
+ import * as schema from "../memory/schema.js";
10
+
11
+ function createTestDb() {
12
+ const sqlite = new Database(":memory:");
13
+ sqlite.exec("PRAGMA journal_mode=WAL");
14
+ sqlite.exec("PRAGMA foreign_keys = ON");
15
+ return drizzle(sqlite, { schema });
16
+ }
17
+
18
+ function bootstrap(raw: Database): void {
19
+ raw.exec(/*sql*/ `
20
+ CREATE TABLE IF NOT EXISTS memory_checkpoints (
21
+ key TEXT PRIMARY KEY,
22
+ value TEXT NOT NULL,
23
+ updated_at INTEGER NOT NULL
24
+ )
25
+ `);
26
+ raw.exec(/*sql*/ `
27
+ CREATE TABLE IF NOT EXISTS conversations (id TEXT PRIMARY KEY)
28
+ `);
29
+ }
30
+
31
+ function insertActivation(
32
+ raw: Database,
33
+ conversationId: string,
34
+ messageId = "msg-1",
35
+ ): void {
36
+ raw
37
+ .query(
38
+ /*sql*/ `INSERT INTO activation_state (conversation_id, message_id, state_json, updated_at) VALUES (?, ?, ?, ?)`,
39
+ )
40
+ .run(conversationId, messageId, "{}", 1);
41
+ }
42
+
43
+ describe("activation_state FK cascade migration", () => {
44
+ test("rebuilds the table with ON DELETE CASCADE", () => {
45
+ const db = createTestDb();
46
+ const raw = getSqliteFrom(db);
47
+ bootstrap(raw);
48
+
49
+ migrateActivationState(db);
50
+ migrateActivationStateFkCascade(db);
51
+
52
+ const ddl = raw
53
+ .query(
54
+ `SELECT sql FROM sqlite_master WHERE type='table' AND name='activation_state'`,
55
+ )
56
+ .get() as { sql: string } | null;
57
+ expect(ddl?.sql).toContain("REFERENCES conversations(id)");
58
+ expect(ddl?.sql).toContain("ON DELETE CASCADE");
59
+ });
60
+
61
+ test("deleting a conversation cascades to activation_state", () => {
62
+ const db = createTestDb();
63
+ const raw = getSqliteFrom(db);
64
+ bootstrap(raw);
65
+
66
+ migrateActivationState(db);
67
+ migrateActivationStateFkCascade(db);
68
+
69
+ raw.query(`INSERT INTO conversations (id) VALUES (?)`).run("conv-1");
70
+ insertActivation(raw, "conv-1");
71
+
72
+ raw.query(`DELETE FROM conversations WHERE id = ?`).run("conv-1");
73
+
74
+ const remaining = raw
75
+ .query(`SELECT COUNT(*) AS n FROM activation_state`)
76
+ .get() as { n: number };
77
+ expect(remaining.n).toBe(0);
78
+ });
79
+
80
+ test("rebuild purges existing orphan rows", () => {
81
+ const db = createTestDb();
82
+ const raw = getSqliteFrom(db);
83
+ bootstrap(raw);
84
+
85
+ migrateActivationState(db);
86
+
87
+ raw.query(`INSERT INTO conversations (id) VALUES (?)`).run("conv-live");
88
+ insertActivation(raw, "conv-live");
89
+ insertActivation(raw, "conv-orphan");
90
+
91
+ migrateActivationStateFkCascade(db);
92
+
93
+ const rows = raw
94
+ .query(
95
+ `SELECT conversation_id FROM activation_state ORDER BY conversation_id`,
96
+ )
97
+ .all() as Array<{ conversation_id: string }>;
98
+ expect(rows.map((r) => r.conversation_id)).toEqual(["conv-live"]);
99
+ });
100
+
101
+ test("is idempotent — second run is a no-op", () => {
102
+ const db = createTestDb();
103
+ const raw = getSqliteFrom(db);
104
+ bootstrap(raw);
105
+
106
+ migrateActivationState(db);
107
+ migrateActivationStateFkCascade(db);
108
+ expect(() => migrateActivationStateFkCascade(db)).not.toThrow();
109
+
110
+ const ddl = raw
111
+ .query(
112
+ `SELECT sql FROM sqlite_master WHERE type='table' AND name='activation_state'`,
113
+ )
114
+ .get() as { sql: string } | null;
115
+ expect(ddl?.sql).toContain("ON DELETE CASCADE");
116
+ });
117
+
118
+ test("no-ops when activation_state table is absent", () => {
119
+ const db = createTestDb();
120
+ const raw = getSqliteFrom(db);
121
+ bootstrap(raw);
122
+
123
+ expect(() => migrateActivationStateFkCascade(db)).not.toThrow();
124
+
125
+ const tableRow = raw
126
+ .query(
127
+ `SELECT name FROM sqlite_master WHERE type='table' AND name='activation_state'`,
128
+ )
129
+ .get();
130
+ expect(tableRow).toBeNull();
131
+ });
132
+ });
@@ -18,6 +18,7 @@ import { resetDb } from "../memory/db-connection.js";
18
18
  import { getSqliteFrom } from "../memory/db-connection.js";
19
19
  import { initializeDb } from "../memory/db-init.js";
20
20
  import { migrateAddConversationInferenceProfile } from "../memory/migrations/227-add-conversation-inference-profile.js";
21
+ import { migrateRenameInferenceProfileSnakeCase } from "../memory/migrations/228-rename-inference-profile-snake-case.js";
21
22
  import * as schema from "../memory/schema.js";
22
23
  import { getDbPath } from "../util/platform.js";
23
24
 
@@ -208,6 +209,42 @@ describe("conversation inference profile migration", () => {
208
209
  expect(row).toEqual({ inferenceProfile: "quality-optimized" });
209
210
  });
210
211
 
212
+ test("replaying 227 + 228 across multiple boots does not re-add the camelCase column", () => {
213
+ const db = createTestDb();
214
+ const raw = getSqliteFrom(db);
215
+
216
+ bootstrapPreInferenceProfileConversations(raw);
217
+
218
+ // First boot: 227 adds camelCase, 228 renames to snake_case.
219
+ migrateAddConversationInferenceProfile(db);
220
+ migrateRenameInferenceProfileSnakeCase(db);
221
+ expect(getColumnNames(raw)).toContain("inference_profile");
222
+ expect(getColumnNames(raw)).not.toContain("inferenceProfile");
223
+
224
+ // Second boot: replays must not re-add the camelCase column.
225
+ migrateAddConversationInferenceProfile(db);
226
+ migrateRenameInferenceProfileSnakeCase(db);
227
+ expect(getColumnNames(raw)).toContain("inference_profile");
228
+ expect(getColumnNames(raw)).not.toContain("inferenceProfile");
229
+ });
230
+
231
+ test("228 self-heals when both columns are present from the legacy bug", () => {
232
+ const db = createTestDb();
233
+ const raw = getSqliteFrom(db);
234
+
235
+ bootstrapPreInferenceProfileConversations(raw);
236
+ // Simulate the legacy state: both columns exist because 227 re-added the
237
+ // camelCase column on a boot after 228 had already renamed it.
238
+ raw.exec(`ALTER TABLE conversations ADD COLUMN inference_profile TEXT`);
239
+ raw.exec(`ALTER TABLE conversations ADD COLUMN inferenceProfile TEXT`);
240
+ expect(getColumnNames(raw)).toContain("inferenceProfile");
241
+
242
+ migrateRenameInferenceProfileSnakeCase(db);
243
+
244
+ expect(getColumnNames(raw)).toContain("inference_profile");
245
+ expect(getColumnNames(raw)).not.toContain("inferenceProfile");
246
+ });
247
+
211
248
  test("new rows default to NULL inferenceProfile after migration", () => {
212
249
  const db = createTestDb();
213
250
  const raw = getSqliteFrom(db);
@@ -28,7 +28,8 @@ function bootstrapTables(raw: Database): void {
28
28
  CREATE TABLE memory_graph_nodes (
29
29
  id TEXT PRIMARY KEY,
30
30
  created INTEGER NOT NULL,
31
- event_date INTEGER
31
+ event_date INTEGER,
32
+ content TEXT NOT NULL DEFAULT ''
32
33
  );
33
34
 
34
35
  CREATE TABLE memory_graph_triggers (
@@ -59,16 +60,35 @@ describe("repairMemoryGraphEventDate", () => {
59
60
  const created = Date.UTC(2026, 3, 26, 5, 23, 20);
60
61
  const wrongEventDate = Date.UTC(2025, 3, 19, 2, 32, 0);
61
62
 
62
- expect(repairMemoryGraphEventDate(created, wrongEventDate)).toBe(
63
- Date.UTC(2026, 3, 19, 2, 32, 0),
64
- );
63
+ expect(
64
+ repairMemoryGraphEventDate(
65
+ created,
66
+ wrongEventDate,
67
+ "Talked about the trip on April 19",
68
+ ),
69
+ ).toBe(Date.UTC(2026, 3, 19, 2, 32, 0));
65
70
  });
66
71
 
67
72
  test("leaves distant historical dates alone", () => {
68
73
  const created = Date.UTC(2026, 3, 26, 5, 23, 20);
69
74
  const historicalEventDate = Date.UTC(2025, 10, 1, 12, 0, 0);
70
75
 
71
- expect(repairMemoryGraphEventDate(created, historicalEventDate)).toBeNull();
76
+ expect(
77
+ repairMemoryGraphEventDate(created, historicalEventDate, ""),
78
+ ).toBeNull();
79
+ });
80
+
81
+ test("leaves dates alone when content explicitly mentions the prior year", () => {
82
+ const created = Date.UTC(2026, 3, 26, 5, 23, 20);
83
+ const explicitHistorical = Date.UTC(2025, 3, 19, 2, 32, 0);
84
+
85
+ expect(
86
+ repairMemoryGraphEventDate(
87
+ created,
88
+ explicitHistorical,
89
+ "User flew on April 19, 2025 to visit family",
90
+ ),
91
+ ).toBeNull();
72
92
  });
73
93
  });
74
94
 
@@ -84,21 +104,23 @@ describe("migrate231RepairMemoryGraphEventDates", () => {
84
104
  const distantHistoricalDate = Date.UTC(2025, 10, 1, 12, 0, 0);
85
105
  const futureDate = Date.UTC(2027, 0, 1, 12, 0, 0);
86
106
 
87
- raw
88
- .prepare(
89
- `INSERT INTO memory_graph_nodes (id, created, event_date) VALUES (?, ?, ?)`,
90
- )
91
- .run("bad-node", created, wrongEventDate);
92
- raw
93
- .prepare(
94
- `INSERT INTO memory_graph_nodes (id, created, event_date) VALUES (?, ?, ?)`,
95
- )
96
- .run("historical-node", created, distantHistoricalDate);
97
- raw
98
- .prepare(
99
- `INSERT INTO memory_graph_nodes (id, created, event_date) VALUES (?, ?, ?)`,
100
- )
101
- .run("future-node", created, futureDate);
107
+ const insertNode = raw.prepare(
108
+ `INSERT INTO memory_graph_nodes (id, created, event_date, content) VALUES (?, ?, ?, ?)`,
109
+ );
110
+ insertNode.run("bad-node", created, wrongEventDate, "Trip on April 19");
111
+ insertNode.run(
112
+ "historical-node",
113
+ created,
114
+ distantHistoricalDate,
115
+ "Notes from last fall",
116
+ );
117
+ insertNode.run("future-node", created, futureDate, "New Year 2027 plans");
118
+ insertNode.run(
119
+ "explicit-year-node",
120
+ created,
121
+ wrongEventDate,
122
+ "User flew on April 19, 2025 to visit family",
123
+ );
102
124
  raw
103
125
  .prepare(
104
126
  `INSERT INTO memory_graph_triggers (id, node_id, type, event_date) VALUES (?, ?, ?, ?)`,
@@ -112,5 +134,6 @@ describe("migrate231RepairMemoryGraphEventDates", () => {
112
134
  expect(triggerEventDateFor(raw, "bad-trigger")).toBe(correctedEventDate);
113
135
  expect(eventDateFor(raw, "historical-node")).toBe(distantHistoricalDate);
114
136
  expect(eventDateFor(raw, "future-node")).toBe(futureDate);
137
+ expect(eventDateFor(raw, "explicit-year-node")).toBe(wrongEventDate);
115
138
  });
116
139
  });
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Tests for the `db_proxy_transaction` IPC handler.
3
+ *
4
+ * Verifies all-or-nothing semantics: every step commits together, any
5
+ * exception or `requireChanges` violation rolls the entire batch back.
6
+ *
7
+ * Uses the real DB (via `initializeDb()`); the test preload points
8
+ * `VELLUM_WORKSPACE_DIR` at a per-file temp dir.
9
+ */
10
+
11
+ import { beforeEach, describe, expect, test } from "bun:test";
12
+
13
+ import { handleDbProxyTransaction } from "../ipc/routes/db-proxy-transaction.js";
14
+ import { getSqlite } from "../memory/db-connection.js";
15
+ import { initializeDb } from "../memory/db-init.js";
16
+ import { RouteError } from "../runtime/routes/errors.js";
17
+
18
+ initializeDb();
19
+
20
+ function resetTestTable(): void {
21
+ const sqlite = getSqlite();
22
+ sqlite.exec("DROP TABLE IF EXISTS proxy_tx_test");
23
+ sqlite.exec(
24
+ "CREATE TABLE proxy_tx_test (id INTEGER PRIMARY KEY, label TEXT NOT NULL, count INTEGER NOT NULL DEFAULT 0)",
25
+ );
26
+ }
27
+
28
+ function rowCount(): number {
29
+ const result = getSqlite()
30
+ .prepare("SELECT COUNT(*) AS n FROM proxy_tx_test")
31
+ .get() as { n: number };
32
+ return result.n;
33
+ }
34
+
35
+ describe("db_proxy_transaction", () => {
36
+ beforeEach(() => {
37
+ resetTestTable();
38
+ });
39
+
40
+ test("commits multiple inserts atomically", () => {
41
+ const result = handleDbProxyTransaction({
42
+ steps: [
43
+ {
44
+ sql: "INSERT INTO proxy_tx_test (id, label) VALUES (?, ?)",
45
+ bind: [1, "alpha"],
46
+ },
47
+ {
48
+ sql: "INSERT INTO proxy_tx_test (id, label) VALUES (?, ?)",
49
+ bind: [2, "beta"],
50
+ },
51
+ ],
52
+ });
53
+
54
+ expect(result.ok).toBe(true);
55
+ if (result.ok) {
56
+ expect(result.results).toHaveLength(2);
57
+ expect(result.results[0].changes).toBe(1);
58
+ expect(result.results[1].changes).toBe(1);
59
+ }
60
+ expect(rowCount()).toBe(2);
61
+ });
62
+
63
+ test("rolls back all writes when a later step throws (SQL constraint)", () => {
64
+ // Pre-existing row that the transaction will collide with.
65
+ getSqlite()
66
+ .prepare("INSERT INTO proxy_tx_test (id, label) VALUES (?, ?)")
67
+ .run(2, "preexisting");
68
+
69
+ let caught: unknown;
70
+ try {
71
+ handleDbProxyTransaction({
72
+ steps: [
73
+ {
74
+ sql: "INSERT INTO proxy_tx_test (id, label) VALUES (?, ?)",
75
+ bind: [1, "alpha"],
76
+ },
77
+ // Primary-key collision triggers a SqliteError mid-transaction.
78
+ {
79
+ sql: "INSERT INTO proxy_tx_test (id, label) VALUES (?, ?)",
80
+ bind: [2, "beta"],
81
+ },
82
+ ],
83
+ });
84
+ } catch (err) {
85
+ caught = err;
86
+ }
87
+
88
+ // The thrown error must be a RouteError carrying the underlying SQL
89
+ // message — without the wrapping, the IPC envelope would lose the
90
+ // statusCode and the gateway-side strict caller would misclassify
91
+ // this as a transport failure ("assistant may not be ready").
92
+ expect(caught).toBeInstanceOf(RouteError);
93
+ if (caught instanceof RouteError) {
94
+ expect(caught.code).toBe("DB_PROXY_TRANSACTION_FAILED");
95
+ expect(caught.statusCode).toBe(500);
96
+ // The original SQL constraint message must survive the wrap so
97
+ // operators can debug from the gateway logs.
98
+ expect(caught.message).toMatch(/UNIQUE|PRIMARY KEY|constraint/i);
99
+ }
100
+
101
+ // The first step's insert must NOT have committed.
102
+ expect(rowCount()).toBe(1);
103
+ const remaining = getSqlite()
104
+ .prepare("SELECT label FROM proxy_tx_test WHERE id = ?")
105
+ .get(2) as { label: string };
106
+ expect(remaining.label).toBe("preexisting");
107
+ });
108
+
109
+ test("requireChanges aborts the transaction when unmet", () => {
110
+ // Seed a row to update; condition will not match so changes = 0.
111
+ getSqlite()
112
+ .prepare("INSERT INTO proxy_tx_test (id, label, count) VALUES (?, ?, ?)")
113
+ .run(1, "active", 0);
114
+
115
+ const result = handleDbProxyTransaction({
116
+ steps: [
117
+ {
118
+ sql: "INSERT INTO proxy_tx_test (id, label) VALUES (?, ?)",
119
+ bind: [99, "should-rollback"],
120
+ },
121
+ {
122
+ // No row matches label='nonexistent', so changes = 0.
123
+ sql: "UPDATE proxy_tx_test SET count = count + 1 WHERE label = ?",
124
+ bind: ["nonexistent"],
125
+ requireChanges: 1,
126
+ },
127
+ ],
128
+ });
129
+
130
+ expect(result.ok).toBe(false);
131
+ if (!result.ok) {
132
+ expect(result.reason).toBe("require_changes_failed");
133
+ expect(result.failedStep).toBe(1);
134
+ expect(result.actualChanges).toBe(0);
135
+ expect(result.requiredChanges).toBe(1);
136
+ }
137
+
138
+ // The earlier insert must have rolled back.
139
+ expect(rowCount()).toBe(1);
140
+ const remaining = getSqlite()
141
+ .prepare("SELECT label FROM proxy_tx_test WHERE id = ?")
142
+ .get(1) as { label: string };
143
+ expect(remaining.label).toBe("active");
144
+ });
145
+
146
+ test("requireChanges allows the transaction to commit when met", () => {
147
+ getSqlite()
148
+ .prepare("INSERT INTO proxy_tx_test (id, label, count) VALUES (?, ?, ?)")
149
+ .run(1, "active", 0);
150
+
151
+ const result = handleDbProxyTransaction({
152
+ steps: [
153
+ {
154
+ sql: "INSERT INTO proxy_tx_test (id, label) VALUES (?, ?)",
155
+ bind: [2, "new"],
156
+ },
157
+ {
158
+ sql: "UPDATE proxy_tx_test SET count = count + 1 WHERE label = ?",
159
+ bind: ["active"],
160
+ requireChanges: 1,
161
+ },
162
+ ],
163
+ });
164
+
165
+ expect(result.ok).toBe(true);
166
+ if (result.ok) {
167
+ expect(result.results[1].changes).toBe(1);
168
+ }
169
+ expect(rowCount()).toBe(2);
170
+ const updated = getSqlite()
171
+ .prepare("SELECT count FROM proxy_tx_test WHERE id = ?")
172
+ .get(1) as { count: number };
173
+ expect(updated.count).toBe(1);
174
+ });
175
+
176
+ test("rejects empty step list with a 400 RouteError", () => {
177
+ let caught: unknown;
178
+ try {
179
+ handleDbProxyTransaction({ steps: [] });
180
+ } catch (err) {
181
+ caught = err;
182
+ }
183
+ expect(caught).toBeInstanceOf(RouteError);
184
+ if (caught instanceof RouteError) {
185
+ expect(caught.statusCode).toBe(400);
186
+ expect(caught.code).toBe("INVALID_PARAMS");
187
+ expect(caught.message).toMatch(/at least one step/);
188
+ }
189
+ });
190
+
191
+ test("returns lastInsertRowid for inserts", () => {
192
+ const result = handleDbProxyTransaction({
193
+ steps: [
194
+ {
195
+ sql: "INSERT INTO proxy_tx_test (label) VALUES (?)",
196
+ bind: ["solo"],
197
+ },
198
+ ],
199
+ });
200
+
201
+ expect(result.ok).toBe(true);
202
+ if (result.ok) {
203
+ expect(result.results[0].lastInsertRowid).toBeGreaterThan(0);
204
+ }
205
+ });
206
+ });