oysterun 1.5.7-beta.8 → 1.5.7

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 (477) hide show
  1. package/bin/oysterun.mjs +25 -1
  2. package/dev/client/connectivity/internal-connectivity-status.d.mts +10 -2
  3. package/dev/client/connectivity/internal-connectivity-status.mjs +17 -6
  4. package/dev/client/connectivity/managed-host-browser.d.mts +19 -3
  5. package/dev/client/connectivity/managed-host-browser.mjs +323 -24
  6. package/dev/client/web/index.html +1490 -393
  7. package/dev/client/web-chat/dist/assets/{ReactPrism-BVwTeJ2J.js → ReactPrism-C_qvQuWU.js} +1 -1
  8. package/dev/client/web-chat/dist/assets/{ReactPrism-BVwTeJ2J.js.map → ReactPrism-C_qvQuWU.js.map} +1 -1
  9. package/dev/client/web-chat/dist/assets/{index-DyTV0z1z.css → index-1o8_vyRd.css} +1 -1
  10. package/dev/client/web-chat/dist/assets/{index-BIJqUapL.js → index-B44MyL7f.js} +2 -2
  11. package/dev/client/web-chat/dist/assets/index-B44MyL7f.js.map +1 -0
  12. package/dev/client/web-chat/dist/assets/{index-B0-fm02U.js → index-BgxQAT-U.js} +90 -90
  13. package/dev/client/web-chat/dist/assets/index-BgxQAT-U.js.map +1 -0
  14. package/dev/client/web-chat/dist/assets/{index-Bcsmmpmp.js → index-DdoJ_noi.js} +1 -1
  15. package/dev/client/web-chat/dist/assets/{index-Bcsmmpmp.js.map → index-DdoJ_noi.js.map} +1 -1
  16. package/dev/client/web-chat/dist/assets/{pdf-Dx9dlfRj.js → pdf-DgSk769O.js} +3 -3
  17. package/dev/client/web-chat/dist/assets/pdf-DgSk769O.js.map +1 -0
  18. package/dev/client/web-chat/dist/assets/{web-Ql5RPS3a.js → web-CIst0rFB.js} +1 -1
  19. package/dev/client/web-chat/dist/assets/{web-Ql5RPS3a.js.map → web-CIst0rFB.js.map} +1 -1
  20. package/dev/client/web-chat/dist/assets/{web-CNSm9WCL.js → web-D3DR1arO.js} +1 -1
  21. package/dev/client/web-chat/dist/assets/{web-CNSm9WCL.js.map → web-D3DR1arO.js.map} +1 -1
  22. package/dev/client/web-chat/dist/index.html +2 -2
  23. package/docs/routec/config_hierachy.md +132 -950
  24. package/docs/routec/dev/chat_local_link_annotation_pipeline.md +4 -0
  25. package/docs/routec/dev/cloud_deplyments.md +8 -0
  26. package/docs/routec/dev/host_update_runtime_identity.md +31 -0
  27. package/docs/routec/dev/node_runtime_startup.md +14 -3
  28. package/docs/routec/dev/npmjs_publish.md +36 -24
  29. package/docs/routec/dev/provider_command_resolution.md +11 -0
  30. package/docs/routec/form_UI_fields.md +287 -427
  31. package/docs/routec/host2_turn_started_idempotency_diagnostics.md +91 -105
  32. package/docs/routec/host_cloud_app_auth.md +102 -203
  33. package/docs/routec/host_owner_message_navigation.md +126 -93
  34. package/docs/routec/host_runtime_error_boundary.md +75 -60
  35. package/docs/routec/host_setup.md +155 -304
  36. package/docs/routec/hyperlink.md +91 -77
  37. package/docs/routec/hyperlink_rendering_mechanism.md +57 -315
  38. package/docs/routec/hyperlink_rendering_rule.md +89 -245
  39. package/docs/routec/large_tool_event_spillover.md +87 -38
  40. package/docs/routec/media_upload_image_compression.md +74 -65
  41. package/docs/routec/oysterun_operation_interface_spec.md +173 -650
  42. package/docs/routec/prev_page_map.md +101 -85
  43. package/docs/routec/provider_contract.md +153 -355
  44. package/docs/routec/skill_installation.md +128 -158
  45. package/docs/routec/tool_message_transfer_compression.md +43 -69
  46. package/host-service/adapters/claude-code-adapter.mjs +145 -5
  47. package/host-service/adapters/codex-app-server-adapter.mjs +34 -0
  48. package/host-service/agent-config.mjs +90 -22
  49. package/host-service/assets/product-skills/Oysterun/modules/oysterun-find-context/SKILL.md +15 -2
  50. package/host-service/assets/product-skills/Oysterun/modules/oysterun-scheduler/SKILL.md +5 -0
  51. package/host-service/assets/product-skills/Oysterun/modules/oysterun-session-chat/SKILL.md +134 -1
  52. package/host-service/assets/product-skills/Oysterun/modules/oysterun-sessions/SKILL.md +98 -2
  53. package/host-service/assets/product-skills/Oysterun/modules/oysterun-telegram/SKILL.md +18 -4
  54. package/host-service/assets/product-skills/Oysterun/modules/oysterun-website/SKILL.md +184 -21
  55. package/host-service/assets/product-skills/oysterun-find-context/SKILL.md +15 -2
  56. package/host-service/assets/product-skills/oysterun-scheduler/SKILL.md +5 -0
  57. package/host-service/assets/product-skills/oysterun-session-chat/SKILL.md +134 -1
  58. package/host-service/assets/product-skills/oysterun-sessions/SKILL.md +98 -2
  59. package/host-service/assets/product-skills/oysterun-telegram/SKILL.md +18 -4
  60. package/host-service/assets/product-skills/oysterun-website/SKILL.md +184 -21
  61. package/host-service/claude-acp-model-discovery.mjs +247 -6
  62. package/host-service/cli/assert-lifecycle-operation-available.mjs +117 -0
  63. package/host-service/cli/product-cli.mjs +140 -264
  64. package/host-service/cli/run-host-lifecycle.mjs +133 -0
  65. package/host-service/config.mjs +116 -26
  66. package/host-service/connectivity/cloud-retry-decision.mjs +57 -0
  67. package/host-service/connectivity/managed-tunnel-runtime-status.mjs +11 -0
  68. package/host-service/connectivity/retry-policy.json +9 -0
  69. package/host-service/connectivity/transport-usage-circuit-store.mjs +161 -0
  70. package/host-service/connectivity/webrtc-signaling-service.mjs +172 -33
  71. package/host-service/frp-agent.mjs +58 -0
  72. package/host-service/host-lifecycle-recovery.mjs +196 -0
  73. package/host-service/host-runtime-diagnostics.mjs +32 -0
  74. package/host-service/managed-identity-lifecycle.mjs +165 -0
  75. package/host-service/matrix-transcript-read-adapter.mjs +176 -0
  76. package/host-service/node-npm-runtime-identity.mjs +349 -7
  77. package/host-service/package.json +11 -2
  78. package/host-service/provider-registry.mjs +47 -0
  79. package/host-service/registered-update-authority.mjs +368 -0
  80. package/host-service/routec-matrix-storage-adapter.mjs +68 -4
  81. package/host-service/scheduler-setup-snapshot-contract.mjs +16 -2
  82. package/host-service/server.mjs +2761 -329
  83. package/host-service/session-history.mjs +3 -0
  84. package/host-service/session-manager.mjs +41 -4
  85. package/host-service/session-profile-runtime.mjs +54 -0
  86. package/host-service/setup.mjs +155 -82
  87. package/host-service/telegram-adapter.mjs +33 -0
  88. package/host-service/telegram-bridge.mjs +673 -190
  89. package/host-service/templates/agent-site/index.html +17 -1
  90. package/host-service/update-reminder-state.mjs +353 -0
  91. package/host-service/website-canonical-url.mjs +220 -0
  92. package/package.json +6 -1
  93. package/static/site/404/en/index.html +75 -0
  94. package/static/site/404/zh/index.html +75 -0
  95. package/static/site/assets/site.css +489 -0
  96. package/static/site/blog/en/index.html +92 -0
  97. package/static/site/blog/en/index.md +9 -0
  98. package/static/site/blog/generated_manifest.json +22 -10
  99. package/static/site/blog/index.html +18 -55
  100. package/static/site/blog/voice-input-model-experiment/en/index.html +55 -18
  101. package/static/site/blog/voice-input-model-experiment/en/index.md +1211 -0
  102. package/static/site/blog/voice-input-model-experiment/zh/index.html +59 -92
  103. package/static/site/blog/voice-input-model-experiment/zh/index.md +1220 -0
  104. package/static/site/blog/zh/index.html +92 -0
  105. package/static/site/blog/zh/index.md +9 -0
  106. package/static/site/docs/choose-and-recover-a-provider/assets/article.css +104 -0
  107. package/static/site/docs/choose-and-recover-a-provider/assets/codex-login-required.png +0 -0
  108. package/static/site/docs/choose-and-recover-a-provider/assets/codex-recovered.png +0 -0
  109. package/static/site/docs/choose-and-recover-a-provider/assets/publication/provider-command-unavailable.png +0 -0
  110. package/static/site/docs/choose-and-recover-a-provider/assets/publication/provider-login-required.png +0 -0
  111. package/static/site/docs/choose-and-recover-a-provider/assets/publication/provider-ready-after-restart.png +0 -0
  112. package/static/site/docs/choose-and-recover-a-provider/assets/publication/provider-refresh-ready.png +0 -0
  113. package/static/site/docs/choose-and-recover-a-provider/assets/publication/provider-restart-menu.png +0 -0
  114. package/static/site/docs/choose-and-recover-a-provider/assets/publication-screenshots.json +150 -0
  115. package/static/site/docs/choose-and-recover-a-provider/en/index.html +474 -0
  116. package/static/site/docs/choose-and-recover-a-provider/en/index.md +174 -0
  117. package/static/site/docs/choose-and-recover-a-provider/zh/index.html +474 -0
  118. package/static/site/docs/choose-and-recover-a-provider/zh/index.md +174 -0
  119. package/static/site/docs/configure-session-files-and-settings/assets/article.css +92 -0
  120. package/static/site/docs/configure-session-files-and-settings/assets/publication/folder-picker-focused.png +0 -0
  121. package/static/site/docs/configure-session-files-and-settings/assets/publication/session-profile-root.png +0 -0
  122. package/static/site/docs/configure-session-files-and-settings/assets/publication/session-setup-confirmed.png +0 -0
  123. package/static/site/docs/configure-session-files-and-settings/assets/publication-screenshots.json +100 -0
  124. package/static/site/docs/configure-session-files-and-settings/en/index.html +456 -0
  125. package/static/site/docs/configure-session-files-and-settings/en/index.md +130 -0
  126. package/static/site/docs/configure-session-files-and-settings/zh/index.html +456 -0
  127. package/static/site/docs/configure-session-files-and-settings/zh/index.md +132 -0
  128. package/static/site/docs/en/index.html +174 -0
  129. package/static/site/docs/en/index.md +31 -0
  130. package/static/site/docs/generated_manifest.json +720 -0
  131. package/static/site/docs/host-authentication-and-connection/assets/article.css +80 -0
  132. package/static/site/docs/host-authentication-and-connection/assets/publication/invalid-credentials-empty-password.png +0 -0
  133. package/static/site/docs/host-authentication-and-connection/assets/publication/password-sign-in.png +0 -0
  134. package/static/site/docs/host-authentication-and-connection/assets/publication/sessions-connected-direct-host.png +0 -0
  135. package/static/site/docs/host-authentication-and-connection/assets/publication-screenshots.json +100 -0
  136. package/static/site/docs/host-authentication-and-connection/en/index.html +429 -0
  137. package/static/site/docs/host-authentication-and-connection/en/index.md +108 -0
  138. package/static/site/docs/host-authentication-and-connection/zh/index.html +429 -0
  139. package/static/site/docs/host-authentication-and-connection/zh/index.md +110 -0
  140. package/static/site/docs/index.html +28 -0
  141. package/static/site/docs/install-and-use-a-skill/assets/article.css +141 -0
  142. package/static/site/docs/install-and-use-a-skill/assets/publication/skill-helper-draft.jpg +0 -0
  143. package/static/site/docs/install-and-use-a-skill/assets/publication/skill-read-only-result.jpg +0 -0
  144. package/static/site/docs/install-and-use-a-skill/assets/publication/skill-state-menu.jpg +0 -0
  145. package/static/site/docs/install-and-use-a-skill/assets/publication/skill-update-result.jpg +0 -0
  146. package/static/site/docs/install-and-use-a-skill/assets/publication/update-result.png +0 -0
  147. package/static/site/docs/install-and-use-a-skill/assets/publication-screenshots.json +122 -0
  148. package/static/site/docs/install-and-use-a-skill/en/index.html +484 -0
  149. package/static/site/docs/install-and-use-a-skill/en/index.md +233 -0
  150. package/static/site/docs/install-and-use-a-skill/zh/index.html +484 -0
  151. package/static/site/docs/install-and-use-a-skill/zh/index.md +233 -0
  152. package/static/site/docs/llms.txt +40 -0
  153. package/static/site/docs/read-large-tool-results/assets/article.css +132 -0
  154. package/static/site/docs/read-large-tool-results/assets/publication/oversized-result.jpg +0 -0
  155. package/static/site/docs/read-large-tool-results/assets/publication/tool-detail-page-two.jpg +0 -0
  156. package/static/site/docs/read-large-tool-results/assets/publication/tool-row-after-close.jpg +0 -0
  157. package/static/site/docs/read-large-tool-results/assets/publication/tool-row-view-details.jpg +0 -0
  158. package/static/site/docs/read-large-tool-results/assets/publication-screenshots.json +130 -0
  159. package/static/site/docs/read-large-tool-results/en/index.html +443 -0
  160. package/static/site/docs/read-large-tool-results/en/index.md +176 -0
  161. package/static/site/docs/read-large-tool-results/zh/index.html +443 -0
  162. package/static/site/docs/read-large-tool-results/zh/index.md +176 -0
  163. package/static/site/docs/recover-from-a-host-runtime-error/assets/article.css +104 -0
  164. package/static/site/docs/recover-from-a-host-runtime-error/assets/publication/recovered-chat.png +0 -0
  165. package/static/site/docs/recover-from-a-host-runtime-error/assets/publication/runtime-error.png +0 -0
  166. package/static/site/docs/recover-from-a-host-runtime-error/assets/publication-screenshots.json +70 -0
  167. package/static/site/docs/recover-from-a-host-runtime-error/en/index.html +453 -0
  168. package/static/site/docs/recover-from-a-host-runtime-error/en/index.md +142 -0
  169. package/static/site/docs/recover-from-a-host-runtime-error/zh/index.html +453 -0
  170. package/static/site/docs/recover-from-a-host-runtime-error/zh/index.md +142 -0
  171. package/static/site/docs/restore-work-after-a-host-restart/assets/article.css +63 -0
  172. package/static/site/docs/restore-work-after-a-host-restart/assets/publication/loop-disabled-after-restart.png +0 -0
  173. package/static/site/docs/restore-work-after-a-host-restart/assets/publication/restart-control.png +0 -0
  174. package/static/site/docs/restore-work-after-a-host-restart/assets/publication/restart-ready-sign-in.png +0 -0
  175. package/static/site/docs/restore-work-after-a-host-restart/assets/publication/restored-checkpoint.png +0 -0
  176. package/static/site/docs/restore-work-after-a-host-restart/assets/publication-screenshots.json +130 -0
  177. package/static/site/docs/restore-work-after-a-host-restart/en/index.html +444 -0
  178. package/static/site/docs/restore-work-after-a-host-restart/en/index.md +110 -0
  179. package/static/site/docs/restore-work-after-a-host-restart/zh/index.html +444 -0
  180. package/static/site/docs/restore-work-after-a-host-restart/zh/index.md +110 -0
  181. package/static/site/docs/search-index.json +273 -0
  182. package/static/site/docs/send-images-and-media/assets/article.css +132 -0
  183. package/static/site/docs/send-images-and-media/assets/publication/safe-image-viewer.jpg +0 -0
  184. package/static/site/docs/send-images-and-media/assets/publication/sent-ordered-group.jpg +0 -0
  185. package/static/site/docs/send-images-and-media/assets/publication/staged-ordered-group.jpg +0 -0
  186. package/static/site/docs/send-images-and-media/assets/publication-screenshots.json +100 -0
  187. package/static/site/docs/send-images-and-media/en/index.html +468 -0
  188. package/static/site/docs/send-images-and-media/en/index.md +152 -0
  189. package/static/site/docs/send-images-and-media/zh/index.html +468 -0
  190. package/static/site/docs/send-images-and-media/zh/index.md +152 -0
  191. package/static/site/docs/set-up-and-understand-a-host/assets/article.css +104 -0
  192. package/static/site/docs/set-up-and-understand-a-host/assets/publication/host-identity-browse-root.png +0 -0
  193. package/static/site/docs/set-up-and-understand-a-host/assets/publication/host-setup-managed-ready.png +0 -0
  194. package/static/site/docs/set-up-and-understand-a-host/assets/publication/host-setup-seven-steps.png +0 -0
  195. package/static/site/docs/set-up-and-understand-a-host/assets/publication/session-profile-identity.png +0 -0
  196. package/static/site/docs/set-up-and-understand-a-host/assets/publication/session-setup-identity.png +0 -0
  197. package/static/site/docs/set-up-and-understand-a-host/assets/publication/website-link.png +0 -0
  198. package/static/site/docs/set-up-and-understand-a-host/assets/publication-screenshots.json +178 -0
  199. package/static/site/docs/set-up-and-understand-a-host/en/index.html +519 -0
  200. package/static/site/docs/set-up-and-understand-a-host/en/index.md +211 -0
  201. package/static/site/docs/set-up-and-understand-a-host/zh/index.html +519 -0
  202. package/static/site/docs/set-up-and-understand-a-host/zh/index.md +211 -0
  203. package/static/site/docs/understand-agent-activity/assets/article.css +154 -0
  204. package/static/site/docs/understand-agent-activity/assets/publication/session-available.png +0 -0
  205. package/static/site/docs/understand-agent-activity/assets/publication/turn-occupied.png +0 -0
  206. package/static/site/docs/understand-agent-activity/assets/publication/turn-terminal.png +0 -0
  207. package/static/site/docs/understand-agent-activity/assets/publication-screenshots.json +100 -0
  208. package/static/site/docs/understand-agent-activity/en/index.html +441 -0
  209. package/static/site/docs/understand-agent-activity/en/index.md +146 -0
  210. package/static/site/docs/understand-agent-activity/zh/index.html +441 -0
  211. package/static/site/docs/understand-agent-activity/zh/index.md +146 -0
  212. package/static/site/docs/use-the-oysterun-cli-safely/assets/article.css +138 -0
  213. package/static/site/docs/use-the-oysterun-cli-safely/assets/publication/cli-post-status.jpg +0 -0
  214. package/static/site/docs/use-the-oysterun-cli-safely/assets/publication/cli-protected-dry-run.jpg +0 -0
  215. package/static/site/docs/use-the-oysterun-cli-safely/assets/publication/cli-supported-modules.jpg +0 -0
  216. package/static/site/docs/use-the-oysterun-cli-safely/assets/publication/cli-target-read.jpg +0 -0
  217. package/static/site/docs/use-the-oysterun-cli-safely/assets/publication-screenshots.json +122 -0
  218. package/static/site/docs/use-the-oysterun-cli-safely/en/index.html +499 -0
  219. package/static/site/docs/use-the-oysterun-cli-safely/en/index.md +548 -0
  220. package/static/site/docs/use-the-oysterun-cli-safely/zh/index.html +499 -0
  221. package/static/site/docs/use-the-oysterun-cli-safely/zh/index.md +548 -0
  222. package/static/site/docs/zh/index.html +174 -0
  223. package/static/site/docs/zh/index.md +31 -0
  224. package/static/site/en/index.html +227 -0
  225. package/static/site/en/index.md +33 -0
  226. package/static/site/faq/en/index.html +116 -0
  227. package/static/site/faq/en/index.md +33 -0
  228. package/static/site/faq/index.html +28 -0
  229. package/static/site/faq/zh/index.html +116 -0
  230. package/static/site/faq/zh/index.md +33 -0
  231. package/static/site/getting-started/en/index.html +131 -0
  232. package/static/site/getting-started/en/index.md +18 -0
  233. package/static/site/getting-started/index.html +28 -0
  234. package/static/site/getting-started/zh/index.html +131 -0
  235. package/static/site/getting-started/zh/index.md +18 -0
  236. package/static/site/index.html +14 -1187
  237. package/static/site/llms.txt +25 -0
  238. package/static/site/overview/en/index.html +87 -0
  239. package/static/site/overview/en/index.md +36 -0
  240. package/static/site/overview/index.html +28 -0
  241. package/static/site/overview/zh/index.html +87 -0
  242. package/static/site/overview/zh/index.md +36 -0
  243. package/static/site/privacy/en/index.html +124 -0
  244. package/static/site/privacy/en/index.md +45 -0
  245. package/static/site/privacy/index.html +18 -171
  246. package/static/site/privacy/zh/index.html +124 -0
  247. package/static/site/privacy/zh/index.md +45 -0
  248. package/static/site/robots.txt +3 -0
  249. package/static/site/sitemap.xml +193 -0
  250. package/static/site/zh/index.html +227 -0
  251. package/static/site/zh/index.md +33 -0
  252. package/static/site_source/content/AGENTS.md +9 -2
  253. package/static/site_source/content/blog/published/voice-input-model-experiment/zh/article.html +0 -70
  254. package/static/site_source/content/tutorials/drafts/build-a-website-with-natural-language/assets/article.css +92 -0
  255. package/static/site_source/content/tutorials/drafts/build-a-website-with-natural-language/assets/build-complete.png +0 -0
  256. package/static/site_source/content/tutorials/drafts/build-a-website-with-natural-language/assets/cover.svg +39 -0
  257. package/static/site_source/content/tutorials/drafts/build-a-website-with-natural-language/assets/empty-project.png +0 -0
  258. package/static/site_source/content/tutorials/drafts/build-a-website-with-natural-language/assets/natural-language-prompt.png +0 -0
  259. package/static/site_source/content/tutorials/drafts/build-a-website-with-natural-language/assets/web-catalog-owner-only.png +0 -0
  260. package/static/site_source/content/tutorials/drafts/build-a-website-with-natural-language/assets/website-result.png +0 -0
  261. package/static/site_source/content/tutorials/drafts/build-a-website-with-natural-language/content.json +33 -0
  262. package/static/site_source/content/tutorials/drafts/build-a-website-with-natural-language/en/article.html +116 -0
  263. package/static/site_source/content/tutorials/drafts/build-a-website-with-natural-language/zh/article.html +116 -0
  264. package/static/site_source/content/tutorials/drafts/find-and-return-to-a-message/assets/article.css +87 -0
  265. package/static/site_source/content/tutorials/drafts/find-and-return-to-a-message/assets/cover.svg +41 -0
  266. package/static/site_source/content/tutorials/drafts/find-and-return-to-a-message/assets/publication/previous-result.png +0 -0
  267. package/static/site_source/content/tutorials/drafts/find-and-return-to-a-message/assets/publication/returned-source.png +0 -0
  268. package/static/site_source/content/tutorials/drafts/find-and-return-to-a-message/assets/publication/source-message.png +0 -0
  269. package/static/site_source/content/tutorials/drafts/find-and-return-to-a-message/assets/publication-screenshots.json +100 -0
  270. package/static/site_source/content/tutorials/drafts/find-and-return-to-a-message/content.json +34 -0
  271. package/static/site_source/content/tutorials/drafts/find-and-return-to-a-message/en/article.html +91 -0
  272. package/static/site_source/content/tutorials/drafts/find-and-return-to-a-message/zh/article.html +91 -0
  273. package/static/site_source/content/tutorials/drafts/follow-live-chat-output/assets/article.css +87 -0
  274. package/static/site_source/content/tutorials/drafts/follow-live-chat-output/assets/cover.svg +55 -0
  275. package/static/site_source/content/tutorials/drafts/follow-live-chat-output/assets/publication/jump-to-latest.png +0 -0
  276. package/static/site_source/content/tutorials/drafts/follow-live-chat-output/assets/publication/live-output-arriving.png +0 -0
  277. package/static/site_source/content/tutorials/drafts/follow-live-chat-output/assets/publication/older-position-stable.png +0 -0
  278. package/static/site_source/content/tutorials/drafts/follow-live-chat-output/assets/publication-screenshots.json +100 -0
  279. package/static/site_source/content/tutorials/drafts/follow-live-chat-output/content.json +34 -0
  280. package/static/site_source/content/tutorials/drafts/follow-live-chat-output/en/article.html +91 -0
  281. package/static/site_source/content/tutorials/drafts/follow-live-chat-output/zh/article.html +91 -0
  282. package/static/site_source/content/tutorials/drafts/getting-started/assets/article.css +50 -0
  283. package/static/site_source/content/tutorials/drafts/getting-started/content.json +10 -4
  284. package/static/site_source/content/tutorials/drafts/getting-started/en/article.html +109 -132
  285. package/static/site_source/content/tutorials/drafts/getting-started/zh/article.html +120 -0
  286. package/static/site_source/content/tutorials/drafts/open-links-safely/assets/article.css +91 -0
  287. package/static/site_source/content/tutorials/drafts/open-links-safely/assets/cover.svg +48 -0
  288. package/static/site_source/content/tutorials/drafts/open-links-safely/assets/publication/file-preview-safe.png +0 -0
  289. package/static/site_source/content/tutorials/drafts/open-links-safely/assets/publication/local-link-confirmed.png +0 -0
  290. package/static/site_source/content/tutorials/drafts/open-links-safely/assets/publication/returned-source-session.png +0 -0
  291. package/static/site_source/content/tutorials/drafts/open-links-safely/assets/publication/source-links.png +0 -0
  292. package/static/site_source/content/tutorials/drafts/open-links-safely/assets/publication-screenshots.json +130 -0
  293. package/static/site_source/content/tutorials/drafts/open-links-safely/content.json +34 -0
  294. package/static/site_source/content/tutorials/drafts/open-links-safely/en/article.html +111 -0
  295. package/static/site_source/content/tutorials/drafts/open-links-safely/zh/article.html +111 -0
  296. package/static/site_source/content/tutorials/drafts/pin-and-return-to-messages/assets/article.css +87 -0
  297. package/static/site_source/content/tutorials/drafts/pin-and-return-to-messages/assets/cover.svg +53 -0
  298. package/static/site_source/content/tutorials/drafts/pin-and-return-to-messages/assets/publication/pin-menu.png +0 -0
  299. package/static/site_source/content/tutorials/drafts/pin-and-return-to-messages/assets/publication/pinned-focus.png +0 -0
  300. package/static/site_source/content/tutorials/drafts/pin-and-return-to-messages/assets/publication/pinned-list.png +0 -0
  301. package/static/site_source/content/tutorials/drafts/pin-and-return-to-messages/assets/publication/previous-page.png +0 -0
  302. package/static/site_source/content/tutorials/drafts/pin-and-return-to-messages/assets/publication-screenshots.json +130 -0
  303. package/static/site_source/content/tutorials/drafts/pin-and-return-to-messages/content.json +34 -0
  304. package/static/site_source/content/tutorials/drafts/pin-and-return-to-messages/en/article.html +123 -0
  305. package/static/site_source/content/tutorials/drafts/pin-and-return-to-messages/zh/article.html +123 -0
  306. package/static/site_source/content/tutorials/drafts/recover-delayed-chat-sync/assets/article.css +87 -0
  307. package/static/site_source/content/tutorials/drafts/recover-delayed-chat-sync/assets/cover.svg +50 -0
  308. package/static/site_source/content/tutorials/drafts/recover-delayed-chat-sync/assets/publication/connection-lost.png +0 -0
  309. package/static/site_source/content/tutorials/drafts/recover-delayed-chat-sync/assets/publication/reconnecting.png +0 -0
  310. package/static/site_source/content/tutorials/drafts/recover-delayed-chat-sync/assets/publication/recovered.png +0 -0
  311. package/static/site_source/content/tutorials/drafts/recover-delayed-chat-sync/assets/publication-screenshots.json +94 -0
  312. package/static/site_source/content/tutorials/drafts/recover-delayed-chat-sync/content.json +34 -0
  313. package/static/site_source/content/tutorials/drafts/recover-delayed-chat-sync/en/article.html +102 -0
  314. package/static/site_source/content/tutorials/drafts/recover-delayed-chat-sync/zh/article.html +102 -0
  315. package/static/site_source/content/tutorials/drafts/schedule-agent-work-with-natural-language/assets/article.css +92 -0
  316. package/static/site_source/content/tutorials/drafts/schedule-agent-work-with-natural-language/assets/cover.svg +39 -0
  317. package/static/site_source/content/tutorials/drafts/schedule-agent-work-with-natural-language/assets/empty-project.png +0 -0
  318. package/static/site_source/content/tutorials/drafts/schedule-agent-work-with-natural-language/assets/latest-report.png +0 -0
  319. package/static/site_source/content/tutorials/drafts/schedule-agent-work-with-natural-language/assets/natural-language-prompt.png +0 -0
  320. package/static/site_source/content/tutorials/drafts/schedule-agent-work-with-natural-language/assets/no-runs.png +0 -0
  321. package/static/site_source/content/tutorials/drafts/schedule-agent-work-with-natural-language/assets/run-history-pass.png +0 -0
  322. package/static/site_source/content/tutorials/drafts/schedule-agent-work-with-natural-language/assets/run-log.png +0 -0
  323. package/static/site_source/content/tutorials/drafts/schedule-agent-work-with-natural-language/assets/test-run-prompt.png +0 -0
  324. package/static/site_source/content/tutorials/drafts/schedule-agent-work-with-natural-language/content.json +33 -0
  325. package/static/site_source/content/tutorials/drafts/schedule-agent-work-with-natural-language/en/article.html +124 -0
  326. package/static/site_source/content/tutorials/drafts/schedule-agent-work-with-natural-language/zh/article.html +124 -0
  327. package/static/site_source/content/tutorials/drafts/write-markdown-in-chat/assets/article.css +105 -0
  328. package/static/site_source/content/tutorials/drafts/write-markdown-in-chat/assets/cover.svg +44 -0
  329. package/static/site_source/content/tutorials/drafts/write-markdown-in-chat/assets/publication/markdown-correction.png +0 -0
  330. package/static/site_source/content/tutorials/drafts/write-markdown-in-chat/assets/publication/markdown-rendered.png +0 -0
  331. package/static/site_source/content/tutorials/drafts/write-markdown-in-chat/assets/publication/markdown-source.png +0 -0
  332. package/static/site_source/content/tutorials/drafts/write-markdown-in-chat/assets/publication-screenshots.json +100 -0
  333. package/static/site_source/content/tutorials/drafts/write-markdown-in-chat/content.json +34 -0
  334. package/static/site_source/content/tutorials/drafts/write-markdown-in-chat/en/article.html +104 -0
  335. package/static/site_source/content/tutorials/drafts/write-markdown-in-chat/zh/article.html +104 -0
  336. package/static/site_source/content/tutorials/published/choose-and-recover-a-provider/assets/article.css +104 -0
  337. package/static/site_source/content/tutorials/published/choose-and-recover-a-provider/assets/codex-login-required.png +0 -0
  338. package/static/site_source/content/tutorials/published/choose-and-recover-a-provider/assets/codex-recovered.png +0 -0
  339. package/static/site_source/content/tutorials/published/choose-and-recover-a-provider/assets/publication/provider-command-unavailable.png +0 -0
  340. package/static/site_source/content/tutorials/published/choose-and-recover-a-provider/assets/publication/provider-login-required.png +0 -0
  341. package/static/site_source/content/tutorials/published/choose-and-recover-a-provider/assets/publication/provider-ready-after-restart.png +0 -0
  342. package/static/site_source/content/tutorials/published/choose-and-recover-a-provider/assets/publication/provider-refresh-ready.png +0 -0
  343. package/static/site_source/content/tutorials/published/choose-and-recover-a-provider/assets/publication/provider-restart-menu.png +0 -0
  344. package/static/site_source/content/tutorials/published/choose-and-recover-a-provider/assets/publication-screenshots.json +150 -0
  345. package/static/site_source/content/tutorials/published/choose-and-recover-a-provider/content.json +23 -0
  346. package/static/site_source/content/tutorials/published/choose-and-recover-a-provider/en/article.html +141 -0
  347. package/static/site_source/content/tutorials/published/choose-and-recover-a-provider/zh/article.html +141 -0
  348. package/static/site_source/content/tutorials/published/configure-session-files-and-settings/assets/article.css +92 -0
  349. package/static/site_source/content/tutorials/published/configure-session-files-and-settings/assets/publication/folder-picker-focused.png +0 -0
  350. package/static/site_source/content/tutorials/published/configure-session-files-and-settings/assets/publication/session-profile-root.png +0 -0
  351. package/static/site_source/content/tutorials/published/configure-session-files-and-settings/assets/publication/session-setup-confirmed.png +0 -0
  352. package/static/site_source/content/tutorials/published/configure-session-files-and-settings/assets/publication-screenshots.json +100 -0
  353. package/static/site_source/content/tutorials/published/configure-session-files-and-settings/content.json +23 -0
  354. package/static/site_source/content/tutorials/published/configure-session-files-and-settings/en/article.html +126 -0
  355. package/static/site_source/content/tutorials/published/configure-session-files-and-settings/zh/article.html +126 -0
  356. package/static/site_source/content/tutorials/published/host-authentication-and-connection/assets/article.css +80 -0
  357. package/static/site_source/content/tutorials/published/host-authentication-and-connection/assets/publication/invalid-credentials-empty-password.png +0 -0
  358. package/static/site_source/content/tutorials/published/host-authentication-and-connection/assets/publication/password-sign-in.png +0 -0
  359. package/static/site_source/content/tutorials/published/host-authentication-and-connection/assets/publication/sessions-connected-direct-host.png +0 -0
  360. package/static/site_source/content/tutorials/published/host-authentication-and-connection/assets/publication-screenshots.json +100 -0
  361. package/static/site_source/content/tutorials/published/host-authentication-and-connection/content.json +23 -0
  362. package/static/site_source/content/tutorials/published/host-authentication-and-connection/en/article.html +101 -0
  363. package/static/site_source/content/tutorials/published/host-authentication-and-connection/zh/article.html +101 -0
  364. package/static/site_source/content/tutorials/published/install-and-use-a-skill/assets/article.css +141 -0
  365. package/static/site_source/content/tutorials/published/install-and-use-a-skill/assets/cover.svg +59 -0
  366. package/static/site_source/content/tutorials/published/install-and-use-a-skill/assets/publication/skill-helper-draft.jpg +0 -0
  367. package/static/site_source/content/tutorials/published/install-and-use-a-skill/assets/publication/skill-read-only-result.jpg +0 -0
  368. package/static/site_source/content/tutorials/published/install-and-use-a-skill/assets/publication/skill-state-menu.jpg +0 -0
  369. package/static/site_source/content/tutorials/published/install-and-use-a-skill/assets/publication/skill-update-result.jpg +0 -0
  370. package/static/site_source/content/tutorials/published/install-and-use-a-skill/assets/publication/update-result.png +0 -0
  371. package/static/site_source/content/tutorials/published/install-and-use-a-skill/assets/publication-screenshots.json +122 -0
  372. package/static/site_source/content/tutorials/published/install-and-use-a-skill/content.json +34 -0
  373. package/static/site_source/content/tutorials/published/install-and-use-a-skill/en/article.html +155 -0
  374. package/static/site_source/content/tutorials/published/install-and-use-a-skill/zh/article.html +155 -0
  375. package/static/site_source/content/tutorials/published/read-large-tool-results/assets/article.css +132 -0
  376. package/static/site_source/content/tutorials/published/read-large-tool-results/assets/publication/oversized-result.jpg +0 -0
  377. package/static/site_source/content/tutorials/published/read-large-tool-results/assets/publication/tool-detail-page-two.jpg +0 -0
  378. package/static/site_source/content/tutorials/published/read-large-tool-results/assets/publication/tool-row-after-close.jpg +0 -0
  379. package/static/site_source/content/tutorials/published/read-large-tool-results/assets/publication/tool-row-view-details.jpg +0 -0
  380. package/static/site_source/content/tutorials/published/read-large-tool-results/assets/publication-screenshots.json +130 -0
  381. package/static/site_source/content/tutorials/published/read-large-tool-results/content.json +23 -0
  382. package/static/site_source/content/tutorials/published/read-large-tool-results/en/article.html +116 -0
  383. package/static/site_source/content/tutorials/published/read-large-tool-results/zh/article.html +116 -0
  384. package/static/site_source/content/tutorials/published/recover-from-a-host-runtime-error/assets/article.css +104 -0
  385. package/static/site_source/content/tutorials/published/recover-from-a-host-runtime-error/assets/publication/recovered-chat.png +0 -0
  386. package/static/site_source/content/tutorials/published/recover-from-a-host-runtime-error/assets/publication/runtime-error.png +0 -0
  387. package/static/site_source/content/tutorials/published/recover-from-a-host-runtime-error/assets/publication-screenshots.json +70 -0
  388. package/static/site_source/content/tutorials/published/recover-from-a-host-runtime-error/content.json +23 -0
  389. package/static/site_source/content/tutorials/published/recover-from-a-host-runtime-error/en/article.html +122 -0
  390. package/static/site_source/content/tutorials/published/recover-from-a-host-runtime-error/zh/article.html +122 -0
  391. package/static/site_source/content/tutorials/published/restore-work-after-a-host-restart/assets/article.css +63 -0
  392. package/static/site_source/content/tutorials/published/restore-work-after-a-host-restart/assets/publication/loop-disabled-after-restart.png +0 -0
  393. package/static/site_source/content/tutorials/published/restore-work-after-a-host-restart/assets/publication/restart-control.png +0 -0
  394. package/static/site_source/content/tutorials/published/restore-work-after-a-host-restart/assets/publication/restart-ready-sign-in.png +0 -0
  395. package/static/site_source/content/tutorials/published/restore-work-after-a-host-restart/assets/publication/restored-checkpoint.png +0 -0
  396. package/static/site_source/content/tutorials/published/restore-work-after-a-host-restart/assets/publication-screenshots.json +130 -0
  397. package/static/site_source/content/tutorials/published/restore-work-after-a-host-restart/content.json +23 -0
  398. package/static/site_source/content/tutorials/published/restore-work-after-a-host-restart/en/article.html +117 -0
  399. package/static/site_source/content/tutorials/published/restore-work-after-a-host-restart/zh/article.html +117 -0
  400. package/static/site_source/content/tutorials/published/send-images-and-media/assets/article.css +132 -0
  401. package/static/site_source/content/tutorials/published/send-images-and-media/assets/publication/safe-image-viewer.jpg +0 -0
  402. package/static/site_source/content/tutorials/published/send-images-and-media/assets/publication/sent-ordered-group.jpg +0 -0
  403. package/static/site_source/content/tutorials/published/send-images-and-media/assets/publication/staged-ordered-group.jpg +0 -0
  404. package/static/site_source/content/tutorials/published/send-images-and-media/assets/publication-screenshots.json +100 -0
  405. package/static/site_source/content/tutorials/published/send-images-and-media/content.json +23 -0
  406. package/static/site_source/content/tutorials/published/send-images-and-media/en/article.html +141 -0
  407. package/static/site_source/content/tutorials/published/send-images-and-media/zh/article.html +141 -0
  408. package/static/site_source/content/tutorials/published/set-up-and-understand-a-host/assets/article.css +104 -0
  409. package/static/site_source/content/tutorials/published/set-up-and-understand-a-host/assets/publication/host-identity-browse-root.png +0 -0
  410. package/static/site_source/content/tutorials/published/set-up-and-understand-a-host/assets/publication/host-setup-managed-ready.png +0 -0
  411. package/static/site_source/content/tutorials/published/set-up-and-understand-a-host/assets/publication/host-setup-seven-steps.png +0 -0
  412. package/static/site_source/content/tutorials/published/set-up-and-understand-a-host/assets/publication/session-profile-identity.png +0 -0
  413. package/static/site_source/content/tutorials/published/set-up-and-understand-a-host/assets/publication/session-setup-identity.png +0 -0
  414. package/static/site_source/content/tutorials/published/set-up-and-understand-a-host/assets/publication/website-link.png +0 -0
  415. package/static/site_source/content/tutorials/published/set-up-and-understand-a-host/assets/publication-screenshots.json +178 -0
  416. package/static/site_source/content/tutorials/published/set-up-and-understand-a-host/content.json +23 -0
  417. package/static/site_source/content/tutorials/published/set-up-and-understand-a-host/en/article.html +177 -0
  418. package/static/site_source/content/tutorials/published/set-up-and-understand-a-host/zh/article.html +177 -0
  419. package/static/site_source/content/tutorials/published/understand-agent-activity/assets/article.css +154 -0
  420. package/static/site_source/content/tutorials/published/understand-agent-activity/assets/publication/session-available.png +0 -0
  421. package/static/site_source/content/tutorials/published/understand-agent-activity/assets/publication/turn-occupied.png +0 -0
  422. package/static/site_source/content/tutorials/published/understand-agent-activity/assets/publication/turn-terminal.png +0 -0
  423. package/static/site_source/content/tutorials/published/understand-agent-activity/assets/publication-screenshots.json +100 -0
  424. package/static/site_source/content/tutorials/published/understand-agent-activity/content.json +23 -0
  425. package/static/site_source/content/tutorials/published/understand-agent-activity/en/article.html +114 -0
  426. package/static/site_source/content/tutorials/published/understand-agent-activity/zh/article.html +114 -0
  427. package/static/site_source/content/tutorials/published/use-the-oysterun-cli-safely/assets/article.css +138 -0
  428. package/static/site_source/content/tutorials/published/use-the-oysterun-cli-safely/assets/publication/cli-post-status.jpg +0 -0
  429. package/static/site_source/content/tutorials/published/use-the-oysterun-cli-safely/assets/publication/cli-protected-dry-run.jpg +0 -0
  430. package/static/site_source/content/tutorials/published/use-the-oysterun-cli-safely/assets/publication/cli-supported-modules.jpg +0 -0
  431. package/static/site_source/content/tutorials/published/use-the-oysterun-cli-safely/assets/publication/cli-target-read.jpg +0 -0
  432. package/static/site_source/content/tutorials/published/use-the-oysterun-cli-safely/assets/publication-screenshots.json +122 -0
  433. package/static/site_source/content/tutorials/published/use-the-oysterun-cli-safely/content.json +23 -0
  434. package/static/site_source/content/tutorials/published/use-the-oysterun-cli-safely/en/article.html +170 -0
  435. package/static/site_source/content/tutorials/published/use-the-oysterun-cli-safely/zh/article.html +170 -0
  436. package/static/site_source/manifests/docs_taxonomy.json +126 -0
  437. package/static/site_source/manifests/public_site.json +230 -0
  438. package/static/site_source/pages/blog/en.html +1 -0
  439. package/static/site_source/pages/blog/zh.html +1 -0
  440. package/static/site_source/pages/docs/en.html +1 -0
  441. package/static/site_source/pages/docs/zh.html +1 -0
  442. package/static/site_source/pages/faq/en.html +35 -0
  443. package/static/site_source/pages/faq/zh.html +35 -0
  444. package/static/site_source/pages/getting-started/en.html +50 -0
  445. package/static/site_source/pages/getting-started/zh.html +50 -0
  446. package/static/site_source/pages/home/en.html +19 -0
  447. package/static/site_source/pages/home/zh.html +19 -0
  448. package/static/site_source/pages/overview/en.html +6 -0
  449. package/static/site_source/pages/overview/zh.html +6 -0
  450. package/static/site_source/pages/privacy/en.html +43 -0
  451. package/static/site_source/pages/privacy/zh.html +43 -0
  452. package/static/site_source/shared/home_analytics.html +127 -0
  453. package/tool_scripts/install_oysterun_launch_agents.sh +57 -0
  454. package/tool_scripts/install_oysterun_update.mjs +76 -13
  455. package/tool_scripts/oysterun_npm_package_manifest.mjs +5 -0
  456. package/tool_scripts/oysterun_release_service.sh +119 -24
  457. package/tool_scripts/oysterun_service_common.sh +556 -23
  458. package/tool_scripts/oysterun_update_restart_runner.mjs +440 -17
  459. package/tool_scripts/preflight_oysterun_restart.sh +45 -0
  460. package/tool_scripts/restart_oysterun.sh +43 -2
  461. package/tool_scripts/run_oysterun_host.sh +15 -5
  462. package/tool_scripts/start_oysterun.sh +15 -5
  463. package/dev/client/web-chat/dist/assets/index-B0-fm02U.js.map +0 -1
  464. package/dev/client/web-chat/dist/assets/index-BIJqUapL.js.map +0 -1
  465. package/dev/client/web-chat/dist/assets/pdf-Dx9dlfRj.js.map +0 -1
  466. package/static/site/content/blog/drafts/20260718-24hr-agent-team/assets/article.css +0 -31
  467. package/static/site/content/blog/drafts/20260718-24hr-agent-team/assets/cover.svg +0 -24
  468. package/static/site/content/blog/drafts/20260718-24hr-agent-team/zh/index.html +0 -224
  469. package/static/site/content/blog/drafts/generated_manifest.json +0 -37
  470. package/static/site/content/tutorials/drafts/generated_manifest.json +0 -49
  471. package/static/site/content/tutorials/drafts/getting-started/assets/AppStore.png +0 -0
  472. package/static/site/content/tutorials/drafts/getting-started/assets/article.css +0 -31
  473. package/static/site/content/tutorials/drafts/getting-started/assets/chat.png +0 -0
  474. package/static/site/content/tutorials/drafts/getting-started/assets/cover.svg +0 -24
  475. package/static/site/content/tutorials/drafts/getting-started/en/index.html +0 -360
  476. package/static/site/tutorial/generated_manifest.json +0 -13
  477. package/static/site/tutorial/index.html +0 -54
package/bin/oysterun.mjs CHANGED
@@ -29,6 +29,11 @@ const serviceCommands = new Map([
29
29
  ["service:start", "start"],
30
30
  ["service:stop", "stop"],
31
31
  ["service:restart", "restart"],
32
+ ["service:update", "update"],
33
+ ["service:complete-update", "complete-update"],
34
+ ["service:repair", "repair"],
35
+ ["service:restore", "restore"],
36
+ ["service:lifecycle-status", "lifecycle-status"],
32
37
  ["service:status", "status"],
33
38
  ["service:logs", "logs"],
34
39
  ["service:uninstall", "uninstall"],
@@ -55,7 +60,21 @@ function runSetup(args = []) {
55
60
  }
56
61
 
57
62
  function runService(command, args = []) {
58
- run(releaseServiceScript, [command, ...args]);
63
+ const result = spawnSync(releaseServiceScript, [command, ...args], {
64
+ cwd: repoRoot,
65
+ env: {
66
+ ...process.env,
67
+ OYSTERUN_BOOTSTRAP_NODE_BIN: process.execPath,
68
+ },
69
+ stdio: "inherit",
70
+ });
71
+ if (result.error) {
72
+ console.error(
73
+ `oysterun: failed to run ${releaseServiceScript}: ${result.error.message}`
74
+ );
75
+ process.exit(1);
76
+ }
77
+ process.exit(result.status ?? 0);
59
78
  }
60
79
 
61
80
  function parseUninstallArgs(args = []) {
@@ -181,6 +200,11 @@ Usage:
181
200
  oysterun service:start
182
201
  oysterun service:stop
183
202
  oysterun service:restart [--restore-sessions]
203
+ oysterun service:update --channel latest|beta
204
+ oysterun service:complete-update
205
+ oysterun service:repair
206
+ oysterun service:restore
207
+ oysterun service:lifecycle-status
184
208
  oysterun service:status
185
209
  oysterun service:logs [--follow]
186
210
  oysterun service:uninstall [--stack production|staging|all]
@@ -1,6 +1,14 @@
1
1
  export type InternalConnectivityStatus = {
2
2
  matrix: "Connected" | "Reconnecting" | "Error" | "Offline";
3
- activePath: "WebRTC" | "Bootstrap" | "Direct" | "None";
3
+ activePath:
4
+ | "WebRTC"
5
+ | "WebRTC (LAN)"
6
+ | "WebRTC (STUN Direct)"
7
+ | "WebRTC (TURN)"
8
+ | "WebRTC (IPv6 Direct)"
9
+ | "Bootstrap"
10
+ | "Direct"
11
+ | "None";
4
12
  promotion: "Idle" | `Attempt ${number}/4` | "Quiesced" | "Not applicable";
5
13
  };
6
14
 
@@ -10,5 +18,5 @@ export function deriveInternalConnectivityStatus(input?: {
10
18
  transportStatus?: Record<string, unknown>;
11
19
  }): InternalConnectivityStatus;
12
20
  export function internalConnectivityStatusText(
13
- status: InternalConnectivityStatus,
21
+ status: InternalConnectivityStatus
14
22
  ): string;
@@ -13,6 +13,14 @@ const ACTIVE_PATH_STATUS = Object.freeze({
13
13
  direct_host: "Direct",
14
14
  });
15
15
 
16
+ const WEBRTC_SELECTED_PATH_STATUS = Object.freeze({
17
+ lan: "WebRTC (LAN)",
18
+ stun_direct: "WebRTC (STUN Direct)",
19
+ turn_udp: "WebRTC (TURN)",
20
+ turn_tcp_tls: "WebRTC (TURN)",
21
+ ipv6: "WebRTC (IPv6 Direct)",
22
+ });
23
+
16
24
  export const INTERNAL_CONNECTIVITY_PROMOTION_ATTEMPT_LIMIT = 4;
17
25
 
18
26
  function finiteNonNegativeInteger(value) {
@@ -32,23 +40,26 @@ export function deriveInternalConnectivityStatus({
32
40
  transportConnectionState === "disconnected"
33
41
  ? "Reconnecting"
34
42
  : transportConnectionState === "connected"
35
- ? "Connected"
36
- : "Offline");
43
+ ? "Connected"
44
+ : "Offline");
37
45
  const activePath =
38
- ACTIVE_PATH_STATUS[transportStatus.active_path_kind] || "None";
46
+ transportStatus.active_path_kind === "webrtc"
47
+ ? WEBRTC_SELECTED_PATH_STATUS[transportStatus.webrtc_selected_path] ||
48
+ ACTIVE_PATH_STATUS.webrtc
49
+ : ACTIVE_PATH_STATUS[transportStatus.active_path_kind] || "None";
39
50
 
40
51
  let promotion = "Not applicable";
41
52
  if (transportStatus.managed_transport_enabled === true) {
42
53
  const attempt = Math.min(
43
54
  finiteNonNegativeInteger(transportStatus.promotion_attempt_count),
44
- INTERNAL_CONNECTIVITY_PROMOTION_ATTEMPT_LIMIT,
55
+ INTERNAL_CONNECTIVITY_PROMOTION_ATTEMPT_LIMIT
45
56
  );
46
57
  promotion =
47
58
  transportStatus.retry_quiesced === true
48
59
  ? "Quiesced"
49
60
  : attempt > 0
50
- ? `Attempt ${attempt}/${INTERNAL_CONNECTIVITY_PROMOTION_ATTEMPT_LIMIT}`
51
- : "Idle";
61
+ ? `Attempt ${attempt}/${INTERNAL_CONNECTIVITY_PROMOTION_ATTEMPT_LIMIT}`
62
+ : "Idle";
52
63
  }
53
64
 
54
65
  return Object.freeze({ matrix, activePath, promotion });
@@ -5,7 +5,8 @@ export class ManagedHostBrowserConnection {
5
5
  close(): Promise<void>;
6
6
  setTicketProvider(ticketProvider: ManagedHostTicketProvider | null): void;
7
7
  subscribeStatus(
8
- listener: (status: Record<string, unknown>) => void
8
+ listener: (status: Record<string, unknown>) => void,
9
+ options?: { includeSelectedWebRtcPath?: boolean }
9
10
  ): () => void;
10
11
  }
11
12
 
@@ -15,7 +16,8 @@ export class DirectHostBrowserConnection {
15
16
  status(): Record<string, unknown>;
16
17
  close(): Promise<void>;
17
18
  subscribeStatus(
18
- listener: (status: Record<string, unknown>) => void
19
+ listener: (status: Record<string, unknown>) => void,
20
+ options?: { includeSelectedWebRtcPath?: boolean }
19
21
  ): () => void;
20
22
  }
21
23
 
@@ -32,6 +34,19 @@ export function classifyManagedHostBrowserOrigin(value?: string | URL): {
32
34
  kind: "managed_endpoint" | "direct_host";
33
35
  managed_transport_enabled: boolean;
34
36
  };
37
+ export type ManagedWebRtcSelectedPath =
38
+ | "lan"
39
+ | "stun_direct"
40
+ | "turn_udp"
41
+ | "turn_tcp_tls"
42
+ | "ipv6";
43
+ export function normalizeManagedWebRtcSelectedPath(
44
+ value: unknown
45
+ ): ManagedWebRtcSelectedPath | null;
46
+ export function readManagedWebRtcSelectedPath(
47
+ hostStatus: unknown,
48
+ connectionId: string
49
+ ): ManagedWebRtcSelectedPath | null;
35
50
  export function getManagedHostBrowserConnection():
36
51
  | ManagedHostBrowserConnection
37
52
  | DirectHostBrowserConnection;
@@ -66,5 +81,6 @@ export function managedMediaObjectUrl(
66
81
  export function waitForManagedHostAvailability(): Promise<boolean>;
67
82
  export function getManagedHostConnectionStatus(): Record<string, unknown>;
68
83
  export function subscribeManagedHostConnectionStatus(
69
- listener: (status: Record<string, unknown>) => void
84
+ listener: (status: Record<string, unknown>) => void,
85
+ options?: { includeSelectedWebRtcPath?: boolean }
70
86
  ): () => void;
@@ -11,6 +11,7 @@ const REQUIRED_CHANNELS = Object.freeze(["control", "events", "bulk"]);
11
11
  const SUPPORTED_TRANSPORT_PROTOCOL_VERSIONS = Object.freeze([1]);
12
12
  const MANAGED_TRANSPORT_CONTRACT = "oysterun.managed_webrtc.v1";
13
13
  const SIGNALING_TIMEOUT_MS = 20_000;
14
+ const MANAGED_ICE_CANDIDATE_SETTLE_MS = 100;
14
15
  const BOOTSTRAP_SAFE_REQUEST_TIMEOUT_MS = 12_000;
15
16
  const BOOTSTRAP_MATRIX_SYNC_TIMEOUT_MS = 45_000;
16
17
  const PRESENCE_WAIT_SECONDS = 55;
@@ -30,6 +31,13 @@ const HOST_UNAVAILABLE_RESPONSE_ERROR =
30
31
  const BULK_REQUEST_TIMEOUT_MS = 120_000;
31
32
  const MATRIX_SYNC_PATH = /^\/_matrix\/client\/[^/]+\/sync(?:\?|$)/;
32
33
  const SIGNALING_PATH_PREFIX = "/connectivity/webrtc/";
34
+ const MANAGED_WEBRTC_SELECTED_PATHS = new Set([
35
+ "lan",
36
+ "stun_direct",
37
+ "turn_udp",
38
+ "turn_tcp_tls",
39
+ "ipv6",
40
+ ]);
33
41
  const MANAGED_ENDPOINT_HOSTNAME = /^h-([a-z2-7]{16})\.tunnel\.oysterun\.com$/i;
34
42
  const SESSION_SNAPSHOT_PATH = /^\/session\/snapshot(?:\?|$)/;
35
43
  const TRANSPORT_PATH_KINDS = Object.freeze([
@@ -354,6 +362,7 @@ function browserConnectionStatusKey(status) {
354
362
  status.last_request_failed,
355
363
  status.browser_online,
356
364
  status.active_path_kind,
365
+ status.webrtc_selected_path,
357
366
  status.transition_state,
358
367
  status.transition_generation,
359
368
  status.browser_peer_state,
@@ -368,6 +377,30 @@ function browserConnectionStatusKey(status) {
368
377
  ]);
369
378
  }
370
379
 
380
+ export function normalizeManagedWebRtcSelectedPath(value) {
381
+ return MANAGED_WEBRTC_SELECTED_PATHS.has(value) ? value : null;
382
+ }
383
+
384
+ export function readManagedWebRtcSelectedPath(hostStatus, connectionId) {
385
+ if (
386
+ !hostStatus ||
387
+ typeof hostStatus !== "object" ||
388
+ !Array.isArray(hostStatus.peers) ||
389
+ typeof connectionId !== "string" ||
390
+ !connectionId
391
+ ) {
392
+ return null;
393
+ }
394
+ const matchingPeers = hostStatus.peers.filter(
395
+ (peer) =>
396
+ peer &&
397
+ typeof peer === "object" &&
398
+ peer.connection_id === connectionId
399
+ );
400
+ if (matchingPeers.length !== 1) return null;
401
+ return normalizeManagedWebRtcSelectedPath(matchingPeers[0].selected_path);
402
+ }
403
+
371
404
  function managedHostUnavailableError() {
372
405
  const error = new Error(
373
406
  "Managed Oysterun Host is unavailable; the request was not sent"
@@ -521,20 +554,161 @@ function fingerprintFromSdp(sdp) {
521
554
  return compact;
522
555
  }
523
556
 
524
- function waitForIceGatheringComplete(peer) {
525
- if (peer.iceGatheringState === "complete") return Promise.resolve();
526
- return withTimeout(
527
- new Promise((resolve) => {
528
- const handleChange = () => {
529
- if (peer.iceGatheringState !== "complete") return;
530
- peer.removeEventListener("icegatheringstatechange", handleChange);
531
- resolve();
532
- };
533
- peer.addEventListener("icegatheringstatechange", handleChange);
534
- }),
535
- SIGNALING_TIMEOUT_MS,
536
- "Browser ICE candidate gathering timed out"
537
- );
557
+ function managedWebRtcAttemptError(code, message) {
558
+ const error = new Error(message);
559
+ error.code = code;
560
+ return error;
561
+ }
562
+
563
+ function signalingCandidateToJson(candidate) {
564
+ if (
565
+ !candidate ||
566
+ typeof candidate.candidate !== "string" ||
567
+ !candidate.candidate.trim()
568
+ ) {
569
+ return null;
570
+ }
571
+ return candidateToJson(candidate);
572
+ }
573
+
574
+ function createManagedIceCandidateReadiness(
575
+ peer,
576
+ {
577
+ assertCurrentAttempt,
578
+ settleMs = MANAGED_ICE_CANDIDATE_SETTLE_MS,
579
+ timeoutMs = SIGNALING_TIMEOUT_MS,
580
+ } = {}
581
+ ) {
582
+ if (typeof assertCurrentAttempt !== "function") {
583
+ throw new Error("Managed ICE readiness requires an attempt owner");
584
+ }
585
+ const candidates = [];
586
+ const readiness = deferred();
587
+ let waitStarted = false;
588
+ let settled = false;
589
+ let settleTimer = null;
590
+ let timeoutTimer = null;
591
+
592
+ // A candidate or peer-close callback can reject between setLocalDescription
593
+ // and wait(). Keep that attempt-owned rejection observed until the caller
594
+ // reaches the browser_ice_gathering stage.
595
+ void readiness.promise.catch(() => {});
596
+
597
+ const cleanup = () => {
598
+ if (settleTimer !== null) {
599
+ clearTimeout(settleTimer);
600
+ settleTimer = null;
601
+ }
602
+ if (timeoutTimer !== null) {
603
+ clearTimeout(timeoutTimer);
604
+ timeoutTimer = null;
605
+ }
606
+ peer.removeEventListener("icecandidate", handleCandidate);
607
+ peer.removeEventListener("icegatheringstatechange", handleGatheringChange);
608
+ peer.removeEventListener("connectionstatechange", handleConnectionChange);
609
+ };
610
+ const reject = (error) => {
611
+ if (settled) return false;
612
+ settled = true;
613
+ cleanup();
614
+ readiness.reject(error);
615
+ return true;
616
+ };
617
+ const resolve = () => {
618
+ if (settled) return false;
619
+ try {
620
+ assertCurrentAttempt(peer);
621
+ } catch (error) {
622
+ return reject(error);
623
+ }
624
+ if (candidates.length === 0) return false;
625
+ settled = true;
626
+ cleanup();
627
+ readiness.resolve(candidates);
628
+ return true;
629
+ };
630
+ const startSettle = () => {
631
+ if (settled || settleTimer !== null) return;
632
+ settleTimer = setTimeout(resolve, settleMs);
633
+ };
634
+ function handleCandidate(event) {
635
+ if (settled) return;
636
+ try {
637
+ assertCurrentAttempt(peer);
638
+ } catch (error) {
639
+ reject(error);
640
+ return;
641
+ }
642
+ const candidate = signalingCandidateToJson(event.candidate);
643
+ if (!candidate) return;
644
+ candidates.push(candidate);
645
+ if (peer.iceGatheringState === "complete") {
646
+ resolve();
647
+ return;
648
+ }
649
+ startSettle();
650
+ }
651
+ function handleGatheringChange() {
652
+ if (settled || peer.iceGatheringState !== "complete") return;
653
+ resolve();
654
+ }
655
+ function handleConnectionChange() {
656
+ if (settled || peer.connectionState !== "closed") return;
657
+ reject(
658
+ managedWebRtcAttemptError(
659
+ "managed_webrtc_attempt_cancelled",
660
+ "Managed WebRTC connect attempt was cancelled"
661
+ )
662
+ );
663
+ }
664
+
665
+ peer.addEventListener("icecandidate", handleCandidate);
666
+ peer.addEventListener("icegatheringstatechange", handleGatheringChange);
667
+ peer.addEventListener("connectionstatechange", handleConnectionChange);
668
+
669
+ return {
670
+ peer,
671
+ candidates,
672
+ wait() {
673
+ if (!waitStarted) {
674
+ waitStarted = true;
675
+ try {
676
+ assertCurrentAttempt(peer);
677
+ } catch (error) {
678
+ reject(error);
679
+ return readiness.promise;
680
+ }
681
+ if (peer.iceGatheringState === "complete" && candidates.length > 0) {
682
+ resolve();
683
+ } else if (!settled) {
684
+ timeoutTimer = setTimeout(
685
+ () =>
686
+ reject(
687
+ new Error("Browser ICE candidate gathering timed out")
688
+ ),
689
+ timeoutMs
690
+ );
691
+ }
692
+ }
693
+ return readiness.promise;
694
+ },
695
+ cancel(error) {
696
+ reject(
697
+ error ||
698
+ managedWebRtcAttemptError(
699
+ "managed_webrtc_attempt_cancelled",
700
+ "Managed WebRTC connect attempt was cancelled"
701
+ )
702
+ );
703
+ },
704
+ dispose() {
705
+ if (!settled) {
706
+ this.cancel();
707
+ } else {
708
+ cleanup();
709
+ }
710
+ },
711
+ };
538
712
  }
539
713
 
540
714
  function waitForPeerReady(peer, channels) {
@@ -939,6 +1113,7 @@ export class ManagedHostBrowserConnection {
939
1113
  });
940
1114
  this.peer = null;
941
1115
  this.connectingPeer = null;
1116
+ this.pendingIceCandidateReadiness = null;
942
1117
  this.webRtcTransport = null;
943
1118
  this.activeConnection = null;
944
1119
  this.iceTransportPolicy = "all";
@@ -962,7 +1137,12 @@ export class ManagedHostBrowserConnection {
962
1137
  this.immediateRecoveryPromise = null;
963
1138
  this.presenceAbortControllers = new Set();
964
1139
  this.statusListeners = new Set();
1140
+ this.selectedPathStatusListeners = new Set();
965
1141
  this.lastNotifiedStatusKey = "";
1142
+ this.webrtcSelectedPath = null;
1143
+ this.webrtcSelectedPathConnectionId = null;
1144
+ this.selectedPathStatusReadConnectionId = null;
1145
+ this.selectedPathStatusReadPromise = null;
966
1146
  this.lastRequestFailed = false;
967
1147
  this.accounting = createTransportAccounting();
968
1148
  this.reconciliationOwner = new EpochBoundTransportReconciliationOwner({
@@ -994,16 +1174,29 @@ export class ManagedHostBrowserConnection {
994
1174
  this.ticketProvider = ticketProvider;
995
1175
  }
996
1176
 
997
- subscribeStatus(listener) {
1177
+ subscribeStatus(listener, { includeSelectedWebRtcPath = false } = {}) {
998
1178
  if (typeof listener !== "function") {
999
1179
  throw new Error("Managed Host status listener must be a function");
1000
1180
  }
1001
1181
  this.statusListeners.add(listener);
1182
+ if (includeSelectedWebRtcPath === true) {
1183
+ this.selectedPathStatusListeners.add(listener);
1184
+ }
1002
1185
  const status = this.status();
1003
1186
  this.lastNotifiedStatusKey = browserConnectionStatusKey(status);
1004
1187
  listener(status);
1188
+ if (
1189
+ includeSelectedWebRtcPath === true &&
1190
+ status.active_path_kind === "webrtc" &&
1191
+ this.activeConnection?.connectionId
1192
+ ) {
1193
+ void this.refreshSelectedWebRtcPath(
1194
+ this.activeConnection.connectionId
1195
+ );
1196
+ }
1005
1197
  return () => {
1006
1198
  this.statusListeners.delete(listener);
1199
+ this.selectedPathStatusListeners.delete(listener);
1007
1200
  };
1008
1201
  }
1009
1202
 
@@ -1109,6 +1302,70 @@ export class ManagedHostBrowserConnection {
1109
1302
  return data;
1110
1303
  }
1111
1304
 
1305
+ refreshSelectedWebRtcPath(connectionId) {
1306
+ if (
1307
+ this.selectedPathStatusListeners.size === 0 ||
1308
+ typeof connectionId !== "string" ||
1309
+ !connectionId ||
1310
+ this.activeConnection?.connectionId !== connectionId ||
1311
+ this.logicalConnection.status().active_path_kind !== "webrtc"
1312
+ ) {
1313
+ return Promise.resolve(null);
1314
+ }
1315
+ if (this.selectedPathStatusReadConnectionId === connectionId) {
1316
+ return (
1317
+ this.selectedPathStatusReadPromise ||
1318
+ Promise.resolve(this.webrtcSelectedPath)
1319
+ );
1320
+ }
1321
+
1322
+ this.selectedPathStatusReadConnectionId = connectionId;
1323
+ this.webrtcSelectedPath = null;
1324
+ this.webrtcSelectedPathConnectionId = connectionId;
1325
+ const readPromise = this.nativeJson(SIGNALING_PATH_PREFIX + "status", {})
1326
+ .then((hostStatus) => {
1327
+ const selectedPath = readManagedWebRtcSelectedPath(
1328
+ hostStatus,
1329
+ connectionId
1330
+ );
1331
+ if (
1332
+ this.selectedPathStatusListeners.size === 0 ||
1333
+ this.activeConnection?.connectionId !== connectionId ||
1334
+ this.logicalConnection.status().active_path_kind !== "webrtc"
1335
+ ) {
1336
+ return null;
1337
+ }
1338
+ this.webrtcSelectedPath = selectedPath;
1339
+ this.webrtcSelectedPathConnectionId = connectionId;
1340
+ this.emitDiagnostic({
1341
+ event_type: "managed_webrtc_selected_path_resolved",
1342
+ selected_path: selectedPath || "unknown",
1343
+ });
1344
+ this.notifyStatusListeners();
1345
+ return selectedPath;
1346
+ })
1347
+ .catch((error) => {
1348
+ if (
1349
+ this.activeConnection?.connectionId === connectionId &&
1350
+ this.logicalConnection.status().active_path_kind === "webrtc"
1351
+ ) {
1352
+ this.emitDiagnostic({
1353
+ event_type: "managed_webrtc_selected_path_status_failed",
1354
+ error_code:
1355
+ error?.code || "managed_webrtc_selected_path_status_failed",
1356
+ });
1357
+ }
1358
+ return null;
1359
+ })
1360
+ .finally(() => {
1361
+ if (this.selectedPathStatusReadPromise === readPromise) {
1362
+ this.selectedPathStatusReadPromise = null;
1363
+ }
1364
+ });
1365
+ this.selectedPathStatusReadPromise = readPromise;
1366
+ return readPromise;
1367
+ }
1368
+
1112
1369
  ensureSyncOwner() {
1113
1370
  if (this.syncOwnerId) return this.syncOwnerId;
1114
1371
  this.syncOwnerId = "routec-matrix-client";
@@ -1196,6 +1453,15 @@ export class ManagedHostBrowserConnection {
1196
1453
  reconciliationEpoch = this.reconciliationOwner.status().epoch,
1197
1454
  lifecycleReason = "initial_start",
1198
1455
  } = {}) {
1456
+ if (this.pendingIceCandidateReadiness) {
1457
+ this.pendingIceCandidateReadiness.cancel(
1458
+ managedWebRtcAttemptError(
1459
+ "managed_webrtc_stale_connect_attempt",
1460
+ "Managed WebRTC connect attempt was replaced"
1461
+ )
1462
+ );
1463
+ this.pendingIceCandidateReadiness = null;
1464
+ }
1199
1465
  const connectionGeneration = ++this.connectionGeneration;
1200
1466
  const connectionAttemptId = createConnectivityRandomId();
1201
1467
  const attempt = {
@@ -1250,6 +1516,7 @@ export class ManagedHostBrowserConnection {
1250
1516
  iceTransportPolicy,
1251
1517
  });
1252
1518
  this.connectingPeer = peer;
1519
+ let iceCandidateReadiness = null;
1253
1520
  try {
1254
1521
  const channels = Object.fromEntries(
1255
1522
  REQUIRED_CHANNELS.map((name) => [
@@ -1260,19 +1527,20 @@ export class ManagedHostBrowserConnection {
1260
1527
  for (const channel of Object.values(channels)) {
1261
1528
  channel.binaryType = "arraybuffer";
1262
1529
  }
1263
- const localCandidates = [];
1264
- peer.addEventListener("icecandidate", (event) => {
1265
- if (event.candidate) {
1266
- localCandidates.push(candidateToJson(event.candidate));
1267
- }
1530
+ iceCandidateReadiness = createManagedIceCandidateReadiness(peer, {
1531
+ assertCurrentAttempt,
1268
1532
  });
1533
+ this.pendingIceCandidateReadiness = iceCandidateReadiness;
1269
1534
  await this.runConnectionStage("browser_offer", attempt, async () => {
1270
1535
  const offer = await peer.createOffer();
1271
1536
  await peer.setLocalDescription(offer);
1272
1537
  });
1273
1538
  await this.runConnectionStage("browser_ice_gathering", attempt, () =>
1274
- waitForIceGatheringComplete(peer)
1539
+ iceCandidateReadiness.wait()
1275
1540
  );
1541
+ if (this.pendingIceCandidateReadiness === iceCandidateReadiness) {
1542
+ this.pendingIceCandidateReadiness = null;
1543
+ }
1276
1544
  assertCurrentAttempt(peer);
1277
1545
  const localDescription = peer.localDescription;
1278
1546
  if (!localDescription) {
@@ -1301,6 +1569,7 @@ export class ManagedHostBrowserConnection {
1301
1569
  client_authority_kind: "host_owner_browser",
1302
1570
  }
1303
1571
  );
1572
+ assertCurrentAttempt(peer);
1304
1573
  if (
1305
1574
  !ticket ||
1306
1575
  typeof ticket.credential !== "string" ||
@@ -1325,7 +1594,7 @@ export class ManagedHostBrowserConnection {
1325
1594
  type: localDescription.type,
1326
1595
  sdp: localDescription.sdp,
1327
1596
  },
1328
- candidates: localCandidates,
1597
+ candidates: iceCandidateReadiness.candidates,
1329
1598
  })
1330
1599
  );
1331
1600
  assertCurrentAttempt(peer);
@@ -1385,6 +1654,12 @@ export class ManagedHostBrowserConnection {
1385
1654
  );
1386
1655
  assertCurrentAttempt(peer);
1387
1656
  this.lastRequestFailed = false;
1657
+ this.webrtcSelectedPath = null;
1658
+ this.webrtcSelectedPathConnectionId = answer.connection_id;
1659
+ this.notifyStatusListeners();
1660
+ if (this.selectedPathStatusListeners.size > 0) {
1661
+ void this.refreshSelectedWebRtcPath(answer.connection_id);
1662
+ }
1388
1663
  this.emitDiagnostic({
1389
1664
  event_type: "managed_webrtc_connected",
1390
1665
  connection_id: answer.connection_id,
@@ -1397,6 +1672,11 @@ export class ManagedHostBrowserConnection {
1397
1672
  if (this.connectingPeer === peer) this.connectingPeer = null;
1398
1673
  peer.close();
1399
1674
  throw error;
1675
+ } finally {
1676
+ if (this.pendingIceCandidateReadiness === iceCandidateReadiness) {
1677
+ this.pendingIceCandidateReadiness = null;
1678
+ }
1679
+ iceCandidateReadiness?.dispose();
1400
1680
  }
1401
1681
  }
1402
1682
 
@@ -1530,6 +1810,15 @@ export class ManagedHostBrowserConnection {
1530
1810
  this.connectionGeneration += 1;
1531
1811
  const connectingPeer = this.connectingPeer;
1532
1812
  this.connectingPeer = null;
1813
+ if (this.pendingIceCandidateReadiness?.peer === connectingPeer) {
1814
+ this.pendingIceCandidateReadiness.cancel(
1815
+ managedWebRtcAttemptError(
1816
+ "managed_webrtc_stale_connect_attempt",
1817
+ "Managed WebRTC connect attempt was replaced"
1818
+ )
1819
+ );
1820
+ this.pendingIceCandidateReadiness = null;
1821
+ }
1533
1822
  connectingPeer?.close();
1534
1823
  const peer = this.peer;
1535
1824
  const connection = this.activeConnection;
@@ -1537,6 +1826,9 @@ export class ManagedHostBrowserConnection {
1537
1826
  this.peer = null;
1538
1827
  this.webRtcTransport = null;
1539
1828
  this.activeConnection = null;
1829
+ this.webrtcSelectedPath = null;
1830
+ this.webrtcSelectedPathConnectionId = null;
1831
+ this.selectedPathStatusReadConnectionId = null;
1540
1832
  if (this.logicalConnection.status().active_path_kind === "webrtc") {
1541
1833
  await this.logicalConnection.activateBootstrap({ reason });
1542
1834
  this.emitDiagnostic({
@@ -2191,6 +2483,12 @@ export class ManagedHostBrowserConnection {
2191
2483
  relay_only_debug_enabled: this.iceTransportPolicy === "relay",
2192
2484
  connection_id: this.activeConnection?.connectionId || null,
2193
2485
  connection_attempt_id: this.activeConnection?.connectionAttemptId || null,
2486
+ webrtc_selected_path:
2487
+ logicalStatus.active_path_kind === "webrtc" &&
2488
+ this.webrtcSelectedPathConnectionId ===
2489
+ this.activeConnection?.connectionId
2490
+ ? this.webrtcSelectedPath
2491
+ : null,
2194
2492
  page_visibility_state: document.visibilityState,
2195
2493
  browser_online: browserOnline,
2196
2494
  retry_count: this.retryCount,
@@ -2234,6 +2532,7 @@ export class ManagedHostBrowserConnection {
2234
2532
  await this.closePeer("browser_connection_closed");
2235
2533
  this.routeUnavailable = false;
2236
2534
  this.statusListeners.clear();
2535
+ this.selectedPathStatusListeners.clear();
2237
2536
  this.abortPresenceRequests();
2238
2537
  this.presenceRecovery?.resolve();
2239
2538
  this.presenceRecovery = null;
@@ -2345,10 +2644,10 @@ export function getManagedHostConnectionStatus() {
2345
2644
  return getManagedHostBrowserConnection().status();
2346
2645
  }
2347
2646
 
2348
- export function subscribeManagedHostConnectionStatus(listener) {
2647
+ export function subscribeManagedHostConnectionStatus(listener, options = {}) {
2349
2648
  const connection = getManagedHostBrowserConnection();
2350
2649
  if (typeof connection.subscribeStatus === "function") {
2351
- return connection.subscribeStatus(listener);
2650
+ return connection.subscribeStatus(listener, options);
2352
2651
  }
2353
2652
  listener(connection.status());
2354
2653
  return () => {};