vellum 0.2.1 → 0.2.7

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 +71 -100
  3. package/package.json +5 -3
  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 +305 -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-twilio-config.test.ts +221 -0
  36. package/src/__tests__/handlers-twitter-config.test.ts +718 -0
  37. package/src/__tests__/intent-routing.test.ts +64 -57
  38. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +237 -0
  39. package/src/__tests__/ipc-snapshot.test.ts +71 -28
  40. package/src/__tests__/llm-usage-store.test.ts +3 -8
  41. package/src/__tests__/media-generate-image.test.ts +1 -1
  42. package/src/__tests__/media-reuse-story.e2e.test.ts +7 -7
  43. package/src/__tests__/memory-regressions.test.ts +100 -2
  44. package/src/__tests__/memory-retrieval.benchmark.test.ts +430 -0
  45. package/src/__tests__/parallel-tool.benchmark.test.ts +294 -0
  46. package/src/__tests__/playbook-tools.test.ts +342 -0
  47. package/src/__tests__/profile-compiler.test.ts +2 -1
  48. package/src/__tests__/provider-commit-message-generator.test.ts +303 -0
  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 +5 -3
  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 +8 -4
  58. package/src/__tests__/run-orchestrator.test.ts +4 -4
  59. package/src/__tests__/runtime-attachment-metadata.test.ts +7 -6
  60. package/src/__tests__/runtime-runs-http.test.ts +4 -4
  61. package/src/__tests__/runtime-runs.test.ts +4 -4
  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-conflict-gate.test.ts +28 -25
  67. package/src/__tests__/session-error.test.ts +28 -0
  68. package/src/__tests__/session-init.benchmark.test.ts +462 -0
  69. package/src/__tests__/session-queue.test.ts +71 -48
  70. package/src/__tests__/session-runtime-assembly.test.ts +161 -0
  71. package/src/__tests__/session-surfaces-task-progress.test.ts +104 -0
  72. package/src/__tests__/signup-e2e.test.ts +2 -1
  73. package/src/__tests__/skill-projection.benchmark.test.ts +328 -0
  74. package/src/__tests__/skill-script-runner.test.ts +159 -0
  75. package/src/__tests__/speaker-identification.test.ts +52 -0
  76. package/src/__tests__/subagent-manager-notify.test.ts +42 -10
  77. package/src/__tests__/subagent-tools.test.ts +141 -41
  78. package/src/__tests__/task-compiler.test.ts +2 -1
  79. package/src/__tests__/task-runner.test.ts +2 -1
  80. package/src/__tests__/task-scheduler.test.ts +2 -1
  81. package/src/__tests__/task-tools.test.ts +49 -56
  82. package/src/__tests__/tool-audit-listener.test.ts +1 -0
  83. package/src/__tests__/tool-domain-event-publisher.test.ts +2 -0
  84. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +500 -0
  85. package/src/__tests__/tool-executor.test.ts +13 -17
  86. package/src/__tests__/turn-commit.test.ts +218 -3
  87. package/src/__tests__/twilio-provider.test.ts +143 -0
  88. package/src/__tests__/twilio-routes.test.ts +789 -0
  89. package/src/__tests__/twitter-auth-handler.test.ts +581 -0
  90. package/src/__tests__/view-image-tool.test.ts +217 -0
  91. package/src/__tests__/workspace-git-service.test.ts +186 -0
  92. package/src/__tests__/workspace-heartbeat-service.test.ts +13 -3
  93. package/src/agent-heartbeat/agent-heartbeat-service.ts +155 -0
  94. package/src/bundler/app-bundler.ts +12 -8
  95. package/src/calls/__tests__/twilio-webhook-urls.test.ts +162 -0
  96. package/src/calls/call-bridge.ts +95 -0
  97. package/src/calls/call-constants.ts +43 -5
  98. package/src/calls/call-domain.ts +276 -0
  99. package/src/calls/call-orchestrator.ts +43 -17
  100. package/src/calls/call-recovery.ts +207 -0
  101. package/src/calls/call-state-machine.ts +68 -0
  102. package/src/calls/call-store.ts +192 -5
  103. package/src/calls/relay-server.ts +41 -4
  104. package/src/calls/speaker-identification.ts +213 -0
  105. package/src/calls/twilio-config.ts +8 -8
  106. package/src/calls/twilio-provider.ts +13 -9
  107. package/src/calls/twilio-routes.ts +90 -76
  108. package/src/calls/twilio-webhook-urls.ts +50 -0
  109. package/src/calls/types.ts +1 -1
  110. package/src/cli/config-commands.ts +334 -0
  111. package/src/cli/core-commands.ts +776 -0
  112. package/src/cli/doordash.ts +251 -1
  113. package/src/cli/ipc-client.ts +82 -0
  114. package/src/cli/map.ts +270 -0
  115. package/src/cli/twitter.ts +575 -0
  116. package/src/cli.ts +7 -5
  117. package/src/commands/__tests__/cc-command-registry.test.ts +319 -0
  118. package/src/commands/cc-command-registry.ts +209 -0
  119. package/src/config/bundled-skills/contacts/SKILL.md +39 -0
  120. package/src/config/bundled-skills/contacts/TOOLS.json +122 -0
  121. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +9 -0
  122. package/src/config/bundled-skills/contacts/tools/contact-search.ts +9 -0
  123. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +9 -0
  124. package/src/config/bundled-skills/document/SKILL.md +18 -0
  125. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  126. package/src/config/bundled-skills/document/tools/document-create.ts +9 -0
  127. package/src/config/bundled-skills/document/tools/document-update.ts +9 -0
  128. package/src/config/bundled-skills/doordash/SKILL.md +82 -23
  129. package/src/config/bundled-skills/followups/SKILL.md +32 -0
  130. package/src/config/bundled-skills/followups/TOOLS.json +100 -0
  131. package/src/config/bundled-skills/followups/tools/followup-create.ts +9 -0
  132. package/src/config/bundled-skills/followups/tools/followup-list.ts +9 -0
  133. package/src/config/bundled-skills/followups/tools/followup-resolve.ts +9 -0
  134. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +1 -23
  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 +34 -0
  179. package/src/config/loader.ts +4 -1
  180. package/src/config/schema.ts +165 -1
  181. package/src/config/system-prompt.ts +61 -16
  182. package/src/config/templates/IDENTITY.md +7 -0
  183. package/src/config/types.ts +4 -0
  184. package/src/config/vellum-skills/telegram-setup/SKILL.md +1 -5
  185. package/src/contacts/contact-store.ts +4 -4
  186. package/src/daemon/assistant-attachments.ts +10 -0
  187. package/src/daemon/classifier.ts +3 -1
  188. package/src/daemon/computer-use-session.ts +3 -1
  189. package/src/daemon/date-context.ts +136 -0
  190. package/src/daemon/handlers/apps.ts +16 -1
  191. package/src/daemon/handlers/browser.ts +54 -0
  192. package/src/daemon/handlers/computer-use.ts +7 -1
  193. package/src/daemon/handlers/config.ts +205 -5
  194. package/src/daemon/handlers/diagnostics.ts +5 -1
  195. package/src/daemon/handlers/documents.ts +18 -29
  196. package/src/daemon/handlers/home-base.ts +5 -1
  197. package/src/daemon/handlers/index.ts +40 -277
  198. package/src/daemon/handlers/misc.ts +9 -1
  199. package/src/daemon/handlers/publish.ts +6 -1
  200. package/src/daemon/handlers/sessions.ts +65 -12
  201. package/src/daemon/handlers/shared.ts +36 -1
  202. package/src/daemon/handlers/signing.ts +37 -0
  203. package/src/daemon/handlers/skills.ts +20 -6
  204. package/src/daemon/handlers/subagents.ts +8 -3
  205. package/src/daemon/handlers/twitter-auth.ts +169 -0
  206. package/src/daemon/handlers/work-items.ts +384 -68
  207. package/src/daemon/ipc-contract-inventory.json +32 -4
  208. package/src/daemon/ipc-contract.ts +156 -37
  209. package/src/daemon/ipc-protocol.ts +7 -2
  210. package/src/daemon/lifecycle.ts +21 -0
  211. package/src/daemon/main.ts +10 -4
  212. package/src/daemon/ride-shotgun-handler.ts +75 -10
  213. package/src/daemon/server.ts +143 -26
  214. package/src/daemon/session-agent-loop.ts +922 -0
  215. package/src/daemon/session-attachments.ts +28 -5
  216. package/src/daemon/session-conflict-gate.ts +18 -109
  217. package/src/daemon/session-error.ts +24 -3
  218. package/src/daemon/session-lifecycle.ts +147 -0
  219. package/src/daemon/session-media-retry.ts +147 -0
  220. package/src/daemon/session-messaging.ts +145 -0
  221. package/src/daemon/session-notifiers.ts +164 -0
  222. package/src/daemon/session-process.ts +2 -2
  223. package/src/daemon/session-queue-manager.ts +1 -0
  224. package/src/daemon/session-runtime-assembly.ts +52 -0
  225. package/src/daemon/session-skill-tools.ts +124 -5
  226. package/src/daemon/session-slash.ts +3 -0
  227. package/src/daemon/session-surfaces.ts +77 -2
  228. package/src/daemon/session-tool-setup.ts +216 -2
  229. package/src/daemon/session-usage.ts +0 -2
  230. package/src/daemon/session.ts +114 -1404
  231. package/src/daemon/video-thumbnail.ts +60 -0
  232. package/src/doordash/client.ts +121 -27
  233. package/src/doordash/queries.ts +1 -2
  234. package/src/export/formatter.ts +3 -1
  235. package/src/followups/followup-store.ts +4 -2
  236. package/src/followups/types.ts +6 -0
  237. package/src/hooks/templates.ts +1 -1
  238. package/src/index.ts +32 -1153
  239. package/src/memory/attachments-store.ts +28 -83
  240. package/src/memory/channel-delivery-store.ts +7 -21
  241. package/src/memory/clarification-resolver.ts +6 -5
  242. package/src/memory/conflict-intent.ts +114 -0
  243. package/src/memory/contradiction-checker.ts +3 -2
  244. package/src/memory/conversation-key-store.ts +10 -29
  245. package/src/memory/conversation-store.ts +2 -1
  246. package/src/memory/db.ts +96 -2
  247. package/src/memory/entity-extractor.ts +6 -3
  248. package/src/memory/items-extractor.ts +5 -4
  249. package/src/memory/job-handlers/conflict.ts +23 -1
  250. package/src/memory/jobs-store.ts +3 -2
  251. package/src/memory/llm-usage-store.ts +1 -2
  252. package/src/memory/runs-store.ts +1 -2
  253. package/src/memory/schema.ts +23 -2
  254. package/src/messaging/style-analyzer.ts +3 -2
  255. package/src/messaging/thread-summarizer.ts +8 -12
  256. package/src/messaging/triage-engine.ts +4 -2
  257. package/src/providers/openrouter/client.ts +20 -0
  258. package/src/providers/registry.ts +8 -0
  259. package/src/runtime/gateway-client.ts +36 -0
  260. package/src/runtime/http-server.ts +166 -22
  261. package/src/runtime/routes/attachment-routes.ts +2 -3
  262. package/src/runtime/routes/call-routes.ts +140 -0
  263. package/src/runtime/routes/channel-routes.ts +125 -88
  264. package/src/runtime/routes/conversation-routes.ts +5 -5
  265. package/src/runtime/routes/run-routes.ts +2 -2
  266. package/src/runtime/run-orchestrator.ts +9 -3
  267. package/src/schedule/recurrence-engine.ts +138 -0
  268. package/src/schedule/recurrence-types.ts +67 -0
  269. package/src/schedule/schedule-store.ts +102 -57
  270. package/src/schedule/scheduler.ts +9 -6
  271. package/src/security/oauth2.ts +29 -4
  272. package/src/security/secret-allowlist.ts +46 -0
  273. package/src/skills/clawhub.ts +1 -1
  274. package/src/subagent/manager.ts +40 -8
  275. package/src/swarm/backend-claude-code.ts +64 -9
  276. package/src/swarm/worker-prompts.ts +2 -1
  277. package/src/tasks/SPEC.md +34 -28
  278. package/src/tasks/ephemeral-permissions.ts +16 -7
  279. package/src/tasks/task-compiler.ts +5 -4
  280. package/src/tasks/task-runner.ts +10 -5
  281. package/src/tasks/task-scheduler.ts +1 -1
  282. package/src/tasks/tool-sanitizer.ts +36 -0
  283. package/src/tools/assets/search.ts +4 -4
  284. package/src/tools/browser/api-map.ts +293 -0
  285. package/src/tools/browser/auto-navigate.ts +270 -0
  286. package/src/tools/browser/browser-execution.ts +2 -1
  287. package/src/tools/browser/browser-manager.ts +2 -2
  288. package/src/tools/browser/network-recorder.ts +5 -4
  289. package/src/tools/browser/x-auto-navigate.ts +207 -0
  290. package/src/tools/calls/call-end.ts +17 -67
  291. package/src/tools/calls/call-start.ts +24 -85
  292. package/src/tools/calls/call-status.ts +35 -51
  293. package/src/tools/claude-code/claude-code.ts +207 -11
  294. package/src/tools/contacts/contact-merge.ts +46 -78
  295. package/src/tools/contacts/contact-search.ts +35 -79
  296. package/src/tools/contacts/contact-upsert.ts +35 -108
  297. package/src/tools/credentials/vault.ts +20 -4
  298. package/src/tools/document/document-tool.ts +71 -144
  299. package/src/tools/executor.ts +129 -10
  300. package/src/tools/followups/followup_create.ts +46 -88
  301. package/src/tools/followups/followup_list.ts +34 -74
  302. package/src/tools/followups/followup_resolve.ts +31 -66
  303. package/src/tools/host-terminal/cli-discover.ts +2 -1
  304. package/src/tools/host-terminal/host-shell.ts +10 -0
  305. package/src/tools/memory/handlers.ts +5 -4
  306. package/src/tools/network/__tests__/web-search.test.ts +427 -0
  307. package/src/tools/network/script-proxy/__tests__/logging.test.ts +248 -0
  308. package/src/tools/network/script-proxy/__tests__/policy.test.ts +234 -0
  309. package/src/tools/network/script-proxy/__tests__/router.test.ts +76 -0
  310. package/src/tools/network/web-fetch.ts +18 -6
  311. package/src/tools/playbooks/index.ts +4 -5
  312. package/src/tools/playbooks/playbook-create.ts +3 -47
  313. package/src/tools/playbooks/playbook-delete.ts +1 -25
  314. package/src/tools/playbooks/playbook-list.ts +1 -28
  315. package/src/tools/playbooks/playbook-update.ts +3 -51
  316. package/src/tools/reminder/reminder.ts +5 -78
  317. package/src/tools/schedule/create.ts +69 -74
  318. package/src/tools/schedule/delete.ts +21 -47
  319. package/src/tools/schedule/list.ts +55 -74
  320. package/src/tools/schedule/update.ts +77 -84
  321. package/src/tools/subagent/abort.ts +29 -58
  322. package/src/tools/subagent/message.ts +30 -63
  323. package/src/tools/subagent/read.ts +53 -84
  324. package/src/tools/subagent/spawn.ts +43 -82
  325. package/src/tools/subagent/status.ts +42 -71
  326. package/src/tools/swarm/delegate.ts +2 -1
  327. package/src/tools/tasks/index.ts +8 -8
  328. package/src/tools/tasks/task-delete.ts +60 -88
  329. package/src/tools/tasks/task-list.ts +31 -52
  330. package/src/tools/tasks/task-run.ts +72 -108
  331. package/src/tools/tasks/task-save.ts +33 -65
  332. package/src/tools/tasks/work-item-enqueue.ts +183 -215
  333. package/src/tools/tasks/work-item-list.ts +33 -63
  334. package/src/tools/tasks/work-item-remove.ts +45 -97
  335. package/src/tools/tasks/work-item-update.ts +91 -163
  336. package/src/tools/terminal/backends/native.ts +3 -1
  337. package/src/tools/tool-manifest.ts +0 -62
  338. package/src/tools/types.ts +6 -0
  339. package/src/tools/ui-surface/definitions.ts +3 -1
  340. package/src/tools/watch/screen-watch.ts +3 -1
  341. package/src/tools/watcher/create.ts +52 -98
  342. package/src/tools/watcher/delete.ts +20 -46
  343. package/src/tools/watcher/digest.ts +36 -70
  344. package/src/tools/watcher/list.ts +49 -79
  345. package/src/tools/watcher/update.ts +45 -91
  346. package/src/twitter/client.ts +690 -0
  347. package/src/twitter/session.ts +91 -0
  348. package/src/usage/types.ts +0 -1
  349. package/src/util/truncate.ts +6 -0
  350. package/src/watcher/providers/slack.ts +2 -1
  351. package/src/watcher/watcher-store.ts +3 -2
  352. package/src/work-items/work-item-store.ts +27 -2
  353. package/src/workspace/commit-message-enrichment-service.ts +31 -7
  354. package/src/workspace/git-service.ts +87 -22
  355. package/src/workspace/provider-commit-message-generator.ts +269 -0
  356. package/src/workspace/turn-commit.ts +62 -3
  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,17 +1,16 @@
1
1
  import { and, eq } from 'drizzle-orm';
2
2
  import { v4 as uuid } from 'uuid';
3
- import { RiskLevel } from '../../permissions/types.js';
4
3
  import type { ToolContext, ToolExecutionResult } from '../types.js';
5
- import { registerTool } from '../registry.js';
6
4
  import { getDb } from '../../memory/db.js';
7
5
  import { computeMemoryFingerprint } from '../../memory/fingerprint.js';
8
6
  import { memoryItems } from '../../memory/schema.js';
9
7
  import { enqueueMemoryJob } from '../../memory/jobs-store.js';
10
8
  import type { Playbook, PlaybookAutonomyLevel } from '../../playbooks/types.js';
9
+ import { truncate } from '../../util/truncate.js';
11
10
 
12
11
  const VALID_AUTONOMY_LEVELS = new Set<string>(['auto', 'draft', 'notify']);
13
12
 
14
- async function execute(input: Record<string, unknown>, context: ToolContext): Promise<ToolExecutionResult> {
13
+ export async function executePlaybookCreate(input: Record<string, unknown>, context: ToolContext): Promise<ToolExecutionResult> {
15
14
  const trigger = input.trigger as string;
16
15
  const action = input.action as string;
17
16
 
@@ -32,7 +31,7 @@ async function execute(input: Record<string, unknown>, context: ToolContext): Pr
32
31
 
33
32
  const playbook: Playbook = { trigger, channel, category, action, autonomyLevel, priority };
34
33
  const statement = JSON.stringify(playbook);
35
- const subject = `Playbook: ${trigger}`.slice(0, 80);
34
+ const subject = truncate(`Playbook: ${trigger}`, 80, '');
36
35
  const scopeId = context.memoryScopeId ?? 'default';
37
36
 
38
37
  const fingerprint = computeMemoryFingerprint(scopeId, 'playbook', subject, statement);
@@ -95,46 +94,3 @@ async function execute(input: Record<string, unknown>, context: ToolContext): Pr
95
94
  return { content: `Error creating playbook: ${msg}`, isError: true };
96
95
  }
97
96
  }
98
-
99
- registerTool({
100
- name: 'playbook_create',
101
- description: 'Create an action playbook — a trigger→action rule that tells the assistant how to handle incoming messages matching a pattern',
102
- category: 'playbook',
103
- defaultRiskLevel: RiskLevel.Low,
104
- getDefinition: () => ({
105
- name: 'playbook_create',
106
- description: 'Create an action playbook — a trigger→action rule that tells the assistant how to handle incoming messages matching a pattern',
107
- input_schema: {
108
- type: 'object',
109
- properties: {
110
- trigger: {
111
- type: 'string',
112
- description: 'Pattern or description that triggers this playbook (e.g. "meeting request", "from:ceo@*", "newsletter")',
113
- },
114
- action: {
115
- type: 'string',
116
- description: 'What to do when the trigger matches — natural language action description (e.g. "check calendar, propose 3 times")',
117
- },
118
- channel: {
119
- type: 'string',
120
- description: 'Channel this rule applies to (e.g. "email", "slack"), or "*" for all channels. Defaults to "*".',
121
- },
122
- category: {
123
- type: 'string',
124
- description: 'Free-form category for grouping (e.g. "scheduling", "triage"). Defaults to "general".',
125
- },
126
- autonomy_level: {
127
- type: 'string',
128
- enum: ['auto', 'draft', 'notify'],
129
- description: 'How much autonomy: "auto" = execute automatically, "draft" = draft for review, "notify" = notify only. Defaults to "draft".',
130
- },
131
- priority: {
132
- type: 'number',
133
- description: 'Relative priority — higher numbers take precedence. Defaults to 0.',
134
- },
135
- },
136
- required: ['trigger', 'action'],
137
- },
138
- }),
139
- execute,
140
- });
@@ -1,12 +1,10 @@
1
1
  import { and, eq } from 'drizzle-orm';
2
- import { RiskLevel } from '../../permissions/types.js';
3
2
  import type { ToolContext, ToolExecutionResult } from '../types.js';
4
- import { registerTool } from '../registry.js';
5
3
  import { getDb } from '../../memory/db.js';
6
4
  import { memoryItems } from '../../memory/schema.js';
7
5
  import { parsePlaybookStatement } from '../../playbooks/types.js';
8
6
 
9
- async function execute(input: Record<string, unknown>, context: ToolContext): Promise<ToolExecutionResult> {
7
+ export async function executePlaybookDelete(input: Record<string, unknown>, context: ToolContext): Promise<ToolExecutionResult> {
10
8
  const playbookId = input.playbook_id as string;
11
9
  if (!playbookId || typeof playbookId !== 'string') {
12
10
  return { content: 'Error: playbook_id is required and must be a string', isError: true };
@@ -52,25 +50,3 @@ async function execute(input: Record<string, unknown>, context: ToolContext): Pr
52
50
  return { content: `Error deleting playbook: ${msg}`, isError: true };
53
51
  }
54
52
  }
55
-
56
- registerTool({
57
- name: 'playbook_delete',
58
- description: 'Delete an action playbook rule',
59
- category: 'playbook',
60
- defaultRiskLevel: RiskLevel.Low,
61
- getDefinition: () => ({
62
- name: 'playbook_delete',
63
- description: 'Delete an action playbook rule',
64
- input_schema: {
65
- type: 'object',
66
- properties: {
67
- playbook_id: {
68
- type: 'string',
69
- description: 'ID of the playbook to delete (from playbook_list results)',
70
- },
71
- },
72
- required: ['playbook_id'],
73
- },
74
- }),
75
- execute,
76
- });
@@ -1,12 +1,10 @@
1
1
  import { and, desc, eq, isNull } from 'drizzle-orm';
2
- import { RiskLevel } from '../../permissions/types.js';
3
2
  import type { ToolContext, ToolExecutionResult } from '../types.js';
4
- import { registerTool } from '../registry.js';
5
3
  import { getDb } from '../../memory/db.js';
6
4
  import { memoryItems } from '../../memory/schema.js';
7
5
  import { parsePlaybookStatement } from '../../playbooks/types.js';
8
6
 
9
- async function execute(input: Record<string, unknown>, context: ToolContext): Promise<ToolExecutionResult> {
7
+ export async function executePlaybookList(input: Record<string, unknown>, context: ToolContext): Promise<ToolExecutionResult> {
10
8
  const scopeId = context.memoryScopeId ?? 'default';
11
9
  const channelFilter = typeof input.channel === 'string' ? input.channel : null;
12
10
  const categoryFilter = typeof input.category === 'string' ? input.category : null;
@@ -74,28 +72,3 @@ async function execute(input: Record<string, unknown>, context: ToolContext): Pr
74
72
  return { content: `Error listing playbooks: ${msg}`, isError: true };
75
73
  }
76
74
  }
77
-
78
- registerTool({
79
- name: 'playbook_list',
80
- description: 'List action playbooks, optionally filtered by channel or category',
81
- category: 'playbook',
82
- defaultRiskLevel: RiskLevel.Low,
83
- getDefinition: () => ({
84
- name: 'playbook_list',
85
- description: 'List action playbooks, optionally filtered by channel or category',
86
- input_schema: {
87
- type: 'object',
88
- properties: {
89
- channel: {
90
- type: 'string',
91
- description: 'Filter by channel (e.g. "email", "slack"). Omit to show all.',
92
- },
93
- category: {
94
- type: 'string',
95
- description: 'Filter by category (e.g. "scheduling", "triage"). Omit to show all.',
96
- },
97
- },
98
- },
99
- }),
100
- execute,
101
- });
@@ -1,17 +1,16 @@
1
1
  import { and, eq } from 'drizzle-orm';
2
- import { RiskLevel } from '../../permissions/types.js';
3
2
  import type { ToolContext, ToolExecutionResult } from '../types.js';
4
- import { registerTool } from '../registry.js';
5
3
  import { getDb } from '../../memory/db.js';
6
4
  import { computeMemoryFingerprint } from '../../memory/fingerprint.js';
7
5
  import { memoryItems } from '../../memory/schema.js';
8
6
  import { enqueueMemoryJob } from '../../memory/jobs-store.js';
9
7
  import { parsePlaybookStatement } from '../../playbooks/types.js';
10
8
  import type { Playbook, PlaybookAutonomyLevel } from '../../playbooks/types.js';
9
+ import { truncate } from '../../util/truncate.js';
11
10
 
12
11
  const VALID_AUTONOMY_LEVELS = new Set<string>(['auto', 'draft', 'notify']);
13
12
 
14
- async function execute(input: Record<string, unknown>, context: ToolContext): Promise<ToolExecutionResult> {
13
+ export async function executePlaybookUpdate(input: Record<string, unknown>, context: ToolContext): Promise<ToolExecutionResult> {
15
14
  const playbookId = input.playbook_id as string;
16
15
  if (!playbookId || typeof playbookId !== 'string') {
17
16
  return { content: 'Error: playbook_id is required and must be a string', isError: true };
@@ -55,7 +54,7 @@ async function execute(input: Record<string, unknown>, context: ToolContext): Pr
55
54
  };
56
55
 
57
56
  const statement = JSON.stringify(updated);
58
- const subject = `Playbook: ${updated.trigger}`.slice(0, 80);
57
+ const subject = truncate(`Playbook: ${updated.trigger}`, 80, '');
59
58
  const now = Date.now();
60
59
 
61
60
  const fingerprint = computeMemoryFingerprint(scopeId, 'playbook', subject, statement);
@@ -110,50 +109,3 @@ async function execute(input: Record<string, unknown>, context: ToolContext): Pr
110
109
  return { content: `Error updating playbook: ${msg}`, isError: true };
111
110
  }
112
111
  }
113
-
114
- registerTool({
115
- name: 'playbook_update',
116
- description: 'Update an existing action playbook rule',
117
- category: 'playbook',
118
- defaultRiskLevel: RiskLevel.Low,
119
- getDefinition: () => ({
120
- name: 'playbook_update',
121
- description: 'Update an existing action playbook rule',
122
- input_schema: {
123
- type: 'object',
124
- properties: {
125
- playbook_id: {
126
- type: 'string',
127
- description: 'ID of the playbook to update (from playbook_list results)',
128
- },
129
- trigger: {
130
- type: 'string',
131
- description: 'Updated trigger pattern',
132
- },
133
- action: {
134
- type: 'string',
135
- description: 'Updated action description',
136
- },
137
- channel: {
138
- type: 'string',
139
- description: 'Updated channel ("*" for all)',
140
- },
141
- category: {
142
- type: 'string',
143
- description: 'Updated category',
144
- },
145
- autonomy_level: {
146
- type: 'string',
147
- enum: ['auto', 'draft', 'notify'],
148
- description: 'Updated autonomy level',
149
- },
150
- priority: {
151
- type: 'number',
152
- description: 'Updated priority',
153
- },
154
- },
155
- required: ['playbook_id'],
156
- },
157
- }),
158
- execute,
159
- });
@@ -1,6 +1,4 @@
1
- import { RiskLevel } from '../../permissions/types.js';
2
- import type { Tool, ToolContext, ToolExecutionResult } from '../types.js';
3
- import type { ToolDefinition } from '../../providers/types.js';
1
+ import type { ToolExecutionResult } from '../types.js';
4
2
  import { formatLocalDate } from '../../schedule/schedule-store.js';
5
3
  import {
6
4
  insertReminder,
@@ -8,28 +6,9 @@ import {
8
6
  cancelReminder,
9
7
  } from './reminder-store.js';
10
8
 
11
- function executeReminder(input: Record<string, unknown>): ToolExecutionResult {
12
- const action = input.action as string | undefined;
13
- if (!action) {
14
- return { content: 'Error: action is required', isError: true };
15
- }
16
-
17
- switch (action) {
18
- case 'create':
19
- return createAction(input);
20
- case 'list':
21
- return listAction();
22
- case 'cancel':
23
- return cancelAction(input);
24
- default:
25
- return {
26
- content: `Error: Unknown action "${action}". Valid actions: create, list, cancel`,
27
- isError: true,
28
- };
29
- }
30
- }
9
+ // ── Exported execute functions ──────────────────────────────────────
31
10
 
32
- function createAction(input: Record<string, unknown>): ToolExecutionResult {
11
+ export function executeReminderCreate(input: Record<string, unknown>): ToolExecutionResult {
33
12
  const fireAtStr = input.fire_at as string | undefined;
34
13
  const label = input.label as string | undefined;
35
14
  const message = input.message as string | undefined;
@@ -68,7 +47,7 @@ function createAction(input: Record<string, unknown>): ToolExecutionResult {
68
47
  };
69
48
  }
70
49
 
71
- function listAction(): ToolExecutionResult {
50
+ export function executeReminderList(): ToolExecutionResult {
72
51
  const all = listReminders();
73
52
  if (all.length === 0) {
74
53
  return { content: 'No reminders found.', isError: false };
@@ -86,7 +65,7 @@ function listAction(): ToolExecutionResult {
86
65
  return { content: `Reminders:\n${lines.join('\n')}`, isError: false };
87
66
  }
88
67
 
89
- function cancelAction(input: Record<string, unknown>): ToolExecutionResult {
68
+ export function executeReminderCancel(input: Record<string, unknown>): ToolExecutionResult {
90
69
  const reminderId = input.reminder_id as string | undefined;
91
70
  if (!reminderId) {
92
71
  return { content: 'Error: reminder_id is required for cancel', isError: true };
@@ -99,55 +78,3 @@ function cancelAction(input: Record<string, unknown>): ToolExecutionResult {
99
78
 
100
79
  return { content: `Reminder "${reminderId}" cancelled.`, isError: false };
101
80
  }
102
-
103
- class ReminderTool implements Tool {
104
- name = 'reminder';
105
- description = 'Create, list, or cancel one-time time-based reminders. Reminders fire at a specific future time and either notify the user or execute a message through the assistant. Use this ONLY when the user wants a time-triggered notification (e.g. "remind me at 3pm", "remind me in 2 hours"). Do NOT use this for "add to my tasks" or "add to my queue" — use task_list_add for those requests.';
106
- category = 'reminder';
107
- defaultRiskLevel = RiskLevel.Low;
108
-
109
- getDefinition(): ToolDefinition {
110
- return {
111
- name: this.name,
112
- description: this.description,
113
- input_schema: {
114
- type: 'object',
115
- properties: {
116
- action: {
117
- type: 'string',
118
- enum: ['create', 'list', 'cancel'],
119
- description: 'Reminder action',
120
- },
121
- fire_at: {
122
- type: 'string',
123
- description: 'ISO 8601 timestamp for when the reminder should fire (required for create)',
124
- },
125
- label: {
126
- type: 'string',
127
- description: 'Human-readable label (required for create)',
128
- },
129
- message: {
130
- type: 'string',
131
- description: 'Content shown in notification (notify) or sent to agent (execute). Required for create.',
132
- },
133
- mode: {
134
- type: 'string',
135
- enum: ['notify', 'execute'],
136
- description: 'How the reminder fires. Defaults to notify.',
137
- },
138
- reminder_id: {
139
- type: 'string',
140
- description: 'Reminder ID (required for cancel)',
141
- },
142
- },
143
- required: ['action'],
144
- },
145
- };
146
- }
147
-
148
- async execute(input: Record<string, unknown>, _context: ToolContext): Promise<ToolExecutionResult> {
149
- return executeReminder(input);
150
- }
151
- }
152
-
153
- export const reminderTool = new ReminderTool();
@@ -1,86 +1,81 @@
1
- import { RiskLevel } from '../../permissions/types.js';
2
- import type { Tool, ToolContext, ToolExecutionResult } from '../types.js';
3
- import type { ToolDefinition } from '../../providers/types.js';
4
- import { registerTool } from '../registry.js';
1
+ import type { ToolContext, ToolExecutionResult } from '../types.js';
5
2
  import { createSchedule, isValidCronExpression, formatLocalDate, describeCronExpression } from '../../schedule/schedule-store.js';
3
+ import { normalizeScheduleSyntax } from '../../schedule/recurrence-types.js';
4
+ import { validateRruleSetLines } from '../../schedule/recurrence-engine.js';
6
5
 
7
- class ScheduleCreateTool implements Tool {
8
- name = 'schedule_create';
9
- description = 'Create a recurring scheduled automation that sends a message at a cron interval. ONLY use this when the user explicitly wants something to run on a schedule (e.g. "every day at 9am", "weekly on Mondays", "every hour"). Do NOT use this for "add to my tasks" or "add to my queue" — use task_list_add for those requests instead.';
10
- category = 'schedule';
11
- defaultRiskLevel = RiskLevel.Medium;
6
+ export async function executeScheduleCreate(
7
+ input: Record<string, unknown>,
8
+ _context: ToolContext,
9
+ ): Promise<ToolExecutionResult> {
10
+ const name = input.name as string;
11
+ const timezone = (input.timezone as string) ?? null;
12
+ const message = input.message as string;
13
+ const enabled = (input.enabled as boolean) ?? true;
12
14
 
13
- getDefinition(): ToolDefinition {
14
- return {
15
- name: this.name,
16
- description: this.description,
17
- input_schema: {
18
- type: 'object',
19
- properties: {
20
- name: {
21
- type: 'string',
22
- description: 'A human-readable name for the scheduled task',
23
- },
24
- cron_expression: {
25
- type: 'string',
26
- description: 'A cron expression (e.g. "0 9 * * 1-5" for weekdays at 9am). Supports standard 5-field cron syntax.',
27
- },
28
- timezone: {
29
- type: 'string',
30
- description: 'IANA timezone (e.g. "America/Los_Angeles"). Defaults to system timezone if omitted.',
31
- },
32
- message: {
33
- type: 'string',
34
- description: 'The message to send to the assistant when the schedule triggers',
35
- },
36
- enabled: {
37
- type: 'boolean',
38
- description: 'Whether the job is enabled immediately. Defaults to true.',
39
- },
40
- },
41
- required: ['name', 'cron_expression', 'message'],
42
- },
43
- };
15
+ if (!name || typeof name !== 'string') {
16
+ return { content: 'Error: name is required and must be a string', isError: true };
17
+ }
18
+ if (!message || typeof message !== 'string') {
19
+ return { content: 'Error: message is required and must be a string', isError: true };
44
20
  }
45
21
 
46
- async execute(input: Record<string, unknown>, _context: ToolContext): Promise<ToolExecutionResult> {
47
- const name = input.name as string;
48
- const cronExpression = input.cron_expression as string;
49
- const timezone = (input.timezone as string) ?? null;
50
- const message = input.message as string;
51
- const enabled = (input.enabled as boolean) ?? true;
22
+ // Resolve syntax and expression from new or legacy fields
23
+ const resolved = normalizeScheduleSyntax({
24
+ syntax: input.syntax as 'cron' | 'rrule' | undefined,
25
+ expression: input.expression as string | undefined,
26
+ legacyCronExpression: input.cron_expression as string | undefined,
27
+ });
52
28
 
53
- if (!name || typeof name !== 'string') {
54
- return { content: 'Error: name is required and must be a string', isError: true };
55
- }
56
- if (!cronExpression || typeof cronExpression !== 'string') {
57
- return { content: 'Error: cron_expression is required and must be a string', isError: true };
58
- }
59
- if (!message || typeof message !== 'string') {
60
- return { content: 'Error: message is required and must be a string', isError: true };
61
- }
62
- if (!isValidCronExpression(cronExpression)) {
63
- return { content: `Error: Invalid cron expression: "${cronExpression}"`, isError: true };
64
- }
29
+ if (!resolved) {
30
+ return { content: 'Error: expression (or cron_expression) is required', isError: true };
31
+ }
65
32
 
66
- try {
67
- const job = createSchedule({ name, cronExpression, timezone, message, enabled });
68
- const nextRunDate = formatLocalDate(job.nextRunAt);
33
+ // Syntax-specific pre-validation for actionable error messages
34
+ if (resolved.syntax === 'cron' && !isValidCronExpression(resolved.expression)) {
35
+ return { content: `Error: Invalid cron expression: "${resolved.expression}"`, isError: true };
36
+ }
37
+ if (resolved.syntax === 'rrule') {
38
+ if (typeof resolved.expression !== 'string') {
39
+ return { content: 'Error: expression must be a string', isError: true };
40
+ }
41
+ const setError = validateRruleSetLines(resolved.expression);
42
+ if (setError) {
69
43
  return {
70
- content: [
71
- `Schedule created successfully.`,
72
- ` Name: ${job.name}`,
73
- ` Schedule: ${describeCronExpression(job.cronExpression)}${job.timezone ? ` (${job.timezone})` : ''}`,
74
- ` Enabled: ${job.enabled}`,
75
- ` Next run: ${nextRunDate}`,
76
- ].join('\n'),
77
- isError: false,
44
+ content: `Error: ${setError}. Supported line types: DTSTART, RRULE, RDATE, EXDATE, EXRULE.`,
45
+ isError: true,
78
46
  };
79
- } catch (err) {
80
- const msg = err instanceof Error ? err.message : String(err);
81
- return { content: `Error creating schedule: ${msg}`, isError: true };
82
47
  }
83
48
  }
84
- }
85
49
 
86
- registerTool(new ScheduleCreateTool());
50
+ try {
51
+ const job = createSchedule({
52
+ name,
53
+ cronExpression: resolved.expression,
54
+ timezone,
55
+ message,
56
+ enabled,
57
+ syntax: resolved.syntax,
58
+ expression: resolved.expression,
59
+ });
60
+
61
+ const scheduleDescription = job.syntax === 'rrule'
62
+ ? job.expression
63
+ : describeCronExpression(job.cronExpression);
64
+
65
+ const nextRunDate = formatLocalDate(job.nextRunAt);
66
+ return {
67
+ content: [
68
+ `Schedule created successfully.`,
69
+ ` Name: ${job.name}`,
70
+ ` Syntax: ${job.syntax}`,
71
+ ` Schedule: ${scheduleDescription}${job.timezone ? ` (${job.timezone})` : ''}`,
72
+ ` Enabled: ${job.enabled}`,
73
+ ` Next run: ${nextRunDate}`,
74
+ ].join('\n'),
75
+ isError: false,
76
+ };
77
+ } catch (err) {
78
+ const msg = err instanceof Error ? err.message : String(err);
79
+ return { content: `Error creating schedule: ${msg}`, isError: true };
80
+ }
81
+ }
@@ -1,54 +1,28 @@
1
- import { RiskLevel } from '../../permissions/types.js';
2
- import type { Tool, ToolContext, ToolExecutionResult } from '../types.js';
3
- import type { ToolDefinition } from '../../providers/types.js';
4
- import { registerTool } from '../registry.js';
1
+ import type { ToolContext, ToolExecutionResult } from '../types.js';
5
2
  import { deleteSchedule, getSchedule } from '../../schedule/schedule-store.js';
6
3
 
7
- class ScheduleDeleteTool implements Tool {
8
- name = 'schedule_delete';
9
- description = 'Delete a recurring scheduled automation and all its run history';
10
- category = 'schedule';
11
- defaultRiskLevel = RiskLevel.High;
12
-
13
- getDefinition(): ToolDefinition {
14
- return {
15
- name: this.name,
16
- description: this.description,
17
- input_schema: {
18
- type: 'object',
19
- properties: {
20
- job_id: {
21
- type: 'string',
22
- description: 'The ID of the schedule to delete',
23
- },
24
- },
25
- required: ['job_id'],
26
- },
27
- };
4
+ export async function executeScheduleDelete(
5
+ input: Record<string, unknown>,
6
+ _context: ToolContext,
7
+ ): Promise<ToolExecutionResult> {
8
+ const jobId = input.job_id as string;
9
+ if (!jobId || typeof jobId !== 'string') {
10
+ return { content: 'Error: job_id is required', isError: true };
28
11
  }
29
12
 
30
- async execute(input: Record<string, unknown>, _context: ToolContext): Promise<ToolExecutionResult> {
31
- const jobId = input.job_id as string;
32
- if (!jobId || typeof jobId !== 'string') {
33
- return { content: 'Error: job_id is required', isError: true };
34
- }
35
-
36
- // Fetch the job first for the confirmation message
37
- const job = getSchedule(jobId);
38
- if (!job) {
39
- return { content: `Error: Schedule not found: ${jobId}`, isError: true };
40
- }
41
-
42
- const deleted = deleteSchedule(jobId);
43
- if (!deleted) {
44
- return { content: `Error: Failed to delete schedule: ${jobId}`, isError: true };
45
- }
13
+ // Fetch the job first for the confirmation message
14
+ const job = getSchedule(jobId);
15
+ if (!job) {
16
+ return { content: `Error: Schedule not found: ${jobId}`, isError: true };
17
+ }
46
18
 
47
- return {
48
- content: `Schedule deleted: "${job.name}"`,
49
- isError: false,
50
- };
19
+ const deleted = deleteSchedule(jobId);
20
+ if (!deleted) {
21
+ return { content: `Error: Failed to delete schedule: ${jobId}`, isError: true };
51
22
  }
52
- }
53
23
 
54
- registerTool(new ScheduleDeleteTool());
24
+ return {
25
+ content: `Schedule deleted: "${job.name}"`,
26
+ isError: false,
27
+ };
28
+ }