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
@@ -31,6 +31,7 @@
31
31
  "GetSigningIdentityResponse",
32
32
  "HistoryRequest",
33
33
  "HomeBaseGetRequest",
34
+ "ImageGenModelSetRequest",
34
35
  "IntegrationConnectRequest",
35
36
  "IntegrationDisconnectRequest",
36
37
  "IntegrationListRequest",
@@ -79,6 +80,9 @@
79
80
  "SuggestionRequest",
80
81
  "TaskSubmit",
81
82
  "TrustRulesList",
83
+ "TwitterAuthStartRequest",
84
+ "TwitterAuthStatusRequest",
85
+ "TwitterIntegrationConfigRequest",
82
86
  "UiSurfaceAction",
83
87
  "UiSurfaceUndoRequest",
84
88
  "UndoRequest",
@@ -88,15 +92,20 @@
88
92
  "UserMessage",
89
93
  "VercelApiConfigRequest",
90
94
  "WatchObservation",
95
+ "WorkItemApprovePermissionsRequest",
96
+ "WorkItemCancelRequest",
91
97
  "WorkItemCompleteRequest",
92
- "WorkItemCreateRequest",
98
+ "WorkItemDeleteRequest",
93
99
  "WorkItemGetRequest",
100
+ "WorkItemOutputRequest",
101
+ "WorkItemPreflightRequest",
94
102
  "WorkItemRunTaskRequest",
95
103
  "WorkItemUpdateRequest",
96
104
  "WorkItemsListRequest"
97
105
  ],
98
106
  "serverMessageTypes": [
99
107
  "AcceptStarterBundleResponse",
108
+ "AgentHeartbeatAlert",
100
109
  "AppDataResponse",
101
110
  "AppFilesChanged",
102
111
  "AppPreviewResponse",
@@ -174,12 +183,17 @@
174
183
  "SubagentStatusChanged",
175
184
  "SuggestionResponse",
176
185
  "TaskRouted",
186
+ "TaskRunThreadCreated",
187
+ "TasksChanged",
177
188
  "ToolInputDelta",
178
189
  "ToolOutputChunk",
179
190
  "ToolResult",
180
191
  "ToolUseStart",
181
192
  "TraceEvent",
182
193
  "TrustRulesListResponse",
194
+ "TwitterAuthResult",
195
+ "TwitterAuthStatusResponse",
196
+ "TwitterIntegrationConfigResponse",
183
197
  "UiSurfaceComplete",
184
198
  "UiSurfaceDismiss",
185
199
  "UiSurfaceShow",
@@ -195,8 +209,12 @@
195
209
  "WatchStarted",
196
210
  "WatcherEscalation",
197
211
  "WatcherNotification",
198
- "WorkItemCreateResponse",
212
+ "WorkItemApprovePermissionsResponse",
213
+ "WorkItemCancelResponse",
214
+ "WorkItemDeleteResponse",
199
215
  "WorkItemGetResponse",
216
+ "WorkItemOutputResponse",
217
+ "WorkItemPreflightResponse",
200
218
  "WorkItemRunTaskResponse",
201
219
  "WorkItemStatusChanged",
202
220
  "WorkItemUpdateResponse",
@@ -234,6 +252,7 @@
234
252
  "get_signing_identity_response",
235
253
  "history_request",
236
254
  "home_base_get",
255
+ "image_gen_model_set",
237
256
  "integration_connect",
238
257
  "integration_disconnect",
239
258
  "integration_list",
@@ -282,6 +301,9 @@
282
301
  "suggestion_request",
283
302
  "task_submit",
284
303
  "trust_rules_list",
304
+ "twitter_auth_start",
305
+ "twitter_auth_status",
306
+ "twitter_integration_config",
285
307
  "ui_surface_action",
286
308
  "ui_surface_undo",
287
309
  "undo",
@@ -291,15 +313,20 @@
291
313
  "user_message",
292
314
  "vercel_api_config",
293
315
  "watch_observation",
316
+ "work_item_approve_permissions",
317
+ "work_item_cancel",
294
318
  "work_item_complete",
295
- "work_item_create",
319
+ "work_item_delete",
296
320
  "work_item_get",
321
+ "work_item_output",
322
+ "work_item_preflight",
297
323
  "work_item_run_task",
298
324
  "work_item_update",
299
325
  "work_items_list"
300
326
  ],
301
327
  "serverWireTypes": [
302
328
  "accept_starter_bundle_response",
329
+ "agent_heartbeat_alert",
303
330
  "app_data_response",
304
331
  "app_files_changed",
305
332
  "app_preview_response",
@@ -377,12 +404,17 @@
377
404
  "subagent_status_changed",
378
405
  "suggestion_response",
379
406
  "task_routed",
407
+ "task_run_thread_created",
408
+ "tasks_changed",
380
409
  "tool_input_delta",
381
410
  "tool_output_chunk",
382
411
  "tool_result",
383
412
  "tool_use_start",
384
413
  "trace_event",
385
414
  "trust_rules_list_response",
415
+ "twitter_auth_result",
416
+ "twitter_auth_status_response",
417
+ "twitter_integration_config_response",
386
418
  "ui_surface_complete",
387
419
  "ui_surface_dismiss",
388
420
  "ui_surface_undo_result",
@@ -397,8 +429,12 @@
397
429
  "watch_started",
398
430
  "watcher_escalation",
399
431
  "watcher_notification",
400
- "work_item_create_response",
432
+ "work_item_approve_permissions_response",
433
+ "work_item_cancel_response",
434
+ "work_item_delete_response",
401
435
  "work_item_get_response",
436
+ "work_item_output_response",
437
+ "work_item_preflight_response",
402
438
  "work_item_run_task_response",
403
439
  "work_item_status_changed",
404
440
  "work_item_update_response",
@@ -45,6 +45,8 @@ export interface UserMessageAttachment {
45
45
  extractedText?: string;
46
46
  /** Original file size in bytes. Present when data was omitted from history_response to reduce payload size. */
47
47
  sizeBytes?: number;
48
+ /** Base64-encoded JPEG thumbnail. Generated server-side for video attachments. */
49
+ thumbnailData?: string;
48
50
  }
49
51
 
50
52
  export interface ConfirmationResponse {
@@ -125,6 +127,11 @@ export interface ModelSetRequest {
125
127
  model: string;
126
128
  }
127
129
 
130
+ export interface ImageGenModelSetRequest {
131
+ type: 'image_gen_model_set';
132
+ model: string;
133
+ }
134
+
128
135
  export interface HistoryRequest {
129
136
  type: 'history_request';
130
137
  sessionId: string;
@@ -205,6 +212,7 @@ export interface RideShotgunStart {
205
212
  intervalSeconds: number;
206
213
  mode?: 'observe' | 'learn';
207
214
  targetDomain?: string;
215
+ autoNavigate?: boolean;
208
216
  }
209
217
 
210
218
  export interface RideShotgunStop {
@@ -423,16 +431,18 @@ export interface OpenBundleRequest {
423
431
  export interface SignBundlePayloadResponse {
424
432
  type: 'sign_bundle_payload_response';
425
433
  requestId: string;
426
- signature: string;
427
- keyId: string;
428
- publicKey: string;
434
+ signature?: string;
435
+ keyId?: string;
436
+ publicKey?: string;
437
+ error?: string;
429
438
  }
430
439
 
431
440
  export interface GetSigningIdentityResponse {
432
441
  type: 'get_signing_identity_response';
433
442
  requestId: string;
434
- keyId: string;
435
- publicKey: string;
443
+ keyId?: string;
444
+ publicKey?: string;
445
+ error?: string;
436
446
  }
437
447
 
438
448
  export interface GalleryListRequest {
@@ -473,6 +483,48 @@ export interface VercelApiConfigResponse {
473
483
  error?: string;
474
484
  }
475
485
 
486
+ export interface TwitterIntegrationConfigRequest {
487
+ type: 'twitter_integration_config';
488
+ action: 'get' | 'set_mode' | 'set_local_client' | 'clear_local_client' | 'disconnect';
489
+ mode?: 'local_byo' | 'managed';
490
+ clientId?: string;
491
+ clientSecret?: string;
492
+ }
493
+
494
+ export interface TwitterIntegrationConfigResponse {
495
+ type: 'twitter_integration_config_response';
496
+ success: boolean;
497
+ mode?: 'local_byo' | 'managed';
498
+ managedAvailable: boolean;
499
+ localClientConfigured: boolean;
500
+ connected: boolean;
501
+ accountInfo?: string;
502
+ error?: string;
503
+ }
504
+
505
+ export interface TwitterAuthStartRequest {
506
+ type: 'twitter_auth_start';
507
+ }
508
+
509
+ export interface TwitterAuthStatusRequest {
510
+ type: 'twitter_auth_status';
511
+ }
512
+
513
+ export interface TwitterAuthResult {
514
+ type: 'twitter_auth_result';
515
+ success: boolean;
516
+ accountInfo?: string;
517
+ error?: string;
518
+ }
519
+
520
+ export interface TwitterAuthStatusResponse {
521
+ type: 'twitter_auth_status_response';
522
+ connected: boolean;
523
+ accountInfo?: string;
524
+ mode?: 'local_byo' | 'managed';
525
+ error?: string;
526
+ }
527
+
476
528
  export interface LinkOpenRequest {
477
529
  type: 'link_open_request';
478
530
  url: string;
@@ -769,15 +821,6 @@ export interface WorkItemGetRequest {
769
821
  id: string;
770
822
  }
771
823
 
772
- export interface WorkItemCreateRequest {
773
- type: 'work_item_create';
774
- taskId: string;
775
- title?: string; // defaults to task title
776
- notes?: string;
777
- priorityTier?: number;
778
- sortIndex?: number;
779
- }
780
-
781
824
  export interface WorkItemUpdateRequest {
782
825
  type: 'work_item_update';
783
826
  id: string;
@@ -793,11 +836,37 @@ export interface WorkItemCompleteRequest {
793
836
  id: string;
794
837
  }
795
838
 
839
+ export interface WorkItemDeleteRequest {
840
+ type: 'work_item_delete';
841
+ id: string;
842
+ }
843
+
796
844
  export interface WorkItemRunTaskRequest {
797
845
  type: 'work_item_run_task';
798
846
  id: string;
799
847
  }
800
848
 
849
+ export interface WorkItemOutputRequest {
850
+ type: 'work_item_output';
851
+ id: string;
852
+ }
853
+
854
+ export interface WorkItemPreflightRequest {
855
+ type: 'work_item_preflight';
856
+ id: string; // work item ID
857
+ }
858
+
859
+ export interface WorkItemApprovePermissionsRequest {
860
+ type: 'work_item_approve_permissions';
861
+ id: string;
862
+ approvedTools: string[]; // tools the user approved
863
+ }
864
+
865
+ export interface WorkItemCancelRequest {
866
+ type: 'work_item_cancel';
867
+ id: string;
868
+ }
869
+
801
870
  export type ClientMessage =
802
871
  | AuthMessage
803
872
  | UserMessage
@@ -811,6 +880,7 @@ export type ClientMessage =
811
880
  | DeleteQueuedMessage
812
881
  | ModelGetRequest
813
882
  | ModelSetRequest
883
+ | ImageGenModelSetRequest
814
884
  | HistoryRequest
815
885
  | UndoRequest
816
886
  | RegenerateRequest
@@ -864,6 +934,9 @@ export type ClientMessage =
864
934
  | ShareToSlackRequest
865
935
  | SlackWebhookConfigRequest
866
936
  | VercelApiConfigRequest
937
+ | TwitterIntegrationConfigRequest
938
+ | TwitterAuthStartRequest
939
+ | TwitterAuthStatusRequest
867
940
  | SessionsClearRequest
868
941
  | GalleryListRequest
869
942
  | GalleryInstallRequest
@@ -886,10 +959,14 @@ export type ClientMessage =
886
959
  | BrowserInteractiveMode
887
960
  | WorkItemsListRequest
888
961
  | WorkItemGetRequest
889
- | WorkItemCreateRequest
890
962
  | WorkItemUpdateRequest
891
963
  | WorkItemCompleteRequest
964
+ | WorkItemDeleteRequest
892
965
  | WorkItemRunTaskRequest
966
+ | WorkItemOutputRequest
967
+ | WorkItemPreflightRequest
968
+ | WorkItemApprovePermissionsRequest
969
+ | WorkItemCancelRequest
893
970
  | SubagentAbortRequest
894
971
  | SubagentStatusRequest
895
972
  | SubagentMessageRequest;
@@ -1070,6 +1147,7 @@ export interface PongMessage {
1070
1147
  export interface DaemonStatusMessage {
1071
1148
  type: 'daemon_status';
1072
1149
  httpPort?: number;
1150
+ version?: string;
1073
1151
  }
1074
1152
 
1075
1153
  export interface GenerationCancelled {
@@ -1128,6 +1206,13 @@ export interface HistoryResponse {
1128
1206
  contentOrder?: string[];
1129
1207
  /** UI surfaces (widgets) embedded in the message. */
1130
1208
  surfaces?: HistoryResponseSurface[];
1209
+ /** Present when this message is a subagent lifecycle notification (completed/failed/aborted). */
1210
+ subagentNotification?: {
1211
+ subagentId: string;
1212
+ label: string;
1213
+ status: 'completed' | 'failed' | 'aborted';
1214
+ error?: string;
1215
+ };
1131
1216
  }>;
1132
1217
  }
1133
1218
 
@@ -1404,6 +1489,8 @@ export interface SchedulesListResponse {
1404
1489
  id: string;
1405
1490
  name: string;
1406
1491
  enabled: boolean;
1492
+ syntax: string;
1493
+ expression: string;
1407
1494
  cronExpression: string;
1408
1495
  timezone: string | null;
1409
1496
  message: string;
@@ -1619,6 +1706,12 @@ export interface WatcherEscalation {
1619
1706
  body: string;
1620
1707
  }
1621
1708
 
1709
+ export interface AgentHeartbeatAlert {
1710
+ type: 'agent_heartbeat_alert';
1711
+ title: string;
1712
+ body: string;
1713
+ }
1714
+
1622
1715
  export interface WatchStarted {
1623
1716
  type: 'watch_started';
1624
1717
  sessionId: string;
@@ -1874,26 +1967,6 @@ export interface WorkItemGetResponse {
1874
1967
  } | null;
1875
1968
  }
1876
1969
 
1877
- export interface WorkItemCreateResponse {
1878
- type: 'work_item_create_response';
1879
- item: {
1880
- id: string;
1881
- taskId: string;
1882
- title: string;
1883
- notes: string | null;
1884
- status: string;
1885
- priorityTier: number;
1886
- sortIndex: number | null;
1887
- lastRunId: string | null;
1888
- lastRunConversationId: string | null;
1889
- lastRunStatus: string | null;
1890
- sourceType: string | null;
1891
- sourceId: string | null;
1892
- createdAt: number;
1893
- updatedAt: number;
1894
- };
1895
- }
1896
-
1897
1970
  export interface WorkItemUpdateResponse {
1898
1971
  type: 'work_item_update_response';
1899
1972
  item: {
@@ -1914,12 +1987,65 @@ export interface WorkItemUpdateResponse {
1914
1987
  } | null;
1915
1988
  }
1916
1989
 
1990
+ export interface WorkItemDeleteResponse {
1991
+ type: 'work_item_delete_response';
1992
+ id: string;
1993
+ success: boolean;
1994
+ }
1995
+
1996
+ export type WorkItemRunTaskErrorCode = 'not_found' | 'already_running' | 'invalid_status' | 'no_task';
1997
+
1917
1998
  export interface WorkItemRunTaskResponse {
1918
1999
  type: 'work_item_run_task_response';
1919
2000
  id: string;
1920
2001
  lastRunId: string;
1921
2002
  success: boolean;
1922
2003
  error?: string;
2004
+ /** Structured error code so the client can deterministically re-enable buttons or show contextual UI. */
2005
+ errorCode?: WorkItemRunTaskErrorCode;
2006
+ }
2007
+
2008
+ export interface WorkItemOutputResponse {
2009
+ type: 'work_item_output_response';
2010
+ id: string;
2011
+ success: boolean;
2012
+ error?: string;
2013
+ output?: {
2014
+ title: string;
2015
+ status: string;
2016
+ runId: string | null;
2017
+ conversationId: string | null;
2018
+ completedAt: number | null;
2019
+ summary: string;
2020
+ highlights: string[];
2021
+ };
2022
+ }
2023
+
2024
+ export interface WorkItemPreflightResponse {
2025
+ type: 'work_item_preflight_response';
2026
+ id: string;
2027
+ success: boolean;
2028
+ error?: string;
2029
+ permissions?: {
2030
+ tool: string;
2031
+ description: string;
2032
+ riskLevel: 'low' | 'medium' | 'high';
2033
+ currentDecision: 'allow' | 'deny' | 'prompt';
2034
+ }[];
2035
+ }
2036
+
2037
+ export interface WorkItemApprovePermissionsResponse {
2038
+ type: 'work_item_approve_permissions_response';
2039
+ id: string;
2040
+ success: boolean;
2041
+ error?: string;
2042
+ }
2043
+
2044
+ export interface WorkItemCancelResponse {
2045
+ type: 'work_item_cancel_response';
2046
+ id: string;
2047
+ success: boolean;
2048
+ error?: string;
1923
2049
  }
1924
2050
 
1925
2051
  /** Server push — tells the client to open/focus the tasks window. */
@@ -1927,6 +2053,11 @@ export interface OpenTasksWindow {
1927
2053
  type: 'open_tasks_window';
1928
2054
  }
1929
2055
 
2056
+ /** Server push — lightweight invalidation signal: the task queue has been mutated, refetch your list. */
2057
+ export interface TasksChanged {
2058
+ type: 'tasks_changed';
2059
+ }
2060
+
1930
2061
  /** Server push — broadcast when a work item status changes (e.g. running -> awaiting_review). */
1931
2062
  export interface WorkItemStatusChanged {
1932
2063
  type: 'work_item_status_changed';
@@ -1942,6 +2073,14 @@ export interface WorkItemStatusChanged {
1942
2073
  };
1943
2074
  }
1944
2075
 
2076
+ /** Server push — broadcast when a task run creates a conversation, so the client can show it as a chat thread. */
2077
+ export interface TaskRunThreadCreated {
2078
+ type: 'task_run_thread_created';
2079
+ conversationId: string;
2080
+ workItemId: string;
2081
+ title: string;
2082
+ }
2083
+
1945
2084
  export type ServerMessage =
1946
2085
  | AuthResult
1947
2086
  | UserMessageEcho
@@ -1996,6 +2135,7 @@ export type ServerMessage =
1996
2135
  | ScheduleComplete
1997
2136
  | WatcherNotification
1998
2137
  | WatcherEscalation
2138
+ | AgentHeartbeatAlert
1999
2139
  | WatchStarted
2000
2140
  | WatchCompleteRequest
2001
2141
  | TrustRulesListResponse
@@ -2019,6 +2159,9 @@ export type ServerMessage =
2019
2159
  | ShareToSlackResponse
2020
2160
  | SlackWebhookConfigResponse
2021
2161
  | VercelApiConfigResponse
2162
+ | TwitterIntegrationConfigResponse
2163
+ | TwitterAuthResult
2164
+ | TwitterAuthStatusResponse
2022
2165
  | OpenUrl
2023
2166
  | AppUpdatePreviewResponse
2024
2167
  | AppPreviewResponse
@@ -2040,10 +2183,16 @@ export type ServerMessage =
2040
2183
  | BrowserHandoffRequest
2041
2184
  | WorkItemsListResponse
2042
2185
  | WorkItemGetResponse
2043
- | WorkItemCreateResponse
2044
2186
  | WorkItemUpdateResponse
2187
+ | WorkItemDeleteResponse
2045
2188
  | WorkItemRunTaskResponse
2189
+ | WorkItemOutputResponse
2190
+ | WorkItemPreflightResponse
2191
+ | WorkItemApprovePermissionsResponse
2192
+ | WorkItemCancelResponse
2046
2193
  | WorkItemStatusChanged
2194
+ | TaskRunThreadCreated
2195
+ | TasksChanged
2047
2196
  | OpenTasksWindow
2048
2197
  | SubagentSpawned
2049
2198
  | SubagentStatusChanged
@@ -2085,7 +2234,6 @@ export interface SubagentStatusRequest {
2085
2234
  type: 'subagent_status';
2086
2235
  /** If omitted, returns all subagents for the session. */
2087
2236
  subagentId?: string;
2088
- sessionId: string;
2089
2237
  }
2090
2238
 
2091
2239
  export interface SubagentMessageRequest {
@@ -2,6 +2,9 @@
2
2
  export * from './ipc-contract.js';
3
3
 
4
4
  import type { ClientMessage, ServerMessage } from './ipc-contract.js';
5
+ import { getLogger } from '../util/logger.js';
6
+
7
+ const log = getLogger('ipc-protocol');
5
8
 
6
9
  // === Serialization ===
7
10
 
@@ -43,8 +46,10 @@ export function createMessageParser(options?: { maxLineSize?: number }) {
43
46
  entry.rawByteLength = Buffer.byteLength(trimmed, 'utf8');
44
47
  }
45
48
  results.push(entry);
46
- } catch {
47
- // Skip malformed messages
49
+ } catch (err) {
50
+ // Log only the error name, not the message — JSON.parse errors embed
51
+ // fragments of the input which could contain sensitive data.
52
+ log.warn({ lineLength: trimmed.length, errorType: err instanceof Error ? err.name : 'unknown' }, 'Skipping malformed IPC message');
48
53
  }
49
54
  }
50
55
  }
@@ -22,6 +22,7 @@ import { initializeTools } from '../tools/registry.js';
22
22
  import { loadConfig } from '../config/loader.js';
23
23
  import { ensurePromptFiles } from '../config/system-prompt.js';
24
24
  import { DaemonServer } from './server.js';
25
+ import { listWorkItems, updateWorkItem } from '../work-items/work-item-store.js';
25
26
  import { getLogger, initLogger } from '../util/logger.js';
26
27
  import { DaemonError } from '../util/errors.js';
27
28
  import { initSentry } from '../instrument.js';
@@ -43,6 +44,10 @@ import { RuntimeHttpServer } from '../runtime/http-server.js';
43
44
  import { getHookManager } from '../hooks/manager.js';
44
45
  import { installTemplates } from '../hooks/templates.js';
45
46
  import { HeartbeatService } from '../workspace/heartbeat-service.js';
47
+ import { AgentHeartbeatService } from '../agent-heartbeat/agent-heartbeat-service.js';
48
+ import { getEnrichmentService } from '../workspace/commit-message-enrichment-service.js';
49
+ import { reconcileCallsOnStartup } from '../calls/call-recovery.js';
50
+ import { TwilioConversationRelayProvider } from '../calls/twilio-provider.js';
46
51
 
47
52
  const log = getLogger('lifecycle');
48
53
 
@@ -279,6 +284,26 @@ export async function runDaemon(): Promise<void> {
279
284
  initializeDb();
280
285
  log.info('Daemon startup: DB initialized');
281
286
 
287
+ // Recover orphaned work items that were left in 'running' state when the
288
+ // daemon previously crashed or was killed mid-task.
289
+ const orphanedRunning = listWorkItems({ status: 'running' });
290
+ if (orphanedRunning.length > 0) {
291
+ for (const item of orphanedRunning) {
292
+ updateWorkItem(item.id, { status: 'failed', lastRunStatus: 'interrupted' });
293
+ log.info({ workItemId: item.id, title: item.title }, 'Recovered orphaned running work item → failed (interrupted)');
294
+ }
295
+ log.info({ count: orphanedRunning.length }, 'Recovered orphaned running work items');
296
+ }
297
+
298
+ // Reconcile in-flight calls that were left in non-terminal states
299
+ // after a daemon crash or restart.
300
+ try {
301
+ const twilioProvider = new TwilioConversationRelayProvider();
302
+ await reconcileCallsOnStartup(twilioProvider, log);
303
+ } catch (err) {
304
+ log.warn({ err }, 'Call recovery failed — continuing startup');
305
+ }
306
+
282
307
  log.info('Daemon startup: loading config');
283
308
  const config = loadConfig();
284
309
 
@@ -328,7 +353,7 @@ export async function runDaemon(): Promise<void> {
328
353
 
329
354
  const scheduler = startScheduler(
330
355
  async (conversationId, message) => {
331
- await server.processMessage('schedule', conversationId, message);
356
+ await server.processMessage(conversationId, message);
332
357
  },
333
358
  (reminder) => {
334
359
  server.broadcast({
@@ -382,10 +407,10 @@ export async function runDaemon(): Promise<void> {
382
407
  port,
383
408
  hostname,
384
409
  bearerToken,
385
- processMessage: (assistantId, conversationId, content, attachmentIds, options, sourceChannel) =>
386
- server.processMessage(assistantId, conversationId, content, attachmentIds, options, sourceChannel),
387
- persistAndProcessMessage: (assistantId, conversationId, content, attachmentIds, options, sourceChannel) =>
388
- server.persistAndProcessMessage(assistantId, conversationId, content, attachmentIds, options, sourceChannel),
410
+ processMessage: (conversationId, content, attachmentIds, options, sourceChannel) =>
411
+ server.processMessage(conversationId, content, attachmentIds, options, sourceChannel),
412
+ persistAndProcessMessage: (conversationId, content, attachmentIds, options, sourceChannel) =>
413
+ server.persistAndProcessMessage(conversationId, content, attachmentIds, options, sourceChannel),
389
414
  runOrchestrator: server.createRunOrchestrator(),
390
415
  interfacesDir: getInterfacesDir(),
391
416
  });
@@ -431,6 +456,14 @@ export async function runDaemon(): Promise<void> {
431
456
  const heartbeat = new HeartbeatService();
432
457
  heartbeat.start();
433
458
 
459
+ // Start model-driven heartbeat service (opt-in via config).
460
+ const agentHeartbeat = new AgentHeartbeatService({
461
+ processMessage: (conversationId, content) =>
462
+ server.processMessage(conversationId, content),
463
+ alerter: (alert) => server.broadcast(alert),
464
+ });
465
+ agentHeartbeat.start();
466
+
434
467
  // Graceful shutdown
435
468
  let shuttingDown = false;
436
469
  const shutdown = async () => {
@@ -451,6 +484,7 @@ export async function runDaemon(): Promise<void> {
451
484
  forceTimer.unref();
452
485
 
453
486
  await heartbeat.stop();
487
+ await agentHeartbeat.stop();
454
488
 
455
489
  try {
456
490
  await hookManager.trigger('daemon-stop', { pid: process.pid });
@@ -477,6 +511,15 @@ export async function runDaemon(): Promise<void> {
477
511
  } catch (err) {
478
512
  log.warn({ err, phase: 'post_stop' }, 'Post-stop workspace commit failed');
479
513
  }
514
+
515
+ // Flush in-flight enrichment jobs so shutdown commit notes are not dropped.
516
+ // The enrichment service's shutdown() drains active jobs and discards pending ones.
517
+ try {
518
+ await getEnrichmentService().shutdown();
519
+ } catch (err) {
520
+ log.warn({ err }, 'Enrichment service shutdown failed (non-fatal)');
521
+ }
522
+
480
523
  if (runtimeHttp) await runtimeHttp.stop();
481
524
  await browserManager.closeAllPages();
482
525
  scheduler.stop();
@@ -1,14 +1,20 @@
1
1
  #!/usr/bin/env bun
2
2
  import * as Sentry from '@sentry/node';
3
3
  import { runDaemon } from './lifecycle.js';
4
+ import { getLogger } from '../util/logger.js';
4
5
 
5
- // Use console.error instead of the structured logger here because
6
- // startDaemon() captures the child process's stderr to surface error
7
- // details to the parent process. The structured logger writes to a file
8
- // by default, so these messages would be lost from stderr.
9
6
  runDaemon().catch(async (err) => {
10
7
  Sentry.captureException(err);
11
8
  await Sentry.flush(2000);
9
+ // Try structured log first; fall back to console.error because
10
+ // startDaemon() captures the child process's stderr to surface error
11
+ // details to the parent process.
12
+ try {
13
+ const log = getLogger('daemon-main');
14
+ log.fatal({ err }, 'Failed to start daemon');
15
+ } catch {
16
+ // Logger may not be initialized yet
17
+ }
12
18
  console.error('Failed to start daemon:', err);
13
19
  console.error('Troubleshooting: check if another daemon is already running, verify ~/.vellum/ permissions, and review logs at ~/.vellum/workspace/data/logs/');
14
20
  process.exit(1);