@vellumai/assistant 0.8.2 → 0.8.4

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 (503) hide show
  1. package/ARCHITECTURE.md +11 -12
  2. package/docker-entrypoint.sh +13 -2
  3. package/docker-init-apt-root.sh +79 -6
  4. package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
  5. package/openapi.yaml +945 -36
  6. package/package.json +1 -1
  7. package/src/__tests__/agent-loop-exit-reason.test.ts +271 -0
  8. package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
  9. package/src/__tests__/agent-loop-provider-error-recording.test.ts +195 -0
  10. package/src/__tests__/agent-loop.test.ts +88 -3
  11. package/src/__tests__/anthropic-provider.test.ts +272 -0
  12. package/src/__tests__/approval-cascade.test.ts +1 -1
  13. package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
  14. package/src/__tests__/channel-delivery-store.test.ts +193 -0
  15. package/src/__tests__/channel-reply-delivery.test.ts +284 -5
  16. package/src/__tests__/channel-retry-sweep.test.ts +274 -1
  17. package/src/__tests__/compaction-events.test.ts +1 -1
  18. package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
  19. package/src/__tests__/compactor-tail-resolution.test.ts +107 -1
  20. package/src/__tests__/config-get-vision-flag.test.ts +136 -0
  21. package/src/__tests__/config-loader-backfill.test.ts +115 -18
  22. package/src/__tests__/config-watcher.test.ts +1 -1
  23. package/src/__tests__/context-token-estimator.test.ts +112 -57
  24. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
  25. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +54 -3
  26. package/src/__tests__/conversation-agent-loop-overflow.test.ts +31 -6
  27. package/src/__tests__/conversation-agent-loop.test.ts +77 -3
  28. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
  29. package/src/__tests__/conversation-clean-command.test.ts +137 -0
  30. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
  31. package/src/__tests__/conversation-fork-crud.test.ts +161 -0
  32. package/src/__tests__/conversation-lifecycle.test.ts +1 -1
  33. package/src/__tests__/conversation-load-cleaned-at.test.ts +279 -0
  34. package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
  35. package/src/__tests__/conversation-media-retry.test.ts +19 -8
  36. package/src/__tests__/conversation-pairing.test.ts +2 -2
  37. package/src/__tests__/conversation-process-callsite.test.ts +1 -1
  38. package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -1
  39. package/src/__tests__/conversation-queue.test.ts +1 -1
  40. package/src/__tests__/conversation-runtime-assembly.test.ts +290 -85
  41. package/src/__tests__/conversation-seed-composer.test.ts +66 -4
  42. package/src/__tests__/conversation-slash-commands.test.ts +36 -8
  43. package/src/__tests__/conversation-slash-queue.test.ts +1 -1
  44. package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
  45. package/src/__tests__/conversation-speed-override.test.ts +1 -1
  46. package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
  47. package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -1
  48. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  49. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  50. package/src/__tests__/credential-security-invariants.test.ts +6 -0
  51. package/src/__tests__/cu-unified-flow.test.ts +10 -1
  52. package/src/__tests__/date-context.test.ts +45 -0
  53. package/src/__tests__/dm-backfill.test.ts +64 -0
  54. package/src/__tests__/dm-persistence.test.ts +33 -0
  55. package/src/__tests__/document-find-replace.test.ts +501 -0
  56. package/src/__tests__/external-plugin-loader.test.ts +91 -19
  57. package/src/__tests__/first-greeting.test.ts +23 -2
  58. package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +0 -1
  59. package/src/__tests__/guardian-dispatch.test.ts +1 -0
  60. package/src/__tests__/headless-browser-navigate.test.ts +172 -0
  61. package/src/__tests__/heartbeat-service.test.ts +24 -164
  62. package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
  63. package/src/__tests__/host-app-control-proxy.test.ts +241 -0
  64. package/src/__tests__/host-bash-proxy.test.ts +6 -0
  65. package/src/__tests__/host-browser-proxy.test.ts +10 -0
  66. package/src/__tests__/host-cu-proxy.test.ts +8 -1
  67. package/src/__tests__/host-file-proxy.test.ts +8 -1
  68. package/src/__tests__/host-proxy-preactivation.test.ts +200 -13
  69. package/src/__tests__/host-transfer-proxy.test.ts +8 -1
  70. package/src/__tests__/identity-routes.test.ts +57 -0
  71. package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
  72. package/src/__tests__/injector-background-turn.test.ts +153 -0
  73. package/src/__tests__/injector-chain.test.ts +7 -0
  74. package/src/__tests__/injector-document-comments.test.ts +378 -0
  75. package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
  76. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +9 -2
  77. package/src/__tests__/list-messages-attachments.test.ts +21 -17
  78. package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
  79. package/src/__tests__/list-messages-page-latest.test.ts +130 -14
  80. package/src/__tests__/list-messages-tool-merge.test.ts +17 -16
  81. package/src/__tests__/llm-callsite-catalog.test.ts +25 -0
  82. package/src/__tests__/llm-catalog-parity.test.ts +3 -0
  83. package/src/__tests__/llm-context-normalization.test.ts +0 -2
  84. package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +116 -0
  85. package/src/__tests__/llm-request-log-error-payload.test.ts +138 -0
  86. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +2 -0
  87. package/src/__tests__/llm-resolver.test.ts +340 -3
  88. package/src/__tests__/log-export-routes.test.ts +99 -2
  89. package/src/__tests__/managed-profile-guard.test.ts +10 -0
  90. package/src/__tests__/message-queue-steer.test.ts +114 -0
  91. package/src/__tests__/notification-decision-fallback.test.ts +0 -91
  92. package/src/__tests__/notification-decision-strategy.test.ts +14 -31
  93. package/src/__tests__/notification-deep-link.test.ts +15 -0
  94. package/src/__tests__/notification-guardian-path.test.ts +1 -2
  95. package/src/__tests__/notification-platform-adapter.test.ts +5 -4
  96. package/src/__tests__/notification-telegram-adapter.test.ts +1 -0
  97. package/src/__tests__/notification-vellum-adapter.test.ts +113 -0
  98. package/src/__tests__/openai-provider.test.ts +323 -3
  99. package/src/__tests__/openai-responses-cutover-guard.test.ts +3 -3
  100. package/src/__tests__/openai-responses-provider.test.ts +4 -4
  101. package/src/__tests__/openrouter-provider-only.test.ts +51 -3
  102. package/src/__tests__/openrouter-token-estimation.test.ts +34 -25
  103. package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
  104. package/src/__tests__/pending-interactions-resolved-event.test.ts +190 -0
  105. package/src/__tests__/platform-proxy-context.test.ts +6 -1
  106. package/src/__tests__/platform.test.ts +0 -3
  107. package/src/__tests__/plugin-source-watcher.test.ts +302 -0
  108. package/src/__tests__/plugin-tool-contribution.test.ts +3 -3
  109. package/src/__tests__/plugin-types.test.ts +2 -2
  110. package/src/__tests__/process-message-background-slack.test.ts +1 -51
  111. package/src/__tests__/process-message-display-content.test.ts +21 -16
  112. package/src/__tests__/provider-catalog-visibility.test.ts +16 -0
  113. package/src/__tests__/provider-platform-proxy-integration.test.ts +27 -25
  114. package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -1
  115. package/src/__tests__/server-history-render.test.ts +83 -4
  116. package/src/__tests__/steer-tool-repair.test.ts +249 -0
  117. package/src/__tests__/system-prompt.test.ts +57 -101
  118. package/src/__tests__/terminal-tools.test.ts +11 -1
  119. package/src/__tests__/thinking-block-replay.test.ts +113 -0
  120. package/src/__tests__/thread-backfill.test.ts +370 -22
  121. package/src/__tests__/tool-executor.test.ts +90 -1
  122. package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
  123. package/src/__tests__/twilio-routes.test.ts +1 -1
  124. package/src/__tests__/web-fetch.test.ts +2 -2
  125. package/src/__tests__/workspace-git-service.test.ts +88 -5
  126. package/src/__tests__/workspace-migration-087-memory-router-balanced-profile.test.ts +228 -0
  127. package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
  128. package/src/a2a/__tests__/agent-card.test.ts +98 -0
  129. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +597 -0
  130. package/src/a2a/__tests__/protocol-helpers.test.ts +113 -0
  131. package/src/a2a/__tests__/task-store.test.ts +246 -0
  132. package/src/a2a/agent-card.ts +58 -0
  133. package/src/a2a/feature-gate.ts +8 -0
  134. package/src/a2a/protocol-constants.ts +21 -0
  135. package/src/a2a/protocol-errors.ts +50 -0
  136. package/src/a2a/protocol-types.ts +162 -0
  137. package/src/a2a/task-store.ts +168 -0
  138. package/src/agent/attachments.ts +1 -0
  139. package/src/agent/loop.ts +208 -22
  140. package/src/background-wake/next-wake.test.ts +289 -0
  141. package/src/background-wake/next-wake.ts +172 -0
  142. package/src/browser/operations.ts +15 -0
  143. package/src/channels/config.ts +9 -0
  144. package/src/channels/types.ts +14 -0
  145. package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
  146. package/src/cli/commands/__tests__/memory-v2.test.ts +9 -12
  147. package/src/cli/{__tests__ → commands/__tests__}/notifications.test.ts +201 -28
  148. package/src/cli/commands/__tests__/schedules.test.ts +469 -0
  149. package/src/cli/commands/conversations.ts +128 -1
  150. package/src/cli/commands/inference-providers.ts +147 -1
  151. package/src/cli/commands/memory-v2.ts +308 -0
  152. package/src/cli/commands/notifications.ts +89 -37
  153. package/src/cli/commands/plugins.ts +67 -0
  154. package/src/cli/commands/schedules.ts +297 -5
  155. package/src/cli/lib/__tests__/search-plugins.test.ts +261 -0
  156. package/src/cli/lib/install-from-github.ts +8 -9
  157. package/src/cli/lib/search-plugins.ts +163 -0
  158. package/src/cli/program.ts +14 -0
  159. package/src/cli/utils/conversation-id.ts +17 -5
  160. package/src/config/assistant-feature-flags.ts +24 -54
  161. package/src/config/bundled-skills/app-builder/SKILL.md +117 -1
  162. package/src/config/bundled-skills/document-editor/SKILL.md +115 -0
  163. package/src/config/bundled-skills/document-editor/TOOLS.json +240 -0
  164. package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
  165. package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
  166. package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
  167. package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
  168. package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
  169. package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
  170. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
  171. package/src/config/bundled-skills/schedule/SKILL.md +8 -0
  172. package/src/config/bundled-tool-registry.ts +22 -12
  173. package/src/config/call-site-defaults.ts +124 -0
  174. package/src/config/feature-flag-registry.json +111 -23
  175. package/src/config/llm-resolver.ts +66 -1
  176. package/src/config/schema.ts +2 -0
  177. package/src/config/schemas/__tests__/memory-v2.test.ts +7 -3
  178. package/src/config/schemas/call-site-catalog.ts +21 -0
  179. package/src/config/schemas/channels.ts +9 -0
  180. package/src/config/schemas/conversations.ts +10 -0
  181. package/src/config/schemas/heartbeat.ts +14 -0
  182. package/src/config/schemas/llm.ts +4 -3
  183. package/src/config/schemas/memory-retrospective.ts +1 -1
  184. package/src/config/schemas/memory-v2.ts +51 -4
  185. package/src/config/schemas/memory.ts +3 -1
  186. package/src/config/seed-inference-profiles.ts +99 -29
  187. package/src/context/compactor.ts +80 -13
  188. package/src/context/token-estimator.ts +72 -31
  189. package/src/context/window-manager.ts +25 -0
  190. package/src/credential-health/credential-health-service.ts +34 -19
  191. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -22
  192. package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
  193. package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
  194. package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
  195. package/src/daemon/conversation-agent-loop-handlers.ts +231 -23
  196. package/src/daemon/conversation-agent-loop.ts +252 -56
  197. package/src/daemon/conversation-lifecycle.ts +142 -116
  198. package/src/daemon/conversation-messaging.ts +3 -0
  199. package/src/daemon/conversation-process.ts +273 -0
  200. package/src/daemon/conversation-queue-manager.ts +14 -0
  201. package/src/daemon/conversation-runtime-assembly.ts +144 -75
  202. package/src/daemon/conversation-slash.ts +37 -5
  203. package/src/daemon/conversation-surfaces.ts +45 -2
  204. package/src/daemon/conversation-tool-setup.ts +7 -0
  205. package/src/daemon/conversation.ts +42 -12
  206. package/src/daemon/date-context.ts +40 -0
  207. package/src/daemon/first-greeting.ts +10 -0
  208. package/src/daemon/guardian-action-generators.ts +1 -125
  209. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
  210. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +248 -0
  211. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +154 -0
  212. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +133 -0
  213. package/src/daemon/handlers/__tests__/config-a2a.test.ts +95 -0
  214. package/src/daemon/handlers/config-a2a.ts +449 -0
  215. package/src/daemon/handlers/config-model.test.ts +1 -0
  216. package/src/daemon/handlers/conversations.ts +80 -0
  217. package/src/daemon/handlers/shared.ts +92 -29
  218. package/src/daemon/host-app-control-proxy.ts +69 -18
  219. package/src/daemon/host-bash-proxy.ts +1 -1
  220. package/src/daemon/host-cu-proxy.ts +1 -1
  221. package/src/daemon/host-file-proxy.ts +1 -1
  222. package/src/daemon/host-proxy-preactivation.ts +85 -18
  223. package/src/daemon/host-transfer-proxy.ts +1 -1
  224. package/src/daemon/lifecycle.ts +67 -65
  225. package/src/daemon/memory-v2-startup.ts +49 -13
  226. package/src/daemon/message-protocol.ts +4 -0
  227. package/src/daemon/message-types/conversations.ts +8 -0
  228. package/src/daemon/message-types/document-comments.ts +50 -0
  229. package/src/daemon/message-types/messages.ts +68 -1
  230. package/src/daemon/message-types/notifications.ts +21 -0
  231. package/src/daemon/message-types/surfaces.ts +3 -1
  232. package/src/daemon/message-types/web-activity.ts +57 -0
  233. package/src/daemon/pkb-reminder-builder.test.ts +10 -53
  234. package/src/daemon/pkb-reminder-builder.ts +4 -19
  235. package/src/daemon/plugin-source-watcher.ts +135 -3
  236. package/src/daemon/process-message.ts +72 -12
  237. package/src/daemon/query-complexity-router.ts +75 -0
  238. package/src/daemon/skill-memory-refresh.ts +5 -1
  239. package/src/daemon/trust-context.ts +6 -0
  240. package/src/daemon/wake-target-adapter.ts +2 -0
  241. package/src/documents/document-comments-store.test.ts +338 -0
  242. package/src/documents/document-comments-store.ts +237 -0
  243. package/src/documents/document-store.ts +202 -0
  244. package/src/export/__tests__/transcript-formatter.test.ts +121 -0
  245. package/src/export/transcript-formatter.ts +54 -20
  246. package/src/heartbeat/__tests__/heartbeat-service.test.ts +44 -1
  247. package/src/heartbeat/heartbeat-service.ts +35 -191
  248. package/src/home/__tests__/feed-types.test.ts +40 -0
  249. package/src/home/__tests__/suggested-prompts.test.ts +33 -2
  250. package/src/home/feed-types.ts +20 -3
  251. package/src/home/home-content-refresh.ts +52 -0
  252. package/src/home/home-greeting-cache.ts +69 -0
  253. package/src/home/home-greeting.ts +94 -0
  254. package/src/home/suggested-prompts.ts +177 -9
  255. package/src/ipc/cli-client.ts +147 -45
  256. package/src/memory/__tests__/conversation-queries.test.ts +220 -0
  257. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
  258. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +2 -50
  259. package/src/memory/__tests__/memory-retrospective-job.test.ts +407 -10
  260. package/src/memory/conversation-crud.ts +133 -43
  261. package/src/memory/conversation-queries.ts +87 -1
  262. package/src/memory/conversation-title-service.ts +26 -4
  263. package/src/memory/db-init.ts +22 -0
  264. package/src/memory/delivery-crud.ts +41 -0
  265. package/src/memory/delivery-status.ts +141 -15
  266. package/src/memory/external-conversation-store.ts +32 -1
  267. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +84 -3
  268. package/src/memory/graph/conversation-graph-memory.ts +18 -6
  269. package/src/memory/graph/tools.ts +6 -37
  270. package/src/memory/invite-store.ts +53 -0
  271. package/src/memory/jobs-worker.ts +21 -1
  272. package/src/memory/llm-request-log-source-clickhouse.ts +7 -2
  273. package/src/memory/llm-request-log-store.ts +92 -1
  274. package/src/memory/memory-retrospective-constants.ts +28 -0
  275. package/src/memory/memory-retrospective-enqueue.ts +4 -22
  276. package/src/memory/memory-retrospective-job.ts +438 -21
  277. package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
  278. package/src/memory/memory-v2-activation-log-store.ts +26 -8
  279. package/src/memory/migrations/100-core-tables.ts +1 -0
  280. package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
  281. package/src/memory/migrations/250-provider-connection-base-url-and-models.ts +28 -0
  282. package/src/memory/migrations/251-a2a-tasks.ts +49 -0
  283. package/src/memory/migrations/252-llm-request-log-agent-loop-exit-reason.ts +32 -0
  284. package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
  285. package/src/memory/migrations/253-document-comments.ts +47 -0
  286. package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
  287. package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
  288. package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
  289. package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
  290. package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
  291. package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
  292. package/src/memory/migrations/index.ts +20 -0
  293. package/src/memory/migrations/registry.ts +33 -0
  294. package/src/memory/onboarding-events-store.ts +7 -0
  295. package/src/memory/schema/a2a.ts +15 -0
  296. package/src/memory/schema/calls.ts +1 -0
  297. package/src/memory/schema/conversations.ts +3 -0
  298. package/src/memory/schema/index.ts +1 -0
  299. package/src/memory/schema/inference.ts +2 -0
  300. package/src/memory/schema/infrastructure.ts +2 -0
  301. package/src/memory/v2/__tests__/activation-store.test.ts +25 -23
  302. package/src/memory/v2/__tests__/cli-command-store.test.ts +404 -0
  303. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +25 -4
  304. package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
  305. package/src/memory/v2/__tests__/injection.test.ts +221 -17
  306. package/src/memory/v2/__tests__/page-index.test.ts +365 -1
  307. package/src/memory/v2/__tests__/router.test.ts +489 -1
  308. package/src/memory/v2/__tests__/static-context.test.ts +12 -1
  309. package/src/memory/v2/activation-store.ts +14 -16
  310. package/src/memory/v2/cli-command-content.ts +19 -0
  311. package/src/memory/v2/cli-command-store.ts +304 -0
  312. package/src/memory/v2/consolidation-job.ts +14 -0
  313. package/src/memory/v2/frontmatter-sweep.ts +7 -1
  314. package/src/memory/v2/injection-events.ts +101 -0
  315. package/src/memory/v2/injection.ts +69 -29
  316. package/src/memory/v2/page-index.ts +246 -19
  317. package/src/memory/v2/page-store.ts +18 -0
  318. package/src/memory/v2/router.ts +209 -55
  319. package/src/memory/v2/static-context.ts +4 -4
  320. package/src/memory/v2/types.ts +23 -0
  321. package/src/messaging/providers/a2a/__tests__/deliver.test.ts +274 -0
  322. package/src/messaging/providers/a2a/deliver.ts +156 -0
  323. package/src/messaging/providers/gmail/client.ts +9 -2
  324. package/src/messaging/providers/index.ts +18 -3
  325. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
  326. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
  327. package/src/messaging/providers/slack/adapter.ts +178 -25
  328. package/src/messaging/providers/slack/api.test.ts +54 -0
  329. package/src/messaging/providers/slack/api.ts +119 -3
  330. package/src/messaging/providers/slack/client.ts +12 -0
  331. package/src/messaging/providers/slack/deep-link.ts +20 -1
  332. package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
  333. package/src/messaging/providers/slack/message-metadata.ts +156 -0
  334. package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
  335. package/src/messaging/providers/slack/render-transcript.ts +176 -49
  336. package/src/messaging/providers/slack/send.test.ts +77 -0
  337. package/src/messaging/providers/slack/send.ts +8 -2
  338. package/src/messaging/providers/slack/types.ts +14 -0
  339. package/src/notifications/__tests__/broadcaster.test.ts +203 -0
  340. package/src/notifications/__tests__/decision-engine.test.ts +283 -0
  341. package/src/notifications/__tests__/deterministic-checks.test.ts +286 -0
  342. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +5 -1
  343. package/src/notifications/__tests__/home-feed-side-effect.test.ts +521 -36
  344. package/src/notifications/adapters/macos.ts +12 -2
  345. package/src/notifications/broadcaster.ts +29 -4
  346. package/src/notifications/conversation-seed-composer.ts +14 -2
  347. package/src/notifications/copy-composer.ts +17 -64
  348. package/src/notifications/decision-engine.ts +111 -44
  349. package/src/notifications/deferred-emit.ts +135 -0
  350. package/src/notifications/deterministic-checks.ts +96 -0
  351. package/src/notifications/emit-signal.ts +10 -1
  352. package/src/notifications/home-feed-side-effect.ts +136 -27
  353. package/src/notifications/signal.ts +0 -4
  354. package/src/notifications/types.ts +8 -0
  355. package/src/oauth/connect-orchestrator.ts +3 -0
  356. package/src/oauth/credential-token-resolver.ts +2 -0
  357. package/src/oauth/manual-token-connection.ts +19 -0
  358. package/src/oauth/oauth-store.ts +12 -0
  359. package/src/oauth/platform-connection.test.ts +43 -3
  360. package/src/oauth/platform-connection.ts +13 -4
  361. package/src/oauth/seed-providers.ts +22 -0
  362. package/src/permissions/prompter.ts +5 -2
  363. package/src/permissions/secret-prompter.ts +4 -1
  364. package/src/plugins/defaults/injectors.ts +118 -26
  365. package/src/plugins/external-plugin-loader.ts +82 -10
  366. package/src/plugins/types.ts +16 -7
  367. package/src/prompts/__tests__/system-prompt.test.ts +44 -45
  368. package/src/prompts/__tests__/task-progress-hint-section.test.ts +4 -8
  369. package/src/prompts/normalize-onboarding.ts +40 -0
  370. package/src/prompts/sections.ts +32 -14
  371. package/src/prompts/system-prompt.ts +105 -76
  372. package/src/prompts/template-detection.ts +37 -0
  373. package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
  374. package/src/prompts/templates/BOOTSTRAP.md +13 -5
  375. package/src/prompts/templates/VOICE.md +3 -0
  376. package/src/prompts/templates/system-sections.ts +51 -10
  377. package/src/providers/__tests__/inference.test.ts +2 -0
  378. package/src/providers/anthropic/client.ts +132 -5
  379. package/src/providers/call-site-routing.ts +24 -6
  380. package/src/providers/connection-resolution.ts +63 -13
  381. package/src/providers/fireworks/client.ts +20 -2
  382. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +74 -0
  383. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
  384. package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
  385. package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
  386. package/src/providers/inference/__tests__/connections-openai-compatible.test.ts +175 -0
  387. package/src/providers/inference/__tests__/connections-status-label.test.ts +15 -0
  388. package/src/providers/inference/adapter-factory.ts +24 -21
  389. package/src/providers/inference/auth.ts +15 -3
  390. package/src/providers/inference/backfill.ts +14 -1
  391. package/src/providers/inference/codex-token-refresh.ts +128 -0
  392. package/src/providers/inference/connections.ts +85 -5
  393. package/src/providers/inference/resolve-auth.ts +50 -5
  394. package/src/providers/model-catalog.ts +244 -242
  395. package/src/providers/model-intents.ts +3 -3
  396. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +235 -0
  397. package/src/providers/openai/chat-completions-provider.ts +215 -25
  398. package/src/providers/openai/responses-provider.ts +9 -3
  399. package/src/providers/openrouter/client.ts +46 -4
  400. package/src/providers/platform-proxy/constants.ts +3 -4
  401. package/src/providers/provider-catalog-visibility.ts +3 -1
  402. package/src/providers/provider-send-message.ts +27 -12
  403. package/src/providers/registry.ts +30 -1
  404. package/src/providers/types.ts +25 -0
  405. package/src/runtime/__tests__/agent-wake.test.ts +214 -0
  406. package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
  407. package/src/runtime/agent-wake.ts +212 -57
  408. package/src/runtime/auth/route-policy.ts +20 -3
  409. package/src/runtime/background-job-runner.ts +26 -0
  410. package/src/runtime/channel-reply-delivery.ts +182 -47
  411. package/src/runtime/channel-retry-sweep.ts +141 -16
  412. package/src/runtime/http-server.ts +7 -16
  413. package/src/runtime/http-types.ts +7 -51
  414. package/src/runtime/pending-interactions.ts +51 -8
  415. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +258 -0
  416. package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
  417. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +121 -5
  418. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +275 -44
  419. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +12 -0
  420. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
  421. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +271 -0
  422. package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
  423. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
  424. package/src/runtime/routes/approval-routes.ts +4 -1
  425. package/src/runtime/routes/channel-availability-routes.ts +5 -0
  426. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
  427. package/src/runtime/routes/consolidation-routes.ts +100 -0
  428. package/src/runtime/routes/content-source-routes.ts +78 -0
  429. package/src/runtime/routes/conversation-cli-routes.ts +146 -1
  430. package/src/runtime/routes/conversation-query-routes.ts +130 -12
  431. package/src/runtime/routes/conversation-routes.ts +288 -76
  432. package/src/runtime/routes/document-comments-routes.ts +287 -0
  433. package/src/runtime/routes/documents-routes.ts +33 -0
  434. package/src/runtime/routes/home-feed-routes.ts +6 -3
  435. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  436. package/src/runtime/routes/host-browser-routes.ts +8 -1
  437. package/src/runtime/routes/identity-routes.ts +21 -0
  438. package/src/runtime/routes/inbound-message-handler.ts +288 -58
  439. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
  440. package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
  441. package/src/runtime/routes/index.ts +14 -4
  442. package/src/runtime/routes/inference-provider-connection-routes.ts +192 -3
  443. package/src/runtime/routes/integrations/a2a.ts +294 -0
  444. package/src/runtime/routes/llm-call-sites-routes.ts +11 -1
  445. package/src/runtime/routes/log-export-routes.ts +39 -0
  446. package/src/runtime/routes/memory-v2-routes.ts +217 -0
  447. package/src/runtime/routes/notification-routes.ts +19 -2
  448. package/src/runtime/routes/question-routes.ts +4 -1
  449. package/src/runtime/routes/sanity-routes.ts +159 -0
  450. package/src/runtime/routes/slack-channel-routes.ts +187 -0
  451. package/src/runtime/routes/subagents-routes.ts +41 -0
  452. package/src/runtime/services/conversation-serializer.ts +30 -4
  453. package/src/schedule/integration-status.ts +3 -1
  454. package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
  455. package/src/security/oauth2-device-code.ts +307 -0
  456. package/src/security/oauth2.ts +26 -9
  457. package/src/security/secure-keys.ts +5 -0
  458. package/src/skills/catalog-install.ts +6 -2
  459. package/src/subagent/manager.ts +2 -0
  460. package/src/tools/browser/__tests__/pinned-tabs.test.ts +80 -0
  461. package/src/tools/browser/browser-execution.ts +93 -0
  462. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
  463. package/src/tools/browser/cdp-client/__tests__/types.test.ts +1 -0
  464. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +10 -0
  465. package/src/tools/browser/cdp-client/extension-cdp-client.ts +15 -1
  466. package/src/tools/browser/cdp-client/factory.ts +87 -3
  467. package/src/tools/browser/cdp-client/local-cdp-client.ts +9 -0
  468. package/src/tools/browser/cdp-client/types.ts +36 -0
  469. package/src/tools/browser/pinned-tabs.ts +90 -0
  470. package/src/tools/document/document-comment-tool.test.ts +379 -0
  471. package/src/tools/document/document-comment-tool.ts +156 -0
  472. package/src/tools/document/document-tool.ts +128 -2
  473. package/src/tools/memory/register.ts +1 -9
  474. package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
  475. package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
  476. package/src/tools/network/domain-normalize.ts +17 -0
  477. package/src/tools/network/web-fetch.ts +213 -64
  478. package/src/tools/network/web-search.ts +191 -66
  479. package/src/tools/registry.ts +2 -2
  480. package/src/tools/terminal/safe-env.ts +3 -2
  481. package/src/tools/tool-approval-handler.ts +19 -12
  482. package/src/tools/types.ts +41 -2
  483. package/src/tools/ui-surface/definitions.ts +3 -1
  484. package/src/types/onboarding-context.ts +4 -0
  485. package/src/util/__tests__/favicon.test.ts +84 -0
  486. package/src/util/favicon.ts +40 -0
  487. package/src/util/platform.ts +0 -5
  488. package/src/workspace/git-service.ts +75 -4
  489. package/src/workspace/migrations/087-memory-router-balanced-profile.ts +91 -0
  490. package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
  491. package/src/workspace/migrations/registry.ts +4 -0
  492. package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -441
  493. package/src/config/bundled-skills/document/SKILL.md +0 -54
  494. package/src/config/bundled-skills/document/TOOLS.json +0 -106
  495. package/src/daemon/seed-files.ts +0 -18
  496. package/src/memory/graph/__tests__/remember-description.test.ts +0 -55
  497. package/src/runtime/guardian-action-conversation-turn.ts +0 -99
  498. package/src/runtime/routes/interface-routes.ts +0 -43
  499. /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
  500. /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
  501. /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
  502. /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
  503. /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
@@ -0,0 +1,40 @@
1
+ import { isPrivateOrLocalHost } from "../tools/network/url-safety.js";
2
+
3
+ /** Strip the trailing `:port` from a host string. IPv6 hosts are bracketed
4
+ * ("[::1]:8080" → "[::1]"); IPv4/DNS hosts have a single colon ("host:8080" → "host"). */
5
+ function stripPort(host: string): string {
6
+ if (host.startsWith("[")) {
7
+ const end = host.indexOf("]");
8
+ return end === -1 ? host : host.slice(0, end + 1);
9
+ }
10
+ const lastColon = host.lastIndexOf(":");
11
+ if (lastColon === -1) return host;
12
+ return host.slice(0, lastColon);
13
+ }
14
+
15
+ /** Match any IP literal — IPv4 dotted-quad or IPv6 (bracketed or bare with a colon).
16
+ * We reject every IP from the favicon path because we don't reverse-lookup hosts,
17
+ * so a raw IP — public or private — would expose the literal to Google when the
18
+ * client renders the icon. DNS names are fine; only literals are rejected. */
19
+ function isIPLiteral(host: string): boolean {
20
+ if (/^\d{1,3}(\.\d{1,3}){3}$/.test(host)) return true;
21
+ if (host.startsWith("[") || host.includes(":")) return true;
22
+ return false;
23
+ }
24
+
25
+ /** Deterministic favicon URL for a host using Google's s2 service.
26
+ * Returns undefined for empty/malformed hosts, raw IP literals, and any host
27
+ * isPrivateOrLocalHost flags. Callers omit the field on undefined so we never
28
+ * leak internal hostnames or arbitrary IPs to Google when clients render the
29
+ * icon. */
30
+ export function faviconUrlForDomain(domain: string): string | undefined {
31
+ const trimmed = domain.trim().toLowerCase();
32
+ if (!trimmed || trimmed.includes("/") || trimmed.includes(" ")) {
33
+ return undefined;
34
+ }
35
+ const hostOnly = stripPort(trimmed);
36
+ if (!hostOnly || isIPLiteral(hostOnly) || isPrivateOrLocalHost(hostOnly)) {
37
+ return undefined;
38
+ }
39
+ return `https://www.google.com/s2/favicons?domain=${encodeURIComponent(hostOnly)}&sz=64`;
40
+ }
@@ -103,10 +103,6 @@ export function getSandboxWorkingDir(): string {
103
103
  return getWorkspaceDir();
104
104
  }
105
105
 
106
- export function getInterfacesDir(): string {
107
- return join(getDataDir(), "interfaces");
108
- }
109
-
110
106
  /**
111
107
  * Returns the sounds directory (~/.vellum/workspace/data/sounds).
112
108
  * Custom sound files and sound configuration live here.
@@ -413,7 +409,6 @@ export function ensureDataDir(): void {
413
409
  join(wsData, "memory", "knowledge"),
414
410
  join(wsData, "apps"),
415
411
  join(wsData, "attachments"),
416
- join(wsData, "interfaces"),
417
412
  join(wsData, "sounds"),
418
413
  ];
419
414
  for (const dir of dirs) {
@@ -1,5 +1,12 @@
1
1
  import { execFile, spawnSync } from "node:child_process";
2
- import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import {
3
+ chmodSync,
4
+ existsSync,
5
+ mkdirSync,
6
+ readFileSync,
7
+ unlinkSync,
8
+ writeFileSync,
9
+ } from "node:fs";
3
10
  import { join } from "node:path";
4
11
  import { promisify } from "node:util";
5
12
 
@@ -70,6 +77,41 @@ const WORKSPACE_GITIGNORE_RULES = [
70
77
  "session-token",
71
78
  ];
72
79
 
80
+ const NULL_GIT_OID = "0000000000000000000000000000000000000000";
81
+
82
+ const WORKSPACE_BRANCH_GUARD_HOOK = `#!/bin/sh
83
+ set -eu
84
+
85
+ state="\${1:-}"
86
+ if [ "$state" != "prepared" ]; then
87
+ exit 0
88
+ fi
89
+
90
+ while read -r _old_oid new_oid refname; do
91
+ case "$refname" in
92
+ refs/heads/main)
93
+ ;;
94
+ refs/heads/*)
95
+ if [ "$new_oid" = "${NULL_GIT_OID}" ]; then
96
+ continue
97
+ fi
98
+
99
+ cat >&2 <<MSG
100
+ Blocked: assistant workspace git branches are disabled.
101
+
102
+ Use the workspace main branch for assistant state. Create task branches only in
103
+ external product repositories or dedicated worktrees.
104
+
105
+ Rejected ref update: $refname
106
+ MSG
107
+ exit 1
108
+ ;;
109
+ esac
110
+ done
111
+
112
+ exit 0
113
+ `;
114
+
73
115
  /** Properties added by Node's child_process errors. */
74
116
  interface ExecError extends Error {
75
117
  killed?: boolean;
@@ -426,7 +468,9 @@ export class WorkspaceGitService {
426
468
  // These calls are OUTSIDE the rev-parse try/catch so that
427
469
  // normalization errors are not misclassified as "no commits".
428
470
  this.ensureGitignoreRulesLocked();
471
+ this.ensureBranchGuardHookLocked();
429
472
  await this.ensureCommitIdentityLocked();
473
+ await this.ensureBranchGuardConfigLocked();
430
474
  await this.ensureOnMainLocked();
431
475
  this.initialized = true;
432
476
  this.recordInitSuccess();
@@ -444,7 +488,9 @@ export class WorkspaceGitService {
444
488
  // in the corruption-recovery path we fall through here after
445
489
  // removing .git, so branch enforcement is still useful.
446
490
  this.ensureGitignoreRulesLocked();
491
+ this.ensureBranchGuardHookLocked();
447
492
  await this.ensureCommitIdentityLocked();
493
+ await this.ensureBranchGuardConfigLocked();
448
494
  await this.ensureOnMainLocked();
449
495
 
450
496
  // Create initial commit synchronously within the lock to prevent
@@ -452,9 +498,14 @@ export class WorkspaceGitService {
452
498
  // initial commit could run concurrently and consume edits meant
453
499
  // for the first user-requested commit.
454
500
  const status = await this.getStatusInternal();
455
- const hasExistingFiles =
456
- status.untracked.length > 1 || // More than just .gitignore
457
- status.untracked.some((f) => f !== ".gitignore");
501
+ const autoCreatedInitFiles = new Set([
502
+ ".gitignore",
503
+ ".githooks/",
504
+ ".githooks/reference-transaction",
505
+ ]);
506
+ const hasExistingFiles = status.untracked.some(
507
+ (f) => !autoCreatedInitFiles.has(f),
508
+ );
458
509
 
459
510
  await this.execGit(["add", "-A"]);
460
511
 
@@ -766,6 +817,26 @@ export class WorkspaceGitService {
766
817
  await this.execGit(["config", "user.email", gitEmail]);
767
818
  }
768
819
 
820
+ /**
821
+ * Ensure workspace branch guard hook is present.
822
+ * Must be called with the mutex lock held.
823
+ */
824
+ private ensureBranchGuardHookLocked(): void {
825
+ const hooksDir = join(this.workspaceDir, ".githooks");
826
+ const hookPath = join(hooksDir, "reference-transaction");
827
+ mkdirSync(hooksDir, { recursive: true });
828
+ writeFileSync(hookPath, WORKSPACE_BRANCH_GUARD_HOOK, "utf-8");
829
+ chmodSync(hookPath, 0o755);
830
+ }
831
+
832
+ /**
833
+ * Ensure workspace git uses the branch guard hook path.
834
+ * Must be called with the mutex lock held.
835
+ */
836
+ private async ensureBranchGuardConfigLocked(): Promise<void> {
837
+ await this.execGit(["config", "core.hooksPath", ".githooks"]);
838
+ }
839
+
769
840
  /**
770
841
  * Ensure the workspace repo is on the `main` branch.
771
842
  * If on a different branch or in detached HEAD state, switches to main
@@ -0,0 +1,91 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { WorkspaceMigration } from "./types.js";
5
+
6
+ // Upgrade callSites.memoryRouter from the 077-seeded
7
+ // {model: "claude-sonnet-4-6", contextWindow: {maxInputTokens: 1_000_000}}
8
+ // shape to {profile: "balanced"} so the router rides the workspace's active
9
+ // inference profile (with thinking enabled, higher effort, etc.) instead of a
10
+ // bare model pin.
11
+ //
12
+ // Two skip conditions guard against runtime regressions:
13
+ //
14
+ // 1. BYOK / non-Anthropic workspaces. `balanced` resolves to the managed
15
+ // Anthropic connection (see seedInferenceProfiles), which off-platform
16
+ // installs explicitly disable. Forcing `balanced` there would make
17
+ // getConfiguredProvider("memoryRouter") return null and silently
18
+ // disable memory injection. Detect this by inspecting llm.default.provider
19
+ // — same heuristic migration 077 used to gate its seed.
20
+ //
21
+ // 2. User-customized memoryRouter config. If the existing entry isn't the
22
+ // exact 077-seeded shape (and isn't already {profile: "balanced"}), the
23
+ // user — or a platform overlay — chose those values deliberately. Match
24
+ // 077's pattern of preserving any prior config.
25
+ export const memoryRouterBalancedProfileMigration: WorkspaceMigration = {
26
+ id: "087-memory-router-balanced-profile",
27
+ description:
28
+ "Set callSites.memoryRouter to { profile: 'balanced' }, dropping the seeded model and contextWindow override",
29
+ run(workspaceDir: string): void {
30
+ if (process.env.VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH) return;
31
+
32
+ const configPath = join(workspaceDir, "config.json");
33
+ const configExisted = existsSync(configPath);
34
+
35
+ let config: Record<string, unknown> = {};
36
+ if (configExisted) {
37
+ try {
38
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
39
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
40
+ config = raw as Record<string, unknown>;
41
+ } catch {
42
+ return;
43
+ }
44
+ }
45
+
46
+ const llm = readObject(config.llm) ?? {};
47
+
48
+ const explicitProvider = readString(readObject(llm.default)?.provider);
49
+ if (explicitProvider !== undefined && explicitProvider !== "anthropic") {
50
+ return;
51
+ }
52
+
53
+ const callSites = readObject(llm.callSites) ?? {};
54
+ const existing = readObject(callSites.memoryRouter);
55
+
56
+ if (existing !== null && !isSeededBy077(existing)) {
57
+ return;
58
+ }
59
+
60
+ callSites.memoryRouter = { profile: "balanced" };
61
+ llm.callSites = callSites;
62
+ config.llm = llm;
63
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
64
+ },
65
+ down(_workspaceDir: string): void {
66
+ // Forward-only.
67
+ },
68
+ };
69
+
70
+ // True when the entry looks exactly like what migration 077 wrote: a model pin
71
+ // of claude-sonnet-4-6 plus the 1M-token context window, and nothing else.
72
+ function isSeededBy077(entry: Record<string, unknown>): boolean {
73
+ const keys = Object.keys(entry);
74
+ if (keys.length !== 2) return false;
75
+ if (entry.model !== "claude-sonnet-4-6") return false;
76
+ const contextWindow = readObject(entry.contextWindow);
77
+ if (contextWindow === null) return false;
78
+ const cwKeys = Object.keys(contextWindow);
79
+ return cwKeys.length === 1 && contextWindow.maxInputTokens === 1_000_000;
80
+ }
81
+
82
+ function readObject(value: unknown): Record<string, unknown> | null {
83
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
84
+ return null;
85
+ }
86
+ return value as Record<string, unknown>;
87
+ }
88
+
89
+ function readString(value: unknown): string | undefined {
90
+ return typeof value === "string" && value.length > 0 ? value : undefined;
91
+ }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Workspace migration 088: Deprecate stale
3
+ * `prompts/system/08-background-conversation.md` overrides.
4
+ *
5
+ * PR #31210 moved the background-conversation guidance out of the bundled
6
+ * system prompt and into a per-turn user-message injector. As a side effect:
7
+ *
8
+ * - Workspace overrides that gated on `{{#isBackgroundConversation}}` now
9
+ * evaluate the gate as false (the key is no longer passed to the system
10
+ * prompt context) and silently stop rendering in background turns.
11
+ * - Plain-text overrides without a gate would now render unconditionally
12
+ * in ALL conversations — the opposite of intended behavior.
13
+ *
14
+ * Either failure mode is silent. To prevent it, this migration renames any
15
+ * existing `prompts/system/08-background-conversation.md` to
16
+ * `08-background-conversation.md.deprecated` so the section-discovery walker
17
+ * (which only picks up `.md` files) stops loading it, while preserving the
18
+ * user's customized text on disk for manual review.
19
+ *
20
+ * Idempotent: re-runs after `08-background-conversation.md` has already been
21
+ * renamed are no-ops. If both files exist (a user re-created the override
22
+ * after a prior partial run), the bundled section is gone — drop the `.md`
23
+ * and keep the previously-preserved `.deprecated` copy.
24
+ */
25
+
26
+ import { existsSync, renameSync, unlinkSync } from "node:fs";
27
+ import { join } from "node:path";
28
+
29
+ import { getLogger } from "../../util/logger.js";
30
+ import type { WorkspaceMigration } from "./types.js";
31
+
32
+ const log = getLogger(
33
+ "workspace-migration-088-deprecate-background-conversation-override",
34
+ );
35
+
36
+ const OVERRIDE_FILENAME = "08-background-conversation.md";
37
+ const DEPRECATED_FILENAME = "08-background-conversation.md.deprecated";
38
+
39
+ export const deprecateBackgroundConversationOverrideMigration: WorkspaceMigration =
40
+ {
41
+ id: "088-deprecate-background-conversation-override",
42
+ description:
43
+ "Rename stale prompts/system/08-background-conversation.md overrides to .deprecated so they stop rendering after the section moved to a per-turn injector",
44
+ retryFailedCheckpoint: true,
45
+
46
+ run(workspaceDir: string): void {
47
+ const promptDir = join(workspaceDir, "prompts", "system");
48
+ const overridePath = join(promptDir, OVERRIDE_FILENAME);
49
+ const deprecatedPath = join(promptDir, DEPRECATED_FILENAME);
50
+
51
+ if (!existsSync(overridePath)) return;
52
+
53
+ if (existsSync(deprecatedPath)) {
54
+ try {
55
+ unlinkSync(overridePath);
56
+ log.info(
57
+ { path: overridePath, preserved: deprecatedPath },
58
+ "Removed re-created background-conversation override; preserved copy already exists",
59
+ );
60
+ } catch (err) {
61
+ log.warn(
62
+ { err, path: overridePath },
63
+ "Failed to remove background-conversation override",
64
+ );
65
+ throw err;
66
+ }
67
+ return;
68
+ }
69
+
70
+ try {
71
+ renameSync(overridePath, deprecatedPath);
72
+ log.info(
73
+ { from: overridePath, to: deprecatedPath },
74
+ "Renamed stale background-conversation override to .deprecated",
75
+ );
76
+ } catch (err) {
77
+ log.warn(
78
+ { err, from: overridePath, to: deprecatedPath },
79
+ "Failed to rename background-conversation override",
80
+ );
81
+ throw err;
82
+ }
83
+ },
84
+
85
+ down(workspaceDir: string): void {
86
+ const promptDir = join(workspaceDir, "prompts", "system");
87
+ const overridePath = join(promptDir, OVERRIDE_FILENAME);
88
+ const deprecatedPath = join(promptDir, DEPRECATED_FILENAME);
89
+
90
+ if (!existsSync(deprecatedPath)) return;
91
+ if (existsSync(overridePath)) return;
92
+
93
+ try {
94
+ renameSync(deprecatedPath, overridePath);
95
+ } catch (err) {
96
+ log.warn(
97
+ { err, from: deprecatedPath, to: overridePath },
98
+ "Failed to restore background-conversation override",
99
+ );
100
+ throw err;
101
+ }
102
+ },
103
+ };
@@ -84,6 +84,8 @@ import { systemPromptPrefixToFileMigration } from "./083-system-prompt-prefix-to
84
84
  import { removeLegacySkillsIndexMigration } from "./084-remove-legacy-skills-index.js";
85
85
  import { memoryV2Bm25BReembedDisabledV2PagesMigration } from "./085-memory-v2-bm25-b-reembed-disabled-v2-pages.js";
86
86
  import { revertStaleGeminiMisRewritesMigration } from "./086-revert-stale-gemini-mis-rewrites.js";
87
+ import { memoryRouterBalancedProfileMigration } from "./087-memory-router-balanced-profile.js";
88
+ import { deprecateBackgroundConversationOverrideMigration } from "./088-deprecate-background-conversation-override.js";
87
89
  import { migrateToWorkspaceVolumeMigration } from "./migrate-to-workspace-volume.js";
88
90
  import type { WorkspaceMigration } from "./types.js";
89
91
 
@@ -179,4 +181,6 @@ export const WORKSPACE_MIGRATIONS: WorkspaceMigration[] = [
179
181
  removeLegacySkillsIndexMigration,
180
182
  memoryV2Bm25BReembedDisabledV2PagesMigration,
181
183
  revertStaleGeminiMisRewritesMigration,
184
+ memoryRouterBalancedProfileMigration,
185
+ deprecateBackgroundConversationOverrideMigration,
182
186
  ];