@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
@@ -3,14 +3,73 @@
3
3
  *
4
4
  * Logs method, path, status, and latency for every request to aid
5
5
  * debugging client issues. Uses structured Pino logging.
6
+ *
7
+ * Routes can opt in to suppress the per-request INFO line after a confirmed
8
+ * run of N successful responses by declaring `logging.silenceSuccessAfter`
9
+ * on the route definition. Warning (4xx) and error (5xx) lines are always
10
+ * emitted regardless of this setting.
6
11
  */
7
12
 
8
13
  import { getLogger } from "../../util/logger.js";
14
+ import type { RouteLoggingConfig } from "../routes/types.js";
9
15
 
10
16
  const log = getLogger("http-request");
11
17
 
12
18
  const UNKNOWN = "unknown" as const;
13
19
 
20
+ /**
21
+ * Optional metadata supplied by the caller (typically resolved from the
22
+ * matched route) that lets the middleware adjust its per-request log
23
+ * behavior — e.g. suppressing success logs after a threshold for noisy
24
+ * polling endpoints like `/v1/health`.
25
+ */
26
+ export interface RequestLogMetadata {
27
+ /**
28
+ * Stable identifier used as the success-suppression counter key. Two
29
+ * requests with the same counterKey share a single counter (so all
30
+ * variants of a parameterized route share suppression state).
31
+ */
32
+ counterKey: string;
33
+ config: RouteLoggingConfig;
34
+ }
35
+
36
+ // Module-level counter map. Tracks the cumulative number of successful
37
+ // (status < 400) responses logged per `counterKey`. Once the count passes
38
+ // the route's `silenceSuccessAfter` threshold, further successful responses
39
+ // skip the per-request INFO log line. Counters never reset within a
40
+ // process — the behavior is "the route worked, stop spamming".
41
+ const successCounters = new Map<string, number>();
42
+
43
+ /**
44
+ * Test-only: reset the per-route success counters. Production code never
45
+ * calls this; tests use it to isolate suppression state between cases.
46
+ */
47
+ export function _resetRequestLoggingCountersForTests(): void {
48
+ successCounters.clear();
49
+ }
50
+
51
+ /**
52
+ * Decide whether the success log line should be suppressed for this
53
+ * request. Returns true when the counter has already reached the
54
+ * configured threshold. Pure read — the counter is only mutated when
55
+ * the log line is actually emitted.
56
+ */
57
+ function shouldSuppressSuccess(meta: RequestLogMetadata | undefined): boolean {
58
+ if (!meta) return false;
59
+ const threshold = meta.config.silenceSuccessAfter;
60
+ if (threshold === undefined || threshold <= 0) return false;
61
+ const current = successCounters.get(meta.counterKey) ?? 0;
62
+ return current >= threshold;
63
+ }
64
+
65
+ /** Record that we just emitted a success log line for this route. */
66
+ function bumpSuccessCounter(meta: RequestLogMetadata | undefined): void {
67
+ if (!meta) return;
68
+ if (meta.config.silenceSuccessAfter === undefined) return;
69
+ const current = successCounters.get(meta.counterKey) ?? 0;
70
+ successCounters.set(meta.counterKey, current + 1);
71
+ }
72
+
14
73
  /**
15
74
  * Wrap a request handler to log request metadata and response timing.
16
75
  *
@@ -20,6 +79,7 @@ const UNKNOWN = "unknown" as const;
20
79
  export async function withRequestLogging(
21
80
  req: Request,
22
81
  handler: () => Promise<Response>,
82
+ meta?: RequestLogMetadata,
23
83
  ): Promise<Response> {
24
84
  const start = performance.now();
25
85
  const url = new URL(req.url);
@@ -66,8 +126,9 @@ export async function withRequestLogging(
66
126
  log.error(logData, `${method} ${path} -> ${status} (${latencyMs}ms)`);
67
127
  } else if (status >= 400) {
68
128
  log.warn(logData, `${method} ${path} -> ${status} (${latencyMs}ms)`);
69
- } else {
129
+ } else if (!shouldSuppressSuccess(meta)) {
70
130
  log.info(logData, `${method} ${path} -> ${status} (${latencyMs}ms)`);
131
+ bumpSuccessCounter(meta);
71
132
  }
72
133
 
73
134
  return response;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Gate for LLM-touching background work that runs between daemon start and
3
+ * the user's first interaction.
4
+ *
5
+ * ## Why this exists
6
+ *
7
+ * Cloud-hosted assistants are served from a warm pool: the daemon boots,
8
+ * background services initialize, and the image waits to be claimed by a
9
+ * real user. Before the user claims an image, no provider credentials are
10
+ * registered, so any background job that tries to call the LLM fails — and
11
+ * those failure rows persist in the local SQLite database, becoming visible
12
+ * in the conversation sidebar the moment the user hatches.
13
+ *
14
+ * ## The probe
15
+ *
16
+ * `hasReceivedUserMessage()` returns `true` once at least one
17
+ * `role='user'` message exists in a `conversation_type='standard'`
18
+ * conversation. Background / scheduled conversations don't count — they're
19
+ * exactly the noise we're trying to suppress.
20
+ *
21
+ * The result is cached in-process after the first `true` because the flag
22
+ * is monotonic: a user message, once present, is never deleted in a way
23
+ * that should re-open the gate. (Even a destructive sweep that wipes all
24
+ * messages would still want background jobs paused until a real user
25
+ * interaction resumes, so re-querying on miss is the correct behavior.)
26
+ *
27
+ * Callers should treat the gate as advisory + defense-in-depth: prefer to
28
+ * skip at the service level (heartbeat, update-bulletin, etc.) so no run
29
+ * row / conversation row is created at all, and rely on the gate inside
30
+ * `runBackgroundJob` as the universal backstop.
31
+ */
32
+ import { rawGet } from "../memory/raw-query.js";
33
+ import { getLogger } from "../util/logger.js";
34
+
35
+ const log = getLogger("pre-first-message-gate");
36
+
37
+ let cachedHasUserMessage = false;
38
+
39
+ /**
40
+ * Returns `true` if the local store has ever recorded a user-authored
41
+ * message in a standard conversation.
42
+ *
43
+ * Cheap: indexed lookup with `LIMIT 1`. After the first `true` result the
44
+ * answer is cached in-process and subsequent calls are O(1).
45
+ *
46
+ * On query error the function logs a warning and returns `false` — the
47
+ * conservative interpretation is "we can't prove the user has interacted,
48
+ * so don't fire background work."
49
+ */
50
+ export function hasReceivedUserMessage(): boolean {
51
+ if (cachedHasUserMessage) return true;
52
+
53
+ try {
54
+ const row = rawGet<{ one: number }>(
55
+ `SELECT 1 AS one FROM messages m
56
+ JOIN conversations c ON m.conversation_id = c.id
57
+ WHERE m.role = 'user'
58
+ AND c.conversation_type = 'standard'
59
+ LIMIT 1`,
60
+ );
61
+ if (row != null) {
62
+ cachedHasUserMessage = true;
63
+ return true;
64
+ }
65
+ return false;
66
+ } catch (err) {
67
+ log.warn(
68
+ { err },
69
+ "hasReceivedUserMessage: query failed; treating as not-yet-received so background work stays paused",
70
+ );
71
+ return false;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Test-only reset of the in-process cache. Real code paths must never
77
+ * call this — the cache is monotonic by design.
78
+ *
79
+ * @internal
80
+ */
81
+ export function _resetPreFirstMessageGateCacheForTests(): void {
82
+ cachedHasUserMessage = false;
83
+ }
@@ -720,10 +720,17 @@ describe("handleBackupVerify", () => {
720
720
  // ---------------------------------------------------------------------------
721
721
 
722
722
  describe("ROUTES", () => {
723
- test("registers four routes with the expected endpoint+method pairs", () => {
723
+ test("registers routes with the expected endpoint+method pairs", () => {
724
724
  const pairs = ROUTES.map((d) => `${d.method} ${d.endpoint}`).sort();
725
725
  expect(pairs).toEqual([
726
+ "GET backup/destinations",
727
+ "GET backup/status",
726
728
  "GET backups",
729
+ "POST backup/destinations/add",
730
+ "POST backup/destinations/remove",
731
+ "POST backup/destinations/set-encrypt",
732
+ "POST backup/disable",
733
+ "POST backup/enable",
727
734
  "POST backups/create",
728
735
  "POST backups/restore",
729
736
  "POST backups/verify",
@@ -0,0 +1,251 @@
1
+ /**
2
+ * Tests for the bookmark route handlers in `bookmark-routes.ts`.
3
+ *
4
+ * Covers:
5
+ * - POST + GET round-trip
6
+ * - POST idempotency (no duplicate row, same id returned)
7
+ * - POST FK validation (unknown messageId → 4xx)
8
+ * - DELETE /by-message/:messageId
9
+ * - SSE event publication on create AND delete
10
+ */
11
+
12
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
13
+
14
+ // Capture publish() invocations so the tests can assert on emitted events
15
+ // without spinning up real SSE infrastructure.
16
+ const publishCalls: unknown[] = [];
17
+
18
+ mock.module("../../assistant-event-hub.js", () => ({
19
+ assistantEventHub: {
20
+ publish: async (event: unknown) => {
21
+ publishCalls.push(event);
22
+ },
23
+ subscribe: () => () => {},
24
+ },
25
+ }));
26
+
27
+ import { getDb } from "../../../memory/db-connection.js";
28
+ import { initializeDb } from "../../../memory/db-init.js";
29
+ import {
30
+ conversations,
31
+ messageBookmarks,
32
+ messages,
33
+ } from "../../../memory/schema.js";
34
+ import { ROUTES as BOOKMARK_ROUTES } from "../bookmark-routes.js";
35
+ import type { RouteDefinition, RouteHandlerArgs } from "../types.js";
36
+
37
+ // ---------------------------------------------------------------------------
38
+ // DB bootstrap
39
+ // ---------------------------------------------------------------------------
40
+
41
+ initializeDb();
42
+
43
+ // ---------------------------------------------------------------------------
44
+ // Helpers
45
+ // ---------------------------------------------------------------------------
46
+
47
+ function findHandler(operationId: string): RouteDefinition["handler"] {
48
+ const route = BOOKMARK_ROUTES.find((r) => r.operationId === operationId);
49
+ if (!route) throw new Error(`Route ${operationId} not found`);
50
+ return route.handler;
51
+ }
52
+
53
+ const listHandler = findHandler("bookmarks_list");
54
+ const createHandler = findHandler("bookmarks_create");
55
+ const deleteByMessageHandler = findHandler("bookmarks_delete_by_message");
56
+
57
+ function clearDb(): void {
58
+ const db = getDb();
59
+ // Bookmarks first (FK), then messages, then conversations.
60
+ db.delete(messageBookmarks).run();
61
+ db.delete(messages).run();
62
+ db.delete(conversations).run();
63
+ }
64
+
65
+ function seedConversationAndMessage(opts: {
66
+ conversationId: string;
67
+ messageId: string;
68
+ conversationTitle?: string;
69
+ messageContent?: string;
70
+ messageRole?: string;
71
+ }): void {
72
+ const now = Date.now();
73
+ const db = getDb();
74
+ db.insert(conversations)
75
+ .values({
76
+ id: opts.conversationId,
77
+ title: opts.conversationTitle ?? "Test conversation",
78
+ createdAt: now,
79
+ updatedAt: now,
80
+ source: "test",
81
+ conversationType: "standard",
82
+ memoryScopeId: "default",
83
+ })
84
+ .run();
85
+ db.insert(messages)
86
+ .values({
87
+ id: opts.messageId,
88
+ conversationId: opts.conversationId,
89
+ role: opts.messageRole ?? "user",
90
+ content: opts.messageContent ?? "hello world",
91
+ createdAt: now,
92
+ })
93
+ .run();
94
+ }
95
+
96
+ async function call(
97
+ handler: RouteDefinition["handler"],
98
+ args: RouteHandlerArgs,
99
+ ): Promise<unknown> {
100
+ return await handler(args);
101
+ }
102
+
103
+ interface EventEnvelope {
104
+ message: { type: string; [key: string]: unknown };
105
+ }
106
+
107
+ function publishedTypes(): string[] {
108
+ return publishCalls.map((e) => (e as EventEnvelope).message.type);
109
+ }
110
+
111
+ beforeEach(() => {
112
+ clearDb();
113
+ publishCalls.length = 0;
114
+ });
115
+
116
+ // ---------------------------------------------------------------------------
117
+ // Tests
118
+ // ---------------------------------------------------------------------------
119
+
120
+ describe("bookmark routes", () => {
121
+ test("POST then GET returns the new bookmark", async () => {
122
+ seedConversationAndMessage({
123
+ conversationId: "conv-1",
124
+ messageId: "msg-1",
125
+ messageContent: "first message body",
126
+ messageRole: "assistant",
127
+ });
128
+
129
+ const created = (await call(createHandler, {
130
+ body: { messageId: "msg-1", conversationId: "conv-1" },
131
+ })) as { id: string; messageId: string; messagePreview: string };
132
+
133
+ expect(created.messageId).toBe("msg-1");
134
+ expect(created.messagePreview).toBe("first message body");
135
+
136
+ const listed = (await call(listHandler, {})) as {
137
+ bookmarks: Array<{ id: string; messageId: string }>;
138
+ };
139
+
140
+ expect(listed.bookmarks).toHaveLength(1);
141
+ expect(listed.bookmarks[0]?.id).toBe(created.id);
142
+ expect(listed.bookmarks[0]?.messageId).toBe("msg-1");
143
+ });
144
+
145
+ test("POST is idempotent — second call returns same id, no duplicate row", async () => {
146
+ seedConversationAndMessage({
147
+ conversationId: "conv-2",
148
+ messageId: "msg-2",
149
+ });
150
+
151
+ const first = (await call(createHandler, {
152
+ body: { messageId: "msg-2", conversationId: "conv-2" },
153
+ })) as { id: string };
154
+ const second = (await call(createHandler, {
155
+ body: { messageId: "msg-2", conversationId: "conv-2" },
156
+ })) as { id: string };
157
+
158
+ expect(second.id).toBe(first.id);
159
+
160
+ const listed = (await call(listHandler, {})) as {
161
+ bookmarks: unknown[];
162
+ };
163
+ expect(listed.bookmarks).toHaveLength(1);
164
+ });
165
+
166
+ test("POST with non-existent messageId returns a 4xx", async () => {
167
+ seedConversationAndMessage({
168
+ conversationId: "conv-3",
169
+ messageId: "msg-3",
170
+ });
171
+
172
+ let caught: unknown = null;
173
+ try {
174
+ await call(createHandler, {
175
+ body: { messageId: "missing-msg", conversationId: "conv-3" },
176
+ });
177
+ } catch (err) {
178
+ caught = err;
179
+ }
180
+
181
+ expect(caught).not.toBeNull();
182
+ // RouteError subclasses (BadRequestError, NotFoundError, …) carry a
183
+ // `statusCode` field that the HTTP adapter forwards to the wire — assert
184
+ // that we throw something in the 4xx range without coupling to the
185
+ // specific subclass.
186
+ const statusCode = (caught as { statusCode?: number }).statusCode;
187
+ expect(
188
+ typeof statusCode === "number" && statusCode >= 400 && statusCode < 500,
189
+ ).toBe(true);
190
+ });
191
+
192
+ test("DELETE /by-message/:messageId removes the row", async () => {
193
+ seedConversationAndMessage({
194
+ conversationId: "conv-5",
195
+ messageId: "msg-5",
196
+ });
197
+ await call(createHandler, {
198
+ body: { messageId: "msg-5", conversationId: "conv-5" },
199
+ });
200
+
201
+ const result = (await call(deleteByMessageHandler, {
202
+ pathParams: { messageId: "msg-5" },
203
+ })) as { success: boolean };
204
+ expect(result.success).toBe(true);
205
+
206
+ const listed = (await call(listHandler, {})) as { bookmarks: unknown[] };
207
+ expect(listed.bookmarks).toHaveLength(0);
208
+ });
209
+
210
+ test("publishes SSE events on create AND delete", async () => {
211
+ seedConversationAndMessage({
212
+ conversationId: "conv-6",
213
+ messageId: "msg-6",
214
+ });
215
+
216
+ const created = (await call(createHandler, {
217
+ body: { messageId: "msg-6", conversationId: "conv-6" },
218
+ })) as { id: string };
219
+
220
+ // Publishes are fire-and-forget (`.catch(...)`), so let any pending
221
+ // microtasks settle before asserting.
222
+ await new Promise((r) => setTimeout(r, 0));
223
+
224
+ expect(publishedTypes()).toEqual(["bookmark.created"]);
225
+ const createdEvent = publishCalls[0] as EventEnvelope;
226
+ expect(createdEvent.message.type).toBe("bookmark.created");
227
+ expect(
228
+ (createdEvent.message as unknown as { bookmark: { id: string } }).bookmark
229
+ .id,
230
+ ).toBe(created.id);
231
+
232
+ publishCalls.length = 0;
233
+
234
+ await call(deleteByMessageHandler, { pathParams: { messageId: "msg-6" } });
235
+ await new Promise((r) => setTimeout(r, 0));
236
+
237
+ expect(publishedTypes()).toEqual(["bookmark.deleted"]);
238
+ const deletedEvent = publishCalls[0] as EventEnvelope;
239
+ expect(
240
+ (deletedEvent.message as unknown as { messageId?: string }).messageId,
241
+ ).toBe("msg-6");
242
+ });
243
+
244
+ test("DELETE on a non-existent messageId does not publish", async () => {
245
+ await call(deleteByMessageHandler, {
246
+ pathParams: { messageId: "does-not-exist" },
247
+ });
248
+ await new Promise((r) => setTimeout(r, 0));
249
+ expect(publishCalls).toHaveLength(0);
250
+ });
251
+ });
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Cutover-proof parity test: CLI create vs HTTP route create.
3
+ *
4
+ * Runs a CLI `createConnection` call and an HTTP-route `handleCreateConnection`
5
+ * call with the same payload, then asserts the resulting DB rows are identical
6
+ * (after normalizing timestamps). This proves the HTTP route wraps the same
7
+ * store path the CLI uses — no divergent code path.
8
+ *
9
+ * Rule: cc-cutover-proof (see PR_B_TASK.md).
10
+ */
11
+
12
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
13
+
14
+ // ── Module mocks (must come before imports) ──────────────────────────────────
15
+
16
+ mock.module("../../../config/loader.js", () => ({
17
+ getConfigReadOnly: () => ({}),
18
+ getConfig: () => ({}),
19
+ invalidateConfigCache: () => {},
20
+ }));
21
+
22
+ mock.module("../../../util/logger.js", () => ({
23
+ getLogger: () =>
24
+ new Proxy({} as Record<string, unknown>, { get: () => () => {} }),
25
+ }));
26
+
27
+ // ── Real imports ──────────────────────────────────────────────────────────────
28
+
29
+ import { getDb } from "../../../memory/db-connection.js";
30
+ import { initializeDb } from "../../../memory/db-init.js";
31
+ import { providerConnections } from "../../../memory/schema/inference.js";
32
+ import { createConnection, getConnection } from "../../../providers/inference/connections.js";
33
+ import { ROUTES } from "../inference-provider-connection-routes.js";
34
+ import type { RouteDefinition } from "../types.js";
35
+
36
+ // ── DB bootstrap ──────────────────────────────────────────────────────────────
37
+
38
+ initializeDb();
39
+
40
+ // ── Helpers ───────────────────────────────────────────────────────────────────
41
+
42
+ function findHandler(operationId: string): RouteDefinition["handler"] {
43
+ const route = ROUTES.find((r) => r.operationId === operationId);
44
+ if (!route) throw new Error(`Route ${operationId} not found`);
45
+ return route.handler;
46
+ }
47
+
48
+ function clearConnections(): void {
49
+ getDb().delete(providerConnections).run();
50
+ }
51
+
52
+ function normalizeTimestamps<T extends object>(obj: T): Omit<T, "createdAt" | "updatedAt"> {
53
+ const { createdAt: _c, updatedAt: _u, ...rest } = obj as T & { createdAt?: unknown; updatedAt?: unknown };
54
+ return rest as Omit<T, "createdAt" | "updatedAt">;
55
+ }
56
+
57
+ // ── Tests ─────────────────────────────────────────────────────────────────────
58
+
59
+ beforeEach(() => {
60
+ clearConnections();
61
+ });
62
+
63
+ describe("CLI vs HTTP route parity", () => {
64
+ test("api_key connection: CLI createConnection and HTTP POST produce identical DB rows", async () => {
65
+ const payload = {
66
+ name: "parity-anthropic",
67
+ provider: "anthropic" as const,
68
+ auth: { type: "api_key" as const, credential: "vault/anthropic/key" },
69
+ };
70
+
71
+ // ── CLI path ──────────────────────────────────────────────────────────────
72
+ const cliResult = createConnection(getDb(), payload);
73
+ expect(cliResult.ok).toBe(true);
74
+ if (!cliResult.ok) throw new Error("CLI create failed");
75
+ const cliRow = getConnection(getDb(), payload.name);
76
+ expect(cliRow).not.toBeNull();
77
+
78
+ // Clean up CLI row before HTTP create so names don't collide.
79
+ clearConnections();
80
+
81
+ // ── HTTP route path ───────────────────────────────────────────────────────
82
+ const httpResult = (await findHandler("inference_provider_connections_create")({
83
+ body: {
84
+ name: payload.name,
85
+ provider: payload.provider,
86
+ auth: payload.auth,
87
+ },
88
+ })) as { name: string; provider: string; auth: object };
89
+
90
+ expect(httpResult.name).toBe(payload.name);
91
+ const httpRow = getConnection(getDb(), payload.name);
92
+ expect(httpRow).not.toBeNull();
93
+
94
+ // ── Compare ───────────────────────────────────────────────────────────────
95
+ // Both rows should have identical non-timestamp fields.
96
+ expect(normalizeTimestamps(httpRow!)).toEqual(normalizeTimestamps(cliRow!));
97
+ });
98
+
99
+ test("platform connection: CLI createConnection and HTTP POST produce identical DB rows", async () => {
100
+ const payload = {
101
+ name: "parity-openai-managed",
102
+ provider: "openai" as const,
103
+ auth: { type: "platform" as const },
104
+ };
105
+
106
+ const cliResult = createConnection(getDb(), payload);
107
+ expect(cliResult.ok).toBe(true);
108
+ if (!cliResult.ok) throw new Error("CLI create failed");
109
+ const cliRow = getConnection(getDb(), payload.name);
110
+
111
+ clearConnections();
112
+
113
+ await findHandler("inference_provider_connections_create")({
114
+ body: { name: payload.name, provider: payload.provider, auth: payload.auth },
115
+ });
116
+ const httpRow = getConnection(getDb(), payload.name);
117
+
118
+ expect(normalizeTimestamps(httpRow!)).toEqual(normalizeTimestamps(cliRow!));
119
+ });
120
+
121
+ test("none auth connection: CLI createConnection and HTTP POST produce identical DB rows", async () => {
122
+ const payload = {
123
+ name: "parity-ollama",
124
+ provider: "ollama" as const,
125
+ auth: { type: "none" as const },
126
+ };
127
+
128
+ const cliResult = createConnection(getDb(), payload);
129
+ expect(cliResult.ok).toBe(true);
130
+ if (!cliResult.ok) throw new Error("CLI create failed");
131
+ const cliRow = getConnection(getDb(), payload.name);
132
+
133
+ clearConnections();
134
+
135
+ await findHandler("inference_provider_connections_create")({
136
+ body: { name: payload.name, provider: payload.provider, auth: payload.auth },
137
+ });
138
+ const httpRow = getConnection(getDb(), payload.name);
139
+
140
+ expect(normalizeTimestamps(httpRow!)).toEqual(normalizeTimestamps(cliRow!));
141
+ });
142
+ });