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,6 +1,4 @@
1
- import { RiskLevel } from '../../permissions/types.js';
2
- import type { Tool, ToolContext, ToolExecutionResult } from '../types.js';
3
- import type { ToolDefinition } from '../../providers/types.js';
1
+ import type { ToolContext, ToolExecutionResult } from '../types.js';
4
2
  import { listFollowUps, getOverdueFollowUps } from '../../followups/followup-store.js';
5
3
  import type { FollowUp, FollowUpStatus } from '../../followups/types.js';
6
4
 
@@ -18,83 +16,45 @@ function formatFollowUpSummary(f: FollowUp): string {
18
16
  return parts.join('\n');
19
17
  }
20
18
 
21
- const definition: ToolDefinition = {
22
- name: 'followup_list',
23
- description: 'List follow-ups with optional filters by status, channel, or contact. Can also show only overdue follow-ups.',
24
- input_schema: {
25
- type: 'object',
26
- properties: {
27
- status: {
28
- type: 'string',
29
- enum: [...VALID_STATUSES],
30
- description: 'Filter by status (pending, resolved, overdue, nudged)',
31
- },
32
- channel: {
33
- type: 'string',
34
- description: 'Filter by communication channel (e.g. email, slack)',
35
- },
36
- contact_id: {
37
- type: 'string',
38
- description: 'Filter by contact ID',
39
- },
40
- overdue_only: {
41
- type: 'boolean',
42
- description: 'When true, return only pending follow-ups past their expected response deadline',
43
- },
44
- },
45
- required: [],
46
- },
47
- };
48
-
49
- class FollowUpListTool implements Tool {
50
- name = 'followup_list';
51
- description = definition.description;
52
- category = 'followups';
53
- defaultRiskLevel = RiskLevel.Low;
54
-
55
- getDefinition(): ToolDefinition {
56
- return definition;
19
+ export async function executeFollowupList(
20
+ input: Record<string, unknown>,
21
+ _context: ToolContext,
22
+ ): Promise<ToolExecutionResult> {
23
+ const status = input.status as FollowUpStatus | undefined;
24
+ const channel = input.channel as string | undefined;
25
+ const contactId = input.contact_id as string | undefined;
26
+ const overdueOnly = input.overdue_only as boolean | undefined;
27
+
28
+ if (status && !VALID_STATUSES.includes(status as typeof VALID_STATUSES[number])) {
29
+ return {
30
+ content: `Error: Invalid status "${status}". Must be one of: ${VALID_STATUSES.join(', ')}`,
31
+ isError: true,
32
+ };
57
33
  }
58
34
 
59
- async execute(input: Record<string, unknown>, _context: ToolContext): Promise<ToolExecutionResult> {
60
- const status = input.status as FollowUpStatus | undefined;
61
- const channel = input.channel as string | undefined;
62
- const contactId = input.contact_id as string | undefined;
63
- const overdueOnly = input.overdue_only as boolean | undefined;
35
+ try {
36
+ let results: FollowUp[];
64
37
 
65
- if (status && !VALID_STATUSES.includes(status as typeof VALID_STATUSES[number])) {
66
- return {
67
- content: `Error: Invalid status "${status}". Must be one of: ${VALID_STATUSES.join(', ')}`,
68
- isError: true,
69
- };
38
+ if (overdueOnly || status === 'overdue') {
39
+ results = getOverdueFollowUps();
40
+ if (channel) results = results.filter((f) => f.channel === channel);
41
+ if (contactId) results = results.filter((f) => f.contactId === contactId);
42
+ } else {
43
+ results = listFollowUps({ status, channel, contactId });
70
44
  }
71
45
 
72
- try {
73
- let results: FollowUp[];
74
-
75
- if (overdueOnly || status === 'overdue') {
76
- results = getOverdueFollowUps();
77
- if (channel) results = results.filter((f) => f.channel === channel);
78
- if (contactId) results = results.filter((f) => f.contactId === contactId);
79
- } else {
80
- results = listFollowUps({ status, channel, contactId });
81
- }
82
-
83
- if (results.length === 0) {
84
- return { content: 'No follow-ups found matching the criteria.', isError: false };
85
- }
86
-
87
- const lines = [`Found ${results.length} follow-up(s):\n`];
88
- for (const followUp of results) {
89
- lines.push(formatFollowUpSummary(followUp));
90
- }
46
+ if (results.length === 0) {
47
+ return { content: 'No follow-ups found matching the criteria.', isError: false };
48
+ }
91
49
 
92
- return { content: lines.join('\n'), isError: false };
93
- } catch (err) {
94
- const msg = err instanceof Error ? err.message : String(err);
95
- return { content: `Error: ${msg}`, isError: true };
50
+ const lines = [`Found ${results.length} follow-up(s):\n`];
51
+ for (const followUp of results) {
52
+ lines.push(formatFollowUpSummary(followUp));
96
53
  }
54
+
55
+ return { content: lines.join('\n'), isError: false };
56
+ } catch (err) {
57
+ const msg = err instanceof Error ? err.message : String(err);
58
+ return { content: `Error: ${msg}`, isError: true };
97
59
  }
98
60
  }
99
-
100
- export const followupListTool = new FollowUpListTool();
@@ -1,6 +1,4 @@
1
- import { RiskLevel } from '../../permissions/types.js';
2
- import type { Tool, ToolContext, ToolExecutionResult } from '../types.js';
3
- import type { ToolDefinition } from '../../providers/types.js';
1
+ import type { ToolContext, ToolExecutionResult } from '../types.js';
4
2
  import { resolveFollowUp, resolveByThread } from '../../followups/followup-store.js';
5
3
  import type { FollowUp } from '../../followups/types.js';
6
4
 
@@ -15,77 +13,44 @@ function formatFollowUp(f: FollowUp): string {
15
13
  return lines.join('\n');
16
14
  }
17
15
 
18
- const definition: ToolDefinition = {
19
- name: 'followup_resolve',
20
- description: 'Manually resolve a follow-up by ID, or auto-resolve by channel + thread ID when a response is received.',
21
- input_schema: {
22
- type: 'object',
23
- properties: {
24
- id: {
25
- type: 'string',
26
- description: 'Follow-up ID to resolve directly',
27
- },
28
- channel: {
29
- type: 'string',
30
- description: 'Channel to match (used with thread_id for auto-resolution)',
31
- },
32
- thread_id: {
33
- type: 'string',
34
- description: 'Thread ID to match (used with channel for auto-resolution)',
35
- },
36
- },
37
- required: [],
38
- },
39
- };
40
-
41
- class FollowUpResolveTool implements Tool {
42
- name = 'followup_resolve';
43
- description = definition.description;
44
- category = 'followups';
45
- defaultRiskLevel = RiskLevel.Low;
46
-
47
- getDefinition(): ToolDefinition {
48
- return definition;
16
+ export async function executeFollowupResolve(
17
+ input: Record<string, unknown>,
18
+ _context: ToolContext,
19
+ ): Promise<ToolExecutionResult> {
20
+ const id = input.id as string | undefined;
21
+ const channel = input.channel as string | undefined;
22
+ const threadId = input.thread_id as string | undefined;
23
+
24
+ if (!id && !(channel && threadId)) {
25
+ return {
26
+ content: 'Error: Either id or both channel and thread_id are required',
27
+ isError: true,
28
+ };
49
29
  }
50
30
 
51
- async execute(input: Record<string, unknown>, _context: ToolContext): Promise<ToolExecutionResult> {
52
- const id = input.id as string | undefined;
53
- const channel = input.channel as string | undefined;
54
- const threadId = input.thread_id as string | undefined;
55
-
56
- if (!id && !(channel && threadId)) {
31
+ try {
32
+ if (id) {
33
+ const followUp = resolveFollowUp(id);
57
34
  return {
58
- content: 'Error: Either id or both channel and thread_id are required',
59
- isError: true,
35
+ content: `Resolved follow-up:\n${formatFollowUp(followUp)}`,
36
+ isError: false,
60
37
  };
61
- }
62
-
63
- try {
64
- if (id) {
65
- const followUp = resolveFollowUp(id);
38
+ } else {
39
+ const resolved = resolveByThread(channel!, threadId!);
40
+ if (resolved.length === 0) {
66
41
  return {
67
- content: `Resolved follow-up:\n${formatFollowUp(followUp)}`,
68
- isError: false,
69
- };
70
- } else {
71
- const resolved = resolveByThread(channel!, threadId!);
72
- if (resolved.length === 0) {
73
- return {
74
- content: `No pending follow-up found for channel="${channel}" thread="${threadId}"`,
75
- isError: false,
76
- };
77
- }
78
- const summaries = resolved.map(formatFollowUp).join('\n\n');
79
- return {
80
- content: `Resolved ${resolved.length} follow-up(s):\n${summaries}`,
42
+ content: `No pending follow-up found for channel="${channel}" thread="${threadId}"`,
81
43
  isError: false,
82
44
  };
83
45
  }
84
- } catch (err) {
85
- const msg = err instanceof Error ? err.message : String(err);
86
- return { content: `Error: ${msg}`, isError: true };
46
+ const summaries = resolved.map(formatFollowUp).join('\n\n');
47
+ return {
48
+ content: `Resolved ${resolved.length} follow-up(s):\n${summaries}`,
49
+ isError: false,
50
+ };
87
51
  }
52
+ } catch (err) {
53
+ const msg = err instanceof Error ? err.message : String(err);
54
+ return { content: `Error: ${msg}`, isError: true };
88
55
  }
89
56
  }
90
-
91
- export const followupResolveTool = new FollowUpResolveTool();
@@ -3,6 +3,7 @@ import { RiskLevel } from '../../permissions/types.js';
3
3
  import type { Tool, ToolContext, ToolExecutionResult } from '../types.js';
4
4
  import type { ToolDefinition } from '../../providers/types.js';
5
5
  import { getLogger } from '../../util/logger.js';
6
+ import { truncate } from '../../util/truncate.js';
6
7
 
7
8
  const log = getLogger('cli-discover');
8
9
 
@@ -141,7 +142,7 @@ class CliDiscoverTool implements Tool {
141
142
  result.authenticated = authOutput !== null && authOutput.length > 0;
142
143
  if (authOutput) {
143
144
  // Keep auth info brief — first line, max 200 chars
144
- result.authInfo = authOutput.split('\n')[0].slice(0, 200);
145
+ result.authInfo = truncate(authOutput.split('\n')[0], 200, '');
145
146
  }
146
147
  }
147
148
 
@@ -40,6 +40,16 @@ function buildSanitizedEnv(): Record<string, string> {
40
40
  env[key] = process.env[key]!;
41
41
  }
42
42
  }
43
+ // Ensure ~/.local/bin and ~/.bun/bin are in PATH so `vellum` and `bun` are
44
+ // always reachable, even when the daemon is launched from a macOS app
45
+ // bundle that inherits a minimal PATH.
46
+ const home = homedir();
47
+ const extraDirs = [`${home}/.local/bin`, `${home}/.bun/bin`];
48
+ const currentPath = env.PATH ?? '';
49
+ const missing = extraDirs.filter(d => !currentPath.split(':').includes(d));
50
+ if (missing.length > 0) {
51
+ env.PATH = [...missing, currentPath].filter(Boolean).join(':');
52
+ }
43
53
  return env;
44
54
  }
45
55
 
@@ -2,6 +2,7 @@ import { and, eq } from 'drizzle-orm';
2
2
  import { v4 as uuid } from 'uuid';
3
3
  import type { AssistantConfig } from '../../config/types.js';
4
4
  import { getLogger } from '../../util/logger.js';
5
+ import { truncate } from '../../util/truncate.js';
5
6
  import { getDb } from '../../memory/db.js';
6
7
  import { computeMemoryFingerprint } from '../../memory/fingerprint.js';
7
8
  import { memoryItems } from '../../memory/schema.js';
@@ -84,14 +85,14 @@ export async function handleMemorySave(
84
85
  }
85
86
 
86
87
  const subject = typeof args.subject === 'string' && args.subject.trim().length > 0
87
- ? args.subject.trim().slice(0, 80)
88
+ ? truncate(args.subject.trim(), 80, '')
88
89
  : inferSubjectFromStatement(statement.trim());
89
90
 
90
91
  try {
91
92
  const db = getDb();
92
93
  const id = uuid();
93
94
  const now = Date.now();
94
- const trimmedStatement = statement.trim().slice(0, 500);
95
+ const trimmedStatement = truncate(statement.trim(), 500, '');
95
96
 
96
97
  const fingerprint = computeMemoryFingerprint(scopeId, kind, subject, trimmedStatement);
97
98
 
@@ -185,7 +186,7 @@ export async function handleMemoryUpdate(
185
186
  }
186
187
 
187
188
  const now = Date.now();
188
- const trimmedStatement = statement.trim().slice(0, 500);
189
+ const trimmedStatement = truncate(statement.trim(), 500, '');
189
190
 
190
191
  const fingerprint = computeMemoryFingerprint(scopeId, existing.kind, existing.subject, trimmedStatement);
191
192
 
@@ -232,7 +233,7 @@ export async function handleMemoryUpdate(
232
233
  function inferSubjectFromStatement(statement: string): string {
233
234
  // Take first few words as a subject label
234
235
  const words = statement.split(/\s+/).slice(0, 6).join(' ');
235
- return words.slice(0, 80);
236
+ return truncate(words, 80, '');
236
237
  }
237
238
 
238
239
  /**