@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
@@ -33,6 +33,7 @@ interface TestState {
33
33
  countResult: number;
34
34
  listPagesResult: string[];
35
35
  enqueueCalls: Array<{ type: string; payload: Record<string, unknown> }>;
36
+ clearSentinelCallCount: number;
36
37
  }
37
38
 
38
39
  const state: TestState = {
@@ -46,6 +47,7 @@ const state: TestState = {
46
47
  countResult: 0,
47
48
  listPagesResult: [],
48
49
  enqueueCalls: [],
50
+ clearSentinelCallCount: 0,
49
51
  };
50
52
 
51
53
  // ---------------------------------------------------------------------------
@@ -66,6 +68,9 @@ mock.module("../memory/v2/qdrant.js", () => ({
66
68
  return state.ensureCollectionResult;
67
69
  },
68
70
  countConceptPagePoints: async (): Promise<number> => state.countResult,
71
+ clearReembedSentinel: async (): Promise<void> => {
72
+ state.clearSentinelCallCount += 1;
73
+ },
69
74
  // The rebuild gate does not call this, but the seed gate's fire-and-forget
70
75
  // chain imports it; provide a no-op so the dynamic import resolves.
71
76
  dropLegacySkillsCollection: async (): Promise<void> => {},
@@ -88,6 +93,11 @@ mock.module("../memory/jobs-store.js", () => ({
88
93
 
89
94
  mock.module("../util/platform.js", () => ({
90
95
  getWorkspaceDir: () => "/tmp/test-workspace",
96
+ // qdrant.ts (mocked away in this file) reads `getDataDir` for the reembed
97
+ // sentinel path; bun mocks share the same module record across files, so
98
+ // include it here too so a peer test importing `getDataDir` doesn't see
99
+ // `undefined` after this mock evaluates.
100
+ getDataDir: () => "/tmp/test-workspace/data",
91
101
  }));
92
102
 
93
103
  mock.module("../util/logger.js", () => ({
@@ -148,6 +158,7 @@ function resetState(): void {
148
158
  state.countResult = 0;
149
159
  state.listPagesResult = [];
150
160
  state.enqueueCalls = [];
161
+ state.clearSentinelCallCount = 0;
151
162
  }
152
163
 
153
164
  describe("maybeSeedMemoryV2Skills (daemon startup gate)", () => {
@@ -202,6 +213,10 @@ describe("maybeRebuildMemoryV2Concepts (daemon startup gate)", () => {
202
213
  expect(state.enqueueCalls).toEqual([
203
214
  { type: "memory_v2_reembed", payload: {} },
204
215
  ]);
216
+ // After the reembed is queued, the on-disk sentinel that the qdrant
217
+ // ensure-path may have written is cleared so it does not re-trigger on
218
+ // the next startup.
219
+ expect(state.clearSentinelCallCount).toBe(1);
205
220
  // Migrated path skips the count probe — drift detection is the trigger.
206
221
  // (The mock's countConceptPagePoints would silently return 0 either way,
207
222
  // but keeping the path conditional keeps the lifecycle hook predictable.)
@@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test";
2
2
 
3
3
  import { getLLMCallSiteLabel } from "../config/llm-callsite-catalog.js";
4
4
  import { CALL_SITE_CATALOG } from "../config/schemas/call-site-catalog.js";
5
- import { LLMCallSiteEnum } from "../config/schemas/llm.js";
5
+ import { LLMCallSiteEnum, LLMSchema } from "../config/schemas/llm.js";
6
6
 
7
7
  describe("LLM call-site catalog", () => {
8
8
  test("resolves every backend call-site enum value from the catalog", () => {
@@ -31,4 +31,23 @@ describe("LLM call-site catalog", () => {
31
31
  test("returns the raw ID for unknown call sites", () => {
32
32
  expect(getLLMCallSiteLabel("unknownCallSite")).toBe("unknownCallSite");
33
33
  });
34
+
35
+ test("registers the memoryRouter call site under the memory domain", () => {
36
+ expect(LLMCallSiteEnum.options).toContain("memoryRouter");
37
+
38
+ const entry = CALL_SITE_CATALOG.find(({ id }) => id === "memoryRouter");
39
+ expect(entry).toBeDefined();
40
+ expect(entry?.domain).toBe("memory");
41
+ expect(entry?.displayName).toBe("Memory Router");
42
+ expect(entry?.description).toBe(
43
+ "Selects which concept pages to inject for the next agent turn by routing over a cached page index.",
44
+ );
45
+ });
46
+
47
+ test("memoryRouter is addressable as a call-site override key in LLMSchema", () => {
48
+ const parsed = LLMSchema.parse({
49
+ callSites: { memoryRouter: { model: "claude-sonnet-4-6" } },
50
+ });
51
+ expect(parsed.callSites.memoryRouter?.model).toBe("claude-sonnet-4-6");
52
+ });
34
53
  });
@@ -2,7 +2,9 @@ import { readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { describe, expect, test } from "bun:test";
4
4
 
5
+ import { MANAGED_PROVIDER_META } from "../providers/managed-proxy/constants.js";
5
6
  import { PROVIDER_CATALOG } from "../providers/model-catalog.js";
7
+ import { resolvePricing, resolvePricingForUsage } from "../util/pricing.js";
6
8
 
7
9
  /**
8
10
  * Parity guard: daemon LLM provider catalog vs client LLM catalog JSON.
@@ -50,6 +52,13 @@ interface ClientCatalogModel {
50
52
  outputPer1mTokens: number;
51
53
  cacheWritePer1mTokens?: number;
52
54
  cacheReadPer1mTokens?: number;
55
+ tiers?: Array<{
56
+ inputTokenThreshold: number;
57
+ inputPer1mTokens: number;
58
+ outputPer1mTokens: number;
59
+ cacheReadPer1mTokens?: number;
60
+ cacheWritePer1mTokens?: number;
61
+ }>;
53
62
  };
54
63
  }
55
64
 
@@ -62,6 +71,7 @@ interface ClientCatalogEntry {
62
71
  envVar?: string;
63
72
  apiKeyPlaceholder?: string;
64
73
  credentialsGuide?: ClientCatalogCredentialsGuide;
74
+ supportsManagedAuth?: boolean;
65
75
  defaultModel: string;
66
76
  models: ClientCatalogModel[];
67
77
  }
@@ -114,6 +124,9 @@ describe("LLM catalog parity: daemon vs client", () => {
114
124
  expect(clientEntry.setupHint).toBe(daemonEntry.setupHint);
115
125
  expect(clientEntry.envVar).toBe(daemonEntry.envVar);
116
126
  expect(clientEntry.apiKeyPlaceholder).toBe(daemonEntry.apiKeyPlaceholder);
127
+ expect(clientEntry.supportsManagedAuth).toBe(
128
+ daemonEntry.supportsManagedAuth,
129
+ );
117
130
  expect(clientEntry.credentialsGuide).toEqual(
118
131
  daemonEntry.credentialsGuide,
119
132
  );
@@ -121,6 +134,19 @@ describe("LLM catalog parity: daemon vs client", () => {
121
134
  }
122
135
  });
123
136
 
137
+ test("supportsManagedAuth mirrors MANAGED_PROVIDER_META", () => {
138
+ // The catalog field is derived from MANAGED_PROVIDER_META at build
139
+ // time. This test guards against future hand-edits to model-catalog.ts
140
+ // that would let the two drift. Adding a provider to MANAGED_PROVIDER_META
141
+ // must auto-propagate; flipping `managed: true` to `false` (or vice
142
+ // versa) must propagate too.
143
+ for (const entry of PROVIDER_CATALOG) {
144
+ const expectedSupportsManagedAuth =
145
+ MANAGED_PROVIDER_META[entry.id]?.managed === true;
146
+ expect(entry.supportsManagedAuth).toBe(expectedSupportsManagedAuth);
147
+ }
148
+ });
149
+
124
150
  test("each provider's model count matches the daemon catalog", () => {
125
151
  const json = loadClientCatalog();
126
152
 
@@ -248,6 +274,126 @@ describe("LLM catalog parity: daemon vs client", () => {
248
274
  });
249
275
  });
250
276
 
277
+ // -----------------------------------------------------------------------
278
+ // pricing.ts ↔ model-catalog.ts parity
279
+ //
280
+ // `assistant/src/util/pricing.ts` reads pricing from `PROVIDER_CATALOG`
281
+ // (catalog-first) with a legacy fallback table for models we still bill
282
+ // for but no longer advertise. These tests probe `resolvePricing` /
283
+ // `resolvePricingForUsage` for every priced catalog model so any drift
284
+ // between the catalog row and the resolver's output (including cache
285
+ // discounts and long-context tier rates) fails CI.
286
+ // -----------------------------------------------------------------------
287
+
288
+ test("each priced catalog model has matching base rates in pricing.ts", () => {
289
+ // 100k tokens stays below every long-context tier threshold in the
290
+ // catalog (smallest threshold is 200k), so resolvePricing returns the
291
+ // base rate uncontaminated by tier selection.
292
+ const PROBE_TOKENS = 100_000;
293
+ const TOKENS_PER_MILLION = 1_000_000;
294
+
295
+ for (const provider of PROVIDER_CATALOG) {
296
+ for (const model of provider.models) {
297
+ if (!model.pricing) continue;
298
+
299
+ const inputResult = resolvePricing(
300
+ provider.id,
301
+ model.id,
302
+ PROBE_TOKENS,
303
+ 0,
304
+ );
305
+ expect(
306
+ inputResult.pricingStatus,
307
+ `${provider.id}/${model.id} unpriced in pricing.ts`,
308
+ ).toBe("priced");
309
+ const inputRate =
310
+ (inputResult.estimatedCostUsd ?? 0) *
311
+ (TOKENS_PER_MILLION / PROBE_TOKENS);
312
+ expect(
313
+ inputRate,
314
+ `${provider.id}/${model.id} input rate drift`,
315
+ ).toBeCloseTo(model.pricing.inputPer1mTokens, 6);
316
+
317
+ const outputResult = resolvePricing(
318
+ provider.id,
319
+ model.id,
320
+ 0,
321
+ PROBE_TOKENS,
322
+ );
323
+ const outputRate =
324
+ (outputResult.estimatedCostUsd ?? 0) *
325
+ (TOKENS_PER_MILLION / PROBE_TOKENS);
326
+ expect(
327
+ outputRate,
328
+ `${provider.id}/${model.id} output rate drift`,
329
+ ).toBeCloseTo(model.pricing.outputPer1mTokens, 6);
330
+ }
331
+ }
332
+ });
333
+
334
+ test("each priced catalog model has matching cache-read rate in pricing.ts", () => {
335
+ const PROBE_TOKENS = 100_000;
336
+ const TOKENS_PER_MILLION = 1_000_000;
337
+
338
+ for (const provider of PROVIDER_CATALOG) {
339
+ for (const model of provider.models) {
340
+ const cacheReadCatalogRate = model.pricing?.cacheReadPer1mTokens;
341
+ if (cacheReadCatalogRate === undefined) continue;
342
+
343
+ const result = resolvePricingForUsage(provider.id, model.id, {
344
+ directInputTokens: 0,
345
+ outputTokens: 0,
346
+ cacheCreationInputTokens: 0,
347
+ cacheReadInputTokens: PROBE_TOKENS,
348
+ anthropicCacheCreation: null,
349
+ });
350
+ expect(
351
+ result.pricingStatus,
352
+ `${provider.id}/${model.id} unpriced in pricing.ts`,
353
+ ).toBe("priced");
354
+ const cacheReadResolvedRate =
355
+ (result.estimatedCostUsd ?? 0) * (TOKENS_PER_MILLION / PROBE_TOKENS);
356
+ expect(
357
+ cacheReadResolvedRate,
358
+ `${provider.id}/${model.id} cache-read rate drift`,
359
+ ).toBeCloseTo(cacheReadCatalogRate, 6);
360
+ }
361
+ }
362
+ });
363
+
364
+ test("each priced catalog tier resolves at its tier rate", () => {
365
+ const TOKENS_PER_MILLION = 1_000_000;
366
+
367
+ for (const provider of PROVIDER_CATALOG) {
368
+ for (const model of provider.models) {
369
+ const tiers = model.pricing?.tiers;
370
+ if (!tiers || tiers.length === 0) continue;
371
+
372
+ for (const tier of tiers) {
373
+ const probeTokens = tier.inputTokenThreshold + 1_000;
374
+ const result = resolvePricingForUsage(provider.id, model.id, {
375
+ directInputTokens: probeTokens,
376
+ outputTokens: 0,
377
+ cacheCreationInputTokens: 0,
378
+ cacheReadInputTokens: 0,
379
+ anthropicCacheCreation: null,
380
+ });
381
+ expect(
382
+ result.pricingStatus,
383
+ `${provider.id}/${model.id} unpriced at tier ${tier.inputTokenThreshold}`,
384
+ ).toBe("priced");
385
+ const resolvedRate =
386
+ (result.estimatedCostUsd ?? 0) *
387
+ (TOKENS_PER_MILLION / probeTokens);
388
+ expect(
389
+ resolvedRate,
390
+ `${provider.id}/${model.id} input rate drift at tier ${tier.inputTokenThreshold}`,
391
+ ).toBeCloseTo(tier.inputPer1mTokens, 6);
392
+ }
393
+ }
394
+ }
395
+ });
396
+
251
397
  test("Gemini 2.5 Pro catalog context matches provider limits", () => {
252
398
  const gemini = PROVIDER_CATALOG.find((entry) => entry.id === "gemini");
253
399
  expect(
@@ -0,0 +1,188 @@
1
+ import { describe, expect, mock, test } from "bun:test";
2
+
3
+ function makeLoggerStub(): Record<string, unknown> {
4
+ const stub: Record<string, unknown> = {};
5
+ for (const m of [
6
+ "info",
7
+ "warn",
8
+ "error",
9
+ "debug",
10
+ "trace",
11
+ "fatal",
12
+ "silent",
13
+ "child",
14
+ ]) {
15
+ stub[m] = m === "child" ? () => makeLoggerStub() : () => {};
16
+ }
17
+ return stub;
18
+ }
19
+
20
+ mock.module("../util/logger.js", () => ({
21
+ getLogger: () => makeLoggerStub(),
22
+ }));
23
+
24
+ import { ClickHouseLlmRequestLogSource } from "../memory/llm-request-log-source-clickhouse.js";
25
+
26
+ const DEFAULT_CONFIG = {
27
+ database: "default",
28
+ table: "llm_request_logs",
29
+ user: "default",
30
+ };
31
+
32
+ interface FakeFetchCall {
33
+ url: string;
34
+ init: RequestInit | undefined;
35
+ }
36
+
37
+ function fakeFetchReturning(
38
+ body: string,
39
+ status = 200,
40
+ recorder?: FakeFetchCall[],
41
+ ): typeof fetch {
42
+ return ((url: string | URL | Request, init?: RequestInit) => {
43
+ recorder?.push({
44
+ url: typeof url === "string" ? url : url.toString(),
45
+ init,
46
+ });
47
+ return Promise.resolve(
48
+ new Response(body, {
49
+ status,
50
+ headers: { "content-type": "application/x-ndjson" },
51
+ }),
52
+ );
53
+ }) as typeof fetch;
54
+ }
55
+
56
+ function makeSource(opts: {
57
+ body?: string;
58
+ status?: number;
59
+ recorder?: FakeFetchCall[];
60
+ resolveTurnMessageIds?: (messageId: string) => string[];
61
+ resolveMessage?: (messageId: string) => { metadata: string | null } | null;
62
+ }) {
63
+ return new ClickHouseLlmRequestLogSource(DEFAULT_CONFIG, {
64
+ resolveUrl: async () => "https://ch.example.test:8443",
65
+ resolvePassword: async () => "hunter2",
66
+ resolveAssistantId: async () => "asst-fixture-001",
67
+ resolveTurnMessageIds: opts.resolveTurnMessageIds ?? (() => []),
68
+ resolveMessage: opts.resolveMessage ?? (() => null),
69
+ fetchImpl: fakeFetchReturning(
70
+ opts.body ?? "",
71
+ opts.status ?? 200,
72
+ opts.recorder,
73
+ ),
74
+ });
75
+ }
76
+
77
+ const SAMPLE_ROW = {
78
+ id: "log-1",
79
+ conversation_id: "conv-1",
80
+ message_id: "msg-1",
81
+ provider: "anthropic",
82
+ request_payload: '{"foo":1}',
83
+ response_payload: '{"bar":2}',
84
+ // ClickHouse emits Int64 as a quoted string under JSONEachRow by default.
85
+ created_at: "1778465138786",
86
+ };
87
+
88
+ describe("ClickHouseLlmRequestLogSource", () => {
89
+ test("getRequestLogById returns null on empty response", async () => {
90
+ const src = makeSource({ body: "" });
91
+ expect(await src.getRequestLogById("missing")).toBeNull();
92
+ });
93
+
94
+ test("getRequestLogById parses a single JSONEachRow row into LogRow", async () => {
95
+ const src = makeSource({ body: JSON.stringify(SAMPLE_ROW) + "\n" });
96
+ const row = await src.getRequestLogById("log-1");
97
+ expect(row).toEqual({
98
+ id: "log-1",
99
+ conversationId: "conv-1",
100
+ messageId: "msg-1",
101
+ provider: "anthropic",
102
+ requestPayload: '{"foo":1}',
103
+ responsePayload: '{"bar":2}',
104
+ createdAt: 1778465138786,
105
+ });
106
+ });
107
+
108
+ test("maps empty-string message_id and provider back to null", async () => {
109
+ const src = makeSource({
110
+ body:
111
+ JSON.stringify({
112
+ ...SAMPLE_ROW,
113
+ message_id: "",
114
+ provider: "",
115
+ }) + "\n",
116
+ });
117
+ const row = await src.getRequestLogById("log-1");
118
+ expect(row?.messageId).toBeNull();
119
+ expect(row?.provider).toBeNull();
120
+ });
121
+
122
+ test("sets the database URL param + assistant_id query param + Basic auth", async () => {
123
+ const recorder: FakeFetchCall[] = [];
124
+ const src = makeSource({
125
+ body: JSON.stringify(SAMPLE_ROW) + "\n",
126
+ recorder,
127
+ });
128
+ await src.getRequestLogById("log-1");
129
+ expect(recorder).toHaveLength(1);
130
+ const call = recorder[0]!;
131
+ const parsed = new URL(call.url);
132
+ expect(parsed.searchParams.get("database")).toBe("default");
133
+ expect(parsed.searchParams.get("param_assistant_id")).toBe("asst-fixture-001");
134
+ expect(parsed.searchParams.get("param_log_id")).toBe("log-1");
135
+ expect(call.init?.method).toBe("POST");
136
+ const auth = (call.init?.headers as Record<string, string>).Authorization;
137
+ expect(auth).toMatch(/^Basic /);
138
+ const decoded = Buffer.from(auth.slice("Basic ".length), "base64").toString(
139
+ "utf8",
140
+ );
141
+ expect(decoded).toBe("default:hunter2");
142
+ // The SQL body should reference the configured table and the parameterized
143
+ // placeholders ClickHouse will substitute from `param_*`.
144
+ expect(call.init?.body).toContain("`llm_request_logs`");
145
+ expect(call.init?.body).toContain("{assistant_id:String}");
146
+ expect(call.init?.body).toContain("{log_id:String}");
147
+ });
148
+
149
+ test("throws a descriptive error on non-2xx", async () => {
150
+ const src = makeSource({ body: "boom", status: 503 });
151
+ await expect(src.getRequestLogById("log-1")).rejects.toThrow(
152
+ /ClickHouse query failed \(HTTP 503\): boom/,
153
+ );
154
+ });
155
+
156
+ test("getRequestLogsByMessageId returns [] when turn resolution yields no message IDs", async () => {
157
+ // The module-level mock of conversation-crud returns [] for the turn,
158
+ // and null for fork-source resolution, so this exercises the empty path
159
+ // without any database setup.
160
+ const src = makeSource({ body: "" });
161
+ const rows = await src.getRequestLogsByMessageId("msg-x");
162
+ expect(rows).toEqual([]);
163
+ });
164
+
165
+ test("missing clickhouse:url credential surfaces a clear error", async () => {
166
+ const src = new ClickHouseLlmRequestLogSource(DEFAULT_CONFIG, {
167
+ resolveUrl: async () => null,
168
+ resolvePassword: async () => "x",
169
+ resolveAssistantId: async () => "asst-1",
170
+ fetchImpl: fakeFetchReturning(""),
171
+ });
172
+ await expect(src.getRequestLogById("log-1")).rejects.toThrow(
173
+ /clickhouse:url credential is required/,
174
+ );
175
+ });
176
+
177
+ test("missing vellum:platform_assistant_id surfaces a clear error", async () => {
178
+ const src = new ClickHouseLlmRequestLogSource(DEFAULT_CONFIG, {
179
+ resolveUrl: async () => "https://ch.example.test",
180
+ resolvePassword: async () => "x",
181
+ resolveAssistantId: async () => null,
182
+ fetchImpl: fakeFetchReturning(""),
183
+ });
184
+ await expect(src.getRequestLogById("log-1")).rejects.toThrow(
185
+ /vellum:platform_assistant_id credential is required/,
186
+ );
187
+ });
188
+ });
@@ -0,0 +1,124 @@
1
+ import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ function makeLoggerStub(): Record<string, unknown> {
4
+ const stub: Record<string, unknown> = {};
5
+ for (const m of [
6
+ "info",
7
+ "warn",
8
+ "error",
9
+ "debug",
10
+ "trace",
11
+ "fatal",
12
+ "silent",
13
+ "child",
14
+ ]) {
15
+ stub[m] = m === "child" ? () => makeLoggerStub() : () => {};
16
+ }
17
+ return stub;
18
+ }
19
+
20
+ mock.module("../util/logger.js", () => ({
21
+ getLogger: () => makeLoggerStub(),
22
+ }));
23
+
24
+ // Configurable config stub. Each test sets `currentConfig` before calling
25
+ // the factory. The ClickHouse source is dynamic-imported, so its constructor
26
+ // runs lazily; we don't need to mock conversation-crud here because none of
27
+ // the factory's tests actually exercise the CH read path.
28
+ const LOCAL_DEFAULT_CONFIG = {
29
+ llmRequestLogs: {
30
+ readSource: "local",
31
+ clickhouse: {
32
+ database: "default",
33
+ table: "llm_request_logs",
34
+ user: "default",
35
+ },
36
+ },
37
+ };
38
+ let currentConfig: unknown = LOCAL_DEFAULT_CONFIG;
39
+ mock.module("../config/loader.js", () => ({
40
+ getConfig: () => currentConfig,
41
+ }));
42
+
43
+ // Bun's `mock.module()` persists process-wide; reset to the safe local
44
+ // default after this file runs so other test files that touch this module
45
+ // (or transitively call `getConfig()` through the factory) don't pick up
46
+ // a stale `readSource=clickhouse` value. Also drop the factory's internal
47
+ // cache so the next caller resolves fresh against the reset config.
48
+ afterAll(() => {
49
+ currentConfig = LOCAL_DEFAULT_CONFIG;
50
+ invalidateLlmRequestLogSourceCache();
51
+ });
52
+
53
+ import {
54
+ getLlmRequestLogSource,
55
+ invalidateLlmRequestLogSourceCache,
56
+ } from "../memory/llm-request-log-source.js";
57
+ import { ClickHouseLlmRequestLogSource } from "../memory/llm-request-log-source-clickhouse.js";
58
+ import { LocalLlmRequestLogSource } from "../memory/llm-request-log-source-local.js";
59
+
60
+ describe("getLlmRequestLogSource factory", () => {
61
+ beforeEach(() => {
62
+ invalidateLlmRequestLogSourceCache();
63
+ });
64
+
65
+ test("returns LocalLlmRequestLogSource when readSource is 'local'", async () => {
66
+ currentConfig = {
67
+ llmRequestLogs: {
68
+ readSource: "local",
69
+ clickhouse: { database: "default", table: "llm_request_logs", user: "default" },
70
+ },
71
+ };
72
+ const src = await getLlmRequestLogSource();
73
+ expect(src).toBeInstanceOf(LocalLlmRequestLogSource);
74
+ });
75
+
76
+ test("returns LocalLlmRequestLogSource when llmRequestLogs is undefined (defensive)", async () => {
77
+ currentConfig = {};
78
+ const src = await getLlmRequestLogSource();
79
+ expect(src).toBeInstanceOf(LocalLlmRequestLogSource);
80
+ });
81
+
82
+ test("returns ClickHouseLlmRequestLogSource when readSource is 'clickhouse'", async () => {
83
+ currentConfig = {
84
+ llmRequestLogs: {
85
+ readSource: "clickhouse",
86
+ clickhouse: { database: "default", table: "llm_request_logs", user: "default" },
87
+ },
88
+ };
89
+ const src = await getLlmRequestLogSource();
90
+ expect(src).toBeInstanceOf(ClickHouseLlmRequestLogSource);
91
+ });
92
+
93
+ test("caches the resolved source across calls", async () => {
94
+ currentConfig = {
95
+ llmRequestLogs: {
96
+ readSource: "local",
97
+ clickhouse: { database: "default", table: "llm_request_logs", user: "default" },
98
+ },
99
+ };
100
+ const first = await getLlmRequestLogSource();
101
+ const second = await getLlmRequestLogSource();
102
+ expect(second).toBe(first);
103
+ });
104
+
105
+ test("invalidateLlmRequestLogSourceCache forces a fresh resolution", async () => {
106
+ currentConfig = {
107
+ llmRequestLogs: {
108
+ readSource: "local",
109
+ clickhouse: { database: "default", table: "llm_request_logs", user: "default" },
110
+ },
111
+ };
112
+ const first = await getLlmRequestLogSource();
113
+ invalidateLlmRequestLogSourceCache();
114
+ currentConfig = {
115
+ llmRequestLogs: {
116
+ readSource: "clickhouse",
117
+ clickhouse: { database: "default", table: "llm_request_logs", user: "default" },
118
+ },
119
+ };
120
+ const second = await getLlmRequestLogSource();
121
+ expect(second).not.toBe(first);
122
+ expect(second).toBeInstanceOf(ClickHouseLlmRequestLogSource);
123
+ });
124
+ });
@@ -52,6 +52,50 @@ describe("resolveCallSiteConfig", () => {
52
52
  expect(resolved.maxTokens).toBe(64000);
53
53
  });
54
54
 
55
+ test("model-only call-site override infers provider from known model owner", () => {
56
+ const llm = LLMSchema.parse({
57
+ default: {
58
+ ...fullDefault,
59
+ provider: "openai",
60
+ model: "gpt-5.5",
61
+ },
62
+ profiles: {
63
+ active: { provider: "openai", model: "gpt-5.5" },
64
+ },
65
+ activeProfile: "active",
66
+ callSites: {
67
+ conversationStarters: {
68
+ model: "claude-haiku-4-5-20251001",
69
+ effort: "low",
70
+ },
71
+ },
72
+ });
73
+
74
+ const resolved = resolveCallSiteConfig("conversationStarters", llm);
75
+
76
+ expect(resolved.provider).toBe("anthropic");
77
+ expect(resolved.model).toBe("claude-haiku-4-5-20251001");
78
+ expect(resolved.effort).toBe("low");
79
+ });
80
+
81
+ test("unknown model-only override preserves inherited provider", () => {
82
+ const llm = LLMSchema.parse({
83
+ default: {
84
+ ...fullDefault,
85
+ provider: "openai",
86
+ model: "gpt-5.5",
87
+ },
88
+ callSites: {
89
+ memoryExtraction: { model: "local-custom-model" },
90
+ },
91
+ });
92
+
93
+ const resolved = resolveCallSiteConfig("memoryExtraction", llm);
94
+
95
+ expect(resolved.provider).toBe("openai");
96
+ expect(resolved.model).toBe("local-custom-model");
97
+ });
98
+
55
99
  test("profile field overrides default when call site references it", () => {
56
100
  const llm = LLMSchema.parse({
57
101
  default: fullDefault,
@@ -207,6 +251,7 @@ describe("resolveCallSiteConfig", () => {
207
251
  callSites: {
208
252
  mainAgent: { profile: "nonexistent" },
209
253
  },
254
+ profileSession: { defaultTtlSeconds: 1800, maxTtlSeconds: 43200 },
210
255
  pricingOverrides: [],
211
256
  };
212
257
  expect(() => resolveCallSiteConfig("mainAgent", llm)).toThrow(
@@ -339,6 +384,7 @@ describe("resolveCallSiteConfig", () => {
339
384
  profileOrder: [],
340
385
  callSites: {},
341
386
  activeProfile: "nonexistent",
387
+ profileSession: { defaultTtlSeconds: 1800, maxTtlSeconds: 43200 },
342
388
  pricingOverrides: [],
343
389
  };
344
390
  const resolved = resolveCallSiteConfig("mainAgent", llm);