@vellumai/assistant 0.7.3 → 0.8.1

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 (778) hide show
  1. package/AGENTS.md +11 -0
  2. package/ARCHITECTURE.md +29 -28
  3. package/Dockerfile +6 -4
  4. package/README.md +2 -2
  5. package/__tests__/permissions/gateway-threshold-reader.test.ts +236 -9
  6. package/bun.lock +3 -0
  7. package/docker-entrypoint.sh +16 -0
  8. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  9. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  10. package/eslint.config.mjs +12 -0
  11. package/knip.json +3 -1
  12. package/node_modules/@vellumai/ipc-server-utils/bun.lock +24 -0
  13. package/node_modules/@vellumai/ipc-server-utils/package.json +18 -0
  14. package/node_modules/@vellumai/ipc-server-utils/src/index.ts +6 -0
  15. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +430 -0
  16. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +221 -0
  17. package/node_modules/@vellumai/ipc-server-utils/tsconfig.json +20 -0
  18. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  19. package/openapi.yaml +4126 -959
  20. package/package.json +5 -1
  21. package/scripts/generate-openapi.ts +52 -4
  22. package/scripts/sync-llm-catalog.ts +165 -0
  23. package/scripts/sync-web-search-catalog.ts +107 -0
  24. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  25. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  26. package/src/__tests__/annotate-risk-options.test.ts +291 -0
  27. package/src/__tests__/anthropic-provider.test.ts +92 -2
  28. package/src/__tests__/app-control-flow.test.ts +7 -0
  29. package/src/__tests__/approval-cascade.test.ts +8 -16
  30. package/src/__tests__/approval-routes-http.test.ts +6 -0
  31. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  32. package/src/__tests__/auto-analysis-end-to-end.test.ts +12 -25
  33. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  34. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  35. package/src/__tests__/btw-routes.test.ts +1 -0
  36. package/src/__tests__/call-constants.test.ts +10 -1
  37. package/src/__tests__/call-controller.test.ts +127 -0
  38. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  39. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  40. package/src/__tests__/channel-policy.test.ts +12 -0
  41. package/src/__tests__/checker.test.ts +89 -0
  42. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +88 -30
  43. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  44. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  45. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  46. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  47. package/src/__tests__/config-loader-platform-defaults.test.ts +345 -8
  48. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  49. package/src/__tests__/config-schema.test.ts +14 -3
  50. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  51. package/src/__tests__/config-set-route.test.ts +198 -0
  52. package/src/__tests__/config-watcher.test.ts +6 -0
  53. package/src/__tests__/contacts-tools.test.ts +51 -199
  54. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  55. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  56. package/src/__tests__/context-search-conversations-source.test.ts +42 -16
  57. package/src/__tests__/context-search-fanout.test.ts +20 -157
  58. package/src/__tests__/context-search-memory-source.test.ts +3 -26
  59. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
  60. package/src/__tests__/context-search-types.test.ts +7 -2
  61. package/src/__tests__/context-window-manager.test.ts +389 -1
  62. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -6
  63. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
  64. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
  65. package/src/__tests__/conversation-agent-loop.test.ts +3 -3
  66. package/src/__tests__/conversation-confirmation-signals.test.ts +5 -13
  67. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  68. package/src/__tests__/conversation-error.test.ts +38 -0
  69. package/src/__tests__/conversation-fork-crud.test.ts +241 -1
  70. package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
  71. package/src/__tests__/conversation-init.benchmark.test.ts +2 -1
  72. package/src/__tests__/conversation-lifecycle.test.ts +124 -0
  73. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  74. package/src/__tests__/conversation-process-callsite.test.ts +22 -7
  75. package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -6
  76. package/src/__tests__/conversation-runtime-assembly.test.ts +19 -10
  77. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  78. package/src/__tests__/conversation-slash-unknown.test.ts +1 -6
  79. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +170 -9
  80. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  81. package/src/__tests__/conversation-surfaces-data-persist.test.ts +73 -1
  82. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +59 -0
  83. package/src/__tests__/conversation-workspace-injection.test.ts +1 -7
  84. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -7
  85. package/src/__tests__/credential-security-invariants.test.ts +5 -6
  86. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  87. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  88. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  89. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  90. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  91. package/src/__tests__/external-plugin-loader.test.ts +458 -0
  92. package/src/__tests__/filing-service.test.ts +25 -22
  93. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  94. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  95. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  96. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +10 -34
  97. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  98. package/src/__tests__/heartbeat-service.test.ts +50 -233
  99. package/src/__tests__/history-repair.test.ts +89 -0
  100. package/src/__tests__/host-app-control-proxy.test.ts +109 -1
  101. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  102. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  103. package/src/__tests__/host-browser-routes.test.ts +325 -33
  104. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  105. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  106. package/src/__tests__/inference-profile-reaper.test.ts +154 -0
  107. package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
  108. package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
  109. package/src/__tests__/injector-chain.test.ts +24 -16
  110. package/src/__tests__/injector-pkb-v2-silenced.test.ts +10 -7
  111. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  112. package/src/__tests__/install-skill-routing.test.ts +2 -2
  113. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +169 -67
  114. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  115. package/src/__tests__/llm-catalog-parity.test.ts +146 -0
  116. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
  117. package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
  118. package/src/__tests__/llm-resolver.test.ts +46 -0
  119. package/src/__tests__/managed-profile-guard.test.ts +131 -2
  120. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  121. package/src/__tests__/mcp-cli.test.ts +182 -220
  122. package/src/__tests__/mcp-health-check.test.ts +56 -27
  123. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  124. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  125. package/src/__tests__/notification-decision-fallback.test.ts +91 -0
  126. package/src/__tests__/notification-decision-strategy.test.ts +22 -0
  127. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  128. package/src/__tests__/oauth-cli.test.ts +38 -1888
  129. package/src/__tests__/oauth-commands-routes.test.ts +711 -0
  130. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  131. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  132. package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
  133. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  134. package/src/__tests__/plugin-bootstrap.test.ts +31 -2
  135. package/src/__tests__/plugin-route-contribution.test.ts +31 -3
  136. package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
  137. package/src/__tests__/plugin-types.test.ts +13 -11
  138. package/src/__tests__/process-message-background-slack.test.ts +46 -0
  139. package/src/__tests__/profile-entry-status.test.ts +43 -0
  140. package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
  141. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  142. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  143. package/src/__tests__/relay-server.test.ts +164 -2
  144. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  145. package/src/__tests__/schedule-retry.test.ts +56 -4
  146. package/src/__tests__/schedule-routes.test.ts +104 -0
  147. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  148. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  149. package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
  150. package/src/__tests__/scheduler-wake.test.ts +0 -63
  151. package/src/__tests__/secret-allowlist.test.ts +1 -0
  152. package/src/__tests__/secret-prompt-log-hygiene.test.ts +7 -5
  153. package/src/__tests__/secret-prompter-channel-fallback.test.ts +7 -5
  154. package/src/__tests__/secret-response-routing.test.ts +7 -5
  155. package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
  156. package/src/__tests__/server-history-render.test.ts +82 -0
  157. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  158. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  159. package/src/__tests__/skill-include-graph.test.ts +31 -0
  160. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  161. package/src/__tests__/skill-load-tool.test.ts +42 -16
  162. package/src/__tests__/skills.test.ts +39 -0
  163. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  164. package/src/__tests__/suggestion-routes.test.ts +3 -3
  165. package/src/__tests__/sync-message-contract.test.ts +63 -0
  166. package/src/__tests__/task-scheduler.test.ts +88 -23
  167. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -42
  168. package/src/__tests__/tool-executor.test.ts +155 -0
  169. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  170. package/src/__tests__/usage-cli.test.ts +11 -73
  171. package/src/__tests__/user-plugin-loader.test.ts +145 -0
  172. package/src/__tests__/vercel-config.test.ts +168 -0
  173. package/src/__tests__/voice-session-bridge.test.ts +3 -0
  174. package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
  175. package/src/__tests__/web-search.test.ts +303 -2
  176. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  177. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
  178. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +153 -0
  179. package/src/__tests__/workspace-migration-071-remove-safe-storage-release-note.test.ts +206 -0
  180. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
  181. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  182. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  183. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  184. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  185. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  186. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  187. package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +15 -27
  188. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  189. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  190. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  191. package/src/acp/resolve-agent.test.ts +25 -0
  192. package/src/acp/resolve-agent.ts +13 -2
  193. package/src/acp/session-manager.ts +14 -0
  194. package/src/agent/loop.ts +11 -0
  195. package/src/approvals/guardian-decision-primitive.ts +0 -13
  196. package/src/approvals/guardian-request-resolvers.ts +19 -102
  197. package/src/calls/call-constants.ts +5 -8
  198. package/src/calls/call-controller.ts +130 -67
  199. package/src/calls/relay-server.ts +42 -1
  200. package/src/calls/relay-setup-router.ts +36 -0
  201. package/src/calls/types.ts +1 -0
  202. package/src/calls/voice-session-bridge.ts +24 -5
  203. package/src/channels/config.ts +14 -1
  204. package/src/channels/types.ts +1 -0
  205. package/src/cli/AGENTS.md +164 -4
  206. package/src/cli/__tests__/notifications.test.ts +54 -0
  207. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  208. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  209. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  210. package/src/cli/commands/__tests__/changelog.test.ts +593 -0
  211. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  212. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  213. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  214. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  215. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  216. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  217. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  218. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  219. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  220. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  221. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  222. package/src/cli/commands/__tests__/status.test.ts +249 -0
  223. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  224. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  225. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  226. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  227. package/src/cli/commands/attachment.ts +8 -3
  228. package/src/cli/commands/audit.ts +95 -64
  229. package/src/cli/commands/auth.ts +61 -58
  230. package/src/cli/commands/avatar.ts +276 -390
  231. package/src/cli/commands/backup.ts +409 -505
  232. package/src/cli/commands/bash.ts +9 -5
  233. package/src/cli/commands/browser.ts +28 -9
  234. package/src/cli/commands/cache.ts +9 -4
  235. package/src/cli/commands/changelog.ts +414 -0
  236. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  237. package/src/cli/commands/clients.ts +8 -3
  238. package/src/cli/commands/completions.ts +9 -9
  239. package/src/cli/commands/config.ts +102 -72
  240. package/src/cli/commands/contacts.ts +575 -696
  241. package/src/cli/commands/conversations-defer.ts +17 -69
  242. package/src/cli/commands/conversations-import.ts +90 -253
  243. package/src/cli/commands/conversations.ts +346 -436
  244. package/src/cli/commands/credential-execution.ts +9 -6
  245. package/src/cli/commands/credentials.ts +456 -736
  246. package/src/cli/commands/domain.ts +128 -206
  247. package/src/cli/commands/email.ts +606 -794
  248. package/src/cli/commands/gateway.ts +8 -1
  249. package/src/cli/commands/image-generation.ts +157 -205
  250. package/src/cli/commands/inference-providers.ts +352 -0
  251. package/src/cli/commands/inference-session.ts +415 -0
  252. package/src/cli/commands/inference.ts +87 -65
  253. package/src/cli/commands/keys.ts +8 -3
  254. package/src/cli/commands/mcp.ts +103 -287
  255. package/src/cli/commands/memory-v2.ts +163 -517
  256. package/src/cli/commands/notifications.ts +33 -7
  257. package/src/cli/commands/oauth/apps.ts +292 -261
  258. package/src/cli/commands/oauth/connect.ts +182 -345
  259. package/src/cli/commands/oauth/disconnect.ts +16 -215
  260. package/src/cli/commands/oauth/index.ts +49 -45
  261. package/src/cli/commands/oauth/mode.ts +43 -199
  262. package/src/cli/commands/oauth/ping.ts +17 -125
  263. package/src/cli/commands/oauth/providers.ts +732 -921
  264. package/src/cli/commands/oauth/request.ts +60 -350
  265. package/src/cli/commands/oauth/shared.ts +11 -121
  266. package/src/cli/commands/oauth/status.ts +31 -121
  267. package/src/cli/commands/oauth/token.ts +13 -55
  268. package/src/cli/commands/pending.ts +19 -10
  269. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  270. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  271. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  272. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  273. package/src/cli/commands/platform/connect.ts +16 -80
  274. package/src/cli/commands/platform/disconnect.ts +14 -112
  275. package/src/cli/commands/platform/index.ts +177 -246
  276. package/src/cli/commands/routes.ts +153 -336
  277. package/src/cli/commands/sequence.ts +316 -360
  278. package/src/cli/commands/skills.ts +449 -671
  279. package/src/cli/commands/status.ts +58 -37
  280. package/src/cli/commands/stt.ts +94 -262
  281. package/src/cli/commands/task.ts +14 -40
  282. package/src/cli/commands/trust.ts +8 -3
  283. package/src/cli/commands/tts.ts +162 -167
  284. package/src/cli/commands/ui.ts +35 -42
  285. package/src/cli/commands/usage.ts +188 -126
  286. package/src/cli/commands/watchers.ts +8 -3
  287. package/src/cli/commands/webhooks.ts +99 -193
  288. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  289. package/src/cli/lib/daemon-credential-client.ts +4 -5
  290. package/src/cli/lib/nested-value.ts +44 -0
  291. package/src/cli/lib/open-browser.ts +36 -0
  292. package/src/cli/lib/register-command.ts +19 -0
  293. package/src/cli/lib/time-ago.ts +34 -0
  294. package/src/cli/program.ts +2 -4
  295. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  296. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  297. package/src/cli/utils/conversation-id.ts +30 -0
  298. package/src/cli/utils/parse-duration.ts +41 -0
  299. package/src/config/acp-defaults.test.ts +5 -1
  300. package/src/config/acp-defaults.ts +11 -4
  301. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  302. package/src/config/bundled-skills/app-builder/SKILL.md +1 -3
  303. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  304. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  305. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  306. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  307. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  308. package/src/config/bundled-tool-registry.ts +0 -2
  309. package/src/config/feature-flag-registry.json +17 -17
  310. package/src/config/llm-resolver.ts +16 -1
  311. package/src/config/loader.ts +148 -33
  312. package/src/config/raw-config-utils.ts +2 -30
  313. package/src/config/schema.ts +4 -0
  314. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  315. package/src/config/schemas/call-site-catalog.ts +29 -7
  316. package/src/config/schemas/llm-request-logs.ts +57 -0
  317. package/src/config/schemas/llm.ts +52 -2
  318. package/src/config/schemas/memory-retrospective.ts +48 -0
  319. package/src/config/schemas/memory-v2.ts +33 -2
  320. package/src/config/schemas/memory.ts +4 -0
  321. package/src/config/schemas/services.ts +15 -12
  322. package/src/config/seed-inference-profiles.ts +195 -134
  323. package/src/contacts/contact-store.ts +0 -61
  324. package/src/context/window-manager.ts +191 -5
  325. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +111 -0
  326. package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
  327. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  328. package/src/daemon/approval-generators.ts +23 -29
  329. package/src/daemon/config-watcher.ts +2 -0
  330. package/src/daemon/conversation-agent-loop-handlers.ts +56 -0
  331. package/src/daemon/conversation-agent-loop.ts +140 -107
  332. package/src/daemon/conversation-error.ts +21 -0
  333. package/src/daemon/conversation-lifecycle.ts +68 -13
  334. package/src/daemon/conversation-process.ts +36 -19
  335. package/src/daemon/conversation-runtime-assembly.ts +14 -5
  336. package/src/daemon/conversation-slash.ts +175 -23
  337. package/src/daemon/conversation-store.ts +17 -10
  338. package/src/daemon/conversation-surfaces.ts +92 -26
  339. package/src/daemon/conversation-tool-setup.ts +33 -19
  340. package/src/daemon/conversation.ts +49 -10
  341. package/src/daemon/external-plugins-bootstrap.ts +18 -8
  342. package/src/daemon/guardian-action-generators.ts +7 -22
  343. package/src/daemon/handlers/config-model.ts +8 -126
  344. package/src/daemon/handlers/config-slack-channel.ts +10 -7
  345. package/src/daemon/handlers/config-vercel.ts +3 -1
  346. package/src/daemon/handlers/shared.ts +26 -0
  347. package/src/daemon/handlers/skills.ts +84 -5
  348. package/src/daemon/history-repair.ts +33 -6
  349. package/src/daemon/host-app-control-proxy.ts +44 -19
  350. package/src/daemon/host-bash-proxy.ts +85 -158
  351. package/src/daemon/host-browser-proxy.ts +97 -36
  352. package/src/daemon/host-cu-proxy.ts +1 -1
  353. package/src/daemon/host-file-proxy.ts +1 -1
  354. package/src/daemon/host-proxy-base.ts +13 -1
  355. package/src/daemon/host-proxy-preactivation.ts +25 -1
  356. package/src/daemon/host-transfer-proxy.ts +2 -2
  357. package/src/daemon/identity-helpers.ts +19 -0
  358. package/src/daemon/lifecycle.ts +128 -114
  359. package/src/daemon/meet-host-supervisor.ts +15 -15
  360. package/src/daemon/memory-v2-startup.ts +62 -14
  361. package/src/daemon/message-protocol.ts +6 -0
  362. package/src/daemon/message-types/bookmarks.ts +18 -0
  363. package/src/daemon/message-types/conversations.ts +12 -9
  364. package/src/daemon/message-types/messages.ts +28 -2
  365. package/src/daemon/message-types/sync.ts +60 -0
  366. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  367. package/src/daemon/pkb-reminder-builder.ts +21 -7
  368. package/src/daemon/process-message.ts +56 -23
  369. package/src/daemon/server.ts +23 -18
  370. package/src/daemon/shutdown-handlers.ts +0 -2
  371. package/src/daemon/tool-setup-types.ts +9 -0
  372. package/src/daemon/tool-side-effects.ts +6 -4
  373. package/src/daemon/wake-target-adapter.ts +11 -0
  374. package/src/documents/document-store.ts +35 -1
  375. package/src/export/transcript-formatter.ts +61 -2
  376. package/src/filing/filing-service.ts +42 -56
  377. package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
  378. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  379. package/src/heartbeat/heartbeat-service.ts +149 -128
  380. package/src/home/__tests__/feed-types.test.ts +63 -131
  381. package/src/home/__tests__/feed-writer.test.ts +77 -278
  382. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  383. package/src/home/feed-types.ts +19 -73
  384. package/src/home/feed-writer.ts +25 -156
  385. package/src/home/post-connect-feed.ts +1 -3
  386. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  387. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  388. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  389. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  390. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  391. package/src/ipc/assistant-server.ts +148 -42
  392. package/src/ipc/cli-client.ts +370 -50
  393. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  394. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  395. package/src/ipc/skill-routes/events.ts +30 -3
  396. package/src/ipc/skill-server.ts +99 -42
  397. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  398. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  399. package/src/live-voice/live-voice-session-manager.ts +11 -4
  400. package/src/live-voice/live-voice-session.ts +14 -6
  401. package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
  402. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  403. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  404. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  405. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +10 -57
  406. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  407. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  408. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
  409. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  410. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  411. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  412. package/src/memory/bookmark-crud.ts +179 -0
  413. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  414. package/src/memory/context-search/agent-protocol.ts +5 -1
  415. package/src/memory/context-search/agent-runner.ts +60 -85
  416. package/src/memory/context-search/limits.ts +1 -4
  417. package/src/memory/context-search/search.ts +23 -113
  418. package/src/memory/context-search/sources/conversations.ts +18 -6
  419. package/src/memory/context-search/sources/memory-v2.ts +40 -31
  420. package/src/memory/context-search/sources/memory.ts +9 -2
  421. package/src/memory/context-search/sources/workspace.ts +13 -10
  422. package/src/memory/context-search/types.ts +1 -1
  423. package/src/memory/conversation-bootstrap.ts +11 -0
  424. package/src/memory/conversation-crud.ts +312 -10
  425. package/src/memory/conversation-queries.ts +9 -5
  426. package/src/memory/conversation-title-service.ts +1 -0
  427. package/src/memory/conversation-types.ts +16 -0
  428. package/src/memory/db-init.ts +14 -0
  429. package/src/memory/embedding-backend.ts +2 -1
  430. package/src/memory/embedding-runtime-manager.ts +1 -2
  431. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +104 -61
  432. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +11 -26
  433. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  434. package/src/memory/graph/conversation-graph-memory.ts +108 -14
  435. package/src/memory/graph/extraction.ts +4 -0
  436. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  437. package/src/memory/graph/graph-search.test.ts +6 -5
  438. package/src/memory/graph/graph-search.ts +3 -4
  439. package/src/memory/graph/retriever.test.ts +12 -7
  440. package/src/memory/graph/retriever.ts +4 -5
  441. package/src/memory/graph/tool-handlers.ts +20 -11
  442. package/src/memory/graph/tools.ts +48 -9
  443. package/src/memory/indexer.ts +18 -2
  444. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +120 -6
  445. package/src/memory/jobs/embed-concept-page.ts +261 -89
  446. package/src/memory/jobs-store.ts +51 -1
  447. package/src/memory/jobs-worker.ts +60 -7
  448. package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
  449. package/src/memory/llm-request-log-source-local.ts +26 -0
  450. package/src/memory/llm-request-log-source.ts +97 -0
  451. package/src/memory/llm-request-log-store.ts +1 -1
  452. package/src/memory/memory-retrospective-constants.ts +13 -0
  453. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  454. package/src/memory/memory-retrospective-job.ts +351 -0
  455. package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
  456. package/src/memory/memory-retrospective-state.ts +162 -0
  457. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  458. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  459. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  460. package/src/memory/message-content.ts +38 -1
  461. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  462. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  463. package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
  464. package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
  465. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  466. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  467. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  468. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  469. package/src/memory/migrations/243-provider-connections.ts +68 -0
  470. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  471. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  472. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  473. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  474. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  475. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  476. package/src/memory/migrations/index.ts +7 -0
  477. package/src/memory/pkb/pkb-search.test.ts +6 -5
  478. package/src/memory/pkb/pkb-search.ts +4 -5
  479. package/src/memory/published-pages-store.ts +16 -0
  480. package/src/memory/qdrant-client.ts +3 -0
  481. package/src/memory/schema/bookmarks.ts +38 -0
  482. package/src/memory/schema/conversations.ts +2 -0
  483. package/src/memory/schema/index.ts +2 -0
  484. package/src/memory/schema/inference.ts +29 -0
  485. package/src/memory/schema/memory-core.ts +9 -0
  486. package/src/memory/search/semantic.ts +5 -9
  487. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  488. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  489. package/src/memory/v2/__tests__/activation.test.ts +46 -9
  490. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  491. package/src/memory/v2/__tests__/consolidation-job.test.ts +140 -163
  492. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  493. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  494. package/src/memory/v2/__tests__/injection.test.ts +768 -33
  495. package/src/memory/v2/__tests__/migration.test.ts +7 -3
  496. package/src/memory/v2/__tests__/page-index.test.ts +277 -0
  497. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  498. package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
  499. package/src/memory/v2/__tests__/qdrant.test.ts +382 -9
  500. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  501. package/src/memory/v2/__tests__/router.test.ts +516 -0
  502. package/src/memory/v2/__tests__/sim.test.ts +163 -8
  503. package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
  504. package/src/memory/v2/__tests__/static-context.test.ts +8 -35
  505. package/src/memory/v2/__tests__/sweep-job.test.ts +114 -33
  506. package/src/memory/v2/activation-store.ts +34 -5
  507. package/src/memory/v2/activation.ts +40 -27
  508. package/src/memory/v2/backfill-jobs.ts +17 -84
  509. package/src/memory/v2/consolidation-job.ts +92 -86
  510. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  511. package/src/memory/v2/injection.ts +466 -115
  512. package/src/memory/v2/migration.ts +117 -20
  513. package/src/memory/v2/page-index.ts +191 -0
  514. package/src/memory/v2/page-store.ts +42 -0
  515. package/src/memory/v2/prompts/consolidation.ts +14 -7
  516. package/src/memory/v2/prompts/router.ts +192 -0
  517. package/src/memory/v2/qdrant.ts +307 -133
  518. package/src/memory/v2/reranker.ts +14 -7
  519. package/src/memory/v2/router.ts +322 -0
  520. package/src/memory/v2/sim.ts +88 -34
  521. package/src/memory/v2/skill-store.ts +118 -29
  522. package/src/memory/v2/static-context.ts +20 -17
  523. package/src/memory/v2/sweep-job.ts +127 -102
  524. package/src/memory/v2/types.ts +16 -5
  525. package/src/memory/validation.ts +13 -0
  526. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  527. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  528. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  529. package/src/notifications/adapters/platform.ts +171 -0
  530. package/src/notifications/conversation-pairing.ts +2 -2
  531. package/src/notifications/copy-composer.ts +61 -12
  532. package/src/notifications/decision-engine.ts +46 -0
  533. package/src/notifications/destination-resolver.ts +21 -0
  534. package/src/notifications/emit-signal.ts +28 -1
  535. package/src/notifications/home-feed-side-effect.ts +111 -0
  536. package/src/notifications/signal.ts +5 -0
  537. package/src/permissions/checker.ts +12 -0
  538. package/src/permissions/gateway-threshold-reader.ts +116 -8
  539. package/src/permissions/ipc-risk-types.ts +2 -0
  540. package/src/permissions/prompter.ts +86 -96
  541. package/src/permissions/secret-prompter.ts +31 -31
  542. package/src/plugin-api/index.ts +13 -0
  543. package/src/plugin-api/package.json +12 -0
  544. package/src/plugin-api/types.ts +62 -0
  545. package/src/plugins/defaults/injectors.ts +20 -5
  546. package/src/plugins/external-plugin-loader.ts +294 -0
  547. package/src/plugins/types.ts +46 -30
  548. package/src/plugins/user-loader.ts +64 -41
  549. package/src/proactive-artifact/job.test.ts +63 -8
  550. package/src/proactive-artifact/job.ts +20 -2
  551. package/src/proactive-artifact/message-copy.ts +18 -1
  552. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  553. package/src/proactive-artifact/trigger-state.ts +4 -0
  554. package/src/prompts/__tests__/system-prompt.test.ts +105 -0
  555. package/src/prompts/system-prompt.ts +22 -1
  556. package/src/prompts/templates/SOUL.md +13 -28
  557. package/src/prompts/update-bulletin-job.ts +61 -73
  558. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  559. package/src/providers/__tests__/inference.test.ts +288 -0
  560. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  561. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  562. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  563. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  564. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  565. package/src/providers/anthropic/client.ts +95 -26
  566. package/src/providers/call-site-routing.ts +94 -16
  567. package/src/providers/connection-resolution.ts +163 -0
  568. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  569. package/src/providers/inference/adapter-factory.ts +173 -0
  570. package/src/providers/inference/auth.ts +112 -0
  571. package/src/providers/inference/backfill.ts +196 -0
  572. package/src/providers/inference/connections.ts +356 -0
  573. package/src/providers/inference/resolve-auth.ts +65 -0
  574. package/src/providers/model-catalog.ts +104 -6
  575. package/src/providers/openai/responses-provider.ts +4 -2
  576. package/src/providers/provider-env-vars.ts +17 -7
  577. package/src/providers/provider-secret-catalog.ts +49 -30
  578. package/src/providers/provider-send-message.ts +41 -20
  579. package/src/providers/registry.ts +143 -159
  580. package/src/providers/retry.ts +18 -10
  581. package/src/providers/search-provider-catalog.ts +121 -0
  582. package/src/runtime/AGENTS.md +18 -5
  583. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  584. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  585. package/src/runtime/actor-trust-resolver.ts +32 -10
  586. package/src/runtime/agent-wake.ts +35 -6
  587. package/src/runtime/assistant-event-hub.ts +3 -85
  588. package/src/runtime/auth/route-policy.ts +304 -8
  589. package/src/runtime/auth/same-actor.ts +2 -0
  590. package/src/runtime/background-job-runner.ts +339 -0
  591. package/src/runtime/btw-sidechain.ts +1 -0
  592. package/src/runtime/channel-approvals.ts +3 -2
  593. package/src/runtime/guardian-reply-router.ts +0 -10
  594. package/src/runtime/http-router.ts +36 -1
  595. package/src/runtime/http-server.ts +31 -5
  596. package/src/runtime/http-types.ts +2 -0
  597. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  598. package/src/runtime/middleware/request-logger.ts +62 -1
  599. package/src/runtime/pending-interactions.ts +19 -15
  600. package/src/runtime/pre-first-message-gate.ts +83 -0
  601. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  602. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
  603. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  604. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
  605. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
  606. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  607. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  608. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +147 -0
  609. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  610. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  611. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  612. package/src/runtime/routes/acp-routes.ts +10 -8
  613. package/src/runtime/routes/app-management-routes.ts +228 -3
  614. package/src/runtime/routes/approval-routes.ts +7 -21
  615. package/src/runtime/routes/audit-routes.ts +43 -0
  616. package/src/runtime/routes/auth-routes.ts +72 -0
  617. package/src/runtime/routes/avatar-routes.ts +273 -20
  618. package/src/runtime/routes/backup-routes.ts +406 -2
  619. package/src/runtime/routes/bookmark-routes.ts +154 -0
  620. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  621. package/src/runtime/routes/consolidation-routes.ts +8 -9
  622. package/src/runtime/routes/contact-routes.ts +0 -160
  623. package/src/runtime/routes/conversation-cli-routes.ts +192 -0
  624. package/src/runtime/routes/conversation-management-routes.ts +30 -43
  625. package/src/runtime/routes/conversation-query-routes.ts +373 -82
  626. package/src/runtime/routes/conversation-routes.ts +31 -10
  627. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  628. package/src/runtime/routes/credential-routes.ts +540 -0
  629. package/src/runtime/routes/debug-bash-routes.ts +2 -0
  630. package/src/runtime/routes/debug-routes.ts +2 -2
  631. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  632. package/src/runtime/routes/domain-routes.ts +167 -0
  633. package/src/runtime/routes/email-routes.ts +603 -0
  634. package/src/runtime/routes/errors.ts +2 -2
  635. package/src/runtime/routes/events-routes.ts +192 -0
  636. package/src/runtime/routes/filing-routes.ts +2 -3
  637. package/src/runtime/routes/home-feed-routes.ts +6 -78
  638. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  639. package/src/runtime/routes/host-browser-routes.ts +103 -22
  640. package/src/runtime/routes/http-adapter.ts +2 -0
  641. package/src/runtime/routes/identity-routes.ts +5 -0
  642. package/src/runtime/routes/image-generation-routes.ts +99 -0
  643. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
  644. package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
  645. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  646. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -7
  647. package/src/runtime/routes/index.ts +36 -0
  648. package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
  649. package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
  650. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  651. package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
  652. package/src/runtime/routes/inference-send-routes.ts +115 -0
  653. package/src/runtime/routes/integrations/twilio.ts +1 -0
  654. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  655. package/src/runtime/routes/memory-item-routes.test.ts +3 -9
  656. package/src/runtime/routes/memory-item-routes.ts +5 -6
  657. package/src/runtime/routes/memory-v2-routes.ts +105 -404
  658. package/src/runtime/routes/notification-routes.ts +2 -0
  659. package/src/runtime/routes/oauth-apps.ts +112 -7
  660. package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
  661. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  662. package/src/runtime/routes/oauth-providers.ts +298 -8
  663. package/src/runtime/routes/platform-routes.ts +336 -0
  664. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  665. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  666. package/src/runtime/routes/playground/state.ts +2 -1
  667. package/src/runtime/routes/publish-routes.ts +221 -0
  668. package/src/runtime/routes/schedule-routes.ts +82 -0
  669. package/src/runtime/routes/sequence-routes.ts +291 -0
  670. package/src/runtime/routes/settings-routes.ts +2 -10
  671. package/src/runtime/routes/skills-routes.ts +31 -1
  672. package/src/runtime/routes/stt-routes.ts +240 -3
  673. package/src/runtime/routes/surface-action-routes.ts +43 -7
  674. package/src/runtime/routes/tts-routes.ts +67 -0
  675. package/src/runtime/routes/types.ts +32 -0
  676. package/src/runtime/routes/user-routes-cli.ts +243 -0
  677. package/src/runtime/routes/webhook-routes.ts +165 -0
  678. package/src/runtime/sync/resource-sync-events.ts +25 -0
  679. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  680. package/src/runtime/sync/sync-publisher.ts +21 -0
  681. package/src/schedule/scheduler.ts +200 -123
  682. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  683. package/src/security/secret-patterns.ts +3 -0
  684. package/src/sequence/engine.ts +38 -40
  685. package/src/skills/include-graph.ts +35 -13
  686. package/src/subagent/manager.ts +20 -15
  687. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  688. package/src/tools/browser/browser-execution.ts +15 -4
  689. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  690. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  691. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  692. package/src/tools/browser/cdp-client/factory.ts +66 -5
  693. package/src/tools/browser/runtime-check.ts +77 -0
  694. package/src/tools/document/document-tool.ts +20 -0
  695. package/src/tools/executor.ts +18 -2
  696. package/src/tools/memory/register.test.ts +10 -8
  697. package/src/tools/memory/register.ts +9 -1
  698. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  699. package/src/tools/network/web-search.ts +280 -37
  700. package/src/tools/permission-checker.ts +28 -5
  701. package/src/tools/skills/load.ts +24 -20
  702. package/src/tools/subagent/spawn.ts +3 -3
  703. package/src/tools/terminal/shell.ts +44 -0
  704. package/src/tools/tool-name-aliases.ts +19 -0
  705. package/src/tools/types.ts +19 -1
  706. package/src/usage/attribution.ts +3 -2
  707. package/src/util/pricing.ts +86 -160
  708. package/src/watcher/__tests__/engine.test.ts +301 -0
  709. package/src/watcher/constants.ts +7 -0
  710. package/src/watcher/engine.ts +90 -90
  711. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  712. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  713. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
  714. package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +4 -62
  715. package/src/workspace/migrations/069-seed-onboarding-threads.ts +34 -0
  716. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +31 -0
  717. package/src/workspace/migrations/071-remove-safe-storage-release-note.ts +111 -0
  718. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
  719. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
  720. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  721. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  722. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  723. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  724. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  725. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  726. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  727. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  728. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  729. package/src/workspace/migrations/registry.ts +28 -0
  730. package/src/workspace/migrations/runner.ts +13 -2
  731. package/src/workspace/migrations/types.ts +13 -3
  732. package/src/workspace/provider-commit-message-generator.ts +3 -2
  733. package/src/__tests__/context-search-pkb-source.test.ts +0 -492
  734. package/src/__tests__/credentials-cli.test.ts +0 -1225
  735. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  736. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  737. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  738. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  739. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  740. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  741. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  742. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  743. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  744. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  745. package/src/cli/commands/autonomy.ts +0 -365
  746. package/src/cli/commands/memory.ts +0 -424
  747. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -1201
  748. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  749. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  750. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  751. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  752. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  753. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  754. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  755. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  756. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  757. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  758. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  759. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  760. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  761. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  762. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  763. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  764. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  765. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  766. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  767. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  768. package/src/home/assistant-feed-authoring.ts +0 -135
  769. package/src/home/emit-feed-event.ts +0 -169
  770. package/src/home/feed-scheduler.ts +0 -281
  771. package/src/home/platform-gmail-digest.ts +0 -163
  772. package/src/home/rewrite-command-preview.ts +0 -66
  773. package/src/home/rewrite-feed-title.ts +0 -58
  774. package/src/home/rollup-producer.ts +0 -426
  775. package/src/memory/admin.ts +0 -326
  776. package/src/memory/context-search/sources/pkb.ts +0 -477
  777. package/src/memory/graph/compaction.ts +0 -299
  778. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Workspace migration `076-home-feed-notification-only`.
3
+ *
4
+ * Rewrites `<workspace>/data/home-feed.json` from the legacy v1 schema
5
+ * (mixed `nudge | digest | action | thread` types with `source`,
6
+ * `author`, `minTimeAway` fields) into the collapsed v2 schema (single
7
+ * `notification` type, no source/author/minTimeAway).
8
+ *
9
+ * Behaviour:
10
+ * - Missing file → no-op.
11
+ * - Malformed JSON → log and no-op (daemon startup must never block;
12
+ * the writer's `readHomeFeed()` already treats unreadable files as
13
+ * empty so the next append cycle naturally rewrites a clean file).
14
+ * - Already v2 → no-op (idempotent).
15
+ * - v1 (or any non-v2 shape with an `items` array): drop entries
16
+ * whose `type !== "action"` (legacy nudge/digest/thread items have
17
+ * no v2 analogue and weren't surfaced as live notifications anyway,
18
+ * per PR 15 of the home-notif-feed-revamp plan); for kept entries
19
+ * drop `source` / `author` / `minTimeAway` and rewrite `type` to
20
+ * `"notification"`. Persist as `{ version: 2, items, updatedAt }`.
21
+ *
22
+ * Idempotent: running the migration a second time on a v2 file is a
23
+ * no-op. The runner's checkpoint also skips re-runs, but this in-file
24
+ * guard keeps the migration safe even if the checkpoint is wiped.
25
+ *
26
+ * `down()` is a no-op — the legacy v1 fields (`source`, `author`,
27
+ * `minTimeAway`, the four item types) were dropped during the
28
+ * forward migration and cannot be recovered. Rolling back to v1 from
29
+ * v2 would also leave the writer producing a shape the older code
30
+ * cannot parse, so a real rollback would require reverting the writer
31
+ * code in lockstep.
32
+ */
33
+
34
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
35
+ import { join } from "node:path";
36
+
37
+ import { getLogger } from "../../util/logger.js";
38
+ import type { WorkspaceMigration } from "./types.js";
39
+
40
+ const log = getLogger("workspace-migration-076-home-feed-notification-only");
41
+
42
+ const HOME_FEED_RELATIVE_PATH = join("data", "home-feed.json");
43
+
44
+ /** v2 file format. Mirrors `HomeFeedFile` in `home/feed-types.ts`. */
45
+ interface V2HomeFeedFile {
46
+ version: 2;
47
+ items: V2FeedItem[];
48
+ updatedAt: string;
49
+ }
50
+
51
+ /**
52
+ * v2 item shape. Inlined rather than imported from `home/feed-types.ts`
53
+ * so the migration stays self-contained — per AGENTS.md migrations
54
+ * should minimise cross-module coupling so they remain stable as code
55
+ * around them evolves.
56
+ */
57
+ interface V2FeedItem {
58
+ id: string;
59
+ type: "notification";
60
+ priority: number;
61
+ title: string;
62
+ summary: string;
63
+ timestamp: string;
64
+ status: string;
65
+ expiresAt?: string;
66
+ actions?: unknown[];
67
+ urgency?: string;
68
+ conversationId?: string;
69
+ detailPanel?: unknown;
70
+ createdAt: string;
71
+ }
72
+
73
+ export const homeFeedNotificationOnlyMigration: WorkspaceMigration = {
74
+ id: "home-feed-notification-only-v2",
75
+ description:
76
+ "Rewrite home-feed.json into v2 schema (single 'notification' type)",
77
+
78
+ run(workspaceDir: string): void {
79
+ const path = join(workspaceDir, HOME_FEED_RELATIVE_PATH);
80
+ if (!existsSync(path)) {
81
+ return;
82
+ }
83
+
84
+ let raw: unknown;
85
+ try {
86
+ raw = JSON.parse(readFileSync(path, "utf-8"));
87
+ } catch (err) {
88
+ // Daemon startup must never block on a parse failure here. The
89
+ // writer's read path also treats malformed files as empty, so
90
+ // skipping the migration just means the next append cycle will
91
+ // overwrite the file with a fresh v2 snapshot.
92
+ log.warn(
93
+ { err, path },
94
+ "Failed to parse home-feed.json; skipping migration",
95
+ );
96
+ return;
97
+ }
98
+
99
+ if (!isPlainObject(raw)) {
100
+ log.warn({ path }, "home-feed.json is not an object; skipping migration");
101
+ return;
102
+ }
103
+
104
+ if (raw.version === 2) {
105
+ // Already migrated.
106
+ return;
107
+ }
108
+
109
+ const rawItems = Array.isArray(raw.items) ? raw.items : [];
110
+ const items: V2FeedItem[] = [];
111
+ for (const entry of rawItems) {
112
+ const migrated = migrateItem(entry);
113
+ if (migrated) items.push(migrated);
114
+ }
115
+
116
+ const next: V2HomeFeedFile = {
117
+ version: 2,
118
+ items,
119
+ updatedAt: new Date().toISOString(),
120
+ };
121
+
122
+ try {
123
+ writeFileSync(path, JSON.stringify(next, null, 2), "utf-8");
124
+ log.info(
125
+ { path, items: items.length },
126
+ "Rewrote home-feed.json to v2 schema",
127
+ );
128
+ } catch (err) {
129
+ log.warn(
130
+ { err, path },
131
+ "Failed to write migrated home-feed.json; leaving prior file in place",
132
+ );
133
+ }
134
+ },
135
+
136
+ down(_workspaceDir: string): void {
137
+ // Lossy migration — legacy fields (source/author/minTimeAway and
138
+ // nudge/digest/thread items) cannot be reconstructed. The writer
139
+ // code itself only emits v2 now, so rolling back would also leave
140
+ // the file in a shape the v1 reader could not parse without
141
+ // reverting feed-writer.ts in lockstep.
142
+ },
143
+ };
144
+
145
+ /**
146
+ * Convert a single legacy item into a v2 item, or return `null` to
147
+ * drop it. Only `type === "action"` items survive — legacy
148
+ * nudge/digest/thread entries have no v2 analogue and were not
149
+ * surfaced as live notifications by PR 4's wiring (only assistant-
150
+ * authored `action` items reached the live feed via
151
+ * `home-feed-side-effect.ts`).
152
+ */
153
+ function migrateItem(entry: unknown): V2FeedItem | null {
154
+ if (!isPlainObject(entry)) return null;
155
+ if (entry.type !== "action") return null;
156
+
157
+ // Required fields — fail-soft on missing critical strings rather
158
+ // than throwing, so a single bad legacy entry does not lose the
159
+ // rest of the items.
160
+ if (
161
+ typeof entry.id !== "string" ||
162
+ typeof entry.title !== "string" ||
163
+ typeof entry.summary !== "string" ||
164
+ typeof entry.timestamp !== "string" ||
165
+ typeof entry.createdAt !== "string"
166
+ ) {
167
+ return null;
168
+ }
169
+ const priority =
170
+ typeof entry.priority === "number" && Number.isInteger(entry.priority)
171
+ ? entry.priority
172
+ : 50;
173
+ const status = typeof entry.status === "string" ? entry.status : "new";
174
+
175
+ const out: V2FeedItem = {
176
+ id: entry.id,
177
+ type: "notification",
178
+ priority,
179
+ title: entry.title,
180
+ summary: entry.summary,
181
+ timestamp: entry.timestamp,
182
+ status,
183
+ createdAt: entry.createdAt,
184
+ };
185
+ if (typeof entry.expiresAt === "string") out.expiresAt = entry.expiresAt;
186
+ if (Array.isArray(entry.actions)) out.actions = entry.actions;
187
+ if (typeof entry.urgency === "string") out.urgency = entry.urgency;
188
+ if (typeof entry.conversationId === "string") {
189
+ out.conversationId = entry.conversationId;
190
+ }
191
+ if (isPlainObject(entry.detailPanel)) out.detailPanel = entry.detailPanel;
192
+ return out;
193
+ }
194
+
195
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
196
+ return typeof value === "object" && value !== null && !Array.isArray(value);
197
+ }
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Workspace migration `080-restrict-vercel-api-token-metadata`.
3
+ *
4
+ * Repairs legacy Vercel API token credential metadata that was stored
5
+ * with overly permissive policy (e.g. `bash` in allowedTools and
6
+ * injection templates targeting `api.vercel.com`). Rewrites the
7
+ * Vercel record to the hardened policy:
8
+ *
9
+ * - `allowedTools: ["publish_page", "unpublish_page"]`
10
+ * - `allowedDomains: []`
11
+ * - `injectionTemplates` removed
12
+ *
13
+ * Behaviour:
14
+ * - Missing metadata file -> no-op.
15
+ * - Malformed JSON -> log and no-op.
16
+ * - Unrecognized future schema version -> no-op.
17
+ * - No `vercel`/`api_token` credential record -> no-op.
18
+ * - Already matches target policy -> no-op (no rewrite, no updatedAt bump).
19
+ * - Non-Vercel credential records are never modified.
20
+ *
21
+ * Idempotent: running twice produces no second write. The runner's
22
+ * checkpoint also prevents re-runs, but this in-file guard keeps the
23
+ * migration safe even if the checkpoint is wiped.
24
+ *
25
+ * This migration never touches secure secret values — only the
26
+ * metadata policy fields.
27
+ */
28
+
29
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
30
+ import { join } from "node:path";
31
+
32
+ import { getLogger } from "../../util/logger.js";
33
+ import type { WorkspaceMigration } from "./types.js";
34
+
35
+ const log = getLogger(
36
+ "workspace-migration-080-restrict-vercel-api-token-metadata",
37
+ );
38
+
39
+ const METADATA_RELATIVE_PATH = join("data", "credentials", "metadata.json");
40
+
41
+ /** Known on-disk schema versions we can safely handle. */
42
+ const KNOWN_VERSIONS = new Set([1, 2, 3, 4, 5]);
43
+
44
+ /** The hardened target policy for the Vercel API token. */
45
+ const TARGET_ALLOWED_TOOLS = ["publish_page", "unpublish_page"];
46
+ const TARGET_ALLOWED_DOMAINS: string[] = [];
47
+
48
+ export const restrictVercelApiTokenMetadataMigration: WorkspaceMigration = {
49
+ id: "080-restrict-vercel-api-token-metadata",
50
+ description:
51
+ "Restrict existing Vercel API token metadata to publish tools only",
52
+
53
+ run(workspaceDir: string): void {
54
+ const metadataPath = join(workspaceDir, METADATA_RELATIVE_PATH);
55
+ if (!existsSync(metadataPath)) {
56
+ return;
57
+ }
58
+
59
+ let raw: string;
60
+ try {
61
+ raw = readFileSync(metadataPath, "utf-8");
62
+ } catch (err) {
63
+ log.warn(
64
+ { err, path: metadataPath },
65
+ "Failed to read credentials metadata; skipping migration",
66
+ );
67
+ return;
68
+ }
69
+
70
+ let parsed: unknown;
71
+ try {
72
+ parsed = JSON.parse(raw);
73
+ } catch (err) {
74
+ log.warn(
75
+ { err, path: metadataPath },
76
+ "Failed to parse credentials metadata JSON; skipping migration",
77
+ );
78
+ return;
79
+ }
80
+
81
+ if (!isPlainObject(parsed)) {
82
+ log.warn(
83
+ { path: metadataPath },
84
+ "Credentials metadata is not an object; skipping migration",
85
+ );
86
+ return;
87
+ }
88
+
89
+ // Respect unrecognized future schema versions — do not touch the file.
90
+ const version = typeof parsed.version === "number" ? parsed.version : 1;
91
+ if (!KNOWN_VERSIONS.has(version)) {
92
+ log.info(
93
+ { version, path: metadataPath },
94
+ "Credentials metadata has unrecognized version; skipping migration",
95
+ );
96
+ return;
97
+ }
98
+
99
+ const credentials = Array.isArray(parsed.credentials)
100
+ ? parsed.credentials
101
+ : [];
102
+
103
+ // Find the Vercel API token record.
104
+ const vercelIdx = credentials.findIndex(
105
+ (c: unknown) =>
106
+ isPlainObject(c) && c.service === "vercel" && c.field === "api_token",
107
+ );
108
+
109
+ if (vercelIdx === -1) {
110
+ // No Vercel credential — nothing to repair.
111
+ return;
112
+ }
113
+
114
+ const vercelRecord = credentials[vercelIdx] as Record<string, unknown>;
115
+
116
+ // Check if already matches target policy.
117
+ if (alreadyMatchesTarget(vercelRecord)) {
118
+ return;
119
+ }
120
+
121
+ // Rewrite the Vercel record to the target policy.
122
+ vercelRecord.allowedTools = TARGET_ALLOWED_TOOLS;
123
+ vercelRecord.allowedDomains = TARGET_ALLOWED_DOMAINS;
124
+ delete vercelRecord.injectionTemplates;
125
+ vercelRecord.updatedAt = Date.now();
126
+
127
+ try {
128
+ writeFileSync(metadataPath, JSON.stringify(parsed, null, 2), "utf-8");
129
+ log.info(
130
+ { path: metadataPath },
131
+ "Repaired Vercel API token metadata to hardened policy",
132
+ );
133
+ } catch (err) {
134
+ log.warn(
135
+ { err, path: metadataPath },
136
+ "Failed to write repaired credentials metadata; leaving prior file in place",
137
+ );
138
+ }
139
+ },
140
+
141
+ down(_workspaceDir: string): void {
142
+ // Cannot recover the original vulnerable policy — and we would not
143
+ // want to even if we could. This is a security hardening migration.
144
+ },
145
+ };
146
+
147
+ /**
148
+ * Returns true when the Vercel record already matches the target
149
+ * hardened policy, meaning no rewrite is necessary.
150
+ */
151
+ function alreadyMatchesTarget(record: Record<string, unknown>): boolean {
152
+ const tools = record.allowedTools;
153
+ const domains = record.allowedDomains;
154
+
155
+ if (!Array.isArray(tools) || tools.length !== TARGET_ALLOWED_TOOLS.length) {
156
+ return false;
157
+ }
158
+ const sortedTools = [...tools].sort();
159
+ const sortedTarget = [...TARGET_ALLOWED_TOOLS].sort();
160
+ for (let i = 0; i < sortedTools.length; i++) {
161
+ if (sortedTools[i] !== sortedTarget[i]) return false;
162
+ }
163
+
164
+ if (!Array.isArray(domains) || domains.length !== 0) {
165
+ return false;
166
+ }
167
+
168
+ // injectionTemplates must be absent or undefined.
169
+ if (
170
+ "injectionTemplates" in record &&
171
+ record.injectionTemplates !== undefined &&
172
+ record.injectionTemplates !== null
173
+ ) {
174
+ return false;
175
+ }
176
+
177
+ return true;
178
+ }
179
+
180
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
181
+ return typeof value === "object" && value !== null && !Array.isArray(value);
182
+ }
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Workspace migration `081-backfill-bash-allowed-tools-for-injection-credentials`.
3
+ *
4
+ * After migration 080 stripped Vercel's injection templates and locked
5
+ * its `allowedTools` to `["publish_page", "unpublish_page"]`, the new
6
+ * shell.ts credential policy enforcement (`isToolAllowed("bash", meta.allowedTools)`)
7
+ * would reject every other service that legitimately uses proxied bash
8
+ * via injection templates — because their `allowedTools` was never populated.
9
+ *
10
+ * This migration backfills `"bash"` into `allowedTools` for any credential
11
+ * that:
12
+ * 1. Has a non-empty `injectionTemplates` array (i.e., it uses proxied bash).
13
+ * 2. Has empty or missing `allowedTools`.
14
+ *
15
+ * Credentials that already have populated `allowedTools` (like the
16
+ * now-hardened Vercel credential) are NOT touched.
17
+ *
18
+ * Behaviour:
19
+ * - Missing metadata file -> no-op.
20
+ * - Malformed JSON -> log and no-op.
21
+ * - Unrecognized future schema version -> no-op.
22
+ * - No qualifying credentials -> no-op (no rewrite).
23
+ * - Already backfilled -> no-op (idempotent).
24
+ *
25
+ * Idempotent: running twice produces no second write.
26
+ */
27
+
28
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
29
+ import { join } from "node:path";
30
+
31
+ import { getLogger } from "../../util/logger.js";
32
+ import type { WorkspaceMigration } from "./types.js";
33
+
34
+ const log = getLogger(
35
+ "workspace-migration-081-backfill-bash-allowed-tools-for-injection-credentials",
36
+ );
37
+
38
+ const METADATA_RELATIVE_PATH = join("data", "credentials", "metadata.json");
39
+
40
+ /** Known on-disk schema versions we can safely handle. */
41
+ const KNOWN_VERSIONS = new Set([1, 2, 3, 4, 5]);
42
+
43
+ export const backfillBashAllowedToolsForInjectionCredentialsMigration: WorkspaceMigration =
44
+ {
45
+ id: "081-backfill-bash-allowed-tools-for-injection-credentials",
46
+ description:
47
+ "Backfill bash into allowedTools for credentials with injection templates",
48
+
49
+ run(workspaceDir: string): void {
50
+ const metadataPath = join(workspaceDir, METADATA_RELATIVE_PATH);
51
+ if (!existsSync(metadataPath)) {
52
+ return;
53
+ }
54
+
55
+ let raw: string;
56
+ try {
57
+ raw = readFileSync(metadataPath, "utf-8");
58
+ } catch (err) {
59
+ log.warn(
60
+ { err, path: metadataPath },
61
+ "Failed to read credentials metadata; skipping migration",
62
+ );
63
+ return;
64
+ }
65
+
66
+ let parsed: unknown;
67
+ try {
68
+ parsed = JSON.parse(raw);
69
+ } catch (err) {
70
+ log.warn(
71
+ { err, path: metadataPath },
72
+ "Failed to parse credentials metadata JSON; skipping migration",
73
+ );
74
+ return;
75
+ }
76
+
77
+ if (!isPlainObject(parsed)) {
78
+ log.warn(
79
+ { path: metadataPath },
80
+ "Credentials metadata is not an object; skipping migration",
81
+ );
82
+ return;
83
+ }
84
+
85
+ // Respect unrecognized future schema versions — do not touch the file.
86
+ const version = typeof parsed.version === "number" ? parsed.version : 1;
87
+ if (!KNOWN_VERSIONS.has(version)) {
88
+ log.info(
89
+ { version, path: metadataPath },
90
+ "Credentials metadata has unrecognized version; skipping migration",
91
+ );
92
+ return;
93
+ }
94
+
95
+ const credentials = Array.isArray(parsed.credentials)
96
+ ? parsed.credentials
97
+ : [];
98
+
99
+ let modified = false;
100
+
101
+ for (const cred of credentials) {
102
+ if (!isPlainObject(cred)) continue;
103
+
104
+ // Only target credentials with non-empty injectionTemplates.
105
+ if (!hasNonEmptyInjectionTemplates(cred)) continue;
106
+
107
+ // Only target credentials with empty or missing allowedTools.
108
+ if (hasPopulatedAllowedTools(cred)) continue;
109
+
110
+ // Backfill "bash" into allowedTools.
111
+ cred.allowedTools = ["bash"];
112
+ cred.updatedAt = Date.now();
113
+ modified = true;
114
+ }
115
+
116
+ if (!modified) {
117
+ return;
118
+ }
119
+
120
+ try {
121
+ writeFileSync(metadataPath, JSON.stringify(parsed, null, 2), "utf-8");
122
+ log.info(
123
+ { path: metadataPath },
124
+ "Backfilled bash into allowedTools for credentials with injection templates",
125
+ );
126
+ } catch (err) {
127
+ log.warn(
128
+ { err, path: metadataPath },
129
+ "Failed to write backfilled credentials metadata; leaving prior file in place",
130
+ );
131
+ }
132
+ },
133
+
134
+ down(_workspaceDir: string): void {
135
+ // This is a forward-only data repair. Rolling back would re-break
136
+ // proxied bash for affected services.
137
+ },
138
+ };
139
+
140
+ /**
141
+ * Returns true when the credential has a non-empty `injectionTemplates` array.
142
+ */
143
+ function hasNonEmptyInjectionTemplates(
144
+ record: Record<string, unknown>,
145
+ ): boolean {
146
+ const templates = record.injectionTemplates;
147
+ return Array.isArray(templates) && templates.length > 0;
148
+ }
149
+
150
+ /**
151
+ * Returns true when the credential has a populated (non-empty) `allowedTools` array.
152
+ */
153
+ function hasPopulatedAllowedTools(record: Record<string, unknown>): boolean {
154
+ const tools = record.allowedTools;
155
+ return Array.isArray(tools) && tools.length > 0;
156
+ }
157
+
158
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
159
+ return typeof value === "object" && value !== null && !Array.isArray(value);
160
+ }
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Workspace migration `082-backfill-managed-profile-labels`.
3
+ *
4
+ * Backfills `label` on the three canonical managed inference profiles
5
+ * (`balanced`, `quality-optimized`, `cost-optimized`) when the on-disk
6
+ * profile is missing it.
7
+ *
8
+ * Why this is needed
9
+ * ------------------
10
+ * Migration 052 (`seed-default-inference-profiles`) seeds the three
11
+ * canonical Anthropic profiles with provider/model/maxTokens/effort/
12
+ * thinking but **no `label`** field. The runtime profile seeder
13
+ * (`seedInferenceProfiles`) materializes labels on its second pass —
14
+ * but only when the profile didn't already exist. In platform mode
15
+ * (`IS_PLATFORM=true`) it deliberately defers to the existing on-disk
16
+ * entry to avoid clobbering platform-supplied overlay fragments, so the
17
+ * label never gets written.
18
+ *
19
+ * Net result: a fresh Cloud-hosted assistant (Marina QA #5, 0.8.1) shows
20
+ * raw slugs in the profile picker — `balanced`, `quality-optimized`,
21
+ * `cost-optimized` — instead of the human labels `Balanced`, `Quality`,
22
+ * `Speed`. This migration heals existing installs by writing the bare
23
+ * template label when absent.
24
+ *
25
+ * Behavior
26
+ * --------
27
+ * - Missing config.json -> no-op.
28
+ * - Malformed JSON -> log and no-op.
29
+ * - `llm.profiles` absent -> no-op.
30
+ * - For each canonical name: backfill `label` only when the key is
31
+ * absent on disk. An explicit `null` (user cleared the label) is
32
+ * preserved. A user-set string is preserved.
33
+ * - Non-canonical profile names are never touched.
34
+ *
35
+ * Idempotent: running twice produces no second write.
36
+ *
37
+ * Does NOT skip on `VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH`: the platform
38
+ * overlay supplies its own label when it cares, and the runtime seeder's
39
+ * `preservedProfileNames` skip path will defer to that overlay-supplied
40
+ * label on every boot. This migration only fills the gap when no source
41
+ * (overlay, migration 052, or seeder) ever wrote a label.
42
+ */
43
+
44
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
45
+ import { join } from "node:path";
46
+
47
+ import { getLogger } from "../../util/logger.js";
48
+ import type { WorkspaceMigration } from "./types.js";
49
+
50
+ const log = getLogger("workspace-migration-082-backfill-managed-profile-labels");
51
+
52
+ /**
53
+ * Bare template labels for the canonical managed profile triplet. Kept in
54
+ * sync with `MANAGED_PROFILE_TEMPLATES` in
55
+ * `assistant/src/config/seed-inference-profiles.ts`. Duplicated here
56
+ * intentionally — migrations are forward-only and self-contained per the
57
+ * workspace migrations AGENTS contract; future renames in the seeder
58
+ * must NOT retroactively change the data this migration writes.
59
+ */
60
+ const CANONICAL_MANAGED_PROFILE_LABELS: Record<string, string> = {
61
+ balanced: "Balanced",
62
+ "quality-optimized": "Quality",
63
+ "cost-optimized": "Speed",
64
+ };
65
+
66
+ export const backfillManagedProfileLabelsMigration: WorkspaceMigration = {
67
+ id: "082-backfill-managed-profile-labels",
68
+ description:
69
+ "Backfill label on canonical managed inference profiles when absent",
70
+
71
+ run(workspaceDir: string): void {
72
+ const configPath = join(workspaceDir, "config.json");
73
+ if (!existsSync(configPath)) {
74
+ return;
75
+ }
76
+
77
+ let raw: string;
78
+ try {
79
+ raw = readFileSync(configPath, "utf-8");
80
+ } catch (err) {
81
+ log.warn(
82
+ { err, path: configPath },
83
+ "Failed to read config.json; skipping migration",
84
+ );
85
+ return;
86
+ }
87
+
88
+ let parsed: unknown;
89
+ try {
90
+ parsed = JSON.parse(raw);
91
+ } catch (err) {
92
+ log.warn(
93
+ { err, path: configPath },
94
+ "Failed to parse config.json; skipping migration",
95
+ );
96
+ return;
97
+ }
98
+
99
+ if (!isPlainObject(parsed)) {
100
+ return;
101
+ }
102
+
103
+ const llm = readObject(parsed.llm);
104
+ if (!llm) return;
105
+
106
+ const profiles = readObject(llm.profiles);
107
+ if (!profiles) return;
108
+
109
+ let modified = false;
110
+
111
+ for (const [name, label] of Object.entries(
112
+ CANONICAL_MANAGED_PROFILE_LABELS,
113
+ )) {
114
+ const profile = readObject(profiles[name]);
115
+ if (!profile) continue;
116
+ // Only backfill when the key is absent. Explicit `null` (user cleared
117
+ // the label) and any user-set string both signal intent and survive.
118
+ if ("label" in profile) continue;
119
+ profile.label = label;
120
+ modified = true;
121
+ }
122
+
123
+ if (!modified) return;
124
+
125
+ try {
126
+ writeFileSync(configPath, JSON.stringify(parsed, null, 2) + "\n", "utf-8");
127
+ log.info(
128
+ { path: configPath },
129
+ "Backfilled missing labels on canonical managed inference profiles",
130
+ );
131
+ } catch (err) {
132
+ log.warn(
133
+ { err, path: configPath },
134
+ "Failed to write backfilled config.json; leaving prior file in place",
135
+ );
136
+ }
137
+ },
138
+
139
+ down(_workspaceDir: string): void {
140
+ // Forward-only data repair. Rolling back would re-break the picker
141
+ // for installs whose only label source was this migration.
142
+ },
143
+ };
144
+
145
+ function readObject(value: unknown): Record<string, unknown> | null {
146
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
147
+ return null;
148
+ }
149
+ return value as Record<string, unknown>;
150
+ }
151
+
152
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
153
+ return typeof value === "object" && value !== null && !Array.isArray(value);
154
+ }