@vellumai/assistant 0.8.3 → 0.8.5

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 (665) hide show
  1. package/ARCHITECTURE.md +2 -2
  2. package/docker-entrypoint.sh +0 -1
  3. package/docs/browser-use-architecture-phase2.md +1 -1
  4. package/knip.json +2 -1
  5. package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
  6. package/openapi.yaml +1492 -100
  7. package/package.json +1 -1
  8. package/src/__tests__/agent-loop-exit-reason.test.ts +4 -5
  9. package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
  10. package/src/__tests__/agent-loop.test.ts +88 -3
  11. package/src/__tests__/anthropic-provider.test.ts +302 -33
  12. package/src/__tests__/approval-cascade.test.ts +1 -1
  13. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
  14. package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
  15. package/src/__tests__/audit-log-rotation.test.ts +70 -16
  16. package/src/__tests__/background-workers-disk-pressure.test.ts +4 -3
  17. package/src/__tests__/btw-routes.test.ts +2 -3
  18. package/src/__tests__/call-controller.test.ts +0 -1
  19. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  20. package/src/__tests__/channel-delivery-store.test.ts +193 -0
  21. package/src/__tests__/channel-guardian.test.ts +3 -3
  22. package/src/__tests__/channel-reply-delivery.test.ts +284 -5
  23. package/src/__tests__/channel-retry-sweep.test.ts +274 -1
  24. package/src/__tests__/checker.test.ts +6 -15
  25. package/src/__tests__/compaction-events.test.ts +2 -1
  26. package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
  27. package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
  28. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
  29. package/src/__tests__/computer-use-tools.test.ts +2 -4
  30. package/src/__tests__/config-watcher.test.ts +1 -1
  31. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  32. package/src/__tests__/context-token-estimator.test.ts +91 -1
  33. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
  34. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
  35. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +55 -4
  36. package/src/__tests__/conversation-agent-loop-overflow.test.ts +228 -8
  37. package/src/__tests__/conversation-agent-loop.test.ts +188 -129
  38. package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
  39. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
  40. package/src/__tests__/conversation-clean-command.test.ts +137 -0
  41. package/src/__tests__/conversation-clear-safety.test.ts +25 -25
  42. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
  43. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  44. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  45. package/src/__tests__/conversation-error.test.ts +31 -0
  46. package/src/__tests__/conversation-fork-crud.test.ts +324 -0
  47. package/src/__tests__/conversation-lifecycle.test.ts +53 -12
  48. package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
  49. package/src/__tests__/conversation-load-history-stripped.test.ts +279 -0
  50. package/src/__tests__/conversation-pairing.test.ts +2 -2
  51. package/src/__tests__/conversation-process-callsite.test.ts +1 -1
  52. package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -1
  53. package/src/__tests__/conversation-queue.test.ts +1 -1
  54. package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
  55. package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
  56. package/src/__tests__/conversation-runtime-assembly.test.ts +264 -81
  57. package/src/__tests__/conversation-seed-composer.test.ts +66 -4
  58. package/src/__tests__/conversation-skill-tools.test.ts +2 -5
  59. package/src/__tests__/conversation-slash-commands.test.ts +36 -8
  60. package/src/__tests__/conversation-slash-queue.test.ts +1 -1
  61. package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
  62. package/src/__tests__/conversation-speed-override.test.ts +1 -1
  63. package/src/__tests__/conversation-store.test.ts +1 -1
  64. package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
  65. package/src/__tests__/conversation-sync-tags.test.ts +99 -32
  66. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -1
  67. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  68. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  69. package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
  70. package/src/__tests__/credential-execution-tools.test.ts +6 -6
  71. package/src/__tests__/credential-security-invariants.test.ts +7 -0
  72. package/src/__tests__/credential-vault-unit.test.ts +2 -2
  73. package/src/__tests__/cu-unified-flow.test.ts +10 -1
  74. package/src/__tests__/dm-backfill.test.ts +64 -0
  75. package/src/__tests__/dm-persistence.test.ts +33 -0
  76. package/src/__tests__/document-find-replace.test.ts +501 -0
  77. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  78. package/src/__tests__/email-html-renderer.test.ts +12 -0
  79. package/src/__tests__/first-greeting.test.ts +23 -2
  80. package/src/__tests__/gateway-flag-listener.test.ts +237 -0
  81. package/src/__tests__/gemini-provider.test.ts +78 -0
  82. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  83. package/src/__tests__/guardian-outbound-http.test.ts +7 -5
  84. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  85. package/src/__tests__/headless-browser-navigate.test.ts +172 -0
  86. package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
  87. package/src/__tests__/heartbeat-service.test.ts +4 -0
  88. package/src/__tests__/host-bash-proxy.test.ts +6 -0
  89. package/src/__tests__/host-browser-proxy.test.ts +10 -0
  90. package/src/__tests__/host-cu-proxy.test.ts +8 -1
  91. package/src/__tests__/host-file-proxy.test.ts +8 -1
  92. package/src/__tests__/host-shell-tool.test.ts +1 -1
  93. package/src/__tests__/host-transfer-proxy.test.ts +8 -1
  94. package/src/__tests__/identity-routes.test.ts +57 -0
  95. package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
  96. package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
  97. package/src/__tests__/injector-chain.test.ts +2 -0
  98. package/src/__tests__/injector-document-comments.test.ts +378 -0
  99. package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
  100. package/src/__tests__/list-messages-attachments.test.ts +21 -17
  101. package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
  102. package/src/__tests__/list-messages-page-latest.test.ts +130 -14
  103. package/src/__tests__/list-messages-tool-merge.test.ts +77 -17
  104. package/src/__tests__/llm-context-normalization.test.ts +0 -2
  105. package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
  106. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
  107. package/src/__tests__/llm-resolver.test.ts +161 -9
  108. package/src/__tests__/llm-usage-store.test.ts +66 -0
  109. package/src/__tests__/log-export-routes.test.ts +99 -2
  110. package/src/__tests__/logger.test.ts +89 -0
  111. package/src/__tests__/mcp-abort-signal.test.ts +2 -2
  112. package/src/__tests__/media-generate-image.test.ts +31 -0
  113. package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
  114. package/src/__tests__/message-queue-steer.test.ts +114 -0
  115. package/src/__tests__/model-intents.test.ts +2 -4
  116. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  117. package/src/__tests__/onboarding-template-contract.test.ts +1 -1
  118. package/src/__tests__/openai-provider.test.ts +151 -0
  119. package/src/__tests__/openai-responses-provider.test.ts +118 -16
  120. package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
  121. package/src/__tests__/pending-interactions-resolved-event.test.ts +189 -0
  122. package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
  123. package/src/__tests__/platform.test.ts +2 -5
  124. package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
  125. package/src/__tests__/plugin-bootstrap.test.ts +2 -2
  126. package/src/__tests__/plugin-source-watcher.test.ts +302 -0
  127. package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
  128. package/src/__tests__/plugin-types.test.ts +3 -2
  129. package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
  130. package/src/__tests__/pricing.test.ts +12 -0
  131. package/src/__tests__/process-message-background-slack.test.ts +1 -51
  132. package/src/__tests__/process-message-display-content.test.ts +21 -16
  133. package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
  134. package/src/__tests__/registry.test.ts +2 -8
  135. package/src/__tests__/require-fresh-approval.test.ts +2 -2
  136. package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
  137. package/src/__tests__/server-history-render.test.ts +83 -4
  138. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  139. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  140. package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
  141. package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
  142. package/src/__tests__/skill-tool-factory.test.ts +1 -1
  143. package/src/__tests__/steer-tool-repair.test.ts +249 -0
  144. package/src/__tests__/subagent-notify-parent.test.ts +1 -1
  145. package/src/__tests__/suggestion-routes.test.ts +1 -0
  146. package/src/__tests__/sync-message-contract.test.ts +59 -0
  147. package/src/__tests__/system-prompt.test.ts +161 -124
  148. package/src/__tests__/terminal-tools.test.ts +12 -2
  149. package/src/__tests__/thinking-block-replay.test.ts +113 -0
  150. package/src/__tests__/thread-backfill.test.ts +370 -22
  151. package/src/__tests__/tool-approval-handler.test.ts +1 -5
  152. package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
  153. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
  154. package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
  155. package/src/__tests__/tool-executor.test.ts +89 -53
  156. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
  157. package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
  158. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  159. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
  160. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  161. package/src/__tests__/twilio-routes.test.ts +1 -1
  162. package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
  163. package/src/__tests__/usage-routes.test.ts +3 -0
  164. package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
  165. package/src/__tests__/web-fetch.test.ts +2 -2
  166. package/src/__tests__/workspace-git-service.test.ts +94 -10
  167. package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
  168. package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
  169. package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
  170. package/src/acp/prepare-agent-env.ts +78 -0
  171. package/src/acp/session-manager.ts +1 -1
  172. package/src/agent/attachments.ts +1 -0
  173. package/src/agent/loop.ts +65 -20
  174. package/src/api/README.md +5 -0
  175. package/src/api/index.ts +4 -0
  176. package/src/api/package.json +10 -0
  177. package/src/background-wake/background-wake-routes.test.ts +233 -0
  178. package/src/background-wake/next-wake.test.ts +289 -0
  179. package/src/background-wake/next-wake.ts +172 -0
  180. package/src/background-wake/runtime-registry.ts +24 -0
  181. package/src/browser/operations.ts +15 -0
  182. package/src/cli/commands/__tests__/browser.test.ts +23 -5
  183. package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
  184. package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
  185. package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
  186. package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
  187. package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
  188. package/src/cli/commands/__tests__/memory-v2.test.ts +10 -12
  189. package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
  190. package/src/cli/commands/browser.ts +247 -0
  191. package/src/cli/commands/conversations.ts +128 -1
  192. package/src/cli/commands/domain.ts +91 -41
  193. package/src/cli/commands/inference-providers.ts +147 -1
  194. package/src/cli/commands/inference.ts +93 -40
  195. package/src/cli/commands/memory-v2-compare-render.ts +115 -0
  196. package/src/cli/commands/memory-v2.ts +483 -0
  197. package/src/cli/commands/memory-v3-render.ts +344 -0
  198. package/src/cli/commands/memory-v3.ts +316 -0
  199. package/src/cli/commands/notifications.ts +24 -2
  200. package/src/cli/program.ts +2 -0
  201. package/src/cli/utils/conversation-id.ts +17 -5
  202. package/src/config/assistant-feature-flags.ts +21 -9
  203. package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
  204. package/src/config/bundled-skills/document-editor/SKILL.md +124 -0
  205. package/src/config/bundled-skills/document-editor/TOOLS.json +258 -0
  206. package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
  207. package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
  208. package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
  209. package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
  210. package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
  211. package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
  212. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  213. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
  214. package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
  215. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
  216. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
  217. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
  218. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
  219. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
  220. package/src/config/bundled-skills/schedule/SKILL.md +8 -0
  221. package/src/config/bundled-tool-registry.ts +24 -12
  222. package/src/config/call-site-defaults.ts +20 -0
  223. package/src/config/feature-flag-registry.json +115 -3
  224. package/src/config/llm-resolver.ts +16 -2
  225. package/src/config/schemas/__tests__/memory-v2.test.ts +217 -1
  226. package/src/config/schemas/call-site-catalog.ts +35 -0
  227. package/src/config/schemas/llm.ts +14 -0
  228. package/src/config/schemas/memory-v2.ts +294 -1
  229. package/src/config/schemas/memory.ts +2 -1
  230. package/src/context/compactor.ts +60 -1
  231. package/src/context/token-estimator.ts +47 -4
  232. package/src/context/window-manager.ts +25 -0
  233. package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
  234. package/src/conversations/message-consolidation.ts +404 -0
  235. package/src/credential-health/credential-health-service.ts +34 -19
  236. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
  237. package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
  238. package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
  239. package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
  240. package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
  241. package/src/daemon/conversation-agent-loop-handlers.ts +155 -36
  242. package/src/daemon/conversation-agent-loop.ts +307 -88
  243. package/src/daemon/conversation-error.ts +31 -1
  244. package/src/daemon/conversation-lifecycle.ts +149 -118
  245. package/src/daemon/conversation-messaging.ts +3 -0
  246. package/src/daemon/conversation-process.ts +273 -0
  247. package/src/daemon/conversation-queue-manager.ts +14 -0
  248. package/src/daemon/conversation-runtime-assembly.ts +145 -84
  249. package/src/daemon/conversation-slash.ts +37 -5
  250. package/src/daemon/conversation-surfaces.ts +45 -2
  251. package/src/daemon/conversation-tool-setup.ts +70 -3
  252. package/src/daemon/conversation-usage.ts +2 -0
  253. package/src/daemon/conversation.ts +54 -32
  254. package/src/daemon/disk-pressure-guard.ts +14 -2
  255. package/src/daemon/first-greeting.ts +10 -0
  256. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
  257. package/src/daemon/handlers/config-a2a.ts +160 -0
  258. package/src/daemon/handlers/config-model.test.ts +2 -0
  259. package/src/daemon/handlers/conversations.ts +90 -3
  260. package/src/daemon/handlers/shared.ts +92 -29
  261. package/src/daemon/host-bash-proxy.ts +1 -1
  262. package/src/daemon/host-browser-proxy.ts +5 -5
  263. package/src/daemon/host-cu-proxy.ts +5 -5
  264. package/src/daemon/host-file-proxy.ts +5 -5
  265. package/src/daemon/host-proxy-base.ts +4 -4
  266. package/src/daemon/host-transfer-proxy.ts +11 -11
  267. package/src/daemon/lifecycle.ts +40 -23
  268. package/src/daemon/meet-manifest-loader.ts +1 -7
  269. package/src/daemon/message-protocol.ts +4 -0
  270. package/src/daemon/message-types/conversations.ts +14 -9
  271. package/src/daemon/message-types/document-comments.ts +50 -0
  272. package/src/daemon/message-types/home.ts +1 -13
  273. package/src/daemon/message-types/messages.ts +66 -7
  274. package/src/daemon/message-types/surfaces.ts +3 -1
  275. package/src/daemon/message-types/sync.ts +14 -0
  276. package/src/daemon/message-types/web-activity.ts +57 -0
  277. package/src/daemon/plugin-source-watcher.ts +135 -3
  278. package/src/daemon/process-message.ts +69 -12
  279. package/src/daemon/shutdown-handlers.ts +24 -5
  280. package/src/daemon/switch-inference-profile-tool.ts +52 -0
  281. package/src/daemon/tool-setup-types.ts +13 -0
  282. package/src/daemon/trust-context.ts +6 -0
  283. package/src/documents/document-comments-store.test.ts +338 -0
  284. package/src/documents/document-comments-store.ts +237 -0
  285. package/src/documents/document-store.ts +202 -0
  286. package/src/events/relationship-state-updated.ts +25 -0
  287. package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -2
  288. package/src/heartbeat/heartbeat-service.ts +1 -0
  289. package/src/home/__tests__/suggested-prompts.test.ts +33 -2
  290. package/src/home/feed-types.ts +6 -1
  291. package/src/home/home-content-refresh.ts +52 -0
  292. package/src/home/home-greeting-cache.ts +69 -0
  293. package/src/home/home-greeting.ts +85 -0
  294. package/src/home/suggested-prompts.ts +168 -9
  295. package/src/ipc/gateway-flag-listener.ts +123 -0
  296. package/src/ipc/skill-routes/registries.ts +8 -12
  297. package/src/memory/__tests__/db-async-query.test.ts +165 -0
  298. package/src/memory/__tests__/db-maintenance.test.ts +115 -0
  299. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
  300. package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
  301. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
  302. package/src/memory/__tests__/memory-retrospective-job.test.ts +327 -6
  303. package/src/memory/auto-analysis-enqueue.ts +5 -1
  304. package/src/memory/conversation-crud.ts +191 -100
  305. package/src/memory/conversation-starters-cadence.ts +3 -1
  306. package/src/memory/conversation-title-service.ts +19 -3
  307. package/src/memory/db-async-query.ts +214 -0
  308. package/src/memory/db-init.ts +26 -0
  309. package/src/memory/db-maintenance.ts +30 -21
  310. package/src/memory/delivery-crud.ts +41 -0
  311. package/src/memory/delivery-status.ts +141 -15
  312. package/src/memory/external-conversation-store.ts +32 -1
  313. package/src/memory/graph/bootstrap.ts +8 -1
  314. package/src/memory/graph/capability-seed.ts +7 -3
  315. package/src/memory/graph/conversation-graph-memory.ts +100 -17
  316. package/src/memory/graph/extraction.ts +1 -5
  317. package/src/memory/graph/graph-search.ts +7 -1
  318. package/src/memory/indexer.ts +28 -18
  319. package/src/memory/job-handlers/cleanup.ts +76 -18
  320. package/src/memory/job-handlers/conversation-starters.ts +1 -4
  321. package/src/memory/jobs/embed-pkb-file.ts +6 -1
  322. package/src/memory/jobs-store.ts +14 -0
  323. package/src/memory/jobs-worker.ts +68 -15
  324. package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
  325. package/src/memory/llm-request-log-source-local.ts +7 -0
  326. package/src/memory/llm-request-log-source.ts +9 -2
  327. package/src/memory/llm-request-log-store.ts +43 -1
  328. package/src/memory/llm-usage-store.ts +24 -0
  329. package/src/memory/memory-retrospective-constants.ts +28 -0
  330. package/src/memory/memory-retrospective-enqueue.ts +11 -3
  331. package/src/memory/memory-retrospective-job.ts +413 -18
  332. package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
  333. package/src/memory/memory-v2-activation-log-store.ts +41 -14
  334. package/src/memory/migrations/100-core-tables.ts +1 -0
  335. package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
  336. package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
  337. package/src/memory/migrations/253-document-comments.ts +47 -0
  338. package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
  339. package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
  340. package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
  341. package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
  342. package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
  343. package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
  344. package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
  345. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
  346. package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
  347. package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
  348. package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
  349. package/src/memory/migrations/index.ts +34 -0
  350. package/src/memory/migrations/registry.ts +58 -0
  351. package/src/memory/onboarding-events-store.ts +7 -0
  352. package/src/memory/schema/calls.ts +1 -0
  353. package/src/memory/schema/conversations.ts +3 -0
  354. package/src/memory/schema/infrastructure.ts +22 -0
  355. package/src/memory/tool-usage-store.ts +36 -8
  356. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
  357. package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
  358. package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
  359. package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
  360. package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
  361. package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
  362. package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
  363. package/src/memory/v2/__tests__/injection.test.ts +158 -112
  364. package/src/memory/v2/__tests__/page-index.test.ts +365 -1
  365. package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
  366. package/src/memory/v2/__tests__/router.test.ts +660 -4
  367. package/src/memory/v2/consolidation-job.ts +14 -0
  368. package/src/memory/v2/harness/compare.ts +57 -0
  369. package/src/memory/v2/harness/metrics.ts +124 -0
  370. package/src/memory/v2/harness/oracle.ts +145 -0
  371. package/src/memory/v2/harness/replay-input.ts +224 -0
  372. package/src/memory/v2/harness/retriever.ts +74 -0
  373. package/src/memory/v2/harness/router-retriever.ts +43 -0
  374. package/src/memory/v2/harness/runner.ts +106 -0
  375. package/src/memory/v2/harness/trace.ts +58 -0
  376. package/src/memory/v2/injection-events.ts +101 -0
  377. package/src/memory/v2/injection.ts +42 -25
  378. package/src/memory/v2/page-index.ts +209 -7
  379. package/src/memory/v2/page-store.ts +18 -0
  380. package/src/memory/v2/prompts/router.ts +26 -1
  381. package/src/memory/v2/qdrant.ts +14 -2
  382. package/src/memory/v2/router.ts +369 -62
  383. package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
  384. package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
  385. package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
  386. package/src/memory/v3/__tests__/edges.test.ts +563 -0
  387. package/src/memory/v3/__tests__/filter.test.ts +512 -0
  388. package/src/memory/v3/__tests__/gate.test.ts +574 -0
  389. package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
  390. package/src/memory/v3/__tests__/loop.test.ts +530 -0
  391. package/src/memory/v3/__tests__/retriever.test.ts +226 -0
  392. package/src/memory/v3/__tests__/scouts.test.ts +440 -0
  393. package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
  394. package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
  395. package/src/memory/v3/__tests__/traversal.test.ts +469 -0
  396. package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
  397. package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
  398. package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
  399. package/src/memory/v3/__tests__/validate.test.ts +245 -0
  400. package/src/memory/v3/auto-edges.ts +223 -0
  401. package/src/memory/v3/coactivation-store.ts +124 -0
  402. package/src/memory/v3/consolidation-job.ts +323 -0
  403. package/src/memory/v3/edge-learning-job.ts +160 -0
  404. package/src/memory/v3/edges.ts +249 -0
  405. package/src/memory/v3/filter.ts +281 -0
  406. package/src/memory/v3/gate.ts +334 -0
  407. package/src/memory/v3/index-composition.ts +113 -0
  408. package/src/memory/v3/llm-capture.ts +46 -0
  409. package/src/memory/v3/loop.ts +382 -0
  410. package/src/memory/v3/maintenance.ts +144 -0
  411. package/src/memory/v3/prompt-context.ts +33 -0
  412. package/src/memory/v3/prompts/consolidation.ts +458 -0
  413. package/src/memory/v3/prompts/system-prompts.ts +196 -0
  414. package/src/memory/v3/retriever.ts +33 -0
  415. package/src/memory/v3/scouts.ts +420 -0
  416. package/src/memory/v3/shadow-middleware.ts +305 -0
  417. package/src/memory/v3/traversal.ts +206 -0
  418. package/src/memory/v3/tree-index.ts +237 -0
  419. package/src/memory/v3/tree-store.ts +394 -0
  420. package/src/memory/v3/tree-walk.ts +351 -0
  421. package/src/memory/v3/types.ts +65 -0
  422. package/src/memory/v3/validate.ts +300 -0
  423. package/src/messaging/providers/index.ts +7 -1
  424. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
  425. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
  426. package/src/messaging/providers/slack/adapter.ts +178 -25
  427. package/src/messaging/providers/slack/api.test.ts +54 -0
  428. package/src/messaging/providers/slack/api.ts +119 -3
  429. package/src/messaging/providers/slack/client.ts +12 -0
  430. package/src/messaging/providers/slack/deep-link.ts +20 -1
  431. package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
  432. package/src/messaging/providers/slack/message-metadata.ts +156 -0
  433. package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
  434. package/src/messaging/providers/slack/render-transcript.ts +176 -49
  435. package/src/messaging/providers/slack/send.test.ts +77 -0
  436. package/src/messaging/providers/slack/send.ts +8 -2
  437. package/src/messaging/providers/slack/types.ts +14 -0
  438. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +4 -1
  439. package/src/notifications/__tests__/home-feed-side-effect.test.ts +116 -54
  440. package/src/notifications/adapters/macos.ts +18 -1
  441. package/src/notifications/adapters/platform.ts +1 -1
  442. package/src/notifications/conversation-seed-composer.ts +14 -2
  443. package/src/notifications/decision-engine.ts +1 -4
  444. package/src/notifications/deferred-emit.ts +135 -0
  445. package/src/notifications/emit-signal.ts +38 -50
  446. package/src/notifications/home-feed-side-effect.ts +60 -30
  447. package/src/oauth/connect-orchestrator.ts +3 -0
  448. package/src/oauth/credential-token-resolver.ts +2 -0
  449. package/src/oauth/manual-token-connection.ts +19 -0
  450. package/src/oauth/oauth-store.ts +12 -0
  451. package/src/oauth/seed-providers.ts +22 -0
  452. package/src/permissions/prompter.ts +8 -5
  453. package/src/permissions/question-prompter.ts +5 -2
  454. package/src/permissions/secret-prompter.ts +6 -3
  455. package/src/plugin-api/index.ts +4 -0
  456. package/src/plugin-api/types.ts +7 -33
  457. package/src/plugins/defaults/index.ts +6 -0
  458. package/src/plugins/defaults/injectors.ts +100 -20
  459. package/src/plugins/external-plugin-loader.ts +5 -68
  460. package/src/plugins/types.ts +11 -16
  461. package/src/proactive-artifact/aux-message-injector.ts +17 -4
  462. package/src/prompts/__tests__/system-prompt.test.ts +46 -2
  463. package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
  464. package/src/prompts/normalize-onboarding.ts +40 -0
  465. package/src/prompts/persona-resolver.ts +36 -21
  466. package/src/prompts/sections.ts +69 -19
  467. package/src/prompts/system-prompt.ts +118 -216
  468. package/src/prompts/template-detection.ts +37 -0
  469. package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
  470. package/src/prompts/templates/BOOTSTRAP.md +10 -2
  471. package/src/prompts/templates/VOICE.md +3 -0
  472. package/src/prompts/templates/system-sections.ts +281 -9
  473. package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
  474. package/src/providers/__tests__/retry-callsite.test.ts +85 -5
  475. package/src/providers/anthropic/client.ts +159 -66
  476. package/src/providers/call-site-routing.ts +14 -2
  477. package/src/providers/connection-model-compat.ts +38 -0
  478. package/src/providers/connection-resolution.ts +16 -2
  479. package/src/providers/fireworks/client.ts +20 -2
  480. package/src/providers/gemini/client.ts +49 -6
  481. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
  482. package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
  483. package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
  484. package/src/providers/inference/adapter-factory.ts +18 -1
  485. package/src/providers/inference/auth.ts +3 -3
  486. package/src/providers/inference/codex-token-refresh.ts +128 -0
  487. package/src/providers/inference/resolve-auth.ts +49 -6
  488. package/src/providers/minimax/client.ts +106 -0
  489. package/src/providers/model-catalog.ts +91 -1
  490. package/src/providers/model-intents.ts +1 -1
  491. package/src/providers/openai/chat-completions-provider.ts +63 -23
  492. package/src/providers/openai/codex-models.ts +18 -0
  493. package/src/providers/openai/responses-provider.ts +86 -23
  494. package/src/providers/openrouter/client.ts +5 -1
  495. package/src/providers/provider-send-message.ts +7 -1
  496. package/src/providers/retry.ts +34 -3
  497. package/src/providers/thinking-config.ts +26 -1
  498. package/src/providers/types.ts +25 -0
  499. package/src/providers/usage-tracking.ts +2 -0
  500. package/src/runtime/AGENTS.md +2 -2
  501. package/src/runtime/__tests__/agent-wake.test.ts +214 -0
  502. package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
  503. package/src/runtime/agent-wake.ts +152 -56
  504. package/src/runtime/assistant-event-hub.ts +76 -6
  505. package/src/runtime/auth/route-policy.ts +43 -3
  506. package/src/runtime/background-job-runner.ts +26 -0
  507. package/src/runtime/btw-sidechain.ts +0 -6
  508. package/src/runtime/channel-reply-delivery.ts +182 -47
  509. package/src/runtime/channel-retry-sweep.ts +141 -16
  510. package/src/runtime/http-types.ts +7 -6
  511. package/src/runtime/migrations/vbundle-builder.ts +10 -3
  512. package/src/runtime/pending-interactions.ts +50 -8
  513. package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
  514. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +161 -1
  515. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
  516. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +290 -0
  517. package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
  518. package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
  519. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
  520. package/src/runtime/routes/acp-routes.test.ts +255 -6
  521. package/src/runtime/routes/acp-routes.ts +8 -1
  522. package/src/runtime/routes/approval-routes.ts +4 -1
  523. package/src/runtime/routes/avatar-routes.ts +10 -10
  524. package/src/runtime/routes/background-wake-routes.ts +188 -0
  525. package/src/runtime/routes/browser-tabs-routes.ts +200 -0
  526. package/src/runtime/routes/btw-routes.ts +0 -6
  527. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
  528. package/src/runtime/routes/content-source-routes.ts +78 -0
  529. package/src/runtime/routes/conversation-cli-routes.ts +147 -2
  530. package/src/runtime/routes/conversation-list-routes.ts +12 -4
  531. package/src/runtime/routes/conversation-management-routes.ts +77 -20
  532. package/src/runtime/routes/conversation-query-routes.ts +196 -31
  533. package/src/runtime/routes/conversation-routes.ts +472 -425
  534. package/src/runtime/routes/conversation-starter-routes.ts +6 -3
  535. package/src/runtime/routes/disk-pressure-routes.ts +1 -1
  536. package/src/runtime/routes/document-comments-routes.ts +287 -0
  537. package/src/runtime/routes/documents-routes.ts +33 -0
  538. package/src/runtime/routes/domain-routes.ts +60 -10
  539. package/src/runtime/routes/email-routes.ts +5 -2
  540. package/src/runtime/routes/events-routes.ts +54 -10
  541. package/src/runtime/routes/group-routes.ts +24 -8
  542. package/src/runtime/routes/home-feed-routes.ts +6 -3
  543. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  544. package/src/runtime/routes/host-browser-routes.ts +17 -2
  545. package/src/runtime/routes/host-cu-routes.ts +2 -2
  546. package/src/runtime/routes/identity-routes.ts +21 -0
  547. package/src/runtime/routes/inbound-message-handler.ts +288 -58
  548. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
  549. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
  550. package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
  551. package/src/runtime/routes/index.ts +20 -4
  552. package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
  553. package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
  554. package/src/runtime/routes/inference-provider-connection-routes.ts +63 -7
  555. package/src/runtime/routes/integrations/a2a.ts +60 -1
  556. package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
  557. package/src/runtime/routes/log-export-routes.ts +39 -0
  558. package/src/runtime/routes/memory-item-routes.ts +8 -3
  559. package/src/runtime/routes/memory-v2-routes.ts +427 -0
  560. package/src/runtime/routes/memory-v3-routes.ts +316 -0
  561. package/src/runtime/routes/migration-routes.ts +21 -24
  562. package/src/runtime/routes/notification-routes.ts +19 -2
  563. package/src/runtime/routes/plugins-routes.ts +337 -0
  564. package/src/runtime/routes/question-routes.ts +4 -1
  565. package/src/runtime/routes/rename-conversation-routes.ts +6 -2
  566. package/src/runtime/routes/sanity-routes.ts +159 -0
  567. package/src/runtime/routes/secret-routes.ts +25 -5
  568. package/src/runtime/routes/settings-routes.ts +12 -11
  569. package/src/runtime/routes/slack-channel-routes.ts +188 -0
  570. package/src/runtime/routes/workspace-routes.ts +25 -10
  571. package/src/runtime/services/conversation-serializer.ts +30 -4
  572. package/src/runtime/sync/resource-sync-events.ts +106 -38
  573. package/src/runtime/sync/sync-publisher.test.ts +49 -0
  574. package/src/runtime/sync/sync-publisher.ts +2 -1
  575. package/src/runtime/verification-outbound-actions.ts +73 -1
  576. package/src/schedule/integration-status.ts +3 -1
  577. package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
  578. package/src/security/oauth2-device-code.ts +307 -0
  579. package/src/security/oauth2.ts +26 -9
  580. package/src/security/secure-keys.ts +5 -0
  581. package/src/skills/catalog-install.ts +6 -2
  582. package/src/telemetry/types.ts +12 -0
  583. package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
  584. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  585. package/src/tools/acp/spawn.test.ts +119 -0
  586. package/src/tools/acp/spawn.ts +15 -2
  587. package/src/tools/apps/definitions.ts +2 -8
  588. package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
  589. package/src/tools/ask-question/ask-question-tool.ts +38 -45
  590. package/src/tools/browser/__tests__/pinned-tabs.test.ts +150 -0
  591. package/src/tools/browser/browser-execution.ts +106 -0
  592. package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
  593. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
  594. package/src/tools/browser/cdp-client/__tests__/types.test.ts +4 -0
  595. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +22 -0
  596. package/src/tools/browser/cdp-client/extension-cdp-client.ts +42 -2
  597. package/src/tools/browser/cdp-client/factory.ts +171 -4
  598. package/src/tools/browser/cdp-client/local-cdp-client.ts +21 -0
  599. package/src/tools/browser/cdp-client/types.ts +101 -0
  600. package/src/tools/browser/pinned-tabs.ts +146 -0
  601. package/src/tools/computer-use/definitions.ts +22 -78
  602. package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
  603. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
  604. package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
  605. package/src/tools/credentials/vault.ts +3 -9
  606. package/src/tools/document/document-comment-tool.test.ts +379 -0
  607. package/src/tools/document/document-comment-tool.ts +156 -0
  608. package/src/tools/document/document-tool.ts +187 -2
  609. package/src/tools/execution-target.ts +21 -23
  610. package/src/tools/executor.ts +6 -1
  611. package/src/tools/filesystem/edit.ts +3 -9
  612. package/src/tools/filesystem/list.ts +3 -9
  613. package/src/tools/filesystem/read.ts +3 -9
  614. package/src/tools/filesystem/write.ts +3 -9
  615. package/src/tools/host-filesystem/edit.ts +3 -9
  616. package/src/tools/host-filesystem/read.ts +3 -9
  617. package/src/tools/host-filesystem/transfer.ts +3 -9
  618. package/src/tools/host-filesystem/write.ts +3 -9
  619. package/src/tools/host-terminal/host-shell.ts +3 -9
  620. package/src/tools/mcp/mcp-tool-factory.ts +1 -8
  621. package/src/tools/memory/register.test.ts +1 -1
  622. package/src/tools/memory/register.ts +4 -9
  623. package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
  624. package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
  625. package/src/tools/network/domain-normalize.ts +17 -0
  626. package/src/tools/network/web-fetch.ts +216 -73
  627. package/src/tools/network/web-search.ts +216 -98
  628. package/src/tools/registry.ts +7 -23
  629. package/src/tools/schema-transforms.ts +1 -1
  630. package/src/tools/skills/execute.ts +3 -9
  631. package/src/tools/skills/load.ts +3 -9
  632. package/src/tools/skills/skill-tool-factory.ts +1 -8
  633. package/src/tools/subagent/notify-parent.ts +3 -9
  634. package/src/tools/system/request-permission.ts +3 -9
  635. package/src/tools/terminal/safe-env.ts +3 -2
  636. package/src/tools/terminal/shell.ts +3 -9
  637. package/src/tools/tool-approval-handler.ts +19 -12
  638. package/src/tools/tool-defaults.ts +94 -0
  639. package/src/tools/types.ts +31 -98
  640. package/src/tools/ui-surface/definitions.ts +9 -23
  641. package/src/types/onboarding-context.ts +4 -0
  642. package/src/usage/pricing.ts +23 -0
  643. package/src/usage/types.ts +12 -0
  644. package/src/util/__tests__/favicon.test.ts +84 -0
  645. package/src/util/favicon.ts +40 -0
  646. package/src/util/logger.ts +16 -7
  647. package/src/util/platform.ts +7 -7
  648. package/src/util/sqlite3-runtime.ts +65 -0
  649. package/src/workspace/git-service.ts +75 -4
  650. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
  651. package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
  652. package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
  653. package/src/workspace/migrations/registry.ts +4 -0
  654. package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
  655. package/src/__tests__/message-complete-display-id.test.ts +0 -175
  656. package/src/config/bundled-skills/document/SKILL.md +0 -54
  657. package/src/config/bundled-skills/document/TOOLS.json +0 -106
  658. package/src/daemon/seed-files.ts +0 -18
  659. package/src/prompts/cache-boundary.ts +0 -8
  660. package/src/runtime/routes/interface-routes.ts +0 -43
  661. /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
  662. /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
  663. /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
  664. /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
  665. /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
@@ -91,7 +91,7 @@ describe("handleListMessages tool_result merging", () => {
91
91
  ]),
92
92
  );
93
93
 
94
- const response = handleListMessages(createTestArgs(conv.id), null);
94
+ const response = handleListMessages(createTestArgs(conv.id));
95
95
  const body = response as { messages: MessagePayload[] };
96
96
 
97
97
  // Should be 2 messages: user prompt + assistant (tool_result user msg suppressed)
@@ -137,7 +137,7 @@ describe("handleListMessages tool_result merging", () => {
137
137
  ]),
138
138
  );
139
139
 
140
- const response = handleListMessages(createTestArgs(conv.id), null);
140
+ const response = handleListMessages(createTestArgs(conv.id));
141
141
  const body = response as { messages: MessagePayload[] };
142
142
 
143
143
  expect(body.messages).toHaveLength(2);
@@ -167,7 +167,7 @@ describe("handleListMessages tool_result merging", () => {
167
167
  JSON.stringify([{ type: "text", text: "how are you?" }]),
168
168
  );
169
169
 
170
- const response = handleListMessages(createTestArgs(conv.id), null);
170
+ const response = handleListMessages(createTestArgs(conv.id));
171
171
  const body = response as { messages: MessagePayload[] };
172
172
 
173
173
  expect(body.messages).toHaveLength(3);
@@ -175,11 +175,13 @@ describe("handleListMessages tool_result merging", () => {
175
175
  expect(body.messages[2].content).toBe("how are you?");
176
176
  });
177
177
 
178
- test("tool_result at start of array (no preceding assistant) is preserved", async () => {
178
+ test("orphan tool_result at pagination boundary is suppressed entirely", async () => {
179
179
  const conv = createConversation();
180
- // Orphan tool_result with no preceding assistant (pagination boundary).
181
- // The preceding assistant tool_use lives in the previous page dropping
182
- // the result would be unrecoverable, so it is kept as-is.
180
+ // Orphan tool_result with no preceding assistant in this page. The
181
+ // matching tool_use lives on the previous page, so renderHistoryContent
182
+ // would silently drop the orphan downstream and leave a blank user
183
+ // bubble. The merger now suppresses the user row outright at the
184
+ // boundary to prevent that blank bubble from reaching the client.
183
185
  await addMessage(
184
186
  conv.id,
185
187
  "user",
@@ -197,19 +199,77 @@ describe("handleListMessages tool_result merging", () => {
197
199
  JSON.stringify([{ type: "text", text: "response" }]),
198
200
  );
199
201
 
200
- const response = handleListMessages(createTestArgs(conv.id), null);
202
+ const response = handleListMessages(createTestArgs(conv.id));
203
+ const body = response as { messages: MessagePayload[] };
204
+
205
+ // User row dropped entirely; only the assistant survives.
206
+ expect(body.messages).toHaveLength(1);
207
+ expect(body.messages[0].role).toBe("assistant");
208
+ expect(body.messages[0].content).toBe("response");
209
+ });
210
+
211
+ test("mixed content at pagination boundary keeps real user text", async () => {
212
+ const conv = createConversation();
213
+ // Row has both real user text AND an orphan tool_result. The orphan
214
+ // gets stripped (it'd be dropped by renderHistoryContent anyway), but
215
+ // the user text is preserved.
216
+ await addMessage(
217
+ conv.id,
218
+ "user",
219
+ JSON.stringify([
220
+ {
221
+ type: "tool_result",
222
+ tool_use_id: "tu_orphan",
223
+ content: "stale result",
224
+ },
225
+ { type: "text", text: "what about this?" },
226
+ ]),
227
+ );
228
+ await addMessage(
229
+ conv.id,
230
+ "assistant",
231
+ JSON.stringify([{ type: "text", text: "answering" }]),
232
+ );
233
+
234
+ const response = handleListMessages(createTestArgs(conv.id));
201
235
  const body = response as { messages: MessagePayload[] };
202
236
 
203
- // Orphan tool_result is preserved (not suppressed) to avoid data loss
204
237
  expect(body.messages).toHaveLength(2);
205
238
  expect(body.messages[0].role).toBe("user");
206
- // The preserved message must retain the actual tool_result payload
207
- const orphanToolCalls = body.messages[0].toolCalls;
208
- expect(orphanToolCalls).toBeDefined();
209
- expect(orphanToolCalls).toHaveLength(1);
210
- expect(orphanToolCalls![0].result).toBe("stale result");
239
+ expect(body.messages[0].content).toBe("what about this?");
240
+ expect(body.messages[0].toolCalls).toBeUndefined();
211
241
  expect(body.messages[1].role).toBe("assistant");
212
- expect(body.messages[1].content).toBe("response");
242
+ expect(body.messages[1].content).toBe("answering");
243
+ });
244
+
245
+ test("orphan tool_result + system_notice at boundary is suppressed", async () => {
246
+ const conv = createConversation();
247
+ // System notices ride alongside tool_results in the agent loop. At a
248
+ // boundary they shouldn't keep the row alive on their own — the row
249
+ // is still semantically tool-result-only from the user's perspective.
250
+ await addMessage(
251
+ conv.id,
252
+ "user",
253
+ JSON.stringify([
254
+ {
255
+ type: "tool_result",
256
+ tool_use_id: "tu_orphan",
257
+ content: "stale",
258
+ },
259
+ { type: "text", text: "<system_notice>internal</system_notice>" },
260
+ ]),
261
+ );
262
+ await addMessage(
263
+ conv.id,
264
+ "assistant",
265
+ JSON.stringify([{ type: "text", text: "ok" }]),
266
+ );
267
+
268
+ const response = handleListMessages(createTestArgs(conv.id));
269
+ const body = response as { messages: MessagePayload[] };
270
+
271
+ expect(body.messages).toHaveLength(1);
272
+ expect(body.messages[0].role).toBe("assistant");
213
273
  });
214
274
 
215
275
  test("multi-turn: each tool_result merges into correct assistant", async () => {
@@ -262,7 +322,7 @@ describe("handleListMessages tool_result merging", () => {
262
322
  JSON.stringify([{ type: "text", text: "thanks" }]),
263
323
  );
264
324
 
265
- const response = handleListMessages(createTestArgs(conv.id), null);
325
+ const response = handleListMessages(createTestArgs(conv.id));
266
326
  const body = response as { messages: MessagePayload[] };
267
327
 
268
328
  // Consecutive assistant messages are merged at query time so the client
@@ -312,7 +372,7 @@ describe("handleListMessages tool_result merging", () => {
312
372
  ]),
313
373
  );
314
374
 
315
- const response = handleListMessages(createTestArgs(conv.id), null);
375
+ const response = handleListMessages(createTestArgs(conv.id));
316
376
  const body = response as { messages: MessagePayload[] };
317
377
 
318
378
  expect(body.messages).toHaveLength(2);
@@ -1152,7 +1152,6 @@ describe("normalizeLlmContextPayloads", () => {
1152
1152
  reasoning: { effort: "high" },
1153
1153
  max_output_tokens: 64000,
1154
1154
  stream: true,
1155
- store: false,
1156
1155
  },
1157
1156
  responsePayload: {
1158
1157
  id: "resp_abc123",
@@ -1245,7 +1244,6 @@ describe("normalizeLlmContextPayloads", () => {
1245
1244
  reasoning: { effort: "high" },
1246
1245
  max_output_tokens: 64000,
1247
1246
  stream: true,
1248
- store: false,
1249
1247
  },
1250
1248
  language: "json",
1251
1249
  },
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Tests for the `call_site` column on `llm_request_logs`. The column is
3
+ * stamped by `recordRequestLog` at insertion time and surfaces in
4
+ * `LogRow.callSite`. Historical rows (pre-migration 264) stay NULL —
5
+ * "we don't know" rather than guessing `mainAgent`.
6
+ */
7
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
8
+
9
+ mock.module("../util/logger.js", () => ({
10
+ getLogger: () =>
11
+ new Proxy({} as Record<string, unknown>, {
12
+ get: () => () => {},
13
+ }),
14
+ }));
15
+
16
+ mock.module("../config/loader.js", () => ({
17
+ getConfig: () => ({
18
+ ui: {},
19
+ model: "test",
20
+ provider: "test",
21
+ memory: { enabled: false },
22
+ rateLimit: { maxRequestsPerMinute: 0 },
23
+ secretDetection: { enabled: false },
24
+ }),
25
+ }));
26
+
27
+ import { getDb, getSqliteFrom } from "../memory/db-connection.js";
28
+ import { initializeDb } from "../memory/db-init.js";
29
+ import {
30
+ getRequestLogById,
31
+ recordRequestLog,
32
+ } from "../memory/llm-request-log-store.js";
33
+ import { migrateLlmRequestLogCallSite } from "../memory/migrations/264-llm-request-log-call-site.js";
34
+ import { llmRequestLogs } from "../memory/schema.js";
35
+
36
+ initializeDb();
37
+
38
+ function resetLogs(): void {
39
+ const db = getDb();
40
+ db.delete(llmRequestLogs).run();
41
+ }
42
+
43
+ describe("recordRequestLog call_site stamping", () => {
44
+ beforeEach(resetLogs);
45
+
46
+ test("stamps callSite when provided", () => {
47
+ const id = recordRequestLog(
48
+ "conv-1",
49
+ '{"req":1}',
50
+ '{"res":1}',
51
+ undefined,
52
+ "anthropic",
53
+ "mainAgent",
54
+ );
55
+ const row = getRequestLogById(id);
56
+ expect(row).not.toBeNull();
57
+ expect(row!.callSite).toBe("mainAgent");
58
+ });
59
+
60
+ test("leaves callSite NULL when omitted (backward compat)", () => {
61
+ const id = recordRequestLog("conv-1", '{"req":1}', '{"res":1}');
62
+ const row = getRequestLogById(id);
63
+ expect(row).not.toBeNull();
64
+ expect(row!.callSite).toBeNull();
65
+ });
66
+
67
+ test("supports the compactionAgent value", () => {
68
+ const id = recordRequestLog(
69
+ "conv-1",
70
+ '{"req":1}',
71
+ '{"res":1}',
72
+ undefined,
73
+ "anthropic",
74
+ "compactionAgent",
75
+ );
76
+ expect(getRequestLogById(id)?.callSite).toBe("compactionAgent");
77
+ });
78
+
79
+ test("two rows in the same conversation can carry different callSites", () => {
80
+ const mainId = recordRequestLog(
81
+ "conv-1",
82
+ '{"req":1}',
83
+ '{"res":1}',
84
+ undefined,
85
+ "anthropic",
86
+ "mainAgent",
87
+ );
88
+ const compactId = recordRequestLog(
89
+ "conv-1",
90
+ '{"req":2}',
91
+ '{"res":2}',
92
+ undefined,
93
+ "anthropic",
94
+ "compactionAgent",
95
+ );
96
+ expect(getRequestLogById(mainId)?.callSite).toBe("mainAgent");
97
+ expect(getRequestLogById(compactId)?.callSite).toBe("compactionAgent");
98
+ });
99
+ });
100
+
101
+ describe("migrateLlmRequestLogCallSite", () => {
102
+ test("adds the call_site column when missing", () => {
103
+ const db = getDb();
104
+ const raw = getSqliteFrom(db);
105
+
106
+ // Drop the column if present (simulate pre-264 state). SQLite supports
107
+ // `DROP COLUMN` since 3.35 (June 2021) — bun-sqlite ships well past that.
108
+ const before = raw
109
+ .query(`PRAGMA table_info(llm_request_logs)`)
110
+ .all() as Array<{ name: string }>;
111
+ if (before.some((c) => c.name === "call_site")) {
112
+ raw.exec(`ALTER TABLE llm_request_logs DROP COLUMN call_site`);
113
+ }
114
+
115
+ const without = raw
116
+ .query(`PRAGMA table_info(llm_request_logs)`)
117
+ .all() as Array<{ name: string }>;
118
+ expect(without.some((c) => c.name === "call_site")).toBe(false);
119
+
120
+ migrateLlmRequestLogCallSite(db);
121
+
122
+ const after = raw
123
+ .query(`PRAGMA table_info(llm_request_logs)`)
124
+ .all() as Array<{ name: string }>;
125
+ expect(after.some((c) => c.name === "call_site")).toBe(true);
126
+ });
127
+
128
+ test("is idempotent — second run is a no-op", () => {
129
+ const db = getDb();
130
+ // First run (column may or may not exist depending on test order; either
131
+ // path is fine for the idempotency contract).
132
+ migrateLlmRequestLogCallSite(db);
133
+ // Second run must not throw.
134
+ expect(() => migrateLlmRequestLogCallSite(db)).not.toThrow();
135
+ });
136
+ });
@@ -84,6 +84,7 @@ const SAMPLE_ROW = {
84
84
  // ClickHouse emits Int64 as a quoted string under JSONEachRow by default.
85
85
  created_at: "1778465138786",
86
86
  agent_loop_exit_reason: "no_tool_calls",
87
+ call_site: "mainAgent",
87
88
  };
88
89
 
89
90
  describe("ClickHouseLlmRequestLogSource", () => {
@@ -104,6 +105,7 @@ describe("ClickHouseLlmRequestLogSource", () => {
104
105
  responsePayload: '{"bar":2}',
105
106
  createdAt: 1778465138786,
106
107
  agentLoopExitReason: "no_tool_calls",
108
+ callSite: "mainAgent",
107
109
  });
108
110
  });
109
111
 
@@ -164,6 +166,30 @@ describe("ClickHouseLlmRequestLogSource", () => {
164
166
  expect(rows).toEqual([]);
165
167
  });
166
168
 
169
+ test("getRequestLogsByConversationId binds conversation id via parameterized placeholder", async () => {
170
+ // Regression guard: the conversation id flows from user-controlled
171
+ // input (conversationKey → conversations.id), so it must travel as a
172
+ // typed parameter, never as an inline string literal.
173
+ const recorder: FakeFetchCall[] = [];
174
+ const malicious = "conv-1' OR 1=1 --";
175
+ const src = makeSource({
176
+ body: JSON.stringify(SAMPLE_ROW) + "\n",
177
+ recorder,
178
+ });
179
+ const rows = await src.getRequestLogsByConversationId(malicious);
180
+ expect(rows).toHaveLength(1);
181
+ expect(recorder).toHaveLength(1);
182
+ const call = recorder[0]!;
183
+ const parsed = new URL(call.url);
184
+ expect(parsed.searchParams.get("param_assistant_id")).toBe(
185
+ "asst-fixture-001",
186
+ );
187
+ expect(parsed.searchParams.get("param_conversation_id")).toBe(malicious);
188
+ const body = String(call.init?.body ?? "");
189
+ expect(body).toContain("conversation_id = {conversation_id:String}");
190
+ expect(body).not.toContain(`'${malicious}'`);
191
+ });
192
+
167
193
  test("getRequestLogsByMessageId binds message ids via parameterized placeholders", async () => {
168
194
  // Regression for ATL-537. `getAssistantMessageIdsInTurn` returns the
169
195
  // caller-supplied id straight through when the message lookup misses,
@@ -2,7 +2,10 @@ import { describe, expect, test } from "bun:test";
2
2
 
3
3
  import { z } from "zod";
4
4
 
5
- import { resolveCallSiteConfig } from "../config/llm-resolver.js";
5
+ import {
6
+ resolveCallSiteConfig,
7
+ resolveDefaultProfileKey,
8
+ } from "../config/llm-resolver.js";
6
9
  import { type LLMCallSite, LLMSchema } from "../config/schemas/llm.js";
7
10
 
8
11
  const fullDefault = {
@@ -690,13 +693,28 @@ describe("resolveCallSiteConfig", () => {
690
693
  });
691
694
 
692
695
  const callSites: LLMCallSite[] = [
693
- "mainAgent", "subagentSpawn", "heartbeatAgent", "filingAgent",
694
- "compactionAgent", "analyzeConversation", "callAgent",
695
- "memoryExtraction", "memoryConsolidation", "memoryRetrieval",
696
- "memoryRouter", "recall", "conversationSummarization",
697
- "commitMessage", "conversationStarters", "replySuggestion",
698
- "conversationTitle", "identityIntro", "emptyStateGreeting",
699
- "notificationDecision", "interactionClassifier", "inference",
696
+ "mainAgent",
697
+ "subagentSpawn",
698
+ "heartbeatAgent",
699
+ "filingAgent",
700
+ "compactionAgent",
701
+ "analyzeConversation",
702
+ "callAgent",
703
+ "memoryExtraction",
704
+ "memoryConsolidation",
705
+ "memoryRetrieval",
706
+ "memoryRouter",
707
+ "recall",
708
+ "conversationSummarization",
709
+ "commitMessage",
710
+ "conversationStarters",
711
+ "replySuggestion",
712
+ "conversationTitle",
713
+ "identityIntro",
714
+ "emptyStateGreeting",
715
+ "notificationDecision",
716
+ "interactionClassifier",
717
+ "inference",
700
718
  ];
701
719
 
702
720
  for (const cs of callSites) {
@@ -778,7 +796,10 @@ describe("resolveCallSiteConfig", () => {
778
796
  provider_connection: "anthropic-managed",
779
797
  },
780
798
  profiles: {
781
- fireworks: { provider: "fireworks", model: "accounts/fireworks/models/kimi-k2p5" },
799
+ fireworks: {
800
+ provider: "fireworks",
801
+ model: "accounts/fireworks/models/kimi-k2p5",
802
+ },
782
803
  },
783
804
  activeProfile: "fireworks",
784
805
  });
@@ -790,3 +811,134 @@ describe("resolveCallSiteConfig", () => {
790
811
  expect(resolved.provider_connection).toBe("anthropic-managed");
791
812
  });
792
813
  });
814
+
815
+ describe("resolveDefaultProfileKey", () => {
816
+ test("mainAgent returns activeProfile when set and enabled", () => {
817
+ const llm = LLMSchema.parse({
818
+ default: fullDefault,
819
+ profiles: {
820
+ balanced: { provider: "anthropic", model: "claude-sonnet-4-7" },
821
+ gemini: { provider: "gemini", model: "gemini-2.5-pro" },
822
+ },
823
+ activeProfile: "gemini",
824
+ });
825
+ expect(resolveDefaultProfileKey("mainAgent", llm)).toBe("gemini");
826
+ });
827
+
828
+ test("mainAgent falls back to catalog default when activeProfile is unset", () => {
829
+ const llm = LLMSchema.parse({
830
+ default: fullDefault,
831
+ profiles: {
832
+ balanced: { provider: "anthropic", model: "claude-sonnet-4-7" },
833
+ },
834
+ });
835
+ // mainAgent's CALL_SITE_DEFAULTS profile is `balanced`.
836
+ expect(resolveDefaultProfileKey("mainAgent", llm)).toBe("balanced");
837
+ });
838
+
839
+ test("mainAgent falls back to catalog default when activeProfile points to a missing profile", () => {
840
+ const llm = LLMSchema.parse({
841
+ default: fullDefault,
842
+ profiles: {
843
+ balanced: { provider: "anthropic", model: "claude-sonnet-4-7" },
844
+ },
845
+ });
846
+ // `LLMSchema.superRefine` rejects unknown `activeProfile` references at
847
+ // config-load time, so this branch is unreachable for a parsed config.
848
+ // Mutate after parse to exercise the resolver's defensive fall-through.
849
+ const mutated = { ...llm, activeProfile: "does-not-exist" };
850
+ expect(resolveDefaultProfileKey("mainAgent", mutated)).toBe("balanced");
851
+ });
852
+
853
+ test("mainAgent falls back to catalog default when activeProfile is disabled", () => {
854
+ const llm = LLMSchema.parse({
855
+ default: fullDefault,
856
+ profiles: {
857
+ balanced: { provider: "anthropic", model: "claude-sonnet-4-7" },
858
+ gemini: {
859
+ provider: "gemini",
860
+ model: "gemini-2.5-pro",
861
+ status: "disabled",
862
+ },
863
+ },
864
+ activeProfile: "gemini",
865
+ });
866
+ expect(resolveDefaultProfileKey("mainAgent", llm)).toBe("balanced");
867
+ });
868
+
869
+ test("non-mainAgent ignores activeProfile and returns catalog default", () => {
870
+ const llm = LLMSchema.parse({
871
+ default: fullDefault,
872
+ profiles: {
873
+ balanced: { provider: "anthropic", model: "claude-sonnet-4-7" },
874
+ "cost-optimized": { provider: "openai", model: "gpt-5-mini" },
875
+ gemini: { provider: "gemini", model: "gemini-2.5-pro" },
876
+ },
877
+ activeProfile: "gemini",
878
+ });
879
+ // filingAgent's CALL_SITE_DEFAULTS profile is `cost-optimized` — not gemini.
880
+ expect(resolveDefaultProfileKey("filingAgent", llm)).toBe("cost-optimized");
881
+ });
882
+
883
+ test("non-mainAgent falls back to custom-* when catalog profile is missing", () => {
884
+ const llm = LLMSchema.parse({
885
+ default: fullDefault,
886
+ profiles: {
887
+ "custom-cost-optimized": {
888
+ provider: "openai",
889
+ model: "gpt-5-mini",
890
+ },
891
+ },
892
+ });
893
+ expect(resolveDefaultProfileKey("filingAgent", llm)).toBe(
894
+ "custom-cost-optimized",
895
+ );
896
+ });
897
+ });
898
+
899
+ describe("memory v3 call sites resolve through the standard resolver", () => {
900
+ const llm = LLMSchema.parse({
901
+ default: fullDefault,
902
+ profiles: {
903
+ balanced: { provider: "anthropic", model: "claude-sonnet-4-7" },
904
+ "cost-optimized": {
905
+ provider: "anthropic",
906
+ model: "claude-haiku-4-5-20251001",
907
+ },
908
+ },
909
+ });
910
+
911
+ test("memoryV3Filter and memoryV3Descent resolve to the cost-optimized profile", () => {
912
+ expect(resolveDefaultProfileKey("memoryV3Filter", llm)).toBe(
913
+ "cost-optimized",
914
+ );
915
+ expect(resolveDefaultProfileKey("memoryV3Descent", llm)).toBe(
916
+ "cost-optimized",
917
+ );
918
+ expect(resolveCallSiteConfig("memoryV3Filter", llm).model).toBe(
919
+ "claude-haiku-4-5-20251001",
920
+ );
921
+ expect(resolveCallSiteConfig("memoryV3Descent", llm).model).toBe(
922
+ "claude-haiku-4-5-20251001",
923
+ );
924
+ });
925
+
926
+ test("memoryV3Gate resolves to the balanced (capable) profile", () => {
927
+ expect(resolveDefaultProfileKey("memoryV3Gate", llm)).toBe("balanced");
928
+ expect(resolveCallSiteConfig("memoryV3Gate", llm).model).toBe(
929
+ "claude-sonnet-4-7",
930
+ );
931
+ });
932
+
933
+ test("v3 call sites are addressable as call-site override keys", () => {
934
+ const overridden = LLMSchema.parse({
935
+ default: fullDefault,
936
+ callSites: {
937
+ memoryV3Gate: { model: "claude-opus-4-7" },
938
+ },
939
+ });
940
+ expect(resolveCallSiteConfig("memoryV3Gate", overridden).model).toBe(
941
+ "claude-opus-4-7",
942
+ );
943
+ });
944
+ });
@@ -31,6 +31,7 @@ function makeInput(overrides?: Partial<UsageEventInput>): UsageEventInput {
31
31
  outputTokens: 500,
32
32
  cacheCreationInputTokens: null,
33
33
  cacheReadInputTokens: null,
34
+ rawUsage: null,
34
35
  actor: "main_agent",
35
36
  conversationId: null,
36
37
  runId: null,
@@ -217,6 +218,44 @@ describe("recordUsageEvent", () => {
217
218
  expect(events[0].cacheCreationInputTokens).toBe(200);
218
219
  expect(events[0].cacheReadInputTokens).toBe(300);
219
220
  });
221
+
222
+ test("round-trips the provider's raw_usage payload verbatim", () => {
223
+ // The `raw_usage` column carries the literal usage object the provider
224
+ // returned (Anthropic nests TTL breakdown under `cache_creation`,
225
+ // OpenAI nests cached-read details under `prompt_tokens_details`, etc.)
226
+ // It must round-trip from `recordUsageEvent` through SQLite back to
227
+ // `listUsageEvents` byte-for-byte so downstream consumers can extract
228
+ // any provider-specific detail without a schema change.
229
+ const rawUsage = {
230
+ input_tokens: 1000,
231
+ output_tokens: 500,
232
+ cache_creation_input_tokens: 500,
233
+ cache_creation: {
234
+ ephemeral_5m_input_tokens: 100,
235
+ ephemeral_1h_input_tokens: 400,
236
+ },
237
+ cache_read_input_tokens: 0,
238
+ service_tier: "standard",
239
+ };
240
+ recordUsageEvent(makeInput({ rawUsage }), pricedResult);
241
+
242
+ const [event] = listUsageEvents();
243
+ expect(event.rawUsage).toEqual(rawUsage);
244
+ });
245
+
246
+ test("raw_usage defaults to null when the provider did not return one", () => {
247
+ // Providers that don't surface a usage block (or daemons predating
248
+ // migration 260) write null. Coercing to `{}` would be
249
+ // indistinguishable from a usage block that genuinely has no fields,
250
+ // so we preserve null as the "absent" signal.
251
+ recordUsageEvent(
252
+ makeInput({ provider: "openai", model: "gpt-4o", rawUsage: null }),
253
+ pricedResult,
254
+ );
255
+
256
+ const [event] = listUsageEvents();
257
+ expect(event.rawUsage).toBeNull();
258
+ });
220
259
  });
221
260
 
222
261
  describe("listUsageEvents", () => {
@@ -1391,4 +1430,31 @@ describe("queryUnreportedUsageEvents", () => {
1391
1430
  // Analytics can treat 0 as "pre-first-turn" if needed.
1392
1431
  expect(events[0].turnIndex).toBe(0);
1393
1432
  });
1433
+
1434
+ test("surfaces raw_usage on unreported events", () => {
1435
+ // The telemetry reporter consumes `queryUnreportedUsageEvents` output
1436
+ // directly and forwards it to BigQuery. If the SELECT projection
1437
+ // drops the `raw_usage` column, every provider-specific detail
1438
+ // (Anthropic TTL breakdown, OpenAI prompt-token details, etc.)
1439
+ // vanishes silently — covered here so a refactor of the projection
1440
+ // can't regress the wire shape.
1441
+ const rawUsage = {
1442
+ input_tokens: 1500,
1443
+ output_tokens: 600,
1444
+ cache_creation_input_tokens: 800,
1445
+ cache_creation: {
1446
+ ephemeral_5m_input_tokens: 300,
1447
+ ephemeral_1h_input_tokens: 500,
1448
+ },
1449
+ };
1450
+ insertEventAt(1000, {
1451
+ cacheCreationInputTokens: 800,
1452
+ rawUsage,
1453
+ });
1454
+
1455
+ const events = queryUnreportedUsageEvents(0, undefined, 100);
1456
+ expect(events).toHaveLength(1);
1457
+ expect(events[0].cacheCreationInputTokens).toBe(800);
1458
+ expect(events[0].rawUsage).toEqual(rawUsage);
1459
+ });
1394
1460
  });