@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
@@ -23,11 +23,14 @@ import type { WorkspaceMigration } from "./types.js";
23
23
  // - Are source: "user" (user-created profiles are untouched)
24
24
  // - Have a non-managed, non-absent source (unknown origin)
25
25
  // - Resolve to a non-Anthropic provider (adaptive thinking is
26
- // Anthropic-specific). A profile with no explicit provider inherits
27
- // llm.default.provider, so the check falls back to that with a
28
- // completely absent llm.default.provider treated as Anthropic, matching
29
- // migration 052's own `?? "anthropic"` default. This keeps the legacy
30
- // non-Anthropic empty `{}` shells seeded by migration 052 off the repair.
26
+ // Anthropic-specific). Effective provider is the profile's explicit
27
+ // `provider`; otherwise the provider implied by a known Claude `model`
28
+ // (mirroring the resolver's withImpliedProviderForKnownModel); otherwise
29
+ // llm.default.provider with a completely absent llm.default.provider
30
+ // treated as Anthropic, matching migration 052's own `?? "anthropic"`
31
+ // default. This keeps the legacy non-Anthropic empty `{}` shells seeded by
32
+ // migration 052 off the repair while still patching profiles that pin a
33
+ // known Claude model under a non-Anthropic default.
31
34
  //
32
35
  // Note: the live startup path re-runs the same repair after the platform
33
36
  // overlay merge — see assistant/src/workspace/adaptive-thinking-repair.ts.
@@ -61,8 +64,9 @@ export const enableAdaptiveThinkingManagedProfilesMigration: WorkspaceMigration
61
64
  const profiles = readObject(llm.profiles);
62
65
  if (profiles === null) return;
63
66
 
64
- // Profiles without an explicit provider inherit llm.default.provider at
65
- // resolution time; an absent llm.default.provider resolves to Anthropic.
67
+ // Profiles without an explicit provider and without a model-implied
68
+ // provider inherit llm.default.provider at resolution time; an absent
69
+ // llm.default.provider resolves to Anthropic.
66
70
  const defaultBlock = readObject(llm.default);
67
71
  const defaultProvider =
68
72
  typeof defaultBlock?.provider === "string"
@@ -79,17 +83,19 @@ export const enableAdaptiveThinkingManagedProfilesMigration: WorkspaceMigration
79
83
  // Legacy profiles created before the `source` metadata field was
80
84
  // introduced have source=undefined. Treat these as managed when the
81
85
  // profile name is one of the canonical managed names (which
82
- // TARGET_PROFILES already guarantees) and the effective provider
83
- // explicit, or inherited from llm.default is Anthropic. Explicit
84
- // `source: "user"` profiles are always skipped.
86
+ // TARGET_PROFILES already guarantees) and the effective provider is
87
+ // Anthropic. Effective provider is the explicit `provider`, else the
88
+ // provider implied by a known Claude `model`, else the inherited
89
+ // llm.default.provider. Explicit `source: "user"` profiles are always
90
+ // skipped.
85
91
  if (profile.source === "user") continue;
86
92
  if (profile.source !== undefined && profile.source !== "managed") {
87
93
  continue;
88
94
  }
89
- const effectiveProvider =
90
- typeof profile.provider === "string"
91
- ? profile.provider
92
- : defaultProvider;
95
+ const effectiveProvider = resolveEffectiveProvider(
96
+ profile,
97
+ defaultProvider,
98
+ );
93
99
  if (effectiveProvider !== "anthropic") continue;
94
100
 
95
101
  // Skip if thinking is already enabled.
@@ -112,6 +118,27 @@ export const enableAdaptiveThinkingManagedProfilesMigration: WorkspaceMigration
112
118
  },
113
119
  };
114
120
 
121
+ // Inline, conservative mirror of the resolver's catalog-based provider
122
+ // implication. Migration modules are frozen, self-contained snapshots and must
123
+ // not import the live model catalog. Anthropic's catalog model ids are bare
124
+ // `claude-*` ids (the slash-prefixed `anthropic/claude-*` ids belong to
125
+ // OpenRouter), so a profile pinning a `claude-*` model with no slash counts as
126
+ // Anthropic.
127
+ function resolveEffectiveProvider(
128
+ profile: Record<string, unknown>,
129
+ defaultProvider: string,
130
+ ): string {
131
+ if (typeof profile.provider === "string") return profile.provider;
132
+ if (
133
+ typeof profile.model === "string" &&
134
+ profile.model.startsWith("claude-") &&
135
+ !profile.model.includes("/")
136
+ ) {
137
+ return "anthropic";
138
+ }
139
+ return defaultProvider;
140
+ }
141
+
115
142
  function readObject(value: unknown): Record<string, unknown> | null {
116
143
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
117
144
  return null;
@@ -0,0 +1,69 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { MigrationRunContext, WorkspaceMigration } from "./types.js";
5
+
6
+ /**
7
+ * Preserve heartbeat behavior for existing workspaces after the schema
8
+ * default for `heartbeat.enabled` flipped from true to false (heartbeats are
9
+ * now opt-in for new users).
10
+ *
11
+ * Most configs never persist `heartbeat.enabled` — they relied on the old
12
+ * default-on schema behavior, so flipping the default would silently turn
13
+ * heartbeats off on upgrade. This migration writes an explicit
14
+ * `enabled: true` for upgrading workspaces that have no persisted value,
15
+ * keeping their effective behavior unchanged. Workspaces with an explicit
16
+ * `enabled` value (either way) are a user choice and are left untouched.
17
+ * Fresh workspaces are skipped so new users start with heartbeats off.
18
+ */
19
+ export const preserveHeartbeatEnabledForExistingWorkspacesMigration: WorkspaceMigration =
20
+ {
21
+ id: "102-preserve-heartbeat-enabled-for-existing-workspaces",
22
+ description:
23
+ "Persist heartbeat.enabled=true for existing workspaces now that the default is off",
24
+ run(workspaceDir: string, ctx?: MigrationRunContext): void {
25
+ // Fresh workspaces get the new opt-in default. Without a context
26
+ // (older callers), treat the workspace as existing — writing
27
+ // enabled=true reproduces the legacy default and never disables
28
+ // heartbeats for anyone.
29
+ if (ctx?.isNewWorkspace) return;
30
+
31
+ const configPath = join(workspaceDir, "config.json");
32
+
33
+ // Existing workspaces may have no config.json at all (schema defaults
34
+ // are applied in memory at load time); create one so the legacy
35
+ // default-on behavior survives the flip.
36
+ let config: Record<string, unknown> = {};
37
+ if (existsSync(configPath)) {
38
+ try {
39
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
40
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
41
+ config = raw as Record<string, unknown>;
42
+ } catch {
43
+ return;
44
+ }
45
+ }
46
+
47
+ if (config.heartbeat === undefined) {
48
+ config.heartbeat = {};
49
+ }
50
+ const heartbeat = config.heartbeat;
51
+ if (
52
+ !heartbeat ||
53
+ typeof heartbeat !== "object" ||
54
+ Array.isArray(heartbeat)
55
+ ) {
56
+ return;
57
+ }
58
+
59
+ const heartbeatConfig = heartbeat as Record<string, unknown>;
60
+ if ("enabled" in heartbeatConfig) return;
61
+
62
+ heartbeatConfig.enabled = true;
63
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
64
+ },
65
+ down(_workspaceDir: string): void {
66
+ // Forward-only: cannot distinguish users who explicitly enabled
67
+ // heartbeats from those opted in by this migration.
68
+ },
69
+ };
@@ -0,0 +1,83 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { WorkspaceMigration } from "./types.js";
5
+
6
+ // Move the managed quality-optimized profile from Claude Fable 5 to Opus 4.8.
7
+ //
8
+ // The quality-optimized intent maps to claude-opus-4-8, but the intent map is
9
+ // only consulted when a profile is seeded: off-platform installs reseed
10
+ // managed profiles on every boot, while on-platform workspaces keep the
11
+ // profile they were hatched with — the seeder skips existing profiles there,
12
+ // and the hatch overlay is consumed exactly once. A platform workspace holding
13
+ // a Claude Fable 5 quality-optimized profile therefore keeps it until a
14
+ // migration rewrites it.
15
+ //
16
+ // Only the managed quality-optimized profile is touched — the user-owned
17
+ // custom-quality-optimized copy is theirs to manage. Within it, only a profile
18
+ // still on claude-fable-5 is rewritten — matching by model value also covers
19
+ // the OpenRouter-prefixed id. A profile whose model the user changed to
20
+ // anything else is left untouched.
21
+
22
+ const TARGET_PROFILES = ["quality-optimized"];
23
+
24
+ const MODEL_UPGRADES: Record<string, string> = {
25
+ "claude-fable-5": "claude-opus-4-8",
26
+ "anthropic/claude-fable-5": "anthropic/claude-opus-4.8",
27
+ };
28
+
29
+ export const upgradeQualityProfileToOpus48Migration: WorkspaceMigration = {
30
+ id: "103-upgrade-quality-profile-to-opus-4-8",
31
+ description:
32
+ "Move the managed quality-optimized profile from Claude Fable 5 to Opus 4.8",
33
+ run(workspaceDir: string): void {
34
+ const configPath = join(workspaceDir, "config.json");
35
+ if (!existsSync(configPath)) return;
36
+
37
+ let config: Record<string, unknown>;
38
+ try {
39
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
40
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
41
+ config = raw as Record<string, unknown>;
42
+ } catch {
43
+ return;
44
+ }
45
+
46
+ const llm = readObject(config.llm);
47
+ if (llm === null) return;
48
+
49
+ const profiles = readObject(llm.profiles);
50
+ if (profiles === null) return;
51
+
52
+ let changed = false;
53
+
54
+ for (const name of TARGET_PROFILES) {
55
+ const profile = readObject(profiles[name]);
56
+ if (profile === null) continue;
57
+ if (typeof profile.model !== "string") continue;
58
+
59
+ const upgraded = MODEL_UPGRADES[profile.model];
60
+ if (upgraded === undefined) continue;
61
+
62
+ profile.model = upgraded;
63
+ profiles[name] = profile;
64
+ changed = true;
65
+ }
66
+
67
+ if (changed) {
68
+ llm.profiles = profiles;
69
+ config.llm = llm;
70
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
71
+ }
72
+ },
73
+ down(_workspaceDir: string): void {
74
+ // Forward-only.
75
+ },
76
+ };
77
+
78
+ function readObject(value: unknown): Record<string, unknown> | null {
79
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
80
+ return null;
81
+ }
82
+ return value as Record<string, unknown>;
83
+ }
@@ -0,0 +1,133 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { WorkspaceMigration } from "./types.js";
5
+
6
+ // Re-run the adaptive-thinking repair on managed "balanced" and
7
+ // "quality-optimized" profiles, this time honoring the provider implied by a
8
+ // known Claude `model`.
9
+ //
10
+ // Migration 097 patches managed Anthropic profiles to enable adaptive thinking.
11
+ // Its original release classified a source-less profile by
12
+ // `profile.provider ?? llm.default.provider`, so a profile that omits
13
+ // `provider` but pins a known Claude `model` under a non-Anthropic default was
14
+ // treated as non-Anthropic and skipped — even though the resolver implies
15
+ // Anthropic from the model id. 097's frozen copy was later corrected to imply
16
+ // the provider from the model, but workspaces that already ran 097 have it
17
+ // checkpointed as completed, so the corrected logic never re-runs for them.
18
+ // The live startup repair (adaptive-thinking-repair.ts) only runs behind the
19
+ // hatch overlay, which is archived after hatch, so already-hatched platform
20
+ // instances are not covered either.
21
+ //
22
+ // This migration re-applies the corrected repair once for those checkpointed
23
+ // workspaces. It is idempotent: profiles that already have thinking enabled are
24
+ // left untouched, so workspaces that were already patched (or that never had
25
+ // the gap) are no-ops.
26
+ //
27
+ // The migration keeps its own frozen copy of the logic because migration
28
+ // modules are self-contained snapshots and must never be imported by other
29
+ // code.
30
+
31
+ const ADAPTIVE_THINKING = { enabled: true, streamThinking: true } as const;
32
+ const TARGET_PROFILES = ["balanced", "quality-optimized"] as const;
33
+
34
+ export const recheckAdaptiveThinkingModelImpliedAnthropicMigration: WorkspaceMigration =
35
+ {
36
+ id: "104-recheck-adaptive-thinking-model-implied-anthropic",
37
+ description:
38
+ "Re-enable adaptive thinking on managed profiles that imply Anthropic via a known Claude model",
39
+ run(workspaceDir: string): void {
40
+ const configPath = join(workspaceDir, "config.json");
41
+ if (!existsSync(configPath)) return;
42
+
43
+ let config: Record<string, unknown>;
44
+ try {
45
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
46
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
47
+ config = raw as Record<string, unknown>;
48
+ } catch {
49
+ return;
50
+ }
51
+
52
+ const llm = readObject(config.llm);
53
+ if (llm === null) return;
54
+
55
+ const profiles = readObject(llm.profiles);
56
+ if (profiles === null) return;
57
+
58
+ // Profiles without an explicit provider and without a model-implied
59
+ // provider inherit llm.default.provider at resolution time; an absent
60
+ // llm.default.provider resolves to Anthropic.
61
+ const defaultBlock = readObject(llm.default);
62
+ const defaultProvider =
63
+ typeof defaultBlock?.provider === "string"
64
+ ? defaultBlock.provider
65
+ : "anthropic";
66
+
67
+ let changed = false;
68
+
69
+ for (const name of TARGET_PROFILES) {
70
+ const profile = readObject(profiles[name]);
71
+ if (profile === null) continue;
72
+
73
+ // Only patch managed Anthropic profiles. Explicit `source: "user"`
74
+ // profiles and non-managed, non-absent sources are skipped. Effective
75
+ // provider is the explicit `provider`, else the provider implied by a
76
+ // known Claude `model`, else the inherited llm.default.provider.
77
+ if (profile.source === "user") continue;
78
+ if (profile.source !== undefined && profile.source !== "managed") {
79
+ continue;
80
+ }
81
+ const effectiveProvider = resolveEffectiveProvider(
82
+ profile,
83
+ defaultProvider,
84
+ );
85
+ if (effectiveProvider !== "anthropic") continue;
86
+
87
+ // Skip if thinking is already enabled.
88
+ const thinking = readObject(profile.thinking);
89
+ if (thinking !== null && thinking.enabled === true) continue;
90
+
91
+ profile.thinking = { ...ADAPTIVE_THINKING };
92
+ profiles[name] = profile;
93
+ changed = true;
94
+ }
95
+
96
+ if (changed) {
97
+ llm.profiles = profiles;
98
+ config.llm = llm;
99
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
100
+ }
101
+ },
102
+ down(_workspaceDir: string): void {
103
+ // Forward-only.
104
+ },
105
+ };
106
+
107
+ // Inline, conservative mirror of the resolver's catalog-based provider
108
+ // implication. Migration modules are frozen, self-contained snapshots and must
109
+ // not import the live model catalog. Anthropic's catalog model ids are bare
110
+ // `claude-*` ids (the slash-prefixed `anthropic/claude-*` ids belong to
111
+ // OpenRouter), so a profile pinning a `claude-*` model with no slash counts as
112
+ // Anthropic.
113
+ function resolveEffectiveProvider(
114
+ profile: Record<string, unknown>,
115
+ defaultProvider: string,
116
+ ): string {
117
+ if (typeof profile.provider === "string") return profile.provider;
118
+ if (
119
+ typeof profile.model === "string" &&
120
+ profile.model.startsWith("claude-") &&
121
+ !profile.model.includes("/")
122
+ ) {
123
+ return "anthropic";
124
+ }
125
+ return defaultProvider;
126
+ }
127
+
128
+ function readObject(value: unknown): Record<string, unknown> | null {
129
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
130
+ return null;
131
+ }
132
+ return value as Record<string, unknown>;
133
+ }
@@ -99,6 +99,9 @@ import { removeStaleUpdatesBulletinFileMigration } from "./098-remove-stale-upda
99
99
  import { disableCacheOneShotCallsitesMigration } from "./099-disable-cache-one-shot-callsites.js";
100
100
  import { upgradeQualityProfileToFable5Migration } from "./100-upgrade-quality-profile-to-fable-5.js";
101
101
  import { upgradeBalancedEconomyToMinimaxM3Migration } from "./101-upgrade-balanced-economy-to-minimax-m3.js";
102
+ import { preserveHeartbeatEnabledForExistingWorkspacesMigration } from "./102-preserve-heartbeat-enabled-for-existing-workspaces.js";
103
+ import { upgradeQualityProfileToOpus48Migration } from "./103-upgrade-quality-profile-to-opus-4-8.js";
104
+ import { recheckAdaptiveThinkingModelImpliedAnthropicMigration } from "./104-recheck-adaptive-thinking-model-implied-anthropic.js";
102
105
  import { migrateToWorkspaceVolumeMigration } from "./migrate-to-workspace-volume.js";
103
106
  import type { WorkspaceMigration } from "./types.js";
104
107
 
@@ -209,4 +212,7 @@ export const WORKSPACE_MIGRATIONS: WorkspaceMigration[] = [
209
212
  disableCacheOneShotCallsitesMigration,
210
213
  upgradeQualityProfileToFable5Migration,
211
214
  upgradeBalancedEconomyToMinimaxM3Migration,
215
+ preserveHeartbeatEnabledForExistingWorkspacesMigration,
216
+ upgradeQualityProfileToOpus48Migration,
217
+ recheckAdaptiveThinkingModelImpliedAnthropicMigration,
212
218
  ];
@@ -197,7 +197,7 @@ export async function runWorkspaceMigrations(
197
197
  * workspace migrations while the assistant is running may cause file conflicts,
198
198
  * stale caches, or data corruption.
199
199
  *
200
- * @param workspaceDir The workspace directory path (e.g., `~/.vellum/workspace`).
200
+ * @param workspaceDir The workspace directory path (e.g., `$VELLUM_WORKSPACE_DIR`).
201
201
  * @param migrations The full ordered array of workspace migrations (from `WORKSPACE_MIGRATIONS`).
202
202
  * @param targetMigrationId The migration ID to roll back to (exclusive — all
203
203
  * migrations after this one are reversed).
package/tsconfig.json CHANGED
@@ -19,5 +19,5 @@
19
19
  }
20
20
  },
21
21
  "include": ["src/**/*", "src/**/*.tsx", "examples/**/*.ts"],
22
- "exclude": ["node_modules", "dist", "drizzle"]
22
+ "exclude": ["node_modules", "dist", "drizzle", "src/config/preloaded-apps"]
23
23
  }
@@ -1,200 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
-
3
- import type {
4
- GuardianActionMessageContext,
5
- GuardianActionMessageScenario,
6
- } from "../runtime/guardian-action-message-composer.js";
7
- import {
8
- composeGuardianActionMessageGenerative,
9
- getGuardianActionFallbackMessage,
10
- } from "../runtime/guardian-action-message-composer.js";
11
- import type { GuardianActionCopyGenerator } from "../runtime/http-types.js";
12
-
13
- // ---------------------------------------------------------------------------
14
- // Every scenario must produce a non-empty string
15
- // ---------------------------------------------------------------------------
16
-
17
- const ALL_SCENARIOS: GuardianActionMessageScenario[] = [
18
- "caller_timeout_acknowledgment",
19
- "caller_timeout_continue",
20
- "guardian_late_answer_followup",
21
- "guardian_followup_dispatching",
22
- "guardian_followup_completed",
23
- "guardian_followup_failed",
24
- "guardian_followup_declined_ack",
25
- "guardian_followup_clarification",
26
- "guardian_pending_disambiguation",
27
- "guardian_expired_disambiguation",
28
- "guardian_followup_disambiguation",
29
- "guardian_stale_answered",
30
- "guardian_stale_expired",
31
- "guardian_stale_followup",
32
- "guardian_stale_superseded",
33
- "guardian_superseded_remap",
34
- "guardian_unknown_code",
35
- "guardian_auto_matched",
36
- "followup_call_started",
37
- "followup_action_failed",
38
- "guardian_answer_delivery_failed",
39
- ];
40
-
41
- describe("guardian-action-copy-generator", () => {
42
- // -----------------------------------------------------------------------
43
- // Fallback messages -- every scenario produces non-empty output
44
- // -----------------------------------------------------------------------
45
-
46
- describe("getGuardianActionFallbackMessage", () => {
47
- for (const scenario of ALL_SCENARIOS) {
48
- test(`scenario "${scenario}" produces a non-empty string`, () => {
49
- const msg = getGuardianActionFallbackMessage({ scenario });
50
- expect(typeof msg).toBe("string");
51
- expect(msg.trim().length).toBeGreaterThan(0);
52
- });
53
- }
54
-
55
- test("caller_timeout_acknowledgment includes guardianIdentifier when provided", () => {
56
- const msg = getGuardianActionFallbackMessage({
57
- scenario: "caller_timeout_acknowledgment",
58
- guardianIdentifier: "Dr. Smith",
59
- });
60
- expect(msg).toContain("Dr. Smith");
61
- });
62
-
63
- test("guardian_late_answer_followup includes callerIdentifier when provided", () => {
64
- const msg = getGuardianActionFallbackMessage({
65
- scenario: "guardian_late_answer_followup",
66
- callerIdentifier: "Alice",
67
- });
68
- expect(msg).toContain("Alice");
69
- });
70
-
71
- test("guardian_followup_dispatching includes followupAction when provided", () => {
72
- const msg = getGuardianActionFallbackMessage({
73
- scenario: "guardian_followup_dispatching",
74
- followupAction: "send them a text message",
75
- });
76
- expect(msg).toContain("send them a text message");
77
- });
78
-
79
- test("guardian_followup_completed includes followupAction when provided", () => {
80
- const msg = getGuardianActionFallbackMessage({
81
- scenario: "guardian_followup_completed",
82
- followupAction: "sent the message",
83
- });
84
- expect(msg).toContain("sent the message");
85
- });
86
-
87
- test("guardian_followup_failed includes failureReason when provided", () => {
88
- const msg = getGuardianActionFallbackMessage({
89
- scenario: "guardian_followup_failed",
90
- failureReason: "The phone number is not valid.",
91
- });
92
- expect(msg).toContain("The phone number is not valid.");
93
- });
94
-
95
- test("guardian_expired_disambiguation includes request codes when provided", () => {
96
- const msg = getGuardianActionFallbackMessage({
97
- scenario: "guardian_expired_disambiguation",
98
- requestCodes: ["Q1A2B3", "Q9Z8Y7"],
99
- });
100
- expect(msg).toContain("Q1A2B3");
101
- expect(msg).toContain("Q9Z8Y7");
102
- });
103
-
104
- test("guardian_followup_disambiguation includes request codes when provided", () => {
105
- const msg = getGuardianActionFallbackMessage({
106
- scenario: "guardian_followup_disambiguation",
107
- requestCodes: ["QFOO12"],
108
- });
109
- expect(msg).toContain("QFOO12");
110
- });
111
- });
112
-
113
- // -----------------------------------------------------------------------
114
- // composeGuardianActionMessageGenerative -- layered composition
115
- // -----------------------------------------------------------------------
116
-
117
- describe("composeGuardianActionMessageGenerative", () => {
118
- test("with no generator returns fallback", async () => {
119
- const context: GuardianActionMessageContext = {
120
- scenario: "caller_timeout_acknowledgment",
121
- guardianIdentifier: "Jane",
122
- };
123
- const msg = await composeGuardianActionMessageGenerative(context);
124
- expect(msg).toBe(getGuardianActionFallbackMessage(context));
125
- });
126
-
127
- test("with generator that returns text uses the generated text", async () => {
128
- const generatedText = "Custom generated message about the timeout.";
129
- const generator: GuardianActionCopyGenerator = async () => generatedText;
130
- const context: GuardianActionMessageContext = {
131
- scenario: "caller_timeout_acknowledgment",
132
- };
133
- // In test env, generator is skipped and fallback is returned
134
- const msg = await composeGuardianActionMessageGenerative(
135
- context,
136
- {},
137
- generator,
138
- );
139
- expect(msg).toBe(getGuardianActionFallbackMessage(context));
140
- });
141
-
142
- test("with generator that throws returns fallback", async () => {
143
- const generator: GuardianActionCopyGenerator = async () => {
144
- throw new Error("Provider unavailable");
145
- };
146
- const context: GuardianActionMessageContext = {
147
- scenario: "guardian_followup_failed",
148
- failureReason: "Network error",
149
- };
150
- const msg = await composeGuardianActionMessageGenerative(
151
- context,
152
- {},
153
- generator,
154
- );
155
- expect(msg).toBe(getGuardianActionFallbackMessage(context));
156
- });
157
-
158
- test("with generator that returns null returns fallback", async () => {
159
- const generator: GuardianActionCopyGenerator = async () => null;
160
- const context: GuardianActionMessageContext = {
161
- scenario: "guardian_stale_expired",
162
- };
163
- const msg = await composeGuardianActionMessageGenerative(
164
- context,
165
- {},
166
- generator,
167
- );
168
- expect(msg).toBe(getGuardianActionFallbackMessage(context));
169
- });
170
-
171
- test("uses custom fallbackText from options when provided", async () => {
172
- const context: GuardianActionMessageContext = {
173
- scenario: "caller_timeout_continue",
174
- };
175
- const customFallback = "Custom fallback text for this scenario.";
176
- const msg = await composeGuardianActionMessageGenerative(context, {
177
- fallbackText: customFallback,
178
- });
179
- expect(msg).toBe(customFallback);
180
- });
181
-
182
- test("skips generation in test environment", async () => {
183
- let generatorCalled = false;
184
- const generator: GuardianActionCopyGenerator = async () => {
185
- generatorCalled = true;
186
- return "This should not be returned in test env";
187
- };
188
- const context: GuardianActionMessageContext = {
189
- scenario: "guardian_followup_declined_ack",
190
- };
191
- const msg = await composeGuardianActionMessageGenerative(
192
- context,
193
- {},
194
- generator,
195
- );
196
- expect(generatorCalled).toBe(false);
197
- expect(msg).toBe(getGuardianActionFallbackMessage(context));
198
- });
199
- });
200
- });