@vellumai/assistant 0.8.4 → 0.8.6

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 (802) hide show
  1. package/AGENTS.md +33 -1
  2. package/ARCHITECTURE.md +3 -3
  3. package/bunfig.toml +6 -1
  4. package/docs/browser-use-architecture-phase2.md +1 -1
  5. package/docs/credential-execution-service.md +6 -6
  6. package/docs/plugins.md +4 -3
  7. package/knip.json +2 -1
  8. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +12 -13
  9. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +4 -1
  10. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
  11. package/openapi.yaml +2748 -216
  12. package/package.json +1 -1
  13. package/src/__tests__/actor-token-service.test.ts +3 -2
  14. package/src/__tests__/agent-loop-exit-reason.test.ts +102 -9
  15. package/src/__tests__/agent-loop-override-profile.test.ts +2 -1
  16. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
  17. package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
  18. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
  19. package/src/__tests__/annotate-risk-options.test.ts +1 -0
  20. package/src/__tests__/anthropic-provider.test.ts +34 -37
  21. package/src/__tests__/approval-cascade.test.ts +1 -0
  22. package/src/__tests__/approval-routes-http.test.ts +9 -13
  23. package/src/__tests__/assert-not-live-db.ts +79 -0
  24. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
  25. package/src/__tests__/assistant-feature-flags-integration.test.ts +12 -28
  26. package/src/__tests__/audit-log-rotation.test.ts +72 -18
  27. package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
  28. package/src/__tests__/background-workers-disk-pressure.test.ts +8 -11
  29. package/src/__tests__/browser-skill-endstate.test.ts +3 -3
  30. package/src/__tests__/btw-routes.test.ts +5 -5
  31. package/src/__tests__/call-controller.test.ts +3 -3
  32. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  33. package/src/__tests__/channel-approval-routes.test.ts +3 -2
  34. package/src/__tests__/channel-guardian.test.ts +6 -5
  35. package/src/__tests__/channel-readiness-slack-remote.test.ts +175 -0
  36. package/src/__tests__/channel-reply-delivery.test.ts +35 -0
  37. package/src/__tests__/channel-retry-sweep.test.ts +320 -3
  38. package/src/__tests__/checker.test.ts +18 -27
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/compaction-trail-store.test.ts +264 -0
  41. package/src/__tests__/compactor-call-site-logging.test.ts +215 -0
  42. package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
  43. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +12 -16
  44. package/src/__tests__/computer-use-tools.test.ts +14 -18
  45. package/src/__tests__/config-loader-backfill.test.ts +13 -28
  46. package/src/__tests__/config-loader-corrupt.test.ts +5 -5
  47. package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
  48. package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
  49. package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
  50. package/src/__tests__/config-schema.test.ts +10 -10
  51. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  52. package/src/__tests__/connection-model-compat.test.ts +83 -0
  53. package/src/__tests__/contacts-tools.test.ts +3 -2
  54. package/src/__tests__/context-token-estimator.test.ts +22 -0
  55. package/src/__tests__/conversation-abort-tool-results.test.ts +5 -0
  56. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +2 -1
  57. package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
  58. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -1
  59. package/src/__tests__/conversation-agent-loop-overflow.test.ts +231 -2
  60. package/src/__tests__/conversation-agent-loop.test.ts +581 -54
  61. package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
  62. package/src/__tests__/conversation-app-control-instantiation.test.ts +31 -24
  63. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -0
  64. package/src/__tests__/conversation-attention-store.test.ts +101 -0
  65. package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
  66. package/src/__tests__/conversation-clear-safety.test.ts +25 -25
  67. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
  68. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  69. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  70. package/src/__tests__/conversation-error.test.ts +61 -0
  71. package/src/__tests__/conversation-fork-crud.test.ts +239 -15
  72. package/src/__tests__/conversation-fork-route.test.ts +3 -2
  73. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  74. package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
  75. package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
  76. package/src/__tests__/conversation-lifecycle.test.ts +53 -11
  77. package/src/__tests__/conversation-list-source.test.ts +3 -2
  78. package/src/__tests__/conversation-load-history-repair.test.ts +2 -1
  79. package/src/__tests__/{conversation-load-cleaned-at.test.ts → conversation-load-history-stripped.test.ts} +14 -13
  80. package/src/__tests__/conversation-pairing.test.ts +53 -0
  81. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +26 -7
  82. package/src/__tests__/conversation-process-callsite.test.ts +1 -0
  83. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  84. package/src/__tests__/conversation-queue.test.ts +333 -291
  85. package/src/__tests__/conversation-routes-disk-view.test.ts +112 -18
  86. package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
  87. package/src/__tests__/conversation-routes-slash-commands.test.ts +68 -2
  88. package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
  89. package/src/__tests__/conversation-skill-tools.test.ts +40 -147
  90. package/src/__tests__/conversation-slash-queue.test.ts +84 -32
  91. package/src/__tests__/conversation-slash-unknown.test.ts +5 -0
  92. package/src/__tests__/conversation-speed-override.test.ts +1 -0
  93. package/src/__tests__/conversation-store.test.ts +1 -1
  94. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +46 -0
  95. package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
  96. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
  97. package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
  98. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -3
  99. package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -17
  100. package/src/__tests__/conversation-sync-tags.test.ts +218 -35
  101. package/src/__tests__/conversation-title-service.test.ts +1 -0
  102. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +30 -0
  103. package/src/__tests__/conversation-usage.test.ts +1 -0
  104. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -0
  105. package/src/__tests__/conversation-workspace-injection.test.ts +6 -1
  106. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -1
  107. package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
  108. package/src/__tests__/credential-broker-server-use.test.ts +5 -5
  109. package/src/__tests__/credential-execution-client.test.ts +72 -1
  110. package/src/__tests__/credential-execution-feature-gates.test.ts +19 -19
  111. package/src/__tests__/credential-execution-tools.test.ts +6 -6
  112. package/src/__tests__/credential-health-service.test.ts +252 -3
  113. package/src/__tests__/credential-security-invariants.test.ts +6 -5
  114. package/src/__tests__/credential-vault-unit.test.ts +21 -21
  115. package/src/__tests__/credential-vault.test.ts +5 -5
  116. package/src/__tests__/cross-provider-web-search.test.ts +56 -2
  117. package/src/__tests__/db-connection-isolation.test.ts +7 -6
  118. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
  119. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
  120. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
  121. package/src/__tests__/db-test-helpers.ts +58 -0
  122. package/src/__tests__/disk-pressure-guard.test.ts +58 -41
  123. package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
  124. package/src/__tests__/disk-pressure-routes.test.ts +0 -33
  125. package/src/__tests__/disk-pressure-tools.test.ts +0 -4
  126. package/src/__tests__/dm-persistence.test.ts +26 -40
  127. package/src/__tests__/document-create-dedupe.test.ts +189 -0
  128. package/src/__tests__/document-find-replace.test.ts +3 -2
  129. package/src/__tests__/document-tool-security.test.ts +81 -2
  130. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  131. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
  132. package/src/__tests__/email-html-renderer.test.ts +12 -0
  133. package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
  134. package/src/__tests__/encrypted-store.test.ts +11 -9
  135. package/src/__tests__/feature-flag-test-helpers.ts +53 -0
  136. package/src/__tests__/filing-service.test.ts +1 -0
  137. package/src/__tests__/first-greeting.test.ts +62 -12
  138. package/src/__tests__/gateway-flag-listener.test.ts +236 -0
  139. package/src/__tests__/gemini-provider.test.ts +104 -0
  140. package/src/__tests__/guardian-action-sweep.test.ts +3 -2
  141. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  142. package/src/__tests__/guardian-outbound-http.test.ts +10 -7
  143. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
  144. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -1
  145. package/src/__tests__/heartbeat-disk-pressure.test.ts +5 -0
  146. package/src/__tests__/heartbeat-service.test.ts +5 -0
  147. package/src/__tests__/helpers/mock-logger.ts +26 -0
  148. package/src/__tests__/host-bash-routes.test.ts +1 -0
  149. package/src/__tests__/host-cu-routes-targeted.test.ts +1 -0
  150. package/src/__tests__/host-file-routes-targeted.test.ts +1 -0
  151. package/src/__tests__/host-shell-tool.test.ts +6 -5
  152. package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
  153. package/src/__tests__/http-conversation-lineage.test.ts +3 -2
  154. package/src/__tests__/http-user-message-parity.test.ts +29 -7
  155. package/src/__tests__/identity-intro-cache.test.ts +133 -22
  156. package/src/__tests__/inbound-slack-persistence.test.ts +44 -72
  157. package/src/__tests__/inference-profile-reaper.test.ts +3 -2
  158. package/src/__tests__/inference-profile-session-ipc.test.ts +3 -2
  159. package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
  160. package/src/__tests__/injector-disk-pressure.test.ts +3 -17
  161. package/src/__tests__/inline-skill-load-permissions.test.ts +4 -4
  162. package/src/__tests__/list-messages-hidden-metadata.test.ts +80 -0
  163. package/src/__tests__/list-messages-tool-merge.test.ts +70 -11
  164. package/src/__tests__/llm-context-normalization.test.ts +42 -0
  165. package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
  166. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
  167. package/src/__tests__/llm-resolver.test.ts +408 -9
  168. package/src/__tests__/llm-schema.test.ts +1 -1
  169. package/src/__tests__/llm-usage-store.test.ts +66 -0
  170. package/src/__tests__/logger.test.ts +89 -0
  171. package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
  172. package/src/__tests__/mcp-abort-signal.test.ts +16 -2
  173. package/src/__tests__/mcp-client-auth.test.ts +14 -0
  174. package/src/__tests__/media-generate-image.test.ts +31 -0
  175. package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
  176. package/src/__tests__/messaging-send-tool.test.ts +1 -0
  177. package/src/__tests__/migration-import-from-url.test.ts +3 -3
  178. package/src/__tests__/mock-gateway-ipc.ts +18 -2
  179. package/src/__tests__/model-intents.test.ts +4 -6
  180. package/src/__tests__/native-web-search.test.ts +30 -2
  181. package/src/__tests__/notification-deep-link.test.ts +62 -0
  182. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  183. package/src/__tests__/oauth-commands-routes.test.ts +37 -0
  184. package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
  185. package/src/__tests__/oauth-store.test.ts +3 -2
  186. package/src/__tests__/onboarding-template-contract.test.ts +4 -3
  187. package/src/__tests__/openai-provider.test.ts +54 -9
  188. package/src/__tests__/openai-responses-provider.test.ts +176 -14
  189. package/src/__tests__/openrouter-provider-only.test.ts +27 -5
  190. package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
  191. package/src/__tests__/pending-interactions-resolved-event.test.ts +0 -1
  192. package/src/__tests__/persistence-pipeline.test.ts +139 -1
  193. package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
  194. package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
  195. package/src/__tests__/platform.test.ts +2 -2
  196. package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
  197. package/src/__tests__/plugin-bootstrap.test.ts +11 -13
  198. package/src/__tests__/plugin-tool-contribution.test.ts +50 -40
  199. package/src/__tests__/plugin-types.test.ts +3 -2
  200. package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
  201. package/src/__tests__/pricing.test.ts +12 -0
  202. package/src/__tests__/process-message-background-slack.test.ts +21 -16
  203. package/src/__tests__/process-message-display-content.test.ts +19 -22
  204. package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
  205. package/src/__tests__/provider-platform-proxy-integration.test.ts +216 -4
  206. package/src/__tests__/provider-registry-ollama.test.ts +45 -22
  207. package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
  208. package/src/__tests__/recording-handler.test.ts +1 -0
  209. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
  210. package/src/__tests__/registry.test.ts +84 -84
  211. package/src/__tests__/relay-server.test.ts +10 -10
  212. package/src/__tests__/require-fresh-approval.test.ts +2 -2
  213. package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
  214. package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
  215. package/src/__tests__/schedule-store.test.ts +16 -1
  216. package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
  217. package/src/__tests__/secret-ingress-http.test.ts +5 -1
  218. package/src/__tests__/secure-keys.test.ts +3 -3
  219. package/src/__tests__/send-endpoint-busy.test.ts +81 -42
  220. package/src/__tests__/server-history-render.test.ts +4 -1
  221. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  222. package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
  223. package/src/__tests__/skill-feature-flags.test.ts +16 -18
  224. package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
  225. package/src/__tests__/skill-projection-feature-flag.test.ts +48 -37
  226. package/src/__tests__/skill-projection.benchmark.test.ts +7 -13
  227. package/src/__tests__/skill-tool-factory.test.ts +97 -96
  228. package/src/__tests__/slack-channel-config.test.ts +3 -3
  229. package/src/__tests__/subagent-call-site-routing.test.ts +11 -3
  230. package/src/__tests__/subagent-disposal.test.ts +27 -8
  231. package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
  232. package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
  233. package/src/__tests__/subagent-manager-notify.test.ts +20 -8
  234. package/src/__tests__/subagent-notify-parent.test.ts +6 -5
  235. package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
  236. package/src/__tests__/subagent-tools.test.ts +2 -1
  237. package/src/__tests__/suggestion-routes.test.ts +2 -0
  238. package/src/__tests__/sync-message-contract.test.ts +59 -0
  239. package/src/__tests__/system-prompt.test.ts +183 -131
  240. package/src/__tests__/terminal-tools.test.ts +1 -1
  241. package/src/__tests__/test-preload-verifier.ts +68 -0
  242. package/src/__tests__/test-preload.ts +32 -39
  243. package/src/__tests__/tool-approval-handler.test.ts +1 -5
  244. package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
  245. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
  246. package/src/__tests__/tool-executor-lifecycle-events.test.ts +35 -12
  247. package/src/__tests__/tool-executor.test.ts +64 -72
  248. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
  249. package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
  250. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  251. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  252. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
  253. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  254. package/src/__tests__/twilio-routes.test.ts +3 -2
  255. package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
  256. package/src/__tests__/usage-routes.test.ts +3 -0
  257. package/src/__tests__/validate-input.test.ts +381 -0
  258. package/src/__tests__/verification-control-plane-policy.test.ts +3 -2
  259. package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -1
  260. package/src/__tests__/voice-session-bridge.test.ts +37 -28
  261. package/src/__tests__/workspace-git-service.test.ts +6 -5
  262. package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
  263. package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
  264. package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
  265. package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
  266. package/src/acp/prepare-agent-env.ts +78 -0
  267. package/src/acp/session-manager.ts +6 -7
  268. package/src/agent/loop.ts +88 -0
  269. package/src/api/README.md +127 -0
  270. package/src/api/constants/call-sites.ts +27 -0
  271. package/src/api/events/assistant-outbound-attachment.ts +51 -0
  272. package/src/api/events/assistant-text-delta.ts +32 -0
  273. package/src/api/events/assistant-turn-start.ts +33 -0
  274. package/src/api/events/document-comment-created.ts +48 -0
  275. package/src/api/events/document-comment-deleted.ts +24 -0
  276. package/src/api/events/document-comment-reopened.ts +25 -0
  277. package/src/api/events/document-comment-resolved.ts +27 -0
  278. package/src/api/events/generation-cancelled.ts +24 -0
  279. package/src/api/events/generation-handoff.ts +41 -0
  280. package/src/api/events/message-complete.ts +42 -0
  281. package/src/api/events/open-url.ts +30 -0
  282. package/src/api/events/relationship-state-updated.ts +25 -0
  283. package/src/api/events/tool-use-start.ts +32 -0
  284. package/src/api/index.ts +129 -0
  285. package/src/api/package.json +10 -0
  286. package/src/api/responses/llm-context-response.ts +39 -0
  287. package/src/api/responses/llm-request-log-entry.ts +93 -0
  288. package/src/api/responses/memory-recall-log.ts +65 -0
  289. package/src/api/responses/memory-v2-activation-log.ts +78 -0
  290. package/src/background-wake/background-wake-routes.test.ts +868 -0
  291. package/src/background-wake/platform-client.test.ts +308 -0
  292. package/src/background-wake/platform-client.ts +167 -0
  293. package/src/background-wake/publisher.ts +91 -0
  294. package/src/background-wake/runtime-registry.ts +24 -0
  295. package/src/background-wake/wake-intent-hooks.test.ts +282 -0
  296. package/src/calls/guardian-dispatch.ts +1 -0
  297. package/src/calls/voice-session-bridge.ts +4 -4
  298. package/src/cli/commands/__tests__/browser.test.ts +23 -5
  299. package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
  300. package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
  301. package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
  302. package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
  303. package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
  304. package/src/cli/commands/__tests__/memory-v2.test.ts +1 -0
  305. package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
  306. package/src/cli/commands/__tests__/notifications.test.ts +184 -40
  307. package/src/cli/commands/browser.ts +247 -0
  308. package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
  309. package/src/cli/commands/channels/index.ts +229 -0
  310. package/src/cli/commands/domain.ts +91 -41
  311. package/src/cli/commands/inference.ts +93 -40
  312. package/src/cli/commands/memory-v2-compare-render.ts +115 -0
  313. package/src/cli/commands/memory-v2.ts +176 -1
  314. package/src/cli/commands/memory-v3-render.ts +491 -0
  315. package/src/cli/commands/memory-v3.ts +567 -0
  316. package/src/cli/commands/notifications.ts +365 -55
  317. package/src/cli/lib/open-browser.ts +7 -2
  318. package/src/cli/program.ts +4 -0
  319. package/src/config/assistant-feature-flags.ts +39 -46
  320. package/src/config/bundled-skills/document-editor/SKILL.md +16 -3
  321. package/src/config/bundled-skills/document-editor/TOOLS.json +18 -0
  322. package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
  323. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  324. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
  325. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
  326. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
  327. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
  328. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
  329. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
  330. package/src/config/bundled-skills/schedule/SKILL.md +1 -1
  331. package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
  332. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
  333. package/src/config/bundled-tool-registry.ts +2 -0
  334. package/src/config/call-site-defaults.ts +8 -7
  335. package/src/config/feature-flag-cache.ts +86 -0
  336. package/src/config/feature-flag-registry.json +33 -17
  337. package/src/config/llm-context-resolution.ts +10 -1
  338. package/src/config/llm-resolver.ts +121 -15
  339. package/src/config/loader.ts +4 -5
  340. package/src/config/schemas/__tests__/memory-v2.test.ts +228 -1
  341. package/src/config/schemas/call-site-catalog.ts +21 -7
  342. package/src/config/schemas/heartbeat.ts +1 -1
  343. package/src/config/schemas/llm.ts +102 -2
  344. package/src/config/schemas/memory-v2.ts +272 -0
  345. package/src/config/schemas/memory.ts +2 -1
  346. package/src/config/schemas/services.ts +6 -2
  347. package/src/config/seed-inference-profiles.ts +36 -16
  348. package/src/context/compactor.ts +52 -0
  349. package/src/context/token-estimator.ts +10 -5
  350. package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
  351. package/src/conversations/message-consolidation.ts +404 -0
  352. package/src/credential-execution/executable-discovery.ts +40 -0
  353. package/src/credential-execution/process-manager.ts +6 -2
  354. package/src/credential-health/credential-health-service.ts +125 -40
  355. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
  356. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +13 -15
  357. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +2 -3
  358. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
  359. package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
  360. package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
  361. package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
  362. package/src/daemon/__tests__/web-search-status-text.test.ts +1 -0
  363. package/src/daemon/conversation-agent-loop-handlers.ts +390 -80
  364. package/src/daemon/conversation-agent-loop.ts +244 -90
  365. package/src/daemon/conversation-error.ts +64 -6
  366. package/src/daemon/conversation-lifecycle.ts +27 -22
  367. package/src/daemon/conversation-messaging.ts +84 -43
  368. package/src/daemon/conversation-process.ts +74 -37
  369. package/src/daemon/conversation-runtime-assembly.ts +38 -17
  370. package/src/daemon/conversation-skill-tools.ts +14 -30
  371. package/src/daemon/conversation-surfaces.ts +69 -34
  372. package/src/daemon/conversation-tool-setup.ts +77 -32
  373. package/src/daemon/conversation-usage.ts +2 -0
  374. package/src/daemon/conversation.ts +40 -75
  375. package/src/daemon/daemon-control.ts +1 -1
  376. package/src/daemon/daemon-skill-host.ts +9 -2
  377. package/src/daemon/disk-pressure-guard.ts +39 -29
  378. package/src/daemon/first-greeting.ts +31 -13
  379. package/src/daemon/handlers/config-model.test.ts +1 -0
  380. package/src/daemon/handlers/conversations.ts +11 -3
  381. package/src/daemon/handlers/shared.ts +6 -1
  382. package/src/daemon/host-browser-proxy.ts +5 -5
  383. package/src/daemon/host-cu-proxy.ts +4 -4
  384. package/src/daemon/host-file-proxy.ts +4 -4
  385. package/src/daemon/host-proxy-base.ts +4 -4
  386. package/src/daemon/host-transfer-proxy.ts +10 -10
  387. package/src/daemon/lifecycle.ts +29 -26
  388. package/src/daemon/mcp-reload-service.ts +1 -1
  389. package/src/daemon/meet-manifest-loader.ts +11 -24
  390. package/src/daemon/message-types/conversations.ts +22 -27
  391. package/src/daemon/message-types/document-comments.ts +8 -44
  392. package/src/daemon/message-types/home.ts +2 -14
  393. package/src/daemon/message-types/integrations.ts +2 -7
  394. package/src/daemon/message-types/messages.ts +25 -48
  395. package/src/daemon/message-types/subagents.ts +6 -0
  396. package/src/daemon/message-types/sync.ts +14 -0
  397. package/src/daemon/process-message.ts +9 -9
  398. package/src/daemon/providers-setup.ts +1 -1
  399. package/src/daemon/server.ts +16 -0
  400. package/src/daemon/shutdown-handlers.ts +24 -5
  401. package/src/daemon/switch-inference-profile-tool.ts +62 -0
  402. package/src/daemon/tool-setup-types.ts +7 -0
  403. package/src/daemon/wake-target-adapter.ts +10 -0
  404. package/src/documents/document-store.ts +38 -0
  405. package/src/export/__tests__/transcript-formatter.test.ts +1 -0
  406. package/src/heartbeat/__tests__/heartbeat-service.test.ts +30 -1
  407. package/src/heartbeat/heartbeat-service.ts +63 -0
  408. package/src/home/__tests__/feed-writer.test.ts +161 -0
  409. package/src/home/__tests__/post-connect-feed.test.ts +1 -0
  410. package/src/home/__tests__/suggested-prompts.test.ts +55 -59
  411. package/src/home/feed-writer.ts +146 -7
  412. package/src/home/home-greeting.ts +0 -9
  413. package/src/home/suggested-prompts.ts +27 -154
  414. package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
  415. package/src/ipc/gateway-client.test.ts +4 -1
  416. package/src/ipc/gateway-flag-listener.ts +123 -0
  417. package/src/ipc/skill-routes/__tests__/memory.test.ts +1 -0
  418. package/src/ipc/skill-routes/__tests__/registries.test.ts +36 -7
  419. package/src/ipc/skill-routes/memory.ts +4 -3
  420. package/src/ipc/skill-routes/registries.ts +35 -40
  421. package/src/memory/__tests__/db-async-query.test.ts +165 -0
  422. package/src/memory/__tests__/db-maintenance.test.ts +115 -0
  423. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +242 -0
  424. package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
  425. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
  426. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
  427. package/src/memory/__tests__/memory-retrospective-job.test.ts +8 -0
  428. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
  429. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
  430. package/src/memory/auto-analysis-enqueue.ts +5 -1
  431. package/src/memory/conversation-attention-store.ts +17 -3
  432. package/src/memory/conversation-crud.ts +423 -182
  433. package/src/memory/conversation-starters-cadence.ts +3 -1
  434. package/src/memory/conversation-title-service.ts +19 -3
  435. package/src/memory/db-async-query.ts +214 -0
  436. package/src/memory/db-connection.ts +29 -19
  437. package/src/memory/db-init.ts +14 -0
  438. package/src/memory/db-maintenance.ts +30 -21
  439. package/src/memory/db-singleton.ts +77 -0
  440. package/src/memory/delivery-channels.ts +82 -0
  441. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
  442. package/src/memory/graph/bootstrap.ts +8 -1
  443. package/src/memory/graph/capability-seed.ts +7 -3
  444. package/src/memory/graph/conversation-graph-memory.ts +100 -17
  445. package/src/memory/graph/extraction.ts +1 -5
  446. package/src/memory/graph/graph-search.ts +7 -1
  447. package/src/memory/graph/retriever.test.ts +3 -3
  448. package/src/memory/indexer.ts +28 -18
  449. package/src/memory/job-handlers/cleanup.ts +76 -18
  450. package/src/memory/job-handlers/conversation-starters.ts +1 -4
  451. package/src/memory/job-handlers/embedding.test.ts +3 -2
  452. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
  453. package/src/memory/jobs/embed-pkb-file.ts +6 -1
  454. package/src/memory/jobs-store.ts +14 -0
  455. package/src/memory/jobs-worker.ts +66 -22
  456. package/src/memory/llm-request-log-source-clickhouse.ts +122 -2
  457. package/src/memory/llm-request-log-source-local.ts +31 -0
  458. package/src/memory/llm-request-log-source.ts +40 -2
  459. package/src/memory/llm-request-log-store.ts +228 -1
  460. package/src/memory/llm-usage-store.ts +24 -0
  461. package/src/memory/memory-retrospective-enqueue.ts +8 -1
  462. package/src/memory/memory-retrospective-job.ts +5 -0
  463. package/src/memory/memory-v2-activation-log-store.ts +110 -7
  464. package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
  465. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
  466. package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
  467. package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
  468. package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
  469. package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
  470. package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
  471. package/src/memory/migrations/index.ts +19 -0
  472. package/src/memory/migrations/registry.ts +33 -0
  473. package/src/memory/schema/conversations.ts +10 -2
  474. package/src/memory/schema/inference.ts +0 -1
  475. package/src/memory/schema/infrastructure.ts +21 -0
  476. package/src/memory/tool-usage-store.ts +36 -8
  477. package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
  478. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
  479. package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
  480. package/src/memory/v2/__tests__/harness-metrics.test.ts +83 -0
  481. package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
  482. package/src/memory/v2/__tests__/harness-replay-input.test.ts +230 -0
  483. package/src/memory/v2/__tests__/harness-runner.test.ts +135 -0
  484. package/src/memory/v2/__tests__/injection.test.ts +127 -98
  485. package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
  486. package/src/memory/v2/__tests__/router.test.ts +171 -3
  487. package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
  488. package/src/memory/v2/harness/compare.ts +57 -0
  489. package/src/memory/v2/harness/metrics.ts +128 -0
  490. package/src/memory/v2/harness/oracle.ts +145 -0
  491. package/src/memory/v2/harness/replay-input.ts +240 -0
  492. package/src/memory/v2/harness/retriever.ts +74 -0
  493. package/src/memory/v2/harness/router-retriever.ts +43 -0
  494. package/src/memory/v2/harness/runner.ts +112 -0
  495. package/src/memory/v2/harness/trace.ts +64 -0
  496. package/src/memory/v2/injection.ts +21 -15
  497. package/src/memory/v2/prompts/router.ts +26 -1
  498. package/src/memory/v2/qdrant.ts +14 -2
  499. package/src/memory/v2/router.ts +171 -18
  500. package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
  501. package/src/memory/v3/__tests__/consolidation-job.test.ts +466 -0
  502. package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
  503. package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
  504. package/src/memory/v3/__tests__/edges.test.ts +706 -0
  505. package/src/memory/v3/__tests__/filter.test.ts +560 -0
  506. package/src/memory/v3/__tests__/gate.test.ts +637 -0
  507. package/src/memory/v3/__tests__/index-composition.test.ts +291 -0
  508. package/src/memory/v3/__tests__/loop.test.ts +775 -0
  509. package/src/memory/v3/__tests__/retriever.test.ts +226 -0
  510. package/src/memory/v3/__tests__/scouts.test.ts +489 -0
  511. package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
  512. package/src/memory/v3/__tests__/shadow-middleware.test.ts +398 -0
  513. package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
  514. package/src/memory/v3/__tests__/traversal.test.ts +508 -0
  515. package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
  516. package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
  517. package/src/memory/v3/__tests__/tree-walk.test.ts +784 -0
  518. package/src/memory/v3/__tests__/validate.test.ts +277 -0
  519. package/src/memory/v3/auto-edges.ts +223 -0
  520. package/src/memory/v3/coactivation-store.ts +124 -0
  521. package/src/memory/v3/consolidation-job.ts +323 -0
  522. package/src/memory/v3/coretrieval-seed.ts +240 -0
  523. package/src/memory/v3/edge-learning-job.ts +160 -0
  524. package/src/memory/v3/edges.ts +286 -0
  525. package/src/memory/v3/filter.ts +286 -0
  526. package/src/memory/v3/gate.ts +349 -0
  527. package/src/memory/v3/index-composition.ts +126 -0
  528. package/src/memory/v3/llm-capture.ts +46 -0
  529. package/src/memory/v3/loop.ts +430 -0
  530. package/src/memory/v3/maintenance.ts +144 -0
  531. package/src/memory/v3/prompt-context.ts +33 -0
  532. package/src/memory/v3/prompts/consolidation.ts +458 -0
  533. package/src/memory/v3/prompts/system-prompts.ts +196 -0
  534. package/src/memory/v3/retriever.ts +33 -0
  535. package/src/memory/v3/scouts.ts +431 -0
  536. package/src/memory/v3/shadow-diff.ts +287 -0
  537. package/src/memory/v3/shadow-middleware.ts +347 -0
  538. package/src/memory/v3/traversal.ts +211 -0
  539. package/src/memory/v3/tree-index.ts +237 -0
  540. package/src/memory/v3/tree-store.ts +394 -0
  541. package/src/memory/v3/tree-walk.ts +356 -0
  542. package/src/memory/v3/types.ts +65 -0
  543. package/src/memory/v3/validate.ts +323 -0
  544. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
  545. package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
  546. package/src/notifications/adapters/macos.ts +18 -1
  547. package/src/notifications/adapters/platform.ts +1 -1
  548. package/src/notifications/adapters/slack.ts +45 -11
  549. package/src/notifications/broadcaster.ts +114 -63
  550. package/src/notifications/conversation-pairing.ts +23 -3
  551. package/src/notifications/decision-engine.ts +1 -4
  552. package/src/notifications/decisions-store.ts +32 -1
  553. package/src/notifications/deliveries-store.ts +45 -0
  554. package/src/notifications/edit-notification.ts +201 -0
  555. package/src/notifications/emit-signal.ts +40 -50
  556. package/src/notifications/signal.ts +10 -0
  557. package/src/notifications/types.ts +37 -0
  558. package/src/oauth/byo-connection.test.ts +67 -3
  559. package/src/oauth/byo-connection.ts +32 -5
  560. package/src/oauth/connect-orchestrator.ts +9 -0
  561. package/src/oauth/connection-resolver.test.ts +76 -0
  562. package/src/oauth/connection-resolver.ts +49 -10
  563. package/src/oauth/manual-token-connection.ts +51 -3
  564. package/src/oauth/seed-providers.ts +3 -0
  565. package/src/permissions/approval-policy.test.ts +19 -5
  566. package/src/permissions/approval-policy.ts +14 -3
  567. package/src/permissions/checker.ts +21 -8
  568. package/src/permissions/prompter.ts +3 -3
  569. package/src/permissions/question-prompter.ts +5 -2
  570. package/src/permissions/secret-prompter.ts +2 -2
  571. package/src/platform/client.test.ts +24 -1
  572. package/src/platform/client.ts +8 -0
  573. package/src/platform/feature-gate.ts +15 -0
  574. package/src/plugin-api/index.ts +4 -0
  575. package/src/plugin-api/types.ts +7 -33
  576. package/src/plugins/defaults/index.ts +6 -0
  577. package/src/plugins/defaults/injectors.ts +20 -19
  578. package/src/plugins/defaults/persistence.ts +25 -6
  579. package/src/plugins/external-plugin-loader.ts +5 -68
  580. package/src/plugins/types.ts +68 -29
  581. package/src/proactive-artifact/aux-message-injector.ts +17 -4
  582. package/src/proactive-artifact/job.test.ts +1 -0
  583. package/src/prompts/__tests__/system-prompt.test.ts +4 -4
  584. package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
  585. package/src/prompts/persona-resolver.ts +36 -21
  586. package/src/prompts/sections.ts +39 -7
  587. package/src/prompts/system-prompt.ts +84 -221
  588. package/src/prompts/template-detection.ts +10 -4
  589. package/src/prompts/templates/BOOTSTRAP.md +9 -13
  590. package/src/prompts/templates/IDENTITY.md +0 -2
  591. package/src/prompts/templates/system-sections.ts +230 -8
  592. package/src/providers/__tests__/connection-model-compat.test.ts +233 -0
  593. package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
  594. package/src/providers/__tests__/retry-callsite.test.ts +85 -5
  595. package/src/providers/anthropic/client.ts +32 -66
  596. package/src/providers/call-site-routing.ts +42 -6
  597. package/src/providers/connection-model-compat.ts +61 -0
  598. package/src/providers/connection-resolution.ts +47 -14
  599. package/src/providers/fireworks/client.ts +1 -0
  600. package/src/providers/gemini/client.ts +70 -6
  601. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
  602. package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
  603. package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
  604. package/src/providers/inference/adapter-factory.ts +3 -0
  605. package/src/providers/inference/auth.ts +0 -8
  606. package/src/providers/inference/connections.ts +3 -66
  607. package/src/providers/inference/resolve-auth.ts +2 -3
  608. package/src/providers/minimax/client.ts +106 -0
  609. package/src/providers/model-catalog.ts +78 -1
  610. package/src/providers/model-intents.ts +4 -4
  611. package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
  612. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -5
  613. package/src/providers/openai/chat-completions-provider.ts +116 -15
  614. package/src/providers/openai/codex-models.ts +20 -0
  615. package/src/providers/openai/responses-provider.ts +87 -30
  616. package/src/providers/openrouter/client.ts +13 -8
  617. package/src/providers/provider-send-message.ts +20 -5
  618. package/src/providers/registry.ts +48 -8
  619. package/src/providers/retry.ts +50 -7
  620. package/src/providers/search-provider-catalog.ts +17 -9
  621. package/src/providers/thinking-config.ts +26 -1
  622. package/src/providers/types.ts +9 -0
  623. package/src/providers/usage-tracking.ts +2 -0
  624. package/src/runtime/AGENTS.md +2 -2
  625. package/src/runtime/__tests__/agent-wake.test.ts +1 -0
  626. package/src/runtime/__tests__/background-job-runner.test.ts +1 -0
  627. package/src/runtime/access-request-helper.ts +1 -0
  628. package/src/runtime/agent-wake.ts +1 -0
  629. package/src/runtime/assistant-event-hub.ts +76 -6
  630. package/src/runtime/auth/route-policy.ts +46 -0
  631. package/src/runtime/btw-sidechain.ts +0 -6
  632. package/src/runtime/channel-readiness-service.ts +68 -0
  633. package/src/runtime/channel-reply-delivery.ts +23 -0
  634. package/src/runtime/channel-retry-sweep.ts +47 -14
  635. package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
  636. package/src/runtime/http-types.ts +0 -2
  637. package/src/runtime/migrations/vbundle-builder.ts +12 -4
  638. package/src/runtime/pending-interactions.ts +0 -1
  639. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -0
  640. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +406 -0
  641. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +204 -0
  642. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
  643. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
  644. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -50
  645. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +76 -9
  646. package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
  647. package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
  648. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
  649. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +294 -0
  650. package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
  651. package/src/runtime/routes/acp-routes-list.test.ts +3 -0
  652. package/src/runtime/routes/acp-routes.test.ts +255 -6
  653. package/src/runtime/routes/acp-routes.ts +8 -1
  654. package/src/runtime/routes/app-management-routes.ts +111 -4
  655. package/src/runtime/routes/avatar-routes.ts +10 -10
  656. package/src/runtime/routes/background-wake-routes.ts +356 -0
  657. package/src/runtime/routes/browser-tabs-routes.ts +200 -0
  658. package/src/runtime/routes/btw-routes.ts +4 -10
  659. package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
  660. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  661. package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
  662. package/src/runtime/routes/conversation-list-routes.ts +159 -4
  663. package/src/runtime/routes/conversation-management-routes.ts +108 -26
  664. package/src/runtime/routes/conversation-query-routes.ts +200 -44
  665. package/src/runtime/routes/conversation-routes.ts +409 -521
  666. package/src/runtime/routes/conversation-starter-routes.ts +6 -3
  667. package/src/runtime/routes/conversations-import-routes.ts +19 -6
  668. package/src/runtime/routes/disk-pressure-routes.ts +1 -1
  669. package/src/runtime/routes/documents-routes.ts +10 -1
  670. package/src/runtime/routes/domain-routes.ts +60 -10
  671. package/src/runtime/routes/email-routes.ts +5 -2
  672. package/src/runtime/routes/events-routes.ts +54 -10
  673. package/src/runtime/routes/group-routes.ts +35 -8
  674. package/src/runtime/routes/home-feed-routes.ts +129 -0
  675. package/src/runtime/routes/host-browser-routes.ts +10 -2
  676. package/src/runtime/routes/host-cu-routes.ts +2 -2
  677. package/src/runtime/routes/identity-intro-cache.ts +61 -16
  678. package/src/runtime/routes/identity-routes.ts +30 -9
  679. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
  680. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +530 -6
  681. package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -8
  682. package/src/runtime/routes/index.ts +10 -0
  683. package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
  684. package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
  685. package/src/runtime/routes/inference-provider-connection-routes.ts +5 -26
  686. package/src/runtime/routes/integrations/vercel.ts +15 -0
  687. package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
  688. package/src/runtime/routes/llm-context-normalization.ts +7 -2
  689. package/src/runtime/routes/memory-item-routes.ts +8 -3
  690. package/src/runtime/routes/memory-v2-routes.ts +215 -5
  691. package/src/runtime/routes/memory-v3-routes.ts +474 -0
  692. package/src/runtime/routes/migration-routes.ts +32 -28
  693. package/src/runtime/routes/notification-routes.ts +63 -1
  694. package/src/runtime/routes/oauth-commands-routes.ts +6 -1
  695. package/src/runtime/routes/plugins-routes.ts +337 -0
  696. package/src/runtime/routes/rename-conversation-routes.ts +6 -2
  697. package/src/runtime/routes/secret-routes.ts +25 -5
  698. package/src/runtime/routes/settings-routes.ts +12 -11
  699. package/src/runtime/routes/slack-channel-routes.ts +5 -4
  700. package/src/runtime/routes/surface-action-routes.ts +1 -38
  701. package/src/runtime/routes/surface-content-routes.ts +12 -5
  702. package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
  703. package/src/runtime/routes/wipe-conversation-routes.ts +3 -0
  704. package/src/runtime/routes/workspace-routes.ts +25 -10
  705. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -0
  706. package/src/runtime/slack-dm-text-delivery.ts +177 -0
  707. package/src/runtime/sync/resource-sync-events.ts +106 -38
  708. package/src/runtime/sync/sync-publisher.test.ts +49 -0
  709. package/src/runtime/sync/sync-publisher.ts +2 -1
  710. package/src/runtime/tool-grant-request-helper.ts +1 -0
  711. package/src/runtime/verification-outbound-actions.ts +73 -1
  712. package/src/schedule/schedule-store.ts +8 -1
  713. package/src/schedule/scheduler.ts +111 -15
  714. package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
  715. package/src/security/encrypted-store.ts +7 -16
  716. package/src/security/store-path-override.ts +61 -0
  717. package/src/signals/user-message.ts +5 -8
  718. package/src/skills/validate-input.ts +177 -0
  719. package/src/subagent/manager.ts +13 -13
  720. package/src/subagent/types.ts +6 -0
  721. package/src/tasks/tool-sanitizer.ts +2 -2
  722. package/src/telemetry/types.ts +12 -0
  723. package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
  724. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  725. package/src/tools/acp/spawn.test.ts +119 -0
  726. package/src/tools/acp/spawn.ts +15 -2
  727. package/src/tools/apps/definitions.ts +36 -28
  728. package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
  729. package/src/tools/ask-question/ask-question-tool.ts +38 -45
  730. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
  731. package/src/tools/browser/__tests__/pinned-tabs.test.ts +70 -0
  732. package/src/tools/browser/browser-execution.ts +16 -3
  733. package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
  734. package/src/tools/browser/cdp-client/__tests__/types.test.ts +3 -0
  735. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +12 -0
  736. package/src/tools/browser/cdp-client/extension-cdp-client.ts +27 -1
  737. package/src/tools/browser/cdp-client/factory.ts +100 -17
  738. package/src/tools/browser/cdp-client/local-cdp-client.ts +12 -0
  739. package/src/tools/browser/cdp-client/types.ts +65 -0
  740. package/src/tools/browser/pinned-tabs.ts +96 -40
  741. package/src/tools/computer-use/definitions.ts +282 -336
  742. package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
  743. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
  744. package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
  745. package/src/tools/credentials/vault.ts +3 -9
  746. package/src/tools/document/document-tool.ts +189 -7
  747. package/src/tools/execution-target.ts +18 -23
  748. package/src/tools/executor.ts +24 -56
  749. package/src/tools/filesystem/edit.ts +3 -9
  750. package/src/tools/filesystem/list.ts +3 -9
  751. package/src/tools/filesystem/read.ts +3 -9
  752. package/src/tools/filesystem/write.ts +3 -9
  753. package/src/tools/host-filesystem/edit.test.ts +1 -0
  754. package/src/tools/host-filesystem/edit.ts +3 -9
  755. package/src/tools/host-filesystem/read.test.ts +1 -0
  756. package/src/tools/host-filesystem/read.ts +3 -9
  757. package/src/tools/host-filesystem/transfer.test.ts +31 -6
  758. package/src/tools/host-filesystem/transfer.ts +3 -9
  759. package/src/tools/host-filesystem/write.test.ts +1 -0
  760. package/src/tools/host-filesystem/write.ts +3 -9
  761. package/src/tools/host-terminal/host-shell.ts +3 -9
  762. package/src/tools/mcp/mcp-tool-factory.ts +1 -10
  763. package/src/tools/memory/register.test.ts +1 -1
  764. package/src/tools/memory/register.ts +4 -9
  765. package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
  766. package/src/tools/network/__tests__/web-search.test.ts +211 -3
  767. package/src/tools/network/managed-search-proxy.ts +183 -0
  768. package/src/tools/network/web-fetch.ts +3 -9
  769. package/src/tools/network/web-search.ts +224 -76
  770. package/src/tools/policy-context.ts +3 -1
  771. package/src/tools/registry.ts +150 -123
  772. package/src/tools/schedule/create.ts +1 -1
  773. package/src/tools/schema-transforms.ts +1 -1
  774. package/src/tools/skills/execute.ts +3 -9
  775. package/src/tools/skills/load.ts +3 -9
  776. package/src/tools/skills/skill-tool-factory.ts +18 -44
  777. package/src/tools/subagent/notify-parent.ts +3 -9
  778. package/src/tools/subagent/spawn.ts +3 -0
  779. package/src/tools/system/request-permission.ts +3 -9
  780. package/src/tools/terminal/shell.ts +3 -9
  781. package/src/tools/tool-approval-handler.ts +10 -4
  782. package/src/tools/tool-defaults.ts +94 -0
  783. package/src/tools/tool-name-aliases.ts +72 -14
  784. package/src/tools/types.ts +32 -101
  785. package/src/tools/ui-surface/definitions.ts +104 -108
  786. package/src/types/onboarding-context.ts +6 -0
  787. package/src/usage/attribution.ts +32 -1
  788. package/src/usage/pricing.ts +23 -0
  789. package/src/usage/types.ts +12 -0
  790. package/src/util/browser.ts +7 -2
  791. package/src/util/logger.ts +16 -7
  792. package/src/util/platform.ts +7 -2
  793. package/src/util/sqlite3-runtime.ts +65 -0
  794. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
  795. package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
  796. package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +109 -0
  797. package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
  798. package/src/workspace/migrations/registry.ts +6 -0
  799. package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
  800. package/src/__tests__/message-complete-display-id.test.ts +0 -175
  801. package/src/daemon/query-complexity-router.ts +0 -75
  802. package/src/prompts/cache-boundary.ts +0 -8
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Tests for self-echo suppression in `AssistantEventHub`.
3
+ *
4
+ * Validates:
5
+ * - hub.publish(event, { excludeClientId }) skips the matching client
6
+ * subscriber and delivers to every other matching subscriber.
7
+ * - Suppression is unconditional: it applies whether the broadcast is
8
+ * untargeted, conversation-scoped, or capability-targeted.
9
+ * - `broadcastMessage(sync_changed { originClientId })` derives the
10
+ * exclusion from the message itself — no caller wiring needed.
11
+ * - `broadcastMessage(sync_changed)` without an originClientId fans out
12
+ * to every subscriber (the daemon-internal emit path).
13
+ * - Process-type subscribers are never excluded by a clientId match.
14
+ */
15
+ import { describe, expect, test } from "bun:test";
16
+
17
+ import type { AssistantEvent } from "../runtime/assistant-event.js";
18
+ import {
19
+ AssistantEventHub,
20
+ assistantEventHub,
21
+ broadcastMessage,
22
+ } from "../runtime/assistant-event-hub.js";
23
+
24
+ function makeSyncChangedEvent(originClientId?: string): AssistantEvent {
25
+ return {
26
+ id: "evt_test_sync",
27
+ conversationId: undefined,
28
+ emittedAt: "2026-05-03T00:00:00.000Z",
29
+ message: {
30
+ type: "sync_changed",
31
+ tags: ["conversation:abc:messages"],
32
+ ...(originClientId ? { originClientId } : {}),
33
+ },
34
+ };
35
+ }
36
+
37
+ describe("AssistantEventHub — self-echo suppression (excludeClientId)", () => {
38
+ test("skips the named client and delivers to every other client", async () => {
39
+ const hub = new AssistantEventHub();
40
+ const receivedA: AssistantEvent[] = [];
41
+ const receivedB: AssistantEvent[] = [];
42
+ const receivedC: AssistantEvent[] = [];
43
+
44
+ hub.subscribe({
45
+ type: "client",
46
+ clientId: "client-a",
47
+ interfaceId: "web",
48
+ capabilities: [],
49
+ callback: (e) => {
50
+ receivedA.push(e);
51
+ },
52
+ });
53
+
54
+ hub.subscribe({
55
+ type: "client",
56
+ clientId: "client-b",
57
+ interfaceId: "web",
58
+ capabilities: [],
59
+ callback: (e) => {
60
+ receivedB.push(e);
61
+ },
62
+ });
63
+
64
+ hub.subscribe({
65
+ type: "client",
66
+ clientId: "client-c",
67
+ interfaceId: "macos",
68
+ capabilities: [],
69
+ callback: (e) => {
70
+ receivedC.push(e);
71
+ },
72
+ });
73
+
74
+ await hub.publish(makeSyncChangedEvent("client-a"), {
75
+ excludeClientId: "client-a",
76
+ });
77
+
78
+ expect(receivedA).toHaveLength(0);
79
+ expect(receivedB).toHaveLength(1);
80
+ expect(receivedC).toHaveLength(1);
81
+ });
82
+
83
+ test("delivers to every subscriber when excludeClientId is omitted", async () => {
84
+ const hub = new AssistantEventHub();
85
+ const receivedA: AssistantEvent[] = [];
86
+ const receivedB: AssistantEvent[] = [];
87
+
88
+ hub.subscribe({
89
+ type: "client",
90
+ clientId: "client-a",
91
+ interfaceId: "web",
92
+ capabilities: [],
93
+ callback: (e) => {
94
+ receivedA.push(e);
95
+ },
96
+ });
97
+ hub.subscribe({
98
+ type: "client",
99
+ clientId: "client-b",
100
+ interfaceId: "web",
101
+ capabilities: [],
102
+ callback: (e) => {
103
+ receivedB.push(e);
104
+ },
105
+ });
106
+
107
+ await hub.publish(makeSyncChangedEvent());
108
+
109
+ expect(receivedA).toHaveLength(1);
110
+ expect(receivedB).toHaveLength(1);
111
+ });
112
+
113
+ test("excludeClientId does not match process-type subscribers", async () => {
114
+ const hub = new AssistantEventHub();
115
+ const receivedProcess: AssistantEvent[] = [];
116
+
117
+ // A process subscriber sits in the same hub as a client whose id
118
+ // matches `excludeClientId`. It must never be suppressed because
119
+ // `excludeClientId` only matches `type: "client"` entries — process
120
+ // entries have no `clientId` field at all.
121
+ hub.subscribe({
122
+ type: "process",
123
+ callback: (e) => {
124
+ receivedProcess.push(e);
125
+ },
126
+ });
127
+
128
+ await hub.publish(makeSyncChangedEvent("client-a"), {
129
+ excludeClientId: "client-a",
130
+ });
131
+
132
+ expect(receivedProcess).toHaveLength(1);
133
+ });
134
+
135
+ test("excludeClientId composes with conversation-scoped subscribers", async () => {
136
+ const hub = new AssistantEventHub();
137
+ const receivedA: AssistantEvent[] = [];
138
+ const receivedB: AssistantEvent[] = [];
139
+
140
+ hub.subscribe({
141
+ type: "client",
142
+ clientId: "client-a",
143
+ interfaceId: "web",
144
+ capabilities: [],
145
+ filter: { conversationId: "sess_x" },
146
+ callback: (e) => {
147
+ receivedA.push(e);
148
+ },
149
+ });
150
+ hub.subscribe({
151
+ type: "client",
152
+ clientId: "client-b",
153
+ interfaceId: "web",
154
+ capabilities: [],
155
+ filter: { conversationId: "sess_x" },
156
+ callback: (e) => {
157
+ receivedB.push(e);
158
+ },
159
+ });
160
+
161
+ // Scoped event for sess_x; both clients filter to sess_x; exclude A.
162
+ const event: AssistantEvent = {
163
+ id: "evt_scoped",
164
+ conversationId: "sess_x",
165
+ emittedAt: "2026-05-03T00:00:00.000Z",
166
+ message: {
167
+ type: "sync_changed",
168
+ tags: ["conversation:sess_x:messages"],
169
+ originClientId: "client-a",
170
+ },
171
+ };
172
+
173
+ await hub.publish(event, { excludeClientId: "client-a" });
174
+
175
+ expect(receivedA).toHaveLength(0);
176
+ expect(receivedB).toHaveLength(1);
177
+ });
178
+ });
179
+
180
+ describe("broadcastMessage — derives excludeClientId from sync_changed.originClientId", () => {
181
+ test("skips the originating client when originClientId is present", async () => {
182
+ const receivedA: AssistantEvent[] = [];
183
+ const receivedB: AssistantEvent[] = [];
184
+
185
+ const subA = assistantEventHub.subscribe({
186
+ type: "client",
187
+ clientId: "broadcast-a",
188
+ interfaceId: "web",
189
+ capabilities: [],
190
+ callback: (e) => {
191
+ receivedA.push(e);
192
+ },
193
+ });
194
+ const subB = assistantEventHub.subscribe({
195
+ type: "client",
196
+ clientId: "broadcast-b",
197
+ interfaceId: "web",
198
+ capabilities: [],
199
+ callback: (e) => {
200
+ receivedB.push(e);
201
+ },
202
+ });
203
+
204
+ try {
205
+ broadcastMessage({
206
+ type: "sync_changed",
207
+ tags: ["resource:test"],
208
+ originClientId: "broadcast-a",
209
+ });
210
+ // broadcastMessage queues onto a microtask chain — yield until it
211
+ // drains. Two awaits cover the publish promise + its `.then` chain.
212
+ await new Promise((r) => setTimeout(r, 0));
213
+ await new Promise((r) => setTimeout(r, 0));
214
+
215
+ expect(receivedA).toHaveLength(0);
216
+ expect(receivedB).toHaveLength(1);
217
+ } finally {
218
+ subA.dispose();
219
+ subB.dispose();
220
+ }
221
+ });
222
+
223
+ test("fans out to every client when originClientId is absent", async () => {
224
+ const receivedA: AssistantEvent[] = [];
225
+ const receivedB: AssistantEvent[] = [];
226
+
227
+ const subA = assistantEventHub.subscribe({
228
+ type: "client",
229
+ clientId: "broadcast-c",
230
+ interfaceId: "web",
231
+ capabilities: [],
232
+ callback: (e) => {
233
+ receivedA.push(e);
234
+ },
235
+ });
236
+ const subB = assistantEventHub.subscribe({
237
+ type: "client",
238
+ clientId: "broadcast-d",
239
+ interfaceId: "web",
240
+ capabilities: [],
241
+ callback: (e) => {
242
+ receivedB.push(e);
243
+ },
244
+ });
245
+
246
+ try {
247
+ broadcastMessage({
248
+ type: "sync_changed",
249
+ tags: ["resource:test"],
250
+ });
251
+ await new Promise((r) => setTimeout(r, 0));
252
+ await new Promise((r) => setTimeout(r, 0));
253
+
254
+ expect(receivedA).toHaveLength(1);
255
+ expect(receivedB).toHaveLength(1);
256
+ } finally {
257
+ subA.dispose();
258
+ subB.dispose();
259
+ }
260
+ });
261
+
262
+ test("ignores an empty-string originClientId (treats as absent)", async () => {
263
+ const receivedA: AssistantEvent[] = [];
264
+
265
+ const subA = assistantEventHub.subscribe({
266
+ type: "client",
267
+ clientId: "broadcast-e",
268
+ interfaceId: "web",
269
+ capabilities: [],
270
+ callback: (e) => {
271
+ receivedA.push(e);
272
+ },
273
+ });
274
+
275
+ try {
276
+ broadcastMessage({
277
+ type: "sync_changed",
278
+ tags: ["resource:test"],
279
+ // Exercise the length-zero guard. `originClientId?: string` accepts
280
+ // empty strings at the type level, but production code path can't
281
+ // produce one — `buildSyncChangedMessage` trims and drops empty
282
+ // values before calling `broadcastMessage`.
283
+ originClientId: "",
284
+ });
285
+ await new Promise((r) => setTimeout(r, 0));
286
+ await new Promise((r) => setTimeout(r, 0));
287
+
288
+ expect(receivedA).toHaveLength(1);
289
+ } finally {
290
+ subA.dispose();
291
+ }
292
+ });
293
+ });
@@ -4,7 +4,7 @@
4
4
  * Covers:
5
5
  * - Missing persisted value falls back to code default
6
6
  * - Protected feature-flags.json is the sole override mechanism
7
- * - Undeclared keys default to enabled
7
+ * - Undeclared keys default to disabled
8
8
  */
9
9
  import { afterEach, beforeEach, describe, expect, test } from "bun:test";
10
10
 
@@ -14,10 +14,11 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
14
14
 
15
15
  const DECLARED_FLAG_ID = "email-channel";
16
16
  const DECLARED_FLAG_KEY = DECLARED_FLAG_ID;
17
- const SAFE_STORAGE_LIMITS_FLAG = "safe-storage-limits";
18
17
 
19
- const { isAssistantFeatureFlagEnabled, _setOverridesForTesting } =
18
+ const { isAssistantFeatureFlagEnabled } =
20
19
  await import("../config/assistant-feature-flags.js");
20
+ const { setOverridesForTesting } =
21
+ await import("./feature-flag-test-helpers.js");
21
22
  const { skillFlagKey } = await import("../config/skill-state.js");
22
23
 
23
24
  // ---------------------------------------------------------------------------
@@ -25,11 +26,11 @@ const { skillFlagKey } = await import("../config/skill-state.js");
25
26
  // ---------------------------------------------------------------------------
26
27
 
27
28
  beforeEach(() => {
28
- _setOverridesForTesting({});
29
+ setOverridesForTesting({});
29
30
  });
30
31
 
31
32
  afterEach(() => {
32
- _setOverridesForTesting({});
33
+ setOverridesForTesting({});
33
34
  });
34
35
 
35
36
  // ---------------------------------------------------------------------------
@@ -38,14 +39,14 @@ afterEach(() => {
38
39
 
39
40
  describe("isAssistantFeatureFlagEnabled", () => {
40
41
  test("reads from file-based overrides", () => {
41
- _setOverridesForTesting({ [DECLARED_FLAG_KEY]: true });
42
+ setOverridesForTesting({ [DECLARED_FLAG_KEY]: true });
42
43
  const config = {} as any;
43
44
 
44
45
  expect(isAssistantFeatureFlagEnabled(DECLARED_FLAG_KEY, config)).toBe(true);
45
46
  });
46
47
 
47
48
  test("explicit false override in file-based overrides", () => {
48
- _setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
49
+ setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
49
50
  const config = {} as any;
50
51
 
51
52
  expect(isAssistantFeatureFlagEnabled(DECLARED_FLAG_KEY, config)).toBe(
@@ -63,31 +64,14 @@ describe("isAssistantFeatureFlagEnabled", () => {
63
64
  );
64
65
  });
65
66
 
66
- test("safe-storage-limits defaults to disabled", () => {
67
+ test("unknown flag defaults to false when no persisted override", () => {
67
68
  const config = {} as any;
68
69
 
69
- expect(
70
- isAssistantFeatureFlagEnabled(SAFE_STORAGE_LIMITS_FLAG, config),
71
- ).toBe(false);
72
- });
73
-
74
- test("safe-storage-limits respects explicit override", () => {
75
- _setOverridesForTesting({ [SAFE_STORAGE_LIMITS_FLAG]: true });
76
- const config = {} as any;
77
-
78
- expect(
79
- isAssistantFeatureFlagEnabled(SAFE_STORAGE_LIMITS_FLAG, config),
80
- ).toBe(true);
81
- });
82
-
83
- test("unknown flag defaults to true when no persisted override", () => {
84
- const config = {} as any;
85
-
86
- expect(isAssistantFeatureFlagEnabled("unknown-skill", config)).toBe(true);
70
+ expect(isAssistantFeatureFlagEnabled("unknown-skill", config)).toBe(false);
87
71
  });
88
72
 
89
73
  test("undeclared flag respects persisted override", () => {
90
- _setOverridesForTesting({ "some-undeclared-flag": false });
74
+ setOverridesForTesting({ "some-undeclared-flag": false });
91
75
  const config = {} as any;
92
76
 
93
77
  expect(isAssistantFeatureFlagEnabled("some-undeclared-flag", config)).toBe(
@@ -98,7 +82,7 @@ describe("isAssistantFeatureFlagEnabled", () => {
98
82
 
99
83
  describe("isAssistantFeatureFlagEnabled with skillFlagKey", () => {
100
84
  test("resolves skill flag via canonical path", () => {
101
- _setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
85
+ setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
102
86
  const config = {} as any;
103
87
 
104
88
  expect(
@@ -12,13 +12,13 @@ mock.module("../util/logger.js", () => ({
12
12
  }),
13
13
  }));
14
14
 
15
- import { resetDb } from "../memory/db-connection.js";
16
15
  import { getSqlite } from "../memory/db-connection.js";
17
16
  import { initializeDb } from "../memory/db-init.js";
18
17
  import {
19
18
  getRecentInvocations,
20
19
  rotateToolInvocations,
21
20
  } from "../memory/tool-usage-store.js";
21
+ import { resetDbForTesting } from "./db-test-helpers.js";
22
22
 
23
23
  // ---------------------------------------------------------------------------
24
24
  // Helpers
@@ -57,7 +57,7 @@ const ONE_DAY_MS = 24 * 60 * 60 * 1000;
57
57
 
58
58
  describe("audit log rotation", () => {
59
59
  beforeAll(() => {
60
- resetDb();
60
+ resetDbForTesting();
61
61
  initializeDb();
62
62
  // Insert a conversations row so FK-enforced ORM inserts succeed
63
63
  getSqlite().run(
@@ -69,72 +69,126 @@ describe("audit log rotation", () => {
69
69
  clearTable();
70
70
  });
71
71
 
72
- test("returns 0 when retentionDays is 0 (retain forever)", () => {
72
+ test("returns 0 when retentionDays is 0 (retain forever)", async () => {
73
73
  addInvocation(100 * ONE_DAY_MS); // 100 days old
74
- const deleted = rotateToolInvocations(0);
74
+ const deleted = await rotateToolInvocations(0);
75
75
  expect(deleted).toBe(0);
76
76
  expect(getRecentInvocations(100).length).toBe(1);
77
77
  });
78
78
 
79
- test("returns 0 when retentionDays is negative", () => {
79
+ test("returns 0 when retentionDays is negative", async () => {
80
80
  addInvocation(100 * ONE_DAY_MS);
81
- const deleted = rotateToolInvocations(-5);
81
+ const deleted = await rotateToolInvocations(-5);
82
82
  expect(deleted).toBe(0);
83
83
  expect(getRecentInvocations(100).length).toBe(1);
84
84
  });
85
85
 
86
- test("deletes records older than retentionDays", () => {
86
+ test("deletes records older than retentionDays", async () => {
87
87
  addInvocation(10 * ONE_DAY_MS); // 10 days old — should be deleted with 7-day retention
88
88
  addInvocation(3 * ONE_DAY_MS); // 3 days old — should be kept
89
89
  addInvocation(1 * ONE_DAY_MS); // 1 day old — should be kept
90
90
 
91
- const deleted = rotateToolInvocations(7);
91
+ const deleted = await rotateToolInvocations(7);
92
92
  expect(deleted).toBe(1);
93
93
  expect(getRecentInvocations(100).length).toBe(2);
94
94
  });
95
95
 
96
- test("keeps all records when none exceed retention", () => {
96
+ test("keeps all records when none exceed retention", async () => {
97
97
  addInvocation(1 * ONE_DAY_MS);
98
98
  addInvocation(2 * ONE_DAY_MS);
99
99
  addInvocation(3 * ONE_DAY_MS);
100
100
 
101
- const deleted = rotateToolInvocations(30);
101
+ const deleted = await rotateToolInvocations(30);
102
102
  expect(deleted).toBe(0);
103
103
  expect(getRecentInvocations(100).length).toBe(3);
104
104
  });
105
105
 
106
- test("deletes all records when all exceed retention", () => {
106
+ test("deletes all records when all exceed retention", async () => {
107
107
  addInvocation(60 * ONE_DAY_MS);
108
108
  addInvocation(90 * ONE_DAY_MS);
109
109
  addInvocation(120 * ONE_DAY_MS);
110
110
 
111
- const deleted = rotateToolInvocations(30);
111
+ const deleted = await rotateToolInvocations(30);
112
112
  expect(deleted).toBe(3);
113
113
  expect(getRecentInvocations(100).length).toBe(0);
114
114
  });
115
115
 
116
- test("returns 0 when table is empty", () => {
117
- const deleted = rotateToolInvocations(7);
116
+ test("returns 0 when table is empty", async () => {
117
+ const deleted = await rotateToolInvocations(7);
118
118
  expect(deleted).toBe(0);
119
119
  });
120
120
 
121
- test("handles 1-day retention (deletes everything older than 24h)", () => {
121
+ test("handles 1-day retention (deletes everything older than 24h)", async () => {
122
122
  addInvocation(2 * ONE_DAY_MS); // 2 days old — delete
123
123
  addInvocation(12 * 60 * 60 * 1000); // 12 hours old — keep
124
124
 
125
- const deleted = rotateToolInvocations(1);
125
+ const deleted = await rotateToolInvocations(1);
126
126
  expect(deleted).toBe(1);
127
127
  expect(getRecentInvocations(100).length).toBe(1);
128
128
  });
129
129
 
130
- test("works with recordToolInvocation (via ORM)", () => {
130
+ test("works with recordToolInvocation (via ORM)", async () => {
131
131
  // Use raw SQL to insert (avoids db singleton issues in parallel test runs)
132
132
  // and verify the rotation/query functions work correctly with it
133
133
  addInvocation(0); // just-created record
134
134
 
135
135
  // This record was just created, so it should not be rotated
136
- const deleted = rotateToolInvocations(1);
136
+ const deleted = await rotateToolInvocations(1);
137
137
  expect(deleted).toBe(0);
138
138
  expect(getRecentInvocations(100).length).toBe(1);
139
139
  });
140
+
141
+ test(
142
+ "yields to the event loop while the purge is in flight (anti-block)",
143
+ async () => {
144
+ // Seed a few thousand rows so the DELETE has measurable
145
+ // subprocess work behind the scenes.
146
+ const ROW_COUNT = 2000;
147
+ const past = 100 * ONE_DAY_MS;
148
+ const sqlite = getSqlite();
149
+ sqlite.exec("BEGIN");
150
+ try {
151
+ for (let i = 0; i < ROW_COUNT; i++) {
152
+ addInvocation(past);
153
+ }
154
+ sqlite.exec("COMMIT");
155
+ } catch (err) {
156
+ sqlite.exec("ROLLBACK");
157
+ throw err;
158
+ }
159
+
160
+ // Race the purge against a `setImmediate` ping. The ping
161
+ // resolves on the very next event-loop iteration after it is
162
+ // scheduled.
163
+ //
164
+ // If the purge is async (subprocess), `rotateToolInvocations`
165
+ // returns a pending Promise immediately; the ping wins the race
166
+ // while the subprocess is still running.
167
+ //
168
+ // If the purge is ever regressed back to a synchronous DELETE,
169
+ // `rotateToolInvocations` blocks the main thread for the full
170
+ // DELETE duration. `setImmediate` cannot fire until the main
171
+ // thread releases, so the purge's already-resolved Promise
172
+ // beats the ping through the microtask queue and "purge" wins.
173
+ //
174
+ // The signal is deterministic regardless of how fast the
175
+ // subprocess is or how busy the event loop is.
176
+ const ping = new Promise<"ping">((resolve) =>
177
+ setImmediate(() => resolve("ping")),
178
+ );
179
+ const purgePromise = rotateToolInvocations(7);
180
+ const winner = await Promise.race([
181
+ ping,
182
+ purgePromise.then(() => "purge" as const),
183
+ ]);
184
+
185
+ expect(winner).toBe("ping");
186
+
187
+ // Drain the purge so the log + subprocess cleanup complete
188
+ // before the test exits.
189
+ const deleted = await purgePromise;
190
+ expect(deleted).toBe(ROW_COUNT);
191
+ },
192
+ 60_000,
193
+ );
140
194
  });
@@ -130,7 +130,6 @@ mock.module("../runtime/services/analyze-conversation.js", () => ({
130
130
 
131
131
  // ── Real imports ──────────────────────────────────────────────────
132
132
 
133
- import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
134
133
  import { conversationAnalyzeJob } from "../memory/conversation-analyze-job.js";
135
134
  import { createConversation } from "../memory/conversation-crud.js";
136
135
  import { getDb } from "../memory/db-connection.js";
@@ -138,6 +137,7 @@ import { initializeDb } from "../memory/db-init.js";
138
137
  import { indexMessageNow } from "../memory/indexer.js";
139
138
  import type { MemoryJob } from "../memory/jobs-store.js";
140
139
  import { conversations, memoryJobs, messages } from "../memory/schema.js";
140
+ import { setOverridesForTesting } from "./feature-flag-test-helpers.js";
141
141
 
142
142
  // ── Helpers ───────────────────────────────────────────────────────
143
143
 
@@ -279,14 +279,14 @@ beforeEach(() => {
279
279
  resetTables();
280
280
  analyzeCalls.length = 0;
281
281
  // Clear any stale feature-flag overrides between tests.
282
- _setOverridesForTesting({});
282
+ setOverridesForTesting({});
283
283
  });
284
284
 
285
285
  // ─────────────────────────────────────────────────────────────────
286
286
 
287
287
  describe("auto-analysis end-to-end trigger path", () => {
288
288
  test("flag on, batch threshold reached → conversation_analyze enqueued, handler runs, analysis conversation created", async () => {
289
- _setOverridesForTesting({ "auto-analyze": true });
289
+ setOverridesForTesting({ "auto-analyze": true });
290
290
 
291
291
  const source = createConversation("source-conv");
292
292
 
@@ -329,7 +329,7 @@ describe("auto-analysis end-to-end trigger path", () => {
329
329
  });
330
330
 
331
331
  test("flag off → no conversation_analyze job is ever enqueued", async () => {
332
- _setOverridesForTesting({ "auto-analyze": false });
332
+ setOverridesForTesting({ "auto-analyze": false });
333
333
 
334
334
  const source = createConversation("source-conv-flag-off");
335
335
  await indexMessages(source.id, 3);
@@ -343,7 +343,7 @@ describe("auto-analysis end-to-end trigger path", () => {
343
343
  });
344
344
 
345
345
  test("recursion guard: indexing into an auto-analysis conversation does not enqueue conversation_analyze or graph_extract", async () => {
346
- _setOverridesForTesting({ "auto-analyze": true });
346
+ setOverridesForTesting({ "auto-analyze": true });
347
347
 
348
348
  // Set up an auto-analysis conversation directly. This is the
349
349
  // scenario we need to protect against — the analysis agent writes
@@ -392,7 +392,7 @@ describe("auto-analysis batch trigger uses analysis.batchSize cadence", () => {
392
392
  const originalV2Enabled = TEST_CONFIG.memory.v2.enabled;
393
393
 
394
394
  beforeEach(() => {
395
- _setOverridesForTesting({ "auto-analyze": true });
395
+ setOverridesForTesting({ "auto-analyze": true });
396
396
  // memory.v2.enabled gates v1 graph_extract enqueue; force off so
397
397
  // these cadence tests can observe the v1 path.
398
398
  TEST_CONFIG.memory.v2.enabled = false;
@@ -1,5 +1,7 @@
1
1
  import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
+ import { createMockLoggerModule } from "./helpers/mock-logger.js";
4
+
3
5
  // Default the warm-pool gate to OPEN — these tests probe background-job
4
6
  // disk-pressure behavior, not the pre-first-message guard.
5
7
  mock.module("../runtime/pre-first-message-gate.js", () => ({
@@ -7,14 +9,7 @@ mock.module("../runtime/pre-first-message-gate.js", () => ({
7
9
  _resetPreFirstMessageGateCacheForTests: () => {},
8
10
  }));
9
11
 
10
- mock.module("../util/logger.js", () => ({
11
- getLogger: () => ({
12
- info: () => {},
13
- debug: () => {},
14
- warn: () => {},
15
- error: () => {},
16
- }),
17
- }));
12
+ mock.module("../util/logger.js", () => createMockLoggerModule());
18
13
 
19
14
  mock.module("../config/loader.js", () => ({
20
15
  getConfig: () => ({
@@ -108,7 +103,6 @@ mock.module("../memory/conversation-crud.js", () => ({
108
103
  addMessage: mock(() => ({ id: "msg-1" })),
109
104
  archiveConversation: mock(() => true),
110
105
  batchSetDisplayOrders: mock(() => {}),
111
- clearStrippedInjectionMetadataForConversation: mock(() => {}),
112
106
  createConversation: (opts: { conversationType: string }) => {
113
107
  createdConversations.push(opts);
114
108
  return { id: "conv-1", ...opts };
@@ -116,7 +110,7 @@ mock.module("../memory/conversation-crud.js", () => ({
116
110
  countConversationsByScheduleJobId: mock(() => 0),
117
111
  countMessagesAfter: mock(() => 0),
118
112
  deleteMessageById: mock(() => {}),
119
- clearAll: mock(() => ({ conversations: 0, messages: 0 })),
113
+ clearAll: mock(async () => ({ conversations: 0, messages: 0 })),
120
114
  deleteConversation: mock(() => ({ memoryIds: [] })),
121
115
  deleteLastExchange: mock(() => 0),
122
116
  findAnalysisConversationFor: mock(() => null),
@@ -156,8 +150,10 @@ mock.module("../memory/conversation-crud.js", () => ({
156
150
  updateConversationTitle: mock(() => {}),
157
151
  updateConversationUsage: mock(() => {}),
158
152
  setLastNotifiedInferenceProfile: mock(() => {}),
159
- setConversationCleanedAt: mock(() => {}),
153
+ setConversationHistoryStrippedAt: mock(() => {}),
160
154
  wipeConversation: mock(() => ({ memoryIds: [] })),
155
+ reserveMessage: mock(async () => ({ id: "msg-reserve" })),
156
+ extractImageSourcePaths: () => undefined,
161
157
  }));
162
158
 
163
159
  mock.module("../memory/conversation-title-service.js", () => ({
@@ -182,6 +178,7 @@ mock.module("../memory/jobs-store.js", () => ({
182
178
  failStalledJobs: mockFailStalledJobs,
183
179
  getMemoryJobCounts: mock(() => ({})),
184
180
  hasActiveJobOfType: mock(() => false),
181
+ isMemoryEnabled: () => true,
185
182
  resetRunningJobsToPending: mock(() => 0),
186
183
  SLOW_LLM_JOB_TYPES: [],
187
184
  upsertAutoAnalysisJob: mock(() => "job-auto-analysis"),