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
@@ -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 {
@@ -210,6 +212,7 @@ export interface RideShotgunStart {
210
212
  intervalSeconds: number;
211
213
  mode?: 'observe' | 'learn';
212
214
  targetDomain?: string;
215
+ autoNavigate?: boolean;
213
216
  }
214
217
 
215
218
  export interface RideShotgunStop {
@@ -428,16 +431,18 @@ export interface OpenBundleRequest {
428
431
  export interface SignBundlePayloadResponse {
429
432
  type: 'sign_bundle_payload_response';
430
433
  requestId: string;
431
- signature: string;
432
- keyId: string;
433
- publicKey: string;
434
+ signature?: string;
435
+ keyId?: string;
436
+ publicKey?: string;
437
+ error?: string;
434
438
  }
435
439
 
436
440
  export interface GetSigningIdentityResponse {
437
441
  type: 'get_signing_identity_response';
438
442
  requestId: string;
439
- keyId: string;
440
- publicKey: string;
443
+ keyId?: string;
444
+ publicKey?: string;
445
+ error?: string;
441
446
  }
442
447
 
443
448
  export interface GalleryListRequest {
@@ -478,6 +483,48 @@ export interface VercelApiConfigResponse {
478
483
  error?: string;
479
484
  }
480
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
+
481
528
  export interface LinkOpenRequest {
482
529
  type: 'link_open_request';
483
530
  url: string;
@@ -774,15 +821,6 @@ export interface WorkItemGetRequest {
774
821
  id: string;
775
822
  }
776
823
 
777
- export interface WorkItemCreateRequest {
778
- type: 'work_item_create';
779
- taskId: string;
780
- title?: string; // defaults to task title
781
- notes?: string;
782
- priorityTier?: number;
783
- sortIndex?: number;
784
- }
785
-
786
824
  export interface WorkItemUpdateRequest {
787
825
  type: 'work_item_update';
788
826
  id: string;
@@ -813,6 +851,22 @@ export interface WorkItemOutputRequest {
813
851
  id: string;
814
852
  }
815
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
+
816
870
  export type ClientMessage =
817
871
  | AuthMessage
818
872
  | UserMessage
@@ -880,6 +934,9 @@ export type ClientMessage =
880
934
  | ShareToSlackRequest
881
935
  | SlackWebhookConfigRequest
882
936
  | VercelApiConfigRequest
937
+ | TwitterIntegrationConfigRequest
938
+ | TwitterAuthStartRequest
939
+ | TwitterAuthStatusRequest
883
940
  | SessionsClearRequest
884
941
  | GalleryListRequest
885
942
  | GalleryInstallRequest
@@ -902,12 +959,14 @@ export type ClientMessage =
902
959
  | BrowserInteractiveMode
903
960
  | WorkItemsListRequest
904
961
  | WorkItemGetRequest
905
- | WorkItemCreateRequest
906
962
  | WorkItemUpdateRequest
907
963
  | WorkItemCompleteRequest
908
964
  | WorkItemDeleteRequest
909
965
  | WorkItemRunTaskRequest
910
966
  | WorkItemOutputRequest
967
+ | WorkItemPreflightRequest
968
+ | WorkItemApprovePermissionsRequest
969
+ | WorkItemCancelRequest
911
970
  | SubagentAbortRequest
912
971
  | SubagentStatusRequest
913
972
  | SubagentMessageRequest;
@@ -1088,6 +1147,7 @@ export interface PongMessage {
1088
1147
  export interface DaemonStatusMessage {
1089
1148
  type: 'daemon_status';
1090
1149
  httpPort?: number;
1150
+ version?: string;
1091
1151
  }
1092
1152
 
1093
1153
  export interface GenerationCancelled {
@@ -1146,6 +1206,13 @@ export interface HistoryResponse {
1146
1206
  contentOrder?: string[];
1147
1207
  /** UI surfaces (widgets) embedded in the message. */
1148
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
+ };
1149
1216
  }>;
1150
1217
  }
1151
1218
 
@@ -1422,6 +1489,8 @@ export interface SchedulesListResponse {
1422
1489
  id: string;
1423
1490
  name: string;
1424
1491
  enabled: boolean;
1492
+ syntax: string;
1493
+ expression: string;
1425
1494
  cronExpression: string;
1426
1495
  timezone: string | null;
1427
1496
  message: string;
@@ -1637,6 +1706,12 @@ export interface WatcherEscalation {
1637
1706
  body: string;
1638
1707
  }
1639
1708
 
1709
+ export interface AgentHeartbeatAlert {
1710
+ type: 'agent_heartbeat_alert';
1711
+ title: string;
1712
+ body: string;
1713
+ }
1714
+
1640
1715
  export interface WatchStarted {
1641
1716
  type: 'watch_started';
1642
1717
  sessionId: string;
@@ -1892,26 +1967,6 @@ export interface WorkItemGetResponse {
1892
1967
  } | null;
1893
1968
  }
1894
1969
 
1895
- export interface WorkItemCreateResponse {
1896
- type: 'work_item_create_response';
1897
- item: {
1898
- id: string;
1899
- taskId: string;
1900
- title: string;
1901
- notes: string | null;
1902
- status: string;
1903
- priorityTier: number;
1904
- sortIndex: number | null;
1905
- lastRunId: string | null;
1906
- lastRunConversationId: string | null;
1907
- lastRunStatus: string | null;
1908
- sourceType: string | null;
1909
- sourceId: string | null;
1910
- createdAt: number;
1911
- updatedAt: number;
1912
- };
1913
- }
1914
-
1915
1970
  export interface WorkItemUpdateResponse {
1916
1971
  type: 'work_item_update_response';
1917
1972
  item: {
@@ -1966,6 +2021,33 @@ export interface WorkItemOutputResponse {
1966
2021
  };
1967
2022
  }
1968
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;
2049
+ }
2050
+
1969
2051
  /** Server push — tells the client to open/focus the tasks window. */
1970
2052
  export interface OpenTasksWindow {
1971
2053
  type: 'open_tasks_window';
@@ -1991,6 +2073,14 @@ export interface WorkItemStatusChanged {
1991
2073
  };
1992
2074
  }
1993
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
+
1994
2084
  export type ServerMessage =
1995
2085
  | AuthResult
1996
2086
  | UserMessageEcho
@@ -2045,6 +2135,7 @@ export type ServerMessage =
2045
2135
  | ScheduleComplete
2046
2136
  | WatcherNotification
2047
2137
  | WatcherEscalation
2138
+ | AgentHeartbeatAlert
2048
2139
  | WatchStarted
2049
2140
  | WatchCompleteRequest
2050
2141
  | TrustRulesListResponse
@@ -2068,6 +2159,9 @@ export type ServerMessage =
2068
2159
  | ShareToSlackResponse
2069
2160
  | SlackWebhookConfigResponse
2070
2161
  | VercelApiConfigResponse
2162
+ | TwitterIntegrationConfigResponse
2163
+ | TwitterAuthResult
2164
+ | TwitterAuthStatusResponse
2071
2165
  | OpenUrl
2072
2166
  | AppUpdatePreviewResponse
2073
2167
  | AppPreviewResponse
@@ -2089,12 +2183,15 @@ export type ServerMessage =
2089
2183
  | BrowserHandoffRequest
2090
2184
  | WorkItemsListResponse
2091
2185
  | WorkItemGetResponse
2092
- | WorkItemCreateResponse
2093
2186
  | WorkItemUpdateResponse
2094
2187
  | WorkItemDeleteResponse
2095
2188
  | WorkItemRunTaskResponse
2096
2189
  | WorkItemOutputResponse
2190
+ | WorkItemPreflightResponse
2191
+ | WorkItemApprovePermissionsResponse
2192
+ | WorkItemCancelResponse
2097
2193
  | WorkItemStatusChanged
2194
+ | TaskRunThreadCreated
2098
2195
  | TasksChanged
2099
2196
  | OpenTasksWindow
2100
2197
  | SubagentSpawned
@@ -2137,7 +2234,6 @@ export interface SubagentStatusRequest {
2137
2234
  type: 'subagent_status';
2138
2235
  /** If omitted, returns all subagents for the session. */
2139
2236
  subagentId?: string;
2140
- sessionId: string;
2141
2237
  }
2142
2238
 
2143
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
  }
@@ -44,7 +44,10 @@ import { RuntimeHttpServer } from '../runtime/http-server.js';
44
44
  import { getHookManager } from '../hooks/manager.js';
45
45
  import { installTemplates } from '../hooks/templates.js';
46
46
  import { HeartbeatService } from '../workspace/heartbeat-service.js';
47
+ import { AgentHeartbeatService } from '../agent-heartbeat/agent-heartbeat-service.js';
47
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';
48
51
 
49
52
  const log = getLogger('lifecycle');
50
53
 
@@ -292,6 +295,15 @@ export async function runDaemon(): Promise<void> {
292
295
  log.info({ count: orphanedRunning.length }, 'Recovered orphaned running work items');
293
296
  }
294
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
+
295
307
  log.info('Daemon startup: loading config');
296
308
  const config = loadConfig();
297
309
 
@@ -444,6 +456,14 @@ export async function runDaemon(): Promise<void> {
444
456
  const heartbeat = new HeartbeatService();
445
457
  heartbeat.start();
446
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
+
447
467
  // Graceful shutdown
448
468
  let shuttingDown = false;
449
469
  const shutdown = async () => {
@@ -464,6 +484,7 @@ export async function runDaemon(): Promise<void> {
464
484
  forceTimer.unref();
465
485
 
466
486
  await heartbeat.stop();
487
+ await agentHeartbeat.stop();
467
488
 
468
489
  try {
469
490
  await hookManager.trigger('daemon-stop', { pid: process.pid });
@@ -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);
@@ -15,12 +15,30 @@ import { getLogger } from '../util/logger.js';
15
15
  import { NetworkRecorder } from '../tools/browser/network-recorder.js';
16
16
  import { saveRecording } from '../tools/browser/recording-store.js';
17
17
  import type { SessionRecording } from '../tools/browser/network-recording-types.js';
18
+ import { navigateXPages } from '../tools/browser/x-auto-navigate.js';
19
+ import { autoNavigate } from '../tools/browser/auto-navigate.js';
18
20
 
19
21
  const log = getLogger('ride-shotgun-handler');
20
22
 
21
23
  /** Active network recorders keyed by watchId. */
22
24
  const activeRecorders = new Map<string, NetworkRecorder>();
23
25
 
26
+ /** Return domain-specific URL patterns that indicate a successful login. */
27
+ function getLoginSignals(targetDomain?: string): string[] {
28
+ if (targetDomain === 'x.com' || targetDomain === 'twitter.com') {
29
+ return [
30
+ '/i/api/graphql/', // any authenticated GraphQL call
31
+ '/1.1/account/settings', // legacy API session check
32
+ ];
33
+ }
34
+ // DoorDash and general fallback
35
+ return [
36
+ '/graphql/postLoginQuery',
37
+ '/graphql/homePageFacetFeed',
38
+ '/graphql/getConsumerOrdersWithDetails',
39
+ ];
40
+ }
41
+
24
42
  /**
25
43
  * Complete a session — finalize recording (if learn mode), generate summary, fire notifier.
26
44
  * Shared by both the duration timeout and the early-stop handler.
@@ -106,11 +124,7 @@ export async function handleRideShotgunStart(
106
124
  }
107
125
  try {
108
126
  const recorder = new NetworkRecorder(targetDomain);
109
- recorder.loginSignals = [
110
- '/graphql/postLoginQuery',
111
- '/graphql/homePageFacetFeed',
112
- '/graphql/getConsumerOrdersWithDetails',
113
- ];
127
+ recorder.loginSignals = getLoginSignals(targetDomain);
114
128
  await recorder.startDirect();
115
129
  // If session completed while we were connecting, stop immediately to avoid leak
116
130
  if (session.status !== 'active') {
@@ -118,13 +132,63 @@ export async function handleRideShotgunStart(
118
132
  await recorder.stop();
119
133
  return;
120
134
  }
121
- // Auto-stop when login is detected
122
- recorder.onLoginDetected = () => {
123
- log.info({ watchId }, 'Login detected — auto-stopping learn session');
124
- completeSession(session);
125
- };
126
135
  activeRecorders.set(watchId, recorder);
127
136
  log.info({ watchId, targetDomain, attempt }, 'Network recording started for learn session');
137
+
138
+ // For x.com, auto-navigate Chrome through key pages to capture the full API surface.
139
+ // Skip login detection — auto-navigation will complete the session when done.
140
+ if (targetDomain === 'x.com' || targetDomain === 'twitter.com') {
141
+ // Don't set onLoginDetected — it would kill the session after the first
142
+ // GraphQL call (5s grace), before auto-navigation finishes.
143
+ const abortSignal = { aborted: false };
144
+ const checkInterval = setInterval(() => {
145
+ if (session.status !== 'active') {
146
+ abortSignal.aborted = true;
147
+ clearInterval(checkInterval);
148
+ }
149
+ }, 1000);
150
+ navigateXPages(abortSignal).then(completed => {
151
+ clearInterval(checkInterval);
152
+ log.info({ watchId, completedSteps: completed.length }, 'X auto-navigation finished');
153
+ if (session.status === 'active') {
154
+ completeSession(session);
155
+ }
156
+ }).catch(err => {
157
+ clearInterval(checkInterval);
158
+ log.warn({ err, watchId }, 'X auto-navigation failed');
159
+ if (session.status === 'active') {
160
+ completeSession(session);
161
+ }
162
+ });
163
+ } else if (msg.autoNavigate && targetDomain) {
164
+ const abortSignal = { aborted: false };
165
+ const checkInterval = setInterval(() => {
166
+ if (session.status !== 'active') {
167
+ abortSignal.aborted = true;
168
+ clearInterval(checkInterval);
169
+ }
170
+ }, 1000);
171
+ autoNavigate(targetDomain, abortSignal).then(visited => {
172
+ clearInterval(checkInterval);
173
+ log.info({ watchId, visitedPages: visited.length }, 'Generic auto-navigation finished');
174
+ if (session.status === 'active') {
175
+ completeSession(session);
176
+ }
177
+ }).catch(err => {
178
+ clearInterval(checkInterval);
179
+ log.warn({ err, watchId }, 'Generic auto-navigation failed');
180
+ if (session.status === 'active') {
181
+ completeSession(session);
182
+ }
183
+ });
184
+ } else {
185
+ // No targetDomain: use login detection as before
186
+ recorder.onLoginDetected = () => {
187
+ log.info({ watchId }, 'Login detected — auto-stopping learn session');
188
+ completeSession(session);
189
+ };
190
+ }
191
+
128
192
  return;
129
193
  } catch (err) {
130
194
  if (attempt < 9) {