@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
@@ -71,7 +71,7 @@ export function createAiConnectionsClient({ webId, podBaseUrl, authenticatedFetc
71
71
  });
72
72
  const payload = await readJson(response);
73
73
  if (!response.ok) {
74
- throw new Error(normalizeAiConnectionsErrorMessage(payload, response.status, context));
74
+ throw new AiConnectionsRequestError(normalizeAiConnectionsErrorMessage(payload, response.status, context), payload);
75
75
  }
76
76
  return payload;
77
77
  };
@@ -83,6 +83,12 @@ export function createAiConnectionsClient({ webId, podBaseUrl, authenticatedFetc
83
83
  const payload = await request(`${providerPath(provider)}${path}`, method, body, { provider });
84
84
  return parseConnectAttempt(payload, provider);
85
85
  };
86
+ const listGatewayModels = async () => {
87
+ const payload = await request('/v1/models', 'GET');
88
+ return Array.isArray(payload.data)
89
+ ? payload.data.map(parseGatewayModel).filter(isDefined)
90
+ : [];
91
+ };
86
92
  return {
87
93
  webId,
88
94
  apiBase,
@@ -93,12 +99,25 @@ export function createAiConnectionsClient({ webId, podBaseUrl, authenticatedFetc
93
99
  const payload = await request('/api/ai/providers', 'GET');
94
100
  return Array.isArray(payload.data) ? parseProviderSummaries(payload.data) : [];
95
101
  },
96
- async listModels() {
97
- const payload = await request('/v1/models', 'GET');
98
- return Array.isArray(payload.data)
99
- ? payload.data.map(parseGatewayModel).filter(isDefined)
102
+ async listAuthorizationMethods() {
103
+ const response = await authenticatedFetch(`${apiBase}/api/ai/connections/authorization-methods`, {
104
+ method: 'GET',
105
+ credentials: 'omit',
106
+ mode: 'cors',
107
+ headers: { accept: 'application/json' },
108
+ });
109
+ if (response.status === 404)
110
+ return [];
111
+ const payload = await readJson(response);
112
+ if (!response.ok) {
113
+ throw new Error(normalizeAiConnectionsErrorMessage(payload, response.status));
114
+ }
115
+ return isRecord(payload) && Array.isArray(payload.data)
116
+ ? payload.data.map(parseAuthorizationMethodsSummary).filter(isDefined)
100
117
  : [];
101
118
  },
119
+ listModels: listGatewayModels,
120
+ listGatewayModels,
102
121
  async listGatewayKeys() {
103
122
  const payload = await request('/api/ai/gateway/keys', 'GET');
104
123
  return Array.isArray(payload.data)
@@ -132,8 +151,12 @@ export function createAiConnectionsClient({ webId, podBaseUrl, authenticatedFetc
132
151
  async deleteGatewayKey(keyId) {
133
152
  await request(`/api/ai/gateway/keys/${encodeURIComponent(keyId)}`, 'DELETE');
134
153
  },
135
- async beginConnect(provider, mode) {
136
- return await requestConnect(provider, '/connect/begin', 'POST', { mode });
154
+ async beginConnect(provider, mode, options) {
155
+ return await requestConnect(provider, '/connect/begin', 'POST', compactObject({
156
+ mode,
157
+ offeringId: options?.offeringId,
158
+ authorizationMethodId: options?.authorizationMethodId,
159
+ }));
137
160
  },
138
161
  connectStatus(provider, attempt) {
139
162
  if (!attempt.attemptId) {
@@ -143,6 +166,8 @@ export function createAiConnectionsClient({ webId, podBaseUrl, authenticatedFetc
143
166
  state: attempt.state ?? '',
144
167
  signature: attempt.signature ?? '',
145
168
  });
169
+ if (attempt.mode)
170
+ query.set('mode', attempt.mode);
146
171
  return requestConnect(provider, `/connect/status/${encodeURIComponent(attempt.attemptId)}?${query}`, 'GET');
147
172
  },
148
173
  completeApiKey(provider, attempt, apiKey, accountLabel, baseUrl) {
@@ -150,6 +175,7 @@ export function createAiConnectionsClient({ webId, podBaseUrl, authenticatedFetc
150
175
  attemptId: attempt.attemptId,
151
176
  state: attempt.state,
152
177
  signature: attempt.signature,
178
+ offeringId: attempt.offeringId,
153
179
  apiKey,
154
180
  accountLabel,
155
181
  baseUrl,
@@ -157,16 +183,29 @@ export function createAiConnectionsClient({ webId, podBaseUrl, authenticatedFetc
157
183
  },
158
184
  pollDevice(provider, attempt) {
159
185
  return requestConnect(provider, '/connect/poll', 'POST', compactObject({
186
+ mode: attempt.mode,
160
187
  attemptId: attempt.attemptId,
161
188
  state: attempt.state,
162
189
  signature: attempt.signature,
190
+ offeringId: attempt.offeringId,
163
191
  }));
164
192
  },
165
- refreshOAuthCredential(provider, credentialId, refreshToken, expectedVersion) {
193
+ cancelConnect(provider, attempt) {
194
+ return requestConnect(provider, '/connect/cancel', 'POST', compactObject({
195
+ mode: attempt.mode,
196
+ attemptId: attempt.attemptId,
197
+ state: attempt.state,
198
+ signature: attempt.signature,
199
+ offeringId: attempt.offeringId,
200
+ }));
201
+ },
202
+ refreshOAuthCredential(provider, credentialId, refreshToken, expectedVersion, offeringId, mode) {
166
203
  return requestConnect(provider, '/connect/refresh', 'POST', {
167
204
  credentialId,
168
205
  refreshToken,
169
206
  expectedVersion,
207
+ ...(offeringId ? { offeringId } : {}),
208
+ ...(mode ? { mode } : {}),
170
209
  });
171
210
  },
172
211
  async disconnect(provider, credentialId) {
@@ -217,7 +256,7 @@ export function createAiConnectionsClient({ webId, podBaseUrl, authenticatedFetc
217
256
  return request(`${providerPath(provider)}/quota/refresh`, 'POST', compactObject(input), { provider });
218
257
  },
219
258
  async discoverModels(provider, input) {
220
- const payload = await request(`${providerPath(provider)}/models/refresh`, 'POST', compactObject({ ...input }), { provider });
259
+ const payload = await request(`${providerPath(provider)}/models/refresh`, 'POST', compactObject({ ...input }), { provider, authMode: input?.authMode });
221
260
  return parseModelDiscovery(payload, provider);
222
261
  },
223
262
  async saveProviderModel(provider, model) {
@@ -236,6 +275,15 @@ export function createAiConnectionsClient({ webId, podBaseUrl, authenticatedFetc
236
275
  },
237
276
  };
238
277
  }
278
+ export class AiConnectionsRequestError extends Error {
279
+ constructor(message, payload) {
280
+ super(message);
281
+ this.name = 'AiConnectionsRequestError';
282
+ this.code = errorCodeFromPayload(payload);
283
+ this.providerStatus = isRecord(payload) && typeof payload.providerStatus === 'number'
284
+ ? payload.providerStatus : undefined;
285
+ }
286
+ }
239
287
  export function normalizeAiConnectionsThrownError(error) {
240
288
  if (error instanceof Error) {
241
289
  return normalizeAiConnectionsErrorText(error.message);
@@ -259,7 +307,7 @@ export function normalizeAiConnectionsErrorMessage(payload, status, context = {}
259
307
  const providerMessage = isRecord(payload) && typeof payload.providerMessage === 'string'
260
308
  ? payload.providerMessage.trim()
261
309
  : undefined;
262
- return withProviderMessage(modelDiscoveryErrorMessage(providerStatus), providerMessage);
310
+ return withProviderMessage(modelDiscoveryErrorMessage(providerStatus, context.authMode), providerMessage);
263
311
  }
264
312
  const coded = code ? messageForSafeErrorCode(code, context.provider) : undefined;
265
313
  if (coded)
@@ -294,7 +342,13 @@ export function normalizeAiConnectionsErrorMessage(payload, status, context = {}
294
342
  return 'AI Connection service is unavailable.';
295
343
  return AI_CONNECTIONS_GENERIC_ERROR_MESSAGE;
296
344
  }
345
+ const LOCAL_SESSION_REFRESH_FAILED_MESSAGE = '订阅登录态自动刷新失败,请稍后重试。';
346
+ const LOCAL_SESSION_REAUTH_REQUIRED_MESSAGE = '订阅登录态已失效,请在原客户端重新登录后重读,或使用设备码登录。';
347
+ const OAUTH_MODEL_AUTH_FAILED_MESSAGE = '订阅登录态不可用,请重读登录态或重新登录后再同步模型。';
297
348
  const MODEL_DISCOVERY_SAFE_MESSAGES = new Set([
349
+ OAUTH_MODEL_AUTH_FAILED_MESSAGE,
350
+ LOCAL_SESSION_REFRESH_FAILED_MESSAGE,
351
+ LOCAL_SESSION_REAUTH_REQUIRED_MESSAGE,
298
352
  '密钥不可用。请检查密钥是否填写正确,或换一个密钥后重试。',
299
353
  '模型服务地址不正确。请检查服务地址后重试。',
300
354
  '请求太频繁。请稍等一会儿再试。',
@@ -361,6 +415,17 @@ function messageForSafeErrorCode(code, provider) {
361
415
  return '该服务地址指向 Xpod 不允许访问的网络,请改用公网 HTTPS 地址。';
362
416
  case 'invalid_proxy_url':
363
417
  return '代理地址必须是无账号密码的 HTTP 或 HTTPS 地址。';
418
+ case 'oauth_refresh_failed':
419
+ case 'oauth_refresh_unavailable':
420
+ case 'local_session_refresh_failed':
421
+ return LOCAL_SESSION_REFRESH_FAILED_MESSAGE;
422
+ case 'oauth_session_reauth_required':
423
+ case 'oauth_refresh_token_required':
424
+ case 'local_session_reauth_required':
425
+ case 'local_session_missing_refresh_token':
426
+ return LOCAL_SESSION_REAUTH_REQUIRED_MESSAGE;
427
+ case 'models_persistence_failed':
428
+ return '模型已获取,但保存到 Pod 失败。请重试同步模型。';
364
429
  case 'quota_credential_not_found':
365
430
  return '当前身份没有可用的额度凭证。';
366
431
  case 'credential_secret_unavailable':
@@ -373,8 +438,10 @@ function messageForSafeErrorCode(code, provider) {
373
438
  return undefined;
374
439
  }
375
440
  }
376
- function modelDiscoveryErrorMessage(providerStatus) {
441
+ function modelDiscoveryErrorMessage(providerStatus, authMode) {
377
442
  if (providerStatus === 401 || providerStatus === 403) {
443
+ if (authMode === 'deviceCodeOAuth')
444
+ return OAUTH_MODEL_AUTH_FAILED_MESSAGE;
378
445
  return '密钥不可用。请检查密钥是否填写正确,或换一个密钥后重试。';
379
446
  }
380
447
  if (providerStatus === 404) {
@@ -450,6 +517,9 @@ function parseGatewayKeyRecord(value) {
450
517
  }
451
518
  return compactObject({
452
519
  id: value.id,
520
+ kind: value.kind === 'client-credentials' ? value.kind : undefined,
521
+ credentialResource: stringValue(value.credentialResource),
522
+ fingerprint: stringValue(value.fingerprint),
453
523
  owner: value.owner,
454
524
  scopes: value.scopes,
455
525
  createdAt: value.createdAt,
@@ -498,6 +568,7 @@ function parseGatewayModel(value) {
498
568
  ?? providerFromModelId(value.id);
499
569
  if (!provider)
500
570
  return undefined;
571
+ const imageInput = isRecord(value.capabilities) ? value.capabilities.imageInput : undefined;
501
572
  return compactObject({
502
573
  id: value.id,
503
574
  provider,
@@ -509,7 +580,8 @@ function parseGatewayModel(value) {
509
580
  ? value.protocols.filter((protocol) => typeof protocol === 'string')
510
581
  : undefined,
511
582
  custom: value.custom === true ? true : undefined,
512
- inputModalities: modalitiesFromWire(value.modalities, 'input'),
583
+ inputModalities: modalitiesFromWire(value.modalities, 'input')
584
+ ?? (imageInput === true ? ['text', 'image'] : imageInput === false ? ['text'] : undefined),
513
585
  outputModalities: modalitiesFromWire(value.modalities, 'output'),
514
586
  capabilities: modelCapabilitiesFromWire(value),
515
587
  });
@@ -633,6 +705,7 @@ function parseProviderOffering(value) {
633
705
  kind: stringValue(value.kind),
634
706
  lifecycle: offeringLifecycleValue(value.lifecycle),
635
707
  authModes,
708
+ authorizationMethods: arrayValue(value.authorizationMethods, parseAuthorizationMethod),
636
709
  runtimeProviderIds: stringListValue(value.runtimeProviderIds),
637
710
  productLabel: stringValue(value.productLabel),
638
711
  credentialPrefixHints: stringListValue(value.credentialPrefixHints),
@@ -645,6 +718,53 @@ function parseProviderOffering(value) {
645
718
  region: stringValue(value.region),
646
719
  });
647
720
  }
721
+ function parseAuthorizationMethodsSummary(value) {
722
+ if (!isRecord(value) || typeof value.offeringId !== 'string' || !value.offeringId)
723
+ return undefined;
724
+ const provider = providerValue(value.provider);
725
+ if (!provider)
726
+ return undefined;
727
+ const authorizationMethods = arrayValue(value.authorizationMethods, parseAuthorizationMethod);
728
+ return {
729
+ provider,
730
+ offeringId: value.offeringId,
731
+ ...(Array.isArray(value.endpoints) ? { endpoints: arrayValue(value.endpoints, parseOfferingEndpoint) } : {}),
732
+ authorizationMethods,
733
+ };
734
+ }
735
+ function parseAuthorizationMethod(value) {
736
+ if (!isRecord(value) || typeof value.id !== 'string' || !value.id)
737
+ return undefined;
738
+ const authMode = offeringAuthModeValue(value.authMode);
739
+ const lifecycle = authorizationMethodLifecycleValue(value.lifecycle);
740
+ if (!authMode || !lifecycle)
741
+ return undefined;
742
+ const connectMode = isConnectMode(value.connectMode) ? value.connectMode : undefined;
743
+ return compactObject({
744
+ id: value.id,
745
+ authMode,
746
+ connectMode,
747
+ label: stringValue(value.label) ?? authorizationMethodFallbackLabel(value.id, authMode),
748
+ lifecycle,
749
+ reason: stringValue(value.reason),
750
+ });
751
+ }
752
+ function authorizationMethodLifecycleValue(value) {
753
+ return value === 'active' || value === 'unavailable' ? value : undefined;
754
+ }
755
+ function authorizationMethodFallbackLabel(id, authMode) {
756
+ if (id === 'device-code')
757
+ return '浏览器登录';
758
+ if (id === 'local-session-import')
759
+ return '已有登录态';
760
+ if (id === 'local-service')
761
+ return '本地服务';
762
+ if (id === 'api-key' || authMode === 'apiKey')
763
+ return 'API Key';
764
+ if (authMode === 'local')
765
+ return '本地服务';
766
+ return '浏览器登录';
767
+ }
648
768
  function offeringLifecycleValue(value) {
649
769
  return value === 'active' || value === 'legacy' || value === 'unavailable'
650
770
  ? value
@@ -769,7 +889,7 @@ function legacyCredentialFromSummary(value, provider) {
769
889
  const authMode = legacyCredentialAuthMode(value.authMode);
770
890
  return compactObject({
771
891
  id: stringValue(value.credentialIri) ?? `${provider}:current`,
772
- offeringId: legacyOfferingId(authMode),
892
+ offeringId: legacyOfferingId(provider, authMode),
773
893
  authMode,
774
894
  label: stringValue(value.accountLabel),
775
895
  enabled: value.status === 'connected',
@@ -789,7 +909,9 @@ function legacyCredentialAuthMode(value) {
789
909
  return 'deviceCode';
790
910
  return 'apiKey';
791
911
  }
792
- function legacyOfferingId(authMode) {
912
+ function legacyOfferingId(provider, authMode) {
913
+ if (provider === 'kimi' && (authMode === 'deviceCode' || authMode === 'oauth'))
914
+ return 'subscription-key';
793
915
  return authMode === 'deviceCode' || authMode === 'oauth'
794
916
  ? 'official-subscription'
795
917
  : 'api-platform';
@@ -895,6 +1017,8 @@ function parseConnectAttempt(value, expectedProvider) {
895
1017
  ? value.apiKeyManagementSupported
896
1018
  : undefined,
897
1019
  credentialId: stringValue(value.credentialId),
1020
+ offeringId: stringValue(value.offeringId),
1021
+ authorizationMethodId: stringValue(value.authorizationMethodId),
898
1022
  oauthCredential: parseOAuthCredential(value.oauthCredential),
899
1023
  message: stringValue(value.message),
900
1024
  });
@@ -916,6 +1040,10 @@ function parseOAuthCredential(value) {
916
1040
  scope: stringValue(value.scope),
917
1041
  idToken: stringValue(value.idToken),
918
1042
  accountSubject: stringValue(value.accountSubject),
1043
+ accountId: stringValue(value.accountId),
1044
+ accountLabel: stringValue(value.accountLabel),
1045
+ offeringId: stringValue(value.offeringId),
1046
+ authorizationMethodId: stringValue(value.authorizationMethodId),
919
1047
  expectedVersion: typeof value.expectedVersion === 'number' ? value.expectedVersion : undefined,
920
1048
  });
921
1049
  }
@@ -964,6 +1092,7 @@ function safeHttpUrl(value) {
964
1092
  function isConnectMode(value) {
965
1093
  return value === 'browserAssistedApiKey'
966
1094
  || value === 'deviceCodeOAuth'
1095
+ || value === 'authorizationCodeOAuth'
967
1096
  || value === 'connectUnsupported';
968
1097
  }
969
1098
  function isConnectStatus(value) {
@@ -5,7 +5,21 @@ export declare class AiClientConfigError extends Error {
5
5
  readonly code: 'model_catalog_empty' | 'model_catalog_invalid' | 'model_not_available';
6
6
  constructor(code: 'model_catalog_empty' | 'model_catalog_invalid' | 'model_not_available', message?: string);
7
7
  }
8
+ interface OwnershipState {
9
+ version: 1;
10
+ client: string;
11
+ webIdHash: string;
12
+ apiKeyFingerprint?: string;
13
+ projectionHashes?: Record<string, string>;
14
+ files: Array<{
15
+ path: string;
16
+ existed: boolean;
17
+ backupPath?: string;
18
+ }>;
19
+ }
8
20
  export declare function hashWebId(webId: string): string;
21
+ declare function contentHash(value: string): string;
22
+ export declare const contentFingerprint: typeof contentHash;
9
23
  export declare function normalizeV1Endpoint(endpoint: string): string;
10
24
  export declare function normalizeMessagesEndpoint(endpoint: string): string;
11
25
  export declare function parseJsonObject(content: string | undefined, label: string): Record<string, unknown>;
@@ -26,7 +40,7 @@ export declare function activeModelReferences(profile: AiConnectionsClientProfil
26
40
  id: string;
27
41
  name: string;
28
42
  }>;
29
- /** Apply catalog validation once at the shared adapter boundary. */
43
+ /** Use supplied model metadata when available; file projection does not require discovery. */
30
44
  export declare function normalizeClientProfile(profile: AiConnectionsClientProfile): AiConnectionsClientProfile;
31
45
  export declare function stripLegacyXpodObject(value: Record<string, unknown>): void;
32
46
  export declare abstract class BaseAiClientConfigAdapter implements AiClientConfigAdapter {
@@ -46,10 +60,12 @@ export declare abstract class BaseAiClientConfigAdapter implements AiClientConfi
46
60
  protected abstract verifyProjection(profile: AiConnectionsClientProfile): Promise<ClientVerification>;
47
61
  protected abstract restoreFile(filePath: string, current: string | undefined, original: string | undefined, originallyExisted: boolean): Promise<string | null>;
48
62
  protected normalizeProfile(profile: AiConnectionsClientProfile): AiConnectionsClientProfile;
63
+ protected currentApiKeyFingerprint(_current: Map<string, string | undefined>): Promise<string | undefined>;
49
64
  protected readOptional(filePath: string): Promise<string | undefined>;
50
65
  private validateProfile;
51
- private readState;
52
- private rejectSymlink;
66
+ protected readState(): Promise<OwnershipState | undefined>;
67
+ protected rejectSymlink(filePath: string): Promise<void>;
53
68
  private exists;
54
69
  private isExecutableOnPath;
55
70
  }
71
+ export {};
@@ -13,6 +13,10 @@ export class AiClientConfigError extends Error {
13
13
  export function hashWebId(webId) {
14
14
  return crypto.createHash('sha256').update(webId.trim(), 'utf8').digest('hex');
15
15
  }
16
+ function contentHash(value) {
17
+ return crypto.createHash('sha256').update(value, 'utf8').digest('hex');
18
+ }
19
+ export const contentFingerprint = contentHash;
16
20
  export function normalizeV1Endpoint(endpoint) {
17
21
  const normalized = endpoint.trim().replace(/\/+$/, '');
18
22
  return normalized.endsWith('/v1') ? normalized : `${normalized}/v1`;
@@ -114,11 +118,11 @@ function normalizeActiveModels(models) {
114
118
  }
115
119
  return normalized;
116
120
  }
117
- /** Apply catalog validation once at the shared adapter boundary. */
121
+ /** Use supplied model metadata when available; file projection does not require discovery. */
118
122
  export function normalizeClientProfile(profile) {
119
123
  return {
120
124
  ...profile,
121
- model: resolveActiveModel(profile),
125
+ model: profile.activeModels?.length ? resolveActiveModel(profile) : profile.model?.trim() || undefined,
122
126
  };
123
127
  }
124
128
  export function stripLegacyXpodObject(value) {
@@ -144,9 +148,23 @@ export class BaseAiClientConfigAdapter {
144
148
  }
145
149
  async inspect() {
146
150
  const state = await this.readState();
151
+ let projectionMatches;
152
+ if (state?.projectionHashes) {
153
+ projectionMatches = true;
154
+ for (const filePath of this.configPaths) {
155
+ await this.rejectSymlink(filePath);
156
+ const content = await this.readOptional(filePath);
157
+ if (content === undefined || contentHash(content) !== state.projectionHashes[filePath]) {
158
+ projectionMatches = false;
159
+ }
160
+ }
161
+ }
147
162
  return {
148
163
  ownership: state ? 'owned' : 'unowned',
149
164
  ...(state ? { webIdHash: state.webIdHash } : {}),
165
+ ...(projectionMatches === undefined ? {} : { projectionMatches }),
166
+ ...(projectionMatches && /^[a-f0-9]{64}$/u.test(state?.apiKeyFingerprint ?? '')
167
+ ? { apiKeyFingerprint: state.apiKeyFingerprint } : {}),
150
168
  configPaths: [...this.configPaths],
151
169
  };
152
170
  }
@@ -163,8 +181,14 @@ export class BaseAiClientConfigAdapter {
163
181
  contents.set(filePath, await this.readOptional(filePath));
164
182
  }
165
183
  const projected = await this.project(normalizedProfile, contents);
184
+ for (const filePath of projected.keys()) {
185
+ if (!contents.has(filePath)) {
186
+ await this.rejectSymlink(filePath);
187
+ contents.set(filePath, await this.readOptional(filePath));
188
+ }
189
+ }
166
190
  const timestamp = Date.now();
167
- const files = this.configPaths.map((filePath) => {
191
+ const files = [...projected.keys()].map((filePath) => {
168
192
  const prior = currentState?.files.find((file) => file.path === filePath);
169
193
  const existed = contents.get(filePath) !== undefined;
170
194
  return prior ?? {
@@ -177,12 +201,14 @@ export class BaseAiClientConfigAdapter {
177
201
  path: filePath,
178
202
  content,
179
203
  backupPath: files.find((file) => file.path === filePath)?.backupPath,
180
- createBackup: !currentState && contents.get(filePath) !== undefined,
204
+ createBackup: !currentState?.files.some((file) => file.path === filePath) && contents.get(filePath) !== undefined,
181
205
  }));
182
206
  const state = {
183
207
  version: 1,
184
208
  client: this.client,
185
209
  webIdHash: ownerHash,
210
+ apiKeyFingerprint: contentHash(profileApiKey(normalizedProfile)),
211
+ projectionHashes: Object.fromEntries([...projected].map(([filePath, content]) => [filePath, contentHash(content)])),
186
212
  files,
187
213
  };
188
214
  writes.push({ path: this.statePath, content: stringifyJson(state) });
@@ -209,10 +235,19 @@ export class BaseAiClientConfigAdapter {
209
235
  if (state.webIdHash !== hashWebId(webId)) {
210
236
  throw new Error(`${this.client} AI Connection projection is owned by another WebID`);
211
237
  }
212
- const writes = [];
238
+ const current = new Map();
213
239
  for (const file of state.files) {
214
240
  await this.rejectSymlink(file.path);
215
- const current = await this.readOptional(file.path);
241
+ current.set(file.path, await this.readOptional(file.path));
242
+ }
243
+ const currentFingerprint = await this.currentApiKeyFingerprint(current);
244
+ if (state.apiKeyFingerprint &&
245
+ currentFingerprint &&
246
+ currentFingerprint !== state.apiKeyFingerprint) {
247
+ throw new Error(`${this.client} API key changed since projection was applied; refusing restore to avoid data loss`);
248
+ }
249
+ const writes = [];
250
+ for (const file of state.files) {
216
251
  let original;
217
252
  if (file.existed) {
218
253
  if (!file.backupPath) {
@@ -226,7 +261,7 @@ export class BaseAiClientConfigAdapter {
226
261
  }
227
262
  writes.push({
228
263
  path: file.path,
229
- content: await this.restoreFile(file.path, current, original, file.existed),
264
+ content: await this.restoreFile(file.path, current.get(file.path), original, file.existed),
230
265
  });
231
266
  }
232
267
  writes.push({ path: this.statePath, content: null });
@@ -235,6 +270,9 @@ export class BaseAiClientConfigAdapter {
235
270
  normalizeProfile(profile) {
236
271
  return normalizeClientProfile(profile);
237
272
  }
273
+ async currentApiKeyFingerprint(_current) {
274
+ return undefined;
275
+ }
238
276
  async readOptional(filePath) {
239
277
  try {
240
278
  return await fs.promises.readFile(filePath, 'utf8');
@@ -1,15 +1,21 @@
1
1
  import { BaseAiClientConfigAdapter } from './base-adapter';
2
- import type { AiConnectionsClientProfile, ClientVerification } from './types';
2
+ import type { AiClientConfigPlan, AiConnectionsClientProfile, ClientInspection, ClientVerification } from './types';
3
3
  export interface CodexConfigAdapterOptions {
4
4
  homeDir?: string;
5
5
  }
6
6
  export declare class CodexConfigAdapter extends BaseAiClientConfigAdapter {
7
7
  private readonly configPath;
8
8
  private readonly authPath;
9
+ private readonly catalogPath;
10
+ private readonly nativeModelsPath;
9
11
  constructor(options?: CodexConfigAdapterOptions);
10
12
  protected normalizeProfile(profile: AiConnectionsClientProfile): AiConnectionsClientProfile;
13
+ inspect(): Promise<ClientInspection>;
14
+ plan(profile: AiConnectionsClientProfile): Promise<AiClientConfigPlan>;
15
+ private ownsLegacyAuth;
11
16
  protected project(profile: AiConnectionsClientProfile, current: Map<string, string | undefined>): Promise<Map<string, string>>;
12
17
  protected verifyProjection(profile: AiConnectionsClientProfile): Promise<ClientVerification>;
13
18
  protected restoreFile(filePath: string, current: string | undefined, original: string | undefined, originallyExisted: boolean): Promise<string | null>;
19
+ protected currentApiKeyFingerprint(current: Map<string, string | undefined>): Promise<string | undefined>;
14
20
  private removeManagedBlock;
15
21
  }