@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,27 +1,11 @@
1
- import {
2
- gatewayGet,
3
- gatewayPost,
4
- GatewayRequestError,
5
- } from "../../../../runtime/gateway-internal-client.js";
1
+ import type { ContactWithChannels } from "../../../../contacts/types.js";
2
+ import { cliIpcCall } from "../../../../ipc/cli-client.js";
3
+ import { resolveGuardianName } from "../../../../prompts/user-reference.js";
6
4
  import type {
7
5
  ToolContext,
8
6
  ToolExecutionResult,
9
7
  } from "../../../../tools/types.js";
10
8
 
11
- interface ContactChannel {
12
- type: string;
13
- address: string;
14
- isPrimary: boolean;
15
- }
16
-
17
- interface ContactResponse {
18
- id: string;
19
- displayName: string;
20
- notes: string | null;
21
- interactionCount: number;
22
- channels: ContactChannel[];
23
- }
24
-
25
9
  export async function executeContactMerge(
26
10
  input: Record<string, unknown>,
27
11
  _context: ToolContext,
@@ -36,79 +20,74 @@ export async function executeContactMerge(
36
20
  return { content: "Error: merge_id is required", isError: true };
37
21
  }
38
22
 
39
- try {
40
- // Validate both contacts exist before merging
41
- const [keepResult, mergeResult] = await Promise.allSettled([
42
- gatewayGet<{ ok: boolean; contact: ContactResponse }>(
43
- `/v1/contacts/${keepId}`,
44
- ),
45
- gatewayGet<{ ok: boolean; contact: ContactResponse }>(
46
- `/v1/contacts/${mergeId}`,
47
- ),
48
- ]);
49
-
50
- if (keepResult.status === "rejected") {
51
- if (
52
- keepResult.reason instanceof GatewayRequestError &&
53
- keepResult.reason.statusCode === 404
54
- ) {
55
- return {
56
- content: `Error: Contact "${keepId}" not found`,
57
- isError: true,
58
- };
59
- }
60
- throw keepResult.reason;
61
- }
62
- if (mergeResult.status === "rejected") {
63
- if (
64
- mergeResult.reason instanceof GatewayRequestError &&
65
- mergeResult.reason.statusCode === 404
66
- ) {
67
- return {
68
- content: `Error: Contact "${mergeId}" not found`,
69
- isError: true,
70
- };
71
- }
72
- throw mergeResult.reason;
73
- }
23
+ // Validate both contacts exist before merging
24
+ const [keepRes, mergeRes] = await Promise.all([
25
+ cliIpcCall<ContactWithChannels | null>("get_contact", { id: keepId }),
26
+ cliIpcCall<ContactWithChannels | null>("get_contact", { id: mergeId }),
27
+ ]);
74
28
 
75
- const keepContact = keepResult.value.contact;
76
- const mergeContact = mergeResult.value.contact;
29
+ if (!keepRes.ok) {
30
+ return { content: `Error: ${keepRes.error}`, isError: true };
31
+ }
32
+ if (!keepRes.result) {
33
+ return { content: `Error: Contact "${keepId}" not found`, isError: true };
34
+ }
35
+ if (!mergeRes.ok) {
36
+ return { content: `Error: ${mergeRes.error}`, isError: true };
37
+ }
38
+ if (!mergeRes.result) {
39
+ return { content: `Error: Contact "${mergeId}" not found`, isError: true };
40
+ }
77
41
 
78
- // Execute the merge
79
- const { data: resultData } = await gatewayPost<{
80
- ok: boolean;
81
- contact: ContactResponse;
82
- }>("/v1/contacts/merge", { keepId, mergeId });
83
- const merged = resultData.contact;
42
+ const keepContact = keepRes.result;
43
+ const mergeContact = mergeRes.result;
84
44
 
85
- const channelList = merged.channels
86
- .map(
87
- (ch) =>
88
- ` - ${ch.type}: ${ch.address}${ch.isPrimary ? " (primary)" : ""}`,
89
- )
90
- .join("\n");
45
+ const mergeResult = await cliIpcCall<ContactWithChannels>("merge_contacts", {
46
+ keepId,
47
+ mergeId,
48
+ });
91
49
 
92
- return {
93
- content: [
94
- `Merged "${mergeContact.displayName}" into "${keepContact.displayName}".`,
95
- ``,
96
- `Surviving contact (${merged.id}):`,
97
- ` Name: ${merged.displayName}`,
98
- ` Interactions: ${merged.interactionCount}`,
99
- merged.notes ? ` Notes: ${merged.notes}` : null,
100
- merged.channels.length > 0 ? ` Channels:\n${channelList}` : null,
101
- ``,
102
- `Deleted contact: ${mergeContact.displayName} (${mergeId})`,
103
- ]
104
- .filter(Boolean)
105
- .join("\n"),
106
- isError: false,
107
- };
108
- } catch (err) {
109
- const msg = err instanceof Error ? err.message : String(err);
110
- return { content: `Error: ${msg}`, isError: true };
50
+ if (!mergeResult.ok) {
51
+ return { content: `Error: ${mergeResult.error}`, isError: true };
111
52
  }
53
+
54
+ const merged = mergeResult.result!;
55
+ const displayName =
56
+ merged.role === "guardian"
57
+ ? resolveGuardianName(merged.displayName)
58
+ : merged.displayName;
59
+ const keepName =
60
+ keepContact.role === "guardian"
61
+ ? resolveGuardianName(keepContact.displayName)
62
+ : keepContact.displayName;
63
+ const mergeName =
64
+ mergeContact.role === "guardian"
65
+ ? resolveGuardianName(mergeContact.displayName)
66
+ : mergeContact.displayName;
67
+
68
+ const channelList = merged.channels
69
+ .map(
70
+ (ch) =>
71
+ ` - ${ch.type}: ${ch.address}${ch.isPrimary ? " (primary)" : ""}`,
72
+ )
73
+ .join("\n");
74
+
75
+ return {
76
+ content: [
77
+ `Merged "${mergeName}" into "${keepName}".`,
78
+ ``,
79
+ `Surviving contact (${merged.id}):`,
80
+ ` Name: ${displayName}`,
81
+ ` Interactions: ${merged.interactionCount}`,
82
+ merged.notes ? ` Notes: ${merged.notes}` : null,
83
+ merged.channels.length > 0 ? ` Channels:\n${channelList}` : null,
84
+ ``,
85
+ `Deleted contact: ${mergeName} (${mergeId})`,
86
+ ]
87
+ .filter(Boolean)
88
+ .join("\n"),
89
+ isError: false,
90
+ };
112
91
  }
113
92
 
114
93
  export { executeContactMerge as run };
@@ -1,30 +1,15 @@
1
- import {
2
- gatewayGet,
3
- GatewayRequestError,
4
- } from "../../../../runtime/gateway-internal-client.js";
1
+ import type { ContactWithChannels } from "../../../../contacts/types.js";
2
+ import { cliIpcCall } from "../../../../ipc/cli-client.js";
3
+ import { resolveGuardianName } from "../../../../prompts/user-reference.js";
5
4
  import type {
6
5
  ToolContext,
7
6
  ToolExecutionResult,
8
7
  } from "../../../../tools/types.js";
9
8
 
10
- interface ContactChannel {
11
- type: string;
12
- address: string;
13
- isPrimary: boolean;
14
- externalUserId?: string | null;
15
- externalChatId?: string | null;
16
- }
17
-
18
- interface ContactResponse {
19
- id: string;
20
- displayName: string;
21
- notes: string | null;
22
- interactionCount: number;
23
- channels: ContactChannel[];
24
- }
25
-
26
- function formatContactSummary(c: ContactResponse): string {
27
- const parts = [`- **${c.displayName}** (ID: ${c.id})`];
9
+ function formatContactSummary(c: ContactWithChannels): string {
10
+ const displayName =
11
+ c.role === "guardian" ? resolveGuardianName(c.displayName) : c.displayName;
12
+ const parts = [`- **${displayName}** (ID: ${c.id})`];
28
13
  if (c.notes) parts.push(` Notes: ${c.notes}`);
29
14
  if (c.interactionCount > 0)
30
15
  parts.push(` Interactions: ${c.interactionCount}`);
@@ -61,40 +46,32 @@ export async function executeContactSearch(
61
46
  };
62
47
  }
63
48
 
64
- try {
65
- const params = new URLSearchParams();
66
- if (query) params.set("query", query);
67
- if (channelAddress) params.set("channelAddress", channelAddress);
68
- if (channelType) params.set("channelType", channelType);
69
- if (limit !== undefined) params.set("limit", String(limit));
49
+ const res = await cliIpcCall<ContactWithChannels[]>("search_contacts", {
50
+ query,
51
+ channelAddress,
52
+ channelType,
53
+ limit,
54
+ });
70
55
 
71
- const qs = params.toString();
72
- const data = await gatewayGet<{ ok: boolean; contacts: ContactResponse[] }>(
73
- `/v1/contacts${qs ? `?${qs}` : ""}`,
74
- );
75
- const results = data.contacts;
56
+ if (!res.ok) {
57
+ return { content: `Error: ${res.error}`, isError: true };
58
+ }
76
59
 
77
- if (results.length === 0) {
78
- return {
79
- content: "No contacts found matching the search criteria.",
80
- isError: false,
81
- };
82
- }
60
+ const results = res.result ?? [];
83
61
 
84
- const lines = [`Found ${results.length} contact(s):\n`];
85
- for (const contact of results) {
86
- lines.push(formatContactSummary(contact));
87
- }
62
+ if (results.length === 0) {
63
+ return {
64
+ content: "No contacts found matching the search criteria.",
65
+ isError: false,
66
+ };
67
+ }
88
68
 
89
- return { content: lines.join("\n"), isError: false };
90
- } catch (err) {
91
- if (err instanceof GatewayRequestError) {
92
- const message = err.gatewayError ?? err.message;
93
- return { content: `Error: ${message}`, isError: true };
94
- }
95
- const msg = err instanceof Error ? err.message : String(err);
96
- return { content: `Error: ${msg}`, isError: true };
69
+ const lines = [`Found ${results.length} contact(s):\n`];
70
+ for (const contact of results) {
71
+ lines.push(formatContactSummary(contact));
97
72
  }
73
+
74
+ return { content: lines.join("\n"), isError: false };
98
75
  }
99
76
 
100
77
  export { executeContactSearch as run };
@@ -1,30 +1,15 @@
1
- import {
2
- gatewayPost,
3
- GatewayRequestError,
4
- } from "../../../../runtime/gateway-internal-client.js";
1
+ import type { ContactWithChannels } from "../../../../contacts/types.js";
2
+ import { cliIpcCall } from "../../../../ipc/cli-client.js";
3
+ import { resolveGuardianName } from "../../../../prompts/user-reference.js";
5
4
  import type {
6
5
  ToolContext,
7
6
  ToolExecutionResult,
8
7
  } from "../../../../tools/types.js";
9
8
 
10
- interface ContactChannel {
11
- type: string;
12
- address: string;
13
- isPrimary: boolean;
14
- externalUserId?: string | null;
15
- externalChatId?: string | null;
16
- }
17
-
18
- interface ContactResponse {
19
- id: string;
20
- displayName: string;
21
- notes: string | null;
22
- interactionCount: number;
23
- channels: ContactChannel[];
24
- }
25
-
26
- function formatContact(c: ContactResponse): string {
27
- const lines = [`Contact ${c.id}`, ` Name: ${c.displayName}`];
9
+ function formatContact(c: ContactWithChannels): string {
10
+ const displayName =
11
+ c.role === "guardian" ? resolveGuardianName(c.displayName) : c.displayName;
12
+ const lines = [`Contact ${c.id}`, ` Name: ${displayName}`];
28
13
  if (c.notes) lines.push(` Notes: ${c.notes}`);
29
14
  if (c.interactionCount > 0)
30
15
  lines.push(` Interactions: ${c.interactionCount}`);
@@ -71,30 +56,27 @@ export async function executeContactUpsert(
71
56
  isPrimary: ch.is_primary,
72
57
  }));
73
58
 
74
- try {
75
- const { status, data } = await gatewayPost<{
76
- ok: boolean;
77
- contact: ContactResponse;
78
- }>("/v1/contacts", {
59
+ const res = await cliIpcCall<ContactWithChannels & { created: boolean }>(
60
+ "upsert_contact",
61
+ {
79
62
  id: input.id as string | undefined,
80
63
  displayName: displayName.trim(),
81
64
  notes: input.notes as string | undefined,
82
65
  channels,
83
- });
84
-
85
- const created = status === 201;
66
+ },
67
+ );
86
68
 
87
- return {
88
- content: `${created ? "Created" : "Updated"} contact:\n${formatContact(data.contact)}`,
89
- isError: false,
90
- };
91
- } catch (err) {
92
- if (err instanceof GatewayRequestError) {
93
- return { content: `Error: ${err.message}`, isError: true };
94
- }
95
- const msg = err instanceof Error ? err.message : String(err);
96
- return { content: `Error: ${msg}`, isError: true };
69
+ if (!res.ok) {
70
+ return { content: `Error: ${res.error}`, isError: true };
97
71
  }
72
+
73
+ const contact = res.result!;
74
+ const verb = contact.created ? "Created" : "Updated";
75
+
76
+ return {
77
+ content: `${verb} contact:\n${formatContact(contact)}`,
78
+ isError: false,
79
+ };
98
80
  }
99
81
 
100
82
  export { executeContactUpsert as run };
@@ -25,10 +25,11 @@ You are an image generation assistant. When the user asks you to create or edit
25
25
 
26
26
  - `gemini-3.1-flash-image-preview` (default) - Nano Banana 2, fast, good quality
27
27
  - `gemini-3-pro-image-preview` - Nano Banana Pro, higher quality, slower
28
+ - `gpt-image-2` - OpenAI GPT Image 2, high fidelity, slower
28
29
 
29
30
  ## Tips
30
31
 
31
32
  - Be descriptive in your prompts for better results. Include details about style, composition, lighting, and mood.
32
33
  - When editing images, clearly describe what changes you want made to the source image.
33
34
  - Use the `variants` parameter (1-4) to generate multiple options and pick the best one.
34
- - If no Gemini API key is configured, the tool will return an error - ask the user to set one up.
35
+ - If no API key is configured for the selected model's provider (Gemini or OpenAI), the tool will return an error - ask the user to set one up.
@@ -29,7 +29,8 @@
29
29
  "type": "string",
30
30
  "enum": [
31
31
  "gemini-3.1-flash-image-preview",
32
- "gemini-3-pro-image-preview"
32
+ "gemini-3-pro-image-preview",
33
+ "gpt-image-2"
33
34
  ],
34
35
  "description": "Which model to use for generation. If omitted, uses the user's configured preference."
35
36
  },
@@ -1,16 +1,12 @@
1
1
  import { getConfig } from "../../../../config/loader.js";
2
+ import { resolveImageGenCredentials } from "../../../../media/image-credentials.js";
2
3
  import {
3
4
  generateImage,
4
- type ImageGenCredentials,
5
- mapGeminiError,
6
- } from "../../../../media/gemini-image-service.js";
5
+ mapImageGenError,
6
+ providerForModel,
7
+ } from "../../../../media/image-service.js";
7
8
  import { getFilePathBySourcePath } from "../../../../memory/attachments-store.js";
8
- import {
9
- buildManagedBaseUrl,
10
- resolveManagedProxyContext,
11
- } from "../../../../providers/managed-proxy/context.js";
12
9
  import type { ImageContent } from "../../../../providers/types.js";
13
- import { getProviderKeyAsync } from "../../../../security/secure-keys.js";
14
10
  import { sandboxPolicy } from "../../../../tools/shared/filesystem/path-policy.js";
15
11
  import type {
16
12
  ToolContext,
@@ -22,42 +18,30 @@ export async function run(
22
18
  context: ToolContext,
23
19
  ): Promise<ToolExecutionResult> {
24
20
  const config = getConfig();
25
- const imageGenMode = config.services["image-generation"].mode;
26
-
27
- // Resolve credentials strictly based on mode no cross-mode fallbacks
28
- let credentials: ImageGenCredentials | undefined;
29
-
30
- if (imageGenMode === "managed") {
31
- const managedBaseUrl = await buildManagedBaseUrl("gemini");
32
- if (managedBaseUrl) {
33
- const ctx = await resolveManagedProxyContext();
34
- credentials = {
35
- type: "managed-proxy",
36
- assistantApiKey: ctx.assistantApiKey,
37
- baseUrl: managedBaseUrl,
38
- };
39
- }
40
- } else {
41
- const apiKey = await getProviderKeyAsync("gemini");
42
- if (apiKey) {
43
- credentials = { type: "direct", apiKey };
44
- }
45
- }
46
-
21
+ const svc = config.services["image-generation"];
22
+ const modelOverride = input.model;
23
+ // Derive provider from the explicit model when supplied so that requesting
24
+ // e.g. `gpt-image-2` while config.provider === "gemini" routes to OpenAI
25
+ // instead of silently falling back to the Gemini default model.
26
+ const provider = providerForModel(modelOverride, svc.provider);
27
+ const { credentials, errorHint } = await resolveImageGenCredentials({
28
+ provider,
29
+ mode: svc.mode,
30
+ });
47
31
  if (!credentials) {
48
- const hint =
49
- imageGenMode === "managed"
50
- ? "Managed proxy is not available. Please log in to Vellum or switch to Your Own mode."
51
- : "No Gemini API key configured. Please set your Gemini API key in Settings > Models & Services.";
52
- return { content: hint, isError: true };
32
+ return {
33
+ content: errorHint ?? "Image generation is not configured.",
34
+ isError: true,
35
+ };
53
36
  }
54
37
 
55
38
  const prompt = input.prompt as string;
56
39
  const mode = (input.mode as "generate" | "edit") ?? "generate";
57
40
  const sourcePaths = input.source_paths as string[] | undefined;
58
41
  const model =
59
- (input.model as string | undefined) ??
60
- config.services["image-generation"].model;
42
+ typeof modelOverride === "string" && modelOverride
43
+ ? modelOverride
44
+ : config.services["image-generation"].model;
61
45
  const variants = input.variants as number | undefined;
62
46
 
63
47
  // Resolve source images from file paths (sandboxed to workingDir, edit mode only)
@@ -111,7 +95,7 @@ export async function run(
111
95
  }
112
96
 
113
97
  try {
114
- const result = await generateImage(credentials, {
98
+ const result = await generateImage(provider, credentials, {
115
99
  prompt,
116
100
  mode,
117
101
  sourceImages,
@@ -147,7 +131,7 @@ export async function run(
147
131
  };
148
132
  } catch (error) {
149
133
  return {
150
- content: mapGeminiError(error),
134
+ content: mapImageGenError(provider, error),
151
135
  isError: true,
152
136
  };
153
137
  }
@@ -145,10 +145,10 @@ Telegram is supported as a messaging provider with limited capabilities compared
145
145
 
146
146
  ## Notifications vs Messages
147
147
 
148
- - `send_notification` is provided by the **notifications** skill (always active) -- use it when the user asks for an alert/notification (for example "send this as a desktop notification").
148
+ - Notifications are sent via the **notifications** skill (always active) using `assistant notifications send` in `bash` -- use it when the user asks for an alert/notification (for example "send this as a desktop notification").
149
149
  - Use `messaging_send` when the user asks to send a message into a specific chat/email destination.
150
- - `send_notification` channel routing is LLM-driven; `preferred_channels` are hints, not hard channel forcing.
151
- - Before using `messaging_send` or `send_notification`, look up the recipient's contact record with `contact_search` to inform tone and content (see **Recipient Context** below).
150
+ - Notification channel routing is LLM-driven; `--preferred-channels` are hints, not hard channel forcing.
151
+ - Before using `messaging_send` or sending a notification, look up the recipient's contact record with `contact_search` to inform tone and content (see **Recipient Context** below).
152
152
 
153
153
  ## Personalized Drafting
154
154