@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
@@ -12,7 +12,9 @@
12
12
  import { v4 as uuid } from "uuid";
13
13
 
14
14
  import { getConversation } from "../memory/conversation-crud.js";
15
+ import type { ApprovalUIMetadata } from "../runtime/channel-approval-types.js";
15
16
  import { getLogger } from "../util/logger.js";
17
+ import { buildAccessRequestContractText } from "./access-request-copy.js";
16
18
  import { isGuardianSensitiveEvent } from "./adapters/macos.js";
17
19
  import { pairDeliveryWithConversation } from "./conversation-pairing.js";
18
20
  import { composeFallbackCopy } from "./copy-composer.js";
@@ -22,6 +24,11 @@ import {
22
24
  updateDeliveryStatus,
23
25
  } from "./deliveries-store.js";
24
26
  import { resolveDestinations } from "./destination-resolver.js";
27
+ import {
28
+ parseGuardianQuestionPayload,
29
+ resolveGuardianInstructionModeFromPayload,
30
+ } from "./guardian-question-mode.js";
31
+ import { nonEmpty } from "./notification-utils.js";
25
32
  import type { NotificationSignal } from "./signal.js";
26
33
  import type {
27
34
  ChannelAdapter,
@@ -35,6 +42,71 @@ import type {
35
42
 
36
43
  const log = getLogger("notif-broadcaster");
37
44
 
45
+ const APPROVAL_ACTIONS: ApprovalUIMetadata["actions"] = [
46
+ { id: "approve_once", label: "Approve once" },
47
+ { id: "reject", label: "Reject" },
48
+ ];
49
+
50
+ /**
51
+ * Resolve structured approval context from a notification signal.
52
+ * Returns `undefined` when the signal does not represent an approval flow.
53
+ */
54
+ function resolveApprovalContext(
55
+ signal: NotificationSignal,
56
+ ): ApprovalUIMetadata | undefined {
57
+ const payload = signal.contextPayload;
58
+ if (!payload) return undefined;
59
+
60
+ if (signal.sourceEventName === "ingress.access_request") {
61
+ const requestId = nonEmpty(
62
+ typeof payload.requestId === "string" ? payload.requestId : undefined,
63
+ );
64
+ if (!requestId) return undefined;
65
+ return {
66
+ requestId,
67
+ actions: APPROVAL_ACTIONS,
68
+ plainTextFallback: buildAccessRequestContractText(payload),
69
+ };
70
+ }
71
+
72
+ if (signal.sourceEventName === "guardian.question") {
73
+ const parsed = parseGuardianQuestionPayload(payload);
74
+ if (!parsed) return undefined;
75
+ const { mode } = resolveGuardianInstructionModeFromPayload(parsed);
76
+ if (mode !== "approval") return undefined;
77
+ const requestId = nonEmpty(parsed.requestId);
78
+ if (!requestId) return undefined;
79
+
80
+ // Extract tool context so channel adapters can render structured
81
+ // approval cards without re-parsing contextPayload.
82
+ let toolName: string | undefined;
83
+ if (
84
+ parsed.requestKind === "tool_approval" ||
85
+ parsed.requestKind === "tool_grant_request"
86
+ ) {
87
+ toolName = nonEmpty(parsed.toolName);
88
+ } else if (parsed.requestKind === "pending_question") {
89
+ toolName = nonEmpty(parsed.toolName);
90
+ }
91
+
92
+ return {
93
+ requestId,
94
+ actions: APPROVAL_ACTIONS,
95
+ plainTextFallback: `Reply "${parsed.requestCode?.toUpperCase() ?? requestId} approve" or "${parsed.requestCode?.toUpperCase() ?? requestId} reject"`,
96
+ permissionDetails: toolName
97
+ ? {
98
+ toolName,
99
+ riskLevel: "medium",
100
+ toolInput: {},
101
+ requesterIdentifier: nonEmpty(parsed.requesterIdentifier),
102
+ }
103
+ : undefined,
104
+ };
105
+ }
106
+
107
+ return undefined;
108
+ }
109
+
38
110
  /** Callback invoked immediately when a vellum notification conversation is created. */
39
111
  export interface ConversationCreatedInfo {
40
112
  conversationId: string;
@@ -108,6 +180,7 @@ export class NotificationBroadcaster {
108
180
  Record<NotificationChannel, RenderedChannelCopy>
109
181
  > | null = null;
110
182
 
183
+ const approvalContext = resolveApprovalContext(signal);
111
184
  const results: NotificationDeliveryResult[] = [];
112
185
 
113
186
  for (const channel of orderedChannels) {
@@ -337,6 +410,7 @@ export class NotificationBroadcaster {
337
410
  deepLinkTarget,
338
411
  contextPayload: signal.contextPayload,
339
412
  urgency: signal.attentionHints.urgency,
413
+ approvalContext,
340
414
  };
341
415
 
342
416
  // Compute conversation decision audit fields for the delivery record
@@ -146,12 +146,14 @@ export async function pairDeliveryWithConversation(
146
146
  signal.conversationMetadata?.conversationType ??
147
147
  (strategy === "start_new_conversation" ? "standard" : "background");
148
148
 
149
- // Prefer model-provided conversationSeedMessage when present and sane;
150
- // fall back to the runtime composer which adapts verbosity to the
151
- // delivery surface (vellum/macos = richer, telegram = compact).
152
- const messageContent = isConversationSeedSane(copy.conversationSeedMessage)
153
- ? copy.conversationSeedMessage
154
- : composeConversationSeed(signal, channel, copy);
149
+ // Structured content blocks take precedence they enable Surface-based
150
+ // rendering in the web/macOS/iOS apps (e.g. a card widget instead of
151
+ // plain text). Falls back to model-provided seed or runtime composer.
152
+ const messageContent = copy.seedContentBlocks
153
+ ? JSON.stringify(copy.seedContentBlocks)
154
+ : isConversationSeedSane(copy.conversationSeedMessage)
155
+ ? copy.conversationSeedMessage
156
+ : composeConversationSeed(signal, channel, copy);
155
157
 
156
158
  // Attempt to reuse an existing conversation when the model requests it
157
159
  if (conversationAction?.action === "reuse_existing") {
@@ -11,16 +11,24 @@
11
11
 
12
12
  import {
13
13
  buildAccessRequestContractText,
14
- sanitizeIdentityField,
14
+ buildAccessRequestSeedContentBlocks,
15
15
  } from "./access-request-copy.js";
16
16
  import {
17
17
  buildGuardianRequestCodeInstruction,
18
+ parseGuardianQuestionPayload,
19
+ resolveGuardianInstructionModeFromPayload,
18
20
  resolveGuardianQuestionInstructionMode,
19
21
  } from "./guardian-question-mode.js";
22
+ import {
23
+ nonEmpty,
24
+ readPayloadString,
25
+ sanitizeIdentityField,
26
+ } from "./notification-utils.js";
20
27
  import type {
21
28
  NotificationSignal,
22
29
  NotificationSourceEventName,
23
30
  } from "./signal.js";
31
+ import { buildToolApprovalSeedContentBlocks } from "./tool-approval-copy.js";
24
32
  import type { NotificationChannel, RenderedChannelCopy } from "./types.js";
25
33
 
26
34
  type CopyTemplate = (payload: Record<string, unknown>) => RenderedChannelCopy;
@@ -30,26 +38,6 @@ function str(value: unknown, fallback: string): string {
30
38
  return fallback;
31
39
  }
32
40
 
33
- export function nonEmpty(value: string | undefined): string | undefined {
34
- if (typeof value !== "string") return undefined;
35
- const trimmed = value.trim();
36
- return trimmed.length > 0 ? trimmed : undefined;
37
- }
38
-
39
- /**
40
- * Safely read a string property from an unknown-typed payload object.
41
- * Returns `undefined` when the payload is falsy, not an object, or the
42
- * key does not hold a string value.
43
- */
44
- export function readPayloadString(
45
- payload: unknown,
46
- key: string,
47
- ): string | undefined {
48
- if (!payload || typeof payload !== "object") return undefined;
49
- const value = (payload as Record<string, unknown>)[key];
50
- return typeof value === "string" ? value : undefined;
51
- }
52
-
53
41
  /**
54
42
  * Derive a short notification title from a message body. Trims to the
55
43
  * first sentence terminator when present, then caps the result at
@@ -76,25 +64,41 @@ const TEMPLATES: Partial<Record<NotificationSourceEventName, CopyTemplate>> = {
76
64
  payload.questionText,
77
65
  "A guardian question needs your attention",
78
66
  );
79
- const requestCode = nonEmpty(
80
- typeof payload.requestCode === "string" ? payload.requestCode : undefined,
81
- );
67
+
68
+ // Parse once with Zod and reuse the typed payload downstream.
69
+ const parsed = parseGuardianQuestionPayload(payload);
82
70
 
83
71
  // For tool_grant_request, the questionText already includes requester name + input summary.
84
72
  // Use it directly as the conversation seed to avoid LLM-generated filler.
85
- const isToolGrant = payload.requestKind === "tool_grant_request";
73
+ const isToolGrant = parsed?.requestKind === "tool_grant_request";
86
74
  const conversationSeedMessage = isToolGrant ? question : undefined;
87
75
 
76
+ const seedContentBlocks =
77
+ (parsed
78
+ ? buildToolApprovalSeedContentBlocks(parsed)
79
+ : buildToolApprovalSeedContentBlocks(payload)) ?? undefined;
80
+
81
+ const requestCode = parsed
82
+ ? nonEmpty(parsed.requestCode)
83
+ : nonEmpty(
84
+ typeof payload.requestCode === "string"
85
+ ? payload.requestCode
86
+ : undefined,
87
+ );
88
+
88
89
  if (!requestCode) {
89
90
  return {
90
91
  title: "Guardian Question",
91
92
  body: question,
92
93
  conversationSeedMessage,
94
+ seedContentBlocks,
93
95
  };
94
96
  }
95
97
 
96
98
  const normalizedCode = requestCode.toUpperCase();
97
- const modeResolution = resolveGuardianQuestionInstructionMode(payload);
99
+ const modeResolution = parsed
100
+ ? resolveGuardianInstructionModeFromPayload(parsed)
101
+ : resolveGuardianQuestionInstructionMode(payload);
98
102
  const instruction = buildGuardianRequestCodeInstruction(
99
103
  normalizedCode,
100
104
  modeResolution.mode,
@@ -103,6 +107,7 @@ const TEMPLATES: Partial<Record<NotificationSourceEventName, CopyTemplate>> = {
103
107
  title: "Guardian Question",
104
108
  body: `${question}\n\n${instruction}`,
105
109
  conversationSeedMessage,
110
+ seedContentBlocks,
106
111
  };
107
112
  },
108
113
 
@@ -118,6 +123,7 @@ const TEMPLATES: Partial<Record<NotificationSourceEventName, CopyTemplate>> = {
118
123
  "ingress.access_request": (payload) => ({
119
124
  title: "Access Request",
120
125
  body: buildAccessRequestContractText(payload),
126
+ seedContentBlocks: buildAccessRequestSeedContentBlocks(payload),
121
127
  }),
122
128
 
123
129
  "ingress.access_request.callback_handoff": (payload) => {
@@ -26,6 +26,7 @@ import { truncate } from "../util/truncate.js";
26
26
  import {
27
27
  buildAccessRequestContractText,
28
28
  buildAccessRequestInviteDirective,
29
+ buildAccessRequestSeedContentBlocks,
29
30
  hasAccessRequestInstructions,
30
31
  hasInviteFlowDirective,
31
32
  } from "./access-request-copy.js";
@@ -34,12 +35,7 @@ import {
34
35
  type ConversationCandidateSet,
35
36
  serializeCandidatesForPrompt,
36
37
  } from "./conversation-candidates.js";
37
- import {
38
- composeFallbackCopy,
39
- deriveTitle,
40
- nonEmpty,
41
- readPayloadString,
42
- } from "./copy-composer.js";
38
+ import { composeFallbackCopy, deriveTitle } from "./copy-composer.js";
43
39
  import { createDecision } from "./decisions-store.js";
44
40
  import {
45
41
  buildGuardianRequestCodeInstruction,
@@ -47,8 +43,10 @@ import {
47
43
  resolveGuardianQuestionInstructionMode,
48
44
  stripConflictingGuardianRequestInstructions,
49
45
  } from "./guardian-question-mode.js";
46
+ import { nonEmpty, readPayloadString } from "./notification-utils.js";
50
47
  import { getPreferenceSummary } from "./preference-summary.js";
51
48
  import type { NotificationSignal, RoutingIntent } from "./signal.js";
49
+ import { buildToolApprovalSeedContentBlocks } from "./tool-approval-copy.js";
52
50
  import type {
53
51
  ConversationAction,
54
52
  NotificationChannel,
@@ -611,6 +609,49 @@ function enforceGuardianRequestCode(
611
609
  };
612
610
  }
613
611
 
612
+ /**
613
+ * Inject seedContentBlocks into every channel's copy when not already present.
614
+ * Used by both tool-approval and access-request guards to ensure Surface cards
615
+ * render on all decision paths (LLM, assistant_tool, fallback).
616
+ */
617
+ function ensureSeedContentBlocks(
618
+ decision: NotificationDecision,
619
+ blocks: unknown[] | null | undefined,
620
+ ): NotificationDecision {
621
+ if (!blocks) return decision;
622
+
623
+ const nextCopy: Partial<Record<NotificationChannel, RenderedChannelCopy>> = {
624
+ ...decision.renderedCopy,
625
+ };
626
+ for (const channel of Object.keys(nextCopy) as NotificationChannel[]) {
627
+ const copy = nextCopy[channel];
628
+ if (!copy) continue;
629
+ if (!copy.seedContentBlocks) {
630
+ nextCopy[channel] = { ...copy, seedContentBlocks: blocks };
631
+ }
632
+ }
633
+
634
+ return {
635
+ ...decision,
636
+ renderedCopy: nextCopy,
637
+ };
638
+ }
639
+
640
+ /**
641
+ * Tool-approval and tool-grant notifications need a Surface card with
642
+ * Approve/Reject buttons on all decision paths.
643
+ */
644
+ function enforceToolApprovalSeedBlocks(
645
+ decision: NotificationDecision,
646
+ signal: NotificationSignal,
647
+ ): NotificationDecision {
648
+ if (signal.sourceEventName !== "guardian.question") return decision;
649
+ return ensureSeedContentBlocks(
650
+ decision,
651
+ buildToolApprovalSeedContentBlocks(signal.contextPayload),
652
+ );
653
+ }
654
+
614
655
  /**
615
656
  * Access-request notifications require deterministic instruction elements:
616
657
  * - Request-code approve/reject directive (when requestCode is present)
@@ -665,10 +706,18 @@ function enforceAccessRequestInstructions(
665
706
  }
666
707
  }
667
708
 
668
- return {
709
+ let result: NotificationDecision = {
669
710
  ...decision,
670
711
  renderedCopy: nextCopy,
671
712
  };
713
+
714
+ // Ensure seedContentBlocks on all paths (LLM, assistant_tool, fallback).
715
+ result = ensureSeedContentBlocks(
716
+ result,
717
+ buildAccessRequestSeedContentBlocks(signal.contextPayload),
718
+ );
719
+
720
+ return result;
672
721
  }
673
722
 
674
723
  function ensureAccessRequestInstructionsInCopy(
@@ -833,6 +882,7 @@ export async function evaluateSignal(
833
882
  ...(deepLinkTarget ? { deepLinkTarget } : {}),
834
883
  };
835
884
  decision = enforceGuardianRequestCode(decision, signal);
885
+ decision = enforceToolApprovalSeedBlocks(decision, signal);
836
886
  decision = enforceAccessRequestInstructions(decision, signal);
837
887
  decision = enforceGuardianCallConversationAffinity(decision, signal);
838
888
  decision = enforceConversationAffinity(
@@ -850,6 +900,7 @@ export async function evaluateSignal(
850
900
  );
851
901
  let decision = buildFallbackDecision(signal, availableChannels);
852
902
  decision = enforceGuardianRequestCode(decision, signal);
903
+ decision = enforceToolApprovalSeedBlocks(decision, signal);
853
904
  decision = enforceAccessRequestInstructions(decision, signal);
854
905
  decision = enforceGuardianCallConversationAffinity(decision, signal);
855
906
  decision = enforceConversationAffinity(
@@ -879,6 +930,7 @@ export async function evaluateSignal(
879
930
  }
880
931
 
881
932
  decision = enforceGuardianRequestCode(decision, signal);
933
+ decision = enforceToolApprovalSeedBlocks(decision, signal);
882
934
  decision = enforceAccessRequestInstructions(decision, signal);
883
935
  decision = enforceGuardianCallConversationAffinity(decision, signal);
884
936
  decision = enforceConversationAffinity(