@vellumai/assistant 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (666) hide show
  1. package/ARCHITECTURE.md +6 -7
  2. package/Dockerfile +1 -0
  3. package/README.md +2 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
  5. package/bun.lock +3 -0
  6. package/docs/architecture/security.md +18 -16
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  9. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
  10. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  11. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  12. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  13. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  14. package/node_modules/@vellumai/slack-text/package.json +18 -0
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  16. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  17. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  18. package/openapi.yaml +294 -107
  19. package/package.json +4 -2
  20. package/scripts/generate-openapi.ts +16 -111
  21. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  22. package/src/__tests__/anthropic-provider.test.ts +56 -13
  23. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  24. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  25. package/src/__tests__/approval-cascade.test.ts +0 -15
  26. package/src/__tests__/approval-routes-http.test.ts +6 -17
  27. package/src/__tests__/assistant-event-hub.test.ts +126 -77
  28. package/src/__tests__/assistant-event.test.ts +0 -5
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
  31. package/src/__tests__/background-shell-host-bash.test.ts +34 -43
  32. package/src/__tests__/call-controller.test.ts +1 -1
  33. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  34. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  35. package/src/__tests__/channel-approvals.test.ts +25 -17
  36. package/src/__tests__/channel-guardian.test.ts +100 -146
  37. package/src/__tests__/checker.test.ts +20 -34
  38. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/config-schema.test.ts +6 -48
  41. package/src/__tests__/config-watcher.test.ts +12 -0
  42. package/src/__tests__/connection-policy.test.ts +1 -52
  43. package/src/__tests__/contacts-write.test.ts +2 -64
  44. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  45. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  46. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  47. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  48. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  49. package/src/__tests__/context-window-manager.test.ts +46 -0
  50. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  51. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  52. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  53. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  54. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  55. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  56. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  57. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  58. package/src/__tests__/conversation-lifecycle.test.ts +4 -4
  59. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  60. package/src/__tests__/conversation-queue.test.ts +3 -8
  61. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
  62. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
  63. package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
  64. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  65. package/src/__tests__/conversation-slash-commands.test.ts +24 -4
  66. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  68. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  69. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  70. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  71. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  72. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  73. package/src/__tests__/conversation-usage.test.ts +253 -3
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  75. package/src/__tests__/credential-health-service.test.ts +68 -0
  76. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  77. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  78. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  79. package/src/__tests__/cu-unified-flow.test.ts +33 -16
  80. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  81. package/src/__tests__/daemon-credential-client.test.ts +4 -1
  82. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  83. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  84. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  85. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  86. package/src/__tests__/document-conversations.test.ts +332 -0
  87. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  88. package/src/__tests__/emit-event-signal.test.ts +4 -6
  89. package/src/__tests__/events-client-registration.test.ts +193 -49
  90. package/src/__tests__/filing-service.test.ts +58 -7
  91. package/src/__tests__/first-greeting.test.ts +156 -150
  92. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  93. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  94. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  95. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  96. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  97. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  98. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  99. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
  100. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
  101. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  102. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  103. package/src/__tests__/heartbeat-service.test.ts +289 -7
  104. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  105. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  106. package/src/__tests__/host-bash-proxy.test.ts +46 -122
  107. package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
  108. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
  109. package/src/__tests__/host-browser-proxy.test.ts +111 -185
  110. package/src/__tests__/host-browser-routes.test.ts +45 -75
  111. package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
  112. package/src/__tests__/host-cu-proxy.test.ts +56 -111
  113. package/src/__tests__/host-file-proxy.test.ts +44 -98
  114. package/src/__tests__/host-file-read-tool.test.ts +42 -21
  115. package/src/__tests__/host-shell-tool.test.ts +33 -68
  116. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  117. package/src/__tests__/host-transfer-proxy.test.ts +43 -53
  118. package/src/__tests__/http-user-message-parity.test.ts +0 -6
  119. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  120. package/src/__tests__/injector-chain.test.ts +10 -5
  121. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  122. package/src/__tests__/inline-command-runner.test.ts +0 -66
  123. package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
  124. package/src/__tests__/install-skill-routing.test.ts +1 -13
  125. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  126. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  127. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  128. package/src/__tests__/llm-resolver.test.ts +80 -12
  129. package/src/__tests__/llm-usage-store.test.ts +269 -4
  130. package/src/__tests__/log-export-routes.test.ts +89 -0
  131. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  132. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
  133. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  134. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  136. package/src/__tests__/migration-export-http.test.ts +33 -26
  137. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  138. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  139. package/src/__tests__/migration-import-commit-http.test.ts +66 -21
  140. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  141. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  142. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  143. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  144. package/src/__tests__/migration-transport.test.ts +115 -23
  145. package/src/__tests__/migration-validate-http.test.ts +105 -80
  146. package/src/__tests__/migration-wizard.test.ts +133 -27
  147. package/src/__tests__/non-member-access-request.test.ts +1 -1
  148. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  149. package/src/__tests__/oauth-store.test.ts +19 -0
  150. package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
  151. package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
  152. package/src/__tests__/pricing.test.ts +68 -4
  153. package/src/__tests__/process-message-background-slack.test.ts +331 -0
  154. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  155. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  156. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  157. package/src/__tests__/reaction-persistence.test.ts +9 -6
  158. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  159. package/src/__tests__/recording-handler.test.ts +64 -81
  160. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  161. package/src/__tests__/relay-server.test.ts +18 -13
  162. package/src/__tests__/require-fresh-approval.test.ts +13 -22
  163. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  164. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  165. package/src/__tests__/runtime-events-sse.test.ts +3 -12
  166. package/src/__tests__/search-skills-unified.test.ts +9 -15
  167. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  168. package/src/__tests__/secret-ingress-http.test.ts +0 -4
  169. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  170. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  171. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  172. package/src/__tests__/secret-response-routing.test.ts +29 -15
  173. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  174. package/src/__tests__/secret-scanner.test.ts +2 -545
  175. package/src/__tests__/send-endpoint-busy.test.ts +9 -24
  176. package/src/__tests__/settings-routes.test.ts +1 -1
  177. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  178. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
  179. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
  180. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  181. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  182. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  183. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  184. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  185. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  186. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  187. package/src/__tests__/system-prompt.test.ts +115 -13
  188. package/src/__tests__/terminal-tools.test.ts +0 -89
  189. package/src/__tests__/thread-backfill.test.ts +945 -31
  190. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  191. package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
  192. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
  193. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  194. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
  195. package/src/__tests__/tool-executor.test.ts +12 -19
  196. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  197. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  198. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  199. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  202. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  203. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  204. package/src/__tests__/usage-attribution.test.ts +247 -0
  205. package/src/__tests__/usage-cli.test.ts +143 -0
  206. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  207. package/src/__tests__/usage-routes.test.ts +150 -0
  208. package/src/__tests__/validation-results-screen.test.ts +39 -16
  209. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  210. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
  211. package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
  212. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  213. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  214. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  215. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  216. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  217. package/src/acp/index.ts +0 -15
  218. package/src/acp/session-manager.ts +37 -34
  219. package/src/agent/loop.ts +16 -1
  220. package/src/approvals/AGENTS.md +4 -0
  221. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  222. package/src/approvals/guardian-request-resolvers.ts +10 -2
  223. package/src/backup/__tests__/backup-worker.test.ts +36 -8
  224. package/src/backup/__tests__/paths.test.ts +2 -2
  225. package/src/backup/__tests__/restore.test.ts +45 -28
  226. package/src/backup/backup-worker.ts +36 -2
  227. package/src/backup/paths.ts +9 -6
  228. package/src/browser-session/events.ts +0 -9
  229. package/src/calls/call-store.ts +1 -34
  230. package/src/calls/guardian-question-copy.ts +0 -108
  231. package/src/calls/relay-server.ts +0 -24
  232. package/src/calls/twilio-rest.ts +0 -38
  233. package/src/calls/twilio-routes.ts +1 -1
  234. package/src/calls/voice-session-bridge.ts +7 -38
  235. package/src/channels/types.ts +1 -36
  236. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  237. package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
  238. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  239. package/src/cli/commands/backup.ts +4 -4
  240. package/src/cli/commands/cache-fs.ts +8 -0
  241. package/src/cli/commands/cache.ts +153 -82
  242. package/src/cli/commands/clients.ts +63 -5
  243. package/src/cli/commands/completions.ts +3 -3
  244. package/src/cli/commands/contacts.ts +231 -76
  245. package/src/cli/commands/keys.ts +4 -1
  246. package/src/cli/commands/memory-v2.ts +24 -52
  247. package/src/cli/commands/oauth/shared.ts +2 -29
  248. package/src/cli/commands/pending.ts +102 -0
  249. package/src/cli/commands/skills.ts +77 -35
  250. package/src/cli/commands/trust.ts +70 -430
  251. package/src/cli/commands/usage.ts +25 -16
  252. package/src/cli/lib/daemon-credential-client.ts +14 -0
  253. package/src/cli/program.ts +2 -0
  254. package/src/cli.ts +0 -21
  255. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  256. package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
  257. package/src/config/env-registry.ts +12 -2
  258. package/src/config/env.ts +3 -14
  259. package/src/config/feature-flag-registry.json +30 -30
  260. package/src/config/llm-callsite-catalog.ts +12 -0
  261. package/src/config/llm-context-resolution.ts +80 -0
  262. package/src/config/llm-resolver.ts +58 -22
  263. package/src/config/loader.ts +3 -3
  264. package/src/config/schema.ts +2 -158
  265. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  266. package/src/config/schemas/call-site-catalog.ts +271 -0
  267. package/src/config/schemas/calls.ts +5 -5
  268. package/src/config/schemas/inference.ts +1 -1
  269. package/src/config/schemas/ingress.ts +1 -1
  270. package/src/config/schemas/llm.ts +31 -3
  271. package/src/config/schemas/memory-retrieval.ts +2 -2
  272. package/src/config/schemas/memory-v2.ts +9 -0
  273. package/src/config/schemas/security.ts +1 -42
  274. package/src/config/schemas/services.ts +6 -6
  275. package/src/config/schemas/skills.ts +5 -5
  276. package/src/config/schemas/tts.ts +1 -1
  277. package/src/config/seed-inference-profiles.ts +117 -0
  278. package/src/config/skills.ts +0 -90
  279. package/src/config/types.ts +3 -6
  280. package/src/contacts/contact-store.ts +0 -17
  281. package/src/contacts/contacts-write.ts +1 -105
  282. package/src/context/window-manager.ts +44 -5
  283. package/src/credential-execution/process-manager.ts +34 -10
  284. package/src/credential-health/credential-health-service.ts +21 -16
  285. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  286. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  287. package/src/daemon/connection-policy.ts +1 -26
  288. package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
  289. package/src/daemon/conversation-agent-loop.ts +277 -36
  290. package/src/daemon/conversation-history.ts +8 -8
  291. package/src/daemon/conversation-launch.ts +20 -135
  292. package/src/daemon/conversation-lifecycle.ts +1 -1
  293. package/src/daemon/conversation-messaging.ts +1 -0
  294. package/src/daemon/conversation-process.ts +83 -163
  295. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  296. package/src/daemon/conversation-slash.ts +47 -5
  297. package/src/daemon/conversation-store.ts +7 -31
  298. package/src/daemon/conversation-surfaces.ts +22 -28
  299. package/src/daemon/conversation-tool-setup.ts +3 -33
  300. package/src/daemon/conversation-usage.ts +36 -0
  301. package/src/daemon/conversation.ts +117 -233
  302. package/src/daemon/daemon-control.ts +3 -71
  303. package/src/daemon/daemon-skill-host.ts +8 -11
  304. package/src/daemon/dictation-profile-store.ts +2 -26
  305. package/src/daemon/first-greeting.ts +44 -156
  306. package/src/daemon/handlers/config-channels.ts +12 -12
  307. package/src/daemon/handlers/config-ingress.ts +4 -165
  308. package/src/daemon/handlers/config-model.ts +1 -1
  309. package/src/daemon/handlers/config-voice.ts +0 -42
  310. package/src/daemon/handlers/conversations.ts +11 -190
  311. package/src/daemon/handlers/recording.ts +26 -158
  312. package/src/daemon/handlers/shared.ts +23 -71
  313. package/src/daemon/handlers/skills.ts +42 -93
  314. package/src/daemon/host-bash-proxy.ts +67 -45
  315. package/src/daemon/host-browser-proxy.ts +65 -27
  316. package/src/daemon/host-cu-proxy.ts +40 -39
  317. package/src/daemon/host-file-proxy.ts +58 -37
  318. package/src/daemon/host-transfer-proxy.ts +84 -46
  319. package/src/daemon/lifecycle.ts +49 -15
  320. package/src/daemon/message-types/conversations.ts +7 -0
  321. package/src/daemon/message-types/host-bash.ts +1 -0
  322. package/src/daemon/message-types/host-cu.ts +1 -0
  323. package/src/daemon/message-types/host-file.ts +1 -0
  324. package/src/daemon/message-types/host-transfer.ts +1 -0
  325. package/src/daemon/message-types/messages.ts +10 -9
  326. package/src/daemon/message-types/workspace.ts +1 -1
  327. package/src/daemon/process-message.ts +102 -239
  328. package/src/daemon/server.ts +13 -462
  329. package/src/daemon/shutdown-handlers.ts +2 -2
  330. package/src/daemon/tool-side-effects.ts +125 -107
  331. package/src/daemon/trust-context.ts +13 -0
  332. package/src/daemon/wake-target-adapter.ts +4 -9
  333. package/src/events/domain-events.ts +0 -8
  334. package/src/events/tool-audit-listener.ts +3 -1
  335. package/src/events/tool-domain-event-publisher.ts +0 -10
  336. package/src/events/tool-metrics-listener.ts +0 -17
  337. package/src/events/tool-trace-listener.ts +0 -14
  338. package/src/filing/filing-service.ts +13 -1
  339. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
  340. package/src/heartbeat/heartbeat-service.ts +23 -5
  341. package/src/home/__tests__/feed-writer.test.ts +0 -4
  342. package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
  343. package/src/home/feed-writer.ts +1 -2
  344. package/src/home/relationship-state-writer.ts +16 -3
  345. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  346. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  347. package/src/ipc/assistant-server.ts +3 -10
  348. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  349. package/src/ipc/routes/route-adapter.ts +1 -1
  350. package/src/ipc/routes/trust-rules.test.ts +0 -95
  351. package/src/ipc/skill-ipc-types.ts +41 -0
  352. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  353. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  354. package/src/ipc/skill-routes/events.ts +12 -23
  355. package/src/ipc/skill-routes/identity.ts +4 -17
  356. package/src/ipc/skill-routes/index.ts +1 -1
  357. package/src/ipc/skill-server.ts +6 -39
  358. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  359. package/src/live-voice/protocol.ts +4 -13
  360. package/src/mcp/manager.ts +0 -5
  361. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  362. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  363. package/src/memory/app-git-service.ts +0 -32
  364. package/src/memory/app-store.ts +154 -0
  365. package/src/memory/attachments-store.ts +6 -0
  366. package/src/memory/context-search/sources/memory-v2.ts +578 -0
  367. package/src/memory/context-search/sources/memory.ts +5 -0
  368. package/src/memory/context-search/sources/pkb.ts +10 -1
  369. package/src/memory/context-search/sources/workspace.ts +3 -2
  370. package/src/memory/conversation-crud.ts +29 -4
  371. package/src/memory/conversation-disk-view.ts +1 -5
  372. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  373. package/src/memory/db-connection.ts +62 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +3 -21
  376. package/src/memory/embedding-gemini.ts +0 -2
  377. package/src/memory/embedding-local.ts +6 -6
  378. package/src/memory/embedding-ollama.ts +6 -6
  379. package/src/memory/embedding-openai.ts +6 -6
  380. package/src/memory/embedding-types.ts +21 -0
  381. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
  382. package/src/memory/graph/conversation-graph-memory.ts +35 -13
  383. package/src/memory/graph/injection.test.ts +2 -2
  384. package/src/memory/graph/injection.ts +1 -1
  385. package/src/memory/guardian-action-store.ts +0 -83
  386. package/src/memory/guardian-approvals.ts +0 -48
  387. package/src/memory/indexer.ts +1 -15
  388. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  389. package/src/memory/job-utils.ts +0 -6
  390. package/src/memory/jobs-store.ts +0 -1
  391. package/src/memory/jobs-worker.ts +2 -16
  392. package/src/memory/llm-request-log-store.ts +0 -41
  393. package/src/memory/llm-usage-store.ts +129 -43
  394. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  395. package/src/memory/migrations/233-document-conversations.ts +54 -0
  396. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  397. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  398. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  399. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  400. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  401. package/src/memory/migrations/index.ts +14 -0
  402. package/src/memory/migrations/registry.ts +24 -0
  403. package/src/memory/raw-query.ts +2 -68
  404. package/src/memory/schema/conversations.ts +7 -0
  405. package/src/memory/schema/infrastructure.ts +25 -0
  406. package/src/memory/search/semantic.ts +5 -16
  407. package/src/memory/tool-usage-store.ts +2 -0
  408. package/src/memory/usage-buckets.ts +40 -1
  409. package/src/memory/usage-grouped-buckets.ts +127 -0
  410. package/src/memory/v2/__tests__/activation.test.ts +289 -90
  411. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  412. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  413. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  414. package/src/memory/v2/__tests__/injection.test.ts +384 -15
  415. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  416. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  417. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  418. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  419. package/src/memory/v2/__tests__/static-context.test.ts +153 -0
  420. package/src/memory/v2/activation.ts +168 -97
  421. package/src/memory/v2/backfill-jobs.ts +15 -100
  422. package/src/memory/v2/consolidation-job.ts +14 -12
  423. package/src/memory/v2/edge-index.ts +191 -0
  424. package/src/memory/v2/injection.ts +182 -58
  425. package/src/memory/v2/migration.ts +57 -64
  426. package/src/memory/v2/now-text.ts +2 -3
  427. package/src/memory/v2/page-store.ts +168 -31
  428. package/src/memory/v2/prompts/consolidation.ts +118 -42
  429. package/src/memory/v2/prompts/sweep.ts +3 -3
  430. package/src/memory/v2/skill-store.ts +55 -7
  431. package/src/memory/v2/static-context.ts +62 -0
  432. package/src/memory/v2/types.ts +10 -20
  433. package/src/memory/validation.ts +0 -11
  434. package/src/messaging/draft-store.ts +0 -6
  435. package/src/messaging/provider-types.ts +8 -0
  436. package/src/messaging/provider.ts +7 -0
  437. package/src/messaging/providers/gmail/client.ts +1 -121
  438. package/src/messaging/providers/outlook/client.ts +0 -73
  439. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  440. package/src/messaging/providers/slack/adapter.ts +122 -21
  441. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  442. package/src/messaging/providers/slack/backfill.ts +89 -11
  443. package/src/messaging/providers/slack/client.ts +10 -124
  444. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  445. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  446. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  447. package/src/messaging/providers/slack/types.ts +1 -0
  448. package/src/oauth/connection-resolver.test.ts +8 -0
  449. package/src/oauth/connection-resolver.ts +8 -16
  450. package/src/oauth/credential-token-resolver.ts +97 -0
  451. package/src/oauth/manual-token-connection.ts +30 -34
  452. package/src/oauth/oauth-store.ts +6 -4
  453. package/src/outbound-proxy/certs.ts +0 -7
  454. package/src/outbound-proxy/config.ts +0 -74
  455. package/src/outbound-proxy/health.ts +0 -44
  456. package/src/outbound-proxy/index.ts +0 -22
  457. package/src/permissions/approval-provenance.test.ts +184 -0
  458. package/src/permissions/approval-provenance.ts +70 -0
  459. package/src/permissions/checker.ts +4 -1
  460. package/src/permissions/gateway-threshold-reader.ts +4 -1
  461. package/src/permissions/prompter.ts +9 -2
  462. package/src/permissions/secret-prompter.ts +21 -48
  463. package/src/permissions/types.ts +33 -0
  464. package/src/permissions/workspace-policy.ts +0 -5
  465. package/src/platform/sync-identity.ts +0 -8
  466. package/src/plugins/defaults/injectors.ts +69 -2
  467. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  468. package/src/plugins/types.ts +8 -0
  469. package/src/prompts/system-prompt.ts +34 -70
  470. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  471. package/src/prompts/update-bulletin-job.ts +2 -0
  472. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  473. package/src/providers/anthropic/client.ts +72 -33
  474. package/src/providers/call-site-routing.ts +42 -3
  475. package/src/providers/gemini/client.ts +18 -2
  476. package/src/providers/managed-proxy/context.ts +0 -5
  477. package/src/providers/model-catalog.ts +105 -19
  478. package/src/providers/openai/chat-completions-provider.ts +6 -0
  479. package/src/providers/openai/responses-provider.ts +7 -1
  480. package/src/providers/provider-send-message.ts +45 -2
  481. package/src/providers/ratelimit.ts +7 -2
  482. package/src/providers/registry.ts +14 -9
  483. package/src/providers/retry.ts +96 -8
  484. package/src/providers/types.ts +13 -0
  485. package/src/providers/usage-tracking.ts +96 -0
  486. package/src/runtime/AGENTS.md +10 -6
  487. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  488. package/src/runtime/agent-wake.ts +39 -2
  489. package/src/runtime/assistant-event-hub.ts +541 -45
  490. package/src/runtime/assistant-event.ts +1 -6
  491. package/src/runtime/auth/context.ts +0 -9
  492. package/src/runtime/auth/middleware.ts +1 -1
  493. package/src/runtime/auth/route-policy.ts +11 -9
  494. package/src/runtime/auth/token-service.ts +0 -11
  495. package/src/runtime/channel-approvals.ts +6 -2
  496. package/src/runtime/channel-verification-service.ts +3 -5
  497. package/src/runtime/http-errors.ts +0 -34
  498. package/src/runtime/http-router.ts +6 -3
  499. package/src/runtime/http-server.ts +22 -82
  500. package/src/runtime/http-types.ts +5 -0
  501. package/src/runtime/interactive-ui.ts +0 -1
  502. package/src/runtime/middleware/auth.ts +0 -20
  503. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  504. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  505. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  506. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  507. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  508. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  509. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
  510. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  511. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  512. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
  513. package/src/runtime/migrations/migration-transport.ts +46 -13
  514. package/src/runtime/migrations/migration-wizard.ts +2 -2
  515. package/src/runtime/migrations/origin-mode.ts +40 -0
  516. package/src/runtime/migrations/vbundle-builder.ts +133 -79
  517. package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
  518. package/src/runtime/migrations/vbundle-importer.ts +7 -7
  519. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  520. package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
  521. package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
  522. package/src/runtime/migrations/vbundle-validator.ts +214 -41
  523. package/src/runtime/pending-interactions.ts +13 -4
  524. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  525. package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
  526. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
  527. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  528. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  529. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  530. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  531. package/src/runtime/routes/acp-routes.test.ts +0 -3
  532. package/src/runtime/routes/acp-routes.ts +3 -7
  533. package/src/runtime/routes/app-management-routes.ts +18 -9
  534. package/src/runtime/routes/approval-routes.ts +55 -14
  535. package/src/runtime/routes/avatar-routes.ts +3 -5
  536. package/src/runtime/routes/browser-routes.ts +1 -15
  537. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  538. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  539. package/src/runtime/routes/channel-route-shared.ts +2 -28
  540. package/src/runtime/routes/client-routes.ts +45 -12
  541. package/src/runtime/routes/consolidation-routes.ts +115 -0
  542. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  543. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  544. package/src/runtime/routes/conversation-query-routes.ts +120 -8
  545. package/src/runtime/routes/conversation-routes.ts +44 -528
  546. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  547. package/src/runtime/routes/documents-routes.ts +53 -18
  548. package/src/runtime/routes/events-routes.ts +59 -91
  549. package/src/runtime/routes/filing-routes.ts +18 -1
  550. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  551. package/src/runtime/routes/host-bash-routes.ts +3 -2
  552. package/src/runtime/routes/host-browser-routes.ts +9 -33
  553. package/src/runtime/routes/host-cu-routes.ts +6 -1
  554. package/src/runtime/routes/host-file-routes.ts +3 -2
  555. package/src/runtime/routes/host-transfer-routes.ts +11 -15
  556. package/src/runtime/routes/identity-routes.ts +78 -6
  557. package/src/runtime/routes/inbound-message-handler.ts +580 -137
  558. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
  559. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  560. package/src/runtime/routes/index.ts +4 -0
  561. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  562. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  563. package/src/runtime/routes/memory-v2-routes.ts +10 -15
  564. package/src/runtime/routes/migration-routes.ts +188 -31
  565. package/src/runtime/routes/playground/guard.ts +1 -1
  566. package/src/runtime/routes/playground/index.ts +0 -2
  567. package/src/runtime/routes/recording-routes.ts +4 -24
  568. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  569. package/src/runtime/routes/schedule-routes.ts +3 -6
  570. package/src/runtime/routes/secret-routes.ts +87 -18
  571. package/src/runtime/routes/settings-routes.ts +29 -28
  572. package/src/runtime/routes/skills-routes.ts +12 -31
  573. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  574. package/src/runtime/routes/task-routes.ts +6 -6
  575. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  576. package/src/runtime/routes/types.ts +4 -4
  577. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  578. package/src/runtime/routes/usage-routes.ts +87 -10
  579. package/src/runtime/routes/user-routes.ts +17 -31
  580. package/src/runtime/routes/work-items-routes.ts +1 -4
  581. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  582. package/src/runtime/services/analyze-conversation.ts +7 -17
  583. package/src/runtime/services/conversation-serializer.ts +2 -4
  584. package/src/runtime/verification-outbound-actions.ts +1 -1
  585. package/src/runtime/verification-rate-limiter.ts +1 -1
  586. package/src/schedule/schedule-store.ts +0 -16
  587. package/src/security/secret-scanner.ts +14 -547
  588. package/src/security/secure-keys.ts +31 -11
  589. package/src/security/token-manager.ts +7 -3
  590. package/src/signals/cancel.ts +16 -25
  591. package/src/signals/conversation-undo.ts +2 -27
  592. package/src/signals/emit-event.ts +1 -2
  593. package/src/signals/user-message.ts +108 -22
  594. package/src/skills/catalog-install.ts +1 -0
  595. package/src/skills/clawhub.ts +2 -2
  596. package/src/skills/inline-command-runner.ts +1 -7
  597. package/src/subagent/manager.ts +67 -84
  598. package/src/tasks/task-store.ts +1 -28
  599. package/src/telemetry/types.ts +6 -0
  600. package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
  601. package/src/telemetry/usage-telemetry-reporter.ts +3 -5
  602. package/src/tools/acp/spawn.test.ts +1 -2
  603. package/src/tools/acp/steer.test.ts +1 -2
  604. package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
  605. package/src/tools/browser/browser-execution.ts +31 -147
  606. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
  607. package/src/tools/browser/cdp-client/factory.ts +48 -76
  608. package/src/tools/browser/cdp-client/index.ts +1 -14
  609. package/src/tools/executor.ts +44 -31
  610. package/src/tools/host-filesystem/edit.ts +3 -2
  611. package/src/tools/host-filesystem/read.ts +3 -2
  612. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  613. package/src/tools/host-filesystem/transfer.ts +4 -3
  614. package/src/tools/host-filesystem/write.ts +3 -2
  615. package/src/tools/host-terminal/host-shell.ts +4 -3
  616. package/src/tools/network/script-proxy/index.ts +1 -10
  617. package/src/tools/permission-checker.ts +66 -1
  618. package/src/tools/skills/sandbox-runner.ts +1 -6
  619. package/src/tools/skills/skill-tool-factory.ts +32 -0
  620. package/src/tools/terminal/safe-env.ts +1 -0
  621. package/src/tools/terminal/shell.ts +2 -78
  622. package/src/tools/types.ts +12 -39
  623. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  624. package/src/tts/provider-catalog.ts +1 -1
  625. package/src/usage/actors.ts +2 -1
  626. package/src/usage/attribution.ts +185 -0
  627. package/src/usage/pricing.ts +166 -0
  628. package/src/usage/types.ts +14 -0
  629. package/src/util/json.ts +13 -0
  630. package/src/util/logger.ts +3 -3
  631. package/src/util/pricing.ts +50 -3
  632. package/src/work-items/work-item-runner.ts +15 -42
  633. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
  634. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  635. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  636. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
  637. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  638. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  639. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  640. package/src/workspace/migrations/registry.ts +8 -0
  641. package/src/workspace/provider-commit-message-generator.ts +3 -3
  642. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  643. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  644. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  645. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  646. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  647. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  648. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  649. package/src/context/__tests__/microcompact.test.ts +0 -805
  650. package/src/context/microcompact.ts +0 -443
  651. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  652. package/src/events/tool-notification-listener.ts +0 -17
  653. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  654. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  655. package/src/memory/v2/edges.ts +0 -217
  656. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  657. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  658. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  659. package/src/runtime/chrome-extension-registry.ts +0 -368
  660. package/src/runtime/client-registry.ts +0 -254
  661. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  662. package/src/tools/secret-detection-handler.ts +0 -269
  663. package/src/tools/terminal/backends/native.ts +0 -327
  664. package/src/tools/terminal/backends/types.ts +0 -37
  665. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  666. package/src/tools/terminal/sandbox.ts +0 -40
@@ -36,8 +36,10 @@ mock.module("../runtime/services/conversation-serializer.js", () => ({
36
36
  buildConversationDetailResponse: (id: string) => ({ id }),
37
37
  }));
38
38
 
39
- import { AssistantEventHub } from "../runtime/assistant-event-hub.js";
40
- import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
39
+ import {
40
+ AssistantEventHub,
41
+ broadcastMessage,
42
+ } from "../runtime/assistant-event-hub.js";
41
43
  import { ROUTES } from "../runtime/routes/conversation-analysis-routes.js";
42
44
 
43
45
  const analyzeRoute = ROUTES.find(
@@ -108,22 +110,22 @@ describe("POST /v1/conversations/:id/analyze", () => {
108
110
  expect(allowedTools).toBeInstanceOf(Set);
109
111
  expect(allowedTools?.size).toBe(0);
110
112
  expect(mockConversation.updateClient).toHaveBeenCalledWith(
111
- expect.any(Function),
113
+ broadcastMessage,
112
114
  true,
113
115
  );
114
116
  expect(mockConversation.runAgentLoop).toHaveBeenCalledWith(
115
117
  expect.any(String),
116
118
  "msg-1",
117
- expect.any(Function),
119
+ undefined,
118
120
  expect.objectContaining({ isInteractive: false, isUserMessage: true }),
119
121
  );
120
122
  });
121
123
 
122
124
  test("keeps analysis non-interactive even when a matching subscriber is connected", async () => {
123
- const sub = testHub.subscribe(
124
- { assistantId: DAEMON_INTERNAL_ASSISTANT_ID },
125
- () => {},
126
- );
125
+ const sub = testHub.subscribe({
126
+ type: "process",
127
+ callback: () => {},
128
+ });
127
129
 
128
130
  try {
129
131
  await analyzeRoute.handler({
@@ -131,13 +133,13 @@ describe("POST /v1/conversations/:id/analyze", () => {
131
133
  });
132
134
 
133
135
  expect(mockConversation.updateClient).toHaveBeenCalledWith(
134
- expect.any(Function),
136
+ broadcastMessage,
135
137
  false,
136
138
  );
137
139
  expect(mockConversation.runAgentLoop).toHaveBeenCalledWith(
138
140
  expect.any(String),
139
141
  "msg-1",
140
- expect.any(Function),
142
+ undefined,
141
143
  expect.objectContaining({ isInteractive: false, isUserMessage: true }),
142
144
  );
143
145
  } finally {
@@ -2,6 +2,14 @@ import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  mock.module("../config/env.js", () => ({ isHttpAuthDisabled: () => true }));
4
4
 
5
+ const _conversationMocks = new Map<string, unknown>();
6
+ mock.module("../daemon/conversation-store.js", () => ({
7
+ findConversation: (id: string) => _conversationMocks.get(id),
8
+ findConversationBySurfaceId: () => undefined,
9
+ getActiveConversations: () => [],
10
+ createConversation: () => undefined,
11
+ }));
12
+
5
13
  // ---------------------------------------------------------------------------
6
14
  // Test isolation: in-memory SQLite via temp directory
7
15
  // ---------------------------------------------------------------------------
@@ -241,12 +249,12 @@ describe("Telegram callback seen signals", () => {
241
249
 
242
250
  // Register a pending interaction so the approval interception handles it
243
251
  const handleConfirmationResponse = mock(() => {});
244
- const mockSession = {
252
+ const _mockSession = {
245
253
  handleConfirmationResponse,
246
254
  ensureActorScopedHistory: async () => {},
247
255
  } as unknown as import("../daemon/conversation.js").Conversation;
256
+ _conversationMocks.set(conversationId, _mockSession);
248
257
  pendingInteractions.register("req-cb-test", {
249
- conversation: mockSession,
250
258
  conversationId,
251
259
  kind: "confirmation",
252
260
  confirmationDetails: {
@@ -266,7 +274,7 @@ describe("Telegram callback seen signals", () => {
266
274
 
267
275
  // Create a guardian binding (via contacts) so approval can be handled
268
276
  const { createGuardianBinding } =
269
- await import("../contacts/contacts-write.js");
277
+ await import("./helpers/create-guardian-binding.js");
270
278
  createGuardianBinding({
271
279
  channel: "telegram",
272
280
  guardianExternalUserId: "telegram-user-default",
@@ -239,8 +239,6 @@ mock.module("../memory/canonical-guardian-store.js", () => ({
239
239
  // ---------------------------------------------------------------------------
240
240
 
241
241
  import { Conversation } from "../daemon/conversation.js";
242
- import { HostBashProxy } from "../daemon/host-bash-proxy.js";
243
- import { HostBrowserProxy } from "../daemon/host-browser-proxy.js";
244
242
 
245
243
  // ---------------------------------------------------------------------------
246
244
  // Helpers
@@ -408,7 +406,6 @@ describe("centralized confirmation emissions", () => {
408
406
  decisionText: "yes please",
409
407
  });
410
408
  });
411
-
412
409
  });
413
410
 
414
411
  describe("activity version ordering", () => {
@@ -548,291 +545,3 @@ describe("sendToClient receives state signals", () => {
548
545
  });
549
546
  });
550
547
  });
551
-
552
- describe("restoreBrowserProxyAvailability", () => {
553
- test("re-enables only the host browser proxy after clearProxyAvailability", () => {
554
- const conversation = makeConversation();
555
- const browserProxy = new HostBrowserProxy(() => {});
556
- const bashProxy = new HostBashProxy(() => {});
557
- conversation.setHostBrowserProxy(browserProxy);
558
- conversation.setHostBashProxy(bashProxy);
559
-
560
- // Mark as having a connected client (interactive desktop path).
561
- conversation.updateClient(() => {}, false);
562
- expect(browserProxy.isAvailable()).toBe(true);
563
- expect(bashProxy.isAvailable()).toBe(true);
564
-
565
- // The drain queue clears all proxies for non-interactive turns.
566
- conversation.clearProxyAvailability();
567
- expect(browserProxy.isAvailable()).toBe(false);
568
- expect(bashProxy.isAvailable()).toBe(false);
569
-
570
- // restoreBrowserProxyAvailability should bring back ONLY the browser proxy.
571
- conversation.restoreBrowserProxyAvailability();
572
- expect(browserProxy.isAvailable()).toBe(true);
573
- expect(bashProxy.isAvailable()).toBe(false);
574
- });
575
-
576
- test("re-enables the browser proxy even when hasNoClient is true (chrome-extension)", () => {
577
- // Regression: chrome-extension is non-interactive (hasNoClient stays
578
- // true so host_bash/host_file tools remain gated), but we still need
579
- // to provision the hostBrowserProxy so it can service CDP commands.
580
- // The helper must NOT gate on hasNoClient.
581
- const conversation = makeConversation();
582
- const browserProxy = new HostBrowserProxy(() => {});
583
- conversation.setHostBrowserProxy(browserProxy);
584
-
585
- // updateClient with hasNoClient=true emulates the non-interactive
586
- // chrome-extension turn. Host proxies start disabled because
587
- // updateClient propagates hasNoClient through to updateSender.
588
- conversation.updateClient(() => {}, true);
589
- expect(browserProxy.isAvailable()).toBe(false);
590
- expect(conversation["hasNoClient"]).toBe(true);
591
-
592
- // The targeted helper bypasses the hasNoClient gate so the
593
- // single-capability chrome-extension turn can drive the browser
594
- // via CDP without flipping hasNoClient (which would also enable
595
- // host_bash/host_file gating downstream).
596
- conversation.restoreBrowserProxyAvailability();
597
- expect(browserProxy.isAvailable()).toBe(true);
598
- // hasNoClient itself MUST remain true so that
599
- // isToolActiveForContext keeps host_bash/host_file/host_cu gated.
600
- expect(conversation["hasNoClient"]).toBe(true);
601
- });
602
-
603
- test("leaves bash/file/cu proxies disabled when called for chrome-extension", () => {
604
- // Regression: the targeted helper must not accidentally re-enable
605
- // proxies other than host_browser, even when called from a path that
606
- // owns multiple proxies (e.g. macOS holdover state with hasNoClient
607
- // forced true for an explicit non-interactive run).
608
- const conversation = makeConversation();
609
- const browserProxy = new HostBrowserProxy(() => {});
610
- const bashProxy = new HostBashProxy(() => {});
611
- conversation.setHostBrowserProxy(browserProxy);
612
- conversation.setHostBashProxy(bashProxy);
613
-
614
- conversation.updateClient(() => {}, true);
615
- expect(browserProxy.isAvailable()).toBe(false);
616
- expect(bashProxy.isAvailable()).toBe(false);
617
-
618
- conversation.restoreBrowserProxyAvailability();
619
- expect(browserProxy.isAvailable()).toBe(true);
620
- // Crucial: bash proxy stays disabled. The helper must touch ONLY the
621
- // browser proxy.
622
- expect(bashProxy.isAvailable()).toBe(false);
623
- });
624
-
625
- test("uses hostBrowserSenderOverride when set so drain-queue restores preserve the registry-routed sender", () => {
626
- // Regression (PR #24129 cycle 2): the queue-drain path calls
627
- // `restoreBrowserProxyAvailability()` on dequeue, which used to pass
628
- // `this.sendToClient` (the SSE hub emitter) to the proxy, clobbering the
629
- // chrome-extension registry-routed sender established by the POST
630
- // /messages handler. The override field lets the HTTP handler pin the
631
- // registry-routed sender so the drain path preserves it.
632
- const sseHub: ServerMessage[] = [];
633
- const registry: ServerMessage[] = [];
634
- const conversation = makeConversation((msg) => sseHub.push(msg));
635
- const browserProxy = new HostBrowserProxy(() => {});
636
- conversation.setHostBrowserProxy(browserProxy);
637
-
638
- // Simulate updateClient setting sendToClient to the SSE hub and
639
- // marking the conversation as client-less (chrome-extension is
640
- // non-interactive).
641
- conversation.updateClient((msg) => sseHub.push(msg), true);
642
- expect(browserProxy.isAvailable()).toBe(false);
643
-
644
- // The HTTP handler stashes the registry-routed sender as the override.
645
- const registrySender = (msg: ServerMessage) => registry.push(msg);
646
- conversation.hostBrowserSenderOverride = registrySender;
647
-
648
- // Drain-queue path calls restoreBrowserProxyAvailability — it must now
649
- // prefer the override over sendToClient.
650
- conversation.restoreBrowserProxyAvailability();
651
- expect(browserProxy.isAvailable()).toBe(true);
652
-
653
- // Send a frame through the proxy and verify it flows through the
654
- // registry sender, not the SSE hub.
655
- const internalSend = (
656
- browserProxy as unknown as {
657
- sendToClient: (msg: ServerMessage) => void;
658
- }
659
- ).sendToClient;
660
- const probe: ServerMessage = {
661
- type: "host_browser_cancel",
662
- requestId: "probe-1",
663
- } as ServerMessage;
664
- internalSend(probe);
665
- expect(registry).toHaveLength(1);
666
- expect(sseHub.some((m) => m === probe)).toBe(false);
667
- });
668
-
669
- test("falls back to sendToClient when hostBrowserSenderOverride is cleared", () => {
670
- // When a non-chrome-extension turn takes over, the HTTP handler clears
671
- // the override and restoreBrowserProxyAvailability must fall back to
672
- // sendToClient (the SSE hub), otherwise macOS turns would route their
673
- // host_browser frames through the stale chrome-extension registry.
674
- const sseHub: ServerMessage[] = [];
675
- const conversation = makeConversation((msg) => sseHub.push(msg));
676
- const browserProxy = new HostBrowserProxy(() => {});
677
- conversation.setHostBrowserProxy(browserProxy);
678
-
679
- // First the chrome-extension path pins the override.
680
- const registry: ServerMessage[] = [];
681
- conversation.hostBrowserSenderOverride = (msg) => registry.push(msg);
682
- conversation.updateClient((msg) => sseHub.push(msg), true);
683
- conversation.restoreBrowserProxyAvailability();
684
-
685
- // Then a macOS handoff clears the override.
686
- conversation.hostBrowserSenderOverride = undefined;
687
- conversation.updateClient((msg) => sseHub.push(msg), false);
688
- conversation.restoreBrowserProxyAvailability();
689
-
690
- const internalSend = (
691
- browserProxy as unknown as {
692
- sendToClient: (msg: ServerMessage) => void;
693
- }
694
- ).sendToClient;
695
- const probe: ServerMessage = {
696
- type: "host_browser_cancel",
697
- requestId: "probe-2",
698
- } as ServerMessage;
699
- internalSend(probe);
700
- expect(sseHub).toContain(probe);
701
- expect(registry).not.toContain(probe);
702
- });
703
- });
704
-
705
- describe("hostBrowserSenderOverride is sender-mode based, not interface-string based", () => {
706
- test("macOS turn with registry override routes browser frames through the registry sender", () => {
707
- // When a macOS turn sets hostBrowserSenderOverride (because the
708
- // guardian has an active extension connection), the browser proxy
709
- // must route through the registry sender, not the SSE hub — the
710
- // same behavior chrome-extension turns have always used.
711
- const sseHub: ServerMessage[] = [];
712
- const registry: ServerMessage[] = [];
713
- const conversation = makeConversation((msg) => sseHub.push(msg));
714
- const browserProxy = new HostBrowserProxy(() => {});
715
- conversation.setHostBrowserProxy(browserProxy);
716
-
717
- // macOS is interactive — hasNoClient is false.
718
- conversation.updateClient((msg) => sseHub.push(msg), false);
719
-
720
- // The POST /messages handler detected an active extension connection
721
- // and set the registry-routed sender override.
722
- const registrySender = (msg: ServerMessage) => registry.push(msg);
723
- conversation.hostBrowserSenderOverride = registrySender;
724
-
725
- // restoreBrowserProxyAvailability (called after updateClient in the
726
- // POST handler) must prefer the override.
727
- conversation.restoreBrowserProxyAvailability();
728
- expect(browserProxy.isAvailable()).toBe(true);
729
-
730
- // Verify frames flow through the registry, not the SSE hub.
731
- const internalSend = (
732
- browserProxy as unknown as {
733
- sendToClient: (msg: ServerMessage) => void;
734
- }
735
- ).sendToClient;
736
- const probe: ServerMessage = {
737
- type: "host_browser_cancel",
738
- requestId: "probe-macos-registry",
739
- } as ServerMessage;
740
- internalSend(probe);
741
- expect(registry).toHaveLength(1);
742
- expect(sseHub.some((m) => m === probe)).toBe(false);
743
- });
744
-
745
- test("macOS turn without registry override clears the browser proxy on restore", () => {
746
- // When a macOS turn has no active extension connection, the override
747
- // is cleared and restoreBrowserProxyAvailability falls back to the
748
- // SSE hub sender. The proxy should not be stuck on an unavailable
749
- // registry-routed sender from a prior chrome-extension turn.
750
- const sseHub: ServerMessage[] = [];
751
- const conversation = makeConversation((msg) => sseHub.push(msg));
752
- const browserProxy = new HostBrowserProxy(() => {});
753
- conversation.setHostBrowserProxy(browserProxy);
754
-
755
- // Interactive macOS turn without extension connectivity.
756
- conversation.updateClient((msg) => sseHub.push(msg), false);
757
- conversation.hostBrowserSenderOverride = undefined;
758
- conversation.restoreBrowserProxyAvailability();
759
-
760
- // The proxy should be available and routed through SSE.
761
- expect(browserProxy.isAvailable()).toBe(true);
762
- const internalSend = (
763
- browserProxy as unknown as {
764
- sendToClient: (msg: ServerMessage) => void;
765
- }
766
- ).sendToClient;
767
- const probe: ServerMessage = {
768
- type: "host_browser_cancel",
769
- requestId: "probe-macos-sse",
770
- } as ServerMessage;
771
- internalSend(probe);
772
- expect(sseHub).toContain(probe);
773
- });
774
-
775
- test("override semantics are symmetric: chrome-extension and macOS both set override when registry-routed", () => {
776
- // The override field must be set for ANY interface that uses a
777
- // registry-routed sender, and cleared for any that does not.
778
- // This test verifies the field is not gated on interface strings.
779
- const conversation = makeConversation();
780
- const registrySender = () => {};
781
-
782
- // Simulate chrome-extension setting the override.
783
- conversation.hostBrowserSenderOverride = registrySender;
784
- expect(conversation.hostBrowserSenderOverride).toBe(registrySender);
785
-
786
- // Simulate macOS-with-extension setting the same override.
787
- // The field value is the same registry sender, not gated by interface.
788
- const macosRegistrySender = () => {};
789
- conversation.hostBrowserSenderOverride = macosRegistrySender;
790
- expect(conversation.hostBrowserSenderOverride).toBe(macosRegistrySender);
791
-
792
- // Simulate macOS-without-extension clearing the override.
793
- conversation.hostBrowserSenderOverride = undefined;
794
- expect(conversation.hostBrowserSenderOverride).toBeUndefined();
795
- });
796
-
797
- test("queue-drain restore path preserves registry-routed sender for macOS turns", () => {
798
- // When a macOS turn with an active extension connection has its
799
- // messages queued and later drained, the drain-queue path calls
800
- // restoreBrowserProxyAvailability(). With the override set, the
801
- // proxy must be restored with the registry sender, not the SSE hub.
802
- const sseHub: ServerMessage[] = [];
803
- const registry: ServerMessage[] = [];
804
- const conversation = makeConversation((msg) => sseHub.push(msg));
805
- const browserProxy = new HostBrowserProxy(() => {});
806
- conversation.setHostBrowserProxy(browserProxy);
807
-
808
- // macOS interactive turn with extension connectivity.
809
- conversation.updateClient((msg) => sseHub.push(msg), false);
810
- const registrySender = (msg: ServerMessage) => registry.push(msg);
811
- conversation.hostBrowserSenderOverride = registrySender;
812
- conversation.restoreBrowserProxyAvailability();
813
- expect(browserProxy.isAvailable()).toBe(true);
814
-
815
- // Simulate drain-queue clearing all proxies for a non-interactive
816
- // queued message, then restoring for the next macOS turn.
817
- conversation.clearProxyAvailability();
818
- expect(browserProxy.isAvailable()).toBe(false);
819
-
820
- // Drain restore — override is still set from the POST handler.
821
- conversation.restoreBrowserProxyAvailability();
822
- expect(browserProxy.isAvailable()).toBe(true);
823
-
824
- // Verify the registry sender was preserved, not the SSE hub.
825
- const internalSend = (
826
- browserProxy as unknown as {
827
- sendToClient: (msg: ServerMessage) => void;
828
- }
829
- ).sendToClient;
830
- const probe: ServerMessage = {
831
- type: "host_browser_cancel",
832
- requestId: "probe-drain-macos",
833
- } as ServerMessage;
834
- internalSend(probe);
835
- expect(registry).toHaveLength(1);
836
- expect(sseHub.some((m) => m === probe)).toBe(false);
837
- });
838
- });
@@ -438,11 +438,14 @@ describe("regenerate with web_search_tool_result", () => {
438
438
  let agentLoopContent = "";
439
439
  let agentLoopUserMessageId = "";
440
440
 
441
+ const events: Array<{ type: string; message?: string }> = [];
442
+
441
443
  const session: HistoryConversationContext = {
442
444
  conversationId,
443
445
  traceEmitter: {
444
446
  emit: () => {},
445
447
  } as unknown as HistoryConversationContext["traceEmitter"],
448
+ sendToClient: (msg) => events.push(msg),
446
449
  messages: [...inMemoryMessages],
447
450
  processing: false,
448
451
  abortController: null,
@@ -453,9 +456,7 @@ describe("regenerate with web_search_tool_result", () => {
453
456
  },
454
457
  };
455
458
 
456
- const events: Array<{ type: string; message?: string }> = [];
457
-
458
- await regenerate(session, (msg) => events.push(msg));
459
+ await regenerate(session);
459
460
 
460
461
  // regenerate should find the real user message (msg-u1) and skip the
461
462
  // web_search_tool_result-only message (msg-ws).
@@ -28,7 +28,6 @@ import {
28
28
  import { getDb, resetDb } from "../memory/db-connection.js";
29
29
  import { initializeDb } from "../memory/db-init.js";
30
30
  import { assistantEventHub } from "../runtime/assistant-event-hub.js";
31
- import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
32
31
  import { ROUTES } from "../runtime/routes/conversation-management-routes.js";
33
32
  import { BadRequestError, NotFoundError } from "../runtime/routes/errors.js";
34
33
 
@@ -61,16 +60,14 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
61
60
  const conversation = createConversation("inference-profile-route");
62
61
 
63
62
  const received: Array<{
64
- assistantId: string;
65
63
  type: string;
66
64
  conversationId?: string;
67
65
  profile?: string | null;
68
66
  }> = [];
69
- const subscription = assistantEventHub.subscribe(
70
- { assistantId: DAEMON_INTERNAL_ASSISTANT_ID },
71
- (event) => {
67
+ const subscription = assistantEventHub.subscribe({
68
+ type: "process",
69
+ callback: (event) => {
72
70
  received.push({
73
- assistantId: event.assistantId,
74
71
  type: event.message.type,
75
72
  conversationId: event.conversationId,
76
73
  profile:
@@ -79,13 +76,12 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
79
76
  : undefined,
80
77
  });
81
78
  },
82
- );
79
+ });
83
80
 
84
81
  const result = profileRoute.handler({
85
82
  pathParams: { id: conversation.id },
86
83
  body: { profile: "quality-optimized" },
87
84
  headers: {},
88
-
89
85
  });
90
86
 
91
87
  await Promise.resolve();
@@ -99,7 +95,6 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
99
95
  );
100
96
  expect(received).toEqual([
101
97
  {
102
- assistantId: DAEMON_INTERNAL_ASSISTANT_ID,
103
98
  type: "conversation_inference_profile_updated",
104
99
  conversationId: conversation.id,
105
100
  profile: "quality-optimized",
@@ -117,7 +112,6 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
117
112
  pathParams: { id: conversation.id },
118
113
  body: { profile: "does-not-exist" },
119
114
  headers: {},
120
-
121
115
  }),
122
116
  ).toThrow(BadRequestError);
123
117
  expect(getConversation(conversation.id)?.inferenceProfile).toBeNull();
@@ -130,25 +124,23 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
130
124
  pathParams: { id: conversation.id },
131
125
  body: { profile: "balanced" },
132
126
  headers: {},
133
-
134
127
  });
135
128
  expect(getConversation(conversation.id)?.inferenceProfile).toBe("balanced");
136
129
 
137
130
  const received: Array<{ profile?: string | null }> = [];
138
- const subscription = assistantEventHub.subscribe(
139
- { assistantId: DAEMON_INTERNAL_ASSISTANT_ID },
140
- (event) => {
131
+ const subscription = assistantEventHub.subscribe({
132
+ type: "process",
133
+ callback: (event) => {
141
134
  if (event.message.type === "conversation_inference_profile_updated") {
142
135
  received.push({ profile: event.message.profile });
143
136
  }
144
137
  },
145
- );
138
+ });
146
139
 
147
140
  const result = profileRoute.handler({
148
141
  pathParams: { id: conversation.id },
149
142
  body: { profile: null },
150
143
  headers: {},
151
-
152
144
  });
153
145
 
154
146
  await Promise.resolve();
@@ -170,25 +162,23 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
170
162
  pathParams: { id: conversation.id },
171
163
  body: { profile: "balanced" },
172
164
  headers: {},
173
-
174
165
  });
175
166
  const updatedAtAfterSet = getConversation(conversation.id)?.updatedAt;
176
167
 
177
168
  const received: Array<{ profile?: string | null }> = [];
178
- const subscription = assistantEventHub.subscribe(
179
- { assistantId: DAEMON_INTERNAL_ASSISTANT_ID },
180
- (event) => {
169
+ const subscription = assistantEventHub.subscribe({
170
+ type: "process",
171
+ callback: (event) => {
181
172
  if (event.message.type === "conversation_inference_profile_updated") {
182
173
  received.push({ profile: event.message.profile });
183
174
  }
184
175
  },
185
- );
176
+ });
186
177
 
187
178
  const result = profileRoute.handler({
188
179
  pathParams: { id: conversation.id },
189
180
  body: { profile: "balanced" },
190
181
  headers: {},
191
-
192
182
  });
193
183
 
194
184
  await Promise.resolve();
@@ -209,7 +199,6 @@ describe("PUT /v1/conversations/:id/inference-profile", () => {
209
199
  pathParams: { id: "missing" },
210
200
  body: { profile: "balanced" },
211
201
  headers: {},
212
-
213
202
  }),
214
203
  ).toThrow(NotFoundError);
215
204
  });
@@ -177,7 +177,7 @@ describe("loadFromDb metadata injection rehydration", () => {
177
177
  expect(messages[0].content).toEqual([
178
178
  {
179
179
  type: "text",
180
- text: "<memory __injected>\nremember: alice\n</memory>",
180
+ text: "<memory>\nremember: alice\n</memory>",
181
181
  },
182
182
  { type: "text", text: "Hi" },
183
183
  ]);
@@ -215,7 +215,7 @@ describe("loadFromDb metadata injection rehydration", () => {
215
215
 
216
216
  expect(messages).toHaveLength(3);
217
217
  // m1 is historical (not tail) — all three blocks should rehydrate in the
218
- // documented shape: [<turn_context>, <memory __injected>, <system_reminder>, ...original]
218
+ // documented shape: [<turn_context>, <memory>, <system_reminder>, ...original]
219
219
  expect(messages[0].role).toBe("user");
220
220
  expect(messages[0].content).toEqual([
221
221
  {
@@ -224,7 +224,7 @@ describe("loadFromDb metadata injection rehydration", () => {
224
224
  },
225
225
  {
226
226
  type: "text",
227
- text: "<memory __injected>\nmem payload\n</memory>",
227
+ text: "<memory>\nmem payload\n</memory>",
228
228
  },
229
229
  {
230
230
  type: "text",
@@ -271,7 +271,7 @@ describe("loadFromDb metadata injection rehydration", () => {
271
271
  expect(messages[2].content).toEqual([
272
272
  {
273
273
  type: "text",
274
- text: "<memory __injected>\nmem payload\n</memory>",
274
+ text: "<memory>\nmem payload\n</memory>",
275
275
  },
276
276
  { type: "text", text: "Tail turn" },
277
277
  ]);