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,88 +1,69 @@
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 { listSchedules, getSchedule, getScheduleRuns, formatLocalDate, describeCronExpression } from '../../schedule/schedule-store.js';
3
+ import { hasSetConstructs } from '../../schedule/recurrence-engine.js';
6
4
 
7
- class ScheduleListTool implements Tool {
8
- name = 'schedule_list';
9
- description = 'List recurring scheduled automations (cron jobs), or show details and recent runs for a specific one. For the user\'s task queue, use task_list_show instead.';
10
- category = 'schedule';
11
- defaultRiskLevel = RiskLevel.Low;
12
-
13
- getDefinition(): ToolDefinition {
14
- return {
15
- name: this.name,
16
- description: this.description,
17
- input_schema: {
18
- type: 'object',
19
- properties: {
20
- enabled_only: {
21
- type: 'boolean',
22
- description: 'When true, only show enabled jobs. Defaults to false.',
23
- },
24
- job_id: {
25
- type: 'string',
26
- description: 'If provided, show detailed info and recent runs for this specific job.',
27
- },
28
- },
29
- required: [],
30
- },
31
- };
5
+ function describeSchedule(job: { syntax: string; expression: string; cronExpression: string }): string {
6
+ if (job.syntax === 'rrule') {
7
+ const label = hasSetConstructs(job.expression) ? '[RRULE set] ' : '';
8
+ return `${label}${job.expression}`;
32
9
  }
10
+ return describeCronExpression(job.cronExpression);
11
+ }
33
12
 
34
- async execute(input: Record<string, unknown>, _context: ToolContext): Promise<ToolExecutionResult> {
35
- const jobId = input.job_id as string | undefined;
36
- const enabledOnly = (input.enabled_only as boolean) ?? false;
13
+ export async function executeScheduleList(
14
+ input: Record<string, unknown>,
15
+ _context: ToolContext,
16
+ ): Promise<ToolExecutionResult> {
17
+ const jobId = input.job_id as string | undefined;
18
+ const enabledOnly = (input.enabled_only as boolean) ?? false;
37
19
 
38
- // Detail mode for a specific job
39
- if (jobId) {
40
- const job = getSchedule(jobId);
41
- if (!job) {
42
- return { content: `Error: Schedule not found: ${jobId}`, isError: true };
43
- }
20
+ // Detail mode for a specific job
21
+ if (jobId) {
22
+ const job = getSchedule(jobId);
23
+ if (!job) {
24
+ return { content: `Error: Schedule not found: ${jobId}`, isError: true };
25
+ }
44
26
 
45
- const runs = getScheduleRuns(jobId, 5);
46
- const lines = [
47
- `Schedule: ${job.name}`,
48
- ` Schedule: ${describeCronExpression(job.cronExpression)}${job.timezone ? ` (${job.timezone})` : ''}`,
49
- ` Enabled: ${job.enabled}`,
50
- ` Message: ${job.message}`,
51
- ` Next run: ${formatLocalDate(job.nextRunAt)}`,
52
- ` Last run: ${job.lastRunAt ? formatLocalDate(job.lastRunAt) : 'never'}`,
53
- ` Last status: ${job.lastStatus ?? 'n/a'}`,
54
- ` Retry count: ${job.retryCount}`,
55
- ` Created: ${formatLocalDate(job.createdAt)}`,
56
- ];
27
+ const runs = getScheduleRuns(jobId, 5);
28
+ const lines = [
29
+ `Schedule: ${job.name}`,
30
+ ` Syntax: ${job.syntax}`,
31
+ ` Expression: ${job.expression}`,
32
+ ` Schedule: ${describeSchedule(job)}${job.timezone ? ` (${job.timezone})` : ''}`,
33
+ ` Enabled: ${job.enabled}`,
34
+ ` Message: ${job.message}`,
35
+ ` Next run: ${formatLocalDate(job.nextRunAt)}`,
36
+ ` Last run: ${job.lastRunAt ? formatLocalDate(job.lastRunAt) : 'never'}`,
37
+ ` Last status: ${job.lastStatus ?? 'n/a'}`,
38
+ ` Retry count: ${job.retryCount}`,
39
+ ` Created: ${formatLocalDate(job.createdAt)}`,
40
+ ];
57
41
 
58
- if (runs.length > 0) {
59
- lines.push('', `Recent runs (${runs.length}):`);
60
- for (const run of runs) {
61
- const dur = run.durationMs != null ? `${run.durationMs}ms` : 'n/a';
62
- lines.push(` - ${run.status} at ${formatLocalDate(run.startedAt)} (${dur})${run.error ? ` error: ${run.error}` : ''}`);
63
- }
64
- } else {
65
- lines.push('', 'No runs yet.');
42
+ if (runs.length > 0) {
43
+ lines.push('', `Recent runs (${runs.length}):`);
44
+ for (const run of runs) {
45
+ const dur = run.durationMs != null ? `${run.durationMs}ms` : 'n/a';
46
+ lines.push(` - ${run.status} at ${formatLocalDate(run.startedAt)} (${dur})${run.error ? ` error: ${run.error}` : ''}`);
66
47
  }
67
-
68
- return { content: lines.join('\n'), isError: false };
48
+ } else {
49
+ lines.push('', 'No runs yet.');
69
50
  }
70
51
 
71
- // List mode
72
- const jobs = listSchedules({ enabledOnly });
73
- if (jobs.length === 0) {
74
- return { content: 'No schedules found.', isError: false };
75
- }
52
+ return { content: lines.join('\n'), isError: false };
53
+ }
76
54
 
77
- const lines = [`Schedules (${jobs.length}):`];
78
- for (const job of jobs) {
79
- const status = job.enabled ? 'enabled' : 'disabled';
80
- const next = job.enabled ? formatLocalDate(job.nextRunAt) : 'n/a';
81
- lines.push(` - [${status}] ${job.name} (${describeCronExpression(job.cronExpression)}) — next: ${next}`);
82
- }
55
+ // List mode
56
+ const jobs = listSchedules({ enabledOnly });
57
+ if (jobs.length === 0) {
58
+ return { content: 'No schedules found.', isError: false };
59
+ }
83
60
 
84
- return { content: lines.join('\n'), isError: false };
61
+ const lines = [`Schedules (${jobs.length}):`];
62
+ for (const job of jobs) {
63
+ const status = job.enabled ? 'enabled' : 'disabled';
64
+ const next = job.enabled ? formatLocalDate(job.nextRunAt) : 'n/a';
65
+ lines.push(` - [${status}] ${job.name} ([${job.syntax}] ${describeSchedule(job)}) — next: ${next}`);
85
66
  }
86
- }
87
67
 
88
- registerTool(new ScheduleListTool());
68
+ return { content: lines.join('\n'), isError: false };
69
+ }
@@ -1,97 +1,90 @@
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 { updateSchedule, formatLocalDate, describeCronExpression } from '../../schedule/schedule-store.js';
3
+ import { normalizeScheduleSyntax, type ScheduleSyntax } from '../../schedule/recurrence-types.js';
4
+ import { validateRruleSetLines } from '../../schedule/recurrence-engine.js';
6
5
 
7
- class ScheduleUpdateTool implements Tool {
8
- name = 'schedule_update';
9
- description = 'Update an existing recurring scheduled automation (cron expression, message, name, or enabled state)';
10
- category = 'schedule';
11
- defaultRiskLevel = RiskLevel.Medium;
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 update',
23
- },
24
- name: {
25
- type: 'string',
26
- description: 'New name for the job',
27
- },
28
- cron_expression: {
29
- type: 'string',
30
- description: 'New cron expression',
31
- },
32
- timezone: {
33
- type: 'string',
34
- description: 'New IANA timezone',
35
- },
36
- message: {
37
- type: 'string',
38
- description: 'New message to send when triggered',
39
- },
40
- enabled: {
41
- type: 'boolean',
42
- description: 'Enable or disable the job',
43
- },
44
- },
45
- required: ['job_id'],
46
- },
47
- };
6
+ export async function executeScheduleUpdate(
7
+ input: Record<string, unknown>,
8
+ _context: ToolContext,
9
+ ): Promise<ToolExecutionResult> {
10
+ const jobId = input.job_id as string;
11
+ if (!jobId || typeof jobId !== 'string') {
12
+ return { content: 'Error: job_id is required', isError: true };
48
13
  }
49
14
 
50
- async execute(input: Record<string, unknown>, _context: ToolContext): Promise<ToolExecutionResult> {
51
- const jobId = input.job_id as string;
52
- if (!jobId || typeof jobId !== 'string') {
53
- return { content: 'Error: job_id is required', isError: true };
54
- }
55
-
56
- const updates: Record<string, unknown> = {};
57
- if (input.name !== undefined) updates.name = input.name;
58
- if (input.cron_expression !== undefined) updates.cronExpression = input.cron_expression;
59
- if (input.timezone !== undefined) updates.timezone = input.timezone;
60
- if (input.message !== undefined) updates.message = input.message;
61
- if (input.enabled !== undefined) updates.enabled = input.enabled;
15
+ const updates: Record<string, unknown> = {};
16
+ if (input.name !== undefined) updates.name = input.name;
17
+ if (input.timezone !== undefined) updates.timezone = input.timezone;
18
+ if (input.message !== undefined) updates.message = input.message;
19
+ if (input.enabled !== undefined) updates.enabled = input.enabled;
62
20
 
63
- if (Object.keys(updates).length === 0) {
64
- return { content: 'Error: No updates provided. Specify at least one field to update.', isError: true };
21
+ // Auto-detect syntax when expression changes without explicit syntax
22
+ const hasExpression = input.expression !== undefined || input.cron_expression !== undefined;
23
+ if (hasExpression || input.syntax !== undefined) {
24
+ const resolved = normalizeScheduleSyntax({
25
+ syntax: input.syntax as 'cron' | 'rrule' | undefined,
26
+ expression: input.expression as string | undefined,
27
+ legacyCronExpression: input.cron_expression as string | undefined,
28
+ });
29
+ if (resolved) {
30
+ updates.syntax = resolved.syntax;
31
+ updates.expression = resolved.expression;
32
+ } else if (input.expression !== undefined) {
33
+ updates.expression = input.expression;
34
+ } else if (input.cron_expression !== undefined) {
35
+ updates.cronExpression = input.cron_expression;
65
36
  }
37
+ }
66
38
 
67
- try {
68
- const job = updateSchedule(jobId, updates as {
69
- name?: string;
70
- cronExpression?: string;
71
- timezone?: string | null;
72
- message?: string;
73
- enabled?: boolean;
74
- });
75
-
76
- if (!job) {
77
- return { content: `Error: Schedule not found: ${jobId}`, isError: true };
78
- }
39
+ if (Object.keys(updates).length === 0) {
40
+ return { content: 'Error: No updates provided. Specify at least one field to update.', isError: true };
41
+ }
79
42
 
43
+ // Set-aware pre-validation for RRULE expressions
44
+ const effectiveSyntax = updates.syntax as string | undefined;
45
+ const effectiveExpr = (updates.expression as string | undefined) ?? (updates.cronExpression as string | undefined);
46
+ if (effectiveExpr && typeof effectiveExpr === 'string' && (effectiveSyntax === 'rrule' || /^(DTSTART|RRULE:)/m.test(effectiveExpr))) {
47
+ const setError = validateRruleSetLines(effectiveExpr);
48
+ if (setError) {
80
49
  return {
81
- content: [
82
- `Schedule updated successfully.`,
83
- ` Name: ${job.name}`,
84
- ` Schedule: ${describeCronExpression(job.cronExpression)}${job.timezone ? ` (${job.timezone})` : ''}`,
85
- ` Enabled: ${job.enabled}`,
86
- ` Next run: ${job.enabled ? formatLocalDate(job.nextRunAt) : 'n/a (disabled)'}`,
87
- ].join('\n'),
88
- isError: false,
50
+ content: `Error: ${setError}. Supported line types: DTSTART, RRULE, RDATE, EXDATE, EXRULE.`,
51
+ isError: true,
89
52
  };
90
- } catch (err) {
91
- const msg = err instanceof Error ? err.message : String(err);
92
- return { content: `Error updating schedule: ${msg}`, isError: true };
93
53
  }
94
54
  }
95
- }
96
55
 
97
- registerTool(new ScheduleUpdateTool());
56
+ try {
57
+ const job = updateSchedule(jobId, updates as {
58
+ name?: string;
59
+ cronExpression?: string;
60
+ timezone?: string | null;
61
+ message?: string;
62
+ enabled?: boolean;
63
+ syntax?: ScheduleSyntax;
64
+ expression?: string;
65
+ });
66
+
67
+ if (!job) {
68
+ return { content: `Error: Schedule not found: ${jobId}`, isError: true };
69
+ }
70
+
71
+ const scheduleDescription = job.syntax === 'rrule'
72
+ ? job.expression
73
+ : describeCronExpression(job.cronExpression);
74
+
75
+ return {
76
+ content: [
77
+ `Schedule updated successfully.`,
78
+ ` Name: ${job.name}`,
79
+ ` Syntax: ${job.syntax}`,
80
+ ` Schedule: ${scheduleDescription}${job.timezone ? ` (${job.timezone})` : ''}`,
81
+ ` Enabled: ${job.enabled}`,
82
+ ` Next run: ${job.enabled ? formatLocalDate(job.nextRunAt) : 'n/a (disabled)'}`,
83
+ ].join('\n'),
84
+ isError: false,
85
+ };
86
+ } catch (err) {
87
+ const msg = err instanceof Error ? err.message : String(err);
88
+ return { content: `Error updating schedule: ${msg}`, isError: true };
89
+ }
90
+ }
@@ -1,62 +1,33 @@
1
- /**
2
- * subagent_abort tool — abort a running subagent.
3
- */
4
-
5
- import { RiskLevel } from '../../permissions/types.js';
6
- import type { Tool, ToolContext, ToolExecutionResult } from '../types.js';
7
- import type { ToolDefinition } from '../../providers/types.js';
1
+ import type { ToolContext, ToolExecutionResult } from '../types.js';
8
2
  import { getSubagentManager } from '../../subagent/index.js';
9
3
 
10
- const definition: ToolDefinition = {
11
- name: 'subagent_abort',
12
- description: 'Abort a running subagent by ID.',
13
- input_schema: {
14
- type: 'object',
15
- properties: {
16
- subagent_id: {
17
- type: 'string',
18
- description: 'The ID of the subagent to abort.',
19
- },
20
- },
21
- required: ['subagent_id'],
22
- },
23
- };
24
-
25
- export const subagentAbortTool: Tool = {
26
- name: 'subagent_abort',
27
- description: definition.description,
28
- category: 'orchestration',
29
- defaultRiskLevel: RiskLevel.Low,
30
-
31
- getDefinition(): ToolDefinition {
32
- return definition;
33
- },
34
-
35
- async execute(input: Record<string, unknown>, context: ToolContext): Promise<ToolExecutionResult> {
36
- const subagentId = input.subagent_id as string;
37
- if (!subagentId) {
38
- return { content: '"subagent_id" is required.', isError: true };
39
- }
40
-
41
- const manager = getSubagentManager();
42
- const sendToClient = context.sendToClient as ((msg: unknown) => void) | undefined;
43
- const aborted = manager.abort(
44
- subagentId,
45
- sendToClient as ((msg: unknown) => void) | undefined,
46
- context.sessionId,
47
- { suppressNotification: true },
48
- );
49
-
50
- if (!aborted) {
51
- return {
52
- content: `Could not abort subagent "${subagentId}". It may not exist or already be in a terminal state.`,
53
- isError: true,
54
- };
55
- }
56
-
4
+ export async function executeSubagentAbort(
5
+ input: Record<string, unknown>,
6
+ context: ToolContext,
7
+ ): Promise<ToolExecutionResult> {
8
+ const subagentId = input.subagent_id as string;
9
+ if (!subagentId) {
10
+ return { content: '"subagent_id" is required.', isError: true };
11
+ }
12
+
13
+ const manager = getSubagentManager();
14
+ const sendToClient = context.sendToClient as ((msg: unknown) => void) | undefined;
15
+ const aborted = manager.abort(
16
+ subagentId,
17
+ sendToClient as ((msg: unknown) => void) | undefined,
18
+ context.sessionId,
19
+ { suppressNotification: true },
20
+ );
21
+
22
+ if (!aborted) {
57
23
  return {
58
- content: JSON.stringify({ subagentId, status: 'aborted', message: 'Subagent aborted successfully.' }),
59
- isError: false,
24
+ content: `Could not abort subagent "${subagentId}". It may not exist or already be in a terminal state.`,
25
+ isError: true,
60
26
  };
61
- },
62
- };
27
+ }
28
+
29
+ return {
30
+ content: JSON.stringify({ subagentId, status: 'aborted', message: 'Subagent aborted successfully.' }),
31
+ isError: false,
32
+ };
33
+ }
@@ -1,72 +1,39 @@
1
- /**
2
- * subagent_message tool — send a follow-up message to a running subagent.
3
- */
4
-
5
- import { RiskLevel } from '../../permissions/types.js';
6
- import type { Tool, ToolContext, ToolExecutionResult } from '../types.js';
7
- import type { ToolDefinition } from '../../providers/types.js';
1
+ import type { ToolContext, ToolExecutionResult } from '../types.js';
8
2
  import { getSubagentManager } from '../../subagent/index.js';
9
3
 
10
- const definition: ToolDefinition = {
11
- name: 'subagent_message',
12
- description: 'Send a follow-up message to a running subagent.',
13
- input_schema: {
14
- type: 'object',
15
- properties: {
16
- subagent_id: {
17
- type: 'string',
18
- description: 'The ID of the subagent to send a message to.',
19
- },
20
- content: {
21
- type: 'string',
22
- description: 'The message content to send to the subagent.',
23
- },
24
- },
25
- required: ['subagent_id', 'content'],
26
- },
27
- };
28
-
29
- export const subagentMessageTool: Tool = {
30
- name: 'subagent_message',
31
- description: definition.description,
32
- category: 'orchestration',
33
- defaultRiskLevel: RiskLevel.Low,
34
-
35
- getDefinition(): ToolDefinition {
36
- return definition;
37
- },
38
-
39
- async execute(input: Record<string, unknown>, context: ToolContext): Promise<ToolExecutionResult> {
40
- const subagentId = input.subagent_id as string;
41
- const content = input.content as string;
4
+ export async function executeSubagentMessage(
5
+ input: Record<string, unknown>,
6
+ context: ToolContext,
7
+ ): Promise<ToolExecutionResult> {
8
+ const subagentId = input.subagent_id as string;
9
+ const content = input.content as string;
42
10
 
43
- if (!subagentId || !content) {
44
- return { content: 'Both "subagent_id" and "content" are required.', isError: true };
45
- }
11
+ if (!subagentId || !content) {
12
+ return { content: 'Both "subagent_id" and "content" are required.', isError: true };
13
+ }
46
14
 
47
- const manager = getSubagentManager();
15
+ const manager = getSubagentManager();
48
16
 
49
- // Ownership check: only the parent session can message a subagent.
50
- const state = manager.getState(subagentId);
51
- if (!state || state.config.parentSessionId !== context.sessionId) {
52
- return {
53
- content: `Could not send message to subagent "${subagentId}". It may not exist or be in a terminal state.`,
54
- isError: true,
55
- };
56
- }
57
-
58
- const sent = manager.sendMessage(subagentId, content);
17
+ // Ownership check: only the parent session can message a subagent.
18
+ const state = manager.getState(subagentId);
19
+ if (!state || state.config.parentSessionId !== context.sessionId) {
20
+ return {
21
+ content: `Could not send message to subagent "${subagentId}". It may not exist or be in a terminal state.`,
22
+ isError: true,
23
+ };
24
+ }
59
25
 
60
- if (!sent) {
61
- return {
62
- content: `Could not send message to subagent "${subagentId}". It may not exist or be in a terminal state.`,
63
- isError: true,
64
- };
65
- }
26
+ const sent = manager.sendMessage(subagentId, content);
66
27
 
28
+ if (!sent) {
67
29
  return {
68
- content: JSON.stringify({ subagentId, message: 'Message sent to subagent.' }),
69
- isError: false,
30
+ content: `Could not send message to subagent "${subagentId}". It may not exist or be in a terminal state.`,
31
+ isError: true,
70
32
  };
71
- },
72
- };
33
+ }
34
+
35
+ return {
36
+ content: JSON.stringify({ subagentId, message: 'Message sent to subagent.' }),
37
+ isError: false,
38
+ };
39
+ }