@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
@@ -148,7 +148,7 @@ const sampleProviderRow = {
148
148
  userinfoUrl: null,
149
149
  baseUrl: null,
150
150
  defaultScopes: "[]",
151
- scopePolicy: "{}",
151
+ availableScopes: null,
152
152
  scopeSeparator: null,
153
153
  authorizeParams: null,
154
154
  managedServiceConfigKey: null,
@@ -148,7 +148,7 @@ const sampleProviderRow = {
148
148
  userinfoUrl: null,
149
149
  baseUrl: null,
150
150
  defaultScopes: "[]",
151
- scopePolicy: "{}",
151
+ availableScopes: null,
152
152
  scopeSeparator: null,
153
153
  authorizeParams: null,
154
154
  managedServiceConfigKey: null,
@@ -105,8 +105,8 @@ Arguments:
105
105
  provider Provider name (e.g. google, slack, notion).
106
106
  Run 'assistant oauth providers list' to see available providers.
107
107
 
108
- In managed mode, --scopes must be in the provider's allowed set (use full
109
- scope URLs). In BYO mode, --scopes are appended to the provider's defaults.
108
+ When --scopes is provided, the specified scopes replace the provider's
109
+ defaults entirely (use full scope URLs).
110
110
  By default, the browser opens automatically and the command waits for
111
111
  completion. Use --no-browser to print the URL instead (useful for headless
112
112
  or SSH sessions).
@@ -13,7 +13,10 @@ import {
13
13
  registerProvider,
14
14
  updateProvider,
15
15
  } from "../../../oauth/oauth-store.js";
16
- import { serializeProvider } from "../../../oauth/provider-serializer.js";
16
+ import {
17
+ type SerializedProvider,
18
+ serializeProvider,
19
+ } from "../../../oauth/provider-serializer.js";
17
20
  import { isProviderVisible } from "../../../oauth/provider-visibility.js";
18
21
  import { SEEDED_PROVIDER_KEYS } from "../../../oauth/seed-providers.js";
19
22
  import { getCliLogger } from "../../logger.js";
@@ -23,6 +26,137 @@ const log = getCliLogger("cli");
23
26
 
24
27
  const LOOPBACK_CALLBACK_PATH = "/oauth/callback";
25
28
 
29
+ // ---------------------------------------------------------------------------
30
+ // Text formatting helpers (non-JSON output)
31
+ // ---------------------------------------------------------------------------
32
+
33
+ /**
34
+ * Format available scopes for text output.
35
+ * Returns a single-line string for URLs, or a multi-line bullet list for
36
+ * structured scope arrays.
37
+ */
38
+ function formatAvailableScopes(
39
+ availableScopes: unknown,
40
+ indent: string = " ",
41
+ ): string | null {
42
+ if (!availableScopes) return null;
43
+ if (typeof availableScopes === "string") return availableScopes;
44
+ if (Array.isArray(availableScopes)) {
45
+ return (
46
+ "\n" +
47
+ (availableScopes as Array<{ scope: string; description?: string }>)
48
+ .map(
49
+ (s) =>
50
+ `${indent}- ${s.scope}${s.description ? ` — ${s.description}` : ""}`,
51
+ )
52
+ .join("\n")
53
+ );
54
+ }
55
+ return null;
56
+ }
57
+
58
+ /** Render a single provider as a concise summary line for `list`. */
59
+ function formatProviderSummary(p: SerializedProvider): string {
60
+ const name = p.displayName ?? p.providerKey;
61
+ const desc = p.description ? ` — ${p.description}` : "";
62
+ const managed = p.supportsManagedMode ? " [managed]" : "";
63
+ const scopes =
64
+ (p.defaultScopes as string[])?.length > 0
65
+ ? ` Scopes: ${(p.defaultScopes as string[]).join(", ")}`
66
+ : "";
67
+ return (
68
+ `${p.providerKey} (${name})${desc}${managed}` +
69
+ `${scopes ? "\n" + scopes : ""}` +
70
+ `\n Run \`assistant oauth providers get ${p.providerKey}\` for full details.`
71
+ );
72
+ }
73
+
74
+ /** Format a JSON value as indented text for `get` detail output. */
75
+ function formatJsonValue(value: unknown, indent: string = " "): string {
76
+ const json = JSON.stringify(value, null, 2);
77
+ return json
78
+ .split("\n")
79
+ .map((line, i) => (i === 0 ? line : indent + line))
80
+ .join("\n");
81
+ }
82
+
83
+ /** Render a single provider as structured text for `get` with all fields. */
84
+ function formatProviderDetail(p: SerializedProvider): string {
85
+ const lines: string[] = [];
86
+ const name = p.displayName ?? p.providerKey;
87
+ lines.push(`${p.providerKey} (${name})`);
88
+ if (p.description) lines.push(` Description: ${p.description}`);
89
+ if (p.supportsManagedMode) lines.push(` Managed mode: yes`);
90
+ if (p.managedServiceIsPaid) lines.push(` Managed service is paid: yes`);
91
+ if (p.dashboardUrl) lines.push(` Dashboard: ${p.dashboardUrl}`);
92
+ if (p.appType) lines.push(` App type: ${p.appType}`);
93
+ lines.push(
94
+ ` Requires client secret: ${p.requiresClientSecret ? "yes" : "no"}`,
95
+ );
96
+ if (p.clientIdPlaceholder)
97
+ lines.push(` Client ID format: ${p.clientIdPlaceholder}`);
98
+ lines.push(` Auth URL: ${p.authUrl}`);
99
+ lines.push(` Token URL: ${p.tokenUrl}`);
100
+ if (p.refreshUrl) lines.push(` Refresh URL: ${p.refreshUrl}`);
101
+ if (p.tokenEndpointAuthMethod)
102
+ lines.push(` Token auth method: ${p.tokenEndpointAuthMethod}`);
103
+ if (p.tokenExchangeBodyFormat && p.tokenExchangeBodyFormat !== "form")
104
+ lines.push(` Token exchange body format: ${p.tokenExchangeBodyFormat}`);
105
+ if ((p.defaultScopes as string[])?.length > 0)
106
+ lines.push(` Default scopes: ${(p.defaultScopes as string[]).join(", ")}`);
107
+ const avail = formatAvailableScopes(p.availableScopes);
108
+ if (avail) lines.push(` Available scopes: ${avail}`);
109
+ if (p.scopeSeparator && p.scopeSeparator !== " ")
110
+ lines.push(` Scope separator: "${p.scopeSeparator}"`);
111
+ if (p.extraParams)
112
+ lines.push(` Authorize params: ${formatJsonValue(p.extraParams)}`);
113
+ if (p.redirectUri) lines.push(` Redirect URI: ${p.redirectUri}`);
114
+ if (p.loopbackPort) lines.push(` Loopback port: ${p.loopbackPort}`);
115
+ if (p.baseUrl) lines.push(` Base URL: ${p.baseUrl}`);
116
+ if (p.userinfoUrl) lines.push(` Userinfo URL: ${p.userinfoUrl}`);
117
+ if (p.pingUrl) lines.push(` Ping URL: ${p.pingUrl}`);
118
+ if (p.pingMethod) lines.push(` Ping method: ${p.pingMethod}`);
119
+ if (p.pingHeaders)
120
+ lines.push(` Ping headers: ${formatJsonValue(p.pingHeaders)}`);
121
+ if (p.pingBody) lines.push(` Ping body: ${formatJsonValue(p.pingBody)}`);
122
+ if (p.revokeUrl) lines.push(` Revoke URL: ${p.revokeUrl}`);
123
+ if (p.revokeBodyTemplate)
124
+ lines.push(
125
+ ` Revoke body template: ${formatJsonValue(p.revokeBodyTemplate)}`,
126
+ );
127
+ if (p.injectionTemplates)
128
+ lines.push(
129
+ ` Injection templates: ${formatJsonValue(p.injectionTemplates)}`,
130
+ );
131
+ if (p.identityUrl) lines.push(` Identity URL: ${p.identityUrl}`);
132
+ if (p.identityMethod) lines.push(` Identity method: ${p.identityMethod}`);
133
+ if (p.identityHeaders)
134
+ lines.push(` Identity headers: ${formatJsonValue(p.identityHeaders)}`);
135
+ if (p.identityBody)
136
+ lines.push(` Identity body: ${formatJsonValue(p.identityBody)}`);
137
+ if (p.identityResponsePaths)
138
+ lines.push(
139
+ ` Identity response paths: ${(p.identityResponsePaths as string[]).join(", ")}`,
140
+ );
141
+ if (p.identityFormat) lines.push(` Identity format: ${p.identityFormat}`);
142
+ if (p.identityOkField)
143
+ lines.push(` Identity ok field: ${p.identityOkField}`);
144
+ if (p.setupNotes) {
145
+ if (Array.isArray(p.setupNotes)) {
146
+ lines.push(
147
+ ` Setup notes:\n${(p.setupNotes as string[]).map((n) => ` - ${n}`).join("\n")}`,
148
+ );
149
+ } else {
150
+ lines.push(` Setup notes: ${formatJsonValue(p.setupNotes)}`);
151
+ }
152
+ }
153
+ if (p.featureFlag) lines.push(` Feature flag: ${p.featureFlag}`);
154
+ if (p.logoUrl) lines.push(` Logo: ${p.logoUrl}`);
155
+ lines.push(` Created: ${p.createdAt}`);
156
+ lines.push(` Updated: ${p.updatedAt}`);
157
+ return lines.join("\n");
158
+ }
159
+
26
160
  /**
27
161
  * Resolve a logo URL from CLI flags, enforcing mutual exclusion between
28
162
  * --logo-url and --logo-simpleicons-slug. Returns:
@@ -171,11 +305,17 @@ Examples:
171
305
  rows = rows.filter((r) => r && r.supportsManagedMode);
172
306
  }
173
307
 
174
- if (!shouldOutputJson(cmd)) {
175
- log.info(`Found ${rows.length} provider(s)`);
308
+ if (shouldOutputJson(cmd)) {
309
+ writeOutput(cmd, rows);
310
+ } else {
311
+ const validRows = rows.filter(
312
+ (r): r is NonNullable<typeof r> => r != null,
313
+ );
314
+ const lines = validRows.map(formatProviderSummary);
315
+ process.stdout.write(
316
+ `${validRows.length} provider(s):\n\n${lines.join("\n\n")}\n`,
317
+ );
176
318
  }
177
-
178
- writeOutput(cmd, rows);
179
319
  } catch (err) {
180
320
  const message = err instanceof Error ? err.message : String(err);
181
321
  writeOutput(cmd, { ok: false, error: message });
@@ -199,7 +339,7 @@ Arguments:
199
339
  Must match the key used during registration or seeding.
200
340
 
201
341
  Returns the full provider configuration including auth URL, token URL,
202
- default scopes, scope policy, and extra parameters. Exits with code 1
342
+ default scopes, available scopes, and extra parameters. Exits with code 1
203
343
  if the provider key is not found.
204
344
 
205
345
  Examples:
@@ -228,7 +368,12 @@ Examples:
228
368
  return;
229
369
  }
230
370
 
231
- writeOutput(cmd, parseProviderRow(row));
371
+ const parsed = parseProviderRow(row);
372
+ if (shouldOutputJson(cmd)) {
373
+ writeOutput(cmd, parsed);
374
+ } else if (parsed) {
375
+ process.stdout.write(formatProviderDetail(parsed) + "\n");
376
+ }
232
377
  } catch (err) {
233
378
  const message = err instanceof Error ? err.message : String(err);
234
379
  writeOutput(cmd, { ok: false, error: message });
@@ -371,6 +516,10 @@ Examples:
371
516
  "--setup-notes <json>",
372
517
  'JSON array of setup instruction notes shown during guided setup (e.g. \'["Enable the Gmail API","Add test users"]\')',
373
518
  )
519
+ .option(
520
+ "--available-scopes <value>",
521
+ "Available scopes: either a JSON array of {scope, description?} objects or a URL to the provider scope docs",
522
+ )
374
523
  .addHelpText(
375
524
  "after",
376
525
  `
@@ -473,6 +622,7 @@ Examples:
473
622
  identityFormat?: string;
474
623
  identityOkField?: string;
475
624
  setupNotes?: string;
625
+ availableScopes?: string;
476
626
  },
477
627
  cmd: Command,
478
628
  ) => {
@@ -492,7 +642,11 @@ Examples:
492
642
  baseUrl: opts.baseUrl,
493
643
  userinfoUrl: opts.userinfoUrl,
494
644
  defaultScopes: opts.scopes ? opts.scopes.split(",") : [],
495
- scopePolicy: {},
645
+ availableScopes: opts.availableScopes
646
+ ? opts.availableScopes.startsWith("http")
647
+ ? opts.availableScopes
648
+ : JSON.parse(opts.availableScopes)
649
+ : undefined,
496
650
  scopeSeparator: opts.scopeSeparator,
497
651
  tokenEndpointAuthMethod: opts.tokenAuthMethod,
498
652
  tokenExchangeBodyFormat: opts.tokenExchangeBodyFormat,
@@ -679,6 +833,10 @@ Examples:
679
833
  "--setup-notes <json>",
680
834
  'JSON array of setup instruction notes shown during guided setup (e.g. \'["Enable the Gmail API","Add test users"]\')',
681
835
  )
836
+ .option(
837
+ "--available-scopes <value>",
838
+ "Available scopes: either a JSON array of {scope, description?} objects or a URL to the provider scope docs",
839
+ )
682
840
  .addHelpText(
683
841
  "after",
684
842
  `
@@ -749,6 +907,7 @@ Examples:
749
907
  identityFormat?: string;
750
908
  identityOkField?: string;
751
909
  setupNotes?: string;
910
+ availableScopes?: string;
752
911
  },
753
912
  cmd: Command,
754
913
  ) => {
@@ -868,6 +1027,15 @@ Examples:
868
1027
  params.identityOkField = opts.identityOkField;
869
1028
  if (opts.setupNotes !== undefined)
870
1029
  params.setupNotes = JSON.parse(opts.setupNotes);
1030
+ if (opts.availableScopes !== undefined) {
1031
+ if (opts.availableScopes === "") {
1032
+ params.availableScopes = null;
1033
+ } else {
1034
+ params.availableScopes = opts.availableScopes.startsWith("http")
1035
+ ? opts.availableScopes
1036
+ : JSON.parse(opts.availableScopes);
1037
+ }
1038
+ }
871
1039
 
872
1040
  // Check if any fields were actually provided
873
1041
  if (Object.keys(params).length === 0) {
@@ -1,7 +1,6 @@
1
1
  import type { Command } from "commander";
2
2
 
3
3
  import { getProvider, listConnections } from "../../../oauth/oauth-store.js";
4
- import { getCliLogger } from "../../logger.js";
5
4
  import { shouldOutputJson, writeOutput } from "../../output.js";
6
5
  import {
7
6
  fetchActiveConnections,
@@ -9,7 +8,36 @@ import {
9
8
  requirePlatformClient,
10
9
  } from "./shared.js";
11
10
 
12
- const log = getCliLogger("cli");
11
+ // ---------------------------------------------------------------------------
12
+ // Text formatting helpers
13
+ // ---------------------------------------------------------------------------
14
+
15
+ interface ConnectionSummary {
16
+ id: string;
17
+ account: string | null;
18
+ grantedScopes: string[];
19
+ status: string;
20
+ expiresAt?: string | null;
21
+ hasRefreshToken?: boolean;
22
+ }
23
+
24
+ function formatConnection(c: ConnectionSummary, mode: string): string {
25
+ const lines: string[] = [];
26
+ lines.push(` ${c.account ?? "(no account)"}`);
27
+ lines.push(` Connection ID: ${c.id}`);
28
+ lines.push(` Status: ${c.status}`);
29
+ if (c.grantedScopes.length > 0) {
30
+ lines.push(` Granted scopes: ${c.grantedScopes.join(", ")}`);
31
+ } else {
32
+ lines.push(` Granted scopes: (none)`);
33
+ }
34
+ if (mode === "byo") {
35
+ if (c.expiresAt) lines.push(` Expires: ${c.expiresAt}`);
36
+ if (c.hasRefreshToken !== undefined)
37
+ lines.push(` Refresh token: ${c.hasRefreshToken ? "yes" : "no"}`);
38
+ }
39
+ return lines.join("\n");
40
+ }
13
41
 
14
42
  // ---------------------------------------------------------------------------
15
43
  // Command registration
@@ -95,25 +123,20 @@ Examples:
95
123
  return;
96
124
  }
97
125
 
98
- // Human output
126
+ // Text output
99
127
  if (connections.length === 0) {
100
- log.info(
101
- `No active connections for ${provider}. Connect with 'assistant oauth connect ${provider}'.`,
128
+ process.stdout.write(
129
+ `No active connections for ${provider}.\nConnect with \`assistant oauth connect ${provider}\`.\n`,
102
130
  );
103
131
  return;
104
132
  }
105
133
 
106
- log.info(`Provider: ${provider} (managed)`);
107
- log.info(`${connections.length} active connection(s):`);
108
- for (const c of connections) {
109
- const scopes =
110
- c.grantedScopes.length > 0
111
- ? `[${c.grantedScopes.join(", ")}]`
112
- : "[]";
113
- log.info(
114
- ` \u2022 ${c.id} ${c.account ?? "(no account)"} ${scopes} ${c.status}`,
115
- );
116
- }
134
+ const blocks = connections.map((c) =>
135
+ formatConnection(c, "managed"),
136
+ );
137
+ process.stdout.write(
138
+ `${provider} (managed) — ${connections.length} active connection(s):\n\n${blocks.join("\n\n")}\n`,
139
+ );
117
140
  } else {
118
141
  // ---------------------------------------------------------------
119
142
  // BYO path
@@ -155,31 +178,18 @@ Examples:
155
178
  return;
156
179
  }
157
180
 
158
- // Human output
181
+ // Text output
159
182
  if (connections.length === 0) {
160
- log.info(
161
- `No active connections for ${provider}. Connect with 'assistant oauth connect ${provider}'.`,
183
+ process.stdout.write(
184
+ `No active connections for ${provider}.\nConnect with \`assistant oauth connect ${provider}\`.\n`,
162
185
  );
163
186
  return;
164
187
  }
165
188
 
166
- log.info(`Provider: ${provider} (byo)`);
167
- log.info(`${connections.length} active connection(s):`);
168
- for (const c of connections) {
169
- const scopes =
170
- c.grantedScopes.length > 0
171
- ? `[${c.grantedScopes.join(", ")}]`
172
- : "[]";
173
- const expires = c.expiresAt
174
- ? `expires ${c.expiresAt}`
175
- : "no expiry";
176
- const refresh = c.hasRefreshToken
177
- ? "refresh: yes"
178
- : "refresh: no";
179
- log.info(
180
- ` \u2022 ${c.id} ${c.account ?? "(no account)"} ${scopes} ${expires} ${refresh}`,
181
- );
182
- }
189
+ const blocks = connections.map((c) => formatConnection(c, "byo"));
190
+ process.stdout.write(
191
+ `${provider} (byo) ${connections.length} active connection(s):\n\n${blocks.join("\n\n")}\n`,
192
+ );
183
193
  }
184
194
  } catch (err) {
185
195
  const message = err instanceof Error ? err.message : String(err);
@@ -78,7 +78,8 @@ Examples:
78
78
  const config = getConfig();
79
79
  const resolved = resolveSkillStates(localCatalog, config);
80
80
  const bundled = resolved.filter(
81
- (r) => r.summary.source === "bundled",
81
+ (r) =>
82
+ r.summary.source === "bundled" || r.summary.source === "plugin",
82
83
  );
83
84
  const installed = resolved.filter(
84
85
  (r) =>
@@ -365,9 +366,7 @@ Examples:
365
366
 
366
367
  // ── Display bundled/installed results ─────────────────────────
367
368
  if (bundledMatches.length > 0) {
368
- log.info(
369
- `Bundled & installed skills (${bundledMatches.length}):\n`,
370
- );
369
+ log.info(`Bundled & installed skills (${bundledMatches.length}):\n`);
371
370
  for (const s of bundledMatches) {
372
371
  const emoji = s.emoji ? `${s.emoji} ` : "";
373
372
  const tag = s.source === "bundled" ? " [bundled]" : " [installed]";
@@ -5,7 +5,6 @@ import { Command } from "commander";
5
5
  import { initFeatureFlagOverrides } from "../config/assistant-feature-flags.js";
6
6
  import { getConfigReadOnly } from "../config/loader.js";
7
7
  import { isEmailEnabled } from "../email/feature-gate.js";
8
- import { registerHooksCommand } from "../hooks/cli.js";
9
8
  import { getWorkspaceDir } from "../util/platform.js";
10
9
  import { APP_VERSION } from "../version.js";
11
10
  import { registerAttachmentCommand } from "./commands/attachment.js";
@@ -18,6 +17,7 @@ import { registerBashCommand } from "./commands/bash.js";
18
17
  import { registerBrowserCommand } from "./commands/browser.js";
19
18
  import { registerCacheCommand } from "./commands/cache.js";
20
19
  import { registerChannelVerificationSessionsCommand } from "./commands/channel-verification-sessions.js";
20
+ import { registerClientsCommand } from "./commands/clients.js";
21
21
  import { registerCompletionsCommand } from "./commands/completions.js";
22
22
  import { registerConfigCommand } from "./commands/config.js";
23
23
  import { registerContactsCommand } from "./commands/contacts.js";
@@ -37,7 +37,6 @@ import { registerOAuthCommand } from "./commands/oauth/index.js";
37
37
  import { registerPlatformCommand } from "./commands/platform/index.js";
38
38
  import { registerRoutesCommand } from "./commands/routes.js";
39
39
  import { registerSequenceCommand } from "./commands/sequence.js";
40
- import { registerShotgunCommand } from "./commands/shotgun.js";
41
40
  import { registerSkillsCommand } from "./commands/skills.js";
42
41
  import { registerSttCommand } from "./commands/stt.js";
43
42
  import { registerTaskCommand } from "./commands/task.js";
@@ -72,49 +71,46 @@ Examples:
72
71
  );
73
72
 
74
73
  registerDefaultAction(program);
74
+
75
+ registerAttachmentCommand(program);
76
+ registerAuditCommand(program);
77
+ registerAuthCommand(program);
78
+ registerAutonomyCommand(program);
79
+ registerAvatarCommand(program);
75
80
  registerBackupCommand(program);
76
81
  registerBashCommand(program);
77
82
  registerBrowserCommand(program);
78
83
  registerCacheCommand(program);
79
- registerTaskCommand(program);
80
- registerConversationsCommand(program);
84
+ registerChannelVerificationSessionsCommand(program);
85
+ registerClientsCommand(program);
86
+ registerCompletionsCommand(program);
81
87
  registerConfigCommand(program);
82
- registerKeysCommand(program);
83
- registerCredentialsCommand(program);
88
+ registerContactsCommand(program);
89
+ registerConversationsCommand(program);
84
90
  registerCredentialExecutionCommand(program);
85
- registerTrustCommand(program);
86
- registerMemoryCommand(program);
87
- registerAuditCommand(program);
88
- registerAuthCommand(program);
89
- registerAttachmentCommand(program);
90
- registerAvatarCommand(program);
91
- registerHooksCommand(program);
92
- registerMcpCommand(program);
91
+ registerCredentialsCommand(program);
93
92
  if (isEmailEnabled(getConfigReadOnly())) {
94
93
  registerDomainCommand(program);
95
94
  registerEmailCommand(program);
96
95
  }
97
- registerContactsCommand(program);
98
- registerChannelVerificationSessionsCommand(program);
99
- registerAutonomyCommand(program);
100
- registerCompletionsCommand(program);
96
+ registerImageGenerationCommand(program);
97
+ registerInferenceCommand(program);
98
+ registerKeysCommand(program);
99
+ registerMcpCommand(program);
100
+ registerMemoryCommand(program);
101
101
  registerNotificationsCommand(program);
102
- registerPlatformCommand(program);
103
102
  registerOAuthCommand(program);
103
+ registerPlatformCommand(program);
104
104
  registerRoutesCommand(program);
105
- registerSkillsCommand(program);
106
- registerUsageCommand(program);
107
- registerWatchersCommand(program);
108
-
109
- registerImageGenerationCommand(program);
110
- registerUiCommand(program);
111
-
112
- registerShotgunCommand(program);
113
105
  registerSequenceCommand(program);
106
+ registerSkillsCommand(program);
114
107
  registerSttCommand(program);
108
+ registerTaskCommand(program);
109
+ registerTrustCommand(program);
115
110
  registerTtsCommand(program);
116
-
117
- registerInferenceCommand(program);
111
+ registerUiCommand(program);
112
+ registerUsageCommand(program);
113
+ registerWatchersCommand(program);
118
114
 
119
115
  // Fail fast when no assistant workspace exists on disk. The workspace is
120
116
  // created by `vellum hatch` and must be present for any command to work.
@@ -12,12 +12,17 @@ describe("BackupConfigSchema", () => {
12
12
  expect(parsed).toEqual({
13
13
  enabled: false,
14
14
  intervalHours: 6,
15
- retention: 7,
15
+ retention: 3,
16
16
  offsite: { enabled: true, destinations: null },
17
17
  localDirectory: null,
18
18
  });
19
19
  });
20
20
 
21
+ test("default retention is 3 (ATL-193 — snapshots are full copies, not incremental)", () => {
22
+ const parsed = BackupConfigSchema.parse({});
23
+ expect(parsed.retention).toBe(3);
24
+ });
25
+
21
26
  test("rejects intervalHours: 0 (must be >= 1)", () => {
22
27
  const result = BackupConfigSchema.safeParse({ intervalHours: 0 });
23
28
  expect(result.success).toBe(false);
@@ -105,7 +110,7 @@ describe("BackupConfigSchema", () => {
105
110
  expect(parsed).toEqual({
106
111
  enabled: true,
107
112
  intervalHours: 6,
108
- retention: 7,
113
+ retention: 3,
109
114
  offsite: { enabled: true, destinations: null },
110
115
  localDirectory: null,
111
116
  });
@@ -260,7 +260,7 @@ app_refresh(app_id)
260
260
  - Preact for UI (not React) - `import { render } from 'preact'`
261
261
  - TypeScript encouraged for all `.tsx`/`.ts` files
262
262
  - No external fonts, images, or resources - use system fonts and CSS/SVG for visuals
263
- - Design for 400-600px width with graceful resizing
263
+ - Design responsively. Apps render at fluid, user-resizable widths avoid fixed-pixel layouts
264
264
  - The WebView blocks all navigation - links and form `action` attributes won't work
265
265
  <!-- feature:app-builder-multifile:end -->
266
266
 
@@ -275,7 +275,7 @@ Write a complete, self-contained HTML document.
275
275
  - Single HTML string - no external files, CDNs, or imports
276
276
  - All CSS in `<style>` in `<head>`, all JavaScript in `<script>` before `</body>`
277
277
  - No external fonts, images, or resources - use system fonts and CSS/SVG for visuals
278
- - Design for 400-600px width with graceful resizing
278
+ - Design responsively. Apps render at fluid, user-resizable widths avoid fixed-pixel layouts
279
279
  - The WebView blocks all navigation - links and form `action` attributes won't work
280
280
 
281
281
  <!-- feature:app-builder-multifile:alt:end -->
@@ -37,16 +37,16 @@ A CSS/JS widget library is auto-injected alongside the design system. Use these
37
37
 
38
38
  ## Content & landing page components
39
39
 
40
- | Widget | Purpose |
41
- | ------------------------------------------------ | --------------------------------------------------- |
42
- | `.v-hero` / `.v-hero-badge` / `.v-hero-subtitle` | Hero banner with gradient, trust badge, accent word |
43
- | `.v-section-header` / `.v-section-label` | Section intro with label |
44
- | `.v-feature-grid` / `.v-feature-card` | Feature showcase with hover lift |
45
- | `.v-pullquote` | Blockquote with gradient accent border |
46
- | `.v-comparison` | Before/after cards (`.before`/`.after`) |
47
- | `.v-page` | Centered container (max-width 600px) |
48
- | `.v-gradient-text` | Accent-colored gradient text |
49
- | `.v-animate-in` | Staggered fade-in for children |
40
+ | Widget | Purpose |
41
+ | ------------------------------------------------ | ------------------------------------------------------ |
42
+ | `.v-hero` / `.v-hero-badge` / `.v-hero-subtitle` | Hero banner with gradient, trust badge, accent word |
43
+ | `.v-section-header` / `.v-section-label` | Section intro with label |
44
+ | `.v-feature-grid` / `.v-feature-card` | Feature showcase with hover lift |
45
+ | `.v-pullquote` | Blockquote with gradient accent border |
46
+ | `.v-comparison` | Before/after cards (`.before`/`.after`) |
47
+ | `.v-page` | Centered flex-column container (fills available width) |
48
+ | `.v-gradient-text` | Accent-colored gradient text |
49
+ | `.v-animate-in` | Staggered fade-in for children |
50
50
 
51
51
  ## Widget JavaScript utilities
52
52