@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
@@ -1,7 +1,6 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { basename } from "node:path";
3
3
 
4
- import { emitFeedEvent } from "../../../../home/emit-feed-event.js";
5
4
  import {
6
5
  addMessage,
7
6
  getConversation,
@@ -150,14 +149,6 @@ export async function run(
150
149
  ccList.length > 0
151
150
  ? `To: ${toList.join(", ")}; Cc: ${ccList.join(", ")}`
152
151
  : `To: ${toList.join(", ")}`;
153
- void emitFeedEvent({
154
- source: "gmail",
155
- title: "Email Draft Created",
156
- summary: `Drafted reply to ${recipientSummary}.`,
157
- dedupKey: `email-draft:${draft.id}`,
158
- }).catch((err) => {
159
- log.warn({ err }, "Failed to emit email draft feed event");
160
- });
161
152
  return ok(
162
153
  `Gmail draft created with ${attachments.length} attachment(s): ${filenames} (Draft ID: ${draft.id}). ${recipientSummary}. Review in Gmail Drafts, then tell me to send it or send it yourself.`,
163
154
  );
@@ -178,14 +169,6 @@ export async function run(
178
169
  ccList.length > 0
179
170
  ? `To: ${toList.join(", ")}; Cc: ${ccList.join(", ")}`
180
171
  : `To: ${toList.join(", ")}`;
181
- void emitFeedEvent({
182
- source: "gmail",
183
- title: "Email Draft Created",
184
- summary: `Drafted reply to ${recipientSummary}.`,
185
- dedupKey: `email-draft:${draft.id}`,
186
- }).catch((err) => {
187
- log.warn({ err }, "Failed to emit email draft feed event");
188
- });
189
172
  return ok(
190
173
  `Gmail draft created (ID: ${draft.id}). ${recipientSummary}. Review in Gmail Drafts, then tell me to send it or send it yourself.`,
191
174
  );
@@ -212,14 +195,6 @@ export async function run(
212
195
  const draft = await createDraftRaw(gmailConn, raw, threadId);
213
196
 
214
197
  const filenames = attachments.map((a) => a.filename).join(", ");
215
- void emitFeedEvent({
216
- source: "gmail",
217
- title: "Email Draft Created",
218
- summary: "Created an email draft.",
219
- dedupKey: `email-draft:${draft.id}`,
220
- }).catch((err) => {
221
- log.warn({ err }, "Failed to emit email draft feed event");
222
- });
223
198
  return ok(
224
199
  `Gmail draft created with ${attachments.length} attachment(s): ${filenames} (Draft ID: ${draft.id}). Review in Gmail Drafts, then tell me to send it or send it yourself.`,
225
200
  );
@@ -236,14 +211,6 @@ export async function run(
236
211
  undefined,
237
212
  threadId,
238
213
  );
239
- void emitFeedEvent({
240
- source: "gmail",
241
- title: "Email Draft Created",
242
- summary: "Created an email draft.",
243
- dedupKey: `email-draft:${draft.id}`,
244
- }).catch((err) => {
245
- log.warn({ err }, "Failed to emit email draft feed event");
246
- });
247
214
  return ok(
248
215
  `Gmail draft created (ID: ${draft.id}). Review it in your Gmail Drafts, then tell me to send it or send it yourself from Gmail.`,
249
216
  );
@@ -257,31 +224,6 @@ export async function run(
257
224
  assistantId: context.assistantId,
258
225
  });
259
226
 
260
- const sendSummary =
261
- provider.id === "slack"
262
- ? "Sent a Slack message."
263
- : provider.id === "telegram"
264
- ? "Sent a Telegram message."
265
- : "Sent an email.";
266
- void emitFeedEvent({
267
- source:
268
- provider.id === "slack"
269
- ? "slack"
270
- : provider.id === "telegram"
271
- ? "telegram"
272
- : "gmail",
273
- title:
274
- provider.id === "slack"
275
- ? "Slack Message Sent"
276
- : provider.id === "telegram"
277
- ? "Telegram Message Sent"
278
- : "Email Sent",
279
- summary: sendSummary,
280
- dedupKey: `message-sent:${result.id}`,
281
- }).catch((err) => {
282
- log.warn({ err }, "Failed to emit message send feed event");
283
- });
284
-
285
227
  const threadSuffix = result.threadId
286
228
  ? `, "thread_id": "${result.threadId}"`
287
229
  : "";
@@ -49,7 +49,6 @@ import * as computerUseWait from "./bundled-skills/computer-use/tools/computer-u
49
49
  // ── contacts ───────────────────────────────────────────────────────────────────
50
50
  import * as contactMerge from "./bundled-skills/contacts/tools/contact-merge.js";
51
51
  import * as contactSearch from "./bundled-skills/contacts/tools/contact-search.js";
52
- import * as contactUpsert from "./bundled-skills/contacts/tools/contact-upsert.js";
53
52
  import * as googleContacts from "./bundled-skills/contacts/tools/google-contacts.js";
54
53
  // ── document ───────────────────────────────────────────────────────────────────
55
54
  import * as documentCreate from "./bundled-skills/document/tools/document-create.js";
@@ -163,7 +162,6 @@ export const bundledToolRegistry = new Map<string, SkillToolScript>([
163
162
  ["computer-use:tools/computer-use-respond.ts", computerUseRespond],
164
163
 
165
164
  // contacts
166
- ["contacts:tools/contact-upsert.ts", contactUpsert],
167
165
  ["contacts:tools/contact-search.ts", contactSearch],
168
166
  ["contacts:tools/contact-merge.ts", contactMerge],
169
167
  ["contacts:tools/google-contacts.ts", googleContacts],
@@ -9,6 +9,14 @@
9
9
  "description": "Automatically trigger conversation analysis on the same cadence as memory extraction (batch threshold, idle debounce, end-of-conversation). The analysis agent has full tool access and writes back to memory and skills without user approval.",
10
10
  "defaultEnabled": false
11
11
  },
12
+ {
13
+ "id": "memory-retrospective",
14
+ "scope": "assistant",
15
+ "key": "memory-retrospective",
16
+ "label": "Memory retrospective pass",
17
+ "description": "Run a focused, memory-only retrospective during active conversations and at conversation lifecycle. The retrospective agent re-reads the messages added since the last successful run, dedupes against memory/archive/, and calls `remember` for what wasn't captured in the moment. Enabling this also relaxes the in-conversation pressure to call `remember` (lighter PKB reminder + relaxed tool description) so the assistant can stay present and trust the retrospective as the backstop.",
18
+ "defaultEnabled": false
19
+ },
12
20
  {
13
21
  "id": "user-hosted-enabled",
14
22
  "scope": "client",
@@ -193,6 +201,14 @@
193
201
  "description": "Route embedding requests through the platform runtime proxy using Vellum-managed Gemini credentials when available",
194
202
  "defaultEnabled": false
195
203
  },
204
+ {
205
+ "id": "bookmarks",
206
+ "scope": "client",
207
+ "key": "bookmarks",
208
+ "label": "Message Bookmarks",
209
+ "description": "Show the bookmark icon on messages and enable the Bookmarks tab in Settings",
210
+ "defaultEnabled": false
211
+ },
196
212
  {
197
213
  "id": "fork-from-message",
198
214
  "scope": "client",
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
 
3
+ import { getCatalogProviderForModel } from "../providers/model-catalog.js";
3
4
  import {
4
5
  type LLMCallSite,
5
6
  LLMConfigBase,
@@ -67,7 +68,7 @@ export function resolveCallSiteConfig(
67
68
  appendCallSiteLayers(layers, callSite, llm, site);
68
69
  }
69
70
 
70
- return finalize(deepMerge(...layers));
71
+ return finalize(deepMerge(...layers.map(withImpliedProviderForKnownModel)));
71
72
  }
72
73
 
73
74
  // ---------------------------------------------------------------------------
@@ -76,6 +77,20 @@ export function resolveCallSiteConfig(
76
77
 
77
78
  type Mergeable = Record<string, unknown>;
78
79
 
80
+ function withImpliedProviderForKnownModel(source: Mergeable): Mergeable {
81
+ if (source.provider !== undefined) return source;
82
+ const model = source.model;
83
+ if (typeof model !== "string" || model.length === 0) return source;
84
+
85
+ const provider = getCatalogProviderForModel(model);
86
+ if (provider === undefined) return source;
87
+
88
+ return {
89
+ ...source,
90
+ provider,
91
+ };
92
+ }
93
+
79
94
  function appendProfileLayer(
80
95
  layers: Mergeable[],
81
96
  profile: ProfileEntry | undefined,
@@ -124,7 +124,6 @@ export function getDeploymentContextDefaults(): Record<string, unknown> {
124
124
  const managed = { mode: "managed" as const };
125
125
  return {
126
126
  services: {
127
- inference: managed,
128
127
  "image-generation": managed,
129
128
  "web-search": managed,
130
129
  "google-oauth": managed,
@@ -520,12 +519,14 @@ export function deepMergeOverwrite(
520
519
  }
521
520
 
522
521
  export type DefaultWorkspaceConfigMergeResult = {
522
+ hadOverlay: boolean;
523
523
  providedLlmProfileNames: Set<string>;
524
524
  providedLlmActiveProfile: boolean;
525
525
  };
526
526
 
527
527
  function emptyDefaultWorkspaceConfigMergeResult(): DefaultWorkspaceConfigMergeResult {
528
528
  return {
529
+ hadOverlay: false,
529
530
  providedLlmProfileNames: new Set(),
530
531
  providedLlmActiveProfile: false,
531
532
  };
@@ -571,6 +572,7 @@ export function mergeDefaultWorkspaceConfig(): DefaultWorkspaceConfigMergeResult
571
572
  );
572
573
  const providedProfiles = readPlainObject(llmDefaults?.profiles);
573
574
  const mergeResult: DefaultWorkspaceConfigMergeResult = {
575
+ hadOverlay: true,
574
576
  providedLlmProfileNames: new Set(
575
577
  providedProfiles ? Object.keys(providedProfiles) : [],
576
578
  ),
@@ -649,7 +651,24 @@ export function loadConfig(): AssistantConfig {
649
651
  let configFileExisted = true;
650
652
  if (existsSync(configPath)) {
651
653
  try {
652
- fileConfig = JSON.parse(readFileSync(configPath, "utf-8"));
654
+ const parsed: unknown = JSON.parse(readFileSync(configPath, "utf-8"));
655
+ if (!isPlainObject(parsed)) {
656
+ // Same shape contract as `loadRawConfig`: top-level value must be a
657
+ // plain object. A `null`, primitive, or array is treated like a
658
+ // parse error so downstream code (`warnAndStripDeprecatedFields`,
659
+ // `setNestedValue` in the managed-Gemini migration block, etc.)
660
+ // never iterates a non-record. Quarantine + fall through to defaults.
661
+ quarantineCorruptConfig(
662
+ configPath,
663
+ new Error(
664
+ `config.json must contain a JSON object at the top level; got ${describeJsonShape(parsed)}`,
665
+ ),
666
+ );
667
+ fileConfig = {};
668
+ configFileExisted = false;
669
+ } else {
670
+ fileConfig = parsed;
671
+ }
653
672
  } catch (err) {
654
673
  // The daemon must never block startup (assistant/CLAUDE.md). A config
655
674
  // file that fails JSON.parse — truncated during a mid-write crash, or
@@ -827,24 +846,67 @@ export function invalidateConfigCache(): void {
827
846
  * Load the raw config from disk without any secure-storage merging.
828
847
  * Used by CLI config commands to read/write the file directly.
829
848
  * API keys in secure storage are managed via `assistant keys` commands.
849
+ *
850
+ * Contract: returns a plain object (`Record<string, unknown>`). When
851
+ * `config.json` is missing → returns `{}`. When the file is unparseable
852
+ * (truncated, hand-edited to invalid JSON) OR when it parses to a value
853
+ * that is technically valid JSON but NOT a plain object (`null`, a
854
+ * primitive like `42`, `"hello"`, `true`, or an array `[…]`) → quarantines
855
+ * the file and returns `{}`. Callers can therefore rely on the return
856
+ * type without runtime shape-checking — the boundary check happens here.
830
857
  */
831
858
  export function loadRawConfig(): Record<string, unknown> {
832
859
  ensureMigratedDataDir();
833
860
  const configPath = getConfigPath();
834
- let raw: Record<string, unknown> = {};
835
- if (existsSync(configPath)) {
836
- try {
837
- raw = JSON.parse(readFileSync(configPath, "utf-8"));
838
- } catch (err) {
839
- // Mirror loadConfig(): quarantine the corrupt file and return an empty
840
- // object rather than throwing. This prevents /v1/config from surfacing
841
- // a 500 when the user's config.json is malformed.
842
- quarantineCorruptConfig(configPath, err);
843
- raw = {};
844
- }
861
+ if (!existsSync(configPath)) {
862
+ return {};
863
+ }
864
+
865
+ let parsed: unknown;
866
+ try {
867
+ parsed = JSON.parse(readFileSync(configPath, "utf-8"));
868
+ } catch (err) {
869
+ // Mirror loadConfig(): quarantine the corrupt file and return an empty
870
+ // object rather than throwing. This prevents /v1/config from surfacing
871
+ // a 500 when the user's config.json is malformed.
872
+ quarantineCorruptConfig(configPath, err);
873
+ return {};
845
874
  }
846
875
 
847
- return raw;
876
+ if (!isPlainObject(parsed)) {
877
+ // Valid JSON but the wrong shape — `null`, a primitive, or an array.
878
+ // Treat the same as a parse error so the return-type contract above is
879
+ // truthful and downstream callers (e.g. /v1/config handlers, twilio
880
+ // integration routes, settings routes) can iterate keys safely.
881
+ quarantineCorruptConfig(
882
+ configPath,
883
+ new Error(
884
+ `config.json must contain a JSON object at the top level; got ${describeJsonShape(parsed)}`,
885
+ ),
886
+ );
887
+ return {};
888
+ }
889
+
890
+ return parsed;
891
+ }
892
+
893
+ /**
894
+ * Predicate for "the value is a plain JSON object" — i.e. not `null`, not
895
+ * a primitive, and not an array. The cast on the truthy branch is safe
896
+ * because the caller's static type narrowed accordingly.
897
+ */
898
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
899
+ return value !== null && typeof value === "object" && !Array.isArray(value);
900
+ }
901
+
902
+ /**
903
+ * Human-readable shape label for error messages. Distinguishes the four
904
+ * non-object JSON shapes the loader rejects.
905
+ */
906
+ function describeJsonShape(value: unknown): string {
907
+ if (value === null) return "null";
908
+ if (Array.isArray(value)) return "an array";
909
+ return `a ${typeof value}`;
848
910
  }
849
911
 
850
912
  export function saveRawConfig(config: Record<string, unknown>): void {
@@ -1,39 +1,11 @@
1
- /**
2
- * Safely set a nested field on a raw config object's `llm.default` map.
3
- *
4
- * Ensures the `llm` and `llm.default` objects exist before writing, so
5
- * callers don't need to guard against undefined intermediate keys.
6
- *
7
- * Example: `setLlmDefaultField(raw, "model", "claude-sonnet-4-6")`
8
- * produces `raw.llm.default.model = "claude-sonnet-4-6"`.
9
- */
10
- export function setLlmDefaultField(
11
- raw: Record<string, unknown>,
12
- field: string,
13
- value: unknown,
14
- ): void {
15
- const llm: Record<string, unknown> =
16
- raw.llm != null && typeof raw.llm === "object" && !Array.isArray(raw.llm)
17
- ? (raw.llm as Record<string, unknown>)
18
- : {};
19
- const existing = llm.default;
20
- const defaultBlock: Record<string, unknown> =
21
- existing != null && typeof existing === "object" && !Array.isArray(existing)
22
- ? (existing as Record<string, unknown>)
23
- : {};
24
- defaultBlock[field] = value;
25
- llm.default = defaultBlock;
26
- raw.llm = llm;
27
- }
28
-
29
1
  /**
30
2
  * Safely set a nested field on a raw config object's `services` map.
31
3
  *
32
4
  * Ensures the `services` and service-level objects exist before writing,
33
5
  * so callers don't need to guard against undefined intermediate keys.
34
6
  *
35
- * Example: `setServiceField(raw, "inference", "mode", "managed")`
36
- * produces `raw.services.inference.mode = "managed"`.
7
+ * Example: `setServiceField(raw, "image-generation", "mode", "managed")`
8
+ * produces `raw.services["image-generation"].mode = "managed"`.
37
9
  */
38
10
  export function setServiceField(
39
11
  raw: Record<string, unknown>,
@@ -32,6 +32,7 @@ import { HostBrowserConfigSchema } from "./schemas/host-browser.js";
32
32
  import { IngressConfigSchema } from "./schemas/ingress.js";
33
33
  import { JournalConfigSchema } from "./schemas/journal.js";
34
34
  import { LLMSchema } from "./schemas/llm.js";
35
+ import { LlmRequestLogsConfigSchema } from "./schemas/llm-request-logs.js";
35
36
  import {
36
37
  AuditLogConfigSchema,
37
38
  LogFileConfigSchema,
@@ -81,6 +82,9 @@ export const AssistantConfigSchema = z
81
82
  // ensures the loader's leaf-deletion recovery path can repair a partially
82
83
  // invalid `llm` block without falling back to `cloneDefaultConfig()`.
83
84
  llm: LLMSchema.default(LLMSchema.parse({})),
85
+ llmRequestLogs: LlmRequestLogsConfigSchema.default(
86
+ LlmRequestLogsConfigSchema.parse({}),
87
+ ),
84
88
  filing: FilingConfigSchema.default(FilingConfigSchema.parse({})),
85
89
  heartbeat: HeartbeatConfigSchema.default(HeartbeatConfigSchema.parse({})),
86
90
  updates: UpdatesConfigSchema.default(UpdatesConfigSchema.parse({})),
@@ -32,6 +32,11 @@ describe("MemoryV2ConfigSchema", () => {
32
32
  model: "Alibaba-NLP/gte-reranker-modernbert-base",
33
33
  dtype: "q8",
34
34
  },
35
+ router: {
36
+ enabled: false,
37
+ max_page_ids: 25,
38
+ router_prompt_path: null,
39
+ },
35
40
  });
36
41
  });
37
42
 
@@ -155,6 +160,50 @@ describe("MemoryV2ConfigSchema", () => {
155
160
  expect(() => MemoryV2ConfigSchema.parse({ epsilon: -0.01 })).toThrow();
156
161
  expect(() => MemoryV2ConfigSchema.parse({ epsilon: 1.5 })).toThrow();
157
162
  });
163
+
164
+ test("router defaults to disabled with max_page_ids=25", () => {
165
+ const parsed = MemoryV2ConfigSchema.parse({});
166
+ expect(parsed.router.enabled).toBe(false);
167
+ expect(parsed.router.max_page_ids).toBe(25);
168
+ });
169
+
170
+ test("accepts explicit router overrides", () => {
171
+ const parsed = MemoryV2ConfigSchema.parse({
172
+ router: { enabled: true, max_page_ids: 50 },
173
+ });
174
+ expect(parsed.router.enabled).toBe(true);
175
+ expect(parsed.router.max_page_ids).toBe(50);
176
+ });
177
+
178
+ test("rejects router.max_page_ids below 1", () => {
179
+ expect(() =>
180
+ MemoryV2ConfigSchema.parse({ router: { max_page_ids: 0 } }),
181
+ ).toThrow();
182
+ });
183
+
184
+ test("rejects router.max_page_ids above 100", () => {
185
+ expect(() =>
186
+ MemoryV2ConfigSchema.parse({ router: { max_page_ids: 101 } }),
187
+ ).toThrow();
188
+ });
189
+
190
+ test("router_prompt_path defaults to null", () => {
191
+ const parsed = MemoryV2ConfigSchema.parse({});
192
+ expect(parsed.router.router_prompt_path).toBeNull();
193
+ });
194
+
195
+ test("accepts an explicit router_prompt_path override", () => {
196
+ const parsed = MemoryV2ConfigSchema.parse({
197
+ router: { router_prompt_path: "~/prompts/router.md" },
198
+ });
199
+ expect(parsed.router.router_prompt_path).toBe("~/prompts/router.md");
200
+ });
201
+
202
+ test("rejects non-string router_prompt_path", () => {
203
+ expect(() =>
204
+ MemoryV2ConfigSchema.parse({ router: { router_prompt_path: 42 } }),
205
+ ).toThrow();
206
+ });
158
207
  });
159
208
 
160
209
  describe("MemoryConfigSchema integration with v2 block", () => {
@@ -114,6 +114,27 @@ const CATALOG_RECORD: CatalogRecord = {
114
114
  description: "Background sweep pass for V2 memory maintenance.",
115
115
  domain: "memory",
116
116
  },
117
+ memoryRouter: {
118
+ id: "memoryRouter",
119
+ displayName: "Memory Router",
120
+ description:
121
+ "Selects which concept pages to inject for the next agent turn by routing over a cached page index.",
122
+ domain: "memory",
123
+ },
124
+ memoryV2Consolidation: {
125
+ id: "memoryV2Consolidation",
126
+ displayName: "Memory V2 Consolidation",
127
+ description:
128
+ "Routes accumulated buffer entries into concept pages and rewrites the recent summary during V2 memory maintenance.",
129
+ domain: "memory",
130
+ },
131
+ memoryRetrospective: {
132
+ id: "memoryRetrospective",
133
+ displayName: "Memory Retrospective",
134
+ description:
135
+ "Background agent that re-reads recent conversation messages and saves what wasn't captured in the moment by calling the `remember` tool.",
136
+ domain: "memory",
137
+ },
117
138
  recall: {
118
139
  id: "recall",
119
140
  displayName: "Recall",
@@ -152,7 +173,14 @@ const CATALOG_RECORD: CatalogRecord = {
152
173
  id: "conversationStarters",
153
174
  displayName: "Conversation Starters",
154
175
  description:
155
- "Generates suggested conversation openers for the home screen.",
176
+ "Generates the personalized starter chips on the empty conversation page.",
177
+ domain: "ui",
178
+ },
179
+ replySuggestion: {
180
+ id: "replySuggestion",
181
+ displayName: "Reply Suggestion",
182
+ description:
183
+ "Generates the tab-to-accept reply hint shown in the chat composer after each assistant turn.",
156
184
  domain: "ui",
157
185
  },
158
186
  conversationTitle: {
@@ -191,12 +219,6 @@ const CATALOG_RECORD: CatalogRecord = {
191
219
  description: "Handles conversational approval flows.",
192
220
  domain: "ui",
193
221
  },
194
- feedEventCopy: {
195
- id: "feedEventCopy",
196
- displayName: "Feed Event Copy",
197
- description: "Generates copy for home feed event cards.",
198
- domain: "ui",
199
- },
200
222
  trustRuleSuggestion: {
201
223
  id: "trustRuleSuggestion",
202
224
  displayName: "Trust Rule Suggestion",
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Configuration for LLM request log read source.
3
+ *
4
+ * Writes always land in the local SQLite `llm_request_logs` table; reads
5
+ * can be switched between local and ClickHouse via `readSource`.
6
+ *
7
+ * When `readSource === "clickhouse"` the URL and password are resolved
8
+ * from the credential store (`clickhouse:url`, `clickhouse:password`).
9
+ * The connection options below describe everything else (database/table/user).
10
+ *
11
+ * Note: the existing retention setting lives under
12
+ * `memory.cleanup.llmRequestLogRetentionMs` and is independent of this block.
13
+ * That covers when local rows get pruned; this block governs where reads
14
+ * are served from.
15
+ */
16
+ import { z } from "zod";
17
+
18
+ export const LlmRequestLogsClickHouseConfigSchema = z
19
+ .object({
20
+ database: z
21
+ .string({ error: "llmRequestLogs.clickhouse.database must be a string" })
22
+ .min(1, "llmRequestLogs.clickhouse.database cannot be empty")
23
+ .default("default")
24
+ .describe("ClickHouse database containing the llm_request_logs table"),
25
+ table: z
26
+ .string({ error: "llmRequestLogs.clickhouse.table must be a string" })
27
+ .min(1, "llmRequestLogs.clickhouse.table cannot be empty")
28
+ .default("llm_request_logs")
29
+ .describe("ClickHouse table name to read from"),
30
+ user: z
31
+ .string({ error: "llmRequestLogs.clickhouse.user must be a string" })
32
+ .min(1, "llmRequestLogs.clickhouse.user cannot be empty")
33
+ .default("default")
34
+ .describe("ClickHouse user (password is read from credential store)"),
35
+ })
36
+ .describe(
37
+ "ClickHouse connection settings used when `readSource` is `clickhouse`",
38
+ );
39
+
40
+ export const LlmRequestLogsConfigSchema = z
41
+ .object({
42
+ readSource: z
43
+ .enum(["local", "clickhouse"])
44
+ .default("local")
45
+ .describe(
46
+ "Where to read LLM request logs from for Inspector queries. `local` reads the SQLite source-of-truth (default, lowest latency). `clickhouse` reads the mirror, which retains data longer than local but only sees writes that the mirror job has flushed.",
47
+ ),
48
+ clickhouse: LlmRequestLogsClickHouseConfigSchema.default(
49
+ LlmRequestLogsClickHouseConfigSchema.parse({}),
50
+ ),
51
+ })
52
+ .describe("LLM request log read source configuration");
53
+
54
+ export type LlmRequestLogsConfig = z.infer<typeof LlmRequestLogsConfigSchema>;
55
+ export type LlmRequestLogsClickHouseConfig = z.infer<
56
+ typeof LlmRequestLogsClickHouseConfigSchema
57
+ >;
@@ -47,11 +47,15 @@ export const LLMCallSiteEnum = z.enum([
47
47
  "memoryRetrieval",
48
48
  "memoryV2Migration",
49
49
  "memoryV2Sweep",
50
+ "memoryRouter",
51
+ "memoryV2Consolidation",
52
+ "memoryRetrospective",
50
53
  "recall",
51
54
  "narrativeRefinement",
52
55
  "patternScan",
53
56
  "conversationSummarization",
54
57
  "conversationStarters",
58
+ "replySuggestion",
55
59
  "conversationTitle",
56
60
  "commitMessage",
57
61
  "identityIntro",
@@ -68,7 +72,6 @@ export const LLMCallSiteEnum = z.enum([
68
72
  "meetConsentMonitor",
69
73
  "meetChatOpportunity",
70
74
  "inference",
71
- "feedEventCopy",
72
75
  "trustRuleSuggestion",
73
76
  "proactiveArtifactDecision",
74
77
  "proactiveArtifactBuild",
@@ -281,6 +284,16 @@ const PricingOverrideSchema = z.object({
281
284
  */
282
285
  export const LLMConfigBase = z.object({
283
286
  provider: LLMProvider.default("anthropic"),
287
+ /**
288
+ * Name of a `provider_connections` row to use for this resolved config.
289
+ * Optional and additive: when set, the dispatcher resolves auth from the
290
+ * connection (mix-and-match managed/your-own per profile). When unset,
291
+ * the dispatcher falls back to the legacy `provider` lookup.
292
+ *
293
+ * Lives on the merged base type so it flows through `resolveCallSiteConfig`
294
+ * naturally — the underlying profile-level field is on `ProfileEntry`.
295
+ */
296
+ provider_connection: z.string().min(1).optional(),
284
297
  model: ModelSchema.default("claude-opus-4-7"),
285
298
  maxTokens: MaxTokensSchema.default(64000),
286
299
  effort: EffortEnum.default("max"),
@@ -313,6 +326,9 @@ const LLMConfigFragment = z.object({
313
326
  });
314
327
  type LLMConfigFragment = z.infer<typeof LLMConfigFragment>;
315
328
 
329
+ export const ProfileStatusSchema = z.enum(["active", "disabled"]);
330
+ export type ProfileStatus = z.infer<typeof ProfileStatusSchema>;
331
+
316
332
  /**
317
333
  * A named profile entry: an `LLMConfigFragment` augmented with
318
334
  * presentation/ownership metadata. These fields are intentionally kept off
@@ -321,8 +337,33 @@ type LLMConfigFragment = z.infer<typeof LLMConfigFragment>;
321
337
  */
322
338
  export const ProfileEntry = LLMConfigFragment.extend({
323
339
  source: ProfileSource.optional(),
324
- label: z.string().min(1).optional(),
340
+ /**
341
+ * `.nullable()` is intentional: the PUT `/v1/config/llm/profiles/:name`
342
+ * route uses `null` as the "clear this override" sentinel for managed
343
+ * profiles (see `patchManagedProfileFields` in
344
+ * `runtime/routes/conversation-query-routes.ts`). Without `.nullable()`,
345
+ * Zod rejects `{ label: null }` at parse time before the route handler
346
+ * ever sees it, and the clear-back-to-seed path is unreachable from any
347
+ * client. `.min(1)` still applies to string values so empty strings
348
+ * remain rejected — `null` is the only non-string-non-undefined input
349
+ * accepted.
350
+ */
351
+ label: z.string().min(1).nullable().optional(),
325
352
  description: z.string().optional(),
353
+ /**
354
+ * Name of a `provider_connections` row to use for this profile.
355
+ * The dispatcher resolves auth from this connection; the legacy `provider`
356
+ * and `source` fields remain as read-only deprecated fallbacks for profiles
357
+ * not yet backfilled by the boot-time migration.
358
+ */
359
+ provider_connection: z.string().min(1).optional(),
360
+ /**
361
+ * Absent means active. `.nullable()` matches `label` so the PUT route's
362
+ * "send `null` to clear" sentinel works for status edits too — see
363
+ * `patchManagedProfileFields`, which has handled `status === null` since
364
+ * #30362 even though the schema didn't accept it until now.
365
+ */
366
+ status: ProfileStatusSchema.nullable().optional(),
326
367
  });
327
368
  export type ProfileEntry = z.infer<typeof ProfileEntry>;
328
369
 
@@ -355,6 +396,15 @@ export const LLMSchema = z
355
396
  // schema level, so `LLMSchema.parse({})` yields an empty map.
356
397
  callSites: z.partialRecord(LLMCallSiteEnum, LLMCallSiteConfig).default({}),
357
398
  activeProfile: z.string().min(1).optional(),
399
+ // TTL bounds for inference profile sessions. `defaultTtlSeconds` is read by
400
+ // the CLI to apply when `--ttl` is omitted; the daemon handler itself only
401
+ // reads `maxTtlSeconds` (to clamp caller-supplied values).
402
+ profileSession: z
403
+ .object({
404
+ defaultTtlSeconds: z.number().int().min(1).default(1800),
405
+ maxTtlSeconds: z.number().int().min(1).default(43200),
406
+ })
407
+ .default({ defaultTtlSeconds: 1800, maxTtlSeconds: 43200 }),
358
408
  pricingOverrides: z.array(PricingOverrideSchema).default([]),
359
409
  })
360
410
  .superRefine((config, ctx) => {