@undefineds.co/xpod 0.4.11 → 0.4.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/components-ignore.json +5 -1
- package/config/notifications.json +68 -0
- package/config/xpod.base.json +9 -11
- package/dist/ai/service/AiCredentialSecret.d.ts +30 -0
- package/dist/ai/service/AiCredentialSecret.js +120 -0
- package/dist/ai/service/CredentialReaderImpl.d.ts +18 -0
- package/dist/ai/service/CredentialReaderImpl.js +81 -5
- package/dist/ai/service/CredentialReaderImpl.jsonld +42 -2
- package/dist/ai/service/EmbeddingModelPolicy.d.ts +79 -0
- package/dist/ai/service/EmbeddingModelPolicy.js +134 -0
- package/dist/ai/service/EmbeddingProviderError.js +6 -0
- package/dist/ai/service/EmbeddingServiceImpl.d.ts +13 -1
- package/dist/ai/service/EmbeddingServiceImpl.js +18 -5
- package/dist/ai/service/EmbeddingServiceImpl.jsonld +35 -0
- package/dist/ai/service/index.d.ts +2 -0
- package/dist/ai/service/index.js +2 -0
- package/dist/api/ai-gateway/connect/index.d.ts +20 -2
- package/dist/api/ai-gateway/connect/index.js +162 -16
- package/dist/api/ai-gateway/credentials/AiCredentialSecretDecoder.d.ts +12 -0
- package/dist/api/ai-gateway/credentials/AiCredentialSecretDecoder.js +30 -0
- package/dist/api/ai-gateway/errors.d.ts +1 -1
- package/dist/api/ai-gateway/models/GatewayEmbeddingModelCatalog.d.ts +11 -0
- package/dist/api/ai-gateway/models/GatewayEmbeddingModelCatalog.js +31 -0
- package/dist/api/ai-gateway/models/PodModelSelectionRepository.js +7 -3
- package/dist/api/ai-gateway/models/ProviderCustomModelsService.d.ts +18 -0
- package/dist/api/ai-gateway/models/ProviderCustomModelsService.js +23 -0
- package/dist/api/ai-gateway/models/ProviderModelDiscoveryAdapters.d.ts +3 -1
- package/dist/api/ai-gateway/models/ProviderModelDiscoveryAdapters.js +2 -45
- package/dist/api/ai-gateway/models/ProviderModelSelectionService.d.ts +10 -0
- package/dist/api/ai-gateway/models/ProviderModelSelectionService.js +57 -20
- package/dist/api/ai-gateway/models/ProviderModelType.d.ts +28 -0
- package/dist/api/ai-gateway/models/ProviderModelType.js +34 -0
- package/dist/api/ai-gateway/models/ProviderModelsAdapter.d.ts +10 -0
- package/dist/api/ai-gateway/models/ProviderModelsAdapter.js +3 -4
- package/dist/api/ai-gateway/models/index.d.ts +1 -0
- package/dist/api/ai-gateway/models/index.js +3 -1
- package/dist/api/ai-gateway/providers/CustomRuntimeAdapter.d.ts +7 -0
- package/dist/api/ai-gateway/providers/CustomRuntimeAdapter.js +9 -2
- package/dist/api/ai-gateway/providers/ModelsDevCatalog.d.ts +7 -1
- package/dist/api/ai-gateway/providers/ModelsDevCatalog.js +4 -10
- package/dist/api/ai-gateway/providers/ProviderRegistry.d.ts +107 -0
- package/dist/api/ai-gateway/providers/ProviderRegistry.js +244 -21
- package/dist/api/ai-gateway/providers/ProviderRuntimeRegistry.d.ts +5 -0
- package/dist/api/ai-gateway/providers/ProviderRuntimeRegistry.js +5 -1
- package/dist/api/ai-gateway/quota/SubscriptionQuotaAdapters.d.ts +12 -4
- package/dist/api/ai-gateway/quota/SubscriptionQuotaAdapters.js +11 -11
- package/dist/api/ai-gateway/routing/ModelRouter.d.ts +14 -0
- package/dist/api/ai-gateway/routing/ModelRouter.js +43 -4
- package/dist/api/ai-gateway/service-access/AiConnectionsServiceAccess.d.ts +9 -1
- package/dist/api/ai-gateway/service-access/AiConnectionsServiceAccess.js +3 -27
- package/dist/api/chatkit/pod-store.d.ts +31 -0
- package/dist/api/chatkit/pod-store.js +132 -8
- package/dist/api/container/common.js +24 -4
- package/dist/api/container/routes.js +17 -2
- package/dist/api/container/types.d.ts +3 -1
- package/dist/api/handlers/AdminHandler.d.ts +13 -0
- package/dist/api/handlers/AdminHandler.js +47 -18
- package/dist/api/handlers/AiConfigHandler.d.ts +6 -0
- package/dist/api/handlers/AiConfigHandler.js +28 -0
- package/dist/api/handlers/AiGatewayManagementHandler.js +36 -0
- package/dist/api/runs/RdfRunContextRetriever.d.ts +14 -0
- package/dist/api/runs/RdfRunContextRetriever.js +41 -5
- package/dist/api/runtime.js +2 -1
- package/dist/cli/commands/secret.d.ts +1 -0
- package/dist/cli/commands/secret.js +25 -7
- package/dist/components/components.jsonld +3 -1
- package/dist/components/context.jsonld +53 -1
- package/dist/http/SubgraphSparqlHttpHandler.d.ts +59 -2
- package/dist/http/SubgraphSparqlHttpHandler.js +145 -13
- package/dist/http/SubgraphSparqlHttpHandler.jsonld +37 -0
- package/dist/identity/drizzle/EdgeNodeRepository.d.ts +0 -12
- package/dist/identity/drizzle/EdgeNodeRepository.js +5 -13
- package/dist/index.d.ts +2 -1
- package/dist/index.js +7 -3
- package/dist/logging/log-file.d.ts +17 -0
- package/dist/logging/log-file.js +69 -0
- package/dist/main.js +2 -1
- package/dist/notifications/NotificationChannelSweeper.d.ts +50 -0
- package/dist/notifications/NotificationChannelSweeper.js +131 -0
- package/dist/notifications/NotificationChannelSweeper.jsonld +136 -0
- package/dist/notifications/ReclaimingWebSocket2023Storer.d.ts +25 -0
- package/dist/notifications/ReclaimingWebSocket2023Storer.js +56 -0
- package/dist/notifications/ReclaimingWebSocket2023Storer.jsonld +77 -0
- package/dist/notifications/index.d.ts +2 -0
- package/dist/notifications/index.js +2 -0
- package/dist/runtime/Proxy.d.ts +37 -0
- package/dist/runtime/Proxy.js +88 -16
- package/dist/runtime/bootstrap.js +2 -1
- package/dist/runtime/upgrade/BunNativeUpgradeRelay.d.ts +116 -0
- package/dist/runtime/upgrade/BunNativeUpgradeRelay.js +423 -0
- package/dist/runtime/upgrade/UpgradeHandshake.d.ts +63 -0
- package/dist/runtime/upgrade/UpgradeHandshake.js +199 -0
- package/dist/runtime/upgrade/WebSocketFrames.d.ts +67 -0
- package/dist/runtime/upgrade/WebSocketFrames.js +224 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiApiKeyPool.js +8 -1
- package/node_modules/@undefineds.co/ai-connections/dist/AiAuthorizationActions.d.ts +11 -2
- package/node_modules/@undefineds.co/ai-connections/dist/AiAuthorizationActions.js +27 -10
- package/node_modules/@undefineds.co/ai-connections/dist/AiClientConfigurationSection.d.ts +7 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiClientConfigurationSection.js +13 -11
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectDialog.js +1 -1
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsList.js +10 -6
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsMain.d.ts +15 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsMain.js +29 -3
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsMainHeader.js +18 -3
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.d.ts +16 -1
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.js +92 -20
- package/node_modules/@undefineds.co/ai-connections/dist/AiCopyButton.d.ts +35 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiCopyButton.js +45 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialPoolSection.js +71 -11
- package/node_modules/@undefineds.co/ai-connections/dist/AiCredentialRow.js +9 -7
- package/node_modules/@undefineds.co/ai-connections/dist/AiEndpointList.d.ts +23 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiEndpointList.js +24 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeysSection.d.ts +13 -4
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeysSection.js +35 -38
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayModelsSection.d.ts +21 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayModelsSection.js +51 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiInfoTooltip.d.ts +15 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiInfoTooltip.js +16 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiModelCatalog.d.ts +175 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiModelCatalog.js +133 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiOfferingDetails.js +2 -2
- package/node_modules/@undefineds.co/ai-connections/dist/AiProviderCard.js +13 -64
- package/node_modules/@undefineds.co/ai-connections/dist/AiProviderHeader.d.ts +21 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiProviderHeader.js +12 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiRowAction.d.ts +15 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiRowAction.js +12 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiSortableCredentialList.js +2 -1
- package/node_modules/@undefineds.co/ai-connections/dist/ai-connections-client.d.ts +7 -0
- package/node_modules/@undefineds.co/ai-connections/dist/ai-connections-client.js +6 -0
- package/node_modules/@undefineds.co/ai-connections/dist/authorization-methods.d.ts +36 -5
- package/node_modules/@undefineds.co/ai-connections/dist/authorization-methods.js +52 -9
- package/node_modules/@undefineds.co/ai-connections/dist/client/normalize.js +30 -3
- package/node_modules/@undefineds.co/ai-connections/dist/client/types.d.ts +21 -1
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/base-adapter.d.ts +1 -3
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/base-adapter.js +3 -7
- package/node_modules/@undefineds.co/ai-connections/dist/client-config/index.cjs +9 -7
- package/node_modules/@undefineds.co/ai-connections/dist/collection-runtime.d.ts +46 -0
- package/node_modules/@undefineds.co/ai-connections/dist/collection-runtime.js +231 -0
- package/node_modules/@undefineds.co/ai-connections/dist/collections.d.ts +119 -0
- package/node_modules/@undefineds.co/ai-connections/dist/collections.js +173 -0
- package/node_modules/@undefineds.co/ai-connections/dist/controller.d.ts +71 -5
- package/node_modules/@undefineds.co/ai-connections/dist/controller.js +285 -16
- package/node_modules/@undefineds.co/ai-connections/dist/credential-labels.d.ts +5 -0
- package/node_modules/@undefineds.co/ai-connections/dist/credential-labels.js +8 -3
- package/node_modules/@undefineds.co/ai-connections/dist/credential-storage.d.ts +59 -0
- package/node_modules/@undefineds.co/ai-connections/dist/credential-storage.js +131 -0
- package/node_modules/@undefineds.co/ai-connections/dist/endpoint-urls.d.ts +15 -0
- package/node_modules/@undefineds.co/ai-connections/dist/endpoint-urls.js +20 -0
- package/node_modules/@undefineds.co/ai-connections/dist/gateway-endpoints.d.ts +14 -0
- package/node_modules/@undefineds.co/ai-connections/dist/gateway-endpoints.js +20 -0
- package/node_modules/@undefineds.co/ai-connections/dist/index.d.ts +8 -0
- package/node_modules/@undefineds.co/ai-connections/dist/index.js +8 -0
- package/node_modules/@undefineds.co/ai-connections/dist/manifest.js +1 -1
- package/node_modules/@undefineds.co/ai-connections/dist/offering-endpoints.d.ts +14 -0
- package/node_modules/@undefineds.co/ai-connections/dist/offering-endpoints.js +17 -0
- package/node_modules/@undefineds.co/ai-connections/dist/provider-catalog.cjs +68 -1
- package/node_modules/@undefineds.co/ai-connections/dist/provider-catalog.d.ts +75 -1
- package/node_modules/@undefineds.co/ai-connections/dist/provider-catalog.js +119 -0
- package/node_modules/@undefineds.co/ai-connections/dist/provider-visuals.d.ts +5 -0
- package/node_modules/@undefineds.co/ai-connections/dist/provider-visuals.js +5 -0
- package/node_modules/@undefineds.co/ai-connections/dist/service-access.js +2 -27
- package/node_modules/@undefineds.co/ai-connections/package.json +1 -0
- package/node_modules/@undefineds.co/extension-sdk/dist/manifest.d.ts +1 -1
- package/node_modules/@undefineds.co/extension-sdk/dist/manifest.js +2 -0
- package/node_modules/@undefineds.co/extension-sdk/dist/web.d.ts +150 -0
- package/node_modules/@undefineds.co/extension-sdk/package.json +2 -1
- package/node_modules/@undefineds.co/models/README.md +1 -1
- package/node_modules/@undefineds.co/models/dist/ai-config/index.d.ts +3 -3
- package/node_modules/@undefineds.co/models/dist/ai-gateway.schema.d.ts +5 -0
- package/node_modules/@undefineds.co/models/dist/ai-gateway.schema.js +9 -0
- package/node_modules/@undefineds.co/models/dist/ai-runtime.repository.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/approval.repository.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/audit.presentation.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/capture.repository.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/chat-project.repository.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/chat.repository.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/control-request.repository.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/conversation-share.repository.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/credential.schema.d.ts +12 -0
- package/node_modules/@undefineds.co/models/dist/credential.schema.js +15 -1
- package/node_modules/@undefineds.co/models/dist/discovery/index.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/discovery/providers.json +248 -7
- package/node_modules/@undefineds.co/models/dist/discovery/types.d.ts +31 -0
- package/node_modules/@undefineds.co/models/dist/extension/index.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/favorite/index.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/fixtures/contracts-chat-contact.d.ts +5 -5
- package/node_modules/@undefineds.co/models/dist/import/index.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/index.d.ts +73 -73
- package/node_modules/@undefineds.co/models/dist/index.js +1 -1
- package/node_modules/@undefineds.co/models/dist/input-request.repository.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/knowledge/index.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/message.repository.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/namespaces.js +5 -0
- package/node_modules/@undefineds.co/models/dist/pod-storage-descriptor.d.ts +4815 -26
- package/node_modules/@undefineds.co/models/dist/pod-storage-descriptor.js +482 -132
- package/node_modules/@undefineds.co/models/dist/schema.d.ts +4 -0
- package/node_modules/@undefineds.co/models/dist/session/index.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/settings/index.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/sidecar/persistence-mapping.d.ts +5 -5
- package/node_modules/@undefineds.co/models/dist/thread.repository.d.ts +2 -2
- package/node_modules/@undefineds.co/models/dist/types/message-block.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/vocab/_namespaces.d.ts +1 -1
- package/node_modules/@undefineds.co/models/dist/vocab/index.d.ts +10 -10
- package/node_modules/@undefineds.co/models/dist/vocab/sidecar.vocab.d.ts +1 -0
- package/node_modules/@undefineds.co/models/dist/vocab/sidecar.vocab.js +1 -0
- package/node_modules/@undefineds.co/models/package.json +4 -2
- package/node_modules/@undefineds.co/pod-collections/README.md +71 -0
- package/node_modules/@undefineds.co/pod-collections/dist/diff.d.ts +85 -0
- package/node_modules/@undefineds.co/pod-collections/dist/diff.js +166 -0
- package/node_modules/@undefineds.co/pod-collections/dist/feed.d.ts +17 -0
- package/node_modules/@undefineds.co/pod-collections/dist/feed.js +27 -0
- package/node_modules/@undefineds.co/pod-collections/dist/index.cjs +1042 -0
- package/node_modules/@undefineds.co/pod-collections/dist/index.d.ts +37 -0
- package/node_modules/@undefineds.co/pod-collections/dist/index.js +89 -0
- package/node_modules/@undefineds.co/pod-collections/dist/layout.d.ts +75 -0
- package/node_modules/@undefineds.co/pod-collections/dist/layout.js +173 -0
- package/node_modules/@undefineds.co/pod-collections/dist/mapping.d.ts +78 -0
- package/node_modules/@undefineds.co/pod-collections/dist/mapping.js +287 -0
- package/node_modules/@undefineds.co/pod-collections/dist/mutations.d.ts +83 -0
- package/node_modules/@undefineds.co/pod-collections/dist/mutations.js +273 -0
- package/node_modules/@undefineds.co/pod-collections/dist/react.d.ts +21 -0
- package/node_modules/@undefineds.co/pod-collections/dist/react.js +22 -0
- package/node_modules/@undefineds.co/pod-collections/dist/read.d.ts +65 -0
- package/node_modules/@undefineds.co/pod-collections/dist/read.js +31 -0
- package/node_modules/@undefineds.co/pod-collections/dist/sync.d.ts +66 -0
- package/node_modules/@undefineds.co/pod-collections/dist/sync.js +260 -0
- package/node_modules/@undefineds.co/pod-collections/dist/types.d.ts +155 -0
- package/node_modules/@undefineds.co/pod-collections/dist/types.js +9 -0
- package/node_modules/@undefineds.co/pod-collections/package.json +42 -0
- package/package.json +15 -7
- package/static/app/assets/main.css +1 -1
- package/static/auth-callback/assets/AiConfigContext-DnQs1ZpW.js +1 -0
- package/static/auth-callback/assets/AiConfigPage-DOtvlxH0.js +1 -0
- package/static/auth-callback/assets/DocumentProcessingPanel-BS2voQgL.js +1 -0
- package/static/auth-callback/assets/IndexLifecyclePanel-Cvt0cJtN.js +1 -0
- package/static/auth-callback/assets/{IndexSubjectPanel-BbUqop4b.js → IndexSubjectPanel-Dhf01GqF.js} +1 -1
- package/static/auth-callback/assets/ModelAssignmentsPanel-BJutWaAF.js +1 -0
- package/static/auth-callback/assets/ModelsPage-BRS0sje3.js +11 -0
- package/static/auth-callback/assets/{NetworkPage-Vp2PrMxs.js → NetworkPage-B3qBfANA.js} +2 -2
- package/static/auth-callback/assets/{PaneListHeader-DY7baSFl.js → PaneListHeader-QQeJGTp4.js} +1 -1
- package/static/auth-callback/assets/SearchIndexingPanel-MyNUSEwT.js +1 -0
- package/static/auth-callback/assets/{StatusSubjectPanel-ArIS-TxT.js → StatusSubjectPanel-DQkEVsFs.js} +1 -1
- package/static/{settings/assets/StatusWorkspace-CoMFRXoV.js → auth-callback/assets/StatusWorkspace-Dkv63Uwk.js} +1 -1
- package/static/auth-callback/assets/{SystemSettingsPage-BDvT1NUz.js → SystemSettingsPage-TIsUfX5d.js} +1 -1
- package/static/{dashboard/assets/SystemSettingsSubjectPanel-WaE8mTQi.js → auth-callback/assets/SystemSettingsSubjectPanel-BJWEt2-7.js} +5 -5
- package/static/auth-callback/assets/XpodAiConnectionsPodStore-BJiXm-PF.js +3 -0
- package/static/auth-callback/assets/{activity-D1Dsfa_0.js → activity-5hNeNKnL.js} +1 -1
- package/static/auth-callback/assets/ai-connections-CryuHGKW.js +1 -0
- package/static/auth-callback/assets/{auth-callback-Cmf4hXVZ.js → auth-callback-CAFZ3R0B.js} +6 -6
- package/static/auth-callback/assets/auth-callback-rk080mvG.css +1 -0
- package/static/auth-callback/assets/{badge-CZsHq3Ih.js → badge-CAIPI0CB.js} +1 -1
- package/static/auth-callback/assets/collection-runtime-D9s7h9YA.js +1 -0
- package/static/auth-callback/assets/dialog-BjA109aX.js +1 -0
- package/static/auth-callback/assets/{download-DU9ntlHw.js → download-B3Up5W2G.js} +1 -1
- package/static/auth-callback/assets/{external-link-BfzaaZDx.js → external-link-BTXgSPzB.js} +1 -1
- package/static/auth-callback/assets/index-BppXlxcp.js +41 -0
- package/static/auth-callback/assets/index-CirW4CJf.js +1 -0
- package/static/auth-callback/assets/index-DlLYWOhw.js +4 -0
- package/static/auth-callback/assets/{index-browser-BNFqqC74.js → index-browser-DtU38ni3.js} +1 -1
- package/static/auth-callback/assets/{key-round-BwP3DBWo.js → key-round-CQCOrZ7x.js} +1 -1
- package/static/auth-callback/assets/layout-DB3pMyTl.js +1 -0
- package/static/auth-callback/assets/pod-collections-host-KnnGFZHL.js +8 -0
- package/static/auth-callback/assets/{rotate-ccw-VMwnmyab.js → rotate-ccw-C1zM2KtS.js} +1 -1
- package/static/auth-callback/assets/{skeleton-CoD55rBT.js → skeleton-Cqp7_M9-.js} +1 -1
- package/static/auth-callback/assets/{waypoints-DRo_1Ca7.js → waypoints-Bj6gAUSQ.js} +1 -1
- package/static/auth-callback/assets/{workspace-layout--mcXl3My.js → workspace-layout-DK8mDzrY.js} +1 -1
- package/static/auth-callback/auth-callback.html +2 -2
- package/static/dashboard/assets/AiConfigContext-BsE7MqX8.js +1 -0
- package/static/dashboard/assets/AiConfigPage-DvM-lRXa.js +1 -0
- package/static/dashboard/assets/DocumentProcessingPanel-BPfdlfuf.js +1 -0
- package/static/dashboard/assets/IndexLifecyclePanel--m0AGxvh.js +1 -0
- package/static/dashboard/assets/{IndexSubjectPanel-B2cXwl8X.js → IndexSubjectPanel-Bb7m1k3d.js} +1 -1
- package/static/dashboard/assets/ModelAssignmentsPanel-BLi_zbMa.js +1 -0
- package/static/dashboard/assets/ModelsPage-CxdpgnfR.js +11 -0
- package/static/dashboard/assets/{NetworkPage-DV2V0qWO.js → NetworkPage-BAIPw-D_.js} +2 -2
- package/static/dashboard/assets/{PaneListHeader-D0c1yCFH.js → PaneListHeader-BBCMei0r.js} +1 -1
- package/static/dashboard/assets/SearchIndexingPanel-Ck4Y-xjR.js +1 -0
- package/static/dashboard/assets/{StatusSubjectPanel-oPSECj7i.js → StatusSubjectPanel-D1KWfAXE.js} +1 -1
- package/static/dashboard/assets/{StatusWorkspace-PdovQPKa.js → StatusWorkspace-JbA5gzXx.js} +1 -1
- package/static/dashboard/assets/{SystemSettingsPage-CtNDklkx.js → SystemSettingsPage-BbwQWsSR.js} +1 -1
- package/static/{settings/assets/SystemSettingsSubjectPanel-DExjDo_v.js → dashboard/assets/SystemSettingsSubjectPanel-N117nMt5.js} +5 -5
- package/static/dashboard/assets/XpodAiConnectionsPodStore-CdDOb4SV.js +18 -0
- package/static/dashboard/assets/{activity-B9ylSoyr.js → activity-DX1I96o_.js} +1 -1
- package/static/dashboard/assets/ai-connections-DwCRqOQa.js +1 -0
- package/static/dashboard/assets/{badge-BNbFbpIb.js → badge-k2vhtDqH.js} +1 -1
- package/static/dashboard/assets/collection-runtime-BFQ8teQJ.js +1 -0
- package/static/dashboard/assets/{dashboard-CD-FFVRD.js → dashboard-DWZ-fmCT.js} +4 -4
- package/static/dashboard/assets/dashboard-rk080mvG.css +1 -0
- package/static/dashboard/assets/dialog-1CCw-iHT.js +1 -0
- package/static/dashboard/assets/{download-nOP38LtW.js → download-C6-SNY1q.js} +1 -1
- package/static/dashboard/assets/{external-link-Bh2ewN9E.js → external-link-BgPcZ_j2.js} +1 -1
- package/static/dashboard/assets/index-6LcIUIYO.js +1 -0
- package/static/dashboard/assets/index-D7A8U6Pt.js +41 -0
- package/static/dashboard/assets/index-UD6QOE7H.js +4 -0
- package/static/dashboard/assets/{key-round-bGmguBLv.js → key-round-BOd7Jo0Q.js} +1 -1
- package/static/dashboard/assets/layout-DB3pMyTl.js +1 -0
- package/static/dashboard/assets/pod-collections-host-KnnGFZHL.js +8 -0
- package/static/dashboard/assets/{rotate-ccw-D2x__ODW.js → rotate-ccw-CCgJqsvx.js} +1 -1
- package/static/dashboard/assets/{skeleton-VOqft8WS.js → skeleton-Bc7abAn5.js} +1 -1
- package/static/dashboard/assets/{waypoints-fgRqm4oH.js → waypoints-s-opmJxx.js} +1 -1
- package/static/dashboard/assets/{workspace-layout-DV4dgeHX.js → workspace-layout-DqIQeTBV.js} +1 -1
- package/static/dashboard/dashboard.html +2 -2
- package/static/settings/assets/AiConfigContext-BB9KZySa.js +1 -0
- package/static/settings/assets/AiConfigPage-DGSXUkLs.js +1 -0
- package/static/settings/assets/DocumentProcessingPanel-Da2Re6Rg.js +1 -0
- package/static/settings/assets/IndexLifecyclePanel-BSZuIzgr.js +1 -0
- package/static/settings/assets/{IndexSubjectPanel-BgbI9c-a.js → IndexSubjectPanel-CFd0ay-r.js} +1 -1
- package/static/settings/assets/ModelAssignmentsPanel-CSAryvWJ.js +1 -0
- package/static/settings/assets/ModelsPage-BQwCwLHU.js +11 -0
- package/static/settings/assets/{NetworkPage-C8OA9Mtp.js → NetworkPage-BKymvsQc.js} +2 -2
- package/static/settings/assets/{PaneListHeader-COvlPJWj.js → PaneListHeader-Bjh3hRdQ.js} +1 -1
- package/static/settings/assets/SearchIndexingPanel-MjKL5QLU.js +1 -0
- package/static/settings/assets/{StatusSubjectPanel-BuLml7qn.js → StatusSubjectPanel-Bvl6K4mx.js} +1 -1
- package/static/settings/assets/StatusWorkspace-B0NzrP--.js +1 -0
- package/static/settings/assets/{SystemSettingsPage-DlzmaWV-.js → SystemSettingsPage-D2z6Z4FE.js} +1 -1
- package/static/{auth-callback/assets/SystemSettingsSubjectPanel-CDqRuC4t.js → settings/assets/SystemSettingsSubjectPanel-4sxma4X4.js} +5 -5
- package/static/settings/assets/XpodAiConnectionsPodStore-BkNQ8fZx.js +3 -0
- package/static/settings/assets/{activity-TLerXgMs.js → activity-CgJJGpjx.js} +1 -1
- package/static/settings/assets/ai-connections-CryuHGKW.js +1 -0
- package/static/settings/assets/{badge-Bcs8iWrH.js → badge-C4NypVyT.js} +1 -1
- package/static/settings/assets/collection-runtime-CTLCDxAi.js +1 -0
- package/static/settings/assets/dialog-Csq0vWUi.js +1 -0
- package/static/settings/assets/{download-Ct3QmHPt.js → download-DaLJJ-Wp.js} +1 -1
- package/static/settings/assets/{external-link-C8KiHbss.js → external-link--w_iW5Au.js} +1 -1
- package/static/settings/assets/index-B0mQa59b.js +4 -0
- package/static/settings/assets/index-BukHiu4y.js +1 -0
- package/static/settings/assets/index-COmVnZi2.js +41 -0
- package/static/settings/assets/{index-browser-CazX1pc2.js → index-browser-BGpvHwD0.js} +1 -1
- package/static/settings/assets/{key-round-B19YD1GA.js → key-round-Bk4YRjBu.js} +1 -1
- package/static/settings/assets/layout-DB3pMyTl.js +1 -0
- package/static/settings/assets/pod-collections-host-KnnGFZHL.js +8 -0
- package/static/settings/assets/{rotate-ccw-AQm2kMgU.js → rotate-ccw-TCabbqsr.js} +1 -1
- package/static/settings/assets/{settings-C-VBtt9r.js → settings-CJWpdbNC.js} +5 -5
- package/static/settings/assets/settings-rk080mvG.css +1 -0
- package/static/settings/assets/{skeleton-DyZ1OBYf.js → skeleton-JDHYVe7t.js} +1 -1
- package/static/settings/assets/{waypoints-CC3wq-SU.js → waypoints-DDvEl-MU.js} +1 -1
- package/static/settings/assets/{workspace-layout-BxXNKgf9.js → workspace-layout-DV5QU30U.js} +1 -1
- package/static/settings/settings.html +2 -2
- package/static/auth-callback/assets/AiConfigContext-DqWRSm7n.js +0 -1
- package/static/auth-callback/assets/AiConfigPage-C5YYyvzl.js +0 -1
- package/static/auth-callback/assets/DocumentProcessingPanel-DZCiacBz.js +0 -1
- package/static/auth-callback/assets/IndexLifecyclePanel-CCLeOljB.js +0 -1
- package/static/auth-callback/assets/ModelAssignmentsPanel-jUUTDKuh.js +0 -1
- package/static/auth-callback/assets/ModelsPage-B08zdtff.js +0 -10
- package/static/auth-callback/assets/SearchIndexingPanel-D4YRg1-8.js +0 -1
- package/static/auth-callback/assets/StatusWorkspace-Cp5LQ9Yx.js +0 -1
- package/static/auth-callback/assets/ai-connections-CHNTKemd.js +0 -1
- package/static/auth-callback/assets/auth-callback-DWMMiFjh.css +0 -1
- package/static/auth-callback/assets/index-DSNnLUbU.js +0 -4
- package/static/auth-callback/assets/index-FHhHoKgp.js +0 -41
- package/static/dashboard/assets/AiConfigContext-BpPDKSzI.js +0 -1
- package/static/dashboard/assets/AiConfigPage-wsqEZDIX.js +0 -1
- package/static/dashboard/assets/DocumentProcessingPanel-CDSy3juc.js +0 -1
- package/static/dashboard/assets/IndexLifecyclePanel-CVd6vQCX.js +0 -1
- package/static/dashboard/assets/ModelAssignmentsPanel-BeBZhnQd.js +0 -1
- package/static/dashboard/assets/ModelsPage-B6McSCJw.js +0 -25
- package/static/dashboard/assets/SearchIndexingPanel-CGs0OZ12.js +0 -1
- package/static/dashboard/assets/ai-connections-CHNTKemd.js +0 -1
- package/static/dashboard/assets/dashboard-DWMMiFjh.css +0 -1
- package/static/dashboard/assets/index-PgS-Bt7X.js +0 -41
- package/static/dashboard/assets/index-QN2QgEwr.js +0 -4
- package/static/settings/assets/AiConfigContext-zKQYdfai.js +0 -1
- package/static/settings/assets/AiConfigPage-Bs1EE3Ei.js +0 -1
- package/static/settings/assets/DocumentProcessingPanel-CSFfdOXS.js +0 -1
- package/static/settings/assets/IndexLifecyclePanel-BR9Su49B.js +0 -1
- package/static/settings/assets/ModelAssignmentsPanel-C0BE7nbk.js +0 -1
- package/static/settings/assets/ModelsPage-CU-YQ8_7.js +0 -10
- package/static/settings/assets/SearchIndexingPanel-Bdd46mIV.js +0 -1
- package/static/settings/assets/ai-connections-CHNTKemd.js +0 -1
- package/static/settings/assets/index-1Q2cRjZd.js +0 -41
- package/static/settings/assets/index-DBO_Vq0P.js +0 -4
- package/static/settings/assets/settings-DWMMiFjh.css +0 -1
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createWebSocketKey = createWebSocketKey;
|
|
4
|
+
exports.buildUpstreamUpgradeRequest = buildUpstreamUpgradeRequest;
|
|
5
|
+
exports.parseUpgradeHandshakeResponse = parseUpgradeHandshakeResponse;
|
|
6
|
+
exports.selectedProtocol = selectedProtocol;
|
|
7
|
+
exports.isWebSocketUpgrade = isWebSocketUpgrade;
|
|
8
|
+
exports.parseRequestedProtocols = parseRequestedProtocols;
|
|
9
|
+
exports.writeUpgradeSocketBytes = writeUpgradeSocketBytes;
|
|
10
|
+
exports.endUpgradeSocket = endUpgradeSocket;
|
|
11
|
+
exports.writeUpgradeErrorResponse = writeUpgradeErrorResponse;
|
|
12
|
+
exports.forwardedHeaderValues = forwardedHeaderValues;
|
|
13
|
+
const node_crypto_1 = require("node:crypto");
|
|
14
|
+
/**
|
|
15
|
+
* HTTP handshake helpers for the gateway's upgrade relay.
|
|
16
|
+
*
|
|
17
|
+
* Upgrade requests are relayed to the internal services byte-for-byte, so the
|
|
18
|
+
* relay has to build the upstream request itself (see `BunNativeUpgradeRelay`).
|
|
19
|
+
* Keeping the header rules here makes them unit-testable and keeps the HTTP
|
|
20
|
+
* semantics of the gateway in one place.
|
|
21
|
+
*/
|
|
22
|
+
/** RFC 7230 hop-by-hop headers: never forwarded to the next hop. */
|
|
23
|
+
const HOP_BY_HOP_HEADERS = new Set([
|
|
24
|
+
'connection',
|
|
25
|
+
'keep-alive',
|
|
26
|
+
'proxy-authenticate',
|
|
27
|
+
'proxy-authorization',
|
|
28
|
+
'te',
|
|
29
|
+
'trailer',
|
|
30
|
+
'transfer-encoding',
|
|
31
|
+
'upgrade',
|
|
32
|
+
]);
|
|
33
|
+
/**
|
|
34
|
+
* Headers that belong to a single WebSocket handshake on one hop. They are set
|
|
35
|
+
* by the relay (or by the WebSocket implementation) for the upstream hop and
|
|
36
|
+
* must not be copied from the client request.
|
|
37
|
+
*/
|
|
38
|
+
const HANDSHAKE_HEADERS = new Set([
|
|
39
|
+
'sec-websocket-accept',
|
|
40
|
+
'sec-websocket-extensions',
|
|
41
|
+
'sec-websocket-key',
|
|
42
|
+
'sec-websocket-version',
|
|
43
|
+
// The relay never forwards a request body, so a content-length from the
|
|
44
|
+
// client must not make the upstream wait for one.
|
|
45
|
+
'content-length',
|
|
46
|
+
]);
|
|
47
|
+
function createWebSocketKey() {
|
|
48
|
+
return (0, node_crypto_1.randomBytes)(16).toString('base64');
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Builds the raw HTTP upgrade request that is sent to the internal service.
|
|
52
|
+
* The client's `Host` and its application headers (authorization, cookies,
|
|
53
|
+
* origin, DPoP, custom `X-*`, ...) are forwarded unchanged so the internal
|
|
54
|
+
* server answers exactly as it would for a direct connection.
|
|
55
|
+
*/
|
|
56
|
+
function buildUpstreamUpgradeRequest(options) {
|
|
57
|
+
const headers = new Map();
|
|
58
|
+
for (const [name, value] of Object.entries(options.headers)) {
|
|
59
|
+
const lower = name.toLowerCase();
|
|
60
|
+
if (HOP_BY_HOP_HEADERS.has(lower) || HANDSHAKE_HEADERS.has(lower) || value === undefined) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
headers.set(lower, Array.isArray(value) ? value.join(', ') : String(value));
|
|
64
|
+
}
|
|
65
|
+
appendForwarded(headers, 'x-forwarded-for', options.forwardedFor);
|
|
66
|
+
appendForwarded(headers, 'x-forwarded-port', options.forwardedPort);
|
|
67
|
+
appendForwarded(headers, 'x-forwarded-proto', options.forwardedProto);
|
|
68
|
+
headers.set('upgrade', 'websocket');
|
|
69
|
+
headers.set('connection', 'Upgrade');
|
|
70
|
+
headers.set('sec-websocket-key', options.key ?? createWebSocketKey());
|
|
71
|
+
headers.set('sec-websocket-version', '13');
|
|
72
|
+
if (options.protocols.length > 0) {
|
|
73
|
+
headers.set('sec-websocket-protocol', options.protocols.join(', '));
|
|
74
|
+
}
|
|
75
|
+
const lines = [`GET ${options.path} HTTP/1.1`];
|
|
76
|
+
for (const [name, value] of headers) {
|
|
77
|
+
lines.push(`${name}: ${value}`);
|
|
78
|
+
}
|
|
79
|
+
lines.push('', '');
|
|
80
|
+
return Buffer.from(lines.join('\r\n'), 'latin1');
|
|
81
|
+
}
|
|
82
|
+
function appendForwarded(headers, name, value) {
|
|
83
|
+
if (!value) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const existing = headers.get(name);
|
|
87
|
+
headers.set(name, existing ? `${existing},${value}` : value);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Parses the beginning of the upstream upgrade response.
|
|
91
|
+
* @returns the parsed response, or `undefined` while the header block is incomplete.
|
|
92
|
+
*/
|
|
93
|
+
function parseUpgradeHandshakeResponse(buffer) {
|
|
94
|
+
const boundary = buffer.indexOf('\r\n\r\n');
|
|
95
|
+
if (boundary < 0) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
const headerBlock = buffer.subarray(0, boundary).toString('latin1');
|
|
99
|
+
const lines = headerBlock.split('\r\n');
|
|
100
|
+
const statusLine = lines.shift() ?? '';
|
|
101
|
+
const match = /^HTTP\/\d\.\d (\d{3}) ?(.*)$/.exec(statusLine);
|
|
102
|
+
if (!match) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
const headers = {};
|
|
106
|
+
for (const line of lines) {
|
|
107
|
+
const separator = line.indexOf(':');
|
|
108
|
+
if (separator <= 0) {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const name = line.slice(0, separator).trim().toLowerCase();
|
|
112
|
+
const value = line.slice(separator + 1).trim();
|
|
113
|
+
headers[name] = headers[name] ? `${headers[name]}, ${value}` : value;
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
statusCode: Number(match[1]),
|
|
117
|
+
statusMessage: match[2] ?? '',
|
|
118
|
+
headers,
|
|
119
|
+
head: buffer.subarray(0, boundary + 4),
|
|
120
|
+
rest: buffer.subarray(boundary + 4),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/** Subprotocol selected by the upstream server, if any. */
|
|
124
|
+
function selectedProtocol(response) {
|
|
125
|
+
const value = response.headers['sec-websocket-protocol'];
|
|
126
|
+
return value ? value.split(',')[0].trim() : '';
|
|
127
|
+
}
|
|
128
|
+
/** True when the upstream actually switched protocols to WebSocket. */
|
|
129
|
+
function isWebSocketUpgrade(response) {
|
|
130
|
+
return response.statusCode === 101 && (response.headers.upgrade ?? '').toLowerCase() === 'websocket';
|
|
131
|
+
}
|
|
132
|
+
function parseRequestedProtocols(header) {
|
|
133
|
+
const value = Array.isArray(header) ? header.join(',') : header;
|
|
134
|
+
if (!value) {
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
return value.split(',').map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Writes raw bytes to a socket handed over by the HTTP server's `upgrade` event.
|
|
141
|
+
*
|
|
142
|
+
* Bun's `node:http` server hands the upgrade listener a socket shim whose
|
|
143
|
+
* `write()` never reaches the peer (`socket.write()` returns `true` and the
|
|
144
|
+
* bytes are dropped), which is why the gateway cannot use `http-proxy`'s
|
|
145
|
+
* WebSocket pass there. The underlying Bun socket handle still writes
|
|
146
|
+
* correctly, so error responses are written through it; on every other runtime
|
|
147
|
+
* the regular socket write is used.
|
|
148
|
+
*/
|
|
149
|
+
function writeUpgradeSocketBytes(socket, chunk) {
|
|
150
|
+
const handle = findBunSocketHandle(socket);
|
|
151
|
+
if (handle) {
|
|
152
|
+
handle.write(chunk);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
socket.write(chunk);
|
|
156
|
+
}
|
|
157
|
+
function endUpgradeSocket(socket) {
|
|
158
|
+
const handle = findBunSocketHandle(socket);
|
|
159
|
+
if (handle?.end) {
|
|
160
|
+
handle.end();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
socket.end();
|
|
164
|
+
}
|
|
165
|
+
function findBunSocketHandle(socket) {
|
|
166
|
+
for (const symbol of Object.getOwnPropertySymbols(socket)) {
|
|
167
|
+
if (symbol.description !== 'handle') {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const handle = socket[symbol];
|
|
171
|
+
if (handle && typeof handle.write === 'function') {
|
|
172
|
+
return handle;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
/** Writes a complete HTTP response to an upgrade request that could not be relayed. */
|
|
178
|
+
function writeUpgradeErrorResponse(socket, statusCode, statusMessage, headers, body) {
|
|
179
|
+
const payload = Buffer.from(body, 'utf8');
|
|
180
|
+
const lines = [`HTTP/1.1 ${statusCode} ${statusMessage}`];
|
|
181
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
182
|
+
lines.push(`${name}: ${value}`);
|
|
183
|
+
}
|
|
184
|
+
lines.push(`Content-Length: ${payload.length}`, 'Connection: close', '', '');
|
|
185
|
+
writeUpgradeSocketBytes(socket, Buffer.concat([Buffer.from(lines.join('\r\n'), 'latin1'), payload]));
|
|
186
|
+
endUpgradeSocket(socket);
|
|
187
|
+
}
|
|
188
|
+
/** Best-effort `X-Forwarded-*` values matching `http-proxy`'s `xfwd: true`. */
|
|
189
|
+
function forwardedHeaderValues(req) {
|
|
190
|
+
const host = Array.isArray(req.headers.host) ? req.headers.host[0] : req.headers.host;
|
|
191
|
+
const port = host?.match(/:(\d+)/)?.[1];
|
|
192
|
+
const encrypted = Boolean(req.socket.encrypted);
|
|
193
|
+
return {
|
|
194
|
+
forwardedFor: req.socket.remoteAddress,
|
|
195
|
+
forwardedPort: port ?? (encrypted ? '443' : '80'),
|
|
196
|
+
forwardedProto: encrypted ? 'wss' : 'ws',
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=UpgradeHandshake.js.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal RFC 6455 frame codec used by the gateway's native (Bun) WebSocket
|
|
3
|
+
* upgrade relay.
|
|
4
|
+
*
|
|
5
|
+
* The gateway only needs it on runtimes whose HTTP server cannot hand the raw
|
|
6
|
+
* upgraded socket back to JavaScript (see `BunNativeUpgradeRelay`): there the
|
|
7
|
+
* client side is a native WebSocket (message level), while the upstream side is
|
|
8
|
+
* a raw socket, so frames have to be decoded/encoded in between.
|
|
9
|
+
*
|
|
10
|
+
* The codec deliberately implements a single, predictable flavour of the
|
|
11
|
+
* protocol: no extensions (the relay never offers `permessage-deflate`), no
|
|
12
|
+
* fragmentation on the outbound path (one frame per message) and a bounded
|
|
13
|
+
* inbound message size.
|
|
14
|
+
*/
|
|
15
|
+
export declare const WS_OPCODE: {
|
|
16
|
+
readonly continuation: 0;
|
|
17
|
+
readonly text: 1;
|
|
18
|
+
readonly binary: 2;
|
|
19
|
+
readonly close: 8;
|
|
20
|
+
readonly ping: 9;
|
|
21
|
+
readonly pong: 10;
|
|
22
|
+
};
|
|
23
|
+
export type WebSocketFrameOpcode = typeof WS_OPCODE[keyof typeof WS_OPCODE];
|
|
24
|
+
/** Close code used when the peer violates the protocol. */
|
|
25
|
+
export declare const WS_CLOSE_PROTOCOL_ERROR = 1002;
|
|
26
|
+
/** Close code used when a message exceeds the configured size limit. */
|
|
27
|
+
export declare const WS_CLOSE_MESSAGE_TOO_BIG = 1009;
|
|
28
|
+
export interface EncodeWebSocketFrameOptions {
|
|
29
|
+
opcode: WebSocketFrameOpcode;
|
|
30
|
+
/** Client-to-server frames must be masked; server-to-client frames must not. */
|
|
31
|
+
mask: boolean;
|
|
32
|
+
/** Deterministic mask key, for tests only. */
|
|
33
|
+
maskKey?: Buffer;
|
|
34
|
+
}
|
|
35
|
+
export declare function encodeWebSocketFrame(payload: Buffer, options: EncodeWebSocketFrameOptions): Buffer;
|
|
36
|
+
/** Encodes a close frame body (`code` + UTF-8 reason). */
|
|
37
|
+
export declare function encodeWebSocketClosePayload(code: number, reason: string): Buffer;
|
|
38
|
+
export interface WebSocketFrameSink {
|
|
39
|
+
/** A complete (possibly reassembled) data message. */
|
|
40
|
+
onMessage(payload: Buffer, isBinary: boolean): void;
|
|
41
|
+
onPing(payload: Buffer): void;
|
|
42
|
+
onPong(payload: Buffer): void;
|
|
43
|
+
onClose(code: number, reason: string): void;
|
|
44
|
+
/** The peer sent something that violates the protocol; the connection should be closed with 1002. */
|
|
45
|
+
onProtocolError(reason: string): void;
|
|
46
|
+
}
|
|
47
|
+
export interface WebSocketFrameParserOptions {
|
|
48
|
+
/** Upper bound for a single (reassembled) message; oversized messages raise a protocol error. */
|
|
49
|
+
maxMessageBytes?: number;
|
|
50
|
+
}
|
|
51
|
+
export declare class WebSocketFrameParser {
|
|
52
|
+
private readonly sink;
|
|
53
|
+
private buffer;
|
|
54
|
+
private fragmentOpcode;
|
|
55
|
+
private fragments;
|
|
56
|
+
private fragmentBytes;
|
|
57
|
+
private failed;
|
|
58
|
+
private readonly maxMessageBytes;
|
|
59
|
+
constructor(sink: WebSocketFrameSink, options?: WebSocketFrameParserOptions);
|
|
60
|
+
push(chunk: Buffer): void;
|
|
61
|
+
private fail;
|
|
62
|
+
/** @returns whether a complete frame was consumed. */
|
|
63
|
+
private parseFrame;
|
|
64
|
+
private handleFrame;
|
|
65
|
+
private appendFragment;
|
|
66
|
+
private completeMessage;
|
|
67
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebSocketFrameParser = exports.WS_CLOSE_MESSAGE_TOO_BIG = exports.WS_CLOSE_PROTOCOL_ERROR = exports.WS_OPCODE = void 0;
|
|
4
|
+
exports.encodeWebSocketFrame = encodeWebSocketFrame;
|
|
5
|
+
exports.encodeWebSocketClosePayload = encodeWebSocketClosePayload;
|
|
6
|
+
const node_crypto_1 = require("node:crypto");
|
|
7
|
+
/**
|
|
8
|
+
* Minimal RFC 6455 frame codec used by the gateway's native (Bun) WebSocket
|
|
9
|
+
* upgrade relay.
|
|
10
|
+
*
|
|
11
|
+
* The gateway only needs it on runtimes whose HTTP server cannot hand the raw
|
|
12
|
+
* upgraded socket back to JavaScript (see `BunNativeUpgradeRelay`): there the
|
|
13
|
+
* client side is a native WebSocket (message level), while the upstream side is
|
|
14
|
+
* a raw socket, so frames have to be decoded/encoded in between.
|
|
15
|
+
*
|
|
16
|
+
* The codec deliberately implements a single, predictable flavour of the
|
|
17
|
+
* protocol: no extensions (the relay never offers `permessage-deflate`), no
|
|
18
|
+
* fragmentation on the outbound path (one frame per message) and a bounded
|
|
19
|
+
* inbound message size.
|
|
20
|
+
*/
|
|
21
|
+
exports.WS_OPCODE = {
|
|
22
|
+
continuation: 0x0,
|
|
23
|
+
text: 0x1,
|
|
24
|
+
binary: 0x2,
|
|
25
|
+
close: 0x8,
|
|
26
|
+
ping: 0x9,
|
|
27
|
+
pong: 0xa,
|
|
28
|
+
};
|
|
29
|
+
/** Close code used when the peer violates the protocol. */
|
|
30
|
+
exports.WS_CLOSE_PROTOCOL_ERROR = 1002;
|
|
31
|
+
/** Close code used when a message exceeds the configured size limit. */
|
|
32
|
+
exports.WS_CLOSE_MESSAGE_TOO_BIG = 1009;
|
|
33
|
+
function encodeWebSocketFrame(payload, options) {
|
|
34
|
+
const { opcode, mask } = options;
|
|
35
|
+
const length = payload.length;
|
|
36
|
+
const lengthBytes = length < 126 ? 1 : length <= 0xffff ? 3 : 9;
|
|
37
|
+
const maskBytes = mask ? 4 : 0;
|
|
38
|
+
const frame = Buffer.allocUnsafe(1 + lengthBytes + maskBytes + length);
|
|
39
|
+
frame[0] = 0x80 | opcode;
|
|
40
|
+
let offset;
|
|
41
|
+
if (length < 126) {
|
|
42
|
+
frame[1] = (mask ? 0x80 : 0) | length;
|
|
43
|
+
offset = 2;
|
|
44
|
+
}
|
|
45
|
+
else if (length <= 0xffff) {
|
|
46
|
+
frame[1] = (mask ? 0x80 : 0) | 126;
|
|
47
|
+
frame.writeUInt16BE(length, 2);
|
|
48
|
+
offset = 4;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
frame[1] = (mask ? 0x80 : 0) | 127;
|
|
52
|
+
frame.writeBigUInt64BE(BigInt(length), 2);
|
|
53
|
+
offset = 10;
|
|
54
|
+
}
|
|
55
|
+
if (!mask) {
|
|
56
|
+
payload.copy(frame, offset);
|
|
57
|
+
return frame;
|
|
58
|
+
}
|
|
59
|
+
const maskKey = options.maskKey ?? (0, node_crypto_1.randomBytes)(4);
|
|
60
|
+
maskKey.copy(frame, offset);
|
|
61
|
+
for (let index = 0; index < length; index++) {
|
|
62
|
+
frame[offset + 4 + index] = payload[index] ^ maskKey[index % 4];
|
|
63
|
+
}
|
|
64
|
+
return frame;
|
|
65
|
+
}
|
|
66
|
+
/** Encodes a close frame body (`code` + UTF-8 reason). */
|
|
67
|
+
function encodeWebSocketClosePayload(code, reason) {
|
|
68
|
+
const reasonBytes = Buffer.from(reason, 'utf8');
|
|
69
|
+
const payload = Buffer.allocUnsafe(2 + reasonBytes.length);
|
|
70
|
+
payload.writeUInt16BE(code, 0);
|
|
71
|
+
reasonBytes.copy(payload, 2);
|
|
72
|
+
return payload;
|
|
73
|
+
}
|
|
74
|
+
const DEFAULT_MAX_MESSAGE_BYTES = 64 * 1024 * 1024;
|
|
75
|
+
class WebSocketFrameParser {
|
|
76
|
+
constructor(sink, options = {}) {
|
|
77
|
+
this.sink = sink;
|
|
78
|
+
this.buffer = Buffer.alloc(0);
|
|
79
|
+
this.fragments = [];
|
|
80
|
+
this.fragmentBytes = 0;
|
|
81
|
+
this.failed = false;
|
|
82
|
+
this.maxMessageBytes = options.maxMessageBytes ?? DEFAULT_MAX_MESSAGE_BYTES;
|
|
83
|
+
}
|
|
84
|
+
push(chunk) {
|
|
85
|
+
if (this.failed || chunk.length === 0) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
this.buffer = this.buffer.length === 0 ? chunk : Buffer.concat([this.buffer, chunk]);
|
|
89
|
+
while (!this.failed && this.parseFrame()) {
|
|
90
|
+
// Keep consuming buffered frames.
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
fail(reason) {
|
|
94
|
+
this.failed = true;
|
|
95
|
+
this.buffer = Buffer.alloc(0);
|
|
96
|
+
this.fragments = [];
|
|
97
|
+
this.fragmentOpcode = undefined;
|
|
98
|
+
this.sink.onProtocolError(reason);
|
|
99
|
+
}
|
|
100
|
+
/** @returns whether a complete frame was consumed. */
|
|
101
|
+
parseFrame() {
|
|
102
|
+
const buffer = this.buffer;
|
|
103
|
+
if (buffer.length < 2) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
const fin = (buffer[0] & 0x80) !== 0;
|
|
107
|
+
const reserved = buffer[0] & 0x70;
|
|
108
|
+
const opcode = (buffer[0] & 0x0f);
|
|
109
|
+
const masked = (buffer[1] & 0x80) !== 0;
|
|
110
|
+
let payloadLength = buffer[1] & 0x7f;
|
|
111
|
+
let offset = 2;
|
|
112
|
+
if (reserved !== 0) {
|
|
113
|
+
this.fail('reserved frame bits set without a negotiated extension');
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
if (payloadLength === 126) {
|
|
117
|
+
if (buffer.length < offset + 2) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
payloadLength = buffer.readUInt16BE(offset);
|
|
121
|
+
offset += 2;
|
|
122
|
+
}
|
|
123
|
+
else if (payloadLength === 127) {
|
|
124
|
+
if (buffer.length < offset + 8) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
const big = buffer.readBigUInt64BE(offset);
|
|
128
|
+
if (big > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
129
|
+
this.fail('frame payload length is out of range');
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
payloadLength = Number(big);
|
|
133
|
+
offset += 8;
|
|
134
|
+
}
|
|
135
|
+
const isControl = (opcode & 0x8) !== 0;
|
|
136
|
+
if (isControl && (!fin || payloadLength > 125)) {
|
|
137
|
+
this.fail('invalid control frame');
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
const maskBytes = masked ? 4 : 0;
|
|
141
|
+
if (payloadLength > this.maxMessageBytes || this.fragmentBytes + payloadLength > this.maxMessageBytes) {
|
|
142
|
+
this.fail('message exceeds the configured size limit');
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
if (buffer.length < offset + maskBytes + payloadLength) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
const maskKey = masked ? buffer.subarray(offset, offset + 4) : undefined;
|
|
149
|
+
offset += maskBytes;
|
|
150
|
+
const payload = Buffer.from(buffer.subarray(offset, offset + payloadLength));
|
|
151
|
+
this.buffer = buffer.subarray(offset + payloadLength);
|
|
152
|
+
if (maskKey) {
|
|
153
|
+
for (let index = 0; index < payload.length; index++) {
|
|
154
|
+
payload[index] = payload[index] ^ maskKey[index % 4];
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
this.handleFrame(fin, opcode, payload);
|
|
158
|
+
return !this.failed;
|
|
159
|
+
}
|
|
160
|
+
handleFrame(fin, opcode, payload) {
|
|
161
|
+
switch (opcode) {
|
|
162
|
+
case exports.WS_OPCODE.continuation:
|
|
163
|
+
if (this.fragmentOpcode === undefined) {
|
|
164
|
+
this.fail('continuation frame without a started message');
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
this.appendFragment(payload);
|
|
168
|
+
if (fin) {
|
|
169
|
+
this.completeMessage();
|
|
170
|
+
}
|
|
171
|
+
return;
|
|
172
|
+
case exports.WS_OPCODE.text:
|
|
173
|
+
case exports.WS_OPCODE.binary:
|
|
174
|
+
if (this.fragmentOpcode !== undefined) {
|
|
175
|
+
this.fail('new data frame while a fragmented message is in progress');
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
this.fragmentOpcode = opcode;
|
|
179
|
+
this.appendFragment(payload);
|
|
180
|
+
if (fin) {
|
|
181
|
+
this.completeMessage();
|
|
182
|
+
}
|
|
183
|
+
return;
|
|
184
|
+
case exports.WS_OPCODE.close: {
|
|
185
|
+
if (payload.length === 1) {
|
|
186
|
+
this.fail('close frame with a 1 byte payload');
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
// The close frame ends the data stream: nothing after it is dispatched.
|
|
190
|
+
this.failed = true;
|
|
191
|
+
this.buffer = Buffer.alloc(0);
|
|
192
|
+
this.sink.onClose(payload.length === 0 ? 1005 : payload.readUInt16BE(0), payload.subarray(2).toString('utf8'));
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
case exports.WS_OPCODE.ping:
|
|
196
|
+
this.sink.onPing(payload);
|
|
197
|
+
return;
|
|
198
|
+
case exports.WS_OPCODE.pong:
|
|
199
|
+
this.sink.onPong(payload);
|
|
200
|
+
return;
|
|
201
|
+
default:
|
|
202
|
+
this.fail(`unsupported opcode ${opcode}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
appendFragment(payload) {
|
|
206
|
+
this.fragmentBytes += payload.length;
|
|
207
|
+
if (this.fragmentBytes > this.maxMessageBytes) {
|
|
208
|
+
this.fail('message exceeds the configured size limit');
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
this.fragments.push(payload);
|
|
212
|
+
}
|
|
213
|
+
completeMessage() {
|
|
214
|
+
const opcode = this.fragmentOpcode;
|
|
215
|
+
const fragments = this.fragments;
|
|
216
|
+
this.fragmentOpcode = undefined;
|
|
217
|
+
this.fragments = [];
|
|
218
|
+
this.fragmentBytes = 0;
|
|
219
|
+
const payload = fragments.length === 1 ? fragments[0] : Buffer.concat(fragments);
|
|
220
|
+
this.sink.onMessage(payload, opcode === exports.WS_OPCODE.binary);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
exports.WebSocketFrameParser = WebSocketFrameParser;
|
|
224
|
+
//# sourceMappingURL=WebSocketFrames.js.map
|
|
@@ -4,6 +4,7 @@ import { Button, Input, cn } from '@undefineds.co/shared-ui';
|
|
|
4
4
|
import { ExternalLink, Eye, EyeOff, KeyRound, Loader2, LogOut, Plus, RotateCw } from 'lucide-react';
|
|
5
5
|
import { normalizeProxyUrl } from './ai-connections-client.js';
|
|
6
6
|
import { offeringTitle } from './offering-label.js';
|
|
7
|
+
import { authorizationMethodsForOffering, isApiKeyMethod } from './authorization-methods.js';
|
|
7
8
|
import { nextCredentialPriority } from './credential-labels.js';
|
|
8
9
|
import { offeringEndpoint } from './offering-endpoints.js';
|
|
9
10
|
export function AiApiKeyPool({ definition, offering, createOfferings, status, credentials, attempt, apiKey, baseUrl, busy, disabled, error, onApiKeyChange, onBaseUrlChange, onBeginApiKey, onBeginBrowser, onSaveApiKey, onDisconnect, onCreateApiKeyCredential, onUpdateCredential, initialEditing, initialCreate = false, onSavingChange, onCloseEdit, }) {
|
|
@@ -11,6 +12,12 @@ export function AiApiKeyPool({ definition, offering, createOfferings, status, cr
|
|
|
11
12
|
const isConfigured = status === 'configured';
|
|
12
13
|
const isConnected = status === 'connected';
|
|
13
14
|
const hasPoolActions = Boolean(onCreateApiKeyCredential);
|
|
15
|
+
/**
|
|
16
|
+
* The legacy no-pool toolbar names its browser entry from the offering's own
|
|
17
|
+
* methods, like every other connect action. An api-key-only offering declares
|
|
18
|
+
* none, so that toolbar shows no browser button at all.
|
|
19
|
+
*/
|
|
20
|
+
const browserMethod = authorizationMethodsForOffering(offering).find((method) => !isApiKeyMethod(method));
|
|
14
21
|
const [createOfferingId, setCreateOfferingId] = useState(offering.id);
|
|
15
22
|
const formOffering = createOfferings.find((item) => item.id === createOfferingId) ?? offering;
|
|
16
23
|
const [showKey, setShowKey] = useState(false);
|
|
@@ -115,7 +122,7 @@ export function AiApiKeyPool({ definition, offering, createOfferings, status, cr
|
|
|
115
122
|
}
|
|
116
123
|
}
|
|
117
124
|
};
|
|
118
|
-
return (_jsxs("div", { className: cn('space-y-3', formMode && 'w-full'), children: [attempt?.userCode ? (_jsxs("div", { className: "border-l-2 border-primary bg-muted/30 px-3 py-2 text-sm", children: ["\u9A8C\u8BC1\u7801\uFF1A", _jsx("strong", { className: "font-mono", children: attempt.userCode })] })) : null, !initialCreate && !initialEditing ? _jsxs("div", { className: "flex flex-wrap gap-2", children: [onCreateApiKeyCredential && createOfferings.length > 0 ? (_jsxs(Button, { variant: "outline", size: "sm", disabled: busy || disabled || saving, onClick: openCreateForm, children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), "\u6DFB\u52A0 API Key"] })) : null, hasPoolActions ? null : isConnected ? (_jsxs(_Fragment, { children: [_jsxs(Button, { variant: "outline", size: "sm", disabled: busy || disabled || saving, onClick: onBeginBrowser, children: [busy ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : _jsx(RotateCw, { className: "mr-2 h-4 w-4" }), "\u91CD\u65B0\u8FDE\u63A5"] }), _jsxs(Button, { variant: "ghost", size: "sm", disabled: busy || disabled || saving, onClick: onDisconnect, children: [_jsx(LogOut, { className: "mr-2 h-4 w-4" }), "\u65AD\u5F00\u8FDE\u63A5"] })] })) : isConfigured ? (_jsxs(_Fragment, { children: [_jsxs(Button, { variant: "outline", size: "sm", "aria-label": "\u66F4\u65B0 API Key", disabled: busy || disabled || saving, onClick: onBeginApiKey, children: [_jsx(KeyRound, { className: "mr-2 h-4 w-4" }), "\u66F4\u65B0 API Key"] }), _jsx(Button, { variant: "ghost", size: "sm", disabled: busy || disabled || saving, onClick: onDisconnect, children: "\u79FB\u9664\u914D\u7F6E" })] })) : (_jsxs(_Fragment, { children: [_jsxs(Button, { variant: "outline", size: "sm", disabled: busy || disabled || saving ||
|
|
125
|
+
return (_jsxs("div", { className: cn('space-y-3', formMode && 'w-full'), children: [attempt?.userCode ? (_jsxs("div", { className: "border-l-2 border-primary bg-muted/30 px-3 py-2 text-sm", children: ["\u9A8C\u8BC1\u7801\uFF1A", _jsx("strong", { className: "font-mono", children: attempt.userCode })] })) : null, !initialCreate && !initialEditing ? _jsxs("div", { className: "flex flex-wrap gap-2", children: [onCreateApiKeyCredential && createOfferings.length > 0 ? (_jsxs(Button, { variant: "outline", size: "sm", disabled: busy || disabled || saving, onClick: openCreateForm, children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), "\u6DFB\u52A0 API Key"] })) : null, hasPoolActions ? null : isConnected ? (_jsxs(_Fragment, { children: [_jsxs(Button, { variant: "outline", size: "sm", disabled: busy || disabled || saving, onClick: onBeginBrowser, children: [busy ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : _jsx(RotateCw, { className: "mr-2 h-4 w-4" }), "\u91CD\u65B0\u8FDE\u63A5"] }), _jsxs(Button, { variant: "ghost", size: "sm", disabled: busy || disabled || saving, onClick: onDisconnect, children: [_jsx(LogOut, { className: "mr-2 h-4 w-4" }), "\u65AD\u5F00\u8FDE\u63A5"] })] })) : isConfigured ? (_jsxs(_Fragment, { children: [_jsxs(Button, { variant: "outline", size: "sm", "aria-label": "\u66F4\u65B0 API Key", disabled: busy || disabled || saving, onClick: onBeginApiKey, children: [_jsx(KeyRound, { className: "mr-2 h-4 w-4" }), "\u66F4\u65B0 API Key"] }), _jsx(Button, { variant: "ghost", size: "sm", disabled: busy || disabled || saving, onClick: onDisconnect, children: "\u79FB\u9664\u914D\u7F6E" })] })) : (_jsxs(_Fragment, { children: [browserMethod ? (_jsxs(Button, { variant: "outline", size: "sm", title: browserMethod.lifecycle === 'unavailable' ? browserMethod.reason : undefined, disabled: busy || disabled || saving || browserMethod.lifecycle === 'unavailable', onClick: onBeginBrowser, children: [busy ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : _jsx(ExternalLink, { className: "mr-2 h-4 w-4" }), browserMethod.label] })) : null, _jsxs(Button, { variant: "outline", size: "sm", "aria-label": `${definition.name} API Key`, disabled: busy || disabled || saving, onClick: onBeginApiKey, children: [_jsx(KeyRound, { className: "mr-2 h-4 w-4" }), "\u914D\u7F6E API Key"] })] }))] }) : null, formMode ? (_jsxs("div", { className: "space-y-2 rounded-lg border border-border/50 bg-muted/10 p-3", children: [formMode === 'create' && createOfferings.length > 1 ? (_jsxs("label", { className: "block space-y-1 text-xs text-muted-foreground", children: [_jsx("span", { children: "\u5957\u9910 / \u533A\u57DF" }), _jsx("select", { "aria-label": `${definition.name} 套餐 / 区域`, value: createOfferingId, disabled: busy || disabled || saving, onChange: (event) => { setCreateOfferingId(event.target.value); setPoolFormError(undefined); }, className: "h-9 w-full rounded-md border border-input bg-background px-3 text-sm text-foreground", children: createOfferings.map((item) => _jsx("option", { value: item.id, children: offeringTitle(item) }, item.id)) })] })) : null, formMode === 'edit' ? (_jsx(Input, { disabled: busy || disabled || saving, autoComplete: "off", "aria-label": `${definition.name} API Key 标签`, placeholder: "\u540D\u79F0\uFF0C\u4F8B\u5982 Work key", value: poolLabel, onChange: (event) => setPoolLabel(event.target.value) })) : null, formMode === 'create' ? (_jsx(Input, { disabled: busy || disabled || saving, type: showKey ? 'text' : 'password', autoComplete: "new-password", "data-lpignore": "true", "data-1p-ignore": true, "aria-label": `${definition.name} API Key 输入`, placeholder: definition.apiKeyPlaceholder || '从官方控制台复制 API Key', value: poolApiKey, onChange: (event) => setPoolApiKey(event.target.value), className: "font-mono" })) : null, formMode === 'edit' || showAdvanced ? (_jsxs(_Fragment, { children: [_jsx(Input, { disabled: busy || disabled || saving, autoComplete: "off", "data-lpignore": "true", "data-1p-ignore": true, "aria-label": `${definition.name} Base URL 输入`, placeholder: offeringEndpoint(formMode === 'edit' ? offering : formOffering) || definition.defaultBaseUrl || '默认服务地址', value: poolBaseUrl, onChange: (event) => setPoolBaseUrl(event.target.value), className: "font-mono text-xs" }), _jsx(Input, { disabled: busy || disabled || saving, autoComplete: "off", "data-lpignore": "true", "data-1p-ignore": true, "aria-label": `${definition.name} Proxy URL 输入`, placeholder: "http://127.0.0.1:7890", value: poolProxyUrl, onChange: (event) => setPoolProxyUrl(event.target.value), className: "font-mono text-xs" })] })) : null, poolFormError ? _jsx("p", { className: "text-xs text-destructive", children: poolFormError }) : null, _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { size: "sm", "aria-label": formMode === 'create' ? `保存 ${definition.name} API Key` : '保存凭证', disabled: busy || disabled || saving || (formMode === 'create' && !poolApiKey.trim()), onClick: savePoolForm, children: formMode === 'create' ? '保存 API Key' : '保存凭证' }), _jsx(Button, { variant: "ghost", size: "sm", disabled: saving, onClick: closePoolForm, children: "\u53D6\u6D88" }), formMode === 'create' ? (_jsx(Button, { variant: "ghost", size: "sm", disabled: saving, onClick: () => setShowAdvanced((current) => !current), children: showAdvanced ? '收起高级设置' : '高级设置' })) : null] })] })) : null, apiKeyAttempt && !formMode ? (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-sm font-medium", children: "API Key" }), definition.apiKeyUrl ? (_jsx("a", { href: definition.apiKeyUrl, target: "_blank", rel: "noreferrer", className: "text-xs text-primary hover:underline", children: "\u83B7\u53D6 API Key" })) : null] }), _jsxs("div", { className: "group relative", children: [_jsx(Input, { disabled: busy || disabled || saving, type: showKey ? 'text' : 'password', autoComplete: "new-password", "data-lpignore": "true", "data-1p-ignore": true, "aria-label": `${definition.name} API Key 输入`, placeholder: definition.apiKeyPlaceholder || '从官方控制台复制 API Key', value: apiKey, onChange: (event) => onApiKeyChange(event.target.value), className: "border-border/60 bg-muted/20 pr-10 font-mono transition-colors focus:border-primary/50 focus:bg-background" }), _jsx("div", { className: "absolute bottom-1 right-1 top-1 flex items-center", children: _jsx(Button, { variant: "ghost", size: "icon", className: "h-full w-8 rounded hover:bg-muted", onClick: () => setShowKey((current) => !current), "aria-label": showKey ? '隐藏 API Key' : '显示 API Key', children: showKey
|
|
119
126
|
? _jsx(EyeOff, { className: "h-4 w-4 text-muted-foreground" })
|
|
120
127
|
: _jsx(Eye, { className: "h-4 w-4 text-muted-foreground" }) }) })] }), onBaseUrlChange ? (_jsxs("div", { className: "space-y-1.5", children: [_jsx("span", { className: "text-xs font-medium text-muted-foreground", children: "Base URL\uFF08\u9009\u586B\uFF09" }), _jsx(Input, { disabled: busy || disabled || saving, autoComplete: "off", "data-lpignore": "true", "data-1p-ignore": true, "aria-label": `${definition.name} Base URL 输入`, placeholder: definition.defaultBaseUrl || '默认服务地址', value: baseUrl, onChange: (event) => onBaseUrlChange(event.target.value), className: "border-border/60 bg-muted/20 font-mono text-xs transition-colors focus:border-primary/50 focus:bg-background" }), _jsxs("p", { className: "break-all font-mono text-[11px] text-muted-foreground opacity-80", children: [_jsx("span", { className: "mr-1 select-none opacity-50", children: "\u9884\u89C8:" }), (baseUrl.trim() || definition.defaultBaseUrl || '').replace(/\/+$/, ''), "/chat/completions"] })] })) : null, _jsx(Button, { size: "sm", "aria-label": `保存 ${definition.name} API Key`, disabled: !apiKey.trim() || busy || disabled, onClick: onSaveApiKey, children: "\u4FDD\u5B58 API Key" })] })) : null, error ? _jsx("p", { className: "text-sm text-destructive", children: error }) : null] }));
|
|
121
128
|
}
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import type { AiConnectionsMode, AiProviderAuthorizationMethod, AiProviderOffering } from './ai-connections-client';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* The offering's own entries, one button per declared `authorizationMethod`.
|
|
4
|
+
*
|
|
5
|
+
* A method that is implemented but unavailable in this deployment still gets its
|
|
6
|
+
* button, greyed at the same spec as its neighbours so the row keeps one line,
|
|
7
|
+
* with the reason as its tooltip. Nothing explains itself in a second row: the
|
|
8
|
+
* entry's own state is the message, and a list of internal reasons underneath
|
|
9
|
+
* the row reflows the buttons around it. Methods this build has not implemented
|
|
10
|
+
* never reach here - the server omits them.
|
|
11
|
+
*/
|
|
12
|
+
export declare function AiAuthorizationActions({ methods, offering, busy, disabled, onBeginOffering, onCreateLocalCredential, }: {
|
|
3
13
|
methods: AiProviderAuthorizationMethod[];
|
|
4
14
|
offering: AiProviderOffering;
|
|
5
|
-
hasCredentials: boolean;
|
|
6
15
|
busy: boolean;
|
|
7
16
|
disabled: boolean;
|
|
8
17
|
onBeginOffering?: (offering: AiProviderOffering, mode: AiConnectionsMode, method?: AiProviderAuthorizationMethod) => void;
|
|
@@ -2,17 +2,34 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Button } from '@undefineds.co/shared-ui';
|
|
3
3
|
import { ExternalLink, Loader2, Plus } from 'lucide-react';
|
|
4
4
|
import { connectModeForMethod, isLocalMethod, isOAuthMode } from './authorization-methods.js';
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* The offering's own entries, one button per declared `authorizationMethod`.
|
|
7
|
+
*
|
|
8
|
+
* A method that is implemented but unavailable in this deployment still gets its
|
|
9
|
+
* button, greyed at the same spec as its neighbours so the row keeps one line,
|
|
10
|
+
* with the reason as its tooltip. Nothing explains itself in a second row: the
|
|
11
|
+
* entry's own state is the message, and a list of internal reasons underneath
|
|
12
|
+
* the row reflows the buttons around it. Methods this build has not implemented
|
|
13
|
+
* never reach here - the server omits them.
|
|
14
|
+
*/
|
|
15
|
+
export function AiAuthorizationActions({ methods, offering, busy, disabled, onBeginOffering, onCreateLocalCredential, }) {
|
|
6
16
|
if (methods.length === 0)
|
|
7
17
|
return null;
|
|
8
|
-
return (_jsx("div", { className: "
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return (_jsxs(Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", title: "\u5BFC\u5165\u5F53\u524D\u8BBE\u5907\u5DF2\u6709\u767B\u5F55\u6001\uFF0C\u4E0D\u4F1A\u53D1\u8D77\u65B0\u7684\u6D4F\u89C8\u5668\u6388\u6743\u3002", disabled: busy || disabled || !onCreateLocalCredential, onClick: () => void onCreateLocalCredential?.(offering, method), children: [busy ? _jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : _jsx(Plus, { className: "h-3.5 w-3.5" }), method.label || '已有登录态'] }, method.id));
|
|
15
|
-
}
|
|
18
|
+
return (_jsx("div", { className: "flex flex-wrap gap-2", children: methods.map((method) => {
|
|
19
|
+
const connectMode = connectModeForMethod(method);
|
|
20
|
+
const unavailable = method.lifecycle === 'unavailable';
|
|
21
|
+
// An entry without a label is not one the offering asked for; the
|
|
22
|
+
// button is named by the method itself, never by a provider default.
|
|
23
|
+
if (!method.label)
|
|
16
24
|
return null;
|
|
17
|
-
|
|
25
|
+
if (isOAuthMode(connectMode)) {
|
|
26
|
+
return (_jsxs(Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", title: unavailable ? method.reason : undefined, disabled: busy || disabled || unavailable || !onBeginOffering, onClick: () => onBeginOffering?.(offering, connectMode, method), children: [busy ? _jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : _jsx(ExternalLink, { className: "h-3.5 w-3.5" }), method.label] }, method.id));
|
|
27
|
+
}
|
|
28
|
+
if (isLocalMethod(method)) {
|
|
29
|
+
return (_jsxs(Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", title: unavailable
|
|
30
|
+
? method.reason
|
|
31
|
+
: '导入当前设备已有登录态,不会发起新的浏览器授权。', disabled: busy || disabled || unavailable || !onCreateLocalCredential, onClick: () => void onCreateLocalCredential?.(offering, method), children: [busy ? _jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : _jsx(Plus, { className: "h-3.5 w-3.5" }), method.label] }, method.id));
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}) }));
|
|
18
35
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AiClientConfigurationModel } from '@undefineds.co/extension-sdk/web';
|
|
2
|
+
import { normalizeV1Endpoint } from './endpoint-urls';
|
|
2
3
|
export declare const AI_CONNECTIONS_CLIENTS: readonly ["codex", "claude-code", "pi", "codebuddy"];
|
|
3
4
|
export type AiConnectionsClientId = (typeof AI_CONNECTIONS_CLIENTS)[number];
|
|
4
5
|
export interface AiClientConfigurationStatus {
|
|
@@ -68,4 +69,10 @@ export declare function AiClientConfigurationSection({ bridge, endpoint, client,
|
|
|
68
69
|
compact?: boolean;
|
|
69
70
|
onComplete?: () => void;
|
|
70
71
|
}): import("react").JSX.Element;
|
|
72
|
+
/**
|
|
73
|
+
* The OpenAI-compatible base a client is pointed at, derived from the Xpod URL.
|
|
74
|
+
* The rule itself is shared with the client-config adapters, so what a copied
|
|
75
|
+
* config claims and what the adapters write cannot drift apart.
|
|
76
|
+
*/
|
|
77
|
+
export declare const openAiCompatibleBaseUrl: typeof normalizeV1Endpoint;
|
|
71
78
|
export declare function manualConfigurationText(client: AiConnectionsClientId, endpoint: string, apiKey?: string): string;
|