@vellumai/assistant 0.7.0 → 0.7.2

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 (989) hide show
  1. package/ARCHITECTURE.md +38 -56
  2. package/Dockerfile +2 -0
  3. package/README.md +3 -4
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +88 -142
  5. package/bun.lock +29 -26
  6. package/docs/architecture/security.md +38 -16
  7. package/docs/plugins.md +7 -9
  8. package/knip.json +2 -0
  9. package/node_modules/@vellumai/gateway-client/src/index.ts +1 -0
  10. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +39 -1
  11. package/node_modules/@vellumai/gateway-client/src/types.ts +11 -0
  12. package/node_modules/@vellumai/service-contracts/package.json +2 -0
  13. package/node_modules/@vellumai/service-contracts/src/__tests__/contracts.test.ts +4 -0
  14. package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +107 -0
  15. package/node_modules/@vellumai/service-contracts/src/index.ts +5 -1
  16. package/node_modules/@vellumai/service-contracts/src/ingress.ts +24 -0
  17. package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +84 -0
  18. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  19. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +9 -5
  20. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  21. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  22. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  23. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  24. package/node_modules/@vellumai/slack-text/package.json +18 -0
  25. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  26. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  27. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  28. package/node_modules/@vellumai/twilio-client/bun.lock +24 -0
  29. package/node_modules/@vellumai/twilio-client/package.json +18 -0
  30. package/node_modules/@vellumai/twilio-client/src/__tests__/twilio-client.test.ts +128 -0
  31. package/node_modules/@vellumai/twilio-client/src/index.ts +179 -0
  32. package/node_modules/@vellumai/twilio-client/tsconfig.json +20 -0
  33. package/openapi.yaml +869 -129
  34. package/package.json +8 -3
  35. package/scripts/generate-openapi.ts +16 -111
  36. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  37. package/src/__tests__/anthropic-provider.test.ts +56 -13
  38. package/src/__tests__/app-builder-tool-scripts.test.ts +3 -3
  39. package/src/__tests__/app-bundler.test.ts +170 -1
  40. package/src/__tests__/app-control-flow.test.ts +374 -0
  41. package/src/__tests__/app-control-no-global-cgevent.test.ts +98 -0
  42. package/src/__tests__/app-control-tool-schemas.test.ts +621 -0
  43. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  44. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  45. package/src/__tests__/app-executors.test.ts +30 -43
  46. package/src/__tests__/approval-cascade.test.ts +0 -15
  47. package/src/__tests__/approval-routes-http.test.ts +29 -23
  48. package/src/__tests__/assistant-event-hub-machine-name.test.ts +146 -0
  49. package/src/__tests__/assistant-event-hub-targeted.test.ts +257 -0
  50. package/src/__tests__/assistant-event-hub.test.ts +235 -79
  51. package/src/__tests__/assistant-event.test.ts +10 -5
  52. package/src/__tests__/assistant-events-sse-hardening.test.ts +44 -17
  53. package/src/__tests__/assistant-feature-flags-integration.test.ts +11 -36
  54. package/src/__tests__/background-shell-host-bash.test.ts +46 -56
  55. package/src/__tests__/bootstrap-turn-cleanup.test.ts +44 -0
  56. package/src/__tests__/btw-routes.test.ts +13 -4
  57. package/src/__tests__/call-controller.test.ts +50 -2
  58. package/src/__tests__/call-domain.test.ts +0 -2
  59. package/src/__tests__/call-routes-http.test.ts +0 -2
  60. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  61. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  62. package/src/__tests__/channel-approvals.test.ts +25 -17
  63. package/src/__tests__/channel-guardian.test.ts +100 -146
  64. package/src/__tests__/channel-readiness-service.test.ts +59 -1
  65. package/src/__tests__/checker.test.ts +23 -38
  66. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  67. package/src/__tests__/compaction-events.test.ts +2 -0
  68. package/src/__tests__/config-loader-backfill.test.ts +90 -155
  69. package/src/__tests__/config-loader-platform-defaults.test.ts +196 -0
  70. package/src/__tests__/config-schema-cmd.test.ts +0 -1
  71. package/src/__tests__/config-schema.test.ts +6 -48
  72. package/src/__tests__/config-set-platform-guard.test.ts +48 -4
  73. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +2 -2
  74. package/src/__tests__/config-watcher.test.ts +14 -2
  75. package/src/__tests__/connection-policy.test.ts +1 -52
  76. package/src/__tests__/contacts-write.test.ts +2 -64
  77. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  78. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  79. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  80. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  81. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  82. package/src/__tests__/context-window-manager.test.ts +46 -0
  83. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  84. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  85. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  86. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  87. package/src/__tests__/conversation-app-control-instantiation.test.ts +392 -0
  88. package/src/__tests__/conversation-app-control-lifecycle.test.ts +237 -0
  89. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  90. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  91. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  92. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  93. package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
  94. package/src/__tests__/conversation-lifecycle.test.ts +40 -4
  95. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +283 -0
  96. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  97. package/src/__tests__/conversation-queue.test.ts +3 -8
  98. package/src/__tests__/conversation-routes-disk-view.test.ts +7 -161
  99. package/src/__tests__/conversation-routes-guardian-reply.test.ts +120 -104
  100. package/src/__tests__/conversation-routes-slash-commands.test.ts +76 -66
  101. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  102. package/src/__tests__/conversation-slash-commands.test.ts +24 -8
  103. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  104. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  105. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  106. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +202 -0
  107. package/src/__tests__/conversation-surfaces-app-control.test.ts +317 -0
  108. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  109. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  110. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  111. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  112. package/src/__tests__/conversation-usage.test.ts +253 -3
  113. package/src/__tests__/credential-execution-feature-gates.test.ts +5 -12
  114. package/src/__tests__/credential-execution-managed-contract.test.ts +3 -131
  115. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  116. package/src/__tests__/credential-health-service.test.ts +68 -0
  117. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  118. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  119. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  120. package/src/__tests__/credentials-cli.test.ts +5 -12
  121. package/src/__tests__/cu-unified-flow.test.ts +206 -27
  122. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  123. package/src/__tests__/daemon-credential-client.test.ts +102 -17
  124. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  125. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  126. package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -0
  127. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  128. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  129. package/src/__tests__/document-conversations.test.ts +332 -0
  130. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  131. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  132. package/src/__tests__/emit-event-signal.test.ts +4 -6
  133. package/src/__tests__/events-client-registration.test.ts +193 -49
  134. package/src/__tests__/filing-service.test.ts +58 -7
  135. package/src/__tests__/first-greeting.test.ts +156 -150
  136. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  137. package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
  138. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  139. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  140. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  141. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  142. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  143. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  144. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -2
  145. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +30 -11
  146. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -84
  147. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  148. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  149. package/src/__tests__/heartbeat-service.test.ts +1007 -8
  150. package/src/__tests__/helpers/call-route-handler.ts +7 -1
  151. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  152. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  153. package/src/__tests__/host-app-control-proxy.test.ts +602 -0
  154. package/src/__tests__/host-app-control-routes.test.ts +263 -0
  155. package/src/__tests__/host-bash-proxy.test.ts +270 -147
  156. package/src/__tests__/host-bash-routes.test.ts +294 -0
  157. package/src/__tests__/host-browser-proxy.test.ts +126 -198
  158. package/src/__tests__/host-browser-routes.test.ts +50 -54
  159. package/src/__tests__/host-cu-proxy.test.ts +78 -144
  160. package/src/__tests__/host-cu-routes-targeted.test.ts +300 -0
  161. package/src/__tests__/host-file-edit-tool.test.ts +47 -1
  162. package/src/__tests__/host-file-proxy-targeted.test.ts +339 -0
  163. package/src/__tests__/host-file-proxy.test.ts +62 -122
  164. package/src/__tests__/host-file-read-tool.test.ts +59 -21
  165. package/src/__tests__/host-file-routes-targeted.test.ts +262 -0
  166. package/src/__tests__/host-file-write-tool.test.ts +42 -1
  167. package/src/__tests__/host-proxy-base.test.ts +312 -0
  168. package/src/__tests__/host-shell-tool.test.ts +53 -70
  169. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  170. package/src/__tests__/host-transfer-proxy-targeted.test.ts +583 -0
  171. package/src/__tests__/host-transfer-proxy.test.ts +145 -56
  172. package/src/__tests__/host-transfer-routes-targeted.test.ts +447 -0
  173. package/src/__tests__/http-user-message-parity.test.ts +1 -6
  174. package/src/__tests__/identity-intro-cache.test.ts +29 -0
  175. package/src/__tests__/identity-routes.test.ts +103 -1
  176. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  177. package/src/__tests__/init-feature-flag-overrides.test.ts +26 -3
  178. package/src/__tests__/injector-chain.test.ts +10 -5
  179. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  180. package/src/__tests__/inline-command-runner.test.ts +0 -67
  181. package/src/__tests__/inline-skill-load-permissions.test.ts +5 -13
  182. package/src/__tests__/install-skill-routing.test.ts +1 -13
  183. package/src/__tests__/integration-status.test.ts +85 -5
  184. package/src/__tests__/intent-routing.test.ts +0 -1
  185. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +95 -5
  186. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +17 -0
  187. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  188. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  189. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  190. package/src/__tests__/llm-resolver.test.ts +80 -12
  191. package/src/__tests__/llm-usage-store.test.ts +269 -4
  192. package/src/__tests__/log-export-routes.test.ts +89 -0
  193. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  194. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -11
  195. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  196. package/src/__tests__/mcp-auth-routes.test.ts +197 -0
  197. package/src/__tests__/mcp-cli.test.ts +338 -2
  198. package/src/__tests__/memory-jobs-worker-lanes.test.ts +188 -0
  199. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  200. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  201. package/src/__tests__/migration-export-http.test.ts +33 -26
  202. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  203. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  204. package/src/__tests__/migration-import-commit-http.test.ts +172 -21
  205. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  206. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  207. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  208. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  209. package/src/__tests__/migration-transport.test.ts +115 -23
  210. package/src/__tests__/migration-validate-http.test.ts +105 -80
  211. package/src/__tests__/migration-wizard.test.ts +133 -27
  212. package/src/__tests__/mock-gateway-ipc.ts +1 -0
  213. package/src/__tests__/non-member-access-request.test.ts +1 -1
  214. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  215. package/src/__tests__/oauth-cli.test.ts +0 -2
  216. package/src/__tests__/oauth-store.test.ts +19 -0
  217. package/src/__tests__/oauth2-gateway-transport.test.ts +0 -1
  218. package/src/__tests__/persistence-secret-redaction.test.ts +299 -0
  219. package/src/__tests__/platform-bash-auto-approve.test.ts +26 -21
  220. package/src/__tests__/prechat-onboarding-contract.test.ts +34 -8
  221. package/src/__tests__/pricing.test.ts +68 -4
  222. package/src/__tests__/process-message-background-slack.test.ts +333 -0
  223. package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
  224. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  225. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  226. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  227. package/src/__tests__/public-ingress-urls.test.ts +97 -0
  228. package/src/__tests__/reaction-persistence.test.ts +9 -6
  229. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  230. package/src/__tests__/recording-handler.test.ts +64 -81
  231. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  232. package/src/__tests__/relay-server.test.ts +18 -13
  233. package/src/__tests__/require-fresh-approval.test.ts +13 -23
  234. package/src/__tests__/retry-backoff.test.ts +87 -0
  235. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  236. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  237. package/src/__tests__/runtime-events-sse.test.ts +13 -18
  238. package/src/__tests__/sanitize-config-for-transfer.test.ts +24 -2
  239. package/src/__tests__/schedule-retry.test.ts +715 -0
  240. package/src/__tests__/script-proxy-mitm-handler.test.ts +1 -1
  241. package/src/__tests__/search-skills-unified.test.ts +9 -15
  242. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  243. package/src/__tests__/secret-ingress-http.test.ts +1 -4
  244. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  245. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  246. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  247. package/src/__tests__/secret-response-routing.test.ts +29 -15
  248. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  249. package/src/__tests__/secret-scanner.test.ts +2 -545
  250. package/src/__tests__/send-endpoint-busy.test.ts +12 -24
  251. package/src/__tests__/settings-routes.test.ts +1 -1
  252. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  253. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -57
  254. package/src/__tests__/skill-feature-flags.test.ts +43 -41
  255. package/src/__tests__/skill-load-feature-flag.test.ts +13 -14
  256. package/src/__tests__/skill-load-inline-command.test.ts +0 -51
  257. package/src/__tests__/skill-load-inline-includes.test.ts +0 -43
  258. package/src/__tests__/skill-projection.benchmark.test.ts +0 -1
  259. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -12
  260. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  261. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  262. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  263. package/src/__tests__/slack-channel-config.test.ts +9 -14
  264. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  265. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  266. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  267. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  268. package/src/__tests__/system-prompt-ask-mode.test.ts +0 -1
  269. package/src/__tests__/system-prompt.test.ts +115 -14
  270. package/src/__tests__/telegram-config.test.ts +0 -1
  271. package/src/__tests__/terminal-tools.test.ts +0 -89
  272. package/src/__tests__/test-preload.ts +8 -0
  273. package/src/__tests__/thread-backfill.test.ts +945 -31
  274. package/src/__tests__/tool-approval-handler.test.ts +3 -4
  275. package/src/__tests__/tool-audit-listener.test.ts +48 -0
  276. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  277. package/src/__tests__/tool-execute-pipeline.test.ts +0 -7
  278. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -17
  279. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  280. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -8
  281. package/src/__tests__/tool-executor.test.ts +12 -20
  282. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  283. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  284. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  285. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  286. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  287. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  288. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  289. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  290. package/src/__tests__/twilio-config.test.ts +3 -16
  291. package/src/__tests__/twilio-routes.test.ts +3 -5
  292. package/src/__tests__/twilio-validation.test.ts +93 -0
  293. package/src/__tests__/usage-attribution.test.ts +247 -0
  294. package/src/__tests__/usage-cli.test.ts +143 -0
  295. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  296. package/src/__tests__/usage-routes.test.ts +150 -0
  297. package/src/__tests__/validation-results-screen.test.ts +39 -16
  298. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  299. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +47 -138
  300. package/src/__tests__/verification-control-plane-policy.test.ts +6 -11
  301. package/src/__tests__/voice-ingress-preflight.test.ts +19 -0
  302. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  303. package/src/__tests__/workspace-migration-006-services-config.test.ts +3 -2
  304. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  305. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  306. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  307. package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +1 -5
  308. package/src/__tests__/workspace-migration-down-functions.test.ts +8 -8
  309. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  310. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +10 -6
  311. package/src/acp/index.ts +0 -15
  312. package/src/acp/session-manager.ts +37 -34
  313. package/src/agent/loop.ts +16 -1
  314. package/src/approvals/AGENTS.md +4 -0
  315. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  316. package/src/approvals/guardian-request-resolvers.ts +10 -2
  317. package/src/backup/__tests__/paths.test.ts +0 -22
  318. package/src/backup/__tests__/restore.test.ts +94 -177
  319. package/src/backup/paths.ts +2 -15
  320. package/src/backup/restore.ts +107 -231
  321. package/src/browser-session/events.ts +0 -9
  322. package/src/bundler/app-bundler.ts +51 -3
  323. package/src/calls/call-store.ts +1 -34
  324. package/src/calls/guardian-question-copy.ts +0 -108
  325. package/src/calls/relay-server.ts +4 -68
  326. package/src/calls/twilio-config.ts +2 -17
  327. package/src/calls/twilio-rest.ts +31 -141
  328. package/src/calls/twilio-routes.ts +12 -13
  329. package/src/calls/voice-session-bridge.ts +7 -38
  330. package/src/channels/types.ts +8 -42
  331. package/src/cli/commands/__tests__/backup.test.ts +6 -277
  332. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  333. package/src/cli/commands/__tests__/gateway.test.ts +288 -0
  334. package/src/cli/commands/__tests__/memory-v2.test.ts +18 -28
  335. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  336. package/src/cli/commands/__tests__/webhooks.test.ts +0 -1
  337. package/src/cli/commands/backup.ts +6 -331
  338. package/src/cli/commands/cache-fs.ts +8 -0
  339. package/src/cli/commands/cache.ts +153 -82
  340. package/src/cli/commands/clients.ts +64 -7
  341. package/src/cli/commands/completions.ts +3 -3
  342. package/src/cli/commands/contacts.ts +304 -76
  343. package/src/cli/commands/conversations.ts +2 -5
  344. package/src/cli/commands/credentials.ts +15 -7
  345. package/src/cli/commands/domain.ts +66 -15
  346. package/src/cli/commands/gateway.ts +183 -0
  347. package/src/cli/commands/keys.ts +13 -7
  348. package/src/cli/commands/mcp.ts +116 -156
  349. package/src/cli/commands/memory-v2.ts +320 -53
  350. package/src/cli/commands/oauth/shared.ts +2 -29
  351. package/src/cli/commands/pending.ts +102 -0
  352. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
  353. package/src/cli/commands/platform/__tests__/connect.test.ts +0 -2
  354. package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -2
  355. package/src/cli/commands/platform/__tests__/status.test.ts +13 -15
  356. package/src/cli/commands/platform/disconnect.ts +5 -4
  357. package/src/cli/commands/platform/index.ts +0 -18
  358. package/src/cli/commands/skills.ts +77 -35
  359. package/src/cli/commands/trust.ts +70 -430
  360. package/src/cli/commands/usage.ts +25 -16
  361. package/src/cli/lib/daemon-credential-client.ts +115 -19
  362. package/src/cli/program.ts +4 -0
  363. package/src/cli.ts +0 -21
  364. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  365. package/src/config/assistant-feature-flags.ts +67 -10
  366. package/src/config/bundled-skills/acp/SKILL.md +6 -0
  367. package/src/config/bundled-skills/acp/TOOLS.json +1 -22
  368. package/src/config/bundled-skills/app-builder/SKILL.md +14 -109
  369. package/src/config/bundled-skills/app-builder/TOOLS.json +1 -28
  370. package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -10
  371. package/src/config/bundled-skills/app-control/SKILL.md +75 -0
  372. package/src/config/bundled-skills/app-control/TOOLS.json +299 -0
  373. package/src/config/bundled-skills/app-control/tools/app-control-click.ts +12 -0
  374. package/src/config/bundled-skills/app-control/tools/app-control-combo.ts +12 -0
  375. package/src/config/bundled-skills/app-control/tools/app-control-drag.ts +12 -0
  376. package/src/config/bundled-skills/app-control/tools/app-control-observe.ts +12 -0
  377. package/src/config/bundled-skills/app-control/tools/app-control-press.ts +12 -0
  378. package/src/config/bundled-skills/app-control/tools/app-control-sequence.ts +12 -0
  379. package/src/config/bundled-skills/app-control/tools/app-control-start.ts +12 -0
  380. package/src/config/bundled-skills/app-control/tools/app-control-stop.ts +12 -0
  381. package/src/config/bundled-skills/app-control/tools/app-control-type.ts +12 -0
  382. package/src/config/bundled-skills/computer-use/SKILL.md +6 -0
  383. package/src/config/bundled-skills/computer-use/TOOLS.json +67 -43
  384. package/src/config/bundled-skills/contacts/TOOLS.json +0 -16
  385. package/src/config/bundled-skills/document/TOOLS.json +0 -8
  386. package/src/config/bundled-skills/followups/TOOLS.json +0 -12
  387. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  388. package/src/config/bundled-skills/image-studio/TOOLS.json +0 -4
  389. package/src/config/bundled-skills/media-processing/TOOLS.json +0 -24
  390. package/src/config/bundled-skills/messaging/TOOLS.json +14 -44
  391. package/src/config/bundled-skills/phone-calls/TOOLS.json +0 -12
  392. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +19 -4
  393. package/src/config/bundled-skills/playbooks/TOOLS.json +0 -16
  394. package/src/config/bundled-skills/schedule/TOOLS.json +14 -14
  395. package/src/config/bundled-skills/sequences/TOOLS.json +0 -36
  396. package/src/config/bundled-skills/settings/SKILL.md +4 -0
  397. package/src/config/bundled-skills/settings/TOOLS.json +0 -12
  398. package/src/config/bundled-skills/skill-management/SKILL.md +6 -0
  399. package/src/config/bundled-skills/skill-management/TOOLS.json +0 -8
  400. package/src/config/bundled-skills/subagent/SKILL.md +6 -2
  401. package/src/config/bundled-skills/subagent/TOOLS.json +0 -20
  402. package/src/config/bundled-skills/transcribe/SKILL.md +4 -0
  403. package/src/config/bundled-skills/transcribe/TOOLS.json +0 -4
  404. package/src/config/bundled-tool-registry.ts +21 -0
  405. package/src/config/env-registry.ts +12 -4
  406. package/src/config/env.ts +22 -26
  407. package/src/config/feature-flag-registry.json +40 -152
  408. package/src/config/llm-callsite-catalog.ts +12 -0
  409. package/src/config/llm-context-resolution.ts +80 -0
  410. package/src/config/llm-resolver.ts +58 -22
  411. package/src/config/loader.ts +76 -102
  412. package/src/config/sanitize-for-transfer.ts +2 -0
  413. package/src/config/schema.ts +2 -158
  414. package/src/config/schemas/__tests__/memory-lifecycle.test.ts +80 -0
  415. package/src/config/schemas/__tests__/memory-v2.test.ts +8 -4
  416. package/src/config/schemas/call-site-catalog.ts +271 -0
  417. package/src/config/schemas/calls.ts +5 -14
  418. package/src/config/schemas/heartbeat.ts +63 -0
  419. package/src/config/schemas/inference.ts +1 -1
  420. package/src/config/schemas/ingress.ts +11 -7
  421. package/src/config/schemas/llm.ts +34 -11
  422. package/src/config/schemas/memory-lifecycle.ts +77 -24
  423. package/src/config/schemas/memory-retrieval.ts +2 -2
  424. package/src/config/schemas/memory-v2.ts +57 -4
  425. package/src/config/schemas/platform.ts +6 -0
  426. package/src/config/schemas/security.ts +1 -42
  427. package/src/config/schemas/services.ts +7 -21
  428. package/src/config/schemas/skills.ts +5 -11
  429. package/src/config/schemas/tts.ts +1 -1
  430. package/src/config/seed-inference-profiles.ts +117 -0
  431. package/src/config/skills.ts +0 -90
  432. package/src/config/types.ts +3 -6
  433. package/src/contacts/contact-store.ts +0 -47
  434. package/src/contacts/contacts-write.ts +1 -132
  435. package/src/context/window-manager.ts +43 -5
  436. package/src/credential-execution/feature-gates.ts +10 -10
  437. package/src/credential-execution/process-manager.ts +46 -51
  438. package/src/credential-health/credential-health-service.ts +21 -16
  439. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  440. package/src/daemon/__tests__/conversation-tool-setup.test.ts +126 -5
  441. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  442. package/src/daemon/bootstrap-turn-cleanup.ts +45 -0
  443. package/src/daemon/config-watcher.ts +4 -3
  444. package/src/daemon/connection-policy.ts +1 -26
  445. package/src/daemon/conversation-agent-loop-handlers.ts +74 -7
  446. package/src/daemon/conversation-agent-loop.ts +309 -64
  447. package/src/daemon/conversation-history.ts +8 -8
  448. package/src/daemon/conversation-launch.ts +20 -135
  449. package/src/daemon/conversation-lifecycle.ts +8 -1
  450. package/src/daemon/conversation-messaging.ts +1 -0
  451. package/src/daemon/conversation-process.ts +97 -172
  452. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  453. package/src/daemon/conversation-slash.ts +47 -5
  454. package/src/daemon/conversation-store.ts +7 -31
  455. package/src/daemon/conversation-surfaces.ts +144 -29
  456. package/src/daemon/conversation-tool-setup.ts +18 -87
  457. package/src/daemon/conversation-usage.ts +36 -0
  458. package/src/daemon/conversation.ts +134 -231
  459. package/src/daemon/daemon-control.ts +3 -71
  460. package/src/daemon/daemon-skill-host.ts +8 -11
  461. package/src/daemon/dictation-profile-store.ts +2 -26
  462. package/src/daemon/doordash-steps.ts +1 -1
  463. package/src/daemon/first-greeting.ts +44 -156
  464. package/src/daemon/handlers/config-channels.ts +12 -12
  465. package/src/daemon/handlers/config-ingress.ts +4 -165
  466. package/src/daemon/handlers/config-model.ts +1 -1
  467. package/src/daemon/handlers/config-voice.ts +0 -42
  468. package/src/daemon/handlers/conversations.ts +11 -190
  469. package/src/daemon/handlers/recording.ts +26 -158
  470. package/src/daemon/handlers/shared.ts +27 -72
  471. package/src/daemon/handlers/skills.ts +42 -93
  472. package/src/daemon/host-app-control-proxy.ts +293 -0
  473. package/src/daemon/host-bash-proxy.ts +124 -92
  474. package/src/daemon/host-browser-proxy.ts +111 -88
  475. package/src/daemon/host-cu-proxy.ts +100 -104
  476. package/src/daemon/host-file-proxy.ts +136 -91
  477. package/src/daemon/host-proxy-base.ts +294 -0
  478. package/src/daemon/host-proxy-preactivation.ts +82 -0
  479. package/src/daemon/host-transfer-proxy.ts +303 -147
  480. package/src/daemon/lifecycle.ts +164 -132
  481. package/src/daemon/message-protocol.ts +3 -8
  482. package/src/daemon/message-types/contacts.ts +23 -1
  483. package/src/daemon/message-types/conversations.ts +18 -8
  484. package/src/daemon/message-types/host-app-control.ts +150 -0
  485. package/src/daemon/message-types/host-bash.ts +5 -0
  486. package/src/daemon/message-types/host-cu.ts +3 -0
  487. package/src/daemon/message-types/host-file.ts +5 -0
  488. package/src/daemon/message-types/host-transfer.ts +4 -0
  489. package/src/daemon/message-types/messages.ts +10 -9
  490. package/src/daemon/message-types/schedules.ts +8 -3
  491. package/src/daemon/message-types/skills.ts +2 -2
  492. package/src/daemon/message-types/workspace.ts +1 -1
  493. package/src/daemon/process-message.ts +119 -239
  494. package/src/daemon/server.ts +13 -462
  495. package/src/daemon/shutdown-handlers.ts +2 -5
  496. package/src/daemon/tool-setup-types.ts +51 -0
  497. package/src/daemon/tool-side-effects.ts +126 -108
  498. package/src/daemon/trust-context.ts +13 -0
  499. package/src/daemon/wake-target-adapter.ts +4 -9
  500. package/src/events/domain-events.ts +0 -8
  501. package/src/events/tool-audit-listener.ts +5 -2
  502. package/src/events/tool-domain-event-publisher.ts +0 -10
  503. package/src/events/tool-metrics-listener.ts +0 -17
  504. package/src/events/tool-trace-listener.ts +0 -14
  505. package/src/filing/filing-service.ts +13 -1
  506. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +21 -9
  507. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +216 -0
  508. package/src/heartbeat/heartbeat-run-store.ts +236 -0
  509. package/src/heartbeat/heartbeat-service.ts +303 -54
  510. package/src/home/__tests__/feed-writer.test.ts +0 -4
  511. package/src/home/__tests__/post-connect-feed.test.ts +99 -0
  512. package/src/home/__tests__/relationship-state-writer.test.ts +41 -9
  513. package/src/home/__tests__/suggested-prompts.test.ts +89 -0
  514. package/src/home/feed-writer.ts +1 -2
  515. package/src/home/post-connect-feed.ts +68 -0
  516. package/src/home/relationship-state-writer.ts +33 -95
  517. package/src/home/suggested-prompts.ts +46 -10
  518. package/src/inbound/public-ingress-urls.ts +32 -34
  519. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  520. package/src/ipc/__tests__/route-error-envelope.test.ts +80 -0
  521. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  522. package/src/ipc/assistant-server.ts +17 -11
  523. package/src/ipc/cli-client.ts +32 -1
  524. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  525. package/src/ipc/routes/route-adapter.ts +1 -1
  526. package/src/ipc/routes/trust-rules.test.ts +0 -95
  527. package/src/ipc/skill-ipc-types.ts +41 -0
  528. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  529. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  530. package/src/ipc/skill-routes/events.ts +12 -23
  531. package/src/ipc/skill-routes/identity.ts +4 -17
  532. package/src/ipc/skill-routes/index.ts +1 -1
  533. package/src/ipc/skill-server.ts +6 -39
  534. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  535. package/src/live-voice/live-voice-metrics.ts +10 -10
  536. package/src/live-voice/protocol.ts +4 -13
  537. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +304 -0
  538. package/src/mcp/manager.ts +0 -5
  539. package/src/mcp/mcp-auth-orchestrator.ts +213 -0
  540. package/src/mcp/mcp-auth-state.ts +133 -0
  541. package/src/mcp/mcp-oauth-provider.ts +19 -0
  542. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  543. package/src/memory/__tests__/jobs-store-job-classes.test.ts +24 -0
  544. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  545. package/src/memory/__tests__/qdrant-client-sentinel.test.ts +49 -0
  546. package/src/memory/__tests__/sparse-tokenize.test.ts +66 -0
  547. package/src/memory/anisotropy.test.ts +247 -0
  548. package/src/memory/anisotropy.ts +443 -0
  549. package/src/memory/app-git-service.ts +0 -32
  550. package/src/memory/app-store.ts +154 -0
  551. package/src/memory/attachments-store.ts +6 -0
  552. package/src/memory/auto-analysis-constants.ts +17 -0
  553. package/src/memory/auto-analysis-guard.ts +5 -15
  554. package/src/memory/canonical-guardian-store.ts +7 -7
  555. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +122 -0
  556. package/src/memory/context-search/agent-protocol.ts +6 -6
  557. package/src/memory/context-search/agent-runner.ts +32 -7
  558. package/src/memory/context-search/sources/memory-v2.ts +590 -0
  559. package/src/memory/context-search/sources/memory.ts +5 -0
  560. package/src/memory/context-search/sources/pkb.ts +10 -1
  561. package/src/memory/context-search/sources/workspace.ts +3 -2
  562. package/src/memory/conversation-crud.ts +30 -5
  563. package/src/memory/conversation-disk-view.ts +1 -5
  564. package/src/memory/conversation-key-store.ts +2 -15
  565. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  566. package/src/memory/db-connection.ts +62 -0
  567. package/src/memory/db-init.ts +18 -0
  568. package/src/memory/embedding-backend.ts +12 -42
  569. package/src/memory/embedding-gemini.ts +0 -2
  570. package/src/memory/embedding-local.ts +6 -6
  571. package/src/memory/embedding-ollama.ts +6 -6
  572. package/src/memory/embedding-openai.ts +6 -6
  573. package/src/memory/embedding-types.ts +21 -0
  574. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +49 -8
  575. package/src/memory/graph/conversation-graph-memory.ts +35 -36
  576. package/src/memory/graph/graph-search.ts +8 -0
  577. package/src/memory/graph/injection.test.ts +2 -2
  578. package/src/memory/graph/injection.ts +1 -1
  579. package/src/memory/graph/retriever.ts +28 -0
  580. package/src/memory/graph/tools.ts +1 -1
  581. package/src/memory/guardian-action-store.ts +0 -83
  582. package/src/memory/guardian-approvals.ts +0 -48
  583. package/src/memory/indexer.ts +1 -15
  584. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  585. package/src/memory/job-utils.ts +0 -6
  586. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +8 -2
  587. package/src/memory/jobs/embed-concept-page.ts +28 -2
  588. package/src/memory/jobs/embed-pkb-file.test.ts +2 -2
  589. package/src/memory/jobs-store.ts +66 -23
  590. package/src/memory/jobs-worker.ts +114 -79
  591. package/src/memory/llm-request-log-store.ts +0 -41
  592. package/src/memory/llm-usage-store.ts +129 -43
  593. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  594. package/src/memory/migrations/233-document-conversations.ts +54 -0
  595. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  596. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  597. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  598. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  599. package/src/memory/migrations/237-heartbeat-runs.ts +45 -0
  600. package/src/memory/migrations/238-schedule-retry-policy.ts +20 -0
  601. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  602. package/src/memory/migrations/index.ts +19 -0
  603. package/src/memory/migrations/registry.ts +32 -0
  604. package/src/memory/pkb/pkb-search.ts +7 -0
  605. package/src/memory/qdrant-client.ts +50 -20
  606. package/src/memory/raw-query.ts +2 -68
  607. package/src/memory/schema/conversations.ts +7 -0
  608. package/src/memory/schema/infrastructure.ts +40 -0
  609. package/src/memory/search/semantic.ts +12 -16
  610. package/src/memory/sparse-tokenize.ts +49 -0
  611. package/src/memory/tool-usage-store.ts +2 -0
  612. package/src/memory/usage-buckets.ts +40 -1
  613. package/src/memory/usage-grouped-buckets.ts +127 -0
  614. package/src/memory/v2/__tests__/activation.test.ts +361 -180
  615. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  616. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  617. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  618. package/src/memory/v2/__tests__/injection.test.ts +424 -33
  619. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  620. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  621. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  622. package/src/memory/v2/__tests__/sim.test.ts +166 -6
  623. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  624. package/src/memory/v2/__tests__/sparse-bm25.test.ts +292 -0
  625. package/src/memory/v2/__tests__/static-context.test.ts +152 -0
  626. package/src/memory/v2/activation.ts +215 -163
  627. package/src/memory/v2/backfill-jobs.ts +15 -100
  628. package/src/memory/v2/consolidation-job.ts +17 -17
  629. package/src/memory/v2/constants.ts +7 -0
  630. package/src/memory/v2/edge-index.ts +191 -0
  631. package/src/memory/v2/injection.ts +241 -84
  632. package/src/memory/v2/migration.ts +57 -64
  633. package/src/memory/v2/now-text.ts +2 -3
  634. package/src/memory/v2/page-store.ts +168 -31
  635. package/src/memory/v2/prompts/consolidation.ts +385 -88
  636. package/src/memory/v2/prompts/sweep.ts +3 -3
  637. package/src/memory/v2/qdrant.ts +99 -1
  638. package/src/memory/v2/sim.ts +126 -16
  639. package/src/memory/v2/skill-qdrant.ts +12 -3
  640. package/src/memory/v2/skill-store.ts +71 -8
  641. package/src/memory/v2/sparse-bm25.ts +245 -0
  642. package/src/memory/v2/static-context.ts +63 -0
  643. package/src/memory/v2/types.ts +10 -20
  644. package/src/memory/validation.ts +0 -11
  645. package/src/messaging/draft-store.ts +0 -6
  646. package/src/messaging/provider-types.ts +8 -0
  647. package/src/messaging/provider.ts +7 -0
  648. package/src/messaging/providers/gmail/client.ts +1 -121
  649. package/src/messaging/providers/gmail/types.ts +0 -49
  650. package/src/messaging/providers/outlook/client.ts +0 -73
  651. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  652. package/src/messaging/providers/slack/adapter.ts +123 -52
  653. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  654. package/src/messaging/providers/slack/backfill.ts +89 -11
  655. package/src/messaging/providers/slack/client.ts +10 -124
  656. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  657. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  658. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  659. package/src/messaging/providers/slack/types.ts +1 -32
  660. package/src/notifications/README.md +10 -10
  661. package/src/notifications/broadcaster.ts +1 -1
  662. package/src/notifications/guardian-question-mode.ts +5 -5
  663. package/src/oauth/connect-orchestrator.ts +4 -0
  664. package/src/oauth/connection-resolver.test.ts +8 -0
  665. package/src/oauth/connection-resolver.ts +8 -16
  666. package/src/oauth/credential-token-resolver.ts +95 -0
  667. package/src/oauth/manual-token-connection.ts +26 -34
  668. package/src/oauth/oauth-store.ts +6 -4
  669. package/src/outbound-proxy/certs.ts +0 -7
  670. package/src/outbound-proxy/index.ts +1 -59
  671. package/src/outbound-proxy/logging.ts +1 -1
  672. package/src/outbound-proxy/policy.ts +6 -5
  673. package/src/outbound-proxy/router.ts +2 -1
  674. package/src/permissions/approval-policy.test.ts +6 -275
  675. package/src/permissions/approval-policy.ts +0 -51
  676. package/src/permissions/approval-provenance.test.ts +184 -0
  677. package/src/permissions/approval-provenance.ts +70 -0
  678. package/src/permissions/checker.test.ts +0 -1
  679. package/src/permissions/checker.ts +7 -18
  680. package/src/permissions/gateway-threshold-reader.ts +6 -1
  681. package/src/permissions/prompter.ts +43 -3
  682. package/src/permissions/secret-prompter.ts +25 -48
  683. package/src/permissions/types.ts +33 -0
  684. package/src/permissions/workspace-policy.ts +0 -5
  685. package/src/platform/sync-identity.ts +0 -8
  686. package/src/plugins/defaults/injectors.ts +69 -2
  687. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  688. package/src/plugins/types.ts +8 -0
  689. package/src/prompts/bootstrap-cleanup.ts +27 -0
  690. package/src/prompts/system-prompt.ts +37 -88
  691. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  692. package/src/prompts/templates/SOUL.md +13 -1
  693. package/src/prompts/update-bulletin-job.ts +2 -0
  694. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  695. package/src/providers/anthropic/client.ts +72 -33
  696. package/src/providers/call-site-routing.ts +42 -3
  697. package/src/providers/gemini/client.ts +18 -2
  698. package/src/providers/managed-proxy/context.ts +0 -5
  699. package/src/providers/model-catalog.ts +105 -19
  700. package/src/providers/openai/chat-completions-provider.ts +6 -0
  701. package/src/providers/openai/responses-provider.ts +7 -1
  702. package/src/providers/provider-send-message.ts +45 -2
  703. package/src/providers/ratelimit.ts +7 -2
  704. package/src/providers/registry.ts +14 -9
  705. package/src/providers/retry.ts +96 -8
  706. package/src/providers/speech-to-text/provider-catalog.ts +7 -8
  707. package/src/providers/types.ts +13 -0
  708. package/src/providers/usage-tracking.ts +96 -0
  709. package/src/runtime/AGENTS.md +10 -6
  710. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  711. package/src/runtime/agent-wake.ts +39 -2
  712. package/src/runtime/assistant-event-hub.ts +570 -52
  713. package/src/runtime/assistant-event.ts +2 -6
  714. package/src/runtime/auth/__tests__/middleware.test.ts +11 -56
  715. package/src/runtime/auth/context.ts +0 -9
  716. package/src/runtime/auth/middleware.ts +1 -97
  717. package/src/runtime/auth/route-policy.ts +30 -9
  718. package/src/runtime/auth/token-service.ts +0 -11
  719. package/src/runtime/btw-sidechain.ts +2 -3
  720. package/src/runtime/channel-approvals.ts +6 -2
  721. package/src/runtime/channel-invite-transport.ts +2 -48
  722. package/src/runtime/channel-invite-transports/email.ts +1 -1
  723. package/src/runtime/channel-invite-transports/slack.ts +1 -1
  724. package/src/runtime/channel-invite-transports/telegram.ts +1 -1
  725. package/src/runtime/channel-invite-transports/voice.ts +1 -1
  726. package/src/runtime/channel-invite-transports/whatsapp.ts +1 -1
  727. package/src/runtime/channel-invite-types.ts +54 -0
  728. package/src/runtime/channel-readiness-service.ts +32 -13
  729. package/src/runtime/channel-verification-service.ts +3 -5
  730. package/src/runtime/http-errors.ts +0 -34
  731. package/src/runtime/http-router.ts +6 -3
  732. package/src/runtime/http-server.ts +16 -402
  733. package/src/runtime/http-types.ts +5 -5
  734. package/src/runtime/interactive-ui.ts +0 -1
  735. package/src/runtime/middleware/auth.ts +0 -20
  736. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  737. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  738. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  739. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  740. package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +413 -0
  741. package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +260 -0
  742. package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +189 -0
  743. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  744. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  745. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +296 -80
  746. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  747. package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +451 -0
  748. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
  749. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +515 -0
  750. package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +437 -0
  751. package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +319 -0
  752. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  753. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +421 -0
  754. package/src/runtime/migrations/migration-transport.ts +49 -16
  755. package/src/runtime/migrations/migration-wizard.ts +2 -2
  756. package/src/runtime/migrations/origin-mode.ts +40 -0
  757. package/src/runtime/migrations/vbundle-builder.ts +457 -136
  758. package/src/runtime/migrations/vbundle-import-analyzer.ts +13 -11
  759. package/src/runtime/migrations/vbundle-import-policy.ts +172 -0
  760. package/src/runtime/migrations/vbundle-importer.ts +251 -74
  761. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  762. package/src/runtime/migrations/vbundle-streaming-importer.ts +329 -38
  763. package/src/runtime/migrations/vbundle-streaming-validator.ts +203 -28
  764. package/src/runtime/migrations/vbundle-tar-stream.ts +15 -6
  765. package/src/runtime/migrations/vbundle-validator.ts +328 -41
  766. package/src/runtime/pending-interactions.ts +48 -13
  767. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  768. package/src/runtime/routes/__tests__/backup-routes.test.ts +49 -168
  769. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +333 -0
  770. package/src/runtime/routes/__tests__/gateway-log-routes.test.ts +242 -0
  771. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +112 -0
  772. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  773. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  774. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  775. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  776. package/src/runtime/routes/acp-routes.test.ts +0 -3
  777. package/src/runtime/routes/acp-routes.ts +3 -7
  778. package/src/runtime/routes/app-management-routes.ts +18 -9
  779. package/src/runtime/routes/approval-interception-types.ts +13 -0
  780. package/src/runtime/routes/approval-routes.ts +55 -14
  781. package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +1 -1
  782. package/src/runtime/routes/avatar-routes.ts +3 -5
  783. package/src/runtime/routes/backup-routes.ts +15 -38
  784. package/src/runtime/routes/browser-routes.ts +1 -15
  785. package/src/runtime/routes/btw-routes.ts +14 -37
  786. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  787. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  788. package/src/runtime/routes/channel-route-shared.ts +2 -28
  789. package/src/runtime/routes/client-routes.ts +46 -12
  790. package/src/runtime/routes/consolidation-routes.ts +115 -0
  791. package/src/runtime/routes/contact-prompt-routes.ts +183 -0
  792. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  793. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  794. package/src/runtime/routes/conversation-query-routes.ts +156 -9
  795. package/src/runtime/routes/conversation-routes.ts +72 -539
  796. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  797. package/src/runtime/routes/document-pdf-renderer.ts +165 -0
  798. package/src/runtime/routes/documents-routes.ts +83 -18
  799. package/src/runtime/routes/errors.ts +19 -4
  800. package/src/runtime/routes/events-routes.ts +68 -94
  801. package/src/runtime/routes/filing-routes.ts +18 -1
  802. package/src/runtime/routes/gateway-log-routes.ts +79 -0
  803. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  804. package/src/runtime/routes/guardian-approval-interception.ts +2 -8
  805. package/src/runtime/routes/heartbeat-routes.ts +103 -38
  806. package/src/runtime/routes/host-app-control-routes.ts +134 -0
  807. package/src/runtime/routes/host-bash-routes.ts +37 -6
  808. package/src/runtime/routes/host-browser-routes.ts +96 -25
  809. package/src/runtime/routes/host-cu-routes.ts +48 -13
  810. package/src/runtime/routes/host-file-routes.ts +35 -11
  811. package/src/runtime/routes/host-transfer-routes.ts +73 -37
  812. package/src/runtime/routes/http-adapter.ts +1 -0
  813. package/src/runtime/routes/identity-intro-cache.ts +30 -0
  814. package/src/runtime/routes/identity-routes.ts +93 -49
  815. package/src/runtime/routes/inbound-message-handler.ts +581 -146
  816. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -95
  817. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  818. package/src/runtime/routes/inbound-stages/edit-intercept.ts +0 -8
  819. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +0 -20
  820. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +5 -13
  821. package/src/runtime/routes/index.ts +12 -0
  822. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  823. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  824. package/src/runtime/routes/mcp-auth-routes.ts +132 -0
  825. package/src/runtime/routes/memory-item-routes.ts +10 -12
  826. package/src/runtime/routes/memory-v2-routes.ts +451 -16
  827. package/src/runtime/routes/migration-routes.ts +284 -31
  828. package/src/runtime/routes/playground/guard.ts +1 -1
  829. package/src/runtime/routes/playground/index.ts +0 -2
  830. package/src/runtime/routes/recording-routes.ts +4 -24
  831. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  832. package/src/runtime/routes/schedule-routes.ts +10 -6
  833. package/src/runtime/routes/secret-routes.ts +87 -18
  834. package/src/runtime/routes/settings-routes.ts +29 -28
  835. package/src/runtime/routes/skills-routes.ts +12 -31
  836. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  837. package/src/runtime/routes/task-routes.ts +6 -6
  838. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  839. package/src/runtime/routes/types.ts +4 -4
  840. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  841. package/src/runtime/routes/usage-routes.ts +87 -10
  842. package/src/runtime/routes/user-routes.ts +17 -31
  843. package/src/runtime/routes/work-items-routes.ts +1 -4
  844. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  845. package/src/runtime/services/analyze-conversation.ts +7 -17
  846. package/src/runtime/services/conversation-serializer.ts +2 -4
  847. package/src/runtime/verification-outbound-actions.ts +1 -1
  848. package/src/runtime/verification-rate-limiter.ts +1 -1
  849. package/src/runtime/verification-templates.ts +4 -7
  850. package/src/schedule/integration-status.ts +66 -2
  851. package/src/schedule/recurrence-engine.ts +4 -1
  852. package/src/schedule/retry-backoff.ts +18 -0
  853. package/src/schedule/retry-policy.ts +82 -0
  854. package/src/schedule/schedule-recovery.ts +64 -0
  855. package/src/schedule/schedule-store.ts +106 -18
  856. package/src/schedule/scheduler-types.ts +25 -0
  857. package/src/schedule/scheduler.ts +63 -38
  858. package/src/security/oauth-callback-registry.ts +8 -0
  859. package/src/security/secret-scanner.ts +14 -547
  860. package/src/security/secure-keys.ts +31 -11
  861. package/src/security/token-manager.ts +7 -3
  862. package/src/sequence/analytics.ts +5 -5
  863. package/src/sequence/engine.ts +1 -1
  864. package/src/signals/cancel.ts +16 -25
  865. package/src/signals/conversation-undo.ts +2 -27
  866. package/src/signals/emit-event.ts +1 -2
  867. package/src/signals/user-message.ts +108 -22
  868. package/src/skills/catalog-files.ts +2 -8
  869. package/src/skills/catalog-install.ts +1 -0
  870. package/src/skills/clawhub.ts +2 -2
  871. package/src/skills/include-graph.ts +5 -5
  872. package/src/skills/inline-command-runner.ts +1 -7
  873. package/src/skills/remote-skill-policy.ts +5 -5
  874. package/src/skills/skill-file-provider.ts +1 -1
  875. package/src/skills/skill-file-types.ts +13 -0
  876. package/src/skills/skillssh-audit-types.ts +28 -0
  877. package/src/skills/skillssh-registry.ts +8 -21
  878. package/src/subagent/manager.ts +67 -84
  879. package/src/tasks/task-store.ts +1 -28
  880. package/src/telemetry/types.ts +8 -0
  881. package/src/telemetry/usage-telemetry-reporter.test.ts +59 -15
  882. package/src/telemetry/usage-telemetry-reporter.ts +4 -5
  883. package/src/tools/acp/spawn.test.ts +1 -2
  884. package/src/tools/acp/steer.test.ts +1 -2
  885. package/src/tools/app-control/skill-proxy-bridge.ts +28 -0
  886. package/src/tools/apps/executors.ts +56 -69
  887. package/src/tools/browser/__tests__/browser-status.test.ts +55 -135
  888. package/src/tools/browser/browser-execution.ts +31 -147
  889. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +145 -70
  890. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +12 -6
  891. package/src/tools/browser/cdp-client/factory.ts +62 -91
  892. package/src/tools/browser/cdp-client/index.ts +1 -27
  893. package/src/tools/computer-use/definitions.ts +42 -20
  894. package/src/tools/executor.ts +46 -31
  895. package/src/tools/host-filesystem/edit.ts +29 -2
  896. package/src/tools/host-filesystem/read.ts +29 -2
  897. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  898. package/src/tools/host-filesystem/transfer.ts +35 -4
  899. package/src/tools/host-filesystem/write.ts +29 -2
  900. package/src/tools/host-terminal/host-shell.ts +62 -3
  901. package/src/tools/network/script-proxy/index.ts +1 -10
  902. package/src/tools/permission-checker.ts +66 -1
  903. package/src/tools/schedule/create.ts +6 -0
  904. package/src/tools/schedule/list.ts +2 -0
  905. package/src/tools/schedule/update.ts +10 -0
  906. package/src/tools/shared/filesystem/file-ops-service.ts +2 -0
  907. package/src/tools/shared/filesystem/path-policy.ts +25 -1
  908. package/src/tools/skills/load.ts +0 -32
  909. package/src/tools/skills/sandbox-runner.ts +1 -6
  910. package/src/tools/skills/skill-tool-factory.ts +32 -0
  911. package/src/tools/terminal/safe-env.ts +1 -0
  912. package/src/tools/terminal/shell.ts +2 -78
  913. package/src/tools/tool-approval-handler.ts +1 -5
  914. package/src/tools/types.ts +16 -39
  915. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  916. package/src/tts/provider-catalog.ts +1 -1
  917. package/src/usage/actors.ts +2 -1
  918. package/src/usage/attribution.ts +185 -0
  919. package/src/usage/pricing.ts +166 -0
  920. package/src/usage/types.ts +14 -0
  921. package/src/util/json.ts +13 -0
  922. package/src/util/logger.ts +3 -3
  923. package/src/util/pricing.ts +50 -3
  924. package/src/work-items/work-item-runner.ts +15 -42
  925. package/src/workspace/hatched-date.ts +86 -0
  926. package/src/workspace/migrations/003-seed-device-id.ts +1 -1
  927. package/src/workspace/migrations/006-services-config.ts +8 -5
  928. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +3 -9
  929. package/src/workspace/migrations/021-move-signals-to-workspace.ts +4 -10
  930. package/src/workspace/migrations/022-move-hooks-to-workspace.ts +4 -10
  931. package/src/workspace/migrations/023-move-config-files-to-workspace.ts +4 -11
  932. package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +3 -10
  933. package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +3 -2
  934. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +6 -4
  935. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  936. package/src/workspace/migrations/059-move-pid-to-workspace.ts +3 -8
  937. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  938. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +54 -0
  939. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  940. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  941. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  942. package/src/workspace/migrations/AGENTS.md +1 -1
  943. package/src/workspace/migrations/migrate-to-workspace-volume.ts +4 -10
  944. package/src/workspace/migrations/registry.ts +8 -0
  945. package/src/workspace/migrations/utils.ts +21 -0
  946. package/src/workspace/provider-commit-message-generator.ts +3 -3
  947. package/src/__tests__/host-browser-e2e-cloud.test.ts +0 -904
  948. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +0 -296
  949. package/src/__tests__/host-browser-ws-events-e2e.test.ts +0 -431
  950. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  951. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  952. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  953. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  954. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  955. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  956. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  957. package/src/__tests__/twilio-rest.test.ts +0 -34
  958. package/src/backup/__tests__/backup-key.test.ts +0 -152
  959. package/src/backup/__tests__/backup-worker.test.ts +0 -754
  960. package/src/backup/__tests__/offsite-writer.test.ts +0 -641
  961. package/src/backup/__tests__/stream-crypt.test.ts +0 -228
  962. package/src/backup/backup-key.ts +0 -137
  963. package/src/backup/backup-worker.ts +0 -438
  964. package/src/backup/offsite-writer.ts +0 -222
  965. package/src/backup/stream-crypt.ts +0 -263
  966. package/src/context/__tests__/microcompact.test.ts +0 -805
  967. package/src/context/microcompact.ts +0 -443
  968. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  969. package/src/daemon/message-types/pairing.ts +0 -58
  970. package/src/events/tool-notification-listener.ts +0 -17
  971. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  972. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  973. package/src/memory/v2/edges.ts +0 -217
  974. package/src/outbound-proxy/config.ts +0 -94
  975. package/src/outbound-proxy/health.ts +0 -62
  976. package/src/outbound-proxy/types.ts +0 -150
  977. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  978. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  979. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  980. package/src/runtime/capability-tokens.ts +0 -190
  981. package/src/runtime/chrome-extension-registry.ts +0 -368
  982. package/src/runtime/client-registry.ts +0 -254
  983. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  984. package/src/signals/mcp-reload.ts +0 -18
  985. package/src/tools/secret-detection-handler.ts +0 -269
  986. package/src/tools/terminal/backends/native.ts +0 -327
  987. package/src/tools/terminal/backends/types.ts +0 -37
  988. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  989. package/src/tools/terminal/sandbox.ts +0 -40
@@ -113,6 +113,30 @@ mock.module("../../../../util/logger.js", () => ({
113
113
  }),
114
114
  }));
115
115
 
116
+ /** Mutable singleton proxy. Tests set this to control extension availability. */
117
+ let mockSingletonProxy: HostBrowserProxy | null = null;
118
+
119
+ /** Default proxy that reports unavailable — used when no test override is set. */
120
+ const unavailableFallback: HostBrowserProxy = {
121
+ isAvailable: () => false,
122
+ hasExtensionClient: () => false,
123
+ request: () => Promise.reject(new Error("no extension")),
124
+ resolve: () => {},
125
+ hasPendingRequest: () => false,
126
+ dispose: () => {},
127
+ } as unknown as HostBrowserProxy;
128
+
129
+ mock.module("../../../../daemon/host-browser-proxy.js", () => ({
130
+ HostBrowserProxy: {
131
+ get instance() {
132
+ return mockSingletonProxy ?? unavailableFallback;
133
+ },
134
+ reset() {
135
+ mockSingletonProxy = null;
136
+ },
137
+ },
138
+ }));
139
+
116
140
  // Import under test AFTER mock.module calls so that the factory's
117
141
  // top-level imports resolve to our fakes.
118
142
  const {
@@ -127,9 +151,9 @@ const {
127
151
  } = await import("../factory.js");
128
152
 
129
153
  /**
130
- * Minimal ToolContext suitable for factory tests. Only the fields the
131
- * factory reads (`conversationId` and `hostBrowserProxy`) need to be
132
- * populated; other required fields are cast away.
154
+ * Minimal ToolContext suitable for factory tests. Only `conversationId`
155
+ * needs to be populated; other required fields are cast away.
156
+ * Extension availability is controlled via `mockSingletonProxy`.
133
157
  */
134
158
  function makeContext(
135
159
  overrides: Partial<ToolContext> & { conversationId: string },
@@ -138,23 +162,38 @@ function makeContext(
138
162
  }
139
163
 
140
164
  /**
141
- * Create a fake HostBrowserProxy that reports as available.
165
+ * Create a fake HostBrowserProxy with a Chrome Extension client connected.
166
+ * Both isAvailable() and hasExtensionClient() return true.
142
167
  */
143
168
  function makeAvailableProxy(): HostBrowserProxy {
144
169
  return {
145
170
  request: mock(async () => ({})),
146
171
  isAvailable: () => true,
172
+ hasExtensionClient: () => true,
173
+ } as unknown as HostBrowserProxy;
174
+ }
175
+
176
+ /**
177
+ * Create a fake HostBrowserProxy where only the macOS SSE bridge is connected
178
+ * (no Chrome Extension). isAvailable() is true but hasExtensionClient() is false.
179
+ */
180
+ function makeMacosBridgeOnlyProxy(): HostBrowserProxy {
181
+ return {
182
+ request: mock(async () => ({})),
183
+ isAvailable: () => true,
184
+ hasExtensionClient: () => false,
147
185
  } as unknown as HostBrowserProxy;
148
186
  }
149
187
 
150
188
  /**
151
189
  * Create a fake HostBrowserProxy that reports as unavailable
152
- * (proxy exists but client is disconnected).
190
+ * (proxy exists but no client of any kind is connected).
153
191
  */
154
192
  function makeUnavailableProxy(): HostBrowserProxy {
155
193
  return {
156
194
  request: mock(async () => ({})),
157
195
  isAvailable: () => false,
196
+ hasExtensionClient: () => false,
158
197
  } as unknown as HostBrowserProxy;
159
198
  }
160
199
 
@@ -171,15 +210,16 @@ describe("getCdpClient", () => {
171
210
  _resetDesktopAutoCooldown();
172
211
  logWarnCalls.length = 0;
173
212
  logDebugCalls.length = 0;
213
+ mockSingletonProxy = null;
174
214
  });
175
215
 
176
216
  // ── Candidate selection (kind reported before first send) ────────────
177
217
 
178
218
  test("routes to ExtensionCdpClient when hostBrowserProxy is set and available", async () => {
179
219
  const fakeProxy = makeAvailableProxy();
220
+ mockSingletonProxy = fakeProxy;
180
221
  const ctx = makeContext({
181
222
  conversationId: "test-convo",
182
- hostBrowserProxy: fakeProxy,
183
223
  });
184
224
 
185
225
  const client = getCdpClient(ctx);
@@ -205,9 +245,9 @@ describe("getCdpClient", () => {
205
245
 
206
246
  test("skips extension when hostBrowserProxy is present but unavailable", async () => {
207
247
  const fakeProxy = makeUnavailableProxy();
248
+ mockSingletonProxy = fakeProxy;
208
249
  const ctx = makeContext({
209
250
  conversationId: "disconnected-proxy",
210
- hostBrowserProxy: fakeProxy,
211
251
  });
212
252
 
213
253
  const client = getCdpClient(ctx);
@@ -227,9 +267,9 @@ describe("getCdpClient", () => {
227
267
  test("skips extension but uses cdp-inspect when proxy unavailable and cdp-inspect enabled", async () => {
228
268
  cdpInspectEnabled = true;
229
269
  const fakeProxy = makeUnavailableProxy();
270
+ mockSingletonProxy = fakeProxy;
230
271
  const ctx = makeContext({
231
272
  conversationId: "disconnected-inspect",
232
- hostBrowserProxy: fakeProxy,
233
273
  });
234
274
 
235
275
  const client = getCdpClient(ctx);
@@ -247,9 +287,9 @@ describe("getCdpClient", () => {
247
287
  test("extension wins even when cdpInspect is enabled", async () => {
248
288
  cdpInspectEnabled = true;
249
289
  const fakeProxy = makeAvailableProxy();
290
+ mockSingletonProxy = fakeProxy;
250
291
  const ctx = makeContext({
251
292
  conversationId: "ext-wins",
252
- hostBrowserProxy: fakeProxy,
253
293
  });
254
294
 
255
295
  const client = getCdpClient(ctx);
@@ -268,7 +308,6 @@ describe("getCdpClient", () => {
268
308
  cdpInspectEnabled = true;
269
309
  const ctx = makeContext({
270
310
  conversationId: "inspect-convo",
271
- hostBrowserProxy: undefined,
272
311
  });
273
312
 
274
313
  const client = getCdpClient(ctx);
@@ -295,7 +334,6 @@ describe("getCdpClient", () => {
295
334
  cdpInspectEnabled = false;
296
335
  const ctx = makeContext({
297
336
  conversationId: "local-convo",
298
- hostBrowserProxy: undefined,
299
337
  });
300
338
 
301
339
  const client = getCdpClient(ctx);
@@ -333,9 +371,9 @@ describe("getCdpClient", () => {
333
371
 
334
372
  test("getCdpClient without options behaves identically to auto mode", async () => {
335
373
  const fakeProxy = makeAvailableProxy();
374
+ mockSingletonProxy = fakeProxy;
336
375
  const ctx = makeContext({
337
376
  conversationId: "no-opts",
338
- hostBrowserProxy: fakeProxy,
339
377
  });
340
378
 
341
379
  const client = getCdpClient(ctx);
@@ -361,9 +399,9 @@ describe("getCdpClient", () => {
361
399
 
362
400
  test("forwards send() through the manager to the extension-backed client", async () => {
363
401
  const fakeProxy = makeAvailableProxy();
402
+ mockSingletonProxy = fakeProxy;
364
403
  const ctx = makeContext({
365
404
  conversationId: "send-ext",
366
- hostBrowserProxy: fakeProxy,
367
405
  });
368
406
 
369
407
  const client = getCdpClient(ctx);
@@ -507,9 +545,9 @@ describe("getCdpClient", () => {
507
545
 
508
546
  test("dispose() on an extension-backed client tears down the extension client", async () => {
509
547
  const fakeProxy = makeAvailableProxy();
548
+ mockSingletonProxy = fakeProxy;
510
549
  const ctx = makeContext({
511
550
  conversationId: "dispose-ext",
512
- hostBrowserProxy: fakeProxy,
513
551
  });
514
552
 
515
553
  const client = getCdpClient(ctx);
@@ -576,9 +614,9 @@ describe("getCdpClient", () => {
576
614
 
577
615
  test("context with transportInterface set routes normally to extension backend", async () => {
578
616
  const fakeProxy = makeAvailableProxy();
617
+ mockSingletonProxy = fakeProxy;
579
618
  const ctx = makeContext({
580
619
  conversationId: "macos-ext",
581
- hostBrowserProxy: fakeProxy,
582
620
  transportInterface: "macos",
583
621
  });
584
622
 
@@ -629,13 +667,14 @@ describe("buildCandidateList", () => {
629
667
  cdpInspectEnabled = false;
630
668
  desktopAutoConfig = { enabled: true, cooldownMs: 30_000 };
631
669
  _resetDesktopAutoCooldown();
670
+ mockSingletonProxy = null;
632
671
  });
633
672
 
634
673
  test("includes extension candidate when proxy is present and available", () => {
635
674
  const fakeProxy = makeAvailableProxy();
675
+ mockSingletonProxy = fakeProxy;
636
676
  const ctx = makeContext({
637
677
  conversationId: "candidates-ext",
638
- hostBrowserProxy: fakeProxy,
639
678
  });
640
679
 
641
680
  const candidates = buildCandidateList(ctx);
@@ -648,9 +687,9 @@ describe("buildCandidateList", () => {
648
687
 
649
688
  test("excludes extension candidate when proxy is present but unavailable", () => {
650
689
  const fakeProxy = makeUnavailableProxy();
690
+ mockSingletonProxy = fakeProxy;
651
691
  const ctx = makeContext({
652
692
  conversationId: "candidates-no-ext",
653
- hostBrowserProxy: fakeProxy,
654
693
  });
655
694
 
656
695
  const candidates = buildCandidateList(ctx);
@@ -659,6 +698,22 @@ describe("buildCandidateList", () => {
659
698
  expect(candidates[0].kind).toBe("local");
660
699
  });
661
700
 
701
+ test("excludes extension candidate when only macOS SSE bridge is connected", () => {
702
+ // isAvailable() = true but hasExtensionClient() = false: only macOS bridge.
703
+ // The macOS bridge routes through localhost:9222 on the host, so it must
704
+ // NOT be included under the "extension" candidate kind.
705
+ const fakeProxy = makeMacosBridgeOnlyProxy();
706
+ mockSingletonProxy = fakeProxy;
707
+ const ctx = makeContext({
708
+ conversationId: "candidates-macos-bridge-only",
709
+ });
710
+
711
+ const candidates = buildCandidateList(ctx);
712
+
713
+ expect(candidates.every((c) => c.kind !== "extension")).toBe(true);
714
+ expect(candidates[candidates.length - 1].kind).toBe("local");
715
+ });
716
+
662
717
  test("includes cdp-inspect candidate when enabled in config", () => {
663
718
  cdpInspectEnabled = true;
664
719
  const ctx = makeContext({ conversationId: "candidates-inspect" });
@@ -672,9 +727,9 @@ describe("buildCandidateList", () => {
672
727
  test("candidate order: extension > cdp-inspect > local when all present", () => {
673
728
  cdpInspectEnabled = true;
674
729
  const fakeProxy = makeAvailableProxy();
730
+ mockSingletonProxy = fakeProxy;
675
731
  const ctx = makeContext({
676
732
  conversationId: "candidates-all",
677
- hostBrowserProxy: fakeProxy,
678
733
  });
679
734
 
680
735
  const candidates = buildCandidateList(ctx);
@@ -710,10 +765,12 @@ describe("buildChainedClient failover", () => {
710
765
  _resetDesktopAutoCooldown();
711
766
  logWarnCalls.length = 0;
712
767
  logDebugCalls.length = 0;
768
+ mockSingletonProxy = null;
713
769
  });
714
770
 
715
771
  test("fails over from extension to local on transport_error", async () => {
716
772
  const fakeProxy = makeAvailableProxy();
773
+ mockSingletonProxy = fakeProxy;
717
774
 
718
775
  // Make extension client fail with transport_error
719
776
  createExtensionCdpClientMock.mockImplementationOnce(
@@ -735,7 +792,6 @@ describe("buildChainedClient failover", () => {
735
792
 
736
793
  const ctx = makeContext({
737
794
  conversationId: "failover-ext-to-local",
738
- hostBrowserProxy: fakeProxy,
739
795
  });
740
796
 
741
797
  const client = getCdpClient(ctx);
@@ -754,6 +810,7 @@ describe("buildChainedClient failover", () => {
754
810
  test("fails over from extension to cdp-inspect to local on transport errors", async () => {
755
811
  cdpInspectEnabled = true;
756
812
  const fakeProxy = makeAvailableProxy();
813
+ mockSingletonProxy = fakeProxy;
757
814
 
758
815
  // Make extension fail with transport_error
759
816
  createExtensionCdpClientMock.mockImplementationOnce(
@@ -785,7 +842,6 @@ describe("buildChainedClient failover", () => {
785
842
 
786
843
  const ctx = makeContext({
787
844
  conversationId: "failover-chain",
788
- hostBrowserProxy: fakeProxy,
789
845
  });
790
846
 
791
847
  const client = getCdpClient(ctx);
@@ -803,6 +859,7 @@ describe("buildChainedClient failover", () => {
803
859
  test("does NOT fail over on cdp_error -- propagates immediately", async () => {
804
860
  cdpInspectEnabled = true;
805
861
  const fakeProxy = makeAvailableProxy();
862
+ mockSingletonProxy = fakeProxy;
806
863
 
807
864
  // Make extension fail with cdp_error (not transport_error)
808
865
  createExtensionCdpClientMock.mockImplementationOnce(
@@ -820,7 +877,6 @@ describe("buildChainedClient failover", () => {
820
877
 
821
878
  const ctx = makeContext({
822
879
  conversationId: "no-failover-cdp-error",
823
- hostBrowserProxy: fakeProxy,
824
880
  });
825
881
 
826
882
  const client = getCdpClient(ctx);
@@ -868,6 +924,7 @@ describe("buildChainedClient failover", () => {
868
924
  test("backend becomes sticky after first successful command", async () => {
869
925
  cdpInspectEnabled = true;
870
926
  const fakeProxy = makeAvailableProxy();
927
+ mockSingletonProxy = fakeProxy;
871
928
 
872
929
  // Make extension fail on first call with transport_error
873
930
  createExtensionCdpClientMock.mockImplementationOnce(
@@ -885,7 +942,6 @@ describe("buildChainedClient failover", () => {
885
942
 
886
943
  const ctx = makeContext({
887
944
  conversationId: "sticky-test",
888
- hostBrowserProxy: fakeProxy,
889
945
  });
890
946
 
891
947
  const client = getCdpClient(ctx);
@@ -946,6 +1002,7 @@ describe("buildChainedClient failover", () => {
946
1002
 
947
1003
  test("kind reflects the active backend after failover", async () => {
948
1004
  const fakeProxy = makeAvailableProxy();
1005
+ mockSingletonProxy = fakeProxy;
949
1006
 
950
1007
  // Make extension fail
951
1008
  createExtensionCdpClientMock.mockImplementationOnce(
@@ -961,7 +1018,6 @@ describe("buildChainedClient failover", () => {
961
1018
 
962
1019
  const ctx = makeContext({
963
1020
  conversationId: "kind-after-failover",
964
- hostBrowserProxy: fakeProxy,
965
1021
  });
966
1022
 
967
1023
  const client = getCdpClient(ctx);
@@ -976,6 +1032,7 @@ describe("buildChainedClient failover", () => {
976
1032
 
977
1033
  test("dispose cleans up failed backends from failover chain", async () => {
978
1034
  const fakeProxy = makeAvailableProxy();
1035
+ mockSingletonProxy = fakeProxy;
979
1036
 
980
1037
  // Make extension fail
981
1038
  createExtensionCdpClientMock.mockImplementationOnce(
@@ -991,7 +1048,6 @@ describe("buildChainedClient failover", () => {
991
1048
 
992
1049
  const ctx = makeContext({
993
1050
  conversationId: "dispose-failover",
994
- hostBrowserProxy: fakeProxy,
995
1051
  });
996
1052
 
997
1053
  const client = getCdpClient(ctx);
@@ -1023,6 +1079,7 @@ describe("desktop-auto cdp-inspect (macOS)", () => {
1023
1079
  _resetDesktopAutoCooldown();
1024
1080
  logWarnCalls.length = 0;
1025
1081
  logDebugCalls.length = 0;
1082
+ mockSingletonProxy = null;
1026
1083
  });
1027
1084
 
1028
1085
  // ── buildCandidateList with desktopAuto ─────────────────────────────
@@ -1043,9 +1100,9 @@ describe("desktop-auto cdp-inspect (macOS)", () => {
1043
1100
 
1044
1101
  test("macOS turn with extension available: extension > cdp-inspect > local", () => {
1045
1102
  const fakeProxy = makeAvailableProxy();
1103
+ mockSingletonProxy = fakeProxy;
1046
1104
  const ctx = makeContext({
1047
1105
  conversationId: "macos-all",
1048
- hostBrowserProxy: fakeProxy,
1049
1106
  transportInterface: "macos",
1050
1107
  });
1051
1108
 
@@ -1060,38 +1117,33 @@ describe("desktop-auto cdp-inspect (macOS)", () => {
1060
1117
 
1061
1118
  test("macOS turn with registry-routed proxy unavailable skips desktop-auto cdp-inspect (extension intent)", () => {
1062
1119
  const fakeProxy = makeUnavailableProxy();
1120
+ mockSingletonProxy = fakeProxy;
1063
1121
  const ctx = makeContext({
1064
1122
  conversationId: "macos-proxy-unavailable-no-inspect",
1065
- hostBrowserProxy: fakeProxy,
1066
1123
  transportInterface: "macos",
1067
- hostBrowserRegistryRouted: true,
1068
1124
  });
1069
1125
 
1070
1126
  const candidates = buildCandidateList(ctx);
1071
1127
 
1072
- // Should only include local -- cdp-inspect is suppressed because extension
1073
- // transport is expected (registry-routed proxy) but temporarily unavailable.
1074
- expect(candidates.length).toBe(1);
1075
- expect(candidates[0].kind).toBe("local");
1128
+ // Extension unavailable => cdp-inspect (desktop-auto) + local
1129
+ expect(candidates.length).toBe(2);
1130
+ expect(candidates[0].kind).toBe("cdp-inspect");
1131
+ expect(candidates[1].kind).toBe("local");
1076
1132
  });
1077
1133
 
1078
- test("macOS turn with SSE-backed proxy unavailable still includes desktop-auto cdp-inspect", () => {
1134
+ test("macOS turn with singleton proxy unavailable still includes desktop-auto cdp-inspect", () => {
1079
1135
  const fakeProxy = makeUnavailableProxy();
1136
+ mockSingletonProxy = fakeProxy;
1080
1137
  const ctx = makeContext({
1081
- conversationId: "macos-sse-proxy-unavailable-inspect-allowed",
1082
- hostBrowserProxy: fakeProxy,
1138
+ conversationId: "macos-proxy-unavailable-inspect-allowed",
1083
1139
  transportInterface: "macos",
1084
- // hostBrowserRegistryRouted is NOT set -- SSE-backed proxy
1085
1140
  });
1086
1141
 
1087
1142
  const candidates = buildCandidateList(ctx);
1088
1143
 
1089
- // SSE-backed proxy that is unavailable (non-interactive turn) should NOT
1090
- // suppress cdp-inspect -- the SSE proxy was never expected to service
1091
- // browser requests, so cdp-inspect remains available as a fallback.
1144
+ // Extension unavailable => cdp-inspect (desktop-auto) + local
1092
1145
  expect(candidates.length).toBe(2);
1093
1146
  expect(candidates[0].kind).toBe("cdp-inspect");
1094
- expect(candidates[0].reason).toContain("desktopAuto");
1095
1147
  expect(candidates[1].kind).toBe("local");
1096
1148
  });
1097
1149
 
@@ -1112,9 +1164,9 @@ describe("desktop-auto cdp-inspect (macOS)", () => {
1112
1164
 
1113
1165
  test("macOS turn with extension available still includes cdp-inspect as fallback", () => {
1114
1166
  const fakeProxy = makeAvailableProxy();
1167
+ mockSingletonProxy = fakeProxy;
1115
1168
  const ctx = makeContext({
1116
1169
  conversationId: "macos-ext-available-inspect-fallback",
1117
- hostBrowserProxy: fakeProxy,
1118
1170
  transportInterface: "macos",
1119
1171
  });
1120
1172
 
@@ -1263,43 +1315,41 @@ describe("desktop-auto cdp-inspect (macOS)", () => {
1263
1315
  expect(candidates[0].kind).toBe("local");
1264
1316
  });
1265
1317
 
1266
- test("macOS turn with registry-routed proxy unavailable routes to local without trying cdp-inspect", async () => {
1318
+ test("macOS turn with registry-routed proxy unavailable still tries cdp-inspect (desktop-auto)", async () => {
1267
1319
  const fakeProxy = makeUnavailableProxy();
1320
+ mockSingletonProxy = fakeProxy;
1268
1321
  const ctx = makeContext({
1269
1322
  conversationId: "macos-proxy-unavail-route",
1270
- hostBrowserProxy: fakeProxy,
1271
1323
  transportInterface: "macos",
1272
- hostBrowserRegistryRouted: true,
1273
1324
  });
1274
1325
 
1275
1326
  const client = getCdpClient(ctx);
1276
1327
 
1277
- // Should go straight to local -- no cdp-inspect candidate inserted
1278
- // because the registry-routed extension was expected but is unavailable.
1279
- expect(client.kind).toBe("local");
1328
+ // Extension unavailable no longer suppresses cdp-inspect desktop-auto
1329
+ // inserts it as a candidate and it succeeds.
1330
+ expect(client.kind).toBe("cdp-inspect");
1280
1331
  const result = await client.send<{ ok: boolean; via: string }>(
1281
1332
  "Page.navigate",
1282
1333
  );
1283
- expect(result).toEqual({ ok: true, via: "local" });
1284
- expect(createCdpInspectClientMock).not.toHaveBeenCalled();
1334
+ expect(result).toEqual({ ok: true, via: "cdp-inspect" });
1335
+ expect(createCdpInspectClientMock).toHaveBeenCalledTimes(1);
1285
1336
  expect(createExtensionCdpClientMock).not.toHaveBeenCalled();
1286
- expect(createLocalCdpClientMock).toHaveBeenCalledTimes(1);
1337
+ expect(createLocalCdpClientMock).not.toHaveBeenCalled();
1287
1338
  client.dispose();
1288
1339
  });
1289
1340
 
1290
- test("macOS turn with SSE-backed proxy unavailable falls through to cdp-inspect", async () => {
1341
+ test("macOS turn with singleton proxy unavailable still tries cdp-inspect (desktop-auto)", async () => {
1291
1342
  const fakeProxy = makeUnavailableProxy();
1343
+ mockSingletonProxy = fakeProxy;
1292
1344
  const ctx = makeContext({
1293
- conversationId: "macos-sse-proxy-unavail-inspect",
1294
- hostBrowserProxy: fakeProxy,
1345
+ conversationId: "macos-proxy-unavail-local",
1295
1346
  transportInterface: "macos",
1296
- // hostBrowserRegistryRouted is NOT set -- SSE-backed proxy
1297
1347
  });
1298
1348
 
1299
1349
  const client = getCdpClient(ctx);
1300
1350
 
1301
- // SSE-backed proxy unavailable (non-interactive turn) should NOT
1302
- // suppress cdp-inspect -- it falls through to desktop-auto cdp-inspect.
1351
+ // Extension unavailable no longer suppresses cdp-inspect desktop-auto
1352
+ // inserts it as a candidate and it succeeds.
1303
1353
  expect(client.kind).toBe("cdp-inspect");
1304
1354
  const result = await client.send<{ ok: boolean; via: string }>(
1305
1355
  "Page.navigate",
@@ -1307,6 +1357,7 @@ describe("desktop-auto cdp-inspect (macOS)", () => {
1307
1357
  expect(result).toEqual({ ok: true, via: "cdp-inspect" });
1308
1358
  expect(createExtensionCdpClientMock).not.toHaveBeenCalled();
1309
1359
  expect(createCdpInspectClientMock).toHaveBeenCalledTimes(1);
1360
+ expect(createLocalCdpClientMock).not.toHaveBeenCalled();
1310
1361
  client.dispose();
1311
1362
  });
1312
1363
 
@@ -1380,15 +1431,16 @@ describe("pinned-mode selection", () => {
1380
1431
  _resetDesktopAutoCooldown();
1381
1432
  logWarnCalls.length = 0;
1382
1433
  logDebugCalls.length = 0;
1434
+ mockSingletonProxy = null;
1383
1435
  });
1384
1436
 
1385
1437
  // ── Pinned extension ────────────────────────────────────────────────
1386
1438
 
1387
1439
  test("pinned extension mode routes to extension when proxy is available", async () => {
1388
1440
  const fakeProxy = makeAvailableProxy();
1441
+ mockSingletonProxy = fakeProxy;
1389
1442
  const ctx = makeContext({
1390
1443
  conversationId: "pinned-ext",
1391
- hostBrowserProxy: fakeProxy,
1392
1444
  });
1393
1445
 
1394
1446
  const client = getCdpClient(ctx, { mode: "extension" });
@@ -1415,7 +1467,7 @@ describe("pinned-mode selection", () => {
1415
1467
  const cdpErr = err as CdpError;
1416
1468
  expect(cdpErr.code).toBe("transport_error");
1417
1469
  expect(cdpErr.message).toContain('Pinned mode "extension" unavailable');
1418
- expect(cdpErr.message).toContain("no host browser proxy provisioned");
1470
+ expect(cdpErr.message).toContain("no Chrome Extension connected");
1419
1471
  expect(cdpErr.attemptDiagnostics).toBeDefined();
1420
1472
  expect(cdpErr.attemptDiagnostics).toHaveLength(1);
1421
1473
  expect(cdpErr.attemptDiagnostics![0].candidateKind).toBe("extension");
@@ -1425,9 +1477,9 @@ describe("pinned-mode selection", () => {
1425
1477
 
1426
1478
  test("pinned extension mode throws when proxy is present but unavailable", () => {
1427
1479
  const fakeProxy = makeUnavailableProxy();
1480
+ mockSingletonProxy = fakeProxy;
1428
1481
  const ctx = makeContext({
1429
1482
  conversationId: "pinned-ext-unavail",
1430
- hostBrowserProxy: fakeProxy,
1431
1483
  });
1432
1484
 
1433
1485
  expect(() => getCdpClient(ctx, { mode: "extension" })).toThrow(CdpError);
@@ -1437,13 +1489,14 @@ describe("pinned-mode selection", () => {
1437
1489
  } catch (err) {
1438
1490
  const cdpErr = err as CdpError;
1439
1491
  expect(cdpErr.code).toBe("transport_error");
1440
- expect(cdpErr.message).toContain("not connected");
1492
+ expect(cdpErr.message).toContain("no Chrome Extension connected");
1441
1493
  expect(cdpErr.attemptDiagnostics![0].stage).toBe("candidate_selection");
1442
1494
  }
1443
1495
  });
1444
1496
 
1445
1497
  test("pinned extension mode does NOT fall back to local on transport error", async () => {
1446
1498
  const fakeProxy = makeAvailableProxy();
1499
+ mockSingletonProxy = fakeProxy;
1447
1500
 
1448
1501
  // Make extension fail with transport_error
1449
1502
  createExtensionCdpClientMock.mockImplementationOnce(
@@ -1459,7 +1512,6 @@ describe("pinned-mode selection", () => {
1459
1512
 
1460
1513
  const ctx = makeContext({
1461
1514
  conversationId: "pinned-ext-no-fallback",
1462
- hostBrowserProxy: fakeProxy,
1463
1515
  });
1464
1516
 
1465
1517
  const client = getCdpClient(ctx, { mode: "extension" });
@@ -1535,9 +1587,9 @@ describe("pinned-mode selection", () => {
1535
1587
 
1536
1588
  test("pinned local mode routes to local", async () => {
1537
1589
  const fakeProxy = makeAvailableProxy();
1590
+ mockSingletonProxy = fakeProxy;
1538
1591
  const ctx = makeContext({
1539
1592
  conversationId: "pinned-local",
1540
- hostBrowserProxy: fakeProxy,
1541
1593
  });
1542
1594
 
1543
1595
  // Even with proxy available, pinned local should skip extension
@@ -1591,13 +1643,14 @@ describe("buildPinnedCandidateList", () => {
1591
1643
  cdpInspectEnabled = false;
1592
1644
  desktopAutoConfig = { enabled: true, cooldownMs: 30_000 };
1593
1645
  _resetDesktopAutoCooldown();
1646
+ mockSingletonProxy = null;
1594
1647
  });
1595
1648
 
1596
1649
  test("extension mode produces single extension candidate", () => {
1597
1650
  const fakeProxy = makeAvailableProxy();
1651
+ mockSingletonProxy = fakeProxy;
1598
1652
  const ctx = makeContext({
1599
1653
  conversationId: "bpl-ext",
1600
- hostBrowserProxy: fakeProxy,
1601
1654
  });
1602
1655
 
1603
1656
  const candidates = buildPinnedCandidateList(ctx, "extension");
@@ -1646,6 +1699,25 @@ describe("buildPinnedCandidateList", () => {
1646
1699
  });
1647
1700
  }
1648
1701
  });
1702
+
1703
+ test("extension mode throws when only macOS SSE bridge is connected", () => {
1704
+ // This is the bug case: isAvailable() = true but hasExtensionClient() = false.
1705
+ // Before the fix, this would build an extension candidate that silently
1706
+ // dispatched to the macOS bridge and failed with a misleading localhost:9222 error.
1707
+ const fakeProxy = makeMacosBridgeOnlyProxy();
1708
+ mockSingletonProxy = fakeProxy;
1709
+ const ctx = makeContext({ conversationId: "bpl-ext-macos-bridge-only" });
1710
+
1711
+ try {
1712
+ buildPinnedCandidateList(ctx, "extension");
1713
+ expect(true).toBe(false); // should not reach
1714
+ } catch (err) {
1715
+ expect(err).toBeInstanceOf(CdpError);
1716
+ const cdpErr = err as CdpError;
1717
+ expect(cdpErr.code).toBe("transport_error");
1718
+ expect(cdpErr.message).toContain("no Chrome Extension connected");
1719
+ }
1720
+ });
1649
1721
  });
1650
1722
 
1651
1723
  // ── Attempt diagnostics & fallback log tests ─────────────────────────────
@@ -1663,11 +1735,13 @@ describe("attempt diagnostics", () => {
1663
1735
  _resetDesktopAutoCooldown();
1664
1736
  logWarnCalls.length = 0;
1665
1737
  logDebugCalls.length = 0;
1738
+ mockSingletonProxy = null;
1666
1739
  });
1667
1740
 
1668
1741
  test("exhausted candidates error includes full attempt diagnostics", async () => {
1669
1742
  cdpInspectEnabled = true;
1670
1743
  const fakeProxy = makeAvailableProxy();
1744
+ mockSingletonProxy = fakeProxy;
1671
1745
 
1672
1746
  // Make extension fail
1673
1747
  createExtensionCdpClientMock.mockImplementationOnce(
@@ -1707,7 +1781,6 @@ describe("attempt diagnostics", () => {
1707
1781
 
1708
1782
  const ctx = makeContext({
1709
1783
  conversationId: "diag-all-fail",
1710
- hostBrowserProxy: fakeProxy,
1711
1784
  });
1712
1785
 
1713
1786
  const client = getCdpClient(ctx);
@@ -1750,6 +1823,7 @@ describe("attempt diagnostics", () => {
1750
1823
 
1751
1824
  test("successful fallback still records diagnostics for failed candidates", async () => {
1752
1825
  const fakeProxy = makeAvailableProxy();
1826
+ mockSingletonProxy = fakeProxy;
1753
1827
 
1754
1828
  // Make extension fail
1755
1829
  createExtensionCdpClientMock.mockImplementationOnce(
@@ -1765,7 +1839,6 @@ describe("attempt diagnostics", () => {
1765
1839
 
1766
1840
  const ctx = makeContext({
1767
1841
  conversationId: "diag-partial",
1768
- hostBrowserProxy: fakeProxy,
1769
1842
  });
1770
1843
 
1771
1844
  const client = getCdpClient(ctx);
@@ -1786,6 +1859,7 @@ describe("attempt diagnostics", () => {
1786
1859
  test("auto-mode fallback log includes candidate sequence and failure reasons", async () => {
1787
1860
  cdpInspectEnabled = true;
1788
1861
  const fakeProxy = makeAvailableProxy();
1862
+ mockSingletonProxy = fakeProxy;
1789
1863
 
1790
1864
  // Make extension fail
1791
1865
  createExtensionCdpClientMock.mockImplementationOnce(
@@ -1813,7 +1887,6 @@ describe("attempt diagnostics", () => {
1813
1887
 
1814
1888
  const ctx = makeContext({
1815
1889
  conversationId: "diag-log-shape",
1816
- hostBrowserProxy: fakeProxy,
1817
1890
  });
1818
1891
 
1819
1892
  const client = getCdpClient(ctx);
@@ -1937,10 +2010,12 @@ describe("no-fallback guarantees", () => {
1937
2010
  desktopAutoConfig = { enabled: true, cooldownMs: 30_000 };
1938
2011
  _resetDesktopAutoCooldown();
1939
2012
  logWarnCalls.length = 0;
2013
+ mockSingletonProxy = null;
1940
2014
  });
1941
2015
 
1942
2016
  test("pinned extension: only one candidate is ever constructed", async () => {
1943
2017
  const fakeProxy = makeAvailableProxy();
2018
+ mockSingletonProxy = fakeProxy;
1944
2019
 
1945
2020
  // Make extension fail
1946
2021
  createExtensionCdpClientMock.mockImplementationOnce(
@@ -1956,7 +2031,6 @@ describe("no-fallback guarantees", () => {
1956
2031
 
1957
2032
  const ctx = makeContext({
1958
2033
  conversationId: "nofb-ext",
1959
- hostBrowserProxy: fakeProxy,
1960
2034
  });
1961
2035
  const client = getCdpClient(ctx, { mode: "extension" });
1962
2036
 
@@ -2043,7 +2117,7 @@ describe("no-fallback guarantees", () => {
2043
2117
  // Verify that macOS turns can use the host browser proxy without requiring
2044
2118
  // extension registry connectivity. When a HostBrowserProxy is provisioned
2045
2119
  // via the SSE sender path (no extension), the factory should select
2046
- // extension as the top candidate (because hostBrowserProxy is available).
2120
+ // extension as the top candidate (because the singleton proxy is available).
2047
2121
  // When both proxy and fallback backends exist, selection is deterministic:
2048
2122
  // extension > cdp-inspect > local.
2049
2123
 
@@ -2060,15 +2134,16 @@ describe("macOS host-browser proxy without extension registry", () => {
2060
2134
  _resetDesktopAutoCooldown();
2061
2135
  logWarnCalls.length = 0;
2062
2136
  logDebugCalls.length = 0;
2137
+ mockSingletonProxy = null;
2063
2138
  });
2064
2139
 
2065
2140
  test("macOS turn with SSE-provisioned hostBrowserProxy selects extension backend", async () => {
2066
2141
  // Simulates macOS provisioning a HostBrowserProxy via SSE (no extension
2067
2142
  // registry connection). The proxy is available so extension is selected.
2068
2143
  const fakeProxy = makeAvailableProxy();
2144
+ mockSingletonProxy = fakeProxy;
2069
2145
  const ctx = makeContext({
2070
2146
  conversationId: "macos-sse-proxy",
2071
- hostBrowserProxy: fakeProxy,
2072
2147
  transportInterface: "macos",
2073
2148
  });
2074
2149
 
@@ -2085,9 +2160,9 @@ describe("macOS host-browser proxy without extension registry", () => {
2085
2160
 
2086
2161
  test("macOS turn with both proxy and cdp-inspect produces deterministic 3-candidate chain", () => {
2087
2162
  const fakeProxy = makeAvailableProxy();
2163
+ mockSingletonProxy = fakeProxy;
2088
2164
  const ctx = makeContext({
2089
2165
  conversationId: "macos-deterministic",
2090
- hostBrowserProxy: fakeProxy,
2091
2166
  transportInterface: "macos",
2092
2167
  });
2093
2168
 
@@ -2119,9 +2194,9 @@ describe("macOS host-browser proxy without extension registry", () => {
2119
2194
  // enablement — proxy presence drives extension selection regardless of
2120
2195
  // interface.
2121
2196
  const fakeProxy = makeAvailableProxy();
2197
+ mockSingletonProxy = fakeProxy;
2122
2198
  const ctx = makeContext({
2123
2199
  conversationId: "non-macos-proxy",
2124
- hostBrowserProxy: fakeProxy,
2125
2200
  transportInterface: "cli",
2126
2201
  });
2127
2202