@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.
- package/config/cloud.json +1 -1
- package/config/main.json +36 -2
- package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.d.ts +3 -0
- package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.js +1 -1
- package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.d.ts +2 -1
- package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.js +101 -32
- package/dist/api/ai-gateway/connect/DeviceCodeProtocol.d.ts +80 -0
- package/dist/api/ai-gateway/connect/DeviceCodeProtocol.js +3 -0
- package/dist/api/ai-gateway/connect/FileSessionImportAdapter.d.ts +38 -0
- package/dist/api/ai-gateway/connect/FileSessionImportAdapter.js +63 -0
- package/dist/api/ai-gateway/connect/LoopbackAuthorizationCallbackReceiver.d.ts +24 -0
- package/dist/api/ai-gateway/connect/LoopbackAuthorizationCallbackReceiver.js +136 -0
- package/dist/api/ai-gateway/connect/OAuthConnectAdapter.d.ts +2 -0
- package/dist/api/ai-gateway/connect/OAuthConnectAdapter.js +2 -1
- package/dist/api/ai-gateway/connect/OAuthIntegrationRegistry.d.ts +17 -13
- package/dist/api/ai-gateway/connect/OAuthIntegrationRegistry.js +52 -19
- package/dist/api/ai-gateway/connect/OpenAiSubscriptionSessionImportAdapter.d.ts +4 -28
- package/dist/api/ai-gateway/connect/OpenAiSubscriptionSessionImportAdapter.js +7 -58
- package/dist/api/ai-gateway/connect/ProviderAuthorizationProfiles.d.ts +4 -0
- package/dist/api/ai-gateway/connect/ProviderAuthorizationProfiles.js +116 -0
- package/dist/api/ai-gateway/connect/SessionImportProfiles.d.ts +10 -0
- package/dist/api/ai-gateway/connect/SessionImportProfiles.js +112 -0
- package/dist/api/ai-gateway/connect/index.d.ts +125 -23
- package/dist/api/ai-gateway/connect/index.js +1277 -260
- package/dist/api/ai-gateway/models/PodModelSelectionRepository.d.ts +4 -1
- package/dist/api/ai-gateway/models/PodModelSelectionRepository.js +154 -19
- package/dist/api/ai-gateway/providers/DeepSeekRuntimeAdapter.js +10 -6
- package/dist/api/ai-gateway/providers/ModelsDevCatalog.d.ts +7 -0
- package/dist/api/ai-gateway/providers/ModelsDevCatalog.js +25 -1
- package/dist/api/ai-gateway/providers/OfferingAuthorization.d.ts +24 -0
- package/dist/api/ai-gateway/providers/OfferingAuthorization.js +37 -0
- package/dist/api/ai-gateway/providers/OpenAiRuntimeAdapter.d.ts +1 -1
- package/dist/api/ai-gateway/providers/OpenAiRuntimeAdapter.js +5 -3
- package/dist/api/ai-gateway/providers/ProviderRegistry.d.ts +6 -3
- package/dist/api/ai-gateway/providers/ProviderRegistry.js +55 -16
- package/dist/api/ai-gateway/providers/ProviderRuntimeAdapter.d.ts +2 -0
- package/dist/api/ai-gateway/providers/ProviderRuntimeAdapter.js +37 -4
- package/dist/api/ai-gateway/providers/ProviderRuntimeRegistry.js +7 -0
- package/dist/api/ai-gateway/quota/SubscriptionQuotaAdapters.js +2 -1
- package/dist/api/ai-gateway/routing/ModelRouter.js +3 -1
- package/dist/api/container/common.js +30 -40
- package/dist/api/container/index.js +6 -2
- package/dist/api/container/routes.js +5 -22
- package/dist/api/handlers/AiClientConfigurationHandler.js +39 -1
- package/dist/api/handlers/AiGatewayManagementHandler.d.ts +3 -0
- package/dist/api/handlers/AiGatewayManagementHandler.js +173 -58
- package/dist/api/service/AiClientConfigurationService.d.ts +4 -15
- package/dist/api/service/AiClientConfigurationService.js +17 -64
- package/dist/cli/commands/start.js +2 -0
- package/dist/components/components.jsonld +1 -0
- package/dist/components/context.jsonld +80 -0
- package/dist/http/InternalPodDataHttpHandler.d.ts +3 -0
- package/dist/http/InternalPodDataHttpHandler.js +13 -2
- package/dist/http/InternalPodDataHttpHandler.jsonld +12 -0
- package/dist/identity/oidc/RememberedClientPromptFactory.d.ts +1 -1
- package/dist/identity/oidc/RememberedClientPromptFactory.js +5 -2
- package/dist/identity/oidc/RememberedConsentHandler.js +1 -1
- package/dist/identity/oidc/ScopedPickWebIdHandler.d.ts +1 -0
- package/dist/identity/oidc/ScopedPickWebIdHandler.js +26 -0
- package/dist/identity/oidc/ScopedPickWebIdHandler.jsonld +4 -0
- package/dist/identity/oidc/SessionBoundIdentityProviderFactory.d.ts +10 -0
- package/dist/identity/oidc/SessionBoundIdentityProviderFactory.js +21 -0
- package/dist/identity/oidc/SessionBoundIdentityProviderFactory.jsonld +172 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -2
- package/dist/runtime/component-parameter-keys.js +18 -2
- package/dist/storage/accessors/MixDataAccessor.js +6 -2
- package/dist/storage/rdf/PostgresRdfEngine.js +10 -2
- package/dist/storage/rdf/RdfContentTypes.js +4 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiClientConfigurationSection.d.ts +3 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiClientConfigurationSection.js +13 -16
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsList.js +1 -3
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsMain.d.ts +2 -1
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsMain.js +2 -2
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.d.ts +4 -1
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.js +127 -57
- package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialPoolSection.d.ts +6 -4
- package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialPoolSection.js +436 -83
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeysSection.d.ts +3 -2
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeysSection.js +212 -76
- package/node_modules/@undefineds.co/ai-connections/dist/AiProviderCard.d.ts +6 -4
- package/node_modules/@undefineds.co/ai-connections/dist/AiProviderCard.js +58 -41
- package/node_modules/@undefineds.co/ai-connections/dist/AiQuotaCard.d.ts +4 -1
- package/node_modules/@undefineds.co/ai-connections/dist/AiQuotaCard.js +63 -4
- package/node_modules/@undefineds.co/ai-connections/dist/ai-connections-client.d.ts +46 -6
- package/node_modules/@undefineds.co/ai-connections/dist/ai-connections-client.js +143 -14
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/base-adapter.d.ts +19 -3
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/base-adapter.js +45 -7
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/codex.d.ts +7 -1
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/codex.js +305 -40
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/index.cjs +383 -50
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/json-env-adapter.js +3 -2
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/pi.js +12 -3
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/transaction.d.ts +2 -0
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/transaction.js +39 -4
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/types.d.ts +8 -1
- package/node_modules/@undefineds.co/ai-connections/dist/client-visuals.d.ts +2 -0
- package/node_modules/@undefineds.co/ai-connections/dist/client-visuals.js +14 -0
- package/node_modules/@undefineds.co/ai-connections/dist/controller.d.ts +2 -2
- package/node_modules/@undefineds.co/ai-connections/dist/controller.js +216 -57
- package/node_modules/@undefineds.co/ai-connections/dist/index.d.ts +3 -1
- package/node_modules/@undefineds.co/ai-connections/dist/index.js +16 -2
- package/node_modules/@undefineds.co/ai-connections/dist/provider-visuals.js +6 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/execution/ldp-executor.js +27 -6
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/pod-database.js +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/select-query-builder.js +2 -2
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/sparql/builder/update-builder.js +12 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/triple/builder.js +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/triple/handlers/array.js +8 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/triple/handlers/default.js +9 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/triple/handlers/inline.js +3 -3
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/execution/ldp-executor.js +27 -6
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/pod-database.js +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/select-query-builder.js +2 -2
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/sparql/builder/update-builder.js +12 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/triple/builder.js +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/triple/handlers/array.js +8 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/triple/handlers/default.js +9 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/triple/handlers/inline.js +3 -3
- package/node_modules/@undefineds.co/extension-sdk/dist/web.d.ts +31 -0
- package/package.json +2 -2
- package/static/app/assets/{index-BikOyGPu.js → index-BCZVzMpj.js} +44 -44
- package/static/app/assets/inrupt-smoke.js +2 -2
- package/static/app/assets/main.css +1 -1
- package/static/app/assets/main.js +10 -10
- package/static/auth-callback/assets/{AiConfigContext-DrCH6ckh.js → AiConfigContext-DVkh8Kg2.js} +1 -1
- package/static/auth-callback/assets/{AiConfigPage-DVrlSSdA.js → AiConfigPage-HWVWpe-P.js} +1 -1
- package/static/auth-callback/assets/{DocumentProcessingPanel-_Md-v2R2.js → DocumentProcessingPanel-DDq-mH17.js} +1 -1
- package/static/auth-callback/assets/{IndexLifecyclePanel-BbWwe23H.js → IndexLifecyclePanel-Cx4cjrdP.js} +1 -1
- package/static/auth-callback/assets/{IndexSubjectPanel-upH9MjU-.js → IndexSubjectPanel-DzSw8M9j.js} +1 -1
- package/static/auth-callback/assets/{ModelAssignmentsPanel-CVGH4t4g.js → ModelAssignmentsPanel-BsRxGc2p.js} +1 -1
- package/static/auth-callback/assets/ModelsPage-DEe1lo6Q.js +10 -0
- package/static/auth-callback/assets/{NetworkPage-Dcbrb1fd.js → NetworkPage-DBiEh1Oz.js} +1 -1
- package/static/auth-callback/assets/{PaneListHeader-DrY-1wBq.js → PaneListHeader-lEEgjyN9.js} +1 -1
- package/static/auth-callback/assets/{SearchIndexingPanel-Dw25y53v.js → SearchIndexingPanel-CZCUUGt6.js} +1 -1
- package/static/auth-callback/assets/{StatusSubjectPanel-BHlz9rNF.js → StatusSubjectPanel-21qdueMr.js} +1 -1
- package/static/auth-callback/assets/{StatusWorkspace-BH7exQP5.js → StatusWorkspace-R8RKsqVz.js} +1 -1
- package/static/auth-callback/assets/{SystemSettingsPage-BYLKnM9f.js → SystemSettingsPage-BQ4e-4Wy.js} +1 -1
- package/static/auth-callback/assets/{SystemSettingsSubjectPanel-DT34LKku.js → SystemSettingsSubjectPanel-BopXD7SE.js} +1 -1
- package/static/auth-callback/assets/{activity-DdULRcSI.js → activity-DSfmTGfY.js} +1 -1
- package/static/auth-callback/assets/ai-connections-C03UWyPh.js +1 -0
- package/static/auth-callback/assets/{auth-callback-D7l2P25I.js → auth-callback-DleaitAS.js} +91 -91
- package/static/auth-callback/assets/auth-callback-vPSC2d2F.css +1 -0
- package/static/auth-callback/assets/{badge-j4zjFnmg.js → badge-B0aLu1sl.js} +1 -1
- package/static/auth-callback/assets/{download-DGXoks01.js → download-D_bFwdYJ.js} +1 -1
- package/static/auth-callback/assets/{external-link-CvbgXXaI.js → external-link-DRfjTaQu.js} +1 -1
- package/static/auth-callback/assets/{index-LRWvKJ2i.js → index-CG23cLYQ.js} +1 -1
- package/static/auth-callback/assets/{index-BOK3j1dz.js → index-CyV9ejwx.js} +1 -1
- package/static/auth-callback/assets/{index-browser-C1Qpe0g4.js → index-browser-D70paxIg.js} +1 -1
- package/static/auth-callback/assets/{key-round-CmgS5UdQ.js → key-round-BjV_mVYH.js} +1 -1
- package/static/auth-callback/assets/{rotate-ccw-c4CSG6Rq.js → rotate-ccw-CKoOAfse.js} +1 -1
- package/static/auth-callback/assets/{skeleton-ZPMTiRSM.js → skeleton-BZNjZaHx.js} +1 -1
- package/static/auth-callback/assets/{waypoints-xjyBflU5.js → waypoints-DoaJVzZv.js} +1 -1
- package/static/auth-callback/assets/{workspace-layout-B9nj6F5J.js → workspace-layout-CaP46_ZR.js} +1 -1
- package/static/auth-callback/auth-callback.html +2 -2
- package/static/dashboard/assets/{AiConfigContext-BWOOSYNr.js → AiConfigContext-BSrR27yD.js} +1 -1
- package/static/dashboard/assets/{AiConfigPage-CG2kQ9Wy.js → AiConfigPage-D65Z2LET.js} +1 -1
- package/static/dashboard/assets/{DocumentProcessingPanel-B4VXajfj.js → DocumentProcessingPanel-DyTe7Nei.js} +1 -1
- package/static/dashboard/assets/{IndexLifecyclePanel-CWCy0CC8.js → IndexLifecyclePanel-fK8ZGlrL.js} +1 -1
- package/static/dashboard/assets/{IndexSubjectPanel-CSgyQnG_.js → IndexSubjectPanel-CZPGor7v.js} +1 -1
- package/static/dashboard/assets/{ModelAssignmentsPanel-CdGIGidT.js → ModelAssignmentsPanel-CfYn5LMQ.js} +1 -1
- package/static/dashboard/assets/ModelsPage-djlJsghe.js +25 -0
- package/static/dashboard/assets/{NetworkPage-COia9NCH.js → NetworkPage-Coj6GnPl.js} +1 -1
- package/static/dashboard/assets/{PaneListHeader-SZWyr602.js → PaneListHeader-CUuFNSsZ.js} +1 -1
- package/static/dashboard/assets/{SearchIndexingPanel-D6PZtG6k.js → SearchIndexingPanel-CyJLioXS.js} +1 -1
- package/static/dashboard/assets/{StatusSubjectPanel-CxRD4kv0.js → StatusSubjectPanel-Cv26GSVC.js} +1 -1
- package/static/dashboard/assets/{StatusWorkspace-D3PfmY9-.js → StatusWorkspace-CDjFrsmB.js} +1 -1
- package/static/dashboard/assets/{SystemSettingsPage-COg1MmMj.js → SystemSettingsPage-BuNOyNoa.js} +1 -1
- package/static/dashboard/assets/{SystemSettingsSubjectPanel-BSVVB9Ol.js → SystemSettingsSubjectPanel-B2dasdez.js} +1 -1
- package/static/dashboard/assets/{activity-BJJx5cN-.js → activity-D1d2j_4Z.js} +1 -1
- package/static/dashboard/assets/ai-connections-C03UWyPh.js +1 -0
- package/static/dashboard/assets/{badge-elmrFSCj.js → badge-BeAAv6sp.js} +1 -1
- package/static/dashboard/assets/{dashboard-IvQrNmru.js → dashboard-BnGrUGv8.js} +68 -68
- package/static/dashboard/assets/dashboard-vPSC2d2F.css +1 -0
- package/static/dashboard/assets/{download-C3FH2KzG.js → download-DfFGiZRn.js} +1 -1
- package/static/dashboard/assets/{external-link-Bx7F0uKb.js → external-link-IsjU_LC9.js} +1 -1
- package/static/dashboard/assets/{index-liRoRIP1.js → index-BWQTucPe.js} +1 -1
- package/static/dashboard/assets/{index-M4-kWiGz.js → index-Dj75OjnW.js} +1 -1
- package/static/dashboard/assets/{key-round-CXg0bKAj.js → key-round-BJ_9wmQ_.js} +1 -1
- package/static/dashboard/assets/{rotate-ccw-yxJKOBrX.js → rotate-ccw-D3JGiFbR.js} +1 -1
- package/static/dashboard/assets/{skeleton-x9jNGrQT.js → skeleton-CC4nc-z-.js} +1 -1
- package/static/dashboard/assets/{waypoints-CTKeRsGp.js → waypoints-h7sqFqiG.js} +1 -1
- package/static/dashboard/assets/{workspace-layout--YkgkS38.js → workspace-layout-ZAPTOHhs.js} +1 -1
- package/static/dashboard/dashboard.html +2 -2
- package/static/settings/assets/{AiConfigContext-CelxXFcQ.js → AiConfigContext-lGkWpvKP.js} +1 -1
- package/static/settings/assets/{AiConfigPage-BaP-EovM.js → AiConfigPage-BbZWIBZq.js} +1 -1
- package/static/settings/assets/{DocumentProcessingPanel-DzLZluFv.js → DocumentProcessingPanel-DvYdjT-V.js} +1 -1
- package/static/settings/assets/{IndexLifecyclePanel-Bzj1-_oI.js → IndexLifecyclePanel-W5OGQZj7.js} +1 -1
- package/static/settings/assets/{IndexSubjectPanel-B263QLUh.js → IndexSubjectPanel-g_Aa5soq.js} +1 -1
- package/static/settings/assets/{ModelAssignmentsPanel-BAdT4UR0.js → ModelAssignmentsPanel-COlMBKXj.js} +1 -1
- package/static/settings/assets/ModelsPage-mApKi-aw.js +10 -0
- package/static/settings/assets/{NetworkPage-BK6a7l4g.js → NetworkPage-BDT05JUq.js} +1 -1
- package/static/settings/assets/{PaneListHeader-BAS2ICPq.js → PaneListHeader-CByhNpMG.js} +1 -1
- package/static/settings/assets/{SearchIndexingPanel-Cb_p-NgW.js → SearchIndexingPanel-BFAyzXls.js} +1 -1
- package/static/settings/assets/{StatusSubjectPanel-CcjqUua6.js → StatusSubjectPanel-Bz_XZ3VU.js} +1 -1
- package/static/settings/assets/{StatusWorkspace-7Ibty3_k.js → StatusWorkspace-CeVypHcW.js} +1 -1
- package/static/settings/assets/{SystemSettingsPage-DPSz4dg4.js → SystemSettingsPage-Dh7cQIfx.js} +1 -1
- package/static/settings/assets/{SystemSettingsSubjectPanel-Cb4HkKT5.js → SystemSettingsSubjectPanel-CSnpciO0.js} +1 -1
- package/static/settings/assets/{activity-Qhsr5Pxu.js → activity-DXz3EfFN.js} +1 -1
- package/static/settings/assets/ai-connections-C03UWyPh.js +1 -0
- package/static/settings/assets/{badge-B1vf2qCl.js → badge-1ZA144i4.js} +1 -1
- package/static/settings/assets/{download-CYNt0aZ-.js → download-CUHimlYa.js} +1 -1
- package/static/settings/assets/{external-link-ClKb39NT.js → external-link-BYHSVj2Z.js} +1 -1
- package/static/settings/assets/{index-y8ew3MLM.js → index-DKPDMdW5.js} +1 -1
- package/static/settings/assets/{index-browser-DJhvgpNI.js → index-browser-BaEFz0e0.js} +1 -1
- package/static/settings/assets/{index-BgiIDSch.js → index-viSgSvbO.js} +1 -1
- package/static/settings/assets/{key-round-5d-DrJz-.js → key-round-COByPOg8.js} +1 -1
- package/static/settings/assets/{rotate-ccw-CHZY7kS5.js → rotate-ccw-BC2EN6cE.js} +1 -1
- package/static/settings/assets/{settings-D5VRWyx6.js → settings-DLH9XUoT.js} +86 -86
- package/static/settings/assets/settings-vPSC2d2F.css +1 -0
- package/static/settings/assets/{skeleton-FNabNxNE.js → skeleton-B0-FOhKL.js} +1 -1
- package/static/settings/assets/{waypoints-BnL_8ljo.js → waypoints-DGMsvqWo.js} +1 -1
- package/static/settings/assets/{workspace-layout-D5q3F59S.js → workspace-layout-B0SVrJIu.js} +1 -1
- package/static/settings/settings.html +2 -2
- package/static/auth-callback/assets/ModelsPage-BpkVFKbf.js +0 -10
- package/static/auth-callback/assets/ai-connections-Bm52UO7Y.js +0 -1
- package/static/auth-callback/assets/auth-callback-01yz-UDU.css +0 -1
- package/static/dashboard/assets/ModelsPage-Chd5UK0D.js +0 -25
- package/static/dashboard/assets/ai-connections-Bm52UO7Y.js +0 -1
- package/static/dashboard/assets/dashboard-01yz-UDU.css +0 -1
- package/static/settings/assets/ModelsPage-C0NFa1zq.js +0 -10
- package/static/settings/assets/ai-connections-Bm52UO7Y.js +0 -1
- package/static/settings/assets/settings-01yz-UDU.css +0 -1
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.registerAiGatewayManagementRoutes = registerAiGatewayManagementRoutes;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
4
5
|
const global_logger_factory_1 = require("global-logger-factory");
|
|
5
6
|
const readBoundedJsonBody_1 = require("../http/readBoundedJsonBody");
|
|
6
7
|
const GatewayPrincipal_1 = require("../ai-gateway/auth/GatewayPrincipal");
|
|
7
|
-
const GatewayApiKey_1 = require("../ai-gateway/auth/GatewayApiKey");
|
|
8
|
-
const GatewayApiKeyAuthenticator_1 = require("../ai-gateway/auth/GatewayApiKeyAuthenticator");
|
|
9
8
|
const models_1 = require("../ai-gateway/models");
|
|
10
9
|
const AiConnectionsServiceAccess_1 = require("../ai-gateway/service-access/AiConnectionsServiceAccess");
|
|
11
10
|
const AiClientConfigurationService_1 = require("../service/AiClientConfigurationService");
|
|
@@ -91,31 +90,50 @@ function registerAiGatewayManagementRoutes(server, options) {
|
|
|
91
90
|
}
|
|
92
91
|
try {
|
|
93
92
|
const auth = request.auth;
|
|
94
|
-
const owner = (0, GatewayPrincipal_1.ownerWebIdForGatewayKeyManagement)(auth,
|
|
93
|
+
const owner = auth.type === 'solid' ? (0, GatewayPrincipal_1.ownerWebIdForGatewayKeyManagement)(auth, undefined) : undefined;
|
|
95
94
|
if (!owner) {
|
|
96
95
|
sendJson(response, 403, { error: 'Gateway API key management requires an owner WebID' });
|
|
97
96
|
return;
|
|
98
97
|
}
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
98
|
+
const apiKey = typeof body.apiKey === 'string' ? body.apiKey : '';
|
|
99
|
+
const credentialResource = validCredentialResource(body.credentialResource);
|
|
100
|
+
if (!validClientCredentialWrapper(apiKey) || !credentialResource) {
|
|
101
|
+
sendJson(response, 400, { error: 'A CSS client credential wrapper and Account credential resource are required' });
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (!options.validateClientCredential || !repository.createKeyId) {
|
|
105
|
+
sendJson(response, 503, { error: 'CSS credential registration is unavailable' });
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const verified = await options.validateClientCredential(apiKey);
|
|
109
|
+
if (!verified.success || verified.context?.type !== 'solid') {
|
|
110
|
+
sendJson(response, verified.category === 'service_unavailable' ? 503 : 401, {
|
|
111
|
+
error: 'CSS client credential verification failed',
|
|
112
|
+
});
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (verified.context.webId !== owner) {
|
|
116
|
+
sendJson(response, 403, { error: 'CSS client credential belongs to another WebID' });
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const name = normalizeOptionalString(body.name) ?? 'Xpod API Key';
|
|
120
|
+
const keyId = repository.createKeyId(owner, options.deployment);
|
|
105
121
|
const createdAt = new Date();
|
|
106
122
|
const record = await repository.create({
|
|
107
|
-
id:
|
|
123
|
+
id: keyId,
|
|
124
|
+
kind: 'client-credentials',
|
|
108
125
|
owner,
|
|
109
|
-
secretHash:
|
|
110
|
-
deployment:
|
|
111
|
-
scopes:
|
|
126
|
+
secretHash: '',
|
|
127
|
+
deployment: options.deployment,
|
|
128
|
+
scopes: [],
|
|
112
129
|
createdAt,
|
|
113
130
|
name,
|
|
114
|
-
|
|
131
|
+
credentialResource,
|
|
132
|
+
plaintext: apiKey,
|
|
115
133
|
}, { auth });
|
|
116
134
|
sendJson(response, 201, {
|
|
117
|
-
key:
|
|
118
|
-
record: publicGatewayAccessKeyRecord(record, true),
|
|
135
|
+
key: apiKey,
|
|
136
|
+
record: publicGatewayAccessKeyRecord(record, true, apiKey),
|
|
119
137
|
});
|
|
120
138
|
}
|
|
121
139
|
catch (error) {
|
|
@@ -169,6 +187,10 @@ function registerAiGatewayManagementRoutes(server, options) {
|
|
|
169
187
|
sendJson(response, 404, { error: 'Gateway API Key not found' });
|
|
170
188
|
return;
|
|
171
189
|
}
|
|
190
|
+
if (record.kind === 'client-credentials') {
|
|
191
|
+
sendJson(response, 409, { error: 'CSS client credentials cannot be suspended through Pod metadata' });
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
172
194
|
const updated = await repository.setEnabled(record.id, body.enabled, new Date(), { auth: request.auth });
|
|
173
195
|
if (!updated) {
|
|
174
196
|
sendJson(response, 404, { error: 'Gateway API Key not found' });
|
|
@@ -197,6 +219,8 @@ function registerAiGatewayManagementRoutes(server, options) {
|
|
|
197
219
|
sendJson(response, 404, { error: 'Gateway API Key not found' });
|
|
198
220
|
return;
|
|
199
221
|
}
|
|
222
|
+
// This removes the saved client configuration only. The Account host
|
|
223
|
+
// revokes CSS credentials before requesting this companion cleanup.
|
|
200
224
|
await repository.delete(record.id, { auth: request.auth });
|
|
201
225
|
sendJson(response, 200, {
|
|
202
226
|
deleted: true,
|
|
@@ -207,6 +231,14 @@ function registerAiGatewayManagementRoutes(server, options) {
|
|
|
207
231
|
sendGatewayAccessKeyError(response, error);
|
|
208
232
|
}
|
|
209
233
|
});
|
|
234
|
+
server.get('/api/ai/connections/authorization-methods', async (request, response) => {
|
|
235
|
+
if (!authorizeProviderConnect(request, response))
|
|
236
|
+
return;
|
|
237
|
+
const connectService = requireConnectService(options, response);
|
|
238
|
+
if (!connectService)
|
|
239
|
+
return;
|
|
240
|
+
sendJson(response, 200, { data: connectService.getAuthorizationMethods() });
|
|
241
|
+
});
|
|
210
242
|
server.get('/api/ai/connections/providers', async (request, response) => {
|
|
211
243
|
if (!authorizeProviderConnect(request, response)) {
|
|
212
244
|
return;
|
|
@@ -443,7 +475,7 @@ function registerAiGatewayManagementRoutes(server, options) {
|
|
|
443
475
|
return;
|
|
444
476
|
}
|
|
445
477
|
const mode = typeof body.mode === 'string' ? body.mode : undefined;
|
|
446
|
-
if (mode !== 'browserAssistedApiKey' && mode !== 'deviceCodeOAuth' && mode !== 'connectUnsupported') {
|
|
478
|
+
if (mode !== 'browserAssistedApiKey' && mode !== 'authorizationCodeOAuth' && mode !== 'deviceCodeOAuth' && mode !== 'connectUnsupported') {
|
|
447
479
|
sendJson(response, 400, { error: 'mode must be a supported Connect mode' });
|
|
448
480
|
return;
|
|
449
481
|
}
|
|
@@ -451,17 +483,26 @@ function registerAiGatewayManagementRoutes(server, options) {
|
|
|
451
483
|
if (!connectService) {
|
|
452
484
|
return;
|
|
453
485
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
? body.
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
486
|
+
try {
|
|
487
|
+
const result = await connectService.begin({
|
|
488
|
+
webId: request.auth.webId,
|
|
489
|
+
deployment: options.deployment,
|
|
490
|
+
provider: params.provider,
|
|
491
|
+
requestedMode: mode,
|
|
492
|
+
...(normalizeOptionalString(body.offeringId) ? { offeringId: normalizeOptionalString(body.offeringId) } : {}),
|
|
493
|
+
...(normalizeOptionalString(body.authorizationMethodId)
|
|
494
|
+
? { authorizationMethodId: normalizeOptionalString(body.authorizationMethodId) }
|
|
495
|
+
: {}),
|
|
496
|
+
expectedCredentialVersion: typeof body.expectedCredentialVersion === 'number'
|
|
497
|
+
? body.expectedCredentialVersion
|
|
498
|
+
: undefined,
|
|
499
|
+
auth: request.auth,
|
|
500
|
+
});
|
|
501
|
+
sendJson(response, 200, publicConnectResult(result));
|
|
502
|
+
}
|
|
503
|
+
catch (error) {
|
|
504
|
+
sendLegacyProviderConnectError(response, error);
|
|
505
|
+
}
|
|
465
506
|
});
|
|
466
507
|
server.get('/api/ai/gateway/providers/:provider/connect/status/:attemptId', async (request, response, params) => {
|
|
467
508
|
if (!authorizeProviderConnect(request, response)) {
|
|
@@ -473,16 +514,23 @@ function registerAiGatewayManagementRoutes(server, options) {
|
|
|
473
514
|
if (!connectService) {
|
|
474
515
|
return;
|
|
475
516
|
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
517
|
+
try {
|
|
518
|
+
const result = await connectService.status({
|
|
519
|
+
webId: request.auth.webId,
|
|
520
|
+
deployment: options.deployment,
|
|
521
|
+
provider: params.provider,
|
|
522
|
+
...(url.searchParams.get('mode') === 'authorizationCodeOAuth' ? { mode: 'authorizationCodeOAuth' } : {}),
|
|
523
|
+
attemptId: decodeURIComponent(params.attemptId),
|
|
524
|
+
state: url.searchParams.get('state') ?? '',
|
|
525
|
+
signature: url.searchParams.get('signature') ?? '',
|
|
526
|
+
...(url.searchParams.get('offeringId') ? { offeringId: url.searchParams.get('offeringId') } : {}),
|
|
527
|
+
auth: request.auth,
|
|
528
|
+
});
|
|
529
|
+
sendJson(response, 200, publicConnectResult(result));
|
|
530
|
+
}
|
|
531
|
+
catch (error) {
|
|
532
|
+
sendLegacyProviderConnectError(response, error);
|
|
533
|
+
}
|
|
486
534
|
});
|
|
487
535
|
server.post('/api/ai/gateway/providers/:provider/connect/complete-api-key', async (request, response, params) => {
|
|
488
536
|
if (!authorizeProviderConnect(request, response)) {
|
|
@@ -507,6 +555,7 @@ function registerAiGatewayManagementRoutes(server, options) {
|
|
|
507
555
|
webId: request.auth.webId,
|
|
508
556
|
deployment: options.deployment,
|
|
509
557
|
provider: params.provider,
|
|
558
|
+
...(normalizeOptionalString(body.offeringId) ? { offeringId: normalizeOptionalString(body.offeringId) } : {}),
|
|
510
559
|
attemptId: stringBody(body.attemptId),
|
|
511
560
|
state: stringBody(body.state),
|
|
512
561
|
signature: stringBody(body.signature),
|
|
@@ -534,16 +583,50 @@ function registerAiGatewayManagementRoutes(server, options) {
|
|
|
534
583
|
if (!connectService) {
|
|
535
584
|
return;
|
|
536
585
|
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
586
|
+
try {
|
|
587
|
+
const result = await connectService.pollDevice({
|
|
588
|
+
webId: request.auth.webId,
|
|
589
|
+
deployment: options.deployment,
|
|
590
|
+
provider: params.provider,
|
|
591
|
+
...(body.mode === 'authorizationCodeOAuth' || body.mode === 'deviceCodeOAuth' ? { mode: body.mode } : {}),
|
|
592
|
+
attemptId: stringBody(body.attemptId),
|
|
593
|
+
state: stringBody(body.state),
|
|
594
|
+
signature: stringBody(body.signature),
|
|
595
|
+
...(normalizeOptionalString(body.offeringId) ? { offeringId: normalizeOptionalString(body.offeringId) } : {}),
|
|
596
|
+
auth: request.auth,
|
|
597
|
+
});
|
|
598
|
+
sendJson(response, 200, publicConnectResult(result));
|
|
599
|
+
}
|
|
600
|
+
catch (error) {
|
|
601
|
+
sendLegacyProviderConnectError(response, error);
|
|
602
|
+
}
|
|
603
|
+
});
|
|
604
|
+
server.post('/api/ai/gateway/providers/:provider/connect/cancel', async (request, response, params) => {
|
|
605
|
+
if (!authorizeProviderConnect(request, response))
|
|
606
|
+
return;
|
|
607
|
+
const body = await readJsonObject(request, response, jsonBodyLimitBytes);
|
|
608
|
+
if (!body)
|
|
609
|
+
return;
|
|
610
|
+
const connectService = requireConnectService(options, response);
|
|
611
|
+
if (!connectService)
|
|
612
|
+
return;
|
|
613
|
+
try {
|
|
614
|
+
const result = await connectService.cancel({
|
|
615
|
+
webId: request.auth.webId,
|
|
616
|
+
deployment: options.deployment,
|
|
617
|
+
provider: params.provider,
|
|
618
|
+
...(body.mode === 'authorizationCodeOAuth' || body.mode === 'deviceCodeOAuth' ? { mode: body.mode } : {}),
|
|
619
|
+
attemptId: stringBody(body.attemptId),
|
|
620
|
+
state: stringBody(body.state),
|
|
621
|
+
signature: stringBody(body.signature),
|
|
622
|
+
...(normalizeOptionalString(body.offeringId) ? { offeringId: normalizeOptionalString(body.offeringId) } : {}),
|
|
623
|
+
auth: request.auth,
|
|
624
|
+
});
|
|
625
|
+
sendJson(response, 200, publicConnectResult(result));
|
|
626
|
+
}
|
|
627
|
+
catch (error) {
|
|
628
|
+
sendLegacyProviderConnectError(response, error);
|
|
629
|
+
}
|
|
547
630
|
});
|
|
548
631
|
server.post('/api/ai/gateway/providers/:provider/connect/refresh', async (request, response, params) => {
|
|
549
632
|
if (!authorizeProviderConnect(request, response)) {
|
|
@@ -570,9 +653,11 @@ function registerAiGatewayManagementRoutes(server, options) {
|
|
|
570
653
|
webId: request.auth.webId,
|
|
571
654
|
deployment: options.deployment,
|
|
572
655
|
provider: params.provider,
|
|
656
|
+
...(body.mode === 'authorizationCodeOAuth' || body.mode === 'deviceCodeOAuth' ? { mode: body.mode } : {}),
|
|
573
657
|
credentialId,
|
|
574
658
|
refreshToken,
|
|
575
659
|
expectedVersion,
|
|
660
|
+
...(normalizeOptionalString(body.offeringId) ? { offeringId: normalizeOptionalString(body.offeringId) } : {}),
|
|
576
661
|
auth: request.auth,
|
|
577
662
|
});
|
|
578
663
|
sendJson(response, 200, publicConnectResult(result));
|
|
@@ -597,6 +682,7 @@ function registerAiGatewayManagementRoutes(server, options) {
|
|
|
597
682
|
deployment: options.deployment,
|
|
598
683
|
provider: params.provider,
|
|
599
684
|
credentialId: normalizeOptionalString(url.searchParams.get('credentialId')),
|
|
685
|
+
...(url.searchParams.get('offeringId') ? { offeringId: url.searchParams.get('offeringId') } : {}),
|
|
600
686
|
auth: request.auth,
|
|
601
687
|
});
|
|
602
688
|
sendJson(response, 200, { record: record ? publicCredentialRecord(record) : undefined });
|
|
@@ -965,6 +1051,7 @@ function requireCredentialPoolManagementService(options, response) {
|
|
|
965
1051
|
return requireConnectService(options, response);
|
|
966
1052
|
}
|
|
967
1053
|
function markLegacyProviderConnectRoute(response) {
|
|
1054
|
+
response.setHeader('Cache-Control', 'no-store');
|
|
968
1055
|
response.setHeader('Deprecation', 'true');
|
|
969
1056
|
response.setHeader('Link', '</api/ai/providers>; rel="successor-version"');
|
|
970
1057
|
}
|
|
@@ -1073,15 +1160,25 @@ function normalizeCustomModelInput(body) {
|
|
|
1073
1160
|
...(capabilities.length > 0 ? { capabilities } : {}),
|
|
1074
1161
|
};
|
|
1075
1162
|
}
|
|
1076
|
-
function
|
|
1077
|
-
if (!
|
|
1078
|
-
return
|
|
1079
|
-
|
|
1080
|
-
const
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1163
|
+
function validClientCredentialWrapper(value) {
|
|
1164
|
+
if (!value.startsWith('sk-'))
|
|
1165
|
+
return false;
|
|
1166
|
+
const encoded = value.slice(3);
|
|
1167
|
+
const decoded = Buffer.from(encoded, 'base64').toString('utf8');
|
|
1168
|
+
return Buffer.from(decoded, 'utf8').toString('base64') === encoded
|
|
1169
|
+
&& /^[^\s\x00-\x1f\x7f:]+:[^\s\x00-\x1f\x7f]+$/u.test(decoded);
|
|
1170
|
+
}
|
|
1171
|
+
function validCredentialResource(value) {
|
|
1172
|
+
if (typeof value !== 'string')
|
|
1173
|
+
return undefined;
|
|
1174
|
+
try {
|
|
1175
|
+
const url = new URL(value);
|
|
1176
|
+
return ['http:', 'https:'].includes(url.protocol) && !url.username && !url.password && !url.search && !url.hash
|
|
1177
|
+
&& url.pathname.startsWith('/.account/') ? url.href : undefined;
|
|
1178
|
+
}
|
|
1179
|
+
catch {
|
|
1180
|
+
return undefined;
|
|
1181
|
+
}
|
|
1085
1182
|
}
|
|
1086
1183
|
async function ownedGatewayAccessKey(repository, keyId, auth) {
|
|
1087
1184
|
if (!keyId) {
|
|
@@ -1114,6 +1211,9 @@ function publicGatewayAccessKeyRecord(record, plaintextAvailable, plaintext) {
|
|
|
1114
1211
|
const enabled = !record.disabledAt && !record.revokedAt;
|
|
1115
1212
|
return {
|
|
1116
1213
|
id: record.id,
|
|
1214
|
+
...(record.kind ? { kind: record.kind } : {}),
|
|
1215
|
+
...(record.credentialResource ? { credentialResource: record.credentialResource } : {}),
|
|
1216
|
+
...(plaintext ? { fingerprint: (0, node_crypto_1.createHash)('sha256').update(plaintext).digest('hex') } : {}),
|
|
1117
1217
|
owner: record.owner,
|
|
1118
1218
|
deployment: record.deployment,
|
|
1119
1219
|
scopes: record.scopes,
|
|
@@ -1216,6 +1316,11 @@ function sendCredentialPoolError(response, error) {
|
|
|
1216
1316
|
return;
|
|
1217
1317
|
}
|
|
1218
1318
|
const message = error instanceof Error ? error.message : String(error);
|
|
1319
|
+
if (message === 'local_session_reauth_required' || message === 'local_session_missing_refresh_token'
|
|
1320
|
+
|| message === 'local_session_refresh_failed') {
|
|
1321
|
+
sendJson(response, message === 'local_session_refresh_failed' ? 502 : 409, { error: message });
|
|
1322
|
+
return;
|
|
1323
|
+
}
|
|
1219
1324
|
if (message === 'credential_version_conflict') {
|
|
1220
1325
|
sendJson(response, 409, { error: 'credential_version_conflict' });
|
|
1221
1326
|
return;
|
|
@@ -1252,7 +1357,7 @@ function sendGatewayAccessKeyError(response, error) {
|
|
|
1252
1357
|
sendJson(response, 500, { error: 'Gateway API Key secret could not be saved' });
|
|
1253
1358
|
return;
|
|
1254
1359
|
}
|
|
1255
|
-
logger.error(`Gateway API Key operation failed: ${message}`);
|
|
1360
|
+
logger.error(`Gateway API Key operation failed: ${(0, AiClientConfigurationService_1.redactSecretText)(message)}`);
|
|
1256
1361
|
sendJson(response, 500, { error: 'Gateway API Key operation failed' });
|
|
1257
1362
|
}
|
|
1258
1363
|
function sendLegacyProviderConnectError(response, error) {
|
|
@@ -1262,6 +1367,14 @@ function sendLegacyProviderConnectError(response, error) {
|
|
|
1262
1367
|
return;
|
|
1263
1368
|
}
|
|
1264
1369
|
const message = error instanceof Error ? error.message : String(error);
|
|
1370
|
+
if (/^OAuth refresh failed: (?:invalid_grant|invalid_token)$/u.test(message)) {
|
|
1371
|
+
sendJson(response, 409, { error: 'oauth_session_reauth_required' });
|
|
1372
|
+
return;
|
|
1373
|
+
}
|
|
1374
|
+
if (message.startsWith('OAuth refresh failed:')) {
|
|
1375
|
+
sendJson(response, 502, { error: 'oauth_refresh_failed' });
|
|
1376
|
+
return;
|
|
1377
|
+
}
|
|
1265
1378
|
if (message === 'credential_version_conflict') {
|
|
1266
1379
|
sendJson(response, 409, { error: 'credential_version_conflict' });
|
|
1267
1380
|
return;
|
|
@@ -1547,6 +1660,8 @@ function publicConnectResult(value) {
|
|
|
1547
1660
|
'webId',
|
|
1548
1661
|
'encryptedSecret',
|
|
1549
1662
|
'metadata',
|
|
1663
|
+
'deviceCode',
|
|
1664
|
+
'codeVerifier',
|
|
1550
1665
|
].includes(key))
|
|
1551
1666
|
.map(([key, item]) => [key, publicConnectResult(item)]));
|
|
1552
1667
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type AiClientModelReference } from '@undefineds.co/ai-connections/client-config';
|
|
1
2
|
import type { AuthContext } from '../auth/AuthContext';
|
|
2
3
|
export type AiClientId = 'codex' | 'claude-code' | 'pi' | 'codebuddy';
|
|
3
4
|
export interface AiClientConfigurationCapabilityDescriptor {
|
|
@@ -10,6 +11,7 @@ export interface AiClientConfigurationStatus {
|
|
|
10
11
|
message?: string;
|
|
11
12
|
installed?: boolean;
|
|
12
13
|
configExists?: boolean;
|
|
14
|
+
appliedKeyFingerprint?: string;
|
|
13
15
|
}
|
|
14
16
|
export interface AiClientConfigurationPlan {
|
|
15
17
|
planId: string;
|
|
@@ -44,24 +46,13 @@ export interface AiClientConfigurationServiceOptions {
|
|
|
44
46
|
}) => Promise<unknown>;
|
|
45
47
|
fetch?: typeof fetch;
|
|
46
48
|
verificationTimeoutMs?: number;
|
|
47
|
-
/** Current authenticated Gateway projection; never use an unauthenticated HTTP self-fetch. */
|
|
48
|
-
listActiveModels?: (input: {
|
|
49
|
-
webId: string;
|
|
50
|
-
auth: AuthContext;
|
|
51
|
-
}) => Promise<readonly AiClientVisibleModel[]>;
|
|
52
49
|
launchClient?: (client: AiClientId) => Promise<void>;
|
|
53
50
|
}
|
|
54
|
-
export interface AiClientVisibleModel {
|
|
55
|
-
id: string;
|
|
56
|
-
provider?: string;
|
|
57
|
-
owned_by?: string;
|
|
58
|
-
displayName?: string;
|
|
59
|
-
availability?: 'available' | 'unavailable' | 'statusUnknown';
|
|
60
|
-
}
|
|
61
51
|
export interface PlanInput {
|
|
62
52
|
client: AiClientId;
|
|
63
53
|
endpoint: string;
|
|
64
54
|
model?: string;
|
|
55
|
+
activeModels?: readonly AiClientModelReference[];
|
|
65
56
|
webId?: string;
|
|
66
57
|
auth?: AuthContext;
|
|
67
58
|
}
|
|
@@ -93,13 +84,12 @@ export declare class AiClientConfigurationService {
|
|
|
93
84
|
private readonly backupRoot;
|
|
94
85
|
private readonly now;
|
|
95
86
|
private readonly verifyGateway;
|
|
96
|
-
private readonly listActiveModels?;
|
|
97
87
|
private readonly launchClient;
|
|
98
88
|
private readonly plans;
|
|
99
89
|
private readonly locks;
|
|
100
90
|
constructor(options?: AiClientConfigurationServiceOptions);
|
|
101
91
|
capability(): AiClientConfigurationCapabilityDescriptor;
|
|
102
|
-
inspect(client: AiClientId): Promise<AiClientConfigurationStatus>;
|
|
92
|
+
inspect(client: AiClientId, webId?: string): Promise<AiClientConfigurationStatus>;
|
|
103
93
|
launch(client: AiClientId): Promise<{
|
|
104
94
|
launched: true;
|
|
105
95
|
}>;
|
|
@@ -109,7 +99,6 @@ export declare class AiClientConfigurationService {
|
|
|
109
99
|
}>;
|
|
110
100
|
verify(input: VerifyInput): Promise<AiClientConfigurationStatus>;
|
|
111
101
|
restore(client: AiClientId, webId?: string): Promise<AiClientConfigurationStatus>;
|
|
112
|
-
private readActiveModels;
|
|
113
102
|
private adapterFor;
|
|
114
103
|
private publicTargets;
|
|
115
104
|
private detectLockTargets;
|
|
@@ -36,7 +36,6 @@ class AiClientConfigurationService {
|
|
|
36
36
|
this.backupRoot = node_path_1.default.resolve(options.backupRoot ?? node_path_1.default.join(this.homeDir, '.xpod/client-config-backups'));
|
|
37
37
|
this.now = options.now ?? (() => new Date());
|
|
38
38
|
this.verifyGateway = options.verifyGateway ?? createDefaultGatewayVerifier(options.fetch ?? fetch, options.verificationTimeoutMs ?? 8_000);
|
|
39
|
-
this.listActiveModels = options.listActiveModels;
|
|
40
39
|
this.launchClient = options.launchClient ?? ((client) => launchLocalClient(client, this.homeDir));
|
|
41
40
|
}
|
|
42
41
|
capability() {
|
|
@@ -46,18 +45,22 @@ class AiClientConfigurationService {
|
|
|
46
45
|
manualInstructions: MANUAL_INSTRUCTIONS,
|
|
47
46
|
};
|
|
48
47
|
}
|
|
49
|
-
async inspect(client) {
|
|
48
|
+
async inspect(client, webId) {
|
|
50
49
|
const adapter = this.adapterFor(client);
|
|
51
50
|
const detection = await mapAdapterError(() => adapter.detect());
|
|
52
51
|
const inspection = await mapAdapterError(() => adapter.inspect());
|
|
53
52
|
const configured = inspection.ownership === 'owned';
|
|
54
53
|
return {
|
|
55
|
-
status: configured ? 'configured' : 'notConfigured',
|
|
54
|
+
status: configured ? inspection.projectionMatches === false ? 'drifted' : 'configured' : 'notConfigured',
|
|
55
|
+
...(configured && webId && inspection.webIdHash === (0, client_config_1.hashWebId)(webId) && inspection.apiKeyFingerprint
|
|
56
|
+
? { appliedKeyFingerprint: inspection.apiKeyFingerprint } : {}),
|
|
56
57
|
installed: detection.installed,
|
|
57
58
|
configExists: detection.configExists,
|
|
58
|
-
message:
|
|
59
|
-
? `${CLIENT_LABELS[client]}
|
|
60
|
-
:
|
|
59
|
+
message: inspection.projectionMatches === false
|
|
60
|
+
? `${CLIENT_LABELS[client]} configuration has changed since it was applied.`
|
|
61
|
+
: configured
|
|
62
|
+
? `${CLIENT_LABELS[client]} is configured for Xpod.`
|
|
63
|
+
: `${CLIENT_LABELS[client]} is not configured for Xpod.`,
|
|
61
64
|
};
|
|
62
65
|
}
|
|
63
66
|
async launch(client) {
|
|
@@ -74,20 +77,13 @@ class AiClientConfigurationService {
|
|
|
74
77
|
const client = requireSupportedClient(input.client);
|
|
75
78
|
const webId = input.webId ?? solidWebId(input.auth)
|
|
76
79
|
?? 'https://xpod.local/.well-known/ai-client-configuration#owner';
|
|
77
|
-
const activeModels = await this.readActiveModels(webId, input.auth);
|
|
78
80
|
const profile = {
|
|
79
81
|
endpoint: normalizeEndpoint(input.endpoint),
|
|
80
82
|
gatewayKey: PLAN_SECRET_PLACEHOLDER,
|
|
81
83
|
webId,
|
|
82
84
|
model: input.model,
|
|
83
|
-
activeModels: activeModels
|
|
84
|
-
catalogVersion: activeModels.version,
|
|
85
|
+
activeModels: client === 'codex' ? input.activeModels : undefined,
|
|
85
86
|
};
|
|
86
|
-
if (client !== 'codex' || profile.model || activeModels.models.length > 0) {
|
|
87
|
-
await mapAdapterError(async () => {
|
|
88
|
-
profile.model = (0, client_config_1.resolveActiveModel)(profile);
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
87
|
const adapter = this.adapterFor(client);
|
|
92
88
|
const nativePlan = await mapAdapterError(() => adapter.plan(profile));
|
|
93
89
|
const targets = await this.publicTargets(nativePlan.writes);
|
|
@@ -130,22 +126,11 @@ class AiClientConfigurationService {
|
|
|
130
126
|
throw new AiClientConfigurationError('configuration_conflict', 'Configuration changed after planning.', 409);
|
|
131
127
|
}
|
|
132
128
|
}
|
|
133
|
-
const currentCatalog = await this.readActiveModels(input.webId ?? plan.profile.webId, input.auth);
|
|
134
|
-
if (currentCatalog.models.length === 0 && (plan.client !== 'codex' || plan.profile.model)) {
|
|
135
|
-
throw new AiClientConfigurationError('model_not_available', 'The planned model is no longer active in the Xpod Gateway.', 409);
|
|
136
|
-
}
|
|
137
129
|
const profile = {
|
|
138
130
|
...plan.profile,
|
|
139
131
|
gatewayKey: input.gatewayKey,
|
|
140
132
|
webId: input.webId ?? plan.profile.webId,
|
|
141
|
-
activeModels: currentCatalog.models,
|
|
142
|
-
catalogVersion: currentCatalog.version,
|
|
143
133
|
};
|
|
144
|
-
if (plan.client !== 'codex' || profile.model || currentCatalog.models.length > 0) {
|
|
145
|
-
await mapAdapterError(async () => {
|
|
146
|
-
profile.model = (0, client_config_1.resolveActiveModel)(profile);
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
134
|
const adapter = this.adapterFor(plan.client);
|
|
150
135
|
const nativePlan = await mapAdapterError(() => adapter.plan(profile));
|
|
151
136
|
await mapAdapterError(() => adapter.apply(nativePlan));
|
|
@@ -153,11 +138,13 @@ class AiClientConfigurationService {
|
|
|
153
138
|
plan.profile = profile;
|
|
154
139
|
plan.nativePlan = nativePlan;
|
|
155
140
|
try {
|
|
156
|
-
await
|
|
141
|
+
const verification = await mapAdapterError(() => adapter.verify(profile));
|
|
142
|
+
if (!verification.ok)
|
|
143
|
+
throw new Error(verification.reason);
|
|
157
144
|
}
|
|
158
145
|
catch {
|
|
159
146
|
await mapAdapterError(() => adapter.restore(profile.webId));
|
|
160
|
-
throw new AiClientConfigurationError('
|
|
147
|
+
throw new AiClientConfigurationError('local_verification_failed_restored', 'Client configuration could not be verified locally.', 500, { restored: true });
|
|
161
148
|
}
|
|
162
149
|
return { applied: true };
|
|
163
150
|
});
|
|
@@ -199,42 +186,6 @@ class AiClientConfigurationService {
|
|
|
199
186
|
}
|
|
200
187
|
return this.inspect(client);
|
|
201
188
|
}
|
|
202
|
-
async readActiveModels(webId, auth) {
|
|
203
|
-
if (!this.listActiveModels) {
|
|
204
|
-
throw new AiClientConfigurationError('model_catalog_unavailable', 'Authenticated Gateway model visibility is not configured for client setup.', 503);
|
|
205
|
-
}
|
|
206
|
-
if (!auth) {
|
|
207
|
-
throw new AiClientConfigurationError('authentication_required', 'Authentication required.', 401);
|
|
208
|
-
}
|
|
209
|
-
try {
|
|
210
|
-
const discovered = await this.listActiveModels({ webId, auth });
|
|
211
|
-
const models = discovered
|
|
212
|
-
.filter((model) => typeof model.id === 'string' && model.id.trim())
|
|
213
|
-
.filter((model) => model.availability === undefined || model.availability === 'available')
|
|
214
|
-
.map((model) => ({
|
|
215
|
-
id: model.id.trim(),
|
|
216
|
-
...(typeof model.provider === 'string' && model.provider.trim()
|
|
217
|
-
? { provider: model.provider.trim() }
|
|
218
|
-
: typeof model.owned_by === 'string' && model.owned_by.trim()
|
|
219
|
-
? { provider: model.owned_by.trim() }
|
|
220
|
-
: {}),
|
|
221
|
-
...(typeof model.displayName === 'string' && model.displayName.trim()
|
|
222
|
-
? { displayName: model.displayName.trim() }
|
|
223
|
-
: {}),
|
|
224
|
-
availability: 'available',
|
|
225
|
-
}));
|
|
226
|
-
const version = hash(JSON.stringify(models.map((model) => ({
|
|
227
|
-
id: model.id,
|
|
228
|
-
provider: model.provider,
|
|
229
|
-
})).sort((left, right) => `${left.provider ?? ''}/${left.id}`.localeCompare(`${right.provider ?? ''}/${right.id}`))));
|
|
230
|
-
return { version, models };
|
|
231
|
-
}
|
|
232
|
-
catch (error) {
|
|
233
|
-
if (error instanceof AiClientConfigurationError)
|
|
234
|
-
throw error;
|
|
235
|
-
throw new AiClientConfigurationError('model_catalog_unavailable', 'Authenticated Gateway model visibility could not be read.', 503);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
189
|
adapterFor(client) {
|
|
239
190
|
requireSupportedClient(client);
|
|
240
191
|
if (client === 'codex')
|
|
@@ -320,7 +271,7 @@ function publicPlan(plan, homeDir) {
|
|
|
320
271
|
required: true,
|
|
321
272
|
token: plan.confirmation.token,
|
|
322
273
|
targetHash: plan.confirmation.targetHash,
|
|
323
|
-
message: 'This client
|
|
274
|
+
message: 'This switches the client connection and keeps a backup of the current configuration. Re-enter the confirmation token before applying.',
|
|
324
275
|
},
|
|
325
276
|
} : {}),
|
|
326
277
|
};
|
|
@@ -569,6 +520,8 @@ function runLauncher(command, args) {
|
|
|
569
520
|
}
|
|
570
521
|
function redactSecretText(input) {
|
|
571
522
|
return input
|
|
523
|
+
.replace(/("(?:[a-z_]*api[_-]?key|[a-z_]*(?:access|refresh|id|bearer)[_-]?token|client[_-]?secret|password)"\s*:\s*)"(?:\\.|[^"\\])*"/giu, '$1"[redacted]"')
|
|
524
|
+
.replace(/(\bexperimental_bearer_token\s*=\s*)(?:"(?:\\.|[^"\\])*"|'[^']*')/giu, '$1"[redacted]"')
|
|
572
525
|
.replace(/\/(?:Users|var|tmp|private|home)\/[^\s"',)]+/gu, '[path]')
|
|
573
526
|
.replace(/xpod_[A-Za-z0-9._-]+/gu, '[redacted]')
|
|
574
527
|
.replace(/sk-[A-Za-z0-9._+/=-]+/gu, '[redacted]')
|
|
@@ -229,6 +229,8 @@ function resolveChildDatabaseUrl(value, childCwd) {
|
|
|
229
229
|
return (0, database_url_1.normalizeDatabaseUrl)(trimmed);
|
|
230
230
|
}
|
|
231
231
|
function resolveCanonicalRuntimeBaseUrl(provisionedPublicUrl, configuredBaseUrl, localFallbackUrl) {
|
|
232
|
+
// A Cloud-issued URL is the canonical Solid identity origin. CSS_BASE_URL is
|
|
233
|
+
// the canonical origin only for deployments that have no managed identity.
|
|
232
234
|
return provisionedPublicUrl?.trim() || configuredBaseUrl?.trim() || localFallbackUrl;
|
|
233
235
|
}
|
|
234
236
|
function resolveMainPort(cliPort, env, configuredBaseUrl) {
|
|
@@ -105,6 +105,7 @@
|
|
|
105
105
|
"undefineds:dist/identity/oidc/RememberedClientGrantStore.jsonld",
|
|
106
106
|
"undefineds:dist/identity/oidc/RememberedConsentHandler.jsonld",
|
|
107
107
|
"undefineds:dist/identity/oidc/RememberedClientPromptFactory.jsonld",
|
|
108
|
+
"undefineds:dist/identity/oidc/SessionBoundIdentityProviderFactory.jsonld",
|
|
108
109
|
"undefineds:dist/identity/oidc/ScopedPickWebIdHandler.jsonld",
|
|
109
110
|
"undefineds:dist/authentication/ConfiguredLoopbackDPoPWebIdExtractor.jsonld",
|
|
110
111
|
"undefineds:dist/identity/AccountStorageBindingsHandler.jsonld",
|