@vellumai/assistant 0.11.3 → 0.11.4-dev.202608190019.b94dbf2

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 (596) hide show
  1. package/AGENTS.md +9 -3
  2. package/ARCHITECTURE.md +32 -10
  3. package/docs/architecture/memory.md +43 -5
  4. package/docs/architecture/security.md +96 -152
  5. package/docs/architecture/turn-actor.md +70 -0
  6. package/docs/browser-use-architecture-phase2.md +128 -56
  7. package/docs/flux-turn-detection-spike.md +248 -0
  8. package/docs/guardian-request-flow.md +35 -0
  9. package/docs/stt-provider-onboarding.md +3 -1
  10. package/knip.json +3 -0
  11. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  12. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
  13. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
  14. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  15. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
  16. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
  17. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  18. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
  19. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
  20. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  21. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
  22. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
  23. package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +34 -0
  24. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +166 -1
  25. package/node_modules/@vellumai/gateway-client/src/index.ts +2 -0
  26. package/node_modules/@vellumai/service-contracts/package.json +1 -0
  27. package/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
  28. package/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
  29. package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  30. package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
  31. package/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
  32. package/openapi.yaml +289 -113
  33. package/package.json +1 -1
  34. package/scripts/voice-ttft-spike.ts +3 -3
  35. package/scripts/write-plugin-api-shim.ts +10 -0
  36. package/src/__tests__/app-compiler.test.ts +38 -3
  37. package/src/__tests__/app-control-flow.test.ts +1 -0
  38. package/src/__tests__/approval-routes-http.test.ts +2 -2
  39. package/src/__tests__/assistant-feature-flag-guard.test.ts +25 -3
  40. package/src/__tests__/attachments-store.test.ts +21 -12
  41. package/src/__tests__/byok-default-profile-ensure.test.ts +17 -0
  42. package/src/__tests__/call-setup-flow-name-capture.test.ts +0 -1
  43. package/src/__tests__/call-site-routing-provider.test.ts +1 -1
  44. package/src/__tests__/channel-availability-routes.test.ts +14 -1
  45. package/src/__tests__/channel-capabilities-dedupe.test.ts +214 -0
  46. package/src/__tests__/channel-delivery-store.test.ts +14 -14
  47. package/src/__tests__/channel-inbound-disk-pressure.test.ts +4 -4
  48. package/src/__tests__/channel-setup-panel-ack.test.ts +1 -1
  49. package/src/__tests__/checker.test.ts +20 -314
  50. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +6 -2
  51. package/src/__tests__/compaction-events.test.ts +8 -10
  52. package/src/__tests__/config-loader-backfill.test.ts +3 -3
  53. package/src/__tests__/config-schema.test.ts +25 -10
  54. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
  55. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +8 -11
  56. package/src/__tests__/conversation-agent-loop-overflow.test.ts +8 -11
  57. package/src/__tests__/conversation-agent-loop.test.ts +32 -21
  58. package/src/__tests__/conversation-attachments.test.ts +0 -1
  59. package/src/__tests__/conversation-attention-store.test.ts +63 -0
  60. package/src/__tests__/conversation-confirmation-signals.test.ts +112 -0
  61. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -4
  62. package/src/__tests__/conversation-fork-crud.test.ts +69 -0
  63. package/src/__tests__/conversation-fork-referential.test.ts +67 -0
  64. package/src/__tests__/conversation-fork-retrospective.test.ts +24 -0
  65. package/src/__tests__/conversation-load-history-repair.test.ts +209 -0
  66. package/src/__tests__/conversation-notifiers-provenance.test.ts +59 -0
  67. package/src/__tests__/conversation-queue.test.ts +154 -4
  68. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
  69. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +1 -1
  70. package/src/__tests__/conversation-routes-guardian-reply.test.ts +9 -9
  71. package/src/__tests__/conversation-routes-hidden-queue.test.ts +1 -1
  72. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -1
  73. package/src/__tests__/conversation-runtime-assembly.test.ts +187 -102
  74. package/src/__tests__/conversation-runtime-workspace.test.ts +14 -10
  75. package/src/__tests__/conversation-slash-queue.test.ts +3 -0
  76. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +1 -0
  77. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +1 -0
  78. package/src/__tests__/conversation-surfaces-app-control.test.ts +1 -0
  79. package/src/__tests__/conversation-surfaces-app-open.test.ts +1 -1
  80. package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -1
  81. package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +21 -14
  82. package/src/__tests__/conversation-surfaces-queued-emit.test.ts +1 -0
  83. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1 -0
  84. package/src/__tests__/conversation-surfaces-standalone.test.ts +1 -0
  85. package/src/__tests__/conversation-surfaces-state-update.test.ts +1 -1
  86. package/src/__tests__/conversation-surfaces-table-action.test.ts +1 -1
  87. package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -1
  88. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +1 -1
  89. package/src/__tests__/conversation-tool-setup-attribution.test.ts +1 -1
  90. package/src/__tests__/credential-prompt-route.test.ts +7 -10
  91. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  92. package/src/__tests__/cu-unified-flow.test.ts +1 -0
  93. package/src/__tests__/custom-profile-ensure.test.ts +5 -1
  94. package/src/__tests__/default-plugin-names-guard.test.ts +12 -1
  95. package/src/__tests__/discord-access-request-privacy.test.ts +5 -1
  96. package/src/__tests__/discord-requester-notice-privacy.test.ts +3 -3
  97. package/src/__tests__/document-append-idempotency.test.ts +233 -0
  98. package/src/__tests__/document-sync-tags.test.ts +0 -75
  99. package/src/__tests__/dynamic-skill-background-guard.test.ts +0 -2
  100. package/src/__tests__/edit-propagation.test.ts +107 -11
  101. package/src/__tests__/file-ops-service.test.ts +163 -30
  102. package/src/__tests__/filesystem-tools.test.ts +23 -24
  103. package/src/__tests__/gateway-only-guard.test.ts +2 -5
  104. package/src/__tests__/helpers/gateway-classify-mock.ts +27 -6
  105. package/src/__tests__/helpers/mock-actor-context.ts +49 -0
  106. package/src/__tests__/helpers/mock-conversation.ts +13 -1
  107. package/src/__tests__/host-file-read-tool.test.ts +16 -19
  108. package/src/__tests__/http-user-message-parity.test.ts +1 -1
  109. package/src/__tests__/init-feature-flag-overrides.test.ts +49 -0
  110. package/src/__tests__/injector-chain.test.ts +63 -41
  111. package/src/__tests__/injector-disk-pressure.test.ts +11 -23
  112. package/src/__tests__/inline-skill-load-permissions.test.ts +47 -36
  113. package/src/__tests__/llm-context-resolution.test.ts +73 -1
  114. package/src/__tests__/llm-schema.test.ts +5 -2
  115. package/src/__tests__/managed-skill-lifecycle.test.ts +7 -0
  116. package/src/__tests__/mcp-list-plugin-servers.test.ts +250 -0
  117. package/src/__tests__/media-generate-image.test.ts +131 -21
  118. package/src/__tests__/memory-retrieval-hook.test.ts +100 -7
  119. package/src/__tests__/messages-read-boundary-guard.test.ts +134 -0
  120. package/src/__tests__/mtime-cache.test.ts +3 -1
  121. package/src/__tests__/non-member-access-request.test.ts +0 -20
  122. package/src/__tests__/outbound-slack-persistence.test.ts +40 -1
  123. package/src/__tests__/platform-bash-auto-approve.test.ts +0 -4
  124. package/src/__tests__/plugin-api-store-credential.test.ts +261 -0
  125. package/src/__tests__/plugin-api-webhook-url.test.ts +10 -7
  126. package/src/__tests__/plugin-disabled-state.test.ts +2 -0
  127. package/src/__tests__/plugin-effective-enabled-set.test.ts +55 -3
  128. package/src/__tests__/plugin-execution-context.test.ts +73 -0
  129. package/src/__tests__/plugin-import-boundary-guard.test.ts +5 -1
  130. package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +7 -4
  131. package/src/__tests__/plugin-secret-pattern-contribution.test.ts +1 -1
  132. package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +14 -7
  133. package/src/__tests__/provider-commit-message-generator.test.ts +20 -0
  134. package/src/__tests__/proxy-approval-callback.test.ts +1 -0
  135. package/src/__tests__/qdrant-manager.test.ts +14 -1
  136. package/src/__tests__/reaction-persistence.test.ts +200 -7
  137. package/src/__tests__/require-fresh-approval.test.ts +0 -4
  138. package/src/__tests__/risk-classification-boundary-guard.test.ts +115 -0
  139. package/src/__tests__/run-conversation-turn-persistence.test.ts +460 -105
  140. package/src/__tests__/run-due-schedules.test.ts +21 -0
  141. package/src/__tests__/scaffold-managed-skill-tool.test.ts +187 -18
  142. package/src/__tests__/schedule-routes.test.ts +23 -0
  143. package/src/__tests__/schedule-store.test.ts +17 -0
  144. package/src/__tests__/scoped-approval-grants.test.ts +11 -6
  145. package/src/__tests__/secret-ingress-channel.test.ts +0 -1
  146. package/src/__tests__/secret-ingress-http.test.ts +1 -1
  147. package/src/__tests__/send-endpoint-busy.test.ts +3 -3
  148. package/src/__tests__/skills.test.ts +32 -0
  149. package/src/__tests__/slack-edit-ordering-characterization.test.ts +0 -1
  150. package/src/__tests__/starter-task-flow.test.ts +5 -4
  151. package/src/__tests__/subagent-call-site-routing.test.ts +31 -19
  152. package/src/__tests__/subagent-fork-prompt-role.test.ts +1 -1
  153. package/src/__tests__/subagent-spawn-and-await.test.ts +18 -17
  154. package/src/__tests__/subagent-tool-gate-mode.test.ts +1 -1
  155. package/src/__tests__/subagent-tools.test.ts +81 -101
  156. package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +1 -0
  157. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
  158. package/src/__tests__/tool-executor-lifecycle-events.test.ts +132 -5
  159. package/src/__tests__/tool-executor.test.ts +68 -39
  160. package/src/__tests__/turn-events-store.test.ts +43 -0
  161. package/src/__tests__/ui-choice-copy-surfaces.test.ts +1 -1
  162. package/src/__tests__/ui-shape-teaching.test.ts +33 -0
  163. package/src/__tests__/ui-visual-surface.test.ts +1 -1
  164. package/src/__tests__/ui-voice-picker-surface.test.ts +128 -0
  165. package/src/__tests__/ui-work-result-surface.test.ts +1 -1
  166. package/src/__tests__/user-plugin-loader.test.ts +3 -1
  167. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  168. package/src/__tests__/visible-app-context.test.ts +16 -9
  169. package/src/__tests__/voice-config-update.test.ts +40 -0
  170. package/src/__tests__/voice-scoped-grant-consumer.test.ts +5 -3
  171. package/src/__tests__/voice-session-bridge.test.ts +85 -29
  172. package/src/__tests__/worker-entrypoint-guards.test.ts +54 -0
  173. package/src/__tests__/worker-plugin-surface.test.ts +77 -0
  174. package/src/__tests__/workspace-migration-142-consolidate-voice-front-door.test.ts +158 -0
  175. package/src/__tests__/workspace-migration-143-repair-deprecated-codex-model-id.test.ts +133 -0
  176. package/src/__tests__/workspace-migration-144-convert-stranded-subscription-openai-profiles.test.ts +316 -0
  177. package/src/__tests__/workspace-migration-145-collapse-profile-bindings-to-entries.test.ts +325 -0
  178. package/src/__tests__/workspace-migration-146-repair-retired-fireworks-deepseek-flash-model-id.test.ts +235 -0
  179. package/src/acp/__tests__/acp-claude-oauth.test.ts +10 -2
  180. package/src/acp/__tests__/auth-required.test.ts +161 -0
  181. package/src/acp/acp-claude-oauth.ts +19 -2
  182. package/src/acp/agent-process.test.ts +100 -0
  183. package/src/acp/agent-process.ts +29 -26
  184. package/src/acp/auth-required.ts +102 -0
  185. package/src/acp/session-manager.test.ts +119 -0
  186. package/src/acp/session-manager.ts +76 -3
  187. package/src/api/events/acp-auth-required.ts +55 -0
  188. package/src/api/events/host-file.ts +2 -2
  189. package/src/api/index.ts +7 -0
  190. package/src/api/surfaces.ts +12 -3
  191. package/src/apps/app-store.ts +3 -0
  192. package/src/bundler/package-resolver.ts +2 -30
  193. package/src/calls/__tests__/voice-session-bridge.test.ts +194 -11
  194. package/src/calls/__tests__/voice-triage-escalate.test.ts +102 -0
  195. package/src/calls/call-controller.ts +19 -3
  196. package/src/calls/call-setup-flow.ts +0 -1
  197. package/src/calls/media-stream-stt-session.ts +15 -0
  198. package/src/calls/voice-session-bridge.ts +115 -41
  199. package/src/calls/voice-triage-escalate.ts +105 -2
  200. package/src/channels/__tests__/plugin-channel-declarations.test.ts +161 -0
  201. package/src/channels/config.ts +13 -0
  202. package/src/channels/plugin-channel-declarations.ts +108 -0
  203. package/src/channels/types.ts +30 -0
  204. package/src/cli/AGENTS.md +5 -2
  205. package/src/cli/bundled-modules.ts +29 -0
  206. package/src/cli/commands/credentials.help.ts +2 -2
  207. package/src/cli/commands/db/repair.ts +4 -8
  208. package/src/cli/commands/domain.ts +6 -3
  209. package/src/cli/commands/email.ts +6 -3
  210. package/src/cli/commands/inference-providers.ts +1 -1
  211. package/src/cli/commands/keys.ts +8 -3
  212. package/src/cli/commands/mcp.help.ts +13 -4
  213. package/src/cli/commands/mcp.ts +9 -0
  214. package/src/cli/commands/memory/__tests__/memory-v2.test.ts +57 -7
  215. package/src/cli/commands/memory/__tests__/memory-v3.test.ts +128 -5
  216. package/src/cli/commands/memory/index.help.ts +84 -28
  217. package/src/cli/commands/memory/index.ts +2 -0
  218. package/src/cli/commands/memory/memory-v2.ts +58 -54
  219. package/src/cli/commands/memory/memory-v3.ts +64 -0
  220. package/src/cli/commands/memory/memory-validate.ts +18 -0
  221. package/src/cli/commands/plugins.ts +85 -36
  222. package/src/cli/commands/schedules.ts +35 -1
  223. package/src/cli/commands/stt.help.ts +27 -2
  224. package/src/cli/commands/trust.ts +3 -14
  225. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +39 -0
  226. package/src/cli/lib/bundled-marketplace.json +14 -1
  227. package/src/cli/lib/upgrade-plugin.ts +42 -0
  228. package/src/config/__tests__/balanced-model-experiment.test.ts +278 -0
  229. package/src/config/__tests__/default-profile-catalog.test.ts +34 -2
  230. package/src/config/__tests__/default-provider.test.ts +6 -1
  231. package/src/config/__tests__/profile-materialization.test.ts +75 -19
  232. package/src/config/assistant-feature-flags.ts +36 -15
  233. package/src/config/balanced-model-experiment.ts +35 -0
  234. package/src/config/bundled-skills/acp/SKILL.md +6 -7
  235. package/src/config/bundled-skills/document-editor/SKILL.md +2 -2
  236. package/src/config/bundled-skills/document-editor/TOOLS.json +2 -2
  237. package/src/config/bundled-skills/image-studio/SKILL.md +5 -4
  238. package/src/config/bundled-skills/image-studio/TOOLS.json +1 -1
  239. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +101 -0
  240. package/src/config/bundled-skills/media-processing/services/preprocess.ts +14 -4
  241. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  242. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.test.ts +65 -0
  243. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +7 -1
  244. package/src/config/bundled-skills/settings/tools/shared.ts +16 -0
  245. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +19 -1
  246. package/src/config/bundled-skills/skill-management/TOOLS.json +9 -3
  247. package/src/config/bundled-skills/subagent/SKILL.md +17 -12
  248. package/src/config/bundled-skills/subagent/TOOLS.json +4 -4
  249. package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +22 -1
  250. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +9 -2
  251. package/src/config/call-site-defaults.ts +11 -5
  252. package/src/config/default-profile-catalog.ts +179 -16
  253. package/src/config/default-profile-names.ts +4 -1
  254. package/src/config/default-provider-resolution.ts +4 -0
  255. package/src/config/feature-flag-registry.json +12 -12
  256. package/src/config/llm-context-resolution.ts +11 -3
  257. package/src/config/llm-resolver.ts +28 -1
  258. package/src/config/profile-materialization.ts +70 -22
  259. package/src/config/schemas/__tests__/live-voice.test.ts +107 -4
  260. package/src/config/schemas/call-site-catalog.ts +4 -4
  261. package/src/config/schemas/live-voice.ts +57 -23
  262. package/src/config/schemas/llm.ts +59 -32
  263. package/src/config/schemas/mcp.ts +23 -0
  264. package/src/config/schemas/plugin-updates.ts +6 -2
  265. package/src/config/schemas/stt.ts +1 -0
  266. package/src/config/skills.ts +9 -2
  267. package/src/context/outbound-sanitize.ts +96 -1
  268. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +1 -1
  269. package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +82 -0
  270. package/src/daemon/conversation-agent-loop-handlers.ts +15 -10
  271. package/src/daemon/conversation-agent-loop.ts +31 -19
  272. package/src/daemon/conversation-messaging.ts +5 -1
  273. package/src/daemon/conversation-notifiers.ts +20 -10
  274. package/src/daemon/conversation-process.ts +20 -6
  275. package/src/daemon/conversation-runtime-assembly.ts +12 -6
  276. package/src/daemon/conversation-store.ts +14 -4
  277. package/src/daemon/conversation-surfaces.ts +75 -26
  278. package/src/daemon/conversation-tool-setup.ts +3 -6
  279. package/src/daemon/conversation.ts +154 -51
  280. package/src/daemon/doordash-steps.ts +2 -2
  281. package/src/daemon/lifecycle.ts +14 -1
  282. package/src/daemon/mcp-reload-service.ts +36 -6
  283. package/src/daemon/process-message.ts +13 -26
  284. package/src/daemon/providers-setup.ts +6 -3
  285. package/src/daemon/trust-context-types.ts +29 -0
  286. package/src/daemon/trust-context.ts +12 -7
  287. package/src/daemon/wake-conversation-ops.ts +3 -2
  288. package/src/daemon/windows-compiled-entry.ts +4 -0
  289. package/src/documents/document-store.ts +143 -240
  290. package/src/hooks/hook-loader.ts +3 -3
  291. package/src/hooks/registry.ts +103 -45
  292. package/src/hooks/types.ts +5 -0
  293. package/src/inbound/__tests__/oauth-callback-url.test.ts +83 -0
  294. package/src/inbound/oauth-callback-url.ts +61 -0
  295. package/src/ipc/gateway-client.test.ts +1 -1
  296. package/src/ipc/gateway-client.ts +14 -21
  297. package/src/ipc/gateway-flag-listener.ts +17 -3
  298. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +1 -104
  299. package/src/live-voice/__tests__/live-voice-events.test.ts +7 -8
  300. package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +1050 -0
  301. package/src/live-voice/__tests__/live-voice-metrics.test.ts +115 -8
  302. package/src/live-voice/__tests__/live-voice-photo.test.ts +100 -0
  303. package/src/live-voice/__tests__/live-voice-progress.test.ts +60 -194
  304. package/src/live-voice/__tests__/live-voice-stt.test.ts +14 -0
  305. package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +29 -0
  306. package/src/live-voice/__tests__/live-voice-tts-session.test.ts +0 -483
  307. package/src/live-voice/__tests__/live-voice-vad.test.ts +0 -16
  308. package/src/live-voice/__tests__/progress-narration.test.ts +214 -0
  309. package/src/live-voice/live-voice-archive.ts +2 -0
  310. package/src/live-voice/live-voice-manager.ts +16 -3
  311. package/src/live-voice/live-voice-metrics.ts +57 -32
  312. package/src/live-voice/live-voice-photo.ts +1 -2
  313. package/src/live-voice/live-voice-session.ts +598 -323
  314. package/src/live-voice/progress-narration.ts +277 -0
  315. package/src/live-voice/protocol.ts +21 -1
  316. package/src/live-voice/windows-compiled-live-voice.ts +4 -0
  317. package/src/mcp/__tests__/effective-config.test.ts +238 -0
  318. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
  319. package/src/mcp/__tests__/mcp-oauth-client-registration.test.ts +200 -0
  320. package/src/mcp/__tests__/mcp-oauth-provider.test.ts +9 -9
  321. package/src/mcp/__tests__/plugin-server-credential-isolation.test.ts +95 -0
  322. package/src/mcp/client.ts +16 -11
  323. package/src/mcp/effective-config.ts +113 -0
  324. package/src/mcp/manager.ts +11 -6
  325. package/src/mcp/mcp-auth-orchestrator.ts +13 -22
  326. package/src/mcp/mcp-oauth-provider.ts +205 -240
  327. package/src/monitoring/__tests__/plugin-auto-update.test.ts +166 -3
  328. package/src/monitoring/control.ts +1 -0
  329. package/src/monitoring/db-integrity-sample.ts +4 -5
  330. package/src/monitoring/plugin-auto-update.ts +128 -24
  331. package/src/notifications/AGENTS.md +2 -0
  332. package/src/notifications/approval-card-data.ts +33 -0
  333. package/src/notifications/signal.ts +1 -0
  334. package/src/permissions/AGENTS.md +16 -0
  335. package/src/permissions/checker.test.ts +75 -122
  336. package/src/permissions/checker.ts +44 -560
  337. package/src/permissions/confirmation-guardian-request.test.ts +15 -11
  338. package/src/permissions/confirmation-guardian-request.ts +2 -2
  339. package/src/permissions/prompter.ts +1 -5
  340. package/src/permissions/question-guardian-request.test.ts +14 -6
  341. package/src/permissions/question-guardian-request.ts +1 -2
  342. package/src/persistence/attachments-store.ts +8 -1
  343. package/src/persistence/bookmark-crud.ts +3 -7
  344. package/src/persistence/conversation-attention-store.ts +16 -45
  345. package/src/persistence/conversation-crud.ts +33 -4
  346. package/src/persistence/conversation-lineage.ts +9 -0
  347. package/src/persistence/conversation-queries.ts +182 -52
  348. package/src/persistence/delivery-crud.ts +150 -36
  349. package/src/persistence/embeddings/qdrant-manager.ts +84 -49
  350. package/src/persistence/external-conversation-store.ts +32 -4
  351. package/src/persistence/llm-request-log-store.ts +4 -10
  352. package/src/persistence/llm-usage-store.ts +8 -3
  353. package/src/persistence/message-reads.test.ts +197 -0
  354. package/src/persistence/message-reads.ts +211 -0
  355. package/src/persistence/migrations/360-add-document-workspace-path.ts +5 -14
  356. package/src/persistence/migrations/366-chatgpt-subscription-row-identity.test.ts +120 -0
  357. package/src/persistence/migrations/366-chatgpt-subscription-row-identity.ts +62 -0
  358. package/src/persistence/real-user-turn-filter.ts +27 -3
  359. package/src/persistence/schema/documents.ts +4 -4
  360. package/src/persistence/steps.ts +9 -0
  361. package/src/plugin-api/__tests__/oauth-callback-url-export.test.ts +29 -0
  362. package/src/plugin-api/constants.ts +8 -0
  363. package/src/plugin-api/conversation-turn.ts +195 -5
  364. package/src/plugin-api/index.ts +38 -6
  365. package/src/plugin-api/resolve-credential.ts +3 -2
  366. package/src/plugin-api/store-credential.ts +146 -0
  367. package/src/plugin-api/vision-support.test.ts +1 -1
  368. package/src/plugin-api/webhook-url.ts +13 -11
  369. package/src/plugins/__tests__/mcp-servers.test.ts +371 -0
  370. package/src/plugins/defaults/main.ts +21 -7
  371. package/src/plugins/defaults/memory/AGENTS.md +15 -3
  372. package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +204 -0
  373. package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +72 -0
  374. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +4 -1
  375. package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +4 -1
  376. package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +0 -1
  377. package/src/plugins/defaults/memory/buffer-format.ts +165 -0
  378. package/src/plugins/defaults/memory/context-search/sources/conversations.ts +6 -0
  379. package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +77 -0
  380. package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +24 -6
  381. package/src/plugins/defaults/memory/graph/image-ref-utils.ts +3 -0
  382. package/src/plugins/defaults/memory/graph/tool-handlers.ts +1 -30
  383. package/src/plugins/defaults/memory/graph-topology/pending-buffer.test.ts +34 -0
  384. package/src/plugins/defaults/memory/graph-topology/pending-buffer.ts +17 -24
  385. package/src/plugins/defaults/memory/hooks/post-compact.ts +1 -4
  386. package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +53 -5
  387. package/src/plugins/defaults/memory/indexer.ts +3 -1
  388. package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +19 -7
  389. package/src/plugins/defaults/memory/memory-retrospective-job.ts +4 -4
  390. package/src/plugins/defaults/memory/src/__tests__/memory-v3-gate-stats.test.ts +281 -0
  391. package/src/plugins/defaults/memory/src/memory-v2-routes.ts +12 -10
  392. package/src/plugins/defaults/memory/src/memory-v3-routes.ts +207 -0
  393. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +147 -0
  394. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +8 -0
  395. package/src/plugins/defaults/memory/substrate/__tests__/edge-index.test.ts +0 -30
  396. package/src/plugins/defaults/memory/substrate/__tests__/ingest.test.ts +73 -1
  397. package/src/plugins/defaults/memory/substrate/__tests__/page-index.test.ts +37 -0
  398. package/src/plugins/defaults/memory/substrate/__tests__/page-links.test.ts +208 -0
  399. package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +158 -1
  400. package/src/plugins/defaults/memory/substrate/__tests__/static-context.test.ts +195 -58
  401. package/src/plugins/defaults/memory/substrate/consolidation-job.ts +93 -24
  402. package/src/plugins/defaults/memory/substrate/edge-index.ts +0 -31
  403. package/src/plugins/defaults/memory/substrate/ingest.ts +59 -0
  404. package/src/plugins/defaults/memory/substrate/page-index.ts +35 -8
  405. package/src/plugins/defaults/memory/substrate/page-links.ts +133 -0
  406. package/src/plugins/defaults/memory/substrate/page-store.ts +10 -0
  407. package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +124 -34
  408. package/src/plugins/defaults/memory/substrate/skill-content.ts +8 -1
  409. package/src/plugins/defaults/memory/substrate/static-context.ts +160 -33
  410. package/src/plugins/defaults/memory/substrate/sweep-job.ts +2 -4
  411. package/src/plugins/defaults/memory/v1/graph/extraction.ts +3 -1
  412. package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +18 -0
  413. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +66 -1
  414. package/src/plugins/defaults/memory/v3/card.ts +9 -9
  415. package/src/plugins/defaults/memory/v3/core-set.test.ts +7 -0
  416. package/src/plugins/defaults/memory/v3/core-set.ts +5 -1
  417. package/src/plugins/defaults/memory/v3/edge.ts +13 -57
  418. package/src/plugins/defaults/memory/v3/injector.ts +8 -0
  419. package/src/plugins/defaults/memory/v3/prune.ts +2 -0
  420. package/src/plugins/defaults/memory/v3/selection-log-store.ts +2 -0
  421. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +23 -9
  422. package/src/plugins/defaults/memory/worker-control.ts +1 -0
  423. package/src/plugins/defaults/memory/worker.ts +6 -3
  424. package/src/plugins/defaults/worker-entrypoints.ts +3 -0
  425. package/src/plugins/external-plugin-loader.ts +47 -0
  426. package/src/plugins/mcp-servers.ts +361 -0
  427. package/src/plugins/mtime-cache.ts +37 -46
  428. package/src/plugins/pipeline.ts +14 -7
  429. package/src/plugins/plugin-execution-context.ts +35 -11
  430. package/src/plugins/worker-plugin-surface.ts +33 -0
  431. package/src/prompts/templates/system-sections.ts +0 -7
  432. package/src/providers/__tests__/connection-model-compat.test.ts +1 -1
  433. package/src/providers/__tests__/context-overflow-error.test.ts +24 -0
  434. package/src/providers/__tests__/dispatch-connection-routing.test.ts +214 -2
  435. package/src/providers/__tests__/preflight-resolved-config.test.ts +57 -0
  436. package/src/providers/__tests__/retry-callsite.test.ts +25 -2
  437. package/src/providers/anthropic/__tests__/pause-turn-continuation.test.ts +170 -0
  438. package/src/providers/anthropic/client.ts +332 -241
  439. package/src/providers/call-site-routing.ts +30 -3
  440. package/src/providers/connection-resolution.ts +194 -11
  441. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +4 -0
  442. package/src/providers/inference/adapter-factory.ts +3 -0
  443. package/src/providers/inference/auth.ts +6 -0
  444. package/src/providers/inference/connection-availability.ts +24 -2
  445. package/src/providers/inference/connections.ts +2 -0
  446. package/src/providers/model-catalog.ts +3 -3
  447. package/src/providers/model-intents.ts +28 -8
  448. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +163 -40
  449. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +125 -2
  450. package/src/providers/openai/chat-completions-provider.ts +133 -36
  451. package/src/providers/openai/codex-models.ts +2 -1
  452. package/src/providers/provider-send-message.ts +32 -3
  453. package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +433 -0
  454. package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +625 -0
  455. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +34 -0
  456. package/src/providers/speech-to-text/__tests__/resolve.test.ts +285 -6
  457. package/src/providers/speech-to-text/deepgram-flux-frames.ts +395 -0
  458. package/src/providers/speech-to-text/deepgram-flux-realtime.ts +679 -0
  459. package/src/providers/speech-to-text/provider-catalog.ts +99 -8
  460. package/src/providers/speech-to-text/resolve.ts +25 -2
  461. package/src/routes/control.ts +1 -0
  462. package/src/routes/route-host-client.ts +1 -0
  463. package/src/routes/route-host-protocol.ts +7 -0
  464. package/src/routes/worker.ts +48 -15
  465. package/src/runtime/AGENTS.md +16 -17
  466. package/src/runtime/access-request-helper.ts +9 -12
  467. package/src/runtime/agent-wake.ts +18 -15
  468. package/src/runtime/effective-capabilities.test.ts +43 -0
  469. package/src/runtime/effective-capabilities.ts +27 -0
  470. package/src/runtime/guardian-reply-router.ts +6 -2
  471. package/src/runtime/pre-first-message-gate.ts +4 -0
  472. package/src/runtime/routes/__tests__/acp-claude-auth-routes.test.ts +12 -4
  473. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +522 -2
  474. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +52 -0
  475. package/src/runtime/routes/__tests__/default-provider-routes.test.ts +61 -0
  476. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +44 -0
  477. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +102 -1
  478. package/src/runtime/routes/__tests__/plugins-routes.test.ts +132 -35
  479. package/src/runtime/routes/__tests__/schedule-routes-disarm-reason.test.ts +215 -0
  480. package/src/runtime/routes/__tests__/stt-routes.test.ts +25 -0
  481. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +55 -6
  482. package/src/runtime/routes/__tests__/user-route-dispatcher-host.test.ts +52 -1
  483. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +133 -1
  484. package/src/runtime/routes/channel-availability-routes.ts +32 -14
  485. package/src/runtime/routes/channel-route-shared.ts +0 -6
  486. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +6 -6
  487. package/src/runtime/routes/conversation-list-routes.ts +181 -23
  488. package/src/runtime/routes/conversation-management-routes.ts +17 -12
  489. package/src/runtime/routes/conversation-query-routes.ts +40 -27
  490. package/src/runtime/routes/conversation-routes.ts +43 -29
  491. package/src/runtime/routes/credential-prompt-routes.ts +4 -7
  492. package/src/runtime/routes/credential-routes.ts +26 -82
  493. package/src/runtime/routes/default-provider-routes.ts +15 -0
  494. package/src/runtime/routes/documents-routes.ts +3 -222
  495. package/src/runtime/routes/inbound-message-handler.ts +21 -45
  496. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +0 -1
  497. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -9
  498. package/src/runtime/routes/inbound-stages/admission-policy.ts +1 -17
  499. package/src/runtime/routes/inbound-stages/bootstrap-intercept.test.ts +0 -1
  500. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -3
  501. package/src/runtime/routes/inbound-stages/edit-intercept.ts +101 -79
  502. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +0 -1
  503. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +12 -7
  504. package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +91 -8
  505. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +72 -79
  506. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +2 -3
  507. package/src/runtime/routes/inference-profiles-routes.ts +20 -11
  508. package/src/runtime/routes/inference-provider-connection-routes.ts +77 -15
  509. package/src/runtime/routes/log-export-routes.ts +3 -0
  510. package/src/runtime/routes/mcp-auth-routes.ts +148 -57
  511. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +2 -0
  512. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +3 -0
  513. package/src/runtime/routes/playground/inject-failures.ts +2 -2
  514. package/src/runtime/routes/playground/reset-circuit.ts +1 -1
  515. package/src/runtime/routes/plugins-routes.ts +38 -8
  516. package/src/runtime/routes/schedule-routes.ts +94 -7
  517. package/src/runtime/routes/settings-routes.ts +6 -6
  518. package/src/runtime/routes/stt-routes.ts +31 -25
  519. package/src/runtime/routes/surface-action-routes.ts +20 -19
  520. package/src/runtime/routes/surface-conversation-resolver.ts +3 -0
  521. package/src/runtime/routes/user-route-dispatcher.ts +69 -15
  522. package/src/runtime/routes/user-route-import.ts +108 -0
  523. package/src/runtime/routes/user-route-resolution.ts +18 -1
  524. package/src/runtime/routes/workspace-routes.ts +0 -9
  525. package/src/runtime/routes/workspace-utils.ts +3 -13
  526. package/src/runtime/services/conversation-serializer.ts +7 -2
  527. package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +68 -5
  528. package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +81 -0
  529. package/src/schedule/plugin-schedule-availability.ts +58 -0
  530. package/src/schedule/plugin-schedule-declarations.ts +23 -27
  531. package/src/schedule/plugin-schedule-reconciler.ts +12 -3
  532. package/src/schedule/schedule-store.ts +5 -1
  533. package/src/schedule/scheduler.ts +9 -4
  534. package/src/schedule/worker-control.ts +1 -0
  535. package/src/schedule/worker.ts +6 -0
  536. package/src/security/oauth2.ts +6 -22
  537. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +22 -0
  538. package/src/stt/__tests__/types.test.ts +94 -0
  539. package/src/stt/daemon-batch-transcriber.ts +10 -0
  540. package/src/stt/stt-stream-session.ts +8 -4
  541. package/src/stt/types.ts +103 -0
  542. package/src/subagent/__tests__/consult-prompt.test.ts +26 -15
  543. package/src/subagent/consult-context.ts +11 -11
  544. package/src/subagent/consult-prompt.ts +26 -35
  545. package/src/subagent/manager.ts +21 -40
  546. package/src/subagent/notify.ts +7 -1
  547. package/src/subagent/types.ts +15 -12
  548. package/src/tools/__tests__/tool-input-schemas.test.ts +7 -7
  549. package/src/tools/acp/spawn.test.ts +97 -0
  550. package/src/tools/acp/spawn.ts +38 -4
  551. package/src/tools/credentials/ref-parse.ts +35 -0
  552. package/src/tools/credentials/resolve.ts +4 -10
  553. package/src/tools/credentials/store.ts +168 -0
  554. package/src/tools/document/document-tool.ts +12 -3
  555. package/src/tools/executor.ts +53 -15
  556. package/src/tools/filesystem/read.ts +27 -10
  557. package/src/tools/host-filesystem/read.ts +27 -15
  558. package/src/tools/network/url-safety.ts +9 -16
  559. package/src/tools/permission-checker.ts +43 -52
  560. package/src/tools/registry.ts +2 -1
  561. package/src/tools/shared/filesystem/file-ops-service.ts +63 -35
  562. package/src/tools/shared/filesystem/legacy-read-args.ts +22 -0
  563. package/src/tools/shared/filesystem/types.ts +5 -5
  564. package/src/tools/skills/scaffold-managed.ts +25 -7
  565. package/src/tools/subagent/spawn.ts +28 -88
  566. package/src/tools/tool-types.ts +26 -13
  567. package/src/tools/types.ts +6 -6
  568. package/src/tools/ui-surface/surface-shape-docs.ts +12 -1
  569. package/src/tools/workflows/run-workflow.ts +1 -2
  570. package/src/tts/__tests__/reasoning-tag-filter.test.ts +78 -0
  571. package/src/tts/reasoning-tag-filter.ts +89 -0
  572. package/src/util/__tests__/worker-process-command.test.ts +37 -0
  573. package/src/util/logger.ts +16 -0
  574. package/src/util/think-tag-stream.ts +95 -0
  575. package/src/util/worker-process.ts +37 -4
  576. package/src/windows-compiled-cli.ts +32 -0
  577. package/src/windows-compiled-entry.ts +4 -0
  578. package/src/windows-compiled-logger.ts +6 -0
  579. package/src/windows-compiled-worker-entry.ts +29 -0
  580. package/src/workspace/byok-default-profile-ensure.ts +76 -24
  581. package/src/workspace/custom-profile-ensure.ts +4 -24
  582. package/src/workspace/migrations/142-consolidate-voice-front-door.ts +70 -0
  583. package/src/workspace/migrations/143-repair-deprecated-codex-model-id.ts +134 -0
  584. package/src/workspace/migrations/144-convert-stranded-subscription-openai-profiles.ts +265 -0
  585. package/src/workspace/migrations/145-collapse-profile-bindings-to-entries.ts +328 -0
  586. package/src/workspace/migrations/146-repair-retired-fireworks-deepseek-flash-model-id.ts +195 -0
  587. package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +0 -10
  588. package/src/workspace/migrations/registry.ts +10 -0
  589. package/src/workspace/provider-commit-message-generator.ts +7 -5
  590. package/src/__tests__/document-workspace-file.test.ts +0 -467
  591. package/src/live-voice/__tests__/front-decision.test.ts +0 -645
  592. package/src/live-voice/front-decision.ts +0 -476
  593. package/src/permissions/ipc-risk-types.ts +0 -143
  594. package/src/permissions/risk-types.ts +0 -76
  595. package/src/subagent/__tests__/consult-transcript.test.ts +0 -184
  596. package/src/subagent/consult-transcript.ts +0 -90
@@ -10,10 +10,11 @@ import { tmpdir } from "node:os";
10
10
  import { join } from "node:path";
11
11
  import { afterEach, describe, expect, test } from "bun:test";
12
12
 
13
+ import { THRESHOLD_CHARS } from "../context/post-turn-tool-result-truncation.js";
13
14
  import {
14
- DEFAULT_READ_LINE_LIMIT,
15
15
  FileSystemOps,
16
16
  type PathPolicy,
17
+ READ_CHAR_BUDGET,
17
18
  } from "../tools/shared/filesystem/file-ops-service.js";
18
19
  import { sandboxPolicy } from "../tools/shared/filesystem/path-policy.js";
19
20
 
@@ -111,34 +112,28 @@ describe("FileSystemOps.readFileSafe", () => {
111
112
  expect(result.error.code).toBe("PATH_OUT_OF_BOUNDS");
112
113
  });
113
114
 
114
- test("respects offset and limit", async () => {
115
+ test("respects startIndex and maxChars", async () => {
115
116
  const dir = makeTempDir();
116
117
  writeFileSync(join(dir, "lines.txt"), "a\nb\nc\nd\ne\n");
117
118
  const ops = new FileSystemOps(sandboxPolicyFor(dir));
118
119
 
119
120
  const result = await ops.readFileSafe({
120
121
  path: "lines.txt",
121
- offset: 2,
122
- limit: 2,
122
+ startIndex: 2,
123
+ maxChars: 3,
123
124
  });
124
125
  expect(result.ok).toBe(true);
125
126
  if (!result.ok) {
126
127
  return;
127
128
  }
128
- // Assert on the numbered lines rather than bare letters: the truncation
129
- // notice is prose, so a bare `toContain("d")` matches its wording.
130
129
  const [body] = result.value.content.split("\n\n[Truncated:");
131
- expect(body).toContain(" 2 b");
132
- expect(body).toContain(" 3 c");
133
- expect(body).not.toContain(" 1 a");
134
- expect(body).not.toContain(" 4 d");
130
+ expect(body).toBe("b\nc");
135
131
  });
136
132
 
137
- test("caps an unbounded read at the default line limit and says so", async () => {
133
+ test("caps an unbounded read at the character budget and says so", async () => {
138
134
  const dir = makeTempDir();
139
- const total = DEFAULT_READ_LINE_LIMIT + 500;
140
- const lines = Array.from({ length: total }, (_, i) => `line${i + 1}`);
141
- writeFileSync(join(dir, "big.txt"), lines.join("\n"));
135
+ const total = READ_CHAR_BUDGET + 500;
136
+ writeFileSync(join(dir, "big.txt"), "x".repeat(total));
142
137
  const ops = new FileSystemOps(sandboxPolicyFor(dir));
143
138
 
144
139
  const result = await ops.readFileSafe({ path: "big.txt" });
@@ -146,36 +141,74 @@ describe("FileSystemOps.readFileSafe", () => {
146
141
  if (!result.ok) {
147
142
  return;
148
143
  }
149
- const content = result.value.content;
150
- expect(content).toContain(` ${DEFAULT_READ_LINE_LIMIT} line2000`);
151
- expect(content).not.toContain("line2001");
152
- expect(content).toContain(
153
- `[Truncated: showing through line ${DEFAULT_READ_LINE_LIMIT} of ${total}. Read on with offset=${DEFAULT_READ_LINE_LIMIT + 1}`,
144
+ const [body] = result.value.content.split("\n\n[Truncated:");
145
+ expect(body).toHaveLength(READ_CHAR_BUDGET);
146
+ expect(result.value.content).toContain(
147
+ `[Truncated: characters 0-${READ_CHAR_BUDGET} of ${total}. Read on with start_index=${READ_CHAR_BUDGET}.]`,
154
148
  );
155
149
  });
156
150
 
157
- test("an explicit limit is honored rather than replaced by the default", async () => {
151
+ test("a maxChars above the budget is clamped to it", async () => {
158
152
  const dir = makeTempDir();
159
- const lines = Array.from(
160
- { length: DEFAULT_READ_LINE_LIMIT + 500 },
161
- (_, i) => `line${i + 1}`,
162
- );
163
- writeFileSync(join(dir, "big.txt"), lines.join("\n"));
153
+ const total = READ_CHAR_BUDGET + 500;
154
+ writeFileSync(join(dir, "big.txt"), "x".repeat(total));
164
155
  const ops = new FileSystemOps(sandboxPolicyFor(dir));
165
156
 
166
157
  const result = await ops.readFileSafe({
167
158
  path: "big.txt",
168
- limit: DEFAULT_READ_LINE_LIMIT + 500,
159
+ maxChars: total,
169
160
  });
170
161
  expect(result.ok).toBe(true);
171
162
  if (!result.ok) {
172
163
  return;
173
164
  }
174
- expect(result.value.content).toContain("line2500");
175
- expect(result.value.content).not.toContain("[Truncated:");
165
+ const [body] = result.value.content.split("\n\n[Truncated:");
166
+ expect(body).toHaveLength(READ_CHAR_BUDGET);
167
+ });
168
+
169
+ test("a maxChars below the budget is honored as given", async () => {
170
+ const dir = makeTempDir();
171
+ writeFileSync(join(dir, "big.txt"), "x".repeat(500));
172
+ const ops = new FileSystemOps(sandboxPolicyFor(dir));
173
+
174
+ const result = await ops.readFileSafe({ path: "big.txt", maxChars: 10 });
175
+ expect(result.ok).toBe(true);
176
+ if (!result.ok) {
177
+ return;
178
+ }
179
+ const [body] = result.value.content.split("\n\n[Truncated:");
180
+ expect(body).toHaveLength(10);
181
+ expect(result.value.content).toContain(
182
+ "[Truncated: characters 0-10 of 500. Read on with start_index=10.]",
183
+ );
184
+ });
185
+
186
+ test("paging with the offset from a notice returns the next window", async () => {
187
+ const dir = makeTempDir();
188
+ writeFileSync(join(dir, "big.txt"), "abcdefghij");
189
+ const ops = new FileSystemOps(sandboxPolicyFor(dir));
190
+
191
+ const first = await ops.readFileSafe({ path: "big.txt", maxChars: 4 });
192
+ expect(first.ok).toBe(true);
193
+ if (!first.ok) {
194
+ return;
195
+ }
196
+ expect(first.value.content).toContain("start_index=4");
197
+
198
+ const second = await ops.readFileSafe({
199
+ path: "big.txt",
200
+ startIndex: 4,
201
+ maxChars: 4,
202
+ });
203
+ expect(second.ok).toBe(true);
204
+ if (!second.ok) {
205
+ return;
206
+ }
207
+ const [body] = second.value.content.split("\n\n[Truncated:");
208
+ expect(body).toBe("efgh");
176
209
  });
177
210
 
178
- test("a read that reaches the last line carries no truncation notice", async () => {
211
+ test("a read that reaches the end carries no truncation notice", async () => {
179
212
  const dir = makeTempDir();
180
213
  writeFileSync(join(dir, "small.txt"), "a\nb\nc");
181
214
  const ops = new FileSystemOps(sandboxPolicyFor(dir));
@@ -193,13 +226,113 @@ describe("FileSystemOps.readFileSafe", () => {
193
226
  writeFileSync(join(dir, "small.txt"), "a\nb\nc");
194
227
  const ops = new FileSystemOps(sandboxPolicyFor(dir));
195
228
 
196
- const result = await ops.readFileSafe({ path: "small.txt", offset: 100 });
229
+ const result = await ops.readFileSafe({
230
+ path: "small.txt",
231
+ startIndex: 100,
232
+ });
197
233
  expect(result.ok).toBe(true);
198
234
  if (!result.ok) {
199
235
  return;
200
236
  }
201
237
  expect(result.value.content).not.toContain("[Truncated:");
202
238
  });
239
+
240
+ test("a window boundary inside a surrogate pair does not corrupt it", async () => {
241
+ const dir = makeTempDir();
242
+ // "ab" + a 2-unit emoji + "cd": a maxChars of 3 would split the pair.
243
+ writeFileSync(join(dir, "emoji.txt"), `ab\u{1F600}cd`);
244
+ const ops = new FileSystemOps(sandboxPolicyFor(dir));
245
+
246
+ const result = await ops.readFileSafe({ path: "emoji.txt", maxChars: 3 });
247
+ expect(result.ok).toBe(true);
248
+ if (!result.ok) {
249
+ return;
250
+ }
251
+ const [body] = result.value.content.split("\n\n[Truncated:");
252
+ expect(body).toBe("ab");
253
+ expect(body).not.toContain("\uFFFD");
254
+ });
255
+
256
+ test("paging across a surrogate pair reassembles the whole file", async () => {
257
+ const dir = makeTempDir();
258
+ const original = `ab\u{1F600}cd`;
259
+ writeFileSync(join(dir, "emoji.txt"), original);
260
+ const ops = new FileSystemOps(sandboxPolicyFor(dir));
261
+
262
+ let assembled = "";
263
+ let startIndex = 0;
264
+ for (let i = 0; i < 10; i++) {
265
+ const result = await ops.readFileSafe({
266
+ path: "emoji.txt",
267
+ startIndex,
268
+ maxChars: 3,
269
+ });
270
+ expect(result.ok).toBe(true);
271
+ if (!result.ok) {
272
+ return;
273
+ }
274
+ const [body] = result.value.content.split("\n\n[Truncated:");
275
+ assembled += body;
276
+ const match = /start_index=(\d+)/.exec(result.value.content);
277
+ if (match?.[1] === undefined) {
278
+ break;
279
+ }
280
+ startIndex = Number(match[1]);
281
+ }
282
+ expect(assembled).toBe(original);
283
+ });
284
+
285
+ test("a lone-low-surrogate startIndex backs up onto the whole pair", async () => {
286
+ const dir = makeTempDir();
287
+ writeFileSync(join(dir, "emoji.txt"), `ab\u{1F600}cd`);
288
+ const ops = new FileSystemOps(sandboxPolicyFor(dir));
289
+
290
+ // Index 3 (0-indexed) is the low half of the emoji.
291
+ const result = await ops.readFileSafe({
292
+ path: "emoji.txt",
293
+ startIndex: 3,
294
+ maxChars: 2,
295
+ });
296
+ expect(result.ok).toBe(true);
297
+ if (!result.ok) {
298
+ return;
299
+ }
300
+ const [body] = result.value.content.split("\n\n[Truncated:");
301
+ expect(body).toBe(`\u{1F600}`);
302
+ expect(body).not.toContain("\uFFFD");
303
+ });
304
+
305
+ test("legacy offset/limit are rejected rather than silently ignored", async () => {
306
+ const { fileReadTool } = await import("../tools/filesystem/read.js");
307
+ const dir = makeTempDir();
308
+ writeFileSync(join(dir, "big.txt"), "x".repeat(500));
309
+
310
+ const result = await fileReadTool.execute(
311
+ { path: join(dir, "big.txt"), offset: 2001, limit: 2000 },
312
+ { workingDir: dir } as never,
313
+ );
314
+ expect(result.isError).toBe(true);
315
+ expect(result.content).toContain("no longer takes");
316
+ expect(result.content).toContain("start_index");
317
+ });
318
+
319
+ test("legacy fields alongside current ones do not trigger the guard", async () => {
320
+ const { fileReadTool } = await import("../tools/filesystem/read.js");
321
+ const dir = makeTempDir();
322
+ writeFileSync(join(dir, "big.txt"), "abcdefghij");
323
+
324
+ const result = await fileReadTool.execute(
325
+ { path: join(dir, "big.txt"), offset: 1, max_chars: 4 },
326
+ { workingDir: dir } as never,
327
+ );
328
+ expect(result.isError).toBe(false);
329
+ const [body] = result.content.split("\n\n[Truncated:");
330
+ expect(body).toBe("abcd");
331
+ });
332
+
333
+ test("the read budget stays under the tool-result spool threshold", () => {
334
+ expect(READ_CHAR_BUDGET).toBeLessThan(THRESHOLD_CHARS);
335
+ });
203
336
  });
204
337
 
205
338
  // ---------------------------------------------------------------------------
@@ -125,16 +125,19 @@ describe("FileSystemOps symlink handling", () => {
125
125
  });
126
126
 
127
127
  // ===========================================================================
128
- // FileSystemOps: read offset/limit edge cases
128
+ // FileSystemOps: read character-window edge cases
129
129
  // ===========================================================================
130
130
 
131
- describe("FileSystemOps read offset/limit edge cases", () => {
132
- test("offset beyond file length returns empty content", async () => {
131
+ describe("FileSystemOps read character-window edge cases", () => {
132
+ test("startIndex beyond file length returns empty content", async () => {
133
133
  const dir = makeTempDir();
134
134
  writeFileSync(join(dir, "short.txt"), "a\nb\nc");
135
135
  const ops = new FileSystemOps(sandboxPolicyFor(dir));
136
136
 
137
- const result = await ops.readFileSafe({ path: "short.txt", offset: 100 });
137
+ const result = await ops.readFileSafe({
138
+ path: "short.txt",
139
+ startIndex: 100,
140
+ });
138
141
  expect(result.ok).toBe(true);
139
142
  if (!result.ok) {
140
143
  return;
@@ -142,12 +145,12 @@ describe("FileSystemOps read offset/limit edge cases", () => {
142
145
  expect(result.value.content).toBe("");
143
146
  });
144
147
 
145
- test("limit of zero returns empty content", async () => {
148
+ test("maxChars of zero returns empty content", async () => {
146
149
  const dir = makeTempDir();
147
150
  writeFileSync(join(dir, "file.txt"), "a\nb\nc");
148
151
  const ops = new FileSystemOps(sandboxPolicyFor(dir));
149
152
 
150
- const result = await ops.readFileSafe({ path: "file.txt", limit: 0 });
153
+ const result = await ops.readFileSafe({ path: "file.txt", maxChars: 0 });
151
154
  expect(result.ok).toBe(true);
152
155
  if (!result.ok) {
153
156
  return;
@@ -155,61 +158,57 @@ describe("FileSystemOps read offset/limit edge cases", () => {
155
158
  expect(result.value.content).toBe("");
156
159
  });
157
160
 
158
- test("offset=1 reads from first line (1-indexed)", async () => {
161
+ test("startIndex=0 reads from the first character (0-indexed)", async () => {
159
162
  const dir = makeTempDir();
160
163
  writeFileSync(join(dir, "file.txt"), "first\nsecond\nthird");
161
164
  const ops = new FileSystemOps(sandboxPolicyFor(dir));
162
165
 
163
166
  const result = await ops.readFileSafe({
164
167
  path: "file.txt",
165
- offset: 1,
166
- limit: 1,
168
+ startIndex: 0,
169
+ maxChars: 5,
167
170
  });
168
171
  expect(result.ok).toBe(true);
169
172
  if (!result.ok) {
170
173
  return;
171
174
  }
172
- expect(result.value.content).toContain("first");
173
- expect(result.value.content).not.toContain("second");
175
+ const [body] = result.value.content.split("\n\n[Truncated:");
176
+ expect(body).toBe("first");
174
177
  });
175
178
 
176
- test("limit exceeding file length returns all remaining lines", async () => {
179
+ test("maxChars exceeding file length returns the rest of the file", async () => {
177
180
  const dir = makeTempDir();
178
181
  writeFileSync(join(dir, "file.txt"), "a\nb");
179
182
  const ops = new FileSystemOps(sandboxPolicyFor(dir));
180
183
 
181
184
  const result = await ops.readFileSafe({
182
185
  path: "file.txt",
183
- offset: 1,
184
- limit: 1000,
186
+ startIndex: 0,
187
+ maxChars: 1000,
185
188
  });
186
189
  expect(result.ok).toBe(true);
187
190
  if (!result.ok) {
188
191
  return;
189
192
  }
190
- expect(result.value.content).toContain("a");
191
- expect(result.value.content).toContain("b");
193
+ expect(result.value.content).toBe("a\nb");
192
194
  });
193
195
 
194
- test("read adds line numbers starting from offset", async () => {
196
+ test("the window starts at startIndex and carries no line numbers", async () => {
195
197
  const dir = makeTempDir();
196
198
  writeFileSync(join(dir, "file.txt"), "a\nb\nc\nd\ne");
197
199
  const ops = new FileSystemOps(sandboxPolicyFor(dir));
198
200
 
199
201
  const result = await ops.readFileSafe({
200
202
  path: "file.txt",
201
- offset: 3,
202
- limit: 2,
203
+ startIndex: 4,
204
+ maxChars: 3,
203
205
  });
204
206
  expect(result.ok).toBe(true);
205
207
  if (!result.ok) {
206
208
  return;
207
209
  }
208
- // Lines should be numbered 3 and 4
209
- expect(result.value.content).toContain("3");
210
- expect(result.value.content).toContain("4");
211
- expect(result.value.content).toContain("c");
212
- expect(result.value.content).toContain("d");
210
+ const [body] = result.value.content.split("\n\n[Truncated:");
211
+ expect(body).toBe("c\nd");
213
212
  });
214
213
  });
215
214
 
@@ -83,11 +83,8 @@ function isGatewayInternal(filePath: string): boolean {
83
83
  /** Additional files allowed for the interpolated-port check only (use gateway port, not runtime). */
84
84
  const INTERPOLATED_PORT_ALLOWLIST = new Set([
85
85
  "clients/macos/src/main/bundle-flow.ts",
86
- // Electron main bridges the host proxy to a local assistant's gateway
87
- // (gatewayPort) over loopback with a Guardian-minted gateway token — same
88
- // class as bundle-flow.ts. Added with #34049 (host proxy for cloud/managed
89
- // assistants); the allowlist entry was missed there.
90
- "clients/macos/src/main/host-proxy-router.ts",
86
+ // Desktop clients connect to local assistants through their loopback gateway.
87
+ "packages/electron-desktop/src/host-proxy/router.ts",
91
88
  ]);
92
89
 
93
90
  /** Shared violation filter: exempt test files, gateway internals, and allowlisted paths. */
@@ -17,7 +17,7 @@
17
17
  * installIpcMock();
18
18
  *
19
19
  * mockIpcResponse("classify_risk",
20
- * { risk: "low", reason: "ls", matchType: "shell" });
20
+ * { risk: "low", reason: "ls", matchType: "registry", scopeOptions: [] });
21
21
  *
22
22
  * const result = await classifyRisk("bash", { command: "ls" });
23
23
  */
@@ -36,12 +36,26 @@ export function mockIpcResponse(method: string, response: unknown): void {
36
36
  responses.set(method, response);
37
37
  }
38
38
 
39
- /** Clear all registered responses. */
39
+ /** Clear all registered responses and captured params. */
40
40
  export function clearIpcMocks(): void {
41
41
  responses.clear();
42
+ lastParams.clear();
42
43
  }
43
44
 
44
- function handleCall(method: string): unknown {
45
+ const lastParams = new Map<string, Record<string, unknown> | undefined>();
46
+
47
+ /**
48
+ * The params of the most recent call to `method`, for asserting what the
49
+ * daemon sent rather than what it did with the answer.
50
+ */
51
+ export function lastIpcParams(
52
+ method: string,
53
+ ): Record<string, unknown> | undefined {
54
+ return lastParams.get(method);
55
+ }
56
+
57
+ function handleCall(method: string, params?: Record<string, unknown>): unknown {
58
+ lastParams.set(method, params);
45
59
  const response = responses.get(method);
46
60
  if (response !== undefined) {
47
61
  return response;
@@ -57,11 +71,18 @@ function handleCall(method: string): unknown {
57
71
  */
58
72
  export function installIpcMock(): void {
59
73
  mock.module("@vellumai/gateway-client/ipc-client", () => ({
60
- ipcCall: async (_socketPath: string, method: string) => handleCall(method),
74
+ ipcCall: async (
75
+ _socketPath: string,
76
+ method: string,
77
+ params?: Record<string, unknown>,
78
+ ) => handleCall(method, params),
61
79
 
62
80
  PersistentIpcClient: class MockPersistentIpcClient {
63
- async call(method: string): Promise<unknown> {
64
- return handleCall(method);
81
+ async call(
82
+ method: string,
83
+ params?: Record<string, unknown>,
84
+ ): Promise<unknown> {
85
+ return handleCall(method, params);
65
86
  }
66
87
  destroy(): void {}
67
88
  },
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Typed fixture factories for actor identity in tests.
3
+ *
4
+ * A fixture built here is a complete, type-checked `TrustContext` or
5
+ * `AuthContext` with conservative defaults; a test overrides only the fields
6
+ * its scenario is about, and the compiler guards the rest. Hand-rolled
7
+ * literals cannot make that guarantee: a missing required field needs a cast
8
+ * to satisfy the checker, and the cast then hides every other mistake in the
9
+ * literal.
10
+ *
11
+ * Type-only imports keep this helper out of the runtime import graph, per the
12
+ * test-machinery isolation rules in `assistant/CLAUDE.md`.
13
+ */
14
+
15
+ import type { TrustContext } from "../../daemon/trust-context-types.js";
16
+ import type { AuthContext, Scope } from "../../runtime/auth/types.js";
17
+
18
+ /**
19
+ * A complete `TrustContext`. Defaults to the guardian on the vellum channel;
20
+ * pass overrides for anything the test cares about.
21
+ */
22
+ export function mockTrustContext(
23
+ overrides: Partial<TrustContext> = {},
24
+ ): TrustContext {
25
+ return {
26
+ sourceChannel: "vellum",
27
+ trustClass: "guardian",
28
+ ...overrides,
29
+ };
30
+ }
31
+
32
+ /**
33
+ * A complete `AuthContext`. Defaults to a local principal with no scopes, the
34
+ * conservative shape, so a test that forgets to opt in exercises the
35
+ * restrictive branch rather than a silently permissive one.
36
+ */
37
+ export function mockAuthContext(
38
+ overrides: Partial<AuthContext> = {},
39
+ ): AuthContext {
40
+ return {
41
+ subject: "local:self:test",
42
+ principalType: "local",
43
+ assistantId: "self",
44
+ scopeProfile: "local_v1",
45
+ scopes: new Set<Scope>(),
46
+ policyEpoch: 0,
47
+ ...overrides,
48
+ };
49
+ }
@@ -26,7 +26,19 @@ import type { ChannelCapabilities } from "../../daemon/conversation-runtime-asse
26
26
  export function asConversation<TExtra extends object = object>(
27
27
  mock: Partial<Conversation> & TExtra,
28
28
  ): Conversation & TExtra {
29
- return mock as unknown as Conversation & TExtra;
29
+ // Trust accessors, derived from the double's own fields exactly as the real
30
+ // class derives them, so a double that sets (or later mutates) the fields
31
+ // resolves the same values production would. Supplied only when the double
32
+ // does not bring its own, and reading through `merged` rather than `mock`
33
+ // so a test that reassigns the fields on the returned object is honoured.
34
+ const merged: Partial<Conversation> & TExtra = {
35
+ getTurnTrust: () => merged.currentTurnTrustContext,
36
+ getTrustContext: () => merged.trustContext,
37
+ getTurnOrRestingTrust: () =>
38
+ merged.currentTurnTrustContext ?? merged.trustContext,
39
+ ...mock,
40
+ };
41
+ return merged as unknown as Conversation & TExtra;
30
42
  }
31
43
 
32
44
  /**
@@ -27,7 +27,7 @@ mock.module("../daemon/host-file-proxy.js", () => ({
27
27
  }));
28
28
 
29
29
  import { hostFileReadTool } from "../tools/host-filesystem/read.js";
30
- import { DEFAULT_READ_LINE_LIMIT } from "../tools/shared/filesystem/file-ops-service.js";
30
+ import { READ_CHAR_BUDGET } from "../tools/shared/filesystem/file-ops-service.js";
31
31
  import type { ToolContext } from "../tools/types.js";
32
32
 
33
33
  const testDirs: string[] = [];
@@ -77,19 +77,19 @@ describe("host_file_read tool", () => {
77
77
  expect(result.content).toContain("must be absolute");
78
78
  });
79
79
 
80
- test("reads file with line numbers", async () => {
80
+ test("reads a character window", async () => {
81
81
  const dir = mkdtempSync(join(tmpdir(), "host-file-read-test-"));
82
82
  testDirs.push(dir);
83
83
  const filePath = join(dir, "sample.txt");
84
84
  writeFileSync(filePath, "first\nsecond\nthird\n");
85
85
 
86
86
  const result = await hostFileReadTool.execute(
87
- { path: filePath, offset: 2, limit: 2 },
87
+ { path: filePath, start_index: 6, max_chars: 6 },
88
88
  makeContext(),
89
89
  );
90
90
  expect(result.isError).toBe(false);
91
- expect(result.content).toContain("2 second");
92
- expect(result.content).toContain("3 third");
91
+ expect(result.content).toContain("second");
92
+ expect(result.content).not.toContain("first");
93
93
  });
94
94
 
95
95
  test("returns error when file does not exist", async () => {
@@ -128,7 +128,7 @@ describe("host_file_read tool", () => {
128
128
  expect(result.content).toContain('Invalid input for tool "host_file_read"');
129
129
  });
130
130
 
131
- test("reads entire file when no offset or limit specified", async () => {
131
+ test("reads the whole file when no window is specified", async () => {
132
132
  const dir = mkdtempSync(join(tmpdir(), "host-file-read-test-"));
133
133
  testDirs.push(dir);
134
134
  const filePath = join(dir, "full.txt");
@@ -139,9 +139,7 @@ describe("host_file_read tool", () => {
139
139
  makeContext(),
140
140
  );
141
141
  expect(result.isError).toBe(false);
142
- expect(result.content).toContain("1 line1");
143
- expect(result.content).toContain("2 line2");
144
- expect(result.content).toContain("3 line3");
142
+ expect(result.content).toBe("line1\nline2\nline3\n");
145
143
  });
146
144
 
147
145
  test("handles empty file", async () => {
@@ -157,20 +155,19 @@ describe("host_file_read tool", () => {
157
155
  expect(result.isError).toBe(false);
158
156
  });
159
157
 
160
- test("offset starts from the correct line (1-indexed)", async () => {
158
+ test("start_index is 0-indexed", async () => {
161
159
  const dir = mkdtempSync(join(tmpdir(), "host-file-read-test-"));
162
160
  testDirs.push(dir);
163
161
  const filePath = join(dir, "lines.txt");
164
162
  writeFileSync(filePath, "a\nb\nc\nd\ne\n");
165
163
 
166
164
  const result = await hostFileReadTool.execute(
167
- { path: filePath, offset: 3, limit: 1 },
165
+ { path: filePath, start_index: 4, max_chars: 1 },
168
166
  makeContext(),
169
167
  );
170
168
  expect(result.isError).toBe(false);
171
- expect(result.content).toContain("3 c");
172
- expect(result.content).not.toContain("2 b");
173
- expect(result.content).not.toContain("4 d");
169
+ const [body] = result.content.split("\n\n[Truncated:");
170
+ expect(body).toBe("c");
174
171
  });
175
172
 
176
173
  test("reads a file with symlinks resolved", async () => {
@@ -228,15 +225,15 @@ describe("host_file_read image support", () => {
228
225
  expect(result.isError).toBe(false);
229
226
  expect(result.contentBlocks).toHaveLength(1);
230
227
  // The proxied request carries the resolved default window, so a host read
231
- // is bounded by the same limit as a local one rather than streaming a
228
+ // is bounded by the same budget as a local one rather than streaming a
232
229
  // whole file across the bridge.
233
230
  expect(requests).toEqual([
234
231
  {
235
232
  input: {
236
233
  operation: "read",
237
234
  path: "/host/screenshot.png",
238
- offset: undefined,
239
- limit: DEFAULT_READ_LINE_LIMIT,
235
+ startIndex: undefined,
236
+ maxChars: READ_CHAR_BUDGET,
240
237
  },
241
238
  conversationId: "test-conversation",
242
239
  signal: undefined,
@@ -306,8 +303,8 @@ describe("host_file_read image support", () => {
306
303
  );
307
304
 
308
305
  expect(result.isError).toBe(false);
309
- expect(result.content).toContain("1 hello world");
310
- expect(result.content).toContain("2 second line");
306
+ expect(result.content).toContain("hello world");
307
+ expect(result.content).toContain("second line");
311
308
  expect((result as any).contentBlocks).toBeUndefined();
312
309
  });
313
310
 
@@ -189,7 +189,7 @@ const _testAuthContext: AuthContext = {
189
189
  function makeConversation(overrides: Record<string, unknown> = {}) {
190
190
  return {
191
191
  setTrustContext: () => {},
192
- updateClient: () => {},
192
+ replayActivityState: () => {},
193
193
  setHostBrowserProxy: () => {},
194
194
  setHostCuProxy: () => {},
195
195
  setHostAppControlProxy: () => {},