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
@@ -2,16 +2,18 @@ import * as net from 'node:net';
2
2
  import type {
3
3
  WorkItemsListRequest,
4
4
  WorkItemGetRequest,
5
- WorkItemCreateRequest,
6
5
  WorkItemUpdateRequest,
7
6
  WorkItemCompleteRequest,
8
7
  WorkItemDeleteRequest,
9
8
  WorkItemRunTaskRequest,
10
9
  WorkItemOutputRequest,
10
+ WorkItemPreflightRequest,
11
+ WorkItemApprovePermissionsRequest,
12
+ WorkItemCancelRequest,
11
13
  } from '../ipc-protocol.js';
12
- import { log, type HandlerContext } from './shared.js';
14
+ import { log, defineHandlers, type HandlerContext } from './shared.js';
15
+ import { getSubagentManager } from '../../subagent/index.js';
13
16
  import {
14
- createWorkItem,
15
17
  deleteWorkItem,
16
18
  getWorkItem,
17
19
  listWorkItems,
@@ -21,6 +23,9 @@ import {
21
23
  import { getTask, getTaskRun } from '../../tasks/task-store.js';
22
24
  import { runTask } from '../../tasks/task-runner.js';
23
25
  import { getMessages } from '../../memory/conversation-store.js';
26
+ import { classifyRisk, check } from '../../permissions/checker.js';
27
+ import { truncate } from '../../util/truncate.js';
28
+ import { sanitizeToolList, getRegisteredToolNames, getToolDescription } from '../../tasks/tool-sanitizer.js';
24
29
 
25
30
  export function handleWorkItemsList(
26
31
  msg: WorkItemsListRequest,
@@ -40,35 +45,20 @@ export function handleWorkItemGet(
40
45
  ctx.send(socket, { type: 'work_item_get_response', item });
41
46
  }
42
47
 
43
- export function handleWorkItemCreate(
44
- msg: WorkItemCreateRequest,
45
- socket: net.Socket,
46
- ctx: HandlerContext,
47
- ): void {
48
- const task = getTask(msg.taskId);
49
- if (!task) {
50
- ctx.send(socket, { type: 'error', message: `Task not found: ${msg.taskId}` });
51
- return;
52
- }
53
- const item = createWorkItem({
54
- taskId: msg.taskId,
55
- title: msg.title ?? task.title,
56
- notes: msg.notes,
57
- priorityTier: msg.priorityTier,
58
- sortIndex: msg.sortIndex,
59
- });
60
- ctx.send(socket, { type: 'work_item_create_response', item });
61
-
62
- // Notify all connected clients so open Task Queue views refresh immediately
63
- broadcastWorkItemStatus(ctx, item.id);
64
- ctx.broadcast({ type: 'tasks_changed' });
65
- }
66
-
67
48
  export function handleWorkItemUpdate(
68
49
  msg: WorkItemUpdateRequest,
69
50
  socket: net.Socket,
70
51
  ctx: HandlerContext,
71
52
  ): void {
53
+ // Don't allow overwriting a cancelled status (e.g. from a late chat-completion observer)
54
+ if (msg.status !== undefined) {
55
+ const existing = getWorkItem(msg.id);
56
+ if (existing?.status === 'cancelled' && msg.status !== 'cancelled') {
57
+ ctx.send(socket, { type: 'work_item_update_response', item: existing });
58
+ return;
59
+ }
60
+ }
61
+
72
62
  const updates: Record<string, unknown> = {};
73
63
  if (msg.title !== undefined) updates.title = msg.title;
74
64
  if (msg.notes !== undefined) updates.notes = msg.notes;
@@ -158,6 +148,107 @@ function broadcastWorkItemStatus(ctx: HandlerContext, id: string): void {
158
148
  }
159
149
  }
160
150
 
151
+ /** Extract plain text from a message content string (handles JSON content block arrays). */
152
+ function extractTextFromContent(content: string): string {
153
+ try {
154
+ const parsed = JSON.parse(content);
155
+ if (Array.isArray(parsed)) {
156
+ return parsed
157
+ .filter((b: { type: string }) => b.type === 'text')
158
+ .map((b: { text: string }) => b.text)
159
+ .join('\n');
160
+ }
161
+ } catch {
162
+ // Plain text content — use as-is
163
+ }
164
+ return content;
165
+ }
166
+
167
+ /** Extract tool_result blocks from a user message's content. */
168
+ function extractToolResults(content: string): Array<{ tool_use_id: string; content: string; is_error?: boolean }> {
169
+ try {
170
+ const parsed = JSON.parse(content);
171
+ if (Array.isArray(parsed)) {
172
+ return parsed
173
+ .filter((b: { type: string }) => b.type === 'tool_result')
174
+ .map((b: { tool_use_id: string; content?: string | Array<{ type: string; text?: string }>; is_error?: boolean }) => {
175
+ let text = '';
176
+ if (typeof b.content === 'string') {
177
+ text = b.content;
178
+ } else if (Array.isArray(b.content)) {
179
+ text = b.content
180
+ .filter((c) => c.type === 'text' && c.text)
181
+ .map((c) => c.text!)
182
+ .join('\n');
183
+ }
184
+ return { tool_use_id: b.tool_use_id, content: text, is_error: b.is_error };
185
+ });
186
+ }
187
+ } catch {
188
+ // Not JSON — no tool_result blocks
189
+ }
190
+ return [];
191
+ }
192
+
193
+ /**
194
+ * Build highlights from tool outcomes in the conversation. Scans for
195
+ * tool_use (assistant) and tool_result (user) pairs, extracting concrete
196
+ * outcomes like errors, file paths, and URLs.
197
+ */
198
+ function extractToolHighlights(
199
+ msgs: Array<{ role: string; content: string }>,
200
+ maxHighlights: number,
201
+ ): string[] {
202
+ const highlights: string[] = [];
203
+
204
+ // Build a map of tool_use_id -> tool name from assistant messages
205
+ const toolNameById = new Map<string, string>();
206
+ for (const m of msgs) {
207
+ if (m.role !== 'assistant') continue;
208
+ try {
209
+ const parsed = JSON.parse(m.content);
210
+ if (Array.isArray(parsed)) {
211
+ for (const block of parsed) {
212
+ if (block.type === 'tool_use' && block.id && block.name) {
213
+ toolNameById.set(block.id, block.name);
214
+ }
215
+ }
216
+ }
217
+ } catch { /* skip */ }
218
+ }
219
+
220
+ // Scan tool_result messages in reverse order (most recent first)
221
+ for (let i = msgs.length - 1; i >= 0 && highlights.length < maxHighlights; i--) {
222
+ const m = msgs[i];
223
+ if (m.role !== 'user') continue;
224
+
225
+ const results = extractToolResults(m.content);
226
+ for (const result of results) {
227
+ if (highlights.length >= maxHighlights) break;
228
+
229
+ const toolName = toolNameById.get(result.tool_use_id) ?? 'tool';
230
+ const resultText = result.content.trim();
231
+
232
+ if (result.is_error) {
233
+ // Always surface errors
234
+ const errorSnippet = truncate(resultText, 200, '...');
235
+ highlights.push(`- ${toolName}: Error — ${errorSnippet}`);
236
+ } else if (resultText) {
237
+ // Extract notable signal from successful results: file paths, URLs, or
238
+ // a short summary of what happened
239
+ const firstLine = resultText.split('\n')[0].trim();
240
+ if (firstLine.length > 0 && firstLine.length <= 200) {
241
+ highlights.push(`- ${toolName}: ${firstLine}`);
242
+ } else if (firstLine.length > 200) {
243
+ highlights.push(`- ${toolName}: ${truncate(firstLine, 200, '...')}`);
244
+ }
245
+ }
246
+ }
247
+ }
248
+
249
+ return highlights;
250
+ }
251
+
161
252
  export function handleWorkItemOutput(
162
253
  msg: WorkItemOutputRequest,
163
254
  socket: net.Socket,
@@ -170,41 +261,50 @@ export function handleWorkItemOutput(
170
261
  return;
171
262
  }
172
263
 
173
- // If the work item has never been run, return an error so the client
174
- // can show "No output yet" instead of an empty loaded state.
175
- if (!workItem.lastRunConversationId) {
264
+ // Use the task run's conversationId as the authoritative source. This
265
+ // ensures we read from the actual run's conversation, not stale references
266
+ // on the work item.
267
+ let conversationId: string | null = null;
268
+ let completedAt: number | null = null;
269
+
270
+ if (workItem.lastRunId) {
271
+ const run = getTaskRun(workItem.lastRunId);
272
+ if (run) {
273
+ conversationId = run.conversationId;
274
+ completedAt = run.finishedAt != null ? Math.floor(run.finishedAt / 1000) : null;
275
+ }
276
+ }
277
+
278
+ // Fall back to the work item's stored conversationId if the run lookup
279
+ // didn't yield one (e.g. run record was deleted but work item still has
280
+ // the reference).
281
+ if (!conversationId) {
282
+ conversationId = workItem.lastRunConversationId;
283
+ }
284
+
285
+ if (!conversationId) {
176
286
  ctx.send(socket, { type: 'work_item_output_response', id: msg.id, success: false, error: 'This task has not been run yet. No output is available.' });
177
287
  return;
178
288
  }
179
289
 
180
290
  let summary = '';
181
- const highlights: string[] = [];
291
+ let highlights: string[] = [];
182
292
 
183
- const msgs = getMessages(workItem.lastRunConversationId);
184
- // Find the last assistant message with text content (not tool calls)
293
+ const msgs = getMessages(conversationId);
294
+
295
+ // Find the last assistant message with text content (not tool calls).
296
+ // Skip messages that are purely about task management rather than
297
+ // reporting what the run actually did.
185
298
  for (let i = msgs.length - 1; i >= 0; i--) {
186
299
  const m = msgs[i];
187
300
  if (m.role !== 'assistant') continue;
188
301
 
189
- let text = m.content;
190
- // Content may be JSON array of content blocks — extract text blocks only
191
- try {
192
- const parsed = JSON.parse(text);
193
- if (Array.isArray(parsed)) {
194
- text = parsed
195
- .filter((b: { type: string }) => b.type === 'text')
196
- .map((b: { text: string }) => b.text)
197
- .join('\n');
198
- }
199
- } catch {
200
- // Plain text content — use as-is
201
- }
202
-
302
+ const text = extractTextFromContent(m.content);
203
303
  if (!text.trim()) continue;
204
304
 
205
- summary = text.length > 2000 ? text.slice(0, 2000) : text;
305
+ summary = truncate(text, 2000, '');
206
306
 
207
- // Extract up to 5 notable lines (bullet points or key findings)
307
+ // Extract bullet points from the assistant's prose
208
308
  const lines = text.split('\n');
209
309
  for (const line of lines) {
210
310
  const trimmed = line.trim();
@@ -216,12 +316,22 @@ export function handleWorkItemOutput(
216
316
  break;
217
317
  }
218
318
 
219
- // Convert finishedAt from milliseconds (Date.now()) to seconds for the
220
- // client, which uses Date(timeIntervalSince1970:) expecting seconds.
221
- let completedAt: number | null = null;
222
- if (workItem.lastRunId) {
223
- const run = getTaskRun(workItem.lastRunId);
224
- completedAt = run?.finishedAt != null ? Math.floor(run.finishedAt / 1000) : null;
319
+ // If we didn't get enough highlights from the assistant prose, supplement
320
+ // with concrete tool outcomes from the conversation.
321
+ if (highlights.length < 5) {
322
+ const toolHighlights = extractToolHighlights(msgs, 5 - highlights.length);
323
+ highlights = [...highlights, ...toolHighlights];
324
+ }
325
+
326
+ // If there's no assistant summary at all, synthesize one from tool results
327
+ // so the user still sees what happened.
328
+ if (!summary && msgs.length > 0) {
329
+ const toolHighlights = extractToolHighlights(msgs, 10);
330
+ if (toolHighlights.length > 0) {
331
+ summary = 'Task completed. Tool outcomes:\n' + toolHighlights.join('\n');
332
+ // Use the tool highlights as the main highlights too
333
+ highlights = toolHighlights.slice(0, 5);
334
+ }
225
335
  }
226
336
 
227
337
  ctx.send(socket, {
@@ -232,7 +342,7 @@ export function handleWorkItemOutput(
232
342
  title: workItem.title,
233
343
  status: workItem.lastRunStatus ?? workItem.status,
234
344
  runId: workItem.lastRunId,
235
- conversationId: workItem.lastRunConversationId,
345
+ conversationId,
236
346
  completedAt,
237
347
  summary,
238
348
  highlights,
@@ -260,7 +370,7 @@ export async function handleWorkItemRunTask(
260
370
  return;
261
371
  }
262
372
 
263
- const NON_RUNNABLE_STATUSES: readonly string[] = ['done', 'archived'];
373
+ const NON_RUNNABLE_STATUSES: readonly string[] = ['archived'];
264
374
  if (NON_RUNNABLE_STATUSES.includes(workItem.status)) {
265
375
  ctx.send(socket, { type: 'work_item_run_task_response', id: msg.id, lastRunId: workItem.lastRunId ?? '', success: false, error: `Work item has status '${workItem.status}' and cannot be run`, errorCode: 'invalid_status' });
266
376
  return;
@@ -272,6 +382,37 @@ export async function handleWorkItemRunTask(
272
382
  return;
273
383
  }
274
384
 
385
+ // Compute required tools using the same resolution logic as preflight:
386
+ // work-item snapshot first, then task template, then all registered tools.
387
+ let requiredTools: string[];
388
+ if (workItem.requiredTools !== null && workItem.requiredTools !== undefined) {
389
+ requiredTools = sanitizeToolList(JSON.parse(workItem.requiredTools));
390
+ } else {
391
+ requiredTools = task.requiredTools
392
+ ? sanitizeToolList(JSON.parse(task.requiredTools))
393
+ : getRegisteredToolNames();
394
+ }
395
+
396
+ // Permission checkpoint: if the task requires tools, verify all have been approved.
397
+ // Empty required tools means no approvals needed.
398
+ let approvedTools: string[] | undefined;
399
+ if (requiredTools.length > 0) {
400
+ approvedTools = workItem.approvedTools ? JSON.parse(workItem.approvedTools) : undefined;
401
+ const approvedSet = new Set<string>(approvedTools ?? []);
402
+ const missingApprovals = requiredTools.filter((t) => !approvedSet.has(t));
403
+ if (missingApprovals.length > 0) {
404
+ ctx.send(socket, {
405
+ type: 'work_item_run_task_response',
406
+ id: msg.id,
407
+ lastRunId: '',
408
+ success: false,
409
+ error: 'Required tool permissions have not been approved. Run preflight first.',
410
+ errorCode: 'permission_required',
411
+ });
412
+ return;
413
+ }
414
+ }
415
+
275
416
  // Set status to running
276
417
  updateWorkItem(msg.id, { status: 'running' });
277
418
 
@@ -282,29 +423,62 @@ export async function handleWorkItemRunTask(
282
423
  broadcastWorkItemStatus(ctx, msg.id);
283
424
  ctx.broadcast({ type: 'tasks_changed' });
284
425
 
285
- // Execute task asynchronously — create a session and wire processMessage
426
+ // Execute task asynchronously — lazily create a session inside the callback
427
+ // using the conversationId provided by runTask, so the session references
428
+ // the conversation that was actually inserted into the database.
286
429
  try {
287
- const session = await ctx.getOrCreateSession(crypto.randomUUID());
430
+ let session: Awaited<ReturnType<typeof ctx.getOrCreateSession>> | null = null;
288
431
  const result = await runTask(
289
- { taskId: workItem.taskId, workingDir: process.cwd() },
290
- async (_conversationId, message) => {
432
+ { taskId: workItem.taskId, workingDir: process.cwd(), approvedTools },
433
+ async (conversationId, message, taskRunId) => {
434
+ if (!session) {
435
+ // Store conversationId on the work item immediately so the cancel
436
+ // handler can locate the session while the task is still running.
437
+ updateWorkItem(msg.id, { lastRunConversationId: conversationId });
438
+ session = await ctx.getOrCreateSession(conversationId);
439
+
440
+ // Notify clients so they can create a visible chat thread for this task run
441
+ ctx.broadcast({
442
+ type: 'task_run_thread_created',
443
+ conversationId,
444
+ workItemId: msg.id,
445
+ title: workItem.title,
446
+ });
447
+ // Wire the taskRunId so the executor can retrieve ephemeral permission rules
448
+ (session as unknown as { taskRunId?: string }).taskRunId = taskRunId;
449
+ // Prevent interactive clients from rebinding to this session mid-run
450
+ (session as unknown as { headlessLock: boolean }).headlessLock = true;
451
+ }
291
452
  await session.processMessage(message, [], (event) => {
292
453
  ctx.broadcast(event);
293
454
  });
294
455
  },
295
456
  );
296
457
 
297
- const finalStatus: WorkItemStatus = result.status === 'completed' ? 'awaiting_review' : 'failed';
298
- updateWorkItem(msg.id, {
299
- status: finalStatus,
300
- lastRunId: result.taskRunId,
301
- lastRunConversationId: result.conversationId,
302
- lastRunStatus: result.status,
303
- });
458
+ // Release the headless lock now that the task run is done
459
+ if (session) {
460
+ (session as unknown as { headlessLock: boolean }).headlessLock = false;
461
+ }
462
+
463
+ // Don't overwrite cancelled status — the cancel handler already set it
464
+ const current = getWorkItem(msg.id);
465
+ if (current?.status !== 'cancelled') {
466
+ const finalStatus: WorkItemStatus = result.status === 'completed' ? 'awaiting_review' : 'failed';
467
+ updateWorkItem(msg.id, {
468
+ status: finalStatus,
469
+ lastRunId: result.taskRunId,
470
+ lastRunConversationId: result.conversationId,
471
+ lastRunStatus: result.status,
472
+ });
473
+ }
304
474
 
305
475
  broadcastWorkItemStatus(ctx, msg.id);
306
476
  ctx.broadcast({ type: 'tasks_changed' });
307
477
  } catch (err) {
478
+ // Release the headless lock on failure
479
+ if (session) {
480
+ (session as unknown as { headlessLock: boolean }).headlessLock = false;
481
+ }
308
482
  log.error({ err, workItemId: msg.id }, 'work_item_run_task failed');
309
483
  updateWorkItem(msg.id, {
310
484
  status: 'failed',
@@ -314,3 +488,145 @@ export async function handleWorkItemRunTask(
314
488
  ctx.broadcast({ type: 'tasks_changed' });
315
489
  }
316
490
  }
491
+
492
+
493
+ export async function handleWorkItemPreflight(
494
+ msg: WorkItemPreflightRequest,
495
+ socket: net.Socket,
496
+ ctx: HandlerContext,
497
+ ): Promise<void> {
498
+ const workItem = getWorkItem(msg.id);
499
+ if (!workItem) {
500
+ ctx.send(socket, { type: 'work_item_preflight_response', id: msg.id, success: false, error: 'Work item not found' });
501
+ return;
502
+ }
503
+
504
+ // Compute required tools from the work-item snapshot first; only fall
505
+ // back to the task template (or all registered tools) when the
506
+ // snapshot is null.
507
+ let requiredTools: string[];
508
+ if (workItem.requiredTools !== null && workItem.requiredTools !== undefined) {
509
+ requiredTools = sanitizeToolList(JSON.parse(workItem.requiredTools));
510
+ } else {
511
+ const task = getTask(workItem.taskId);
512
+ if (!task) {
513
+ ctx.send(socket, { type: 'work_item_preflight_response', id: msg.id, success: false, error: `Associated task not found: ${workItem.taskId}` });
514
+ return;
515
+ }
516
+ requiredTools = task.requiredTools
517
+ ? sanitizeToolList(JSON.parse(task.requiredTools))
518
+ : getRegisteredToolNames();
519
+ }
520
+
521
+ // If the work item explicitly requires no tools, skip the dialog.
522
+ if (requiredTools.length === 0) {
523
+ ctx.send(socket, { type: 'work_item_preflight_response', id: msg.id, success: true, permissions: [] });
524
+ return;
525
+ }
526
+
527
+ // If some tools are already approved, only prompt for the missing ones.
528
+ // When all required tools are covered, skip the dialog entirely.
529
+ if (workItem.approvedTools) {
530
+ const approvedSet = new Set<string>(JSON.parse(workItem.approvedTools));
531
+ requiredTools = requiredTools.filter((t) => !approvedSet.has(t));
532
+ if (requiredTools.length === 0) {
533
+ ctx.send(socket, { type: 'work_item_preflight_response', id: msg.id, success: true, permissions: [] });
534
+ return;
535
+ }
536
+ }
537
+
538
+ const workingDir = process.cwd();
539
+ const permissions = await Promise.all(
540
+ requiredTools.map(async (tool) => {
541
+ const risk = await classifyRisk(tool, {}, workingDir);
542
+ const result = await check(tool, {}, workingDir);
543
+ return {
544
+ tool,
545
+ description: getToolDescription(tool),
546
+ riskLevel: risk.toLowerCase() as 'low' | 'medium' | 'high',
547
+ currentDecision: result.decision as 'allow' | 'deny' | 'prompt',
548
+ };
549
+ }),
550
+ );
551
+
552
+ ctx.send(socket, { type: 'work_item_preflight_response', id: msg.id, success: true, permissions });
553
+ }
554
+
555
+ export function handleWorkItemApprovePermissions(
556
+ msg: WorkItemApprovePermissionsRequest,
557
+ socket: net.Socket,
558
+ ctx: HandlerContext,
559
+ ): void {
560
+ const workItem = getWorkItem(msg.id);
561
+ if (!workItem) {
562
+ ctx.send(socket, { type: 'work_item_approve_permissions_response', id: msg.id, success: false, error: 'Work item not found' });
563
+ return;
564
+ }
565
+
566
+ // Merge newly approved tools with any previously approved ones so reruns
567
+ // that only need a subset of previously-approved tools don't require
568
+ // re-approval.
569
+ const existingApproved: string[] = workItem.approvedTools
570
+ ? JSON.parse(workItem.approvedTools)
571
+ : [];
572
+ const newApproved = sanitizeToolList(msg.approvedTools);
573
+ const merged = [...new Set([...existingApproved, ...newApproved])];
574
+
575
+ updateWorkItem(msg.id, {
576
+ approvedTools: JSON.stringify(sanitizeToolList(merged)),
577
+ approvalStatus: 'approved',
578
+ });
579
+
580
+ ctx.send(socket, { type: 'work_item_approve_permissions_response', id: msg.id, success: true });
581
+ }
582
+
583
+ export function handleWorkItemCancel(
584
+ msg: WorkItemCancelRequest,
585
+ socket: net.Socket,
586
+ ctx: HandlerContext,
587
+ ): void {
588
+ const workItem = getWorkItem(msg.id);
589
+ if (!workItem) {
590
+ ctx.send(socket, { type: 'work_item_cancel_response', id: msg.id, success: false, error: 'Work item not found' });
591
+ return;
592
+ }
593
+
594
+ if (workItem.status !== 'running') {
595
+ ctx.send(socket, { type: 'work_item_cancel_response', id: msg.id, success: false, error: `Work item is not running (status: ${workItem.status})` });
596
+ return;
597
+ }
598
+
599
+ // Abort the session associated with this work item's current run
600
+ const conversationId = workItem.lastRunConversationId;
601
+ if (conversationId) {
602
+ const session = ctx.sessions.get(conversationId);
603
+ if (session) {
604
+ (session as unknown as { headlessLock: boolean }).headlessLock = false;
605
+ session.abort();
606
+ getSubagentManager().abortAllForParent(conversationId);
607
+ }
608
+ }
609
+
610
+ updateWorkItem(msg.id, {
611
+ status: 'cancelled',
612
+ lastRunStatus: 'cancelled',
613
+ });
614
+
615
+ ctx.send(socket, { type: 'work_item_cancel_response', id: msg.id, success: true });
616
+
617
+ broadcastWorkItemStatus(ctx, msg.id);
618
+ ctx.broadcast({ type: 'tasks_changed' });
619
+ }
620
+
621
+ export const workItemHandlers = defineHandlers({
622
+ work_items_list: handleWorkItemsList,
623
+ work_item_get: handleWorkItemGet,
624
+ work_item_update: handleWorkItemUpdate,
625
+ work_item_complete: handleWorkItemComplete,
626
+ work_item_delete: handleWorkItemDelete,
627
+ work_item_run_task: handleWorkItemRunTask,
628
+ work_item_output: handleWorkItemOutput,
629
+ work_item_preflight: handleWorkItemPreflight,
630
+ work_item_approve_permissions: handleWorkItemApprovePermissions,
631
+ work_item_cancel: handleWorkItemCancel,
632
+ });
@@ -80,6 +80,9 @@
80
80
  "SuggestionRequest",
81
81
  "TaskSubmit",
82
82
  "TrustRulesList",
83
+ "TwitterAuthStartRequest",
84
+ "TwitterAuthStatusRequest",
85
+ "TwitterIntegrationConfigRequest",
83
86
  "UiSurfaceAction",
84
87
  "UiSurfaceUndoRequest",
85
88
  "UndoRequest",
@@ -89,17 +92,20 @@
89
92
  "UserMessage",
90
93
  "VercelApiConfigRequest",
91
94
  "WatchObservation",
95
+ "WorkItemApprovePermissionsRequest",
96
+ "WorkItemCancelRequest",
92
97
  "WorkItemCompleteRequest",
93
- "WorkItemCreateRequest",
94
98
  "WorkItemDeleteRequest",
95
99
  "WorkItemGetRequest",
96
100
  "WorkItemOutputRequest",
101
+ "WorkItemPreflightRequest",
97
102
  "WorkItemRunTaskRequest",
98
103
  "WorkItemUpdateRequest",
99
104
  "WorkItemsListRequest"
100
105
  ],
101
106
  "serverMessageTypes": [
102
107
  "AcceptStarterBundleResponse",
108
+ "AgentHeartbeatAlert",
103
109
  "AppDataResponse",
104
110
  "AppFilesChanged",
105
111
  "AppPreviewResponse",
@@ -177,6 +183,7 @@
177
183
  "SubagentStatusChanged",
178
184
  "SuggestionResponse",
179
185
  "TaskRouted",
186
+ "TaskRunThreadCreated",
180
187
  "TasksChanged",
181
188
  "ToolInputDelta",
182
189
  "ToolOutputChunk",
@@ -184,6 +191,9 @@
184
191
  "ToolUseStart",
185
192
  "TraceEvent",
186
193
  "TrustRulesListResponse",
194
+ "TwitterAuthResult",
195
+ "TwitterAuthStatusResponse",
196
+ "TwitterIntegrationConfigResponse",
187
197
  "UiSurfaceComplete",
188
198
  "UiSurfaceDismiss",
189
199
  "UiSurfaceShow",
@@ -199,10 +209,12 @@
199
209
  "WatchStarted",
200
210
  "WatcherEscalation",
201
211
  "WatcherNotification",
202
- "WorkItemCreateResponse",
212
+ "WorkItemApprovePermissionsResponse",
213
+ "WorkItemCancelResponse",
203
214
  "WorkItemDeleteResponse",
204
215
  "WorkItemGetResponse",
205
216
  "WorkItemOutputResponse",
217
+ "WorkItemPreflightResponse",
206
218
  "WorkItemRunTaskResponse",
207
219
  "WorkItemStatusChanged",
208
220
  "WorkItemUpdateResponse",
@@ -289,6 +301,9 @@
289
301
  "suggestion_request",
290
302
  "task_submit",
291
303
  "trust_rules_list",
304
+ "twitter_auth_start",
305
+ "twitter_auth_status",
306
+ "twitter_integration_config",
292
307
  "ui_surface_action",
293
308
  "ui_surface_undo",
294
309
  "undo",
@@ -298,17 +313,20 @@
298
313
  "user_message",
299
314
  "vercel_api_config",
300
315
  "watch_observation",
316
+ "work_item_approve_permissions",
317
+ "work_item_cancel",
301
318
  "work_item_complete",
302
- "work_item_create",
303
319
  "work_item_delete",
304
320
  "work_item_get",
305
321
  "work_item_output",
322
+ "work_item_preflight",
306
323
  "work_item_run_task",
307
324
  "work_item_update",
308
325
  "work_items_list"
309
326
  ],
310
327
  "serverWireTypes": [
311
328
  "accept_starter_bundle_response",
329
+ "agent_heartbeat_alert",
312
330
  "app_data_response",
313
331
  "app_files_changed",
314
332
  "app_preview_response",
@@ -386,6 +404,7 @@
386
404
  "subagent_status_changed",
387
405
  "suggestion_response",
388
406
  "task_routed",
407
+ "task_run_thread_created",
389
408
  "tasks_changed",
390
409
  "tool_input_delta",
391
410
  "tool_output_chunk",
@@ -393,6 +412,9 @@
393
412
  "tool_use_start",
394
413
  "trace_event",
395
414
  "trust_rules_list_response",
415
+ "twitter_auth_result",
416
+ "twitter_auth_status_response",
417
+ "twitter_integration_config_response",
396
418
  "ui_surface_complete",
397
419
  "ui_surface_dismiss",
398
420
  "ui_surface_undo_result",
@@ -407,10 +429,12 @@
407
429
  "watch_started",
408
430
  "watcher_escalation",
409
431
  "watcher_notification",
410
- "work_item_create_response",
432
+ "work_item_approve_permissions_response",
433
+ "work_item_cancel_response",
411
434
  "work_item_delete_response",
412
435
  "work_item_get_response",
413
436
  "work_item_output_response",
437
+ "work_item_preflight_response",
414
438
  "work_item_run_task_response",
415
439
  "work_item_status_changed",
416
440
  "work_item_update_response",