@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
@@ -0,0 +1,408 @@
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ // These tests exercise the PATCH-side `workflowName` validation, which only
4
+ // runs once the `workflows` feature flag is ON (the flag gate short-circuits
5
+ // first when it is off). Mock the flag resolver to ON so the validation path is
6
+ // reachable; the sibling schedule-routes.test.ts keeps the flag OFF and asserts
7
+ // the flag-gate behavior, so the two files do not conflict.
8
+ mock.module("../util/logger.js", () => ({
9
+ getLogger: () =>
10
+ new Proxy({} as Record<string, unknown>, {
11
+ get: () => () => {},
12
+ }),
13
+ }));
14
+
15
+ mock.module("../config/assistant-feature-flags.js", () => ({
16
+ isAssistantFeatureFlagEnabled: (key: string) => key === "workflows",
17
+ getAssistantFeatureFlagValue: (key: string) => key === "workflows",
18
+ }));
19
+
20
+ mock.module("../config/loader.js", () => ({
21
+ getConfig: () => ({}),
22
+ invalidateConfigCache: () => {},
23
+ loadRawConfig: () => ({}),
24
+ saveRawConfig: () => {},
25
+ }));
26
+
27
+ // Capture workflow-mode run-now dispatch. `handleRunScheduleNow`'s workflow
28
+ // branch calls `getWorkflowRunManager().start(...)`; stub the singleton so the
29
+ // trigger is observable without spinning up the real engine.
30
+ const workflowStartCalls: Array<Record<string, unknown>> = [];
31
+ mock.module("../workflows/run-manager.js", () => ({
32
+ getWorkflowRunManager: () => ({
33
+ start: (opts: Record<string, unknown>) => {
34
+ workflowStartCalls.push(opts);
35
+ return { runId: "wf-run-1" };
36
+ },
37
+ }),
38
+ }));
39
+
40
+ // Control the tool-registry readiness gate the run-now workflow branch checks
41
+ // before launching. Defaults to ready; the boot-race test flips it. Only the
42
+ // schedule route consumes registry in this test's graph, so a minimal mock
43
+ // suffices (mirrors task-scheduler.test.ts).
44
+ let coreToolsReady = true;
45
+ mock.module("../tools/registry.js", () => ({
46
+ areCoreToolsInitialized: () => coreToolsReady,
47
+ }));
48
+
49
+ import { getDb } from "../memory/db-connection.js";
50
+ import { initializeDb } from "../memory/db-init.js";
51
+ import {
52
+ BadRequestError,
53
+ ServiceUnavailableError,
54
+ } from "../runtime/routes/errors.js";
55
+ import { ROUTES as SCHEDULE_ROUTES } from "../runtime/routes/schedule-routes.js";
56
+ import type { RouteDefinition } from "../runtime/routes/types.js";
57
+ import {
58
+ createSchedule,
59
+ getScheduleRuns,
60
+ listSchedules,
61
+ } from "../schedule/schedule-store.js";
62
+
63
+ initializeDb();
64
+
65
+ function clearTables(): void {
66
+ const db = getDb();
67
+ db.run("DELETE FROM cron_runs");
68
+ db.run("DELETE FROM cron_jobs");
69
+ }
70
+
71
+ function patchRoute(): RouteDefinition {
72
+ const route = SCHEDULE_ROUTES.find(
73
+ (r) => r.endpoint === "schedules/:id" && r.method === "PATCH",
74
+ );
75
+ if (!route) throw new Error("PATCH schedules/:id route not found");
76
+ return route;
77
+ }
78
+
79
+ function createRoute(): RouteDefinition {
80
+ const route = SCHEDULE_ROUTES.find(
81
+ (r) => r.endpoint === "schedules" && r.method === "POST",
82
+ );
83
+ if (!route) throw new Error("POST schedules route not found");
84
+ return route;
85
+ }
86
+
87
+ function runNowRoute(): RouteDefinition {
88
+ const route = SCHEDULE_ROUTES.find(
89
+ (r) => r.endpoint === "schedules/:id/run" && r.method === "POST",
90
+ );
91
+ if (!route) throw new Error("POST schedules/:id/run route not found");
92
+ return route;
93
+ }
94
+
95
+ describe("PATCH /schedules/:id — workflow-mode name validation", () => {
96
+ beforeEach(clearTables);
97
+
98
+ test("rejects switching mode to workflow without a workflowName (flag on)", () => {
99
+ const schedule = createSchedule({
100
+ name: "Plain execute",
101
+ cronExpression: "0 9 * * *",
102
+ message: "hi",
103
+ syntax: "cron",
104
+ });
105
+
106
+ expect(() =>
107
+ patchRoute().handler({
108
+ pathParams: { id: schedule.id },
109
+ body: { mode: "workflow" },
110
+ }),
111
+ ).toThrow("workflowName is required");
112
+
113
+ // The schedule must stay in its prior mode — the wedge-prone nameless
114
+ // workflow row was never persisted.
115
+ expect(listSchedules()[0].mode).toBe("execute");
116
+ });
117
+
118
+ test("rejects switching to workflow with a blank/whitespace workflowName", () => {
119
+ const schedule = createSchedule({
120
+ name: "Plain execute",
121
+ cronExpression: "0 9 * * *",
122
+ message: "hi",
123
+ syntax: "cron",
124
+ });
125
+
126
+ expect(() =>
127
+ patchRoute().handler({
128
+ pathParams: { id: schedule.id },
129
+ body: { mode: "workflow", workflowName: " " },
130
+ }),
131
+ ).toThrow("workflowName is required");
132
+ expect(listSchedules()[0].mode).toBe("execute");
133
+ });
134
+
135
+ test("rejects clearing the workflowName on an already-workflow schedule", () => {
136
+ // An existing workflow-mode schedule (created via the store, which is not
137
+ // flag-gated). PATCH does not touch `mode`, so the resulting mode is still
138
+ // `workflow` and a cleared name must be rejected.
139
+ const schedule = createSchedule({
140
+ name: "Workflow schedule",
141
+ cronExpression: "0 9 * * *",
142
+ message: "trigger",
143
+ syntax: "cron",
144
+ mode: "workflow",
145
+ workflowName: "triage-inbox",
146
+ });
147
+
148
+ expect(() =>
149
+ patchRoute().handler({
150
+ pathParams: { id: schedule.id },
151
+ body: { workflowName: "" },
152
+ }),
153
+ ).toThrow("workflowName is required");
154
+
155
+ // Null clears the name too — same rejection.
156
+ expect(() =>
157
+ patchRoute().handler({
158
+ pathParams: { id: schedule.id },
159
+ body: { workflowName: null },
160
+ }),
161
+ ).toThrow("workflowName is required");
162
+
163
+ // The original name is intact (neither PATCH was applied).
164
+ expect(listSchedules()[0].workflowName).toBe("triage-inbox");
165
+ });
166
+
167
+ test("rejects with a BadRequestError instance (400 shape, matching create)", () => {
168
+ const schedule = createSchedule({
169
+ name: "Plain execute",
170
+ cronExpression: "0 9 * * *",
171
+ message: "hi",
172
+ syntax: "cron",
173
+ });
174
+
175
+ expect(() =>
176
+ patchRoute().handler({
177
+ pathParams: { id: schedule.id },
178
+ body: { mode: "workflow" },
179
+ }),
180
+ ).toThrow(BadRequestError);
181
+ });
182
+
183
+ test("allows switching to workflow mode WITH a valid workflowName", () => {
184
+ const schedule = createSchedule({
185
+ name: "Plain execute",
186
+ cronExpression: "0 9 * * *",
187
+ message: "hi",
188
+ syntax: "cron",
189
+ });
190
+
191
+ const result = patchRoute().handler({
192
+ pathParams: { id: schedule.id },
193
+ body: { mode: "workflow", workflowName: "triage-inbox" },
194
+ }) as { schedules: Array<{ id: string; mode: string }> };
195
+
196
+ const updated = result.schedules.find((s) => s.id === schedule.id);
197
+ expect(updated?.mode).toBe("workflow");
198
+ expect(listSchedules()[0].workflowName).toBe("triage-inbox");
199
+ });
200
+
201
+ test("allows an unrelated PATCH on a workflow schedule (name untouched)", () => {
202
+ const schedule = createSchedule({
203
+ name: "Workflow schedule",
204
+ cronExpression: "0 9 * * *",
205
+ message: "trigger",
206
+ syntax: "cron",
207
+ mode: "workflow",
208
+ workflowName: "triage-inbox",
209
+ });
210
+
211
+ // Patching only the message leaves mode=workflow and the name in place, so
212
+ // the validation passes (it reads the persisted name).
213
+ const result = patchRoute().handler({
214
+ pathParams: { id: schedule.id },
215
+ body: { message: "trigger now" },
216
+ }) as { schedules: Array<{ id: string; workflowName: string | null }> };
217
+
218
+ expect(result.schedules[0].workflowName).toBe("triage-inbox");
219
+ });
220
+ });
221
+
222
+ describe("POST /schedules — workflow mode does not require a message", () => {
223
+ beforeEach(clearTables);
224
+
225
+ test("creates a workflow schedule with no message field", () => {
226
+ // Workflow runs trigger workflowName/workflowArgs and ignore job.message,
227
+ // so the endpoint must not force a dummy message for workflow mode.
228
+ const result = createRoute().handler({
229
+ body: {
230
+ name: "Nightly triage",
231
+ description: "Run the triage workflow",
232
+ expression: "0 9 * * *",
233
+ mode: "workflow",
234
+ workflowName: "triage-inbox",
235
+ // no `message`
236
+ },
237
+ }) as { schedules: Array<{ mode: string; workflowName: string | null }> };
238
+
239
+ const created = result.schedules.find((s) => s.mode === "workflow");
240
+ expect(created?.workflowName).toBe("triage-inbox");
241
+ });
242
+
243
+ test("still rejects a workflow schedule with no workflowName", () => {
244
+ expect(() =>
245
+ createRoute().handler({
246
+ body: {
247
+ name: "Nightly triage",
248
+ description: "d",
249
+ expression: "0 9 * * *",
250
+ mode: "workflow",
251
+ },
252
+ }),
253
+ ).toThrow("workflowName is required");
254
+ });
255
+
256
+ test("execute mode still requires a message", () => {
257
+ expect(() =>
258
+ createRoute().handler({
259
+ body: {
260
+ name: "Plain execute",
261
+ description: "d",
262
+ expression: "0 9 * * *",
263
+ mode: "execute",
264
+ // no `message`
265
+ },
266
+ }),
267
+ ).toThrow("message is required");
268
+ });
269
+ });
270
+
271
+ describe("POST /schedules/:id/run — workflow mode triggers the workflow", () => {
272
+ beforeEach(() => {
273
+ clearTables();
274
+ workflowStartCalls.length = 0;
275
+ coreToolsReady = true;
276
+ });
277
+
278
+ test("starts the saved workflow instead of running a message turn", async () => {
279
+ const schedule = createSchedule({
280
+ name: "Nightly triage",
281
+ cronExpression: "0 9 * * *",
282
+ message: "", // workflow mode carries no message
283
+ syntax: "cron",
284
+ mode: "workflow",
285
+ workflowName: "triage-inbox",
286
+ workflowArgs: { scope: "unread" },
287
+ // schedule_create stores the originating conversation here.
288
+ createdFromConversationId: "conv-creator",
289
+ });
290
+
291
+ const result = (await runNowRoute().handler({
292
+ pathParams: { id: schedule.id },
293
+ })) as { schedules: Array<{ id: string }> };
294
+
295
+ // The workflow was launched with the read-only baseline manifest and
296
+ // guardian trust, forwarding name + args — not a message turn.
297
+ expect(workflowStartCalls).toHaveLength(1);
298
+ const call = workflowStartCalls[0]!;
299
+ expect(call.name).toBe("triage-inbox");
300
+ expect(call.args).toEqual({ scope: "unread" });
301
+ expect(call.manifest).toEqual({
302
+ tools: [],
303
+ hostFunctions: [],
304
+ persona: false,
305
+ });
306
+ expect((call.trustContext as { trustClass: string }).trustClass).toBe(
307
+ "guardian",
308
+ );
309
+ // No wakeConversationId → completion summary targets the creating
310
+ // conversation so the run's result is actually delivered.
311
+ expect(call.conversationId).toBe("conv-creator");
312
+
313
+ // A schedule run row was recorded as ok with the workflow run id.
314
+ const runs = getScheduleRuns(schedule.id);
315
+ expect(runs).toHaveLength(1);
316
+ expect(runs[0].status).toBe("ok");
317
+ expect(runs[0].output).toContain("wf-run-1");
318
+ // Response is the standard schedule list.
319
+ expect(Array.isArray(result.schedules)).toBe(true);
320
+ });
321
+
322
+ test("fires with the schedule's stored side-effecting manifest", async () => {
323
+ const schedule = createSchedule({
324
+ name: "Side-effecting workflow",
325
+ cronExpression: "0 9 * * *",
326
+ message: "",
327
+ syntax: "cron",
328
+ mode: "workflow",
329
+ workflowName: "send-report",
330
+ capabilities: {
331
+ tools: ["file_write"],
332
+ hostFunctions: ["notify"],
333
+ persona: true,
334
+ },
335
+ });
336
+
337
+ await runNowRoute().handler({ pathParams: { id: schedule.id } });
338
+
339
+ expect(workflowStartCalls).toHaveLength(1);
340
+ expect(workflowStartCalls[0]!.manifest).toEqual({
341
+ tools: ["file_write"],
342
+ hostFunctions: ["notify"],
343
+ persona: true,
344
+ });
345
+ });
346
+
347
+ test("a legacy schedule (null capabilities) fires with the read-only baseline", async () => {
348
+ const schedule = createSchedule({
349
+ name: "Legacy workflow",
350
+ cronExpression: "0 9 * * *",
351
+ message: "",
352
+ syntax: "cron",
353
+ mode: "workflow",
354
+ workflowName: "triage-inbox",
355
+ capabilities: null,
356
+ });
357
+
358
+ await runNowRoute().handler({ pathParams: { id: schedule.id } });
359
+
360
+ expect(workflowStartCalls).toHaveLength(1);
361
+ expect(workflowStartCalls[0]!.manifest).toEqual({
362
+ tools: [],
363
+ hostFunctions: [],
364
+ persona: false,
365
+ });
366
+ });
367
+
368
+ test("rejects a workflow schedule with no workflowName", async () => {
369
+ // Defensive guard mirroring the scheduler's automatic firing path; a
370
+ // nameless workflow schedule cannot be created via the routes, but the store
371
+ // does not enforce it, so run-now must fail fast rather than fall through.
372
+ const schedule = createSchedule({
373
+ name: "Nameless workflow",
374
+ cronExpression: "0 9 * * *",
375
+ message: "",
376
+ syntax: "cron",
377
+ mode: "workflow",
378
+ });
379
+
380
+ await expect(
381
+ runNowRoute().handler({ pathParams: { id: schedule.id } }),
382
+ ).rejects.toThrow("workflowName");
383
+ expect(workflowStartCalls).toHaveLength(0);
384
+ });
385
+
386
+ test("defers (503) a manual run during the boot window before tools are ready", async () => {
387
+ // Mirrors the scheduler's boot-race guard: launching before the read-only
388
+ // baseline is registered would give the run an empty toolset. A manual run
389
+ // can't defer to a later tick, so it fails fast with a retryable 503 and
390
+ // never calls start().
391
+ coreToolsReady = false;
392
+ const schedule = createSchedule({
393
+ name: "Nightly triage",
394
+ cronExpression: "0 9 * * *",
395
+ message: "",
396
+ syntax: "cron",
397
+ mode: "workflow",
398
+ workflowName: "triage-inbox",
399
+ });
400
+
401
+ await expect(
402
+ runNowRoute().handler({ pathParams: { id: schedule.id } }),
403
+ ).rejects.toThrow(ServiceUnavailableError);
404
+ expect(workflowStartCalls).toHaveLength(0);
405
+ // No schedule run row was recorded — the guard trips before createScheduleRun.
406
+ expect(getScheduleRuns(schedule.id)).toHaveLength(0);
407
+ });
408
+ });