@undefineds.co/xpod 0.4.10 → 0.4.12

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 (402) hide show
  1. package/config/components-ignore.json +5 -1
  2. package/config/notifications.json +68 -0
  3. package/config/xpod.base.json +9 -11
  4. package/dist/ai/service/AiCredentialSecret.d.ts +30 -0
  5. package/dist/ai/service/AiCredentialSecret.js +120 -0
  6. package/dist/ai/service/CredentialReaderImpl.d.ts +18 -0
  7. package/dist/ai/service/CredentialReaderImpl.js +81 -5
  8. package/dist/ai/service/CredentialReaderImpl.jsonld +42 -2
  9. package/dist/ai/service/EmbeddingModelPolicy.d.ts +79 -0
  10. package/dist/ai/service/EmbeddingModelPolicy.js +134 -0
  11. package/dist/ai/service/EmbeddingProviderError.js +6 -0
  12. package/dist/ai/service/EmbeddingServiceImpl.d.ts +13 -1
  13. package/dist/ai/service/EmbeddingServiceImpl.js +18 -5
  14. package/dist/ai/service/EmbeddingServiceImpl.jsonld +35 -0
  15. package/dist/ai/service/index.d.ts +2 -0
  16. package/dist/ai/service/index.js +2 -0
  17. package/dist/api/ai-gateway/connect/index.d.ts +20 -2
  18. package/dist/api/ai-gateway/connect/index.js +162 -16
  19. package/dist/api/ai-gateway/credentials/AiCredentialSecretDecoder.d.ts +12 -0
  20. package/dist/api/ai-gateway/credentials/AiCredentialSecretDecoder.js +30 -0
  21. package/dist/api/ai-gateway/errors.d.ts +1 -1
  22. package/dist/api/ai-gateway/models/GatewayEmbeddingModelCatalog.d.ts +11 -0
  23. package/dist/api/ai-gateway/models/GatewayEmbeddingModelCatalog.js +31 -0
  24. package/dist/api/ai-gateway/models/PodModelSelectionRepository.js +7 -3
  25. package/dist/api/ai-gateway/models/ProviderCustomModelsService.d.ts +18 -0
  26. package/dist/api/ai-gateway/models/ProviderCustomModelsService.js +23 -0
  27. package/dist/api/ai-gateway/models/ProviderModelDiscoveryAdapters.d.ts +3 -1
  28. package/dist/api/ai-gateway/models/ProviderModelDiscoveryAdapters.js +2 -45
  29. package/dist/api/ai-gateway/models/ProviderModelSelectionService.d.ts +10 -0
  30. package/dist/api/ai-gateway/models/ProviderModelSelectionService.js +57 -20
  31. package/dist/api/ai-gateway/models/ProviderModelType.d.ts +28 -0
  32. package/dist/api/ai-gateway/models/ProviderModelType.js +34 -0
  33. package/dist/api/ai-gateway/models/ProviderModelsAdapter.d.ts +10 -0
  34. package/dist/api/ai-gateway/models/ProviderModelsAdapter.js +3 -4
  35. package/dist/api/ai-gateway/models/index.d.ts +1 -0
  36. package/dist/api/ai-gateway/models/index.js +3 -1
  37. package/dist/api/ai-gateway/providers/CustomRuntimeAdapter.d.ts +7 -0
  38. package/dist/api/ai-gateway/providers/CustomRuntimeAdapter.js +9 -2
  39. package/dist/api/ai-gateway/providers/ModelsDevCatalog.d.ts +7 -1
  40. package/dist/api/ai-gateway/providers/ModelsDevCatalog.js +4 -10
  41. package/dist/api/ai-gateway/providers/ProviderRegistry.d.ts +107 -0
  42. package/dist/api/ai-gateway/providers/ProviderRegistry.js +244 -21
  43. package/dist/api/ai-gateway/providers/ProviderRuntimeRegistry.d.ts +5 -0
  44. package/dist/api/ai-gateway/providers/ProviderRuntimeRegistry.js +5 -1
  45. package/dist/api/ai-gateway/quota/SubscriptionQuotaAdapters.d.ts +12 -4
  46. package/dist/api/ai-gateway/quota/SubscriptionQuotaAdapters.js +11 -11
  47. package/dist/api/ai-gateway/routing/ModelRouter.d.ts +14 -0
  48. package/dist/api/ai-gateway/routing/ModelRouter.js +43 -4
  49. package/dist/api/ai-gateway/service-access/AiConnectionsServiceAccess.d.ts +9 -1
  50. package/dist/api/ai-gateway/service-access/AiConnectionsServiceAccess.js +3 -27
  51. package/dist/api/auth/ClientCredentialsAuthenticator.d.ts +0 -1
  52. package/dist/api/auth/ClientCredentialsAuthenticator.js +0 -3
  53. package/dist/api/auth/index.d.ts +1 -0
  54. package/dist/api/auth/index.js +1 -1
  55. package/dist/api/chatkit/pod-store.d.ts +31 -0
  56. package/dist/api/chatkit/pod-store.js +132 -8
  57. package/dist/api/container/common.js +24 -4
  58. package/dist/api/container/routes.js +17 -2
  59. package/dist/api/container/types.d.ts +3 -1
  60. package/dist/api/handlers/AdminHandler.d.ts +13 -0
  61. package/dist/api/handlers/AdminHandler.js +47 -18
  62. package/dist/api/handlers/AiConfigHandler.d.ts +6 -0
  63. package/dist/api/handlers/AiConfigHandler.js +28 -0
  64. package/dist/api/handlers/AiGatewayManagementHandler.js +36 -0
  65. package/dist/api/runs/RdfRunContextRetriever.d.ts +14 -0
  66. package/dist/api/runs/RdfRunContextRetriever.js +41 -5
  67. package/dist/api/runtime.js +2 -1
  68. package/dist/cli/commands/secret.d.ts +1 -0
  69. package/dist/cli/commands/secret.js +25 -7
  70. package/dist/components/components.jsonld +3 -1
  71. package/dist/components/context.jsonld +53 -1
  72. package/dist/http/SubgraphSparqlHttpHandler.d.ts +59 -2
  73. package/dist/http/SubgraphSparqlHttpHandler.js +145 -13
  74. package/dist/http/SubgraphSparqlHttpHandler.jsonld +37 -0
  75. package/dist/identity/drizzle/AccountRoleRepository.d.ts +30 -2
  76. package/dist/identity/drizzle/AccountRoleRepository.js +163 -15
  77. package/dist/identity/drizzle/EdgeNodeRepository.d.ts +0 -12
  78. package/dist/identity/drizzle/EdgeNodeRepository.js +5 -13
  79. package/dist/identity/drizzle/PodLookupRepository.d.ts +58 -4
  80. package/dist/identity/drizzle/PodLookupRepository.js +248 -105
  81. package/dist/identity/drizzle/db.d.ts +19 -0
  82. package/dist/identity/drizzle/db.js +39 -4
  83. package/dist/index.d.ts +2 -1
  84. package/dist/index.js +7 -3
  85. package/dist/logging/log-file.d.ts +17 -0
  86. package/dist/logging/log-file.js +69 -0
  87. package/dist/main.js +2 -1
  88. package/dist/notifications/NotificationChannelSweeper.d.ts +50 -0
  89. package/dist/notifications/NotificationChannelSweeper.js +131 -0
  90. package/dist/notifications/NotificationChannelSweeper.jsonld +136 -0
  91. package/dist/notifications/ReclaimingWebSocket2023Storer.d.ts +25 -0
  92. package/dist/notifications/ReclaimingWebSocket2023Storer.js +56 -0
  93. package/dist/notifications/ReclaimingWebSocket2023Storer.jsonld +77 -0
  94. package/dist/notifications/index.d.ts +2 -0
  95. package/dist/notifications/index.js +2 -0
  96. package/dist/runtime/Proxy.d.ts +37 -0
  97. package/dist/runtime/Proxy.js +88 -16
  98. package/dist/runtime/bootstrap.js +2 -1
  99. package/dist/runtime/upgrade/BunNativeUpgradeRelay.d.ts +116 -0
  100. package/dist/runtime/upgrade/BunNativeUpgradeRelay.js +423 -0
  101. package/dist/runtime/upgrade/UpgradeHandshake.d.ts +63 -0
  102. package/dist/runtime/upgrade/UpgradeHandshake.js +199 -0
  103. package/dist/runtime/upgrade/WebSocketFrames.d.ts +67 -0
  104. package/dist/runtime/upgrade/WebSocketFrames.js +224 -0
  105. package/node_modules/@undefineds.co/ai-connections/dist/AiApiKeyPool.js +8 -1
  106. package/node_modules/@undefineds.co/ai-connections/dist/AiAuthorizationActions.d.ts +11 -2
  107. package/node_modules/@undefineds.co/ai-connections/dist/AiAuthorizationActions.js +27 -10
  108. package/node_modules/@undefineds.co/ai-connections/dist/AiClientConfigurationSection.d.ts +7 -0
  109. package/node_modules/@undefineds.co/ai-connections/dist/AiClientConfigurationSection.js +13 -11
  110. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectDialog.js +1 -1
  111. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsList.js +10 -6
  112. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsMain.d.ts +15 -0
  113. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsMain.js +29 -3
  114. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsMainHeader.js +18 -3
  115. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.d.ts +16 -1
  116. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.js +92 -20
  117. package/node_modules/@undefineds.co/ai-connections/dist/AiCopyButton.d.ts +35 -0
  118. package/node_modules/@undefineds.co/ai-connections/dist/AiCopyButton.js +45 -0
  119. package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialPoolSection.js +71 -11
  120. package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialRow.js +9 -7
  121. package/node_modules/@undefineds.co/ai-connections/dist/AiEndpointList.d.ts +23 -0
  122. package/node_modules/@undefineds.co/ai-connections/dist/AiEndpointList.js +24 -0
  123. package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeysSection.d.ts +13 -4
  124. package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeysSection.js +35 -38
  125. package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayModelsSection.d.ts +21 -0
  126. package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayModelsSection.js +51 -0
  127. package/node_modules/@undefineds.co/ai-connections/dist/AiInfoTooltip.d.ts +15 -0
  128. package/node_modules/@undefineds.co/ai-connections/dist/AiInfoTooltip.js +16 -0
  129. package/node_modules/@undefineds.co/ai-connections/dist/AiModelCatalog.d.ts +175 -0
  130. package/node_modules/@undefineds.co/ai-connections/dist/AiModelCatalog.js +133 -0
  131. package/node_modules/@undefineds.co/ai-connections/dist/AiOfferingDetails.js +2 -2
  132. package/node_modules/@undefineds.co/ai-connections/dist/AiProviderCard.js +13 -64
  133. package/node_modules/@undefineds.co/ai-connections/dist/AiProviderHeader.d.ts +21 -0
  134. package/node_modules/@undefineds.co/ai-connections/dist/AiProviderHeader.js +12 -0
  135. package/node_modules/@undefineds.co/ai-connections/dist/AiRowAction.d.ts +15 -0
  136. package/node_modules/@undefineds.co/ai-connections/dist/AiRowAction.js +12 -0
  137. package/node_modules/@undefineds.co/ai-connections/dist/AiSortableCredentialList.js +2 -1
  138. package/node_modules/@undefineds.co/ai-connections/dist/ai-connections-client.d.ts +7 -0
  139. package/node_modules/@undefineds.co/ai-connections/dist/ai-connections-client.js +6 -0
  140. package/node_modules/@undefineds.co/ai-connections/dist/authorization-methods.d.ts +36 -5
  141. package/node_modules/@undefineds.co/ai-connections/dist/authorization-methods.js +52 -9
  142. package/node_modules/@undefineds.co/ai-connections/dist/client/normalize.js +30 -3
  143. package/node_modules/@undefineds.co/ai-connections/dist/client/types.d.ts +21 -1
  144. package/node_modules/@undefineds.co/ai-connections/dist/client-config/base-adapter.d.ts +1 -3
  145. package/node_modules/@undefineds.co/ai-connections/dist/client-config/base-adapter.js +3 -7
  146. package/node_modules/@undefineds.co/ai-connections/dist/client-config/index.cjs +9 -7
  147. package/node_modules/@undefineds.co/ai-connections/dist/collection-runtime.d.ts +46 -0
  148. package/node_modules/@undefineds.co/ai-connections/dist/collection-runtime.js +231 -0
  149. package/node_modules/@undefineds.co/ai-connections/dist/collections.d.ts +119 -0
  150. package/node_modules/@undefineds.co/ai-connections/dist/collections.js +173 -0
  151. package/node_modules/@undefineds.co/ai-connections/dist/controller.d.ts +71 -5
  152. package/node_modules/@undefineds.co/ai-connections/dist/controller.js +285 -16
  153. package/node_modules/@undefineds.co/ai-connections/dist/credential-labels.d.ts +5 -0
  154. package/node_modules/@undefineds.co/ai-connections/dist/credential-labels.js +8 -3
  155. package/node_modules/@undefineds.co/ai-connections/dist/credential-storage.d.ts +59 -0
  156. package/node_modules/@undefineds.co/ai-connections/dist/credential-storage.js +131 -0
  157. package/node_modules/@undefineds.co/ai-connections/dist/endpoint-urls.d.ts +15 -0
  158. package/node_modules/@undefineds.co/ai-connections/dist/endpoint-urls.js +20 -0
  159. package/node_modules/@undefineds.co/ai-connections/dist/gateway-endpoints.d.ts +14 -0
  160. package/node_modules/@undefineds.co/ai-connections/dist/gateway-endpoints.js +20 -0
  161. package/node_modules/@undefineds.co/ai-connections/dist/index.d.ts +8 -0
  162. package/node_modules/@undefineds.co/ai-connections/dist/index.js +8 -0
  163. package/node_modules/@undefineds.co/ai-connections/dist/manifest.js +1 -1
  164. package/node_modules/@undefineds.co/ai-connections/dist/offering-endpoints.d.ts +14 -0
  165. package/node_modules/@undefineds.co/ai-connections/dist/offering-endpoints.js +17 -0
  166. package/node_modules/@undefineds.co/ai-connections/dist/provider-catalog.cjs +68 -1
  167. package/node_modules/@undefineds.co/ai-connections/dist/provider-catalog.d.ts +75 -1
  168. package/node_modules/@undefineds.co/ai-connections/dist/provider-catalog.js +119 -0
  169. package/node_modules/@undefineds.co/ai-connections/dist/provider-visuals.d.ts +5 -0
  170. package/node_modules/@undefineds.co/ai-connections/dist/provider-visuals.js +5 -0
  171. package/node_modules/@undefineds.co/ai-connections/dist/service-access.js +2 -27
  172. package/node_modules/@undefineds.co/ai-connections/package.json +1 -0
  173. package/node_modules/@undefineds.co/extension-sdk/dist/manifest.d.ts +1 -1
  174. package/node_modules/@undefineds.co/extension-sdk/dist/manifest.js +2 -0
  175. package/node_modules/@undefineds.co/extension-sdk/dist/web.d.ts +150 -0
  176. package/node_modules/@undefineds.co/extension-sdk/package.json +2 -1
  177. package/node_modules/@undefineds.co/models/README.md +1 -1
  178. package/node_modules/@undefineds.co/models/dist/ai-config/index.d.ts +3 -3
  179. package/node_modules/@undefineds.co/models/dist/ai-gateway.schema.d.ts +5 -0
  180. package/node_modules/@undefineds.co/models/dist/ai-gateway.schema.js +9 -0
  181. package/node_modules/@undefineds.co/models/dist/ai-runtime.repository.d.ts +1 -1
  182. package/node_modules/@undefineds.co/models/dist/approval.repository.d.ts +2 -2
  183. package/node_modules/@undefineds.co/models/dist/audit.presentation.d.ts +2 -2
  184. package/node_modules/@undefineds.co/models/dist/capture.repository.d.ts +1 -1
  185. package/node_modules/@undefineds.co/models/dist/chat-project.repository.d.ts +1 -1
  186. package/node_modules/@undefineds.co/models/dist/chat.repository.d.ts +2 -2
  187. package/node_modules/@undefineds.co/models/dist/control-request.repository.d.ts +2 -2
  188. package/node_modules/@undefineds.co/models/dist/conversation-share.repository.d.ts +1 -1
  189. package/node_modules/@undefineds.co/models/dist/credential.schema.d.ts +12 -0
  190. package/node_modules/@undefineds.co/models/dist/credential.schema.js +15 -1
  191. package/node_modules/@undefineds.co/models/dist/discovery/index.d.ts +2 -2
  192. package/node_modules/@undefineds.co/models/dist/discovery/providers.json +248 -7
  193. package/node_modules/@undefineds.co/models/dist/discovery/types.d.ts +31 -0
  194. package/node_modules/@undefineds.co/models/dist/extension/index.d.ts +1 -1
  195. package/node_modules/@undefineds.co/models/dist/favorite/index.d.ts +2 -2
  196. package/node_modules/@undefineds.co/models/dist/fixtures/contracts-chat-contact.d.ts +5 -5
  197. package/node_modules/@undefineds.co/models/dist/import/index.d.ts +1 -1
  198. package/node_modules/@undefineds.co/models/dist/index.d.ts +73 -73
  199. package/node_modules/@undefineds.co/models/dist/index.js +1 -1
  200. package/node_modules/@undefineds.co/models/dist/input-request.repository.d.ts +2 -2
  201. package/node_modules/@undefineds.co/models/dist/knowledge/index.d.ts +1 -1
  202. package/node_modules/@undefineds.co/models/dist/message.repository.d.ts +1 -1
  203. package/node_modules/@undefineds.co/models/dist/namespaces.js +5 -0
  204. package/node_modules/@undefineds.co/models/dist/pod-storage-descriptor.d.ts +4815 -26
  205. package/node_modules/@undefineds.co/models/dist/pod-storage-descriptor.js +482 -132
  206. package/node_modules/@undefineds.co/models/dist/schema.d.ts +4 -0
  207. package/node_modules/@undefineds.co/models/dist/session/index.d.ts +1 -1
  208. package/node_modules/@undefineds.co/models/dist/settings/index.d.ts +1 -1
  209. package/node_modules/@undefineds.co/models/dist/sidecar/persistence-mapping.d.ts +5 -5
  210. package/node_modules/@undefineds.co/models/dist/thread.repository.d.ts +2 -2
  211. package/node_modules/@undefineds.co/models/dist/types/message-block.d.ts +1 -1
  212. package/node_modules/@undefineds.co/models/dist/vocab/_namespaces.d.ts +1 -1
  213. package/node_modules/@undefineds.co/models/dist/vocab/index.d.ts +10 -10
  214. package/node_modules/@undefineds.co/models/dist/vocab/sidecar.vocab.d.ts +1 -0
  215. package/node_modules/@undefineds.co/models/dist/vocab/sidecar.vocab.js +1 -0
  216. package/node_modules/@undefineds.co/models/package.json +4 -2
  217. package/node_modules/@undefineds.co/pod-collections/README.md +71 -0
  218. package/node_modules/@undefineds.co/pod-collections/dist/diff.d.ts +85 -0
  219. package/node_modules/@undefineds.co/pod-collections/dist/diff.js +166 -0
  220. package/node_modules/@undefineds.co/pod-collections/dist/feed.d.ts +17 -0
  221. package/node_modules/@undefineds.co/pod-collections/dist/feed.js +27 -0
  222. package/node_modules/@undefineds.co/pod-collections/dist/index.cjs +1042 -0
  223. package/node_modules/@undefineds.co/pod-collections/dist/index.d.ts +37 -0
  224. package/node_modules/@undefineds.co/pod-collections/dist/index.js +89 -0
  225. package/node_modules/@undefineds.co/pod-collections/dist/layout.d.ts +75 -0
  226. package/node_modules/@undefineds.co/pod-collections/dist/layout.js +173 -0
  227. package/node_modules/@undefineds.co/pod-collections/dist/mapping.d.ts +78 -0
  228. package/node_modules/@undefineds.co/pod-collections/dist/mapping.js +287 -0
  229. package/node_modules/@undefineds.co/pod-collections/dist/mutations.d.ts +83 -0
  230. package/node_modules/@undefineds.co/pod-collections/dist/mutations.js +273 -0
  231. package/node_modules/@undefineds.co/pod-collections/dist/react.d.ts +21 -0
  232. package/node_modules/@undefineds.co/pod-collections/dist/react.js +22 -0
  233. package/node_modules/@undefineds.co/pod-collections/dist/read.d.ts +65 -0
  234. package/node_modules/@undefineds.co/pod-collections/dist/read.js +31 -0
  235. package/node_modules/@undefineds.co/pod-collections/dist/sync.d.ts +66 -0
  236. package/node_modules/@undefineds.co/pod-collections/dist/sync.js +260 -0
  237. package/node_modules/@undefineds.co/pod-collections/dist/types.d.ts +155 -0
  238. package/node_modules/@undefineds.co/pod-collections/dist/types.js +9 -0
  239. package/node_modules/@undefineds.co/pod-collections/package.json +42 -0
  240. package/node_modules/@undefineds.co/shared-ui/dist/index.d.ts +0 -1
  241. package/node_modules/@undefineds.co/shared-ui/dist/index.js +0 -1
  242. package/package.json +15 -7
  243. package/static/app/assets/main.css +1 -1
  244. package/static/app/assets/main.js +12 -13
  245. package/static/auth-callback/assets/AiConfigContext-DnQs1ZpW.js +1 -0
  246. package/static/auth-callback/assets/AiConfigPage-DOtvlxH0.js +1 -0
  247. package/static/auth-callback/assets/DocumentProcessingPanel-BS2voQgL.js +1 -0
  248. package/static/auth-callback/assets/IndexLifecyclePanel-Cvt0cJtN.js +1 -0
  249. package/static/auth-callback/assets/{IndexSubjectPanel-C4YG0whI.js → IndexSubjectPanel-Dhf01GqF.js} +1 -1
  250. package/static/auth-callback/assets/ModelAssignmentsPanel-BJutWaAF.js +1 -0
  251. package/static/auth-callback/assets/ModelsPage-BRS0sje3.js +11 -0
  252. package/static/auth-callback/assets/{NetworkPage-Cbdn_P1e.js → NetworkPage-B3qBfANA.js} +2 -2
  253. package/static/auth-callback/assets/{PaneListHeader-jy70Q00L.js → PaneListHeader-QQeJGTp4.js} +1 -1
  254. package/static/auth-callback/assets/SearchIndexingPanel-MyNUSEwT.js +1 -0
  255. package/static/auth-callback/assets/{StatusSubjectPanel-hfjoB5aS.js → StatusSubjectPanel-DQkEVsFs.js} +1 -1
  256. package/static/{settings/assets/StatusWorkspace-CKD_Rzdr.js → auth-callback/assets/StatusWorkspace-Dkv63Uwk.js} +1 -1
  257. package/static/auth-callback/assets/SystemSettingsPage-TIsUfX5d.js +1 -0
  258. package/static/auth-callback/assets/SystemSettingsSubjectPanel-BJWEt2-7.js +33 -0
  259. package/static/auth-callback/assets/XpodAiConnectionsPodStore-BJiXm-PF.js +3 -0
  260. package/static/auth-callback/assets/{activity-BcsZZxxw.js → activity-5hNeNKnL.js} +1 -1
  261. package/static/auth-callback/assets/admin-C6qCRFiY.js +1 -0
  262. package/static/auth-callback/assets/ai-connections-CryuHGKW.js +1 -0
  263. package/static/auth-callback/assets/{auth-callback-atKg_oig.js → auth-callback-CAFZ3R0B.js} +80 -84
  264. package/static/auth-callback/assets/auth-callback-rk080mvG.css +1 -0
  265. package/static/auth-callback/assets/{badge-BWbRHThQ.js → badge-CAIPI0CB.js} +1 -1
  266. package/static/auth-callback/assets/collection-runtime-D9s7h9YA.js +1 -0
  267. package/static/auth-callback/assets/dialog-BjA109aX.js +1 -0
  268. package/static/auth-callback/assets/{download-BmvG1Vya.js → download-B3Up5W2G.js} +1 -1
  269. package/static/auth-callback/assets/{external-link-DZ34d3g3.js → external-link-BTXgSPzB.js} +1 -1
  270. package/static/auth-callback/assets/index-BppXlxcp.js +41 -0
  271. package/static/auth-callback/assets/index-CirW4CJf.js +1 -0
  272. package/static/auth-callback/assets/index-DlLYWOhw.js +4 -0
  273. package/static/auth-callback/assets/{index-browser-B9Z7GU-T.js → index-browser-DtU38ni3.js} +1 -1
  274. package/static/auth-callback/assets/{key-round-tjP76Se-.js → key-round-CQCOrZ7x.js} +1 -1
  275. package/static/auth-callback/assets/layout-DB3pMyTl.js +1 -0
  276. package/static/auth-callback/assets/pod-collections-host-KnnGFZHL.js +8 -0
  277. package/static/auth-callback/assets/{rotate-ccw-C_L5ZLx1.js → rotate-ccw-C1zM2KtS.js} +1 -1
  278. package/static/auth-callback/assets/settings-projection-CUkyprDQ.js +1 -0
  279. package/static/auth-callback/assets/{skeleton-C7tGDQIs.js → skeleton-Cqp7_M9-.js} +1 -1
  280. package/static/auth-callback/assets/{waypoints-VMNQlWdU.js → waypoints-Bj6gAUSQ.js} +1 -1
  281. package/static/auth-callback/assets/{workspace-layout-SAp6BtYK.js → workspace-layout-DK8mDzrY.js} +1 -1
  282. package/static/auth-callback/auth-callback.html +2 -2
  283. package/static/dashboard/assets/AiConfigContext-BsE7MqX8.js +1 -0
  284. package/static/dashboard/assets/AiConfigPage-DvM-lRXa.js +1 -0
  285. package/static/dashboard/assets/DocumentProcessingPanel-BPfdlfuf.js +1 -0
  286. package/static/dashboard/assets/IndexLifecyclePanel--m0AGxvh.js +1 -0
  287. package/static/dashboard/assets/{IndexSubjectPanel-DQFPP6-p.js → IndexSubjectPanel-Bb7m1k3d.js} +1 -1
  288. package/static/dashboard/assets/ModelAssignmentsPanel-BLi_zbMa.js +1 -0
  289. package/static/dashboard/assets/ModelsPage-CxdpgnfR.js +11 -0
  290. package/static/dashboard/assets/{NetworkPage-CHQ3YxIB.js → NetworkPage-BAIPw-D_.js} +2 -2
  291. package/static/dashboard/assets/{PaneListHeader-DsXemAdR.js → PaneListHeader-BBCMei0r.js} +1 -1
  292. package/static/dashboard/assets/SearchIndexingPanel-Ck4Y-xjR.js +1 -0
  293. package/static/dashboard/assets/{StatusSubjectPanel-D3PGEYT4.js → StatusSubjectPanel-D1KWfAXE.js} +1 -1
  294. package/static/dashboard/assets/{StatusWorkspace-BcpePYUW.js → StatusWorkspace-JbA5gzXx.js} +1 -1
  295. package/static/dashboard/assets/SystemSettingsPage-BbwQWsSR.js +1 -0
  296. package/static/dashboard/assets/SystemSettingsSubjectPanel-N117nMt5.js +33 -0
  297. package/static/dashboard/assets/XpodAiConnectionsPodStore-CdDOb4SV.js +18 -0
  298. package/static/dashboard/assets/{activity-j5zrznu-.js → activity-DX1I96o_.js} +1 -1
  299. package/static/dashboard/assets/admin-C6qCRFiY.js +1 -0
  300. package/static/dashboard/assets/ai-connections-DwCRqOQa.js +1 -0
  301. package/static/dashboard/assets/{badge-CzeBdG7h.js → badge-k2vhtDqH.js} +1 -1
  302. package/static/dashboard/assets/collection-runtime-BFQ8teQJ.js +1 -0
  303. package/static/dashboard/assets/{dashboard-D-xANHk1.js → dashboard-DWZ-fmCT.js} +105 -109
  304. package/static/dashboard/assets/dashboard-rk080mvG.css +1 -0
  305. package/static/dashboard/assets/dialog-1CCw-iHT.js +1 -0
  306. package/static/dashboard/assets/{download-IcNdEZWi.js → download-C6-SNY1q.js} +1 -1
  307. package/static/dashboard/assets/{external-link-DxBxK8Vu.js → external-link-BgPcZ_j2.js} +1 -1
  308. package/static/dashboard/assets/index-6LcIUIYO.js +1 -0
  309. package/static/dashboard/assets/index-D7A8U6Pt.js +41 -0
  310. package/static/dashboard/assets/index-UD6QOE7H.js +4 -0
  311. package/static/dashboard/assets/{key-round-D1K7warM.js → key-round-BOd7Jo0Q.js} +1 -1
  312. package/static/dashboard/assets/layout-DB3pMyTl.js +1 -0
  313. package/static/dashboard/assets/pod-collections-host-KnnGFZHL.js +8 -0
  314. package/static/dashboard/assets/{rotate-ccw-CcN1N6p9.js → rotate-ccw-CCgJqsvx.js} +1 -1
  315. package/static/dashboard/assets/settings-projection-CUkyprDQ.js +1 -0
  316. package/static/dashboard/assets/{skeleton-CKnmJMUH.js → skeleton-Bc7abAn5.js} +1 -1
  317. package/static/dashboard/assets/{waypoints-DuZPO_wu.js → waypoints-s-opmJxx.js} +1 -1
  318. package/static/dashboard/assets/{workspace-layout-BUj3wZ_m.js → workspace-layout-DqIQeTBV.js} +1 -1
  319. package/static/dashboard/dashboard.html +2 -2
  320. package/static/settings/assets/AiConfigContext-BB9KZySa.js +1 -0
  321. package/static/settings/assets/AiConfigPage-DGSXUkLs.js +1 -0
  322. package/static/settings/assets/DocumentProcessingPanel-Da2Re6Rg.js +1 -0
  323. package/static/settings/assets/IndexLifecyclePanel-BSZuIzgr.js +1 -0
  324. package/static/settings/assets/{IndexSubjectPanel-73sM16Ma.js → IndexSubjectPanel-CFd0ay-r.js} +1 -1
  325. package/static/settings/assets/ModelAssignmentsPanel-CSAryvWJ.js +1 -0
  326. package/static/settings/assets/ModelsPage-BQwCwLHU.js +11 -0
  327. package/static/settings/assets/{NetworkPage-i6j-M2RY.js → NetworkPage-BKymvsQc.js} +2 -2
  328. package/static/settings/assets/{PaneListHeader-DpqC0jd5.js → PaneListHeader-Bjh3hRdQ.js} +1 -1
  329. package/static/settings/assets/SearchIndexingPanel-MjKL5QLU.js +1 -0
  330. package/static/settings/assets/{StatusSubjectPanel-Dv4q3PGh.js → StatusSubjectPanel-Bvl6K4mx.js} +1 -1
  331. package/static/settings/assets/StatusWorkspace-B0NzrP--.js +1 -0
  332. package/static/settings/assets/SystemSettingsPage-D2z6Z4FE.js +1 -0
  333. package/static/settings/assets/SystemSettingsSubjectPanel-4sxma4X4.js +33 -0
  334. package/static/settings/assets/XpodAiConnectionsPodStore-BkNQ8fZx.js +3 -0
  335. package/static/settings/assets/{activity-DaFkk8f3.js → activity-CgJJGpjx.js} +1 -1
  336. package/static/settings/assets/admin-C6qCRFiY.js +1 -0
  337. package/static/settings/assets/ai-connections-CryuHGKW.js +1 -0
  338. package/static/settings/assets/{badge-d5SHdc-x.js → badge-C4NypVyT.js} +1 -1
  339. package/static/settings/assets/collection-runtime-CTLCDxAi.js +1 -0
  340. package/static/settings/assets/dialog-Csq0vWUi.js +1 -0
  341. package/static/settings/assets/{download-CpkwomDr.js → download-DaLJJ-Wp.js} +1 -1
  342. package/static/settings/assets/{external-link-_4YT42Mf.js → external-link--w_iW5Au.js} +1 -1
  343. package/static/settings/assets/index-B0mQa59b.js +4 -0
  344. package/static/settings/assets/index-BukHiu4y.js +1 -0
  345. package/static/settings/assets/index-COmVnZi2.js +41 -0
  346. package/static/settings/assets/{index-browser-B06xjBdZ.js → index-browser-BGpvHwD0.js} +1 -1
  347. package/static/settings/assets/{key-round-Dlqmp1Kq.js → key-round-Bk4YRjBu.js} +1 -1
  348. package/static/settings/assets/layout-DB3pMyTl.js +1 -0
  349. package/static/settings/assets/pod-collections-host-KnnGFZHL.js +8 -0
  350. package/static/settings/assets/{rotate-ccw-TAY65xWT.js → rotate-ccw-TCabbqsr.js} +1 -1
  351. package/static/settings/assets/{settings-ExBXGgbj.js → settings-CJWpdbNC.js} +105 -109
  352. package/static/settings/assets/settings-projection-CUkyprDQ.js +1 -0
  353. package/static/settings/assets/settings-rk080mvG.css +1 -0
  354. package/static/settings/assets/{skeleton-DKIWjNr9.js → skeleton-JDHYVe7t.js} +1 -1
  355. package/static/settings/assets/{waypoints-9erLIxyR.js → waypoints-DDvEl-MU.js} +1 -1
  356. package/static/settings/assets/{workspace-layout-CYXfYIa3.js → workspace-layout-DV5QU30U.js} +1 -1
  357. package/static/settings/settings.html +2 -2
  358. package/node_modules/@undefineds.co/shared-ui/dist/oidc-consent.d.ts +0 -54
  359. package/node_modules/@undefineds.co/shared-ui/dist/oidc-consent.js +0 -21
  360. package/static/auth-callback/assets/AiConfigContext-C81deMM9.js +0 -1
  361. package/static/auth-callback/assets/AiConfigPage-evWI8T56.js +0 -1
  362. package/static/auth-callback/assets/DocumentProcessingPanel-B9GrDEMe.js +0 -1
  363. package/static/auth-callback/assets/IndexLifecyclePanel-qCo8ABQZ.js +0 -1
  364. package/static/auth-callback/assets/ModelAssignmentsPanel-DG7Lxh3t.js +0 -1
  365. package/static/auth-callback/assets/ModelsPage-CgEuqE6p.js +0 -10
  366. package/static/auth-callback/assets/SearchIndexingPanel-ByU3u7kp.js +0 -1
  367. package/static/auth-callback/assets/StatusWorkspace-BZd617sV.js +0 -1
  368. package/static/auth-callback/assets/SystemSettingsPage-BirzWAQM.js +0 -1
  369. package/static/auth-callback/assets/SystemSettingsSubjectPanel-CmsVWNCx.js +0 -31
  370. package/static/auth-callback/assets/admin-BU4m6Ko2.js +0 -1
  371. package/static/auth-callback/assets/ai-connections-CHNTKemd.js +0 -1
  372. package/static/auth-callback/assets/auth-callback-C_7MUXJb.css +0 -1
  373. package/static/auth-callback/assets/index-BpV1hsqs.js +0 -4
  374. package/static/auth-callback/assets/index-D9oE6FXK.js +0 -41
  375. package/static/dashboard/assets/AiConfigContext-De-OtAWo.js +0 -1
  376. package/static/dashboard/assets/AiConfigPage-macP4Mop.js +0 -1
  377. package/static/dashboard/assets/DocumentProcessingPanel-C5ObvCCl.js +0 -1
  378. package/static/dashboard/assets/IndexLifecyclePanel-xVNa2l40.js +0 -1
  379. package/static/dashboard/assets/ModelAssignmentsPanel-DMOATFpQ.js +0 -1
  380. package/static/dashboard/assets/ModelsPage-91UbnETA.js +0 -25
  381. package/static/dashboard/assets/SearchIndexingPanel-Dh70PNFZ.js +0 -1
  382. package/static/dashboard/assets/SystemSettingsPage-BiN5GcKx.js +0 -1
  383. package/static/dashboard/assets/SystemSettingsSubjectPanel-B9QrSiFp.js +0 -31
  384. package/static/dashboard/assets/admin-BU4m6Ko2.js +0 -1
  385. package/static/dashboard/assets/ai-connections-CHNTKemd.js +0 -1
  386. package/static/dashboard/assets/dashboard-C_7MUXJb.css +0 -1
  387. package/static/dashboard/assets/index-FWZ-s52O.js +0 -41
  388. package/static/dashboard/assets/index-ZiQZ96oC.js +0 -4
  389. package/static/settings/assets/AiConfigContext-C0cQMPfG.js +0 -1
  390. package/static/settings/assets/AiConfigPage-CPhB4iFb.js +0 -1
  391. package/static/settings/assets/DocumentProcessingPanel-sYI7OpuH.js +0 -1
  392. package/static/settings/assets/IndexLifecyclePanel-yj8iyiT8.js +0 -1
  393. package/static/settings/assets/ModelAssignmentsPanel-BFIgUX5v.js +0 -1
  394. package/static/settings/assets/ModelsPage-BdppXl7E.js +0 -10
  395. package/static/settings/assets/SearchIndexingPanel-BlPnrkT3.js +0 -1
  396. package/static/settings/assets/SystemSettingsPage-CiOm2NzV.js +0 -1
  397. package/static/settings/assets/SystemSettingsSubjectPanel-Cd-GECon.js +0 -31
  398. package/static/settings/assets/admin-BU4m6Ko2.js +0 -1
  399. package/static/settings/assets/ai-connections-CHNTKemd.js +0 -1
  400. package/static/settings/assets/index-BFi9yn7_.js +0 -41
  401. package/static/settings/assets/index-BGgEhIUy.js +0 -4
  402. package/static/settings/assets/settings-C_7MUXJb.css +0 -1
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Minimal RFC 6455 frame codec used by the gateway's native (Bun) WebSocket
3
+ * upgrade relay.
4
+ *
5
+ * The gateway only needs it on runtimes whose HTTP server cannot hand the raw
6
+ * upgraded socket back to JavaScript (see `BunNativeUpgradeRelay`): there the
7
+ * client side is a native WebSocket (message level), while the upstream side is
8
+ * a raw socket, so frames have to be decoded/encoded in between.
9
+ *
10
+ * The codec deliberately implements a single, predictable flavour of the
11
+ * protocol: no extensions (the relay never offers `permessage-deflate`), no
12
+ * fragmentation on the outbound path (one frame per message) and a bounded
13
+ * inbound message size.
14
+ */
15
+ export declare const WS_OPCODE: {
16
+ readonly continuation: 0;
17
+ readonly text: 1;
18
+ readonly binary: 2;
19
+ readonly close: 8;
20
+ readonly ping: 9;
21
+ readonly pong: 10;
22
+ };
23
+ export type WebSocketFrameOpcode = typeof WS_OPCODE[keyof typeof WS_OPCODE];
24
+ /** Close code used when the peer violates the protocol. */
25
+ export declare const WS_CLOSE_PROTOCOL_ERROR = 1002;
26
+ /** Close code used when a message exceeds the configured size limit. */
27
+ export declare const WS_CLOSE_MESSAGE_TOO_BIG = 1009;
28
+ export interface EncodeWebSocketFrameOptions {
29
+ opcode: WebSocketFrameOpcode;
30
+ /** Client-to-server frames must be masked; server-to-client frames must not. */
31
+ mask: boolean;
32
+ /** Deterministic mask key, for tests only. */
33
+ maskKey?: Buffer;
34
+ }
35
+ export declare function encodeWebSocketFrame(payload: Buffer, options: EncodeWebSocketFrameOptions): Buffer;
36
+ /** Encodes a close frame body (`code` + UTF-8 reason). */
37
+ export declare function encodeWebSocketClosePayload(code: number, reason: string): Buffer;
38
+ export interface WebSocketFrameSink {
39
+ /** A complete (possibly reassembled) data message. */
40
+ onMessage(payload: Buffer, isBinary: boolean): void;
41
+ onPing(payload: Buffer): void;
42
+ onPong(payload: Buffer): void;
43
+ onClose(code: number, reason: string): void;
44
+ /** The peer sent something that violates the protocol; the connection should be closed with 1002. */
45
+ onProtocolError(reason: string): void;
46
+ }
47
+ export interface WebSocketFrameParserOptions {
48
+ /** Upper bound for a single (reassembled) message; oversized messages raise a protocol error. */
49
+ maxMessageBytes?: number;
50
+ }
51
+ export declare class WebSocketFrameParser {
52
+ private readonly sink;
53
+ private buffer;
54
+ private fragmentOpcode;
55
+ private fragments;
56
+ private fragmentBytes;
57
+ private failed;
58
+ private readonly maxMessageBytes;
59
+ constructor(sink: WebSocketFrameSink, options?: WebSocketFrameParserOptions);
60
+ push(chunk: Buffer): void;
61
+ private fail;
62
+ /** @returns whether a complete frame was consumed. */
63
+ private parseFrame;
64
+ private handleFrame;
65
+ private appendFragment;
66
+ private completeMessage;
67
+ }
@@ -0,0 +1,224 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebSocketFrameParser = exports.WS_CLOSE_MESSAGE_TOO_BIG = exports.WS_CLOSE_PROTOCOL_ERROR = exports.WS_OPCODE = void 0;
4
+ exports.encodeWebSocketFrame = encodeWebSocketFrame;
5
+ exports.encodeWebSocketClosePayload = encodeWebSocketClosePayload;
6
+ const node_crypto_1 = require("node:crypto");
7
+ /**
8
+ * Minimal RFC 6455 frame codec used by the gateway's native (Bun) WebSocket
9
+ * upgrade relay.
10
+ *
11
+ * The gateway only needs it on runtimes whose HTTP server cannot hand the raw
12
+ * upgraded socket back to JavaScript (see `BunNativeUpgradeRelay`): there the
13
+ * client side is a native WebSocket (message level), while the upstream side is
14
+ * a raw socket, so frames have to be decoded/encoded in between.
15
+ *
16
+ * The codec deliberately implements a single, predictable flavour of the
17
+ * protocol: no extensions (the relay never offers `permessage-deflate`), no
18
+ * fragmentation on the outbound path (one frame per message) and a bounded
19
+ * inbound message size.
20
+ */
21
+ exports.WS_OPCODE = {
22
+ continuation: 0x0,
23
+ text: 0x1,
24
+ binary: 0x2,
25
+ close: 0x8,
26
+ ping: 0x9,
27
+ pong: 0xa,
28
+ };
29
+ /** Close code used when the peer violates the protocol. */
30
+ exports.WS_CLOSE_PROTOCOL_ERROR = 1002;
31
+ /** Close code used when a message exceeds the configured size limit. */
32
+ exports.WS_CLOSE_MESSAGE_TOO_BIG = 1009;
33
+ function encodeWebSocketFrame(payload, options) {
34
+ const { opcode, mask } = options;
35
+ const length = payload.length;
36
+ const lengthBytes = length < 126 ? 1 : length <= 0xffff ? 3 : 9;
37
+ const maskBytes = mask ? 4 : 0;
38
+ const frame = Buffer.allocUnsafe(1 + lengthBytes + maskBytes + length);
39
+ frame[0] = 0x80 | opcode;
40
+ let offset;
41
+ if (length < 126) {
42
+ frame[1] = (mask ? 0x80 : 0) | length;
43
+ offset = 2;
44
+ }
45
+ else if (length <= 0xffff) {
46
+ frame[1] = (mask ? 0x80 : 0) | 126;
47
+ frame.writeUInt16BE(length, 2);
48
+ offset = 4;
49
+ }
50
+ else {
51
+ frame[1] = (mask ? 0x80 : 0) | 127;
52
+ frame.writeBigUInt64BE(BigInt(length), 2);
53
+ offset = 10;
54
+ }
55
+ if (!mask) {
56
+ payload.copy(frame, offset);
57
+ return frame;
58
+ }
59
+ const maskKey = options.maskKey ?? (0, node_crypto_1.randomBytes)(4);
60
+ maskKey.copy(frame, offset);
61
+ for (let index = 0; index < length; index++) {
62
+ frame[offset + 4 + index] = payload[index] ^ maskKey[index % 4];
63
+ }
64
+ return frame;
65
+ }
66
+ /** Encodes a close frame body (`code` + UTF-8 reason). */
67
+ function encodeWebSocketClosePayload(code, reason) {
68
+ const reasonBytes = Buffer.from(reason, 'utf8');
69
+ const payload = Buffer.allocUnsafe(2 + reasonBytes.length);
70
+ payload.writeUInt16BE(code, 0);
71
+ reasonBytes.copy(payload, 2);
72
+ return payload;
73
+ }
74
+ const DEFAULT_MAX_MESSAGE_BYTES = 64 * 1024 * 1024;
75
+ class WebSocketFrameParser {
76
+ constructor(sink, options = {}) {
77
+ this.sink = sink;
78
+ this.buffer = Buffer.alloc(0);
79
+ this.fragments = [];
80
+ this.fragmentBytes = 0;
81
+ this.failed = false;
82
+ this.maxMessageBytes = options.maxMessageBytes ?? DEFAULT_MAX_MESSAGE_BYTES;
83
+ }
84
+ push(chunk) {
85
+ if (this.failed || chunk.length === 0) {
86
+ return;
87
+ }
88
+ this.buffer = this.buffer.length === 0 ? chunk : Buffer.concat([this.buffer, chunk]);
89
+ while (!this.failed && this.parseFrame()) {
90
+ // Keep consuming buffered frames.
91
+ }
92
+ }
93
+ fail(reason) {
94
+ this.failed = true;
95
+ this.buffer = Buffer.alloc(0);
96
+ this.fragments = [];
97
+ this.fragmentOpcode = undefined;
98
+ this.sink.onProtocolError(reason);
99
+ }
100
+ /** @returns whether a complete frame was consumed. */
101
+ parseFrame() {
102
+ const buffer = this.buffer;
103
+ if (buffer.length < 2) {
104
+ return false;
105
+ }
106
+ const fin = (buffer[0] & 0x80) !== 0;
107
+ const reserved = buffer[0] & 0x70;
108
+ const opcode = (buffer[0] & 0x0f);
109
+ const masked = (buffer[1] & 0x80) !== 0;
110
+ let payloadLength = buffer[1] & 0x7f;
111
+ let offset = 2;
112
+ if (reserved !== 0) {
113
+ this.fail('reserved frame bits set without a negotiated extension');
114
+ return false;
115
+ }
116
+ if (payloadLength === 126) {
117
+ if (buffer.length < offset + 2) {
118
+ return false;
119
+ }
120
+ payloadLength = buffer.readUInt16BE(offset);
121
+ offset += 2;
122
+ }
123
+ else if (payloadLength === 127) {
124
+ if (buffer.length < offset + 8) {
125
+ return false;
126
+ }
127
+ const big = buffer.readBigUInt64BE(offset);
128
+ if (big > BigInt(Number.MAX_SAFE_INTEGER)) {
129
+ this.fail('frame payload length is out of range');
130
+ return false;
131
+ }
132
+ payloadLength = Number(big);
133
+ offset += 8;
134
+ }
135
+ const isControl = (opcode & 0x8) !== 0;
136
+ if (isControl && (!fin || payloadLength > 125)) {
137
+ this.fail('invalid control frame');
138
+ return false;
139
+ }
140
+ const maskBytes = masked ? 4 : 0;
141
+ if (payloadLength > this.maxMessageBytes || this.fragmentBytes + payloadLength > this.maxMessageBytes) {
142
+ this.fail('message exceeds the configured size limit');
143
+ return false;
144
+ }
145
+ if (buffer.length < offset + maskBytes + payloadLength) {
146
+ return false;
147
+ }
148
+ const maskKey = masked ? buffer.subarray(offset, offset + 4) : undefined;
149
+ offset += maskBytes;
150
+ const payload = Buffer.from(buffer.subarray(offset, offset + payloadLength));
151
+ this.buffer = buffer.subarray(offset + payloadLength);
152
+ if (maskKey) {
153
+ for (let index = 0; index < payload.length; index++) {
154
+ payload[index] = payload[index] ^ maskKey[index % 4];
155
+ }
156
+ }
157
+ this.handleFrame(fin, opcode, payload);
158
+ return !this.failed;
159
+ }
160
+ handleFrame(fin, opcode, payload) {
161
+ switch (opcode) {
162
+ case exports.WS_OPCODE.continuation:
163
+ if (this.fragmentOpcode === undefined) {
164
+ this.fail('continuation frame without a started message');
165
+ return;
166
+ }
167
+ this.appendFragment(payload);
168
+ if (fin) {
169
+ this.completeMessage();
170
+ }
171
+ return;
172
+ case exports.WS_OPCODE.text:
173
+ case exports.WS_OPCODE.binary:
174
+ if (this.fragmentOpcode !== undefined) {
175
+ this.fail('new data frame while a fragmented message is in progress');
176
+ return;
177
+ }
178
+ this.fragmentOpcode = opcode;
179
+ this.appendFragment(payload);
180
+ if (fin) {
181
+ this.completeMessage();
182
+ }
183
+ return;
184
+ case exports.WS_OPCODE.close: {
185
+ if (payload.length === 1) {
186
+ this.fail('close frame with a 1 byte payload');
187
+ return;
188
+ }
189
+ // The close frame ends the data stream: nothing after it is dispatched.
190
+ this.failed = true;
191
+ this.buffer = Buffer.alloc(0);
192
+ this.sink.onClose(payload.length === 0 ? 1005 : payload.readUInt16BE(0), payload.subarray(2).toString('utf8'));
193
+ return;
194
+ }
195
+ case exports.WS_OPCODE.ping:
196
+ this.sink.onPing(payload);
197
+ return;
198
+ case exports.WS_OPCODE.pong:
199
+ this.sink.onPong(payload);
200
+ return;
201
+ default:
202
+ this.fail(`unsupported opcode ${opcode}`);
203
+ }
204
+ }
205
+ appendFragment(payload) {
206
+ this.fragmentBytes += payload.length;
207
+ if (this.fragmentBytes > this.maxMessageBytes) {
208
+ this.fail('message exceeds the configured size limit');
209
+ return;
210
+ }
211
+ this.fragments.push(payload);
212
+ }
213
+ completeMessage() {
214
+ const opcode = this.fragmentOpcode;
215
+ const fragments = this.fragments;
216
+ this.fragmentOpcode = undefined;
217
+ this.fragments = [];
218
+ this.fragmentBytes = 0;
219
+ const payload = fragments.length === 1 ? fragments[0] : Buffer.concat(fragments);
220
+ this.sink.onMessage(payload, opcode === exports.WS_OPCODE.binary);
221
+ }
222
+ }
223
+ exports.WebSocketFrameParser = WebSocketFrameParser;
224
+ //# sourceMappingURL=WebSocketFrames.js.map
@@ -4,6 +4,7 @@ import { Button, Input, cn } from '@undefineds.co/shared-ui';
4
4
  import { ExternalLink, Eye, EyeOff, KeyRound, Loader2, LogOut, Plus, RotateCw } from 'lucide-react';
5
5
  import { normalizeProxyUrl } from './ai-connections-client.js';
6
6
  import { offeringTitle } from './offering-label.js';
7
+ import { authorizationMethodsForOffering, isApiKeyMethod } from './authorization-methods.js';
7
8
  import { nextCredentialPriority } from './credential-labels.js';
8
9
  import { offeringEndpoint } from './offering-endpoints.js';
9
10
  export function AiApiKeyPool({ definition, offering, createOfferings, status, credentials, attempt, apiKey, baseUrl, busy, disabled, error, onApiKeyChange, onBaseUrlChange, onBeginApiKey, onBeginBrowser, onSaveApiKey, onDisconnect, onCreateApiKeyCredential, onUpdateCredential, initialEditing, initialCreate = false, onSavingChange, onCloseEdit, }) {
@@ -11,6 +12,12 @@ export function AiApiKeyPool({ definition, offering, createOfferings, status, cr
11
12
  const isConfigured = status === 'configured';
12
13
  const isConnected = status === 'connected';
13
14
  const hasPoolActions = Boolean(onCreateApiKeyCredential);
15
+ /**
16
+ * The legacy no-pool toolbar names its browser entry from the offering's own
17
+ * methods, like every other connect action. An api-key-only offering declares
18
+ * none, so that toolbar shows no browser button at all.
19
+ */
20
+ const browserMethod = authorizationMethodsForOffering(offering).find((method) => !isApiKeyMethod(method));
14
21
  const [createOfferingId, setCreateOfferingId] = useState(offering.id);
15
22
  const formOffering = createOfferings.find((item) => item.id === createOfferingId) ?? offering;
16
23
  const [showKey, setShowKey] = useState(false);
@@ -115,7 +122,7 @@ export function AiApiKeyPool({ definition, offering, createOfferings, status, cr
115
122
  }
116
123
  }
117
124
  };
118
- return (_jsxs("div", { className: cn('space-y-3', formMode && 'w-full'), children: [attempt?.userCode ? (_jsxs("div", { className: "border-l-2 border-primary bg-muted/30 px-3 py-2 text-sm", children: ["\u9A8C\u8BC1\u7801\uFF1A", _jsx("strong", { className: "font-mono", children: attempt.userCode })] })) : null, !initialCreate && !initialEditing ? _jsxs("div", { className: "flex flex-wrap gap-2", children: [onCreateApiKeyCredential && createOfferings.length > 0 ? (_jsxs(Button, { variant: "outline", size: "sm", disabled: busy || disabled || saving, onClick: openCreateForm, children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), "\u6DFB\u52A0 API Key"] })) : null, hasPoolActions ? null : isConnected ? (_jsxs(_Fragment, { children: [_jsxs(Button, { variant: "outline", size: "sm", disabled: busy || disabled || saving, onClick: onBeginBrowser, children: [busy ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : _jsx(RotateCw, { className: "mr-2 h-4 w-4" }), "\u91CD\u65B0\u8FDE\u63A5"] }), _jsxs(Button, { variant: "ghost", size: "sm", disabled: busy || disabled || saving, onClick: onDisconnect, children: [_jsx(LogOut, { className: "mr-2 h-4 w-4" }), "\u65AD\u5F00\u8FDE\u63A5"] })] })) : isConfigured ? (_jsxs(_Fragment, { children: [_jsxs(Button, { variant: "outline", size: "sm", "aria-label": "\u66F4\u65B0 API Key", disabled: busy || disabled || saving, onClick: onBeginApiKey, children: [_jsx(KeyRound, { className: "mr-2 h-4 w-4" }), "\u66F4\u65B0 API Key"] }), _jsx(Button, { variant: "ghost", size: "sm", disabled: busy || disabled || saving, onClick: onDisconnect, children: "\u79FB\u9664\u914D\u7F6E" })] })) : (_jsxs(_Fragment, { children: [_jsxs(Button, { variant: "outline", size: "sm", disabled: busy || disabled || saving || definition.browserMode === 'connectUnsupported', onClick: onBeginBrowser, children: [busy ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : _jsx(ExternalLink, { className: "mr-2 h-4 w-4" }), definition.browserLabel] }), _jsxs(Button, { variant: "outline", size: "sm", "aria-label": `${definition.name} API Key`, disabled: busy || disabled || saving, onClick: onBeginApiKey, children: [_jsx(KeyRound, { className: "mr-2 h-4 w-4" }), "\u914D\u7F6E API Key"] })] }))] }) : null, formMode ? (_jsxs("div", { className: "space-y-2 rounded-lg border border-border/50 bg-muted/10 p-3", children: [formMode === 'create' && createOfferings.length > 1 ? (_jsxs("label", { className: "block space-y-1 text-xs text-muted-foreground", children: [_jsx("span", { children: "\u5957\u9910 / \u533A\u57DF" }), _jsx("select", { "aria-label": `${definition.name} 套餐 / 区域`, value: createOfferingId, disabled: busy || disabled || saving, onChange: (event) => { setCreateOfferingId(event.target.value); setPoolFormError(undefined); }, className: "h-9 w-full rounded-md border border-input bg-background px-3 text-sm text-foreground", children: createOfferings.map((item) => _jsx("option", { value: item.id, children: offeringTitle(item) }, item.id)) })] })) : null, formMode === 'edit' ? (_jsx(Input, { disabled: busy || disabled || saving, autoComplete: "off", "aria-label": `${definition.name} API Key 标签`, placeholder: "\u540D\u79F0\uFF0C\u4F8B\u5982 Work key", value: poolLabel, onChange: (event) => setPoolLabel(event.target.value) })) : null, formMode === 'create' ? (_jsx(Input, { disabled: busy || disabled || saving, type: showKey ? 'text' : 'password', autoComplete: "new-password", "data-lpignore": "true", "data-1p-ignore": true, "aria-label": `${definition.name} API Key 输入`, placeholder: definition.apiKeyPlaceholder || '从官方控制台复制 API Key', value: poolApiKey, onChange: (event) => setPoolApiKey(event.target.value), className: "font-mono" })) : null, formMode === 'edit' || showAdvanced ? (_jsxs(_Fragment, { children: [_jsx(Input, { disabled: busy || disabled || saving, autoComplete: "off", "data-lpignore": "true", "data-1p-ignore": true, "aria-label": `${definition.name} Base URL 输入`, placeholder: offeringEndpoint(formMode === 'edit' ? offering : formOffering) || definition.defaultBaseUrl || '默认服务地址', value: poolBaseUrl, onChange: (event) => setPoolBaseUrl(event.target.value), className: "font-mono text-xs" }), _jsx(Input, { disabled: busy || disabled || saving, autoComplete: "off", "data-lpignore": "true", "data-1p-ignore": true, "aria-label": `${definition.name} Proxy URL 输入`, placeholder: "http://127.0.0.1:7890", value: poolProxyUrl, onChange: (event) => setPoolProxyUrl(event.target.value), className: "font-mono text-xs" })] })) : null, poolFormError ? _jsx("p", { className: "text-xs text-destructive", children: poolFormError }) : null, _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { size: "sm", "aria-label": formMode === 'create' ? `保存 ${definition.name} API Key` : '保存凭证', disabled: busy || disabled || saving || (formMode === 'create' && !poolApiKey.trim()), onClick: savePoolForm, children: formMode === 'create' ? '保存 API Key' : '保存凭证' }), _jsx(Button, { variant: "ghost", size: "sm", disabled: saving, onClick: closePoolForm, children: "\u53D6\u6D88" }), formMode === 'create' ? (_jsx(Button, { variant: "ghost", size: "sm", disabled: saving, onClick: () => setShowAdvanced((current) => !current), children: showAdvanced ? '收起高级设置' : '高级设置' })) : null] })] })) : null, apiKeyAttempt && !formMode ? (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-sm font-medium", children: "API Key" }), definition.apiKeyUrl ? (_jsx("a", { href: definition.apiKeyUrl, target: "_blank", rel: "noreferrer", className: "text-xs text-primary hover:underline", children: "\u83B7\u53D6 API Key" })) : null] }), _jsxs("div", { className: "group relative", children: [_jsx(Input, { disabled: busy || disabled || saving, type: showKey ? 'text' : 'password', autoComplete: "new-password", "data-lpignore": "true", "data-1p-ignore": true, "aria-label": `${definition.name} API Key 输入`, placeholder: definition.apiKeyPlaceholder || '从官方控制台复制 API Key', value: apiKey, onChange: (event) => onApiKeyChange(event.target.value), className: "border-border/60 bg-muted/20 pr-10 font-mono transition-colors focus:border-primary/50 focus:bg-background" }), _jsx("div", { className: "absolute bottom-1 right-1 top-1 flex items-center", children: _jsx(Button, { variant: "ghost", size: "icon", className: "h-full w-8 rounded hover:bg-muted", onClick: () => setShowKey((current) => !current), "aria-label": showKey ? '隐藏 API Key' : '显示 API Key', children: showKey
125
+ return (_jsxs("div", { className: cn('space-y-3', formMode && 'w-full'), children: [attempt?.userCode ? (_jsxs("div", { className: "border-l-2 border-primary bg-muted/30 px-3 py-2 text-sm", children: ["\u9A8C\u8BC1\u7801\uFF1A", _jsx("strong", { className: "font-mono", children: attempt.userCode })] })) : null, !initialCreate && !initialEditing ? _jsxs("div", { className: "flex flex-wrap gap-2", children: [onCreateApiKeyCredential && createOfferings.length > 0 ? (_jsxs(Button, { variant: "outline", size: "sm", disabled: busy || disabled || saving, onClick: openCreateForm, children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), "\u6DFB\u52A0 API Key"] })) : null, hasPoolActions ? null : isConnected ? (_jsxs(_Fragment, { children: [_jsxs(Button, { variant: "outline", size: "sm", disabled: busy || disabled || saving, onClick: onBeginBrowser, children: [busy ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : _jsx(RotateCw, { className: "mr-2 h-4 w-4" }), "\u91CD\u65B0\u8FDE\u63A5"] }), _jsxs(Button, { variant: "ghost", size: "sm", disabled: busy || disabled || saving, onClick: onDisconnect, children: [_jsx(LogOut, { className: "mr-2 h-4 w-4" }), "\u65AD\u5F00\u8FDE\u63A5"] })] })) : isConfigured ? (_jsxs(_Fragment, { children: [_jsxs(Button, { variant: "outline", size: "sm", "aria-label": "\u66F4\u65B0 API Key", disabled: busy || disabled || saving, onClick: onBeginApiKey, children: [_jsx(KeyRound, { className: "mr-2 h-4 w-4" }), "\u66F4\u65B0 API Key"] }), _jsx(Button, { variant: "ghost", size: "sm", disabled: busy || disabled || saving, onClick: onDisconnect, children: "\u79FB\u9664\u914D\u7F6E" })] })) : (_jsxs(_Fragment, { children: [browserMethod ? (_jsxs(Button, { variant: "outline", size: "sm", title: browserMethod.lifecycle === 'unavailable' ? browserMethod.reason : undefined, disabled: busy || disabled || saving || browserMethod.lifecycle === 'unavailable', onClick: onBeginBrowser, children: [busy ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : _jsx(ExternalLink, { className: "mr-2 h-4 w-4" }), browserMethod.label] })) : null, _jsxs(Button, { variant: "outline", size: "sm", "aria-label": `${definition.name} API Key`, disabled: busy || disabled || saving, onClick: onBeginApiKey, children: [_jsx(KeyRound, { className: "mr-2 h-4 w-4" }), "\u914D\u7F6E API Key"] })] }))] }) : null, formMode ? (_jsxs("div", { className: "space-y-2 rounded-lg border border-border/50 bg-muted/10 p-3", children: [formMode === 'create' && createOfferings.length > 1 ? (_jsxs("label", { className: "block space-y-1 text-xs text-muted-foreground", children: [_jsx("span", { children: "\u5957\u9910 / \u533A\u57DF" }), _jsx("select", { "aria-label": `${definition.name} 套餐 / 区域`, value: createOfferingId, disabled: busy || disabled || saving, onChange: (event) => { setCreateOfferingId(event.target.value); setPoolFormError(undefined); }, className: "h-9 w-full rounded-md border border-input bg-background px-3 text-sm text-foreground", children: createOfferings.map((item) => _jsx("option", { value: item.id, children: offeringTitle(item) }, item.id)) })] })) : null, formMode === 'edit' ? (_jsx(Input, { disabled: busy || disabled || saving, autoComplete: "off", "aria-label": `${definition.name} API Key 标签`, placeholder: "\u540D\u79F0\uFF0C\u4F8B\u5982 Work key", value: poolLabel, onChange: (event) => setPoolLabel(event.target.value) })) : null, formMode === 'create' ? (_jsx(Input, { disabled: busy || disabled || saving, type: showKey ? 'text' : 'password', autoComplete: "new-password", "data-lpignore": "true", "data-1p-ignore": true, "aria-label": `${definition.name} API Key 输入`, placeholder: definition.apiKeyPlaceholder || '从官方控制台复制 API Key', value: poolApiKey, onChange: (event) => setPoolApiKey(event.target.value), className: "font-mono" })) : null, formMode === 'edit' || showAdvanced ? (_jsxs(_Fragment, { children: [_jsx(Input, { disabled: busy || disabled || saving, autoComplete: "off", "data-lpignore": "true", "data-1p-ignore": true, "aria-label": `${definition.name} Base URL 输入`, placeholder: offeringEndpoint(formMode === 'edit' ? offering : formOffering) || definition.defaultBaseUrl || '默认服务地址', value: poolBaseUrl, onChange: (event) => setPoolBaseUrl(event.target.value), className: "font-mono text-xs" }), _jsx(Input, { disabled: busy || disabled || saving, autoComplete: "off", "data-lpignore": "true", "data-1p-ignore": true, "aria-label": `${definition.name} Proxy URL 输入`, placeholder: "http://127.0.0.1:7890", value: poolProxyUrl, onChange: (event) => setPoolProxyUrl(event.target.value), className: "font-mono text-xs" })] })) : null, poolFormError ? _jsx("p", { className: "text-xs text-destructive", children: poolFormError }) : null, _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { size: "sm", "aria-label": formMode === 'create' ? `保存 ${definition.name} API Key` : '保存凭证', disabled: busy || disabled || saving || (formMode === 'create' && !poolApiKey.trim()), onClick: savePoolForm, children: formMode === 'create' ? '保存 API Key' : '保存凭证' }), _jsx(Button, { variant: "ghost", size: "sm", disabled: saving, onClick: closePoolForm, children: "\u53D6\u6D88" }), formMode === 'create' ? (_jsx(Button, { variant: "ghost", size: "sm", disabled: saving, onClick: () => setShowAdvanced((current) => !current), children: showAdvanced ? '收起高级设置' : '高级设置' })) : null] })] })) : null, apiKeyAttempt && !formMode ? (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-sm font-medium", children: "API Key" }), definition.apiKeyUrl ? (_jsx("a", { href: definition.apiKeyUrl, target: "_blank", rel: "noreferrer", className: "text-xs text-primary hover:underline", children: "\u83B7\u53D6 API Key" })) : null] }), _jsxs("div", { className: "group relative", children: [_jsx(Input, { disabled: busy || disabled || saving, type: showKey ? 'text' : 'password', autoComplete: "new-password", "data-lpignore": "true", "data-1p-ignore": true, "aria-label": `${definition.name} API Key 输入`, placeholder: definition.apiKeyPlaceholder || '从官方控制台复制 API Key', value: apiKey, onChange: (event) => onApiKeyChange(event.target.value), className: "border-border/60 bg-muted/20 pr-10 font-mono transition-colors focus:border-primary/50 focus:bg-background" }), _jsx("div", { className: "absolute bottom-1 right-1 top-1 flex items-center", children: _jsx(Button, { variant: "ghost", size: "icon", className: "h-full w-8 rounded hover:bg-muted", onClick: () => setShowKey((current) => !current), "aria-label": showKey ? '隐藏 API Key' : '显示 API Key', children: showKey
119
126
  ? _jsx(EyeOff, { className: "h-4 w-4 text-muted-foreground" })
120
127
  : _jsx(Eye, { className: "h-4 w-4 text-muted-foreground" }) }) })] }), onBaseUrlChange ? (_jsxs("div", { className: "space-y-1.5", children: [_jsx("span", { className: "text-xs font-medium text-muted-foreground", children: "Base URL\uFF08\u9009\u586B\uFF09" }), _jsx(Input, { disabled: busy || disabled || saving, autoComplete: "off", "data-lpignore": "true", "data-1p-ignore": true, "aria-label": `${definition.name} Base URL 输入`, placeholder: definition.defaultBaseUrl || '默认服务地址', value: baseUrl, onChange: (event) => onBaseUrlChange(event.target.value), className: "border-border/60 bg-muted/20 font-mono text-xs transition-colors focus:border-primary/50 focus:bg-background" }), _jsxs("p", { className: "break-all font-mono text-[11px] text-muted-foreground opacity-80", children: [_jsx("span", { className: "mr-1 select-none opacity-50", children: "\u9884\u89C8:" }), (baseUrl.trim() || definition.defaultBaseUrl || '').replace(/\/+$/, ''), "/chat/completions"] })] })) : null, _jsx(Button, { size: "sm", "aria-label": `保存 ${definition.name} API Key`, disabled: !apiKey.trim() || busy || disabled, onClick: onSaveApiKey, children: "\u4FDD\u5B58 API Key" })] })) : null, error ? _jsx("p", { className: "text-sm text-destructive", children: error }) : null] }));
121
128
  }
@@ -1,8 +1,17 @@
1
1
  import type { AiConnectionsMode, AiProviderAuthorizationMethod, AiProviderOffering } from './ai-connections-client';
2
- export declare function AiAuthorizationActions({ methods, offering, hasCredentials, busy, disabled, onBeginOffering, onCreateLocalCredential, }: {
2
+ /**
3
+ * The offering's own entries, one button per declared `authorizationMethod`.
4
+ *
5
+ * A method that is implemented but unavailable in this deployment still gets its
6
+ * button, greyed at the same spec as its neighbours so the row keeps one line,
7
+ * with the reason as its tooltip. Nothing explains itself in a second row: the
8
+ * entry's own state is the message, and a list of internal reasons underneath
9
+ * the row reflows the buttons around it. Methods this build has not implemented
10
+ * never reach here - the server omits them.
11
+ */
12
+ export declare function AiAuthorizationActions({ methods, offering, busy, disabled, onBeginOffering, onCreateLocalCredential, }: {
3
13
  methods: AiProviderAuthorizationMethod[];
4
14
  offering: AiProviderOffering;
5
- hasCredentials: boolean;
6
15
  busy: boolean;
7
16
  disabled: boolean;
8
17
  onBeginOffering?: (offering: AiProviderOffering, mode: AiConnectionsMode, method?: AiProviderAuthorizationMethod) => void;
@@ -2,17 +2,34 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Button } from '@undefineds.co/shared-ui';
3
3
  import { ExternalLink, Loader2, Plus } from 'lucide-react';
4
4
  import { connectModeForMethod, isLocalMethod, isOAuthMode } from './authorization-methods.js';
5
- export function AiAuthorizationActions({ methods, offering, hasCredentials, busy, disabled, onBeginOffering, onCreateLocalCredential, }) {
5
+ /**
6
+ * The offering's own entries, one button per declared `authorizationMethod`.
7
+ *
8
+ * A method that is implemented but unavailable in this deployment still gets its
9
+ * button, greyed at the same spec as its neighbours so the row keeps one line,
10
+ * with the reason as its tooltip. Nothing explains itself in a second row: the
11
+ * entry's own state is the message, and a list of internal reasons underneath
12
+ * the row reflows the buttons around it. Methods this build has not implemented
13
+ * never reach here - the server omits them.
14
+ */
15
+ export function AiAuthorizationActions({ methods, offering, busy, disabled, onBeginOffering, onCreateLocalCredential, }) {
6
16
  if (methods.length === 0)
7
17
  return null;
8
- return (_jsx("div", { className: "space-y-2", children: _jsx("div", { className: "flex flex-wrap gap-2", children: methods.map((method) => {
9
- const connectMode = connectModeForMethod(method);
10
- if (isOAuthMode(connectMode)) {
11
- return (_jsxs(Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", disabled: busy || disabled || !onBeginOffering, onClick: () => onBeginOffering?.(offering, connectMode, method), children: [busy ? _jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : _jsx(ExternalLink, { className: "h-3.5 w-3.5" }), method.label || (hasCredentials ? '添加账号' : '登录')] }, method.id));
12
- }
13
- if (isLocalMethod(method)) {
14
- return (_jsxs(Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", title: "\u5BFC\u5165\u5F53\u524D\u8BBE\u5907\u5DF2\u6709\u767B\u5F55\u6001\uFF0C\u4E0D\u4F1A\u53D1\u8D77\u65B0\u7684\u6D4F\u89C8\u5668\u6388\u6743\u3002", disabled: busy || disabled || !onCreateLocalCredential, onClick: () => void onCreateLocalCredential?.(offering, method), children: [busy ? _jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : _jsx(Plus, { className: "h-3.5 w-3.5" }), method.label || '已有登录态'] }, method.id));
15
- }
18
+ return (_jsx("div", { className: "flex flex-wrap gap-2", children: methods.map((method) => {
19
+ const connectMode = connectModeForMethod(method);
20
+ const unavailable = method.lifecycle === 'unavailable';
21
+ // An entry without a label is not one the offering asked for; the
22
+ // button is named by the method itself, never by a provider default.
23
+ if (!method.label)
16
24
  return null;
17
- }) }) }));
25
+ if (isOAuthMode(connectMode)) {
26
+ return (_jsxs(Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", title: unavailable ? method.reason : undefined, disabled: busy || disabled || unavailable || !onBeginOffering, onClick: () => onBeginOffering?.(offering, connectMode, method), children: [busy ? _jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : _jsx(ExternalLink, { className: "h-3.5 w-3.5" }), method.label] }, method.id));
27
+ }
28
+ if (isLocalMethod(method)) {
29
+ return (_jsxs(Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", title: unavailable
30
+ ? method.reason
31
+ : '导入当前设备已有登录态,不会发起新的浏览器授权。', disabled: busy || disabled || unavailable || !onCreateLocalCredential, onClick: () => void onCreateLocalCredential?.(offering, method), children: [busy ? _jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : _jsx(Plus, { className: "h-3.5 w-3.5" }), method.label] }, method.id));
32
+ }
33
+ return null;
34
+ }) }));
18
35
  }
@@ -1,4 +1,5 @@
1
1
  import type { AiClientConfigurationModel } from '@undefineds.co/extension-sdk/web';
2
+ import { normalizeV1Endpoint } from './endpoint-urls';
2
3
  export declare const AI_CONNECTIONS_CLIENTS: readonly ["codex", "claude-code", "pi", "codebuddy"];
3
4
  export type AiConnectionsClientId = (typeof AI_CONNECTIONS_CLIENTS)[number];
4
5
  export interface AiClientConfigurationStatus {
@@ -68,4 +69,10 @@ export declare function AiClientConfigurationSection({ bridge, endpoint, client,
68
69
  compact?: boolean;
69
70
  onComplete?: () => void;
70
71
  }): import("react").JSX.Element;
72
+ /**
73
+ * The OpenAI-compatible base a client is pointed at, derived from the Xpod URL.
74
+ * The rule itself is shared with the client-config adapters, so what a copied
75
+ * config claims and what the adapters write cannot drift apart.
76
+ */
77
+ export declare const openAiCompatibleBaseUrl: typeof normalizeV1Endpoint;
71
78
  export declare function manualConfigurationText(client: AiConnectionsClientId, endpoint: string, apiKey?: string): string;
@@ -1,9 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useRef, useState } from 'react';
3
3
  import { Badge, Button, Input, } from '@undefineds.co/shared-ui';
4
- import { Copy, RotateCcw, SquareTerminal } from 'lucide-react';
4
+ import { RotateCcw, SquareTerminal } from 'lucide-react';
5
5
  import { normalizeAiConnectionsThrownError } from './ai-connections-client.js';
6
6
  import { getClientAvatar } from './client-visuals.js';
7
+ import { normalizeMessagesEndpoint, normalizeV1Endpoint } from './endpoint-urls.js';
8
+ import { AiCopyButton } from './AiCopyButton.js';
7
9
  export const AI_CONNECTIONS_CLIENTS = ['codex', 'claude-code', 'pi', 'codebuddy'];
8
10
  export const AI_CLIENT_LABELS = {
9
11
  codex: 'Codex',
@@ -23,12 +25,10 @@ export function AiClientConfigurationSection({ bridge, endpoint, client, createC
23
25
  const [dryRun, setDryRun] = useState();
24
26
  const [confirmationValue, setConfirmationValue] = useState('');
25
27
  const [busy, setBusy] = useState(false);
26
- const [copiedManualConfig, setCopiedManualConfig] = useState(false);
27
28
  const autoApplyStarted = useRef(false);
28
29
  useEffect(() => {
29
30
  setDryRun(undefined);
30
31
  setConfirmationValue('');
31
- setCopiedManualConfig(false);
32
32
  if (!bridge) {
33
33
  setStatus({ status: 'unavailable' });
34
34
  return;
@@ -149,13 +149,10 @@ export function AiClientConfigurationSection({ bridge, endpoint, client, createC
149
149
  const confirmationSatisfied = !confirmation?.required || confirmationValue === confirmation.token;
150
150
  const clientLabel = AI_CLIENT_LABELS[client];
151
151
  const manual = !bridge;
152
- const copyManualConfig = async () => {
153
- await navigator.clipboard?.writeText(manualConfigurationText(client, endpoint, manualApiKey));
154
- setCopiedManualConfig(true);
155
- };
152
+ const manualConfig = manualConfigurationText(client, endpoint, manualApiKey);
156
153
  return (_jsxs("div", { className: compact ? '' : 'overflow-hidden rounded-md border border-border/60', children: [!compact ? _jsxs("div", { className: "flex flex-wrap items-center gap-2 px-3 py-2", children: [_jsx("span", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground", children: _jsx(AiClientIcon, { client: client }) }), _jsxs("div", { className: "min-w-[10rem] flex-1", children: [_jsx("div", { className: "text-sm font-medium", children: clientLabel }), !manual ? _jsx("div", { className: "mt-0.5 text-xs text-muted-foreground", children: status.message ?? (status.status === 'configured'
157
154
  ? `${clientLabel} 正在使用 Xpod。`
158
- : '可自动写入本机配置。') }) : null] }), !manual ? _jsx(Badge, { variant: "secondary", children: statusLabel(status.status) }) : null, manual ? (_jsxs(Button, { variant: "ghost", size: "icon", "aria-label": `复制 ${clientLabel} 配置`, title: `复制 ${clientLabel} 配置`, onClick: () => void copyManualConfig(), children: [_jsx(Copy, { className: "h-4 w-4" }), _jsx("span", { className: "sr-only", children: copiedManualConfig ? '已复制' : '复制配置' })] })) : (_jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Button, { variant: "outline", size: "sm", "aria-label": `配置 ${clientLabel}`, disabled: busy, onClick: () => void plan(), children: "\u914D\u7F6E" }), _jsx(Button, { variant: "ghost", size: "icon", "aria-label": `恢复 ${clientLabel} 配置`, disabled: status.status === 'notConfigured' || busy, onClick: () => void restore(), children: _jsx(RotateCcw, { className: "h-4 w-4" }) })] }))] }) : null, compact && busy ? (_jsxs("div", { className: "py-1 text-xs text-muted-foreground", children: ["\u6B63\u5728\u5E94\u7528 ", clientLabel, " \u914D\u7F6E\u2026"] })) : null, compact && !busy && status.message ? (_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2 py-1 text-xs text-destructive", children: [_jsx("span", { children: status.message }), _jsx(Button, { variant: "outline", size: "sm", onClick: () => void plan(), children: "\u91CD\u8BD5\u5E94\u7528\u914D\u7F6E" })] })) : null, dryRun ? (_jsxs("div", { className: "space-y-3 border-t border-border/60 bg-muted/20 px-4 py-3", children: [_jsx("div", { className: "text-xs font-medium", children: "\u5C06\u6267\u884C\u4EE5\u4E0B\u66F4\u6539" }), dryRun.changes.map((change) => (_jsxs("div", { className: "text-xs text-muted-foreground", children: [_jsx("span", { className: "font-mono", children: change.target }), ' · ', changeActionLabel(change.action), change.backup ? ' · 创建备份' : ''] }, `${change.target}:${change.action}`))), confirmation?.required ? (_jsxs("div", { className: "space-y-2", children: [confirmation.message ? _jsx("div", { className: "text-xs text-muted-foreground", children: confirmation.message }) : null, _jsxs("div", { className: "text-xs text-muted-foreground", children: ["\u786E\u8BA4\u7801\uFF1A", _jsx("code", { className: "font-mono text-foreground", children: confirmation.token })] }), _jsx(Input, { "aria-label": `输入确认码以应用 ${clientLabel} 配置`, value: confirmationValue, onChange: (event) => setConfirmationValue(event.target.value) })] })) : null, _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { size: "sm", "aria-label": confirmation?.required
155
+ : '可自动写入本机配置。') }) : null] }), !manual ? _jsx(Badge, { variant: "secondary", children: statusLabel(status.status) }) : null, manual ? (_jsx(AiCopyButton, { value: manualConfig, label: `${clientLabel} 配置`, variant: "ghost", size: "icon", iconClassName: "h-4 w-4" })) : (_jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Button, { variant: "outline", size: "sm", "aria-label": `配置 ${clientLabel}`, disabled: busy, onClick: () => void plan(), children: "\u914D\u7F6E" }), _jsx(Button, { variant: "ghost", size: "icon", "aria-label": `恢复 ${clientLabel} 配置`, disabled: status.status === 'notConfigured' || busy, onClick: () => void restore(), children: _jsx(RotateCcw, { className: "h-4 w-4" }) })] }))] }) : null, compact && busy ? (_jsxs("div", { className: "py-1 text-xs text-muted-foreground", children: ["\u6B63\u5728\u5E94\u7528 ", clientLabel, " \u914D\u7F6E\u2026"] })) : null, compact && !busy && status.message ? (_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2 py-1 text-xs text-destructive", children: [_jsx("span", { children: status.message }), _jsx(Button, { variant: "outline", size: "sm", onClick: () => void plan(), children: "\u91CD\u8BD5\u5E94\u7528\u914D\u7F6E" })] })) : null, dryRun ? (_jsxs("div", { className: "space-y-3 border-t border-border/60 bg-muted/20 px-4 py-3", children: [_jsx("div", { className: "text-xs font-medium", children: "\u5C06\u6267\u884C\u4EE5\u4E0B\u66F4\u6539" }), dryRun.changes.map((change) => (_jsxs("div", { className: "text-xs text-muted-foreground", children: [_jsx("span", { className: "font-mono", children: change.target }), ' · ', changeActionLabel(change.action), change.backup ? ' · 创建备份' : ''] }, `${change.target}:${change.action}`))), confirmation?.required ? (_jsxs("div", { className: "space-y-2", children: [confirmation.message ? _jsx("div", { className: "text-xs text-muted-foreground", children: confirmation.message }) : null, _jsxs("div", { className: "text-xs text-muted-foreground", children: ["\u786E\u8BA4\u7801\uFF1A", _jsx("code", { className: "font-mono text-foreground", children: confirmation.token })] }), _jsx(Input, { "aria-label": `输入确认码以应用 ${clientLabel} 配置`, value: confirmationValue, onChange: (event) => setConfirmationValue(event.target.value) })] })) : null, _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { size: "sm", "aria-label": confirmation?.required
159
156
  ? `确认并应用 ${clientLabel} 配置`
160
157
  : `应用 ${clientLabel} 配置`, disabled: !createClientCredential || busy || !confirmationSatisfied, onClick: () => void apply(), children: confirmation?.required ? '确认并应用' : '应用配置' }), _jsx(Button, { variant: "ghost", size: "sm", disabled: busy, onClick: () => {
161
158
  setDryRun(undefined);
@@ -179,11 +176,16 @@ function statusLabel(status) {
179
176
  default: return '未配置';
180
177
  }
181
178
  }
179
+ /**
180
+ * The OpenAI-compatible base a client is pointed at, derived from the Xpod URL.
181
+ * The rule itself is shared with the client-config adapters, so what a copied
182
+ * config claims and what the adapters write cannot drift apart.
183
+ */
184
+ export const openAiCompatibleBaseUrl = normalizeV1Endpoint;
182
185
  export function manualConfigurationText(client, endpoint, apiKey) {
183
186
  const secret = apiKey ?? '<粘贴 Xpod API Key>';
184
- const baseUrl = endpoint.trim().replace(/\/+$/, '');
185
- const v1Url = baseUrl.endsWith('/v1') ? baseUrl : `${baseUrl}/v1`;
186
- const messagesUrl = baseUrl.replace(/\/v1$/, '');
187
+ const v1Url = normalizeV1Endpoint(endpoint);
188
+ const messagesUrl = normalizeMessagesEndpoint(endpoint);
187
189
  switch (client) {
188
190
  case 'codex':
189
191
  return [
@@ -33,7 +33,7 @@ export function AiConnectDialog({ controller, definition, offerings, apiOffering
33
33
  const authorizationError = error?.offeringId === offering.id ? error.authorization : undefined;
34
34
  const attemptedMethod = methods.find((method) => method.id === (authorizationError?.authorizationMethodId ?? offeringAttempt?.authorizationMethodId))
35
35
  ?? activeMethods.find(isOAuthMethod);
36
- const attemptedMode = authorizationError?.mode ?? offeringAttempt?.mode ?? (attemptedMethod ? connectModeForMethod(attemptedMethod) : modeForOffering(offering, definition));
36
+ const attemptedMode = authorizationError?.mode ?? offeringAttempt?.mode ?? (attemptedMethod ? connectModeForMethod(attemptedMethod) : modeForOffering(offering));
37
37
  const offeringError = error?.offeringId === offering.id ? error.message : undefined;
38
38
  if (offering.lifecycle === 'unavailable' && activeMethods.length === 0) {
39
39
  return _jsxs("fieldset", { "data-create-offering": offering.id, className: "space-y-2 border-t border-border/50 pt-3 first:border-t-0 first:pt-0", children: [_jsx("legend", { className: "px-1 text-sm font-medium", children: offeringTitle(offering) }), _jsx("p", { className: "text-xs text-muted-foreground", children: offering.kind === 'oauth-subscription'
@@ -2,9 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useContext, useRef } from 'react';
3
3
  import { Avatar, AvatarFallback, AvatarImage, cn } from '@undefineds.co/shared-ui';
4
4
  import { WorkspaceLayoutContext } from '@undefineds.co/extension-sdk/react';
5
- import { getProviderAvatar, getProviderAvatarBackground } from './provider-visuals.js';
6
- import { AI_CONNECTIONS_PINNED_SECTIONS, PROVIDERS, useProviderLoadError, useProviderProducts, useProviderSearch, useProviderStates, useSelectedCredentialId, useSelectedProvider, useSelectedSection, } from './controller.js';
5
+ import { XPOD_AVATAR, getProviderAvatar, getProviderAvatarBackground } from './provider-visuals.js';
6
+ import { AI_CONNECTIONS_PINNED_SECTIONS, PROVIDERS, useAvailableProviders, useProviderLoadError, useProviderProducts, useProviderSearch, useProviderStates, useSelectedCredentialId, useSelectedProvider, useSelectedSection, } from './controller.js';
7
7
  export function AiConnectionsList({ controller }) {
8
+ const availableProviders = useAvailableProviders(controller);
8
9
  const workspace = useContext(WorkspaceLayoutContext);
9
10
  const selectedSection = useSelectedSection(controller);
10
11
  const selectedProvider = useSelectedProvider(controller);
@@ -13,7 +14,10 @@ export function AiConnectionsList({ controller }) {
13
14
  const providerStates = useProviderStates(controller);
14
15
  const providerProducts = useProviderProducts(controller);
15
16
  const providerLoadError = useProviderLoadError(controller);
16
- const providerItems = PROVIDERS.reduce((items, provider) => {
17
+ const visibleProviders = availableProviders
18
+ ? PROVIDERS.filter((provider) => availableProviders.includes(provider.id))
19
+ : PROVIDERS;
20
+ const providerItems = visibleProviders.reduce((items, provider) => {
17
21
  if (provider.id !== 'custom')
18
22
  return [...items, { ...provider }];
19
23
  const credentials = providerProducts.custom?.credentials ?? [];
@@ -86,11 +90,11 @@ function moveSelection(items, requestedIndex, controller, optionRefs) {
86
90
  }
87
91
  /**
88
92
  * The pinned section is an issued-credential surface, i.e. another provider from
89
- * the client's point of view, so it uses the provider row's mark slot instead of
90
- * a generic key icon.
93
+ * the client's point of view, so it carries the Xpod provider mark and falls
94
+ * back to its initials only while that mark is unavailable.
91
95
  */
92
96
  function PinnedMark({ section: _section }) {
93
- return (_jsx(Avatar, { className: "h-9 w-9 shrink-0 rounded-md border border-border/20 bg-muted", children: _jsx(AvatarFallback, { className: "rounded-md bg-muted text-[10px] font-bold uppercase text-muted-foreground", children: "XP" }) }));
97
+ return (_jsxs(Avatar, { className: "h-9 w-9 shrink-0 rounded-md border border-border/20", children: [_jsx(AvatarImage, { src: XPOD_AVATAR, className: "object-cover" }), _jsx(AvatarFallback, { className: "rounded-md bg-muted text-[10px] font-bold uppercase text-muted-foreground", children: "XP" })] }));
94
98
  }
95
99
  function ProviderStateIndicator({ state, statusId, }) {
96
100
  const active = state === 'configured' || state === 'connected';
@@ -1,4 +1,19 @@
1
1
  import { type AiConnectionsController } from './controller';
2
+ /**
3
+ * The page's live credentials table.
4
+ *
5
+ * `useCredentialRows` subscribes to the controller's snapshot of the collection:
6
+ * the rows it returns already include optimistic writes, so a create/update/
7
+ * delete shows before the Pod has confirmed it, and the projection diff keeps
8
+ * unchanged rows identical. Both the table and the layer that reads it are
9
+ * loaded lazily, so this hook is a plain `useSyncExternalStore` over whatever the
10
+ * controller has - which is nothing until the collection's first read lands.
11
+ *
12
+ * Until then - while the layer is still loading, after a failed first read, or
13
+ * when the host offers no collection at all - `credentialRows` stays undefined
14
+ * and the page keeps rendering what the store reported, so a table that cannot
15
+ * load is never shown as an empty table.
16
+ */
2
17
  export declare function AiConnectionsMain({ controller, renderToaster }: {
3
18
  controller: AiConnectionsController;
4
19
  renderToaster?: boolean;