@vellumai/assistant 0.8.0 → 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 (692) hide show
  1. package/AGENTS.md +11 -0
  2. package/Dockerfile +5 -4
  3. package/README.md +2 -2
  4. package/docker-entrypoint.sh +16 -0
  5. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  6. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  7. package/eslint.config.mjs +12 -0
  8. package/knip.json +2 -1
  9. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  10. package/openapi.yaml +4847 -1698
  11. package/package.json +3 -1
  12. package/scripts/generate-openapi.ts +52 -4
  13. package/scripts/sync-llm-catalog.ts +165 -0
  14. package/scripts/sync-web-search-catalog.ts +107 -0
  15. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  16. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  17. package/src/__tests__/anthropic-provider.test.ts +92 -2
  18. package/src/__tests__/app-control-flow.test.ts +7 -0
  19. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  20. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  21. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  22. package/src/__tests__/btw-routes.test.ts +1 -0
  23. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  24. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  25. package/src/__tests__/channel-policy.test.ts +12 -0
  26. package/src/__tests__/checker.test.ts +89 -0
  27. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +35 -7
  28. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  29. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  30. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  31. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  32. package/src/__tests__/config-loader-platform-defaults.test.ts +77 -23
  33. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  34. package/src/__tests__/config-schema.test.ts +14 -3
  35. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  36. package/src/__tests__/config-set-route.test.ts +198 -0
  37. package/src/__tests__/config-watcher.test.ts +6 -0
  38. package/src/__tests__/contacts-tools.test.ts +51 -199
  39. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  40. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  41. package/src/__tests__/context-search-conversations-source.test.ts +42 -16
  42. package/src/__tests__/context-search-fanout.test.ts +20 -157
  43. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
  44. package/src/__tests__/context-search-types.test.ts +7 -2
  45. package/src/__tests__/context-window-manager.test.ts +389 -1
  46. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  47. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  48. package/src/__tests__/conversation-error.test.ts +38 -0
  49. package/src/__tests__/conversation-fork-crud.test.ts +241 -1
  50. package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
  51. package/src/__tests__/conversation-init.benchmark.test.ts +1 -0
  52. package/src/__tests__/conversation-lifecycle.test.ts +124 -0
  53. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  54. package/src/__tests__/conversation-process-callsite.test.ts +21 -1
  55. package/src/__tests__/conversation-runtime-assembly.test.ts +4 -4
  56. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  57. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  58. package/src/__tests__/credential-security-invariants.test.ts +5 -6
  59. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  60. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  61. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  62. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  63. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  64. package/src/__tests__/external-plugin-loader.test.ts +458 -0
  65. package/src/__tests__/filing-service.test.ts +23 -3
  66. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  67. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  68. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  69. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -8
  70. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  71. package/src/__tests__/heartbeat-service.test.ts +50 -233
  72. package/src/__tests__/history-repair.test.ts +89 -0
  73. package/src/__tests__/host-app-control-proxy.test.ts +109 -1
  74. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  75. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  76. package/src/__tests__/host-browser-routes.test.ts +325 -33
  77. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  78. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  79. package/src/__tests__/inference-profile-reaper.test.ts +154 -0
  80. package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
  81. package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
  82. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  83. package/src/__tests__/install-skill-routing.test.ts +2 -2
  84. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +15 -0
  85. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  86. package/src/__tests__/llm-catalog-parity.test.ts +146 -0
  87. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
  88. package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
  89. package/src/__tests__/llm-resolver.test.ts +46 -0
  90. package/src/__tests__/managed-profile-guard.test.ts +131 -2
  91. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  92. package/src/__tests__/mcp-cli.test.ts +182 -220
  93. package/src/__tests__/mcp-health-check.test.ts +56 -27
  94. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  95. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  96. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  97. package/src/__tests__/oauth-cli.test.ts +38 -2009
  98. package/src/__tests__/oauth-commands-routes.test.ts +711 -0
  99. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  100. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  101. package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
  102. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  103. package/src/__tests__/plugin-bootstrap.test.ts +31 -2
  104. package/src/__tests__/plugin-route-contribution.test.ts +31 -3
  105. package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
  106. package/src/__tests__/plugin-types.test.ts +13 -11
  107. package/src/__tests__/process-message-background-slack.test.ts +46 -0
  108. package/src/__tests__/profile-entry-status.test.ts +43 -0
  109. package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
  110. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  111. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  112. package/src/__tests__/relay-server.test.ts +118 -0
  113. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  114. package/src/__tests__/schedule-retry.test.ts +56 -4
  115. package/src/__tests__/schedule-routes.test.ts +104 -0
  116. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  117. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  118. package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
  119. package/src/__tests__/scheduler-wake.test.ts +0 -63
  120. package/src/__tests__/secret-allowlist.test.ts +1 -0
  121. package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
  122. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  123. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  124. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  125. package/src/__tests__/skill-load-tool.test.ts +2 -4
  126. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  127. package/src/__tests__/suggestion-routes.test.ts +3 -3
  128. package/src/__tests__/sync-message-contract.test.ts +63 -0
  129. package/src/__tests__/task-scheduler.test.ts +88 -23
  130. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  131. package/src/__tests__/usage-cli.test.ts +11 -73
  132. package/src/__tests__/user-plugin-loader.test.ts +145 -0
  133. package/src/__tests__/vercel-config.test.ts +168 -0
  134. package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
  135. package/src/__tests__/web-search.test.ts +303 -2
  136. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  137. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
  138. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +53 -20
  139. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
  140. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  141. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  142. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  143. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  144. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  145. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  146. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  147. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  148. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  149. package/src/acp/resolve-agent.test.ts +25 -0
  150. package/src/acp/resolve-agent.ts +13 -2
  151. package/src/acp/session-manager.ts +14 -0
  152. package/src/approvals/guardian-request-resolvers.ts +32 -87
  153. package/src/calls/relay-server.ts +35 -0
  154. package/src/calls/relay-setup-router.ts +36 -0
  155. package/src/calls/types.ts +1 -0
  156. package/src/calls/voice-session-bridge.ts +23 -4
  157. package/src/channels/config.ts +14 -1
  158. package/src/channels/types.ts +1 -0
  159. package/src/cli/AGENTS.md +164 -4
  160. package/src/cli/__tests__/notifications.test.ts +54 -0
  161. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  162. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  163. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  164. package/src/cli/commands/__tests__/changelog.test.ts +593 -0
  165. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  166. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  167. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  168. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  169. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  170. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  171. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  172. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  173. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  174. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  175. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  176. package/src/cli/commands/__tests__/status.test.ts +249 -0
  177. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  178. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  179. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  180. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  181. package/src/cli/commands/attachment.ts +8 -3
  182. package/src/cli/commands/audit.ts +95 -64
  183. package/src/cli/commands/auth.ts +61 -58
  184. package/src/cli/commands/avatar.ts +276 -390
  185. package/src/cli/commands/backup.ts +409 -505
  186. package/src/cli/commands/bash.ts +9 -5
  187. package/src/cli/commands/browser.ts +28 -9
  188. package/src/cli/commands/cache.ts +9 -4
  189. package/src/cli/commands/changelog.ts +414 -0
  190. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  191. package/src/cli/commands/clients.ts +8 -3
  192. package/src/cli/commands/completions.ts +9 -9
  193. package/src/cli/commands/config.ts +102 -72
  194. package/src/cli/commands/contacts.ts +575 -696
  195. package/src/cli/commands/conversations-defer.ts +17 -69
  196. package/src/cli/commands/conversations-import.ts +90 -253
  197. package/src/cli/commands/conversations.ts +346 -436
  198. package/src/cli/commands/credential-execution.ts +9 -6
  199. package/src/cli/commands/credentials.ts +456 -736
  200. package/src/cli/commands/domain.ts +128 -206
  201. package/src/cli/commands/email.ts +606 -794
  202. package/src/cli/commands/gateway.ts +8 -1
  203. package/src/cli/commands/image-generation.ts +157 -205
  204. package/src/cli/commands/inference-providers.ts +352 -0
  205. package/src/cli/commands/inference-session.ts +415 -0
  206. package/src/cli/commands/inference.ts +87 -65
  207. package/src/cli/commands/keys.ts +8 -3
  208. package/src/cli/commands/mcp.ts +103 -287
  209. package/src/cli/commands/memory-v2.ts +162 -516
  210. package/src/cli/commands/notifications.ts +33 -7
  211. package/src/cli/commands/oauth/apps.ts +292 -261
  212. package/src/cli/commands/oauth/connect.ts +176 -297
  213. package/src/cli/commands/oauth/disconnect.ts +16 -215
  214. package/src/cli/commands/oauth/index.ts +49 -45
  215. package/src/cli/commands/oauth/mode.ts +43 -199
  216. package/src/cli/commands/oauth/ping.ts +17 -125
  217. package/src/cli/commands/oauth/providers.ts +732 -921
  218. package/src/cli/commands/oauth/request.ts +60 -350
  219. package/src/cli/commands/oauth/shared.ts +11 -121
  220. package/src/cli/commands/oauth/status.ts +31 -121
  221. package/src/cli/commands/oauth/token.ts +13 -55
  222. package/src/cli/commands/pending.ts +19 -10
  223. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  224. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  225. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  226. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  227. package/src/cli/commands/platform/connect.ts +16 -80
  228. package/src/cli/commands/platform/disconnect.ts +14 -112
  229. package/src/cli/commands/platform/index.ts +177 -246
  230. package/src/cli/commands/routes.ts +153 -336
  231. package/src/cli/commands/sequence.ts +316 -360
  232. package/src/cli/commands/skills.ts +449 -671
  233. package/src/cli/commands/status.ts +58 -37
  234. package/src/cli/commands/stt.ts +94 -262
  235. package/src/cli/commands/task.ts +14 -40
  236. package/src/cli/commands/trust.ts +8 -3
  237. package/src/cli/commands/tts.ts +162 -167
  238. package/src/cli/commands/ui.ts +35 -42
  239. package/src/cli/commands/usage.ts +188 -126
  240. package/src/cli/commands/watchers.ts +8 -3
  241. package/src/cli/commands/webhooks.ts +99 -193
  242. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  243. package/src/cli/lib/daemon-credential-client.ts +4 -5
  244. package/src/cli/lib/nested-value.ts +44 -0
  245. package/src/cli/lib/open-browser.ts +36 -0
  246. package/src/cli/lib/register-command.ts +19 -0
  247. package/src/cli/lib/time-ago.ts +34 -0
  248. package/src/cli/program.ts +2 -4
  249. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  250. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  251. package/src/cli/utils/conversation-id.ts +30 -0
  252. package/src/cli/utils/parse-duration.ts +41 -0
  253. package/src/config/acp-defaults.test.ts +5 -1
  254. package/src/config/acp-defaults.ts +11 -4
  255. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  256. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  257. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  258. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  259. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  260. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  261. package/src/config/bundled-tool-registry.ts +0 -2
  262. package/src/config/feature-flag-registry.json +16 -0
  263. package/src/config/llm-resolver.ts +16 -1
  264. package/src/config/loader.ts +76 -14
  265. package/src/config/raw-config-utils.ts +2 -30
  266. package/src/config/schema.ts +4 -0
  267. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  268. package/src/config/schemas/call-site-catalog.ts +29 -7
  269. package/src/config/schemas/llm-request-logs.ts +57 -0
  270. package/src/config/schemas/llm.ts +52 -2
  271. package/src/config/schemas/memory-retrospective.ts +48 -0
  272. package/src/config/schemas/memory-v2.ts +32 -1
  273. package/src/config/schemas/memory.ts +4 -0
  274. package/src/config/schemas/services.ts +15 -12
  275. package/src/config/seed-inference-profiles.ts +195 -134
  276. package/src/contacts/contact-store.ts +0 -61
  277. package/src/context/window-manager.ts +191 -5
  278. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +79 -0
  279. package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
  280. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  281. package/src/daemon/approval-generators.ts +23 -29
  282. package/src/daemon/config-watcher.ts +2 -0
  283. package/src/daemon/conversation-agent-loop-handlers.ts +24 -0
  284. package/src/daemon/conversation-agent-loop.ts +127 -97
  285. package/src/daemon/conversation-error.ts +21 -0
  286. package/src/daemon/conversation-lifecycle.ts +46 -5
  287. package/src/daemon/conversation-process.ts +36 -19
  288. package/src/daemon/conversation-runtime-assembly.ts +14 -5
  289. package/src/daemon/conversation-slash.ts +175 -23
  290. package/src/daemon/conversation-store.ts +17 -10
  291. package/src/daemon/conversation-surfaces.ts +76 -12
  292. package/src/daemon/conversation-tool-setup.ts +24 -14
  293. package/src/daemon/conversation.ts +48 -9
  294. package/src/daemon/external-plugins-bootstrap.ts +18 -8
  295. package/src/daemon/guardian-action-generators.ts +7 -22
  296. package/src/daemon/handlers/config-model.ts +8 -126
  297. package/src/daemon/handlers/config-slack-channel.ts +10 -7
  298. package/src/daemon/handlers/config-vercel.ts +3 -1
  299. package/src/daemon/handlers/skills.ts +84 -5
  300. package/src/daemon/history-repair.ts +33 -6
  301. package/src/daemon/host-app-control-proxy.ts +44 -19
  302. package/src/daemon/host-bash-proxy.ts +85 -158
  303. package/src/daemon/host-browser-proxy.ts +96 -35
  304. package/src/daemon/host-proxy-base.ts +13 -1
  305. package/src/daemon/host-proxy-preactivation.ts +25 -1
  306. package/src/daemon/identity-helpers.ts +19 -0
  307. package/src/daemon/lifecycle.ts +42 -43
  308. package/src/daemon/meet-host-supervisor.ts +15 -15
  309. package/src/daemon/memory-v2-startup.ts +9 -2
  310. package/src/daemon/message-protocol.ts +6 -0
  311. package/src/daemon/message-types/bookmarks.ts +18 -0
  312. package/src/daemon/message-types/conversations.ts +12 -9
  313. package/src/daemon/message-types/messages.ts +9 -1
  314. package/src/daemon/message-types/sync.ts +60 -0
  315. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  316. package/src/daemon/pkb-reminder-builder.ts +21 -7
  317. package/src/daemon/process-message.ts +56 -23
  318. package/src/daemon/server.ts +23 -18
  319. package/src/daemon/shutdown-handlers.ts +0 -2
  320. package/src/daemon/tool-setup-types.ts +9 -0
  321. package/src/daemon/tool-side-effects.ts +6 -4
  322. package/src/daemon/wake-target-adapter.ts +11 -0
  323. package/src/export/transcript-formatter.ts +61 -2
  324. package/src/filing/filing-service.ts +40 -53
  325. package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
  326. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  327. package/src/heartbeat/heartbeat-service.ts +148 -127
  328. package/src/home/__tests__/feed-types.test.ts +63 -131
  329. package/src/home/__tests__/feed-writer.test.ts +77 -278
  330. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  331. package/src/home/feed-types.ts +19 -73
  332. package/src/home/feed-writer.ts +25 -156
  333. package/src/home/post-connect-feed.ts +1 -3
  334. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  335. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  336. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  337. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  338. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  339. package/src/ipc/assistant-server.ts +55 -6
  340. package/src/ipc/cli-client.ts +370 -50
  341. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  342. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  343. package/src/ipc/skill-routes/events.ts +30 -3
  344. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  345. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  346. package/src/live-voice/live-voice-session-manager.ts +11 -4
  347. package/src/live-voice/live-voice-session.ts +14 -6
  348. package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
  349. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  350. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  351. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  352. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  353. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  354. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
  355. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  356. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  357. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  358. package/src/memory/bookmark-crud.ts +179 -0
  359. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  360. package/src/memory/context-search/agent-protocol.ts +5 -1
  361. package/src/memory/context-search/agent-runner.ts +60 -85
  362. package/src/memory/context-search/limits.ts +1 -4
  363. package/src/memory/context-search/search.ts +23 -113
  364. package/src/memory/context-search/sources/conversations.ts +18 -6
  365. package/src/memory/context-search/sources/memory-v2.ts +39 -14
  366. package/src/memory/context-search/sources/memory.ts +7 -0
  367. package/src/memory/context-search/sources/workspace.ts +13 -10
  368. package/src/memory/context-search/types.ts +1 -1
  369. package/src/memory/conversation-bootstrap.ts +11 -0
  370. package/src/memory/conversation-crud.ts +312 -10
  371. package/src/memory/conversation-queries.ts +9 -5
  372. package/src/memory/conversation-title-service.ts +1 -0
  373. package/src/memory/conversation-types.ts +16 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +2 -1
  376. package/src/memory/embedding-runtime-manager.ts +1 -2
  377. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  378. package/src/memory/graph/conversation-graph-memory.ts +76 -5
  379. package/src/memory/graph/extraction.ts +4 -0
  380. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  381. package/src/memory/graph/tool-handlers.ts +17 -7
  382. package/src/memory/graph/tools.ts +44 -5
  383. package/src/memory/indexer.ts +17 -0
  384. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +13 -15
  385. package/src/memory/jobs/embed-concept-page.ts +45 -9
  386. package/src/memory/jobs-store.ts +51 -1
  387. package/src/memory/jobs-worker.ts +52 -3
  388. package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
  389. package/src/memory/llm-request-log-source-local.ts +26 -0
  390. package/src/memory/llm-request-log-source.ts +97 -0
  391. package/src/memory/llm-request-log-store.ts +1 -1
  392. package/src/memory/memory-retrospective-constants.ts +13 -0
  393. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  394. package/src/memory/memory-retrospective-job.ts +351 -0
  395. package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
  396. package/src/memory/memory-retrospective-state.ts +162 -0
  397. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  398. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  399. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  400. package/src/memory/message-content.ts +38 -1
  401. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  402. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  403. package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
  404. package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
  405. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  406. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  407. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  408. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  409. package/src/memory/migrations/243-provider-connections.ts +68 -0
  410. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  411. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  412. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  413. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  414. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  415. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  416. package/src/memory/migrations/index.ts +7 -0
  417. package/src/memory/published-pages-store.ts +16 -0
  418. package/src/memory/schema/bookmarks.ts +38 -0
  419. package/src/memory/schema/conversations.ts +2 -0
  420. package/src/memory/schema/index.ts +2 -0
  421. package/src/memory/schema/inference.ts +29 -0
  422. package/src/memory/schema/memory-core.ts +9 -0
  423. package/src/memory/search/semantic.ts +1 -4
  424. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  425. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  426. package/src/memory/v2/__tests__/activation.test.ts +11 -4
  427. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  428. package/src/memory/v2/__tests__/consolidation-job.test.ts +123 -135
  429. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  430. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  431. package/src/memory/v2/__tests__/injection.test.ts +628 -10
  432. package/src/memory/v2/__tests__/migration.test.ts +7 -3
  433. package/src/memory/v2/__tests__/page-index.test.ts +277 -0
  434. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  435. package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
  436. package/src/memory/v2/__tests__/qdrant.test.ts +72 -0
  437. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  438. package/src/memory/v2/__tests__/router.test.ts +516 -0
  439. package/src/memory/v2/__tests__/sim.test.ts +45 -1
  440. package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
  441. package/src/memory/v2/__tests__/static-context.test.ts +7 -22
  442. package/src/memory/v2/__tests__/sweep-job.test.ts +95 -0
  443. package/src/memory/v2/activation-store.ts +34 -5
  444. package/src/memory/v2/activation.ts +40 -27
  445. package/src/memory/v2/backfill-jobs.ts +17 -84
  446. package/src/memory/v2/consolidation-job.ts +85 -78
  447. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  448. package/src/memory/v2/injection.ts +440 -109
  449. package/src/memory/v2/migration.ts +117 -20
  450. package/src/memory/v2/page-index.ts +191 -0
  451. package/src/memory/v2/page-store.ts +3 -0
  452. package/src/memory/v2/prompts/consolidation.ts +9 -7
  453. package/src/memory/v2/prompts/router.ts +192 -0
  454. package/src/memory/v2/qdrant.ts +100 -87
  455. package/src/memory/v2/reranker.ts +14 -7
  456. package/src/memory/v2/router.ts +322 -0
  457. package/src/memory/v2/sim.ts +25 -12
  458. package/src/memory/v2/skill-store.ts +118 -29
  459. package/src/memory/v2/static-context.ts +16 -9
  460. package/src/memory/v2/sweep-job.ts +122 -96
  461. package/src/memory/v2/types.ts +10 -6
  462. package/src/memory/validation.ts +13 -0
  463. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  464. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  465. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  466. package/src/notifications/adapters/platform.ts +171 -0
  467. package/src/notifications/conversation-pairing.ts +2 -2
  468. package/src/notifications/copy-composer.ts +15 -0
  469. package/src/notifications/destination-resolver.ts +21 -0
  470. package/src/notifications/emit-signal.ts +28 -1
  471. package/src/notifications/home-feed-side-effect.ts +111 -0
  472. package/src/notifications/signal.ts +5 -0
  473. package/src/permissions/checker.ts +12 -0
  474. package/src/permissions/ipc-risk-types.ts +2 -0
  475. package/src/plugin-api/index.ts +13 -0
  476. package/src/plugin-api/package.json +12 -0
  477. package/src/plugin-api/types.ts +62 -0
  478. package/src/plugins/defaults/injectors.ts +19 -3
  479. package/src/plugins/external-plugin-loader.ts +294 -0
  480. package/src/plugins/types.ts +46 -30
  481. package/src/plugins/user-loader.ts +64 -41
  482. package/src/proactive-artifact/job.test.ts +12 -4
  483. package/src/proactive-artifact/job.ts +4 -0
  484. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  485. package/src/proactive-artifact/trigger-state.ts +4 -0
  486. package/src/prompts/__tests__/system-prompt.test.ts +105 -0
  487. package/src/prompts/system-prompt.ts +22 -1
  488. package/src/prompts/update-bulletin-job.ts +61 -73
  489. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  490. package/src/providers/__tests__/inference.test.ts +288 -0
  491. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  492. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  493. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  494. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  495. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  496. package/src/providers/anthropic/client.ts +95 -26
  497. package/src/providers/call-site-routing.ts +94 -16
  498. package/src/providers/connection-resolution.ts +163 -0
  499. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  500. package/src/providers/inference/adapter-factory.ts +173 -0
  501. package/src/providers/inference/auth.ts +112 -0
  502. package/src/providers/inference/backfill.ts +196 -0
  503. package/src/providers/inference/connections.ts +356 -0
  504. package/src/providers/inference/resolve-auth.ts +65 -0
  505. package/src/providers/model-catalog.ts +104 -6
  506. package/src/providers/openai/responses-provider.ts +4 -2
  507. package/src/providers/provider-env-vars.ts +17 -7
  508. package/src/providers/provider-secret-catalog.ts +49 -30
  509. package/src/providers/provider-send-message.ts +41 -20
  510. package/src/providers/registry.ts +143 -159
  511. package/src/providers/retry.ts +18 -10
  512. package/src/providers/search-provider-catalog.ts +121 -0
  513. package/src/runtime/AGENTS.md +18 -5
  514. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  515. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  516. package/src/runtime/actor-trust-resolver.ts +32 -10
  517. package/src/runtime/agent-wake.ts +35 -6
  518. package/src/runtime/assistant-event-hub.ts +3 -85
  519. package/src/runtime/auth/route-policy.ts +303 -8
  520. package/src/runtime/auth/same-actor.ts +2 -0
  521. package/src/runtime/background-job-runner.ts +339 -0
  522. package/src/runtime/btw-sidechain.ts +1 -0
  523. package/src/runtime/http-router.ts +36 -1
  524. package/src/runtime/http-server.ts +31 -5
  525. package/src/runtime/http-types.ts +2 -0
  526. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  527. package/src/runtime/middleware/request-logger.ts +62 -1
  528. package/src/runtime/pre-first-message-gate.ts +83 -0
  529. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  530. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
  531. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  532. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
  533. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
  534. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  535. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  536. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +4 -4
  537. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  538. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  539. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  540. package/src/runtime/routes/acp-routes.ts +10 -8
  541. package/src/runtime/routes/app-management-routes.ts +228 -3
  542. package/src/runtime/routes/approval-routes.ts +0 -18
  543. package/src/runtime/routes/audit-routes.ts +43 -0
  544. package/src/runtime/routes/auth-routes.ts +72 -0
  545. package/src/runtime/routes/avatar-routes.ts +273 -20
  546. package/src/runtime/routes/backup-routes.ts +406 -2
  547. package/src/runtime/routes/bookmark-routes.ts +154 -0
  548. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  549. package/src/runtime/routes/contact-routes.ts +0 -160
  550. package/src/runtime/routes/conversation-cli-routes.ts +192 -0
  551. package/src/runtime/routes/conversation-management-routes.ts +30 -43
  552. package/src/runtime/routes/conversation-query-routes.ts +334 -86
  553. package/src/runtime/routes/conversation-routes.ts +31 -10
  554. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  555. package/src/runtime/routes/credential-routes.ts +540 -0
  556. package/src/runtime/routes/debug-routes.ts +2 -2
  557. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  558. package/src/runtime/routes/domain-routes.ts +167 -0
  559. package/src/runtime/routes/email-routes.ts +603 -0
  560. package/src/runtime/routes/errors.ts +2 -2
  561. package/src/runtime/routes/events-routes.ts +192 -0
  562. package/src/runtime/routes/home-feed-routes.ts +6 -78
  563. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  564. package/src/runtime/routes/host-browser-routes.ts +103 -22
  565. package/src/runtime/routes/http-adapter.ts +2 -0
  566. package/src/runtime/routes/identity-routes.ts +5 -0
  567. package/src/runtime/routes/image-generation-routes.ts +99 -0
  568. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
  569. package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
  570. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  571. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -4
  572. package/src/runtime/routes/index.ts +36 -0
  573. package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
  574. package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
  575. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  576. package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
  577. package/src/runtime/routes/inference-send-routes.ts +115 -0
  578. package/src/runtime/routes/integrations/twilio.ts +1 -0
  579. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  580. package/src/runtime/routes/memory-v2-routes.ts +13 -398
  581. package/src/runtime/routes/notification-routes.ts +2 -0
  582. package/src/runtime/routes/oauth-apps.ts +112 -7
  583. package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
  584. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  585. package/src/runtime/routes/oauth-providers.ts +298 -8
  586. package/src/runtime/routes/platform-routes.ts +336 -0
  587. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  588. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  589. package/src/runtime/routes/playground/state.ts +2 -1
  590. package/src/runtime/routes/publish-routes.ts +221 -0
  591. package/src/runtime/routes/schedule-routes.ts +82 -0
  592. package/src/runtime/routes/sequence-routes.ts +291 -0
  593. package/src/runtime/routes/settings-routes.ts +2 -10
  594. package/src/runtime/routes/skills-routes.ts +31 -1
  595. package/src/runtime/routes/stt-routes.ts +240 -3
  596. package/src/runtime/routes/surface-action-routes.ts +43 -7
  597. package/src/runtime/routes/tts-routes.ts +67 -0
  598. package/src/runtime/routes/types.ts +32 -0
  599. package/src/runtime/routes/user-routes-cli.ts +243 -0
  600. package/src/runtime/routes/webhook-routes.ts +165 -0
  601. package/src/runtime/sync/resource-sync-events.ts +25 -0
  602. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  603. package/src/runtime/sync/sync-publisher.ts +21 -0
  604. package/src/schedule/scheduler.ts +200 -123
  605. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  606. package/src/security/secret-patterns.ts +3 -0
  607. package/src/sequence/engine.ts +38 -40
  608. package/src/subagent/manager.ts +20 -15
  609. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  610. package/src/tools/browser/browser-execution.ts +15 -4
  611. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  612. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  613. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  614. package/src/tools/browser/cdp-client/factory.ts +66 -5
  615. package/src/tools/browser/runtime-check.ts +77 -0
  616. package/src/tools/memory/register.test.ts +3 -3
  617. package/src/tools/memory/register.ts +9 -1
  618. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  619. package/src/tools/network/web-search.ts +280 -37
  620. package/src/tools/permission-checker.ts +13 -5
  621. package/src/tools/subagent/spawn.ts +3 -3
  622. package/src/tools/terminal/shell.ts +44 -0
  623. package/src/usage/attribution.ts +3 -2
  624. package/src/util/pricing.ts +86 -160
  625. package/src/watcher/__tests__/engine.test.ts +301 -0
  626. package/src/watcher/constants.ts +7 -0
  627. package/src/watcher/engine.ts +90 -90
  628. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  629. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  630. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
  631. package/src/workspace/migrations/069-seed-onboarding-threads.ts +8 -2
  632. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
  633. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
  634. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  635. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  636. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  637. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  638. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  639. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  640. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  641. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  642. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  643. package/src/workspace/migrations/registry.ts +22 -0
  644. package/src/workspace/migrations/runner.ts +13 -2
  645. package/src/workspace/migrations/types.ts +13 -3
  646. package/src/workspace/provider-commit-message-generator.ts +3 -2
  647. package/src/__tests__/context-search-pkb-source.test.ts +0 -498
  648. package/src/__tests__/credentials-cli.test.ts +0 -1225
  649. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  650. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  651. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  652. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  653. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  654. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  655. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  656. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  657. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  658. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  659. package/src/cli/commands/autonomy.ts +0 -365
  660. package/src/cli/commands/memory.ts +0 -424
  661. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -947
  662. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  663. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  664. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  665. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  666. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  667. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  668. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  669. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  670. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  671. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  672. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  673. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  674. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  675. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  676. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  677. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  678. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  679. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  680. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  681. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  682. package/src/home/assistant-feed-authoring.ts +0 -135
  683. package/src/home/emit-feed-event.ts +0 -169
  684. package/src/home/feed-scheduler.ts +0 -281
  685. package/src/home/platform-gmail-digest.ts +0 -163
  686. package/src/home/rewrite-command-preview.ts +0 -66
  687. package/src/home/rewrite-feed-title.ts +0 -58
  688. package/src/home/rollup-producer.ts +0 -426
  689. package/src/memory/admin.ts +0 -326
  690. package/src/memory/context-search/sources/pkb.ts +0 -476
  691. package/src/memory/graph/compaction.ts +0 -299
  692. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -0,0 +1,48 @@
1
+ import { z } from "zod";
2
+
3
+ export const MemoryRetrospectiveConfigSchema = z
4
+ .object({
5
+ timeThresholdMs: z
6
+ .number({
7
+ error: "memory.retrospective.timeThresholdMs must be a number",
8
+ })
9
+ .int("memory.retrospective.timeThresholdMs must be an integer")
10
+ .positive(
11
+ "memory.retrospective.timeThresholdMs must be a positive integer",
12
+ )
13
+ .default(30 * 60 * 1000)
14
+ .describe(
15
+ "Milliseconds since the last retrospective attempt before the interval trigger fires.",
16
+ ),
17
+
18
+ messageThreshold: z
19
+ .number({
20
+ error: "memory.retrospective.messageThreshold must be a number",
21
+ })
22
+ .int("memory.retrospective.messageThreshold must be an integer")
23
+ .positive(
24
+ "memory.retrospective.messageThreshold must be a positive integer",
25
+ )
26
+ .default(10)
27
+ .describe(
28
+ "New messages since the last successful retrospective run before the message-count trigger fires.",
29
+ ),
30
+
31
+ minCooldownMs: z
32
+ .number({ error: "memory.retrospective.minCooldownMs must be a number" })
33
+ .int("memory.retrospective.minCooldownMs must be an integer")
34
+ .nonnegative(
35
+ "memory.retrospective.minCooldownMs must be a non-negative integer",
36
+ )
37
+ .default(5 * 60 * 1000)
38
+ .describe(
39
+ "Minimum milliseconds between attempts (success or failure). Prevents tight retry loops across trigger types. Pre-compaction bypasses this gate.",
40
+ ),
41
+ })
42
+ .describe(
43
+ "Controls the memory-retrospective background pass triggered by the `memory-retrospective` feature flag. Model selection lives under llm.callSites.memoryRetrospective.",
44
+ );
45
+
46
+ export type MemoryRetrospectiveConfig = z.infer<
47
+ typeof MemoryRetrospectiveConfigSchema
48
+ >;
@@ -256,9 +256,40 @@ export const MemoryV2ConfigSchema = z
256
256
  .describe(
257
257
  "Cross-encoder rerank configuration. When enabled, picks the top-K candidates by pre-rerank A_o, runs the cross-encoder once per channel (user, assistant) on that unified set, and adds an alpha-weighted normalized boost to A_o for each scored slug.",
258
258
  ),
259
+ router: z
260
+ .object({
261
+ enabled: z
262
+ .boolean()
263
+ .default(false)
264
+ .describe(
265
+ "Whether to use the LLM router as the per-turn page-selection mechanism in place of spreading activation. Disabled by default — opt in once the router orchestration and dispatcher land.",
266
+ ),
267
+ max_page_ids: z
268
+ .number()
269
+ .int()
270
+ .min(1)
271
+ .max(100)
272
+ .default(25)
273
+ .describe(
274
+ "Upper bound on the number of concept-page ids the router may return per turn. Caps both prompt size and downstream injection budget.",
275
+ ),
276
+ router_prompt_path: z
277
+ .string({
278
+ error: "memory.v2.router.router_prompt_path must be a string",
279
+ })
280
+ .nullable()
281
+ .default(null)
282
+ .describe(
283
+ "Optional path to a file whose contents replace the bundled router prompt. Absolute paths are used as-is, a leading `~/` is expanded to the home directory, otherwise the path is resolved under the workspace root. The loaded contents may include `{{ASSISTANT_NAME}}`, `{{USER_NAME}}`, and `{{PAGE_INDEX}}`, which are substituted at runtime. If the file is missing, unreadable, or empty, the bundled prompt is used and a warning is logged.",
284
+ ),
285
+ })
286
+ .default({ enabled: false, max_page_ids: 25, router_prompt_path: null })
287
+ .describe(
288
+ "LLM router configuration. When enabled, a single Sonnet router call replaces spreading activation for per-turn page selection.",
289
+ ),
259
290
  })
260
291
  .describe(
261
- "Memory v2 — concept-page activation model with hourly LLM-driven consolidation",
292
+ "Memory v2 — concept-page activation model with periodic LLM-driven consolidation",
262
293
  )
263
294
  .superRefine((config, ctx) => {
264
295
  const activationSum =
@@ -10,6 +10,7 @@ import {
10
10
  MemorySummarizationConfigSchema,
11
11
  } from "./memory-processing.js";
12
12
  import { MemoryRetrievalConfigSchema } from "./memory-retrieval.js";
13
+ import { MemoryRetrospectiveConfigSchema } from "./memory-retrospective.js";
13
14
  import {
14
15
  MemoryEmbeddingsConfigSchema,
15
16
  MemorySegmentationConfigSchema,
@@ -47,6 +48,9 @@ export const MemoryConfigSchema = z
47
48
  MemorySummarizationConfigSchema.parse({}),
48
49
  ),
49
50
  v2: MemoryV2ConfigSchema.default(MemoryV2ConfigSchema.parse({})),
51
+ retrospective: MemoryRetrospectiveConfigSchema.default(
52
+ MemoryRetrospectiveConfigSchema.parse({}),
53
+ ),
50
54
  })
51
55
  .describe(
52
56
  "Long-term memory system — stores, retrieves, and manages persistent knowledge across conversations",
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
 
3
+ import { SEARCH_PROVIDER_IDS } from "../../providers/search-provider-catalog.js";
3
4
  import { SttServiceSchema } from "./stt.js";
4
5
  import { TtsServiceSchema } from "./tts.js";
5
6
 
@@ -17,25 +18,27 @@ export const VALID_INFERENCE_PROVIDERS = [
17
18
 
18
19
  const VALID_IMAGE_GEN_PROVIDERS = ["gemini", "openai"] as const;
19
20
 
20
- const VALID_WEB_SEARCH_PROVIDERS = [
21
- "perplexity",
22
- "brave",
23
- "inference-provider-native",
24
- ] as const;
21
+ /**
22
+ * Derived from `SEARCH_PROVIDER_CATALOG`. Adding a new web-search provider
23
+ * to the catalog automatically extends the config-schema enum — no edit
24
+ * here required.
25
+ */
26
+ const VALID_WEB_SEARCH_PROVIDERS = SEARCH_PROVIDER_IDS;
25
27
 
26
28
  const BaseServiceSchema = z.object({
27
29
  mode: ServiceModeSchema.default("your-own"),
28
30
  });
29
31
 
30
32
  /**
31
- * Inference service entry. Carries only the routing `mode`
32
- * (`managed` vs `your-own`) the provider and model live under
33
- * `llm.default.{provider, model}` (see `schemas/llm.ts`). PR 19 of the
34
- * unify-llm-callsites plan removed the `provider` and `model` fields here;
35
- * legacy configs that still carry them have those keys stripped by
36
- * workspace migration `039-drop-legacy-llm-keys`.
33
+ * Inference service entry. Carries no fields routing is now governed
34
+ * entirely by `provider_connections` rows and the `provider_connection`
35
+ * reference on each `llm.profile`. The namespace is kept so callers
36
+ * that walk `config.services.inference` do not need updating.
37
+ *
38
+ * Legacy `provider`, `model`, and `mode` fields are stripped by workspace
39
+ * migrations `039-drop-legacy-llm-keys` and `076-drop-services-inference-mode`.
37
40
  */
38
- const InferenceServiceSchema = BaseServiceSchema;
41
+ const InferenceServiceSchema = z.object({});
39
42
 
40
43
  const ImageGenerationServiceSchema = BaseServiceSchema.extend({
41
44
  provider: z.enum(VALID_IMAGE_GEN_PROVIDERS).default("gemini"),
@@ -1,26 +1,44 @@
1
+ import type { DrizzleDb } from "../memory/db-connection.js";
2
+ import {
3
+ createConnection,
4
+ disableManagedConnectionsForByokHatch,
5
+ getConnection,
6
+ } from "../providers/inference/connections.js";
1
7
  import { PROVIDER_CATALOG } from "../providers/model-catalog.js";
2
8
  import { resolveModelIntent } from "../providers/model-intents.js";
3
9
  import type { ModelIntent } from "../providers/types.js";
10
+ import { credentialKey } from "../security/credential-key.js";
11
+ import { getLogger } from "../util/logger.js";
4
12
  import { loadRawConfig, saveRawConfig } from "./loader.js";
5
13
  import {
6
14
  DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS,
7
15
  type ProfileEntry,
8
16
  } from "./schemas/llm.js";
9
17
 
18
+ const log = getLogger("seed-inference-profiles");
19
+
20
+ const MANAGED_CONNECTION_NAME = "anthropic-managed";
21
+ const MANAGED_PROFILE_PROVIDER: NonNullable<ProfileEntry["provider"]> =
22
+ "anthropic";
23
+
10
24
  /**
11
25
  * Template for a daemon-managed inference profile. The profile's model is
12
26
  * resolved at seed time from `PROVIDER_MODEL_INTENTS` so the catalog stays the
13
27
  * single source of truth for "which model does this intent map to?".
14
28
  */
15
- type ManagedProfileTemplate = Omit<ProfileEntry, "provider" | "model"> & {
29
+ type ManagedProfileTemplate = Omit<
30
+ ProfileEntry,
31
+ "provider" | "model" | "provider_connection"
32
+ > & {
16
33
  intent: ModelIntent;
17
34
  };
18
35
 
19
36
  /**
20
- * Anthropic-managed profiles. Always seeded so users can target Anthropic via
21
- * their own key, even when the resolved default provider is something else.
37
+ * Managed Anthropic profiles. Overwritten on every daemon boot so Vellum can
38
+ * push model/config updates to customers in new releases. Platform overlays
39
+ * (`preserveProfileNames`) take precedence when present.
22
40
  */
23
- const ANTHROPIC_PROFILE_TEMPLATES: Record<string, ManagedProfileTemplate> = {
41
+ const MANAGED_PROFILE_TEMPLATES: Record<string, ManagedProfileTemplate> = {
24
42
  balanced: {
25
43
  intent: "balanced",
26
44
  source: "managed",
@@ -54,15 +72,15 @@ const ANTHROPIC_PROFILE_TEMPLATES: Record<string, ManagedProfileTemplate> = {
54
72
  };
55
73
 
56
74
  /**
57
- * Custom-provider profile templates. Materialized at seed time when the
58
- * resolved default provider is non-Anthropic, using `resolveModelIntent` to
59
- * pick the model.
75
+ * User profile templates. Materialized at hatch time for off-platform
76
+ * installations. Each points at the user's personal provider connection
77
+ * (backed by their API key in CES).
60
78
  */
61
- const CUSTOM_PROFILE_TEMPLATES: Record<string, ManagedProfileTemplate> = {
79
+ const USER_PROFILE_TEMPLATES: Record<string, ManagedProfileTemplate> = {
62
80
  "custom-balanced": {
63
81
  intent: "balanced",
64
82
  source: "user",
65
- label: "Balanced (Custom Provider)",
83
+ label: "Balanced",
66
84
  description: "Good balance of quality, cost, and speed",
67
85
  maxTokens: 16000,
68
86
  effort: "high",
@@ -72,7 +90,7 @@ const CUSTOM_PROFILE_TEMPLATES: Record<string, ManagedProfileTemplate> = {
72
90
  "custom-quality-optimized": {
73
91
  intent: "quality-optimized",
74
92
  source: "user",
75
- label: "Quality (Custom Provider)",
93
+ label: "Quality",
76
94
  description: "Best results with the most capable model",
77
95
  maxTokens: 32000,
78
96
  effort: "max",
@@ -82,7 +100,7 @@ const CUSTOM_PROFILE_TEMPLATES: Record<string, ManagedProfileTemplate> = {
82
100
  "custom-cost-optimized": {
83
101
  intent: "latency-optimized",
84
102
  source: "user",
85
- label: "Speed (Custom Provider)",
103
+ label: "Speed",
86
104
  description: "Fastest responses at lower cost",
87
105
  maxTokens: 8192,
88
106
  effort: "low",
@@ -92,41 +110,37 @@ const CUSTOM_PROFILE_TEMPLATES: Record<string, ManagedProfileTemplate> = {
92
110
  };
93
111
 
94
112
  export const MANAGED_PROFILE_NAMES = new Set(
95
- Object.keys(ANTHROPIC_PROFILE_TEMPLATES),
113
+ Object.keys(MANAGED_PROFILE_TEMPLATES),
96
114
  );
97
115
 
98
- const SEEDED_PROFILE_NAMES = new Set([
99
- ...Object.keys(ANTHROPIC_PROFILE_TEMPLATES),
100
- ...Object.keys(CUSTOM_PROFILE_TEMPLATES),
101
- ]);
102
-
103
- const KNOWN_PROVIDERS = new Set(PROVIDER_CATALOG.map((entry) => entry.id));
104
-
105
116
  export type SeedInferenceProfilesOptions = {
106
117
  /**
107
- * Managed profile names supplied by the platform/default overlay for this
108
- * startup. Those entries are already on disk by the time seeding runs and
109
- * should remain authoritative for this boot.
118
+ * Profile names supplied by the platform/default overlay for this startup.
119
+ * Those entries are already on disk and should remain authoritative.
110
120
  */
111
121
  preserveProfileNames?: Iterable<string>;
112
122
  preserveActiveProfile?: boolean;
123
+ /** True when a hatch overlay was consumed this startup. */
124
+ isHatch?: boolean;
125
+ /** DB handle for creating user provider connections at hatch time. */
126
+ db?: DrizzleDb;
113
127
  };
114
128
 
115
129
  /**
116
- * Seed managed inference profiles into the workspace config.
130
+ * Seed inference profiles into the workspace config.
131
+ *
132
+ * Runs on every daemon startup. Two responsibilities:
117
133
  *
118
- * Called on every daemon startup after workspace migrations and default-config
119
- * overlay merge, but before the first `loadConfig()`. The 3 Anthropic-managed
120
- * profiles (`balanced`, `quality-optimized`, `cost-optimized`) are always
121
- * written so users can target Anthropic via their own key. When the resolved
122
- * default provider is non-Anthropic, the 3 `custom-*` profiles are also
123
- * materialized using `resolveModelIntent` against that provider, and
124
- * `custom-balanced` becomes the active profile for fresh hatches.
134
+ * 1. **Managed profiles** (`balanced`, `quality-optimized`, `cost-optimized`):
135
+ * overwritten on every boot so Vellum can push model/config updates to
136
+ * customers. Each carries `provider_connection: "anthropic-managed"`.
137
+ * Platform overlays (`preserveProfileNames`) take precedence.
125
138
  *
126
- * Default-config overlays can provide their own profile fragments and active
127
- * profile. Lifecycle passes those explicit fields in `options`, letting local
128
- * hatches still receive managed defaults while platform-owned profile choices
129
- * remain authoritative.
139
+ * 2. **User profiles** (`custom-balanced`, `custom-quality-optimized`,
140
+ * `custom-cost-optimized`): materialized once at hatch time for
141
+ * off-platform installations. Each points at a personal provider
142
+ * connection backed by the user's API key in CES. Subsequent boots
143
+ * leave these untouched — the user owns them.
130
144
  */
131
145
  export function seedInferenceProfiles(
132
146
  options: SeedInferenceProfilesOptions = {},
@@ -144,56 +158,131 @@ export function seedInferenceProfiles(
144
158
  }
145
159
  const profiles = llm.profiles as Record<string, Record<string, unknown>>;
146
160
 
147
- const requestedProvider =
148
- readString(readObject(llm.default)?.provider) ?? "anthropic";
149
- const isKnownProvider = KNOWN_PROVIDERS.has(requestedProvider);
150
- const resolvedProvider: NonNullable<ProfileEntry["provider"]> =
151
- isKnownProvider
152
- ? (requestedProvider as NonNullable<ProfileEntry["provider"]>)
153
- : "anthropic";
154
- const isAnthropicDefault = resolvedProvider === "anthropic";
161
+ const isPlatform =
162
+ process.env.IS_PLATFORM === "true" || process.env.IS_PLATFORM === "1";
155
163
 
156
- // Persist the resolved provider when the overlay supplied an unrecognized
157
- // value, so the on-disk config doesn't keep emitting Zod warnings for
158
- // `unknownprov` on every load.
159
- if (!isKnownProvider) {
160
- const defaultBlock = (readObject(llm.default) ?? {}) as Record<
161
- string,
162
- unknown
163
- >;
164
- defaultBlock.provider = resolvedProvider;
165
- llm.default = defaultBlock;
166
- }
164
+ // BYOK mode = off-platform installs. The user is bringing their own provider
165
+ // API key; managed profile labels get a " (Managed)" suffix to disambiguate
166
+ // from the personal "custom-*" profiles that share base labels. Managed
167
+ // profile + connection status is initially "disabled" so the picker doesn't
168
+ // offer an unusable platform-auth option on day one — but ONLY at hatch
169
+ // time, and ONLY when the entry isn't already in the user's config (i.e.
170
+ // first materialization). Post-hatch user toggles survive every subsequent
171
+ // boot.
172
+ const isByokMode = !isPlatform;
167
173
 
168
- for (const [name, template] of Object.entries(ANTHROPIC_PROFILE_TEMPLATES)) {
174
+ // 1. Managed profiles. Off-platform: overwrite on every boot so Vellum can
175
+ // push model/config updates in new releases. On-platform: insert only if
176
+ // absent — the platform controls profiles through overlays, and the
177
+ // overlay fragment is authoritative even when it omits fields the local
178
+ // template carries (e.g. an overlay supplying only provider/model/label
179
+ // must not get its maxTokens/thinking polluted from the template). The
180
+ // legacy migration-052 backfill that seeds label-less Anthropic
181
+ // defaults is healed by workspace migration 082
182
+ // (`backfill-managed-profile-labels`) rather than the seeder, so
183
+ // this skip path stays simple.
184
+ //
185
+ // Two user-editable fields survive the overwrite: `label` (display
186
+ // rename) and `status` (active/disabled toggle). The PUT route
187
+ // `/v1/config/llm/profiles/:name` lets users patch these on managed
188
+ // profiles without duplicating; we have to honor those edits across
189
+ // reseeds or they'd silently revert on every boot. Carry by
190
+ // key-presence rather than truthiness so an explicit `null` (user
191
+ // cleared the label) survives too. Codex P1 finding on PR #30362.
192
+ //
193
+ // BYOK seed defaults (off-platform only):
194
+ // • label: " (Managed)" suffix disambiguates managed profile labels
195
+ // from personal "custom-*" profiles that share base labels.
196
+ // Upgrade migration: existing installs that already have the bare
197
+ // template label ("Balanced" / "Quality" / "Speed") on disk get
198
+ // rewritten to the suffixed form. Any other previous label value
199
+ // (user-set custom string, explicit null, already-suffixed) is
200
+ // preserved as-is.
201
+ // • status: "disabled" on fresh materialization at hatch only —
202
+ // gated on (isHatch && !previous) so post-hatch boots and existing
203
+ // installs are never auto-disabled. A user re-enable persists
204
+ // across boots via the key-presence preservation below.
205
+ for (const [name, template] of Object.entries(MANAGED_PROFILE_TEMPLATES)) {
169
206
  if (preservedProfileNames.has(name)) continue;
170
- // Preserve a previously overlay-supplied profile whose provider matches
171
- // the resolved default — that's the platform-managed case where the
172
- // overlay file has already been consumed and archived. Only valid for
173
- // non-Anthropic resolutions; when the default is Anthropic the daemon
174
- // owns these names and re-seeds with Anthropic data so a stale openai
175
- // `balanced` doesn't keep routing through the wrong provider after a
176
- // re-hatch back to Anthropic.
177
- const existing = readObject(profiles[name]);
178
- const existingProvider = readString(existing?.provider);
179
- if (
180
- existing !== null &&
181
- !isAnthropicDefault &&
182
- existingProvider === resolvedProvider
183
- ) {
184
- continue;
207
+ if (isPlatform && readObject(profiles[name]) !== null) continue;
208
+
209
+ const previous = readObject(profiles[name]);
210
+ const effectiveTemplate: ManagedProfileTemplate = isByokMode
211
+ ? { ...template, label: `${template.label} (Managed)` }
212
+ : template;
213
+ const next = materializeProfile(
214
+ effectiveTemplate,
215
+ MANAGED_PROFILE_PROVIDER,
216
+ MANAGED_CONNECTION_NAME,
217
+ ) as Record<string, unknown>;
218
+ if (isByokMode && options.isHatch && !previous) {
219
+ next.status = "disabled";
185
220
  }
186
- profiles[name] = materializeProfile(template, "anthropic");
221
+ if (previous) {
222
+ // Preserve user overrides on these whitelisted fields. The label path
223
+ // also runs the BYOK upgrade migration described above: if the on-disk
224
+ // label exactly equals the bare template default and we're in BYOK
225
+ // mode, rewrite to the suffixed effective label so existing installs
226
+ // get the disambiguation, not just fresh hatches.
227
+ if ("label" in previous) {
228
+ next.label =
229
+ isByokMode && previous.label === template.label
230
+ ? effectiveTemplate.label
231
+ : previous.label;
232
+ }
233
+ if ("status" in previous) next.status = previous.status;
234
+ }
235
+ profiles[name] = next as ProfileEntry;
187
236
  }
188
237
 
189
- if (!isAnthropicDefault) {
190
- for (const [name, template] of Object.entries(CUSTOM_PROFILE_TEMPLATES)) {
191
- if (preservedProfileNames.has(name)) continue;
192
- if (readObject(profiles[name]) !== null) continue;
193
- profiles[name] = materializeProfile(template, resolvedProvider);
238
+ // 2. User profiles — only at hatch time for off-platform installations.
239
+ let userConnectionName: string | undefined;
240
+ if (options.isHatch && !isPlatform) {
241
+ // BYOK hatch: disable the three canonical managed connections so the
242
+ // picker doesn't surface unusable platform-auth options on day one.
243
+ // Runs only here, only at hatch — `seedCanonicalConnections` leaves
244
+ // `status` alone on subsequent boots so a post-hatch user re-enable
245
+ // persists.
246
+ if (options.db) {
247
+ disableManagedConnectionsForByokHatch(options.db);
248
+ }
249
+
250
+ const hatchProvider = readString(readObject(llm.default)?.provider);
251
+ if (hatchProvider && hatchProvider !== "ollama") {
252
+ userConnectionName = `${hatchProvider}-personal`;
253
+
254
+ if (options.db) {
255
+ if (!getConnection(options.db, userConnectionName)) {
256
+ const credName = credentialKey(hatchProvider, "api_key");
257
+ const result = createConnection(options.db, {
258
+ name: userConnectionName,
259
+ provider: hatchProvider,
260
+ auth: { type: "api_key", credential: credName },
261
+ label: personalConnectionLabel(hatchProvider),
262
+ });
263
+ if (!result.ok) {
264
+ log.warn(
265
+ { provider: hatchProvider, error: result.error },
266
+ "Failed to create personal connection during hatch seeding",
267
+ );
268
+ }
269
+ }
270
+ }
271
+
272
+ const provider =
273
+ hatchProvider as NonNullable<ProfileEntry["provider"]>;
274
+ for (const [name, template] of Object.entries(USER_PROFILE_TEMPLATES)) {
275
+ if (preservedProfileNames.has(name)) continue;
276
+ profiles[name] = materializeProfile(
277
+ template,
278
+ provider,
279
+ userConnectionName,
280
+ );
281
+ }
194
282
  }
195
283
  }
196
284
 
285
+ // Active profile resolution.
197
286
  const requestedActiveProfile = readString(llm.activeProfile);
198
287
  const requestedActiveEntry =
199
288
  requestedActiveProfile !== undefined
@@ -203,80 +292,37 @@ export function seedInferenceProfiles(
203
292
  const shouldPreserveActiveProfile =
204
293
  options.preserveActiveProfile === true && requestedActiveExists;
205
294
 
206
- // Decide whether the existing active profile is still appropriate. A managed
207
- // profile whose provider no longer matches the resolved default goes stale
208
- // (e.g. re-hatching anthropic→openai leaves `balanced` pointing at anthropic;
209
- // re-hatching openai→anthropic leaves `custom-balanced` pointing at openai).
210
- // Either direction should land the user on the new default's `balanced`
211
- // counterpart rather than routing the main agent to a stale provider.
212
- // User-created profiles are left alone — those are the user's choice.
213
- let keepActiveProfile = shouldPreserveActiveProfile;
214
- if (!keepActiveProfile && requestedActiveExists) {
215
- const isSeededName = SEEDED_PROFILE_NAMES.has(requestedActiveProfile!);
216
- const activeProvider = readString(requestedActiveEntry?.provider);
217
- const managedActiveProviderMismatch =
218
- isSeededName && activeProvider !== resolvedProvider;
219
- keepActiveProfile = !managedActiveProviderMismatch;
220
- }
221
-
222
- let activeProfileName: string;
223
- if (keepActiveProfile) {
224
- activeProfileName = requestedActiveProfile!;
225
- } else {
226
- activeProfileName = isAnthropicDefault ? "balanced" : "custom-balanced";
227
- llm.activeProfile = activeProfileName;
228
- }
229
-
230
- // Sync `llm.default.model` to the active profile's model so the providers
231
- // registry sees a coherent provider/model pair. Only writes when the on-disk
232
- // default model is missing or unambiguously belongs to a *different*
233
- // provider's catalog (e.g. `claude-opus-4-7` paired with `provider: openai`).
234
- // A user-supplied model not listed in any provider's catalog is preserved —
235
- // ollama and openrouter expose far more models than `PROVIDER_CATALOG` lists,
236
- // and silently overwriting `codellama`/`phi3`/etc. on every restart would
237
- // break those users' configs. Skipped when the overlay owns the active
238
- // profile (platform mode).
239
295
  if (!shouldPreserveActiveProfile) {
240
- const activeEntry = readObject(profiles[activeProfileName]);
241
- const activeModel = readString(activeEntry?.model);
242
- if (activeModel !== undefined) {
243
- const defaultBlock = (readObject(llm.default) ?? {}) as Record<
244
- string,
245
- unknown
246
- >;
247
- const currentModel = readString(defaultBlock.model);
248
- const modelBelongsToOtherProvider =
249
- currentModel !== undefined &&
250
- PROVIDER_CATALOG.some(
251
- (p) =>
252
- p.id !== resolvedProvider &&
253
- p.models.some((m) => m.id === currentModel),
254
- );
255
- const shouldOverwriteDefaultModel =
256
- currentModel === undefined || modelBelongsToOtherProvider;
257
- if (shouldOverwriteDefaultModel) {
258
- defaultBlock.model = activeModel;
259
- llm.default = defaultBlock;
260
- }
296
+ if (options.isHatch) {
297
+ // Hatch = fresh setup. Pick the right default based on platform mode.
298
+ llm.activeProfile = userConnectionName ? "custom-balanced" : "balanced";
299
+ } else if (!requestedActiveExists) {
300
+ llm.activeProfile = "balanced";
261
301
  }
262
302
  }
263
303
 
304
+ // Profile ordering — ensure all seeded profiles appear in the order array.
264
305
  const profileOrder = Array.isArray(llm.profileOrder)
265
306
  ? (llm.profileOrder as string[])
266
307
  : [];
267
308
  const orderSet = new Set(profileOrder);
268
- const seededOrder = [
269
- ...Object.keys(ANTHROPIC_PROFILE_TEMPLATES),
270
- ...(isAnthropicDefault ? [] : Object.keys(CUSTOM_PROFILE_TEMPLATES)),
271
- ];
272
- for (const name of seededOrder) {
309
+ for (const name of Object.keys(MANAGED_PROFILE_TEMPLATES)) {
273
310
  if (!orderSet.has(name)) {
274
311
  profileOrder.push(name);
275
312
  orderSet.add(name);
276
313
  }
277
314
  }
315
+ if (userConnectionName) {
316
+ for (const name of Object.keys(USER_PROFILE_TEMPLATES)) {
317
+ if (!orderSet.has(name)) {
318
+ profileOrder.push(name);
319
+ orderSet.add(name);
320
+ }
321
+ }
322
+ }
278
323
  llm.profileOrder = profileOrder;
279
324
 
325
+ // Tag any remaining profiles without a source as user-created.
280
326
  for (const [name, profile] of Object.entries(profiles)) {
281
327
  if (MANAGED_PROFILE_NAMES.has(name)) continue;
282
328
  if (
@@ -294,11 +340,13 @@ export function seedInferenceProfiles(
294
340
  function materializeProfile(
295
341
  template: ManagedProfileTemplate,
296
342
  provider: NonNullable<ProfileEntry["provider"]>,
343
+ connectionName: string,
297
344
  ): ProfileEntry {
298
345
  const { intent, ...rest } = template;
299
346
  return {
300
347
  ...rest,
301
348
  provider,
349
+ provider_connection: connectionName,
302
350
  model: resolveModelIntent(provider, intent),
303
351
  };
304
352
  }
@@ -312,3 +360,16 @@ function readObject(value: unknown): Record<string, unknown> | null {
312
360
  function readString(value: unknown): string | undefined {
313
361
  return typeof value === "string" && value.length > 0 ? value : undefined;
314
362
  }
363
+
364
+ /**
365
+ * Format the human-readable label seeded onto a personal provider connection
366
+ * at hatch time, e.g. `"Anthropic (Personal)"`. The display name is sourced
367
+ * from `PROVIDER_CATALOG` so it tracks the canonical provider directory; an
368
+ * unrecognised provider id falls back to the raw id with the suffix.
369
+ */
370
+ function personalConnectionLabel(providerId: string): string {
371
+ const displayName =
372
+ PROVIDER_CATALOG.find((p) => p.id === providerId)?.displayName ??
373
+ providerId;
374
+ return `${displayName} (Personal)`;
375
+ }