@undefineds.co/xpod 0.4.3 → 0.4.5

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 (223) hide show
  1. package/config/cloud.json +1 -1
  2. package/config/main.json +36 -2
  3. package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.d.ts +3 -0
  4. package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.js +1 -1
  5. package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.d.ts +2 -1
  6. package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.js +101 -32
  7. package/dist/api/ai-gateway/connect/DeviceCodeProtocol.d.ts +80 -0
  8. package/dist/api/ai-gateway/connect/DeviceCodeProtocol.js +3 -0
  9. package/dist/api/ai-gateway/connect/FileSessionImportAdapter.d.ts +38 -0
  10. package/dist/api/ai-gateway/connect/FileSessionImportAdapter.js +63 -0
  11. package/dist/api/ai-gateway/connect/LoopbackAuthorizationCallbackReceiver.d.ts +24 -0
  12. package/dist/api/ai-gateway/connect/LoopbackAuthorizationCallbackReceiver.js +136 -0
  13. package/dist/api/ai-gateway/connect/OAuthConnectAdapter.d.ts +2 -0
  14. package/dist/api/ai-gateway/connect/OAuthConnectAdapter.js +2 -1
  15. package/dist/api/ai-gateway/connect/OAuthIntegrationRegistry.d.ts +17 -13
  16. package/dist/api/ai-gateway/connect/OAuthIntegrationRegistry.js +52 -19
  17. package/dist/api/ai-gateway/connect/OpenAiSubscriptionSessionImportAdapter.d.ts +4 -28
  18. package/dist/api/ai-gateway/connect/OpenAiSubscriptionSessionImportAdapter.js +7 -58
  19. package/dist/api/ai-gateway/connect/ProviderAuthorizationProfiles.d.ts +4 -0
  20. package/dist/api/ai-gateway/connect/ProviderAuthorizationProfiles.js +116 -0
  21. package/dist/api/ai-gateway/connect/SessionImportProfiles.d.ts +10 -0
  22. package/dist/api/ai-gateway/connect/SessionImportProfiles.js +112 -0
  23. package/dist/api/ai-gateway/connect/index.d.ts +125 -23
  24. package/dist/api/ai-gateway/connect/index.js +1277 -260
  25. package/dist/api/ai-gateway/models/PodModelSelectionRepository.d.ts +4 -1
  26. package/dist/api/ai-gateway/models/PodModelSelectionRepository.js +154 -19
  27. package/dist/api/ai-gateway/providers/DeepSeekRuntimeAdapter.js +10 -6
  28. package/dist/api/ai-gateway/providers/ModelsDevCatalog.d.ts +7 -0
  29. package/dist/api/ai-gateway/providers/ModelsDevCatalog.js +25 -1
  30. package/dist/api/ai-gateway/providers/OfferingAuthorization.d.ts +24 -0
  31. package/dist/api/ai-gateway/providers/OfferingAuthorization.js +37 -0
  32. package/dist/api/ai-gateway/providers/OpenAiRuntimeAdapter.d.ts +1 -1
  33. package/dist/api/ai-gateway/providers/OpenAiRuntimeAdapter.js +5 -3
  34. package/dist/api/ai-gateway/providers/ProviderRegistry.d.ts +6 -3
  35. package/dist/api/ai-gateway/providers/ProviderRegistry.js +55 -16
  36. package/dist/api/ai-gateway/providers/ProviderRuntimeAdapter.d.ts +2 -0
  37. package/dist/api/ai-gateway/providers/ProviderRuntimeAdapter.js +37 -4
  38. package/dist/api/ai-gateway/providers/ProviderRuntimeRegistry.js +7 -0
  39. package/dist/api/ai-gateway/quota/SubscriptionQuotaAdapters.js +2 -1
  40. package/dist/api/ai-gateway/routing/ModelRouter.js +3 -1
  41. package/dist/api/container/common.js +30 -40
  42. package/dist/api/container/index.js +6 -2
  43. package/dist/api/container/routes.js +5 -22
  44. package/dist/api/handlers/AiClientConfigurationHandler.js +39 -1
  45. package/dist/api/handlers/AiGatewayManagementHandler.d.ts +3 -0
  46. package/dist/api/handlers/AiGatewayManagementHandler.js +173 -58
  47. package/dist/api/service/AiClientConfigurationService.d.ts +4 -15
  48. package/dist/api/service/AiClientConfigurationService.js +17 -64
  49. package/dist/cli/commands/start.js +2 -0
  50. package/dist/components/components.jsonld +1 -0
  51. package/dist/components/context.jsonld +80 -0
  52. package/dist/http/InternalPodDataHttpHandler.d.ts +3 -0
  53. package/dist/http/InternalPodDataHttpHandler.js +13 -2
  54. package/dist/http/InternalPodDataHttpHandler.jsonld +12 -0
  55. package/dist/identity/oidc/RememberedClientPromptFactory.d.ts +1 -1
  56. package/dist/identity/oidc/RememberedClientPromptFactory.js +5 -2
  57. package/dist/identity/oidc/RememberedConsentHandler.js +1 -1
  58. package/dist/identity/oidc/ScopedPickWebIdHandler.d.ts +1 -0
  59. package/dist/identity/oidc/ScopedPickWebIdHandler.js +26 -0
  60. package/dist/identity/oidc/ScopedPickWebIdHandler.jsonld +4 -0
  61. package/dist/identity/oidc/SessionBoundIdentityProviderFactory.d.ts +10 -0
  62. package/dist/identity/oidc/SessionBoundIdentityProviderFactory.js +21 -0
  63. package/dist/identity/oidc/SessionBoundIdentityProviderFactory.jsonld +172 -0
  64. package/dist/index.d.ts +2 -1
  65. package/dist/index.js +4 -2
  66. package/dist/runtime/component-parameter-keys.js +18 -2
  67. package/dist/storage/accessors/MixDataAccessor.js +6 -2
  68. package/dist/storage/rdf/PostgresRdfEngine.js +10 -2
  69. package/dist/storage/rdf/RdfContentTypes.js +4 -0
  70. package/node_modules/@undefineds.co/ai-connections/dist/AiClientConfigurationSection.d.ts +3 -0
  71. package/node_modules/@undefineds.co/ai-connections/dist/AiClientConfigurationSection.js +13 -16
  72. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsList.js +1 -3
  73. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsMain.d.ts +2 -1
  74. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsMain.js +2 -2
  75. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.d.ts +4 -1
  76. package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.js +127 -57
  77. package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialPoolSection.d.ts +6 -4
  78. package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialPoolSection.js +436 -83
  79. package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeysSection.d.ts +3 -2
  80. package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeysSection.js +212 -76
  81. package/node_modules/@undefineds.co/ai-connections/dist/AiProviderCard.d.ts +6 -4
  82. package/node_modules/@undefineds.co/ai-connections/dist/AiProviderCard.js +58 -41
  83. package/node_modules/@undefineds.co/ai-connections/dist/AiQuotaCard.d.ts +4 -1
  84. package/node_modules/@undefineds.co/ai-connections/dist/AiQuotaCard.js +63 -4
  85. package/node_modules/@undefineds.co/ai-connections/dist/ai-connections-client.d.ts +46 -6
  86. package/node_modules/@undefineds.co/ai-connections/dist/ai-connections-client.js +143 -14
  87. package/node_modules/@undefineds.co/ai-connections/dist/client-config/base-adapter.d.ts +19 -3
  88. package/node_modules/@undefineds.co/ai-connections/dist/client-config/base-adapter.js +45 -7
  89. package/node_modules/@undefineds.co/ai-connections/dist/client-config/codex.d.ts +7 -1
  90. package/node_modules/@undefineds.co/ai-connections/dist/client-config/codex.js +305 -40
  91. package/node_modules/@undefineds.co/ai-connections/dist/client-config/index.cjs +383 -50
  92. package/node_modules/@undefineds.co/ai-connections/dist/client-config/json-env-adapter.js +3 -2
  93. package/node_modules/@undefineds.co/ai-connections/dist/client-config/pi.js +12 -3
  94. package/node_modules/@undefineds.co/ai-connections/dist/client-config/transaction.d.ts +2 -0
  95. package/node_modules/@undefineds.co/ai-connections/dist/client-config/transaction.js +39 -4
  96. package/node_modules/@undefineds.co/ai-connections/dist/client-config/types.d.ts +8 -1
  97. package/node_modules/@undefineds.co/ai-connections/dist/client-visuals.d.ts +2 -0
  98. package/node_modules/@undefineds.co/ai-connections/dist/client-visuals.js +14 -0
  99. package/node_modules/@undefineds.co/ai-connections/dist/controller.d.ts +2 -2
  100. package/node_modules/@undefineds.co/ai-connections/dist/controller.js +216 -57
  101. package/node_modules/@undefineds.co/ai-connections/dist/index.d.ts +3 -1
  102. package/node_modules/@undefineds.co/ai-connections/dist/index.js +16 -2
  103. package/node_modules/@undefineds.co/ai-connections/dist/provider-visuals.js +6 -1
  104. package/node_modules/@undefineds.co/drizzle-solid/dist/core/execution/ldp-executor.js +27 -6
  105. package/node_modules/@undefineds.co/drizzle-solid/dist/core/pod-database.js +1 -1
  106. package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/select-query-builder.js +2 -2
  107. package/node_modules/@undefineds.co/drizzle-solid/dist/core/sparql/builder/update-builder.js +12 -1
  108. package/node_modules/@undefineds.co/drizzle-solid/dist/core/triple/builder.js +1 -1
  109. package/node_modules/@undefineds.co/drizzle-solid/dist/core/triple/handlers/array.js +8 -0
  110. package/node_modules/@undefineds.co/drizzle-solid/dist/core/triple/handlers/default.js +9 -1
  111. package/node_modules/@undefineds.co/drizzle-solid/dist/core/triple/handlers/inline.js +3 -3
  112. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/execution/ldp-executor.js +27 -6
  113. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/pod-database.js +1 -1
  114. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/select-query-builder.js +2 -2
  115. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/sparql/builder/update-builder.js +12 -1
  116. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/triple/builder.js +1 -1
  117. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/triple/handlers/array.js +8 -0
  118. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/triple/handlers/default.js +9 -1
  119. package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/triple/handlers/inline.js +3 -3
  120. package/node_modules/@undefineds.co/extension-sdk/dist/web.d.ts +31 -0
  121. package/package.json +2 -2
  122. package/static/app/assets/{index-BikOyGPu.js → index-BCZVzMpj.js} +44 -44
  123. package/static/app/assets/inrupt-smoke.js +2 -2
  124. package/static/app/assets/main.css +1 -1
  125. package/static/app/assets/main.js +10 -10
  126. package/static/auth-callback/assets/{AiConfigContext-DrCH6ckh.js → AiConfigContext-DVkh8Kg2.js} +1 -1
  127. package/static/auth-callback/assets/{AiConfigPage-DVrlSSdA.js → AiConfigPage-HWVWpe-P.js} +1 -1
  128. package/static/auth-callback/assets/{DocumentProcessingPanel-_Md-v2R2.js → DocumentProcessingPanel-DDq-mH17.js} +1 -1
  129. package/static/auth-callback/assets/{IndexLifecyclePanel-BbWwe23H.js → IndexLifecyclePanel-Cx4cjrdP.js} +1 -1
  130. package/static/auth-callback/assets/{IndexSubjectPanel-upH9MjU-.js → IndexSubjectPanel-DzSw8M9j.js} +1 -1
  131. package/static/auth-callback/assets/{ModelAssignmentsPanel-CVGH4t4g.js → ModelAssignmentsPanel-BsRxGc2p.js} +1 -1
  132. package/static/auth-callback/assets/ModelsPage-DEe1lo6Q.js +10 -0
  133. package/static/auth-callback/assets/{NetworkPage-Dcbrb1fd.js → NetworkPage-DBiEh1Oz.js} +1 -1
  134. package/static/auth-callback/assets/{PaneListHeader-DrY-1wBq.js → PaneListHeader-lEEgjyN9.js} +1 -1
  135. package/static/auth-callback/assets/{SearchIndexingPanel-Dw25y53v.js → SearchIndexingPanel-CZCUUGt6.js} +1 -1
  136. package/static/auth-callback/assets/{StatusSubjectPanel-BHlz9rNF.js → StatusSubjectPanel-21qdueMr.js} +1 -1
  137. package/static/auth-callback/assets/{StatusWorkspace-BH7exQP5.js → StatusWorkspace-R8RKsqVz.js} +1 -1
  138. package/static/auth-callback/assets/{SystemSettingsPage-BYLKnM9f.js → SystemSettingsPage-BQ4e-4Wy.js} +1 -1
  139. package/static/auth-callback/assets/{SystemSettingsSubjectPanel-DT34LKku.js → SystemSettingsSubjectPanel-BopXD7SE.js} +1 -1
  140. package/static/auth-callback/assets/{activity-DdULRcSI.js → activity-DSfmTGfY.js} +1 -1
  141. package/static/auth-callback/assets/ai-connections-C03UWyPh.js +1 -0
  142. package/static/auth-callback/assets/{auth-callback-D7l2P25I.js → auth-callback-DleaitAS.js} +91 -91
  143. package/static/auth-callback/assets/auth-callback-vPSC2d2F.css +1 -0
  144. package/static/auth-callback/assets/{badge-j4zjFnmg.js → badge-B0aLu1sl.js} +1 -1
  145. package/static/auth-callback/assets/{download-DGXoks01.js → download-D_bFwdYJ.js} +1 -1
  146. package/static/auth-callback/assets/{external-link-CvbgXXaI.js → external-link-DRfjTaQu.js} +1 -1
  147. package/static/auth-callback/assets/{index-LRWvKJ2i.js → index-CG23cLYQ.js} +1 -1
  148. package/static/auth-callback/assets/{index-BOK3j1dz.js → index-CyV9ejwx.js} +1 -1
  149. package/static/auth-callback/assets/{index-browser-C1Qpe0g4.js → index-browser-D70paxIg.js} +1 -1
  150. package/static/auth-callback/assets/{key-round-CmgS5UdQ.js → key-round-BjV_mVYH.js} +1 -1
  151. package/static/auth-callback/assets/{rotate-ccw-c4CSG6Rq.js → rotate-ccw-CKoOAfse.js} +1 -1
  152. package/static/auth-callback/assets/{skeleton-ZPMTiRSM.js → skeleton-BZNjZaHx.js} +1 -1
  153. package/static/auth-callback/assets/{waypoints-xjyBflU5.js → waypoints-DoaJVzZv.js} +1 -1
  154. package/static/auth-callback/assets/{workspace-layout-B9nj6F5J.js → workspace-layout-CaP46_ZR.js} +1 -1
  155. package/static/auth-callback/auth-callback.html +2 -2
  156. package/static/dashboard/assets/{AiConfigContext-BWOOSYNr.js → AiConfigContext-BSrR27yD.js} +1 -1
  157. package/static/dashboard/assets/{AiConfigPage-CG2kQ9Wy.js → AiConfigPage-D65Z2LET.js} +1 -1
  158. package/static/dashboard/assets/{DocumentProcessingPanel-B4VXajfj.js → DocumentProcessingPanel-DyTe7Nei.js} +1 -1
  159. package/static/dashboard/assets/{IndexLifecyclePanel-CWCy0CC8.js → IndexLifecyclePanel-fK8ZGlrL.js} +1 -1
  160. package/static/dashboard/assets/{IndexSubjectPanel-CSgyQnG_.js → IndexSubjectPanel-CZPGor7v.js} +1 -1
  161. package/static/dashboard/assets/{ModelAssignmentsPanel-CdGIGidT.js → ModelAssignmentsPanel-CfYn5LMQ.js} +1 -1
  162. package/static/dashboard/assets/ModelsPage-djlJsghe.js +25 -0
  163. package/static/dashboard/assets/{NetworkPage-COia9NCH.js → NetworkPage-Coj6GnPl.js} +1 -1
  164. package/static/dashboard/assets/{PaneListHeader-SZWyr602.js → PaneListHeader-CUuFNSsZ.js} +1 -1
  165. package/static/dashboard/assets/{SearchIndexingPanel-D6PZtG6k.js → SearchIndexingPanel-CyJLioXS.js} +1 -1
  166. package/static/dashboard/assets/{StatusSubjectPanel-CxRD4kv0.js → StatusSubjectPanel-Cv26GSVC.js} +1 -1
  167. package/static/dashboard/assets/{StatusWorkspace-D3PfmY9-.js → StatusWorkspace-CDjFrsmB.js} +1 -1
  168. package/static/dashboard/assets/{SystemSettingsPage-COg1MmMj.js → SystemSettingsPage-BuNOyNoa.js} +1 -1
  169. package/static/dashboard/assets/{SystemSettingsSubjectPanel-BSVVB9Ol.js → SystemSettingsSubjectPanel-B2dasdez.js} +1 -1
  170. package/static/dashboard/assets/{activity-BJJx5cN-.js → activity-D1d2j_4Z.js} +1 -1
  171. package/static/dashboard/assets/ai-connections-C03UWyPh.js +1 -0
  172. package/static/dashboard/assets/{badge-elmrFSCj.js → badge-BeAAv6sp.js} +1 -1
  173. package/static/dashboard/assets/{dashboard-IvQrNmru.js → dashboard-BnGrUGv8.js} +68 -68
  174. package/static/dashboard/assets/dashboard-vPSC2d2F.css +1 -0
  175. package/static/dashboard/assets/{download-C3FH2KzG.js → download-DfFGiZRn.js} +1 -1
  176. package/static/dashboard/assets/{external-link-Bx7F0uKb.js → external-link-IsjU_LC9.js} +1 -1
  177. package/static/dashboard/assets/{index-liRoRIP1.js → index-BWQTucPe.js} +1 -1
  178. package/static/dashboard/assets/{index-M4-kWiGz.js → index-Dj75OjnW.js} +1 -1
  179. package/static/dashboard/assets/{key-round-CXg0bKAj.js → key-round-BJ_9wmQ_.js} +1 -1
  180. package/static/dashboard/assets/{rotate-ccw-yxJKOBrX.js → rotate-ccw-D3JGiFbR.js} +1 -1
  181. package/static/dashboard/assets/{skeleton-x9jNGrQT.js → skeleton-CC4nc-z-.js} +1 -1
  182. package/static/dashboard/assets/{waypoints-CTKeRsGp.js → waypoints-h7sqFqiG.js} +1 -1
  183. package/static/dashboard/assets/{workspace-layout--YkgkS38.js → workspace-layout-ZAPTOHhs.js} +1 -1
  184. package/static/dashboard/dashboard.html +2 -2
  185. package/static/settings/assets/{AiConfigContext-CelxXFcQ.js → AiConfigContext-lGkWpvKP.js} +1 -1
  186. package/static/settings/assets/{AiConfigPage-BaP-EovM.js → AiConfigPage-BbZWIBZq.js} +1 -1
  187. package/static/settings/assets/{DocumentProcessingPanel-DzLZluFv.js → DocumentProcessingPanel-DvYdjT-V.js} +1 -1
  188. package/static/settings/assets/{IndexLifecyclePanel-Bzj1-_oI.js → IndexLifecyclePanel-W5OGQZj7.js} +1 -1
  189. package/static/settings/assets/{IndexSubjectPanel-B263QLUh.js → IndexSubjectPanel-g_Aa5soq.js} +1 -1
  190. package/static/settings/assets/{ModelAssignmentsPanel-BAdT4UR0.js → ModelAssignmentsPanel-COlMBKXj.js} +1 -1
  191. package/static/settings/assets/ModelsPage-mApKi-aw.js +10 -0
  192. package/static/settings/assets/{NetworkPage-BK6a7l4g.js → NetworkPage-BDT05JUq.js} +1 -1
  193. package/static/settings/assets/{PaneListHeader-BAS2ICPq.js → PaneListHeader-CByhNpMG.js} +1 -1
  194. package/static/settings/assets/{SearchIndexingPanel-Cb_p-NgW.js → SearchIndexingPanel-BFAyzXls.js} +1 -1
  195. package/static/settings/assets/{StatusSubjectPanel-CcjqUua6.js → StatusSubjectPanel-Bz_XZ3VU.js} +1 -1
  196. package/static/settings/assets/{StatusWorkspace-7Ibty3_k.js → StatusWorkspace-CeVypHcW.js} +1 -1
  197. package/static/settings/assets/{SystemSettingsPage-DPSz4dg4.js → SystemSettingsPage-Dh7cQIfx.js} +1 -1
  198. package/static/settings/assets/{SystemSettingsSubjectPanel-Cb4HkKT5.js → SystemSettingsSubjectPanel-CSnpciO0.js} +1 -1
  199. package/static/settings/assets/{activity-Qhsr5Pxu.js → activity-DXz3EfFN.js} +1 -1
  200. package/static/settings/assets/ai-connections-C03UWyPh.js +1 -0
  201. package/static/settings/assets/{badge-B1vf2qCl.js → badge-1ZA144i4.js} +1 -1
  202. package/static/settings/assets/{download-CYNt0aZ-.js → download-CUHimlYa.js} +1 -1
  203. package/static/settings/assets/{external-link-ClKb39NT.js → external-link-BYHSVj2Z.js} +1 -1
  204. package/static/settings/assets/{index-y8ew3MLM.js → index-DKPDMdW5.js} +1 -1
  205. package/static/settings/assets/{index-browser-DJhvgpNI.js → index-browser-BaEFz0e0.js} +1 -1
  206. package/static/settings/assets/{index-BgiIDSch.js → index-viSgSvbO.js} +1 -1
  207. package/static/settings/assets/{key-round-5d-DrJz-.js → key-round-COByPOg8.js} +1 -1
  208. package/static/settings/assets/{rotate-ccw-CHZY7kS5.js → rotate-ccw-BC2EN6cE.js} +1 -1
  209. package/static/settings/assets/{settings-D5VRWyx6.js → settings-DLH9XUoT.js} +86 -86
  210. package/static/settings/assets/settings-vPSC2d2F.css +1 -0
  211. package/static/settings/assets/{skeleton-FNabNxNE.js → skeleton-B0-FOhKL.js} +1 -1
  212. package/static/settings/assets/{waypoints-BnL_8ljo.js → waypoints-DGMsvqWo.js} +1 -1
  213. package/static/settings/assets/{workspace-layout-D5q3F59S.js → workspace-layout-B0SVrJIu.js} +1 -1
  214. package/static/settings/settings.html +2 -2
  215. package/static/auth-callback/assets/ModelsPage-BpkVFKbf.js +0 -10
  216. package/static/auth-callback/assets/ai-connections-Bm52UO7Y.js +0 -1
  217. package/static/auth-callback/assets/auth-callback-01yz-UDU.css +0 -1
  218. package/static/dashboard/assets/ModelsPage-Chd5UK0D.js +0 -25
  219. package/static/dashboard/assets/ai-connections-Bm52UO7Y.js +0 -1
  220. package/static/dashboard/assets/dashboard-01yz-UDU.css +0 -1
  221. package/static/settings/assets/ModelsPage-C0NFa1zq.js +0 -10
  222. package/static/settings/assets/ai-connections-Bm52UO7Y.js +0 -1
  223. package/static/settings/assets/settings-01yz-UDU.css +0 -1
@@ -4,8 +4,7 @@ import { Avatar, AvatarFallback, AvatarImage, Badge, Button, Input, Tooltip, Too
4
4
  import { getProviderAvatar, getProviderAvatarBackground } from './provider-visuals.js';
5
5
  import { Box, Brain, Check, Copy, ExternalLink, Globe, Image as ImageIcon, Info, Loader2, Pencil, Plus, RotateCw, Search, Trash2, } from 'lucide-react';
6
6
  import { AiCredentialPoolSection, } from './AiCredentialPoolSection.js';
7
- import { offeringTitle } from './offering-label.js';
8
- export function AiProviderCard({ definition, product, status, accountLabel, attempt, attemptOfferingId, apiKey, baseUrl = '', busy, disabled = false, error, quotas, models, verifyPending = false, onApiKeyChange, onBaseUrlChange, onBeginApiKey, onBeginOffering, onBeginBrowser, onSaveApiKey, onDisconnect, onCreateApiKeyCredential, onCreateLocalCredential, onUpdateCredential, onDeleteCredential, onTestCredential, onReorderCredentials, onRefreshQuota, onVerify, onAddModel, onEditModel, onDeleteModel, selectedModelIds, onModelSelectionChange, onDismissError, }) {
7
+ export function AiProviderCard({ definition, product, status, accountLabel, attempt, attemptOfferingId, apiKey, baseUrl = '', busy, disabled = false, error, quotas, models, verifyPending = false, onApiKeyChange, onBaseUrlChange, onBeginApiKey, onBeginOffering, onCancelConnect, onBeginBrowser, onSaveApiKey, onDisconnect, onCreateApiKeyCredential, onCreateLocalCredential, onUpdateCredential, onDeleteCredential, onTestCredential, onReorderCredentials, onRefreshQuota, onVerify, onAddModel, onEditModel, onDeleteModel, selectedModelIds, modelSelectionStatus, onModelSelectionChange, onDismissError, }) {
9
8
  const isConfigured = status === 'configured';
10
9
  const isConnected = status === 'connected';
11
10
  const catalogError = models.length === 0 && error?.message && !error.offeringId
@@ -15,21 +14,20 @@ export function AiProviderCard({ definition, product, status, accountLabel, atte
15
14
  const [copiedModelId, setCopiedModelId] = useState();
16
15
  const [localSelectedModelIds, setLocalSelectedModelIds] = useState(selectedModelIds ?? []);
17
16
  const effectiveSelectedModelIds = selectedModelIds ?? localSelectedModelIds;
18
- const offeringSources = useMemo(() => new Map(product?.offerings.map((offering) => [offering.id, {
19
- id: offering.id,
20
- label: offeringTitle(offering),
21
- }]) ?? []), [product?.offerings]);
17
+ const catalog = useMemo(() => aggregateProviderModels(models), [models]);
18
+ const isModelSelected = (model) => model.selectionIds.some((id) => effectiveSelectedModelIds.includes(id));
22
19
  const visibleModels = useMemo(() => {
23
20
  const query = modelSearch.trim().toLocaleLowerCase();
24
21
  if (!query)
25
- return models;
26
- return models.filter((model) => modelSearchText(model, offeringSources).includes(query));
27
- }, [models, modelSearch, offeringSources]);
22
+ return catalog;
23
+ return catalog.filter((model) => model.searchText.includes(query));
24
+ }, [catalog, modelSearch]);
28
25
  const selectableVisibleModels = visibleModels.filter((model) => model.availability !== 'unavailable');
29
- const selectedVisibleCount = selectableVisibleModels.filter((model) => effectiveSelectedModelIds.includes(modelSelectionId(model))).length;
26
+ const selectedVisibleCount = selectableVisibleModels.filter(isModelSelected).length;
30
27
  const allVisibleSelected = selectableVisibleModels.length > 0 && selectedVisibleCount === selectableVisibleModels.length;
31
28
  const someVisibleSelected = selectedVisibleCount > 0 && !allVisibleSelected;
32
- const unavailableModelCount = models.filter((model) => model.availability === 'unavailable').length;
29
+ const selectedModelCount = catalog.filter(isModelSelected).length;
30
+ const unavailableModelCount = catalog.filter((model) => model.availability === 'unavailable').length;
33
31
  const copyModelId = async (modelId) => {
34
32
  try {
35
33
  await navigator.clipboard.writeText(modelId);
@@ -40,12 +38,15 @@ export function AiProviderCard({ definition, product, status, accountLabel, atte
40
38
  setCopiedModelId(undefined);
41
39
  }
42
40
  };
43
- const toggleModel = (modelId) => {
41
+ const toggleModel = (model) => {
44
42
  const next = new Set(effectiveSelectedModelIds);
45
- if (next.has(modelId))
46
- next.delete(modelId);
47
- else
48
- next.add(modelId);
43
+ const remove = isModelSelected(model);
44
+ for (const id of remove ? model.selectionIds : model.availableSelectionIds) {
45
+ if (remove)
46
+ next.delete(id);
47
+ else
48
+ next.add(id);
49
+ }
49
50
  const nextModelIds = [...next];
50
51
  if (selectedModelIds === undefined)
51
52
  setLocalSelectedModelIds(nextModelIds);
@@ -54,34 +55,38 @@ export function AiProviderCard({ definition, product, status, accountLabel, atte
54
55
  const toggleVisibleModels = () => {
55
56
  const next = new Set(effectiveSelectedModelIds);
56
57
  for (const model of selectableVisibleModels) {
57
- const selectionId = modelSelectionId(model);
58
- if (allVisibleSelected)
59
- next.delete(selectionId);
60
- else
61
- next.add(selectionId);
58
+ for (const id of allVisibleSelected ? model.selectionIds : model.availableSelectionIds) {
59
+ if (allVisibleSelected)
60
+ next.delete(id);
61
+ else
62
+ next.add(id);
63
+ }
62
64
  }
63
65
  const nextModelIds = [...next];
64
66
  if (selectedModelIds === undefined)
65
67
  setLocalSelectedModelIds(nextModelIds);
66
68
  onModelSelectionChange?.(definition.id, nextModelIds);
67
69
  };
68
- return (_jsx(TooltipProvider, { children: _jsxs("div", { className: "space-y-8", children: [_jsxs("header", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsxs(Avatar, { className: "h-9 w-9 shrink-0 rounded-lg border border-border/50 bg-muted/50 shadow-sm", style: getProviderAvatarBackground(definition.id) ? { backgroundColor: getProviderAvatarBackground(definition.id) } : undefined, children: [_jsx(AvatarImage, { src: getProviderAvatar(definition.id), className: "object-cover" }), _jsx(AvatarFallback, { className: "rounded-lg bg-transparent text-sm font-bold uppercase text-muted-foreground", children: providerMark(definition.id) })] }), _jsxs("div", { className: "flex flex-col justify-center gap-0.5", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("h2", { className: "text-base font-semibold leading-none tracking-tight text-foreground", children: definition.name }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": "\u63D0\u4F9B\u5546\u8BF4\u660E", 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 text-xs", children: definition.description })] })] }), _jsxs("a", { href: definition.homeUrl, target: "_blank", rel: "noreferrer", className: "flex items-center gap-0.5 text-[10px] leading-none text-muted-foreground transition-colors hover:text-primary", children: ["\u8BBF\u95EE\u5B98\u7F51 ", _jsx(ExternalLink, { "aria-hidden": "true", className: "h-2.5 w-2.5" })] })] })] }), _jsx(Badge, { variant: isConnected || isConfigured ? 'default' : 'secondary', children: connectionStatusLabel(status) })] }), _jsx(AiCredentialPoolSection, { definition: definition, product: product, status: status, accountLabel: accountLabel, attempt: attempt, attemptOfferingId: attemptOfferingId, apiKey: apiKey, baseUrl: baseUrl, busy: busy, disabled: disabled, error: error, suppressError: Boolean(catalogError), quotas: quotas, onApiKeyChange: onApiKeyChange, onBaseUrlChange: onBaseUrlChange, onBeginApiKey: onBeginApiKey, onBeginOffering: onBeginOffering, onBeginBrowser: onBeginBrowser, onSaveApiKey: onSaveApiKey, onDisconnect: onDisconnect, onCreateApiKeyCredential: product?.offerings.length ? onCreateApiKeyCredential : undefined, onCreateLocalCredential: product?.offerings.length ? onCreateLocalCredential : undefined, onUpdateCredential: onUpdateCredential, onDeleteCredential: onDeleteCredential, onTestCredential: onTestCredential, onReorderCredentials: onReorderCredentials, onRefreshQuota: onRefreshQuota, onDismissError: onDismissError }), _jsxs("section", { className: "space-y-4", children: [_jsxs("div", { "data-testid": "provider-models-header", className: "flex flex-col gap-3 border-b border-border/40 pb-4 sm:flex-row sm:items-center sm:justify-between", children: [_jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [_jsx(Box, { className: "h-4 w-4 shrink-0 text-primary" }), _jsx("h3", { className: "shrink-0 text-sm font-medium text-foreground/90", children: "\u53EF\u7528\u6A21\u578B" }), _jsxs("span", { className: "text-xs text-muted-foreground", children: ["\u5171 ", models.length, " \u00B7 \u5DF2\u52A0\u5165 ", effectiveSelectedModelIds.length, " \u00B7 \u5DF2\u5931\u6548 ", unavailableModelCount] })] }), _jsxs("div", { "data-testid": "provider-models-actions", className: "flex w-full flex-wrap items-center gap-2 sm:w-auto sm:flex-nowrap sm:justify-end", children: [(isConfigured || isConnected) && (onVerify || onAddModel) ? (_jsxs(_Fragment, { children: [onAddModel ? (_jsxs(Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", disabled: disabled || busy, onClick: onAddModel, children: [_jsx(Plus, { "aria-hidden": "true", className: "h-3.5 w-3.5" }), "\u6DFB\u52A0\u6A21\u578B"] })) : null, onVerify && models.length > 0 ? (_jsxs(Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", disabled: disabled || busy || verifyPending, onClick: onVerify, children: [verifyPending
70
+ return (_jsx(TooltipProvider, { children: _jsxs("div", { className: "space-y-8", children: [_jsxs("header", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsxs(Avatar, { className: "h-9 w-9 shrink-0 rounded-lg border border-border/50 bg-muted/50 shadow-sm", style: getProviderAvatarBackground(definition.id) ? { backgroundColor: getProviderAvatarBackground(definition.id) } : undefined, children: [_jsx(AvatarImage, { src: getProviderAvatar(definition.id), className: "object-cover" }), _jsx(AvatarFallback, { className: "rounded-lg bg-transparent text-sm font-bold uppercase text-muted-foreground", children: providerMark(definition.id) })] }), _jsxs("div", { className: "flex flex-col justify-center gap-0.5", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("h2", { className: "text-base font-semibold leading-none tracking-tight text-foreground", children: definition.name }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": "\u63D0\u4F9B\u5546\u8BF4\u660E", 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" }) }) }), _jsxs(TooltipContent, { className: "max-w-xs space-y-2 text-xs", children: [_jsx("p", { children: definition.description }), _jsx("p", { children: "Provider \u51ED\u8BC1\u4FDD\u5B58\u5728\u5F53\u524D Pod\uFF0C\u7531 Pod \u6743\u9650\u4FDD\u62A4\u3002" })] })] })] }), _jsxs("a", { href: definition.homeUrl, target: "_blank", rel: "noreferrer", className: "flex items-center gap-0.5 text-[10px] leading-none text-muted-foreground transition-colors hover:text-primary", children: ["\u8BBF\u95EE\u5B98\u7F51 ", _jsx(ExternalLink, { "aria-hidden": "true", className: "h-2.5 w-2.5" })] })] })] }), _jsx(Badge, { variant: isConnected || isConfigured ? 'default' : 'secondary', children: connectionStatusLabel(status) })] }), _jsx(AiCredentialPoolSection, { definition: definition, product: product, status: status, accountLabel: accountLabel, attempt: attempt, attemptOfferingId: attemptOfferingId, apiKey: apiKey, baseUrl: baseUrl, busy: busy, disabled: disabled, error: error, suppressError: Boolean(catalogError), quotas: quotas, onApiKeyChange: onApiKeyChange, onBaseUrlChange: onBaseUrlChange, onBeginApiKey: onBeginApiKey, onBeginOffering: onBeginOffering, onCancelConnect: onCancelConnect, onBeginBrowser: onBeginBrowser, onSaveApiKey: onSaveApiKey, onDisconnect: onDisconnect, onCreateApiKeyCredential: product?.offerings.length ? onCreateApiKeyCredential : undefined, onCreateLocalCredential: product?.offerings.length ? onCreateLocalCredential : undefined, onUpdateCredential: onUpdateCredential, onDeleteCredential: onDeleteCredential, onTestCredential: onTestCredential, onReorderCredentials: onReorderCredentials, onRefreshQuota: onRefreshQuota, onDismissError: onDismissError }), _jsxs("section", { className: "space-y-4", children: [_jsxs("div", { "data-testid": "provider-models-header", className: "flex flex-col gap-3 border-b border-border/40 pb-4 sm:flex-row sm:items-center sm:justify-between", children: [_jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [_jsx(Box, { className: "h-4 w-4 shrink-0 text-primary" }), _jsx("h3", { className: "shrink-0 text-sm font-medium text-foreground/90", children: "\u53EF\u7528\u6A21\u578B" }), _jsxs("span", { className: "text-xs text-muted-foreground", children: ["\u5171 ", catalog.length, " \u00B7 \u5DF2\u52A0\u5165 ", selectedModelCount, " \u00B7 \u5DF2\u5931\u6548 ", unavailableModelCount] }), _jsxs("span", { role: "status", "aria-live": "polite", "aria-atomic": "true", className: cn('inline-flex items-center gap-1 text-xs', modelSelectionStatus === 'error' ? 'text-destructive' : 'text-muted-foreground'), children: [modelSelectionStatus === 'saving'
71
+ ? _jsx(Loader2, { "aria-hidden": "true", className: "h-3 w-3 animate-spin motion-reduce:animate-none" })
72
+ : modelSelectionStatus === 'saved' ? _jsx(Check, { "aria-hidden": "true", className: "h-3 w-3" }) : null, modelSelectionStatus === 'saving' ? '保存中…'
73
+ : modelSelectionStatus === 'saved' ? '已保存'
74
+ : modelSelectionStatus === 'error' ? '保存失败,请重试' : '选择后自动保存'] })] }), _jsxs("div", { "data-testid": "provider-models-actions", className: "flex w-full flex-wrap items-center gap-2 sm:w-auto sm:flex-nowrap sm:justify-end", children: [(isConfigured || isConnected) && (onVerify || onAddModel) ? (_jsxs(_Fragment, { children: [onAddModel ? (_jsxs(Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", disabled: disabled || busy, onClick: onAddModel, children: [_jsx(Plus, { "aria-hidden": "true", className: "h-3.5 w-3.5" }), "\u6DFB\u52A0\u6A21\u578B"] })) : null, onVerify && models.length > 0 ? (_jsxs(Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", disabled: disabled || busy || verifyPending, onClick: onVerify, children: [verifyPending
69
75
  ? _jsx(Loader2, { "aria-hidden": "true", className: "h-3.5 w-3.5 animate-spin" })
70
76
  : _jsx(RotateCw, { "aria-hidden": "true", className: "h-3.5 w-3.5" }), verifyPending ? '同步中...' : '刷新模型'] })) : onVerify ? (_jsxs(Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", disabled: disabled || busy || verifyPending, onClick: onVerify, children: [verifyPending
71
77
  ? _jsx(Loader2, { "aria-hidden": "true", className: "h-3.5 w-3.5 animate-spin" })
72
78
  : _jsx(RotateCw, { "aria-hidden": "true", className: "h-3.5 w-3.5" }), verifyPending ? '同步中...' : '同步模型'] })) : null] })) : null, _jsxs("div", { className: "relative w-full sm:w-auto", children: [_jsx(Search, { className: "absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { value: modelSearch, onChange: (event) => setModelSearch(event.target.value), placeholder: "\u641C\u7D22\u6A21\u578B...", className: "h-8 w-full bg-background pl-8 text-xs sm:w-[232px]", autoComplete: "off", "data-lpignore": "true", "data-1p-ignore": true })] })] })] }), models.length === 0 ? (_jsx("div", { className: "rounded-lg border border-dashed border-border/50 bg-muted/5 py-12 text-center text-sm text-muted-foreground", children: catalogError ? (_jsx("p", { className: "text-destructive", children: catalogError })) : ('暂无可用模型') })) : visibleModels.length === 0 ? (_jsx("div", { className: "rounded-lg border border-dashed border-border/50 bg-muted/5 py-12 text-center text-sm text-muted-foreground", children: "\u672A\u627E\u5230\u5339\u914D\u7684\u6A21\u578B" })) : (_jsxs("div", { className: "grid gap-2", children: [_jsx("div", { className: "flex items-center justify-between px-1 py-1", children: _jsxs("button", { type: "button", role: "checkbox", "aria-label": "\u5168\u9009\u5F53\u524D\u7ED3\u679C", "aria-checked": someVisibleSelected ? 'mixed' : allVisibleSelected, disabled: disabled || busy || selectableVisibleModels.length === 0, onClick: toggleVisibleModels, className: "flex items-center gap-2 text-xs text-muted-foreground disabled:opacity-50", children: [_jsx("span", { className: cn('flex h-4 w-4 items-center justify-center rounded border', allVisibleSelected || someVisibleSelected ? 'border-primary bg-primary text-primary-foreground' : 'border-border'), children: someVisibleSelected ? _jsx("span", { "aria-hidden": "true", children: "\u2212" }) : _jsx(Check, { "aria-hidden": "true", className: cn('h-3 w-3', !allVisibleSelected && 'invisible') }) }), "\u5168\u9009\u5F53\u524D\u7ED3\u679C"] }) }), visibleModels.map((model) => {
73
79
  const selectionId = modelSelectionId(model);
74
- const isSelected = effectiveSelectedModelIds.includes(selectionId);
80
+ const isSelected = isModelSelected(model);
75
81
  const isUnavailable = model.availability === 'unavailable';
76
82
  const modelLabel = model.displayName ?? model.id;
77
- const source = modelOfferingSource(model, offeringSources);
78
83
  const iconTokens = [
79
84
  ...(model.inputModalities ?? []).filter((modality) => modality !== 'text'),
80
85
  ...(model.capabilities ?? []),
81
86
  ];
82
87
  return (_jsxs("div", { className: cn('group flex items-center gap-3 rounded-lg border bg-card p-3 transition-all duration-200 hover:border-border/60 hover:bg-accent/30', isSelected ? 'border-primary/40 bg-primary/[0.03]' : 'border-border/40', isUnavailable && 'opacity-75'), children: [_jsx("button", { type: "button", role: "checkbox", "aria-checked": isSelected, "aria-label": `${isSelected ? '取消选择' : '选择'} ${modelLabel}`, className: cn('flex h-5 w-5 shrink-0 items-center justify-center rounded border transition-colors focus:outline-none focus-visible:border-ring', isSelected
83
88
  ? 'border-primary bg-primary text-primary-foreground'
84
- : 'border-border text-transparent hover:border-primary/60'), disabled: disabled || busy || (isUnavailable && !isSelected), onClick: () => toggleModel(selectionId), children: _jsx(Check, { "aria-hidden": "true", className: "h-3.5 w-3.5" }) }), _jsx("div", { className: "shrink-0 rounded bg-muted/50 p-2 text-muted-foreground transition-colors group-hover:text-primary", children: _jsx(Box, { className: "h-4 w-4" }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "truncate text-sm font-medium text-foreground/90", children: modelLabel }), _jsx("div", { className: "flex items-center gap-1", children: iconTokens.map((token) => _jsx(CapabilityIcon, { type: token }, token)) }), source ? (_jsx(Badge, { variant: "outline", className: "shrink-0 text-[10px] font-normal", "aria-label": `模型来源:${source.label}`, title: source.id, children: source.label })) : null, model.custom ? _jsx(Badge, { variant: "outline", className: "shrink-0 text-[10px] font-normal", children: "\u624B\u5DE5" }) : null, isUnavailable ? (_jsx(Badge, { variant: "destructive", className: "shrink-0 text-[10px] font-normal", children: "\u5DF2\u5931\u6548" })) : null] }), model.displayName ? (_jsxs("div", { className: "mt-0.5 flex items-center gap-1.5", children: [_jsx("code", { className: "max-w-[300px] truncate font-mono text-[10px] text-muted-foreground opacity-70", children: model.id }), _jsx("button", { type: "button", onClick: () => void copyModelId(model.id), className: "rounded p-0.5 text-muted-foreground opacity-0 transition-opacity hover:bg-muted hover:text-foreground group-hover:opacity-100 group-focus-within:opacity-100 focus:opacity-100", "aria-label": `复制 ${model.displayName} ID`, title: "\u590D\u5236 ID", children: copiedModelId === model.id
89
+ : 'border-border text-transparent hover:border-primary/60'), disabled: disabled || busy || (isUnavailable && !isSelected), onClick: () => toggleModel(model), children: _jsx(Check, { "aria-hidden": "true", className: "h-3.5 w-3.5" }) }), _jsx("div", { className: "shrink-0 rounded bg-muted/50 p-2 text-muted-foreground transition-colors group-hover:text-primary", children: _jsx(Box, { className: "h-4 w-4" }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "truncate text-sm font-medium text-foreground/90", children: modelLabel }), _jsx("div", { className: "flex items-center gap-1", children: iconTokens.map((token) => _jsx(CapabilityIcon, { type: token }, token)) }), model.custom ? _jsx(Badge, { variant: "outline", className: "shrink-0 text-[10px] font-normal", children: "\u624B\u5DE5" }) : null, isUnavailable ? (_jsx(Badge, { variant: "destructive", className: "shrink-0 text-[10px] font-normal", children: "\u5DF2\u5931\u6548" })) : null] }), model.displayName ? (_jsxs("div", { className: "mt-0.5 flex items-center gap-1.5", children: [_jsx("code", { className: "max-w-[300px] truncate font-mono text-[10px] text-muted-foreground opacity-70", children: model.id }), _jsx("button", { type: "button", onClick: () => void copyModelId(model.id), className: "rounded p-0.5 text-muted-foreground opacity-0 transition-opacity hover:bg-muted hover:text-foreground group-hover:opacity-100 group-focus-within:opacity-100 focus:opacity-100", "aria-label": `复制 ${model.displayName} ID`, title: "\u590D\u5236 ID", children: copiedModelId === model.id
85
90
  ? _jsx(Check, { "aria-hidden": "true", className: "h-3 w-3 text-primary" })
86
91
  : _jsx(Copy, { "aria-hidden": "true", className: "h-3 w-3" }) })] })) : null] }), model.custom && (onEditModel || onDeleteModel) ? (_jsxs("div", { className: "flex shrink-0 items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 focus-within:opacity-100", children: [onEditModel ? (_jsx(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", "aria-label": `编辑 ${model.displayName ?? model.id}`, onClick: () => onEditModel(model), children: _jsx(Pencil, { "aria-hidden": "true", className: "h-3.5 w-3.5 text-muted-foreground" }) })) : null, onDeleteModel ? (_jsx(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", "aria-label": `删除 ${model.displayName ?? model.id}`, onClick: () => onDeleteModel(model), children: _jsx(Trash2, { "aria-hidden": "true", className: "h-3.5 w-3.5 text-muted-foreground" }) })) : null] })) : null] }, selectionId));
87
92
  })] }))] })] }) }));
@@ -114,22 +119,34 @@ function modelSelectionId(model) {
114
119
  return model.resourceId
115
120
  ?? (model.offeringId ? `${model.offeringId}:${model.id}` : model.id);
116
121
  }
117
- function modelSearchText(model, offeringSources) {
118
- const source = modelOfferingSource(model, offeringSources);
119
- return [
120
- model.id,
121
- model.displayName,
122
- source?.label,
123
- source?.id,
124
- ]
125
- .filter(Boolean)
126
- .join('\n')
127
- .toLocaleLowerCase();
128
- }
129
- function modelOfferingSource(model, offeringSources) {
130
- if (!model.offeringId)
131
- return undefined;
132
- return offeringSources.get(model.offeringId) ?? { id: model.offeringId, label: model.offeringId };
122
+ function aggregateProviderModels(models) {
123
+ const catalog = new Map();
124
+ for (const model of models) {
125
+ const key = `${model.provider}\0${model.id}`;
126
+ const selectionId = modelSelectionId(model);
127
+ const existing = catalog.get(key);
128
+ const searchText = [model.id, model.displayName].filter(Boolean).join('\n').toLocaleLowerCase();
129
+ if (!existing) {
130
+ catalog.set(key, {
131
+ ...model,
132
+ selectionIds: [selectionId],
133
+ availableSelectionIds: model.availability === 'unavailable' ? [] : [selectionId],
134
+ searchText,
135
+ });
136
+ continue;
137
+ }
138
+ if (!existing.selectionIds.includes(selectionId))
139
+ existing.selectionIds.push(selectionId);
140
+ if (model.availability !== 'unavailable' && !existing.availableSelectionIds.includes(selectionId)) {
141
+ existing.availableSelectionIds.push(selectionId);
142
+ }
143
+ if (model.availability !== 'unavailable')
144
+ existing.availability = model.availability;
145
+ existing.capabilities = [...new Set([...(existing.capabilities ?? []), ...(model.capabilities ?? [])])];
146
+ existing.inputModalities = [...new Set([...(existing.inputModalities ?? []), ...(model.inputModalities ?? [])])];
147
+ existing.searchText += `\n${searchText}`;
148
+ }
149
+ return [...catalog.values()];
133
150
  }
134
151
  function connectionStatusLabel(status) {
135
152
  switch (status) {
@@ -1,11 +1,14 @@
1
1
  import type { AiQuotaSnapshot } from './ai-connections-client';
2
- export declare function AiQuotaCard({ providerName, offeringName, quota, busy, disabled, credentialLabel, error, onRefresh, }: {
2
+ export declare function AiQuotaCard({ providerName, offeringName, quota, busy, disabled, credentialLabel, multiple, compact, paused, error, onRefresh, }: {
3
3
  providerName: string;
4
4
  offeringName: string;
5
5
  quota?: AiQuotaSnapshot;
6
6
  busy: boolean;
7
7
  disabled?: boolean;
8
8
  credentialLabel?: string;
9
+ multiple?: boolean;
10
+ compact?: boolean;
11
+ paused?: boolean;
9
12
  error?: string;
10
13
  onRefresh: () => void;
11
14
  }): import("react").JSX.Element;
@@ -1,8 +1,67 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Button } from '@undefineds.co/shared-ui';
3
- import { RefreshCcw, Wallet } from 'lucide-react';
4
- export function AiQuotaCard({ providerName, offeringName, quota, busy, disabled = false, credentialLabel, error, onRefresh, }) {
5
- return (_jsxs("div", { className: "space-y-3 border-t border-border/40 pt-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Wallet, { className: "h-4 w-4 text-primary" }), _jsx("div", { className: "text-sm font-medium text-foreground/90", children: "\u5269\u4F59\u989D\u5EA6" })] }), _jsxs(Button, { variant: "ghost", size: "sm", "aria-label": `刷新 ${providerName} ${offeringName}额度`, disabled: busy || disabled, onClick: onRefresh, children: [_jsx(RefreshCcw, { className: "mr-2 h-3.5 w-3.5" }), "\u5237\u65B0"] })] }), credentialLabel ? (_jsxs("p", { className: "text-xs text-muted-foreground", children: ["\u51ED\u8BC1\uFF1A", credentialLabel] })) : null, error ? (_jsx("p", { className: "text-sm text-destructive", children: error })) : !quota ? (_jsx("p", { className: "text-xs text-muted-foreground", children: credentialLabel ? '尚未检查' : '连接后可查询' })) : quota.status === 'unsupported' ? (_jsxs(_Fragment, { children: [_jsx("p", { className: "text-sm", children: "\u5B98\u65B9\u989D\u5EA6\u63A5\u53E3\u4E0D\u652F\u6301" }), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["\u6765\u6E90\uFF1A", quota.source] })] })) : quota.status === 'error' ? (_jsx("p", { className: "text-sm text-destructive", children: "\u989D\u5EA6\u67E5\u8BE2\u5931\u8D25" })) : (_jsxs("div", { className: "space-y-3 text-sm", children: [typeof quota.balance === 'number' ? _jsxs("div", { children: ["\u4F59\u989D\uFF1A", quota.balance] }) : null, quota.windows.map((window, index) => (_jsxs("div", { className: "space-y-1.5", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("span", { className: "font-medium text-foreground", children: quotaWindowLabel(window.name) }), _jsx("span", { className: "text-muted-foreground", children: remainingLabel(window) })] }), remainingPercent(window) !== undefined ? (_jsx("div", { "aria-label": `${quotaWindowLabel(window.name)}剩余 ${String(remainingPercent(window))}%`, className: "h-1.5 overflow-hidden rounded-full bg-muted", role: "progressbar", "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": remainingPercent(window), children: _jsx("div", { className: "h-full rounded-full bg-primary", style: { width: `${String(remainingPercent(window))}%` } }) })) : null, window.resetsAt ? _jsxs("p", { className: "text-xs text-muted-foreground", children: ["\u91CD\u7F6E\uFF1A", formatTimestamp(window.resetsAt)] }) : null] }, `${String(window.name)}-${index}`))), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["\u66F4\u65B0\uFF1A", formatTimestamp(quota.observedAt)] }), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["\u6765\u6E90\uFF1A", quota.source, quota.stale ? ' · 数据可能已过期' : ''] })] }))] }));
2
+ import { useEffect, useRef, useState } from 'react';
3
+ import { Button, Dialog, DialogContent, DialogTitle, DialogTrigger } from '@undefineds.co/shared-ui';
4
+ import { Info, Loader2, RefreshCcw, Wallet } from 'lucide-react';
5
+ export function AiQuotaCard({ providerName, offeringName, quota, busy, disabled = false, credentialLabel, multiple = false, compact = false, paused = false, error, onRefresh, }) {
6
+ if (compact) {
7
+ const available = !busy && !error && quota?.status === 'available';
8
+ return (_jsx("div", { className: `min-w-0 text-xs text-muted-foreground ${paused ? 'opacity-60' : ''}`, children: _jsxs("div", { className: "flex items-start gap-1", children: [_jsxs("div", { className: "min-w-0 flex-1 truncate py-1 [&>span+span]:ml-3", children: [paused ? _jsx("span", { children: "\u5DF2\u505C\u7528 \u00B7 \u4E0D\u53C2\u4E0E\u5168\u90E8\u5237\u65B0" }) : null, busy ? _jsx("span", { role: "status", children: "\u6B63\u5728\u67E5\u8BE2\u989D\u5EA6\u2026" })
9
+ : error ? _jsx("span", { role: "alert", title: error, className: "text-destructive", children: error })
10
+ : !quota ? _jsx("span", { children: credentialLabel ? '尚未检查' : `连接${offeringName}后可查询` })
11
+ : quota.status === 'unsupported' ? _jsx("span", { children: "\u5B98\u65B9\u989D\u5EA6\u63A5\u53E3\u4E0D\u652F\u6301" })
12
+ : quota.status === 'error' ? _jsx("span", { role: "alert", className: "text-destructive", children: "\u989D\u5EA6\u67E5\u8BE2\u5931\u8D25" })
13
+ : _jsx(QuotaSummary, { quota: quota }), available && quota.stale ? _jsx("span", { children: "\u6570\u636E\u53EF\u80FD\u5DF2\u8FC7\u671F" }) : null] }), _jsx(QuotaInfo, { quota: quota, label: credentialLabel ?? offeringName }), _jsx(Button, { className: "h-6 w-6 shrink-0 p-0", variant: "ghost", size: "sm", "aria-label": `刷新 ${providerName} ${offeringName}${credentialLabel ? ` ${credentialLabel}` : ''}额度`, disabled: busy || disabled, onClick: onRefresh, children: busy ? _jsx(Loader2, { "aria-hidden": "true", className: "h-3 w-3 animate-spin" }) : _jsx(RefreshCcw, { "aria-hidden": "true", className: "h-3 w-3" }) })] }) }));
14
+ }
15
+ return (_jsxs("div", { className: `${multiple ? 'space-y-1.5' : 'space-y-3'} border-t border-border/40 pt-3 ${paused ? 'opacity-60' : ''}`, children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [!multiple ? _jsx(Wallet, { className: "h-4 w-4 shrink-0 text-primary" }) : null, _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "break-all text-sm font-medium text-foreground/90", children: multiple ? `凭证:${credentialLabel}` : '剩余额度' }), multiple && !busy && !error && quota?.status === 'available' ? (_jsx("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground", children: _jsx(QuotaSummary, { quota: quota }) })) : null] })] }), _jsxs(Button, { className: "shrink-0", variant: "ghost", size: "sm", "aria-label": `刷新 ${providerName} ${offeringName}${multiple ? ` ${credentialLabel}` : ''}额度`, disabled: busy || disabled, onClick: onRefresh, children: [busy
16
+ ? _jsx(Loader2, { "aria-hidden": "true", className: "mr-2 h-3.5 w-3.5 animate-spin" })
17
+ : _jsx(RefreshCcw, { "aria-hidden": "true", className: "mr-2 h-3.5 w-3.5" }), busy ? '查询中' : '刷新'] })] }), credentialLabel && !multiple ? (_jsxs("p", { className: "text-xs text-muted-foreground", children: ["\u51ED\u8BC1\uFF1A", credentialLabel] })) : null, paused ? _jsx("p", { className: "text-xs text-muted-foreground", children: "\u5DF2\u505C\u7528 \u00B7 \u4E0D\u53C2\u4E0E\u5168\u90E8\u5237\u65B0" }) : null, busy ? (_jsx("p", { role: "status", className: "text-xs text-muted-foreground", children: "\u6B63\u5728\u67E5\u8BE2\u989D\u5EA6\u2026" })) : error ? (_jsx("p", { role: "alert", className: "text-sm text-destructive", children: error })) : !quota ? (_jsx("p", { className: "text-xs text-muted-foreground", children: credentialLabel ? '尚未检查' : `连接${offeringName}后可查询` })) : quota.status === 'unsupported' ? (_jsxs(_Fragment, { children: [_jsx("p", { className: "text-sm", children: "\u5B98\u65B9\u989D\u5EA6\u63A5\u53E3\u4E0D\u652F\u6301" }), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["\u6765\u6E90\uFF1A", quota.source] })] })) : quota.status === 'error' ? (_jsx("p", { className: "text-sm text-destructive", children: "\u989D\u5EA6\u67E5\u8BE2\u5931\u8D25" })) : (multiple ? (_jsxs("details", { className: "text-xs text-muted-foreground", children: [_jsx("summary", { className: "cursor-pointer", "aria-label": `${credentialLabel}额度详情`, children: "\u8BE6\u60C5" }), _jsx("div", { className: "pt-3", children: _jsx(QuotaDetails, { quota: quota, hideBalance: true }) })] })) : _jsx(QuotaDetails, { quota: quota }))] }));
18
+ }
19
+ function QuotaInfo({ quota, label }) {
20
+ const [position, setPosition] = useState({ left: 16, top: 16, maxHeight: 400 });
21
+ const [open, setOpen] = useState(false);
22
+ const triggerRef = useRef(null);
23
+ const contentRef = useRef(null);
24
+ const outsideRef = useRef(false);
25
+ useEffect(() => {
26
+ if (!open)
27
+ return;
28
+ // Capture also covers clicks on the page margin outside React's root.
29
+ const dismissOutside = (event) => {
30
+ if (!(event.target instanceof Node) || triggerRef.current?.contains(event.target) || contentRef.current?.contains(event.target))
31
+ return;
32
+ outsideRef.current = true;
33
+ setOpen(false);
34
+ };
35
+ const dismissMoved = (event) => {
36
+ if (event.type === 'scroll' && event.target instanceof Node && contentRef.current?.contains(event.target))
37
+ return;
38
+ outsideRef.current = true;
39
+ setOpen(false);
40
+ };
41
+ document.addEventListener('pointerdown', dismissOutside, true);
42
+ document.addEventListener('scroll', dismissMoved, true);
43
+ window.addEventListener('resize', dismissMoved);
44
+ return () => {
45
+ document.removeEventListener('pointerdown', dismissOutside, true);
46
+ document.removeEventListener('scroll', dismissMoved, true);
47
+ window.removeEventListener('resize', dismissMoved);
48
+ };
49
+ }, [open]);
50
+ return (_jsxs(Dialog, { modal: false, open: open, onOpenChange: (next) => { outsideRef.current = false; setOpen(next); }, children: [_jsx(DialogTrigger, { asChild: true, children: _jsx(Button, { ref: triggerRef, className: "h-6 w-6 shrink-0 p-0", variant: "ghost", size: "sm", "aria-label": `${label}额度详情`, disabled: !quota || quota.status === 'error', onClick: (event) => {
51
+ const rect = event.currentTarget.getBoundingClientRect();
52
+ const width = Math.min(320, window.innerWidth - 32);
53
+ const left = Math.max(16, Math.min(rect.right - width, window.innerWidth - width - 16));
54
+ const top = Math.max(16, Math.min(rect.bottom + 8, window.innerHeight - 320));
55
+ setPosition({ left, top, maxHeight: window.innerHeight - top - 16 });
56
+ }, children: _jsx(Info, { "aria-hidden": "true", className: "h-3 w-3" }) }) }), _jsxs(DialogContent, { ref: contentRef, className: "w-[calc(100vw-2rem)] max-w-xs overflow-y-auto p-4", onEscapeKeyDown: () => triggerRef.current?.focus(), onCloseAutoFocus: (event) => { if (outsideRef.current)
57
+ event.preventDefault(); }, style: { ...position, transform: 'none', animation: 'none' }, "aria-describedby": undefined, children: [_jsx(DialogTitle, { className: "pr-8 text-sm", children: "\u989D\u5EA6\u8BE6\u60C5" }), quota?.status === 'available' ? _jsx(QuotaDetails, { quota: quota })
58
+ : quota ? _jsxs("p", { className: "break-words text-xs text-muted-foreground", children: ["\u6765\u6E90\uFF1A", quota.source] }) : null] })] }));
59
+ }
60
+ function QuotaSummary({ quota }) {
61
+ return (_jsxs(_Fragment, { children: [typeof quota.balance === 'number' ? _jsxs("span", { children: ["\u4F59\u989D\uFF1A", quota.balance] }) : null, quota.windows.map((window, index) => _jsxs("span", { children: [quotaWindowLabel(window.name), " \u00B7 ", remainingLabel(window)] }, index)), typeof quota.balance !== 'number' && quota.windows.length === 0 ? _jsx("span", { children: "\u670D\u52A1\u5546\u672A\u8FD4\u56DE\u989D\u5EA6\u6570\u636E" }) : null] }));
62
+ }
63
+ function QuotaDetails({ quota, hideBalance = false }) {
64
+ return (_jsxs("div", { className: "space-y-3 text-sm", children: [!hideBalance && typeof quota.balance === 'number' ? _jsxs("div", { children: ["\u4F59\u989D\uFF1A", quota.balance] }) : null, quota.windows.map((window, index) => (_jsxs("div", { className: "space-y-1.5", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("span", { className: "font-medium text-foreground", children: quotaWindowLabel(window.name) }), _jsx("span", { className: "text-muted-foreground", children: remainingLabel(window) })] }), remainingPercent(window) !== undefined ? (_jsx("div", { "aria-label": `${quotaWindowLabel(window.name)}剩余 ${String(remainingPercent(window))}%`, className: "h-1.5 overflow-hidden rounded-full bg-muted", role: "progressbar", "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": remainingPercent(window), children: _jsx("div", { className: "h-full rounded-full bg-primary", style: { width: `${String(remainingPercent(window))}%` } }) })) : null, window.resetsAt ? _jsxs("p", { className: "text-xs text-muted-foreground", children: ["\u91CD\u7F6E\uFF1A", formatTimestamp(window.resetsAt)] }) : null] }, `${String(window.name)}-${index}`))), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["\u66F4\u65B0\uFF1A", formatTimestamp(quota.observedAt)] }), _jsxs("p", { className: "break-words text-xs text-muted-foreground", children: ["\u6765\u6E90\uFF1A", quota.source, quota.stale ? ' · 数据可能已过期' : ''] })] }));
6
65
  }
7
66
  function quotaWindowLabel(name) {
8
67
  switch (name) {
@@ -1,7 +1,7 @@
1
1
  import type { AiConnectionsModelSelection, AiConnectionsOAuthCredential } from '@undefineds.co/extension-sdk/web';
2
2
  export declare const AI_CONNECTIONS_PROVIDERS: readonly ["openai", "anthropic", "kimi", "bailian", "deepseek", "zhipu", "ollama", "custom"];
3
3
  export type AiConnectionsProvider = (typeof AI_CONNECTIONS_PROVIDERS)[number];
4
- export type AiConnectionsMode = 'browserAssistedApiKey' | 'deviceCodeOAuth' | 'connectUnsupported';
4
+ export type AiConnectionsMode = 'browserAssistedApiKey' | 'deviceCodeOAuth' | 'authorizationCodeOAuth' | 'connectUnsupported';
5
5
  export type AiConnectStatus = 'pending' | 'authorization_pending' | 'slow_down' | 'completed' | 'expired' | 'cancelled' | 'unsupported';
6
6
  export interface AiConnectAttempt {
7
7
  mode: AiConnectionsMode;
@@ -18,6 +18,8 @@ export interface AiConnectAttempt {
18
18
  intervalSeconds?: number;
19
19
  apiKeyManagementSupported?: boolean;
20
20
  credentialId?: string;
21
+ offeringId?: string;
22
+ authorizationMethodId?: string;
21
23
  oauthCredential?: AiConnectionsOAuthCredential;
22
24
  message?: string;
23
25
  }
@@ -53,6 +55,9 @@ export interface AiQuotaSnapshot {
53
55
  }
54
56
  export interface GatewayKeyRecord {
55
57
  id: string;
58
+ kind?: 'client-credentials';
59
+ credentialResource?: string;
60
+ fingerprint?: string;
56
61
  owner: string;
57
62
  scopes: string[];
58
63
  createdAt: string;
@@ -95,18 +100,40 @@ export interface CustomProviderModel {
95
100
  capabilities?: string[];
96
101
  }
97
102
  export interface ProviderModelDiscovery {
103
+ /** False when some service scopes failed; retain their previous catalog. */
104
+ complete?: boolean;
98
105
  provider: AiConnectionsProvider;
99
106
  credential: string;
100
107
  models: DiscoveredProviderModel[];
101
108
  observedAt: string;
102
109
  source: string;
103
110
  }
111
+ export type AiProviderAuthorizationMethodId = 'device-code' | 'local-session-import' | 'api-key' | 'local-service' | string;
112
+ export interface AiProviderAuthorizationMethod {
113
+ id: AiProviderAuthorizationMethodId;
114
+ authMode: 'oauth' | 'deviceCode' | 'local' | 'apiKey';
115
+ connectMode?: AiConnectionsMode;
116
+ label: string;
117
+ lifecycle: 'active' | 'unavailable';
118
+ reason?: string;
119
+ }
120
+ export interface AiProviderAuthorizationMethodsSummary {
121
+ provider: AiConnectionsProvider;
122
+ offeringId: string;
123
+ endpoints?: AiProviderOffering['endpoints'];
124
+ authorizationMethods: AiProviderAuthorizationMethod[];
125
+ }
126
+ export interface AiConnectionBeginOptions {
127
+ offeringId?: string;
128
+ authorizationMethodId?: string;
129
+ }
104
130
  export interface AiProviderOffering {
105
131
  id: string;
106
132
  label?: string;
107
133
  kind?: 'oauth-subscription' | 'api-platform' | 'token-plan' | 'local';
108
134
  lifecycle?: 'active' | 'legacy' | 'unavailable';
109
135
  authModes?: Array<'oauth' | 'deviceCode' | 'apiKey' | 'local'>;
136
+ authorizationMethods?: AiProviderAuthorizationMethod[];
110
137
  runtimeProviderIds?: string[];
111
138
  productLabel?: string;
112
139
  credentialPrefixHints?: string[];
@@ -196,10 +223,15 @@ export interface AiConnectionsClient {
196
223
  readonly apiBase: string;
197
224
  getServiceAccess(): Promise<unknown>;
198
225
  listProviders(): Promise<AiProviderSummary[]>;
226
+ listAuthorizationMethods?(): Promise<AiProviderAuthorizationMethodsSummary[]>;
199
227
  listModels(): Promise<AiGatewayModel[]>;
228
+ /** Active Gateway routing projection, independent of a host's Pod catalog. */
229
+ listGatewayModels?(): Promise<AiGatewayModel[]>;
200
230
  listGatewayKeys(): Promise<GatewayKeyRecord[]>;
201
231
  createGatewayKey(input: {
202
232
  name: string;
233
+ apiKey?: string;
234
+ credentialResource?: string;
203
235
  appliedClient?: string;
204
236
  scopes?: string[];
205
237
  expiresAt?: string;
@@ -209,14 +241,16 @@ export interface AiConnectionsClient {
209
241
  enabled: boolean;
210
242
  }): Promise<GatewayKeyRecord>;
211
243
  deleteGatewayKey(keyId: string): Promise<void>;
212
- beginConnect(provider: AiConnectionsProvider, mode: AiConnectionsMode): Promise<AiConnectAttempt>;
213
- connectStatus(provider: AiConnectionsProvider, attempt: Pick<AiConnectAttempt, 'attemptId' | 'state' | 'signature'>): Promise<AiConnectAttempt>;
214
- completeApiKey(provider: AiConnectionsProvider, attempt: Pick<AiConnectAttempt, 'attemptId' | 'state' | 'signature'>, apiKey: string, accountLabel?: string, baseUrl?: string): Promise<AiConnectAttempt>;
215
- pollDevice(provider: AiConnectionsProvider, attempt: Pick<AiConnectAttempt, 'attemptId' | 'state' | 'signature'>): Promise<AiConnectAttempt>;
216
- refreshOAuthCredential(provider: AiConnectionsProvider, credentialId: string, refreshToken: string, expectedVersion: number): Promise<AiConnectAttempt>;
244
+ beginConnect(provider: AiConnectionsProvider, mode: AiConnectionsMode, options?: AiConnectionBeginOptions): Promise<AiConnectAttempt>;
245
+ connectStatus(provider: AiConnectionsProvider, attempt: Pick<AiConnectAttempt, 'attemptId' | 'state' | 'signature' | 'offeringId'> & Partial<Pick<AiConnectAttempt, 'mode'>>): Promise<AiConnectAttempt>;
246
+ completeApiKey(provider: AiConnectionsProvider, attempt: Pick<AiConnectAttempt, 'attemptId' | 'state' | 'signature' | 'offeringId'> & Partial<Pick<AiConnectAttempt, 'mode'>>, apiKey: string, accountLabel?: string, baseUrl?: string): Promise<AiConnectAttempt>;
247
+ pollDevice(provider: AiConnectionsProvider, attempt: Pick<AiConnectAttempt, 'attemptId' | 'state' | 'signature' | 'offeringId'> & Partial<Pick<AiConnectAttempt, 'mode'>>): Promise<AiConnectAttempt>;
248
+ cancelConnect?(provider: AiConnectionsProvider, attempt: Pick<AiConnectAttempt, 'attemptId' | 'state' | 'signature' | 'offeringId'> & Partial<Pick<AiConnectAttempt, 'mode'>>): Promise<AiConnectAttempt>;
249
+ refreshOAuthCredential(provider: AiConnectionsProvider, credentialId: string, refreshToken: string, expectedVersion: number, offeringId?: string, mode?: AiConnectionsMode): Promise<AiConnectAttempt>;
217
250
  disconnect(provider: AiConnectionsProvider, credentialId?: string): Promise<AiConnectionsCredential | undefined>;
218
251
  createApiKeyCredential(provider: AiConnectionsProvider, input: CreateApiKeyCredentialInput): Promise<AiProviderCredentialSummary>;
219
252
  createLocalCredential(provider: AiConnectionsProvider, input: {
253
+ authorizationMethodId?: string;
220
254
  offeringId?: string;
221
255
  label?: string;
222
256
  baseUrl?: string;
@@ -269,8 +303,14 @@ interface CreateAiConnectionsClientInput {
269
303
  }
270
304
  export declare function resolveAiConnectionsApiBase(podBaseUrl: string): string;
271
305
  export declare function createAiConnectionsClient({ webId, podBaseUrl, authenticatedFetch, }: CreateAiConnectionsClientInput): AiConnectionsClient;
306
+ export declare class AiConnectionsRequestError extends Error {
307
+ readonly code?: string;
308
+ readonly providerStatus?: number;
309
+ constructor(message: string, payload: unknown);
310
+ }
272
311
  export declare function normalizeAiConnectionsThrownError(error: unknown): string;
273
312
  export declare function normalizeAiConnectionsErrorMessage(payload: unknown, status: number, context?: {
274
313
  provider?: AiConnectionsProvider;
314
+ authMode?: 'apiKey' | 'deviceCodeOAuth' | 'local';
275
315
  }): string;
276
316
  export {};