@mycadet/assistant 0.12.7 → 0.12.9

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 (904) hide show
  1. package/README.md +1 -1
  2. package/docs/activation-funnel-telemetry.md +6 -6
  3. package/docs/cadet-doctor.md +7 -7
  4. package/docs/desktop-browser-cli.md +7 -7
  5. package/docs/skills.md +2 -2
  6. package/docs/voice-input-diagnostics.md +1 -1
  7. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +2 -2
  8. package/node_modules/@mycadet/avatar-manifest/src/__tests__/notification-avatar.test.ts +1 -1
  9. package/node_modules/@mycadet/avatar-manifest/src/notification-avatar.ts +2 -2
  10. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/package.json +2 -2
  11. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/{platform-credential.ts → cloud-credential.ts} +9 -9
  12. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
  13. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
  14. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
  15. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
  16. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
  17. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
  18. package/node_modules/@mycadet/ces-client/package.json +1 -1
  19. package/node_modules/@mycadet/ces-client/src/__tests__/ces-client.test.ts +14 -14
  20. package/node_modules/@mycadet/ces-client/src/rpc-client.ts +1 -1
  21. package/node_modules/@mycadet/credential-storage/src/oauth-runtime.ts +1 -1
  22. package/node_modules/@mycadet/credential-storage/src/static-credentials.ts +1 -1
  23. package/node_modules/@mycadet/environments/src/seeds.ts +6 -6
  24. package/node_modules/@mycadet/environments/src/shell.test.ts +1 -1
  25. package/node_modules/@mycadet/environments/src/types.ts +6 -6
  26. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/package.json +2 -2
  27. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/{platform-credential.ts → cloud-credential.ts} +9 -9
  28. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
  29. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
  30. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
  31. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
  32. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
  33. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
  34. package/node_modules/@mycadet/gateway-client/src/binding-strength-contract.ts +5 -5
  35. package/node_modules/@mycadet/gateway-client/src/gateway-ipc-contracts.ts +1 -1
  36. package/node_modules/@mycadet/gateway-client/src/inbound-contract.ts +2 -2
  37. package/node_modules/@mycadet/gateway-client/src/outbound-contract.ts +1 -1
  38. package/node_modules/@mycadet/service-contracts/package.json +2 -2
  39. package/node_modules/@mycadet/service-contracts/src/{platform-credential.ts → cloud-credential.ts} +9 -9
  40. package/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
  41. package/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
  42. package/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
  43. package/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
  44. package/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
  45. package/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
  46. package/openapi.yaml +6804 -799
  47. package/package.json +2 -2
  48. package/scripts/build-test-fixtures.ts +1 -1
  49. package/scripts/probe-skill-retrieval.ts +1 -1
  50. package/scripts/sync-llm-catalog.ts +2 -2
  51. package/scripts/voice-ttft-spike.ts +2 -2
  52. package/src/__tests__/adaptive-thinking-repair.test.ts +4 -4
  53. package/src/__tests__/agent-loop-override-profile.test.ts +4 -4
  54. package/src/__tests__/agent-loop-subagent-billing-headers.test.ts +1 -1
  55. package/src/__tests__/anthropic-provider.test.ts +2 -2
  56. package/src/__tests__/available-skills.test.ts +11 -12
  57. package/src/__tests__/avatar-identity-sync.test.ts +1 -1
  58. package/src/__tests__/byok-default-profile-ensure.test.ts +7 -7
  59. package/src/__tests__/call-domain.test.ts +1 -1
  60. package/src/__tests__/call-site-routing-connection-auto-resolve.test.ts +2 -2
  61. package/src/__tests__/catalog-files.test.ts +10 -10
  62. package/src/__tests__/catalog-install-normalize.test.ts +3 -3
  63. package/src/__tests__/channel-availability-routes.test.ts +8 -8
  64. package/src/__tests__/channel-readiness-routes.test.ts +4 -4
  65. package/src/__tests__/channel-readiness-service.test.ts +14 -14
  66. package/src/__tests__/channel-readiness-telegram-remote.test.ts +1 -1
  67. package/src/__tests__/chat-reveal-guard-priming.test.ts +5 -6
  68. package/src/__tests__/checker.test.ts +6 -6
  69. package/src/__tests__/clawhub.test.ts +1 -1
  70. package/src/__tests__/{platform-callback-registration.test.ts → cloud-callback-registration.test.ts} +66 -90
  71. package/src/__tests__/{platform-client-verify-credential.test.ts → cloud-client-verify-credential.test.ts} +14 -14
  72. package/src/__tests__/{managed-credential-catalog-cli.test.ts → cloud-credential-catalog-cli.test.ts} +41 -41
  73. package/src/__tests__/{managed-fallback-dispatch.test.ts → cloud-fallback-dispatch.test.ts} +21 -16
  74. package/src/__tests__/{managed-profile-guard.test.ts → cloud-profile-guard.test.ts} +77 -75
  75. package/src/__tests__/{platform-proxy-context.test.ts → cloud-proxy-context.test.ts} +44 -44
  76. package/src/__tests__/{managed-speech-defaults.test.ts → cloud-speech-defaults.test.ts} +41 -41
  77. package/src/__tests__/{managed-store.test.ts → cloud-store.test.ts} +99 -99
  78. package/src/__tests__/compaction-events.test.ts +7 -5
  79. package/src/__tests__/config-loader-backfill.test.ts +65 -65
  80. package/src/__tests__/config-loader-cloud-defaults.test.ts +373 -0
  81. package/src/__tests__/config-loader-corrupt.test.ts +1 -1
  82. package/src/__tests__/config-loader-validation-reset-notice.test.ts +1 -1
  83. package/src/__tests__/config-schema.test.ts +3 -3
  84. package/src/__tests__/{config-set-platform-guard.test.ts → config-set-cloud-guard.test.ts} +6 -6
  85. package/src/__tests__/config-set-route.test.ts +12 -8
  86. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +0 -8
  87. package/src/__tests__/config-watcher.test.ts +1 -1
  88. package/src/__tests__/contacts-write.test.ts +1 -1
  89. package/src/__tests__/conversation-agent-loop.test.ts +2 -2
  90. package/src/__tests__/conversation-app-control-instantiation.test.ts +18 -18
  91. package/src/__tests__/conversation-error.test.ts +45 -45
  92. package/src/__tests__/conversation-inference-profile-route.test.ts +4 -4
  93. package/src/__tests__/conversation-rendered-delegation-state.test.ts +4 -4
  94. package/src/__tests__/conversation-skill-tools.test.ts +7 -8
  95. package/src/__tests__/conversation-slash.test.ts +2 -2
  96. package/src/__tests__/conversation-speed-override.test.ts +8 -10
  97. package/src/__tests__/conversation-summarize-up-to.test.ts +4 -4
  98. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +1 -1
  99. package/src/__tests__/conversation-wait-for-idle.test.ts +7 -5
  100. package/src/__tests__/credential-execution-api-key-propagation.test.ts +5 -5
  101. package/src/__tests__/{credential-execution-managed-contract.test.ts → credential-execution-cloud-contract.test.ts} +24 -24
  102. package/src/__tests__/credential-health-service.test.ts +28 -40
  103. package/src/__tests__/credential-routes.test.ts +85 -165
  104. package/src/__tests__/credential-security-invariants.test.ts +6 -7
  105. package/src/__tests__/custom-profile-ensure.test.ts +1 -1
  106. package/src/__tests__/date-context.test.ts +1 -1
  107. package/src/__tests__/default-profile-catalog-fallback.test.ts +15 -15
  108. package/src/__tests__/delete-managed-skill-tool.test.ts +8 -8
  109. package/src/__tests__/discord-callback-round-trip.test.ts +1 -1
  110. package/src/__tests__/disk-usage.test.ts +3 -3
  111. package/src/__tests__/email-invite-adapter.test.ts +5 -5
  112. package/src/__tests__/{embedding-managed-proxy-selection.test.ts → embedding-cloud-proxy-selection.test.ts} +44 -43
  113. package/src/__tests__/emit-signal-routing-intent.test.ts +13 -15
  114. package/src/__tests__/events-dev-bypass-actor.test.ts +2 -2
  115. package/src/__tests__/fallback-breaker.test.ts +7 -7
  116. package/src/__tests__/feature-flag-test-helpers.ts +106 -0
  117. package/src/__tests__/gateway-flag-listener.test.ts +1 -1
  118. package/src/__tests__/gemini-image-service.test.ts +2 -2
  119. package/src/__tests__/gemini-provider.test.ts +5 -5
  120. package/src/__tests__/get-skill-detail-audit.test.ts +134 -288
  121. package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
  122. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +5 -5
  123. package/src/__tests__/host-cu-routes-targeted.test.ts +8 -8
  124. package/src/__tests__/image-credentials.test.ts +13 -13
  125. package/src/__tests__/inbound-admitted-introduction-nudge.test.ts +14 -6
  126. package/src/__tests__/inbound-trust-verdict.test.ts +14 -6
  127. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +11 -11
  128. package/src/__tests__/inference-profile-session-handler.test.ts +7 -7
  129. package/src/__tests__/inference-profile-session-ipc.test.ts +5 -5
  130. package/src/__tests__/inference-profile-validation-jev.test.ts +1 -1
  131. package/src/__tests__/init-feature-flag-overrides.test.ts +40 -24
  132. package/src/__tests__/input-repairs.test.ts +1 -1
  133. package/src/__tests__/install-skill-routing.test.ts +10 -8
  134. package/src/__tests__/integration-status.test.ts +5 -5
  135. package/src/__tests__/internal-telemetry-routes.test.ts +3 -3
  136. package/src/__tests__/invite-routes-http.test.ts +1 -1
  137. package/src/__tests__/llm-catalog-parity.test.ts +5 -7
  138. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +2 -2
  139. package/src/__tests__/llm-resolver-override-or-default.test.ts +3 -3
  140. package/src/__tests__/llm-resolver.test.ts +1 -1
  141. package/src/__tests__/llm-schema-fallback-profile.test.ts +25 -19
  142. package/src/__tests__/llm-usage-store.test.ts +1 -1
  143. package/src/__tests__/managed-skill-lifecycle.test.ts +12 -12
  144. package/src/__tests__/mcp-abort-signal.test.ts +1 -2
  145. package/src/__tests__/mcp-client-auth.test.ts +1 -2
  146. package/src/__tests__/mcp-config-secret-boundary.test.ts +44 -40
  147. package/src/__tests__/mcp-tool-annotations-risk.test.ts +1 -2
  148. package/src/__tests__/media-generate-image.test.ts +30 -30
  149. package/src/__tests__/memory-config-file-parity.test.ts +6 -6
  150. package/src/__tests__/migration-export-to-gcs.test.ts +4 -4
  151. package/src/__tests__/migration-import-commit-http.test.ts +1 -1
  152. package/src/__tests__/mtime-cache.test.ts +2 -2
  153. package/src/__tests__/{notification-platform-adapter.test.ts → notification-cloud-adapter.test.ts} +39 -39
  154. package/src/__tests__/notification-deep-link.test.ts +40 -40
  155. package/src/__tests__/oauth-apps-routes.test.ts +3 -3
  156. package/src/__tests__/oauth-cli.test.ts +9 -9
  157. package/src/__tests__/oauth-commands-routes.test.ts +16 -16
  158. package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -2
  159. package/src/__tests__/oauth-provider-serializer.test.ts +11 -11
  160. package/src/__tests__/oauth-providers-routes.test.ts +12 -12
  161. package/src/__tests__/oauth-store.test.ts +1 -1
  162. package/src/__tests__/oauth2-gateway-transport.test.ts +3 -3
  163. package/src/__tests__/onboarding-persona-write.test.ts +2 -2
  164. package/src/__tests__/openai-image-service.test.ts +2 -2
  165. package/src/__tests__/openai-responses-cutover-guard.test.ts +2 -2
  166. package/src/__tests__/openai-responses-provider.test.ts +1 -1
  167. package/src/__tests__/path-policy.test.ts +4 -4
  168. package/src/__tests__/personal-memory-auth-bypass.test.ts +1 -1
  169. package/src/__tests__/platform-bash-auto-approve.test.ts +18 -18
  170. package/src/__tests__/plugin-api-model-profiles.test.ts +1 -1
  171. package/src/__tests__/plugin-api-provider.test.ts +1 -1
  172. package/src/__tests__/plugin-api-store-credential.test.ts +4 -1
  173. package/src/__tests__/plugin-api-webhook-url.test.ts +4 -5
  174. package/src/__tests__/plugin-import-boundary-guard.test.ts +8 -39
  175. package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +2 -2
  176. package/src/__tests__/{provider-platform-proxy-integration.test.ts → provider-cloud-proxy-integration.test.ts} +70 -72
  177. package/src/__tests__/provider-commit-message-generator.test.ts +1 -1
  178. package/src/__tests__/provider-connections-backfill.test.ts +9 -9
  179. package/src/__tests__/provider-error-scenarios.test.ts +8 -8
  180. package/src/__tests__/provider-registry-ollama.test.ts +1 -1
  181. package/src/__tests__/provider-send-message-override-profile.test.ts +5 -5
  182. package/src/__tests__/registry.test.ts +3 -3
  183. package/src/__tests__/requests-mock.ts +972 -0
  184. package/src/__tests__/resolve-trust-class.test.ts +1 -1
  185. package/src/__tests__/resource-pressure-guard.test.ts +6 -6
  186. package/src/__tests__/resource-pressure-routes.test.ts +5 -5
  187. package/src/__tests__/retry-fallback-escalation.test.ts +5 -5
  188. package/src/__tests__/sanitize-config-for-transfer.test.ts +1 -1
  189. package/src/__tests__/scaffold-managed-skill-tool.test.ts +97 -97
  190. package/src/__tests__/schedule-store.test.ts +1 -1
  191. package/src/__tests__/search-skills-unified.test.ts +9 -7
  192. package/src/__tests__/{secret-routes-platform-proxy.test.ts → secret-routes-cloud-proxy.test.ts} +48 -95
  193. package/src/__tests__/secret-routes-scrub.test.ts +2 -59
  194. package/src/__tests__/secure-keys.test.ts +1 -1
  195. package/src/__tests__/skill-load-plugin-scope.test.ts +2 -2
  196. package/src/__tests__/skill-load-tool.test.ts +1 -1
  197. package/src/__tests__/skill-projection-feature-flag.test.ts +0 -19
  198. package/src/__tests__/skill-projection.benchmark.test.ts +5 -7
  199. package/src/__tests__/skill-tool-factory.test.ts +1 -1
  200. package/src/__tests__/skills-file-content-endpoint.test.ts +222 -536
  201. package/src/__tests__/skills-files-catalog-fallback.test.ts +259 -577
  202. package/src/__tests__/skills.test.ts +1 -1
  203. package/src/__tests__/slim-skill-category.test.ts +11 -9
  204. package/src/__tests__/stt-stream-session.test.ts +3 -3
  205. package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
  206. package/src/__tests__/subagent-disposal.test.ts +5 -5
  207. package/src/__tests__/subagent-fork-notifications.test.ts +4 -4
  208. package/src/__tests__/subagent-fork-spawn.test.ts +5 -5
  209. package/src/__tests__/subagent-manager-notify.test.ts +5 -5
  210. package/src/__tests__/subagent-tool-gate-mode.test.ts +2 -2
  211. package/src/__tests__/system-prompt.test.ts +1 -1
  212. package/src/__tests__/telegram-bot-username-resolution.test.ts +34 -52
  213. package/src/__tests__/telegram-config.test.ts +16 -16
  214. package/src/__tests__/telephony-tts-guard.test.ts +13 -13
  215. package/src/__tests__/test-preload.ts +17 -7
  216. package/src/__tests__/tool-audit.test.ts +1 -1
  217. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +7 -5
  218. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  219. package/src/__tests__/turn-events-store.test.ts +1 -1
  220. package/src/__tests__/twilio-routes.test.ts +2 -1
  221. package/src/__tests__/ui-choice-copy-surfaces.test.ts +1 -1
  222. package/src/__tests__/unified-turn-context-client-os.test.ts +1 -1
  223. package/src/__tests__/validate-input.test.ts +5 -5
  224. package/src/__tests__/verification-outbound-delivery.test.ts +1 -1
  225. package/src/__tests__/voice-config-update.test.ts +15 -15
  226. package/src/__tests__/voice-ingress-preflight.test.ts +4 -4
  227. package/src/__tests__/web-search.test.ts +340 -859
  228. package/src/__tests__/workspace-git-service.test.ts +1 -1
  229. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +12 -12
  230. package/src/__tests__/workspace-migration-087-memory-router-balanced-profile.test.ts +1 -1
  231. package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +1 -1
  232. package/src/__tests__/workspace-migration-100-upgrade-quality-profile-to-fable-5.test.ts +1 -1
  233. package/src/__tests__/workspace-migration-103-upgrade-quality-profile-to-opus-4-8.test.ts +1 -1
  234. package/src/__tests__/workspace-migration-110-flip-balanced-profile-to-together.test.ts +1 -1
  235. package/src/__tests__/workspace-migration-113-swap-balanced-profile-to-glm-5p2.test.ts +1 -1
  236. package/src/__tests__/workspace-migration-114-swap-quality-profile-to-opus.test.ts +1 -1
  237. package/src/__tests__/workspace-migration-123-swap-quality-profile-to-fable.test.ts +1 -1
  238. package/src/__tests__/workspace-migration-125-repoint-managed-connections-to-cadet.test.ts +3 -3
  239. package/src/__tests__/workspace-migration-126-strip-managed-profile-bodies.test.ts +9 -9
  240. package/src/__tests__/workspace-migration-127-backfill-default-provider.test.ts +11 -11
  241. package/src/__tests__/workspace-migration-130-speech-mode-to-provider.test.ts +3 -3
  242. package/src/__tests__/workspace-migration-132-web-search-mode-to-provider.test.ts +6 -6
  243. package/src/__tests__/workspace-migration-133-collapse-provider-connections.test.ts +3 -3
  244. package/src/__tests__/workspace-migration-134-image-generation-mode-to-provider.test.ts +6 -6
  245. package/src/__tests__/workspace-migration-136-repair-stale-fireworks-kimi-model-id.test.ts +1 -1
  246. package/src/__tests__/workspace-migration-137-repair-retired-fireworks-minimax-model-id.test.ts +1 -1
  247. package/src/__tests__/workspace-migration-146-repair-retired-fireworks-deepseek-flash-model-id.test.ts +1 -1
  248. package/src/__tests__/workspace-migration-147-rename-colliding-backup-profile-names.test.ts +1 -1
  249. package/src/__tests__/workspace-migration-151-repair-renamed-fireworks-deepseek-pro-model-id.test.ts +1 -1
  250. package/src/__tests__/workspace-migration-152-repair-retired-fireworks-minimax-m2p7-model-id.test.ts +1 -1
  251. package/src/__tests__/workspace-migration-159-rename-colliding-jev-profile-name.test.ts +1 -1
  252. package/src/__tests__/workspace-migration-160-repair-retired-fireworks-model-ids.test.ts +1 -1
  253. package/src/__tests__/workspace-migration-161-repair-retired-fireworks-glm-5p2-model-id.test.ts +1 -1
  254. package/src/api/events/cloud-disconnected.ts +21 -0
  255. package/src/api/events/host-bash.ts +1 -1
  256. package/src/api/events/host-cu.ts +1 -1
  257. package/src/api/events/host-file.ts +1 -1
  258. package/src/api/events/notification-intent.ts +1 -1
  259. package/src/api/events/show-cloud-login.ts +18 -0
  260. package/src/api/index.ts +11 -11
  261. package/src/api/responses/home.ts +1 -1
  262. package/src/api/surfaces.ts +4 -4
  263. package/src/approvals/guardian-request-resolvers.ts +2 -2
  264. package/src/avatar/accent-backfill.ts +1 -1
  265. package/src/avatar/identity-avatar.ts +1 -1
  266. package/src/avatar/notification-avatar.test.ts +2 -2
  267. package/src/avatar/notification-avatar.ts +2 -2
  268. package/src/avatar/resvg-lazy.test.ts +1 -1
  269. package/src/avatar/resvg-lazy.ts +3 -3
  270. package/src/avatar/sync-avatar.test.ts +76 -76
  271. package/src/avatar/sync-avatar.ts +15 -15
  272. package/src/avatar/traits-png-sync.ts +1 -1
  273. package/src/background-wake/background-wake-routes.test.ts +39 -39
  274. package/src/background-wake/{platform-client.test.ts → cloud-client.test.ts} +11 -11
  275. package/src/background-wake/{platform-client.ts → cloud-client.ts} +14 -14
  276. package/src/background-wake/publisher.ts +4 -4
  277. package/src/background-wake/wake-intent-hooks.test.ts +3 -3
  278. package/src/calls/__tests__/call-controller.test.ts +2 -2
  279. package/src/calls/__tests__/voice-session-bridge.test.ts +1 -1
  280. package/src/calls/call-domain.ts +1 -1
  281. package/src/calls/resolve-call-tts-provider.ts +6 -6
  282. package/src/calls/telephony-credential-preflight.ts +3 -3
  283. package/src/calls/telephony-tts-capability.ts +5 -6
  284. package/src/calls/tts-call-strategy.ts +1 -1
  285. package/src/calls/voice-escalation-judge.ts +1 -1
  286. package/src/calls/voice-ingress-preflight.ts +4 -4
  287. package/src/cli/bundled-modules.ts +1 -1
  288. package/src/cli/commands/__tests__/apps.test.ts +18 -53
  289. package/src/cli/commands/__tests__/plugins.test.ts +13 -13
  290. package/src/cli/commands/__tests__/tts.test.ts +1 -1
  291. package/src/cli/commands/auth.help.ts +3 -3
  292. package/src/cli/commands/auth.ts +2 -4
  293. package/src/cli/commands/browser.help.ts +2 -2
  294. package/src/cli/commands/channels/index.help.ts +2 -2
  295. package/src/cli/commands/channels/index.ts +1 -1
  296. package/src/cli/commands/channels/send.ts +1 -1
  297. package/src/cli/commands/cloud/__tests__/callback-routes-list.test.ts +2 -2
  298. package/src/cli/commands/cloud/__tests__/connect.test.ts +1 -1
  299. package/src/cli/commands/cloud/__tests__/disconnect.test.ts +3 -4
  300. package/src/cli/commands/cloud/connect.ts +2 -2
  301. package/src/cli/commands/cloud/credits-format.ts +1 -1
  302. package/src/cli/commands/cloud/index.help.ts +35 -35
  303. package/src/cli/commands/cloud/index.ts +1 -1
  304. package/src/cli/commands/config.ts +2 -2
  305. package/src/cli/commands/credentials.ts +10 -12
  306. package/src/cli/commands/domain.ts +1 -1
  307. package/src/cli/commands/email.help.ts +1 -1
  308. package/src/cli/commands/email.ts +2 -2
  309. package/src/cli/commands/gateway.help.ts +1 -1
  310. package/src/cli/commands/gateway.ts +1 -1
  311. package/src/cli/commands/image-generation.help.ts +1 -1
  312. package/src/cli/commands/inference-providers.ts +1 -1
  313. package/src/cli/commands/inference.help.ts +2 -2
  314. package/src/cli/commands/memory/index.help.ts +1 -1
  315. package/src/cli/commands/oauth/connect.test.ts +2 -2
  316. package/src/cli/commands/oauth/connect.ts +1 -1
  317. package/src/cli/commands/oauth/index.help.ts +5 -5
  318. package/src/cli/commands/oauth/providers.ts +2 -2
  319. package/src/cli/commands/oauth/shared.ts +3 -3
  320. package/src/cli/commands/plugins.help.ts +2 -3
  321. package/src/cli/commands/plugins.ts +5 -5
  322. package/src/cli/commands/roadmap.help.ts +1 -1
  323. package/src/cli/commands/telemetry.help.ts +2 -2
  324. package/src/cli/commands/telemetry.ts +2 -2
  325. package/src/cli/commands/tts.help.ts +3 -3
  326. package/src/cli/commands/webhooks.help.ts +9 -9
  327. package/src/cli/commands/webhooks.ts +1 -1
  328. package/src/cli/lib/__tests__/inspect-plugin.test.ts +8 -8
  329. package/src/cli/lib/__tests__/{install-from-platform.test.ts → install-from-cloud.test.ts} +54 -54
  330. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +18 -18
  331. package/src/cli/lib/__tests__/{plugin-catalog-platform.test.ts → plugin-catalog-cloud.test.ts} +2 -2
  332. package/src/cli/lib/__tests__/plugin-catalog-local.test.ts +1 -1
  333. package/src/cli/lib/__tests__/plugin-catalog-resolve.test.ts +9 -9
  334. package/src/cli/lib/__tests__/plugin-details.test.ts +10 -10
  335. package/src/cli/lib/__tests__/plugins-install-offline.test.ts +24 -24
  336. package/src/cli/lib/bundled-marketplace.json +1 -1
  337. package/src/cli/lib/inspect-plugin.ts +2 -2
  338. package/src/cli/lib/{install-from-platform.ts → install-from-cloud.ts} +29 -29
  339. package/src/cli/lib/install-from-github.ts +4 -4
  340. package/src/cli/lib/plugin-catalog-cache.ts +7 -7
  341. package/src/cli/lib/{plugin-catalog-platform.ts → plugin-catalog-cloud.ts} +6 -6
  342. package/src/cli/lib/plugin-catalog-local.ts +2 -2
  343. package/src/cli/lib/publish-plugin.ts +9 -10
  344. package/src/cli/lib/search-plugins.ts +2 -2
  345. package/src/{platform → cloud}/client.test.ts +85 -86
  346. package/src/{platform → cloud}/client.ts +38 -46
  347. package/src/{platform/platform-patch-queue.test.ts → cloud/cloud-patch-queue.test.ts} +6 -9
  348. package/src/{platform/platform-patch-queue.ts → cloud/cloud-patch-queue.ts} +11 -11
  349. package/src/{platform/managed-speech.test.ts → cloud/cloud-speech.test.ts} +19 -19
  350. package/src/{platform/managed-speech.ts → cloud/cloud-speech.ts} +41 -41
  351. package/src/{platform → cloud}/consent-cache.test.ts +5 -5
  352. package/src/{platform → cloud}/consent-cache.ts +8 -8
  353. package/src/cloud/feature-gate.ts +8 -0
  354. package/src/{platform → cloud}/sync-identity.test.ts +4 -4
  355. package/src/{platform → cloud}/sync-identity.ts +6 -6
  356. package/src/config/__tests__/{platform-identity.test.ts → cloud-identity.test.ts} +54 -56
  357. package/src/config/__tests__/{platform-rehydration.test.ts → cloud-rehydration.test.ts} +47 -80
  358. package/src/config/__tests__/default-profile-catalog.test.ts +12 -12
  359. package/src/config/__tests__/default-provider.test.ts +4 -4
  360. package/src/config/__tests__/deployment-context-defaults.test.ts +23 -23
  361. package/src/config/__tests__/{jev-managed-profile.test.ts → jev-cloud-profile.test.ts} +3 -5
  362. package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +2 -2
  363. package/src/config/__tests__/loader-last-known-good.test.ts +6 -6
  364. package/src/config/__tests__/loader-sparse-array-cleanup.test.ts +2 -2
  365. package/src/config/__tests__/profile-materialization.test.ts +7 -7
  366. package/src/config/__tests__/seed-default-provider.test.ts +17 -17
  367. package/src/config/__tests__/substrate-twin-shadowing.test.ts +36 -26
  368. package/src/config/__tests__/sync-gated-profiles.test.ts +20 -20
  369. package/src/config/__tests__/webhook-routing.test.ts +51 -51
  370. package/src/config/bundled-skills/computer-use/TOOLS.json +12 -12
  371. package/src/config/bundled-skills/messaging/SKILL.md +8 -8
  372. package/src/config/bundled-skills/messaging/TOOLS.json +2 -2
  373. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +1 -1
  374. package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
  375. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +2 -2
  376. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  377. package/src/config/bundled-skills/settings/tools/shared.ts +1 -1
  378. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +12 -12
  379. package/src/config/bundled-skills/skill-management/SKILL.md +3 -3
  380. package/src/config/bundled-skills/skill-management/TOOLS.json +8 -8
  381. package/src/config/bundled-skills/skill-management/tools/{delete-managed.ts → delete-cloud.ts} +2 -2
  382. package/src/config/bundled-skills/skill-management/tools/{scaffold-managed.ts → scaffold-cloud.ts} +2 -2
  383. package/src/config/call-site-defaults.ts +6 -6
  384. package/src/config/{platform-identity.ts → cloud-identity.ts} +39 -42
  385. package/src/config/cloud-rehydration.ts +35 -0
  386. package/src/config/{managed-speech-defaults.ts → cloud-speech-defaults.ts} +13 -13
  387. package/src/config/default-profile-catalog.ts +36 -38
  388. package/src/config/default-profile-names.ts +11 -11
  389. package/src/config/default-provider-resolution.ts +2 -2
  390. package/src/config/default-provider.ts +1 -1
  391. package/src/config/env-registry.ts +21 -26
  392. package/src/config/env.ts +33 -46
  393. package/src/config/feature-flag-registry.json +5 -5
  394. package/src/config/inference-profile-validation.ts +1 -1
  395. package/src/config/llm-resolver.ts +9 -10
  396. package/src/config/loader.ts +33 -17
  397. package/src/config/profile-materialization.ts +8 -8
  398. package/src/config/profile-text-generation.test.ts +1 -1
  399. package/src/config/sanitize-for-transfer.ts +1 -1
  400. package/src/config/schema.ts +6 -6
  401. package/src/config/schemas/__tests__/stt.test.ts +2 -2
  402. package/src/config/schemas/call-site-catalog.ts +1 -1
  403. package/src/config/schemas/channels.ts +8 -0
  404. package/src/config/schemas/{platform.ts → cloud.ts} +7 -6
  405. package/src/config/schemas/host-browser.ts +1 -0
  406. package/src/config/schemas/ingress.ts +29 -10
  407. package/src/config/schemas/llm.ts +36 -36
  408. package/src/config/schemas/memory-lifecycle.ts +11 -1
  409. package/src/config/schemas/services.ts +4 -4
  410. package/src/config/schemas/stt.ts +3 -3
  411. package/src/config/schemas/tts.ts +10 -5
  412. package/src/config/schemas/voice.ts +1 -1
  413. package/src/config/seed-inference-profiles.ts +19 -19
  414. package/src/config/skill-state.ts +2 -2
  415. package/src/config/skills.ts +4 -4
  416. package/src/config/substrate-twin-shadowing.ts +12 -17
  417. package/src/config/sync-gated-profiles.ts +8 -9
  418. package/src/config/webhook-routing.ts +19 -19
  419. package/src/contacts/contacts-write.ts +1 -1
  420. package/src/credential-execution/ces-runtime.ts +6 -6
  421. package/src/credential-execution/{managed-catalog.ts → cloud-catalog.ts} +24 -24
  422. package/src/credential-execution/prompted-credential.ts +2 -23
  423. package/src/credential-health/credential-health-service.ts +59 -70
  424. package/src/daemon/__tests__/can-spawn-subagents.test.ts +1 -1
  425. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +4 -4
  426. package/src/daemon/config-watcher.ts +2 -2
  427. package/src/daemon/conversation-agent-loop.ts +9 -9
  428. package/src/daemon/conversation-error.ts +36 -36
  429. package/src/daemon/conversation-skill-tools.ts +7 -7
  430. package/src/daemon/conversation-surfaces.ts +1 -1
  431. package/src/daemon/conversation-tool-setup.ts +2 -2
  432. package/src/daemon/conversation-turn-finalize.ts +1 -1
  433. package/src/daemon/conversation-workspace.ts +1 -1
  434. package/src/daemon/conversation.ts +1 -1
  435. package/src/daemon/credential-transcript-scrub.ts +32 -35
  436. package/src/daemon/daemon-readiness.ts +1 -1
  437. package/src/daemon/event-loop-watchdog.ts +2 -2
  438. package/src/daemon/handlers/config-ingress.ts +9 -9
  439. package/src/daemon/handlers/config-telegram.ts +6 -6
  440. package/src/daemon/handlers/skills.ts +20 -20
  441. package/src/daemon/host-cu-proxy.ts +1 -1
  442. package/src/daemon/lifecycle.ts +19 -19
  443. package/src/daemon/parse-actual-tokens-from-error.ts +3 -3
  444. package/src/daemon/providers-setup.ts +6 -6
  445. package/src/daemon/resource-pressure-guard-lifecycle.ts +1 -1
  446. package/src/daemon/resource-pressure-guard.ts +6 -6
  447. package/src/daemon/shutdown-handlers.ts +1 -1
  448. package/src/daemon/sqlite-corruption-watchdog.ts +3 -3
  449. package/src/daemon/trust-context.ts +1 -1
  450. package/src/desktop/desktop-automation-lease.ts +1 -1
  451. package/src/desktop/desktop-browser-endpoint.ts +2 -4
  452. package/src/desktop/desktop-computer-use-routing.test.ts +6 -6
  453. package/src/desktop/desktop-stream-bridge.test.ts +4 -4
  454. package/src/desktop/desktop-stream-bridge.ts +1 -1
  455. package/src/desktop/{virtual-desktop-platform.test.ts → virtual-desktop-cloud.test.ts} +6 -6
  456. package/src/desktop/virtual-desktop-feature.ts +7 -7
  457. package/src/email/byo-email-credential.ts +1 -1
  458. package/src/email/registered-inbox.test.ts +16 -16
  459. package/src/email/registered-inbox.ts +20 -20
  460. package/src/heartbeat/heartbeat-service.ts +1 -1
  461. package/src/hooks/hook-loader.ts +2 -2
  462. package/src/inbound/__tests__/oauth-callback-url.test.ts +2 -2
  463. package/src/inbound/__tests__/tunnel-probe.test.ts +8 -8
  464. package/src/inbound/{platform-callback-registration.ts → cloud-callback-registration.ts} +49 -60
  465. package/src/inbound/oauth-callback-url.ts +6 -6
  466. package/src/inbound/pod-webhook-claim.ts +2 -2
  467. package/src/inbound/public-ingress-urls.ts +3 -3
  468. package/src/inbound/tunnel-probe.ts +21 -15
  469. package/src/inbound/tunnel-webhooks-gate.ts +3 -3
  470. package/src/ipc/__tests__/db-readiness-ipc-gate.test.ts +1 -1
  471. package/src/ipc/__tests__/email-ipc.test.ts +8 -8
  472. package/src/ipc/gateway-client.test.ts +55 -59
  473. package/src/ipc/gateway-flag-listener.ts +3 -3
  474. package/src/ipc/routes/db-proxy.ts +1 -1
  475. package/src/live-voice/__tests__/live-activity-reporter.test.ts +2 -2
  476. package/src/live-voice/__tests__/{live-voice-managed-speech-fallback.test.ts → live-voice-cloud-speech-fallback.test.ts} +15 -15
  477. package/src/live-voice/__tests__/live-voice-credential-preflight.test.ts +7 -7
  478. package/src/live-voice/__tests__/live-voice-stt.test.ts +1 -1
  479. package/src/live-voice/live-activity-reporter.ts +7 -7
  480. package/src/live-voice/live-voice-credential-preflight.ts +6 -6
  481. package/src/live-voice/live-voice-session.ts +3 -3
  482. package/src/live-voice/live-voice-tts.ts +1 -1
  483. package/src/mcp/__tests__/mcp-oauth-client-registration.test.ts +4 -4
  484. package/src/mcp/__tests__/mcp-oauth-provider.test.ts +1 -1
  485. package/src/mcp/mcp-oauth-provider.ts +2 -2
  486. package/src/media/gemini-image-service.ts +11 -13
  487. package/src/media/image-credentials.ts +9 -9
  488. package/src/media/openai-image-service.ts +1 -1
  489. package/src/media/types.ts +3 -3
  490. package/src/messaging/providers/channel-transport.ts +1 -1
  491. package/src/messaging/providers/discord/transport.ts +1 -1
  492. package/src/messaging/providers/gmail/adapter.ts +1 -1
  493. package/src/messaging/providers/gmail/client.ts +4 -4
  494. package/src/messaging/providers/outlook/adapter.ts +1 -1
  495. package/src/messaging/providers/slack/adapter.ts +1 -1
  496. package/src/messaging/providers/slack/transport.ts +1 -1
  497. package/src/messaging/providers/telegram-bot/transport.ts +1 -1
  498. package/src/monitoring/db-integrity-check.ts +1 -1
  499. package/src/monitoring/db-integrity-sample.ts +2 -2
  500. package/src/monitoring/mount-watch.ts +1 -1
  501. package/src/monitoring/oom-kill-reporter.ts +1 -1
  502. package/src/monitoring/worker.ts +5 -5
  503. package/src/notifications/README.md +2 -2
  504. package/src/notifications/__tests__/broadcaster.test.ts +9 -9
  505. package/src/notifications/__tests__/completion-policy.test.ts +1 -1
  506. package/src/notifications/__tests__/emit-signal-pipeline-failure.test.ts +4 -4
  507. package/src/notifications/activity-failed-dedupe.ts +1 -1
  508. package/src/notifications/adapters/{platform.ts → cloud.ts} +8 -8
  509. package/src/notifications/broadcaster.ts +10 -10
  510. package/src/notifications/decision-engine.ts +1 -1
  511. package/src/notifications/destination-resolver.ts +1 -1
  512. package/src/notifications/emit-signal.ts +6 -6
  513. package/src/notifications/types.ts +2 -2
  514. package/src/oauth/__tests__/identity-verifier.test.ts +1 -1
  515. package/src/oauth/__tests__/{seed-providers-managed.test.ts → seed-providers-cloud.test.ts} +13 -13
  516. package/src/oauth/byo-connection.test.ts +2 -2
  517. package/src/oauth/{platform-connection.test.ts → cloud-connection.test.ts} +41 -43
  518. package/src/oauth/{platform-connection.ts → cloud-connection.ts} +19 -19
  519. package/src/oauth/connection-resolver.test.ts +59 -61
  520. package/src/oauth/connection-resolver.ts +22 -22
  521. package/src/oauth/connection.ts +1 -1
  522. package/src/oauth/oauth-store.ts +8 -8
  523. package/src/oauth/provider-serializer.ts +4 -4
  524. package/src/oauth/revoke.ts +1 -1
  525. package/src/oauth/seed-providers.ts +32 -32
  526. package/src/permissions/approval-provenance.ts +1 -1
  527. package/src/permissions/checker.test.ts +18 -16
  528. package/src/permissions/checker.ts +3 -3
  529. package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
  530. package/src/persistence/embeddings/embedding-backend.test.ts +16 -16
  531. package/src/persistence/embeddings/embedding-backend.ts +13 -13
  532. package/src/persistence/embeddings/embedding-gemini.test.ts +9 -12
  533. package/src/persistence/embeddings/embedding-gemini.ts +11 -11
  534. package/src/persistence/embeddings/embedding-runtime-manager.ts +2 -2
  535. package/src/persistence/jobs-store.ts +1 -1
  536. package/src/persistence/lifecycle-events-store.ts +1 -1
  537. package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
  538. package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
  539. package/src/persistence/migrations/224-oauth-providers-managed-service-is-paid.ts +1 -1
  540. package/src/persistence/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +1 -1
  541. package/src/persistence/migrations/296-rewrite-balanced-economy-profile-pins.ts +2 -2
  542. package/src/persistence/migrations/306-rewrite-frontier-profile-pins.test.ts +1 -1
  543. package/src/persistence/migrations/306-rewrite-frontier-profile-pins.ts +1 -1
  544. package/src/persistence/migrations/351-schedule-skill-script-handoff.ts +1 -1
  545. package/src/persistence/migrations/361-normalize-managed-connection-rows.test.ts +3 -3
  546. package/src/persistence/migrations/361-normalize-managed-connection-rows.ts +7 -7
  547. package/src/persistence/migrations/__tests__/319-remove-legacy-managed-connections.test.ts +2 -2
  548. package/src/persistence/schema/oauth.ts +1 -1
  549. package/src/plugin-api/index.ts +4 -4
  550. package/src/plugin-api/model-profiles.test.ts +1 -1
  551. package/src/plugin-api/model-profiles.ts +1 -1
  552. package/src/plugin-api/transcription-session.ts +1 -1
  553. package/src/plugin-api/vision-support.test.ts +1 -1
  554. package/src/plugin-api/webhook-url.ts +12 -12
  555. package/src/plugins/__tests__/source-fingerprint.test.ts +1 -1
  556. package/src/plugins/defaults/{platform-hosted → cloud-hosted}/__tests__/reengage.test.ts +5 -6
  557. package/src/plugins/defaults/cloud-hosted/package.json +14 -0
  558. package/src/plugins/defaults/{platform-hosted → cloud-hosted}/routes/reengage.ts +3 -3
  559. package/src/plugins/defaults/index.ts +6 -6
  560. package/src/plugins/defaults/main.ts +5 -5
  561. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +5 -5
  562. package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +1 -1
  563. package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +1 -1
  564. package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +5 -0
  565. package/src/plugins/defaults/memory/config.ts +4 -4
  566. package/src/plugins/defaults/memory/memory-retrospective-constants.ts +2 -2
  567. package/src/plugins/defaults/memory/memory-retrospective-job.ts +7 -7
  568. package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +5 -5
  569. package/src/plugins/defaults/memory/memory-retrospective-skill-card.ts +2 -2
  570. package/src/plugins/defaults/memory/src/__tests__/memory-v2-routes.test.ts +1 -1
  571. package/src/plugins/defaults/memory/src/__tests__/memory-worker-routes.test.ts +1 -1
  572. package/src/plugins/defaults/memory/substrate/__tests__/boot-maintenance.test.ts +20 -20
  573. package/src/plugins/defaults/memory/substrate/__tests__/cli-command-store.test.ts +1 -1
  574. package/src/plugins/defaults/memory/substrate/__tests__/skill-store.test.ts +3 -3
  575. package/src/plugins/defaults/memory/substrate/boot-maintenance.ts +17 -17
  576. package/src/plugins/defaults/memory/substrate/cli-command-store.ts +2 -2
  577. package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +1 -1
  578. package/src/plugins/defaults/memory/substrate/skill-store.ts +4 -4
  579. package/src/plugins/defaults/memory/v3/__tests__/maintain-job.test.ts +3 -3
  580. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +2 -2
  581. package/src/plugins/defaults/memory/v3/maintain-job.ts +10 -10
  582. package/src/plugins/defaults/memory/v3/orchestrate.ts +3 -3
  583. package/src/plugins/defaults/memory/worker.ts +5 -5
  584. package/src/plugins/defaults/workspace/injectors.ts +2 -2
  585. package/src/plugins/mtime-cache.ts +1 -1
  586. package/src/plugins/source-versions.ts +1 -1
  587. package/src/plugins/types.ts +1 -1
  588. package/src/prompts/__tests__/system-prompt.test.ts +1 -1
  589. package/src/prompts/normalize-onboarding.ts +1 -1
  590. package/src/prompts/persona-resolver.ts +1 -1
  591. package/src/prompts/templates/system-sections.ts +3 -3
  592. package/src/providers/__tests__/cadet-connection-routing.test.ts +7 -7
  593. package/src/providers/__tests__/cadet-mismatch-routing.test.ts +12 -12
  594. package/src/providers/__tests__/connection-model-compat.test.ts +2 -2
  595. package/src/providers/__tests__/dispatch-connection-routing.test.ts +10 -10
  596. package/src/providers/__tests__/inference.test.ts +2 -2
  597. package/src/providers/__tests__/preflight-resolved-config.test.ts +16 -16
  598. package/src/providers/__tests__/retry-callsite.test.ts +1 -1
  599. package/src/providers/__tests__/satellite-connection-routing.test.ts +4 -4
  600. package/src/providers/__tests__/search-provider-catalog.test.ts +2 -2
  601. package/src/providers/__tests__/voice-error-copy.test.ts +3 -3
  602. package/src/providers/anthropic/client.ts +1 -1
  603. package/src/providers/cadet/client.ts +1 -1
  604. package/src/providers/cadet-model-routing.test.ts +19 -19
  605. package/src/providers/cadet-model-routing.ts +23 -23
  606. package/src/providers/call-site-routing.ts +10 -10
  607. package/src/providers/{platform-proxy → cloud-proxy}/constants.ts +11 -11
  608. package/src/providers/{platform-proxy → cloud-proxy}/context.ts +26 -26
  609. package/src/providers/connection-resolution.ts +43 -43
  610. package/src/providers/fallback-breaker.ts +2 -2
  611. package/src/providers/fetch-provider-catalog.ts +3 -3
  612. package/src/providers/gemini/client.ts +5 -5
  613. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +3 -3
  614. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +8 -8
  615. package/src/providers/inference/__tests__/base-url-security.test.ts +4 -4
  616. package/src/providers/inference/adapter-factory.ts +35 -35
  617. package/src/providers/inference/auth.ts +10 -10
  618. package/src/providers/inference/backfill.ts +11 -11
  619. package/src/providers/inference/connection-availability.ts +24 -24
  620. package/src/providers/inference/connections.ts +18 -20
  621. package/src/providers/inference/profile-probe.ts +4 -4
  622. package/src/providers/inference/resolve-auth.ts +8 -8
  623. package/src/providers/jev/ask.test.ts +1 -1
  624. package/src/providers/jev/ask.ts +2 -2
  625. package/src/providers/model-catalog.ts +8 -9
  626. package/src/providers/openai/__tests__/api-error-normalization.test.ts +3 -3
  627. package/src/providers/openai/api-error-normalization.ts +2 -2
  628. package/src/providers/provider-availability.ts +4 -4
  629. package/src/providers/provider-env-vars.ts +1 -1
  630. package/src/providers/provider-secret-catalog.ts +1 -1
  631. package/src/providers/registry.ts +20 -20
  632. package/src/providers/retry.ts +26 -26
  633. package/src/providers/routing-identity.ts +10 -10
  634. package/src/providers/search-provider-catalog.ts +2 -2
  635. package/src/providers/speech-to-text/__tests__/{cadet-managed-realtime.test.ts → cadet-cloud-realtime.test.ts} +3 -3
  636. package/src/providers/speech-to-text/__tests__/{cadet-managed.test.ts → cadet-cloud.test.ts} +35 -35
  637. package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +1 -1
  638. package/src/providers/speech-to-text/__tests__/resolve.test.ts +27 -27
  639. package/src/providers/speech-to-text/{cadet-managed-flux-realtime.ts → cadet-cloud-flux-realtime.ts} +6 -8
  640. package/src/providers/speech-to-text/{cadet-managed-realtime.ts → cadet-cloud-realtime.ts} +3 -3
  641. package/src/providers/speech-to-text/{cadet-managed.ts → cadet-cloud.ts} +18 -20
  642. package/src/providers/speech-to-text/cadet-speech-relay-connection.ts +7 -7
  643. package/src/providers/speech-to-text/deepgram-flux-frames.ts +3 -3
  644. package/src/providers/speech-to-text/deepgram-flux-realtime.ts +4 -4
  645. package/src/providers/speech-to-text/provider-catalog.ts +3 -3
  646. package/src/providers/speech-to-text/resolve.ts +26 -28
  647. package/src/providers/together/client.ts +1 -1
  648. package/src/providers/types.ts +4 -4
  649. package/src/providers/voice-error-copy.ts +1 -1
  650. package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +10 -10
  651. package/src/runtime/agent-wake.ts +1 -1
  652. package/src/runtime/auth/__tests__/middleware.test.ts +1 -1
  653. package/src/runtime/auth/middleware.ts +1 -1
  654. package/src/runtime/auth/scopes.ts +1 -1
  655. package/src/runtime/capabilities.ts +1 -1
  656. package/src/runtime/channel-invite-transports/discord.ts +1 -1
  657. package/src/runtime/channel-invite-transports/email.ts +2 -2
  658. package/src/runtime/channel-readiness-service.ts +15 -13
  659. package/src/runtime/channel-reply-session.test.ts +1 -1
  660. package/src/runtime/channel-reply-session.ts +1 -1
  661. package/src/runtime/http-server.ts +4 -4
  662. package/src/runtime/introduction-policy.ts +4 -4
  663. package/src/runtime/migrations/__tests__/origin-mode.test.ts +14 -14
  664. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +1 -1
  665. package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +2 -2
  666. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +3 -4
  667. package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +6 -7
  668. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +1 -1
  669. package/src/runtime/migrations/migration-transport.ts +3 -3
  670. package/src/runtime/migrations/origin-mode.ts +6 -9
  671. package/src/runtime/migrations/vbundle-import-policy.ts +2 -2
  672. package/src/runtime/migrations/vbundle-importer.ts +4 -4
  673. package/src/runtime/migrations/vbundle-streaming-importer.ts +6 -6
  674. package/src/runtime/migrations/vbundle-validator.ts +1 -1
  675. package/src/runtime/routes/__tests__/{platform-credits-routes.test.ts → cloud-credits-routes.test.ts} +9 -9
  676. package/src/runtime/routes/__tests__/{platform-invoice-routes.test.ts → cloud-invoice-routes.test.ts} +13 -13
  677. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +1 -1
  678. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +126 -82
  679. package/src/runtime/routes/__tests__/default-plugin-routes.test.ts +5 -5
  680. package/src/runtime/routes/__tests__/default-provider-routes.test.ts +10 -10
  681. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +18 -18
  682. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +18 -16
  683. package/src/runtime/routes/__tests__/inference-send-routes.test.ts +1 -1
  684. package/src/runtime/routes/__tests__/ingress-status-routes.test.ts +1 -1
  685. package/src/runtime/routes/__tests__/migration-cadet-metadata-reconcile.test.ts +5 -20
  686. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -22
  687. package/src/runtime/routes/__tests__/oauth-proxy-routes.test.ts +27 -27
  688. package/src/runtime/routes/__tests__/plugins-routes.test.ts +5 -5
  689. package/src/runtime/routes/__tests__/ps-routes.test.ts +5 -3
  690. package/src/runtime/routes/__tests__/roadmap-routes.test.ts +15 -15
  691. package/src/runtime/routes/__tests__/webhook-routes.test.ts +31 -31
  692. package/src/runtime/routes/app-management-routes.ts +1 -1
  693. package/src/runtime/routes/attachment-routes.ts +1 -1
  694. package/src/runtime/routes/auth-routes.ts +14 -14
  695. package/src/runtime/routes/avatar-routes.ts +0 -14
  696. package/src/runtime/routes/background-wake-routes.ts +4 -4
  697. package/src/runtime/routes/channel-availability-routes.ts +4 -4
  698. package/src/runtime/routes/client-routes.ts +5 -5
  699. package/src/runtime/routes/cloud-credentials.ts +45 -0
  700. package/src/runtime/routes/{platform-routes.ts → cloud-routes.ts} +86 -119
  701. package/src/runtime/routes/conversation-compaction-routes.ts +1 -1
  702. package/src/runtime/routes/conversation-query-routes.ts +345 -667
  703. package/src/runtime/routes/credential-routes.ts +28 -30
  704. package/src/runtime/routes/default-provider-routes.ts +1 -1
  705. package/src/runtime/routes/desktop-setup-routes.test.ts +5 -5
  706. package/src/runtime/routes/desktop-setup-routes.ts +1 -1
  707. package/src/runtime/routes/domain-routes.ts +15 -21
  708. package/src/runtime/routes/email-routes.ts +13 -13
  709. package/src/runtime/routes/errors.ts +1 -1
  710. package/src/runtime/routes/gateway-status-routes.ts +1 -1
  711. package/src/runtime/routes/identity-routes.ts +3 -3
  712. package/src/runtime/routes/inbound-message-handler.ts +1 -1
  713. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +1 -1
  714. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +1 -1
  715. package/src/runtime/routes/index.ts +1 -1
  716. package/src/runtime/routes/inference-profile-availability-guard.ts +5 -5
  717. package/src/runtime/routes/inference-profiles-routes.ts +11 -11
  718. package/src/runtime/routes/inference-provider-connection-routes.ts +24 -24
  719. package/src/runtime/routes/ingress-status-routes.ts +1 -1
  720. package/src/runtime/routes/integrations/a2a.ts +2 -2
  721. package/src/runtime/routes/integrations/twilio.ts +21 -35
  722. package/src/runtime/routes/internal-telemetry-routes.ts +2 -2
  723. package/src/runtime/routes/live-voice-routes.test.ts +4 -4
  724. package/src/runtime/routes/live-voice-routes.ts +6 -6
  725. package/src/runtime/routes/migration-routes.ts +34 -40
  726. package/src/runtime/routes/oauth-commands-routes.ts +31 -31
  727. package/src/runtime/routes/oauth-providers.ts +5 -5
  728. package/src/runtime/routes/oauth-proxy-passthrough.test.ts +1 -1
  729. package/src/runtime/routes/oauth-proxy-passthrough.ts +8 -8
  730. package/src/runtime/routes/oauth-proxy-routes.ts +15 -17
  731. package/src/runtime/routes/oauth-request-hints.test.ts +1 -1
  732. package/src/runtime/routes/oauth-request-hints.ts +1 -1
  733. package/src/runtime/routes/plugins-routes.ts +9 -9
  734. package/src/runtime/routes/profiler-routes.ts +1 -1
  735. package/src/runtime/routes/ps-routes.ts +4 -0
  736. package/src/runtime/routes/roadmap-routes.ts +18 -20
  737. package/src/runtime/routes/secret-routes.ts +20 -61
  738. package/src/runtime/routes/settings-routes.ts +18 -23
  739. package/src/runtime/routes/telemetry-routes.ts +4 -4
  740. package/src/runtime/routes/tts-routes.ts +4 -4
  741. package/src/runtime/routes/user-route-resolution.ts +1 -1
  742. package/src/runtime/routes/webhook-routes.ts +18 -18
  743. package/src/runtime/routes/workflow-routes.ts +5 -5
  744. package/src/runtime/sync/resource-sync-events.ts +2 -2
  745. package/src/runtime/verification-outbound-actions.ts +4 -4
  746. package/src/schedule/integration-status.ts +6 -6
  747. package/src/schedule/run-script.ts +1 -1
  748. package/src/schedule/schedule-timezone.ts +1 -1
  749. package/src/schedule/worker.ts +5 -5
  750. package/src/security/auth-fallback-events-store.ts +1 -1
  751. package/src/security/oauth2.ts +4 -4
  752. package/src/skills/available-skills.ts +4 -4
  753. package/src/skills/catalog-files.ts +8 -8
  754. package/src/skills/catalog-install.ts +12 -12
  755. package/src/skills/categories-cache.ts +3 -3
  756. package/src/skills/clawhub.ts +1 -1
  757. package/src/skills/{platform-compatibility.test.ts → cloud-compatibility.test.ts} +7 -7
  758. package/src/skills/{platform-compatibility.ts → cloud-compatibility.ts} +2 -4
  759. package/src/skills/{managed-store.ts → cloud-store.ts} +21 -23
  760. package/src/skills/inline-command-runner.ts +1 -1
  761. package/src/skills/install-meta.ts +1 -1
  762. package/src/skills/path-classifier.ts +4 -4
  763. package/src/skills/skill-history.ts +4 -4
  764. package/src/skills/skillssh-registry.ts +1 -1
  765. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +1 -1
  766. package/src/stt/daemon-batch-transcriber.ts +7 -7
  767. package/src/stt/types.ts +3 -3
  768. package/src/subagent/manager.ts +15 -15
  769. package/src/subagent/types.ts +1 -1
  770. package/src/telegram/__tests__/webhook-health.test.ts +16 -16
  771. package/src/telegram/webhook-health.ts +10 -10
  772. package/src/telemetry/__tests__/config-setting-events-store.test.ts +1 -1
  773. package/src/telemetry/__tests__/outbox-test-harness.ts +2 -2
  774. package/src/telemetry/config-setting-events-store.ts +1 -1
  775. package/src/telemetry/config-setting-snapshot.ts +1 -1
  776. package/src/telemetry/memory-corpus-size.ts +1 -1
  777. package/src/telemetry/memory-tier-reporter.test.ts +2 -2
  778. package/src/telemetry/memory-tier-reporter.ts +3 -3
  779. package/src/telemetry/telemetry-event-sources.test.ts +2 -2
  780. package/src/telemetry/telemetry-event-sources.ts +9 -9
  781. package/src/telemetry/telemetry-events-outbox.ts +2 -2
  782. package/src/telemetry/telemetry-wire-validation.test.ts +1 -1
  783. package/src/telemetry/telemetry-wire-validation.ts +3 -3
  784. package/src/telemetry/telemetry-wire.generated.ts +1 -1
  785. package/src/telemetry/tool-audit.ts +1 -1
  786. package/src/telemetry/tool-executed-events-store.test.ts +1 -1
  787. package/src/telemetry/trace-collection-policy.ts +4 -4
  788. package/src/telemetry/turn-events-store.ts +1 -1
  789. package/src/telemetry/turn-outcome.ts +1 -1
  790. package/src/telemetry/turn-trace-store.ts +2 -2
  791. package/src/telemetry/types.test.ts +1 -1
  792. package/src/telemetry/types.ts +19 -19
  793. package/src/telemetry/usage-telemetry-reporter.test.ts +42 -42
  794. package/src/telemetry/usage-telemetry-reporter.ts +17 -17
  795. package/src/telemetry/watchdog-direct-emit.test.ts +9 -9
  796. package/src/telemetry/watchdog-direct-emit.ts +10 -10
  797. package/src/tools/__tests__/side-effect-abort-guard.test.ts +2 -2
  798. package/src/tools/browser/cdp-client/factory.ts +1 -1
  799. package/src/tools/computer-use/target.ts +2 -2
  800. package/src/tools/credentials/store.ts +2 -20
  801. package/src/tools/network/__tests__/{managed-search-proxy.test.ts → cloud-search-proxy.test.ts} +20 -20
  802. package/src/tools/network/__tests__/web-search.test.ts +14 -14
  803. package/src/tools/network/{managed-search-proxy.ts → cloud-search-proxy.ts} +13 -13
  804. package/src/tools/network/web-search.ts +9 -9
  805. package/src/tools/permission-checker.ts +2 -2
  806. package/src/tools/shared/input-misuse.ts +1 -1
  807. package/src/tools/shared/input-repairs.ts +4 -4
  808. package/src/tools/skills/{delete-managed.ts → delete-cloud.ts} +4 -4
  809. package/src/tools/skills/find-similar-skills.test.ts +7 -7
  810. package/src/tools/skills/find-similar-skills.ts +15 -15
  811. package/src/tools/skills/load.ts +6 -6
  812. package/src/tools/skills/{scaffold-managed.ts → scaffold-cloud.ts} +16 -16
  813. package/src/tools/skills/skill-script-runner.ts +2 -2
  814. package/src/tools/terminal/safe-env.ts +3 -3
  815. package/src/tools/tool-types.ts +2 -2
  816. package/src/tools/types.ts +2 -2
  817. package/src/tools/ui-surface/surface-shape-docs.ts +2 -2
  818. package/src/tools/workflows/manage-workflows.ts +1 -1
  819. package/src/tools/workspace-tools/loader.ts +1 -1
  820. package/src/tts/__tests__/cadet-provider.test.ts +5 -5
  821. package/src/tts/provider-catalog.ts +1 -1
  822. package/src/tts/providers/cadet-provider.ts +23 -23
  823. package/src/tts/providers/cadet-tts-socket.ts +2 -2
  824. package/src/tts/tts-config-resolver.ts +1 -1
  825. package/src/tts/tts-voice-field.ts +3 -3
  826. package/src/usage/subagent-attribution.ts +1 -1
  827. package/src/util/__tests__/process-table.test.ts +47 -0
  828. package/src/util/canonicalize-identity.ts +1 -1
  829. package/src/util/cgroup-cpu.ts +5 -5
  830. package/src/util/cgroup-memory.ts +2 -2
  831. package/src/util/container-cpu-sampler.ts +4 -4
  832. package/src/util/disk-usage.ts +4 -4
  833. package/src/util/errors.ts +3 -3
  834. package/src/util/layout.ts +479 -0
  835. package/src/util/oom-priority.ts +1 -1
  836. package/src/util/platform.ts +12 -468
  837. package/src/util/process-table.ts +39 -5
  838. package/src/util/provider-error-patterns.ts +2 -2
  839. package/src/watch/__tests__/watch-retro.test.ts +2 -2
  840. package/src/watch/watch-retro.ts +1 -1
  841. package/src/watcher/__tests__/telemetry.test.ts +2 -2
  842. package/src/watcher/telemetry.ts +1 -1
  843. package/src/windows-compiled-cli.ts +1 -1
  844. package/src/workspace/adaptive-thinking-repair.ts +4 -4
  845. package/src/workspace/byok-default-profile-ensure.ts +7 -7
  846. package/src/workspace/git-service.ts +2 -2
  847. package/src/workspace/migrations/006-services-config.ts +1 -1
  848. package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +1 -1
  849. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +1 -1
  850. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +1 -1
  851. package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +1 -1
  852. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +4 -4
  853. package/src/workspace/migrations/087-memory-router-balanced-profile.ts +3 -3
  854. package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +4 -4
  855. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +5 -5
  856. package/src/workspace/migrations/100-upgrade-quality-profile-to-fable-5.ts +4 -4
  857. package/src/workspace/migrations/101-upgrade-balanced-economy-to-minimax-m3.ts +4 -4
  858. package/src/workspace/migrations/103-upgrade-quality-profile-to-opus-4-8.ts +5 -5
  859. package/src/workspace/migrations/104-recheck-adaptive-thinking-model-implied-anthropic.ts +1 -1
  860. package/src/workspace/migrations/106-drop-collect-usage-data.ts +1 -1
  861. package/src/workspace/migrations/108-drop-balanced-economy-profile.ts +4 -4
  862. package/src/workspace/migrations/109-swap-quality-profile-to-glm-5p2.ts +11 -11
  863. package/src/workspace/migrations/110-flip-balanced-profile-to-together.ts +6 -6
  864. package/src/workspace/migrations/113-swap-balanced-profile-to-glm-5p2.ts +5 -5
  865. package/src/workspace/migrations/114-swap-quality-profile-to-opus.ts +4 -4
  866. package/src/workspace/migrations/115-drop-frontier-profile.ts +5 -5
  867. package/src/workspace/migrations/123-swap-quality-profile-to-fable.ts +5 -5
  868. package/src/workspace/migrations/125-repoint-managed-connections-to-cadet.ts +3 -3
  869. package/src/workspace/migrations/126-strip-managed-profile-bodies.ts +2 -2
  870. package/src/workspace/migrations/127-backfill-default-provider.ts +6 -6
  871. package/src/workspace/migrations/130-speech-mode-to-provider.ts +4 -4
  872. package/src/workspace/migrations/131-drop-web-fetch-mode.ts +1 -1
  873. package/src/workspace/migrations/132-web-search-mode-to-provider.ts +6 -6
  874. package/src/workspace/migrations/133-collapse-provider-connections.ts +3 -3
  875. package/src/workspace/migrations/134-image-generation-mode-to-provider.ts +4 -4
  876. package/src/workspace/migrations/136-repair-stale-fireworks-kimi-model-id.ts +2 -2
  877. package/src/workspace/migrations/137-repair-retired-fireworks-minimax-model-id.ts +2 -2
  878. package/src/workspace/migrations/139-clear-renamed-cost-profile-label.ts +2 -2
  879. package/src/workspace/migrations/141-stt-english-default-to-multilingual.ts +4 -4
  880. package/src/workspace/migrations/144-convert-stranded-subscription-openai-profiles.ts +1 -1
  881. package/src/workspace/migrations/145-collapse-profile-bindings-to-entries.ts +2 -2
  882. package/src/workspace/migrations/146-repair-retired-fireworks-deepseek-flash-model-id.ts +2 -2
  883. package/src/workspace/migrations/148-strip-unsupported-fallback-profiles.ts +2 -2
  884. package/src/workspace/migrations/150-stt-flux-provider-to-model-family.ts +1 -1
  885. package/src/workspace/migrations/151-repair-renamed-fireworks-deepseek-pro-model-id.ts +2 -2
  886. package/src/workspace/migrations/152-repair-retired-fireworks-minimax-m2p7-model-id.ts +2 -2
  887. package/src/workspace/migrations/159-rename-colliding-jev-profile-name.ts +2 -2
  888. package/src/workspace/migrations/160-repair-retired-fireworks-model-ids.ts +2 -2
  889. package/src/workspace/migrations/161-repair-retired-fireworks-glm-5p2-model-id.ts +2 -2
  890. package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +1 -1
  891. package/src/workspace/migrations/__tests__/150-stt-flux-provider-to-model-family.test.ts +1 -1
  892. package/src/workspace/migrations/registry.ts +6 -6
  893. package/src/workspace/top-level-renderer.ts +1 -1
  894. package/src/workspace/turn-commit.ts +2 -2
  895. package/src/__tests__/config-loader-platform-defaults.test.ts +0 -606
  896. package/src/__tests__/mock-gateway-ipc.ts +0 -260
  897. package/src/api/events/platform-disconnected.ts +0 -21
  898. package/src/api/events/show-platform-login.ts +0 -20
  899. package/src/config/platform-rehydration.ts +0 -60
  900. package/src/platform/feature-gate.ts +0 -8
  901. package/src/plugins/defaults/platform-hosted/package.json +0 -14
  902. package/src/runtime/routes/platform-managed-credentials.ts +0 -50
  903. /package/src/__tests__/{gateway-client-managed-outbound.test.ts → gateway-client-cloud-outbound.test.ts} +0 -0
  904. /package/src/__tests__/{secure-keys-managed-failover.test.ts → secure-keys-cloud-failover.test.ts} +0 -0
@@ -0,0 +1,972 @@
1
+ /**
2
+ * requests_mock-style test helper for HTTP and IPC calls.
3
+ *
4
+ * Replaces hand-rolled `mock.module` stubs of `ipc/cli-client.js` and inline
5
+ * `globalThis.fetch` swaps with one declarative pattern: a test registers the
6
+ * requests it expects and the responses it assumes, exercises the code under
7
+ * test, then asserts on the recorded calls.
8
+ *
9
+ * const ipc = await mockIpc("cli");
10
+ * ipc.on("apps_refresh", { appId: "app-1", compiled: true });
11
+ * ipc.on({ method: "apps_refresh", params: { pathParams: { id: "x" } } }, { ... });
12
+ *
13
+ * const http = mockHttp();
14
+ * http.on("GET", "/v1/apps", { status: 200, body: [] });
15
+ *
16
+ * Semantics (requests_mock-style):
17
+ * - The newest matching registration wins (LIFO). A registration whose
18
+ * sequence is exhausted falls through to older registrations.
19
+ * - A single response repeats on every matching call; an array response is a
20
+ * sequence consumed FIFO, one entry per call.
21
+ * - An `Error` response (direct or returned from a function) is thrown at
22
+ * the caller.
23
+ * - A function response receives the recorded request and returns the
24
+ * response dynamically.
25
+ * - An unmatched request throws `NoMockMatchError` listing the request and
26
+ * the registered handlers (CLI channel + HTTP). The gateway transport is
27
+ * the exception: it answers every method — registrations are consulted
28
+ * first, then per-test transport defaults, then a kernel
29
+ * `get_feature_flags` sentinel — because incidental `get_feature_flags`
30
+ * calls are ubiquitous in this suite.
31
+ *
32
+ * Channels reset automatically after every test (`afterEach` registered in
33
+ * test-preload.ts), so registrations are per-test: anything registered at
34
+ * module scope dies at the first reset. Register inside the test or a
35
+ * `beforeEach`.
36
+ *
37
+ * `mockIpc("cli")` must be awaited BEFORE the module under test is imported
38
+ * (same discipline as `mock.module`): it lazily swaps `ipc/cli-client.js` for
39
+ * the channel-backed fake. Files that never call it keep the real client —
40
+ * the real-socket tests rely on that.
41
+ */
42
+
43
+ import { EventEmitter } from "node:events";
44
+ import { mock } from "bun:test";
45
+
46
+ // ---------------------------------------------------------------------------
47
+ // Shared matching kernel
48
+ // ---------------------------------------------------------------------------
49
+
50
+ /** A recorded CLI/gateway IPC request. */
51
+ export interface IpcCallRecord {
52
+ method: string;
53
+ params?: Record<string, unknown>;
54
+ }
55
+
56
+ /** A recorded HTTP request (body is the JSON-parsed request body when parseable). */
57
+ export interface HttpRequestRecord {
58
+ url: string;
59
+ method: string;
60
+ headers: Record<string, string>;
61
+ body?: unknown;
62
+ }
63
+
64
+ export class NoMockMatchError extends Error {
65
+ constructor(message: string) {
66
+ super(message);
67
+ this.name = "NoMockMatchError";
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Response forms every channel accepts: a bare value, a `Response` (HTTP),
73
+ * an `Error` (thrown), a function of the request, or an array (sequence).
74
+ * See the file docblock for semantics.
75
+ */
76
+ export type MockResponse<I> =
77
+ | ((req: I) => unknown)
78
+ | Error
79
+ | MockResponse<I>[]
80
+ | Response
81
+ | Record<string, unknown>
82
+ | Uint8Array
83
+ | string
84
+ | number
85
+ | boolean
86
+ | null;
87
+
88
+ function isRecord(value: unknown): value is Record<string, unknown> {
89
+ return typeof value === "object" && value !== null && !Array.isArray(value);
90
+ }
91
+
92
+ /** Subset match: every key in `expected` must deep-match the same key in `actual`. */
93
+ function deepMatches(expected: unknown, actual: unknown): boolean {
94
+ if (expected === actual) {
95
+ return true;
96
+ }
97
+ if (Array.isArray(expected) && Array.isArray(actual)) {
98
+ return (
99
+ expected.length === actual.length &&
100
+ expected.every((entry, index) => deepMatches(entry, actual[index]))
101
+ );
102
+ }
103
+ if (!isRecord(expected) || !isRecord(actual)) {
104
+ return false;
105
+ }
106
+ return Object.keys(expected).every(
107
+ (key) => key in actual && deepMatches(expected[key], actual[key]),
108
+ );
109
+ }
110
+
111
+ interface CompiledMatcher<I> {
112
+ match: (req: I) => boolean;
113
+ describe: string;
114
+ }
115
+
116
+ interface Registration<I> {
117
+ match: (req: I) => boolean;
118
+ describe: string;
119
+ /** FIFO sequence; empty = exhausted (no longer matches). */
120
+ queue?: MockResponse<I>[];
121
+ /** Single repeating response resolver. Present when queue is undefined. */
122
+ respond?: (req: I) => unknown;
123
+ }
124
+
125
+ class MockChannel<I> {
126
+ private registrations: Registration<I>[] = [];
127
+ private callHistory: I[] = [];
128
+
129
+ constructor(
130
+ private readonly compileMatcher: (matcher: unknown) => CompiledMatcher<I>,
131
+ private readonly describeRequest: (req: I) => string,
132
+ ) {}
133
+
134
+ on(matcher: unknown, response: MockResponse<I>): void {
135
+ const { match, describe } = this.compileMatcher(matcher);
136
+ if (typeof response === "function") {
137
+ this.registrations.push({
138
+ match,
139
+ describe,
140
+ respond: (req) => {
141
+ const result = response(req);
142
+ if (result instanceof Error) {
143
+ throw result;
144
+ }
145
+ return result;
146
+ },
147
+ });
148
+ return;
149
+ }
150
+ if (response instanceof Error) {
151
+ this.registrations.push({
152
+ match,
153
+ describe,
154
+ respond: () => {
155
+ throw response;
156
+ },
157
+ });
158
+ return;
159
+ }
160
+ if (Array.isArray(response)) {
161
+ this.registrations.push({ match, describe, queue: [...response] });
162
+ return;
163
+ }
164
+ this.registrations.push({ match, describe, respond: () => response });
165
+ }
166
+
167
+ dispatch(req: I): unknown {
168
+ for (let i = this.registrations.length - 1; i >= 0; i--) {
169
+ const registration = this.registrations[i];
170
+ if (registration.queue !== undefined && registration.queue.length === 0) {
171
+ continue; // sequence exhausted — fall through to older registrations
172
+ }
173
+ if (!registration.match(req)) {
174
+ continue;
175
+ }
176
+ this.callHistory.push(req);
177
+ if (registration.queue !== undefined) {
178
+ const next = registration.queue.shift();
179
+ if (next !== undefined) {
180
+ return this.resolve(next, req);
181
+ }
182
+ continue;
183
+ }
184
+ return registration.respond!(req);
185
+ }
186
+ throw new NoMockMatchError(this.unmatchedMessage(req));
187
+ }
188
+
189
+ history(): readonly I[] {
190
+ return this.callHistory;
191
+ }
192
+
193
+ isEmpty(): boolean {
194
+ return this.registrations.length === 0;
195
+ }
196
+
197
+ reset(): void {
198
+ this.registrations = [];
199
+ this.callHistory = [];
200
+ }
201
+
202
+ private resolve(response: MockResponse<I>, req: I): unknown {
203
+ if (typeof response === "function") {
204
+ const result = response(req);
205
+ if (result instanceof Error) {
206
+ throw result;
207
+ }
208
+ return result;
209
+ }
210
+ if (response instanceof Error) {
211
+ throw response;
212
+ }
213
+ return response;
214
+ }
215
+
216
+ private unmatchedMessage(req: I): string {
217
+ const lines = this.registrations
218
+ .slice()
219
+ .reverse()
220
+ .map((registration, index) => {
221
+ const remaining =
222
+ registration.queue === undefined
223
+ ? "repeats"
224
+ : `${registration.queue.length} left`;
225
+ return ` ${index + 1}. ${registration.describe} (${remaining})`;
226
+ });
227
+ const registered =
228
+ lines.length > 0
229
+ ? `\nRegistered handlers (newest first):\n${lines.join("\n")}`
230
+ : "\nNo handlers registered.";
231
+ return (
232
+ `No mock registered for ${this.describeRequest(req)}.${registered}` +
233
+ `\nRegister a response before the call, e.g. mockIpc("cli").on(...) or mockHttp().on(...).`
234
+ );
235
+ }
236
+ }
237
+
238
+ // ---------------------------------------------------------------------------
239
+ // IPC channels (CLI daemon + gateway)
240
+ // ---------------------------------------------------------------------------
241
+
242
+ export type IpcMatcher =
243
+ | string
244
+ | RegExp
245
+ | { method?: string; params?: Record<string, unknown> }
246
+ | ((req: IpcCallRecord) => boolean);
247
+
248
+ function compileIpcMatcher(matcher: unknown): CompiledMatcher<IpcCallRecord> {
249
+ if (typeof matcher === "string") {
250
+ return { match: (req) => req.method === matcher, describe: matcher };
251
+ }
252
+ if (matcher instanceof RegExp) {
253
+ return {
254
+ match: (req) => matcher.test(req.method),
255
+ describe: String(matcher),
256
+ };
257
+ }
258
+ if (typeof matcher === "function") {
259
+ return { match: (req) => matcher(req), describe: "(predicate)" };
260
+ }
261
+ const spec = isRecord(matcher) ? matcher : {};
262
+ const method = typeof spec.method === "string" ? spec.method : undefined;
263
+ const params = isRecord(spec.params) ? spec.params : undefined;
264
+ return {
265
+ match: (req) =>
266
+ (method === undefined || req.method === method) &&
267
+ (params === undefined ||
268
+ (isRecord(req.params) && deepMatches(params, req.params))),
269
+ describe: JSON.stringify(matcher),
270
+ };
271
+ }
272
+
273
+ function describeIpcRequest(req: IpcCallRecord): string {
274
+ return `IPC ${req.method} ${JSON.stringify(req.params ?? {})}`;
275
+ }
276
+
277
+ const cliChannel = new MockChannel<IpcCallRecord>(
278
+ compileIpcMatcher,
279
+ describeIpcRequest,
280
+ );
281
+ const gatewayChannel = new MockChannel<IpcCallRecord>(
282
+ compileIpcMatcher,
283
+ describeIpcRequest,
284
+ );
285
+
286
+ function filterIpcCalls(
287
+ channel: MockChannel<IpcCallRecord>,
288
+ method: string | undefined,
289
+ ): IpcCallRecord[] {
290
+ const history = channel.history();
291
+ if (method === undefined) {
292
+ return [...history];
293
+ }
294
+ return history.filter((req) => req.method === method);
295
+ }
296
+
297
+ export interface IpcMockController {
298
+ /** Register a response for matching IPC calls. Newest registration wins. */
299
+ on(matcher: IpcMatcher, response: MockResponse<IpcCallRecord>): void;
300
+ calls(method?: string): IpcCallRecord[];
301
+ callCount(method?: string): number;
302
+ lastCall(method?: string): IpcCallRecord | undefined;
303
+ }
304
+
305
+ /**
306
+ * Transport-level controls unique to the gateway channel. The fake answers
307
+ * every method (it never throws `NoMockMatchError` — incidental gateway
308
+ * calls are ubiquitous in the suite), so tests shape what the transport says
309
+ * to UN-registered requests instead.
310
+ */
311
+ export interface GatewayTransportControls {
312
+ /**
313
+ * Results answered for methods no `.on` registration claimed. A key mapped
314
+ * to `undefined` suppresses even the `get_feature_flags` sentinel for that
315
+ * method. Replaces any previously set defaults.
316
+ */
317
+ setDefaults(results: Record<string, unknown>): void;
318
+ /**
319
+ * Simulate a failed socket connect: the persistent client throws
320
+ * `IpcConnectError`, the one-shot `ipcCall` returns `undefined` (mirroring
321
+ * the real module).
322
+ */
323
+ failConnect(opts?: { code?: string }): void;
324
+ /**
325
+ * Throw a transient (retryable) connect error for the first `n`
326
+ * persistent-client calls; with `ipcCallError`, a non-retryable
327
+ * `IpcCallError` instead. Consulted AFTER `.on` registrations, so a
328
+ * registered response is never "failed" by these knobs.
329
+ */
330
+ failFirstN(n: number, opts?: { ipcCallError?: boolean }): void;
331
+ /** Persistent-client `.call` invocations for `method` since the last reset. */
332
+ persistentCallCount(method: string): number;
333
+ }
334
+
335
+ export type IpcMockChannel = "cli" | "gateway";
336
+
337
+ export async function mockIpc(
338
+ channel: "gateway",
339
+ ): Promise<IpcMockController & GatewayTransportControls>;
340
+ export async function mockIpc(channel: "cli"): Promise<IpcMockController>;
341
+ export async function mockIpc(
342
+ channel: IpcMockChannel,
343
+ ): Promise<IpcMockController & Partial<GatewayTransportControls>> {
344
+ if (channel === "cli") {
345
+ await ensureCliClientMock();
346
+ }
347
+ const target = channel === "cli" ? cliChannel : gatewayChannel;
348
+ const base: IpcMockController = {
349
+ on: (matcher, response) => target.on(matcher, response),
350
+ calls: (method) => filterIpcCalls(target, method),
351
+ callCount: (method) => filterIpcCalls(target, method).length,
352
+ lastCall: (method) => {
353
+ const list = filterIpcCalls(target, method);
354
+ return list[list.length - 1];
355
+ },
356
+ };
357
+ if (channel !== "gateway") {
358
+ return base;
359
+ }
360
+ return {
361
+ ...base,
362
+ setDefaults: (results) => {
363
+ gatewayDefaults = { ...results };
364
+ },
365
+ failConnect: (opts) => {
366
+ gatewayConnectError = true;
367
+ if (opts?.code !== undefined) {
368
+ gatewayConnectErrorCode = opts.code;
369
+ }
370
+ },
371
+ failFirstN: (n, opts) => {
372
+ gatewayFailFirstN = n;
373
+ gatewayFailFirstNIpcCallError = opts?.ipcCallError ?? false;
374
+ },
375
+ persistentCallCount: (method) => gatewayPersistentCallCounts[method] ?? 0,
376
+ };
377
+ }
378
+
379
+ /**
380
+ * Build a `ok: false` IPC response with the typed failure fields
381
+ * (`statusCode` / `errorCode` / `errorDetails` mirror the daemon's
382
+ * RouteError envelope).
383
+ */
384
+ export function ipcError(
385
+ error: string,
386
+ fields?: {
387
+ statusCode?: number;
388
+ errorCode?: string;
389
+ errorDetails?: unknown;
390
+ },
391
+ ): Record<string, unknown> {
392
+ const result: Record<string, unknown> = { ok: false, error };
393
+ if (fields?.statusCode !== undefined) {
394
+ result.statusCode = fields.statusCode;
395
+ }
396
+ if (fields?.errorCode !== undefined) {
397
+ result.errorCode = fields.errorCode;
398
+ }
399
+ if (fields?.errorDetails !== undefined) {
400
+ result.errorDetails = fields.errorDetails;
401
+ }
402
+ return result;
403
+ }
404
+
405
+ /**
406
+ * Hook for the gateway transport fake (below): consult the gateway channel
407
+ * FIRST, falling through to the per-test transport defaults when nothing
408
+ * matches. An `Error`-instance response comes back as the resolved value so
409
+ * the caller can apply the one-shot/persistent failure contract.
410
+ */
411
+ export function dispatchGatewayIpcRequest(
412
+ method: string,
413
+ params?: Record<string, unknown>,
414
+ ): { handled: boolean; value?: unknown } {
415
+ if (gatewayChannel.isEmpty()) {
416
+ return { handled: false };
417
+ }
418
+ try {
419
+ return {
420
+ handled: true,
421
+ value: gatewayChannel.dispatch({ method, params }),
422
+ };
423
+ } catch (error) {
424
+ if (error instanceof NoMockMatchError) {
425
+ return { handled: false };
426
+ }
427
+ return { handled: true, value: error };
428
+ }
429
+ }
430
+
431
+ // ---------------------------------------------------------------------------
432
+ // Gateway transport fake (installed globally once by test-preload.ts)
433
+ // ---------------------------------------------------------------------------
434
+
435
+ /**
436
+ * Sentinel answered for `get_feature_flags` when neither a registration nor
437
+ * a per-test default covers it. Keeps the response non-empty so
438
+ * `initFeatureFlagOverrides()` does not enter its 7.75 s empty-result retry
439
+ * loop in tests that build the CLI program or otherwise trigger flag
440
+ * initialization. The key starts with a double underscore so it cannot
441
+ * collide with any real registry-declared flag.
442
+ */
443
+ const GET_FEATURE_FLAGS_SENTINEL: Record<string, boolean> = {
444
+ __test_default__: false,
445
+ };
446
+
447
+ class FakeIpcCallError extends Error {
448
+ readonly statusCode?: number;
449
+ readonly errorCode?: string;
450
+ readonly errorDetails?: unknown;
451
+
452
+ constructor(
453
+ message: string,
454
+ fields: {
455
+ statusCode?: number;
456
+ errorCode?: string;
457
+ errorDetails?: unknown;
458
+ } = {},
459
+ ) {
460
+ super(message);
461
+ this.name = "IpcCallError";
462
+ if (fields.statusCode !== undefined) {
463
+ this.statusCode = fields.statusCode;
464
+ }
465
+ if (fields.errorCode !== undefined) {
466
+ this.errorCode = fields.errorCode;
467
+ }
468
+ if (fields.errorDetails !== undefined) {
469
+ this.errorDetails = fields.errorDetails;
470
+ }
471
+ }
472
+ }
473
+
474
+ class FakeIpcConnectError extends Error {
475
+ readonly code?: string;
476
+
477
+ constructor(message: string, code?: string) {
478
+ super(message);
479
+ this.name = "IpcConnectError";
480
+ if (code !== undefined) {
481
+ this.code = code;
482
+ }
483
+ }
484
+ }
485
+
486
+ const RETRYABLE_CONNECT_CODES = new Set(["ENOENT", "ECONNREFUSED"]);
487
+
488
+ function isRetryableIpcConnectError(err: unknown): boolean {
489
+ if (typeof err === "object" && err !== null && "code" in err) {
490
+ const code = (err as { code?: unknown }).code;
491
+ return typeof code === "string" && RETRYABLE_CONNECT_CODES.has(code);
492
+ }
493
+ return false;
494
+ }
495
+
496
+ // Per-test transport state — cleared by resetRequestMockChannels.
497
+ let gatewayDefaults: Record<string, unknown> = {};
498
+ let gatewayConnectError = false;
499
+ let gatewayConnectErrorCode: string | undefined;
500
+ let gatewayFailFirstN = 0;
501
+ let gatewayFailFirstNIpcCallError = false;
502
+ const gatewayPersistentCallCounts: Record<string, number> = {};
503
+
504
+ function mockConnectError(): FakeIpcConnectError {
505
+ return new FakeIpcConnectError(
506
+ "Mock IPC socket error",
507
+ gatewayConnectErrorCode ?? "ENOENT",
508
+ );
509
+ }
510
+
511
+ /** The transport's answer for a method no `.on` registration claimed. */
512
+ function gatewayDefaultAnswer(method: string): unknown {
513
+ if (method in gatewayDefaults) {
514
+ return gatewayDefaults[method];
515
+ }
516
+ if (method === "get_feature_flags") {
517
+ return GET_FEATURE_FLAGS_SENTINEL;
518
+ }
519
+ return undefined;
520
+ }
521
+
522
+ class FakePersistentIpcClient extends EventEmitter {
523
+ async call(
524
+ method: string,
525
+ _params?: Record<string, unknown>,
526
+ _timeoutMs?: number,
527
+ ): Promise<unknown> {
528
+ gatewayPersistentCallCounts[method] =
529
+ (gatewayPersistentCallCounts[method] ?? 0) + 1;
530
+ const dispatched = dispatchGatewayIpcRequest(method, _params);
531
+ if (dispatched.handled) {
532
+ if (dispatched.value instanceof Error) {
533
+ throw dispatched.value;
534
+ }
535
+ return dispatched.value;
536
+ }
537
+ if (gatewayFailFirstN > 0) {
538
+ gatewayFailFirstN--;
539
+ if (gatewayFailFirstNIpcCallError) {
540
+ throw new FakeIpcCallError("Mock deterministic gateway error");
541
+ }
542
+ throw mockConnectError();
543
+ }
544
+ if (gatewayConnectError) {
545
+ throw mockConnectError();
546
+ }
547
+ return gatewayDefaultAnswer(method);
548
+ }
549
+
550
+ destroy(): void {
551
+ /* no-op */
552
+ }
553
+ }
554
+
555
+ /**
556
+ * Swap `@mycadet/gateway-client/ipc-client` for the channel-backed fake.
557
+ * Registered once in the test preload so every test file gets a no-op IPC
558
+ * layer by default — no test accidentally connects to a real gateway socket.
559
+ */
560
+ export function installGatewayIpcMock(): void {
561
+ // Named exports here must cover every ipc-client symbol the package barrel
562
+ // re-exports. Bun's mock replaces that module for relative and package
563
+ // imports, so a missing name fails assistant tests at load time.
564
+ mock.module("@mycadet/gateway-client/ipc-client", () => ({
565
+ ipcCall: async (
566
+ _socketPath: string,
567
+ method: string,
568
+ params?: Record<string, unknown>,
569
+ ): Promise<unknown> => {
570
+ const dispatched = dispatchGatewayIpcRequest(method, params);
571
+ if (dispatched.handled) {
572
+ // Real ipcCall returns undefined on failure — mirror that behavior.
573
+ return dispatched.value instanceof Error ? undefined : dispatched.value;
574
+ }
575
+ if (gatewayConnectError) {
576
+ // Real ipcCall returns undefined on failure — mirror that behavior.
577
+ return undefined;
578
+ }
579
+ return gatewayDefaultAnswer(method);
580
+ },
581
+ IpcCallError: FakeIpcCallError,
582
+ IpcConnectError: FakeIpcConnectError,
583
+ isRetryableIpcConnectError,
584
+ PersistentIpcClient: FakePersistentIpcClient,
585
+ }));
586
+ }
587
+
588
+ // ---------------------------------------------------------------------------
589
+ // CLI client transport fake (lazy — only files that call mockIpc("cli"))
590
+ // ---------------------------------------------------------------------------
591
+
592
+ const CLI_CLIENT_MODULE = "../ipc/cli-client.js";
593
+ let cliClientMockInstalled = false;
594
+
595
+ async function ensureCliClientMock(): Promise<void> {
596
+ if (cliClientMockInstalled) {
597
+ return;
598
+ }
599
+ cliClientMockInstalled = true;
600
+ // Spread the REAL module and replace only the transport functions — the
601
+ // same shape the hand-rolled per-file stubs used, minus the boilerplate.
602
+ // exitCodeFromIpcResult stays real (pure mapping, zero drift).
603
+ const real = await import(CLI_CLIENT_MODULE);
604
+ mock.module(CLI_CLIENT_MODULE, () => ({
605
+ ...real,
606
+ cliIpcCall: fakeCliIpcCall,
607
+ cliIpcCallBinary: fakeCliIpcCallBinary,
608
+ cliIpcCallStream: fakeCliIpcCallStream,
609
+ exitFromIpcResult: (
610
+ result: { ok: boolean; error?: string; statusCode?: number },
611
+ _command?: unknown,
612
+ ) => {
613
+ // Non-killing stand-in for the real process.exit (the hand-rolled-stub
614
+ // convention): same stderr line + exit code, no process death.
615
+ process.stderr.write(`${result.error ?? "Unknown error"}\n`);
616
+ process.exitCode = real.exitCodeFromIpcResult(result);
617
+ },
618
+ }));
619
+ }
620
+
621
+ function normalizeCliResponse(value: unknown): Record<string, unknown> {
622
+ if (isRecord(value)) {
623
+ if (typeof value.error === "string") {
624
+ const result: Record<string, unknown> = { ok: false, error: value.error };
625
+ if (typeof value.statusCode === "number") {
626
+ result.statusCode = value.statusCode;
627
+ }
628
+ if (typeof value.errorCode === "string") {
629
+ result.errorCode = value.errorCode;
630
+ }
631
+ if (value.errorDetails !== undefined) {
632
+ result.errorDetails = value.errorDetails;
633
+ }
634
+ return result;
635
+ }
636
+ if (
637
+ typeof value.ok === "boolean" &&
638
+ ("result" in value || "error" in value)
639
+ ) {
640
+ // Full CliIpcCallResult passthrough. A bare result that merely CONTAINS
641
+ // an `ok` field (APIs echo ok:true in their payloads) must still be
642
+ // wrapped, so requiring a result/error key disambiguates the envelope.
643
+ return value;
644
+ }
645
+ }
646
+ return { ok: true, result: value };
647
+ }
648
+
649
+ function encodeChunk(value: unknown): Uint8Array {
650
+ if (value instanceof Uint8Array) {
651
+ return value;
652
+ }
653
+ if (typeof value === "string") {
654
+ return new TextEncoder().encode(value);
655
+ }
656
+ return new TextEncoder().encode(JSON.stringify(value));
657
+ }
658
+
659
+ function streamFrom(body: unknown): ReadableStream<Uint8Array> {
660
+ const chunks = Array.isArray(body)
661
+ ? body.map(encodeChunk)
662
+ : [encodeChunk(body)];
663
+ return new ReadableStream<Uint8Array>({
664
+ start(controller) {
665
+ for (const chunk of chunks) {
666
+ controller.enqueue(chunk);
667
+ }
668
+ controller.close();
669
+ },
670
+ });
671
+ }
672
+
673
+ async function fakeCliIpcCall(
674
+ method: string,
675
+ params?: Record<string, unknown>,
676
+ options?: {
677
+ timeoutMs?: number;
678
+ signal?: AbortSignal;
679
+ cancelOnDisconnect?: boolean;
680
+ },
681
+ ): Promise<Record<string, unknown>> {
682
+ if (options?.signal?.aborted) {
683
+ throw options.signal.reason ?? new DOMException("Aborted", "AbortError");
684
+ }
685
+ const value = cliChannel.dispatch({ method, params });
686
+ return normalizeCliResponse(value);
687
+ }
688
+
689
+ async function fakeCliIpcCallBinary(
690
+ method: string,
691
+ params?: Record<string, unknown>,
692
+ options?: { timeoutMs?: number; signal?: AbortSignal },
693
+ ): Promise<Record<string, unknown>> {
694
+ if (options?.signal?.aborted) {
695
+ throw options.signal.reason ?? new DOMException("Aborted", "AbortError");
696
+ }
697
+ const value = cliChannel.dispatch({ method, params });
698
+ if (value instanceof Uint8Array) {
699
+ return { ok: true, headers: {}, bytes: value };
700
+ }
701
+ if (isRecord(value) && "bytes" in value) {
702
+ return {
703
+ ok: true,
704
+ headers: isRecord(value.headers) ? value.headers : {},
705
+ bytes: value.bytes,
706
+ };
707
+ }
708
+ return normalizeCliResponse(value);
709
+ }
710
+
711
+ async function fakeCliIpcCallStream(
712
+ method: string,
713
+ params?: Record<string, unknown>,
714
+ options?: { firstByteTimeoutMs?: number; signal?: AbortSignal },
715
+ ): Promise<Record<string, unknown>> {
716
+ if (options?.signal?.aborted) {
717
+ throw options.signal.reason ?? new DOMException("Aborted", "AbortError");
718
+ }
719
+ const value = cliChannel.dispatch({ method, params });
720
+ if (value instanceof Uint8Array || typeof value === "string") {
721
+ return { ok: true, headers: {}, body: streamFrom(value), abort: () => {} };
722
+ }
723
+ if (isRecord(value) && "body" in value) {
724
+ return {
725
+ ok: true,
726
+ headers: isRecord(value.headers) ? value.headers : {},
727
+ body: streamFrom(value.body),
728
+ abort: () => {},
729
+ };
730
+ }
731
+ return normalizeCliResponse(value);
732
+ }
733
+
734
+ // ---------------------------------------------------------------------------
735
+ // HTTP channel (globalThis.fetch)
736
+ // ---------------------------------------------------------------------------
737
+
738
+ export type HttpMatcher =
739
+ | string
740
+ | RegExp
741
+ | { method?: string; url?: string; path?: string; body?: unknown }
742
+ | ((req: HttpRequestRecord) => boolean);
743
+
744
+ function compileHttpMatcher(
745
+ matcher: unknown,
746
+ ): CompiledMatcher<HttpRequestRecord> {
747
+ if (typeof matcher === "string") {
748
+ return { match: (req) => req.url.includes(matcher), describe: matcher };
749
+ }
750
+ if (matcher instanceof RegExp) {
751
+ return {
752
+ match: (req) => matcher.test(req.url),
753
+ describe: String(matcher),
754
+ };
755
+ }
756
+ if (typeof matcher === "function") {
757
+ return { match: (req) => matcher(req), describe: "(predicate)" };
758
+ }
759
+ const spec = isRecord(matcher) ? matcher : {};
760
+ const method =
761
+ typeof spec.method === "string" ? spec.method.toUpperCase() : undefined;
762
+ const url = typeof spec.url === "string" ? spec.url : undefined;
763
+ const path = typeof spec.path === "string" ? spec.path : undefined;
764
+ const body = spec.body;
765
+ return {
766
+ match: (req) =>
767
+ (method === undefined || req.method === method) &&
768
+ (url === undefined || req.url.includes(url)) &&
769
+ (path === undefined || req.url.includes(path)) &&
770
+ (body === undefined ||
771
+ (req.body !== undefined && deepMatches(body, req.body))),
772
+ describe: JSON.stringify(matcher),
773
+ };
774
+ }
775
+
776
+ function describeHttpRequest(req: HttpRequestRecord): string {
777
+ return `${req.method} ${req.url}`;
778
+ }
779
+
780
+ function headersToRecord(
781
+ headers: HeadersInit | undefined,
782
+ ): Record<string, string> {
783
+ if (headers === undefined) {
784
+ return {};
785
+ }
786
+ if (headers instanceof Headers) {
787
+ return Object.fromEntries(headers.entries());
788
+ }
789
+ if (Array.isArray(headers)) {
790
+ const record: Record<string, string> = {};
791
+ for (const entry of headers) {
792
+ const key = entry[0];
793
+ const value = entry[1];
794
+ if (key !== undefined && value !== undefined) {
795
+ record[key] = value;
796
+ }
797
+ }
798
+ return record;
799
+ }
800
+ return { ...headers };
801
+ }
802
+
803
+ function toHttpRequestRecord(
804
+ input: RequestInfo | URL,
805
+ init: RequestInit | undefined,
806
+ ): HttpRequestRecord {
807
+ const url = input instanceof Request ? input.url : String(input);
808
+ const method = (
809
+ init?.method ?? (input instanceof Request ? input.method : "GET")
810
+ ).toUpperCase();
811
+ const headers = headersToRecord(
812
+ init?.headers ?? (input instanceof Request ? input.headers : undefined),
813
+ );
814
+ const rawBody = init?.body;
815
+ let body: unknown;
816
+ if (typeof rawBody === "string") {
817
+ try {
818
+ body = JSON.parse(rawBody);
819
+ } catch {
820
+ body = rawBody;
821
+ }
822
+ } else if (rawBody !== undefined) {
823
+ body = rawBody;
824
+ }
825
+ return { url, method, headers, body };
826
+ }
827
+
828
+ function isResponseEnvelope(value: Record<string, unknown>): boolean {
829
+ return (
830
+ typeof value.status === "number" || "body" in value || "headers" in value
831
+ );
832
+ }
833
+
834
+ function toResponse(value: unknown): Response {
835
+ if (value instanceof Response) {
836
+ return value;
837
+ }
838
+ if (isRecord(value) && isResponseEnvelope(value)) {
839
+ const status = typeof value.status === "number" ? value.status : 200;
840
+ const headers: Record<string, string> = {
841
+ "Content-Type": "application/json",
842
+ };
843
+ if (isRecord(value.headers)) {
844
+ for (const [key, headerValue] of Object.entries(value.headers)) {
845
+ headers[key] = String(headerValue);
846
+ }
847
+ }
848
+ const payload = "body" in value ? value.body : undefined;
849
+ const text =
850
+ typeof payload === "string"
851
+ ? payload
852
+ : payload === undefined
853
+ ? "null"
854
+ : JSON.stringify(payload);
855
+ return new Response(text, { status, headers });
856
+ }
857
+ if (typeof value === "string") {
858
+ return new Response(value, { status: 200 });
859
+ }
860
+ return new Response(JSON.stringify(value ?? null), {
861
+ status: 200,
862
+ headers: { "Content-Type": "application/json" },
863
+ });
864
+ }
865
+
866
+ let httpChannel: MockChannel<HttpRequestRecord> | undefined;
867
+ let originalFetch: typeof globalThis.fetch | undefined;
868
+
869
+ const mockedFetch = Object.assign(
870
+ async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {
871
+ const channel = httpChannel;
872
+ const real = originalFetch;
873
+ if (channel === undefined || real === undefined) {
874
+ throw new Error(
875
+ "mockHttp() channel is not active — did resetRequestMockChannels() run mid-test?",
876
+ );
877
+ }
878
+ const value = channel.dispatch(toHttpRequestRecord(input, init));
879
+ return toResponse(value);
880
+ },
881
+ { preconnect: () => {} },
882
+ );
883
+
884
+ function filterHttpCalls(
885
+ channel: MockChannel<HttpRequestRecord>,
886
+ method: string | undefined,
887
+ ): HttpRequestRecord[] {
888
+ const history = channel.history();
889
+ if (method === undefined) {
890
+ return [...history];
891
+ }
892
+ const upper = method.toUpperCase();
893
+ return history.filter((req) => req.method === upper);
894
+ }
895
+
896
+ export interface HttpMockController {
897
+ /** Register a response for matching requests. Newest registration wins. */
898
+ on(matcher: HttpMatcher, response: MockResponse<HttpRequestRecord>): void;
899
+ on(
900
+ method: string,
901
+ url: string,
902
+ response: MockResponse<HttpRequestRecord>,
903
+ ): void;
904
+ calls(method?: string): HttpRequestRecord[];
905
+ callCount(method?: string): number;
906
+ lastCall(method?: string): HttpRequestRecord | undefined;
907
+ }
908
+
909
+ /** Mock HTTP at the `globalThis.fetch` boundary. Restored on channel reset. */
910
+ export function mockHttp(): HttpMockController {
911
+ if (httpChannel === undefined) {
912
+ httpChannel = new MockChannel<HttpRequestRecord>(
913
+ compileHttpMatcher,
914
+ describeHttpRequest,
915
+ );
916
+ }
917
+ if (originalFetch === undefined) {
918
+ originalFetch = globalThis.fetch;
919
+ globalThis.fetch = mockedFetch;
920
+ }
921
+ const channel = httpChannel;
922
+ return {
923
+ on: (
924
+ ...args:
925
+ | [matcher: HttpMatcher, response: MockResponse<HttpRequestRecord>]
926
+ | [
927
+ method: string,
928
+ url: string,
929
+ response: MockResponse<HttpRequestRecord>,
930
+ ]
931
+ ) => {
932
+ if (args.length === 3) {
933
+ channel.on({ method: args[0], url: args[1] }, args[2]);
934
+ return;
935
+ }
936
+ channel.on(args[0], args[1]);
937
+ },
938
+ calls: (method) => filterHttpCalls(channel, method),
939
+ callCount: (method) => filterHttpCalls(channel, method).length,
940
+ lastCall: (method) => {
941
+ const list = filterHttpCalls(channel, method);
942
+ return list[list.length - 1];
943
+ },
944
+ };
945
+ }
946
+
947
+ // ---------------------------------------------------------------------------
948
+ // Lifecycle
949
+ // ---------------------------------------------------------------------------
950
+
951
+ /**
952
+ * Clear every requests-mock channel and restore the real fetch. Registered
953
+ * once as a global `afterEach` in test-preload.ts — per-test isolation is
954
+ * automatic; tests never call this themselves.
955
+ */
956
+ export function resetRequestMockChannels(): void {
957
+ cliChannel.reset();
958
+ gatewayChannel.reset();
959
+ gatewayDefaults = {};
960
+ gatewayConnectError = false;
961
+ gatewayConnectErrorCode = undefined;
962
+ gatewayFailFirstN = 0;
963
+ gatewayFailFirstNIpcCallError = false;
964
+ for (const key of Object.keys(gatewayPersistentCallCounts)) {
965
+ delete gatewayPersistentCallCounts[key];
966
+ }
967
+ if (originalFetch !== undefined) {
968
+ globalThis.fetch = originalFetch;
969
+ originalFetch = undefined;
970
+ }
971
+ httpChannel = undefined;
972
+ }