vellum 0.2.0 → 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 (361) 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 +161 -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__/app-bundler.test.ts +12 -33
  11. package/src/__tests__/asset-materialize-tool.test.ts +16 -15
  12. package/src/__tests__/asset-search-tool.test.ts +23 -22
  13. package/src/__tests__/attachments-store.test.ts +56 -127
  14. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +5 -4
  15. package/src/__tests__/browser-skill-endstate.test.ts +5 -8
  16. package/src/__tests__/call-bridge.test.ts +385 -0
  17. package/src/__tests__/call-constants.test.ts +40 -0
  18. package/src/__tests__/call-orchestrator.test.ts +454 -0
  19. package/src/__tests__/call-recovery.test.ts +518 -0
  20. package/src/__tests__/call-routes-http.test.ts +459 -0
  21. package/src/__tests__/call-state-machine.test.ts +143 -0
  22. package/src/__tests__/call-state.test.ts +133 -0
  23. package/src/__tests__/call-store.test.ts +691 -0
  24. package/src/__tests__/cli-discover.test.ts +1 -1
  25. package/src/__tests__/commit-message-enrichment-service.test.ts +550 -0
  26. package/src/__tests__/compaction.benchmark.test.ts +176 -0
  27. package/src/__tests__/computer-use-tools.test.ts +250 -0
  28. package/src/__tests__/config-schema.test.ts +348 -3
  29. package/src/__tests__/conflict-store.test.ts +2 -1
  30. package/src/__tests__/contacts-tools.test.ts +331 -0
  31. package/src/__tests__/conversation-store.test.ts +30 -32
  32. package/src/__tests__/credential-security-invariants.test.ts +4 -0
  33. package/src/__tests__/date-context.test.ts +373 -0
  34. package/src/__tests__/db-schedule-syntax-migration.test.ts +129 -0
  35. package/src/__tests__/doordash-session.test.ts +9 -0
  36. package/src/__tests__/fixtures/media-reuse-fixtures.ts +3 -3
  37. package/src/__tests__/followup-tools.test.ts +303 -0
  38. package/src/__tests__/handlers-twitter-config.test.ts +718 -0
  39. package/src/__tests__/intent-routing.test.ts +64 -57
  40. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +237 -0
  41. package/src/__tests__/ipc-snapshot.test.ts +96 -28
  42. package/src/__tests__/llm-usage-store.test.ts +3 -8
  43. package/src/__tests__/media-generate-image.test.ts +1 -1
  44. package/src/__tests__/media-reuse-story.e2e.test.ts +7 -7
  45. package/src/__tests__/memory-retrieval.benchmark.test.ts +430 -0
  46. package/src/__tests__/parallel-tool.benchmark.test.ts +294 -0
  47. package/src/__tests__/playbook-tools.test.ts +342 -0
  48. package/src/__tests__/profile-compiler.test.ts +2 -1
  49. package/src/__tests__/provider-streaming.benchmark.test.ts +773 -0
  50. package/src/__tests__/recurrence-engine-rruleset.test.ts +78 -0
  51. package/src/__tests__/recurrence-engine.test.ts +69 -0
  52. package/src/__tests__/recurrence-types.test.ts +71 -0
  53. package/src/__tests__/registry.test.ts +17 -10
  54. package/src/__tests__/relay-server.test.ts +633 -0
  55. package/src/__tests__/reminder-store.test.ts +6 -3
  56. package/src/__tests__/reminder.test.ts +43 -77
  57. package/src/__tests__/run-orchestrator-assistant-events.test.ts +222 -0
  58. package/src/__tests__/run-orchestrator.test.ts +7 -7
  59. package/src/__tests__/runtime-attachment-metadata.test.ts +19 -20
  60. package/src/__tests__/runtime-runs-http.test.ts +5 -23
  61. package/src/__tests__/runtime-runs.test.ts +11 -11
  62. package/src/__tests__/schedule-store.test.ts +482 -0
  63. package/src/__tests__/schedule-tools.test.ts +700 -0
  64. package/src/__tests__/scheduler-recurrence.test.ts +329 -0
  65. package/src/__tests__/server-history-render.test.ts +14 -13
  66. package/src/__tests__/session-error.test.ts +28 -0
  67. package/src/__tests__/session-init.benchmark.test.ts +462 -0
  68. package/src/__tests__/session-queue.test.ts +89 -16
  69. package/src/__tests__/session-runtime-assembly.test.ts +161 -0
  70. package/src/__tests__/session-surfaces-task-progress.test.ts +104 -0
  71. package/src/__tests__/signup-e2e.test.ts +2 -1
  72. package/src/__tests__/skill-projection.benchmark.test.ts +328 -0
  73. package/src/__tests__/skill-script-runner.test.ts +159 -0
  74. package/src/__tests__/speaker-identification.test.ts +52 -0
  75. package/src/__tests__/subagent-manager-notify.test.ts +42 -10
  76. package/src/__tests__/subagent-tools.test.ts +141 -41
  77. package/src/__tests__/task-compiler.test.ts +2 -1
  78. package/src/__tests__/task-runner.test.ts +2 -1
  79. package/src/__tests__/task-scheduler.test.ts +2 -1
  80. package/src/__tests__/task-tools.test.ts +49 -56
  81. package/src/__tests__/tool-audit-listener.test.ts +1 -0
  82. package/src/__tests__/tool-domain-event-publisher.test.ts +2 -0
  83. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +500 -0
  84. package/src/__tests__/tool-executor.test.ts +13 -17
  85. package/src/__tests__/turn-commit.test.ts +273 -2
  86. package/src/__tests__/twilio-provider.test.ts +143 -0
  87. package/src/__tests__/twilio-routes.test.ts +789 -0
  88. package/src/__tests__/twitter-auth-handler.test.ts +581 -0
  89. package/src/__tests__/view-image-tool.test.ts +217 -0
  90. package/src/__tests__/workspace-git-service.test.ts +403 -0
  91. package/src/__tests__/workspace-heartbeat-service.test.ts +141 -2
  92. package/src/agent-heartbeat/agent-heartbeat-service.ts +155 -0
  93. package/src/bundler/app-bundler.ts +35 -14
  94. package/src/calls/call-bridge.ts +95 -0
  95. package/src/calls/call-constants.ts +48 -0
  96. package/src/calls/call-domain.ts +276 -0
  97. package/src/calls/call-orchestrator.ts +390 -0
  98. package/src/calls/call-recovery.ts +207 -0
  99. package/src/calls/call-state-machine.ts +68 -0
  100. package/src/calls/call-state.ts +64 -0
  101. package/src/calls/call-store.ts +416 -0
  102. package/src/calls/relay-server.ts +335 -0
  103. package/src/calls/speaker-identification.ts +213 -0
  104. package/src/calls/twilio-config.ts +34 -0
  105. package/src/calls/twilio-provider.ts +173 -0
  106. package/src/calls/twilio-routes.ts +250 -0
  107. package/src/calls/types.ts +37 -0
  108. package/src/calls/voice-provider.ts +14 -0
  109. package/src/cli/config-commands.ts +334 -0
  110. package/src/cli/core-commands.ts +776 -0
  111. package/src/cli/doordash.ts +256 -25
  112. package/src/cli/ipc-client.ts +82 -0
  113. package/src/cli/map.ts +246 -0
  114. package/src/cli/twitter.ts +575 -0
  115. package/src/cli.ts +7 -5
  116. package/src/commands/__tests__/cc-command-registry.test.ts +319 -0
  117. package/src/commands/cc-command-registry.ts +209 -0
  118. package/src/config/bundled-skills/contacts/SKILL.md +39 -0
  119. package/src/config/bundled-skills/contacts/TOOLS.json +122 -0
  120. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +9 -0
  121. package/src/config/bundled-skills/contacts/tools/contact-search.ts +9 -0
  122. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +9 -0
  123. package/src/config/bundled-skills/document/SKILL.md +18 -0
  124. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  125. package/src/config/bundled-skills/document/tools/document-create.ts +9 -0
  126. package/src/config/bundled-skills/document/tools/document-update.ts +9 -0
  127. package/src/config/bundled-skills/doordash/SKILL.md +163 -0
  128. package/src/config/bundled-skills/followups/SKILL.md +32 -0
  129. package/src/config/bundled-skills/followups/TOOLS.json +100 -0
  130. package/src/config/bundled-skills/followups/tools/followup-create.ts +9 -0
  131. package/src/config/bundled-skills/followups/tools/followup-list.ts +9 -0
  132. package/src/config/bundled-skills/followups/tools/followup-resolve.ts +9 -0
  133. package/src/config/bundled-skills/image-studio/TOOLS.json +2 -2
  134. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -24
  135. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -1
  136. package/src/config/bundled-skills/playbooks/SKILL.md +31 -0
  137. package/src/config/bundled-skills/playbooks/TOOLS.json +126 -0
  138. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +9 -0
  139. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +9 -0
  140. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +9 -0
  141. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +9 -0
  142. package/src/config/bundled-skills/reminder/SKILL.md +20 -0
  143. package/src/config/bundled-skills/reminder/TOOLS.json +67 -0
  144. package/src/config/bundled-skills/reminder/tools/reminder-cancel.ts +9 -0
  145. package/src/config/bundled-skills/reminder/tools/reminder-create.ts +9 -0
  146. package/src/config/bundled-skills/reminder/tools/reminder-list.ts +9 -0
  147. package/src/config/bundled-skills/schedule/SKILL.md +74 -0
  148. package/src/config/bundled-skills/schedule/TOOLS.json +135 -0
  149. package/src/config/bundled-skills/schedule/tools/schedule-create.ts +9 -0
  150. package/src/config/bundled-skills/schedule/tools/schedule-delete.ts +9 -0
  151. package/src/config/bundled-skills/schedule/tools/schedule-list.ts +9 -0
  152. package/src/config/bundled-skills/schedule/tools/schedule-update.ts +9 -0
  153. package/src/config/bundled-skills/subagent/SKILL.md +25 -0
  154. package/src/config/bundled-skills/subagent/TOOLS.json +107 -0
  155. package/src/config/bundled-skills/subagent/tools/subagent-abort.ts +9 -0
  156. package/src/config/bundled-skills/subagent/tools/subagent-message.ts +9 -0
  157. package/src/config/bundled-skills/subagent/tools/subagent-read.ts +9 -0
  158. package/src/config/bundled-skills/subagent/tools/subagent-spawn.ts +9 -0
  159. package/src/config/bundled-skills/subagent/tools/subagent-status.ts +9 -0
  160. package/src/config/bundled-skills/tasks/SKILL.md +28 -0
  161. package/src/config/bundled-skills/tasks/TOOLS.json +256 -0
  162. package/src/config/bundled-skills/tasks/tools/task-delete.ts +9 -0
  163. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +9 -0
  164. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +9 -0
  165. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +9 -0
  166. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +9 -0
  167. package/src/config/bundled-skills/tasks/tools/task-list.ts +9 -0
  168. package/src/config/bundled-skills/tasks/tools/task-run.ts +9 -0
  169. package/src/config/bundled-skills/tasks/tools/task-save.ts +9 -0
  170. package/src/config/bundled-skills/twitter/SKILL.md +134 -0
  171. package/src/config/bundled-skills/watcher/SKILL.md +27 -0
  172. package/src/config/bundled-skills/watcher/TOOLS.json +147 -0
  173. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +9 -0
  174. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +9 -0
  175. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +9 -0
  176. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +9 -0
  177. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +9 -0
  178. package/src/config/defaults.ts +44 -0
  179. package/src/config/loader.ts +4 -1
  180. package/src/config/schema.ts +218 -1
  181. package/src/config/system-prompt.ts +100 -6
  182. package/src/config/templates/IDENTITY.md +7 -0
  183. package/src/config/types.ts +5 -0
  184. package/src/contacts/contact-store.ts +4 -4
  185. package/src/daemon/assistant-attachments.ts +10 -0
  186. package/src/daemon/classifier.ts +3 -1
  187. package/src/daemon/computer-use-session.ts +3 -1
  188. package/src/daemon/date-context.ts +136 -0
  189. package/src/daemon/handlers/apps.ts +16 -1
  190. package/src/daemon/handlers/browser.ts +54 -0
  191. package/src/daemon/handlers/computer-use.ts +7 -1
  192. package/src/daemon/handlers/config.ts +192 -4
  193. package/src/daemon/handlers/diagnostics.ts +5 -1
  194. package/src/daemon/handlers/documents.ts +18 -29
  195. package/src/daemon/handlers/home-base.ts +5 -1
  196. package/src/daemon/handlers/index.ts +40 -271
  197. package/src/daemon/handlers/misc.ts +9 -1
  198. package/src/daemon/handlers/publish.ts +6 -1
  199. package/src/daemon/handlers/sessions.ts +65 -12
  200. package/src/daemon/handlers/shared.ts +36 -1
  201. package/src/daemon/handlers/signing.ts +37 -0
  202. package/src/daemon/handlers/skills.ts +20 -6
  203. package/src/daemon/handlers/subagents.ts +8 -3
  204. package/src/daemon/handlers/twitter-auth.ts +169 -0
  205. package/src/daemon/handlers/work-items.ts +495 -39
  206. package/src/daemon/ipc-contract-inventory.json +40 -4
  207. package/src/daemon/ipc-contract.ts +185 -37
  208. package/src/daemon/ipc-protocol.ts +7 -2
  209. package/src/daemon/lifecycle.ts +48 -5
  210. package/src/daemon/main.ts +10 -4
  211. package/src/daemon/ride-shotgun-handler.ts +74 -10
  212. package/src/daemon/server.ts +144 -29
  213. package/src/daemon/session-agent-loop.ts +887 -0
  214. package/src/daemon/session-attachments.ts +28 -5
  215. package/src/daemon/session-error.ts +24 -3
  216. package/src/daemon/session-lifecycle.ts +147 -0
  217. package/src/daemon/session-media-retry.ts +147 -0
  218. package/src/daemon/session-messaging.ts +145 -0
  219. package/src/daemon/session-notifiers.ts +164 -0
  220. package/src/daemon/session-process.ts +2 -2
  221. package/src/daemon/session-queue-manager.ts +1 -0
  222. package/src/daemon/session-runtime-assembly.ts +52 -0
  223. package/src/daemon/session-skill-tools.ts +124 -5
  224. package/src/daemon/session-slash.ts +3 -0
  225. package/src/daemon/session-surfaces.ts +77 -2
  226. package/src/daemon/session-tool-setup.ts +222 -2
  227. package/src/daemon/session-usage.ts +0 -2
  228. package/src/daemon/session.ts +114 -1365
  229. package/src/daemon/video-thumbnail.ts +60 -0
  230. package/src/doordash/client.ts +121 -27
  231. package/src/doordash/queries.ts +1 -2
  232. package/src/export/formatter.ts +3 -1
  233. package/src/followups/followup-store.ts +4 -2
  234. package/src/followups/types.ts +6 -0
  235. package/src/hooks/templates.ts +1 -1
  236. package/src/index.ts +32 -1151
  237. package/src/media/gemini-image-service.ts +1 -1
  238. package/src/memory/attachments-store.ts +28 -83
  239. package/src/memory/channel-delivery-store.ts +7 -21
  240. package/src/memory/clarification-resolver.ts +6 -5
  241. package/src/memory/contradiction-checker.ts +3 -2
  242. package/src/memory/conversation-key-store.ts +10 -29
  243. package/src/memory/conversation-store.ts +2 -1
  244. package/src/memory/db.ts +362 -2
  245. package/src/memory/entity-extractor.ts +6 -3
  246. package/src/memory/items-extractor.ts +5 -4
  247. package/src/memory/jobs-store.ts +3 -2
  248. package/src/memory/llm-usage-store.ts +1 -2
  249. package/src/memory/runs-store.ts +1 -2
  250. package/src/memory/schema.ts +65 -2
  251. package/src/messaging/style-analyzer.ts +3 -2
  252. package/src/messaging/thread-summarizer.ts +8 -12
  253. package/src/messaging/triage-engine.ts +4 -2
  254. package/src/providers/openrouter/client.ts +20 -0
  255. package/src/providers/registry.ts +8 -0
  256. package/src/runtime/http-server.ts +277 -25
  257. package/src/runtime/http-types.ts +0 -2
  258. package/src/runtime/routes/attachment-routes.ts +5 -6
  259. package/src/runtime/routes/call-routes.ts +140 -0
  260. package/src/runtime/routes/channel-routes.ts +12 -19
  261. package/src/runtime/routes/conversation-routes.ts +5 -9
  262. package/src/runtime/routes/run-routes.ts +4 -8
  263. package/src/runtime/run-orchestrator.ts +39 -6
  264. package/src/schedule/recurrence-engine.ts +138 -0
  265. package/src/schedule/recurrence-types.ts +67 -0
  266. package/src/schedule/schedule-store.ts +102 -57
  267. package/src/schedule/scheduler.ts +9 -6
  268. package/src/security/oauth2.ts +29 -4
  269. package/src/security/secret-allowlist.ts +46 -0
  270. package/src/skills/clawhub.ts +1 -1
  271. package/src/subagent/manager.ts +40 -8
  272. package/src/swarm/backend-claude-code.ts +64 -9
  273. package/src/swarm/worker-prompts.ts +2 -1
  274. package/src/tasks/SPEC.md +34 -28
  275. package/src/tasks/ephemeral-permissions.ts +16 -7
  276. package/src/tasks/task-compiler.ts +5 -4
  277. package/src/tasks/task-runner.ts +10 -5
  278. package/src/tasks/task-scheduler.ts +1 -1
  279. package/src/tasks/tool-sanitizer.ts +36 -0
  280. package/src/tools/assets/search.ts +4 -4
  281. package/src/tools/browser/api-map.ts +220 -0
  282. package/src/tools/browser/auto-navigate.ts +270 -0
  283. package/src/tools/browser/browser-execution.ts +2 -1
  284. package/src/tools/browser/browser-manager.ts +2 -2
  285. package/src/tools/browser/network-recorder.ts +5 -4
  286. package/src/tools/browser/x-auto-navigate.ts +207 -0
  287. package/src/tools/calls/call-end.ts +67 -0
  288. package/src/tools/calls/call-start.ts +73 -0
  289. package/src/tools/calls/call-status.ts +81 -0
  290. package/src/tools/claude-code/claude-code.ts +77 -11
  291. package/src/tools/contacts/contact-merge.ts +46 -78
  292. package/src/tools/contacts/contact-search.ts +35 -79
  293. package/src/tools/contacts/contact-upsert.ts +35 -108
  294. package/src/tools/credentials/vault.ts +21 -5
  295. package/src/tools/document/document-tool.ts +71 -144
  296. package/src/tools/executor.ts +129 -10
  297. package/src/tools/followups/followup_create.ts +46 -88
  298. package/src/tools/followups/followup_list.ts +34 -74
  299. package/src/tools/followups/followup_resolve.ts +31 -66
  300. package/src/tools/host-terminal/cli-discover.ts +2 -1
  301. package/src/tools/host-terminal/host-shell.ts +10 -0
  302. package/src/tools/memory/handlers.ts +5 -4
  303. package/src/tools/network/__tests__/web-search.test.ts +427 -0
  304. package/src/tools/network/script-proxy/__tests__/logging.test.ts +248 -0
  305. package/src/tools/network/script-proxy/__tests__/policy.test.ts +234 -0
  306. package/src/tools/network/script-proxy/__tests__/router.test.ts +76 -0
  307. package/src/tools/network/web-fetch.ts +18 -6
  308. package/src/tools/playbooks/index.ts +4 -5
  309. package/src/tools/playbooks/playbook-create.ts +3 -47
  310. package/src/tools/playbooks/playbook-delete.ts +1 -25
  311. package/src/tools/playbooks/playbook-list.ts +1 -28
  312. package/src/tools/playbooks/playbook-update.ts +3 -51
  313. package/src/tools/registry.ts +2 -4
  314. package/src/tools/reminder/reminder.ts +5 -78
  315. package/src/tools/schedule/create.ts +69 -74
  316. package/src/tools/schedule/delete.ts +21 -47
  317. package/src/tools/schedule/list.ts +55 -74
  318. package/src/tools/schedule/update.ts +77 -84
  319. package/src/tools/subagent/abort.ts +29 -58
  320. package/src/tools/subagent/message.ts +30 -63
  321. package/src/tools/subagent/read.ts +53 -84
  322. package/src/tools/subagent/spawn.ts +43 -82
  323. package/src/tools/subagent/status.ts +42 -71
  324. package/src/tools/swarm/delegate.ts +2 -1
  325. package/src/tools/tasks/index.ts +8 -6
  326. package/src/tools/tasks/task-delete.ts +69 -56
  327. package/src/tools/tasks/task-list.ts +31 -52
  328. package/src/tools/tasks/task-run.ts +74 -102
  329. package/src/tools/tasks/task-save.ts +33 -65
  330. package/src/tools/tasks/work-item-enqueue.ts +192 -134
  331. package/src/tools/tasks/work-item-list.ts +33 -78
  332. package/src/tools/tasks/work-item-remove.ts +60 -0
  333. package/src/tools/tasks/work-item-update.ts +114 -0
  334. package/src/tools/terminal/backends/native.ts +3 -1
  335. package/src/tools/tool-manifest.ts +20 -74
  336. package/src/tools/types.ts +6 -0
  337. package/src/tools/ui-surface/definitions.ts +6 -1
  338. package/src/tools/watch/screen-watch.ts +3 -1
  339. package/src/tools/watcher/create.ts +52 -98
  340. package/src/tools/watcher/delete.ts +20 -46
  341. package/src/tools/watcher/digest.ts +36 -70
  342. package/src/tools/watcher/list.ts +49 -79
  343. package/src/tools/watcher/update.ts +45 -91
  344. package/src/twitter/client.ts +690 -0
  345. package/src/twitter/session.ts +91 -0
  346. package/src/usage/types.ts +0 -1
  347. package/src/util/truncate.ts +6 -0
  348. package/src/watcher/providers/slack.ts +2 -1
  349. package/src/watcher/watcher-store.ts +3 -2
  350. package/src/work-items/work-item-store.ts +236 -2
  351. package/src/workspace/commit-message-enrichment-service.ts +284 -0
  352. package/src/workspace/commit-message-provider.ts +95 -0
  353. package/src/workspace/git-service.ts +272 -52
  354. package/src/workspace/heartbeat-service.ts +70 -13
  355. package/src/workspace/provider-commit-message-generator.ts +242 -0
  356. package/src/workspace/turn-commit.ts +100 -51
  357. package/src/tools/contacts/index.ts +0 -4
  358. package/src/tools/document/index.ts +0 -5
  359. package/src/tools/followups/index.ts +0 -3
  360. package/src/tools/subagent/index.ts +0 -5
  361. /package/src/__tests__/{memory-context-benchmark.test.ts → memory-context-benchmark.benchmark.test.ts} +0 -0
@@ -36,7 +36,7 @@ mock.module('../config/loader.js', () => ({
36
36
  }),
37
37
  }));
38
38
 
39
- import { initializeDb, getDb } from '../memory/db.js';
39
+ import { initializeDb, getDb, resetDb } from '../memory/db.js';
40
40
  import { uploadAttachment, linkAttachmentToMessage } from '../memory/attachments-store.js';
41
41
  import { createConversation, addMessage } from '../memory/conversation-store.js';
42
42
  import { assetMaterializeTool } from '../tools/assets/materialize.js';
@@ -49,6 +49,7 @@ import { mkdirSync } from 'node:fs';
49
49
  mkdirSync(sandboxDir, { recursive: true });
50
50
 
51
51
  afterAll(() => {
52
+ resetDb();
52
53
  try { rmSync(testDir, { recursive: true }); } catch { /* best effort */ }
53
54
  });
54
55
 
@@ -103,7 +104,7 @@ describe('AssetMaterializeTool sandbox path enforcement', () => {
103
104
  beforeEach(resetTables);
104
105
 
105
106
  test('rejects path that escapes sandbox via ../', async () => {
106
- const stored = uploadAttachment('ast-1', 'test.png', 'image/png', 'AAAA');
107
+ const stored = uploadAttachment('test.png', 'image/png', 'AAAA');
107
108
  const result = await assetMaterializeTool.execute(
108
109
  { attachment_id: stored.id, destination_path: '../../etc/evil.png' },
109
110
  dummyContext,
@@ -113,7 +114,7 @@ describe('AssetMaterializeTool sandbox path enforcement', () => {
113
114
  });
114
115
 
115
116
  test('rejects absolute path outside sandbox', async () => {
116
- const stored = uploadAttachment('ast-1', 'test.png', 'image/png', 'AAAA');
117
+ const stored = uploadAttachment('test.png', 'image/png', 'AAAA');
117
118
  const result = await assetMaterializeTool.execute(
118
119
  { attachment_id: stored.id, destination_path: '/tmp/outside-sandbox/evil.png' },
119
120
  dummyContext,
@@ -123,7 +124,7 @@ describe('AssetMaterializeTool sandbox path enforcement', () => {
123
124
  });
124
125
 
125
126
  test('accepts relative path inside sandbox', async () => {
126
- const stored = uploadAttachment('ast-1', 'test.png', 'image/png', 'AAAA');
127
+ const stored = uploadAttachment('test.png', 'image/png', 'AAAA');
127
128
  const result = await assetMaterializeTool.execute(
128
129
  { attachment_id: stored.id, destination_path: 'output.png' },
129
130
  dummyContext,
@@ -133,7 +134,7 @@ describe('AssetMaterializeTool sandbox path enforcement', () => {
133
134
  });
134
135
 
135
136
  test('accepts nested path inside sandbox with auto-created subdirs', async () => {
136
- const stored = uploadAttachment('ast-1', 'test.png', 'image/png', 'AAAA');
137
+ const stored = uploadAttachment('test.png', 'image/png', 'AAAA');
137
138
  const result = await assetMaterializeTool.execute(
138
139
  { attachment_id: stored.id, destination_path: 'subdir/deep/output.png' },
139
140
  dummyContext,
@@ -172,7 +173,7 @@ describe('AssetMaterializeTool materialization', () => {
172
173
  const originalContent = 'Hello, World!';
173
174
  const base64Content = Buffer.from(originalContent).toString('base64');
174
175
 
175
- const stored = uploadAttachment('ast-1', 'hello.txt', 'text/plain', base64Content);
176
+ const stored = uploadAttachment('hello.txt', 'text/plain', base64Content);
176
177
 
177
178
  const destPath = 'materialized-hello.txt';
178
179
  const result = await assetMaterializeTool.execute(
@@ -194,7 +195,7 @@ describe('AssetMaterializeTool materialization', () => {
194
195
  const binaryBytes = Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]);
195
196
  const base64Content = binaryBytes.toString('base64');
196
197
 
197
- const stored = uploadAttachment('ast-1', 'tiny.png', 'image/png', base64Content);
198
+ const stored = uploadAttachment('tiny.png', 'image/png', base64Content);
198
199
 
199
200
  const result = await assetMaterializeTool.execute(
200
201
  { attachment_id: stored.id, destination_path: 'images/tiny.png' },
@@ -209,7 +210,7 @@ describe('AssetMaterializeTool materialization', () => {
209
210
 
210
211
  test('result includes resolved path', async () => {
211
212
  const base64Content = Buffer.from('test').toString('base64');
212
- const stored = uploadAttachment('ast-1', 'doc.txt', 'text/plain', base64Content);
213
+ const stored = uploadAttachment('doc.txt', 'text/plain', base64Content);
213
214
 
214
215
  const result = await assetMaterializeTool.execute(
215
216
  { attachment_id: stored.id, destination_path: 'output/doc.txt' },
@@ -222,7 +223,7 @@ describe('AssetMaterializeTool materialization', () => {
222
223
 
223
224
  test('result includes filename, MIME type and size info', async () => {
224
225
  const base64Content = Buffer.from('some data here').toString('base64');
225
- const stored = uploadAttachment('ast-1', 'report.pdf', 'application/pdf', base64Content);
226
+ const stored = uploadAttachment('report.pdf', 'application/pdf', base64Content);
226
227
 
227
228
  const result = await assetMaterializeTool.execute(
228
229
  { attachment_id: stored.id, destination_path: 'report.pdf' },
@@ -307,7 +308,7 @@ describe('AssetMaterializeTool visibility policy', () => {
307
308
  test('materializing from a standard thread works from any context', async () => {
308
309
  const standardConv = createConversation({ title: 'standard-conv' });
309
310
  const base64Content = Buffer.from('standard content').toString('base64');
310
- const attachment = uploadAttachment('ast-1', 'public.txt', 'text/plain', base64Content);
311
+ const attachment = uploadAttachment('public.txt', 'text/plain', base64Content);
311
312
  const msg = addMessage(standardConv.id, 'user', 'standard message');
312
313
  linkAttachmentToMessage(msg.id, attachment.id, 0);
313
314
 
@@ -330,7 +331,7 @@ describe('AssetMaterializeTool visibility policy', () => {
330
331
  test('materializing from a private thread works within the same private thread', async () => {
331
332
  const privateConv = createConversation({ title: 'private-conv', threadType: 'private' });
332
333
  const base64Content = Buffer.from('private content').toString('base64');
333
- const attachment = uploadAttachment('ast-1', 'secret.txt', 'text/plain', base64Content);
334
+ const attachment = uploadAttachment('secret.txt', 'text/plain', base64Content);
334
335
  const msg = addMessage(privateConv.id, 'user', 'private message');
335
336
  linkAttachmentToMessage(msg.id, attachment.id, 0);
336
337
 
@@ -352,7 +353,7 @@ describe('AssetMaterializeTool visibility policy', () => {
352
353
  test('materializing from a private thread is REJECTED from a different conversation', async () => {
353
354
  const privateConv = createConversation({ title: 'private-conv', threadType: 'private' });
354
355
  const base64Content = Buffer.from('private content').toString('base64');
355
- const attachment = uploadAttachment('ast-1', 'secret.txt', 'text/plain', base64Content);
356
+ const attachment = uploadAttachment('secret.txt', 'text/plain', base64Content);
356
357
  const msg = addMessage(privateConv.id, 'user', 'private message');
357
358
  linkAttachmentToMessage(msg.id, attachment.id, 0);
358
359
 
@@ -376,7 +377,7 @@ describe('AssetMaterializeTool visibility policy', () => {
376
377
  test('error message is user-actionable', async () => {
377
378
  const privateConv = createConversation({ title: 'private-conv', threadType: 'private' });
378
379
  const base64Content = Buffer.from('private content').toString('base64');
379
- const attachment = uploadAttachment('ast-1', 'confidential.pdf', 'application/pdf', base64Content);
380
+ const attachment = uploadAttachment('confidential.pdf', 'application/pdf', base64Content);
380
381
  const msg = addMessage(privateConv.id, 'user', 'private message');
381
382
  linkAttachmentToMessage(msg.id, attachment.id, 0);
382
383
 
@@ -402,7 +403,7 @@ describe('AssetMaterializeTool visibility policy', () => {
402
403
  test('materializing from a different private thread is REJECTED', async () => {
403
404
  const privateConv1 = createConversation({ title: 'private-conv-1', threadType: 'private' });
404
405
  const base64Content = Buffer.from('private content').toString('base64');
405
- const attachment = uploadAttachment('ast-1', 'secret.txt', 'text/plain', base64Content);
406
+ const attachment = uploadAttachment('secret.txt', 'text/plain', base64Content);
406
407
  const msg = addMessage(privateConv1.id, 'user', 'private message');
407
408
  linkAttachmentToMessage(msg.id, attachment.id, 0);
408
409
 
@@ -426,7 +427,7 @@ describe('AssetMaterializeTool visibility policy', () => {
426
427
  const privateConv = createConversation({ title: 'private-conv', threadType: 'private' });
427
428
  const standardConv = createConversation({ title: 'standard-conv' });
428
429
  const base64Content = Buffer.from('shared content').toString('base64');
429
- const attachment = uploadAttachment('ast-1', 'shared.txt', 'text/plain', base64Content);
430
+ const attachment = uploadAttachment('shared.txt', 'text/plain', base64Content);
430
431
 
431
432
  const msg1 = addMessage(privateConv.id, 'user', 'private message');
432
433
  const msg2 = addMessage(standardConv.id, 'user', 'standard message');
@@ -35,7 +35,7 @@ mock.module('../config/loader.js', () => ({
35
35
  }),
36
36
  }));
37
37
 
38
- import { initializeDb, getDb } from '../memory/db.js';
38
+ import { initializeDb, getDb, resetDb } from '../memory/db.js';
39
39
  import { uploadAttachment, linkAttachmentToMessage } from '../memory/attachments-store.js';
40
40
  import { createConversation, addMessage } from '../memory/conversation-store.js';
41
41
  import { searchAttachments } from '../tools/assets/search.js';
@@ -45,6 +45,7 @@ import type { ToolContext } from '../tools/types.js';
45
45
  initializeDb();
46
46
 
47
47
  afterAll(() => {
48
+ resetDb();
48
49
  try { rmSync(testDir, { recursive: true }); } catch { /* best effort */ }
49
50
  });
50
51
 
@@ -66,10 +67,10 @@ function seedAttachments() {
66
67
  // Force createdAt by uploading then manipulating the DB
67
68
  const db = getDb();
68
69
 
69
- const png1 = uploadAttachment('ast-1', 'selfie.png', 'image/png', 'AAAA');
70
- const jpg1 = uploadAttachment('ast-1', 'photo.jpg', 'image/jpeg', 'BBBB');
71
- const pdf1 = uploadAttachment('ast-1', 'report.pdf', 'application/pdf', 'CCCC');
72
- const png2 = uploadAttachment('ast-1', 'screenshot.png', 'image/png', 'DDDD');
70
+ const png1 = uploadAttachment('selfie.png', 'image/png', 'AAAA');
71
+ const jpg1 = uploadAttachment('photo.jpg', 'image/jpeg', 'BBBB');
72
+ const pdf1 = uploadAttachment('report.pdf', 'application/pdf', 'CCCC');
73
+ const png2 = uploadAttachment('screenshot.png', 'image/png', 'DDDD');
73
74
 
74
75
  // Backdate some attachments for recency testing
75
76
  db.run(`UPDATE attachments SET created_at = ${oneDayAgo} WHERE id = '${jpg1.id}'`);
@@ -217,8 +218,8 @@ describe('searchAttachments with conversation_id', () => {
217
218
  beforeEach(resetTables);
218
219
 
219
220
  test('returns only attachments linked to the specified conversation', () => {
220
- const png1 = uploadAttachment('ast-1', 'in-conv.png', 'image/png', 'AAAA');
221
- const png2 = uploadAttachment('ast-1', 'other-conv.png', 'image/png', 'BBBB');
221
+ const png1 = uploadAttachment('in-conv.png', 'image/png', 'AAAA');
222
+ const png2 = uploadAttachment('other-conv.png', 'image/png', 'BBBB');
222
223
 
223
224
  const conv1 = createConversation();
224
225
  const conv2 = createConversation();
@@ -234,7 +235,7 @@ describe('searchAttachments with conversation_id', () => {
234
235
  });
235
236
 
236
237
  test('returns empty when conversation has no attachments', () => {
237
- uploadAttachment('ast-1', 'orphan.png', 'image/png', 'AAAA');
238
+ uploadAttachment('orphan.png', 'image/png', 'AAAA');
238
239
  const conv = createConversation();
239
240
  addMessage(conv.id, 'user', 'No attachments here');
240
241
 
@@ -243,14 +244,14 @@ describe('searchAttachments with conversation_id', () => {
243
244
  });
244
245
 
245
246
  test('returns empty for nonexistent conversation_id', () => {
246
- uploadAttachment('ast-1', 'file.png', 'image/png', 'AAAA');
247
+ uploadAttachment('file.png', 'image/png', 'AAAA');
247
248
  const results = searchAttachments({ conversation_id: 'conv-nonexistent' });
248
249
  expect(results.length).toBe(0);
249
250
  });
250
251
 
251
252
  test('combines conversation_id with mime_type filter', () => {
252
- const png = uploadAttachment('ast-1', 'image.png', 'image/png', 'AAAA');
253
- const pdf = uploadAttachment('ast-1', 'doc.pdf', 'application/pdf', 'BBBB');
253
+ const png = uploadAttachment('image.png', 'image/png', 'AAAA');
254
+ const pdf = uploadAttachment('doc.pdf', 'application/pdf', 'BBBB');
254
255
 
255
256
  const conv = createConversation();
256
257
  const msg = addMessage(conv.id, 'user', 'Both types');
@@ -264,8 +265,8 @@ describe('searchAttachments with conversation_id', () => {
264
265
  });
265
266
 
266
267
  test('combines conversation_id with filename filter', () => {
267
- const a = uploadAttachment('ast-1', 'target.png', 'image/png', 'AAAA');
268
- const b = uploadAttachment('ast-1', 'other.png', 'image/png', 'BBBB');
268
+ const a = uploadAttachment('target.png', 'image/png', 'AAAA');
269
+ const b = uploadAttachment('other.png', 'image/png', 'BBBB');
269
270
 
270
271
  const conv = createConversation();
271
272
  const msg = addMessage(conv.id, 'user', 'Both');
@@ -294,7 +295,7 @@ describe('AssetSearchTool.execute', () => {
294
295
  });
295
296
 
296
297
  test('returns formatted results for matching assets', async () => {
297
- uploadAttachment('ast-1', 'selfie.png', 'image/png', 'AAAA');
298
+ uploadAttachment('selfie.png', 'image/png', 'AAAA');
298
299
  const result = await tool.execute({}, dummyContext);
299
300
  expect(result.isError).toBe(false);
300
301
  expect(result.content).toContain('selfie.png');
@@ -320,14 +321,14 @@ describe('AssetSearchTool.execute', () => {
320
321
  });
321
322
 
322
323
  test('includes attachment ID in output', async () => {
323
- const stored = uploadAttachment('ast-1', 'chart.png', 'image/png', 'AAAA');
324
+ const stored = uploadAttachment('chart.png', 'image/png', 'AAAA');
324
325
  const result = await tool.execute({}, dummyContext);
325
326
  expect(result.isError).toBe(false);
326
327
  expect(result.content).toContain(stored.id);
327
328
  });
328
329
 
329
330
  test('includes MIME type and kind in output', async () => {
330
- uploadAttachment('ast-1', 'chart.png', 'image/png', 'AAAA');
331
+ uploadAttachment('chart.png', 'image/png', 'AAAA');
331
332
  const result = await tool.execute({}, dummyContext);
332
333
  expect(result.isError).toBe(false);
333
334
  expect(result.content).toContain('image/png');
@@ -363,7 +364,7 @@ describe('AssetSearchTool visibility policy', () => {
363
364
 
364
365
  test('attachments from standard threads are visible from any context', async () => {
365
366
  const standardConv = createConversation({ title: 'standard-conv' });
366
- const attachment = uploadAttachment('ast-1', 'public.png', 'image/png', 'AAAA');
367
+ const attachment = uploadAttachment('public.png', 'image/png', 'AAAA');
367
368
  const msg = addMessage(standardConv.id, 'user', 'standard message');
368
369
  linkAttachmentToMessage(msg.id, attachment.id, 0);
369
370
 
@@ -382,7 +383,7 @@ describe('AssetSearchTool visibility policy', () => {
382
383
 
383
384
  test('attachments from private threads are visible within the same private thread', async () => {
384
385
  const privateConv = createConversation({ title: 'private-conv', threadType: 'private' });
385
- const attachment = uploadAttachment('ast-1', 'secret.png', 'image/png', 'AAAA');
386
+ const attachment = uploadAttachment('secret.png', 'image/png', 'AAAA');
386
387
  const msg = addMessage(privateConv.id, 'user', 'private message');
387
388
  linkAttachmentToMessage(msg.id, attachment.id, 0);
388
389
 
@@ -400,7 +401,7 @@ describe('AssetSearchTool visibility policy', () => {
400
401
 
401
402
  test('attachments from private threads are NOT visible from a different conversation', async () => {
402
403
  const privateConv = createConversation({ title: 'private-conv', threadType: 'private' });
403
- const attachment = uploadAttachment('ast-1', 'secret.png', 'image/png', 'AAAA');
404
+ const attachment = uploadAttachment('secret.png', 'image/png', 'AAAA');
404
405
  const msg = addMessage(privateConv.id, 'user', 'private message');
405
406
  linkAttachmentToMessage(msg.id, attachment.id, 0);
406
407
 
@@ -419,7 +420,7 @@ describe('AssetSearchTool visibility policy', () => {
419
420
 
420
421
  test('attachments from private threads are NOT visible from standard threads', async () => {
421
422
  const privateConv = createConversation({ title: 'private-conv', threadType: 'private' });
422
- const attachment = uploadAttachment('ast-1', 'secret.png', 'image/png', 'AAAA');
423
+ const attachment = uploadAttachment('secret.png', 'image/png', 'AAAA');
423
424
  const msg = addMessage(privateConv.id, 'user', 'private message');
424
425
  linkAttachmentToMessage(msg.id, attachment.id, 0);
425
426
 
@@ -439,7 +440,7 @@ describe('AssetSearchTool visibility policy', () => {
439
440
  test('attachment linked to both private and standard threads is visible everywhere', async () => {
440
441
  const privateConv = createConversation({ title: 'private-conv', threadType: 'private' });
441
442
  const standardConv = createConversation({ title: 'standard-conv' });
442
- const attachment = uploadAttachment('ast-1', 'shared.png', 'image/png', 'AAAA');
443
+ const attachment = uploadAttachment('shared.png', 'image/png', 'AAAA');
443
444
 
444
445
  const msg1 = addMessage(privateConv.id, 'user', 'private message');
445
446
  const msg2 = addMessage(standardConv.id, 'user', 'standard message');
@@ -460,7 +461,7 @@ describe('AssetSearchTool visibility policy', () => {
460
461
  });
461
462
 
462
463
  test('orphan attachments (no message linkage) remain visible', async () => {
463
- uploadAttachment('ast-1', 'orphan.png', 'image/png', 'AAAA');
464
+ uploadAttachment('orphan.png', 'image/png', 'AAAA');
464
465
 
465
466
  const conv = createConversation({ title: 'any-conv' });
466
467
  const context: ToolContext = {