@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
@@ -1,13 +1,22 @@
1
1
  import type { AiConnectionsClient, AiGatewayModel } from './ai-connections-client';
2
2
  import { type AiClientConfigurationBridge } from './AiClientConfigurationSection';
3
+ import { type GatewayModelSelection } from './AiGatewayModelsSection';
3
4
  /**
4
5
  * The Xpod provider page. From a coding client's point of view Xpod is just
5
- * another provider, so this surface shares the provider pages' chrome: a
6
- * provider-style header, a credential-pool-style section, and rows that only
7
- * record what the issued credential means.
6
+ * another provider, so this surface shares the provider pages' components: the
7
+ * same header (`AiProviderHeader`), the same model list (`AiGatewayModelsSection`
8
+ * over `AiModelCatalog`), and the same endpoint list (`AiEndpointList`) that the
9
+ * provider pages use for their offerings' protocols.
8
10
  */
9
- export declare function AiGatewayKeysSection({ client, clientConfigurationBridge, gatewayModels, }: {
11
+ export declare function AiGatewayKeysSection({ client, clientConfigurationBridge, gatewayModels, modelSelection, liveRevision, }: {
10
12
  client: AiConnectionsClient;
11
13
  clientConfigurationBridge?: AiClientConfigurationBridge;
12
14
  gatewayModels?: AiGatewayModel[];
15
+ /** Publishes or withdraws models on the models list endpoint, from this page. */
16
+ modelSelection?: GatewayModelSelection;
17
+ /**
18
+ * Advances when the credentials table changed outside this page (another
19
+ * client, a script); the Key list lives in that table and re-reads with it.
20
+ */
21
+ liveRevision?: number;
13
22
  }): import("react").JSX.Element;
@@ -1,13 +1,22 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useRef, useState } from 'react';
3
- import { Avatar, AvatarFallback, Badge, Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Input, controlFocusClass, dismissToast, toast, } from '@undefineds.co/shared-ui';
4
- import { Check, Copy, KeyRound, Loader2, Plus } from 'lucide-react';
3
+ import { Badge, Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Input, TooltipProvider, controlFocusClass, dismissToast, toast, } from '@undefineds.co/shared-ui';
4
+ import { Check, Loader2, Plus, Settings2 } from 'lucide-react';
5
5
  import { AI_CONNECTIONS_CLIENTS, AI_CLIENT_LABELS, manualConfigurationText, } from './AiClientConfigurationSection.js';
6
+ import { AiCopyButton } from './AiCopyButton.js';
7
+ import { AiEndpointList } from './AiEndpointList.js';
8
+ import { AiProviderHeader } from './AiProviderHeader.js';
9
+ import { xpodProtocolEndpoints } from './gateway-endpoints.js';
10
+ import { XPOD_AVATAR } from './provider-visuals.js';
6
11
  import { AiGatewayKeyRow } from './AiGatewayKeyRow.js';
12
+ import { AiGatewayModelsSection } from './AiGatewayModelsSection.js';
7
13
  const DEFAULT_KEY_NAME = '我的 API Key';
8
14
  const CREATED_NOTIFICATION = 'API Key 已创建,请复制或应用到客户端。';
9
15
  const UNPERSISTED_COPY_MESSAGE = '这个 API Key 只在创建时可见:请销毁它,然后重新创建并立即复制或应用。';
10
16
  const UNPERSISTED_APPLY_MESSAGE = '这个 API Key 只在创建时可见:请销毁它,然后重新创建并直接应用到客户端。';
17
+ /** Header tooltip: what Xpod is, then how the Key itself is protected. */
18
+ const XPOD_DESCRIPTION = '把已接入的 Provider 模型统一发布给编码客户端,兼容 OpenAI 与 Anthropic 协议。';
19
+ const XPOD_CREDENTIAL_NOTE = 'API Key 保存在当前 Pod,由 Pod 权限保护;Xpod 不保存明文。';
11
20
  const SELECT_CLASS = [
12
21
  'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm transition-[border-color]',
13
22
  'disabled:cursor-not-allowed disabled:opacity-50',
@@ -15,11 +24,12 @@ const SELECT_CLASS = [
15
24
  ].join(' ');
16
25
  /**
17
26
  * The Xpod provider page. From a coding client's point of view Xpod is just
18
- * another provider, so this surface shares the provider pages' chrome: a
19
- * provider-style header, a credential-pool-style section, and rows that only
20
- * record what the issued credential means.
27
+ * another provider, so this surface shares the provider pages' components: the
28
+ * same header (`AiProviderHeader`), the same model list (`AiGatewayModelsSection`
29
+ * over `AiModelCatalog`), and the same endpoint list (`AiEndpointList`) that the
30
+ * provider pages use for their offerings' protocols.
21
31
  */
22
- export function AiGatewayKeysSection({ client, clientConfigurationBridge, gatewayModels, }) {
32
+ export function AiGatewayKeysSection({ client, clientConfigurationBridge, gatewayModels, modelSelection, liveRevision = 0, }) {
23
33
  const [keys, setKeys] = useState([]);
24
34
  const [loading, setLoading] = useState(true);
25
35
  const [showCreate, setShowCreate] = useState(false);
@@ -32,13 +42,11 @@ export function AiGatewayKeysSection({ client, clientConfigurationBridge, gatewa
32
42
  const [issuedClient, setIssuedClient] = useState();
33
43
  const [appliedClient, setAppliedClient] = useState();
34
44
  const [applying, setApplying] = useState(false);
35
- const [copied, setCopied] = useState();
36
45
  const [busyKeyId, setBusyKeyId] = useState();
37
46
  const [error, setError] = useState();
38
47
  const plaintexts = useRef(new Map());
39
48
  const operation = useRef(false);
40
49
  const notification = useRef(undefined);
41
- const copyTimer = useRef(undefined);
42
50
  const notify = useCallback((options) => {
43
51
  if (notification.current)
44
52
  dismissToast(notification.current);
@@ -69,16 +77,30 @@ export function AiGatewayKeysSection({ client, clientConfigurationBridge, gatewa
69
77
  });
70
78
  return () => {
71
79
  active = false;
72
- clearTimeout(copyTimer.current);
73
80
  if (notification.current)
74
81
  dismissToast(notification.current);
75
82
  };
76
83
  }, [client, notifyError]);
84
+ // A change made elsewhere only needs new rows: it must not drop the wrapper
85
+ // copies this session is still showing, nor flash the loading state.
86
+ useEffect(() => {
87
+ if (liveRevision === 0)
88
+ return;
89
+ let active = true;
90
+ void client.listGatewayKeys()
91
+ .then((records) => {
92
+ if (active)
93
+ setKeys(records.filter((record) => !record.revokedAt));
94
+ })
95
+ .catch(() => undefined);
96
+ return () => {
97
+ active = false;
98
+ };
99
+ }, [client, liveRevision]);
77
100
  const openCreate = () => {
78
101
  setError(undefined);
79
102
  setName(DEFAULT_KEY_NAME);
80
103
  setPurpose('');
81
- setCopied(undefined);
82
104
  // A key issued earlier in this session keeps its wrapper in the cache, so
83
105
  // the flow resumes there instead of pretending the key was never created.
84
106
  setShowCreate(true);
@@ -87,7 +109,6 @@ export function AiGatewayKeysSection({ client, clientConfigurationBridge, gatewa
87
109
  setIssued(undefined);
88
110
  setIssuedClient(undefined);
89
111
  setAppliedClient(undefined);
90
- setCopied(undefined);
91
112
  setError(undefined);
92
113
  setName(DEFAULT_KEY_NAME);
93
114
  setPurpose('');
@@ -116,7 +137,6 @@ export function AiGatewayKeysSection({ client, clientConfigurationBridge, gatewa
116
137
  setIssued(created.record);
117
138
  setIssuedClient(purpose);
118
139
  setAppliedClient(undefined);
119
- setCopied(undefined);
120
140
  notify({ variant: 'success', description: CREATED_NOTIFICATION });
121
141
  }
122
142
  catch (cause) {
@@ -132,24 +152,6 @@ export function AiGatewayKeysSection({ client, clientConfigurationBridge, gatewa
132
152
  throw new Error(message);
133
153
  return plaintext;
134
154
  };
135
- const copy = async (record, target) => {
136
- setError(undefined);
137
- try {
138
- const plaintext = sessionPlaintext(record, UNPERSISTED_COPY_MESSAGE);
139
- if (!navigator.clipboard?.writeText) {
140
- throw new Error('当前浏览器无法访问剪贴板,请允许剪贴板访问后重试。');
141
- }
142
- await navigator.clipboard.writeText(target === 'key'
143
- ? plaintext
144
- : manualConfigurationText(target, client.apiBase, plaintext));
145
- setCopied(target);
146
- clearTimeout(copyTimer.current);
147
- copyTimer.current = setTimeout(() => setCopied(undefined), 2000);
148
- }
149
- catch (cause) {
150
- setError(errorMessage(cause));
151
- }
152
- };
153
155
  const apply = async () => {
154
156
  if (!issued || !issuedClient || !clientConfigurationBridge)
155
157
  return;
@@ -212,7 +214,6 @@ export function AiGatewayKeysSection({ client, clientConfigurationBridge, gatewa
212
214
  setIssued(undefined);
213
215
  setIssuedClient(undefined);
214
216
  setAppliedClient(undefined);
215
- setCopied(undefined);
216
217
  }
217
218
  }
218
219
  catch (cause) {
@@ -223,13 +224,9 @@ export function AiGatewayKeysSection({ client, clientConfigurationBridge, gatewa
223
224
  setBusyKeyId(undefined);
224
225
  }
225
226
  };
226
- return (_jsxs("section", { className: "space-y-8 [container-type:inline-size]", "aria-label": "API Keys", children: [_jsxs("header", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Avatar, { className: "h-9 w-9 shrink-0 rounded-lg border border-border/50 bg-muted/50 shadow-sm", children: _jsx(AvatarFallback, { className: "rounded-lg bg-transparent text-sm font-bold uppercase text-muted-foreground", children: "XP" }) }), _jsxs("div", { className: "flex flex-col justify-center gap-1", children: [_jsx("h2", { className: "text-base font-semibold leading-none tracking-tight text-foreground", children: "Xpod" }), _jsx("p", { className: "max-w-3xl text-xs leading-snug text-muted-foreground", children: "API Key \u7528\u4E8E\u8BA9\u5BA2\u6237\u7AEF\u628A Xpod \u5F53\u4F5C Provider \u63A5\u5165\uFF1BXpod \u4E0D\u4FDD\u5B58 Key \u660E\u6587\u3002" })] })] }), _jsx(Badge, { variant: keys.length > 0 ? 'default' : 'secondary', children: keys.length > 0 ? `已签发 ${keys.length} 个` : '未配置' })] }), _jsxs("section", { className: "space-y-3", "aria-label": "\u5DF2\u7B7E\u53D1 API Key", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [_jsxs("h3", { className: "flex items-center gap-2 text-sm font-medium text-foreground/90", children: [_jsx(KeyRound, { "aria-hidden": "true", className: "h-4 w-4 text-primary" }), "\u5DF2\u7B7E\u53D1 API Key"] }), _jsxs(Button, { size: "sm", "aria-label": "\u65B0\u5EFA API Key", disabled: creating || loading, onClick: openCreate, children: [_jsx(Plus, { "aria-hidden": "true", className: "mr-2 h-4 w-4" }), "\u65B0\u5EFA API Key"] })] }), loading ? (_jsxs("div", { className: "flex items-center gap-2 py-6 text-sm text-muted-foreground", children: [_jsx(Loader2, { "aria-hidden": "true", className: "h-4 w-4 animate-spin" }), "\u6B63\u5728\u8BFB\u53D6 API Key"] })) : keys.length === 0 ? (_jsx("p", { className: "py-8 text-center text-sm text-muted-foreground", children: "\u5C1A\u672A\u7B7E\u53D1 API Key\u3002" })) : (_jsx("ul", { "aria-label": "API Key \u5217\u8868", className: "rounded-xl border border-border/70", children: keys.map((record) => (_jsx(AiGatewayKeyRow, { record: record, busy: Boolean(busyKeyId), onDestroy: () => void destroy(record) }, record.id))) }))] }), _jsx(Dialog, { open: showCreate, onOpenChange: (open) => { if (!open && (creating || applying))
227
- return; setShowCreate(open); }, children: _jsxs(DialogContent, { className: "sm:max-w-md", "aria-describedby": undefined, children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: issued ? 'API Key 已签发' : '新建 API Key' }) }), issued && issuedClient ? (_jsxs("div", { className: "space-y-5", children: [_jsxs("div", { className: "space-y-1.5", children: [_jsxs("p", { className: "text-sm", children: ["\u5DF2\u7B7E\u53D1\u300C", issued.name || '未命名 API Key', "\u300D\uFF0C\u7528\u9014\uFF1A", AI_CLIENT_LABELS[issuedClient], "\u3002"] }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Xpod \u4E0D\u4FDD\u5B58 Key \u660E\u6587\uFF0C\u8BF7\u7ACB\u5373\u590D\u5236\u6216\u76F4\u63A5\u5E94\u7528\u5230\u5BA2\u6237\u7AEF\uFF1B\u79BB\u5F00\u672C\u6B21\u4F1A\u8BDD\u540E\u65E0\u6CD5\u518D\u6B21\u83B7\u53D6\u3002" })] }), issued.maskedHint ? (_jsx("code", { className: "block truncate rounded-md border border-border/60 bg-muted/30 px-3 py-2 font-mono text-xs text-muted-foreground", children: issued.maskedHint })) : null, !clientConfigurationBridge ? (_jsx("p", { className: "text-xs text-muted-foreground", children: "\u5F53\u524D Web \u73AF\u5883\u65E0\u6CD5\u81EA\u52A8\u5199\u5165\u5BA2\u6237\u7AEF\u914D\u7F6E\uFF0C\u8BF7\u590D\u5236\u540E\u624B\u52A8\u7C98\u8D34\uFF1B\u81EA\u52A8\u5E94\u7528\u9700\u8981\u672C\u673A\u8FDE\u63A5\u3002" })) : null, error ? _jsx("p", { role: "alert", className: "text-sm text-destructive", children: error }) : null, _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsxs(Button, { type: "button", variant: "outline", size: "sm", "aria-label": "\u590D\u5236 API Key", disabled: applying, onClick: () => void copy(issued, 'key'), children: [copied === 'key'
228
- ? _jsx(Check, { "aria-hidden": "true", className: "mr-1.5 h-3.5 w-3.5 text-emerald-600" })
229
- : _jsx(Copy, { "aria-hidden": "true", className: "mr-1.5 h-3.5 w-3.5" }), copied === 'key' ? '已复制' : '复制 API Key'] }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", disabled: applying, "aria-label": `复制 ${AI_CLIENT_LABELS[issuedClient]} 配置`, onClick: () => void copy(issued, issuedClient), children: [copied === issuedClient
230
- ? _jsx(Check, { "aria-hidden": "true", className: "mr-1.5 h-3.5 w-3.5 text-emerald-600" })
231
- : _jsx(Copy, { "aria-hidden": "true", className: "mr-1.5 h-3.5 w-3.5" }), copied === issuedClient ? '已复制' : `复制 ${AI_CLIENT_LABELS[issuedClient]} 配置`] }), clientConfigurationBridge ? (appliedClient ? (_jsxs("span", { role: "status", className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(Check, { "aria-hidden": "true", className: "h-3.5 w-3.5" }), "\u5DF2\u5E94\u7528\u5230 ", AI_CLIENT_LABELS[appliedClient]] })) : (_jsxs(Button, { type: "button", size: "sm", disabled: applying, "aria-label": `应用到 ${AI_CLIENT_LABELS[issuedClient]}`, onClick: () => void apply(), children: [applying ? _jsx(Loader2, { "aria-hidden": "true", className: "mr-2 h-4 w-4 animate-spin" }) : null, applying ? '正在应用…' : `应用到 ${AI_CLIENT_LABELS[issuedClient]}`] }))) : null] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", disabled: applying, onClick: beginAnother, children: "\u518D\u5EFA\u4E00\u4E2A" }), _jsx(Button, { type: "button", variant: "outline", onClick: () => setShowCreate(false), children: "\u5B8C\u6210" })] })] })) : (_jsxs("form", { className: "space-y-5", onSubmit: (event) => { event.preventDefault(); if (!creating)
232
- void create(); }, children: [_jsxs("label", { className: "block space-y-2", children: [_jsx("span", { className: "text-sm font-medium", children: "\u540D\u79F0" }), _jsx(Input, { autoFocus: true, "aria-label": "API Key \u540D\u79F0", value: name, disabled: creating, onChange: (event) => setName(event.target.value) })] }), _jsxs("label", { className: "block space-y-2", children: [_jsx("span", { className: "text-sm font-medium", children: "\u7528\u9014" }), _jsxs("select", { "aria-label": "API Key \u7528\u9014", className: SELECT_CLASS, value: purpose, disabled: creating, onChange: (event) => setPurpose(event.target.value), children: [_jsx("option", { value: "", disabled: true, children: "\u9009\u62E9\u5BA2\u6237\u7AEF\u5E94\u7528" }), AI_CONNECTIONS_CLIENTS.map((clientId) => (_jsx("option", { value: clientId, children: AI_CLIENT_LABELS[clientId] }, clientId)))] })] }), _jsx("p", { className: "text-xs text-muted-foreground", children: "\u7528\u9014\u5728\u521B\u5EFA\u65F6\u786E\u5B9A\uFF0CKey \u4F1A\u7ED1\u5B9A\u5230\u8BE5\u5BA2\u6237\u7AEF\u5E94\u7528\u3002" }), error ? _jsx("p", { role: "alert", className: "text-sm text-destructive", children: error }) : null, _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", disabled: creating, onClick: () => setShowCreate(false), children: "\u53D6\u6D88" }), _jsxs(Button, { type: "submit", "aria-label": "\u521B\u5EFA API Key", disabled: creating || !name.trim() || !purpose, children: [creating ? _jsx(Loader2, { "aria-hidden": "true", className: "mr-2 h-4 w-4 animate-spin" }) : null, creating ? '正在创建…' : '创建 API Key'] })] })] }))] }) })] }));
227
+ return (_jsx(TooltipProvider, { children: _jsxs("section", { className: "space-y-8", "aria-label": "API Keys", children: [_jsx(AiProviderHeader, { name: "Xpod", mark: "XP", avatar: XPOD_AVATAR, infoLabel: "Xpod \u8BF4\u660E", infoLines: [XPOD_DESCRIPTION, XPOD_CREDENTIAL_NOTE], link: { href: client.apiBase, label: '访问 Xpod' }, badge: (_jsx(Badge, { variant: keys.length > 0 ? 'default' : 'secondary', children: keys.length > 0 ? `已签发 ${keys.length} 个` : '未配置' })) }), _jsxs("section", { className: "space-y-3", "aria-label": "\u5F53\u524D\u8FDE\u63A5", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [_jsxs("h3", { className: "flex items-center gap-2 text-sm font-medium text-foreground/90", children: [_jsx(Settings2, { "aria-hidden": "true", className: "h-4 w-4 text-primary" }), "\u5F53\u524D\u8FDE\u63A5"] }), _jsx("div", { className: "flex flex-wrap items-center justify-end gap-2", children: _jsxs(Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", "aria-label": "\u65B0\u5EFA API Key", disabled: creating || loading, onClick: openCreate, children: [_jsx(Plus, { "aria-hidden": "true", className: "h-3.5 w-3.5" }), "API Key"] }) })] }), loading ? (_jsxs("div", { className: "flex items-center gap-2 py-6 text-sm text-muted-foreground", children: [_jsx(Loader2, { "aria-hidden": "true", className: "h-4 w-4 animate-spin" }), "\u6B63\u5728\u8BFB\u53D6 API Key"] })) : keys.length === 0 ? (_jsx("p", { className: "py-2 text-xs text-muted-foreground", children: "\u5C1A\u672A\u7B7E\u53D1 API Key" })) : (_jsx("ul", { "aria-label": "API Key \u5217\u8868", className: "rounded-xl border border-border/70", children: keys.map((record) => (_jsx(AiGatewayKeyRow, { record: record, busy: Boolean(busyKeyId), onDestroy: () => void destroy(record) }, record.id))) })), _jsxs("details", { className: "text-xs text-muted-foreground", children: [_jsx("summary", { className: "w-fit cursor-pointer", children: "\u63A5\u5165\u4FE1\u606F" }), _jsx("div", { className: "mt-2 space-y-3", children: _jsxs("section", { className: "space-y-2", "aria-labelledby": "xpod-access-info", children: [_jsx("h4", { id: "xpod-access-info", className: "text-sm font-medium text-foreground", children: "Xpod \u63A5\u5165\u4FE1\u606F" }), _jsx("p", { className: "text-xs text-muted-foreground", children: "API Key \u662F\u7B7E\u53D1\u7ED9\u5BA2\u6237\u7AEF\u5E94\u7528\u7684 CSS \u5BA2\u6237\u7AEF\u51ED\u636E\uFF1BPod \u53EA\u8BB0\u5F55\u5B83\u7ED1\u5B9A\u5230\u54EA\u4E2A\u5BA2\u6237\u7AEF\uFF0C\u4E0D\u4FDD\u5B58 Key \u660E\u6587\u3002" }), _jsx("p", { className: "text-xs text-muted-foreground", children: "\u540C\u4E00\u4E2A API Key \u652F\u6301\u4EE5\u4E0B\u517C\u5BB9\u534F\u8BAE\uFF0C\u6309\u5BA2\u6237\u7AEF\u9009\u62E9\u5E76\u590D\u5236\u5BF9\u5E94\u5730\u5740\uFF1A" }), _jsx(AiEndpointList, { endpoints: xpodProtocolEndpoints(client.apiBase), copy: true, display: "protocol" })] }) })] })] }), _jsx(AiGatewayModelsSection, { models: gatewayModels, selection: modelSelection }), _jsx(Dialog, { open: showCreate, onOpenChange: (open) => { if (!open && (creating || applying))
228
+ return; setShowCreate(open); }, children: _jsxs(DialogContent, { className: "sm:max-w-md", "aria-describedby": undefined, children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: issued ? 'API Key 已签发' : '新建 API Key' }) }), issued && issuedClient ? (_jsxs("div", { className: "space-y-5", children: [_jsxs("div", { className: "space-y-1.5", children: [_jsxs("p", { className: "text-sm", children: ["\u5DF2\u7B7E\u53D1\u300C", issued.name || '未命名 API Key', "\u300D\uFF0C\u7528\u9014\uFF1A", AI_CLIENT_LABELS[issuedClient], "\u3002"] }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Xpod \u4E0D\u4FDD\u5B58 Key \u660E\u6587\uFF0C\u8BF7\u7ACB\u5373\u590D\u5236\u6216\u76F4\u63A5\u5E94\u7528\u5230\u5BA2\u6237\u7AEF\uFF1B\u79BB\u5F00\u672C\u6B21\u4F1A\u8BDD\u540E\u65E0\u6CD5\u518D\u6B21\u83B7\u53D6\u3002" })] }), issued.maskedHint ? (_jsx("code", { className: "block truncate rounded-md border border-border/60 bg-muted/30 px-3 py-2 font-mono text-xs text-muted-foreground", children: issued.maskedHint })) : null, !clientConfigurationBridge ? (_jsx("p", { className: "text-xs text-muted-foreground", children: "\u5F53\u524D Web \u73AF\u5883\u65E0\u6CD5\u81EA\u52A8\u5199\u5165\u5BA2\u6237\u7AEF\u914D\u7F6E\uFF0C\u8BF7\u590D\u5236\u540E\u624B\u52A8\u7C98\u8D34\uFF1B\u81EA\u52A8\u5E94\u7528\u9700\u8981\u672C\u673A\u8FDE\u63A5\u3002" })) : null, error ? _jsx("p", { role: "alert", className: "text-sm text-destructive", children: error }) : null, _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(AiCopyButton, { value: () => sessionPlaintext(issued, UNPERSISTED_COPY_MESSAGE), label: "API Key", text: "\u590D\u5236 API Key", disabled: applying, iconClassName: "mr-1.5 h-3.5 w-3.5", copiedIconClassName: "mr-1.5 h-3.5 w-3.5 text-emerald-600", onError: (cause) => setError(errorMessage(cause)) }), _jsx(AiCopyButton, { value: () => manualConfigurationText(issuedClient, client.apiBase, sessionPlaintext(issued, UNPERSISTED_COPY_MESSAGE)), label: `${AI_CLIENT_LABELS[issuedClient]} 配置`, text: `复制 ${AI_CLIENT_LABELS[issuedClient]} 配置`, disabled: applying, iconClassName: "mr-1.5 h-3.5 w-3.5", copiedIconClassName: "mr-1.5 h-3.5 w-3.5 text-emerald-600", onError: (cause) => setError(errorMessage(cause)) }), clientConfigurationBridge ? (appliedClient ? (_jsxs("span", { role: "status", className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(Check, { "aria-hidden": "true", className: "h-3.5 w-3.5" }), "\u5DF2\u5E94\u7528\u5230 ", AI_CLIENT_LABELS[appliedClient]] })) : (_jsxs(Button, { type: "button", size: "sm", disabled: applying, "aria-label": `应用到 ${AI_CLIENT_LABELS[issuedClient]}`, onClick: () => void apply(), children: [applying ? _jsx(Loader2, { "aria-hidden": "true", className: "mr-2 h-4 w-4 animate-spin" }) : null, applying ? '正在应用…' : `应用到 ${AI_CLIENT_LABELS[issuedClient]}`] }))) : null] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", disabled: applying, onClick: beginAnother, children: "\u518D\u5EFA\u4E00\u4E2A" }), _jsx(Button, { type: "button", variant: "outline", onClick: () => setShowCreate(false), children: "\u5B8C\u6210" })] })] })) : (_jsxs("form", { className: "space-y-5", onSubmit: (event) => { event.preventDefault(); if (!creating)
229
+ void create(); }, children: [_jsxs("label", { className: "block space-y-2", children: [_jsx("span", { className: "text-sm font-medium", children: "\u540D\u79F0" }), _jsx(Input, { autoFocus: true, "aria-label": "API Key \u540D\u79F0", value: name, disabled: creating, onChange: (event) => setName(event.target.value) })] }), _jsxs("label", { className: "block space-y-2", children: [_jsx("span", { className: "text-sm font-medium", children: "\u7528\u9014" }), _jsxs("select", { "aria-label": "API Key \u7528\u9014", className: SELECT_CLASS, value: purpose, disabled: creating, onChange: (event) => setPurpose(event.target.value), children: [_jsx("option", { value: "", disabled: true, children: "\u9009\u62E9\u5BA2\u6237\u7AEF\u5E94\u7528" }), AI_CONNECTIONS_CLIENTS.map((clientId) => (_jsx("option", { value: clientId, children: AI_CLIENT_LABELS[clientId] }, clientId)))] })] }), _jsx("p", { className: "text-xs text-muted-foreground", children: "\u7528\u9014\u5728\u521B\u5EFA\u65F6\u786E\u5B9A\uFF0CKey \u4F1A\u7ED1\u5B9A\u5230\u8BE5\u5BA2\u6237\u7AEF\u5E94\u7528\u3002" }), error ? _jsx("p", { role: "alert", className: "text-sm text-destructive", children: error }) : null, _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", disabled: creating, onClick: () => setShowCreate(false), children: "\u53D6\u6D88" }), _jsxs(Button, { type: "submit", "aria-label": "\u521B\u5EFA API Key", disabled: creating || !name.trim() || !purpose, children: [creating ? _jsx(Loader2, { "aria-hidden": "true", className: "mr-2 h-4 w-4 animate-spin" }) : null, creating ? '正在创建…' : '创建 API Key'] })] })] }))] }) })] }) }));
233
230
  }
234
231
  function errorMessage(error) {
235
232
  const message = error instanceof Error ? error.message.trim() : '';
@@ -0,0 +1,21 @@
1
+ import type { AiGatewayModel } from './ai-connections-client';
2
+ /**
3
+ * What the gateway list shares with the provider pages.
4
+ *
5
+ * A published model is a joined one, so switching here writes the same
6
+ * selection the provider pages write rather than a second flag to keep in sync.
7
+ */
8
+ export interface GatewayModelSelection {
9
+ isSelected(model: AiGatewayModel): boolean;
10
+ toggle(model: AiGatewayModel): void;
11
+ disabled?: boolean;
12
+ }
13
+ /**
14
+ * The catalog the Gateway publishes to clients (`/v1/models`), switched with the
15
+ * same row the provider pages use: 停用 withdraws a model from the models list
16
+ * endpoint, 启用 publishes it again.
17
+ */
18
+ export declare function AiGatewayModelsSection({ models, selection }: {
19
+ models?: AiGatewayModel[];
20
+ selection?: GatewayModelSelection;
21
+ }): import("react").JSX.Element;
@@ -0,0 +1,51 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useMemo, useState } from 'react';
3
+ import { Badge } from '@undefineds.co/shared-ui';
4
+ import { Box } from 'lucide-react';
5
+ import { AiModelEmptyPanel, AiModelSearchInput, AiModelRow, modelIconTokens, withCatalogModelId, } from './AiModelCatalog.js';
6
+ /**
7
+ * The catalog the Gateway publishes to clients (`/v1/models`), switched with the
8
+ * same row the provider pages use: 停用 withdraws a model from the models list
9
+ * endpoint, 启用 publishes it again.
10
+ */
11
+ export function AiGatewayModelsSection({ models, selection }) {
12
+ const [search, setSearch] = useState('');
13
+ const catalog = useMemo(() => aggregateGatewayModels(models ?? []), [models]);
14
+ const query = search.trim().toLocaleLowerCase();
15
+ const visibleModels = query
16
+ ? catalog.filter((model) => model.searchText.includes(query))
17
+ : catalog;
18
+ const unavailableCount = catalog.filter((model) => model.availability === 'unavailable').length;
19
+ const publishedCount = selection
20
+ ? catalog.filter((model) => selection.isSelected(model)).length
21
+ : catalog.length;
22
+ return (_jsxs("section", { className: "space-y-8", "aria-label": "\u53EF\u7528\u6A21\u578B", children: [_jsxs("div", { "data-testid": "gateway-models-header", className: "flex flex-wrap items-center justify-between gap-2", children: [_jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [_jsxs("h3", { className: "flex items-center gap-2 text-sm font-medium text-foreground/90", children: [_jsx(Box, { "aria-hidden": "true", className: "h-4 w-4 text-primary" }), "\u53EF\u7528\u6A21\u578B"] }), _jsx("span", { className: "text-xs text-muted-foreground", children: selection
23
+ ? `共 ${catalog.length} · 已发布 ${publishedCount} · 已失效 ${unavailableCount}`
24
+ : `共 ${catalog.length} · 已失效 ${unavailableCount}` }), _jsx("span", { className: "text-xs text-muted-foreground", children: "Xpod \u5F53\u524D\u53D1\u5E03\u7684\u6A21\u578B" })] }), _jsx(AiModelSearchInput, { value: search, onChange: setSearch })] }), models === undefined ? (_jsx(AiModelEmptyPanel, { children: "Xpod \u6A21\u578B\u76EE\u5F55\u5C1A\u672A\u5C31\u7EEA" })) : catalog.length === 0 ? (_jsx(AiModelEmptyPanel, { children: "\u6682\u65E0\u53EF\u7528\u6A21\u578B" })) : visibleModels.length === 0 ? (_jsx(AiModelEmptyPanel, { children: "\u672A\u627E\u5230\u5339\u914D\u7684\u6A21\u578B" })) : (_jsx("div", { className: "grid gap-2", children: visibleModels.map((model) => (_jsx(AiModelRow, { label: model.displayName ?? model.id, modelId: model.id, iconTokens: model.iconTokens, enabled: selection?.isSelected(model) ?? false, toggleDisabled: selection?.disabled, onToggle: selection ? () => selection.toggle(model) : undefined, unavailable: model.availability === 'unavailable', badges: (_jsxs(_Fragment, { children: [model.custom ? _jsx(Badge, { variant: "outline", className: "shrink-0 text-[10px] font-normal", children: "\u624B\u5DE5" }) : null, model.availability === 'unavailable' ? (_jsx(Badge, { variant: "destructive", className: "shrink-0 text-[10px] font-normal", children: "\u5DF2\u5931\u6548" })) : null] })) }, model.key))) }))] }));
25
+ }
26
+ /**
27
+ * One gateway model can be published once per credential/offering, so the
28
+ * read surface folds those entries the same way the provider page does.
29
+ */
30
+ function aggregateGatewayModels(models) {
31
+ const catalog = new Map();
32
+ for (const entry of models) {
33
+ const model = withCatalogModelId(entry);
34
+ const key = `${model.provider}\0${model.id}`;
35
+ const iconTokens = modelIconTokens(model);
36
+ const searchText = [model.id, model.displayName].filter(Boolean).join('\n').toLocaleLowerCase();
37
+ const existing = catalog.get(key);
38
+ if (!existing) {
39
+ catalog.set(key, { ...model, key, iconTokens, searchText });
40
+ continue;
41
+ }
42
+ if (model.availability !== 'unavailable')
43
+ existing.availability = model.availability;
44
+ if (existing.displayName === undefined && model.displayName !== undefined) {
45
+ existing.displayName = model.displayName;
46
+ }
47
+ existing.iconTokens = [...new Set([...existing.iconTokens, ...iconTokens])];
48
+ existing.searchText += `\n${searchText}`;
49
+ }
50
+ return [...catalog.values()];
51
+ }
@@ -0,0 +1,15 @@
1
+ import type { ReactNode } from 'react';
2
+ /**
3
+ * The ⓘ affordance that explains a provider-style page.
4
+ *
5
+ * It owns its `TooltipProvider` on purpose. Radix keeps one "pointer in transit"
6
+ * flag per provider, and every trigger inside that provider ignores pointer
7
+ * moves while the flag is set. Sharing a provider with the model list below the
8
+ * header meant that leaving a capability glyph silently swallowed the next hover
9
+ * of the ⓘ, so it never opened on the pages whose catalog carries capability
10
+ * metadata. An island per ⓘ keeps that state out of everyone else's way.
11
+ */
12
+ export declare function AiInfoTooltip({ label, lines }: {
13
+ label: string;
14
+ lines: ReactNode[];
15
+ }): import("react").JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from '@undefineds.co/shared-ui';
3
+ import { Info } from 'lucide-react';
4
+ /**
5
+ * The ⓘ affordance that explains a provider-style page.
6
+ *
7
+ * It owns its `TooltipProvider` on purpose. Radix keeps one "pointer in transit"
8
+ * flag per provider, and every trigger inside that provider ignores pointer
9
+ * moves while the flag is set. Sharing a provider with the model list below the
10
+ * header meant that leaving a capability glyph silently swallowed the next hover
11
+ * of the ⓘ, so it never opened on the pages whose catalog carries capability
12
+ * metadata. An island per ⓘ keeps that state out of everyone else's way.
13
+ */
14
+ export function AiInfoTooltip({ label, lines }) {
15
+ return (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": label, className: "cursor-help rounded-sm text-muted-foreground/50 focus:outline-none focus-visible:text-foreground", children: _jsx(Info, { "aria-hidden": "true", className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { className: "max-w-xs space-y-2 text-xs", children: lines.map((line, index) => _jsx("p", { children: line }, index)) })] }) }));
16
+ }
@@ -0,0 +1,175 @@
1
+ import { type ReactNode } from 'react';
2
+ /**
3
+ * Presentation of a model catalog, shared by the provider pages and the Xpod
4
+ * keys page: both list models, so the search box, the inline placeholder and the
5
+ * model rows must stay one implementation.
6
+ */
7
+ /**
8
+ * Every capability a model row can show, and the glyph that carries it.
9
+ *
10
+ * This is the single definition of the vocabulary: a row renders a glyph for
11
+ * every token it is given, so a token without an entry here would leave a hole.
12
+ * `modelIconTokens` therefore filters through it. The two lists used to be
13
+ * maintained separately, which is how `embedding` and the non-image input
14
+ * modalities (`pdf`, `audio`, `video`) reached the row with nothing to draw.
15
+ */
16
+ export declare const MODEL_CAPABILITY_PRESENTATION: {
17
+ readonly image: {
18
+ readonly icon: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
19
+ readonly label: "视觉识别";
20
+ readonly className: "text-green-500";
21
+ };
22
+ readonly pdf: {
23
+ readonly icon: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
24
+ readonly label: "文档输入";
25
+ readonly className: "text-teal-500";
26
+ };
27
+ readonly audio: {
28
+ readonly icon: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
29
+ readonly label: "音频输入";
30
+ readonly className: "text-cyan-500";
31
+ };
32
+ readonly video: {
33
+ readonly icon: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
34
+ readonly label: "视频输入";
35
+ readonly className: "text-indigo-500";
36
+ };
37
+ readonly web: {
38
+ readonly icon: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
39
+ readonly label: "联网搜索";
40
+ readonly className: "text-blue-500";
41
+ };
42
+ readonly tool_call: {
43
+ readonly icon: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
44
+ readonly label: "函数调用";
45
+ readonly className: "text-orange-500";
46
+ };
47
+ readonly reasoning: {
48
+ readonly icon: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
49
+ readonly label: "推理";
50
+ readonly className: "text-purple-500";
51
+ };
52
+ readonly embedding: {
53
+ readonly icon: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
54
+ readonly label: "向量模型";
55
+ readonly className: "text-sky-500";
56
+ };
57
+ readonly fast: {
58
+ readonly icon: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
59
+ readonly label: "快速模型";
60
+ readonly className: "text-amber-500";
61
+ };
62
+ };
63
+ export type ModelCapabilityToken = keyof typeof MODEL_CAPABILITY_PRESENTATION;
64
+ export declare function isPresentedCapability(token: string): token is ModelCapabilityToken;
65
+ /**
66
+ * Capability glyph shown beside a model name.
67
+ *
68
+ * Each glyph owns its `TooltipProvider` on purpose. Radix keeps one "pointer in
69
+ * transit" flag per provider and every trigger inside it ignores pointer moves
70
+ * while that flag is set, so a glyph whose tooltip is mid-transit would silently
71
+ * swallow the next hover of any other tooltip in the same provider - including
72
+ * the ⓘ next to the provider name. Isolating the glyphs keeps that state local.
73
+ */
74
+ export declare function CapabilityIcon({ type }: {
75
+ type: string;
76
+ }): import("react").JSX.Element | null;
77
+ /**
78
+ * Capability tokens for one model row.
79
+ *
80
+ * Both surfaces that list models fold the same two sources, and both used to
81
+ * build the list inline. Duplicates are folded too: a model whose catalog entry
82
+ * declares an `image` input modality *and* `imageInput: true` describes one
83
+ * capability, but the two sources would render it twice under one React key.
84
+ *
85
+ * Tokens outside the vocabulary are dropped here rather than handed to a glyph
86
+ * that would render nothing, so a row never carries a mark it cannot show.
87
+ */
88
+ export declare function modelIconTokens(model: {
89
+ inputModalities?: readonly string[];
90
+ capabilities?: readonly string[];
91
+ }): ModelCapabilityToken[];
92
+ /**
93
+ * The id a model is listed under, however the Pod stored it.
94
+ *
95
+ * A Pod persists a picked model as the resource it selected, so an entry can
96
+ * arrive with that resource reference where the model id belongs - typically a
97
+ * pinned selection whose document moved to another offering
98
+ * (`…/settings/providers/openai-official-subscription.ttl#gpt-6-astra`). The
99
+ * fragment names the model and the document only says where it is stored, so a
100
+ * reference folds down to the id it names instead of listing that model twice,
101
+ * once as `GPT-6-Astra` and once as a URL-shaped row.
102
+ *
103
+ * `@undefineds.co/models` owns this rule for Pod reads (`normalizeAIConfigModelId`
104
+ * in its `ai-config` module); the catalog repeats just the identity both lists
105
+ * fold on, because this package carries no Pod schema.
106
+ */
107
+ export declare function modelCatalogId(model: {
108
+ id: string;
109
+ }): string;
110
+ /** Fold one entry onto the model id both surfaces list it under. */
111
+ export declare function withCatalogModelId<T extends {
112
+ id: string;
113
+ }>(model: T): T;
114
+ /**
115
+ * Turns one model in a list on or off.
116
+ *
117
+ * A checkbox reads as "pick some of these" and says nothing about what picking
118
+ * does. This is a state with a consequence - the model joins the account's
119
+ * models, or it is withdrawn from the models list endpoint - so it uses the same
120
+ * affordance the credential rows already use for 启用/停用, and names the action.
121
+ */
122
+ export declare function AiModelEnableToggle({ enabled, disabled, label, onToggle, }: {
123
+ enabled: boolean;
124
+ disabled?: boolean;
125
+ /** The model name; the action verb is added around it. */
126
+ label: string;
127
+ onToggle(): void;
128
+ }): import("react").JSX.Element;
129
+ /** Magnifier-prefixed model search, sat on the right of a model list header. */
130
+ export declare function AiModelSearchInput({ value, onChange }: {
131
+ value: string;
132
+ onChange: (value: string) => void;
133
+ }): import("react").JSX.Element;
134
+ /** Inline placeholder used when a model list has nothing to show. */
135
+ export declare function AiModelEmptyPanel({ tone, children }: {
136
+ tone?: 'destructive';
137
+ children: ReactNode;
138
+ }): import("react").JSX.Element;
139
+ /**
140
+ * One model row, as every list of models renders it.
141
+ *
142
+ * This is the component both surfaces use. They used to assemble `AiModelTile`
143
+ * themselves - each with its own leading control, its own badges and its own
144
+ * spacing - which is exactly how one list drifted away from the other. A caller
145
+ * supplies the model, the switch state and any per-row extras; the row itself
146
+ * is decided here.
147
+ */
148
+ export declare function AiModelRow({ label, modelId, iconTokens, enabled, toggleDisabled, onToggle, onEdit, onDelete, unavailable, badges, }: {
149
+ label: string;
150
+ modelId?: string;
151
+ iconTokens?: string[];
152
+ /** The model is on: it is joined to the account and published to clients. */
153
+ enabled: boolean;
154
+ toggleDisabled?: boolean;
155
+ /** Omit for a list that cannot be switched. */
156
+ onToggle?: () => void;
157
+ onEdit?: () => void;
158
+ onDelete?: () => void;
159
+ unavailable?: boolean;
160
+ badges?: ReactNode;
161
+ }): import("react").JSX.Element;
162
+ /**
163
+ * One model row. `leading` carries the provider page's selection checkbox and
164
+ * `actions` its edit/delete buttons; a read-only list passes neither.
165
+ */
166
+ export declare function AiModelTile({ label, modelId, iconTokens, badges, leading, actions, selected, unavailable, }: {
167
+ label: string;
168
+ modelId?: string;
169
+ iconTokens?: string[];
170
+ badges?: ReactNode;
171
+ leading?: ReactNode;
172
+ actions?: ReactNode;
173
+ selected?: boolean;
174
+ unavailable?: boolean;
175
+ }): import("react").JSX.Element;