@vellumai/assistant 0.8.3 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (665) hide show
  1. package/ARCHITECTURE.md +2 -2
  2. package/docker-entrypoint.sh +0 -1
  3. package/docs/browser-use-architecture-phase2.md +1 -1
  4. package/knip.json +2 -1
  5. package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
  6. package/openapi.yaml +1492 -100
  7. package/package.json +1 -1
  8. package/src/__tests__/agent-loop-exit-reason.test.ts +4 -5
  9. package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
  10. package/src/__tests__/agent-loop.test.ts +88 -3
  11. package/src/__tests__/anthropic-provider.test.ts +302 -33
  12. package/src/__tests__/approval-cascade.test.ts +1 -1
  13. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
  14. package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
  15. package/src/__tests__/audit-log-rotation.test.ts +70 -16
  16. package/src/__tests__/background-workers-disk-pressure.test.ts +4 -3
  17. package/src/__tests__/btw-routes.test.ts +2 -3
  18. package/src/__tests__/call-controller.test.ts +0 -1
  19. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  20. package/src/__tests__/channel-delivery-store.test.ts +193 -0
  21. package/src/__tests__/channel-guardian.test.ts +3 -3
  22. package/src/__tests__/channel-reply-delivery.test.ts +284 -5
  23. package/src/__tests__/channel-retry-sweep.test.ts +274 -1
  24. package/src/__tests__/checker.test.ts +6 -15
  25. package/src/__tests__/compaction-events.test.ts +2 -1
  26. package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
  27. package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
  28. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
  29. package/src/__tests__/computer-use-tools.test.ts +2 -4
  30. package/src/__tests__/config-watcher.test.ts +1 -1
  31. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  32. package/src/__tests__/context-token-estimator.test.ts +91 -1
  33. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
  34. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
  35. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +55 -4
  36. package/src/__tests__/conversation-agent-loop-overflow.test.ts +228 -8
  37. package/src/__tests__/conversation-agent-loop.test.ts +188 -129
  38. package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
  39. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
  40. package/src/__tests__/conversation-clean-command.test.ts +137 -0
  41. package/src/__tests__/conversation-clear-safety.test.ts +25 -25
  42. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
  43. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  44. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  45. package/src/__tests__/conversation-error.test.ts +31 -0
  46. package/src/__tests__/conversation-fork-crud.test.ts +324 -0
  47. package/src/__tests__/conversation-lifecycle.test.ts +53 -12
  48. package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
  49. package/src/__tests__/conversation-load-history-stripped.test.ts +279 -0
  50. package/src/__tests__/conversation-pairing.test.ts +2 -2
  51. package/src/__tests__/conversation-process-callsite.test.ts +1 -1
  52. package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -1
  53. package/src/__tests__/conversation-queue.test.ts +1 -1
  54. package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
  55. package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
  56. package/src/__tests__/conversation-runtime-assembly.test.ts +264 -81
  57. package/src/__tests__/conversation-seed-composer.test.ts +66 -4
  58. package/src/__tests__/conversation-skill-tools.test.ts +2 -5
  59. package/src/__tests__/conversation-slash-commands.test.ts +36 -8
  60. package/src/__tests__/conversation-slash-queue.test.ts +1 -1
  61. package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
  62. package/src/__tests__/conversation-speed-override.test.ts +1 -1
  63. package/src/__tests__/conversation-store.test.ts +1 -1
  64. package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
  65. package/src/__tests__/conversation-sync-tags.test.ts +99 -32
  66. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -1
  67. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  68. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  69. package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
  70. package/src/__tests__/credential-execution-tools.test.ts +6 -6
  71. package/src/__tests__/credential-security-invariants.test.ts +7 -0
  72. package/src/__tests__/credential-vault-unit.test.ts +2 -2
  73. package/src/__tests__/cu-unified-flow.test.ts +10 -1
  74. package/src/__tests__/dm-backfill.test.ts +64 -0
  75. package/src/__tests__/dm-persistence.test.ts +33 -0
  76. package/src/__tests__/document-find-replace.test.ts +501 -0
  77. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  78. package/src/__tests__/email-html-renderer.test.ts +12 -0
  79. package/src/__tests__/first-greeting.test.ts +23 -2
  80. package/src/__tests__/gateway-flag-listener.test.ts +237 -0
  81. package/src/__tests__/gemini-provider.test.ts +78 -0
  82. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  83. package/src/__tests__/guardian-outbound-http.test.ts +7 -5
  84. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  85. package/src/__tests__/headless-browser-navigate.test.ts +172 -0
  86. package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
  87. package/src/__tests__/heartbeat-service.test.ts +4 -0
  88. package/src/__tests__/host-bash-proxy.test.ts +6 -0
  89. package/src/__tests__/host-browser-proxy.test.ts +10 -0
  90. package/src/__tests__/host-cu-proxy.test.ts +8 -1
  91. package/src/__tests__/host-file-proxy.test.ts +8 -1
  92. package/src/__tests__/host-shell-tool.test.ts +1 -1
  93. package/src/__tests__/host-transfer-proxy.test.ts +8 -1
  94. package/src/__tests__/identity-routes.test.ts +57 -0
  95. package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
  96. package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
  97. package/src/__tests__/injector-chain.test.ts +2 -0
  98. package/src/__tests__/injector-document-comments.test.ts +378 -0
  99. package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
  100. package/src/__tests__/list-messages-attachments.test.ts +21 -17
  101. package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
  102. package/src/__tests__/list-messages-page-latest.test.ts +130 -14
  103. package/src/__tests__/list-messages-tool-merge.test.ts +77 -17
  104. package/src/__tests__/llm-context-normalization.test.ts +0 -2
  105. package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
  106. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
  107. package/src/__tests__/llm-resolver.test.ts +161 -9
  108. package/src/__tests__/llm-usage-store.test.ts +66 -0
  109. package/src/__tests__/log-export-routes.test.ts +99 -2
  110. package/src/__tests__/logger.test.ts +89 -0
  111. package/src/__tests__/mcp-abort-signal.test.ts +2 -2
  112. package/src/__tests__/media-generate-image.test.ts +31 -0
  113. package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
  114. package/src/__tests__/message-queue-steer.test.ts +114 -0
  115. package/src/__tests__/model-intents.test.ts +2 -4
  116. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  117. package/src/__tests__/onboarding-template-contract.test.ts +1 -1
  118. package/src/__tests__/openai-provider.test.ts +151 -0
  119. package/src/__tests__/openai-responses-provider.test.ts +118 -16
  120. package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
  121. package/src/__tests__/pending-interactions-resolved-event.test.ts +189 -0
  122. package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
  123. package/src/__tests__/platform.test.ts +2 -5
  124. package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
  125. package/src/__tests__/plugin-bootstrap.test.ts +2 -2
  126. package/src/__tests__/plugin-source-watcher.test.ts +302 -0
  127. package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
  128. package/src/__tests__/plugin-types.test.ts +3 -2
  129. package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
  130. package/src/__tests__/pricing.test.ts +12 -0
  131. package/src/__tests__/process-message-background-slack.test.ts +1 -51
  132. package/src/__tests__/process-message-display-content.test.ts +21 -16
  133. package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
  134. package/src/__tests__/registry.test.ts +2 -8
  135. package/src/__tests__/require-fresh-approval.test.ts +2 -2
  136. package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
  137. package/src/__tests__/server-history-render.test.ts +83 -4
  138. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  139. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  140. package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
  141. package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
  142. package/src/__tests__/skill-tool-factory.test.ts +1 -1
  143. package/src/__tests__/steer-tool-repair.test.ts +249 -0
  144. package/src/__tests__/subagent-notify-parent.test.ts +1 -1
  145. package/src/__tests__/suggestion-routes.test.ts +1 -0
  146. package/src/__tests__/sync-message-contract.test.ts +59 -0
  147. package/src/__tests__/system-prompt.test.ts +161 -124
  148. package/src/__tests__/terminal-tools.test.ts +12 -2
  149. package/src/__tests__/thinking-block-replay.test.ts +113 -0
  150. package/src/__tests__/thread-backfill.test.ts +370 -22
  151. package/src/__tests__/tool-approval-handler.test.ts +1 -5
  152. package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
  153. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
  154. package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
  155. package/src/__tests__/tool-executor.test.ts +89 -53
  156. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
  157. package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
  158. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  159. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
  160. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  161. package/src/__tests__/twilio-routes.test.ts +1 -1
  162. package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
  163. package/src/__tests__/usage-routes.test.ts +3 -0
  164. package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
  165. package/src/__tests__/web-fetch.test.ts +2 -2
  166. package/src/__tests__/workspace-git-service.test.ts +94 -10
  167. package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
  168. package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
  169. package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
  170. package/src/acp/prepare-agent-env.ts +78 -0
  171. package/src/acp/session-manager.ts +1 -1
  172. package/src/agent/attachments.ts +1 -0
  173. package/src/agent/loop.ts +65 -20
  174. package/src/api/README.md +5 -0
  175. package/src/api/index.ts +4 -0
  176. package/src/api/package.json +10 -0
  177. package/src/background-wake/background-wake-routes.test.ts +233 -0
  178. package/src/background-wake/next-wake.test.ts +289 -0
  179. package/src/background-wake/next-wake.ts +172 -0
  180. package/src/background-wake/runtime-registry.ts +24 -0
  181. package/src/browser/operations.ts +15 -0
  182. package/src/cli/commands/__tests__/browser.test.ts +23 -5
  183. package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
  184. package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
  185. package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
  186. package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
  187. package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
  188. package/src/cli/commands/__tests__/memory-v2.test.ts +10 -12
  189. package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
  190. package/src/cli/commands/browser.ts +247 -0
  191. package/src/cli/commands/conversations.ts +128 -1
  192. package/src/cli/commands/domain.ts +91 -41
  193. package/src/cli/commands/inference-providers.ts +147 -1
  194. package/src/cli/commands/inference.ts +93 -40
  195. package/src/cli/commands/memory-v2-compare-render.ts +115 -0
  196. package/src/cli/commands/memory-v2.ts +483 -0
  197. package/src/cli/commands/memory-v3-render.ts +344 -0
  198. package/src/cli/commands/memory-v3.ts +316 -0
  199. package/src/cli/commands/notifications.ts +24 -2
  200. package/src/cli/program.ts +2 -0
  201. package/src/cli/utils/conversation-id.ts +17 -5
  202. package/src/config/assistant-feature-flags.ts +21 -9
  203. package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
  204. package/src/config/bundled-skills/document-editor/SKILL.md +124 -0
  205. package/src/config/bundled-skills/document-editor/TOOLS.json +258 -0
  206. package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
  207. package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
  208. package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
  209. package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
  210. package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
  211. package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
  212. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  213. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
  214. package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
  215. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
  216. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
  217. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
  218. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
  219. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
  220. package/src/config/bundled-skills/schedule/SKILL.md +8 -0
  221. package/src/config/bundled-tool-registry.ts +24 -12
  222. package/src/config/call-site-defaults.ts +20 -0
  223. package/src/config/feature-flag-registry.json +115 -3
  224. package/src/config/llm-resolver.ts +16 -2
  225. package/src/config/schemas/__tests__/memory-v2.test.ts +217 -1
  226. package/src/config/schemas/call-site-catalog.ts +35 -0
  227. package/src/config/schemas/llm.ts +14 -0
  228. package/src/config/schemas/memory-v2.ts +294 -1
  229. package/src/config/schemas/memory.ts +2 -1
  230. package/src/context/compactor.ts +60 -1
  231. package/src/context/token-estimator.ts +47 -4
  232. package/src/context/window-manager.ts +25 -0
  233. package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
  234. package/src/conversations/message-consolidation.ts +404 -0
  235. package/src/credential-health/credential-health-service.ts +34 -19
  236. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
  237. package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
  238. package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
  239. package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
  240. package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
  241. package/src/daemon/conversation-agent-loop-handlers.ts +155 -36
  242. package/src/daemon/conversation-agent-loop.ts +307 -88
  243. package/src/daemon/conversation-error.ts +31 -1
  244. package/src/daemon/conversation-lifecycle.ts +149 -118
  245. package/src/daemon/conversation-messaging.ts +3 -0
  246. package/src/daemon/conversation-process.ts +273 -0
  247. package/src/daemon/conversation-queue-manager.ts +14 -0
  248. package/src/daemon/conversation-runtime-assembly.ts +145 -84
  249. package/src/daemon/conversation-slash.ts +37 -5
  250. package/src/daemon/conversation-surfaces.ts +45 -2
  251. package/src/daemon/conversation-tool-setup.ts +70 -3
  252. package/src/daemon/conversation-usage.ts +2 -0
  253. package/src/daemon/conversation.ts +54 -32
  254. package/src/daemon/disk-pressure-guard.ts +14 -2
  255. package/src/daemon/first-greeting.ts +10 -0
  256. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
  257. package/src/daemon/handlers/config-a2a.ts +160 -0
  258. package/src/daemon/handlers/config-model.test.ts +2 -0
  259. package/src/daemon/handlers/conversations.ts +90 -3
  260. package/src/daemon/handlers/shared.ts +92 -29
  261. package/src/daemon/host-bash-proxy.ts +1 -1
  262. package/src/daemon/host-browser-proxy.ts +5 -5
  263. package/src/daemon/host-cu-proxy.ts +5 -5
  264. package/src/daemon/host-file-proxy.ts +5 -5
  265. package/src/daemon/host-proxy-base.ts +4 -4
  266. package/src/daemon/host-transfer-proxy.ts +11 -11
  267. package/src/daemon/lifecycle.ts +40 -23
  268. package/src/daemon/meet-manifest-loader.ts +1 -7
  269. package/src/daemon/message-protocol.ts +4 -0
  270. package/src/daemon/message-types/conversations.ts +14 -9
  271. package/src/daemon/message-types/document-comments.ts +50 -0
  272. package/src/daemon/message-types/home.ts +1 -13
  273. package/src/daemon/message-types/messages.ts +66 -7
  274. package/src/daemon/message-types/surfaces.ts +3 -1
  275. package/src/daemon/message-types/sync.ts +14 -0
  276. package/src/daemon/message-types/web-activity.ts +57 -0
  277. package/src/daemon/plugin-source-watcher.ts +135 -3
  278. package/src/daemon/process-message.ts +69 -12
  279. package/src/daemon/shutdown-handlers.ts +24 -5
  280. package/src/daemon/switch-inference-profile-tool.ts +52 -0
  281. package/src/daemon/tool-setup-types.ts +13 -0
  282. package/src/daemon/trust-context.ts +6 -0
  283. package/src/documents/document-comments-store.test.ts +338 -0
  284. package/src/documents/document-comments-store.ts +237 -0
  285. package/src/documents/document-store.ts +202 -0
  286. package/src/events/relationship-state-updated.ts +25 -0
  287. package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -2
  288. package/src/heartbeat/heartbeat-service.ts +1 -0
  289. package/src/home/__tests__/suggested-prompts.test.ts +33 -2
  290. package/src/home/feed-types.ts +6 -1
  291. package/src/home/home-content-refresh.ts +52 -0
  292. package/src/home/home-greeting-cache.ts +69 -0
  293. package/src/home/home-greeting.ts +85 -0
  294. package/src/home/suggested-prompts.ts +168 -9
  295. package/src/ipc/gateway-flag-listener.ts +123 -0
  296. package/src/ipc/skill-routes/registries.ts +8 -12
  297. package/src/memory/__tests__/db-async-query.test.ts +165 -0
  298. package/src/memory/__tests__/db-maintenance.test.ts +115 -0
  299. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
  300. package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
  301. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
  302. package/src/memory/__tests__/memory-retrospective-job.test.ts +327 -6
  303. package/src/memory/auto-analysis-enqueue.ts +5 -1
  304. package/src/memory/conversation-crud.ts +191 -100
  305. package/src/memory/conversation-starters-cadence.ts +3 -1
  306. package/src/memory/conversation-title-service.ts +19 -3
  307. package/src/memory/db-async-query.ts +214 -0
  308. package/src/memory/db-init.ts +26 -0
  309. package/src/memory/db-maintenance.ts +30 -21
  310. package/src/memory/delivery-crud.ts +41 -0
  311. package/src/memory/delivery-status.ts +141 -15
  312. package/src/memory/external-conversation-store.ts +32 -1
  313. package/src/memory/graph/bootstrap.ts +8 -1
  314. package/src/memory/graph/capability-seed.ts +7 -3
  315. package/src/memory/graph/conversation-graph-memory.ts +100 -17
  316. package/src/memory/graph/extraction.ts +1 -5
  317. package/src/memory/graph/graph-search.ts +7 -1
  318. package/src/memory/indexer.ts +28 -18
  319. package/src/memory/job-handlers/cleanup.ts +76 -18
  320. package/src/memory/job-handlers/conversation-starters.ts +1 -4
  321. package/src/memory/jobs/embed-pkb-file.ts +6 -1
  322. package/src/memory/jobs-store.ts +14 -0
  323. package/src/memory/jobs-worker.ts +68 -15
  324. package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
  325. package/src/memory/llm-request-log-source-local.ts +7 -0
  326. package/src/memory/llm-request-log-source.ts +9 -2
  327. package/src/memory/llm-request-log-store.ts +43 -1
  328. package/src/memory/llm-usage-store.ts +24 -0
  329. package/src/memory/memory-retrospective-constants.ts +28 -0
  330. package/src/memory/memory-retrospective-enqueue.ts +11 -3
  331. package/src/memory/memory-retrospective-job.ts +413 -18
  332. package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
  333. package/src/memory/memory-v2-activation-log-store.ts +41 -14
  334. package/src/memory/migrations/100-core-tables.ts +1 -0
  335. package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
  336. package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
  337. package/src/memory/migrations/253-document-comments.ts +47 -0
  338. package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
  339. package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
  340. package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
  341. package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
  342. package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
  343. package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
  344. package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
  345. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
  346. package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
  347. package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
  348. package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
  349. package/src/memory/migrations/index.ts +34 -0
  350. package/src/memory/migrations/registry.ts +58 -0
  351. package/src/memory/onboarding-events-store.ts +7 -0
  352. package/src/memory/schema/calls.ts +1 -0
  353. package/src/memory/schema/conversations.ts +3 -0
  354. package/src/memory/schema/infrastructure.ts +22 -0
  355. package/src/memory/tool-usage-store.ts +36 -8
  356. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
  357. package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
  358. package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
  359. package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
  360. package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
  361. package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
  362. package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
  363. package/src/memory/v2/__tests__/injection.test.ts +158 -112
  364. package/src/memory/v2/__tests__/page-index.test.ts +365 -1
  365. package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
  366. package/src/memory/v2/__tests__/router.test.ts +660 -4
  367. package/src/memory/v2/consolidation-job.ts +14 -0
  368. package/src/memory/v2/harness/compare.ts +57 -0
  369. package/src/memory/v2/harness/metrics.ts +124 -0
  370. package/src/memory/v2/harness/oracle.ts +145 -0
  371. package/src/memory/v2/harness/replay-input.ts +224 -0
  372. package/src/memory/v2/harness/retriever.ts +74 -0
  373. package/src/memory/v2/harness/router-retriever.ts +43 -0
  374. package/src/memory/v2/harness/runner.ts +106 -0
  375. package/src/memory/v2/harness/trace.ts +58 -0
  376. package/src/memory/v2/injection-events.ts +101 -0
  377. package/src/memory/v2/injection.ts +42 -25
  378. package/src/memory/v2/page-index.ts +209 -7
  379. package/src/memory/v2/page-store.ts +18 -0
  380. package/src/memory/v2/prompts/router.ts +26 -1
  381. package/src/memory/v2/qdrant.ts +14 -2
  382. package/src/memory/v2/router.ts +369 -62
  383. package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
  384. package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
  385. package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
  386. package/src/memory/v3/__tests__/edges.test.ts +563 -0
  387. package/src/memory/v3/__tests__/filter.test.ts +512 -0
  388. package/src/memory/v3/__tests__/gate.test.ts +574 -0
  389. package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
  390. package/src/memory/v3/__tests__/loop.test.ts +530 -0
  391. package/src/memory/v3/__tests__/retriever.test.ts +226 -0
  392. package/src/memory/v3/__tests__/scouts.test.ts +440 -0
  393. package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
  394. package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
  395. package/src/memory/v3/__tests__/traversal.test.ts +469 -0
  396. package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
  397. package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
  398. package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
  399. package/src/memory/v3/__tests__/validate.test.ts +245 -0
  400. package/src/memory/v3/auto-edges.ts +223 -0
  401. package/src/memory/v3/coactivation-store.ts +124 -0
  402. package/src/memory/v3/consolidation-job.ts +323 -0
  403. package/src/memory/v3/edge-learning-job.ts +160 -0
  404. package/src/memory/v3/edges.ts +249 -0
  405. package/src/memory/v3/filter.ts +281 -0
  406. package/src/memory/v3/gate.ts +334 -0
  407. package/src/memory/v3/index-composition.ts +113 -0
  408. package/src/memory/v3/llm-capture.ts +46 -0
  409. package/src/memory/v3/loop.ts +382 -0
  410. package/src/memory/v3/maintenance.ts +144 -0
  411. package/src/memory/v3/prompt-context.ts +33 -0
  412. package/src/memory/v3/prompts/consolidation.ts +458 -0
  413. package/src/memory/v3/prompts/system-prompts.ts +196 -0
  414. package/src/memory/v3/retriever.ts +33 -0
  415. package/src/memory/v3/scouts.ts +420 -0
  416. package/src/memory/v3/shadow-middleware.ts +305 -0
  417. package/src/memory/v3/traversal.ts +206 -0
  418. package/src/memory/v3/tree-index.ts +237 -0
  419. package/src/memory/v3/tree-store.ts +394 -0
  420. package/src/memory/v3/tree-walk.ts +351 -0
  421. package/src/memory/v3/types.ts +65 -0
  422. package/src/memory/v3/validate.ts +300 -0
  423. package/src/messaging/providers/index.ts +7 -1
  424. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
  425. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
  426. package/src/messaging/providers/slack/adapter.ts +178 -25
  427. package/src/messaging/providers/slack/api.test.ts +54 -0
  428. package/src/messaging/providers/slack/api.ts +119 -3
  429. package/src/messaging/providers/slack/client.ts +12 -0
  430. package/src/messaging/providers/slack/deep-link.ts +20 -1
  431. package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
  432. package/src/messaging/providers/slack/message-metadata.ts +156 -0
  433. package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
  434. package/src/messaging/providers/slack/render-transcript.ts +176 -49
  435. package/src/messaging/providers/slack/send.test.ts +77 -0
  436. package/src/messaging/providers/slack/send.ts +8 -2
  437. package/src/messaging/providers/slack/types.ts +14 -0
  438. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +4 -1
  439. package/src/notifications/__tests__/home-feed-side-effect.test.ts +116 -54
  440. package/src/notifications/adapters/macos.ts +18 -1
  441. package/src/notifications/adapters/platform.ts +1 -1
  442. package/src/notifications/conversation-seed-composer.ts +14 -2
  443. package/src/notifications/decision-engine.ts +1 -4
  444. package/src/notifications/deferred-emit.ts +135 -0
  445. package/src/notifications/emit-signal.ts +38 -50
  446. package/src/notifications/home-feed-side-effect.ts +60 -30
  447. package/src/oauth/connect-orchestrator.ts +3 -0
  448. package/src/oauth/credential-token-resolver.ts +2 -0
  449. package/src/oauth/manual-token-connection.ts +19 -0
  450. package/src/oauth/oauth-store.ts +12 -0
  451. package/src/oauth/seed-providers.ts +22 -0
  452. package/src/permissions/prompter.ts +8 -5
  453. package/src/permissions/question-prompter.ts +5 -2
  454. package/src/permissions/secret-prompter.ts +6 -3
  455. package/src/plugin-api/index.ts +4 -0
  456. package/src/plugin-api/types.ts +7 -33
  457. package/src/plugins/defaults/index.ts +6 -0
  458. package/src/plugins/defaults/injectors.ts +100 -20
  459. package/src/plugins/external-plugin-loader.ts +5 -68
  460. package/src/plugins/types.ts +11 -16
  461. package/src/proactive-artifact/aux-message-injector.ts +17 -4
  462. package/src/prompts/__tests__/system-prompt.test.ts +46 -2
  463. package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
  464. package/src/prompts/normalize-onboarding.ts +40 -0
  465. package/src/prompts/persona-resolver.ts +36 -21
  466. package/src/prompts/sections.ts +69 -19
  467. package/src/prompts/system-prompt.ts +118 -216
  468. package/src/prompts/template-detection.ts +37 -0
  469. package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
  470. package/src/prompts/templates/BOOTSTRAP.md +10 -2
  471. package/src/prompts/templates/VOICE.md +3 -0
  472. package/src/prompts/templates/system-sections.ts +281 -9
  473. package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
  474. package/src/providers/__tests__/retry-callsite.test.ts +85 -5
  475. package/src/providers/anthropic/client.ts +159 -66
  476. package/src/providers/call-site-routing.ts +14 -2
  477. package/src/providers/connection-model-compat.ts +38 -0
  478. package/src/providers/connection-resolution.ts +16 -2
  479. package/src/providers/fireworks/client.ts +20 -2
  480. package/src/providers/gemini/client.ts +49 -6
  481. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
  482. package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
  483. package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
  484. package/src/providers/inference/adapter-factory.ts +18 -1
  485. package/src/providers/inference/auth.ts +3 -3
  486. package/src/providers/inference/codex-token-refresh.ts +128 -0
  487. package/src/providers/inference/resolve-auth.ts +49 -6
  488. package/src/providers/minimax/client.ts +106 -0
  489. package/src/providers/model-catalog.ts +91 -1
  490. package/src/providers/model-intents.ts +1 -1
  491. package/src/providers/openai/chat-completions-provider.ts +63 -23
  492. package/src/providers/openai/codex-models.ts +18 -0
  493. package/src/providers/openai/responses-provider.ts +86 -23
  494. package/src/providers/openrouter/client.ts +5 -1
  495. package/src/providers/provider-send-message.ts +7 -1
  496. package/src/providers/retry.ts +34 -3
  497. package/src/providers/thinking-config.ts +26 -1
  498. package/src/providers/types.ts +25 -0
  499. package/src/providers/usage-tracking.ts +2 -0
  500. package/src/runtime/AGENTS.md +2 -2
  501. package/src/runtime/__tests__/agent-wake.test.ts +214 -0
  502. package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
  503. package/src/runtime/agent-wake.ts +152 -56
  504. package/src/runtime/assistant-event-hub.ts +76 -6
  505. package/src/runtime/auth/route-policy.ts +43 -3
  506. package/src/runtime/background-job-runner.ts +26 -0
  507. package/src/runtime/btw-sidechain.ts +0 -6
  508. package/src/runtime/channel-reply-delivery.ts +182 -47
  509. package/src/runtime/channel-retry-sweep.ts +141 -16
  510. package/src/runtime/http-types.ts +7 -6
  511. package/src/runtime/migrations/vbundle-builder.ts +10 -3
  512. package/src/runtime/pending-interactions.ts +50 -8
  513. package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
  514. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +161 -1
  515. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
  516. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +290 -0
  517. package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
  518. package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
  519. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
  520. package/src/runtime/routes/acp-routes.test.ts +255 -6
  521. package/src/runtime/routes/acp-routes.ts +8 -1
  522. package/src/runtime/routes/approval-routes.ts +4 -1
  523. package/src/runtime/routes/avatar-routes.ts +10 -10
  524. package/src/runtime/routes/background-wake-routes.ts +188 -0
  525. package/src/runtime/routes/browser-tabs-routes.ts +200 -0
  526. package/src/runtime/routes/btw-routes.ts +0 -6
  527. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
  528. package/src/runtime/routes/content-source-routes.ts +78 -0
  529. package/src/runtime/routes/conversation-cli-routes.ts +147 -2
  530. package/src/runtime/routes/conversation-list-routes.ts +12 -4
  531. package/src/runtime/routes/conversation-management-routes.ts +77 -20
  532. package/src/runtime/routes/conversation-query-routes.ts +196 -31
  533. package/src/runtime/routes/conversation-routes.ts +472 -425
  534. package/src/runtime/routes/conversation-starter-routes.ts +6 -3
  535. package/src/runtime/routes/disk-pressure-routes.ts +1 -1
  536. package/src/runtime/routes/document-comments-routes.ts +287 -0
  537. package/src/runtime/routes/documents-routes.ts +33 -0
  538. package/src/runtime/routes/domain-routes.ts +60 -10
  539. package/src/runtime/routes/email-routes.ts +5 -2
  540. package/src/runtime/routes/events-routes.ts +54 -10
  541. package/src/runtime/routes/group-routes.ts +24 -8
  542. package/src/runtime/routes/home-feed-routes.ts +6 -3
  543. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  544. package/src/runtime/routes/host-browser-routes.ts +17 -2
  545. package/src/runtime/routes/host-cu-routes.ts +2 -2
  546. package/src/runtime/routes/identity-routes.ts +21 -0
  547. package/src/runtime/routes/inbound-message-handler.ts +288 -58
  548. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
  549. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
  550. package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
  551. package/src/runtime/routes/index.ts +20 -4
  552. package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
  553. package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
  554. package/src/runtime/routes/inference-provider-connection-routes.ts +63 -7
  555. package/src/runtime/routes/integrations/a2a.ts +60 -1
  556. package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
  557. package/src/runtime/routes/log-export-routes.ts +39 -0
  558. package/src/runtime/routes/memory-item-routes.ts +8 -3
  559. package/src/runtime/routes/memory-v2-routes.ts +427 -0
  560. package/src/runtime/routes/memory-v3-routes.ts +316 -0
  561. package/src/runtime/routes/migration-routes.ts +21 -24
  562. package/src/runtime/routes/notification-routes.ts +19 -2
  563. package/src/runtime/routes/plugins-routes.ts +337 -0
  564. package/src/runtime/routes/question-routes.ts +4 -1
  565. package/src/runtime/routes/rename-conversation-routes.ts +6 -2
  566. package/src/runtime/routes/sanity-routes.ts +159 -0
  567. package/src/runtime/routes/secret-routes.ts +25 -5
  568. package/src/runtime/routes/settings-routes.ts +12 -11
  569. package/src/runtime/routes/slack-channel-routes.ts +188 -0
  570. package/src/runtime/routes/workspace-routes.ts +25 -10
  571. package/src/runtime/services/conversation-serializer.ts +30 -4
  572. package/src/runtime/sync/resource-sync-events.ts +106 -38
  573. package/src/runtime/sync/sync-publisher.test.ts +49 -0
  574. package/src/runtime/sync/sync-publisher.ts +2 -1
  575. package/src/runtime/verification-outbound-actions.ts +73 -1
  576. package/src/schedule/integration-status.ts +3 -1
  577. package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
  578. package/src/security/oauth2-device-code.ts +307 -0
  579. package/src/security/oauth2.ts +26 -9
  580. package/src/security/secure-keys.ts +5 -0
  581. package/src/skills/catalog-install.ts +6 -2
  582. package/src/telemetry/types.ts +12 -0
  583. package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
  584. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  585. package/src/tools/acp/spawn.test.ts +119 -0
  586. package/src/tools/acp/spawn.ts +15 -2
  587. package/src/tools/apps/definitions.ts +2 -8
  588. package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
  589. package/src/tools/ask-question/ask-question-tool.ts +38 -45
  590. package/src/tools/browser/__tests__/pinned-tabs.test.ts +150 -0
  591. package/src/tools/browser/browser-execution.ts +106 -0
  592. package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
  593. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
  594. package/src/tools/browser/cdp-client/__tests__/types.test.ts +4 -0
  595. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +22 -0
  596. package/src/tools/browser/cdp-client/extension-cdp-client.ts +42 -2
  597. package/src/tools/browser/cdp-client/factory.ts +171 -4
  598. package/src/tools/browser/cdp-client/local-cdp-client.ts +21 -0
  599. package/src/tools/browser/cdp-client/types.ts +101 -0
  600. package/src/tools/browser/pinned-tabs.ts +146 -0
  601. package/src/tools/computer-use/definitions.ts +22 -78
  602. package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
  603. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
  604. package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
  605. package/src/tools/credentials/vault.ts +3 -9
  606. package/src/tools/document/document-comment-tool.test.ts +379 -0
  607. package/src/tools/document/document-comment-tool.ts +156 -0
  608. package/src/tools/document/document-tool.ts +187 -2
  609. package/src/tools/execution-target.ts +21 -23
  610. package/src/tools/executor.ts +6 -1
  611. package/src/tools/filesystem/edit.ts +3 -9
  612. package/src/tools/filesystem/list.ts +3 -9
  613. package/src/tools/filesystem/read.ts +3 -9
  614. package/src/tools/filesystem/write.ts +3 -9
  615. package/src/tools/host-filesystem/edit.ts +3 -9
  616. package/src/tools/host-filesystem/read.ts +3 -9
  617. package/src/tools/host-filesystem/transfer.ts +3 -9
  618. package/src/tools/host-filesystem/write.ts +3 -9
  619. package/src/tools/host-terminal/host-shell.ts +3 -9
  620. package/src/tools/mcp/mcp-tool-factory.ts +1 -8
  621. package/src/tools/memory/register.test.ts +1 -1
  622. package/src/tools/memory/register.ts +4 -9
  623. package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
  624. package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
  625. package/src/tools/network/domain-normalize.ts +17 -0
  626. package/src/tools/network/web-fetch.ts +216 -73
  627. package/src/tools/network/web-search.ts +216 -98
  628. package/src/tools/registry.ts +7 -23
  629. package/src/tools/schema-transforms.ts +1 -1
  630. package/src/tools/skills/execute.ts +3 -9
  631. package/src/tools/skills/load.ts +3 -9
  632. package/src/tools/skills/skill-tool-factory.ts +1 -8
  633. package/src/tools/subagent/notify-parent.ts +3 -9
  634. package/src/tools/system/request-permission.ts +3 -9
  635. package/src/tools/terminal/safe-env.ts +3 -2
  636. package/src/tools/terminal/shell.ts +3 -9
  637. package/src/tools/tool-approval-handler.ts +19 -12
  638. package/src/tools/tool-defaults.ts +94 -0
  639. package/src/tools/types.ts +31 -98
  640. package/src/tools/ui-surface/definitions.ts +9 -23
  641. package/src/types/onboarding-context.ts +4 -0
  642. package/src/usage/pricing.ts +23 -0
  643. package/src/usage/types.ts +12 -0
  644. package/src/util/__tests__/favicon.test.ts +84 -0
  645. package/src/util/favicon.ts +40 -0
  646. package/src/util/logger.ts +16 -7
  647. package/src/util/platform.ts +7 -7
  648. package/src/util/sqlite3-runtime.ts +65 -0
  649. package/src/workspace/git-service.ts +75 -4
  650. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
  651. package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
  652. package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
  653. package/src/workspace/migrations/registry.ts +4 -0
  654. package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
  655. package/src/__tests__/message-complete-display-id.test.ts +0 -175
  656. package/src/config/bundled-skills/document/SKILL.md +0 -54
  657. package/src/config/bundled-skills/document/TOOLS.json +0 -106
  658. package/src/daemon/seed-files.ts +0 -18
  659. package/src/prompts/cache-boundary.ts +0 -8
  660. package/src/runtime/routes/interface-routes.ts +0 -43
  661. /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
  662. /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
  663. /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
  664. /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
  665. /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
@@ -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
 
@@ -80,10 +80,10 @@ describe("isAssistantFeatureFlagEnabled", () => {
80
80
  ).toBe(true);
81
81
  });
82
82
 
83
- test("unknown flag defaults to true when no persisted override", () => {
83
+ test("unknown flag defaults to false when no persisted override", () => {
84
84
  const config = {} as any;
85
85
 
86
- expect(isAssistantFeatureFlagEnabled("unknown-skill", config)).toBe(true);
86
+ expect(isAssistantFeatureFlagEnabled("unknown-skill", config)).toBe(false);
87
87
  });
88
88
 
89
89
  test("undeclared flag respects persisted override", () => {
@@ -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
  });
@@ -108,7 +108,6 @@ mock.module("../memory/conversation-crud.js", () => ({
108
108
  addMessage: mock(() => ({ id: "msg-1" })),
109
109
  archiveConversation: mock(() => true),
110
110
  batchSetDisplayOrders: mock(() => {}),
111
- clearStrippedInjectionMetadataForConversation: mock(() => {}),
112
111
  createConversation: (opts: { conversationType: string }) => {
113
112
  createdConversations.push(opts);
114
113
  return { id: "conv-1", ...opts };
@@ -116,7 +115,7 @@ mock.module("../memory/conversation-crud.js", () => ({
116
115
  countConversationsByScheduleJobId: mock(() => 0),
117
116
  countMessagesAfter: mock(() => 0),
118
117
  deleteMessageById: mock(() => {}),
119
- clearAll: mock(() => ({ conversations: 0, messages: 0 })),
118
+ clearAll: mock(async () => ({ conversations: 0, messages: 0 })),
120
119
  deleteConversation: mock(() => ({ memoryIds: [] })),
121
120
  deleteLastExchange: mock(() => 0),
122
121
  findAnalysisConversationFor: mock(() => null),
@@ -131,7 +130,6 @@ mock.module("../memory/conversation-crud.js", () => ({
131
130
  getConversationSource: () => null,
132
131
  getAssistantMessageIdsInTurn: () => [],
133
132
  getDisplayMetaForConversations: () => new Map(),
134
- getLastAssistantTimestampBefore: () => null,
135
133
  getLastUserTimestampBefore: () => null,
136
134
  getMessageById: () => null,
137
135
  getMessages: () => [],
@@ -156,6 +154,8 @@ mock.module("../memory/conversation-crud.js", () => ({
156
154
  updateConversationSlackContextWatermark: mock(() => {}),
157
155
  updateConversationTitle: mock(() => {}),
158
156
  updateConversationUsage: mock(() => {}),
157
+ setLastNotifiedInferenceProfile: mock(() => {}),
158
+ setConversationHistoryStrippedAt: mock(() => {}),
159
159
  wipeConversation: mock(() => ({ memoryIds: [] })),
160
160
  }));
161
161
 
@@ -181,6 +181,7 @@ mock.module("../memory/jobs-store.js", () => ({
181
181
  failStalledJobs: mockFailStalledJobs,
182
182
  getMemoryJobCounts: mock(() => ({})),
183
183
  hasActiveJobOfType: mock(() => false),
184
+ isMemoryEnabled: () => true,
184
185
  resetRunningJobsToPending: mock(() => 0),
185
186
  SLOW_LLM_JOB_TYPES: [],
186
187
  upsertAutoAnalysisJob: mock(() => "job-auto-analysis"),
@@ -317,12 +317,11 @@ describe("POST /v1/btw", () => {
317
317
 
318
318
  expect(tools).toEqual(MOCK_TOOLS);
319
319
  expect(systemPrompt).toBe(MOCK_SYSTEM_PROMPT);
320
+ // Persona is resolved internally now; btw-routes no longer plumbs
321
+ // it through to buildSystemPrompt.
320
322
  expect(mockBuildSystemPrompt).toHaveBeenCalledWith({
321
- channelPersona: null,
322
323
  excludeBootstrap: true,
323
324
  excludeCustomPrefix: true,
324
- userPersona: null,
325
- userSlug: null,
326
325
  });
327
326
  expect(options!.config!.tool_choice).toEqual({ type: "none" });
328
327
  expect(options!.config!.callSite).toBe("identityIntro");
@@ -166,7 +166,6 @@ mock.module("../notifications/emit-signal.js", () => ({
166
166
  reason: "mocked",
167
167
  deliveryResults: [],
168
168
  }),
169
- registerBroadcastFn: () => {},
170
169
  }));
171
170
 
172
171
  mock.module("../calls/voice-session-bridge.js", () => {
@@ -49,7 +49,7 @@ mock.module("../daemon/handlers/conversations.js", () => ({
49
49
  return true;
50
50
  },
51
51
  switchConversation: async () => null,
52
- clearAllConversations: () => 0,
52
+ clearAllConversations: async () => 0,
53
53
  undoLastMessage: async () => null,
54
54
  regenerateResponse: async () => null,
55
55
  }));