vellum 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (349) hide show
  1. package/README.md +15 -2
  2. package/bun.lock +5 -2
  3. package/package.json +4 -2
  4. package/scripts/capture-x-graphql.ts +562 -0
  5. package/scripts/ipc/check-swift-decoder-drift.ts +2 -1
  6. package/scripts/test.sh +5 -0
  7. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +133 -34
  8. package/src/__tests__/account-registry.test.ts +2 -1
  9. package/src/__tests__/agent-heartbeat-service.test.ts +250 -0
  10. package/src/__tests__/asset-materialize-tool.test.ts +16 -15
  11. package/src/__tests__/asset-search-tool.test.ts +23 -22
  12. package/src/__tests__/attachments-store.test.ts +56 -127
  13. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +5 -4
  14. package/src/__tests__/browser-skill-endstate.test.ts +4 -3
  15. package/src/__tests__/call-bridge.test.ts +385 -0
  16. package/src/__tests__/call-constants.test.ts +40 -0
  17. package/src/__tests__/call-orchestrator.test.ts +130 -4
  18. package/src/__tests__/call-recovery.test.ts +518 -0
  19. package/src/__tests__/call-routes-http.test.ts +459 -0
  20. package/src/__tests__/call-state-machine.test.ts +143 -0
  21. package/src/__tests__/call-store.test.ts +216 -1
  22. package/src/__tests__/cli-discover.test.ts +1 -1
  23. package/src/__tests__/commit-message-enrichment-service.test.ts +148 -7
  24. package/src/__tests__/compaction.benchmark.test.ts +176 -0
  25. package/src/__tests__/computer-use-tools.test.ts +250 -0
  26. package/src/__tests__/config-schema.test.ts +299 -3
  27. package/src/__tests__/conflict-store.test.ts +2 -1
  28. package/src/__tests__/contacts-tools.test.ts +331 -0
  29. package/src/__tests__/conversation-store.test.ts +30 -32
  30. package/src/__tests__/credential-security-invariants.test.ts +4 -0
  31. package/src/__tests__/date-context.test.ts +373 -0
  32. package/src/__tests__/db-schedule-syntax-migration.test.ts +129 -0
  33. package/src/__tests__/fixtures/media-reuse-fixtures.ts +3 -3
  34. package/src/__tests__/followup-tools.test.ts +303 -0
  35. package/src/__tests__/handlers-twitter-config.test.ts +718 -0
  36. package/src/__tests__/intent-routing.test.ts +64 -57
  37. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +237 -0
  38. package/src/__tests__/ipc-snapshot.test.ts +62 -28
  39. package/src/__tests__/llm-usage-store.test.ts +3 -8
  40. package/src/__tests__/media-generate-image.test.ts +1 -1
  41. package/src/__tests__/media-reuse-story.e2e.test.ts +7 -7
  42. package/src/__tests__/memory-retrieval.benchmark.test.ts +430 -0
  43. package/src/__tests__/parallel-tool.benchmark.test.ts +294 -0
  44. package/src/__tests__/playbook-tools.test.ts +342 -0
  45. package/src/__tests__/profile-compiler.test.ts +2 -1
  46. package/src/__tests__/provider-streaming.benchmark.test.ts +773 -0
  47. package/src/__tests__/recurrence-engine-rruleset.test.ts +78 -0
  48. package/src/__tests__/recurrence-engine.test.ts +69 -0
  49. package/src/__tests__/recurrence-types.test.ts +71 -0
  50. package/src/__tests__/registry.test.ts +5 -3
  51. package/src/__tests__/relay-server.test.ts +633 -0
  52. package/src/__tests__/reminder-store.test.ts +6 -3
  53. package/src/__tests__/reminder.test.ts +43 -77
  54. package/src/__tests__/run-orchestrator-assistant-events.test.ts +8 -4
  55. package/src/__tests__/run-orchestrator.test.ts +4 -4
  56. package/src/__tests__/runtime-attachment-metadata.test.ts +7 -6
  57. package/src/__tests__/runtime-runs-http.test.ts +4 -4
  58. package/src/__tests__/runtime-runs.test.ts +4 -4
  59. package/src/__tests__/schedule-store.test.ts +482 -0
  60. package/src/__tests__/schedule-tools.test.ts +700 -0
  61. package/src/__tests__/scheduler-recurrence.test.ts +329 -0
  62. package/src/__tests__/server-history-render.test.ts +14 -13
  63. package/src/__tests__/session-error.test.ts +28 -0
  64. package/src/__tests__/session-init.benchmark.test.ts +462 -0
  65. package/src/__tests__/session-queue.test.ts +71 -48
  66. package/src/__tests__/session-runtime-assembly.test.ts +161 -0
  67. package/src/__tests__/session-surfaces-task-progress.test.ts +104 -0
  68. package/src/__tests__/signup-e2e.test.ts +2 -1
  69. package/src/__tests__/skill-projection.benchmark.test.ts +328 -0
  70. package/src/__tests__/skill-script-runner.test.ts +159 -0
  71. package/src/__tests__/speaker-identification.test.ts +52 -0
  72. package/src/__tests__/subagent-manager-notify.test.ts +42 -10
  73. package/src/__tests__/subagent-tools.test.ts +141 -41
  74. package/src/__tests__/task-compiler.test.ts +2 -1
  75. package/src/__tests__/task-runner.test.ts +2 -1
  76. package/src/__tests__/task-scheduler.test.ts +2 -1
  77. package/src/__tests__/task-tools.test.ts +49 -56
  78. package/src/__tests__/tool-audit-listener.test.ts +1 -0
  79. package/src/__tests__/tool-domain-event-publisher.test.ts +2 -0
  80. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +500 -0
  81. package/src/__tests__/tool-executor.test.ts +13 -17
  82. package/src/__tests__/turn-commit.test.ts +218 -3
  83. package/src/__tests__/twilio-provider.test.ts +143 -0
  84. package/src/__tests__/twilio-routes.test.ts +789 -0
  85. package/src/__tests__/twitter-auth-handler.test.ts +581 -0
  86. package/src/__tests__/view-image-tool.test.ts +217 -0
  87. package/src/__tests__/workspace-git-service.test.ts +186 -0
  88. package/src/__tests__/workspace-heartbeat-service.test.ts +13 -3
  89. package/src/agent-heartbeat/agent-heartbeat-service.ts +155 -0
  90. package/src/bundler/app-bundler.ts +12 -8
  91. package/src/calls/call-bridge.ts +95 -0
  92. package/src/calls/call-constants.ts +43 -5
  93. package/src/calls/call-domain.ts +276 -0
  94. package/src/calls/call-orchestrator.ts +43 -17
  95. package/src/calls/call-recovery.ts +207 -0
  96. package/src/calls/call-state-machine.ts +68 -0
  97. package/src/calls/call-store.ts +192 -5
  98. package/src/calls/relay-server.ts +41 -4
  99. package/src/calls/speaker-identification.ts +213 -0
  100. package/src/calls/twilio-provider.ts +10 -6
  101. package/src/calls/twilio-routes.ts +90 -76
  102. package/src/calls/types.ts +1 -1
  103. package/src/cli/config-commands.ts +334 -0
  104. package/src/cli/core-commands.ts +776 -0
  105. package/src/cli/doordash.ts +251 -1
  106. package/src/cli/ipc-client.ts +82 -0
  107. package/src/cli/map.ts +246 -0
  108. package/src/cli/twitter.ts +575 -0
  109. package/src/cli.ts +7 -5
  110. package/src/commands/__tests__/cc-command-registry.test.ts +319 -0
  111. package/src/commands/cc-command-registry.ts +209 -0
  112. package/src/config/bundled-skills/contacts/SKILL.md +39 -0
  113. package/src/config/bundled-skills/contacts/TOOLS.json +122 -0
  114. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +9 -0
  115. package/src/config/bundled-skills/contacts/tools/contact-search.ts +9 -0
  116. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +9 -0
  117. package/src/config/bundled-skills/document/SKILL.md +18 -0
  118. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  119. package/src/config/bundled-skills/document/tools/document-create.ts +9 -0
  120. package/src/config/bundled-skills/document/tools/document-update.ts +9 -0
  121. package/src/config/bundled-skills/doordash/SKILL.md +82 -23
  122. package/src/config/bundled-skills/followups/SKILL.md +32 -0
  123. package/src/config/bundled-skills/followups/TOOLS.json +100 -0
  124. package/src/config/bundled-skills/followups/tools/followup-create.ts +9 -0
  125. package/src/config/bundled-skills/followups/tools/followup-list.ts +9 -0
  126. package/src/config/bundled-skills/followups/tools/followup-resolve.ts +9 -0
  127. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +1 -23
  128. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -1
  129. package/src/config/bundled-skills/playbooks/SKILL.md +31 -0
  130. package/src/config/bundled-skills/playbooks/TOOLS.json +126 -0
  131. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +9 -0
  132. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +9 -0
  133. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +9 -0
  134. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +9 -0
  135. package/src/config/bundled-skills/reminder/SKILL.md +20 -0
  136. package/src/config/bundled-skills/reminder/TOOLS.json +67 -0
  137. package/src/config/bundled-skills/reminder/tools/reminder-cancel.ts +9 -0
  138. package/src/config/bundled-skills/reminder/tools/reminder-create.ts +9 -0
  139. package/src/config/bundled-skills/reminder/tools/reminder-list.ts +9 -0
  140. package/src/config/bundled-skills/schedule/SKILL.md +74 -0
  141. package/src/config/bundled-skills/schedule/TOOLS.json +135 -0
  142. package/src/config/bundled-skills/schedule/tools/schedule-create.ts +9 -0
  143. package/src/config/bundled-skills/schedule/tools/schedule-delete.ts +9 -0
  144. package/src/config/bundled-skills/schedule/tools/schedule-list.ts +9 -0
  145. package/src/config/bundled-skills/schedule/tools/schedule-update.ts +9 -0
  146. package/src/config/bundled-skills/subagent/SKILL.md +25 -0
  147. package/src/config/bundled-skills/subagent/TOOLS.json +107 -0
  148. package/src/config/bundled-skills/subagent/tools/subagent-abort.ts +9 -0
  149. package/src/config/bundled-skills/subagent/tools/subagent-message.ts +9 -0
  150. package/src/config/bundled-skills/subagent/tools/subagent-read.ts +9 -0
  151. package/src/config/bundled-skills/subagent/tools/subagent-spawn.ts +9 -0
  152. package/src/config/bundled-skills/subagent/tools/subagent-status.ts +9 -0
  153. package/src/config/bundled-skills/tasks/SKILL.md +28 -0
  154. package/src/config/bundled-skills/tasks/TOOLS.json +256 -0
  155. package/src/config/bundled-skills/tasks/tools/task-delete.ts +9 -0
  156. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +9 -0
  157. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +9 -0
  158. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +9 -0
  159. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +9 -0
  160. package/src/config/bundled-skills/tasks/tools/task-list.ts +9 -0
  161. package/src/config/bundled-skills/tasks/tools/task-run.ts +9 -0
  162. package/src/config/bundled-skills/tasks/tools/task-save.ts +9 -0
  163. package/src/config/bundled-skills/twitter/SKILL.md +134 -0
  164. package/src/config/bundled-skills/watcher/SKILL.md +27 -0
  165. package/src/config/bundled-skills/watcher/TOOLS.json +147 -0
  166. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +9 -0
  167. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +9 -0
  168. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +9 -0
  169. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +9 -0
  170. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +9 -0
  171. package/src/config/defaults.ts +33 -0
  172. package/src/config/loader.ts +4 -1
  173. package/src/config/schema.ts +161 -1
  174. package/src/config/system-prompt.ts +61 -16
  175. package/src/config/templates/IDENTITY.md +7 -0
  176. package/src/config/types.ts +4 -0
  177. package/src/contacts/contact-store.ts +4 -4
  178. package/src/daemon/assistant-attachments.ts +10 -0
  179. package/src/daemon/classifier.ts +3 -1
  180. package/src/daemon/computer-use-session.ts +3 -1
  181. package/src/daemon/date-context.ts +136 -0
  182. package/src/daemon/handlers/apps.ts +16 -1
  183. package/src/daemon/handlers/browser.ts +54 -0
  184. package/src/daemon/handlers/computer-use.ts +7 -1
  185. package/src/daemon/handlers/config.ts +163 -5
  186. package/src/daemon/handlers/diagnostics.ts +5 -1
  187. package/src/daemon/handlers/documents.ts +18 -29
  188. package/src/daemon/handlers/home-base.ts +5 -1
  189. package/src/daemon/handlers/index.ts +40 -277
  190. package/src/daemon/handlers/misc.ts +9 -1
  191. package/src/daemon/handlers/publish.ts +6 -1
  192. package/src/daemon/handlers/sessions.ts +65 -12
  193. package/src/daemon/handlers/shared.ts +36 -1
  194. package/src/daemon/handlers/signing.ts +37 -0
  195. package/src/daemon/handlers/skills.ts +20 -6
  196. package/src/daemon/handlers/subagents.ts +8 -3
  197. package/src/daemon/handlers/twitter-auth.ts +169 -0
  198. package/src/daemon/handlers/work-items.ts +384 -68
  199. package/src/daemon/ipc-contract-inventory.json +28 -4
  200. package/src/daemon/ipc-contract.ts +133 -37
  201. package/src/daemon/ipc-protocol.ts +7 -2
  202. package/src/daemon/lifecycle.ts +21 -0
  203. package/src/daemon/main.ts +10 -4
  204. package/src/daemon/ride-shotgun-handler.ts +74 -10
  205. package/src/daemon/server.ts +143 -26
  206. package/src/daemon/session-agent-loop.ts +887 -0
  207. package/src/daemon/session-attachments.ts +28 -5
  208. package/src/daemon/session-error.ts +24 -3
  209. package/src/daemon/session-lifecycle.ts +147 -0
  210. package/src/daemon/session-media-retry.ts +147 -0
  211. package/src/daemon/session-messaging.ts +145 -0
  212. package/src/daemon/session-notifiers.ts +164 -0
  213. package/src/daemon/session-process.ts +2 -2
  214. package/src/daemon/session-queue-manager.ts +1 -0
  215. package/src/daemon/session-runtime-assembly.ts +52 -0
  216. package/src/daemon/session-skill-tools.ts +124 -5
  217. package/src/daemon/session-slash.ts +3 -0
  218. package/src/daemon/session-surfaces.ts +77 -2
  219. package/src/daemon/session-tool-setup.ts +216 -2
  220. package/src/daemon/session-usage.ts +0 -2
  221. package/src/daemon/session.ts +114 -1404
  222. package/src/daemon/video-thumbnail.ts +60 -0
  223. package/src/doordash/client.ts +121 -27
  224. package/src/doordash/queries.ts +1 -2
  225. package/src/export/formatter.ts +3 -1
  226. package/src/followups/followup-store.ts +4 -2
  227. package/src/followups/types.ts +6 -0
  228. package/src/hooks/templates.ts +1 -1
  229. package/src/index.ts +32 -1153
  230. package/src/memory/attachments-store.ts +28 -83
  231. package/src/memory/channel-delivery-store.ts +7 -21
  232. package/src/memory/clarification-resolver.ts +6 -5
  233. package/src/memory/contradiction-checker.ts +3 -2
  234. package/src/memory/conversation-key-store.ts +10 -29
  235. package/src/memory/conversation-store.ts +2 -1
  236. package/src/memory/db.ts +96 -2
  237. package/src/memory/entity-extractor.ts +6 -3
  238. package/src/memory/items-extractor.ts +5 -4
  239. package/src/memory/jobs-store.ts +3 -2
  240. package/src/memory/llm-usage-store.ts +1 -2
  241. package/src/memory/runs-store.ts +1 -2
  242. package/src/memory/schema.ts +23 -2
  243. package/src/messaging/style-analyzer.ts +3 -2
  244. package/src/messaging/thread-summarizer.ts +8 -12
  245. package/src/messaging/triage-engine.ts +4 -2
  246. package/src/providers/openrouter/client.ts +20 -0
  247. package/src/providers/registry.ts +8 -0
  248. package/src/runtime/http-server.ts +108 -20
  249. package/src/runtime/routes/attachment-routes.ts +2 -3
  250. package/src/runtime/routes/call-routes.ts +140 -0
  251. package/src/runtime/routes/channel-routes.ts +5 -10
  252. package/src/runtime/routes/conversation-routes.ts +5 -5
  253. package/src/runtime/routes/run-routes.ts +2 -2
  254. package/src/runtime/run-orchestrator.ts +9 -3
  255. package/src/schedule/recurrence-engine.ts +138 -0
  256. package/src/schedule/recurrence-types.ts +67 -0
  257. package/src/schedule/schedule-store.ts +102 -57
  258. package/src/schedule/scheduler.ts +9 -6
  259. package/src/security/oauth2.ts +29 -4
  260. package/src/security/secret-allowlist.ts +46 -0
  261. package/src/skills/clawhub.ts +1 -1
  262. package/src/subagent/manager.ts +40 -8
  263. package/src/swarm/backend-claude-code.ts +64 -9
  264. package/src/swarm/worker-prompts.ts +2 -1
  265. package/src/tasks/SPEC.md +34 -28
  266. package/src/tasks/ephemeral-permissions.ts +16 -7
  267. package/src/tasks/task-compiler.ts +5 -4
  268. package/src/tasks/task-runner.ts +10 -5
  269. package/src/tasks/task-scheduler.ts +1 -1
  270. package/src/tasks/tool-sanitizer.ts +36 -0
  271. package/src/tools/assets/search.ts +4 -4
  272. package/src/tools/browser/api-map.ts +220 -0
  273. package/src/tools/browser/auto-navigate.ts +270 -0
  274. package/src/tools/browser/browser-execution.ts +2 -1
  275. package/src/tools/browser/browser-manager.ts +2 -2
  276. package/src/tools/browser/network-recorder.ts +5 -4
  277. package/src/tools/browser/x-auto-navigate.ts +207 -0
  278. package/src/tools/calls/call-end.ts +17 -67
  279. package/src/tools/calls/call-start.ts +24 -85
  280. package/src/tools/calls/call-status.ts +35 -51
  281. package/src/tools/claude-code/claude-code.ts +77 -11
  282. package/src/tools/contacts/contact-merge.ts +46 -78
  283. package/src/tools/contacts/contact-search.ts +35 -79
  284. package/src/tools/contacts/contact-upsert.ts +35 -108
  285. package/src/tools/credentials/vault.ts +20 -4
  286. package/src/tools/document/document-tool.ts +71 -144
  287. package/src/tools/executor.ts +129 -10
  288. package/src/tools/followups/followup_create.ts +46 -88
  289. package/src/tools/followups/followup_list.ts +34 -74
  290. package/src/tools/followups/followup_resolve.ts +31 -66
  291. package/src/tools/host-terminal/cli-discover.ts +2 -1
  292. package/src/tools/host-terminal/host-shell.ts +10 -0
  293. package/src/tools/memory/handlers.ts +5 -4
  294. package/src/tools/network/__tests__/web-search.test.ts +427 -0
  295. package/src/tools/network/script-proxy/__tests__/logging.test.ts +248 -0
  296. package/src/tools/network/script-proxy/__tests__/policy.test.ts +234 -0
  297. package/src/tools/network/script-proxy/__tests__/router.test.ts +76 -0
  298. package/src/tools/network/web-fetch.ts +18 -6
  299. package/src/tools/playbooks/index.ts +4 -5
  300. package/src/tools/playbooks/playbook-create.ts +3 -47
  301. package/src/tools/playbooks/playbook-delete.ts +1 -25
  302. package/src/tools/playbooks/playbook-list.ts +1 -28
  303. package/src/tools/playbooks/playbook-update.ts +3 -51
  304. package/src/tools/reminder/reminder.ts +5 -78
  305. package/src/tools/schedule/create.ts +69 -74
  306. package/src/tools/schedule/delete.ts +21 -47
  307. package/src/tools/schedule/list.ts +55 -74
  308. package/src/tools/schedule/update.ts +77 -84
  309. package/src/tools/subagent/abort.ts +29 -58
  310. package/src/tools/subagent/message.ts +30 -63
  311. package/src/tools/subagent/read.ts +53 -84
  312. package/src/tools/subagent/spawn.ts +43 -82
  313. package/src/tools/subagent/status.ts +42 -71
  314. package/src/tools/swarm/delegate.ts +2 -1
  315. package/src/tools/tasks/index.ts +8 -8
  316. package/src/tools/tasks/task-delete.ts +60 -88
  317. package/src/tools/tasks/task-list.ts +31 -52
  318. package/src/tools/tasks/task-run.ts +72 -108
  319. package/src/tools/tasks/task-save.ts +33 -65
  320. package/src/tools/tasks/work-item-enqueue.ts +183 -215
  321. package/src/tools/tasks/work-item-list.ts +33 -63
  322. package/src/tools/tasks/work-item-remove.ts +45 -97
  323. package/src/tools/tasks/work-item-update.ts +91 -163
  324. package/src/tools/terminal/backends/native.ts +3 -1
  325. package/src/tools/tool-manifest.ts +0 -62
  326. package/src/tools/types.ts +6 -0
  327. package/src/tools/ui-surface/definitions.ts +3 -1
  328. package/src/tools/watch/screen-watch.ts +3 -1
  329. package/src/tools/watcher/create.ts +52 -98
  330. package/src/tools/watcher/delete.ts +20 -46
  331. package/src/tools/watcher/digest.ts +36 -70
  332. package/src/tools/watcher/list.ts +49 -79
  333. package/src/tools/watcher/update.ts +45 -91
  334. package/src/twitter/client.ts +690 -0
  335. package/src/twitter/session.ts +91 -0
  336. package/src/usage/types.ts +0 -1
  337. package/src/util/truncate.ts +6 -0
  338. package/src/watcher/providers/slack.ts +2 -1
  339. package/src/watcher/watcher-store.ts +3 -2
  340. package/src/work-items/work-item-store.ts +27 -2
  341. package/src/workspace/commit-message-enrichment-service.ts +31 -7
  342. package/src/workspace/git-service.ts +87 -22
  343. package/src/workspace/provider-commit-message-generator.ts +242 -0
  344. package/src/workspace/turn-commit.ts +62 -3
  345. package/src/tools/contacts/index.ts +0 -4
  346. package/src/tools/document/index.ts +0 -5
  347. package/src/tools/followups/index.ts +0 -3
  348. package/src/tools/subagent/index.ts +0 -5
  349. /package/src/__tests__/{memory-context-benchmark.test.ts → memory-context-benchmark.benchmark.test.ts} +0 -0
@@ -1,110 +1,64 @@
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 { createWatcher } from '../../watcher/watcher-store.js';
6
3
  import { getWatcherProvider, listWatcherProviders } from '../../watcher/provider-registry.js';
7
4
 
8
- class WatcherCreateTool implements Tool {
9
- name = 'watcher_create';
10
- description = 'Create a new watcher that polls an external service for events and processes them with an action prompt';
11
- category = 'watcher';
12
- defaultRiskLevel = RiskLevel.Medium;
5
+ export async function executeWatcherCreate(
6
+ input: Record<string, unknown>,
7
+ _context: ToolContext,
8
+ ): Promise<ToolExecutionResult> {
9
+ const name = input.name as string;
10
+ const providerId = input.provider as string;
11
+ const actionPrompt = input.action_prompt as string;
12
+ const pollIntervalMs = (input.poll_interval_ms as number) ?? undefined;
13
+ const config = input.config as Record<string, unknown> | undefined;
13
14
 
14
- getDefinition(): ToolDefinition {
15
- return {
16
- name: this.name,
17
- description: this.description,
18
- input_schema: {
19
- type: 'object',
20
- properties: {
21
- name: {
22
- type: 'string',
23
- description: 'A human-readable name for this watcher (e.g. "My Gmail")',
24
- },
25
- provider: {
26
- type: 'string',
27
- description: 'The provider to poll (e.g. "gmail")',
28
- },
29
- action_prompt: {
30
- type: 'string',
31
- description: 'Instructions for the LLM on how to handle detected events. This prompt is sent along with event data to a background conversation.',
32
- },
33
- poll_interval_ms: {
34
- type: 'number',
35
- description: 'How often to poll in milliseconds. Defaults to 60000 (1 minute). Minimum 15000.',
36
- },
37
- credential_service: {
38
- type: 'string',
39
- description: 'Override the credential service to use. Defaults to the provider\'s required service.',
40
- },
41
- config: {
42
- type: 'object',
43
- description: 'Provider-specific configuration (e.g. filter criteria)',
44
- },
45
- },
46
- required: ['name', 'provider', 'action_prompt'],
47
- },
48
- };
15
+ if (!name || typeof name !== 'string') {
16
+ return { content: 'Error: name is required and must be a string', isError: true };
17
+ }
18
+ if (!providerId || typeof providerId !== 'string') {
19
+ return { content: 'Error: provider is required and must be a string', isError: true };
20
+ }
21
+ if (!actionPrompt || typeof actionPrompt !== 'string') {
22
+ return { content: 'Error: action_prompt is required and must be a string', isError: true };
49
23
  }
50
24
 
51
- async execute(input: Record<string, unknown>, _context: ToolContext): Promise<ToolExecutionResult> {
52
- const name = input.name as string;
53
- const providerId = input.provider as string;
54
- const actionPrompt = input.action_prompt as string;
55
- const pollIntervalMs = (input.poll_interval_ms as number) ?? undefined;
56
- const config = input.config as Record<string, unknown> | undefined;
57
-
58
- if (!name || typeof name !== 'string') {
59
- return { content: 'Error: name is required and must be a string', isError: true };
60
- }
61
- if (!providerId || typeof providerId !== 'string') {
62
- return { content: 'Error: provider is required and must be a string', isError: true };
63
- }
64
- if (!actionPrompt || typeof actionPrompt !== 'string') {
65
- return { content: 'Error: action_prompt is required and must be a string', isError: true };
66
- }
67
-
68
- const provider = getWatcherProvider(providerId);
69
- if (!provider) {
70
- const available = listWatcherProviders().map((p) => p.id).join(', ') || 'none';
71
- return { content: `Error: Unknown provider "${providerId}". Available: ${available}`, isError: true };
72
- }
25
+ const provider = getWatcherProvider(providerId);
26
+ if (!provider) {
27
+ const available = listWatcherProviders().map((p) => p.id).join(', ') || 'none';
28
+ return { content: `Error: Unknown provider "${providerId}". Available: ${available}`, isError: true };
29
+ }
73
30
 
74
- if (pollIntervalMs !== undefined && pollIntervalMs < 15000) {
75
- return { content: 'Error: poll_interval_ms must be at least 15000 (15 seconds)', isError: true };
76
- }
31
+ if (pollIntervalMs !== undefined && pollIntervalMs < 15000) {
32
+ return { content: 'Error: poll_interval_ms must be at least 15000 (15 seconds)', isError: true };
33
+ }
77
34
 
78
- const credentialService = (input.credential_service as string) ?? provider.requiredCredentialService;
35
+ const credentialService = (input.credential_service as string) ?? provider.requiredCredentialService;
79
36
 
80
- try {
81
- const watcher = createWatcher({
82
- name,
83
- providerId,
84
- actionPrompt,
85
- credentialService,
86
- pollIntervalMs,
87
- configJson: config ? JSON.stringify(config) : null,
88
- });
37
+ try {
38
+ const watcher = createWatcher({
39
+ name,
40
+ providerId,
41
+ actionPrompt,
42
+ credentialService,
43
+ pollIntervalMs,
44
+ configJson: config ? JSON.stringify(config) : null,
45
+ });
89
46
 
90
- const intervalSec = Math.round(watcher.pollIntervalMs / 1000);
91
- return {
92
- content: [
93
- 'Watcher created successfully.',
94
- ` Name: ${watcher.name}`,
95
- ` Provider: ${provider.displayName}`,
96
- ` Poll interval: ${intervalSec}s`,
97
- ` Credential: ${watcher.credentialService}`,
98
- ` Status: ${watcher.status}`,
99
- ` ID: ${watcher.id}`,
100
- ].join('\n'),
101
- isError: false,
102
- };
103
- } catch (err) {
104
- const msg = err instanceof Error ? err.message : String(err);
105
- return { content: `Error creating watcher: ${msg}`, isError: true };
106
- }
47
+ const intervalSec = Math.round(watcher.pollIntervalMs / 1000);
48
+ return {
49
+ content: [
50
+ 'Watcher created successfully.',
51
+ ` Name: ${watcher.name}`,
52
+ ` Provider: ${provider.displayName}`,
53
+ ` Poll interval: ${intervalSec}s`,
54
+ ` Credential: ${watcher.credentialService}`,
55
+ ` Status: ${watcher.status}`,
56
+ ` ID: ${watcher.id}`,
57
+ ].join('\n'),
58
+ isError: false,
59
+ };
60
+ } catch (err) {
61
+ const msg = err instanceof Error ? err.message : String(err);
62
+ return { content: `Error creating watcher: ${msg}`, isError: true };
107
63
  }
108
64
  }
109
-
110
- registerTool(new WatcherCreateTool());
@@ -1,53 +1,27 @@
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 { getWatcher, deleteWatcher } from '../../watcher/watcher-store.js';
6
3
 
7
- class WatcherDeleteTool implements Tool {
8
- name = 'watcher_delete';
9
- description = 'Delete a watcher and all its event history';
10
- category = 'watcher';
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
- watcher_id: {
21
- type: 'string',
22
- description: 'The ID of the watcher to delete',
23
- },
24
- },
25
- required: ['watcher_id'],
26
- },
27
- };
4
+ export async function executeWatcherDelete(
5
+ input: Record<string, unknown>,
6
+ _context: ToolContext,
7
+ ): Promise<ToolExecutionResult> {
8
+ const watcherId = input.watcher_id as string;
9
+ if (!watcherId || typeof watcherId !== 'string') {
10
+ return { content: 'Error: watcher_id is required', isError: true };
28
11
  }
29
12
 
30
- async execute(input: Record<string, unknown>, _context: ToolContext): Promise<ToolExecutionResult> {
31
- const watcherId = input.watcher_id as string;
32
- if (!watcherId || typeof watcherId !== 'string') {
33
- return { content: 'Error: watcher_id is required', isError: true };
34
- }
35
-
36
- const watcher = getWatcher(watcherId);
37
- if (!watcher) {
38
- return { content: `Error: Watcher not found: ${watcherId}`, isError: true };
39
- }
40
-
41
- const deleted = deleteWatcher(watcherId);
42
- if (!deleted) {
43
- return { content: `Error: Failed to delete watcher: ${watcherId}`, isError: true };
44
- }
13
+ const watcher = getWatcher(watcherId);
14
+ if (!watcher) {
15
+ return { content: `Error: Watcher not found: ${watcherId}`, isError: true };
16
+ }
45
17
 
46
- return {
47
- content: `Watcher deleted: "${watcher.name}"`,
48
- isError: false,
49
- };
18
+ const deleted = deleteWatcher(watcherId);
19
+ if (!deleted) {
20
+ return { content: `Error: Failed to delete watcher: ${watcherId}`, isError: true };
50
21
  }
51
- }
52
22
 
53
- registerTool(new WatcherDeleteTool());
23
+ return {
24
+ content: `Watcher deleted: "${watcher.name}"`,
25
+ isError: false,
26
+ };
27
+ }
@@ -1,84 +1,50 @@
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 { listWatchers, listWatcherEvents } from '../../watcher/watcher-store.js';
6
3
 
7
- class WatcherDigestTool implements Tool {
8
- name = 'watcher_digest';
9
- description = 'Get a summary of recent watcher activity. Use this when the user asks about what happened with their email, notifications, etc.';
10
- category = 'watcher';
11
- defaultRiskLevel = RiskLevel.Low;
4
+ export async function executeWatcherDigest(
5
+ input: Record<string, unknown>,
6
+ _context: ToolContext,
7
+ ): Promise<ToolExecutionResult> {
8
+ const watcherId = input.watcher_id as string | undefined;
9
+ const hours = (input.hours as number) ?? 24;
10
+ const limit = (input.limit as number) ?? 50;
12
11
 
13
- getDefinition(): ToolDefinition {
14
- return {
15
- name: this.name,
16
- description: this.description,
17
- input_schema: {
18
- type: 'object',
19
- properties: {
20
- watcher_id: {
21
- type: 'string',
22
- description: 'Filter to events from a specific watcher. If omitted, shows events from all watchers.',
23
- },
24
- hours: {
25
- type: 'number',
26
- description: 'How many hours back to look. Defaults to 24.',
27
- },
28
- limit: {
29
- type: 'number',
30
- description: 'Maximum number of events to return. Defaults to 50.',
31
- },
32
- },
33
- required: [],
34
- },
35
- };
36
- }
37
-
38
- async execute(input: Record<string, unknown>, _context: ToolContext): Promise<ToolExecutionResult> {
39
- const watcherId = input.watcher_id as string | undefined;
40
- const hours = (input.hours as number) ?? 24;
41
- const limit = (input.limit as number) ?? 50;
42
-
43
- const since = Date.now() - hours * 60 * 60 * 1000;
12
+ const since = Date.now() - hours * 60 * 60 * 1000;
44
13
 
45
- const events = listWatcherEvents({ watcherId, limit, since });
14
+ const events = listWatcherEvents({ watcherId, limit, since });
46
15
 
47
- if (events.length === 0) {
48
- const period = hours === 24 ? 'today' : `the last ${hours} hours`;
49
- return { content: `No watcher events detected ${period}.`, isError: false };
50
- }
16
+ if (events.length === 0) {
17
+ const period = hours === 24 ? 'today' : `the last ${hours} hours`;
18
+ return { content: `No watcher events detected ${period}.`, isError: false };
19
+ }
51
20
 
52
- // Group events by watcher
53
- const watcherMap = new Map<string, typeof events>();
54
- for (const event of events) {
55
- const existing = watcherMap.get(event.watcherId) ?? [];
56
- existing.push(event);
57
- watcherMap.set(event.watcherId, existing);
58
- }
21
+ // Group events by watcher
22
+ const watcherMap = new Map<string, typeof events>();
23
+ for (const event of events) {
24
+ const existing = watcherMap.get(event.watcherId) ?? [];
25
+ existing.push(event);
26
+ watcherMap.set(event.watcherId, existing);
27
+ }
59
28
 
60
- // Get watcher names
61
- const allWatchers = listWatchers();
62
- const nameMap = new Map(allWatchers.map((w) => [w.id, w.name]));
29
+ // Get watcher names
30
+ const allWatchers = listWatchers();
31
+ const nameMap = new Map(allWatchers.map((w) => [w.id, w.name]));
63
32
 
64
- const lines = [`Watcher activity (last ${hours}h, ${events.length} events):`];
33
+ const lines = [`Watcher activity (last ${hours}h, ${events.length} events):`];
65
34
 
66
- for (const [wId, wEvents] of watcherMap) {
67
- const name = nameMap.get(wId) ?? wId;
68
- lines.push('', `${name} (${wEvents.length} events):`);
35
+ for (const [wId, wEvents] of watcherMap) {
36
+ const name = nameMap.get(wId) ?? wId;
37
+ lines.push('', `${name} (${wEvents.length} events):`);
69
38
 
70
- for (const event of wEvents) {
71
- const time = new Date(event.createdAt).toLocaleString();
72
- const disposition = event.disposition !== 'pending' ? ` [${event.disposition}]` : '';
73
- lines.push(` - ${event.summary}${disposition} (${time})`);
74
- if (event.llmAction) {
75
- lines.push(` Action: ${event.llmAction}`);
76
- }
39
+ for (const event of wEvents) {
40
+ const time = new Date(event.createdAt).toLocaleString();
41
+ const disposition = event.disposition !== 'pending' ? ` [${event.disposition}]` : '';
42
+ lines.push(` - ${event.summary}${disposition} (${time})`);
43
+ if (event.llmAction) {
44
+ lines.push(` Action: ${event.llmAction}`);
77
45
  }
78
46
  }
79
-
80
- return { content: lines.join('\n'), isError: false };
81
47
  }
82
- }
83
48
 
84
- registerTool(new WatcherDigestTool());
49
+ return { content: lines.join('\n'), isError: false };
50
+ }
@@ -1,90 +1,60 @@
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 { listWatchers, getWatcher, listWatcherEvents } from '../../watcher/watcher-store.js';
6
3
 
7
- class WatcherListTool implements Tool {
8
- name = 'watcher_list';
9
- description = 'List all watchers with their status, or show details for a specific watcher';
10
- category = 'watcher';
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
- watcher_id: {
21
- type: 'string',
22
- description: 'If provided, show detailed info for this specific watcher including recent events.',
23
- },
24
- enabled_only: {
25
- type: 'boolean',
26
- description: 'When true, only show enabled watchers. Defaults to false.',
27
- },
28
- },
29
- required: [],
30
- },
31
- };
32
- }
33
-
34
- async execute(input: Record<string, unknown>, _context: ToolContext): Promise<ToolExecutionResult> {
35
- const watcherId = input.watcher_id as string | undefined;
36
- const enabledOnly = (input.enabled_only as boolean) ?? false;
37
-
38
- if (watcherId) {
39
- const watcher = getWatcher(watcherId);
40
- if (!watcher) {
41
- return { content: `Error: Watcher not found: ${watcherId}`, isError: true };
42
- }
43
-
44
- const events = listWatcherEvents({ watcherId, limit: 10 });
45
- const lines = [
46
- `Watcher: ${watcher.name}`,
47
- ` ID: ${watcher.id}`,
48
- ` Provider: ${watcher.providerId}`,
49
- ` Status: ${watcher.status}`,
50
- ` Enabled: ${watcher.enabled}`,
51
- ` Poll interval: ${Math.round(watcher.pollIntervalMs / 1000)}s`,
52
- ` Credential: ${watcher.credentialService}`,
53
- ` Last poll: ${watcher.lastPollAt ? new Date(watcher.lastPollAt).toLocaleString() : 'never'}`,
54
- ` Next poll: ${watcher.nextPollAt ? new Date(watcher.nextPollAt).toLocaleString() : 'n/a'}`,
55
- ` Errors: ${watcher.consecutiveErrors}`,
56
- ];
57
-
58
- if (watcher.lastError) {
59
- lines.push(` Last error: ${watcher.lastError}`);
60
- }
61
-
62
- if (events.length > 0) {
63
- lines.push('', `Recent events (${events.length}):`);
64
- for (const event of events) {
65
- lines.push(` - [${event.disposition}] ${event.summary} (${new Date(event.createdAt).toLocaleString()})`);
66
- }
67
- } else {
68
- lines.push('', 'No events detected yet.');
69
- }
70
-
71
- return { content: lines.join('\n'), isError: false };
4
+ export async function executeWatcherList(
5
+ input: Record<string, unknown>,
6
+ _context: ToolContext,
7
+ ): Promise<ToolExecutionResult> {
8
+ const watcherId = input.watcher_id as string | undefined;
9
+ const enabledOnly = (input.enabled_only as boolean) ?? false;
10
+
11
+ if (watcherId) {
12
+ const watcher = getWatcher(watcherId);
13
+ if (!watcher) {
14
+ return { content: `Error: Watcher not found: ${watcherId}`, isError: true };
72
15
  }
73
16
 
74
- const allWatchers = listWatchers({ enabledOnly });
75
- if (allWatchers.length === 0) {
76
- return { content: 'No watchers found.', isError: false };
17
+ const events = listWatcherEvents({ watcherId, limit: 10 });
18
+ const lines = [
19
+ `Watcher: ${watcher.name}`,
20
+ ` ID: ${watcher.id}`,
21
+ ` Provider: ${watcher.providerId}`,
22
+ ` Status: ${watcher.status}`,
23
+ ` Enabled: ${watcher.enabled}`,
24
+ ` Poll interval: ${Math.round(watcher.pollIntervalMs / 1000)}s`,
25
+ ` Credential: ${watcher.credentialService}`,
26
+ ` Last poll: ${watcher.lastPollAt ? new Date(watcher.lastPollAt).toLocaleString() : 'never'}`,
27
+ ` Next poll: ${watcher.nextPollAt ? new Date(watcher.nextPollAt).toLocaleString() : 'n/a'}`,
28
+ ` Errors: ${watcher.consecutiveErrors}`,
29
+ ];
30
+
31
+ if (watcher.lastError) {
32
+ lines.push(` Last error: ${watcher.lastError}`);
77
33
  }
78
34
 
79
- const lines = [`Watchers (${allWatchers.length}):`];
80
- for (const w of allWatchers) {
81
- const status = w.enabled ? w.status : 'disabled';
82
- const lastPoll = w.lastPollAt ? new Date(w.lastPollAt).toLocaleString() : 'never';
83
- lines.push(` - [${status}] ${w.name} (${w.providerId}) — last: ${lastPoll}`);
35
+ if (events.length > 0) {
36
+ lines.push('', `Recent events (${events.length}):`);
37
+ for (const event of events) {
38
+ lines.push(` - [${event.disposition}] ${event.summary} (${new Date(event.createdAt).toLocaleString()})`);
39
+ }
40
+ } else {
41
+ lines.push('', 'No events detected yet.');
84
42
  }
85
43
 
86
44
  return { content: lines.join('\n'), isError: false };
87
45
  }
88
- }
89
46
 
90
- registerTool(new WatcherListTool());
47
+ const allWatchers = listWatchers({ enabledOnly });
48
+ if (allWatchers.length === 0) {
49
+ return { content: 'No watchers found.', isError: false };
50
+ }
51
+
52
+ const lines = [`Watchers (${allWatchers.length}):`];
53
+ for (const w of allWatchers) {
54
+ const status = w.enabled ? w.status : 'disabled';
55
+ const lastPoll = w.lastPollAt ? new Date(w.lastPollAt).toLocaleString() : 'never';
56
+ lines.push(` - [${status}] ${w.name} (${w.providerId}) — last: ${lastPoll}`);
57
+ }
58
+
59
+ return { content: lines.join('\n'), isError: false };
60
+ }
@@ -1,102 +1,56 @@
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 { updateWatcher } from '../../watcher/watcher-store.js';
6
3
 
7
- class WatcherUpdateTool implements Tool {
8
- name = 'watcher_update';
9
- description = 'Update a watcher\'s configuration (name, action prompt, interval, enabled state)';
10
- category = 'watcher';
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
- watcher_id: {
21
- type: 'string',
22
- description: 'The ID of the watcher to update',
23
- },
24
- name: {
25
- type: 'string',
26
- description: 'New name for the watcher',
27
- },
28
- action_prompt: {
29
- type: 'string',
30
- description: 'New action prompt for event processing',
31
- },
32
- poll_interval_ms: {
33
- type: 'number',
34
- description: 'New poll interval in milliseconds (minimum 15000)',
35
- },
36
- enabled: {
37
- type: 'boolean',
38
- description: 'Enable or disable the watcher',
39
- },
40
- config: {
41
- type: 'object',
42
- description: 'New provider-specific configuration',
43
- },
44
- },
45
- required: ['watcher_id'],
46
- },
47
- };
4
+ export async function executeWatcherUpdate(
5
+ input: Record<string, unknown>,
6
+ _context: ToolContext,
7
+ ): Promise<ToolExecutionResult> {
8
+ const watcherId = input.watcher_id as string;
9
+ if (!watcherId || typeof watcherId !== 'string') {
10
+ return { content: 'Error: watcher_id is required', isError: true };
48
11
  }
49
12
 
50
- async execute(input: Record<string, unknown>, _context: ToolContext): Promise<ToolExecutionResult> {
51
- const watcherId = input.watcher_id as string;
52
- if (!watcherId || typeof watcherId !== 'string') {
53
- return { content: 'Error: watcher_id is required', isError: true };
13
+ const updates: Record<string, unknown> = {};
14
+ if (input.name !== undefined) updates.name = input.name;
15
+ if (input.action_prompt !== undefined) updates.actionPrompt = input.action_prompt;
16
+ if (input.poll_interval_ms !== undefined) {
17
+ if ((input.poll_interval_ms as number) < 15000) {
18
+ return { content: 'Error: poll_interval_ms must be at least 15000 (15 seconds)', isError: true };
54
19
  }
20
+ updates.pollIntervalMs = input.poll_interval_ms;
21
+ }
22
+ if (input.enabled !== undefined) updates.enabled = input.enabled;
23
+ if (input.config !== undefined) updates.configJson = JSON.stringify(input.config);
55
24
 
56
- const updates: Record<string, unknown> = {};
57
- if (input.name !== undefined) updates.name = input.name;
58
- if (input.action_prompt !== undefined) updates.actionPrompt = input.action_prompt;
59
- if (input.poll_interval_ms !== undefined) {
60
- if ((input.poll_interval_ms as number) < 15000) {
61
- return { content: 'Error: poll_interval_ms must be at least 15000 (15 seconds)', isError: true };
62
- }
63
- updates.pollIntervalMs = input.poll_interval_ms;
64
- }
65
- if (input.enabled !== undefined) updates.enabled = input.enabled;
66
- if (input.config !== undefined) updates.configJson = JSON.stringify(input.config);
25
+ if (Object.keys(updates).length === 0) {
26
+ return { content: 'Error: No updates provided. Specify at least one field to update.', isError: true };
27
+ }
67
28
 
68
- if (Object.keys(updates).length === 0) {
69
- return { content: 'Error: No updates provided. Specify at least one field to update.', isError: true };
29
+ try {
30
+ const watcher = updateWatcher(watcherId, updates as {
31
+ name?: string;
32
+ actionPrompt?: string;
33
+ pollIntervalMs?: number;
34
+ enabled?: boolean;
35
+ configJson?: string | null;
36
+ });
37
+
38
+ if (!watcher) {
39
+ return { content: `Error: Watcher not found: ${watcherId}`, isError: true };
70
40
  }
71
41
 
72
- try {
73
- const watcher = updateWatcher(watcherId, updates as {
74
- name?: string;
75
- actionPrompt?: string;
76
- pollIntervalMs?: number;
77
- enabled?: boolean;
78
- configJson?: string | null;
79
- });
80
-
81
- if (!watcher) {
82
- return { content: `Error: Watcher not found: ${watcherId}`, isError: true };
83
- }
84
-
85
- return {
86
- content: [
87
- 'Watcher updated successfully.',
88
- ` Name: ${watcher.name}`,
89
- ` Enabled: ${watcher.enabled}`,
90
- ` Status: ${watcher.status}`,
91
- ` Poll interval: ${Math.round(watcher.pollIntervalMs / 1000)}s`,
92
- ].join('\n'),
93
- isError: false,
94
- };
95
- } catch (err) {
96
- const msg = err instanceof Error ? err.message : String(err);
97
- return { content: `Error updating watcher: ${msg}`, isError: true };
98
- }
42
+ return {
43
+ content: [
44
+ 'Watcher updated successfully.',
45
+ ` Name: ${watcher.name}`,
46
+ ` Enabled: ${watcher.enabled}`,
47
+ ` Status: ${watcher.status}`,
48
+ ` Poll interval: ${Math.round(watcher.pollIntervalMs / 1000)}s`,
49
+ ].join('\n'),
50
+ isError: false,
51
+ };
52
+ } catch (err) {
53
+ const msg = err instanceof Error ? err.message : String(err);
54
+ return { content: `Error updating watcher: ${msg}`, isError: true };
99
55
  }
100
56
  }
101
-
102
- registerTool(new WatcherUpdateTool());