@vellumai/assistant 0.7.3 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (778) hide show
  1. package/AGENTS.md +11 -0
  2. package/ARCHITECTURE.md +29 -28
  3. package/Dockerfile +6 -4
  4. package/README.md +2 -2
  5. package/__tests__/permissions/gateway-threshold-reader.test.ts +236 -9
  6. package/bun.lock +3 -0
  7. package/docker-entrypoint.sh +16 -0
  8. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  9. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  10. package/eslint.config.mjs +12 -0
  11. package/knip.json +3 -1
  12. package/node_modules/@vellumai/ipc-server-utils/bun.lock +24 -0
  13. package/node_modules/@vellumai/ipc-server-utils/package.json +18 -0
  14. package/node_modules/@vellumai/ipc-server-utils/src/index.ts +6 -0
  15. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +430 -0
  16. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +221 -0
  17. package/node_modules/@vellumai/ipc-server-utils/tsconfig.json +20 -0
  18. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  19. package/openapi.yaml +4126 -959
  20. package/package.json +5 -1
  21. package/scripts/generate-openapi.ts +52 -4
  22. package/scripts/sync-llm-catalog.ts +165 -0
  23. package/scripts/sync-web-search-catalog.ts +107 -0
  24. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  25. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  26. package/src/__tests__/annotate-risk-options.test.ts +291 -0
  27. package/src/__tests__/anthropic-provider.test.ts +92 -2
  28. package/src/__tests__/app-control-flow.test.ts +7 -0
  29. package/src/__tests__/approval-cascade.test.ts +8 -16
  30. package/src/__tests__/approval-routes-http.test.ts +6 -0
  31. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  32. package/src/__tests__/auto-analysis-end-to-end.test.ts +12 -25
  33. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  34. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  35. package/src/__tests__/btw-routes.test.ts +1 -0
  36. package/src/__tests__/call-constants.test.ts +10 -1
  37. package/src/__tests__/call-controller.test.ts +127 -0
  38. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  39. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  40. package/src/__tests__/channel-policy.test.ts +12 -0
  41. package/src/__tests__/checker.test.ts +89 -0
  42. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +88 -30
  43. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  44. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  45. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  46. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  47. package/src/__tests__/config-loader-platform-defaults.test.ts +345 -8
  48. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  49. package/src/__tests__/config-schema.test.ts +14 -3
  50. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  51. package/src/__tests__/config-set-route.test.ts +198 -0
  52. package/src/__tests__/config-watcher.test.ts +6 -0
  53. package/src/__tests__/contacts-tools.test.ts +51 -199
  54. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  55. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  56. package/src/__tests__/context-search-conversations-source.test.ts +42 -16
  57. package/src/__tests__/context-search-fanout.test.ts +20 -157
  58. package/src/__tests__/context-search-memory-source.test.ts +3 -26
  59. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
  60. package/src/__tests__/context-search-types.test.ts +7 -2
  61. package/src/__tests__/context-window-manager.test.ts +389 -1
  62. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -6
  63. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
  64. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
  65. package/src/__tests__/conversation-agent-loop.test.ts +3 -3
  66. package/src/__tests__/conversation-confirmation-signals.test.ts +5 -13
  67. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  68. package/src/__tests__/conversation-error.test.ts +38 -0
  69. package/src/__tests__/conversation-fork-crud.test.ts +241 -1
  70. package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
  71. package/src/__tests__/conversation-init.benchmark.test.ts +2 -1
  72. package/src/__tests__/conversation-lifecycle.test.ts +124 -0
  73. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  74. package/src/__tests__/conversation-process-callsite.test.ts +22 -7
  75. package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -6
  76. package/src/__tests__/conversation-runtime-assembly.test.ts +19 -10
  77. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  78. package/src/__tests__/conversation-slash-unknown.test.ts +1 -6
  79. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +170 -9
  80. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  81. package/src/__tests__/conversation-surfaces-data-persist.test.ts +73 -1
  82. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +59 -0
  83. package/src/__tests__/conversation-workspace-injection.test.ts +1 -7
  84. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -7
  85. package/src/__tests__/credential-security-invariants.test.ts +5 -6
  86. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  87. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  88. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  89. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  90. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  91. package/src/__tests__/external-plugin-loader.test.ts +458 -0
  92. package/src/__tests__/filing-service.test.ts +25 -22
  93. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  94. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  95. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  96. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +10 -34
  97. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  98. package/src/__tests__/heartbeat-service.test.ts +50 -233
  99. package/src/__tests__/history-repair.test.ts +89 -0
  100. package/src/__tests__/host-app-control-proxy.test.ts +109 -1
  101. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  102. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  103. package/src/__tests__/host-browser-routes.test.ts +325 -33
  104. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  105. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  106. package/src/__tests__/inference-profile-reaper.test.ts +154 -0
  107. package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
  108. package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
  109. package/src/__tests__/injector-chain.test.ts +24 -16
  110. package/src/__tests__/injector-pkb-v2-silenced.test.ts +10 -7
  111. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  112. package/src/__tests__/install-skill-routing.test.ts +2 -2
  113. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +169 -67
  114. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  115. package/src/__tests__/llm-catalog-parity.test.ts +146 -0
  116. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
  117. package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
  118. package/src/__tests__/llm-resolver.test.ts +46 -0
  119. package/src/__tests__/managed-profile-guard.test.ts +131 -2
  120. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  121. package/src/__tests__/mcp-cli.test.ts +182 -220
  122. package/src/__tests__/mcp-health-check.test.ts +56 -27
  123. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  124. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  125. package/src/__tests__/notification-decision-fallback.test.ts +91 -0
  126. package/src/__tests__/notification-decision-strategy.test.ts +22 -0
  127. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  128. package/src/__tests__/oauth-cli.test.ts +38 -1888
  129. package/src/__tests__/oauth-commands-routes.test.ts +711 -0
  130. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  131. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  132. package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
  133. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  134. package/src/__tests__/plugin-bootstrap.test.ts +31 -2
  135. package/src/__tests__/plugin-route-contribution.test.ts +31 -3
  136. package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
  137. package/src/__tests__/plugin-types.test.ts +13 -11
  138. package/src/__tests__/process-message-background-slack.test.ts +46 -0
  139. package/src/__tests__/profile-entry-status.test.ts +43 -0
  140. package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
  141. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  142. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  143. package/src/__tests__/relay-server.test.ts +164 -2
  144. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  145. package/src/__tests__/schedule-retry.test.ts +56 -4
  146. package/src/__tests__/schedule-routes.test.ts +104 -0
  147. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  148. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  149. package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
  150. package/src/__tests__/scheduler-wake.test.ts +0 -63
  151. package/src/__tests__/secret-allowlist.test.ts +1 -0
  152. package/src/__tests__/secret-prompt-log-hygiene.test.ts +7 -5
  153. package/src/__tests__/secret-prompter-channel-fallback.test.ts +7 -5
  154. package/src/__tests__/secret-response-routing.test.ts +7 -5
  155. package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
  156. package/src/__tests__/server-history-render.test.ts +82 -0
  157. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  158. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  159. package/src/__tests__/skill-include-graph.test.ts +31 -0
  160. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  161. package/src/__tests__/skill-load-tool.test.ts +42 -16
  162. package/src/__tests__/skills.test.ts +39 -0
  163. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  164. package/src/__tests__/suggestion-routes.test.ts +3 -3
  165. package/src/__tests__/sync-message-contract.test.ts +63 -0
  166. package/src/__tests__/task-scheduler.test.ts +88 -23
  167. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -42
  168. package/src/__tests__/tool-executor.test.ts +155 -0
  169. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  170. package/src/__tests__/usage-cli.test.ts +11 -73
  171. package/src/__tests__/user-plugin-loader.test.ts +145 -0
  172. package/src/__tests__/vercel-config.test.ts +168 -0
  173. package/src/__tests__/voice-session-bridge.test.ts +3 -0
  174. package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
  175. package/src/__tests__/web-search.test.ts +303 -2
  176. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  177. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
  178. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +153 -0
  179. package/src/__tests__/workspace-migration-071-remove-safe-storage-release-note.test.ts +206 -0
  180. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
  181. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  182. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  183. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  184. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  185. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  186. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  187. package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +15 -27
  188. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  189. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  190. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  191. package/src/acp/resolve-agent.test.ts +25 -0
  192. package/src/acp/resolve-agent.ts +13 -2
  193. package/src/acp/session-manager.ts +14 -0
  194. package/src/agent/loop.ts +11 -0
  195. package/src/approvals/guardian-decision-primitive.ts +0 -13
  196. package/src/approvals/guardian-request-resolvers.ts +19 -102
  197. package/src/calls/call-constants.ts +5 -8
  198. package/src/calls/call-controller.ts +130 -67
  199. package/src/calls/relay-server.ts +42 -1
  200. package/src/calls/relay-setup-router.ts +36 -0
  201. package/src/calls/types.ts +1 -0
  202. package/src/calls/voice-session-bridge.ts +24 -5
  203. package/src/channels/config.ts +14 -1
  204. package/src/channels/types.ts +1 -0
  205. package/src/cli/AGENTS.md +164 -4
  206. package/src/cli/__tests__/notifications.test.ts +54 -0
  207. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  208. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  209. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  210. package/src/cli/commands/__tests__/changelog.test.ts +593 -0
  211. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  212. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  213. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  214. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  215. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  216. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  217. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  218. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  219. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  220. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  221. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  222. package/src/cli/commands/__tests__/status.test.ts +249 -0
  223. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  224. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  225. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  226. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  227. package/src/cli/commands/attachment.ts +8 -3
  228. package/src/cli/commands/audit.ts +95 -64
  229. package/src/cli/commands/auth.ts +61 -58
  230. package/src/cli/commands/avatar.ts +276 -390
  231. package/src/cli/commands/backup.ts +409 -505
  232. package/src/cli/commands/bash.ts +9 -5
  233. package/src/cli/commands/browser.ts +28 -9
  234. package/src/cli/commands/cache.ts +9 -4
  235. package/src/cli/commands/changelog.ts +414 -0
  236. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  237. package/src/cli/commands/clients.ts +8 -3
  238. package/src/cli/commands/completions.ts +9 -9
  239. package/src/cli/commands/config.ts +102 -72
  240. package/src/cli/commands/contacts.ts +575 -696
  241. package/src/cli/commands/conversations-defer.ts +17 -69
  242. package/src/cli/commands/conversations-import.ts +90 -253
  243. package/src/cli/commands/conversations.ts +346 -436
  244. package/src/cli/commands/credential-execution.ts +9 -6
  245. package/src/cli/commands/credentials.ts +456 -736
  246. package/src/cli/commands/domain.ts +128 -206
  247. package/src/cli/commands/email.ts +606 -794
  248. package/src/cli/commands/gateway.ts +8 -1
  249. package/src/cli/commands/image-generation.ts +157 -205
  250. package/src/cli/commands/inference-providers.ts +352 -0
  251. package/src/cli/commands/inference-session.ts +415 -0
  252. package/src/cli/commands/inference.ts +87 -65
  253. package/src/cli/commands/keys.ts +8 -3
  254. package/src/cli/commands/mcp.ts +103 -287
  255. package/src/cli/commands/memory-v2.ts +163 -517
  256. package/src/cli/commands/notifications.ts +33 -7
  257. package/src/cli/commands/oauth/apps.ts +292 -261
  258. package/src/cli/commands/oauth/connect.ts +182 -345
  259. package/src/cli/commands/oauth/disconnect.ts +16 -215
  260. package/src/cli/commands/oauth/index.ts +49 -45
  261. package/src/cli/commands/oauth/mode.ts +43 -199
  262. package/src/cli/commands/oauth/ping.ts +17 -125
  263. package/src/cli/commands/oauth/providers.ts +732 -921
  264. package/src/cli/commands/oauth/request.ts +60 -350
  265. package/src/cli/commands/oauth/shared.ts +11 -121
  266. package/src/cli/commands/oauth/status.ts +31 -121
  267. package/src/cli/commands/oauth/token.ts +13 -55
  268. package/src/cli/commands/pending.ts +19 -10
  269. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  270. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  271. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  272. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  273. package/src/cli/commands/platform/connect.ts +16 -80
  274. package/src/cli/commands/platform/disconnect.ts +14 -112
  275. package/src/cli/commands/platform/index.ts +177 -246
  276. package/src/cli/commands/routes.ts +153 -336
  277. package/src/cli/commands/sequence.ts +316 -360
  278. package/src/cli/commands/skills.ts +449 -671
  279. package/src/cli/commands/status.ts +58 -37
  280. package/src/cli/commands/stt.ts +94 -262
  281. package/src/cli/commands/task.ts +14 -40
  282. package/src/cli/commands/trust.ts +8 -3
  283. package/src/cli/commands/tts.ts +162 -167
  284. package/src/cli/commands/ui.ts +35 -42
  285. package/src/cli/commands/usage.ts +188 -126
  286. package/src/cli/commands/watchers.ts +8 -3
  287. package/src/cli/commands/webhooks.ts +99 -193
  288. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  289. package/src/cli/lib/daemon-credential-client.ts +4 -5
  290. package/src/cli/lib/nested-value.ts +44 -0
  291. package/src/cli/lib/open-browser.ts +36 -0
  292. package/src/cli/lib/register-command.ts +19 -0
  293. package/src/cli/lib/time-ago.ts +34 -0
  294. package/src/cli/program.ts +2 -4
  295. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  296. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  297. package/src/cli/utils/conversation-id.ts +30 -0
  298. package/src/cli/utils/parse-duration.ts +41 -0
  299. package/src/config/acp-defaults.test.ts +5 -1
  300. package/src/config/acp-defaults.ts +11 -4
  301. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  302. package/src/config/bundled-skills/app-builder/SKILL.md +1 -3
  303. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  304. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  305. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  306. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  307. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  308. package/src/config/bundled-tool-registry.ts +0 -2
  309. package/src/config/feature-flag-registry.json +17 -17
  310. package/src/config/llm-resolver.ts +16 -1
  311. package/src/config/loader.ts +148 -33
  312. package/src/config/raw-config-utils.ts +2 -30
  313. package/src/config/schema.ts +4 -0
  314. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  315. package/src/config/schemas/call-site-catalog.ts +29 -7
  316. package/src/config/schemas/llm-request-logs.ts +57 -0
  317. package/src/config/schemas/llm.ts +52 -2
  318. package/src/config/schemas/memory-retrospective.ts +48 -0
  319. package/src/config/schemas/memory-v2.ts +33 -2
  320. package/src/config/schemas/memory.ts +4 -0
  321. package/src/config/schemas/services.ts +15 -12
  322. package/src/config/seed-inference-profiles.ts +195 -134
  323. package/src/contacts/contact-store.ts +0 -61
  324. package/src/context/window-manager.ts +191 -5
  325. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +111 -0
  326. package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
  327. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  328. package/src/daemon/approval-generators.ts +23 -29
  329. package/src/daemon/config-watcher.ts +2 -0
  330. package/src/daemon/conversation-agent-loop-handlers.ts +56 -0
  331. package/src/daemon/conversation-agent-loop.ts +140 -107
  332. package/src/daemon/conversation-error.ts +21 -0
  333. package/src/daemon/conversation-lifecycle.ts +68 -13
  334. package/src/daemon/conversation-process.ts +36 -19
  335. package/src/daemon/conversation-runtime-assembly.ts +14 -5
  336. package/src/daemon/conversation-slash.ts +175 -23
  337. package/src/daemon/conversation-store.ts +17 -10
  338. package/src/daemon/conversation-surfaces.ts +92 -26
  339. package/src/daemon/conversation-tool-setup.ts +33 -19
  340. package/src/daemon/conversation.ts +49 -10
  341. package/src/daemon/external-plugins-bootstrap.ts +18 -8
  342. package/src/daemon/guardian-action-generators.ts +7 -22
  343. package/src/daemon/handlers/config-model.ts +8 -126
  344. package/src/daemon/handlers/config-slack-channel.ts +10 -7
  345. package/src/daemon/handlers/config-vercel.ts +3 -1
  346. package/src/daemon/handlers/shared.ts +26 -0
  347. package/src/daemon/handlers/skills.ts +84 -5
  348. package/src/daemon/history-repair.ts +33 -6
  349. package/src/daemon/host-app-control-proxy.ts +44 -19
  350. package/src/daemon/host-bash-proxy.ts +85 -158
  351. package/src/daemon/host-browser-proxy.ts +97 -36
  352. package/src/daemon/host-cu-proxy.ts +1 -1
  353. package/src/daemon/host-file-proxy.ts +1 -1
  354. package/src/daemon/host-proxy-base.ts +13 -1
  355. package/src/daemon/host-proxy-preactivation.ts +25 -1
  356. package/src/daemon/host-transfer-proxy.ts +2 -2
  357. package/src/daemon/identity-helpers.ts +19 -0
  358. package/src/daemon/lifecycle.ts +128 -114
  359. package/src/daemon/meet-host-supervisor.ts +15 -15
  360. package/src/daemon/memory-v2-startup.ts +62 -14
  361. package/src/daemon/message-protocol.ts +6 -0
  362. package/src/daemon/message-types/bookmarks.ts +18 -0
  363. package/src/daemon/message-types/conversations.ts +12 -9
  364. package/src/daemon/message-types/messages.ts +28 -2
  365. package/src/daemon/message-types/sync.ts +60 -0
  366. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  367. package/src/daemon/pkb-reminder-builder.ts +21 -7
  368. package/src/daemon/process-message.ts +56 -23
  369. package/src/daemon/server.ts +23 -18
  370. package/src/daemon/shutdown-handlers.ts +0 -2
  371. package/src/daemon/tool-setup-types.ts +9 -0
  372. package/src/daemon/tool-side-effects.ts +6 -4
  373. package/src/daemon/wake-target-adapter.ts +11 -0
  374. package/src/documents/document-store.ts +35 -1
  375. package/src/export/transcript-formatter.ts +61 -2
  376. package/src/filing/filing-service.ts +42 -56
  377. package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
  378. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  379. package/src/heartbeat/heartbeat-service.ts +149 -128
  380. package/src/home/__tests__/feed-types.test.ts +63 -131
  381. package/src/home/__tests__/feed-writer.test.ts +77 -278
  382. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  383. package/src/home/feed-types.ts +19 -73
  384. package/src/home/feed-writer.ts +25 -156
  385. package/src/home/post-connect-feed.ts +1 -3
  386. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  387. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  388. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  389. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  390. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  391. package/src/ipc/assistant-server.ts +148 -42
  392. package/src/ipc/cli-client.ts +370 -50
  393. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  394. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  395. package/src/ipc/skill-routes/events.ts +30 -3
  396. package/src/ipc/skill-server.ts +99 -42
  397. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  398. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  399. package/src/live-voice/live-voice-session-manager.ts +11 -4
  400. package/src/live-voice/live-voice-session.ts +14 -6
  401. package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
  402. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  403. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  404. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  405. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +10 -57
  406. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  407. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  408. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
  409. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  410. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  411. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  412. package/src/memory/bookmark-crud.ts +179 -0
  413. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  414. package/src/memory/context-search/agent-protocol.ts +5 -1
  415. package/src/memory/context-search/agent-runner.ts +60 -85
  416. package/src/memory/context-search/limits.ts +1 -4
  417. package/src/memory/context-search/search.ts +23 -113
  418. package/src/memory/context-search/sources/conversations.ts +18 -6
  419. package/src/memory/context-search/sources/memory-v2.ts +40 -31
  420. package/src/memory/context-search/sources/memory.ts +9 -2
  421. package/src/memory/context-search/sources/workspace.ts +13 -10
  422. package/src/memory/context-search/types.ts +1 -1
  423. package/src/memory/conversation-bootstrap.ts +11 -0
  424. package/src/memory/conversation-crud.ts +312 -10
  425. package/src/memory/conversation-queries.ts +9 -5
  426. package/src/memory/conversation-title-service.ts +1 -0
  427. package/src/memory/conversation-types.ts +16 -0
  428. package/src/memory/db-init.ts +14 -0
  429. package/src/memory/embedding-backend.ts +2 -1
  430. package/src/memory/embedding-runtime-manager.ts +1 -2
  431. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +104 -61
  432. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +11 -26
  433. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  434. package/src/memory/graph/conversation-graph-memory.ts +108 -14
  435. package/src/memory/graph/extraction.ts +4 -0
  436. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  437. package/src/memory/graph/graph-search.test.ts +6 -5
  438. package/src/memory/graph/graph-search.ts +3 -4
  439. package/src/memory/graph/retriever.test.ts +12 -7
  440. package/src/memory/graph/retriever.ts +4 -5
  441. package/src/memory/graph/tool-handlers.ts +20 -11
  442. package/src/memory/graph/tools.ts +48 -9
  443. package/src/memory/indexer.ts +18 -2
  444. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +120 -6
  445. package/src/memory/jobs/embed-concept-page.ts +261 -89
  446. package/src/memory/jobs-store.ts +51 -1
  447. package/src/memory/jobs-worker.ts +60 -7
  448. package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
  449. package/src/memory/llm-request-log-source-local.ts +26 -0
  450. package/src/memory/llm-request-log-source.ts +97 -0
  451. package/src/memory/llm-request-log-store.ts +1 -1
  452. package/src/memory/memory-retrospective-constants.ts +13 -0
  453. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  454. package/src/memory/memory-retrospective-job.ts +351 -0
  455. package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
  456. package/src/memory/memory-retrospective-state.ts +162 -0
  457. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  458. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  459. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  460. package/src/memory/message-content.ts +38 -1
  461. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  462. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  463. package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
  464. package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
  465. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  466. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  467. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  468. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  469. package/src/memory/migrations/243-provider-connections.ts +68 -0
  470. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  471. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  472. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  473. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  474. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  475. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  476. package/src/memory/migrations/index.ts +7 -0
  477. package/src/memory/pkb/pkb-search.test.ts +6 -5
  478. package/src/memory/pkb/pkb-search.ts +4 -5
  479. package/src/memory/published-pages-store.ts +16 -0
  480. package/src/memory/qdrant-client.ts +3 -0
  481. package/src/memory/schema/bookmarks.ts +38 -0
  482. package/src/memory/schema/conversations.ts +2 -0
  483. package/src/memory/schema/index.ts +2 -0
  484. package/src/memory/schema/inference.ts +29 -0
  485. package/src/memory/schema/memory-core.ts +9 -0
  486. package/src/memory/search/semantic.ts +5 -9
  487. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  488. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  489. package/src/memory/v2/__tests__/activation.test.ts +46 -9
  490. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  491. package/src/memory/v2/__tests__/consolidation-job.test.ts +140 -163
  492. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  493. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  494. package/src/memory/v2/__tests__/injection.test.ts +768 -33
  495. package/src/memory/v2/__tests__/migration.test.ts +7 -3
  496. package/src/memory/v2/__tests__/page-index.test.ts +277 -0
  497. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  498. package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
  499. package/src/memory/v2/__tests__/qdrant.test.ts +382 -9
  500. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  501. package/src/memory/v2/__tests__/router.test.ts +516 -0
  502. package/src/memory/v2/__tests__/sim.test.ts +163 -8
  503. package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
  504. package/src/memory/v2/__tests__/static-context.test.ts +8 -35
  505. package/src/memory/v2/__tests__/sweep-job.test.ts +114 -33
  506. package/src/memory/v2/activation-store.ts +34 -5
  507. package/src/memory/v2/activation.ts +40 -27
  508. package/src/memory/v2/backfill-jobs.ts +17 -84
  509. package/src/memory/v2/consolidation-job.ts +92 -86
  510. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  511. package/src/memory/v2/injection.ts +466 -115
  512. package/src/memory/v2/migration.ts +117 -20
  513. package/src/memory/v2/page-index.ts +191 -0
  514. package/src/memory/v2/page-store.ts +42 -0
  515. package/src/memory/v2/prompts/consolidation.ts +14 -7
  516. package/src/memory/v2/prompts/router.ts +192 -0
  517. package/src/memory/v2/qdrant.ts +307 -133
  518. package/src/memory/v2/reranker.ts +14 -7
  519. package/src/memory/v2/router.ts +322 -0
  520. package/src/memory/v2/sim.ts +88 -34
  521. package/src/memory/v2/skill-store.ts +118 -29
  522. package/src/memory/v2/static-context.ts +20 -17
  523. package/src/memory/v2/sweep-job.ts +127 -102
  524. package/src/memory/v2/types.ts +16 -5
  525. package/src/memory/validation.ts +13 -0
  526. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  527. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  528. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  529. package/src/notifications/adapters/platform.ts +171 -0
  530. package/src/notifications/conversation-pairing.ts +2 -2
  531. package/src/notifications/copy-composer.ts +61 -12
  532. package/src/notifications/decision-engine.ts +46 -0
  533. package/src/notifications/destination-resolver.ts +21 -0
  534. package/src/notifications/emit-signal.ts +28 -1
  535. package/src/notifications/home-feed-side-effect.ts +111 -0
  536. package/src/notifications/signal.ts +5 -0
  537. package/src/permissions/checker.ts +12 -0
  538. package/src/permissions/gateway-threshold-reader.ts +116 -8
  539. package/src/permissions/ipc-risk-types.ts +2 -0
  540. package/src/permissions/prompter.ts +86 -96
  541. package/src/permissions/secret-prompter.ts +31 -31
  542. package/src/plugin-api/index.ts +13 -0
  543. package/src/plugin-api/package.json +12 -0
  544. package/src/plugin-api/types.ts +62 -0
  545. package/src/plugins/defaults/injectors.ts +20 -5
  546. package/src/plugins/external-plugin-loader.ts +294 -0
  547. package/src/plugins/types.ts +46 -30
  548. package/src/plugins/user-loader.ts +64 -41
  549. package/src/proactive-artifact/job.test.ts +63 -8
  550. package/src/proactive-artifact/job.ts +20 -2
  551. package/src/proactive-artifact/message-copy.ts +18 -1
  552. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  553. package/src/proactive-artifact/trigger-state.ts +4 -0
  554. package/src/prompts/__tests__/system-prompt.test.ts +105 -0
  555. package/src/prompts/system-prompt.ts +22 -1
  556. package/src/prompts/templates/SOUL.md +13 -28
  557. package/src/prompts/update-bulletin-job.ts +61 -73
  558. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  559. package/src/providers/__tests__/inference.test.ts +288 -0
  560. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  561. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  562. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  563. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  564. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  565. package/src/providers/anthropic/client.ts +95 -26
  566. package/src/providers/call-site-routing.ts +94 -16
  567. package/src/providers/connection-resolution.ts +163 -0
  568. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  569. package/src/providers/inference/adapter-factory.ts +173 -0
  570. package/src/providers/inference/auth.ts +112 -0
  571. package/src/providers/inference/backfill.ts +196 -0
  572. package/src/providers/inference/connections.ts +356 -0
  573. package/src/providers/inference/resolve-auth.ts +65 -0
  574. package/src/providers/model-catalog.ts +104 -6
  575. package/src/providers/openai/responses-provider.ts +4 -2
  576. package/src/providers/provider-env-vars.ts +17 -7
  577. package/src/providers/provider-secret-catalog.ts +49 -30
  578. package/src/providers/provider-send-message.ts +41 -20
  579. package/src/providers/registry.ts +143 -159
  580. package/src/providers/retry.ts +18 -10
  581. package/src/providers/search-provider-catalog.ts +121 -0
  582. package/src/runtime/AGENTS.md +18 -5
  583. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  584. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  585. package/src/runtime/actor-trust-resolver.ts +32 -10
  586. package/src/runtime/agent-wake.ts +35 -6
  587. package/src/runtime/assistant-event-hub.ts +3 -85
  588. package/src/runtime/auth/route-policy.ts +304 -8
  589. package/src/runtime/auth/same-actor.ts +2 -0
  590. package/src/runtime/background-job-runner.ts +339 -0
  591. package/src/runtime/btw-sidechain.ts +1 -0
  592. package/src/runtime/channel-approvals.ts +3 -2
  593. package/src/runtime/guardian-reply-router.ts +0 -10
  594. package/src/runtime/http-router.ts +36 -1
  595. package/src/runtime/http-server.ts +31 -5
  596. package/src/runtime/http-types.ts +2 -0
  597. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  598. package/src/runtime/middleware/request-logger.ts +62 -1
  599. package/src/runtime/pending-interactions.ts +19 -15
  600. package/src/runtime/pre-first-message-gate.ts +83 -0
  601. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  602. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
  603. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  604. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
  605. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
  606. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  607. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  608. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +147 -0
  609. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  610. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  611. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  612. package/src/runtime/routes/acp-routes.ts +10 -8
  613. package/src/runtime/routes/app-management-routes.ts +228 -3
  614. package/src/runtime/routes/approval-routes.ts +7 -21
  615. package/src/runtime/routes/audit-routes.ts +43 -0
  616. package/src/runtime/routes/auth-routes.ts +72 -0
  617. package/src/runtime/routes/avatar-routes.ts +273 -20
  618. package/src/runtime/routes/backup-routes.ts +406 -2
  619. package/src/runtime/routes/bookmark-routes.ts +154 -0
  620. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  621. package/src/runtime/routes/consolidation-routes.ts +8 -9
  622. package/src/runtime/routes/contact-routes.ts +0 -160
  623. package/src/runtime/routes/conversation-cli-routes.ts +192 -0
  624. package/src/runtime/routes/conversation-management-routes.ts +30 -43
  625. package/src/runtime/routes/conversation-query-routes.ts +373 -82
  626. package/src/runtime/routes/conversation-routes.ts +31 -10
  627. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  628. package/src/runtime/routes/credential-routes.ts +540 -0
  629. package/src/runtime/routes/debug-bash-routes.ts +2 -0
  630. package/src/runtime/routes/debug-routes.ts +2 -2
  631. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  632. package/src/runtime/routes/domain-routes.ts +167 -0
  633. package/src/runtime/routes/email-routes.ts +603 -0
  634. package/src/runtime/routes/errors.ts +2 -2
  635. package/src/runtime/routes/events-routes.ts +192 -0
  636. package/src/runtime/routes/filing-routes.ts +2 -3
  637. package/src/runtime/routes/home-feed-routes.ts +6 -78
  638. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  639. package/src/runtime/routes/host-browser-routes.ts +103 -22
  640. package/src/runtime/routes/http-adapter.ts +2 -0
  641. package/src/runtime/routes/identity-routes.ts +5 -0
  642. package/src/runtime/routes/image-generation-routes.ts +99 -0
  643. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
  644. package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
  645. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  646. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -7
  647. package/src/runtime/routes/index.ts +36 -0
  648. package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
  649. package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
  650. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  651. package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
  652. package/src/runtime/routes/inference-send-routes.ts +115 -0
  653. package/src/runtime/routes/integrations/twilio.ts +1 -0
  654. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  655. package/src/runtime/routes/memory-item-routes.test.ts +3 -9
  656. package/src/runtime/routes/memory-item-routes.ts +5 -6
  657. package/src/runtime/routes/memory-v2-routes.ts +105 -404
  658. package/src/runtime/routes/notification-routes.ts +2 -0
  659. package/src/runtime/routes/oauth-apps.ts +112 -7
  660. package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
  661. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  662. package/src/runtime/routes/oauth-providers.ts +298 -8
  663. package/src/runtime/routes/platform-routes.ts +336 -0
  664. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  665. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  666. package/src/runtime/routes/playground/state.ts +2 -1
  667. package/src/runtime/routes/publish-routes.ts +221 -0
  668. package/src/runtime/routes/schedule-routes.ts +82 -0
  669. package/src/runtime/routes/sequence-routes.ts +291 -0
  670. package/src/runtime/routes/settings-routes.ts +2 -10
  671. package/src/runtime/routes/skills-routes.ts +31 -1
  672. package/src/runtime/routes/stt-routes.ts +240 -3
  673. package/src/runtime/routes/surface-action-routes.ts +43 -7
  674. package/src/runtime/routes/tts-routes.ts +67 -0
  675. package/src/runtime/routes/types.ts +32 -0
  676. package/src/runtime/routes/user-routes-cli.ts +243 -0
  677. package/src/runtime/routes/webhook-routes.ts +165 -0
  678. package/src/runtime/sync/resource-sync-events.ts +25 -0
  679. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  680. package/src/runtime/sync/sync-publisher.ts +21 -0
  681. package/src/schedule/scheduler.ts +200 -123
  682. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  683. package/src/security/secret-patterns.ts +3 -0
  684. package/src/sequence/engine.ts +38 -40
  685. package/src/skills/include-graph.ts +35 -13
  686. package/src/subagent/manager.ts +20 -15
  687. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  688. package/src/tools/browser/browser-execution.ts +15 -4
  689. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  690. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  691. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  692. package/src/tools/browser/cdp-client/factory.ts +66 -5
  693. package/src/tools/browser/runtime-check.ts +77 -0
  694. package/src/tools/document/document-tool.ts +20 -0
  695. package/src/tools/executor.ts +18 -2
  696. package/src/tools/memory/register.test.ts +10 -8
  697. package/src/tools/memory/register.ts +9 -1
  698. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  699. package/src/tools/network/web-search.ts +280 -37
  700. package/src/tools/permission-checker.ts +28 -5
  701. package/src/tools/skills/load.ts +24 -20
  702. package/src/tools/subagent/spawn.ts +3 -3
  703. package/src/tools/terminal/shell.ts +44 -0
  704. package/src/tools/tool-name-aliases.ts +19 -0
  705. package/src/tools/types.ts +19 -1
  706. package/src/usage/attribution.ts +3 -2
  707. package/src/util/pricing.ts +86 -160
  708. package/src/watcher/__tests__/engine.test.ts +301 -0
  709. package/src/watcher/constants.ts +7 -0
  710. package/src/watcher/engine.ts +90 -90
  711. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  712. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  713. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
  714. package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +4 -62
  715. package/src/workspace/migrations/069-seed-onboarding-threads.ts +34 -0
  716. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +31 -0
  717. package/src/workspace/migrations/071-remove-safe-storage-release-note.ts +111 -0
  718. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
  719. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
  720. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  721. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  722. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  723. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  724. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  725. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  726. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  727. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  728. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  729. package/src/workspace/migrations/registry.ts +28 -0
  730. package/src/workspace/migrations/runner.ts +13 -2
  731. package/src/workspace/migrations/types.ts +13 -3
  732. package/src/workspace/provider-commit-message-generator.ts +3 -2
  733. package/src/__tests__/context-search-pkb-source.test.ts +0 -492
  734. package/src/__tests__/credentials-cli.test.ts +0 -1225
  735. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  736. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  737. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  738. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  739. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  740. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  741. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  742. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  743. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  744. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  745. package/src/cli/commands/autonomy.ts +0 -365
  746. package/src/cli/commands/memory.ts +0 -424
  747. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -1201
  748. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  749. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  750. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  751. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  752. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  753. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  754. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  755. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  756. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  757. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  758. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  759. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  760. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  761. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  762. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  763. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  764. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  765. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  766. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  767. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  768. package/src/home/assistant-feed-authoring.ts +0 -135
  769. package/src/home/emit-feed-event.ts +0 -169
  770. package/src/home/feed-scheduler.ts +0 -281
  771. package/src/home/platform-gmail-digest.ts +0 -163
  772. package/src/home/rewrite-command-preview.ts +0 -66
  773. package/src/home/rewrite-feed-title.ts +0 -58
  774. package/src/home/rollup-producer.ts +0 -426
  775. package/src/memory/admin.ts +0 -326
  776. package/src/memory/context-search/sources/pkb.ts +0 -477
  777. package/src/memory/graph/compaction.ts +0 -299
  778. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -4,7 +4,6 @@
4
4
  * context inspection, and queued message deletion.
5
5
  *
6
6
  * GET /v1/model — current model info
7
- * PUT /v1/model — set model
8
7
  * PUT /v1/model/image-gen — set image-gen model
9
8
  * GET /v1/config/embeddings — current embedding config
10
9
  * PUT /v1/config/embeddings — set embedding provider/model
@@ -22,14 +21,18 @@ import { z } from "zod";
22
21
 
23
22
  import {
24
23
  deepMergeOverwrite,
24
+ fillContextDefaultsForMissingKeys,
25
25
  getConfig,
26
+ getDeploymentContextDefaults,
26
27
  invalidateConfigCache,
27
28
  loadRawConfig,
28
29
  saveRawConfig,
30
+ setNestedValue,
29
31
  } from "../../config/loader.js";
32
+ import { AssistantConfigSchema } from "../../config/schema.js";
33
+ import { getSchemaAtPath } from "../../config/schema-utils.js";
30
34
  import { ProfileEntry } from "../../config/schemas/llm.js";
31
35
  import { VALID_MEMORY_EMBEDDING_PROVIDERS } from "../../config/schemas/memory-storage.js";
32
- import { VALID_INFERENCE_PROVIDERS } from "../../config/schemas/services.js";
33
36
  import { getConfigWatcher } from "../../daemon/config-watcher.js";
34
37
  import {
35
38
  getEmbeddingConfigInfo,
@@ -39,7 +42,6 @@ import {
39
42
  getModelInfo,
40
43
  type ModelSetContext,
41
44
  setImageGenModel,
42
- setModel,
43
45
  } from "../../daemon/handlers/config-model.js";
44
46
  import {
45
47
  getMessageContent,
@@ -56,14 +58,12 @@ import {
56
58
  getMessageById,
57
59
  } from "../../memory/conversation-crud.js";
58
60
  import { clearEmbeddingBackendCache } from "../../memory/embedding-backend.js";
59
- import {
60
- getRequestLogById,
61
- getRequestLogsByMessageId,
62
- } from "../../memory/llm-request-log-store.js";
61
+ import { getLlmRequestLogSource } from "../../memory/llm-request-log-source.js";
63
62
  import { getMemoryRecallLogByMessageIds } from "../../memory/memory-recall-log-store.js";
64
63
  import { getMemoryV2ActivationLogByMessageIds } from "../../memory/memory-v2-activation-log-store.js";
65
64
  import { MEMORY_V2_CONSOLIDATION_SOURCE } from "../../memory/v2/constants.js";
66
65
  import { initializeProviders } from "../../providers/registry.js";
66
+ import { validateAllowlistFile } from "../../security/secret-allowlist.js";
67
67
  import { resolvePricingForUsage } from "../../util/pricing.js";
68
68
  import { BadRequestError, InternalError, NotFoundError } from "./errors.js";
69
69
  import {
@@ -72,7 +72,6 @@ import {
72
72
  } from "./llm-context-normalization.js";
73
73
  import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
74
74
 
75
- const validProviderSet = new Set<string>(VALID_INFERENCE_PROVIDERS);
76
75
  const validEmbeddingProviderSet = new Set<string>(
77
76
  VALID_MEMORY_EMBEDDING_PROVIDERS,
78
77
  );
@@ -93,8 +92,15 @@ type LlmContextRouteResult = Omit<LlmContextNormalizationResult, "summary"> & {
93
92
 
94
93
  import { MANAGED_PROFILE_NAMES } from "../../config/seed-inference-profiles.js";
95
94
 
95
+ const RESERVED_PROFILE_NAMES = new Set([
96
+ "__proto__",
97
+ "constructor",
98
+ "prototype",
99
+ ]);
100
+
96
101
  const INFERENCE_PROFILE_UI_KEYS = new Set([
97
102
  "provider",
103
+ "provider_connection",
98
104
  "model",
99
105
  "maxTokens",
100
106
  "effort",
@@ -237,33 +243,6 @@ async function handleGetModel() {
237
243
  return getModelInfo();
238
244
  }
239
245
 
240
- async function handleSetModel({ body }: RouteHandlerArgs) {
241
- if (!body || typeof body !== "object") {
242
- throw new BadRequestError("Request body is required");
243
- }
244
- const { modelId, provider } = body as {
245
- modelId?: string;
246
- provider?: string;
247
- };
248
- if (!modelId || typeof modelId !== "string") {
249
- throw new BadRequestError("Missing required field: modelId");
250
- }
251
- if (
252
- provider !== undefined &&
253
- (typeof provider !== "string" || !validProviderSet.has(provider))
254
- ) {
255
- throw new BadRequestError(
256
- `Invalid provider "${provider}". Valid providers: ${[...validProviderSet].join(", ")}`,
257
- );
258
- }
259
- try {
260
- return await setModel(modelId, getModelSetContext(), provider);
261
- } catch (err) {
262
- const message = err instanceof Error ? err.message : String(err);
263
- throw new InternalError(`Failed to set model: ${message}`);
264
- }
265
- }
266
-
267
246
  async function handleSetImageGenModel({ body }: RouteHandlerArgs) {
268
247
  if (!body || typeof body !== "object") {
269
248
  throw new BadRequestError("Request body is required");
@@ -312,15 +291,131 @@ async function handleSetEmbeddingConfig({ body }: RouteHandlerArgs) {
312
291
  }
313
292
  }
314
293
 
294
+ /**
295
+ * Apply deployment-context defaults to a raw config payload before it goes
296
+ * out over the wire from `GET /v1/config`. The in-memory `loadConfig()`
297
+ * already layers these defaults for daemon-internal consumers; the GET
298
+ * response needs the same treatment so external clients (macOS, web, CLI)
299
+ * see the effective value rather than `undefined` when the daemon hasn't
300
+ * persisted an explicit choice yet. For example, on a freshly-hatched
301
+ * platform-managed assistant, `services.image-generation.mode` may be absent
302
+ * from disk (only `llm.profiles` was written by `seedInferenceProfiles`); the
303
+ * fill pass ensures clients receive `"managed"` rather than falling back to
304
+ * their own defaults.
305
+ *
306
+ * Guards against `loadRawConfig()` handing us a value that is technically
307
+ * valid JSON but not a plain object (e.g. literal `null`, a number, or an
308
+ * array). `loadRawConfig` is typed `Record<string, unknown>` but `JSON.parse`
309
+ * itself doesn't enforce that — a malformed-but-parseable `config.json`
310
+ * would blow up `fillContextDefaultsForMissingKeys` on its `target[key]` /
311
+ * `fileConfig[key]` accesses, turning `GET /v1/config` into a 500 where it
312
+ * used to succeed (returning the malformed payload as-is). When `raw` is
313
+ * not a plain object, we return it unchanged.
314
+ *
315
+ * Exported for direct unit testing.
316
+ */
317
+ export function applyContextDefaultsToRawConfig(raw: unknown): unknown {
318
+ const contextDefaults = getDeploymentContextDefaults();
319
+ if (
320
+ Object.keys(contextDefaults).length === 0 ||
321
+ raw === null ||
322
+ typeof raw !== "object" ||
323
+ Array.isArray(raw)
324
+ ) {
325
+ return raw;
326
+ }
327
+ fillContextDefaultsForMissingKeys(
328
+ raw as Record<string, unknown>,
329
+ raw as Record<string, unknown>,
330
+ contextDefaults,
331
+ );
332
+ synthesizeLegacyInferenceModeForPlatform(raw as Record<string, unknown>);
333
+ return raw;
334
+ }
335
+
336
+ /**
337
+ * Backwards-compat wire field for `GET /v1/config`. PR removed
338
+ * `services.inference.mode` from the typed schema (routing is now governed
339
+ * by `provider_connections` rows + `llm.default.provider_connection`), but
340
+ * the macOS settings client (`SettingsStore.swift:loadServiceModes`) still
341
+ * reads this field and falls back to its `@Published` default of "your-own"
342
+ * when absent. On a platform-managed assistant served by a newer daemon and
343
+ * an older macOS client, that fallback would show the wrong mode in the UI
344
+ * until the user explicitly saved. Synthesize the value here so the wire
345
+ * shape stays compatible during the rollout window. Remove once the macOS
346
+ * Providers UI (the follow-up PR that retires this field on the client) has
347
+ * shipped to the majority of installs.
348
+ *
349
+ * The synthesis is wire-only: it never persists to disk and never reaches
350
+ * the typed `AssistantConfig` consumed by daemon-internal code. The on-disk
351
+ * config is stripped of `mode` by workspace migration 076.
352
+ *
353
+ * Only runs when this function is reached, which is guarded by
354
+ * `getDeploymentContextDefaults()` returning non-empty (IS_PLATFORM=true).
355
+ */
356
+ function synthesizeLegacyInferenceModeForPlatform(
357
+ root: Record<string, unknown>,
358
+ ): void {
359
+ const services = readPlainObject(root.services);
360
+ if (!services) return;
361
+ let inference = readPlainObject(services.inference);
362
+ if (!inference) {
363
+ inference = {};
364
+ services.inference = inference;
365
+ }
366
+ if (inference.mode === undefined) {
367
+ inference.mode = "managed";
368
+ }
369
+ }
370
+
371
+ function readPlainObject(value: unknown): Record<string, unknown> | undefined {
372
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
373
+ return undefined;
374
+ }
375
+ return value as Record<string, unknown>;
376
+ }
377
+
315
378
  function handleGetConfig() {
316
379
  try {
317
- return loadRawConfig();
380
+ return applyContextDefaultsToRawConfig(loadRawConfig());
318
381
  } catch (err) {
319
382
  const message = err instanceof Error ? err.message : String(err);
320
383
  throw new InternalError(`Failed to read config: ${message}`);
321
384
  }
322
385
  }
323
386
 
387
+ /**
388
+ * Return the JSON Schema for the assistant config (full or scoped).
389
+ *
390
+ * The schema is derived from `AssistantConfigSchema` at runtime via
391
+ * `z.toJSONSchema()`. Pure read; no daemon state involved.
392
+ */
393
+ function handleGetConfigSchema({ queryParams = {} }: RouteHandlerArgs) {
394
+ const rawPath = queryParams.path;
395
+ const path = typeof rawPath === "string" ? rawPath.trim() : "";
396
+
397
+ if (!path) {
398
+ return {
399
+ schema: z.toJSONSchema(AssistantConfigSchema, {
400
+ unrepresentable: "any",
401
+ io: "input",
402
+ }),
403
+ };
404
+ }
405
+
406
+ const subSchema = getSchemaAtPath(AssistantConfigSchema, path);
407
+ if (!subSchema) {
408
+ throw new BadRequestError(`No schema found at path: ${path}`);
409
+ }
410
+
411
+ return {
412
+ schema: z.toJSONSchema(subSchema, {
413
+ unrepresentable: "any",
414
+ io: "input",
415
+ }),
416
+ };
417
+ }
418
+
324
419
  function rejectManagedProfileDeletion(body: Record<string, unknown>): void {
325
420
  const llm = asMutablePlainObject(body.llm);
326
421
  if (!llm) return;
@@ -338,28 +433,24 @@ function rejectManagedProfileDeletion(body: Record<string, unknown>): void {
338
433
  }
339
434
  }
340
435
 
341
- async function handlePatchConfig({ body }: RouteHandlerArgs) {
342
- if (
343
- !body ||
344
- typeof body !== "object" ||
345
- Array.isArray(body) ||
346
- Object.keys(body).length === 0
347
- ) {
348
- throw new BadRequestError("Body must be a non-empty JSON object");
349
- }
350
- rejectManagedProfileDeletion(body as Record<string, unknown>);
351
-
352
- const raw = loadRawConfig();
353
- const patch = body as Record<string, unknown>;
354
- deepMergeOverwrite(raw, patch);
355
-
436
+ /**
437
+ * Persist a mutated raw config object to disk and synchronize the running
438
+ * daemon (file-watcher, embedding cache, provider registry).
439
+ *
440
+ * Shared by `handlePatchConfig` and `handleSetConfig` so both write paths get
441
+ * identical post-write side effects.
442
+ */
443
+ async function commitConfigWrite(
444
+ raw: Record<string, unknown>,
445
+ opLabel: string,
446
+ ): Promise<void> {
356
447
  // Suppress the file-watcher callback for the duration of the debounce
357
448
  // window. Without this, the ConfigWatcher detects the config.json write
358
449
  // ~200ms later, sees a stale fingerprint, and calls initializeProviders a
359
- // second time starting with providers.clear() which races with the
450
+ // second time - starting with providers.clear() which races with the
360
451
  // explicit reinit below. The watcher also fires onConversationEvict(),
361
- // which would evict all cached conversations on every PATCH. Mirror the
362
- // suppress/reset pattern used in setModel (config-model.ts).
452
+ // which would evict all cached conversations on every write. Mirror the
453
+ // suppress/reset pattern used in setImageGenModel (config-model.ts).
363
454
  const configWatcher = getConfigWatcher();
364
455
  const wasSuppressed = configWatcher.suppressConfigReload;
365
456
  configWatcher.suppressConfigReload = true;
@@ -368,7 +459,7 @@ async function handlePatchConfig({ body }: RouteHandlerArgs) {
368
459
  } catch (err) {
369
460
  configWatcher.suppressConfigReload = wasSuppressed;
370
461
  const message = err instanceof Error ? err.message : String(err);
371
- throw new InternalError(`Failed to patch config: ${message}`);
462
+ throw new InternalError(`Failed to ${opLabel} config: ${message}`);
372
463
  }
373
464
  configWatcher.timers.schedule(
374
465
  "__suppress_reset__",
@@ -383,7 +474,7 @@ async function handlePatchConfig({ body }: RouteHandlerArgs) {
383
474
  // Reinitialize providers so the live registry reflects the new config
384
475
  // (e.g. a mode flip between managed and your-own). Isolated try/catch so
385
476
  // a provider reinit failure doesn't mask the successful config save.
386
- // Only advance the config fingerprint on success if reinit failed, leave
477
+ // Only advance the config fingerprint on success - if reinit failed, leave
387
478
  // it stale so the watcher can detect the saved config on the next event
388
479
  // and retry provider initialization.
389
480
  try {
@@ -391,11 +482,101 @@ async function handlePatchConfig({ body }: RouteHandlerArgs) {
391
482
  configWatcher.updateFingerprint();
392
483
  } catch (err) {
393
484
  const message = err instanceof Error ? err.message : String(err);
394
- log.error({ err }, `handlePatchConfig: provider reinit failed: ${message}`);
485
+ log.error({ err }, `${opLabel} config: provider reinit failed: ${message}`);
486
+ }
487
+ }
488
+
489
+ async function handlePatchConfig({ body }: RouteHandlerArgs) {
490
+ if (
491
+ !body ||
492
+ typeof body !== "object" ||
493
+ Array.isArray(body) ||
494
+ Object.keys(body).length === 0
495
+ ) {
496
+ throw new BadRequestError("Body must be a non-empty JSON object");
497
+ }
498
+ rejectManagedProfileDeletion(body as Record<string, unknown>);
499
+
500
+ const raw = loadRawConfig();
501
+ const patch = body as Record<string, unknown>;
502
+ deepMergeOverwrite(raw, patch);
503
+
504
+ await commitConfigWrite(raw, "patch");
505
+ return { ok: true };
506
+ }
507
+
508
+ /**
509
+ * Direct path assignment - replaces `config_patch` for the `assistant
510
+ * config set <key> <value>` CLI path.
511
+ *
512
+ * `config_patch` uses `deepMergeOverwrite` semantics, which strips `null`
513
+ * leaves when the target subtree doesn't exist and merges (rather than
514
+ * replaces) object subtrees. That's correct for partial updates (embedding
515
+ * config, profile patches) but breaks single-key `set` semantics, where the
516
+ * user expects:
517
+ * - `set heartbeat.activeHoursStart null` to persist explicit `null`
518
+ * - `set llm {}` to replace `llm`, not merge into it
519
+ *
520
+ * `config_set` performs `setNestedValue` directly on the loaded raw config
521
+ * (no merge), then runs the same post-write side effects as patch.
522
+ */
523
+ async function handleSetConfig({ body }: RouteHandlerArgs) {
524
+ if (!body || typeof body !== "object" || Array.isArray(body)) {
525
+ throw new BadRequestError(
526
+ "Body must be a JSON object with `path` and `value`",
527
+ );
395
528
  }
529
+ const bodyRecord = body as Record<string, unknown>;
530
+ const { path, value } = bodyRecord as { path?: unknown; value?: unknown };
531
+ if (typeof path !== "string" || path.length === 0) {
532
+ throw new BadRequestError("`path` must be a non-empty string");
533
+ }
534
+ // `value` must be present (use explicit `null` to clear a key). Without
535
+ // this check, `undefined` flows into `setNestedValue` and gets dropped by
536
+ // `JSON.stringify` at save time, silently removing the key - which is
537
+ // distinct from the documented "set to null" semantics.
538
+ if (!("value" in bodyRecord)) {
539
+ throw new BadRequestError(
540
+ "`value` is required (use `null` to clear a key)",
541
+ );
542
+ }
543
+ // Build the equivalent patch shape so the managed-profile guard can
544
+ // inspect the touched subtree.
545
+ const patchShape: Record<string, unknown> = {};
546
+ setNestedValue(patchShape, path, value);
547
+ rejectManagedProfileDeletion(patchShape);
548
+
549
+ const raw = loadRawConfig();
550
+ setNestedValue(raw, path, value);
551
+
552
+ await commitConfigWrite(raw, "set");
396
553
  return { ok: true };
397
554
  }
398
555
 
556
+ /**
557
+ * Validate the regex patterns inside the workspace's
558
+ * `secret-allowlist.json` file.
559
+ *
560
+ * Pure read: opens the file, attempts to compile each pattern, returns
561
+ * structured errors. The handler returns `{ exists: false }` if the file is
562
+ * absent, or `{ exists: true, errors: [...] }` otherwise.
563
+ */
564
+ function handleValidateAllowlist() {
565
+ try {
566
+ const errors = validateAllowlistFile();
567
+ if (errors == null) return { exists: false } as const;
568
+ return { exists: true, errors } as const;
569
+ } catch (err) {
570
+ // `validateAllowlistFile` does a raw `JSON.parse` on
571
+ // `secret-allowlist.json` and can throw on malformed JSON. Surface
572
+ // that as a structured `parseError` in the response payload instead
573
+ // of letting it propagate as a 500. Preserves the pre-IPC CLI
574
+ // behavior, which printed a user-readable failure and exited 1.
575
+ const message = err instanceof Error ? err.message : String(err);
576
+ return { exists: true, parseError: message, errors: [] } as const;
577
+ }
578
+ }
579
+
399
580
  function handleReplaceInferenceProfile({
400
581
  pathParams = {},
401
582
  body,
@@ -407,9 +588,9 @@ function handleReplaceInferenceProfile({
407
588
  if (!body || typeof body !== "object" || Array.isArray(body)) {
408
589
  throw new BadRequestError("Body must be a JSON object");
409
590
  }
410
- if (MANAGED_PROFILE_NAMES.has(name)) {
591
+ if (RESERVED_PROFILE_NAMES.has(name)) {
411
592
  throw new BadRequestError(
412
- `Cannot edit managed profile "${name}". Duplicate it to create a custom profile.`,
593
+ `Profile name "${name}" is reserved and cannot be used.`,
413
594
  );
414
595
  }
415
596
  const parsed = ProfileEntry.safeParse(body);
@@ -417,13 +598,44 @@ function handleReplaceInferenceProfile({
417
598
  const detail = parsed.error.issues.map((issue) => issue.message).join("; ");
418
599
  throw new BadRequestError(`Invalid profile fragment: ${detail}`);
419
600
  }
601
+ const isManaged = MANAGED_PROFILE_NAMES.has(name);
602
+ if (isManaged) {
603
+ // Managed profiles are daemon-seeded — provider, model, advanced params,
604
+ // and the connection binding all belong to the seed contract and can't
605
+ // be reshaped by the user. The two fields that ARE user policy (display
606
+ // label and enabled status) are allowed through so users can rename a
607
+ // managed profile or temporarily disable it without duplicating it.
608
+ const requestedKeys = Object.keys(parsed.data);
609
+ const disallowed = requestedKeys.filter(
610
+ (k) => k !== "label" && k !== "status",
611
+ );
612
+ if (disallowed.length > 0) {
613
+ throw new BadRequestError(
614
+ `Cannot edit managed profile "${name}" fields [${disallowed.join(", ")}]. ` +
615
+ `Only label and status may be edited; duplicate to a custom profile to change other fields.`,
616
+ );
617
+ }
618
+ }
420
619
  try {
421
620
  const raw = loadRawConfig();
422
- replaceInferenceProfileConfig(
423
- raw,
424
- name,
425
- parsed.data as Record<string, unknown>,
426
- );
621
+ if (isManaged) {
622
+ // Partial overlay: keep every existing key intact, only update label
623
+ // and/or status from the fragment. Using `replaceInferenceProfileConfig`
624
+ // here would wipe the UI-owned seed fields (provider, model, advanced
625
+ // params) because that function assumes the body carries the full UI
626
+ // surface.
627
+ patchManagedProfileFields(
628
+ raw,
629
+ name,
630
+ parsed.data as Record<string, unknown>,
631
+ );
632
+ } else {
633
+ replaceInferenceProfileConfig(
634
+ raw,
635
+ name,
636
+ parsed.data as Record<string, unknown>,
637
+ );
638
+ }
427
639
  saveRawConfig(raw);
428
640
  return { ok: true };
429
641
  } catch (err) {
@@ -432,6 +644,45 @@ function handleReplaceInferenceProfile({
432
644
  }
433
645
  }
434
646
 
647
+ /**
648
+ * Apply a `{label?, status?}` patch to a managed profile entry, preserving
649
+ * every other field already on disk (provider, model, advanced params, etc).
650
+ * Caller is responsible for having already restricted the fragment to the
651
+ * managed-allowed keys.
652
+ */
653
+ function patchManagedProfileFields(
654
+ raw: Record<string, unknown>,
655
+ name: string,
656
+ fragment: Record<string, unknown>,
657
+ ): void {
658
+ const existingLlm = asMutablePlainObject(raw.llm);
659
+ const llm = existingLlm ?? {};
660
+ if (!existingLlm) raw.llm = llm;
661
+
662
+ const existingProfiles = asMutablePlainObject(llm.profiles);
663
+ const profiles = existingProfiles ?? {};
664
+ if (!existingProfiles) llm.profiles = profiles;
665
+
666
+ const existingProfile = asMutablePlainObject(profiles[name]) ?? {};
667
+ const nextProfile: Record<string, unknown> = { ...existingProfile };
668
+ // Send `null` to clear; omit to leave untouched.
669
+ if ("label" in fragment) {
670
+ if (fragment.label === null) {
671
+ delete nextProfile.label;
672
+ } else {
673
+ nextProfile.label = fragment.label;
674
+ }
675
+ }
676
+ if ("status" in fragment) {
677
+ if (fragment.status === null) {
678
+ delete nextProfile.status;
679
+ } else {
680
+ nextProfile.status = fragment.status;
681
+ }
682
+ }
683
+ profiles[name] = nextProfile;
684
+ }
685
+
435
686
  function handleSearchConversations({ queryParams = {} }: RouteHandlerArgs) {
436
687
  const q = queryParams.q;
437
688
  if (!q) {
@@ -484,12 +735,13 @@ function resolveConversationKind(
484
735
  return "user";
485
736
  }
486
737
 
487
- function handleGetLlmContext({ pathParams = {} }: RouteHandlerArgs) {
738
+ async function handleGetLlmContext({ pathParams = {} }: RouteHandlerArgs) {
488
739
  const messageId = pathParams.id;
489
740
  if (!messageId) {
490
741
  throw new BadRequestError("message id is required");
491
742
  }
492
- const logs = getRequestLogsByMessageId(messageId);
743
+ const source = await getLlmRequestLogSource();
744
+ const logs = await source.getRequestLogsByMessageId(messageId);
493
745
  const turnMessageIds = getAssistantMessageIdsInTurn(messageId);
494
746
  const memoryRecallLog = getMemoryRecallLogByMessageIds(turnMessageIds);
495
747
  const memoryV2Activation =
@@ -502,9 +754,15 @@ function handleGetLlmContext({ pathParams = {} }: RouteHandlerArgs) {
502
754
  conversation.conversationType,
503
755
  )
504
756
  : "user";
757
+ // Running total of estimated USD cost across every priced LLM call in
758
+ // the conversation. Maintained by `updateConversationUsage` whenever a
759
+ // turn finishes — see `assistant/src/memory/conversation-crud.ts`.
760
+ const conversationTotalEstimatedCostUsd =
761
+ conversation?.totalEstimatedCost ?? null;
505
762
  return {
506
763
  messageId,
507
764
  conversationKind,
765
+ conversationTotalEstimatedCostUsd,
508
766
  logs: logs.map((log) => {
509
767
  let requestPayload: unknown;
510
768
  try {
@@ -540,12 +798,15 @@ function handleGetLlmContext({ pathParams = {} }: RouteHandlerArgs) {
540
798
  };
541
799
  }
542
800
 
543
- function handleGetLlmRequestLogPayload({ pathParams = {} }: RouteHandlerArgs) {
801
+ async function handleGetLlmRequestLogPayload({
802
+ pathParams = {},
803
+ }: RouteHandlerArgs) {
544
804
  const logId = pathParams.id;
545
805
  if (!logId) {
546
806
  throw new BadRequestError("log id is required");
547
807
  }
548
- const log = getRequestLogById(logId);
808
+ const source = await getLlmRequestLogSource();
809
+ const log = await source.getRequestLogById(logId);
549
810
  if (!log) {
550
811
  throw new NotFoundError("log not found");
551
812
  }
@@ -600,20 +861,6 @@ export const ROUTES: RouteDefinition[] = [
600
861
  tags: ["config"],
601
862
  handler: handleGetModel,
602
863
  },
603
- {
604
- operationId: "model_set",
605
- endpoint: "model",
606
- method: "PUT",
607
- policyKey: "model",
608
- summary: "Set LLM model",
609
- description: "Change the active LLM model and optionally its provider.",
610
- tags: ["config"],
611
- requestBody: z.object({
612
- modelId: z.string(),
613
- provider: z.string().describe("Optional provider override").optional(),
614
- }),
615
- handler: handleSetModel,
616
- },
617
864
  {
618
865
  operationId: "model_image_gen_set",
619
866
  endpoint: "model/image-gen",
@@ -671,6 +918,49 @@ export const ROUTES: RouteDefinition[] = [
671
918
  tags: ["config"],
672
919
  handler: handlePatchConfig,
673
920
  },
921
+ {
922
+ operationId: "config_set",
923
+ endpoint: "config/set",
924
+ method: "POST",
925
+ policyKey: "config/set",
926
+ summary: "Set a single config path",
927
+ description:
928
+ "Assign a value at a dotted config path with direct-replacement semantics " +
929
+ "(preserves explicit null, replaces object subtrees instead of merging). " +
930
+ "Used by the `assistant config set <key> <value>` CLI command.",
931
+ tags: ["config"],
932
+ handler: handleSetConfig,
933
+ },
934
+ {
935
+ operationId: "config_allowlist_validate",
936
+ endpoint: "config/allowlist/validate",
937
+ method: "GET",
938
+ policyKey: "config/allowlist/validate",
939
+ summary: "Validate secret-allowlist.json regex patterns",
940
+ description:
941
+ "Compile each regex pattern in secret-allowlist.json and return any " +
942
+ "syntax errors. Returns { exists: false } if no file is present.",
943
+ tags: ["config"],
944
+ handler: handleValidateAllowlist,
945
+ },
946
+ {
947
+ operationId: "config_schema_get",
948
+ endpoint: "config/schema",
949
+ method: "GET",
950
+ policyKey: "config/schema",
951
+ summary: "Get config JSON Schema",
952
+ description:
953
+ "Return the JSON Schema for the assistant config, optionally scoped to a dotted-path sub-schema (e.g. ?path=calls).",
954
+ tags: ["config"],
955
+ queryParams: [
956
+ {
957
+ name: "path",
958
+ schema: { type: "string" },
959
+ description: "Optional dotted path to a config sub-key",
960
+ },
961
+ ],
962
+ handler: handleGetConfigSchema,
963
+ },
674
964
  {
675
965
  operationId: "config_llm_profiles_replace",
676
966
  endpoint: "config/llm/profiles/:name",
@@ -744,6 +1034,7 @@ export const ROUTES: RouteDefinition[] = [
744
1034
  responseBody: z.object({
745
1035
  messageId: z.string(),
746
1036
  conversationKind: z.enum(CONVERSATION_KINDS),
1037
+ conversationTotalEstimatedCostUsd: z.number().nullable(),
747
1038
  logs: z.array(z.unknown()),
748
1039
  memoryRecall: z.object({}).passthrough().nullable(),
749
1040
  memoryV2Activation: z.object({}).passthrough().nullable(),