@undefineds.co/xpod 0.4.13 → 0.4.15

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 (331) hide show
  1. package/config/cloud.json +0 -3
  2. package/config/components-ignore.json +11 -7
  3. package/config/local.json +0 -3
  4. package/config/xpod.base.json +0 -24
  5. package/dist/api/ai-config/AiConfigStore.d.ts +2 -2
  6. package/dist/api/ai-config/AiConfigStore.js +4 -1
  7. package/dist/api/ai-gateway/auth/CallerPodAccess.d.ts +2 -5
  8. package/dist/api/ai-gateway/auth/CallerPodAccess.js +3 -42
  9. package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.d.ts +2 -1
  10. package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.js +1 -1
  11. package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.d.ts +3 -8
  12. package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.js +9 -32
  13. package/dist/api/ai-gateway/connect/index.d.ts +3 -3
  14. package/dist/api/ai-gateway/connect/index.js +9 -38
  15. package/dist/api/ai-gateway/errors.js +2 -1
  16. package/dist/api/ai-gateway/models/PodModelSelectionRepository.d.ts +3 -3
  17. package/dist/api/ai-gateway/models/PodModelSelectionRepository.js +7 -11
  18. package/dist/api/ai-gateway/pod/HostedPodRoute.d.ts +27 -0
  19. package/dist/api/ai-gateway/pod/HostedPodRoute.js +47 -0
  20. package/dist/api/ai-gateway/pod/OwnerPodAccess.d.ts +79 -0
  21. package/dist/api/ai-gateway/pod/OwnerPodAccess.js +192 -0
  22. package/dist/api/ai-gateway/pod/PodInterfaceKeyStore.d.ts +52 -0
  23. package/dist/api/ai-gateway/pod/PodInterfaceKeyStore.js +61 -0
  24. package/dist/api/ai-gateway/providers/ProviderRegistry.js +1 -1
  25. package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.d.ts +3 -3
  26. package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.js +7 -32
  27. package/dist/api/ai-gateway/service-access/AiConnectionsServiceAccess.d.ts +1 -1
  28. package/dist/api/ai-gateway/service-access/AiConnectionsServiceAccess.js +1 -1
  29. package/dist/api/auth/ClientCredentialsAuthenticator.js +5 -28
  30. package/dist/api/auth/TokenEndpointRoute.d.ts +18 -0
  31. package/dist/api/auth/TokenEndpointRoute.js +36 -0
  32. package/dist/api/chatkit/pod-store.d.ts +4 -4
  33. package/dist/api/chatkit/pod-store.js +24 -95
  34. package/dist/api/container/common.js +36 -23
  35. package/dist/api/container/index.js +1 -0
  36. package/dist/api/container/local.js +88 -37
  37. package/dist/api/container/routes.js +41 -7
  38. package/dist/api/container/types.d.ts +4 -2
  39. package/dist/api/handlers/AdminHandler.d.ts +17 -1
  40. package/dist/api/handlers/AdminHandler.js +40 -3
  41. package/dist/api/handlers/AiGatewayManagementHandler.d.ts +6 -0
  42. package/dist/api/handlers/AiGatewayManagementHandler.js +17 -4
  43. package/dist/api/handlers/EdgeNodeSignalHandler.js +10 -2
  44. package/dist/api/handlers/NetworkSettingsHandler.d.ts +44 -5
  45. package/dist/api/handlers/NetworkSettingsHandler.js +46 -11
  46. package/dist/api/handlers/PodSettingsHandler.d.ts +3 -3
  47. package/dist/api/handlers/PodSettingsHandler.js +3 -3
  48. package/dist/api/handlers/ProvisionHandler.d.ts +35 -1
  49. package/dist/api/handlers/ProvisionHandler.js +53 -2
  50. package/dist/api/handlers/ReachabilityHandler.d.ts +6 -0
  51. package/dist/api/handlers/ReachabilityHandler.js +25 -6
  52. package/dist/api/network/NetworkEnvironmentConfigurationStore.d.ts +6 -1
  53. package/dist/api/network/NetworkEnvironmentConfigurationStore.js +72 -16
  54. package/dist/api/runtime.d.ts +18 -0
  55. package/dist/api/runtime.js +28 -2
  56. package/dist/api/service/AiClientConfigurationService.d.ts +1 -1
  57. package/dist/api/service/AiClientConfigurationService.js +1 -1
  58. package/dist/cli/commands/start.d.ts +26 -1
  59. package/dist/cli/commands/start.js +69 -5
  60. package/dist/components/components.jsonld +1 -1
  61. package/dist/components/context.jsonld +35 -42
  62. package/dist/edge/EdgeNodeAgent.d.ts +16 -0
  63. package/dist/edge/EdgeNodeAgent.js +56 -1
  64. package/dist/edge/EdgeNodeAgent.jsonld +8 -0
  65. package/dist/edge/EdgeNodeAgentInitializer.d.ts +2 -0
  66. package/dist/edge/EdgeNodeAgentInitializer.js +1 -0
  67. package/dist/edge/EdgeNodeAgentInitializer.jsonld +19 -0
  68. package/dist/edge/EdgeNodeDnsCoordinator.d.ts +11 -1
  69. package/dist/edge/EdgeNodeDnsCoordinator.js +12 -2
  70. package/dist/edge/EdgeNodeHealthProbeService.d.ts +15 -0
  71. package/dist/edge/EdgeNodeHealthProbeService.js +44 -12
  72. package/dist/edge/EdgeNodeHealthProbeService.jsonld +77 -0
  73. package/dist/edge/ProbeTargetGuard.d.ts +35 -0
  74. package/dist/edge/ProbeTargetGuard.js +142 -0
  75. package/dist/edge/reachability/NodeAccessResolver.d.ts +16 -0
  76. package/dist/edge/reachability/NodeAccessResolver.js +30 -0
  77. package/dist/edge/reachability/ReachabilitySessionService.js +4 -1
  78. package/dist/edge/reachability/RouteSetBuilder.d.ts +18 -1
  79. package/dist/edge/reachability/RouteSetBuilder.js +47 -0
  80. package/dist/edge/reachability/RouteSetBuilder.jsonld +29 -0
  81. package/dist/edge/reachability/types.d.ts +8 -2
  82. package/dist/http/SubgraphSparqlHttpHandler.d.ts +1 -25
  83. package/dist/http/SubgraphSparqlHttpHandler.js +0 -100
  84. package/dist/http/SubgraphSparqlHttpHandler.jsonld +0 -8
  85. package/dist/identity/drizzle/PodInterfaceKeyRepository.d.ts +33 -0
  86. package/dist/identity/drizzle/PodInterfaceKeyRepository.js +78 -0
  87. package/dist/identity/drizzle/db.d.ts +7 -0
  88. package/dist/identity/drizzle/db.js +30 -0
  89. package/dist/identity/drizzle/schema.pg.d.ts +9 -0
  90. package/dist/identity/drizzle/schema.pg.js +16 -1
  91. package/dist/identity/drizzle/schema.sqlite.d.ts +106 -0
  92. package/dist/identity/drizzle/schema.sqlite.js +16 -1
  93. package/dist/index.d.ts +3 -2
  94. package/dist/index.js +9 -5
  95. package/dist/main.js +7 -0
  96. package/dist/runtime/GatewayAdminProxyAuth.d.ts +1 -16
  97. package/dist/runtime/GatewayAdminProxyAuth.js +2 -71
  98. package/dist/runtime/Proxy.d.ts +32 -1
  99. package/dist/runtime/Proxy.js +125 -31
  100. package/dist/runtime/bootstrap.d.ts +21 -0
  101. package/dist/runtime/bootstrap.js +45 -1
  102. package/dist/runtime/css-process.d.ts +1 -0
  103. package/dist/runtime/css-process.js +1 -0
  104. package/dist/runtime/host/node/NodeRuntimeHost.js +6 -1
  105. package/dist/runtime/host/types.d.ts +6 -0
  106. package/dist/runtime/index.d.ts +1 -1
  107. package/dist/runtime/index.js +4 -1
  108. package/dist/runtime/js-runtime.js +10 -3
  109. package/dist/runtime/lifecycle.js +6 -4
  110. package/dist/runtime/port-finder.d.ts +26 -0
  111. package/dist/runtime/port-finder.js +64 -0
  112. package/dist/runtime/runner/node/NodeGatewayRuntimeRunner.js +1 -0
  113. package/dist/runtime/runner/types.d.ts +5 -0
  114. package/dist/runtime/runtime-types.d.ts +1 -0
  115. package/dist/test-utils/local-managed-client-p2p-e2e-smoke.js +1 -1
  116. package/dist/tunnel/AutoTunnelProvider.d.ts +56 -0
  117. package/dist/tunnel/AutoTunnelProvider.js +181 -0
  118. package/dist/tunnel/LocalTunnelProvider.d.ts +15 -0
  119. package/dist/tunnel/LocalTunnelProvider.js +87 -18
  120. package/dist/tunnel/LocalTunnelProvider.jsonld +27 -0
  121. package/dist/tunnel/NgrokTunnelProvider.d.ts +4 -0
  122. package/dist/tunnel/NgrokTunnelProvider.js +117 -43
  123. package/dist/tunnel/NgrokTunnelProvider.jsonld +4 -0
  124. package/dist/tunnel/SakuraFrpTunnelProvider.d.ts +65 -3
  125. package/dist/tunnel/SakuraFrpTunnelProvider.js +268 -25
  126. package/dist/tunnel/TunnelLifecycle.d.ts +14 -0
  127. package/dist/tunnel/TunnelLifecycle.js +34 -0
  128. package/dist/tunnel/TunnelProfiles.d.ts +33 -3
  129. package/dist/tunnel/TunnelProfiles.js +105 -78
  130. package/dist/tunnel/TunnelProvider.d.ts +15 -2
  131. package/dist/tunnel/TunnelProvider.jsonld +8 -0
  132. package/dist/tunnel/TunnelProviderCatalog.d.ts +62 -0
  133. package/dist/tunnel/TunnelProviderCatalog.js +130 -0
  134. package/dist/tunnel/index.d.ts +1 -0
  135. package/dist/tunnel/index.js +3 -1
  136. package/node_modules/@undefineds.co/ai-connections/dist/AiApiKeyPool.d.ts +1 -1
  137. package/node_modules/@undefineds.co/ai-connections/dist/AiApiKeyPool.js +1 -1
  138. package/node_modules/@undefineds.co/ai-connections/dist/AiAuthorizationActions.d.ts +1 -1
  139. package/node_modules/@undefineds.co/ai-connections/dist/AiClientConfigurationSection.d.ts +1 -1
  140. package/node_modules/@undefineds.co/ai-connections/dist/AiClientConfigurationSection.js +1 -1
  141. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectDialog.d.ts +1 -1
  142. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.d.ts +1 -1
  143. package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialPoolSection.d.ts +1 -1
  144. package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialRow.d.ts +1 -1
  145. package/node_modules/@undefineds.co/ai-connections/dist/AiCustomProviderDialog.d.ts +1 -1
  146. package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeyRow.d.ts +1 -1
  147. package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeysSection.d.ts +1 -1
  148. package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayModelsSection.d.ts +1 -1
  149. package/node_modules/@undefineds.co/ai-connections/dist/AiOfferingDetails.d.ts +1 -1
  150. package/node_modules/@undefineds.co/ai-connections/dist/AiProviderCard.d.ts +1 -1
  151. package/node_modules/@undefineds.co/ai-connections/dist/AiQuotaCard.d.ts +1 -1
  152. package/node_modules/@undefineds.co/ai-connections/dist/AiSortableCredentialList.d.ts +1 -1
  153. package/node_modules/@undefineds.co/ai-connections/dist/authorization-methods.d.ts +1 -1
  154. package/node_modules/@undefineds.co/ai-connections/dist/collection-runtime.d.ts +1 -1
  155. package/node_modules/@undefineds.co/ai-connections/dist/collection-runtime.js +3 -3
  156. package/node_modules/@undefineds.co/ai-connections/dist/collections.d.ts +1 -1
  157. package/node_modules/@undefineds.co/ai-connections/dist/collections.js +3 -3
  158. package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/ai-connections-client.d.ts +1 -1
  159. package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/ai-connections-client.js +1 -1
  160. package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client-config/index.cjs +8 -8
  161. package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/index.d.ts +1 -1
  162. package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/index.js +1 -1
  163. package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/provider-catalog.cjs +3 -3
  164. package/node_modules/@undefineds.co/ai-connections/dist/controller.d.ts +1 -1
  165. package/node_modules/@undefineds.co/ai-connections/dist/controller.js +1 -1
  166. package/node_modules/@undefineds.co/ai-connections/dist/credential-labels.d.ts +1 -1
  167. package/node_modules/@undefineds.co/ai-connections/dist/display-wording.d.ts +1 -1
  168. package/node_modules/@undefineds.co/ai-connections/dist/error-wording.d.ts +1 -1
  169. package/node_modules/@undefineds.co/ai-connections/dist/error-wording.js +8 -3
  170. package/node_modules/@undefineds.co/ai-connections/dist/gateway-endpoints.js +1 -1
  171. package/node_modules/@undefineds.co/ai-connections/dist/offering-endpoints.d.ts +1 -1
  172. package/node_modules/@undefineds.co/ai-connections/dist/offering-label.d.ts +1 -1
  173. package/node_modules/@undefineds.co/ai-connections/dist/provider-visuals.d.ts +1 -1
  174. package/node_modules/@undefineds.co/ai-connections/dist/service-access.js +1 -1
  175. package/node_modules/@undefineds.co/ai-connections/dist/useAiConnectDialog.d.ts +1 -1
  176. package/node_modules/@undefineds.co/ai-connections/package.json +31 -1
  177. package/node_modules/@undefineds.co/solid-sdk/dist/access-route.cjs +230 -0
  178. package/node_modules/@undefineds.co/solid-sdk/dist/access-route.d.ts +76 -0
  179. package/node_modules/@undefineds.co/solid-sdk/dist/access-route.js +115 -0
  180. package/node_modules/@undefineds.co/solid-sdk/dist/index.cjs +89 -0
  181. package/node_modules/@undefineds.co/solid-sdk/dist/index.d.ts +1 -0
  182. package/node_modules/@undefineds.co/solid-sdk/dist/index.js +1 -0
  183. package/node_modules/@undefineds.co/solid-sdk/package.json +6 -1
  184. package/package.json +5 -6
  185. package/static/app/assets/inrupt-smoke.js +23 -23
  186. package/static/app/assets/main.css +1 -1
  187. package/static/auth-callback/assets/{AiConfigContext-DlFyEWy9.js → AiConfigContext-Bx0HCAW5.js} +1 -1
  188. package/static/auth-callback/assets/{AiConfigPage-CkYk-SFW.js → AiConfigPage-ChQImMbm.js} +1 -1
  189. package/static/auth-callback/assets/{DocumentProcessingPanel-CqIr3JqN.js → DocumentProcessingPanel-D830H4SH.js} +1 -1
  190. package/static/auth-callback/assets/{IndexLifecyclePanel-C1GKV3Vx.js → IndexLifecyclePanel-CnlkjMF8.js} +1 -1
  191. package/static/auth-callback/assets/{IndexSubjectPanel-ro9lC6XW.js → IndexSubjectPanel-CdEfg_CO.js} +1 -1
  192. package/static/auth-callback/assets/{ModelAssignmentsPanel-DxNdyKRJ.js → ModelAssignmentsPanel-D-8A8dZx.js} +1 -1
  193. package/static/auth-callback/assets/{ModelsPage-BVtWSPBU.js → ModelsPage-Cim7cubp.js} +3 -3
  194. package/static/auth-callback/assets/NetworkPage-CfK3x-pb.js +2 -0
  195. package/static/auth-callback/assets/{PaneListHeader-ByKw8ada.js → PaneListHeader-Bf_kEd4U.js} +1 -1
  196. package/static/auth-callback/assets/{SearchIndexingPanel-CulBKcYT.js → SearchIndexingPanel-4kD4RBEQ.js} +1 -1
  197. package/static/auth-callback/assets/{StatusSubjectPanel-VOcfrt8o.js → StatusSubjectPanel-Bw9AiTSf.js} +1 -1
  198. package/static/auth-callback/assets/{StatusWorkspace-Jsz6hAdE.js → StatusWorkspace-C-301H-0.js} +1 -1
  199. package/static/auth-callback/assets/{SystemSettingsPage-BFNvGAle.js → SystemSettingsPage-BbWn-eG6.js} +1 -1
  200. package/static/auth-callback/assets/{SystemSettingsSubjectPanel-DFRdrSfK.js → SystemSettingsSubjectPanel-DA4wvNSm.js} +1 -1
  201. package/static/auth-callback/assets/{XpodAiConnectionsPodStore-C6KpvHVg.js → XpodAiConnectionsPodStore-CohdyLoX.js} +1 -1
  202. package/static/auth-callback/assets/{activity-DnTlb9iM.js → activity-CCsb9Oam.js} +1 -1
  203. package/static/auth-callback/assets/ai-connections-DexTPyfC.js +1 -0
  204. package/static/auth-callback/assets/{auth-callback-D2UkK5Xj.js → auth-callback-Ds-c62W3.js} +5 -5
  205. package/static/auth-callback/assets/auth-callback-rk080mvG.css +1 -0
  206. package/static/auth-callback/assets/{badge-D7IJuuTM.js → badge-CQm5OyzR.js} +1 -1
  207. package/static/auth-callback/assets/{collection-runtime-wT1n4GS2.js → collection-runtime-DlAuU5TW.js} +1 -1
  208. package/static/auth-callback/assets/{dialog-DickLu5z.js → dialog-CnGzg5Ff.js} +1 -1
  209. package/static/auth-callback/assets/{download-kn8WnRu3.js → download-DwMONJvm.js} +1 -1
  210. package/static/auth-callback/assets/{external-link-B6B8jfSn.js → external-link-Bu5AGqCO.js} +1 -1
  211. package/static/auth-callback/assets/{index-DHF97YLP.js → index-B0T-1YO8.js} +1 -1
  212. package/static/auth-callback/assets/{index-Dz83EEHD.js → index-C8QZf_4W.js} +1 -1
  213. package/static/auth-callback/assets/index-DwIlrIDG.js +4 -0
  214. package/static/auth-callback/assets/{index-browser-CSghinyi.js → index-browser-lRsMcP_7.js} +1 -1
  215. package/static/auth-callback/assets/{key-round-ChkOx3E1.js → key-round-BDMtU57P.js} +1 -1
  216. package/static/auth-callback/assets/{rotate-ccw-B3hE-nyd.js → rotate-ccw-CoKIGCsQ.js} +1 -1
  217. package/static/auth-callback/assets/{skeleton-kEqR7tpI.js → skeleton-CPoSWHDr.js} +1 -1
  218. package/static/auth-callback/assets/{waypoints-D6Jo-SZa.js → waypoints-BeYHxqHv.js} +1 -1
  219. package/static/auth-callback/assets/{workspace-layout-BHwT_cHd.js → workspace-layout-xA5YxiK3.js} +1 -1
  220. package/static/auth-callback/auth-callback.html +2 -2
  221. package/static/dashboard/assets/{AiConfigContext-BfC3v-x2.js → AiConfigContext-rWx4TyiH.js} +1 -1
  222. package/static/dashboard/assets/{AiConfigPage-QNS3u7Ff.js → AiConfigPage-StVJpDFT.js} +1 -1
  223. package/static/dashboard/assets/{DocumentProcessingPanel-Dr4XLeT4.js → DocumentProcessingPanel-DJ5yul2O.js} +1 -1
  224. package/static/dashboard/assets/{IndexLifecyclePanel-KtM_gpeO.js → IndexLifecyclePanel-CpjtgezK.js} +1 -1
  225. package/static/dashboard/assets/{IndexSubjectPanel-DLaiKdLc.js → IndexSubjectPanel-BVKcot1_.js} +1 -1
  226. package/static/dashboard/assets/{ModelAssignmentsPanel-Bk7TvQRq.js → ModelAssignmentsPanel-BxVgWZPc.js} +1 -1
  227. package/static/dashboard/assets/{ModelsPage-Cci3vlos.js → ModelsPage-CECBwmeO.js} +3 -3
  228. package/static/dashboard/assets/NetworkPage-zQgFscEW.js +2 -0
  229. package/static/dashboard/assets/{PaneListHeader-qHME_s08.js → PaneListHeader-DIPe8pS6.js} +1 -1
  230. package/static/dashboard/assets/{SearchIndexingPanel-HZPKj8H9.js → SearchIndexingPanel-lalFJ3c8.js} +1 -1
  231. package/static/dashboard/assets/{StatusSubjectPanel-ij7IpI8d.js → StatusSubjectPanel-CpY_KU-G.js} +1 -1
  232. package/static/dashboard/assets/{StatusWorkspace-Cp02JcaN.js → StatusWorkspace-BwWCii3A.js} +1 -1
  233. package/static/dashboard/assets/{SystemSettingsPage-BSeuvb8X.js → SystemSettingsPage-BKZxX-_n.js} +1 -1
  234. package/static/dashboard/assets/{SystemSettingsSubjectPanel-CP4_luGS.js → SystemSettingsSubjectPanel-BZrqb2C5.js} +1 -1
  235. package/static/dashboard/assets/{XpodAiConnectionsPodStore-urO6zaHL.js → XpodAiConnectionsPodStore-Bbpx9dTN.js} +1 -1
  236. package/static/dashboard/assets/{activity-DxjgQNvr.js → activity-BJ15TLVP.js} +1 -1
  237. package/static/dashboard/assets/ai-connections-GG6qkTJt.js +1 -0
  238. package/static/dashboard/assets/{badge-53qCrRbl.js → badge-BBX5FlaB.js} +1 -1
  239. package/static/dashboard/assets/{collection-runtime-BPAmHG46.js → collection-runtime-UBbHBzdf.js} +1 -1
  240. package/static/dashboard/assets/{dashboard-BcT2ByXw.js → dashboard-7Y6BHyV9.js} +62 -62
  241. package/static/dashboard/assets/dashboard-rk080mvG.css +1 -0
  242. package/static/dashboard/assets/{dialog-B28YtNhS.js → dialog-QrOJ-hB0.js} +1 -1
  243. package/static/dashboard/assets/{download-DkLNceJ4.js → download-DK9x-VOP.js} +1 -1
  244. package/static/dashboard/assets/{external-link-D3TXnlo3.js → external-link-Cnkn87mJ.js} +1 -1
  245. package/static/dashboard/assets/index-B1z84it5.js +4 -0
  246. package/static/dashboard/assets/{index-CIiBu9mr.js → index-DzjauX3N.js} +1 -1
  247. package/static/dashboard/assets/{index-CFIenkeK.js → index-cIa8_efI.js} +1 -1
  248. package/static/dashboard/assets/{key-round-B5ccp6nx.js → key-round-BoS6UqKz.js} +1 -1
  249. package/static/dashboard/assets/{rotate-ccw-DUpfkNnk.js → rotate-ccw-BeWV76i0.js} +1 -1
  250. package/static/dashboard/assets/{skeleton-BRe19fO0.js → skeleton-CypcJL07.js} +1 -1
  251. package/static/dashboard/assets/{waypoints-BKDMxEvu.js → waypoints-zHOOqfhi.js} +1 -1
  252. package/static/dashboard/assets/{workspace-layout-ZTF7C16h.js → workspace-layout-DZ9JuxnM.js} +1 -1
  253. package/static/dashboard/dashboard.html +2 -2
  254. package/static/settings/assets/{AiConfigContext-DsyWgu2i.js → AiConfigContext-D3b1l_Kw.js} +1 -1
  255. package/static/settings/assets/{AiConfigPage-CSCBckKo.js → AiConfigPage-DYKw-atP.js} +1 -1
  256. package/static/settings/assets/{DocumentProcessingPanel-w9yQDbBe.js → DocumentProcessingPanel-DguRfsIV.js} +1 -1
  257. package/static/settings/assets/{IndexLifecyclePanel-CUUXI8mP.js → IndexLifecyclePanel-B85qJJA4.js} +1 -1
  258. package/static/settings/assets/{IndexSubjectPanel-BypAU5TJ.js → IndexSubjectPanel-CsN7IxaV.js} +1 -1
  259. package/static/settings/assets/{ModelAssignmentsPanel-BetgXw1G.js → ModelAssignmentsPanel-DEp9byI6.js} +1 -1
  260. package/static/settings/assets/{ModelsPage-DZpTlTZ3.js → ModelsPage-CzTnPs_G.js} +3 -3
  261. package/static/settings/assets/NetworkPage-BDVnmUU0.js +2 -0
  262. package/static/settings/assets/{PaneListHeader-BGOqGec4.js → PaneListHeader-Cpe39N76.js} +1 -1
  263. package/static/settings/assets/{SearchIndexingPanel-DYAbpZ_9.js → SearchIndexingPanel-DA9w8lLL.js} +1 -1
  264. package/static/settings/assets/{StatusSubjectPanel-CFgzeQ8Q.js → StatusSubjectPanel-BU0Aq0CS.js} +1 -1
  265. package/static/settings/assets/{StatusWorkspace-4Z6g4Jvv.js → StatusWorkspace-D1AC1i5N.js} +1 -1
  266. package/static/settings/assets/{SystemSettingsPage-C1tlrgvI.js → SystemSettingsPage-ChKvOioO.js} +1 -1
  267. package/static/settings/assets/{SystemSettingsSubjectPanel-CcURI-1L.js → SystemSettingsSubjectPanel-DyTpOnD2.js} +1 -1
  268. package/static/settings/assets/{XpodAiConnectionsPodStore-owBQc5nY.js → XpodAiConnectionsPodStore-VU5Bsz1a.js} +1 -1
  269. package/static/settings/assets/{activity-CtBc9cNy.js → activity-DGpLfsQB.js} +1 -1
  270. package/static/settings/assets/ai-connections-DexTPyfC.js +1 -0
  271. package/static/settings/assets/{badge--r-FDIhU.js → badge-_hCrrWRP.js} +1 -1
  272. package/static/settings/assets/{collection-runtime-CnhPmwAM.js → collection-runtime-E40TZ8Cl.js} +1 -1
  273. package/static/settings/assets/{dialog-B7ZRsjN7.js → dialog-DTr2JkHn.js} +1 -1
  274. package/static/settings/assets/{download-DgQ1F8QR.js → download-B_D21DDX.js} +1 -1
  275. package/static/settings/assets/{external-link-Bz7NckNO.js → external-link-BATYaM13.js} +1 -1
  276. package/static/settings/assets/index-BAlAVi-J.js +4 -0
  277. package/static/settings/assets/{index-CkGda_Pg.js → index-Ckh4h9jj.js} +1 -1
  278. package/static/settings/assets/{index-Vv-8Vslg.js → index-DOiwLF4B.js} +1 -1
  279. package/static/settings/assets/{index-browser-Dq7omlpY.js → index-browser-DFFWN3Kr.js} +1 -1
  280. package/static/settings/assets/{key-round-CvuhloKV.js → key-round-ZTVU_1O1.js} +1 -1
  281. package/static/settings/assets/{rotate-ccw-DgFKDaz7.js → rotate-ccw-DDdw8PTU.js} +1 -1
  282. package/static/settings/assets/{settings-BvqY7K96.js → settings-CyLnISOv.js} +62 -62
  283. package/static/settings/assets/settings-rk080mvG.css +1 -0
  284. package/static/settings/assets/{skeleton-D3OeFDF6.js → skeleton-DEzA3hc2.js} +1 -1
  285. package/static/settings/assets/{waypoints-C4WbspTb.js → waypoints-BSdfNvEb.js} +1 -1
  286. package/static/settings/assets/{workspace-layout-B9H1Tqrk.js → workspace-layout-BOQnl_3d.js} +1 -1
  287. package/static/settings/settings.html +2 -2
  288. package/dist/api/ai-gateway/pod/HostedPodDataAccess.d.ts +0 -31
  289. package/dist/api/ai-gateway/pod/HostedPodDataAccess.js +0 -330
  290. package/dist/http/InternalPodDataHttpHandler.d.ts +0 -57
  291. package/dist/http/InternalPodDataHttpHandler.js +0 -551
  292. package/dist/http/InternalPodDataHttpHandler.jsonld +0 -243
  293. package/node_modules/@undefineds.co/ai-connections-core/package.json +0 -61
  294. package/static/auth-callback/assets/NetworkPage-cEvxRMAl.js +0 -2
  295. package/static/auth-callback/assets/ai-connections-C6yaE6WQ.js +0 -1
  296. package/static/auth-callback/assets/auth-callback-Cx9D_1qj.css +0 -1
  297. package/static/auth-callback/assets/index-Cu0EguPo.js +0 -4
  298. package/static/dashboard/assets/NetworkPage-Ot4G2dX5.js +0 -2
  299. package/static/dashboard/assets/ai-connections-CXp5gd1J.js +0 -1
  300. package/static/dashboard/assets/dashboard-Cx9D_1qj.css +0 -1
  301. package/static/dashboard/assets/index-Gp3cLolR.js +0 -4
  302. package/static/settings/assets/NetworkPage-BVkasFGM.js +0 -2
  303. package/static/settings/assets/ai-connections-C6yaE6WQ.js +0 -1
  304. package/static/settings/assets/index-BdXwm8nh.js +0 -4
  305. package/static/settings/assets/settings-Cx9D_1qj.css +0 -1
  306. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client/normalize.d.ts +0 -0
  307. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client/normalize.js +0 -0
  308. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client/request.d.ts +0 -0
  309. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client/request.js +0 -0
  310. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client/types.d.ts +0 -0
  311. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client/types.js +0 -0
  312. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client-config/base-adapter.d.ts +0 -0
  313. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client-config/base-adapter.js +0 -0
  314. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client-config/codex.d.ts +0 -0
  315. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client-config/codex.js +0 -0
  316. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client-config/index.d.ts +0 -0
  317. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client-config/index.js +0 -0
  318. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client-config/json-env-adapter.d.ts +0 -0
  319. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client-config/json-env-adapter.js +0 -0
  320. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client-config/pi.d.ts +0 -0
  321. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client-config/pi.js +0 -0
  322. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client-config/transaction.d.ts +0 -0
  323. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client-config/transaction.js +0 -0
  324. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client-config/types.d.ts +0 -0
  325. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/client-config/types.js +0 -0
  326. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/credential-storage.d.ts +0 -0
  327. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/credential-storage.js +0 -0
  328. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/endpoint-urls.d.ts +0 -0
  329. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/endpoint-urls.js +0 -0
  330. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/provider-catalog.d.ts +0 -0
  331. /package/node_modules/@undefineds.co/{ai-connections-core/dist → ai-connections/dist/contract}/provider-catalog.js +0 -0
@@ -3,7 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.findGatewayIngressPort = findGatewayIngressPort;
6
7
  exports.getFreePort = getFreePort;
8
+ exports.getEphemeralLoopbackPort = getEphemeralLoopbackPort;
9
+ exports.requireFreePortForWildcard = requireFreePortForWildcard;
7
10
  exports.getFreePortForWildcard = getFreePortForWildcard;
8
11
  const node_net_1 = __importDefault(require("node:net"));
9
12
  const node_os_1 = __importDefault(require("node:os"));
@@ -97,6 +100,23 @@ async function canListen(port, host, timeoutMs = PORT_PROBE_TIMEOUT_MS) {
97
100
  server.listen(port, host);
98
101
  });
99
102
  }
103
+ /**
104
+ * The port a remote tunnel forwards to: the Gateway's tunnel entry.
105
+ *
106
+ * It sits a few ports above the Gateway so it is predictable - the user copies this one number
107
+ * into a provider console and it survives restarts - while staying clear of the block a
108
+ * neighbouring runtime plans for its own services. When the neighbourhood is busy the caller
109
+ * gets an OS-assigned port instead of a stolen one; the runtime reports whichever it got.
110
+ */
111
+ async function findGatewayIngressPort(gatewayPort) {
112
+ for (let offset = 3; offset < 10; offset += 1) {
113
+ const candidate = gatewayPort + offset;
114
+ if (await getFreePortForWildcard(candidate) === candidate) {
115
+ return candidate;
116
+ }
117
+ }
118
+ return await getEphemeralLoopbackPort();
119
+ }
100
120
  async function getFreePort(basePort, host = '127.0.0.1', timeoutMs = PORT_PROBE_TIMEOUT_MS) {
101
121
  for (let port = basePort; port <= HIGHEST_PORT; port++) {
102
122
  if (await canListen(port, host, timeoutMs)) {
@@ -105,6 +125,32 @@ async function getFreePort(basePort, host = '127.0.0.1', timeoutMs = PORT_PROBE_
105
125
  }
106
126
  throw new Error(`No open port available from ${host}:${basePort} to ${host}:${HIGHEST_PORT}`);
107
127
  }
128
+ /**
129
+ * Loopback port handed out by the OS for a listener that must not collide with ports the
130
+ * embedding process plans for other services.
131
+ *
132
+ * Probing next to the ports this runtime already owns is not safe: a host that allocates
133
+ * `gateway + 10`/`gateway + 11` (the full integration matrix does) has already reserved
134
+ * the neighbour of our own `api` port for another runtime, and binding it steals that
135
+ * runtime's service.
136
+ */
137
+ async function getEphemeralLoopbackPort() {
138
+ return await new Promise((resolve, reject) => {
139
+ const server = node_net_1.default.createServer();
140
+ server.once('error', reject);
141
+ server.listen(0, '127.0.0.1', () => {
142
+ const address = server.address();
143
+ const port = typeof address === 'object' && address ? address.port : 0;
144
+ server.close((error) => {
145
+ if (error) {
146
+ reject(error);
147
+ return;
148
+ }
149
+ resolve(port);
150
+ });
151
+ });
152
+ });
153
+ }
108
154
  function hasIpv6Address() {
109
155
  return Object.values(node_os_1.default.networkInterfaces()).some((entries) => entries?.some((entry) => entry.family === 'IPv6'));
110
156
  }
@@ -113,6 +159,24 @@ function hasIpv6Address() {
113
159
  * CSS may bind `::` while the API binds `0.0.0.0`, so probing only localhost
114
160
  * can miss an occupied port on the other address family.
115
161
  */
162
+ /**
163
+ * Takes exactly this port or fails.
164
+ *
165
+ * A port that a tunnel console forwards to cannot be substituted: `getFreePortForWildcard`
166
+ * scans upward, which would leave the runtime listening somewhere the tunnel never reaches.
167
+ */
168
+ async function requireFreePortForWildcard(port, timeoutMs = PORT_PROBE_TIMEOUT_MS) {
169
+ if (!Number.isInteger(port) || port <= 0 || port > 65535) {
170
+ throw new Error(`ingress port ${port} is not a valid port number`);
171
+ }
172
+ if (!await canListen(port, '0.0.0.0', timeoutMs)) {
173
+ throw new Error(`ingress port ${port} is already in use; free it or point the tunnel at another port`);
174
+ }
175
+ if (hasIpv6Address() && !await canListen(port, '::', timeoutMs)) {
176
+ throw new Error(`ingress port ${port} is already in use on IPv6; free it or point the tunnel at another port`);
177
+ }
178
+ return port;
179
+ }
116
180
  async function getFreePortForWildcard(basePort, timeoutMs = PORT_PROBE_TIMEOUT_MS) {
117
181
  const probeIpv6 = hasIpv6Address();
118
182
  for (let port = basePort; port <= HIGHEST_PORT; port++) {
@@ -15,6 +15,7 @@ class NodeGatewayRuntimeRunner {
15
15
  runtimeHost: options.runtimeHost,
16
16
  internalAdminAuthSecret: options.internalAdminAuthSecret,
17
17
  clientRemoteAddressResolver: options.clientRemoteAddressResolver,
18
+ ingressPort: options.ingressPort,
18
19
  });
19
20
  gateway.setTargets(options.targets);
20
21
  await gateway.start();
@@ -33,6 +33,11 @@ export interface GatewayRuntimeRunnerStartOptions {
33
33
  supervisor: Supervisor;
34
34
  internalAdminAuthSecret: string;
35
35
  clientRemoteAddressResolver?: (req: http.IncomingMessage) => string | undefined;
36
+ /**
37
+ * Loopback-only ingress listener for remote forwarding paths (tunnels, P2P).
38
+ * Port transport only; socket transport has no remote ingress.
39
+ */
40
+ ingressPort?: number;
36
41
  targets: {
37
42
  css: RuntimeConnectionTarget;
38
43
  api: RuntimeConnectionTarget;
@@ -10,6 +10,7 @@ export interface XpodRuntimePorts {
10
10
  gateway?: number;
11
11
  css?: number;
12
12
  api?: number;
13
+ ingress?: number;
13
14
  }
14
15
  export interface XpodRuntimeSockets {
15
16
  gateway?: string;
@@ -38,7 +38,7 @@ async function runLocalManagedClientP2PE2ESmoke(options = {}) {
38
38
  const { token: serviceToken } = await serviceTokenRepo.createToken({
39
39
  serviceType: 'cloud',
40
40
  serviceId: 'managed-client-smoke',
41
- scopes: ['reachability:read', 'reachability:write'],
41
+ scopes: ['network:read', 'network:write'],
42
42
  });
43
43
  const signalApi = await startSignalApi({
44
44
  nodeRepo,
@@ -0,0 +1,56 @@
1
+ import type { TunnelConfig, TunnelProvider, TunnelSetupOptions, TunnelStatus } from './TunnelProvider';
2
+ /** One tunnel the auto provider may bring up, in the order it is worth trying. */
3
+ export interface AutoTunnelCandidate {
4
+ /** Provider or profile id, used in status and in the failure detail. */
5
+ id: string;
6
+ provider: TunnelProvider;
7
+ }
8
+ export interface AutoTunnelProviderOptions {
9
+ candidates: readonly AutoTunnelCandidate[];
10
+ /**
11
+ * How long one candidate gets to reach `proxy-ready` before the next one is
12
+ * tried. A candidate that is blocked (network policy, rejected credential)
13
+ * usually fails faster than this; the timeout only bounds the silent ones.
14
+ */
15
+ readinessTimeoutMs?: number;
16
+ /** Poll interval while waiting for readiness. */
17
+ pollIntervalMs?: number;
18
+ }
19
+ /**
20
+ * Brings up whichever tunnel actually works.
21
+ *
22
+ * An operator configures the providers they have credentials for; which of them
23
+ * can reach its control plane is a property of the network, not of the list. So
24
+ * the candidates are tried in order and the first one that publishes a proxy
25
+ * wins, with the losers stopped and their reasons kept for the failure report.
26
+ * An explicit selection never goes through here: the runtime registers that
27
+ * provider directly, so a closed or pinned tunnel cannot come back on its own.
28
+ */
29
+ export declare class AutoTunnelProvider implements TunnelProvider {
30
+ readonly name = "auto";
31
+ private readonly logger;
32
+ private readonly candidates;
33
+ private readonly readinessTimeoutMs;
34
+ private readonly pollIntervalMs;
35
+ private configs;
36
+ private active?;
37
+ private started;
38
+ private status;
39
+ /** Why each candidate that did not win was dropped. */
40
+ private readonly attempts;
41
+ constructor(options: AutoTunnelProviderOptions);
42
+ setup(options: TunnelSetupOptions): Promise<TunnelConfig>;
43
+ start(config?: TunnelConfig): Promise<void>;
44
+ stop(): Promise<void>;
45
+ getStatus(): TunnelStatus;
46
+ getEndpoint(): string | undefined;
47
+ cleanup(config: TunnelConfig): Promise<void>;
48
+ /** Id of the candidate currently serving, once one is ready. */
49
+ getActiveId(): string | undefined;
50
+ /** The candidates that were tried, and why the ones that lost did. */
51
+ getAttempts(): readonly string[];
52
+ private waitForReady;
53
+ /** Stop a candidate that lost and stop counting it as started. */
54
+ private dropCandidate;
55
+ private stopLosers;
56
+ }
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AutoTunnelProvider = void 0;
4
+ const global_logger_factory_1 = require("global-logger-factory");
5
+ const TunnelLifecycle_1 = require("./TunnelLifecycle");
6
+ const DEFAULT_READINESS_TIMEOUT_MS = 30_000;
7
+ const DEFAULT_POLL_INTERVAL_MS = 250;
8
+ /**
9
+ * Brings up whichever tunnel actually works.
10
+ *
11
+ * An operator configures the providers they have credentials for; which of them
12
+ * can reach its control plane is a property of the network, not of the list. So
13
+ * the candidates are tried in order and the first one that publishes a proxy
14
+ * wins, with the losers stopped and their reasons kept for the failure report.
15
+ * An explicit selection never goes through here: the runtime registers that
16
+ * provider directly, so a closed or pinned tunnel cannot come back on its own.
17
+ */
18
+ class AutoTunnelProvider {
19
+ constructor(options) {
20
+ this.name = 'auto';
21
+ this.logger = (0, global_logger_factory_1.getLoggerFor)(this);
22
+ this.configs = new Map();
23
+ this.started = [];
24
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('stopped');
25
+ /** Why each candidate that did not win was dropped. */
26
+ this.attempts = [];
27
+ this.candidates = options.candidates;
28
+ this.readinessTimeoutMs = options.readinessTimeoutMs ?? DEFAULT_READINESS_TIMEOUT_MS;
29
+ this.pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
30
+ }
31
+ async setup(options) {
32
+ this.configs = new Map();
33
+ for (const candidate of this.candidates) {
34
+ try {
35
+ this.configs.set(candidate.id, await candidate.provider.setup(options));
36
+ }
37
+ catch (error) {
38
+ this.attempts.push(`${candidate.id}: ${describeError(error)}`);
39
+ this.logger.warn(`Tunnel candidate ${candidate.id} could not be prepared: ${describeError(error)}`);
40
+ }
41
+ }
42
+ // The driver round-trips this config back into `start`, which drives the
43
+ // candidates itself, so it only has to describe the requested origin.
44
+ const first = this.candidates[0];
45
+ const config = first ? this.configs.get(first.id) : undefined;
46
+ return config ?? {
47
+ subdomain: options.subdomain,
48
+ provider: 'cloudflare',
49
+ endpoint: '',
50
+ originUrl: `${options.localProtocol ?? 'http'}://127.0.0.1:${options.localPort}`,
51
+ };
52
+ }
53
+ async start(config) {
54
+ void config;
55
+ for (const candidate of this.candidates) {
56
+ const candidateConfig = this.configs.get(candidate.id);
57
+ if (!candidateConfig) {
58
+ continue;
59
+ }
60
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('process-started', { endpoint: candidate.provider.getEndpoint() });
61
+ try {
62
+ this.started.push(candidate);
63
+ await candidate.provider.start(candidateConfig);
64
+ const ready = await this.waitForReady(candidate.provider);
65
+ if (ready) {
66
+ this.active = candidate;
67
+ this.status = withCandidate(candidate, candidate.provider.getStatus());
68
+ this.logger.info(`Tunnel ready through ${candidate.id}`);
69
+ await this.stopLosers(candidate);
70
+ return;
71
+ }
72
+ this.attempts.push(`${candidate.id}: ${describeStatus(candidate.provider.getStatus())}`);
73
+ this.logger.warn(`Tunnel candidate ${candidate.id} did not become ready; trying the next one`);
74
+ await this.dropCandidate(candidate);
75
+ }
76
+ catch (error) {
77
+ this.attempts.push(`${candidate.id}: ${describeError(error)}`);
78
+ this.logger.warn(`Tunnel candidate ${candidate.id} failed: ${describeError(error)}`);
79
+ await this.dropCandidate(candidate);
80
+ }
81
+ }
82
+ // Nothing worked: report which candidates were tried and why, so a caller
83
+ // never has to guess whether the tunnel is off or merely unreachable.
84
+ const detail = this.attempts.length > 0
85
+ ? this.attempts.join('; ')
86
+ : 'no tunnel provider is configured';
87
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('failed', { error: `no-tunnel-candidate-ready: ${detail}` });
88
+ }
89
+ async stop() {
90
+ const targets = this.started;
91
+ this.started = [];
92
+ this.active = undefined;
93
+ await Promise.all(targets.map(async (candidate) => {
94
+ await candidate.provider.stop().catch((error) => {
95
+ this.logger.warn(`Stopping tunnel candidate ${candidate.id} failed: ${describeError(error)}`);
96
+ });
97
+ }));
98
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('stopped');
99
+ }
100
+ getStatus() {
101
+ if (!this.active) {
102
+ return this.status;
103
+ }
104
+ const current = this.active.provider.getStatus();
105
+ // A tunnel that was ready and then died is still the active one, so its
106
+ // failure is what callers must see - never a stale "connected".
107
+ return withCandidate(this.active, current);
108
+ }
109
+ getEndpoint() {
110
+ return this.active?.provider.getEndpoint();
111
+ }
112
+ async cleanup(config) {
113
+ await Promise.all(this.candidates.map(async (candidate) => {
114
+ await candidate.provider.cleanup(config).catch((error) => {
115
+ this.logger.warn(`Cleaning up tunnel candidate ${candidate.id} failed: ${describeError(error)}`);
116
+ });
117
+ }));
118
+ }
119
+ /** Id of the candidate currently serving, once one is ready. */
120
+ getActiveId() {
121
+ return this.active?.id;
122
+ }
123
+ /** The candidates that were tried, and why the ones that lost did. */
124
+ getAttempts() {
125
+ return this.attempts;
126
+ }
127
+ async waitForReady(provider) {
128
+ const deadline = Date.now() + this.readinessTimeoutMs;
129
+ while (Date.now() < deadline) {
130
+ const status = provider.getStatus();
131
+ if (status.stage === 'proxy-ready' || status.connected) {
132
+ return true;
133
+ }
134
+ if (status.stage === 'failed') {
135
+ return false;
136
+ }
137
+ await delay(this.pollIntervalMs);
138
+ }
139
+ return false;
140
+ }
141
+ /** Stop a candidate that lost and stop counting it as started. */
142
+ async dropCandidate(candidate) {
143
+ await candidate.provider.stop().catch((error) => {
144
+ this.logger.warn(`Stopping tunnel candidate ${candidate.id} failed: ${describeError(error)}`);
145
+ });
146
+ this.started = this.started.filter((started) => started.id !== candidate.id);
147
+ }
148
+ async stopLosers(winner) {
149
+ await Promise.all(this.started
150
+ .filter((candidate) => candidate.id !== winner.id)
151
+ .map(async (candidate) => {
152
+ await candidate.provider.stop().catch(() => undefined);
153
+ }));
154
+ this.started = [winner];
155
+ }
156
+ }
157
+ exports.AutoTunnelProvider = AutoTunnelProvider;
158
+ /**
159
+ * The winning candidate's own status, with its error text attributed to the
160
+ * profile id the operator configured rather than to the provider class name.
161
+ */
162
+ function withCandidate(candidate, status) {
163
+ const stage = status.stage ?? (status.connected ? 'proxy-ready' : 'process-started');
164
+ const error = status.error ? `${candidate.id}: ${status.error}` : undefined;
165
+ return (0, TunnelLifecycle_1.createTunnelStatus)(stage, {
166
+ ...status,
167
+ ...(error ? { error } : {}),
168
+ });
169
+ }
170
+ function describeStatus(status) {
171
+ return status.error ?? status.stage ?? (status.connected ? 'connected' : 'unknown');
172
+ }
173
+ function describeError(error) {
174
+ return error instanceof Error ? error.message : String(error);
175
+ }
176
+ function delay(ms) {
177
+ return new Promise((resolve) => {
178
+ setTimeout(resolve, ms);
179
+ });
180
+ }
181
+ //# sourceMappingURL=AutoTunnelProvider.js.map
@@ -10,6 +10,8 @@ export interface LocalTunnelProviderOptions {
10
10
  publicUrl?: string;
11
11
  /** cloudflared 可执行文件路径 (默认 'cloudflared') */
12
12
  cloudflaredPath?: string;
13
+ /** 等待代理发布的毫秒数;超时后状态为 failed,而不是"仍在连接" */
14
+ connectTimeoutMs?: number;
13
15
  }
14
16
  /**
15
17
  * Local Tunnel Provider
@@ -28,6 +30,7 @@ export declare class LocalTunnelProvider implements TunnelProvider {
28
30
  private readonly tunnelToken;
29
31
  private readonly publicUrl?;
30
32
  private readonly cloudflaredPath;
33
+ private readonly connectTimeoutMs;
31
34
  private process;
32
35
  private status;
33
36
  private currentConfig;
@@ -46,6 +49,8 @@ export declare class LocalTunnelProvider implements TunnelProvider {
46
49
  /**
47
50
  * 解析并打印 cloudflared 日志
48
51
  */
52
+ /** Set when the dashboard's origin port and this runtime's ingress port disagree. */
53
+ private originMismatch?;
49
54
  private logOutput;
50
55
  /**
51
56
  * 停止隧道
@@ -86,3 +91,13 @@ export declare class LocalTunnelProvider implements TunnelProvider {
86
91
  */
87
92
  isManagedByUs(): boolean;
88
93
  }
94
+ /**
95
+ * The origin a remotely-managed tunnel declares for its hostname.
96
+ *
97
+ * Both halves are reported: pointing the dashboard at `https://localhost:<port>` while this
98
+ * runtime serves plain HTTP there fails the TLS handshake, and the edge shows only a 502.
99
+ */
100
+ export declare function readDashboardOrigin(output: string): {
101
+ scheme: string;
102
+ port: number;
103
+ } | undefined;
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LocalTunnelProvider = void 0;
4
+ exports.readDashboardOrigin = readDashboardOrigin;
4
5
  const node_child_process_1 = require("node:child_process");
5
6
  const global_logger_factory_1 = require("global-logger-factory");
7
+ const TunnelLifecycle_1 = require("./TunnelLifecycle");
6
8
  /** cloudflared metrics 端口 */
7
9
  const CLOUDFLARED_METRICS_PORT = 33863;
8
10
  /**
@@ -31,6 +33,7 @@ class LocalTunnelProvider {
31
33
  this.tunnelToken = options.tunnelToken;
32
34
  this.publicUrl = normalizePublicEndpoint(options.publicUrl);
33
35
  this.cloudflaredPath = options.cloudflaredPath ?? 'cloudflared';
36
+ this.connectTimeoutMs = options.connectTimeoutMs ?? 30_000;
34
37
  }
35
38
  /**
36
39
  * Local 模式不需要 setup,直接返回基于 Token 的配置
@@ -71,7 +74,7 @@ class LocalTunnelProvider {
71
74
  throw new Error('Tunnel token is required');
72
75
  }
73
76
  this.logger.info('Starting cloudflared tunnel...');
74
- this.status = { running: true, connected: false };
77
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('process-started', { endpoint: this.status.endpoint });
75
78
  this.managedByUs = true;
76
79
  const args = [
77
80
  'tunnel',
@@ -92,10 +95,13 @@ class LocalTunnelProvider {
92
95
  if (output) {
93
96
  this.logOutput(output);
94
97
  }
95
- // 检测连接成功
96
- if (output.includes('Connection registered') || output.includes('Registered tunnel connection')) {
97
- this.status.connected = true;
98
- this.status.lastHeartbeat = new Date();
98
+ // 检测连接成功:只有连接注册成功才代表代理已发布
99
+ if (output.includes('Registered tunnel connection') || output.includes('Connection registered')) {
100
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('proxy-ready', {
101
+ endpoint: this.status.endpoint,
102
+ lastHeartbeat: new Date(),
103
+ error: this.status.error,
104
+ });
99
105
  this.logger.info('Tunnel connected successfully');
100
106
  }
101
107
  });
@@ -106,10 +112,31 @@ class LocalTunnelProvider {
106
112
  this.logOutput(output);
107
113
  // 检测连接成功
108
114
  if (output.includes('Registered tunnel connection') || output.includes('Connection registered')) {
109
- this.status.connected = true;
110
- this.status.lastHeartbeat = new Date();
115
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('proxy-ready', {
116
+ endpoint: this.status.endpoint,
117
+ lastHeartbeat: new Date(),
118
+ error: this.status.error ?? this.originMismatch,
119
+ });
111
120
  // logOutput 已经打印了信息,这里不需要重复打印
112
121
  }
122
+ // A remotely-managed tunnel forwards to the port the dashboard declares, which is
123
+ // not the port we dialled if the operator never matched them: naming that mismatch
124
+ // is the difference between "the entry is unreachable" and a fixable configuration.
125
+ const declared = readDashboardOrigin(output);
126
+ if (declared !== undefined) {
127
+ const dialled = this.currentConfig?.originUrl;
128
+ // Scheme matters as much as the port: an https service pointed at this plain-HTTP
129
+ // ingress listener fails the handshake, which the edge reports as a bare 502.
130
+ this.originMismatch = dialled && (declared.port !== readPort(dialled) || declared.scheme !== readScheme(dialled))
131
+ ? `origin-mismatch:dashboard=${declared.scheme}://localhost:${declared.port},runtime=${dialled}`
132
+ : undefined;
133
+ if (this.originMismatch) {
134
+ this.logger.warn(`The Cloudflare dashboard forwards this hostname to ${declared.scheme}://localhost:${declared.port}, but this runtime serves ${dialled}: set the dashboard service to that address`);
135
+ }
136
+ if (this.status.stage === 'proxy-ready') {
137
+ this.status.error = this.originMismatch ?? this.status.error;
138
+ }
139
+ }
113
140
  // 检测错误
114
141
  if (output.includes('ERR') || output.includes('failed')) {
115
142
  this.status.error = output;
@@ -118,24 +145,25 @@ class LocalTunnelProvider {
118
145
  });
119
146
  this.process.on('exit', (code) => {
120
147
  this.logger.info(`Process exited with code ${code}`);
121
- this.status = { running: false, connected: false };
148
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('failed', {
149
+ endpoint: this.status.endpoint,
150
+ error: this.status.error ?? (code === 0 ? 'cloudflared-exited' : `cloudflared exited with code ${code}`),
151
+ });
122
152
  this.process = null;
123
153
  this.managedByUs = false;
124
154
  });
125
155
  this.process.on('error', (error) => {
126
- this.logger.error(`Failed to start: ${error.message}`);
127
- this.status = { running: false, connected: false, error: error.message };
156
+ const described = (0, TunnelLifecycle_1.describeSpawnError)('cloudflare', this.cloudflaredPath, error);
157
+ this.logger.error(`Failed to start: ${described}`);
158
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('failed', { endpoint: this.status.endpoint, error: described });
128
159
  this.process = null;
129
160
  this.managedByUs = false;
130
161
  });
131
162
  this.currentConfig = actualConfig;
132
163
  this.status.endpoint = actualConfig.endpoint;
133
164
  // 等待连接建立
134
- await this.waitForConnection();
165
+ await this.waitForConnection(this.connectTimeoutMs);
135
166
  }
136
- /**
137
- * 解析并打印 cloudflared 日志
138
- */
139
167
  logOutput(raw) {
140
168
  const lines = raw.split('\n');
141
169
  for (const line of lines) {
@@ -174,7 +202,8 @@ class LocalTunnelProvider {
174
202
  async stop() {
175
203
  if (!this.managedByUs) {
176
204
  this.logger.info('Not managed by us, skipping stop');
177
- this.status = { running: false, connected: false };
205
+ // Keep the last error: stopping must not launder a failed tunnel into a clean one.
206
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('stopped', { endpoint: this.status.endpoint, error: this.status.error });
178
207
  return;
179
208
  }
180
209
  if (this.process) {
@@ -195,7 +224,7 @@ class LocalTunnelProvider {
195
224
  this.process = null;
196
225
  this.logger.info('Tunnel stopped');
197
226
  }
198
- this.status = { running: false, connected: false };
227
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('stopped', { endpoint: this.status.endpoint, error: this.status.error });
199
228
  this.managedByUs = false;
200
229
  }
201
230
  /**
@@ -280,8 +309,13 @@ class LocalTunnelProvider {
280
309
  }
281
310
  await new Promise((r) => setTimeout(r, 500));
282
311
  }
283
- // 超时不抛错,cloudflared 可能还在连接中
284
- this.logger.warn('Connection timeout, tunnel may still be connecting...');
312
+ // A timeout is a fact the caller has to see: the process exists but nothing is
313
+ // published yet, so the tunnel is not ready.
314
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('failed', {
315
+ endpoint: this.status.endpoint,
316
+ error: this.status.error ?? 'cloudflared-connect-timeout',
317
+ });
318
+ this.logger.warn('cloudflared did not register a tunnel connection before the timeout');
285
319
  }
286
320
  /**
287
321
  * 获取是否由我们管理
@@ -306,4 +340,39 @@ function normalizePublicEndpoint(value) {
306
340
  return value.trim();
307
341
  }
308
342
  }
343
+ /**
344
+ * The origin a remotely-managed tunnel declares for its hostname.
345
+ *
346
+ * Both halves are reported: pointing the dashboard at `https://localhost:<port>` while this
347
+ * runtime serves plain HTTP there fails the TLS handshake, and the edge shows only a 502.
348
+ */
349
+ function readDashboardOrigin(output) {
350
+ const match = /"service"\s*:\s*"(https?):\/\/(?:localhost|127\.0\.0\.1):(\d+)/iu.exec(output)
351
+ ?? /ingress[^\n]*service["']?\s*[:=]\s*["']?(https?):\/\/(?:localhost|127\.0\.0\.1):(\d+)/iu.exec(output);
352
+ if (!match) {
353
+ return undefined;
354
+ }
355
+ const port = Number.parseInt(match[2], 10);
356
+ return Number.isInteger(port) && port > 0 ? { scheme: match[1].toLowerCase(), port } : undefined;
357
+ }
358
+ function readPort(value) {
359
+ if (!value)
360
+ return undefined;
361
+ try {
362
+ return Number.parseInt(new URL(value).port, 10) || undefined;
363
+ }
364
+ catch {
365
+ return undefined;
366
+ }
367
+ }
368
+ function readScheme(value) {
369
+ if (!value)
370
+ return undefined;
371
+ try {
372
+ return new URL(value).protocol.replace(':', '');
373
+ }
374
+ catch {
375
+ return undefined;
376
+ }
377
+ }
309
378
  //# sourceMappingURL=LocalTunnelProvider.js.map
@@ -43,6 +43,19 @@
43
43
  ]
44
44
  },
45
45
  "comment": "cloudflared 可执行文件路径 (默认 'cloudflared')"
46
+ },
47
+ {
48
+ "@id": "undefineds:dist/tunnel/LocalTunnelProvider.jsonld#LocalTunnelProvider_options_connectTimeoutMs",
49
+ "range": {
50
+ "@type": "ParameterRangeUnion",
51
+ "parameterRangeElements": [
52
+ "xsd:number",
53
+ {
54
+ "@type": "ParameterRangeUndefined"
55
+ }
56
+ ]
57
+ },
58
+ "comment": "等待代理发布的毫秒数;超时后状态为 failed,而不是\"仍在连接\""
46
59
  }
47
60
  ],
48
61
  "memberFields": [
@@ -66,6 +79,10 @@
66
79
  "@id": "undefineds:dist/tunnel/LocalTunnelProvider.jsonld#LocalTunnelProvider__member_cloudflaredPath",
67
80
  "memberFieldName": "cloudflaredPath"
68
81
  },
82
+ {
83
+ "@id": "undefineds:dist/tunnel/LocalTunnelProvider.jsonld#LocalTunnelProvider__member_connectTimeoutMs",
84
+ "memberFieldName": "connectTimeoutMs"
85
+ },
69
86
  {
70
87
  "@id": "undefineds:dist/tunnel/LocalTunnelProvider.jsonld#LocalTunnelProvider__member_process",
71
88
  "memberFieldName": "process"
@@ -94,6 +111,10 @@
94
111
  "@id": "undefineds:dist/tunnel/LocalTunnelProvider.jsonld#LocalTunnelProvider__member_start",
95
112
  "memberFieldName": "start"
96
113
  },
114
+ {
115
+ "@id": "undefineds:dist/tunnel/LocalTunnelProvider.jsonld#LocalTunnelProvider__member_originMismatch",
116
+ "memberFieldName": "originMismatch"
117
+ },
97
118
  {
98
119
  "@id": "undefineds:dist/tunnel/LocalTunnelProvider.jsonld#LocalTunnelProvider__member_logOutput",
99
120
  "memberFieldName": "logOutput"
@@ -156,6 +177,12 @@
156
177
  "value": {
157
178
  "@id": "undefineds:dist/tunnel/LocalTunnelProvider.jsonld#LocalTunnelProvider_options_cloudflaredPath"
158
179
  }
180
+ },
181
+ {
182
+ "keyRaw": "connectTimeoutMs",
183
+ "value": {
184
+ "@id": "undefineds:dist/tunnel/LocalTunnelProvider.jsonld#LocalTunnelProvider_options_connectTimeoutMs"
185
+ }
159
186
  }
160
187
  ]
161
188
  }
@@ -31,6 +31,8 @@ export declare class NgrokTunnelProvider implements TunnelProvider {
31
31
  private status;
32
32
  private currentConfig;
33
33
  private managedByUs;
34
+ /** Origin this instance asked ngrok to expose; the agent answer must match it. */
35
+ private expectedLocalOrigin?;
34
36
  constructor(options?: NgrokTunnelProviderOptions);
35
37
  setup(options: TunnelSetupOptions): Promise<TunnelConfig>;
36
38
  start(config?: TunnelConfig): Promise<void>;
@@ -44,3 +46,5 @@ export declare class NgrokTunnelProvider implements TunnelProvider {
44
46
  private waitForConnection;
45
47
  private discoverEndpointFromAgentApi;
46
48
  }
49
+ /** Loopback endpoints belong to the agent itself, never to a published tunnel. */
50
+ export declare function isLocalAgentUrl(url: string): boolean;