vellum 0.2.1 → 0.2.2

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 (349) hide show
  1. package/README.md +15 -2
  2. package/bun.lock +5 -2
  3. package/package.json +4 -2
  4. package/scripts/capture-x-graphql.ts +562 -0
  5. package/scripts/ipc/check-swift-decoder-drift.ts +2 -1
  6. package/scripts/test.sh +5 -0
  7. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +133 -34
  8. package/src/__tests__/account-registry.test.ts +2 -1
  9. package/src/__tests__/agent-heartbeat-service.test.ts +250 -0
  10. package/src/__tests__/asset-materialize-tool.test.ts +16 -15
  11. package/src/__tests__/asset-search-tool.test.ts +23 -22
  12. package/src/__tests__/attachments-store.test.ts +56 -127
  13. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +5 -4
  14. package/src/__tests__/browser-skill-endstate.test.ts +4 -3
  15. package/src/__tests__/call-bridge.test.ts +385 -0
  16. package/src/__tests__/call-constants.test.ts +40 -0
  17. package/src/__tests__/call-orchestrator.test.ts +130 -4
  18. package/src/__tests__/call-recovery.test.ts +518 -0
  19. package/src/__tests__/call-routes-http.test.ts +459 -0
  20. package/src/__tests__/call-state-machine.test.ts +143 -0
  21. package/src/__tests__/call-store.test.ts +216 -1
  22. package/src/__tests__/cli-discover.test.ts +1 -1
  23. package/src/__tests__/commit-message-enrichment-service.test.ts +148 -7
  24. package/src/__tests__/compaction.benchmark.test.ts +176 -0
  25. package/src/__tests__/computer-use-tools.test.ts +250 -0
  26. package/src/__tests__/config-schema.test.ts +299 -3
  27. package/src/__tests__/conflict-store.test.ts +2 -1
  28. package/src/__tests__/contacts-tools.test.ts +331 -0
  29. package/src/__tests__/conversation-store.test.ts +30 -32
  30. package/src/__tests__/credential-security-invariants.test.ts +4 -0
  31. package/src/__tests__/date-context.test.ts +373 -0
  32. package/src/__tests__/db-schedule-syntax-migration.test.ts +129 -0
  33. package/src/__tests__/fixtures/media-reuse-fixtures.ts +3 -3
  34. package/src/__tests__/followup-tools.test.ts +303 -0
  35. package/src/__tests__/handlers-twitter-config.test.ts +718 -0
  36. package/src/__tests__/intent-routing.test.ts +64 -57
  37. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +237 -0
  38. package/src/__tests__/ipc-snapshot.test.ts +62 -28
  39. package/src/__tests__/llm-usage-store.test.ts +3 -8
  40. package/src/__tests__/media-generate-image.test.ts +1 -1
  41. package/src/__tests__/media-reuse-story.e2e.test.ts +7 -7
  42. package/src/__tests__/memory-retrieval.benchmark.test.ts +430 -0
  43. package/src/__tests__/parallel-tool.benchmark.test.ts +294 -0
  44. package/src/__tests__/playbook-tools.test.ts +342 -0
  45. package/src/__tests__/profile-compiler.test.ts +2 -1
  46. package/src/__tests__/provider-streaming.benchmark.test.ts +773 -0
  47. package/src/__tests__/recurrence-engine-rruleset.test.ts +78 -0
  48. package/src/__tests__/recurrence-engine.test.ts +69 -0
  49. package/src/__tests__/recurrence-types.test.ts +71 -0
  50. package/src/__tests__/registry.test.ts +5 -3
  51. package/src/__tests__/relay-server.test.ts +633 -0
  52. package/src/__tests__/reminder-store.test.ts +6 -3
  53. package/src/__tests__/reminder.test.ts +43 -77
  54. package/src/__tests__/run-orchestrator-assistant-events.test.ts +8 -4
  55. package/src/__tests__/run-orchestrator.test.ts +4 -4
  56. package/src/__tests__/runtime-attachment-metadata.test.ts +7 -6
  57. package/src/__tests__/runtime-runs-http.test.ts +4 -4
  58. package/src/__tests__/runtime-runs.test.ts +4 -4
  59. package/src/__tests__/schedule-store.test.ts +482 -0
  60. package/src/__tests__/schedule-tools.test.ts +700 -0
  61. package/src/__tests__/scheduler-recurrence.test.ts +329 -0
  62. package/src/__tests__/server-history-render.test.ts +14 -13
  63. package/src/__tests__/session-error.test.ts +28 -0
  64. package/src/__tests__/session-init.benchmark.test.ts +462 -0
  65. package/src/__tests__/session-queue.test.ts +71 -48
  66. package/src/__tests__/session-runtime-assembly.test.ts +161 -0
  67. package/src/__tests__/session-surfaces-task-progress.test.ts +104 -0
  68. package/src/__tests__/signup-e2e.test.ts +2 -1
  69. package/src/__tests__/skill-projection.benchmark.test.ts +328 -0
  70. package/src/__tests__/skill-script-runner.test.ts +159 -0
  71. package/src/__tests__/speaker-identification.test.ts +52 -0
  72. package/src/__tests__/subagent-manager-notify.test.ts +42 -10
  73. package/src/__tests__/subagent-tools.test.ts +141 -41
  74. package/src/__tests__/task-compiler.test.ts +2 -1
  75. package/src/__tests__/task-runner.test.ts +2 -1
  76. package/src/__tests__/task-scheduler.test.ts +2 -1
  77. package/src/__tests__/task-tools.test.ts +49 -56
  78. package/src/__tests__/tool-audit-listener.test.ts +1 -0
  79. package/src/__tests__/tool-domain-event-publisher.test.ts +2 -0
  80. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +500 -0
  81. package/src/__tests__/tool-executor.test.ts +13 -17
  82. package/src/__tests__/turn-commit.test.ts +218 -3
  83. package/src/__tests__/twilio-provider.test.ts +143 -0
  84. package/src/__tests__/twilio-routes.test.ts +789 -0
  85. package/src/__tests__/twitter-auth-handler.test.ts +581 -0
  86. package/src/__tests__/view-image-tool.test.ts +217 -0
  87. package/src/__tests__/workspace-git-service.test.ts +186 -0
  88. package/src/__tests__/workspace-heartbeat-service.test.ts +13 -3
  89. package/src/agent-heartbeat/agent-heartbeat-service.ts +155 -0
  90. package/src/bundler/app-bundler.ts +12 -8
  91. package/src/calls/call-bridge.ts +95 -0
  92. package/src/calls/call-constants.ts +43 -5
  93. package/src/calls/call-domain.ts +276 -0
  94. package/src/calls/call-orchestrator.ts +43 -17
  95. package/src/calls/call-recovery.ts +207 -0
  96. package/src/calls/call-state-machine.ts +68 -0
  97. package/src/calls/call-store.ts +192 -5
  98. package/src/calls/relay-server.ts +41 -4
  99. package/src/calls/speaker-identification.ts +213 -0
  100. package/src/calls/twilio-provider.ts +10 -6
  101. package/src/calls/twilio-routes.ts +90 -76
  102. package/src/calls/types.ts +1 -1
  103. package/src/cli/config-commands.ts +334 -0
  104. package/src/cli/core-commands.ts +776 -0
  105. package/src/cli/doordash.ts +251 -1
  106. package/src/cli/ipc-client.ts +82 -0
  107. package/src/cli/map.ts +246 -0
  108. package/src/cli/twitter.ts +575 -0
  109. package/src/cli.ts +7 -5
  110. package/src/commands/__tests__/cc-command-registry.test.ts +319 -0
  111. package/src/commands/cc-command-registry.ts +209 -0
  112. package/src/config/bundled-skills/contacts/SKILL.md +39 -0
  113. package/src/config/bundled-skills/contacts/TOOLS.json +122 -0
  114. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +9 -0
  115. package/src/config/bundled-skills/contacts/tools/contact-search.ts +9 -0
  116. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +9 -0
  117. package/src/config/bundled-skills/document/SKILL.md +18 -0
  118. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  119. package/src/config/bundled-skills/document/tools/document-create.ts +9 -0
  120. package/src/config/bundled-skills/document/tools/document-update.ts +9 -0
  121. package/src/config/bundled-skills/doordash/SKILL.md +82 -23
  122. package/src/config/bundled-skills/followups/SKILL.md +32 -0
  123. package/src/config/bundled-skills/followups/TOOLS.json +100 -0
  124. package/src/config/bundled-skills/followups/tools/followup-create.ts +9 -0
  125. package/src/config/bundled-skills/followups/tools/followup-list.ts +9 -0
  126. package/src/config/bundled-skills/followups/tools/followup-resolve.ts +9 -0
  127. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +1 -23
  128. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -1
  129. package/src/config/bundled-skills/playbooks/SKILL.md +31 -0
  130. package/src/config/bundled-skills/playbooks/TOOLS.json +126 -0
  131. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +9 -0
  132. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +9 -0
  133. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +9 -0
  134. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +9 -0
  135. package/src/config/bundled-skills/reminder/SKILL.md +20 -0
  136. package/src/config/bundled-skills/reminder/TOOLS.json +67 -0
  137. package/src/config/bundled-skills/reminder/tools/reminder-cancel.ts +9 -0
  138. package/src/config/bundled-skills/reminder/tools/reminder-create.ts +9 -0
  139. package/src/config/bundled-skills/reminder/tools/reminder-list.ts +9 -0
  140. package/src/config/bundled-skills/schedule/SKILL.md +74 -0
  141. package/src/config/bundled-skills/schedule/TOOLS.json +135 -0
  142. package/src/config/bundled-skills/schedule/tools/schedule-create.ts +9 -0
  143. package/src/config/bundled-skills/schedule/tools/schedule-delete.ts +9 -0
  144. package/src/config/bundled-skills/schedule/tools/schedule-list.ts +9 -0
  145. package/src/config/bundled-skills/schedule/tools/schedule-update.ts +9 -0
  146. package/src/config/bundled-skills/subagent/SKILL.md +25 -0
  147. package/src/config/bundled-skills/subagent/TOOLS.json +107 -0
  148. package/src/config/bundled-skills/subagent/tools/subagent-abort.ts +9 -0
  149. package/src/config/bundled-skills/subagent/tools/subagent-message.ts +9 -0
  150. package/src/config/bundled-skills/subagent/tools/subagent-read.ts +9 -0
  151. package/src/config/bundled-skills/subagent/tools/subagent-spawn.ts +9 -0
  152. package/src/config/bundled-skills/subagent/tools/subagent-status.ts +9 -0
  153. package/src/config/bundled-skills/tasks/SKILL.md +28 -0
  154. package/src/config/bundled-skills/tasks/TOOLS.json +256 -0
  155. package/src/config/bundled-skills/tasks/tools/task-delete.ts +9 -0
  156. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +9 -0
  157. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +9 -0
  158. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +9 -0
  159. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +9 -0
  160. package/src/config/bundled-skills/tasks/tools/task-list.ts +9 -0
  161. package/src/config/bundled-skills/tasks/tools/task-run.ts +9 -0
  162. package/src/config/bundled-skills/tasks/tools/task-save.ts +9 -0
  163. package/src/config/bundled-skills/twitter/SKILL.md +134 -0
  164. package/src/config/bundled-skills/watcher/SKILL.md +27 -0
  165. package/src/config/bundled-skills/watcher/TOOLS.json +147 -0
  166. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +9 -0
  167. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +9 -0
  168. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +9 -0
  169. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +9 -0
  170. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +9 -0
  171. package/src/config/defaults.ts +33 -0
  172. package/src/config/loader.ts +4 -1
  173. package/src/config/schema.ts +161 -1
  174. package/src/config/system-prompt.ts +61 -16
  175. package/src/config/templates/IDENTITY.md +7 -0
  176. package/src/config/types.ts +4 -0
  177. package/src/contacts/contact-store.ts +4 -4
  178. package/src/daemon/assistant-attachments.ts +10 -0
  179. package/src/daemon/classifier.ts +3 -1
  180. package/src/daemon/computer-use-session.ts +3 -1
  181. package/src/daemon/date-context.ts +136 -0
  182. package/src/daemon/handlers/apps.ts +16 -1
  183. package/src/daemon/handlers/browser.ts +54 -0
  184. package/src/daemon/handlers/computer-use.ts +7 -1
  185. package/src/daemon/handlers/config.ts +163 -5
  186. package/src/daemon/handlers/diagnostics.ts +5 -1
  187. package/src/daemon/handlers/documents.ts +18 -29
  188. package/src/daemon/handlers/home-base.ts +5 -1
  189. package/src/daemon/handlers/index.ts +40 -277
  190. package/src/daemon/handlers/misc.ts +9 -1
  191. package/src/daemon/handlers/publish.ts +6 -1
  192. package/src/daemon/handlers/sessions.ts +65 -12
  193. package/src/daemon/handlers/shared.ts +36 -1
  194. package/src/daemon/handlers/signing.ts +37 -0
  195. package/src/daemon/handlers/skills.ts +20 -6
  196. package/src/daemon/handlers/subagents.ts +8 -3
  197. package/src/daemon/handlers/twitter-auth.ts +169 -0
  198. package/src/daemon/handlers/work-items.ts +384 -68
  199. package/src/daemon/ipc-contract-inventory.json +28 -4
  200. package/src/daemon/ipc-contract.ts +133 -37
  201. package/src/daemon/ipc-protocol.ts +7 -2
  202. package/src/daemon/lifecycle.ts +21 -0
  203. package/src/daemon/main.ts +10 -4
  204. package/src/daemon/ride-shotgun-handler.ts +74 -10
  205. package/src/daemon/server.ts +143 -26
  206. package/src/daemon/session-agent-loop.ts +887 -0
  207. package/src/daemon/session-attachments.ts +28 -5
  208. package/src/daemon/session-error.ts +24 -3
  209. package/src/daemon/session-lifecycle.ts +147 -0
  210. package/src/daemon/session-media-retry.ts +147 -0
  211. package/src/daemon/session-messaging.ts +145 -0
  212. package/src/daemon/session-notifiers.ts +164 -0
  213. package/src/daemon/session-process.ts +2 -2
  214. package/src/daemon/session-queue-manager.ts +1 -0
  215. package/src/daemon/session-runtime-assembly.ts +52 -0
  216. package/src/daemon/session-skill-tools.ts +124 -5
  217. package/src/daemon/session-slash.ts +3 -0
  218. package/src/daemon/session-surfaces.ts +77 -2
  219. package/src/daemon/session-tool-setup.ts +216 -2
  220. package/src/daemon/session-usage.ts +0 -2
  221. package/src/daemon/session.ts +114 -1404
  222. package/src/daemon/video-thumbnail.ts +60 -0
  223. package/src/doordash/client.ts +121 -27
  224. package/src/doordash/queries.ts +1 -2
  225. package/src/export/formatter.ts +3 -1
  226. package/src/followups/followup-store.ts +4 -2
  227. package/src/followups/types.ts +6 -0
  228. package/src/hooks/templates.ts +1 -1
  229. package/src/index.ts +32 -1153
  230. package/src/memory/attachments-store.ts +28 -83
  231. package/src/memory/channel-delivery-store.ts +7 -21
  232. package/src/memory/clarification-resolver.ts +6 -5
  233. package/src/memory/contradiction-checker.ts +3 -2
  234. package/src/memory/conversation-key-store.ts +10 -29
  235. package/src/memory/conversation-store.ts +2 -1
  236. package/src/memory/db.ts +96 -2
  237. package/src/memory/entity-extractor.ts +6 -3
  238. package/src/memory/items-extractor.ts +5 -4
  239. package/src/memory/jobs-store.ts +3 -2
  240. package/src/memory/llm-usage-store.ts +1 -2
  241. package/src/memory/runs-store.ts +1 -2
  242. package/src/memory/schema.ts +23 -2
  243. package/src/messaging/style-analyzer.ts +3 -2
  244. package/src/messaging/thread-summarizer.ts +8 -12
  245. package/src/messaging/triage-engine.ts +4 -2
  246. package/src/providers/openrouter/client.ts +20 -0
  247. package/src/providers/registry.ts +8 -0
  248. package/src/runtime/http-server.ts +108 -20
  249. package/src/runtime/routes/attachment-routes.ts +2 -3
  250. package/src/runtime/routes/call-routes.ts +140 -0
  251. package/src/runtime/routes/channel-routes.ts +5 -10
  252. package/src/runtime/routes/conversation-routes.ts +5 -5
  253. package/src/runtime/routes/run-routes.ts +2 -2
  254. package/src/runtime/run-orchestrator.ts +9 -3
  255. package/src/schedule/recurrence-engine.ts +138 -0
  256. package/src/schedule/recurrence-types.ts +67 -0
  257. package/src/schedule/schedule-store.ts +102 -57
  258. package/src/schedule/scheduler.ts +9 -6
  259. package/src/security/oauth2.ts +29 -4
  260. package/src/security/secret-allowlist.ts +46 -0
  261. package/src/skills/clawhub.ts +1 -1
  262. package/src/subagent/manager.ts +40 -8
  263. package/src/swarm/backend-claude-code.ts +64 -9
  264. package/src/swarm/worker-prompts.ts +2 -1
  265. package/src/tasks/SPEC.md +34 -28
  266. package/src/tasks/ephemeral-permissions.ts +16 -7
  267. package/src/tasks/task-compiler.ts +5 -4
  268. package/src/tasks/task-runner.ts +10 -5
  269. package/src/tasks/task-scheduler.ts +1 -1
  270. package/src/tasks/tool-sanitizer.ts +36 -0
  271. package/src/tools/assets/search.ts +4 -4
  272. package/src/tools/browser/api-map.ts +220 -0
  273. package/src/tools/browser/auto-navigate.ts +270 -0
  274. package/src/tools/browser/browser-execution.ts +2 -1
  275. package/src/tools/browser/browser-manager.ts +2 -2
  276. package/src/tools/browser/network-recorder.ts +5 -4
  277. package/src/tools/browser/x-auto-navigate.ts +207 -0
  278. package/src/tools/calls/call-end.ts +17 -67
  279. package/src/tools/calls/call-start.ts +24 -85
  280. package/src/tools/calls/call-status.ts +35 -51
  281. package/src/tools/claude-code/claude-code.ts +77 -11
  282. package/src/tools/contacts/contact-merge.ts +46 -78
  283. package/src/tools/contacts/contact-search.ts +35 -79
  284. package/src/tools/contacts/contact-upsert.ts +35 -108
  285. package/src/tools/credentials/vault.ts +20 -4
  286. package/src/tools/document/document-tool.ts +71 -144
  287. package/src/tools/executor.ts +129 -10
  288. package/src/tools/followups/followup_create.ts +46 -88
  289. package/src/tools/followups/followup_list.ts +34 -74
  290. package/src/tools/followups/followup_resolve.ts +31 -66
  291. package/src/tools/host-terminal/cli-discover.ts +2 -1
  292. package/src/tools/host-terminal/host-shell.ts +10 -0
  293. package/src/tools/memory/handlers.ts +5 -4
  294. package/src/tools/network/__tests__/web-search.test.ts +427 -0
  295. package/src/tools/network/script-proxy/__tests__/logging.test.ts +248 -0
  296. package/src/tools/network/script-proxy/__tests__/policy.test.ts +234 -0
  297. package/src/tools/network/script-proxy/__tests__/router.test.ts +76 -0
  298. package/src/tools/network/web-fetch.ts +18 -6
  299. package/src/tools/playbooks/index.ts +4 -5
  300. package/src/tools/playbooks/playbook-create.ts +3 -47
  301. package/src/tools/playbooks/playbook-delete.ts +1 -25
  302. package/src/tools/playbooks/playbook-list.ts +1 -28
  303. package/src/tools/playbooks/playbook-update.ts +3 -51
  304. package/src/tools/reminder/reminder.ts +5 -78
  305. package/src/tools/schedule/create.ts +69 -74
  306. package/src/tools/schedule/delete.ts +21 -47
  307. package/src/tools/schedule/list.ts +55 -74
  308. package/src/tools/schedule/update.ts +77 -84
  309. package/src/tools/subagent/abort.ts +29 -58
  310. package/src/tools/subagent/message.ts +30 -63
  311. package/src/tools/subagent/read.ts +53 -84
  312. package/src/tools/subagent/spawn.ts +43 -82
  313. package/src/tools/subagent/status.ts +42 -71
  314. package/src/tools/swarm/delegate.ts +2 -1
  315. package/src/tools/tasks/index.ts +8 -8
  316. package/src/tools/tasks/task-delete.ts +60 -88
  317. package/src/tools/tasks/task-list.ts +31 -52
  318. package/src/tools/tasks/task-run.ts +72 -108
  319. package/src/tools/tasks/task-save.ts +33 -65
  320. package/src/tools/tasks/work-item-enqueue.ts +183 -215
  321. package/src/tools/tasks/work-item-list.ts +33 -63
  322. package/src/tools/tasks/work-item-remove.ts +45 -97
  323. package/src/tools/tasks/work-item-update.ts +91 -163
  324. package/src/tools/terminal/backends/native.ts +3 -1
  325. package/src/tools/tool-manifest.ts +0 -62
  326. package/src/tools/types.ts +6 -0
  327. package/src/tools/ui-surface/definitions.ts +3 -1
  328. package/src/tools/watch/screen-watch.ts +3 -1
  329. package/src/tools/watcher/create.ts +52 -98
  330. package/src/tools/watcher/delete.ts +20 -46
  331. package/src/tools/watcher/digest.ts +36 -70
  332. package/src/tools/watcher/list.ts +49 -79
  333. package/src/tools/watcher/update.ts +45 -91
  334. package/src/twitter/client.ts +690 -0
  335. package/src/twitter/session.ts +91 -0
  336. package/src/usage/types.ts +0 -1
  337. package/src/util/truncate.ts +6 -0
  338. package/src/watcher/providers/slack.ts +2 -1
  339. package/src/watcher/watcher-store.ts +3 -2
  340. package/src/work-items/work-item-store.ts +27 -2
  341. package/src/workspace/commit-message-enrichment-service.ts +31 -7
  342. package/src/workspace/git-service.ts +87 -22
  343. package/src/workspace/provider-commit-message-generator.ts +242 -0
  344. package/src/workspace/turn-commit.ts +62 -3
  345. package/src/tools/contacts/index.ts +0 -4
  346. package/src/tools/document/index.ts +0 -5
  347. package/src/tools/followups/index.ts +0 -3
  348. package/src/tools/subagent/index.ts +0 -5
  349. /package/src/__tests__/{memory-context-benchmark.test.ts → memory-context-benchmark.benchmark.test.ts} +0 -0
@@ -1,51 +1,33 @@
1
- import { describe, test, expect, beforeEach } from 'bun:test';
2
- import { initializeDb } from '../memory/db.js';
3
- import { getDb } from '../memory/db.js';
1
+ import { afterAll, describe, test, expect, beforeEach } from 'bun:test';
2
+ import { initializeDb, getDb, resetDb } from '../memory/db.js';
4
3
  import { reminders } from '../memory/schema.js';
5
- import { reminderTool } from '../tools/reminder/reminder.js';
4
+ import { executeReminderCreate, executeReminderList, executeReminderCancel } from '../tools/reminder/reminder.js';
6
5
  import { claimDueReminders } from '../tools/reminder/reminder-store.js';
7
6
 
8
7
  initializeDb();
9
8
 
10
- const dummyContext = {
11
- workingDir: '/tmp',
12
- sessionId: 'test-session',
13
- conversationId: 'test-conversation',
14
- };
15
-
16
9
  function clearReminders() {
17
10
  getDb().delete(reminders).run();
18
11
  }
19
12
 
13
+ afterAll(() => {
14
+ resetDb();
15
+ });
16
+
20
17
  describe('reminder tool', () => {
21
18
  beforeEach(() => {
22
19
  clearReminders();
23
20
  });
24
21
 
25
- // ── action validation ───────────────────────────────────────────────
26
-
27
- test('rejects missing action', async () => {
28
- const result = await reminderTool.execute({}, dummyContext);
29
- expect(result.isError).toBe(true);
30
- expect(result.content).toContain('action is required');
31
- });
32
-
33
- test('rejects unknown action', async () => {
34
- const result = await reminderTool.execute({ action: 'explode' }, dummyContext);
35
- expect(result.isError).toBe(true);
36
- expect(result.content).toContain('Unknown action');
37
- });
38
-
39
22
  // ── create ──────────────────────────────────────────────────────────
40
23
 
41
24
  test('create with valid future ISO timestamp succeeds', async () => {
42
25
  const future = new Date(Date.now() + 60_000).toISOString();
43
- const result = await reminderTool.execute({
44
- action: 'create',
26
+ const result = executeReminderCreate({
45
27
  fire_at: future,
46
28
  label: 'Call Sidd',
47
29
  message: 'Remember to call Sidd',
48
- }, dummyContext);
30
+ });
49
31
 
50
32
  expect(result.isError).toBe(false);
51
33
  expect(result.content).toContain('Reminder created');
@@ -55,48 +37,44 @@ describe('reminder tool', () => {
55
37
 
56
38
  test('create with past timestamp returns error', async () => {
57
39
  const past = new Date(Date.now() - 60_000).toISOString();
58
- const result = await reminderTool.execute({
59
- action: 'create',
40
+ const result = executeReminderCreate({
60
41
  fire_at: past,
61
42
  label: 'Too late',
62
43
  message: 'This is in the past',
63
- }, dummyContext);
44
+ });
64
45
 
65
46
  expect(result.isError).toBe(true);
66
47
  expect(result.content).toContain('must be in the future');
67
48
  });
68
49
 
69
50
  test('create with invalid timestamp string returns error', async () => {
70
- const result = await reminderTool.execute({
71
- action: 'create',
51
+ const result = executeReminderCreate({
72
52
  fire_at: 'not-a-date',
73
53
  label: 'Bad date',
74
54
  message: 'This has a bad date',
75
- }, dummyContext);
55
+ });
76
56
 
77
57
  expect(result.isError).toBe(true);
78
58
  expect(result.content).toContain('Invalid timestamp');
79
59
  });
80
60
 
81
61
  test('create rejects non-ISO date formats like MM/DD/YYYY', async () => {
82
- const result = await reminderTool.execute({
83
- action: 'create',
62
+ const result = executeReminderCreate({
84
63
  fire_at: '03/04/2027',
85
64
  label: 'Ambiguous date',
86
65
  message: 'This format is locale-dependent',
87
- }, dummyContext);
66
+ });
88
67
 
89
68
  expect(result.isError).toBe(true);
90
69
  expect(result.content).toContain('Invalid timestamp');
91
70
  });
92
71
 
93
72
  test('create rejects ISO timestamp without timezone', async () => {
94
- const result = await reminderTool.execute({
95
- action: 'create',
73
+ const result = executeReminderCreate({
96
74
  fire_at: '2027-03-15T09:00:00',
97
75
  label: 'No timezone',
98
76
  message: 'Missing timezone offset',
99
- }, dummyContext);
77
+ });
100
78
 
101
79
  expect(result.isError).toBe(true);
102
80
  expect(result.content).toContain('Invalid timestamp');
@@ -106,12 +84,11 @@ describe('reminder tool', () => {
106
84
  const future = new Date(Date.now() + 120_000);
107
85
  const offset = '-05:00';
108
86
  const isoWithOffset = future.toISOString().replace('Z', offset);
109
- const result = await reminderTool.execute({
110
- action: 'create',
87
+ const result = executeReminderCreate({
111
88
  fire_at: isoWithOffset,
112
89
  label: 'With offset',
113
90
  message: 'Has explicit timezone',
114
- }, dummyContext);
91
+ });
115
92
 
116
93
  expect(result.isError).toBe(false);
117
94
  expect(result.content).toContain('Reminder created');
@@ -119,12 +96,11 @@ describe('reminder tool', () => {
119
96
 
120
97
  test('create defaults mode to notify', async () => {
121
98
  const future = new Date(Date.now() + 60_000).toISOString();
122
- const result = await reminderTool.execute({
123
- action: 'create',
99
+ const result = executeReminderCreate({
124
100
  fire_at: future,
125
101
  label: 'Default mode',
126
102
  message: 'Should be notify',
127
- }, dummyContext);
103
+ });
128
104
 
129
105
  expect(result.isError).toBe(false);
130
106
  expect(result.content).toContain('Mode: notify');
@@ -132,24 +108,22 @@ describe('reminder tool', () => {
132
108
 
133
109
  test('create with mode execute sets mode correctly', async () => {
134
110
  const future = new Date(Date.now() + 60_000).toISOString();
135
- const result = await reminderTool.execute({
136
- action: 'create',
111
+ const result = executeReminderCreate({
137
112
  fire_at: future,
138
113
  label: 'Execute mode',
139
114
  message: 'Should be execute',
140
115
  mode: 'execute',
141
- }, dummyContext);
116
+ });
142
117
 
143
118
  expect(result.isError).toBe(false);
144
119
  expect(result.content).toContain('Mode: execute');
145
120
  });
146
121
 
147
122
  test('create requires fire_at', async () => {
148
- const result = await reminderTool.execute({
149
- action: 'create',
123
+ const result = executeReminderCreate({
150
124
  label: 'No fire_at',
151
125
  message: 'Missing fire_at',
152
- }, dummyContext);
126
+ });
153
127
 
154
128
  expect(result.isError).toBe(true);
155
129
  expect(result.content).toContain('fire_at is required');
@@ -157,11 +131,10 @@ describe('reminder tool', () => {
157
131
 
158
132
  test('create requires label', async () => {
159
133
  const future = new Date(Date.now() + 60_000).toISOString();
160
- const result = await reminderTool.execute({
161
- action: 'create',
134
+ const result = executeReminderCreate({
162
135
  fire_at: future,
163
136
  message: 'Missing label',
164
- }, dummyContext);
137
+ });
165
138
 
166
139
  expect(result.isError).toBe(true);
167
140
  expect(result.content).toContain('label is required');
@@ -169,11 +142,10 @@ describe('reminder tool', () => {
169
142
 
170
143
  test('create requires message', async () => {
171
144
  const future = new Date(Date.now() + 60_000).toISOString();
172
- const result = await reminderTool.execute({
173
- action: 'create',
145
+ const result = executeReminderCreate({
174
146
  fire_at: future,
175
147
  label: 'No message',
176
- }, dummyContext);
148
+ });
177
149
 
178
150
  expect(result.isError).toBe(true);
179
151
  expect(result.content).toContain('message is required');
@@ -182,21 +154,20 @@ describe('reminder tool', () => {
182
154
  // ── list ────────────────────────────────────────────────────────────
183
155
 
184
156
  test('list returns "No reminders found" when empty', async () => {
185
- const result = await reminderTool.execute({ action: 'list' }, dummyContext);
157
+ const result = executeReminderList();
186
158
  expect(result.isError).toBe(false);
187
159
  expect(result.content).toContain('No reminders found');
188
160
  });
189
161
 
190
162
  test('list returns formatted reminders', async () => {
191
163
  const future = new Date(Date.now() + 60_000).toISOString();
192
- await reminderTool.execute({
193
- action: 'create',
164
+ executeReminderCreate({
194
165
  fire_at: future,
195
166
  label: 'Test reminder',
196
167
  message: 'Test message',
197
- }, dummyContext);
168
+ });
198
169
 
199
- const result = await reminderTool.execute({ action: 'list' }, dummyContext);
170
+ const result = executeReminderList();
200
171
  expect(result.isError).toBe(false);
201
172
  expect(result.content).toContain('Test reminder');
202
173
  expect(result.content).toContain('pending');
@@ -206,32 +177,29 @@ describe('reminder tool', () => {
206
177
 
207
178
  test('cancel with valid pending reminder succeeds', async () => {
208
179
  const future = new Date(Date.now() + 60_000).toISOString();
209
- const createResult = await reminderTool.execute({
210
- action: 'create',
180
+ const createResult = executeReminderCreate({
211
181
  fire_at: future,
212
182
  label: 'Cancel me',
213
183
  message: 'To be cancelled',
214
- }, dummyContext);
184
+ });
215
185
 
216
186
  // Extract ID from the create result
217
187
  const idMatch = createResult.content.match(/ID: (.+)/);
218
188
  expect(idMatch).not.toBeNull();
219
189
  const id = idMatch![1].trim();
220
190
 
221
- const result = await reminderTool.execute({
222
- action: 'cancel',
191
+ const result = executeReminderCancel({
223
192
  reminder_id: id,
224
- }, dummyContext);
193
+ });
225
194
 
226
195
  expect(result.isError).toBe(false);
227
196
  expect(result.content).toContain('cancelled');
228
197
  });
229
198
 
230
199
  test('cancel with nonexistent ID returns error', async () => {
231
- const result = await reminderTool.execute({
232
- action: 'cancel',
200
+ const result = executeReminderCancel({
233
201
  reminder_id: 'nonexistent',
234
- }, dummyContext);
202
+ });
235
203
 
236
204
  expect(result.isError).toBe(true);
237
205
  expect(result.content).toContain('not found');
@@ -239,12 +207,11 @@ describe('reminder tool', () => {
239
207
 
240
208
  test('cancel with already-fired reminder returns error', async () => {
241
209
  const future = new Date(Date.now() + 60_000).toISOString();
242
- const createResult = await reminderTool.execute({
243
- action: 'create',
210
+ const createResult = executeReminderCreate({
244
211
  fire_at: future,
245
212
  label: 'Fire then cancel',
246
213
  message: 'x',
247
- }, dummyContext);
214
+ });
248
215
 
249
216
  const idMatch = createResult.content.match(/ID: (.+)/);
250
217
  const id = idMatch![1].trim();
@@ -252,10 +219,9 @@ describe('reminder tool', () => {
252
219
  // Force-fire by claiming with a future timestamp
253
220
  claimDueReminders(Date.now() + 120_000);
254
221
 
255
- const result = await reminderTool.execute({
256
- action: 'cancel',
222
+ const result = executeReminderCancel({
257
223
  reminder_id: id,
258
- }, dummyContext);
224
+ });
259
225
 
260
226
  expect(result.isError).toBe(true);
261
227
  expect(result.content).toContain('not found or already fired');
@@ -15,7 +15,7 @@
15
15
  * - assistant_text_delta + message_complete (onEvent path) → hub emits in order
16
16
  * - sessionId falls back to conversationId when the message lacks it
17
17
  */
18
- import { describe, test, expect, beforeEach, mock } from 'bun:test';
18
+ import { afterAll, describe, test, expect, beforeEach, mock } from 'bun:test';
19
19
  import { mkdtempSync } from 'node:fs';
20
20
  import { tmpdir } from 'node:os';
21
21
  import { join } from 'node:path';
@@ -44,13 +44,17 @@ mock.module('../util/logger.js', () => ({
44
44
  }),
45
45
  }));
46
46
 
47
- import { initializeDb, getDb } from '../memory/db.js';
47
+ import { initializeDb, getDb, resetDb } from '../memory/db.js';
48
48
  import { createConversation } from '../memory/conversation-store.js';
49
49
  import { RunOrchestrator } from '../runtime/run-orchestrator.js';
50
50
  import { assistantEventHub } from '../runtime/assistant-event-hub.js';
51
51
 
52
52
  initializeDb();
53
53
 
54
+ afterAll(() => {
55
+ resetDb();
56
+ });
57
+
54
58
  // ── Helpers ──────────────────────────────────────────────────────────────────
55
59
 
56
60
  /**
@@ -62,7 +66,7 @@ function makeSessionEmittingViaClient(...messages: ServerMessage[]): Session {
62
66
  return {
63
67
  isProcessing: () => false,
64
68
  persistUserMessage: () => undefined as unknown as string,
65
- setAssistantId: () => {},
69
+ setChannelCapabilities: () => {},
66
70
  updateClient: (handler: (msg: ServerMessage) => void) => {
67
71
  clientHandler = handler;
68
72
  },
@@ -83,7 +87,7 @@ function makeSessionEmittingViaAgentLoop(...messages: ServerMessage[]): Session
83
87
  return {
84
88
  isProcessing: () => false,
85
89
  persistUserMessage: () => undefined as unknown as string,
86
- setAssistantId: () => {},
90
+ setChannelCapabilities: () => {},
87
91
  updateClient: () => {},
88
92
  runAgentLoop: async (_content: string, _messageId: string, onEvent: (msg: ServerMessage) => void) => {
89
93
  for (const msg of messages) {
@@ -40,7 +40,7 @@ function makeSessionWithConfirmation(message: ServerMessage): Session {
40
40
  // Return undefined so createRun stores messageId as null and avoids
41
41
  // a foreign-key dependency on the conversation-store message table.
42
42
  persistUserMessage: () => undefined as unknown as string,
43
- setAssistantId: () => {},
43
+ setChannelCapabilities: () => {},
44
44
  updateClient: (handler: (msg: ServerMessage) => void) => {
45
45
  clientHandler = handler;
46
46
  },
@@ -60,7 +60,7 @@ function makeSessionWithEvent(message: ServerMessage): Session {
60
60
  return {
61
61
  isProcessing: () => false,
62
62
  persistUserMessage: () => undefined as unknown as string,
63
- setAssistantId: () => {},
63
+ setChannelCapabilities: () => {},
64
64
  updateClient: () => {},
65
65
  runAgentLoop: async (_content: string, _messageId: string, onEvent: (msg: ServerMessage) => void) => {
66
66
  onEvent(message);
@@ -139,7 +139,7 @@ describe('run approval state executionTarget', () => {
139
139
 
140
140
  test('stores pending confirmation executionTarget when provided', () => {
141
141
  const conversation = createConversation('run test');
142
- const run = createRun('assistant-1', conversation.id);
142
+ const run = createRun(conversation.id);
143
143
 
144
144
  setRunConfirmation(run.id, {
145
145
  toolName: 'host_file_read',
@@ -158,7 +158,7 @@ describe('run approval state executionTarget', () => {
158
158
 
159
159
  test('parses pending confirmations without executionTarget for legacy rows', () => {
160
160
  const conversation = createConversation('legacy run test');
161
- const run = createRun('assistant-1', conversation.id);
161
+ const run = createRun(conversation.id);
162
162
 
163
163
  setRunConfirmation(run.id, {
164
164
  toolName: 'bash',
@@ -34,7 +34,7 @@ mock.module('../config/loader.js', () => ({
34
34
  }),
35
35
  }));
36
36
 
37
- import { initializeDb, getDb } from '../memory/db.js';
37
+ import { initializeDb, getDb, resetDb } from '../memory/db.js';
38
38
  import * as conversationStore from '../memory/conversation-store.js';
39
39
  import { getOrCreateConversation } from '../memory/conversation-key-store.js';
40
40
  import {
@@ -46,6 +46,7 @@ import { RuntimeHttpServer } from '../runtime/http-server.js';
46
46
  initializeDb();
47
47
 
48
48
  afterAll(() => {
49
+ resetDb();
49
50
  try { rmSync(testDir, { recursive: true }); } catch { /* best effort */ }
50
51
  });
51
52
 
@@ -82,7 +83,7 @@ describe('Runtime attachment metadata', () => {
82
83
  const conversationKey = 'test-conv-1';
83
84
 
84
85
  // Set up conversation and messages using "self" as the assistantId
85
- const mapping = getOrCreateConversation("self", conversationKey);
86
+ const mapping = getOrCreateConversation(conversationKey);
86
87
  conversationStore.addMessage(mapping.conversationId, 'user', 'Hello');
87
88
  const assistantMsg = conversationStore.addMessage(
88
89
  mapping.conversationId,
@@ -91,7 +92,7 @@ describe('Runtime attachment metadata', () => {
91
92
  );
92
93
 
93
94
  // Upload and link an attachment using "self" as the assistantId
94
- const stored = uploadAttachment("self", 'chart.png', 'image/png', 'iVBOR');
95
+ const stored = uploadAttachment('chart.png', 'image/png', 'iVBOR');
95
96
  linkAttachmentToMessage(assistantMsg.id, stored.id, 0);
96
97
 
97
98
  const res = await fetch(
@@ -121,7 +122,7 @@ describe('Runtime attachment metadata', () => {
121
122
  test('GET /messages returns empty attachments when none linked', async () => {
122
123
  const conversationKey = 'test-conv-2';
123
124
 
124
- const mapping = getOrCreateConversation("self", conversationKey);
125
+ const mapping = getOrCreateConversation(conversationKey);
125
126
  conversationStore.addMessage(mapping.conversationId, 'user', 'Hello');
126
127
  conversationStore.addMessage(
127
128
  mapping.conversationId,
@@ -142,7 +143,7 @@ describe('Runtime attachment metadata', () => {
142
143
  });
143
144
 
144
145
  test('GET /attachments/:id returns attachment with payload', async () => {
145
- const stored = uploadAttachment("self", 'report.pdf', 'application/pdf', 'JVBER');
146
+ const stored = uploadAttachment('report.pdf', 'application/pdf', 'JVBER');
146
147
 
147
148
  const res = await fetch(
148
149
  `http://127.0.0.1:${port}/v1/attachments/${stored.id}`,
@@ -162,7 +163,7 @@ describe('Runtime attachment metadata', () => {
162
163
  });
163
164
 
164
165
  test('GET /attachments/:id returns attachment stored under "self"', async () => {
165
- const stored = uploadAttachment("self", 'shared.txt', 'text/plain', 'c2hhcmVk');
166
+ const stored = uploadAttachment('shared.txt', 'text/plain', 'c2hhcmVk');
166
167
 
167
168
  const res = await fetch(
168
169
  `http://127.0.0.1:${port}/v1/attachments/${stored.id}`,
@@ -58,7 +58,7 @@ function makeCompletingSession(): Session {
58
58
  return {
59
59
  isProcessing: () => processing,
60
60
  persistUserMessage: () => undefined as unknown as string,
61
- setAssistantId: () => {},
61
+ setChannelCapabilities: () => {},
62
62
  updateClient: () => {},
63
63
  runAgentLoop: async () => {
64
64
  processing = true;
@@ -73,7 +73,7 @@ function makeFailingSession(errorMsg: string): Session {
73
73
  return {
74
74
  isProcessing: () => false,
75
75
  persistUserMessage: () => undefined as unknown as string,
76
- setAssistantId: () => {},
76
+ setChannelCapabilities: () => {},
77
77
  updateClient: () => {},
78
78
  runAgentLoop: async (_content: string, _messageId: string, onEvent: (msg: ServerMessage) => void) => {
79
79
  onEvent({ type: 'error', message: errorMsg });
@@ -87,7 +87,7 @@ function makeConfirmationSession(toolName: string): Session {
87
87
  return {
88
88
  isProcessing: () => false,
89
89
  persistUserMessage: () => undefined as unknown as string,
90
- setAssistantId: () => {},
90
+ setChannelCapabilities: () => {},
91
91
  updateClient: (handler: (msg: ServerMessage) => void) => {
92
92
  clientHandler = handler;
93
93
  },
@@ -113,7 +113,7 @@ function makeHangingSession(): Session {
113
113
  return {
114
114
  isProcessing: () => processing,
115
115
  persistUserMessage: () => undefined as unknown as string,
116
- setAssistantId: () => {},
116
+ setChannelCapabilities: () => {},
117
117
  updateClient: () => {},
118
118
  runAgentLoop: async () => {
119
119
  processing = true;
@@ -48,7 +48,7 @@ function makeCompletingSession(): Session {
48
48
  return {
49
49
  isProcessing: () => processing,
50
50
  persistUserMessage: () => undefined as unknown as string,
51
- setAssistantId: () => {},
51
+ setChannelCapabilities: () => {},
52
52
  updateClient: () => {},
53
53
  runAgentLoop: async () => {
54
54
  processing = true;
@@ -66,7 +66,7 @@ function makeHangingSession(): Session {
66
66
  return {
67
67
  isProcessing: () => processing,
68
68
  persistUserMessage: () => undefined as unknown as string,
69
- setAssistantId: () => {},
69
+ setChannelCapabilities: () => {},
70
70
  updateClient: () => {},
71
71
  runAgentLoop: async () => {
72
72
  processing = true;
@@ -82,7 +82,7 @@ function makeFailingSession(errorMsg: string): Session {
82
82
  return {
83
83
  isProcessing: () => false,
84
84
  persistUserMessage: () => undefined as unknown as string,
85
- setAssistantId: () => {},
85
+ setChannelCapabilities: () => {},
86
86
  updateClient: () => {},
87
87
  runAgentLoop: async (_content: string, _messageId: string, onEvent: (msg: ServerMessage) => void) => {
88
88
  onEvent({ type: 'error', message: errorMsg });
@@ -97,7 +97,7 @@ function makeConfirmationSession(toolName: string, principal?: { kind?: string;
97
97
  return {
98
98
  isProcessing: () => false,
99
99
  persistUserMessage: () => undefined as unknown as string,
100
- setAssistantId: () => {},
100
+ setChannelCapabilities: () => {},
101
101
  updateClient: (handler: (msg: ServerMessage) => void) => {
102
102
  clientHandler = handler;
103
103
  },