@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
@@ -5,12 +5,20 @@
5
5
  * 使用 SakuraFRP 提供隧道服务
6
6
  * 用于没有公网 IP 的 Local 节点
7
7
  *
8
- * 需要用户在 SakuraFRP 控制台创建隧道并获取 Token
8
+ * 凭据就是控制台「配置文件」里那串启动参数 (`<访问密钥>:<隧道ID>`)。公网入口
9
+ * **不由用户声明**:控制台只让用户选节点和本地端口,访问地址是平台分配的,因此
10
+ * provider 用同一个凭据向 SakuraFrp 开放 API 查询分配结果(节点地址 + 远程端口),
11
+ * 声明字段只作为 API 不可用时的可选兜底。
9
12
  */
10
13
  Object.defineProperty(exports, "__esModule", { value: true });
11
14
  exports.SakuraFrpTunnelProvider = void 0;
15
+ exports.resolveSakuraAssignedLocalPort = resolveSakuraAssignedLocalPort;
16
+ exports.parseSakuraCredential = parseSakuraCredential;
12
17
  const node_child_process_1 = require("node:child_process");
13
18
  const global_logger_factory_1 = require("global-logger-factory");
19
+ const TunnelLifecycle_1 = require("./TunnelLifecycle");
20
+ /** Where SakuraFrp assigns each tunnel's public entry. */
21
+ const DEFAULT_SAKURA_API_BASE_URL = 'https://api.natfrp.com/v4';
14
22
  /**
15
23
  * SakuraFRP Tunnel Provider
16
24
  *
@@ -20,6 +28,8 @@ class SakuraFrpTunnelProvider {
20
28
  constructor(options) {
21
29
  this.name = 'sakura-frp';
22
30
  this.logger = (0, global_logger_factory_1.getLoggerFor)(this);
31
+ /** Whether the platform terminates TLS for this entry (auto HTTPS). */
32
+ this.autoHttpsEnabled = false;
23
33
  this.process = null;
24
34
  this.status = {
25
35
  running: false,
@@ -30,7 +40,131 @@ class SakuraFrpTunnelProvider {
30
40
  this.token = options.token;
31
41
  this.publicUrl = normalizePublicEndpoint(options.publicUrl);
32
42
  this.frpcPath = options.frpcPath ?? 'frpc';
43
+ this.connectTimeoutMs = options.connectTimeoutMs ?? 30_000;
33
44
  this.serverAddr = options.serverAddr;
45
+ this.apiBaseUrl = (options.apiBaseUrl ?? DEFAULT_SAKURA_API_BASE_URL).replace(/\/+$/u, '');
46
+ this.fetchImpl = options.fetchImpl ?? fetch;
47
+ }
48
+ /**
49
+ * Reads back the entry the platform assigned to this tunnel.
50
+ *
51
+ * The console never asks for a domain: for a TCP tunnel it assigns a node host and a
52
+ * remote port, and for a bound tunnel it assigns the domain itself. Asking the provider
53
+ * is therefore the only honest way to learn the entry, and a failure to ask changes
54
+ * nothing except that the status stops short of naming an endpoint.
55
+ */
56
+ async discoverEndpoint() {
57
+ const { accessKey, tunnelIds } = parseSakuraCredential(this.token);
58
+ if (!accessKey) {
59
+ return undefined;
60
+ }
61
+ try {
62
+ const tunnels = await this.fetchJson('/tunnels', accessKey);
63
+ if (!Array.isArray(tunnels)) {
64
+ return undefined;
65
+ }
66
+ const selected = tunnelIds.length > 0
67
+ ? tunnels.filter((tunnel) => tunnelIds.includes(String(tunnel?.id ?? '')))
68
+ : tunnels;
69
+ const tunnel = selected[0];
70
+ if (!tunnel) {
71
+ return undefined;
72
+ }
73
+ const remote = typeof tunnel.remote === 'string' ? tunnel.remote.trim() : '';
74
+ if (!remote) {
75
+ return undefined;
76
+ }
77
+ // Whether the platform terminates TLS is decided before any address lookup, because
78
+ // it also governs the entry the client prints in its own log.
79
+ this.autoHttpsEnabled = /auto_https\s*=\s*(auto|on|true)/iu.test(tunnel.extra ?? '')
80
+ || tunnel.type === 'https';
81
+ // A bound domain arrives as the remote value itself; a TCP tunnel arrives as a
82
+ // remote port and needs the node's host to become an address.
83
+ if (/[a-z]/iu.test(remote) && !remote.startsWith(':')) {
84
+ return `https://${remote.replace(/^https?:\/\//u, '')}/`;
85
+ }
86
+ const nodeHost = await this.resolveNodeHost(tunnel.node, accessKey);
87
+ // A TCP tunnel without auto-HTTPS leaves the entry as plain HTTP. SakuraFrp refuses
88
+ // plain HTTP to a web service on its mainland nodes by policy ("网页(国内节点)必须"
89
+ // enable it, per their own auto-HTTPS guide), so claiming such a URL would be a
90
+ // reachability claim the platform itself rejects.
91
+ if (!this.autoHttpsEnabled) {
92
+ this.discoveryBlockedReason = nodeHost
93
+ ? `sakura-auto-https-required: enable 自动 HTTPS in the SakuraFrp console for ${nodeHost}:${remote}`
94
+ : `sakura-auto-https-required: enable 自动 HTTPS in the SakuraFrp console for the entry on port ${remote}`;
95
+ return undefined;
96
+ }
97
+ if (!nodeHost) {
98
+ // No API host: the client's own log names the entry, and the reason is not a policy
99
+ // block, so leave discoveryBlockedReason unset and let the log answer.
100
+ return undefined;
101
+ }
102
+ return `https://${nodeHost}:${remote}/`;
103
+ }
104
+ catch (error) {
105
+ this.logger.warn(`Could not read the assigned SakuraFrp endpoint: ${error.message}`);
106
+ return undefined;
107
+ }
108
+ }
109
+ /**
110
+ * Builds the parameter frpc needs, completing a bare access key with the tunnel it owns.
111
+ *
112
+ * `-f` accepts `<访问密钥>:<隧道ID>`; an operator who pasted only the access key would
113
+ * otherwise get `Bad fetch parameter` even though discovery can read the tunnel with that
114
+ * same key. Completion is only safe when the answer is unambiguous.
115
+ */
116
+ async resolveClientCredential() {
117
+ const { accessKey, tunnelIds } = parseSakuraCredential(this.token);
118
+ if (!accessKey || tunnelIds.length > 0) {
119
+ return undefined;
120
+ }
121
+ try {
122
+ const tunnels = await this.fetchJson('/tunnels', accessKey);
123
+ if (!Array.isArray(tunnels) || tunnels.length !== 1) {
124
+ if (Array.isArray(tunnels) && tunnels.length > 1) {
125
+ this.logger.warn(`SakuraFrp credential holds no tunnel id and the account has ${tunnels.length} tunnels; use the console startup parameter`);
126
+ }
127
+ return undefined;
128
+ }
129
+ const completed = `${accessKey}:${tunnels[0]?.id}`;
130
+ this.logger.info(`SakuraFrp credential completed with the single tunnel id ${tunnels[0]?.id}`);
131
+ return completed;
132
+ }
133
+ catch {
134
+ return undefined;
135
+ }
136
+ }
137
+ async resolveNodeHost(node, accessKey) {
138
+ if (node === undefined) {
139
+ return undefined;
140
+ }
141
+ const nodes = await this.fetchJson('/nodes', accessKey);
142
+ const record = nodes?.[String(node)];
143
+ const host = record?.host?.trim();
144
+ if (!host) {
145
+ return undefined;
146
+ }
147
+ return host.replace(/^https?:\/\//u, '').replace(/\/+$/u, '');
148
+ }
149
+ async fetchJson(path, accessKey) {
150
+ const response = await this.fetchImpl(`${this.apiBaseUrl}${path}`, {
151
+ headers: { authorization: `Bearer ${accessKey}`, accept: 'application/json' },
152
+ signal: AbortSignal.timeout(10_000),
153
+ });
154
+ if (!response.ok) {
155
+ throw new Error(`${path} answered ${response.status}`);
156
+ }
157
+ return await response.json();
158
+ }
159
+ /**
160
+ * The endpoint to report: what the platform assigned, else what the client printed, else
161
+ * what was declared. Nothing is invented when no source names an entry.
162
+ */
163
+ currentEndpoint() {
164
+ return normalizePublicEndpoint(this.discoveredEndpoint)
165
+ ?? this.logEndpoint
166
+ ?? this.publicUrl
167
+ ?? this.status.endpoint;
34
168
  }
35
169
  /**
36
170
  * Setup: 解析 Token 获取配置
@@ -40,7 +174,7 @@ class SakuraFrpTunnelProvider {
40
174
  // 这里返回基本配置,实际配置由 frpc 从 Token 获取
41
175
  const config = {
42
176
  subdomain: 'sakura',
43
- provider: 'sakura-frp',
177
+ provider: 'sakura_frp',
44
178
  endpoint: this.publicUrl ?? '',
45
179
  tunnelToken: this.token,
46
180
  };
@@ -53,14 +187,30 @@ class SakuraFrpTunnelProvider {
53
187
  async start(config) {
54
188
  const actualConfig = config ?? {
55
189
  subdomain: 'sakura',
56
- provider: 'sakura-frp',
190
+ provider: 'sakura_frp',
57
191
  endpoint: this.publicUrl ?? '',
58
192
  tunnelToken: this.token,
59
193
  };
60
- // 检测是否已经在运行
194
+ // Ask the platform where this tunnel is reachable before claiming any endpoint.
195
+ // The same answer completes the client parameter: the console's access key alone is not
196
+ // enough for `frpc -f`, which needs `<访问密钥>:<隧道ID>`.
197
+ this.discoveryBlockedReason = undefined;
198
+ this.discoveredEndpoint = await this.discoverEndpoint();
199
+ this.clientCredential = await this.resolveClientCredential();
200
+ if (this.discoveredEndpoint) {
201
+ this.logger.info(`SakuraFrp assigned ${this.discoveredEndpoint}`);
202
+ }
203
+ else if (this.discoveryBlockedReason) {
204
+ this.logger.warn(this.discoveryBlockedReason);
205
+ }
206
+ // A foreign frpc is not ours to adopt: another instance's tunnel would be reported as
207
+ // this provider's readiness and its stop would kill a process we do not own.
61
208
  if (this.isFrpcRunning()) {
62
- this.logger.info('frpc already running externally');
63
- this.status = { running: true, connected: true };
209
+ this.logger.warn('Another frpc process is already running; refusing to take it over');
210
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('failed', {
211
+ endpoint: this.currentEndpoint(),
212
+ error: 'frpc-already-running',
213
+ });
64
214
  this.currentConfig = actualConfig;
65
215
  this.managedByUs = false;
66
216
  return;
@@ -69,12 +219,12 @@ class SakuraFrpTunnelProvider {
69
219
  this.logger.info('Already running (managed by us)');
70
220
  return;
71
221
  }
72
- const token = actualConfig.tunnelToken ?? this.token;
222
+ const token = this.clientCredential ?? actualConfig.tunnelToken ?? this.token;
73
223
  if (!token) {
74
224
  throw new Error('SakuraFRP token is required');
75
225
  }
76
226
  this.logger.info('Starting SakuraFRP tunnel...');
77
- this.status = { running: true, connected: false };
227
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('process-started', { endpoint: this.currentEndpoint() });
78
228
  this.managedByUs = true;
79
229
  // SakuraFRP 使用 frpc 客户端
80
230
  // 命令格式: frpc -f <token>
@@ -101,32 +251,67 @@ class SakuraFrpTunnelProvider {
101
251
  });
102
252
  this.process.on('exit', (code) => {
103
253
  this.logger.info(`frpc exited with code ${code}`);
104
- this.status = { running: false, connected: false };
254
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('failed', {
255
+ endpoint: this.currentEndpoint(),
256
+ error: this.status.error ?? (code === 0 ? 'frpc-exited' : `frpc exited with code ${code}`),
257
+ });
105
258
  this.process = null;
106
259
  this.managedByUs = false;
107
260
  });
108
261
  this.process.on('error', (error) => {
109
- this.logger.error(`Failed to start frpc: ${error.message}`);
110
- this.status = { running: false, connected: false, error: error.message };
262
+ const described = (0, TunnelLifecycle_1.describeSpawnError)('sakura-frp', this.frpcPath, error);
263
+ this.logger.error(`Failed to start frpc: ${described}`);
264
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('failed', { endpoint: this.currentEndpoint(), error: described });
111
265
  this.process = null;
112
266
  this.managedByUs = false;
113
267
  });
114
268
  this.currentConfig = actualConfig;
115
269
  // 等待连接
116
- await this.waitForConnection();
270
+ await this.waitForConnection(this.connectTimeoutMs);
117
271
  }
118
272
  checkConnectionStatus(output) {
119
- // 检测连接成功的关键字
120
- if (output.includes('start proxy success') ||
121
- output.includes('login to server success') ||
122
- output.includes('tunnel running')) {
123
- this.status.connected = true;
124
- this.status.lastHeartbeat = new Date();
273
+ const lower = output.toLowerCase();
274
+ // The vendor client logs Chinese and the upstream client logs English; both vocabularies
275
+ // must count, otherwise a healthy official tunnel never leaves control-connected.
276
+ const proxyReady = lower.includes('start proxy success')
277
+ || lower.includes('tunnel running')
278
+ || output.includes('隧道启动成功');
279
+ const controlConnected = lower.includes('login to server success')
280
+ || output.includes('连接节点成功');
281
+ // The official client prints the assigned entry ("使用 >>host:port<< 连接你的隧道"), which
282
+ // is the only source for nodes whose API record publishes no host.
283
+ const assigned = /使用\s*>>([^<]+)<<|连接方式[::]?\s*([\w.-]+:\d+)/u.exec(output);
284
+ if (assigned && this.autoHttpsEnabled) {
285
+ const address = (assigned[1] ?? assigned[2]).trim().replace(/^https?:\/\//u, '');
286
+ this.logEndpoint = `https://${address.replace(/\/+$/u, '')}/`;
287
+ }
288
+ // 代理已发布才算就绪
289
+ if (proxyReady) {
290
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('proxy-ready', {
291
+ endpoint: this.currentEndpoint(),
292
+ lastHeartbeat: new Date(),
293
+ // The proxy is up, but an entry the platform refuses to serve is not an entry.
294
+ error: this.discoveryBlockedReason ?? this.status.error,
295
+ });
125
296
  this.logger.info('SakuraFRP tunnel connected');
126
297
  }
127
- // 检测错误
128
- if (output.includes('error') || output.includes('failed')) {
129
- this.status.error = output;
298
+ else if (controlConnected && this.status.stage !== 'proxy-ready') {
299
+ // 控制连接成功说明凭据可用,但代理还没起来
300
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('control-connected', {
301
+ endpoint: this.currentEndpoint(),
302
+ error: this.status.error,
303
+ });
304
+ }
305
+ // 检测错误:代理启动失败必须撤销"已连接"
306
+ if (lower.includes('start proxy error') || lower.includes('start error')) {
307
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('failed', {
308
+ endpoint: this.currentEndpoint(),
309
+ error: output,
310
+ });
311
+ return;
312
+ }
313
+ if (lower.includes('error') || lower.includes('failed')) {
314
+ this.status = { ...this.status, error: output };
130
315
  }
131
316
  }
132
317
  /**
@@ -135,7 +320,7 @@ class SakuraFrpTunnelProvider {
135
320
  async stop() {
136
321
  if (!this.managedByUs) {
137
322
  this.logger.info('Not managed by us, skipping stop');
138
- this.status = { running: false, connected: false };
323
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('stopped', { endpoint: this.status.endpoint, error: this.status.error });
139
324
  return;
140
325
  }
141
326
  if (this.process) {
@@ -155,14 +340,14 @@ class SakuraFrpTunnelProvider {
155
340
  this.process = null;
156
341
  this.logger.info('SakuraFRP tunnel stopped');
157
342
  }
158
- this.status = { running: false, connected: false };
343
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('stopped', { endpoint: this.status.endpoint, error: this.status.error });
159
344
  this.managedByUs = false;
160
345
  }
161
346
  getStatus() {
162
347
  return { ...this.status };
163
348
  }
164
349
  getEndpoint() {
165
- return this.currentConfig?.endpoint;
350
+ return this.currentEndpoint();
166
351
  }
167
352
  async cleanup(_config) {
168
353
  await this.stop();
@@ -198,13 +383,71 @@ class SakuraFrpTunnelProvider {
198
383
  }
199
384
  await new Promise((r) => setTimeout(r, 500));
200
385
  }
201
- this.logger.warn('Connection timeout, tunnel may still be connecting...');
386
+ // Timeout is a visible failure: frpc is running but no proxy was published.
387
+ this.status = (0, TunnelLifecycle_1.createTunnelStatus)('failed', {
388
+ endpoint: this.currentEndpoint(),
389
+ error: this.status.error ?? 'frpc-connect-timeout',
390
+ });
391
+ this.logger.warn('frpc did not publish a proxy before the timeout');
392
+ throw new Error('SakuraFRP connection timeout');
202
393
  }
203
394
  isManagedByUs() {
204
395
  return this.managedByUs;
205
396
  }
206
397
  }
207
398
  exports.SakuraFrpTunnelProvider = SakuraFrpTunnelProvider;
399
+ /**
400
+ * The local port the SakuraFrp console told the tunnel to forward to.
401
+ *
402
+ * The console already owns this fact, and the provider reads the same API for the public
403
+ * entry, so the runtime must take the port from there instead of asking the operator to type
404
+ * it a second time.
405
+ */
406
+ async function resolveSakuraAssignedLocalPort(token, options = {}) {
407
+ const { accessKey, tunnelIds } = parseSakuraCredential(token);
408
+ if (!accessKey) {
409
+ return undefined;
410
+ }
411
+ const base = (options.apiBaseUrl ?? DEFAULT_SAKURA_API_BASE_URL).replace(/\/+$/u, '');
412
+ const doFetch = options.fetchImpl ?? fetch;
413
+ try {
414
+ const response = await doFetch(`${base}/tunnels`, {
415
+ headers: { authorization: `Bearer ${accessKey}`, accept: 'application/json' },
416
+ signal: AbortSignal.timeout(10_000),
417
+ });
418
+ if (!response.ok) {
419
+ return undefined;
420
+ }
421
+ const tunnels = await response.json();
422
+ if (!Array.isArray(tunnels)) {
423
+ return undefined;
424
+ }
425
+ const selected = tunnelIds.length > 0
426
+ ? tunnels.find((tunnel) => tunnelIds.includes(String(tunnel?.id ?? '')))
427
+ : tunnels[0];
428
+ const port = Number(selected?.local_port);
429
+ return Number.isInteger(port) && port > 0 && port <= 65535 ? port : undefined;
430
+ }
431
+ catch {
432
+ return undefined;
433
+ }
434
+ }
435
+ /** Splits the console's startup parameter into the access key and the tunnel ids. */
436
+ function parseSakuraCredential(value) {
437
+ const raw = value?.trim();
438
+ if (!raw) {
439
+ return { tunnelIds: [] };
440
+ }
441
+ const separator = raw.indexOf(':');
442
+ if (separator < 0) {
443
+ // Older setups stored the bare access key; the platform then decides the tunnel.
444
+ return { accessKey: raw, tunnelIds: [] };
445
+ }
446
+ return {
447
+ accessKey: raw.slice(0, separator).trim() || undefined,
448
+ tunnelIds: raw.slice(separator + 1).split(',').map((id) => id.trim()).filter(Boolean),
449
+ };
450
+ }
208
451
  function normalizePublicEndpoint(value) {
209
452
  if (!value?.trim()) {
210
453
  return undefined;
@@ -0,0 +1,14 @@
1
+ import type { TunnelStage, TunnelStatus } from './TunnelProvider';
2
+ /**
3
+ * Tunnel readiness is a sequence, not a boolean.
4
+ *
5
+ * A provider process that started is not a control connection, a control connection is not
6
+ * a published proxy, and a published proxy is not proof that the Gateway is reachable from
7
+ * outside. These helpers keep every provider reporting the same four facts so the UI and
8
+ * the diagnostics never turn "we spawned something" into "the tunnel is up".
9
+ */
10
+ export declare function createTunnelStatus(stage: TunnelStage, patch?: Partial<TunnelStatus>): TunnelStatus;
11
+ /** Keeps the previous error visible while a provider transitions through a restart. */
12
+ export declare function mergeTunnelError(previous: string | undefined, next: string | undefined): string | undefined;
13
+ /** Recognizes a missing client binary, which is a deployment fact, not a network failure. */
14
+ export declare function describeSpawnError(provider: string, binary: string, error: unknown): string;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createTunnelStatus = createTunnelStatus;
4
+ exports.mergeTunnelError = mergeTunnelError;
5
+ exports.describeSpawnError = describeSpawnError;
6
+ /**
7
+ * Tunnel readiness is a sequence, not a boolean.
8
+ *
9
+ * A provider process that started is not a control connection, a control connection is not
10
+ * a published proxy, and a published proxy is not proof that the Gateway is reachable from
11
+ * outside. These helpers keep every provider reporting the same four facts so the UI and
12
+ * the diagnostics never turn "we spawned something" into "the tunnel is up".
13
+ */
14
+ function createTunnelStatus(stage, patch = {}) {
15
+ return {
16
+ running: stage !== 'stopped' && stage !== 'failed',
17
+ connected: stage === 'proxy-ready',
18
+ stage,
19
+ ...patch,
20
+ };
21
+ }
22
+ /** Keeps the previous error visible while a provider transitions through a restart. */
23
+ function mergeTunnelError(previous, next) {
24
+ return next ?? previous;
25
+ }
26
+ /** Recognizes a missing client binary, which is a deployment fact, not a network failure. */
27
+ function describeSpawnError(provider, binary, error) {
28
+ const code = typeof error === 'object' && error && 'code' in error ? String(error.code) : '';
29
+ if (code === 'ENOENT') {
30
+ return `binary-missing:${provider}:${binary}`;
31
+ }
32
+ return `spawn-failed:${provider}:${error?.message ?? String(error)}`;
33
+ }
34
+ //# sourceMappingURL=TunnelLifecycle.js.map
@@ -1,6 +1,10 @@
1
+ import { TUNNEL_PROVIDER_IDS, isTunnelProviderId, tunnelProfileCredentialEnvKey, tunnelProviderDescriptor, type ActiveTunnelProvider, type TunnelProviderId } from './TunnelProviderCatalog';
2
+ export { TUNNEL_PROVIDER_IDS };
1
3
  export declare const TUNNEL_PROVIDER_VALUES: readonly ["ngrok", "cloudflare", "sakura_frp", "frp"];
2
- export type TunnelProfileProvider = (typeof TUNNEL_PROVIDER_VALUES)[number];
3
- export type ActiveTunnelProvider = TunnelProfileProvider | 'none';
4
+ export type TunnelProfileProvider = TunnelProviderId;
5
+ export type { ActiveTunnelProvider };
6
+ /** The canonical off value: an explicit "no tunnel" is a decision, not a missing value. */
7
+ export declare const TUNNEL_ACTIVE_PROFILE_NONE = "none";
4
8
  export interface TunnelProfile {
5
9
  id: string;
6
10
  provider: TunnelProfileProvider;
@@ -8,6 +12,14 @@ export interface TunnelProfile {
8
12
  publicUrl?: string;
9
13
  credentialEnvKey?: string;
10
14
  credentialConfigured?: boolean;
15
+ /**
16
+ * Provider parameters as stored by the settings API.
17
+ *
18
+ * They are carried rather than dropped so the runtime never silently loses a value the
19
+ * API accepted, and so a provider that can honour one has it available; a parameter no
20
+ * provider consumes is reported by `unconsumedProfileParameters()` instead of vanishing.
21
+ */
22
+ parameters?: Record<string, string>;
11
23
  }
12
24
  export interface TunnelProfileState {
13
25
  profiles: TunnelProfile[];
@@ -15,8 +27,26 @@ export interface TunnelProfileState {
15
27
  activeProfile?: TunnelProfile;
16
28
  inactiveProfiles: TunnelProfile[];
17
29
  activeProvider: ActiveTunnelProvider;
30
+ /** Why the requested profile is not active; missing when the state is unremarkable. */
31
+ activationError?: string;
18
32
  }
19
33
  type EnvLike = Record<string, string | undefined>;
34
+ /**
35
+ * Resolves the tunnel profile state for a runtime environment.
36
+ *
37
+ * Authority rules (they are what stops a closed tunnel from coming back):
38
+ * - `XPOD_TUNNEL_PROFILES` being **present** is authoritative — an empty list means "no
39
+ * profiles", never "fall back to the legacy keys".
40
+ * - `XPOD_TUNNEL_ACTIVE_PROFILE_ID` being **present** is authoritative — an empty value or
41
+ * `none` means "explicitly off" and suppresses the legacy provider and the auto-pick.
42
+ */
20
43
  export declare function resolveTunnelProfileState(env: EnvLike): TunnelProfileState;
21
44
  export declare function selectActiveTunnelProfile(inputProfiles: readonly TunnelProfile[], activeProfileId?: string): TunnelProfileState;
22
- export {};
45
+ /**
46
+ * Parameters a profile declares that no provider implementation consumes.
47
+ *
48
+ * Reporting them is what keeps the settings form from collecting values with no effect:
49
+ * the fix is either to consume the parameter or to stop declaring the field.
50
+ */
51
+ export declare function unconsumedProfileParameters(profile: Pick<TunnelProfile, 'parameters'>, consumed?: readonly string[]): string[];
52
+ export { isTunnelProviderId, tunnelProviderDescriptor, tunnelProfileCredentialEnvKey };