@vellumai/assistant 0.8.12 → 0.9.0-staging.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (442) hide show
  1. package/AGENTS.md +0 -14
  2. package/ARCHITECTURE.md +45 -45
  3. package/README.md +1 -1
  4. package/bun.lock +200 -154
  5. package/docs/architecture/integrations.md +3 -3
  6. package/docs/architecture/memory.md +2 -2
  7. package/docs/architecture/security.md +10 -10
  8. package/docs/runbook-trusted-contacts.md +12 -12
  9. package/docs/skills.md +6 -6
  10. package/docs/workflows-testing.md +221 -0
  11. package/docs/workflows.md +510 -0
  12. package/examples/plugins/echo/README.md +5 -5
  13. package/knip.json +2 -0
  14. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +105 -0
  15. package/node_modules/@vellumai/gateway-client/src/index.ts +12 -0
  16. package/openapi.yaml +7197 -5708
  17. package/package.json +8 -4
  18. package/scripts/generate-openapi.ts +66 -114
  19. package/src/__tests__/access-request-seed-content-blocks.test.ts +213 -0
  20. package/src/__tests__/adaptive-thinking-repair.test.ts +32 -3
  21. package/src/__tests__/agent-loop-output-hooks.test.ts +183 -0
  22. package/src/__tests__/agent-loop-regrowth-guard.test.ts +506 -0
  23. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
  24. package/src/__tests__/agent-wake-override-profile.test.ts +77 -0
  25. package/src/__tests__/app-compiler.test.ts +7 -1
  26. package/src/__tests__/app-dir-path-guard.test.ts +27 -3
  27. package/src/__tests__/app-executors.test.ts +43 -0
  28. package/src/__tests__/approval-cascade.test.ts +0 -5
  29. package/src/__tests__/approval-routes-http.test.ts +91 -0
  30. package/src/__tests__/assistant-stream-state.test.ts +107 -0
  31. package/src/__tests__/browser-fill-credential.test.ts +3 -3
  32. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +1 -1
  33. package/src/__tests__/compaction-events.test.ts +63 -7
  34. package/src/__tests__/compaction-trail-store.test.ts +74 -1
  35. package/src/__tests__/compaction.benchmark.test.ts +63 -41
  36. package/src/__tests__/compactor-low-watermark-cut.test.ts +349 -0
  37. package/src/__tests__/context-window-manager-compact-retry.test.ts +64 -0
  38. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -5
  39. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -5
  40. package/src/__tests__/conversation-history-web-search.test.ts +7 -0
  41. package/src/__tests__/conversation-process-callsite.test.ts +0 -5
  42. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -5
  43. package/src/__tests__/conversation-queue.test.ts +0 -5
  44. package/src/__tests__/conversation-slash-queue.test.ts +0 -5
  45. package/src/__tests__/conversation-slash-unknown.test.ts +0 -5
  46. package/src/__tests__/conversation-speed-override.test.ts +0 -5
  47. package/src/__tests__/conversation-surfaces-data-persist.test.ts +97 -0
  48. package/src/__tests__/conversation-surfaces-task-progress.test.ts +67 -0
  49. package/src/__tests__/conversation-usage.test.ts +2 -0
  50. package/src/__tests__/conversation-workspace-injection.test.ts +0 -5
  51. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -5
  52. package/src/__tests__/credential-broker-browser-fill.test.ts +2 -2
  53. package/src/__tests__/credential-broker-server-use.test.ts +2 -2
  54. package/src/__tests__/credential-broker.test.ts +1 -1
  55. package/src/__tests__/credential-prompt-route.test.ts +417 -0
  56. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  57. package/src/__tests__/credential-vault.test.ts +37 -0
  58. package/src/__tests__/db-schedule-syntax-migration.test.ts +24 -0
  59. package/src/__tests__/dynamic-page-surface.test.ts +219 -0
  60. package/src/__tests__/empty-state-greeting-cache.test.ts +94 -0
  61. package/src/__tests__/gateway-flag-listener.test.ts +24 -7
  62. package/src/__tests__/guardian-action-sweep.test.ts +56 -219
  63. package/src/__tests__/guardian-routing-invariants.test.ts +138 -0
  64. package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
  65. package/src/__tests__/list-messages-hidden-metadata.test.ts +99 -0
  66. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +87 -1
  67. package/src/__tests__/llm-resolver.test.ts +115 -0
  68. package/src/__tests__/managed-profile-guard.test.ts +6 -5
  69. package/src/__tests__/max-tokens-continue-hook.test.ts +184 -0
  70. package/src/__tests__/media-generate-image.test.ts +20 -9
  71. package/src/__tests__/mock-gateway-ipc.ts +23 -0
  72. package/src/__tests__/model-intents.test.ts +1 -1
  73. package/src/__tests__/normalize-onboarding.test.ts +26 -0
  74. package/src/__tests__/notification-decision-strategy.test.ts +4 -2
  75. package/src/__tests__/notification-telegram-adapter.test.ts +21 -3
  76. package/src/__tests__/pending-interactions-resolved-event.test.ts +62 -0
  77. package/src/__tests__/post-turn-tool-result-truncation.test.ts +72 -18
  78. package/src/__tests__/require-fresh-approval.test.ts +425 -1
  79. package/src/__tests__/resolve-app-id.test.ts +56 -0
  80. package/src/__tests__/runtime-events-sse-parity.test.ts +2 -0
  81. package/src/__tests__/schedule-routes-workflow-validation.test.ts +408 -0
  82. package/src/__tests__/schedule-routes.test.ts +257 -4
  83. package/src/__tests__/schedule-store.test.ts +60 -0
  84. package/src/__tests__/schedule-tools.test.ts +247 -2
  85. package/src/__tests__/skill-execute-input.test.ts +85 -0
  86. package/src/__tests__/skill-secret-handling-guard.test.ts +21 -20
  87. package/src/__tests__/skills.test.ts +3 -3
  88. package/src/__tests__/slack-app-setup-skill-regression.test.ts +1 -1
  89. package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
  90. package/src/__tests__/subagent-tool-gate-mode.test.ts +547 -0
  91. package/src/__tests__/system-prompt.test.ts +1 -1
  92. package/src/__tests__/task-progress-nudge-hook.test.ts +372 -0
  93. package/src/__tests__/task-scheduler.test.ts +299 -0
  94. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +209 -0
  95. package/src/__tests__/tool-result-spool.test.ts +3 -1
  96. package/src/__tests__/workspace-migration-102-preserve-heartbeat-enabled-for-existing-workspaces.test.ts +181 -0
  97. package/src/__tests__/workspace-migration-103-upgrade-quality-profile-to-opus-4-8.test.ts +174 -0
  98. package/src/agent/compaction-circuit.ts +11 -0
  99. package/src/agent/loop.ts +181 -12
  100. package/src/api/constants/call-sites.ts +12 -0
  101. package/src/api/events/assistant-thinking-delta.ts +10 -0
  102. package/src/api/events/usage-update.ts +7 -0
  103. package/src/api/index.ts +4 -1
  104. package/src/api/responses/memory-v3-selection-log.ts +18 -11
  105. package/src/approvals/approval-primitive.ts +2 -2
  106. package/src/background-wake/background-wake-routes.test.ts +5 -2
  107. package/src/bundler/compiler-tools.ts +1 -1
  108. package/src/bundler/package-resolver.ts +0 -1
  109. package/src/calls/call-domain.ts +1 -1
  110. package/src/calls/guardian-action-sweep.ts +16 -93
  111. package/src/cli/AGENTS.md +4 -0
  112. package/src/cli/commands/__tests__/schedules.test.ts +430 -1
  113. package/src/cli/commands/credentials.ts +28 -24
  114. package/src/cli/commands/image-generation.ts +23 -9
  115. package/src/cli/commands/notifications.ts +1 -1
  116. package/src/cli/commands/plugins.ts +89 -46
  117. package/src/cli/commands/schedules.ts +384 -11
  118. package/src/cli/lib/__tests__/inspect-plugin.test.ts +69 -5
  119. package/src/cli/lib/__tests__/install-from-github.test.ts +15 -0
  120. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +81 -4
  121. package/src/cli/lib/inspect-plugin.ts +62 -1
  122. package/src/cli/lib/install-from-github.ts +52 -5
  123. package/src/cli/lib/upgrade-plugin.ts +18 -0
  124. package/src/config/__tests__/workflows-schema.test.ts +60 -0
  125. package/src/config/bundled-skills/acp/SKILL.md +2 -2
  126. package/src/config/bundled-skills/app-builder/SKILL.md +1 -1
  127. package/src/config/bundled-skills/app-builder/tools/app-create.ts +6 -1
  128. package/src/config/bundled-skills/app-builder/tools/app-generate-icon.ts +7 -1
  129. package/src/config/bundled-skills/app-builder/tools/app-refresh.ts +7 -1
  130. package/src/config/bundled-skills/app-builder/tools/app-update.ts +10 -1
  131. package/src/config/bundled-skills/image-studio/SKILL.md +66 -19
  132. package/src/config/bundled-skills/image-studio/TOOLS.json +1 -6
  133. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +22 -3
  134. package/src/config/bundled-skills/personal-page/SKILL.md +57 -0
  135. package/src/config/bundled-skills/personal-page/TOOLS.json +27 -0
  136. package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +17 -0
  137. package/src/config/bundled-skills/schedule/SKILL.md +7 -2
  138. package/src/config/bundled-skills/schedule/TOOLS.json +48 -4
  139. package/src/config/bundled-skills/workflows/SKILL.md +214 -0
  140. package/src/config/bundled-skills/workflows/TOOLS.json +84 -0
  141. package/src/config/bundled-skills/workflows/tools/manage-workflows.ts +12 -0
  142. package/src/config/bundled-skills/workflows/tools/run-workflow.ts +12 -0
  143. package/src/config/bundled-tool-registry.ts +14 -2
  144. package/src/config/call-site-defaults.ts +5 -0
  145. package/src/config/feature-flag-registry.json +12 -4
  146. package/src/config/llm-context-resolution.ts +8 -0
  147. package/src/config/llm-resolver.ts +30 -0
  148. package/src/config/preloaded-apps/personal-page/src/components/About.tsx +22 -0
  149. package/src/config/preloaded-apps/personal-page/src/components/App.tsx +16 -0
  150. package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +77 -0
  151. package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +57 -0
  152. package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +28 -0
  153. package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +234 -0
  154. package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +48 -0
  155. package/src/config/preloaded-apps/personal-page/src/components/media.ts +16 -0
  156. package/src/config/preloaded-apps/personal-page/src/index.html +20 -0
  157. package/src/config/preloaded-apps/personal-page/src/main.tsx +7 -0
  158. package/src/config/preloaded-apps/personal-page/src/profile-data.ts +82 -0
  159. package/src/config/preloaded-apps/personal-page/src/styles.css +759 -0
  160. package/src/config/schema.ts +2 -0
  161. package/src/config/schemas/call-site-catalog.ts +7 -0
  162. package/src/config/schemas/heartbeat.ts +4 -1
  163. package/src/config/schemas/llm.ts +33 -26
  164. package/src/config/schemas/memory-retrospective.ts +19 -0
  165. package/src/config/schemas/platform.ts +8 -0
  166. package/src/config/schemas/services.ts +5 -2
  167. package/src/config/schemas/workflows.ts +42 -0
  168. package/src/config/skills.ts +3 -3
  169. package/src/context/compactor.ts +273 -39
  170. package/src/context/post-turn-tool-result-truncation.ts +23 -6
  171. package/src/context/tool-result-spool.ts +12 -17
  172. package/src/credential-execution/executable-discovery.ts +1 -1
  173. package/src/credential-execution/process-manager.ts +37 -3
  174. package/src/credential-execution/prompted-credential.ts +205 -0
  175. package/src/daemon/conversation-agent-loop-handlers.ts +14 -0
  176. package/src/daemon/conversation-process.ts +11 -2
  177. package/src/daemon/conversation-surfaces.ts +167 -3
  178. package/src/daemon/conversation-tool-setup.ts +103 -26
  179. package/src/daemon/conversation-usage.ts +2 -0
  180. package/src/daemon/conversation.ts +115 -11
  181. package/src/daemon/handlers/shared.ts +26 -14
  182. package/src/daemon/host-cu-proxy.ts +15 -12
  183. package/src/daemon/host-file-proxy.ts +15 -12
  184. package/src/daemon/host-transfer-proxy.ts +30 -24
  185. package/src/daemon/lifecycle.ts +40 -3
  186. package/src/daemon/message-protocol.ts +3 -0
  187. package/src/daemon/message-types/messages.ts +2 -10
  188. package/src/daemon/message-types/workflows.ts +49 -0
  189. package/src/daemon/parse-actual-tokens-from-error.test.ts +62 -1
  190. package/src/daemon/parse-actual-tokens-from-error.ts +43 -4
  191. package/src/daemon/process-message.ts +6 -0
  192. package/src/daemon/tool-setup-types.ts +57 -0
  193. package/src/daemon/wake-conversation-ops.ts +18 -0
  194. package/src/heartbeat/heartbeat-run-store.ts +8 -2
  195. package/src/home/feed-types.ts +1 -1
  196. package/src/ipc/gateway-flag-listener.ts +28 -6
  197. package/src/mcp/mcp-auth-state.ts +8 -20
  198. package/src/media/__tests__/image-models.test.ts +57 -0
  199. package/src/media/image-models.ts +66 -0
  200. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +38 -0
  201. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +12 -2
  202. package/src/memory/__tests__/memory-retrospective-job.test.ts +911 -34
  203. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +227 -5
  204. package/src/memory/__tests__/memory-retrospective-state.test.ts +195 -0
  205. package/src/memory/__tests__/preloaded-apps.test.ts +85 -0
  206. package/src/memory/auto-analysis-enqueue.ts +14 -1
  207. package/src/memory/compaction-log-store-clickhouse.ts +6 -4
  208. package/src/memory/conversation-crud.ts +9 -2
  209. package/src/memory/conversation-disk-view.ts +1 -1
  210. package/src/memory/conversation-queries.ts +22 -7
  211. package/src/memory/db-init.ts +20 -0
  212. package/src/memory/db-maintenance.ts +16 -0
  213. package/src/memory/embedding-runtime-manager.ts +1 -1
  214. package/src/memory/llm-request-log-source-clickhouse.ts +112 -14
  215. package/src/memory/llm-request-log-source-local.ts +19 -1
  216. package/src/memory/llm-request-log-source.ts +35 -6
  217. package/src/memory/llm-request-log-store.ts +90 -2
  218. package/src/memory/memory-retrospective-constants.ts +9 -0
  219. package/src/memory/memory-retrospective-enqueue.ts +3 -6
  220. package/src/memory/memory-retrospective-fork-boundary.ts +94 -0
  221. package/src/memory/memory-retrospective-job.ts +500 -208
  222. package/src/memory/memory-retrospective-startup-cleanup.ts +97 -19
  223. package/src/memory/memory-retrospective-state.ts +85 -2
  224. package/src/memory/migrations/281-memory-retrospective-remembered-log.ts +40 -0
  225. package/src/memory/migrations/282-schedule-inference-profile.test.ts +77 -0
  226. package/src/memory/migrations/282-schedule-inference-profile.ts +26 -0
  227. package/src/memory/migrations/283-memory-v3-selections-message-id-and-sections.test.ts +102 -0
  228. package/src/memory/migrations/283-memory-v3-selections-message-id-and-sections.ts +53 -0
  229. package/src/memory/migrations/284-workflow-runs.ts +51 -0
  230. package/src/memory/migrations/285-schedule-workflow-mode.ts +26 -0
  231. package/src/memory/migrations/286-workflow-run-trust.ts +27 -0
  232. package/src/memory/migrations/287-conversation-origin-channel-index.ts +15 -0
  233. package/src/memory/migrations/288-backfill-origin-channel-from-bindings.ts +43 -0
  234. package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +115 -0
  235. package/src/memory/migrations/290-schedule-capabilities.test.ts +77 -0
  236. package/src/memory/migrations/290-schedule-capabilities.ts +25 -0
  237. package/src/memory/migrations/__tests__/281-memory-retrospective-remembered-log.test.ts +96 -0
  238. package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +571 -0
  239. package/src/memory/migrations/index.ts +10 -0
  240. package/src/memory/preloaded-apps.ts +116 -0
  241. package/src/memory/schema/infrastructure.ts +4 -0
  242. package/src/memory/schema/memory-core.ts +4 -0
  243. package/src/memory/v2/__tests__/concept-page-frontmatter-schema.test.ts +45 -0
  244. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +11 -7
  245. package/src/memory/v2/__tests__/page-store.test.ts +13 -2
  246. package/src/memory/v2/__tests__/qdrant.test.ts +24 -0
  247. package/src/memory/v2/frontmatter-sweep.ts +7 -6
  248. package/src/memory/v2/page-store.ts +4 -3
  249. package/src/memory/v2/qdrant.ts +42 -3
  250. package/src/memory/v2/types.ts +16 -10
  251. package/src/messaging/draft-store.ts +1 -1
  252. package/src/notifications/access-request-copy.ts +200 -113
  253. package/src/notifications/adapters/slack.ts +250 -111
  254. package/src/notifications/adapters/telegram.ts +7 -44
  255. package/src/notifications/approval-card-builder.ts +93 -0
  256. package/src/notifications/broadcaster.ts +74 -0
  257. package/src/notifications/conversation-pairing.ts +8 -6
  258. package/src/notifications/copy-composer.ts +32 -26
  259. package/src/notifications/decision-engine.ts +59 -7
  260. package/src/notifications/guardian-question-mode.ts +145 -155
  261. package/src/notifications/home-feed-side-effect.ts +28 -11
  262. package/src/notifications/notification-utils.ts +66 -0
  263. package/src/notifications/signal.ts +6 -0
  264. package/src/notifications/tool-approval-copy.ts +142 -0
  265. package/src/notifications/types.ts +19 -0
  266. package/src/permissions/threshold.ts +11 -0
  267. package/src/plugin-api/types.ts +16 -4
  268. package/src/plugins/defaults/compaction/window-manager.ts +44 -0
  269. package/src/plugins/defaults/index.ts +46 -0
  270. package/src/plugins/defaults/max-tokens-continue/continue-state-store.ts +53 -0
  271. package/src/plugins/defaults/max-tokens-continue/hooks/post-model-call.ts +80 -0
  272. package/src/plugins/defaults/max-tokens-continue/hooks/stop.ts +20 -0
  273. package/src/plugins/defaults/max-tokens-continue/package.json +14 -0
  274. package/src/plugins/defaults/memory-retrieval/hooks/__tests__/user-prompt-submit.test.ts +37 -0
  275. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +29 -1
  276. package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +8 -3
  277. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +4 -2
  278. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +28 -18
  279. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +67 -0
  280. package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +122 -22
  281. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +2 -0
  282. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +63 -1
  283. package/src/plugins/defaults/memory-v3-shadow/injector.ts +61 -18
  284. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +1 -1
  285. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +39 -10
  286. package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +34 -1
  287. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +112 -47
  288. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +78 -15
  289. package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +206 -0
  290. package/src/plugins/defaults/task-progress-nudge/package.json +15 -0
  291. package/src/prompts/__tests__/system-prompt.test.ts +100 -1
  292. package/src/prompts/__tests__/task-progress-hint-section.test.ts +5 -7
  293. package/src/prompts/normalize-onboarding.ts +2 -0
  294. package/src/prompts/persona-resolver.ts +3 -0
  295. package/src/prompts/system-prompt.ts +51 -2
  296. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +3 -1
  297. package/src/prompts/templates/system-sections.ts +8 -3
  298. package/src/providers/call-site-routing.ts +6 -3
  299. package/src/providers/fireworks/client.ts +3 -0
  300. package/src/providers/inference/auth.ts +52 -46
  301. package/src/providers/model-intents.ts +2 -2
  302. package/src/providers/openai/__tests__/coerce-object-args.test.ts +105 -0
  303. package/src/providers/openai/chat-completions-provider.ts +47 -9
  304. package/src/providers/openai/coerce-object-args.ts +104 -0
  305. package/src/providers/retry.ts +8 -5
  306. package/src/providers/types.ts +10 -0
  307. package/src/runtime/__tests__/agent-wake.test.ts +629 -7
  308. package/src/runtime/access-request-helper.ts +16 -9
  309. package/src/runtime/agent-wake.ts +302 -51
  310. package/src/runtime/assistant-stream-state.ts +141 -8
  311. package/src/runtime/background-job-runner.ts +9 -0
  312. package/src/runtime/channel-approval-types.ts +1 -0
  313. package/src/runtime/channel-invite-transports/telegram.ts +6 -5
  314. package/src/runtime/channel-invite-transports/voice.ts +2 -2
  315. package/src/runtime/channel-invite-types.ts +4 -2
  316. package/src/runtime/channel-retry-sweep.ts +19 -41
  317. package/src/runtime/finalize-event-delivery.ts +72 -0
  318. package/src/runtime/guardian-action-message-composer.ts +0 -54
  319. package/src/runtime/http-server.ts +6 -14
  320. package/src/runtime/http-types.ts +0 -1
  321. package/src/runtime/message-composer-types.ts +0 -9
  322. package/src/runtime/middleware/__tests__/rate-limiter.test.ts +63 -0
  323. package/src/runtime/middleware/auth.ts +27 -3
  324. package/src/runtime/middleware/rate-limiter.ts +28 -1
  325. package/src/runtime/migrations/vbundle-builder.ts +6 -5
  326. package/src/runtime/pending-interactions.ts +20 -1
  327. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +232 -173
  328. package/src/runtime/routes/__tests__/plugins-routes.test.ts +18 -0
  329. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +436 -0
  330. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +11 -0
  331. package/src/runtime/routes/approval-routes.ts +35 -8
  332. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -1
  333. package/src/runtime/routes/btw-routes.ts +37 -1
  334. package/src/runtime/routes/channel-delivery-routes.ts +11 -7
  335. package/src/runtime/routes/channel-route-definitions.ts +3 -0
  336. package/src/runtime/routes/channel-route-shared.ts +3 -1
  337. package/src/runtime/routes/consolidation-routes.ts +17 -13
  338. package/src/runtime/routes/conversation-compaction-routes.ts +159 -119
  339. package/src/runtime/routes/conversation-list-routes.ts +41 -4
  340. package/src/runtime/routes/conversation-query-routes.ts +196 -11
  341. package/src/runtime/routes/conversation-routes.ts +15 -1
  342. package/src/runtime/routes/credential-prompt-routes.ts +39 -17
  343. package/src/runtime/routes/empty-state-greeting-cache.ts +65 -0
  344. package/src/runtime/routes/heartbeat-routes.ts +18 -13
  345. package/src/runtime/routes/image-generation-routes.ts +20 -2
  346. package/src/runtime/routes/inbound-message-handler.ts +13 -12
  347. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +32 -31
  348. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +7 -5
  349. package/src/runtime/routes/inbound-stages/background-dispatch.ts +7 -21
  350. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +5 -5
  351. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +6 -15
  352. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +1 -1
  353. package/src/runtime/routes/index.ts +6 -0
  354. package/src/runtime/routes/log-export/AGENTS.md +1 -1
  355. package/src/runtime/routes/log-export/workspace-allowlist.ts +1 -1
  356. package/src/runtime/routes/migration-routes.ts +5 -9
  357. package/src/runtime/routes/plugins-routes.ts +26 -0
  358. package/src/runtime/routes/ps-routes.ts +10 -8
  359. package/src/runtime/routes/retrospective-routes.ts +235 -0
  360. package/src/runtime/routes/runs-pagination.ts +75 -0
  361. package/src/runtime/routes/schedule-routes.ts +367 -59
  362. package/src/runtime/routes/sounds-config-routes.ts +239 -0
  363. package/src/runtime/routes/surface-action-routes.ts +84 -4
  364. package/src/runtime/routes/workflow-routes.test.ts +372 -0
  365. package/src/runtime/routes/workflow-routes.ts +363 -0
  366. package/src/runtime/routes/workspace-routes.test.ts +61 -1
  367. package/src/runtime/routes/workspace-routes.ts +26 -1
  368. package/src/runtime/services/__tests__/analyze-conversation.test.ts +38 -0
  369. package/src/runtime/services/analyze-conversation.ts +26 -13
  370. package/src/schedule/inference-profile.ts +28 -0
  371. package/src/schedule/schedule-store.ts +152 -4
  372. package/src/schedule/scheduler-types.ts +6 -0
  373. package/src/schedule/scheduler.ts +96 -0
  374. package/src/security/secret-allowlist.ts +1 -1
  375. package/src/skills/path-classifier.ts +1 -1
  376. package/src/tools/apps/executors.ts +23 -0
  377. package/src/tools/apps/resolve-app-id.ts +42 -0
  378. package/src/tools/browser/browser-execution.ts +9 -11
  379. package/src/tools/credentials/broker.ts +4 -4
  380. package/src/tools/credentials/vault.ts +26 -137
  381. package/src/tools/executor.ts +69 -0
  382. package/src/tools/flag-gated-tools.test.ts +76 -0
  383. package/src/tools/permission-checker.ts +8 -1
  384. package/src/tools/registry.ts +51 -0
  385. package/src/tools/schedule/create.ts +77 -1
  386. package/src/tools/schedule/list.ts +1 -0
  387. package/src/tools/schedule/update.ts +73 -1
  388. package/src/tools/skills/execute.ts +56 -0
  389. package/src/tools/terminal/shell.ts +1 -1
  390. package/src/tools/ui-surface/definitions.ts +91 -2
  391. package/src/tools/workflows/manage-workflows.ts +183 -0
  392. package/src/tools/workflows/run-workflow.test.ts +442 -0
  393. package/src/tools/workflows/run-workflow.ts +88 -0
  394. package/src/types/onboarding-context.ts +2 -0
  395. package/src/usage/attribution.ts +24 -0
  396. package/src/util/canonicalize-identity.ts +12 -3
  397. package/src/util/platform.ts +17 -17
  398. package/src/watcher/__tests__/engine.test.ts +24 -0
  399. package/src/watcher/__tests__/telemetry.test.ts +135 -0
  400. package/src/watcher/engine.ts +7 -0
  401. package/src/watcher/telemetry.ts +74 -0
  402. package/src/workflows/capabilities.test.ts +365 -0
  403. package/src/workflows/capabilities.ts +359 -0
  404. package/src/workflows/deterministic-stringify.ts +27 -0
  405. package/src/workflows/engine-integration.test.ts +656 -0
  406. package/src/workflows/engine.test.ts +1144 -0
  407. package/src/workflows/engine.ts +1078 -0
  408. package/src/workflows/fanout-load.test.ts +168 -0
  409. package/src/workflows/journal-store.test.ts +369 -0
  410. package/src/workflows/journal-store.ts +470 -0
  411. package/src/workflows/leaf-runner.test.ts +704 -0
  412. package/src/workflows/leaf-runner.ts +589 -0
  413. package/src/workflows/library.test.ts +134 -0
  414. package/src/workflows/library.ts +124 -0
  415. package/src/workflows/run-manager.test.ts +711 -0
  416. package/src/workflows/run-manager.ts +593 -0
  417. package/src/workflows/sandbox-escape.test.ts +339 -0
  418. package/src/workflows/sandbox.test.ts +251 -0
  419. package/src/workflows/sandbox.ts +447 -0
  420. package/src/workspace/adaptive-thinking-repair.ts +33 -11
  421. package/src/workspace/migrations/021-move-signals-to-workspace.ts +1 -1
  422. package/src/workspace/migrations/022-move-hooks-to-workspace.ts +1 -1
  423. package/src/workspace/migrations/026-backfill-install-meta.ts +1 -1
  424. package/src/workspace/migrations/030-seed-pkb-autoinject.ts +2 -1
  425. package/src/workspace/migrations/031-drop-user-md.ts +1 -4
  426. package/src/workspace/migrations/048-remove-workspace-hooks.ts +1 -1
  427. package/src/workspace/migrations/056-release-notes-inference-profile-reordering.ts +5 -2
  428. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +1 -1
  429. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +8 -2
  430. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +41 -14
  431. package/src/workspace/migrations/102-preserve-heartbeat-enabled-for-existing-workspaces.ts +69 -0
  432. package/src/workspace/migrations/103-upgrade-quality-profile-to-opus-4-8.ts +83 -0
  433. package/src/workspace/migrations/104-recheck-adaptive-thinking-model-implied-anthropic.ts +133 -0
  434. package/src/workspace/migrations/registry.ts +6 -0
  435. package/src/workspace/migrations/runner.ts +1 -1
  436. package/tsconfig.json +1 -1
  437. package/src/__tests__/guardian-action-copy-generator.test.ts +0 -200
  438. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -579
  439. package/src/__tests__/guardian-action-store.test.ts +0 -106
  440. package/src/daemon/guardian-action-generators.ts +0 -71
  441. package/src/memory/guardian-action-store.ts +0 -484
  442. package/src/runtime/guardian-action-grant-minter.ts +0 -150
@@ -98,8 +98,10 @@ describe("schedules command", () => {
98
98
  expect(schedules).toBeDefined();
99
99
  expect(schedules!.commands.map((command) => command.name())).toEqual([
100
100
  "list",
101
+ "get",
101
102
  "runs",
102
103
  "create",
104
+ "update",
103
105
  "enable",
104
106
  "disable",
105
107
  "cancel",
@@ -252,6 +254,125 @@ describe("schedules list", () => {
252
254
  });
253
255
  });
254
256
 
257
+ describe("schedules get", () => {
258
+ const scheduleFixture = {
259
+ id: "schedule-1",
260
+ name: "Heartbeat",
261
+ enabled: true,
262
+ syntax: "cron",
263
+ expression: "*/30 * * * *",
264
+ cronExpression: "*/30 * * * *",
265
+ timezone: "UTC",
266
+ message: "run heartbeat",
267
+ script: null,
268
+ nextRunAt: 1_778_800_000_000,
269
+ lastRunAt: 1_778_799_000_000,
270
+ lastStatus: "ok",
271
+ retryCount: 0,
272
+ maxRetries: 3,
273
+ retryBackoffMs: 60_000,
274
+ timeoutMs: null,
275
+ createdFromConversationId: "conv-abc",
276
+ description: "Authored heartbeat check",
277
+ cadenceDescription: "Every 30 minutes",
278
+ mode: "execute",
279
+ status: "active",
280
+ routingIntent: "all_channels",
281
+ reuseConversation: false,
282
+ wakeConversationId: null,
283
+ isOneShot: false,
284
+ };
285
+
286
+ test("calls getSchedule with the schedule ID path param", async () => {
287
+ mockIpcResult = { ok: true, result: { schedule: scheduleFixture } };
288
+
289
+ const { exitCode } = await runCommand(["schedules", "get", "schedule-1"]);
290
+
291
+ expect(exitCode).toBe(0);
292
+ expect(ipcCalls).toEqual([
293
+ {
294
+ method: "getSchedule",
295
+ params: { pathParams: { id: "schedule-1" } },
296
+ },
297
+ ]);
298
+ });
299
+
300
+ test("inspect alias resolves to the same getSchedule handler", async () => {
301
+ // GIVEN the daemon returns a schedule for the requested ID
302
+ mockIpcResult = { ok: true, result: { schedule: scheduleFixture } };
303
+
304
+ // WHEN the user invokes the `inspect` alias instead of `get`
305
+ const { exitCode } = await runCommand([
306
+ "schedules",
307
+ "inspect",
308
+ "schedule-1",
309
+ ]);
310
+
311
+ // THEN it calls the same getSchedule IPC method with the ID path param
312
+ expect(exitCode).toBe(0);
313
+ expect(ipcCalls).toEqual([
314
+ {
315
+ method: "getSchedule",
316
+ params: { pathParams: { id: "schedule-1" } },
317
+ },
318
+ ]);
319
+ // AND it renders the same human-readable detail view
320
+ expect(logLines.join("\n")).toContain("run heartbeat");
321
+ });
322
+
323
+ test("renders a detail view for human output", async () => {
324
+ mockIpcResult = { ok: true, result: { schedule: scheduleFixture } };
325
+
326
+ const { exitCode } = await runCommand(["schedules", "get", "schedule-1"]);
327
+
328
+ expect(exitCode).toBe(0);
329
+ const output = logLines.join("\n");
330
+ expect(output).toContain("ID:");
331
+ expect(output).toContain("schedule-1");
332
+ expect(output).toContain("Heartbeat");
333
+ expect(output).toContain("Authored heartbeat check");
334
+ expect(output).toContain("Every 30 minutes (UTC)");
335
+ expect(output).toContain("run heartbeat");
336
+ expect(output).toContain("all_channels");
337
+ expect(output).toContain("conv-abc");
338
+ });
339
+
340
+ test("emits JSON result when --json is set", async () => {
341
+ mockIpcResult = { ok: true, result: { schedule: scheduleFixture } };
342
+
343
+ const { stdout, exitCode } = await runCommand([
344
+ "schedules",
345
+ "get",
346
+ "schedule-1",
347
+ "--json",
348
+ ]);
349
+
350
+ expect(exitCode).toBe(0);
351
+ expect(JSON.parse(stdout)).toEqual({
352
+ schedule: expect.objectContaining({
353
+ id: "schedule-1",
354
+ name: "Heartbeat",
355
+ description: "Authored heartbeat check",
356
+ }),
357
+ });
358
+ expect(logLines).toEqual([]);
359
+ });
360
+
361
+ test("routes IPC failure through exitFromIpcResult", async () => {
362
+ mockIpcResult = { ok: false, error: "Schedule not found" };
363
+
364
+ const { exitCode } = await runCommand([
365
+ "schedules",
366
+ "get",
367
+ "missing-schedule",
368
+ ]);
369
+
370
+ expect(exitCode).toBe(10);
371
+ expect(exitFromIpcResultCalls).toEqual([mockIpcResult]);
372
+ expect(errorLines).toEqual([]);
373
+ });
374
+ });
375
+
255
376
  describe("schedules runs", () => {
256
377
  test("calls listScheduleRuns with the schedule ID path param", async () => {
257
378
  mockIpcResult = { ok: true, result: { runs: [] } };
@@ -343,10 +464,49 @@ describe("schedules runs", () => {
343
464
  expect(exitCode).toBe(0);
344
465
  expect(logLines.join("\n")).toContain("STATUS");
345
466
  expect(logLines.join("\n")).toContain("run-1");
346
- expect(logLines.join("\n")).toContain("2500ms");
467
+ expect(logLines.join("\n")).toContain("2.5s");
347
468
  expect(logLines.join("\n")).toContain("conversation-1");
348
469
  });
349
470
 
471
+ test("formats run durations into human-friendly units", async () => {
472
+ const durations = [
473
+ { ms: 450, expected: "450ms" },
474
+ { ms: 29_854, expected: "29.9s" },
475
+ { ms: 30_000, expected: "30s" },
476
+ { ms: 90_000, expected: "1m 30s" },
477
+ { ms: 300_000, expected: "5m" },
478
+ { ms: 3_600_000, expected: "1h" },
479
+ { ms: 8_100_000, expected: "2h 15m" },
480
+ { ms: 93_600_000, expected: "1d 2h" },
481
+ ];
482
+
483
+ mockIpcResult = {
484
+ ok: true,
485
+ result: {
486
+ runs: durations.map((d, i) => ({
487
+ id: `run-${i}`,
488
+ jobId: "schedule-1",
489
+ status: "ok",
490
+ startedAt: 1_778_799_000_000,
491
+ finishedAt: 1_778_799_000_000 + d.ms,
492
+ durationMs: d.ms,
493
+ output: "done",
494
+ error: null,
495
+ conversationId: `conversation-${i}`,
496
+ createdAt: 1_778_799_000_000,
497
+ })),
498
+ },
499
+ };
500
+
501
+ const { exitCode } = await runCommand(["schedules", "runs", "schedule-1"]);
502
+
503
+ expect(exitCode).toBe(0);
504
+ const output = logLines.join("\n");
505
+ for (const { expected } of durations) {
506
+ expect(output).toContain(expected);
507
+ }
508
+ });
509
+
350
510
  test("prints an empty message when no runs are found", async () => {
351
511
  mockIpcResult = { ok: true, result: { runs: [] } };
352
512
 
@@ -590,6 +750,275 @@ describe("schedules create", () => {
590
750
  });
591
751
  });
592
752
 
753
+ describe("schedules update", () => {
754
+ test("calls updateSchedule with only the provided flags", async () => {
755
+ mockIpcResult = { ok: true, result: { schedules: [] } };
756
+
757
+ const { exitCode } = await runCommand([
758
+ "schedules",
759
+ "update",
760
+ "schedule-1",
761
+ "--name",
762
+ "Renamed",
763
+ "--expression",
764
+ "0 9 * * MON-FRI",
765
+ "--timezone",
766
+ "America/New_York",
767
+ ]);
768
+
769
+ expect(exitCode).toBe(0);
770
+ expect(ipcCalls).toEqual([
771
+ {
772
+ method: "updateSchedule",
773
+ params: {
774
+ pathParams: { id: "schedule-1" },
775
+ body: {
776
+ name: "Renamed",
777
+ expression: "0 9 * * MON-FRI",
778
+ timezone: "America/New_York",
779
+ },
780
+ },
781
+ },
782
+ ]);
783
+ expect(logLines).toEqual(["Updated schedule: schedule-1"]);
784
+ });
785
+
786
+ test("errors when no update flags are provided", async () => {
787
+ const { exitCode } = await runCommand([
788
+ "schedules",
789
+ "update",
790
+ "schedule-1",
791
+ ]);
792
+
793
+ expect(exitCode).toBe(1);
794
+ expect(ipcCalls).toEqual([]);
795
+ expect(errorLines.join("\n")).toContain(
796
+ "At least one update flag is required",
797
+ );
798
+ });
799
+
800
+ test("parses numeric retry and timeout flags into numbers", async () => {
801
+ mockIpcResult = { ok: true, result: { schedules: [] } };
802
+
803
+ const { exitCode } = await runCommand([
804
+ "schedules",
805
+ "update",
806
+ "schedule-1",
807
+ "--max-retries",
808
+ "5",
809
+ "--retry-backoff-ms",
810
+ "30000",
811
+ "--timeout-ms",
812
+ "5000",
813
+ ]);
814
+
815
+ expect(exitCode).toBe(0);
816
+ expect(ipcCalls).toEqual([
817
+ {
818
+ method: "updateSchedule",
819
+ params: {
820
+ pathParams: { id: "schedule-1" },
821
+ body: { maxRetries: 5, retryBackoffMs: 30_000, timeoutMs: 5000 },
822
+ },
823
+ },
824
+ ]);
825
+ });
826
+
827
+ test("rejects a non-integer --max-retries", async () => {
828
+ const { exitCode } = await runCommand([
829
+ "schedules",
830
+ "update",
831
+ "schedule-1",
832
+ "--max-retries",
833
+ "lots",
834
+ ]);
835
+
836
+ expect(exitCode).toBe(1);
837
+ expect(ipcCalls).toEqual([]);
838
+ expect(errorLines.join("\n")).toContain("--max-retries must be an integer");
839
+ });
840
+
841
+ test("sends timeoutMs null with --clear-timeout", async () => {
842
+ mockIpcResult = { ok: true, result: { schedules: [] } };
843
+
844
+ const { exitCode } = await runCommand([
845
+ "schedules",
846
+ "update",
847
+ "schedule-1",
848
+ "--clear-timeout",
849
+ ]);
850
+
851
+ expect(exitCode).toBe(0);
852
+ expect(ipcCalls).toEqual([
853
+ {
854
+ method: "updateSchedule",
855
+ params: {
856
+ pathParams: { id: "schedule-1" },
857
+ body: { timeoutMs: null },
858
+ },
859
+ },
860
+ ]);
861
+ });
862
+
863
+ test("rejects --timeout-ms combined with --clear-timeout", async () => {
864
+ const { exitCode } = await runCommand([
865
+ "schedules",
866
+ "update",
867
+ "schedule-1",
868
+ "--timeout-ms",
869
+ "5000",
870
+ "--clear-timeout",
871
+ ]);
872
+
873
+ expect(exitCode).toBe(1);
874
+ expect(ipcCalls).toEqual([]);
875
+ expect(errorLines.join("\n")).toContain("mutually exclusive");
876
+ });
877
+
878
+ test("rejects --mode wake when the schedule has no wake conversation target", async () => {
879
+ mockIpcResult = {
880
+ ok: true,
881
+ result: { schedule: { wakeConversationId: null } },
882
+ };
883
+
884
+ const { exitCode } = await runCommand([
885
+ "schedules",
886
+ "update",
887
+ "schedule-1",
888
+ "--mode",
889
+ "wake",
890
+ ]);
891
+
892
+ expect(exitCode).toBe(1);
893
+ expect(ipcCalls).toEqual([
894
+ { method: "getSchedule", params: { pathParams: { id: "schedule-1" } } },
895
+ ]);
896
+ expect(errorLines.join("\n")).toContain("wake conversation target");
897
+ });
898
+
899
+ test("allows --mode wake when the schedule already has a wake target", async () => {
900
+ // The shared mock returns one shape for both IPC calls; satisfy the
901
+ // getSchedule guard and the update response renderer simultaneously.
902
+ mockIpcResult = {
903
+ ok: true,
904
+ result: {
905
+ schedule: { wakeConversationId: "conv-1" },
906
+ schedules: [],
907
+ },
908
+ };
909
+
910
+ const { exitCode } = await runCommand([
911
+ "schedules",
912
+ "update",
913
+ "schedule-1",
914
+ "--mode",
915
+ "wake",
916
+ ]);
917
+
918
+ expect(exitCode).toBe(0);
919
+ expect(ipcCalls).toHaveLength(2);
920
+ expect(ipcCalls[0].method).toBe("getSchedule");
921
+ expect(ipcCalls[1]).toEqual({
922
+ method: "updateSchedule",
923
+ params: {
924
+ pathParams: { id: "schedule-1" },
925
+ body: { mode: "wake" },
926
+ },
927
+ });
928
+ });
929
+
930
+ test("sends boolean false for negated flags", async () => {
931
+ mockIpcResult = { ok: true, result: { schedules: [] } };
932
+
933
+ const { exitCode } = await runCommand([
934
+ "schedules",
935
+ "update",
936
+ "schedule-1",
937
+ "--no-quiet",
938
+ "--no-reuse-conversation",
939
+ ]);
940
+
941
+ expect(exitCode).toBe(0);
942
+ expect(ipcCalls).toEqual([
943
+ {
944
+ method: "updateSchedule",
945
+ params: {
946
+ pathParams: { id: "schedule-1" },
947
+ body: { quiet: false, reuseConversation: false },
948
+ },
949
+ },
950
+ ]);
951
+ });
952
+
953
+ test("emits JSON result when --json is set", async () => {
954
+ mockIpcResult = {
955
+ ok: true,
956
+ result: {
957
+ schedules: [
958
+ {
959
+ id: "schedule-1",
960
+ name: "Renamed",
961
+ enabled: true,
962
+ syntax: "cron",
963
+ expression: "0 9 * * MON-FRI",
964
+ cronExpression: "0 9 * * MON-FRI",
965
+ timezone: "America/New_York",
966
+ message: "run heartbeat",
967
+ script: null,
968
+ nextRunAt: 1_778_800_000_000,
969
+ lastRunAt: null,
970
+ lastStatus: "ok",
971
+ retryCount: 0,
972
+ maxRetries: 3,
973
+ retryBackoffMs: 60_000,
974
+ description: "Authored heartbeat check",
975
+ cadenceDescription: "At 9:00 AM, Monday through Friday",
976
+ mode: "execute",
977
+ status: "active",
978
+ routingIntent: "all_channels",
979
+ reuseConversation: false,
980
+ wakeConversationId: null,
981
+ isOneShot: false,
982
+ },
983
+ ],
984
+ },
985
+ };
986
+
987
+ const { stdout, exitCode } = await runCommand([
988
+ "schedules",
989
+ "update",
990
+ "schedule-1",
991
+ "--name",
992
+ "Renamed",
993
+ "--json",
994
+ ]);
995
+
996
+ expect(exitCode).toBe(0);
997
+ expect(JSON.parse(stdout)).toEqual({
998
+ schedules: [
999
+ expect.objectContaining({ id: "schedule-1", name: "Renamed" }),
1000
+ ],
1001
+ });
1002
+ expect(logLines).toEqual([]);
1003
+ });
1004
+
1005
+ test("routes IPC failure through exitFromIpcResult", async () => {
1006
+ mockIpcResult = { ok: false, error: "Schedule not found" };
1007
+
1008
+ const { exitCode } = await runCommand([
1009
+ "schedules",
1010
+ "update",
1011
+ "missing-schedule",
1012
+ "--name",
1013
+ "Renamed",
1014
+ ]);
1015
+
1016
+ expect(exitCode).toBe(10);
1017
+ expect(exitFromIpcResultCalls).toEqual([mockIpcResult]);
1018
+ expect(errorLines).toEqual([]);
1019
+ });
1020
+ });
1021
+
593
1022
  describe("schedules enable/disable", () => {
594
1023
  test("enable calls toggleSchedule with enabled true", async () => {
595
1024
  mockIpcResult = { ok: true, result: { schedules: [] } };
@@ -5,6 +5,7 @@ import type { CredentialPromptResult } from "../../runtime/routes/credential-pro
5
5
  import { registerCommand } from "../lib/register-command.js";
6
6
  import { log } from "../logger.js";
7
7
  import { shouldOutputJson, writeOutput } from "../output.js";
8
+ import { tryResolveConversationId } from "../utils/conversation-id.js";
8
9
 
9
10
  // ---------------------------------------------------------------------------
10
11
  // Format-aware error output
@@ -114,8 +115,7 @@ export function registerCredentialsCommand(program: Command): void {
114
115
  description:
115
116
  "Manage credentials in the encrypted vault (API keys, tokens, passwords)",
116
117
  build: (credential) => {
117
- credential
118
- .option("--json", "Machine-readable compact JSON output");
118
+ credential.option("--json", "Machine-readable compact JSON output");
119
119
 
120
120
  credential.addHelpText(
121
121
  "after",
@@ -224,9 +224,7 @@ Examples:
224
224
 
225
225
  credential
226
226
  .command("status")
227
- .description(
228
- "Show the active credential backend and its configuration",
229
- )
227
+ .description("Show the active credential backend and its configuration")
230
228
  .addHelpText(
231
229
  "after",
232
230
  `
@@ -248,9 +246,8 @@ Examples:
248
246
  $ assistant credentials status --json`,
249
247
  )
250
248
  .action(async (_opts: Record<string, unknown>, cmd: Command) => {
251
- const r = await cliIpcCall<CredentialsStatusResponse>(
252
- "credentials_status",
253
- );
249
+ const r =
250
+ await cliIpcCall<CredentialsStatusResponse>("credentials_status");
254
251
  if (!r.ok) {
255
252
  return exitFromIpcResult(
256
253
  r as { ok: false; error?: string; statusCode?: number },
@@ -286,7 +283,10 @@ Examples:
286
283
  credential
287
284
  .command("set <value>")
288
285
  .description("Store a secret and create or update its metadata")
289
- .requiredOption("--service <service>", "Service namespace (e.g. google)")
286
+ .requiredOption(
287
+ "--service <service>",
288
+ "Service namespace (e.g. google)",
289
+ )
290
290
  .requiredOption("--field <field>", "Field name (e.g. client_secret)")
291
291
  .option("--label <label>", 'Human-friendly label (e.g. "prod", "work")')
292
292
  .option(
@@ -345,7 +345,8 @@ Examples:
345
345
  if (!r.ok) {
346
346
  writeError(
347
347
  cmd,
348
- r.error ?? `Failed to store credential ${opts.service}:${opts.field}`,
348
+ r.error ??
349
+ `Failed to store credential ${opts.service}:${opts.field}`,
349
350
  );
350
351
  process.exitCode = 1;
351
352
  return;
@@ -397,7 +398,8 @@ Examples:
397
398
  if (!r.ok) {
398
399
  writeError(
399
400
  cmd,
400
- r.error ?? `Failed to delete credential ${opts.service}:${opts.field}`,
401
+ r.error ??
402
+ `Failed to delete credential ${opts.service}:${opts.field}`,
401
403
  );
402
404
  process.exitCode = 1;
403
405
  return;
@@ -410,9 +412,7 @@ Examples:
410
412
  field: opts.field,
411
413
  });
412
414
  } else {
413
- log.info(
414
- `Deleted credential ${opts.service}:${opts.field}`,
415
- );
415
+ log.info(`Deleted credential ${opts.service}:${opts.field}`);
416
416
  }
417
417
  },
418
418
  );
@@ -588,6 +588,10 @@ Examples:
588
588
  .requiredOption("--label <label>", "Display label for the prompt UI")
589
589
  .option("--description <description>", "Context shown in the prompt UI")
590
590
  .option("--placeholder <placeholder>", "Placeholder text for the input")
591
+ .option(
592
+ "--usage-description <description>",
593
+ "Human-readable description of intended usage, stored in credential metadata and shown as the prompt's purpose",
594
+ )
591
595
  .option(
592
596
  "--allowed-domains <domains>",
593
597
  "Comma-separated domains where this credential may be used",
@@ -613,6 +617,7 @@ Requires the assistant to be running with at least one connected client.
613
617
  Examples:
614
618
  $ assistant credentials prompt --service sentry --field auth_token \\
615
619
  --label "Sentry Auth Token" --placeholder "sntrys_..." \\
620
+ --usage-description "Read Sentry issues and events" \\
616
621
  --allowed-domains "sentry.io" \\
617
622
  --injection-templates '[{"hostPattern":"sentry.io","injectionType":"header","headerName":"Authorization","valuePrefix":"Bearer "}]'`,
618
623
  )
@@ -624,6 +629,7 @@ Examples:
624
629
  label: string;
625
630
  description?: string;
626
631
  placeholder?: string;
632
+ usageDescription?: string;
627
633
  allowedDomains?: string;
628
634
  allowedTools?: string;
629
635
  injectionTemplates?: string;
@@ -663,9 +669,11 @@ Examples:
663
669
  label: opts.label,
664
670
  description: opts.description,
665
671
  placeholder: opts.placeholder,
672
+ usageDescription: opts.usageDescription,
666
673
  allowedDomains,
667
674
  allowedTools,
668
675
  injectionTemplates,
676
+ conversationId: tryResolveConversationId(),
669
677
  },
670
678
  },
671
679
  { timeoutMs: PROMPT_TIMEOUT_MS },
@@ -681,22 +689,18 @@ Examples:
681
689
  }
682
690
 
683
691
  if (!ipc.result?.ok) {
684
- writeError(
685
- cmd,
686
- ipc.result?.error ?? "Credential prompt failed",
687
- );
692
+ writeError(cmd, ipc.result?.error ?? "Credential prompt failed");
688
693
  process.exitCode = 1;
689
694
  return;
690
695
  }
691
696
 
692
697
  if (shouldOutputJson(cmd)) {
693
- writeOutput(cmd, {
694
- ok: true,
695
- service: opts.service,
696
- field: opts.field,
697
- });
698
+ writeOutput(cmd, ipc.result);
698
699
  } else {
699
- log.info(`Stored credential ${opts.service}:${opts.field}`);
700
+ log.info(
701
+ ipc.result.message ??
702
+ `Stored credential ${opts.service}:${opts.field}`,
703
+ );
700
704
  }
701
705
  },
702
706
  );
@@ -66,10 +66,13 @@ Modes:
66
66
  managed — Uses platform-managed credentials (requires login to Vellum).
67
67
  your-own — Uses your own Gemini or OpenAI API key depending on the configured model.
68
68
 
69
- Supported models:
70
- gemini-3.1-flash-image-preview (default)
71
- gemini-3-pro-image-preview
72
- gpt-image-2
69
+ Supported models: pass a tier alias, the assistant resolves it to the
70
+ current model for that tier.
71
+ fast (default) quickest, good quality
72
+ quality higher fidelity, slower
73
+ openai OpenAI's model
74
+ A concrete model ID is also accepted; unknown values return an error
75
+ listing the currently available models.
73
76
 
74
77
  Examples:
75
78
  $ assistant image-generation generate --prompt "A sunset over the ocean"
@@ -113,8 +116,8 @@ Examples:
113
116
  $ assistant image-generation generate --prompt "A mountain landscape at dawn"
114
117
  $ assistant image-generation generate --prompt "Make it darker" --mode edit --source input.png
115
118
  $ assistant image-generation generate --prompt "Logo variations" --variants 4 --output-dir ./logos
116
- $ assistant image-generation generate --prompt "A robot" --model gemini-3-pro-image-preview --json
117
- $ assistant image-generation generate --prompt "A robot" --model gpt-image-2 --json`,
119
+ $ assistant image-generation generate --prompt "A robot" --model quality --json
120
+ $ assistant image-generation generate --prompt "A robot" --model openai --json`,
118
121
  );
119
122
 
120
123
  generate.action(async (opts) => {
@@ -166,7 +169,10 @@ Examples:
166
169
  file.type !== "application/octet-stream"
167
170
  ? file.type
168
171
  : mimeForExtension(filePath);
169
- validImages.push({ mimeType, dataBase64: buffer.toString("base64") });
172
+ validImages.push({
173
+ mimeType,
174
+ dataBase64: buffer.toString("base64"),
175
+ });
170
176
  } catch (err) {
171
177
  errors.push(
172
178
  `Could not read ${filePath}: ${(err as Error).message}`,
@@ -191,7 +197,11 @@ Examples:
191
197
 
192
198
  // Call daemon via IPC
193
199
  const r = await cliIpcCall<{
194
- images: Array<{ mimeType: string; dataBase64: string; title?: string }>;
200
+ images: Array<{
201
+ mimeType: string;
202
+ dataBase64: string;
203
+ title?: string;
204
+ }>;
195
205
  text?: string;
196
206
  resolvedModel: string;
197
207
  }>("image_generation_generate", {
@@ -204,7 +214,11 @@ Examples:
204
214
  },
205
215
  });
206
216
 
207
- if (!r.ok) return exitFromIpcResult({ ok: false, error: r.error, statusCode: r.statusCode }, generate);
217
+ if (!r.ok)
218
+ return exitFromIpcResult(
219
+ { ok: false, error: r.error, statusCode: r.statusCode },
220
+ generate,
221
+ );
208
222
 
209
223
  // Write images to disk (stays in CLI)
210
224
  if (!existsSync(outputDir)) {
@@ -548,7 +548,7 @@ Examples:
548
548
  .addHelpText(
549
549
  "after",
550
550
  `
551
- Reads the home feed at ~/.vellum/workspace/data/home-feed.json — the
551
+ Reads the home feed at $VELLUM_WORKSPACE_DIR/data/home-feed.json — the
552
552
  user's notification inbox. Items are ordered by priority then recency,
553
553
  matching what the user sees in the macOS Home page. The home feed covers
554
554
  background/async notifications mirrored from the unified pipeline;