@vellumai/assistant 0.6.5 → 0.6.6

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 (443) hide show
  1. package/AGENTS.md +9 -1
  2. package/ARCHITECTURE.md +15 -17
  3. package/Dockerfile +6 -4
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +283 -0
  5. package/docs/architecture/integrations.md +32 -39
  6. package/docs/architecture/memory.md +25 -30
  7. package/docs/architecture/security.md +7 -6
  8. package/docs/browser-use-architecture-phase2.md +63 -20
  9. package/docs/plugins.md +761 -0
  10. package/examples/plugins/echo/README.md +132 -0
  11. package/examples/plugins/echo/package.json +17 -0
  12. package/examples/plugins/echo/register.ts +187 -0
  13. package/node_modules/@vellumai/egress-proxy/src/types.ts +19 -0
  14. package/openapi.yaml +212 -68
  15. package/package.json +1 -1
  16. package/src/__tests__/app-compiler.test.ts +57 -0
  17. package/src/__tests__/approval-cascade.test.ts +7 -2
  18. package/src/__tests__/auto-analysis-end-to-end.test.ts +1 -0
  19. package/src/__tests__/avatar-generator.test.ts +4 -2
  20. package/src/__tests__/bundled-asset.test.ts +6 -6
  21. package/src/__tests__/catalog-cache.test.ts +69 -0
  22. package/src/__tests__/checker.test.ts +459 -171
  23. package/src/__tests__/circuit-breaker-pipeline.test.ts +406 -0
  24. package/src/__tests__/compaction-events.test.ts +501 -0
  25. package/src/__tests__/compaction-pipeline.test.ts +210 -0
  26. package/src/__tests__/compaction-strip-metadata-clear.test.ts +181 -0
  27. package/src/__tests__/compaction-timeout-recovery.test.ts +262 -0
  28. package/src/__tests__/config-model-image-provider.test.ts +110 -0
  29. package/src/__tests__/config-schema.test.ts +22 -9
  30. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +0 -4
  31. package/src/__tests__/contacts-tools.test.ts +26 -0
  32. package/src/__tests__/context-overflow-policy.test.ts +7 -7
  33. package/src/__tests__/context-window-manager.test.ts +355 -4
  34. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
  35. package/src/__tests__/conversation-agent-loop-overflow.test.ts +26 -30
  36. package/src/__tests__/conversation-agent-loop.test.ts +30 -141
  37. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -1
  38. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  39. package/src/__tests__/conversation-init.benchmark.test.ts +2 -16
  40. package/src/__tests__/conversation-pairing.test.ts +174 -10
  41. package/src/__tests__/conversation-pre-run-repair.test.ts +4 -1
  42. package/src/__tests__/conversation-process-callsite.test.ts +3 -0
  43. package/src/__tests__/conversation-provider-retry-repair.test.ts +16 -7
  44. package/src/__tests__/conversation-queue.test.ts +29 -14
  45. package/src/__tests__/conversation-routes-disk-view.test.ts +7 -6
  46. package/src/__tests__/conversation-runtime-assembly.test.ts +155 -110
  47. package/src/__tests__/conversation-runtime-workspace.test.ts +23 -38
  48. package/src/__tests__/conversation-seed-composer.test.ts +2 -2
  49. package/src/__tests__/conversation-slash-queue.test.ts +7 -2
  50. package/src/__tests__/conversation-slash-unknown.test.ts +25 -2
  51. package/src/__tests__/conversation-speed-override.test.ts +6 -1
  52. package/src/__tests__/conversation-title-service.test.ts +116 -0
  53. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +41 -2
  54. package/src/__tests__/conversation-usage.test.ts +1 -1
  55. package/src/__tests__/conversation-workspace-cache-state.test.ts +4 -1
  56. package/src/__tests__/conversation-workspace-injection.test.ts +3 -0
  57. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +4 -1
  58. package/src/__tests__/credential-health-service.test.ts +78 -9
  59. package/src/__tests__/credential-security-invariants.test.ts +2 -2
  60. package/src/__tests__/db-schedule-syntax-migration.test.ts +1 -0
  61. package/src/__tests__/empty-response-pipeline.test.ts +305 -0
  62. package/src/__tests__/extension-id-sync-guard.test.ts +3 -3
  63. package/src/__tests__/first-greeting.test.ts +247 -5
  64. package/src/__tests__/headless-browser-mode.test.ts +57 -0
  65. package/src/__tests__/history-repair-pipeline.test.ts +399 -0
  66. package/src/__tests__/host-browser-e2e-cloud.test.ts +307 -0
  67. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +3 -3
  68. package/src/__tests__/host-proxy-interface.test.ts +36 -2
  69. package/src/__tests__/image-credentials.test.ts +137 -0
  70. package/src/__tests__/image-service-dispatcher.test.ts +186 -0
  71. package/src/__tests__/injector-chain.test.ts +526 -0
  72. package/src/__tests__/intent-routing.test.ts +0 -26
  73. package/src/__tests__/llm-call-pipeline.test.ts +285 -0
  74. package/src/__tests__/llm-schema.test.ts +1 -1
  75. package/src/__tests__/media-generate-image.test.ts +119 -13
  76. package/src/__tests__/memory-retrieval-pipeline.test.ts +401 -0
  77. package/src/__tests__/memory-upsert-concurrency.test.ts +1 -0
  78. package/src/__tests__/migration-import-from-url.test.ts +5 -68
  79. package/src/__tests__/model-intents.test.ts +4 -2
  80. package/src/__tests__/notification-broadcaster.test.ts +3 -3
  81. package/src/__tests__/notification-decision-strategy.test.ts +0 -11
  82. package/src/__tests__/notification-schedule-notify-dedup.test.ts +108 -0
  83. package/src/__tests__/oauth-apps-routes.test.ts +1 -1
  84. package/src/__tests__/oauth-cli.test.ts +14 -12
  85. package/src/__tests__/oauth-connect-orchestrator.test.ts +4 -13
  86. package/src/__tests__/oauth-provider-serializer.test.ts +6 -4
  87. package/src/__tests__/oauth-provider-visibility.test.ts +3 -5
  88. package/src/__tests__/oauth-providers-routes.test.ts +3 -2
  89. package/src/__tests__/oauth-store.test.ts +41 -76
  90. package/src/__tests__/onboarding-template-contract.test.ts +16 -64
  91. package/src/__tests__/openai-image-service.test.ts +368 -0
  92. package/src/__tests__/overflow-reduce-pipeline.test.ts +676 -0
  93. package/src/__tests__/permission-checker-host-gate.test.ts +0 -24
  94. package/src/__tests__/persist-onboarding-artifacts.test.ts +266 -0
  95. package/src/__tests__/persistence-pipeline.test.ts +377 -0
  96. package/src/__tests__/pipeline-runner.test.ts +565 -0
  97. package/src/__tests__/platform.test.ts +5 -2
  98. package/src/__tests__/plugin-bootstrap.test.ts +483 -0
  99. package/src/__tests__/plugin-registry.test.ts +273 -0
  100. package/src/__tests__/plugin-route-contribution.test.ts +288 -0
  101. package/src/__tests__/plugin-skill-contribution.test.ts +367 -0
  102. package/src/__tests__/plugin-tool-contribution.test.ts +286 -0
  103. package/src/__tests__/plugin-types.test.ts +320 -0
  104. package/src/__tests__/pricing.test.ts +44 -12
  105. package/src/__tests__/proxy-approval-callback.test.ts +69 -8
  106. package/src/__tests__/reaction-persistence.test.ts +1 -0
  107. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
  108. package/src/__tests__/registry.test.ts +0 -2
  109. package/src/__tests__/schedule-routes.test.ts +131 -1
  110. package/src/__tests__/scheduler-recurrence.test.ts +14 -70
  111. package/src/__tests__/scheduler-reuse-conversation.test.ts +10 -50
  112. package/src/__tests__/secret-detection-handler.test.ts +0 -10
  113. package/src/__tests__/shell-identity.test.ts +0 -134
  114. package/src/__tests__/suggestion-routes.test.ts +103 -4
  115. package/src/__tests__/task-memory-cleanup.test.ts +1 -0
  116. package/src/__tests__/task-scheduler.test.ts +3 -15
  117. package/src/__tests__/test-preload.ts +11 -0
  118. package/src/__tests__/title-generate-pipeline.test.ts +224 -0
  119. package/src/__tests__/token-estimate-pipeline.test.ts +431 -0
  120. package/src/__tests__/tool-error-pipeline.test.ts +244 -0
  121. package/src/__tests__/tool-execute-pipeline.test.ts +431 -0
  122. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -6
  123. package/src/__tests__/tool-executor-shell-integration.test.ts +7 -10
  124. package/src/__tests__/tool-executor.test.ts +141 -0
  125. package/src/__tests__/tool-result-truncate-pipeline.test.ts +356 -0
  126. package/src/__tests__/tool-result-truncation.test.ts +0 -110
  127. package/src/__tests__/user-plugin-loader.test.ts +191 -0
  128. package/src/__tests__/workspace-migration-046-seed-conversation-starters-callsite.test.ts +185 -0
  129. package/src/__tests__/workspace-migration-049-release-notes-default-sonnet.test.ts +100 -0
  130. package/src/__tests__/workspace-migration-050-seed-main-agent-opus-callsite.test.ts +171 -0
  131. package/src/__tests__/workspace-migration-051-seed-conversation-summarization-callsite.test.ts +252 -0
  132. package/src/__tests__/workspace-migration-remove-hooks.test.ts +99 -0
  133. package/src/__tests__/workspace-policy.test.ts +21 -3
  134. package/src/agent/loop.ts +340 -102
  135. package/src/approvals/__tests__/guardian-feed-event.test.ts +304 -0
  136. package/src/approvals/guardian-request-resolvers.ts +80 -0
  137. package/src/backup/__tests__/backup-worker.test.ts +2 -13
  138. package/src/backup/backup-worker.ts +3 -15
  139. package/src/bundler/app-compiler.ts +84 -1
  140. package/src/calls/call-state.ts +2 -2
  141. package/src/channels/__tests__/types.test.ts +3 -3
  142. package/src/channels/types.ts +6 -4
  143. package/src/cli/__tests__/notifications.test.ts +87 -211
  144. package/src/cli/commands/__tests__/backup.test.ts +1 -1
  145. package/src/cli/commands/__tests__/image-generation.test.ts +255 -35
  146. package/src/cli/commands/__tests__/inference-send.test.ts +12 -0
  147. package/src/cli/commands/__tests__/tts-synthesize.test.ts +12 -0
  148. package/src/cli/commands/backup.ts +2 -2
  149. package/src/cli/commands/clients.ts +138 -0
  150. package/src/cli/commands/completions.ts +2 -9
  151. package/src/cli/commands/conversations.ts +55 -7
  152. package/src/cli/commands/image-generation.ts +33 -34
  153. package/src/cli/commands/notifications.ts +68 -103
  154. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -1
  155. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -1
  156. package/src/cli/commands/oauth/connect.ts +2 -2
  157. package/src/cli/commands/oauth/providers.ts +176 -8
  158. package/src/cli/commands/oauth/status.ts +46 -36
  159. package/src/cli/commands/skills.ts +3 -4
  160. package/src/cli/program.ts +25 -29
  161. package/src/config/__tests__/backup-schema.test.ts +7 -2
  162. package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
  163. package/src/config/bundled-skills/app-builder/references/WIDGETS.md +10 -10
  164. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +66 -87
  165. package/src/config/bundled-skills/contacts/tools/contact-search.ts +28 -51
  166. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +22 -40
  167. package/src/config/bundled-skills/image-studio/SKILL.md +2 -1
  168. package/src/config/bundled-skills/image-studio/TOOLS.json +2 -1
  169. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +23 -39
  170. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  171. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +207 -0
  172. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +12 -0
  173. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +58 -0
  174. package/src/config/bundled-skills/schedule/SKILL.md +8 -3
  175. package/src/config/bundled-skills/schedule/TOOLS.json +15 -7
  176. package/src/config/bundled-skills/schedule/references/SCRIPT_MODE_PATTERNS.md +59 -0
  177. package/src/config/bundled-tool-registry.ts +0 -15
  178. package/src/config/feature-flag-registry.json +17 -1
  179. package/src/config/schema.ts +19 -0
  180. package/src/config/schemas/backup.ts +1 -1
  181. package/src/config/schemas/conversations.ts +16 -0
  182. package/src/config/schemas/llm.ts +2 -3
  183. package/src/config/schemas/security.ts +6 -6
  184. package/src/config/schemas/tts.ts +11 -0
  185. package/src/config/skill-state.ts +6 -2
  186. package/src/config/skills.ts +94 -5
  187. package/src/context/__tests__/compact-prompt.test.ts +27 -9
  188. package/src/context/prompts/compact.md +26 -12
  189. package/src/context/tool-result-truncation.ts +3 -63
  190. package/src/context/window-manager.ts +190 -16
  191. package/src/credential-health/credential-health-service.ts +19 -6
  192. package/src/daemon/__tests__/conversation-feed-event.test.ts +317 -0
  193. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +4 -12
  194. package/src/daemon/__tests__/conversation-tool-setup.test.ts +14 -15
  195. package/src/daemon/config-watcher.ts +0 -2
  196. package/src/daemon/context-overflow-policy.ts +4 -13
  197. package/src/daemon/conversation-agent-loop-handlers.ts +83 -22
  198. package/src/daemon/conversation-agent-loop.ts +984 -683
  199. package/src/daemon/conversation-history.ts +10 -19
  200. package/src/daemon/conversation-lifecycle.ts +37 -19
  201. package/src/daemon/conversation-notifiers.ts +2 -110
  202. package/src/daemon/conversation-process.ts +14 -7
  203. package/src/daemon/conversation-runtime-assembly.ts +532 -411
  204. package/src/daemon/conversation-tool-setup.ts +41 -4
  205. package/src/daemon/conversation.ts +80 -35
  206. package/src/daemon/external-plugins-bootstrap.ts +478 -0
  207. package/src/daemon/first-greeting.ts +191 -14
  208. package/src/daemon/handlers/config-model.ts +11 -0
  209. package/src/daemon/handlers/skills.ts +5 -1
  210. package/src/daemon/lifecycle.ts +33 -68
  211. package/src/daemon/message-types/computer-use.ts +2 -34
  212. package/src/daemon/message-types/conversations.ts +49 -0
  213. package/src/daemon/message-types/messages.ts +12 -0
  214. package/src/daemon/server.ts +5 -3
  215. package/src/daemon/shutdown-handlers.ts +2 -12
  216. package/src/daemon/tool-side-effects.ts +14 -56
  217. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +160 -0
  218. package/src/heartbeat/heartbeat-service.ts +24 -1
  219. package/src/home/__tests__/feed-population-integration.test.ts +312 -0
  220. package/src/home/emit-feed-event.ts +7 -0
  221. package/src/home/feed-types.ts +41 -2
  222. package/src/home/rewrite-command-preview.ts +66 -0
  223. package/src/ipc/__tests__/socket-path.test.ts +11 -50
  224. package/src/ipc/cli-client.ts +1 -1
  225. package/src/ipc/cli-server.ts +3 -3
  226. package/src/ipc/gateway-client.ts +4 -1
  227. package/src/ipc/routes/browser-context.ts +2 -0
  228. package/src/ipc/routes/browser.ts +1 -0
  229. package/src/ipc/routes/get-contact.ts +16 -0
  230. package/src/ipc/routes/index.ts +14 -0
  231. package/src/ipc/routes/list-clients.ts +31 -0
  232. package/src/ipc/routes/merge-contacts.ts +17 -0
  233. package/src/ipc/routes/notification.ts +133 -0
  234. package/src/ipc/routes/rename-conversation.ts +59 -0
  235. package/src/ipc/routes/search-contacts.ts +19 -0
  236. package/src/ipc/routes/upsert-contact.ts +25 -0
  237. package/src/ipc/socket-path.ts +14 -38
  238. package/src/media/app-icon-generator.ts +23 -46
  239. package/src/media/avatar-router.ts +26 -41
  240. package/src/media/gemini-image-service.ts +8 -41
  241. package/src/media/image-credentials.ts +73 -0
  242. package/src/media/image-service.ts +85 -0
  243. package/src/media/openai-image-service.ts +131 -0
  244. package/src/media/types.ts +46 -0
  245. package/src/memory/conversation-crud.ts +48 -18
  246. package/src/memory/conversation-queries.ts +57 -4
  247. package/src/memory/conversation-title-service.ts +25 -0
  248. package/src/memory/db-init.ts +8 -0
  249. package/src/memory/embedding-gemini.test.ts +41 -2
  250. package/src/memory/embedding-gemini.ts +6 -1
  251. package/src/memory/graph/bootstrap.test.ts +282 -0
  252. package/src/memory/graph/bootstrap.ts +8 -5
  253. package/src/memory/graph/extraction.ts +10 -2
  254. package/src/memory/graph/graph-search.test.ts +1 -0
  255. package/src/memory/graph/inspect.ts +2 -2
  256. package/src/memory/graph/retriever.ts +10 -3
  257. package/src/memory/migrations/041-approval-prompt-ts-tracker.ts +26 -0
  258. package/src/memory/migrations/149-oauth-tables.ts +1 -0
  259. package/src/memory/migrations/223-schedule-script-column.ts +11 -0
  260. package/src/memory/migrations/224-oauth-providers-managed-service-is-paid.ts +24 -0
  261. package/src/memory/migrations/225-oauth-providers-available-scopes.ts +13 -0
  262. package/src/memory/migrations/index.ts +4 -0
  263. package/src/memory/pkb/pkb-index.test.ts +1 -0
  264. package/src/memory/pkb/pkb-reconcile.test.ts +1 -0
  265. package/src/memory/pkb/pkb-search.test.ts +65 -4
  266. package/src/memory/pkb/pkb-search.ts +40 -18
  267. package/src/memory/qdrant-client.test.ts +60 -0
  268. package/src/memory/qdrant-client.ts +25 -0
  269. package/src/memory/schema/infrastructure.ts +1 -0
  270. package/src/memory/schema/oauth.ts +4 -1
  271. package/src/messaging/providers/slack/render-transcript.test.ts +77 -29
  272. package/src/messaging/providers/slack/render-transcript.ts +58 -0
  273. package/src/notifications/conversation-pairing.ts +78 -19
  274. package/src/notifications/copy-composer.ts +0 -5
  275. package/src/notifications/emit-signal.ts +1 -1
  276. package/src/notifications/signal.ts +1 -2
  277. package/src/oauth/AGENTS.md +1 -1
  278. package/src/oauth/__tests__/identity-verifier.test.ts +2 -1
  279. package/src/oauth/connect-orchestrator.ts +8 -34
  280. package/src/oauth/connect-types.ts +6 -10
  281. package/src/oauth/manual-token-connection.ts +23 -0
  282. package/src/oauth/oauth-store.ts +30 -14
  283. package/src/oauth/provider-serializer.ts +6 -1
  284. package/src/oauth/seed-providers.ts +56 -108
  285. package/src/outbound-proxy/http-forwarder.ts +9 -0
  286. package/src/permissions/approval-policy.test.ts +293 -18
  287. package/src/permissions/approval-policy.ts +110 -58
  288. package/src/permissions/arg-parser.test.ts +161 -0
  289. package/src/permissions/arg-parser.ts +141 -0
  290. package/src/permissions/bash-risk-classifier.test.ts +414 -2
  291. package/src/permissions/bash-risk-classifier.ts +303 -60
  292. package/src/permissions/checker.ts +157 -29
  293. package/src/permissions/command-registry.test.ts +239 -0
  294. package/src/permissions/command-registry.ts +234 -54
  295. package/src/permissions/defaults.ts +5 -4
  296. package/src/permissions/gateway-threshold-reader.ts +196 -0
  297. package/src/permissions/prompter.ts +4 -0
  298. package/src/permissions/risk-types.ts +61 -4
  299. package/src/permissions/schedule-risk-classifier.test.ts +129 -0
  300. package/src/permissions/schedule-risk-classifier.ts +85 -0
  301. package/src/permissions/shell-identity.ts +2 -42
  302. package/src/permissions/types.ts +2 -0
  303. package/src/permissions/workspace-policy.ts +8 -3
  304. package/src/plugins/defaults/circuit-breaker.ts +146 -0
  305. package/src/plugins/defaults/compaction.ts +145 -0
  306. package/src/plugins/defaults/empty-response.ts +126 -0
  307. package/src/plugins/defaults/history-repair.ts +85 -0
  308. package/src/plugins/defaults/index.ts +116 -0
  309. package/src/plugins/defaults/injectors.ts +491 -0
  310. package/src/plugins/defaults/llm-call.ts +82 -0
  311. package/src/plugins/defaults/memory-retrieval.ts +226 -0
  312. package/src/plugins/defaults/overflow-reduce.ts +181 -0
  313. package/src/plugins/defaults/persistence.ts +129 -0
  314. package/src/plugins/defaults/title-generate.ts +95 -0
  315. package/src/plugins/defaults/token-estimate.ts +104 -0
  316. package/src/plugins/defaults/tool-error.ts +126 -0
  317. package/src/plugins/defaults/tool-execute.ts +89 -0
  318. package/src/plugins/defaults/tool-result-truncate.ts +88 -0
  319. package/src/plugins/pipeline.ts +316 -0
  320. package/src/plugins/plugin-skill-contributions.ts +292 -0
  321. package/src/plugins/registry.ts +241 -0
  322. package/src/plugins/types.ts +1134 -0
  323. package/src/plugins/user-loader.ts +177 -0
  324. package/src/prompts/templates/BOOTSTRAP.md +27 -77
  325. package/src/providers/model-catalog.ts +52 -29
  326. package/src/providers/model-intents.ts +1 -1
  327. package/src/providers/openrouter/client.ts +5 -1
  328. package/src/providers/speech-to-text/deepgram-realtime.test.ts +61 -0
  329. package/src/providers/speech-to-text/deepgram-realtime.ts +57 -0
  330. package/src/providers/speech-to-text/xai-realtime.test.ts +72 -4
  331. package/src/providers/speech-to-text/xai-realtime.ts +39 -14
  332. package/src/runtime/AGENTS.md +25 -16
  333. package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +3 -3
  334. package/src/runtime/__tests__/client-registry.test.ts +293 -0
  335. package/src/runtime/client-registry.ts +261 -0
  336. package/src/runtime/http-server.ts +77 -8
  337. package/src/runtime/http-types.ts +0 -2
  338. package/src/runtime/migrations/vbundle-builder.ts +1 -22
  339. package/src/runtime/routes/approval-prompt-ts-tracker.ts +51 -31
  340. package/src/runtime/routes/approval-routes.ts +17 -0
  341. package/src/runtime/routes/browser-extension-pair-routes.ts +27 -8
  342. package/src/runtime/routes/conversation-routes.ts +223 -116
  343. package/src/runtime/routes/inbound-message-handler.ts +88 -13
  344. package/src/runtime/routes/memory-item-routes.test.ts +1 -0
  345. package/src/runtime/routes/migration-routes.ts +0 -3
  346. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +284 -0
  347. package/src/runtime/routes/playground/__tests__/guard.test.ts +80 -0
  348. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +294 -0
  349. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +271 -0
  350. package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +202 -0
  351. package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +309 -0
  352. package/src/runtime/routes/playground/__tests__/state.test.ts +224 -0
  353. package/src/runtime/routes/playground/conversation-not-found.ts +29 -0
  354. package/src/runtime/routes/playground/deps.ts +56 -0
  355. package/src/runtime/routes/playground/force-compact.ts +73 -0
  356. package/src/runtime/routes/playground/guard.ts +37 -0
  357. package/src/runtime/routes/playground/index.ts +28 -0
  358. package/src/runtime/routes/playground/inject-failures.ts +159 -0
  359. package/src/runtime/routes/playground/reset-circuit.ts +115 -0
  360. package/src/runtime/routes/playground/seed-conversation.ts +139 -0
  361. package/src/runtime/routes/playground/seeded-conversations.ts +78 -0
  362. package/src/runtime/routes/playground/state.ts +78 -0
  363. package/src/runtime/routes/schedule-routes.ts +89 -8
  364. package/src/runtime/skill-route-registry.ts +75 -15
  365. package/src/schedule/run-script.ts +68 -0
  366. package/src/schedule/schedule-store.ts +7 -1
  367. package/src/schedule/scheduler.ts +48 -8
  368. package/src/skills/catalog-cache.ts +12 -5
  369. package/src/tools/browser/__tests__/browser-status.test.ts +189 -0
  370. package/src/tools/browser/browser-execution.ts +88 -19
  371. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +230 -0
  372. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +146 -3
  373. package/src/tools/browser/cdp-client/extension-cdp-client.ts +54 -3
  374. package/src/tools/browser/cdp-client/factory.ts +15 -4
  375. package/src/tools/executor.ts +126 -74
  376. package/src/tools/network/script-proxy/session-manager.ts +37 -1
  377. package/src/tools/permission-checker.ts +98 -49
  378. package/src/tools/policy-context.ts +4 -0
  379. package/src/tools/registry.ts +140 -3
  380. package/src/tools/schedule/create.ts +23 -8
  381. package/src/tools/schedule/update.ts +3 -1
  382. package/src/tools/secret-detection-handler.ts +0 -51
  383. package/src/tools/system/avatar-generator.ts +6 -2
  384. package/src/tools/types.ts +28 -2
  385. package/src/util/platform.ts +7 -2
  386. package/src/util/pricing.ts +26 -3
  387. package/src/workspace/migrations/006-services-config.ts +2 -4
  388. package/src/workspace/migrations/022-move-hooks-to-workspace.ts +2 -3
  389. package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +3 -4
  390. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +108 -0
  391. package/src/workspace/migrations/047-remove-watch-callsites.ts +54 -0
  392. package/src/workspace/migrations/048-remove-workspace-hooks.ts +81 -0
  393. package/src/workspace/migrations/049-release-notes-default-sonnet.ts +80 -0
  394. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +86 -0
  395. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +128 -0
  396. package/src/workspace/migrations/registry.ts +12 -0
  397. package/tsconfig.json +1 -1
  398. package/hook-templates/debug-prompt-logger/hook.json +0 -7
  399. package/hook-templates/debug-prompt-logger/run.sh +0 -66
  400. package/src/__tests__/compaction-circuit-breaker.test.ts +0 -336
  401. package/src/__tests__/context-overflow-approval.test.ts +0 -156
  402. package/src/__tests__/hooks-blocking.test.ts +0 -178
  403. package/src/__tests__/hooks-cli.test.ts +0 -182
  404. package/src/__tests__/hooks-config.test.ts +0 -108
  405. package/src/__tests__/hooks-discovery.test.ts +0 -211
  406. package/src/__tests__/hooks-integration.test.ts +0 -196
  407. package/src/__tests__/hooks-manager.test.ts +0 -226
  408. package/src/__tests__/hooks-runner.test.ts +0 -175
  409. package/src/__tests__/hooks-settings.test.ts +0 -160
  410. package/src/__tests__/hooks-templates.test.ts +0 -169
  411. package/src/__tests__/hooks-ts-runner.test.ts +0 -170
  412. package/src/__tests__/hooks-watch.test.ts +0 -112
  413. package/src/__tests__/notification-schedule-dedup.test.ts +0 -213
  414. package/src/__tests__/oauth-scope-policy.test.ts +0 -180
  415. package/src/__tests__/send-notification-tool.test.ts +0 -83
  416. package/src/cli/commands/shotgun.ts +0 -266
  417. package/src/config/bundled-skills/conversations/SKILL.md +0 -20
  418. package/src/config/bundled-skills/conversations/TOOLS.json +0 -23
  419. package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +0 -88
  420. package/src/config/bundled-skills/heartbeat/SKILL.md +0 -43
  421. package/src/config/bundled-skills/notifications/SKILL.md +0 -40
  422. package/src/config/bundled-skills/notifications/TOOLS.json +0 -80
  423. package/src/config/bundled-skills/notifications/tools/send-notification.ts +0 -152
  424. package/src/config/bundled-skills/notifications/tools/shared.ts +0 -13
  425. package/src/config/bundled-skills/screen-watch/SKILL.md +0 -27
  426. package/src/config/bundled-skills/screen-watch/TOOLS.json +0 -35
  427. package/src/config/bundled-skills/screen-watch/tools/start-screen-watch.ts +0 -12
  428. package/src/config/bundled-skills/skills-catalog/SKILL.md +0 -84
  429. package/src/daemon/context-overflow-approval.ts +0 -52
  430. package/src/daemon/watch-handler.ts +0 -399
  431. package/src/hooks/cli.ts +0 -253
  432. package/src/hooks/config.ts +0 -100
  433. package/src/hooks/discovery.ts +0 -135
  434. package/src/hooks/manager.ts +0 -179
  435. package/src/hooks/runner.ts +0 -117
  436. package/src/hooks/templates.ts +0 -77
  437. package/src/hooks/types.ts +0 -75
  438. package/src/oauth/scope-policy.ts +0 -89
  439. package/src/runtime/gateway-internal-client.ts +0 -94
  440. package/src/runtime/routes/watch-routes.ts +0 -156
  441. package/src/signals/shotgun.ts +0 -203
  442. package/src/tools/watch/screen-watch.ts +0 -144
  443. package/src/tools/watch/watch-state.ts +0 -142
@@ -1,266 +0,0 @@
1
- import { randomUUID } from "node:crypto";
2
- import {
3
- existsSync,
4
- mkdirSync,
5
- readFileSync,
6
- unlinkSync,
7
- writeFileSync,
8
- } from "node:fs";
9
- import { join } from "node:path";
10
-
11
- import type { Command } from "commander";
12
-
13
- import { getSignalsDir } from "../../util/platform.js";
14
- import { log } from "../logger.js";
15
-
16
- const POLL_INTERVAL_MS = 100;
17
- const DEFAULT_TIMEOUT_MS = 30_000;
18
-
19
- interface ShotgunResult {
20
- requestId: string;
21
- ok: boolean;
22
- error?: string;
23
- watchId?: string;
24
- conversationId?: string;
25
- status?: string;
26
- }
27
-
28
- function writeShotgunSignal(
29
- requestId: string,
30
- payload: Record<string, unknown>,
31
- ): { signalPath: string; resultPath: string } | null {
32
- const signalsDir = getSignalsDir();
33
- try {
34
- mkdirSync(signalsDir, { recursive: true });
35
- } catch {
36
- log.error("Failed to create signals directory.");
37
- return null;
38
- }
39
-
40
- const signalPath = join(signalsDir, `shotgun.${requestId}`);
41
- const resultPath = join(signalsDir, `shotgun.${requestId}.result`);
42
-
43
- try {
44
- writeFileSync(signalPath, JSON.stringify({ requestId, ...payload }));
45
- } catch {
46
- log.error("Failed to write shotgun signal file.");
47
- return null;
48
- }
49
-
50
- return { signalPath, resultPath };
51
- }
52
-
53
- function pollForResult(
54
- requestId: string,
55
- resultPath: string,
56
- signalPath: string,
57
- timeoutMs: number,
58
- callback: (result: ShotgunResult) => void,
59
- ): void {
60
- const deadline = Date.now() + timeoutMs + 5_000;
61
-
62
- const poll = setInterval(() => {
63
- if (Date.now() > deadline) {
64
- clearInterval(poll);
65
- cleanup(signalPath, resultPath);
66
- log.error("Timed out waiting for response. Is the assistant running?");
67
- process.exitCode = 1;
68
- return;
69
- }
70
-
71
- if (!existsSync(resultPath)) return;
72
-
73
- let result: ShotgunResult;
74
- try {
75
- const content = readFileSync(resultPath, "utf-8");
76
- result = JSON.parse(content) as ShotgunResult;
77
- } catch {
78
- return;
79
- }
80
-
81
- if (result.requestId !== requestId) return;
82
-
83
- clearInterval(poll);
84
- cleanup(signalPath, resultPath);
85
- callback(result);
86
- }, POLL_INTERVAL_MS);
87
- }
88
-
89
- function cleanup(...paths: string[]): void {
90
- for (const p of paths) {
91
- try {
92
- unlinkSync(p);
93
- } catch {
94
- // Best-effort cleanup.
95
- }
96
- }
97
- }
98
-
99
- export function registerShotgunCommand(program: Command): void {
100
- const shotgun = program
101
- .command("shotgun")
102
- .description("Start and monitor screen-watch (shotgun) sessions via IPC");
103
-
104
- shotgun.addHelpText(
105
- "after",
106
- `
107
- Screen-watch sessions capture periodic screenshots and feed them to the
108
- assistant for observation. The CLI communicates with the running assistant
109
- via IPC signal files — the assistant must be running for these commands
110
- to work.
111
-
112
- Examples:
113
- $ assistant shotgun start --duration 600 --focus "browsing workflow"
114
- $ assistant shotgun status <watchId>`,
115
- );
116
-
117
- shotgun
118
- .command("start")
119
- .description("Start a new screen-watch session")
120
- .option(
121
- "-d, --duration <seconds>",
122
- "Duration in seconds for the watch session",
123
- "300",
124
- )
125
- .option("-i, --interval <seconds>", "Seconds between screen captures", "5")
126
- .option(
127
- "-f, --focus <area>",
128
- "What to focus on observing",
129
- "general observation",
130
- )
131
- .option(
132
- "-t, --timeout <ms>",
133
- "Timeout in milliseconds waiting for the assistant to respond",
134
- String(DEFAULT_TIMEOUT_MS),
135
- )
136
- .addHelpText(
137
- "after",
138
- `
139
- Starts a screen-watch session via IPC signal files. The assistant
140
- creates a watch session and begins accepting screen observations from the
141
- desktop client.
142
-
143
- The CLI writes the request to signals/shotgun.<requestId> and polls
144
- signals/shotgun.<requestId>.result for the response. The assistant must
145
- be running for this to work.
146
-
147
- Output (JSON): { ok, watchId, conversationId }
148
-
149
- Examples:
150
- $ assistant shotgun start
151
- $ assistant shotgun start --duration 600 --interval 10 --focus "doordash.com"
152
- $ assistant shotgun start -d 300 -i 5 -f "browsing workflow"`,
153
- )
154
- .action(
155
- (opts: {
156
- duration: string;
157
- interval: string;
158
- focus: string;
159
- timeout: string;
160
- }) => {
161
- const durationSeconds = parseInt(opts.duration, 10);
162
- if (!Number.isFinite(durationSeconds) || durationSeconds < 1) {
163
- log.error("Invalid duration. Must be a positive integer.");
164
- process.exitCode = 1;
165
- return;
166
- }
167
-
168
- const intervalSeconds = parseInt(opts.interval, 10);
169
- if (!Number.isFinite(intervalSeconds) || intervalSeconds < 1) {
170
- log.error("Invalid interval. Must be a positive integer.");
171
- process.exitCode = 1;
172
- return;
173
- }
174
-
175
- const timeoutMs = parseInt(opts.timeout, 10);
176
- if (!Number.isFinite(timeoutMs) || timeoutMs < 1) {
177
- log.error("Invalid timeout. Must be a positive integer.");
178
- process.exitCode = 1;
179
- return;
180
- }
181
-
182
- const requestId = randomUUID();
183
- const paths = writeShotgunSignal(requestId, {
184
- action: "start",
185
- durationSeconds,
186
- intervalSeconds,
187
- focusArea: opts.focus,
188
- });
189
- if (!paths) {
190
- process.exitCode = 1;
191
- return;
192
- }
193
-
194
- pollForResult(
195
- requestId,
196
- paths.resultPath,
197
- paths.signalPath,
198
- timeoutMs,
199
- (result) => {
200
- if (!result.ok) {
201
- process.stdout.write(JSON.stringify(result) + "\n");
202
- process.exitCode = 1;
203
- return;
204
- }
205
- process.stdout.write(JSON.stringify(result) + "\n");
206
- },
207
- );
208
- },
209
- );
210
-
211
- shotgun
212
- .command("status <watchId>")
213
- .description("Check the status of an active screen-watch session")
214
- .option(
215
- "-t, --timeout <ms>",
216
- "Timeout in milliseconds waiting for the assistant to respond",
217
- String(DEFAULT_TIMEOUT_MS),
218
- )
219
- .addHelpText(
220
- "after",
221
- `
222
- Arguments:
223
- watchId The watch session ID returned by 'assistant shotgun start'.
224
-
225
- Queries the status of an existing screen-watch session by watchId.
226
-
227
- Output (JSON): { ok, watchId, conversationId, status }
228
-
229
- The status field is one of: "active", "completing", "completed", "cancelled".
230
-
231
- Examples:
232
- $ assistant shotgun status abc12345
233
- $ assistant shotgun status abc12345 --timeout 5000`,
234
- )
235
- .action((watchId: string, opts: { timeout: string }) => {
236
- const timeoutMs = parseInt(opts.timeout, 10);
237
- if (!Number.isFinite(timeoutMs) || timeoutMs < 1) {
238
- log.error("Invalid timeout. Must be a positive integer.");
239
- process.exitCode = 1;
240
- return;
241
- }
242
-
243
- const requestId = randomUUID();
244
- const paths = writeShotgunSignal(requestId, {
245
- action: "status",
246
- watchId,
247
- });
248
- if (!paths) {
249
- process.exitCode = 1;
250
- return;
251
- }
252
-
253
- pollForResult(
254
- requestId,
255
- paths.resultPath,
256
- paths.signalPath,
257
- timeoutMs,
258
- (result) => {
259
- process.stdout.write(JSON.stringify(result) + "\n");
260
- if (!result.ok) {
261
- process.exitCode = 1;
262
- }
263
- },
264
- );
265
- });
266
- }
@@ -1,20 +0,0 @@
1
- ---
2
- name: conversations
3
- description: Manage conversation threads (rename)
4
- compatibility: "Designed for Vellum personal assistants"
5
- metadata:
6
- emoji: "\U0001F4AC"
7
- vellum:
8
- display-name: "Conversations"
9
- ---
10
-
11
- Tools for managing conversation threads.
12
-
13
- ## Renaming
14
-
15
- Use the `rename_conversation` tool to rename the current conversation thread when:
16
- - The topic has shifted significantly from the original title
17
- - The auto-generated title is generic or unhelpful
18
- - The user explicitly asks to rename the thread
19
-
20
- Keep titles concise (under 60 characters) and descriptive of the current topic.
@@ -1,23 +0,0 @@
1
- {
2
- "version": 1,
3
- "tools": [
4
- {
5
- "name": "rename_conversation",
6
- "description": "Rename the current conversation thread. Use this when the conversation topic has shifted significantly from the original title, or when you notice the title is generic/unhelpful and you can provide a better one based on what has been discussed.",
7
- "category": "conversation",
8
- "risk": "low",
9
- "input_schema": {
10
- "type": "object",
11
- "properties": {
12
- "title": {
13
- "type": "string",
14
- "description": "The new title for the conversation. Should be concise (under 60 characters) and descriptive of the current topic."
15
- }
16
- },
17
- "required": ["title"]
18
- },
19
- "executor": "tools/rename-conversation.ts",
20
- "execution_target": "host"
21
- }
22
- ]
23
- }
@@ -1,88 +0,0 @@
1
- import {
2
- getConversation,
3
- updateConversationTitle,
4
- } from "../../../../memory/conversation-crud.js";
5
- import { buildAssistantEvent } from "../../../../runtime/assistant-event.js";
6
- import { assistantEventHub } from "../../../../runtime/assistant-event-hub.js";
7
- import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../../../runtime/assistant-scope.js";
8
- import type {
9
- ToolContext,
10
- ToolExecutionResult,
11
- } from "../../../../tools/types.js";
12
- import { getLogger } from "../../../../util/logger.js";
13
-
14
- const log = getLogger("rename-conversation");
15
-
16
- export async function run(
17
- input: Record<string, unknown>,
18
- context: ToolContext,
19
- ): Promise<ToolExecutionResult> {
20
- const title = input.title;
21
- if (typeof title !== "string" || title.trim() === "") {
22
- return {
23
- content: "Error: title must be a non-empty string.",
24
- isError: true,
25
- };
26
- }
27
-
28
- const trimmedTitle = title.trim();
29
- const conversationId = context.conversationId;
30
-
31
- const conversation = getConversation(conversationId);
32
- if (!conversation) {
33
- return {
34
- content: `Error: conversation ${conversationId} not found.`,
35
- isError: true,
36
- };
37
- }
38
-
39
- // Persist with isAutoTitle = 0 so auto-generation won't overwrite it
40
- updateConversationTitle(conversationId, trimmedTitle, 0);
41
-
42
- // Notify the client currently viewing this conversation so the header
43
- // updates in-place. Scoped to this conversation so foreign
44
- // `conversationId` values don't leak to other subscribers' speculative
45
- // ID-resolution paths. Other clients learn about the rename via the
46
- // unscoped `conversation_list_invalidated` published below, which
47
- // triggers their sidebars to refetch and pick up the new title.
48
- const assistantId = context.assistantId ?? DAEMON_INTERNAL_ASSISTANT_ID;
49
- assistantEventHub
50
- .publish(
51
- buildAssistantEvent(
52
- assistantId,
53
- {
54
- type: "conversation_title_updated",
55
- conversationId,
56
- title: trimmedTitle,
57
- },
58
- conversationId,
59
- ),
60
- )
61
- .catch((err) => {
62
- log.warn({ err }, "Failed to publish conversation_title_updated event");
63
- });
64
-
65
- // Broadcast `conversation_list_invalidated` unscoped so every connected
66
- // client's sidebar refetches and picks up the renamed title. Mirrors
67
- // the HTTP rename route in `conversation-management-routes.ts`.
68
- assistantEventHub
69
- .publish(
70
- buildAssistantEvent(assistantId, {
71
- type: "conversation_list_invalidated",
72
- reason: "renamed",
73
- }),
74
- )
75
- .catch((err) => {
76
- log.warn(
77
- { err },
78
- "Failed to publish conversation_list_invalidated for rename",
79
- );
80
- });
81
-
82
- log.info({ conversationId, title: trimmedTitle }, "Conversation renamed");
83
-
84
- return {
85
- content: `Conversation renamed to "${trimmedTitle}".`,
86
- isError: false,
87
- };
88
- }
@@ -1,43 +0,0 @@
1
- ---
2
- name: heartbeat
3
- description: Configure periodic background checklist runs
4
- compatibility: "Designed for Vellum personal assistants"
5
- metadata:
6
- emoji: "\U0001F493"
7
- vellum:
8
- display-name: "Heartbeat"
9
- activation-hints:
10
- - "Set up a heartbeat, periodic checklist, background health check, or recurring background task"
11
- avoid-when:
12
- - "One-off or recurring schedules with specific payloads - use the schedule skill instead"
13
- ---
14
-
15
- The heartbeat feature runs your `HEARTBEAT.md` checklist periodically in a background conversation. Each run, the assistant works through the checklist and flags anything that needs attention.
16
-
17
- ## Setup
18
-
19
- Edit `config.json` using `file_edit`:
20
-
21
- 1. **Enable heartbeat**: Set `heartbeat.enabled` to `true`.
22
- 2. **Set interval**: Set `heartbeat.intervalMs` (milliseconds between runs, default: 3600000 = 1 hour).
23
- 3. **Optional active hours**: Set `heartbeat.activeHoursStart` and `heartbeat.activeHoursEnd` (0-23) to restrict runs to certain hours. Both must be set together.
24
-
25
- Example config.json heartbeat section:
26
- ```json
27
- {
28
- "heartbeat": {
29
- "enabled": true,
30
- "intervalMs": 1800000,
31
- "activeHoursStart": 8,
32
- "activeHoursEnd": 22
33
- }
34
- }
35
- ```
36
-
37
- Then edit `HEARTBEAT.md` with the checklist items. The assistant will work through this file each heartbeat run.
38
-
39
- ## Notes
40
-
41
- - Toggling `heartbeat.enabled` requires an assistant restart to take effect.
42
- - Changes to `HEARTBEAT.md` take effect on the next heartbeat run (no restart needed).
43
- - The heartbeat runs in a separate background conversation, not the user's active chat.
@@ -1,40 +0,0 @@
1
- ---
2
- name: notifications
3
- description: Send notifications through the unified notification router
4
- compatibility: "Designed for Vellum personal assistants"
5
- metadata:
6
- emoji: "🔔"
7
- vellum:
8
- display-name: "Notifications"
9
- ---
10
-
11
- Use `send_notification` for user-facing alerts and notifications. This tool routes through the unified notification pipeline, which handles channel selection, delivery, deduplication, and audit logging.
12
-
13
- ## Routing Behavior
14
-
15
- - `preferred_channels` are **routing hints**, not hard channel forcing. The notification router makes the final delivery decision based on user preferences, channel availability, and urgency.
16
- - Channel selection and delivery are handled entirely by the notification router -- do not attempt to control delivery manually.
17
-
18
- ## Deduplication (`dedupe_key`)
19
-
20
- - `dedupe_key` suppresses duplicate signals **permanently**. A second notification with the same key is **dropped entirely** for the lifetime of the assistant's event store. Once a key has been used, it cannot be reused - any future notification with the same key will be silently discarded.
21
- - Never reuse a `dedupe_key` across logically distinct notifications, even if they are related. The key means "this exact event already fired," not "these events are in the same category."
22
- - If you omit `dedupe_key`, the LLM decision engine may generate one automatically based on signal context. This means even keyless signals can be deduplicated if the engine considers them duplicates of a recent event.
23
-
24
- ## Conversation Grouping
25
-
26
- Conversation grouping is handled by the LLM-powered decision engine, not by any parameter you pass. There is no explicit "post to conversation X" parameter - conversation reuse is inferred, not commanded.
27
-
28
- **How it works:** The engine evaluates recent notification conversation candidates and decides whether a new signal is a continuation of an existing conversation based on `source_event_name`, provenance metadata, and message content. Use natural, descriptive titles and bodies - the engine groups by semantic relatedness, not string matching.
29
-
30
- **`source_event_name` is the primary grouping signal.** Use a stable event name for notifications that belong to the same logical stream (e.g. `dog.news.thread.reply` for all replies in a thread). Use a distinct event name when the notification represents a genuinely different kind of event.
31
-
32
- **Practical constraints:**
33
-
34
- - Conversation candidates are scoped to the **last 24 hours** (max 5 per channel). You cannot reuse an old conversation from days ago.
35
- - The engine will only reuse conversations originally created by the notification system (`source === 'notification'`). It will never append to a user-initiated conversation, even if it looks related.
36
-
37
- ## Important
38
-
39
- - Do **NOT** use AppleScript `display notification` or other OS-level notification commands for assistant-managed alerts. Always use `send_notification`.
40
- - For sending rich content (digests, summaries, reports) to a specific chat or email destination, use the appropriate platform's API directly. For Gmail, use `messaging_send`. For Slack, use the Slack Web API directly (see the **slack** skill). The decision engine rewrites `send_notification` content into short alerts, which strips rich formatting.
@@ -1,80 +0,0 @@
1
- {
2
- "version": 1,
3
- "tools": [
4
- {
5
- "name": "send_notification",
6
- "description": "Send an immediate notification. Fires instantly with no delay capability. For one-time future alerts, use schedule_create with fire_at. For recurring alerts, use schedule_create with expression (cron/RRULE). The router decides channels/copy from preferences and urgency hints. Include a confidence score (0-1).",
7
- "category": "notifications",
8
- "risk": "medium",
9
- "input_schema": {
10
- "type": "object",
11
- "properties": {
12
- "message": {
13
- "type": "string",
14
- "description": "Notification message the user should receive"
15
- },
16
- "title": {
17
- "type": "string",
18
- "description": "Optional notification title"
19
- },
20
- "urgency": {
21
- "type": "string",
22
- "enum": ["low", "medium", "high"],
23
- "description": "Urgency hint (default: \"medium\")"
24
- },
25
- "requires_action": {
26
- "type": "boolean",
27
- "description": "Whether the notification expects user action (default: true)"
28
- },
29
- "is_async_background": {
30
- "type": "boolean",
31
- "description": "Whether the event is asynchronous/background work (default: false)"
32
- },
33
- "visible_in_source_now": {
34
- "type": "boolean",
35
- "description": "Set true when user is already viewing the source context (default: false)"
36
- },
37
- "deadline_at": {
38
- "type": "number",
39
- "description": "Optional deadline timestamp in epoch milliseconds"
40
- },
41
- "preferred_channels": {
42
- "type": "array",
43
- "items": {
44
- "type": "string",
45
- "enum": ["vellum", "telegram", "slack"]
46
- },
47
- "description": "Optional routing hints for preferred channels (not deterministic)"
48
- },
49
- "conversation_id": {
50
- "type": "string",
51
- "description": "Optional source conversation ID for notification context"
52
- },
53
- "source_event_name": {
54
- "type": "string",
55
- "description": "Optional event name for audit and dedupe grouping (default: \"user.send_notification\")"
56
- },
57
- "deep_link_metadata": {
58
- "type": "object",
59
- "description": "Optional metadata clients can use for deep linking"
60
- },
61
- "dedupe_key": {
62
- "type": "string",
63
- "description": "Optional dedupe key to suppress duplicate notifications"
64
- },
65
- "confidence": {
66
- "type": "number",
67
- "description": "Confidence score (0-1) for this action"
68
- },
69
- "activity": {
70
- "type": "string",
71
- "description": "Brief non-technical explanation of why this tool is being called"
72
- }
73
- },
74
- "required": ["message", "confidence"]
75
- },
76
- "executor": "tools/send-notification.ts",
77
- "execution_target": "host"
78
- }
79
- ]
80
- }