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
@@ -1,69 +1,82 @@
1
- import { RiskLevel } from '../../permissions/types.js';
2
- import type { Tool, ToolContext, ToolExecutionResult } from '../types.js';
3
- import type { ToolDefinition } from '../../providers/types.js';
1
+ import type { ToolContext, ToolExecutionResult } from '../types.js';
4
2
  import { deleteTask, deleteTasks, getTask } from '../../tasks/task-store.js';
3
+ import { removeWorkItemFromQueue } from '../../work-items/work-item-store.js';
4
+ import { getLogger } from '../../util/logger.js';
5
5
 
6
- const definition: ToolDefinition = {
7
- name: 'task_delete',
8
- description: 'Delete one or more task templates by ID. Also removes associated task runs and work items (Tasks).',
9
- input_schema: {
10
- type: 'object',
11
- properties: {
12
- task_ids: {
13
- type: 'array',
14
- items: { type: 'string' },
15
- description: 'One or more task IDs to delete.',
16
- },
17
- },
18
- required: ['task_ids'],
19
- },
20
- };
6
+ const log = getLogger('task-delete');
21
7
 
22
- class TaskDeleteTool implements Tool {
23
- name = 'task_delete';
24
- description = definition.description;
25
- category = 'tasks';
26
- defaultRiskLevel = RiskLevel.Medium;
27
-
28
- getDefinition(): ToolDefinition {
29
- return definition;
8
+ export async function executeTaskDelete(
9
+ input: Record<string, unknown>,
10
+ _context: ToolContext,
11
+ ): Promise<ToolExecutionResult> {
12
+ const raw = input.task_ids;
13
+ if (!Array.isArray(raw) || raw.length === 0) {
14
+ return { content: 'Error: task_ids must be a non-empty array of task ID strings', isError: true };
15
+ }
16
+ const ids = raw.filter((v): v is string => typeof v === 'string' && v.trim().length > 0);
17
+ if (ids.length === 0) {
18
+ return { content: 'Error: task_ids must contain at least one non-empty string', isError: true };
30
19
  }
31
20
 
32
- async execute(input: Record<string, unknown>, _context: ToolContext): Promise<ToolExecutionResult> {
33
- const raw = input.task_ids;
34
- if (!Array.isArray(raw) || raw.length === 0) {
35
- return { content: 'Error: task_ids must be a non-empty array of task ID strings', isError: true };
36
- }
37
- const ids = raw.filter((v): v is string => typeof v === 'string' && v.trim().length > 0);
38
- if (ids.length === 0) {
39
- return { content: 'Error: task_ids must contain at least one non-empty string', isError: true };
21
+ try {
22
+ if (ids.length === 1) {
23
+ const task = getTask(ids[0]);
24
+ const deleted = deleteTask(ids[0]);
25
+ if (!deleted) {
26
+ // The LLM may pass a work item ID instead of a task template ID.
27
+ // Fall back to removing from the task queue so the user's intent succeeds.
28
+ const result = removeWorkItemFromQueue(ids[0]);
29
+ if (result.success) {
30
+ log.info({ inputId: ids[0], fallback: true, deletedCount: 1 }, 'deleted via work item fallback');
31
+ return { content: result.message, isError: false };
32
+ }
33
+ log.warn({ inputId: ids[0] }, 'no task or work item found for deletion');
34
+ return { content: `No task template or work item found with ID "${ids[0]}". Use task_list to see task templates or task_list_show to see work items in the queue.`, isError: true };
35
+ }
36
+ log.info({ taskId: ids[0], title: task?.title, deletedCount: 1 }, 'task deleted');
37
+ return { content: `Deleted task: ${task?.title ?? ids[0]}`, isError: false };
40
38
  }
41
39
 
42
- try {
43
- if (ids.length === 1) {
44
- const task = getTask(ids[0]);
45
- const deleted = deleteTask(ids[0]);
46
- if (!deleted) {
47
- return { content: `No task found with ID ${ids[0]}`, isError: true };
40
+ const taskIds: string[] = [];
41
+ const taskTitles: string[] = [];
42
+ const workItemTitles: string[] = [];
43
+
44
+ for (const id of ids) {
45
+ const task = getTask(id);
46
+ if (task) {
47
+ taskIds.push(id);
48
+ taskTitles.push(task.title);
49
+ } else {
50
+ const result = removeWorkItemFromQueue(id);
51
+ if (result.success) {
52
+ log.info({ inputId: id, fallback: true }, 'deleted work item in batch (fallback)');
53
+ workItemTitles.push(result.title);
54
+ } else {
55
+ log.warn({ inputId: id }, 'batch delete: no task or work item found');
48
56
  }
49
- return { content: `Deleted task: ${task?.title ?? ids[0]}`, isError: false };
50
57
  }
58
+ }
51
59
 
52
- const titles = ids.map((id) => {
53
- const t = getTask(id);
54
- return t ? t.title : id;
55
- });
56
- const count = deleteTasks(ids);
57
- if (count === 0) {
58
- return { content: 'No matching tasks found to delete.', isError: true };
59
- }
60
- const lines = [`Deleted ${count} task(s):`, ...titles.map((t) => `- ${t}`)];
61
- return { content: lines.join('\n'), isError: false };
62
- } catch (err) {
63
- const msg = err instanceof Error ? err.message : String(err);
64
- return { content: `Error: ${msg}`, isError: true };
60
+ const taskCount = taskIds.length > 0 ? deleteTasks(taskIds) : 0;
61
+
62
+ if (taskCount === 0 && workItemTitles.length === 0) {
63
+ log.warn({ inputIds: ids }, 'no matching tasks found to delete');
64
+ return { content: 'No matching tasks found to delete.', isError: true };
65
65
  }
66
+
67
+ log.info({ deletedTasks: taskCount, deletedWorkItems: workItemTitles.length, totalInput: ids.length }, 'batch delete completed');
68
+
69
+ const lines: string[] = [];
70
+ if (taskCount > 0) {
71
+ lines.push(`Deleted ${taskCount} task(s):`, ...taskTitles.map((t) => `- ${t}`));
72
+ }
73
+ if (workItemTitles.length > 0) {
74
+ lines.push(`Removed ${workItemTitles.length} item(s) from the task queue:`, ...workItemTitles.map((t) => `- ${t}`));
75
+ }
76
+ return { content: lines.join('\n'), isError: false };
77
+ } catch (err) {
78
+ const msg = err instanceof Error ? err.message : String(err);
79
+ log.error({ inputIds: ids, error: msg }, 'delete failed');
80
+ return { content: `Error: ${msg}`, isError: true };
66
81
  }
67
82
  }
68
-
69
- export const taskDeleteTool = new TaskDeleteTool();
@@ -1,65 +1,44 @@
1
- import { RiskLevel } from '../../permissions/types.js';
2
- import type { Tool, ToolContext, ToolExecutionResult } from '../types.js';
3
- import type { ToolDefinition } from '../../providers/types.js';
1
+ import type { ToolContext, ToolExecutionResult } from '../types.js';
4
2
  import { listTasks } from '../../tasks/task-store.js';
5
3
 
6
- const definition: ToolDefinition = {
7
- name: 'task_list',
8
- description: 'List saved task templates (reusable definitions). To see your active Tasks (work items), use task_list_show instead.',
9
- input_schema: {
10
- type: 'object',
11
- properties: {},
12
- },
13
- };
4
+ export async function executeTaskList(
5
+ _input: Record<string, unknown>,
6
+ _context: ToolContext,
7
+ ): Promise<ToolExecutionResult> {
8
+ try {
9
+ const tasks = listTasks();
14
10
 
15
- class TaskListTool implements Tool {
16
- name = 'task_list';
17
- description = definition.description;
18
- category = 'tasks';
19
- defaultRiskLevel = RiskLevel.Low;
11
+ if (tasks.length === 0) {
12
+ return { content: 'No task templates found. Use task_save to create one from a conversation.\n\nTip: To see your active Tasks (work items in the queue), use the task_list_show tool.', isError: false };
13
+ }
20
14
 
21
- getDefinition(): ToolDefinition {
22
- return definition;
23
- }
15
+ const lines = [`Found ${tasks.length} task template(s):`, ''];
24
16
 
25
- async execute(_input: Record<string, unknown>, _context: ToolContext): Promise<ToolExecutionResult> {
26
- try {
27
- const tasks = listTasks();
17
+ for (const task of tasks) {
18
+ const requiredTools: string[] = task.requiredTools ? JSON.parse(task.requiredTools) : [];
19
+ const createdAt = new Date(task.createdAt).toISOString();
28
20
 
29
- if (tasks.length === 0) {
30
- return { content: 'No task templates found. Use task_save to create one from a conversation.\n\nTip: To see your active Tasks (work items in the queue), use the task_list_show tool.', isError: false };
21
+ lines.push(`- ${task.title}`);
22
+ lines.push(` ID: ${task.id}`);
23
+ lines.push(` Status: ${task.status}`);
24
+ lines.push(` Created: ${createdAt}`);
25
+ if (requiredTools.length > 0) {
26
+ lines.push(` Required tools: ${requiredTools.join(', ')}`);
31
27
  }
32
-
33
- const lines = [`Found ${tasks.length} task template(s):`, ''];
34
-
35
- for (const task of tasks) {
36
- const requiredTools: string[] = task.requiredTools ? JSON.parse(task.requiredTools) : [];
37
- const createdAt = new Date(task.createdAt).toISOString();
38
-
39
- lines.push(`- ${task.title}`);
40
- lines.push(` ID: ${task.id}`);
41
- lines.push(` Status: ${task.status}`);
42
- lines.push(` Created: ${createdAt}`);
43
- if (requiredTools.length > 0) {
44
- lines.push(` Required tools: ${requiredTools.join(', ')}`);
28
+ if (task.inputSchema) {
29
+ const schema = JSON.parse(task.inputSchema) as { properties?: Record<string, unknown> };
30
+ if (schema.properties) {
31
+ lines.push(` Inputs: ${Object.keys(schema.properties).join(', ')}`);
45
32
  }
46
- if (task.inputSchema) {
47
- const schema = JSON.parse(task.inputSchema) as { properties?: Record<string, unknown> };
48
- if (schema.properties) {
49
- lines.push(` Inputs: ${Object.keys(schema.properties).join(', ')}`);
50
- }
51
- }
52
- lines.push('');
53
33
  }
34
+ lines.push('');
35
+ }
54
36
 
55
- lines.push('Tip: To see your active Tasks (work items in the queue), use the task_list_show tool.');
37
+ lines.push('Tip: To see your active Tasks (work items in the queue), use the task_list_show tool.');
56
38
 
57
- return { content: lines.join('\n'), isError: false };
58
- } catch (err) {
59
- const msg = err instanceof Error ? err.message : String(err);
60
- return { content: `Error: ${msg}`, isError: true };
61
- }
39
+ return { content: lines.join('\n'), isError: false };
40
+ } catch (err) {
41
+ const msg = err instanceof Error ? err.message : String(err);
42
+ return { content: `Error: ${msg}`, isError: true };
62
43
  }
63
44
  }
64
-
65
- export const taskListTool = new TaskListTool();
@@ -1,125 +1,97 @@
1
- import { RiskLevel } from '../../permissions/types.js';
2
- import type { Tool, ToolContext, ToolExecutionResult } from '../types.js';
3
- import type { ToolDefinition } from '../../providers/types.js';
1
+ import type { ToolContext, ToolExecutionResult } from '../types.js';
4
2
  import { getTask, listTasks } from '../../tasks/task-store.js';
5
3
  import { renderTemplate } from '../../tasks/task-runner.js';
6
-
7
- const definition: ToolDefinition = {
8
- name: 'task_run',
9
- description:
10
- 'Run a task template. Resolves the template by name (fuzzy match) or ID, renders it with the provided inputs, and returns the rendered prompt for execution as a Task (work item).',
11
- input_schema: {
12
- type: 'object',
13
- properties: {
14
- task_name: {
15
- type: 'string',
16
- description: 'Fuzzy match a task template by name (case-insensitive substring match)',
17
- },
18
- task_id: {
19
- type: 'string',
20
- description: 'Exact match a task template by ID',
21
- },
22
- inputs: {
23
- type: 'object',
24
- description: 'Values for template placeholders (e.g. {"file_path": "/tmp/foo.txt", "url": "https://example.com"})',
25
- additionalProperties: { type: 'string' },
26
- },
27
- },
28
- },
29
- };
30
-
31
- class TaskRunTool implements Tool {
32
- name = 'task_run';
33
- description = definition.description;
34
- category = 'tasks';
35
- defaultRiskLevel = RiskLevel.Low;
36
-
37
- getDefinition(): ToolDefinition {
38
- return definition;
4
+ import { identifyEntityById, buildWorkItemMismatchError } from '../../work-items/work-item-store.js';
5
+
6
+ export async function executeTaskRun(
7
+ input: Record<string, unknown>,
8
+ _context: ToolContext,
9
+ ): Promise<ToolExecutionResult> {
10
+ const taskName = input.task_name as string | undefined;
11
+ const taskId = input.task_id as string | undefined;
12
+ const inputs = (input.inputs as Record<string, string> | undefined) ?? {};
13
+
14
+ if (!taskName && !taskId) {
15
+ return {
16
+ content: 'Error: At least one of task_name or task_id must be provided',
17
+ isError: true,
18
+ };
39
19
  }
40
20
 
41
- async execute(input: Record<string, unknown>, _context: ToolContext): Promise<ToolExecutionResult> {
42
- const taskName = input.task_name as string | undefined;
43
- const taskId = input.task_id as string | undefined;
44
- const inputs = (input.inputs as Record<string, string> | undefined) ?? {};
45
-
46
- if (!taskName && !taskId) {
47
- return {
48
- content: 'Error: At least one of task_name or task_id must be provided',
49
- isError: true,
50
- };
51
- }
52
-
53
- try {
54
- // Resolve the task
55
- let task;
21
+ try {
22
+ // Resolve the task
23
+ let task;
56
24
 
57
- if (taskId) {
58
- task = getTask(taskId);
59
- if (!task) {
60
- return { content: `Error: No task found with ID "${taskId}"`, isError: true };
61
- }
62
- } else if (taskName) {
63
- const allTasks = listTasks();
64
- const needle = taskName.toLowerCase();
65
-
66
- // Case-insensitive substring match
67
- task = allTasks.find((t) => t.title.toLowerCase().includes(needle));
68
-
69
- if (!task) {
70
- if (allTasks.length === 0) {
71
- return { content: 'Error: No task templates found. Use task_save to create one first.', isError: true };
72
- }
73
- const available = allTasks.map((t) => ` - "${t.title}" (${t.id})`).join('\n');
25
+ if (taskId) {
26
+ task = getTask(taskId);
27
+ if (!task) {
28
+ const entity = identifyEntityById(taskId);
29
+ if (entity.type === 'work_item') {
74
30
  return {
75
- content: `Error: No task template matching "${taskName}" found. Available templates:\n${available}`,
31
+ content: `Error: ${buildWorkItemMismatchError(taskId, entity.title!, 'task_list_show to view work items, or task_list_update to modify them')}`,
76
32
  isError: true,
77
33
  };
78
34
  }
35
+ return { content: `Error: No task template found with ID "${taskId}". Use task_list to see available templates.`, isError: true };
79
36
  }
37
+ } else if (taskName) {
38
+ const allTasks = listTasks();
39
+ const needle = taskName.toLowerCase();
40
+
41
+ // Case-insensitive substring match
42
+ task = allTasks.find((t) => t.title.toLowerCase().includes(needle));
80
43
 
81
44
  if (!task) {
82
- return { content: 'Error: Could not resolve task template', isError: true };
45
+ if (allTasks.length === 0) {
46
+ return { content: 'Error: No task templates found. Use task_save to create one first.', isError: true };
47
+ }
48
+ const available = allTasks.map((t) => ` - "${t.title}" (${t.id})`).join('\n');
49
+ return {
50
+ content: `Error: No task template matching "${taskName}" found. Available templates:\n${available}`,
51
+ isError: true,
52
+ };
83
53
  }
54
+ }
55
+
56
+ if (!task) {
57
+ return { content: 'Error: Could not resolve task template', isError: true };
58
+ }
84
59
 
85
- // Check if required inputs are provided
86
- if (task.inputSchema) {
87
- const schema = JSON.parse(task.inputSchema) as { properties?: Record<string, unknown> };
88
- if (schema.properties) {
89
- const requiredKeys = Object.keys(schema.properties);
90
- const missingKeys = requiredKeys.filter((k) => !(k in inputs));
91
- if (missingKeys.length > 0) {
92
- return {
93
- content: `Error: Missing required inputs: ${missingKeys.join(', ')}. Provide them in the "inputs" parameter.`,
94
- isError: true,
95
- };
96
- }
60
+ // Check if required inputs are provided
61
+ if (task.inputSchema) {
62
+ const schema = JSON.parse(task.inputSchema) as { properties?: Record<string, unknown> };
63
+ if (schema.properties) {
64
+ const requiredKeys = Object.keys(schema.properties);
65
+ const missingKeys = requiredKeys.filter((k) => !(k in inputs));
66
+ if (missingKeys.length > 0) {
67
+ return {
68
+ content: `Error: Missing required inputs: ${missingKeys.join(', ')}. Provide them in the "inputs" parameter.`,
69
+ isError: true,
70
+ };
97
71
  }
98
72
  }
73
+ }
99
74
 
100
- // Render the template
101
- const rendered = renderTemplate(task.template, inputs);
102
-
103
- const requiredTools: string[] = task.requiredTools ? JSON.parse(task.requiredTools) : [];
75
+ // Render the template
76
+ const rendered = renderTemplate(task.template, inputs);
104
77
 
105
- const lines = [
106
- `Template "${task.title}" resolved and rendered.`,
107
- ``,
108
- `I'll now execute the following:`,
109
- ``,
110
- rendered,
111
- ];
78
+ const requiredTools: string[] = task.requiredTools ? JSON.parse(task.requiredTools) : [];
112
79
 
113
- if (requiredTools.length > 0) {
114
- lines.push('', `Required tools: ${requiredTools.join(', ')}`);
115
- }
80
+ const lines = [
81
+ `Template "${task.title}" resolved and rendered.`,
82
+ ``,
83
+ `I'll now execute the following:`,
84
+ ``,
85
+ rendered,
86
+ ];
116
87
 
117
- return { content: lines.join('\n'), isError: false };
118
- } catch (err) {
119
- const msg = err instanceof Error ? err.message : String(err);
120
- return { content: `Error: ${msg}`, isError: true };
88
+ if (requiredTools.length > 0) {
89
+ lines.push('', `Required tools: ${requiredTools.join(', ')}`);
121
90
  }
91
+
92
+ return { content: lines.join('\n'), isError: false };
93
+ } catch (err) {
94
+ const msg = err instanceof Error ? err.message : String(err);
95
+ return { content: `Error: ${msg}`, isError: true };
122
96
  }
123
97
  }
124
-
125
- export const taskRunTool = new TaskRunTool();
@@ -1,79 +1,47 @@
1
- import { RiskLevel } from '../../permissions/types.js';
2
- import type { Tool, ToolContext, ToolExecutionResult } from '../types.js';
3
- import type { ToolDefinition } from '../../providers/types.js';
1
+ import type { ToolContext, ToolExecutionResult } from '../types.js';
4
2
  import { compileTaskFromConversation, saveCompiledTask } from '../../tasks/task-compiler.js';
5
3
 
6
- const definition: ToolDefinition = {
7
- name: 'task_save',
8
- description:
9
- 'Save the current conversation as a reusable task template (definition). This is NOT for adding items to the user\'s task queue — use task_list_add for that. task_save extracts the conversation pattern into a reusable definition with placeholders that can be run later with different inputs.',
10
- input_schema: {
11
- type: 'object',
12
- properties: {
13
- conversation_id: {
14
- type: 'string',
15
- description: 'The conversation to capture as a task template. If omitted, uses the current conversation.',
16
- },
17
- title: {
18
- type: 'string',
19
- description: 'Optional override for the auto-generated task title',
20
- },
21
- },
22
- required: [],
23
- },
24
- };
25
-
26
- class TaskSaveTool implements Tool {
27
- name = 'task_save';
28
- description = definition.description;
29
- category = 'tasks';
30
- defaultRiskLevel = RiskLevel.Low;
31
-
32
- getDefinition(): ToolDefinition {
33
- return definition;
4
+ export async function executeTaskSave(
5
+ input: Record<string, unknown>,
6
+ context: ToolContext,
7
+ ): Promise<ToolExecutionResult> {
8
+ const conversationId = (input.conversation_id as string | undefined) || context.conversationId;
9
+ if (!conversationId || typeof conversationId !== 'string' || conversationId.trim().length === 0) {
10
+ return { content: 'Error: conversation_id is required and must be a non-empty string', isError: true };
34
11
  }
35
12
 
36
- async execute(input: Record<string, unknown>, context: ToolContext): Promise<ToolExecutionResult> {
37
- const conversationId = (input.conversation_id as string | undefined) || context.conversationId;
38
- if (!conversationId || typeof conversationId !== 'string' || conversationId.trim().length === 0) {
39
- return { content: 'Error: conversation_id is required and must be a non-empty string', isError: true };
40
- }
41
-
42
- const titleOverride = input.title as string | undefined;
13
+ const titleOverride = input.title as string | undefined;
43
14
 
44
- try {
45
- const compiled = compileTaskFromConversation(conversationId);
15
+ try {
16
+ const compiled = compileTaskFromConversation(conversationId);
46
17
 
47
- if (titleOverride && typeof titleOverride === 'string' && titleOverride.trim().length > 0) {
48
- compiled.title = titleOverride.trim();
49
- }
18
+ if (titleOverride && typeof titleOverride === 'string' && titleOverride.trim().length > 0) {
19
+ compiled.title = titleOverride.trim();
20
+ }
50
21
 
51
- const task = saveCompiledTask(compiled, conversationId);
22
+ const task = saveCompiledTask(compiled, conversationId);
52
23
 
53
- const lines = [
54
- `Task saved successfully.`,
55
- ` ID: ${task.id}`,
56
- ` Title: ${task.title}`,
57
- ` Template: ${task.template}`,
58
- ];
24
+ const lines = [
25
+ `Task saved successfully.`,
26
+ ` ID: ${task.id}`,
27
+ ` Title: ${task.title}`,
28
+ ` Template: ${task.template}`,
29
+ ];
59
30
 
60
- if (compiled.requiredTools.length > 0) {
61
- lines.push(` Required tools: ${compiled.requiredTools.join(', ')}`);
62
- }
31
+ if (compiled.requiredTools.length > 0) {
32
+ lines.push(` Required tools: ${compiled.requiredTools.join(', ')}`);
33
+ }
63
34
 
64
- if (compiled.inputSchema) {
65
- const props = (compiled.inputSchema as Record<string, unknown>).properties as Record<string, unknown> | undefined;
66
- if (props) {
67
- lines.push(` Input placeholders: ${Object.keys(props).join(', ')}`);
68
- }
35
+ if (compiled.inputSchema) {
36
+ const props = (compiled.inputSchema as Record<string, unknown>).properties as Record<string, unknown> | undefined;
37
+ if (props) {
38
+ lines.push(` Input placeholders: ${Object.keys(props).join(', ')}`);
69
39
  }
70
-
71
- return { content: lines.join('\n'), isError: false };
72
- } catch (err) {
73
- const msg = err instanceof Error ? err.message : String(err);
74
- return { content: `Error: ${msg}`, isError: true };
75
40
  }
41
+
42
+ return { content: lines.join('\n'), isError: false };
43
+ } catch (err) {
44
+ const msg = err instanceof Error ? err.message : String(err);
45
+ return { content: `Error: ${msg}`, isError: true };
76
46
  }
77
47
  }
78
-
79
- export const taskSaveTool = new TaskSaveTool();