@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,365 @@
1
+ import { afterAll, beforeEach, describe, expect, test } from "bun:test";
2
+
3
+ import { RiskLevel } from "../permissions/types.js";
4
+ import {
5
+ __clearRegistryForTesting,
6
+ __resetRegistryForTesting,
7
+ registerTool,
8
+ registerWorkspaceTools,
9
+ } from "../tools/registry.js";
10
+ import { isSideEffectTool } from "../tools/side-effects.js";
11
+ import type {
12
+ ExecutionTarget,
13
+ Tool,
14
+ ToolContext,
15
+ ToolExecutionResult,
16
+ } from "../tools/types.js";
17
+ import {
18
+ CapabilityManifestSchema,
19
+ CapabilityResolutionError,
20
+ manifestGrantsSideEffects,
21
+ normalizeCapabilityManifest,
22
+ resolveCapabilities,
23
+ WORKFLOW_FORBIDDEN_TOOLS,
24
+ WORKFLOW_READONLY_BASELINE,
25
+ } from "./capabilities.js";
26
+
27
+ function makeFakeTool(
28
+ name: string,
29
+ executionTarget: ExecutionTarget = "sandbox",
30
+ ): Tool {
31
+ return {
32
+ name,
33
+ description: `Fake ${name}`,
34
+ category: "test",
35
+ defaultRiskLevel: RiskLevel.Low,
36
+ executionTarget,
37
+ input_schema: { type: "object", properties: {}, required: [] },
38
+ async execute(
39
+ _input: Record<string, unknown>,
40
+ _context: ToolContext,
41
+ ): Promise<ToolExecutionResult> {
42
+ return { content: "ok", isError: false };
43
+ },
44
+ };
45
+ }
46
+
47
+ // A declarable side-effecting tool that is NOT part of the baseline — used to
48
+ // exercise the "baseline ∪ declared" union path.
49
+ const DECLARABLE_TOOL = "file_write";
50
+
51
+ beforeEach(() => {
52
+ // Deterministic registry: only the baseline tools plus one declarable tool.
53
+ __clearRegistryForTesting();
54
+ for (const name of WORKFLOW_READONLY_BASELINE) {
55
+ registerTool(makeFakeTool(name));
56
+ }
57
+ registerTool(makeFakeTool(DECLARABLE_TOOL));
58
+ });
59
+
60
+ afterAll(() => {
61
+ // Restore the registry to its post-init baseline so other test files in a
62
+ // combined run are not contaminated.
63
+ __resetRegistryForTesting();
64
+ });
65
+
66
+ describe("CapabilityManifestSchema", () => {
67
+ test("applies documented defaults for omitted fields", () => {
68
+ const manifest = CapabilityManifestSchema.parse({});
69
+ expect(manifest).toEqual({
70
+ tools: [],
71
+ hostFunctions: [],
72
+ persona: false,
73
+ });
74
+ });
75
+
76
+ test("preserves declared values", () => {
77
+ const manifest = CapabilityManifestSchema.parse({
78
+ tools: ["file_write"],
79
+ hostFunctions: ["notify"],
80
+ persona: true,
81
+ });
82
+ expect(manifest).toEqual({
83
+ tools: ["file_write"],
84
+ hostFunctions: ["notify"],
85
+ persona: true,
86
+ });
87
+ });
88
+ });
89
+
90
+ describe("resolveCapabilities", () => {
91
+ test("grants the read-only baseline without declaration", () => {
92
+ const resolved = resolveCapabilities(CapabilityManifestSchema.parse({}));
93
+ const names = resolved.tools.map((t) => t.name).sort();
94
+ expect(names).toEqual([...WORKFLOW_READONLY_BASELINE].sort());
95
+ });
96
+
97
+ test("the read-only baseline contains no side-effect tools", () => {
98
+ // The baseline is auto-granted with NO launch approval, so every entry must
99
+ // be read-only per the single side-effect source of truth. This invariant
100
+ // is what the defense-in-depth filter in resolveCapabilities enforces.
101
+ for (const name of WORKFLOW_READONLY_BASELINE) {
102
+ expect(isSideEffectTool(name)).toBe(false);
103
+ }
104
+ });
105
+
106
+ test("does NOT auto-grant web_fetch, but it can still be declared", () => {
107
+ // web_fetch is a side-effect tool (its URL can exfiltrate read data or
108
+ // trigger external actions), so an empty-manifest (no-approval) run must not
109
+ // get it — even when it is registered as a core tool.
110
+ registerTool(makeFakeTool("web_fetch"));
111
+ const baseline = resolveCapabilities(CapabilityManifestSchema.parse({}));
112
+ expect(baseline.tools.map((t) => t.name)).not.toContain("web_fetch");
113
+
114
+ // A run that DECLARES web_fetch still gets it — and declaring it flips
115
+ // manifestGrantsSideEffects, which forces the launch approval gate.
116
+ const declared = resolveCapabilities(
117
+ CapabilityManifestSchema.parse({ tools: ["web_fetch"] }),
118
+ );
119
+ expect(declared.tools.map((t) => t.name)).toContain("web_fetch");
120
+ expect(manifestGrantsSideEffects({ tools: ["web_fetch"] })).toBe(true);
121
+ });
122
+
123
+ test("unions baseline with declared tools (no duplicates)", () => {
124
+ const manifest = CapabilityManifestSchema.parse({
125
+ // Declare one new tool plus a baseline tool that should not duplicate.
126
+ tools: [DECLARABLE_TOOL, "file_read"],
127
+ });
128
+ const resolved = resolveCapabilities(manifest);
129
+ const names = resolved.tools.map((t) => t.name).sort();
130
+ expect(names).toEqual(
131
+ [...WORKFLOW_READONLY_BASELINE, DECLARABLE_TOOL].sort(),
132
+ );
133
+ // No duplicate entries for the redeclared baseline tool.
134
+ expect(names.filter((n) => n === "file_read")).toHaveLength(1);
135
+ });
136
+
137
+ test("passes through hostFunctions and persona", () => {
138
+ const manifest = CapabilityManifestSchema.parse({
139
+ hostFunctions: ["host_a", "host_b"],
140
+ persona: true,
141
+ });
142
+ const resolved = resolveCapabilities(manifest);
143
+ expect(resolved.hostFunctions).toEqual(["host_a", "host_b"]);
144
+ expect(resolved.persona).toBe(true);
145
+ });
146
+
147
+ test("rejects a declared tool that does not exist in the registry", () => {
148
+ const manifest = CapabilityManifestSchema.parse({
149
+ tools: ["does_not_exist"],
150
+ });
151
+ expect(() => resolveCapabilities(manifest)).toThrow(
152
+ CapabilityResolutionError,
153
+ );
154
+ try {
155
+ resolveCapabilities(manifest);
156
+ } catch (err) {
157
+ expect(err).toBeInstanceOf(CapabilityResolutionError);
158
+ expect((err as CapabilityResolutionError).reason).toBe("unknown_tool");
159
+ expect((err as CapabilityResolutionError).toolName).toBe(
160
+ "does_not_exist",
161
+ );
162
+ }
163
+ });
164
+
165
+ test("rejects a declared forbidden tool", () => {
166
+ const forbidden = WORKFLOW_FORBIDDEN_TOOLS[0]!;
167
+ // Even if it were registered, declaring a forbidden tool must throw.
168
+ registerTool(makeFakeTool(forbidden));
169
+ const manifest = CapabilityManifestSchema.parse({ tools: [forbidden] });
170
+ try {
171
+ resolveCapabilities(manifest);
172
+ throw new Error("expected resolveCapabilities to throw");
173
+ } catch (err) {
174
+ expect(err).toBeInstanceOf(CapabilityResolutionError);
175
+ expect((err as CapabilityResolutionError).reason).toBe("forbidden_tool");
176
+ expect((err as CapabilityResolutionError).toolName).toBe(forbidden);
177
+ }
178
+ });
179
+
180
+ test("forbids the CES authenticated tools (executor post-processing bypass)", () => {
181
+ // run_authenticated_command / make_authenticated_request can return
182
+ // `cesApprovalRequired`, which only ToolExecutor bridges + retries. A leaf
183
+ // calls tool.execute() directly, so it would see the raw approval-required
184
+ // result as an error — hence these are forbidden until leaf invocations run
185
+ // the executor's post-processing. Declaring either is a hard error.
186
+ for (const name of [
187
+ "run_authenticated_command",
188
+ "make_authenticated_request",
189
+ ]) {
190
+ expect(WORKFLOW_FORBIDDEN_TOOLS).toContain(name);
191
+ registerTool(makeFakeTool(name));
192
+ const manifest = CapabilityManifestSchema.parse({ tools: [name] });
193
+ try {
194
+ resolveCapabilities(manifest);
195
+ throw new Error(`expected resolveCapabilities to throw for ${name}`);
196
+ } catch (err) {
197
+ expect(err).toBeInstanceOf(CapabilityResolutionError);
198
+ expect((err as CapabilityResolutionError).reason).toBe(
199
+ "forbidden_tool",
200
+ );
201
+ expect((err as CapabilityResolutionError).toolName).toBe(name);
202
+ }
203
+ }
204
+ });
205
+
206
+ test("rejects a declared host-proxy tool (executionTarget host)", () => {
207
+ // A leaf builds a synthetic, anonymous ToolContext that carries none of the
208
+ // originating turn's host-routing fields (transportInterface,
209
+ // sourceActorPrincipalId, proxy resolver), so a host tool would mis-route
210
+ // at run time. Rejection keys off the resolved executionTarget, NOT the
211
+ // name — `send_to_host` has no `host_` prefix yet must still be rejected.
212
+ // Every real host tool (host_bash, host_file_*, computer-use) declares
213
+ // `executionTarget: "host"`, so this is the path that catches them.
214
+ registerTool(makeFakeTool("send_to_host", "host"));
215
+ const manifest = CapabilityManifestSchema.parse({
216
+ tools: ["send_to_host"],
217
+ });
218
+ try {
219
+ resolveCapabilities(manifest);
220
+ throw new Error("expected resolveCapabilities to throw");
221
+ } catch (err) {
222
+ expect(err).toBeInstanceOf(CapabilityResolutionError);
223
+ expect((err as CapabilityResolutionError).reason).toBe("host_tool");
224
+ expect((err as CapabilityResolutionError).toolName).toBe("send_to_host");
225
+ }
226
+ });
227
+
228
+ test("baseline resolves the CORE tool, not a workspace override of the name", () => {
229
+ // A workspace tool may register under a core baseline name (file_read). The
230
+ // baseline is granted to every empty-manifest run WITHOUT the launch
231
+ // approval declared tools require, so it must resolve the trusted core
232
+ // implementation — never the workspace replacement, which could run
233
+ // arbitrary side-effecting behavior unconsented.
234
+ registerWorkspaceTools([
235
+ {
236
+ tool: {
237
+ name: "file_read",
238
+ description: "Workspace override of file_read",
239
+ // A distinct category so we can tell which implementation resolved.
240
+ category: "workspace-marker",
241
+ defaultRiskLevel: RiskLevel.Low,
242
+ executionTarget: "sandbox",
243
+ input_schema: { type: "object", properties: {}, required: [] },
244
+ async execute(): Promise<ToolExecutionResult> {
245
+ return { content: "workspace", isError: false };
246
+ },
247
+ },
248
+ workspacePath: "/ws",
249
+ },
250
+ ]);
251
+
252
+ const resolved = resolveCapabilities(CapabilityManifestSchema.parse({}));
253
+ const fileRead = resolved.tools.find((t) => t.name === "file_read");
254
+ expect(fileRead).toBeDefined();
255
+ // The stashed CORE tool (category "test" from makeFakeTool) wins — NOT the
256
+ // workspace override (category "workspace-marker").
257
+ expect(fileRead?.category).toBe("test");
258
+ });
259
+
260
+ test("never includes a forbidden tool in the resolved set", () => {
261
+ // Sanity: forbidden tools and baseline tools are disjoint.
262
+ for (const name of WORKFLOW_FORBIDDEN_TOOLS) {
263
+ expect(WORKFLOW_READONLY_BASELINE).not.toContain(name);
264
+ }
265
+ const resolved = resolveCapabilities(CapabilityManifestSchema.parse({}));
266
+ const names = new Set(resolved.tools.map((t) => t.name));
267
+ for (const forbidden of WORKFLOW_FORBIDDEN_TOOLS) {
268
+ expect(names.has(forbidden)).toBe(false);
269
+ }
270
+ });
271
+ });
272
+
273
+ describe("manifestGrantsSideEffects", () => {
274
+ // The launch-time consent gate keys off this predicate: a run that grants
275
+ // side-effecting tools/host functions must prompt; a read-only run must not.
276
+ test("false for an absent or empty manifest (read-only baseline only)", () => {
277
+ expect(manifestGrantsSideEffects(undefined)).toBe(false);
278
+ expect(manifestGrantsSideEffects(null)).toBe(false);
279
+ expect(manifestGrantsSideEffects({})).toBe(false);
280
+ expect(manifestGrantsSideEffects({ tools: [], hostFunctions: [] })).toBe(
281
+ false,
282
+ );
283
+ });
284
+
285
+ test("true when the manifest declares side-effecting tools", () => {
286
+ expect(manifestGrantsSideEffects({ tools: ["file_write"] })).toBe(true);
287
+ expect(manifestGrantsSideEffects({ tools: ["bash", "send_email"] })).toBe(
288
+ true,
289
+ );
290
+ });
291
+
292
+ test("true when the manifest declares host functions", () => {
293
+ expect(manifestGrantsSideEffects({ hostFunctions: ["notify"] })).toBe(true);
294
+ });
295
+
296
+ test("persona alone is NOT side-effecting (identity/memory, not tools)", () => {
297
+ expect(manifestGrantsSideEffects({ persona: true })).toBe(false);
298
+ expect(
299
+ manifestGrantsSideEffects({
300
+ tools: [],
301
+ hostFunctions: [],
302
+ persona: true,
303
+ }),
304
+ ).toBe(false);
305
+ });
306
+
307
+ test("false (never throws) for a malformed manifest — execute re-parses and rejects it", () => {
308
+ expect(manifestGrantsSideEffects({ tools: "not-an-array" })).toBe(false);
309
+ expect(manifestGrantsSideEffects(42)).toBe(false);
310
+ expect(manifestGrantsSideEffects("nope")).toBe(false);
311
+ });
312
+
313
+ test("true for the older RESOLVED stored shape (tools as Tool objects)", () => {
314
+ // Some interrupted runs persisted resolved Tool objects rather than string
315
+ // names. resume() recovers those names and grants the tools, so the consent
316
+ // gate must see them as side-effecting too — a strict parse would reject the
317
+ // object shape and wrongly report a read-only run, letting resume restart
318
+ // side-effecting leaves without approval.
319
+ expect(
320
+ manifestGrantsSideEffects({
321
+ tools: [{ name: "bash" }],
322
+ hostFunctions: [],
323
+ persona: false,
324
+ }),
325
+ ).toBe(true);
326
+ expect(
327
+ manifestGrantsSideEffects({
328
+ tools: [{ name: "file_write", category: "fs" }],
329
+ }),
330
+ ).toBe(true);
331
+ // An empty resolved-shape run is still read-only.
332
+ expect(manifestGrantsSideEffects({ tools: [] })).toBe(false);
333
+ });
334
+ });
335
+
336
+ describe("normalizeCapabilityManifest", () => {
337
+ test("recovers tool names from BOTH string and Tool-object entries", () => {
338
+ expect(
339
+ normalizeCapabilityManifest({
340
+ tools: ["file_read", { name: "bash" }, { nope: 1 }, 42],
341
+ hostFunctions: ["notify", 7],
342
+ persona: true,
343
+ }),
344
+ ).toEqual({
345
+ tools: ["file_read", "bash"],
346
+ hostFunctions: ["notify"],
347
+ persona: true,
348
+ });
349
+ });
350
+
351
+ test("total: a malformed/absent blob yields empty arrays, never throws", () => {
352
+ expect(normalizeCapabilityManifest(undefined)).toEqual({
353
+ tools: [],
354
+ hostFunctions: [],
355
+ persona: false,
356
+ });
357
+ expect(normalizeCapabilityManifest({ tools: "x", persona: "yes" })).toEqual(
358
+ {
359
+ tools: [],
360
+ hostFunctions: [],
361
+ persona: false,
362
+ },
363
+ );
364
+ });
365
+ });