@undefineds.co/xpod 0.1.7 → 0.2.0
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/README.md +164 -3
- package/config/cli.json +9 -71
- package/config/cloud.json +34 -7
- package/config/local.json +6 -2
- package/config/resolver.json +11 -49
- package/config/runtime-open.json +22 -0
- package/config/xpod.base.json +32 -0
- package/config/xpod.cluster.json +2 -44
- package/config/xpod.json +5 -2
- package/dist/agents/AgentExecutorFactory.js +1 -1
- package/dist/agents/AgentExecutorFactory.js.map +1 -1
- package/dist/agents/AgentManager.js +1 -1
- package/dist/agents/AgentManager.js.map +1 -1
- package/dist/agents/config/agent-meta-schema.d.ts +7 -7
- package/dist/agents/config/agent-meta-schema.js +1 -1
- package/dist/agents/config/agent-meta-schema.js.map +1 -1
- package/dist/agents/config/resolve.js +1 -1
- package/dist/agents/config/resolve.js.map +1 -1
- package/dist/agents/schema/agent-config.d.ts +18 -18
- package/dist/agents/schema/agent-config.js +1 -1
- package/dist/agents/schema/agent-config.js.map +1 -1
- package/dist/agents/schema/tables.d.ts +8 -8
- package/dist/agents/schema/tables.js +1 -1
- package/dist/agents/schema/tables.js.map +1 -1
- package/dist/ai/schema/config.d.ts +7 -7
- package/dist/ai/schema/config.js +1 -1
- package/dist/ai/schema/config.js.map +1 -1
- package/dist/ai/schema/model.d.ts +13 -13
- package/dist/ai/schema/model.js +1 -1
- package/dist/ai/schema/model.js.map +1 -1
- package/dist/ai/schema/provider.d.ts +7 -7
- package/dist/ai/schema/provider.js +1 -1
- package/dist/ai/schema/provider.js.map +1 -1
- package/dist/ai/schema/vector-store.d.ts +17 -17
- package/dist/ai/schema/vector-store.js +1 -1
- package/dist/ai/schema/vector-store.js.map +1 -1
- package/dist/ai/service/CredentialReaderImpl.js +1 -1
- package/dist/ai/service/CredentialReaderImpl.js.map +1 -1
- package/dist/ai/service/DefaultAiConfigService.js.map +1 -1
- package/dist/api/ApiServer.d.ts +3 -1
- package/dist/api/ApiServer.js +14 -1
- package/dist/api/ApiServer.js.map +1 -1
- package/dist/api/auth/AuthContext.d.ts +12 -1
- package/dist/api/auth/AuthContext.js +18 -1
- package/dist/api/auth/AuthContext.js.map +1 -1
- package/dist/api/auth/ClientCredentialsAuthenticator.d.ts +0 -1
- package/dist/api/auth/ClientCredentialsAuthenticator.js.map +1 -1
- package/dist/api/auth/ServiceTokenAuthenticator.d.ts +18 -0
- package/dist/api/auth/ServiceTokenAuthenticator.js +50 -0
- package/dist/api/auth/ServiceTokenAuthenticator.js.map +1 -0
- package/dist/api/auth/index.d.ts +1 -0
- package/dist/api/auth/index.js +1 -0
- package/dist/api/auth/index.js.map +1 -1
- package/dist/api/chatkit/ai-provider.d.ts +0 -10
- package/dist/api/chatkit/ai-provider.js +11 -120
- package/dist/api/chatkit/ai-provider.js.map +1 -1
- package/dist/api/chatkit/default-agent.js +11 -8
- package/dist/api/chatkit/default-agent.js.map +1 -1
- package/dist/api/chatkit/pod-store.d.ts +6 -0
- package/dist/api/chatkit/pod-store.js +103 -36
- package/dist/api/chatkit/pod-store.js.map +1 -1
- package/dist/api/chatkit/schema.d.ts +32 -26
- package/dist/api/chatkit/schema.js +16 -8
- package/dist/api/chatkit/schema.js.map +1 -1
- package/dist/api/container/business-token.d.ts +9 -0
- package/dist/api/container/business-token.js +32 -0
- package/dist/api/container/business-token.js.map +1 -0
- package/dist/api/container/cloud.js +36 -12
- package/dist/api/container/cloud.js.map +1 -1
- package/dist/api/container/common.js +13 -5
- package/dist/api/container/common.js.map +1 -1
- package/dist/api/container/index.js +94 -14
- package/dist/api/container/index.js.map +1 -1
- package/dist/api/container/local.js +2 -1
- package/dist/api/container/local.js.map +1 -1
- package/dist/api/container/routes.js +81 -9
- package/dist/api/container/routes.js.map +1 -1
- package/dist/api/container/types.d.ts +8 -6
- package/dist/api/container/types.js.map +1 -1
- package/dist/api/handlers/AdminHandler.js +9 -9
- package/dist/api/handlers/AdminHandler.js.map +1 -1
- package/dist/api/handlers/ApiKeyHandler.js +0 -6
- package/dist/api/handlers/ApiKeyHandler.js.map +1 -1
- package/dist/api/handlers/EdgeNodeSignalHandler.d.ts +17 -0
- package/dist/api/handlers/EdgeNodeSignalHandler.js +171 -0
- package/dist/api/handlers/EdgeNodeSignalHandler.js.map +1 -0
- package/dist/api/handlers/PodManagementHandler.d.ts +5 -4
- package/dist/api/handlers/PodManagementHandler.js +11 -10
- package/dist/api/handlers/PodManagementHandler.js.map +1 -1
- package/dist/api/handlers/ProvisionHandler.d.ts +42 -0
- package/dist/api/handlers/ProvisionHandler.js +161 -0
- package/dist/api/handlers/ProvisionHandler.js.map +1 -0
- package/dist/api/handlers/QuotaHandler.d.ts +7 -7
- package/dist/api/handlers/QuotaHandler.js +143 -73
- package/dist/api/handlers/QuotaHandler.js.map +1 -1
- package/dist/api/handlers/SubdomainClientHandler.js +2 -2
- package/dist/api/handlers/SubdomainClientHandler.js.map +1 -1
- package/dist/api/handlers/SubdomainHandler.js +13 -8
- package/dist/api/handlers/SubdomainHandler.js.map +1 -1
- package/dist/api/handlers/UsageHandler.d.ts +14 -0
- package/dist/api/handlers/UsageHandler.js +123 -0
- package/dist/api/handlers/UsageHandler.js.map +1 -0
- package/dist/api/handlers/index.d.ts +3 -1
- package/dist/api/handlers/index.js +3 -1
- package/dist/api/handlers/index.js.map +1 -1
- package/dist/api/main.js +18 -0
- package/dist/api/main.js.map +1 -1
- package/dist/api/middleware/OpenAuthMiddleware.d.ts +12 -0
- package/dist/api/middleware/OpenAuthMiddleware.js +27 -0
- package/dist/api/middleware/OpenAuthMiddleware.js.map +1 -0
- package/dist/api/runtime.d.ts +15 -0
- package/dist/api/runtime.js +125 -0
- package/dist/api/runtime.js.map +1 -0
- package/dist/api/service/VectorStoreService.js +1 -1
- package/dist/api/service/VectorStoreService.js.map +1 -1
- package/dist/api/service/VercelChatService.d.ts +16 -7
- package/dist/api/service/VercelChatService.js +98 -178
- package/dist/api/service/VercelChatService.js.map +1 -1
- package/dist/api/store/DrizzleClientCredentialsStore.d.ts +6 -11
- package/dist/api/store/DrizzleClientCredentialsStore.js +9 -39
- package/dist/api/store/DrizzleClientCredentialsStore.js.map +1 -1
- package/dist/authorization/AuthModeSelector.d.ts +10 -0
- package/dist/authorization/AuthModeSelector.js +27 -0
- package/dist/authorization/AuthModeSelector.js.map +1 -0
- package/dist/authorization/AuthModeSelector.jsonld +81 -0
- package/dist/cli/commands/account.d.ts +6 -0
- package/dist/cli/commands/account.js +119 -0
- package/dist/cli/commands/account.js.map +1 -0
- package/dist/cli/commands/auth.js +20 -29
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/backup.d.ts +15 -0
- package/dist/cli/commands/backup.js +286 -0
- package/dist/cli/commands/backup.js.map +1 -0
- package/dist/cli/commands/config.d.ts +34 -3
- package/dist/cli/commands/config.js +195 -258
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +6 -0
- package/dist/cli/commands/doctor.js +94 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/pod.d.ts +6 -0
- package/dist/cli/commands/pod.js +124 -0
- package/dist/cli/commands/pod.js.map +1 -0
- package/dist/cli/commands/start.js +28 -5
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/index.js +9 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/lib/credentials-store.d.ts +17 -0
- package/dist/cli/lib/credentials-store.js +73 -0
- package/dist/cli/lib/credentials-store.js.map +1 -0
- package/dist/cli/lib/css-account.d.ts +17 -0
- package/dist/cli/lib/css-account.js +56 -0
- package/dist/cli/lib/css-account.js.map +1 -1
- package/dist/cli/lib/pod-thread-store.d.ts +57 -0
- package/dist/cli/lib/pod-thread-store.js +310 -0
- package/dist/cli/lib/pod-thread-store.js.map +1 -0
- package/dist/cli/lib/solid-auth.d.ts +20 -0
- package/dist/cli/lib/solid-auth.js +70 -0
- package/dist/cli/lib/solid-auth.js.map +1 -0
- package/dist/components/components.jsonld +5 -8
- package/dist/components/context.jsonld +114 -244
- package/dist/credential/schema/tables.d.ts +14 -14
- package/dist/credential/schema/tables.js +1 -1
- package/dist/credential/schema/tables.js.map +1 -1
- package/dist/edge/EdgeNodeAgent.js +2 -2
- package/dist/edge/EdgeNodeAgent.js.map +1 -1
- package/dist/edge/EdgeNodeDnsCoordinator.d.ts +1 -7
- package/dist/edge/EdgeNodeDnsCoordinator.js +31 -41
- package/dist/edge/EdgeNodeDnsCoordinator.js.map +1 -1
- package/dist/edge/EdgeNodeDnsCoordinator.jsonld +1 -27
- package/dist/edge/EdgeNodeModeDetector.d.ts +1 -1
- package/dist/edge/EdgeNodeModeDetector.js +9 -11
- package/dist/edge/EdgeNodeModeDetector.js.map +1 -1
- package/dist/http/ClusterIngressRouter.js +3 -3
- package/dist/http/ClusterIngressRouter.js.map +1 -1
- package/dist/http/ClusterWebSocketConfigurator.js +2 -2
- package/dist/http/ClusterWebSocketConfigurator.js.map +1 -1
- package/dist/http/PodRoutingHttpHandler.js +2 -2
- package/dist/http/PodRoutingHttpHandler.js.map +1 -1
- package/dist/http/cluster/PodMigrationHttpHandler.d.ts +1 -1
- package/dist/http/cluster/PodMigrationHttpHandler.js +1 -1
- package/dist/http/cluster/PodMigrationHttpHandler.js.map +1 -1
- package/dist/identity/drizzle/EdgeNodeRepository.d.ts +37 -4
- package/dist/identity/drizzle/EdgeNodeRepository.js +120 -128
- package/dist/identity/drizzle/EdgeNodeRepository.js.map +1 -1
- package/dist/identity/drizzle/ServiceTokenRepository.d.ts +52 -0
- package/dist/identity/drizzle/ServiceTokenRepository.js +142 -0
- package/dist/identity/drizzle/ServiceTokenRepository.js.map +1 -0
- package/dist/identity/drizzle/db.d.ts +9 -0
- package/dist/identity/drizzle/db.js +235 -3
- package/dist/identity/drizzle/db.js.map +1 -1
- package/dist/identity/drizzle/schema.pg.d.ts +5 -0
- package/dist/identity/drizzle/schema.pg.js +49 -20
- package/dist/identity/drizzle/schema.pg.js.map +1 -1
- package/dist/identity/drizzle/schema.sqlite.d.ts +332 -57
- package/dist/identity/drizzle/schema.sqlite.js +48 -18
- package/dist/identity/drizzle/schema.sqlite.js.map +1 -1
- package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js +6 -4
- package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js.map +1 -1
- package/dist/index.d.ts +6 -9
- package/dist/index.js +12 -14
- package/dist/index.js.map +1 -1
- package/dist/main.js +25 -8
- package/dist/main.js.map +1 -1
- package/dist/provision/ProvisionCodeCodec.d.ts +39 -0
- package/dist/provision/ProvisionCodeCodec.js +65 -0
- package/dist/provision/ProvisionCodeCodec.js.map +1 -0
- package/dist/provision/ProvisionCodeCodec.jsonld +47 -0
- package/dist/provision/ProvisionPodCreator.d.ts +20 -0
- package/dist/provision/ProvisionPodCreator.js +84 -0
- package/dist/provision/ProvisionPodCreator.js.map +1 -0
- package/dist/provision/ProvisionPodCreator.jsonld +118 -0
- package/dist/quota/DrizzleQuotaService.d.ts +17 -3
- package/dist/quota/DrizzleQuotaService.js +108 -8
- package/dist/quota/DrizzleQuotaService.js.map +1 -1
- package/dist/quota/DrizzleQuotaService.jsonld +33 -22
- package/dist/quota/NoopQuotaService.d.ts +7 -1
- package/dist/quota/NoopQuotaService.js +12 -0
- package/dist/quota/NoopQuotaService.js.map +1 -1
- package/dist/quota/NoopQuotaService.jsonld +24 -0
- package/dist/quota/QuotaService.d.ts +17 -0
- package/dist/quota/QuotaService.js +5 -0
- package/dist/quota/QuotaService.js.map +1 -1
- package/dist/quota/QuotaService.jsonld +50 -0
- package/dist/runtime/Proxy.d.ts +22 -4
- package/dist/runtime/Proxy.js +154 -35
- package/dist/runtime/Proxy.js.map +1 -1
- package/dist/runtime/XpodRuntime.d.ts +49 -0
- package/dist/runtime/XpodRuntime.js +374 -0
- package/dist/runtime/XpodRuntime.js.map +1 -0
- package/dist/runtime/env-utils.d.ts +2 -0
- package/dist/runtime/env-utils.js +55 -0
- package/dist/runtime/env-utils.js.map +1 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.js +8 -1
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/socket-fetch.d.ts +1 -0
- package/dist/runtime/socket-fetch.js +72 -0
- package/dist/runtime/socket-fetch.js.map +1 -0
- package/dist/runtime/socket-http.d.ts +1 -0
- package/dist/runtime/socket-http.js +142 -0
- package/dist/runtime/socket-http.js.map +1 -0
- package/dist/runtime/socket-utils.d.ts +2 -0
- package/dist/runtime/socket-utils.js +34 -0
- package/dist/runtime/socket-utils.js.map +1 -0
- package/dist/service/{EdgeNodeHeartbeatService.d.ts → EdgeNodeSignalClient.d.ts} +3 -3
- package/dist/service/{EdgeNodeHeartbeatService.js → EdgeNodeSignalClient.js} +4 -4
- package/dist/service/EdgeNodeSignalClient.js.map +1 -0
- package/dist/service/PodMigrationService.d.ts +1 -2
- package/dist/service/PodMigrationService.js +1 -2
- package/dist/service/PodMigrationService.js.map +1 -1
- package/dist/storage/SparqlUpdateResourceStore.js +1 -1
- package/dist/storage/SparqlUpdateResourceStore.js.map +1 -1
- package/dist/storage/accessors/MinioDataAccessor.d.ts +6 -0
- package/dist/storage/accessors/MinioDataAccessor.js +10 -0
- package/dist/storage/accessors/MinioDataAccessor.js.map +1 -1
- package/dist/storage/accessors/MinioDataAccessor.jsonld +4 -0
- package/dist/storage/accessors/MixDataAccessor.d.ts +2 -1
- package/dist/storage/accessors/MixDataAccessor.js +12 -1
- package/dist/storage/accessors/MixDataAccessor.js.map +1 -1
- package/dist/storage/accessors/MixDataAccessor.jsonld +19 -0
- package/dist/storage/locking/UrlAwareRedisLocker.d.ts +18 -0
- package/dist/storage/locking/UrlAwareRedisLocker.js +60 -0
- package/dist/storage/locking/UrlAwareRedisLocker.js.map +1 -0
- package/dist/storage/locking/UrlAwareRedisLocker.jsonld +123 -0
- package/dist/storage/quota/UsageRepository.d.ts +41 -8
- package/dist/storage/quota/UsageRepository.js +252 -50
- package/dist/storage/quota/UsageRepository.js.map +1 -1
- package/dist/storage/sparql/ComunicaQuintEngine.d.ts +9 -0
- package/dist/storage/sparql/ComunicaQuintEngine.js +50 -9
- package/dist/storage/sparql/ComunicaQuintEngine.js.map +1 -1
- package/dist/storage/sparql/QueryOptimizer.js +13 -1
- package/dist/storage/sparql/QueryOptimizer.js.map +1 -1
- package/dist/storage/sparql/QuintQuerySource.d.ts +14 -0
- package/dist/storage/sparql/QuintQuerySource.js +152 -1
- package/dist/storage/sparql/QuintQuerySource.js.map +1 -1
- package/dist/storage/sparql/SubgraphQueryEngine.d.ts +1 -0
- package/dist/storage/sparql/SubgraphQueryEngine.js +6 -2
- package/dist/storage/sparql/SubgraphQueryEngine.js.map +1 -1
- package/dist/storage/sparql/SubgraphQueryEngine.jsonld +4 -0
- package/dist/subdomain/SubdomainClient.d.ts +3 -3
- package/dist/subdomain/SubdomainClient.js +1 -1
- package/dist/subdomain/SubdomainClient.js.map +1 -1
- package/dist/subdomain/SubdomainService.d.ts +15 -16
- package/dist/subdomain/SubdomainService.js +80 -54
- package/dist/subdomain/SubdomainService.js.map +1 -1
- package/dist/subdomain/SubdomainService.jsonld +22 -26
- package/dist/supervisor/Supervisor.d.ts +7 -2
- package/dist/supervisor/Supervisor.js +33 -1
- package/dist/supervisor/Supervisor.js.map +1 -1
- package/dist/task/DrizzleTaskQueue.d.ts +1 -1
- package/dist/task/DrizzleTaskQueue.js +1 -1
- package/dist/task/DrizzleTaskQueue.js.map +1 -1
- package/dist/task/schema.d.ts +10 -10
- package/dist/task/schema.js +1 -1
- package/dist/task/schema.js.map +1 -1
- package/dist/test-utils/index.d.ts +4 -0
- package/dist/test-utils/index.js +8 -0
- package/dist/test-utils/index.js.map +1 -0
- package/dist/test-utils/no-auth-xpod.d.ts +11 -0
- package/dist/test-utils/no-auth-xpod.js +25 -0
- package/dist/test-utils/no-auth-xpod.js.map +1 -0
- package/dist/test-utils/seed-pod.d.ts +5 -0
- package/dist/test-utils/seed-pod.js +61 -0
- package/dist/test-utils/seed-pod.js.map +1 -0
- package/package.json +38 -10
- package/templates/identity/account/create-pod.html.ejs +110 -0
- package/templates/main.html.ejs +10 -0
- package/dist/api/handlers/DevHandler.d.ts +0 -18
- package/dist/api/handlers/DevHandler.js +0 -276
- package/dist/api/handlers/DevHandler.js.map +0 -1
- package/dist/api/handlers/SignalHandler.d.ts +0 -13
- package/dist/api/handlers/SignalHandler.js +0 -122
- package/dist/api/handlers/SignalHandler.js.map +0 -1
- package/dist/gateway/Proxy.d.ts +0 -24
- package/dist/gateway/Proxy.js +0 -209
- package/dist/gateway/Proxy.js.map +0 -1
- package/dist/gateway/Supervisor.d.ts +0 -2
- package/dist/gateway/Supervisor.js +0 -7
- package/dist/gateway/Supervisor.js.map +0 -1
- package/dist/gateway/port-finder.d.ts +0 -4
- package/dist/gateway/port-finder.js +0 -15
- package/dist/gateway/port-finder.js.map +0 -1
- package/dist/gateway/types.d.ts +0 -1
- package/dist/gateway/types.js +0 -3
- package/dist/gateway/types.js.map +0 -1
- package/dist/http/SignalInterceptHttpHandler.d.ts +0 -24
- package/dist/http/SignalInterceptHttpHandler.js +0 -47
- package/dist/http/SignalInterceptHttpHandler.js.map +0 -1
- package/dist/http/SignalInterceptHttpHandler.jsonld +0 -103
- package/dist/http/admin/EdgeNodeSignalHttpHandler.d.ts +0 -71
- package/dist/http/admin/EdgeNodeSignalHttpHandler.js +0 -674
- package/dist/http/admin/EdgeNodeSignalHttpHandler.js.map +0 -1
- package/dist/http/admin/EdgeNodeSignalHttpHandler.jsonld +0 -406
- package/dist/http/cluster/PodMigrationHttpHandler.jsonld +0 -169
- package/dist/quota/DefaultQuotaService.d.ts +0 -16
- package/dist/quota/DefaultQuotaService.js +0 -37
- package/dist/quota/DefaultQuotaService.js.map +0 -1
- package/dist/quota/DefaultQuotaService.jsonld +0 -85
- package/dist/service/EdgeNodeHeartbeatService.js.map +0 -1
- package/dist/service/PodMigrationService.jsonld +0 -76
- package/dist/storage/MigratableDataAccessor.d.ts +0 -63
- package/dist/storage/MigratableDataAccessor.js +0 -11
- package/dist/storage/MigratableDataAccessor.js.map +0 -1
- package/dist/storage/MigratableDataAccessor.jsonld +0 -60
- package/dist/storage/accessors/TieredMinioDataAccessor.d.ts +0 -150
- package/dist/storage/accessors/TieredMinioDataAccessor.js +0 -582
- package/dist/storage/accessors/TieredMinioDataAccessor.js.map +0 -1
- package/dist/storage/accessors/TieredMinioDataAccessor.jsonld +0 -333
- package/static/app/assets/index.css +0 -1
- package/static/app/assets/main.js +0 -11
|
@@ -16,25 +16,25 @@
|
|
|
16
16
|
/**
|
|
17
17
|
* Model - 基础模型定义
|
|
18
18
|
*/
|
|
19
|
-
export declare const Model: import("drizzle-solid/dist/core/schema").PodTableWithColumns<import("drizzle-solid/dist/core/schema").ResolvedColumns<{
|
|
20
|
-
id: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, false>;
|
|
21
|
-
displayName: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
22
|
-
modelType: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
23
|
-
isProvidedBy: import("drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
24
|
-
dimension: import("drizzle-solid/dist/core/schema").ColumnBuilder<"integer", null, false, false>;
|
|
25
|
-
contextLength: import("drizzle-solid/dist/core/schema").ColumnBuilder<"integer", null, false, false>;
|
|
26
|
-
maxOutputTokens: import("drizzle-solid/dist/core/schema").ColumnBuilder<"integer", null, false, false>;
|
|
27
|
-
status: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
28
|
-
createdAt: import("drizzle-solid/dist/core/schema").ColumnBuilder<"datetime", null, false, false>;
|
|
29
|
-
updatedAt: import("drizzle-solid/dist/core/schema").ColumnBuilder<"datetime", null, false, false>;
|
|
19
|
+
export declare const Model: import("@undefineds.co/drizzle-solid/dist/core/schema").PodTableWithColumns<import("@undefineds.co/drizzle-solid/dist/core/schema").ResolvedColumns<{
|
|
20
|
+
id: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, false>;
|
|
21
|
+
displayName: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
22
|
+
modelType: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
23
|
+
isProvidedBy: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
24
|
+
dimension: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"integer", null, false, false>;
|
|
25
|
+
contextLength: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"integer", null, false, false>;
|
|
26
|
+
maxOutputTokens: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"integer", null, false, false>;
|
|
27
|
+
status: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
28
|
+
createdAt: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"datetime", null, false, false>;
|
|
29
|
+
updatedAt: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"datetime", null, false, false>;
|
|
30
30
|
}>>;
|
|
31
31
|
export type ModelRow = typeof Model.$inferSelect;
|
|
32
32
|
export type ModelInsert = typeof Model.$inferInsert;
|
|
33
33
|
/**
|
|
34
34
|
* Model -> Provider 关系定义
|
|
35
35
|
*/
|
|
36
|
-
export declare const ModelRelations: Record<string, import("drizzle-solid").RelationDefinition>;
|
|
36
|
+
export declare const ModelRelations: Record<string, import("@undefineds.co/drizzle-solid").RelationDefinition>;
|
|
37
37
|
/**
|
|
38
38
|
* Provider -> Model 关系定义
|
|
39
39
|
*/
|
|
40
|
-
export declare const ProviderRelations: Record<string, import("drizzle-solid").RelationDefinition>;
|
|
40
|
+
export declare const ProviderRelations: Record<string, import("@undefineds.co/drizzle-solid").RelationDefinition>;
|
package/dist/ai/schema/model.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.ProviderRelations = exports.ModelRelations = exports.Model = void 0;
|
|
19
|
-
const drizzle_solid_1 = require("drizzle-solid");
|
|
19
|
+
const drizzle_solid_1 = require("@undefineds.co/drizzle-solid");
|
|
20
20
|
const vocab_1 = require("../../vocab");
|
|
21
21
|
const provider_1 = require("./provider");
|
|
22
22
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/ai/schema/model.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAEH,
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/ai/schema/model.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAEH,gEAA+F;AAC/F,uCAAmD;AACnD,yCAAsC;AAEtC;;GAEG;AACU,QAAA,KAAK,GAAG,IAAA,wBAAQ,EAC3B,OAAO,EACP;IACE,EAAE,EAAE,IAAA,sBAAM,EAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC7B,WAAW,EAAE,IAAA,sBAAM,EAAC,aAAa,CAAC;IAClC,SAAS,EAAE,IAAA,sBAAM,EAAC,WAAW,CAAC;IAC9B,YAAY,EAAE,IAAA,mBAAG,EAAC,cAAc,CAAC;IACjC,SAAS,EAAE,IAAA,mBAAG,EAAC,WAAW,CAAC;IAC3B,aAAa,EAAE,IAAA,mBAAG,EAAC,eAAe,CAAC;IACnC,eAAe,EAAE,IAAA,mBAAG,EAAC,iBAAiB,CAAC;IACvC,MAAM,EAAE,IAAA,sBAAM,EAAC,QAAQ,CAAC;IACxB,SAAS,EAAE,IAAA,wBAAQ,EAAC,WAAW,CAAC;IAChC,SAAS,EAAE,IAAA,wBAAQ,EAAC,WAAW,CAAC;CACjC,EACD;IACE,IAAI,EAAE,yBAAyB;IAC/B,IAAI,EAAE,YAAI,CAAC,KAAK;IAChB,SAAS,EAAE,sBAAc;IACzB,eAAe,EAAE,OAAO;CACzB,CACF,CAAC;AAKF;;GAEG;AACU,QAAA,cAAc,GAAG,IAAA,yBAAS,EAAC,aAAK,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IAC3D,QAAQ,EAAE,GAAG,CAAC,mBAAQ,EAAE;QACtB,MAAM,EAAE,CAAC,aAAK,CAAC,YAAY,CAAC;QAC5B,UAAU,EAAE,CAAC,mBAAQ,CAAC,EAAS,CAAC;KACjC,CAAC;CACH,CAAC,CAAC,CAAC;AAEJ;;GAEG;AACU,QAAA,iBAAiB,GAAG,IAAA,yBAAS,EAAC,mBAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAClE,MAAM,EAAE,IAAI,CAAC,aAAK,EAAE;QAClB,MAAM,EAAE,CAAC,mBAAQ,CAAC,QAAQ,CAAC;QAC3B,UAAU,EAAE,CAAC,aAAK,CAAC,EAAS,CAAC;KAC9B,CAAC;CACH,CAAC,CAAC,CAAC","sourcesContent":["/**\n * Model Schema - AI 模型配置\n *\n * 存储位置: /settings/ai/models.ttl\n *\n * RDF 示例:\n * <#text-embedding-004> a udfs:Model ;\n * udfs:displayName \"Google Text Embedding 004\" ;\n * udfs:modelType \"embedding\" ;\n * udfs:dimension 768 ;\n * udfs:status \"active\" ;\n * udfs:isProvidedBy </settings/ai/providers.ttl#google> .\n *\n * 注:id 即为模型名(如 text-embedding-004),与供应商 API 对齐\n */\n\nimport { podTable, string, int, datetime, uri, relations } from '@undefineds.co/drizzle-solid';\nimport { UDFS, UDFS_NAMESPACE } from '../../vocab';\nimport { Provider } from './provider';\n\n/**\n * Model - 基础模型定义\n */\nexport const Model = podTable(\n 'Model',\n {\n id: string('id').primaryKey(),\n displayName: string('displayName'),\n modelType: string('modelType'),\n isProvidedBy: uri('isProvidedBy'),\n dimension: int('dimension'),\n contextLength: int('contextLength'),\n maxOutputTokens: int('maxOutputTokens'),\n status: string('status'),\n createdAt: datetime('createdAt'),\n updatedAt: datetime('updatedAt'),\n },\n {\n base: '/settings/ai/models.ttl',\n type: UDFS.Model,\n namespace: UDFS_NAMESPACE,\n subjectTemplate: '#{id}',\n },\n);\n\nexport type ModelRow = typeof Model.$inferSelect;\nexport type ModelInsert = typeof Model.$inferInsert;\n\n/**\n * Model -> Provider 关系定义\n */\nexport const ModelRelations = relations(Model, ({ one }) => ({\n provider: one(Provider, {\n fields: [Model.isProvidedBy],\n references: [Provider.id as any],\n }),\n}));\n\n/**\n * Provider -> Model 关系定义\n */\nexport const ProviderRelations = relations(Provider, ({ many }) => ({\n models: many(Model, {\n fields: [Provider.hasModel],\n references: [Model.id as any],\n }),\n}));\n"]}
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
* udfs:baseUrl "https://generativelanguage.googleapis.com/v1beta/openai" ;
|
|
10
10
|
* udfs:hasModel </settings/ai/models.ttl#text-embedding-004> .
|
|
11
11
|
*/
|
|
12
|
-
export declare const Provider: import("drizzle-solid/dist/core/schema").PodTableWithColumns<import("drizzle-solid/dist/core/schema").ResolvedColumns<{
|
|
13
|
-
id: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, false>;
|
|
14
|
-
displayName: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
15
|
-
baseUrl: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
16
|
-
proxyUrl: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
17
|
-
hasModel: import("drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
18
|
-
hasCredential: import("drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
12
|
+
export declare const Provider: import("@undefineds.co/drizzle-solid/dist/core/schema").PodTableWithColumns<import("@undefineds.co/drizzle-solid/dist/core/schema").ResolvedColumns<{
|
|
13
|
+
id: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, false>;
|
|
14
|
+
displayName: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
15
|
+
baseUrl: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
16
|
+
proxyUrl: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
17
|
+
hasModel: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
18
|
+
hasCredential: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
19
19
|
}>>;
|
|
20
20
|
export type ProviderRow = typeof Provider.$inferSelect;
|
|
21
21
|
export type ProviderInsert = typeof Provider.$inferInsert;
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
exports.Provider = void 0;
|
|
15
|
-
const drizzle_solid_1 = require("drizzle-solid");
|
|
15
|
+
const drizzle_solid_1 = require("@undefineds.co/drizzle-solid");
|
|
16
16
|
const vocab_1 = require("../../vocab");
|
|
17
17
|
exports.Provider = (0, drizzle_solid_1.podTable)('Provider', {
|
|
18
18
|
id: (0, drizzle_solid_1.string)('id').primaryKey(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/ai/schema/provider.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAEH,
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/ai/schema/provider.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAEH,gEAAqE;AACrE,uCAAmD;AAEtC,QAAA,QAAQ,GAAG,IAAA,wBAAQ,EAC9B,UAAU,EACV;IACE,EAAE,EAAE,IAAA,sBAAM,EAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC7B,WAAW,EAAE,IAAA,sBAAM,EAAC,aAAa,CAAC;IAClC,OAAO,EAAE,IAAA,sBAAM,EAAC,SAAS,CAAC;IAC1B,QAAQ,EAAE,IAAA,sBAAM,EAAC,UAAU,CAAC;IAC5B,QAAQ,EAAE,IAAA,mBAAG,EAAC,UAAU,CAAC;IACzB,aAAa,EAAE,IAAA,mBAAG,EAAC,eAAe,CAAC;CACpC,EACD;IACE,IAAI,EAAE,4BAA4B;IAClC,IAAI,EAAE,YAAI,CAAC,QAAQ;IACnB,SAAS,EAAE,sBAAc;IACzB,eAAe,EAAE,OAAO;CACzB,CACF,CAAC","sourcesContent":["/**\n * Provider Schema - AI 供应商配置\n *\n * 存储位置: /settings/ai/providers.ttl\n *\n * RDF 示例:\n * <#google> a udfs:Provider ;\n * udfs:displayName \"Google AI\" ;\n * udfs:baseUrl \"https://generativelanguage.googleapis.com/v1beta/openai\" ;\n * udfs:hasModel </settings/ai/models.ttl#text-embedding-004> .\n */\n\nimport { podTable, string, uri } from '@undefineds.co/drizzle-solid';\nimport { UDFS, UDFS_NAMESPACE } from '../../vocab';\n\nexport const Provider = podTable(\n 'Provider',\n {\n id: string('id').primaryKey(),\n displayName: string('displayName'),\n baseUrl: string('baseUrl'),\n proxyUrl: string('proxyUrl'),\n hasModel: uri('hasModel'),\n hasCredential: uri('hasCredential'),\n },\n {\n base: '/settings/ai/providers.ttl',\n type: UDFS.Provider,\n namespace: UDFS_NAMESPACE,\n subjectTemplate: '#{id}',\n },\n);\n\nexport type ProviderRow = typeof Provider.$inferSelect;\nexport type ProviderInsert = typeof Provider.$inferInsert;\n"]}
|
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
* udfs:status "completed" ;
|
|
15
15
|
* udfs:createdAt "2024-01-15T10:30:00Z"^^xsd:dateTime .
|
|
16
16
|
*/
|
|
17
|
-
export declare const VectorStore: import("drizzle-solid/dist/core/schema").PodTableWithColumns<import("drizzle-solid/dist/core/schema").ResolvedColumns<{
|
|
18
|
-
id: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, false>;
|
|
19
|
-
name: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
20
|
-
container: import("drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
21
|
-
chunkingStrategy: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
22
|
-
status: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
23
|
-
createdAt: import("drizzle-solid/dist/core/schema").ColumnBuilder<"datetime", null, false, false>;
|
|
24
|
-
lastActiveAt: import("drizzle-solid/dist/core/schema").ColumnBuilder<"datetime", null, false, false>;
|
|
17
|
+
export declare const VectorStore: import("@undefineds.co/drizzle-solid/dist/core/schema").PodTableWithColumns<import("@undefineds.co/drizzle-solid/dist/core/schema").ResolvedColumns<{
|
|
18
|
+
id: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, false>;
|
|
19
|
+
name: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
20
|
+
container: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
21
|
+
chunkingStrategy: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
22
|
+
status: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
23
|
+
createdAt: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"datetime", null, false, false>;
|
|
24
|
+
lastActiveAt: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"datetime", null, false, false>;
|
|
25
25
|
}>>;
|
|
26
26
|
export type VectorStoreRow = typeof VectorStore.$inferSelect;
|
|
27
27
|
export type VectorStoreInsert = typeof VectorStore.$inferInsert;
|
|
@@ -39,15 +39,15 @@ export type VectorStoreInsert = typeof VectorStore.$inferInsert;
|
|
|
39
39
|
* udfs:usageBytes "1024"^^xsd:integer ;
|
|
40
40
|
* udfs:indexedAt "2024-01-15T10:30:00Z"^^xsd:dateTime .
|
|
41
41
|
*/
|
|
42
|
-
export declare const IndexedFile: import("drizzle-solid/dist/core/schema").PodTableWithColumns<import("drizzle-solid/dist/core/schema").ResolvedColumns<{
|
|
43
|
-
id: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, false>;
|
|
44
|
-
fileUrl: import("drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
45
|
-
vectorId: import("drizzle-solid/dist/core/schema").ColumnBuilder<"integer", null, false, false>;
|
|
46
|
-
chunkingStrategy: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
47
|
-
status: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
48
|
-
usageBytes: import("drizzle-solid/dist/core/schema").ColumnBuilder<"integer", null, false, false>;
|
|
49
|
-
lastError: import("drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
50
|
-
indexedAt: import("drizzle-solid/dist/core/schema").ColumnBuilder<"datetime", null, false, false>;
|
|
42
|
+
export declare const IndexedFile: import("@undefineds.co/drizzle-solid/dist/core/schema").PodTableWithColumns<import("@undefineds.co/drizzle-solid/dist/core/schema").ResolvedColumns<{
|
|
43
|
+
id: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, false>;
|
|
44
|
+
fileUrl: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
45
|
+
vectorId: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"integer", null, false, false>;
|
|
46
|
+
chunkingStrategy: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
47
|
+
status: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
48
|
+
usageBytes: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"integer", null, false, false>;
|
|
49
|
+
lastError: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
50
|
+
indexedAt: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"datetime", null, false, false>;
|
|
51
51
|
}>>;
|
|
52
52
|
export type IndexedFileRow = typeof IndexedFile.$inferSelect;
|
|
53
53
|
export type IndexedFileInsert = typeof IndexedFile.$inferInsert;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.IndexedFile = exports.VectorStore = void 0;
|
|
9
|
-
const drizzle_solid_1 = require("drizzle-solid");
|
|
9
|
+
const drizzle_solid_1 = require("@undefineds.co/drizzle-solid");
|
|
10
10
|
const vocab_1 = require("../../vocab");
|
|
11
11
|
/**
|
|
12
12
|
* VectorStore - Container 级别的知识库配置
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vector-store.js","sourceRoot":"","sources":["../../../src/ai/schema/vector-store.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,
|
|
1
|
+
{"version":3,"file":"vector-store.js","sourceRoot":"","sources":["../../../src/ai/schema/vector-store.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,gEAAoF;AACpF,uCAAmD;AAEnD;;;;;;;;;;GAUG;AACU,QAAA,WAAW,GAAG,IAAA,wBAAQ,EACjC,aAAa,EACb;IACE,EAAE,EAAE,IAAA,sBAAM,EAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC7B,IAAI,EAAE,IAAA,sBAAM,EAAC,MAAM,CAAC;IACpB,SAAS,EAAE,IAAA,mBAAG,EAAC,WAAW,CAAC;IAC3B,gBAAgB,EAAE,IAAA,sBAAM,EAAC,kBAAkB,CAAC;IAC5C,MAAM,EAAE,IAAA,sBAAM,EAAC,QAAQ,CAAC;IACxB,SAAS,EAAE,IAAA,wBAAQ,EAAC,WAAW,CAAC;IAChC,YAAY,EAAE,IAAA,wBAAQ,EAAC,cAAc,CAAC;CACvC,EACD;IACE,IAAI,EAAE,gCAAgC;IACtC,IAAI,EAAE,YAAI,CAAC,WAAW;IACtB,SAAS,EAAE,sBAAc;IACzB,eAAe,EAAE,OAAO;CACzB,CACF,CAAC;AAKF;;;;;;;;;;;;;GAaG;AACU,QAAA,WAAW,GAAG,IAAA,wBAAQ,EACjC,aAAa,EACb;IACE,EAAE,EAAE,IAAA,sBAAM,EAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC7B,OAAO,EAAE,IAAA,mBAAG,EAAC,SAAS,CAAC;IACvB,QAAQ,EAAE,IAAA,mBAAG,EAAC,UAAU,CAAC;IACzB,gBAAgB,EAAE,IAAA,sBAAM,EAAC,kBAAkB,CAAC;IAC5C,MAAM,EAAE,IAAA,sBAAM,EAAC,QAAQ,CAAC;IACxB,UAAU,EAAE,IAAA,mBAAG,EAAC,YAAY,CAAC;IAC7B,SAAS,EAAE,IAAA,sBAAM,EAAC,WAAW,CAAC;IAC9B,SAAS,EAAE,IAAA,wBAAQ,EAAC,WAAW,CAAC;CACjC,EACD;IACE,IAAI,EAAE,gCAAgC;IACtC,IAAI,EAAE,YAAI,CAAC,WAAW;IACtB,SAAS,EAAE,sBAAc;IACzB,eAAe,EAAE,OAAO;CACzB,CACF,CAAC","sourcesContent":["/**\n * VectorStore Schema - Container 级别的知识库配置\n *\n * 存储位置: /settings/ai/vector-stores.ttl\n */\n\nimport { podTable, string, int, datetime, uri } from '@undefineds.co/drizzle-solid';\nimport { UDFS, UDFS_NAMESPACE } from '../../vocab';\n\n/**\n * VectorStore - Container 级别的知识库配置\n *\n * RDF 示例:\n * <#vs_abc123> a udfs:VectorStore ;\n * udfs:name \"My Notes\" ;\n * udfs:container </notes/> ;\n * udfs:chunkingStrategy \"auto\" ;\n * udfs:status \"completed\" ;\n * udfs:createdAt \"2024-01-15T10:30:00Z\"^^xsd:dateTime .\n */\nexport const VectorStore = podTable(\n 'VectorStore',\n {\n id: string('id').primaryKey(),\n name: string('name'),\n container: uri('container'),\n chunkingStrategy: string('chunkingStrategy'),\n status: string('status'),\n createdAt: datetime('createdAt'),\n lastActiveAt: datetime('lastActiveAt'),\n },\n {\n base: '/settings/ai/vector-stores.ttl',\n type: UDFS.VectorStore,\n namespace: UDFS_NAMESPACE,\n subjectTemplate: '#{id}',\n },\n);\n\nexport type VectorStoreRow = typeof VectorStore.$inferSelect;\nexport type VectorStoreInsert = typeof VectorStore.$inferInsert;\n\n/**\n * IndexedFile - 全局文件索引状态管理\n *\n * 存储位置: /settings/ai/indexed-files.ttl\n *\n * RDF 示例:\n * <#idx_abc123> a udfs:IndexedFile ;\n * udfs:fileUrl </notes/hello.md> ;\n * udfs:vectorId \"123456789\"^^xsd:integer ;\n * udfs:chunkingStrategy \"auto\" ;\n * udfs:status \"completed\" ;\n * udfs:usageBytes \"1024\"^^xsd:integer ;\n * udfs:indexedAt \"2024-01-15T10:30:00Z\"^^xsd:dateTime .\n */\nexport const IndexedFile = podTable(\n 'IndexedFile',\n {\n id: string('id').primaryKey(),\n fileUrl: uri('fileUrl'),\n vectorId: int('vectorId'),\n chunkingStrategy: string('chunkingStrategy'),\n status: string('status'),\n usageBytes: int('usageBytes'),\n lastError: string('lastError'),\n indexedAt: datetime('indexedAt'),\n },\n {\n base: '/settings/ai/indexed-files.ttl',\n type: UDFS.IndexedFile,\n namespace: UDFS_NAMESPACE,\n subjectTemplate: '#{id}',\n },\n);\n\nexport type IndexedFileRow = typeof IndexedFile.$inferSelect;\nexport type IndexedFileInsert = typeof IndexedFile.$inferInsert;\n"]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CredentialReaderImpl = void 0;
|
|
4
4
|
const global_logger_factory_1 = require("global-logger-factory");
|
|
5
|
-
const drizzle_solid_1 = require("drizzle-solid");
|
|
5
|
+
const drizzle_solid_1 = require("@undefineds.co/drizzle-solid");
|
|
6
6
|
const CredentialReader_1 = require("./CredentialReader");
|
|
7
7
|
const tables_1 = require("../../credential/schema/tables");
|
|
8
8
|
const provider_1 = require("../schema/provider");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CredentialReaderImpl.js","sourceRoot":"","sources":["../../../src/ai/service/CredentialReaderImpl.ts"],"names":[],"mappings":";;;AAAA,iEAAqD;AACrD,
|
|
1
|
+
{"version":3,"file":"CredentialReaderImpl.js","sourceRoot":"","sources":["../../../src/ai/service/CredentialReaderImpl.ts"],"names":[],"mappings":";;;AAAA,iEAAqD;AACrD,gEAAgE;AAChE,yDAAsD;AAEtD,2DAA4D;AAC5D,iDAA8C;AAC9C,yDAA8E;AAE9E,MAAM,MAAM,GAAG;IACb,UAAU,EAAE,mBAAU;IACtB,QAAQ,EAAE,mBAAQ;CACnB,CAAC;AAEF,MAAa,oBAAqB,SAAQ,mCAAgB;IAA1D;;QACqB,WAAM,GAAG,IAAA,oCAAY,EAAC,IAAI,CAAC,CAAC;IAiDjD,CAAC;IA/CiB,KAAK,CAAC,eAAe,CACnC,UAAkB,EAClB,UAAkB,EAClB,kBAAgC,EAChC,KAAc;QAEd,IAAI,CAAC;YACH,MAAM,OAAO,GAAG;gBACd,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE;gBACjC,KAAK,EAAE,kBAAkB;aAC1B,CAAC;YACF,MAAM,EAAE,GAAG,IAAA,uBAAO,EAAC,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAExC,kBAAkB;YAClB,MAAM,WAAW,GAAG,GAAG,UAAU,6BAA6B,UAAU,EAAE,CAAC;YAE3E,qCAAqC;YACrC,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC;gBACrD,KAAK,EAAE,IAAA,mBAAG,EACR,IAAA,kBAAE,EAAC,mBAAU,CAAC,OAAO,EAAE,mBAAW,CAAC,EAAE,CAAC,EACtC,IAAA,kBAAE,EAAC,mBAAU,CAAC,MAAM,EAAE,wBAAgB,CAAC,MAAM,CAAC,EAC9C,IAAA,kBAAE,EAAC,mBAAU,CAAC,QAAQ,EAAE,WAAW,CAAC,CACrC;gBACD,IAAI,EAAE;oBACJ,QAAQ,EAAE,IAAI;iBACf;aACF,CAAC,CAAC;YAEH,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC7B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4CAA4C,UAAU,EAAE,CAAC,CAAC;gBAC5E,OAAO,IAAI,CAAC;YACd,CAAC;YAED,eAAe;YACf,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,CAAQ,CAAC;YAEtF,OAAO;gBACL,QAAQ,EAAE,UAAU;gBACpB,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,OAAO,EAAE,UAAU,CAAC,OAAO,IAAI,UAAU,CAAC,QAAQ,EAAE,OAAO,IAAI,SAAS;gBACxE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,QAAQ,IAAI,SAAS;aACrD,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0CAA0C,UAAU,GAAG,EAAE,KAAK,CAAC,CAAC;YAClF,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;CACF;AAlDD,oDAkDC","sourcesContent":["import { getLoggerFor } from 'global-logger-factory';\nimport { drizzle, eq, and } from '@undefineds.co/drizzle-solid';\nimport { CredentialReader } from './CredentialReader';\nimport type { AiCredential } from './types';\nimport { Credential } from '../../credential/schema/tables';\nimport { Provider } from '../schema/provider';\nimport { ServiceType, CredentialStatus } from '../../credential/schema/types';\n\nconst schema = {\n credential: Credential,\n provider: Provider,\n};\n\nexport class CredentialReaderImpl extends CredentialReader {\n protected readonly logger = getLoggerFor(this);\n\n public override async getAiCredential(\n podBaseUrl: string,\n providerId: string,\n authenticatedFetch: typeof fetch,\n webId?: string,\n ): Promise<AiCredential | null> {\n try {\n const session = {\n info: { isLoggedIn: true, webId },\n fetch: authenticatedFetch,\n };\n const db = drizzle(session, { schema });\n\n // 构建 Provider URI\n const providerUri = `${podBaseUrl}settings/ai/providers.ttl#${providerId}`;\n\n // 查询 credential,直接通过 provider URI 过滤\n const credentials = await db.query.credential.findMany({\n where: and(\n eq(Credential.service, ServiceType.AI),\n eq(Credential.status, CredentialStatus.ACTIVE),\n eq(Credential.provider, providerUri),\n ),\n with: {\n provider: true,\n },\n });\n\n if (credentials.length === 0) {\n this.logger.debug(`No active credential found for provider: ${providerId}`);\n return null;\n }\n\n // 随机选择一个(负载均衡)\n const credential = credentials[Math.floor(Math.random() * credentials.length)] as any;\n\n return {\n provider: providerId,\n apiKey: credential.apiKey,\n baseUrl: credential.baseUrl || credential.provider?.baseUrl || undefined,\n proxyUrl: credential.provider?.proxyUrl || undefined,\n };\n } catch (error) {\n this.logger.error(`Failed to read credential for provider ${providerId}:`, error);\n return null;\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultAiConfigService.js","sourceRoot":"","sources":["../../../src/ai/service/DefaultAiConfigService.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 默认 AI 配置服务\n *\n * 当用户没有配置任何 AI provider 时,使用 OpenRouter 免费模型\n * 智能识别用户输入中的 AI 配置信息并存储到 Pod\n */\n\nimport { getLoggerFor } from 'global-logger-factory';\nimport { drizzle } from 'drizzle-solid';\nimport { Provider } from '../schema/provider';\nimport { Model } from '../schema/model';\nimport { Credential } from '../../credential/schema/tables';\nimport { ServiceType, CredentialStatus } from '../../credential/schema/types';\n\nconst logger = getLoggerFor('DefaultAiConfigService');\n\nconst schema = {\n provider: Provider,\n model: Model,\n credential: Credential,\n};\n\n/**\n * 默认 AI 配置(OpenRouter 免费模型)\n */\nexport const DEFAULT_AI_CONFIG = {\n baseURL: 'https://openrouter.ai/api/v1',\n apiKey: '', // 用户需要填入自己的 OpenRouter API Key\n model: 'stepfun/step-3.5-flash:free',\n displayName: 'OpenRouter Free',\n};\n\n/**\n * 从用户输入中识别 AI 配置信息\n */\nexport interface ParsedAiConfig {\n provider?: string;\n baseUrl?: string;\n apiKey?: string;\n model?: string;\n proxyUrl?: string;\n}\n\n/**\n * 识别用户输入中的 AI 配置信息\n */\nexport function parseAiConfigFromInput(input: string): ParsedAiConfig | null {\n const result: ParsedAiConfig = {};\n \n // 识别 API Key (常见的 key 格式)\n const apiKeyPatterns = [\n /(?:api[_-]?key|key|token|sk)[\\s:=]+[\"']?([a-zA-Z0-9_\\-]{20,})[\"']?/i,\n /(sk-[a-zA-Z0-9]{20,})/i,\n /([a-f0-9]{32,})/i,\n ];\n \n for (const pattern of apiKeyPatterns) {\n const match = input.match(pattern);\n if (match) {\n result.apiKey = match[1];\n break;\n }\n }\n \n // 识别 Provider / Base URL\n const providerPatterns: Record<string, RegExp[]> = {\n openai: [/openai\\.com/i, /api\\.openai\\.com/i],\n google: [/google.*gemini/i, /generativelanguage\\.googleapis\\.com/i, /gemini/i],\n anthropic: [/anthropic/i, /claude/i, /api\\.anthropic\\.com/i],\n deepseek: [/deepseek/i, /api\\.deepseek\\.com/i],\n openrouter: [/openrouter/i, /openrouter\\.ai/i],\n ollama: [/ollama/i, /localhost:11434/i],\n mistral: [/mistral/i, /api\\.mistral\\.ai/i],\n cohere: [/cohere/i, /api\\.cohere\\.ai/i],\n zhipu: [/zhipu/i, /智谱/i, /bigmodel/i],\n };\n \n for (const [name, patterns] of Object.entries(providerPatterns)) {\n for (const pattern of patterns) {\n if (pattern.test(input)) {\n result.provider = name;\n break;\n }\n }\n if (result.provider) break;\n }\n \n // 识别 Base URL\n const urlPattern = /(https?:\\/\\/[a-zA-Z0-9\\-\\.]+(?:\\:\\d+)?(?:\\/[a-zA-Z0-9\\-\\/]*)?)/i;\n const urlMatch = input.match(urlPattern);\n if (urlMatch) {\n result.baseUrl = urlMatch[1];\n }\n \n // 识别 Model\n const modelPatterns = [\n // OpenAI\n /gpt-4[\\w\\-]*/i,\n /gpt-3\\.5-turbo/i,\n // Google\n /gemini-[\\w\\-]+/i,\n // Anthropic\n /claude-[\\w\\-]+/i,\n // DeepSeek\n /deepseek-[\\w\\-]+/i,\n // Llama\n /llama-[\\d\\.]+[\\w\\-]*/i,\n // Mistral\n /mistral-[\\w\\-]+/i,\n // Qwen\n /qwen[\\w\\-]*/i,\n // 通用\n /[\"']([a-zA-Z0-9\\/\\-\\:]+free)[\"']/i,\n /model[:\\s=]+[\"']?([a-zA-Z0-9\\/\\-\\:_\\.]+)[\"']?/i,\n ];\n \n for (const pattern of modelPatterns) {\n const match = input.match(pattern);\n if (match) {\n result.model = match[0].replace(/[\"']/g, '');\n break;\n }\n }\n \n // 识别 Proxy URL\n const proxyPattern = /proxy[:\\s=]+[\"']?(https?:\\/\\/[^\"'\\s]+)[\"']?/i;\n const proxyMatch = input.match(proxyPattern);\n if (proxyMatch) {\n result.proxyUrl = proxyMatch[1];\n }\n \n // 如果什么都没识别到,返回 null\n if (Object.keys(result).length === 0) {\n return null;\n }\n \n logger.debug(`Parsed AI config from input: ${JSON.stringify(result)}`);\n return result;\n}\n\n/**\n * 获取完整的 AI 配置(默认 + 解析出的)\n */\nexport function getDefaultAiConfig(userInput?: string): {\n baseURL: string;\n apiKey: string;\n model: string;\n displayName: string;\n parsedConfig?: ParsedAiConfig;\n} {\n const parsedConfig = userInput ? parseAiConfigFromInput(userInput) : null;\n \n // 如果用户提供了 baseUrl,使用用户的;否则使用默认\n const baseURL = parsedConfig?.baseUrl || \n (parsedConfig?.provider ? getDefaultBaseUrl(parsedConfig.provider) : DEFAULT_AI_CONFIG.baseURL);\n \n // 使用用户提供的 API Key 或空字符串\n const apiKey = parsedConfig?.apiKey || DEFAULT_AI_CONFIG.apiKey;\n \n // 使用用户提供的模型或默认模型\n const model = parsedConfig?.model || DEFAULT_AI_CONFIG.model;\n \n return {\n baseURL,\n apiKey,\n model,\n displayName: parsedConfig?.provider \n ? `${parsedConfig.provider.charAt(0).toUpperCase() + parsedConfig.provider.slice(1)}` \n : DEFAULT_AI_CONFIG.displayName,\n parsedConfig: parsedConfig || undefined,\n };\n}\n\n/**\n * 根据 provider 名称获取默认 base URL\n */\nfunction getDefaultBaseUrl(provider: string): string {\n const urls: Record<string, string> = {\n openai: 'https://api.openai.com/v1',\n google: 'https://generativelanguage.googleapis.com/v1beta/openai',\n anthropic: 'https://api.anthropic.com/v1',\n deepseek: 'https://api.deepseek.com/v1',\n openrouter: 'https://openrouter.ai/api/v1',\n ollama: 'http://localhost:11434/v1',\n mistral: 'https://api.mistral.ai/v1',\n cohere: 'https://api.cohere.ai/v1',\n zhipu: 'https://open.bigmodel.cn/api/paas/v4',\n };\n return urls[provider.toLowerCase()] || DEFAULT_AI_CONFIG.baseURL;\n}\n\n/**\n * 保存 AI 配置到 Pod\n * \n * 注意:这是一个占位实现,实际的保存逻辑需要调用 PodChatKitStore 的方法\n * 或通过 API 端点进行保存\n */\nexport async function saveAiConfigToPod(\n _podBaseUrl: string,\n config: ParsedAiConfig,\n _authenticatedFetch: typeof fetch,\n _webId?: string,\n): Promise<{ success: boolean; message: string }> {\n const logger = getLoggerFor('DefaultAiConfigService');\n \n // 验证必要的字段\n if (!config.provider && !config.baseUrl) {\n return { success: false, message: '无法识别 AI Provider' };\n }\n if (!config.apiKey) {\n return { success: false, message: '无法识别 API Key' };\n }\n \n const providerId = config.provider || 'custom';\n const displayName = config.provider \n ? config.provider.charAt(0).toUpperCase() + config.provider.slice(1)\n : 'Custom Provider';\n \n logger.debug(`AI config parsed: provider=${providerId}, model=${config.model}`);\n \n return { \n success: true, \n message: `已识别 AI 配置:${displayName}${config.model ? ` (${config.model})` : ''}。请在设置中确认保存。` \n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"DefaultAiConfigService.js","sourceRoot":"","sources":["../../../src/ai/service/DefaultAiConfigService.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 默认 AI 配置服务\n *\n * 当用户没有配置任何 AI provider 时,使用 OpenRouter 免费模型\n * 智能识别用户输入中的 AI 配置信息并存储到 Pod\n */\n\nimport { getLoggerFor } from 'global-logger-factory';\nimport { drizzle } from '@undefineds.co/drizzle-solid';\nimport { Provider } from '../schema/provider';\nimport { Model } from '../schema/model';\nimport { Credential } from '../../credential/schema/tables';\nimport { ServiceType, CredentialStatus } from '../../credential/schema/types';\n\nconst logger = getLoggerFor('DefaultAiConfigService');\n\nconst schema = {\n provider: Provider,\n model: Model,\n credential: Credential,\n};\n\n/**\n * 默认 AI 配置(OpenRouter 免费模型)\n */\nexport const DEFAULT_AI_CONFIG = {\n baseURL: 'https://openrouter.ai/api/v1',\n apiKey: '', // 用户需要填入自己的 OpenRouter API Key\n model: 'stepfun/step-3.5-flash:free',\n displayName: 'OpenRouter Free',\n};\n\n/**\n * 从用户输入中识别 AI 配置信息\n */\nexport interface ParsedAiConfig {\n provider?: string;\n baseUrl?: string;\n apiKey?: string;\n model?: string;\n proxyUrl?: string;\n}\n\n/**\n * 识别用户输入中的 AI 配置信息\n */\nexport function parseAiConfigFromInput(input: string): ParsedAiConfig | null {\n const result: ParsedAiConfig = {};\n \n // 识别 API Key (常见的 key 格式)\n const apiKeyPatterns = [\n /(?:api[_-]?key|key|token|sk)[\\s:=]+[\"']?([a-zA-Z0-9_\\-]{20,})[\"']?/i,\n /(sk-[a-zA-Z0-9]{20,})/i,\n /([a-f0-9]{32,})/i,\n ];\n \n for (const pattern of apiKeyPatterns) {\n const match = input.match(pattern);\n if (match) {\n result.apiKey = match[1];\n break;\n }\n }\n \n // 识别 Provider / Base URL\n const providerPatterns: Record<string, RegExp[]> = {\n openai: [/openai\\.com/i, /api\\.openai\\.com/i],\n google: [/google.*gemini/i, /generativelanguage\\.googleapis\\.com/i, /gemini/i],\n anthropic: [/anthropic/i, /claude/i, /api\\.anthropic\\.com/i],\n deepseek: [/deepseek/i, /api\\.deepseek\\.com/i],\n openrouter: [/openrouter/i, /openrouter\\.ai/i],\n ollama: [/ollama/i, /localhost:11434/i],\n mistral: [/mistral/i, /api\\.mistral\\.ai/i],\n cohere: [/cohere/i, /api\\.cohere\\.ai/i],\n zhipu: [/zhipu/i, /智谱/i, /bigmodel/i],\n };\n \n for (const [name, patterns] of Object.entries(providerPatterns)) {\n for (const pattern of patterns) {\n if (pattern.test(input)) {\n result.provider = name;\n break;\n }\n }\n if (result.provider) break;\n }\n \n // 识别 Base URL\n const urlPattern = /(https?:\\/\\/[a-zA-Z0-9\\-\\.]+(?:\\:\\d+)?(?:\\/[a-zA-Z0-9\\-\\/]*)?)/i;\n const urlMatch = input.match(urlPattern);\n if (urlMatch) {\n result.baseUrl = urlMatch[1];\n }\n \n // 识别 Model\n const modelPatterns = [\n // OpenAI\n /gpt-4[\\w\\-]*/i,\n /gpt-3\\.5-turbo/i,\n // Google\n /gemini-[\\w\\-]+/i,\n // Anthropic\n /claude-[\\w\\-]+/i,\n // DeepSeek\n /deepseek-[\\w\\-]+/i,\n // Llama\n /llama-[\\d\\.]+[\\w\\-]*/i,\n // Mistral\n /mistral-[\\w\\-]+/i,\n // Qwen\n /qwen[\\w\\-]*/i,\n // 通用\n /[\"']([a-zA-Z0-9\\/\\-\\:]+free)[\"']/i,\n /model[:\\s=]+[\"']?([a-zA-Z0-9\\/\\-\\:_\\.]+)[\"']?/i,\n ];\n \n for (const pattern of modelPatterns) {\n const match = input.match(pattern);\n if (match) {\n result.model = match[0].replace(/[\"']/g, '');\n break;\n }\n }\n \n // 识别 Proxy URL\n const proxyPattern = /proxy[:\\s=]+[\"']?(https?:\\/\\/[^\"'\\s]+)[\"']?/i;\n const proxyMatch = input.match(proxyPattern);\n if (proxyMatch) {\n result.proxyUrl = proxyMatch[1];\n }\n \n // 如果什么都没识别到,返回 null\n if (Object.keys(result).length === 0) {\n return null;\n }\n \n logger.debug(`Parsed AI config from input: ${JSON.stringify(result)}`);\n return result;\n}\n\n/**\n * 获取完整的 AI 配置(默认 + 解析出的)\n */\nexport function getDefaultAiConfig(userInput?: string): {\n baseURL: string;\n apiKey: string;\n model: string;\n displayName: string;\n parsedConfig?: ParsedAiConfig;\n} {\n const parsedConfig = userInput ? parseAiConfigFromInput(userInput) : null;\n \n // 如果用户提供了 baseUrl,使用用户的;否则使用默认\n const baseURL = parsedConfig?.baseUrl || \n (parsedConfig?.provider ? getDefaultBaseUrl(parsedConfig.provider) : DEFAULT_AI_CONFIG.baseURL);\n \n // 使用用户提供的 API Key 或空字符串\n const apiKey = parsedConfig?.apiKey || DEFAULT_AI_CONFIG.apiKey;\n \n // 使用用户提供的模型或默认模型\n const model = parsedConfig?.model || DEFAULT_AI_CONFIG.model;\n \n return {\n baseURL,\n apiKey,\n model,\n displayName: parsedConfig?.provider \n ? `${parsedConfig.provider.charAt(0).toUpperCase() + parsedConfig.provider.slice(1)}` \n : DEFAULT_AI_CONFIG.displayName,\n parsedConfig: parsedConfig || undefined,\n };\n}\n\n/**\n * 根据 provider 名称获取默认 base URL\n */\nfunction getDefaultBaseUrl(provider: string): string {\n const urls: Record<string, string> = {\n openai: 'https://api.openai.com/v1',\n google: 'https://generativelanguage.googleapis.com/v1beta/openai',\n anthropic: 'https://api.anthropic.com/v1',\n deepseek: 'https://api.deepseek.com/v1',\n openrouter: 'https://openrouter.ai/api/v1',\n ollama: 'http://localhost:11434/v1',\n mistral: 'https://api.mistral.ai/v1',\n cohere: 'https://api.cohere.ai/v1',\n zhipu: 'https://open.bigmodel.cn/api/paas/v4',\n };\n return urls[provider.toLowerCase()] || DEFAULT_AI_CONFIG.baseURL;\n}\n\n/**\n * 保存 AI 配置到 Pod\n * \n * 注意:这是一个占位实现,实际的保存逻辑需要调用 PodChatKitStore 的方法\n * 或通过 API 端点进行保存\n */\nexport async function saveAiConfigToPod(\n _podBaseUrl: string,\n config: ParsedAiConfig,\n _authenticatedFetch: typeof fetch,\n _webId?: string,\n): Promise<{ success: boolean; message: string }> {\n const logger = getLoggerFor('DefaultAiConfigService');\n \n // 验证必要的字段\n if (!config.provider && !config.baseUrl) {\n return { success: false, message: '无法识别 AI Provider' };\n }\n if (!config.apiKey) {\n return { success: false, message: '无法识别 API Key' };\n }\n \n const providerId = config.provider || 'custom';\n const displayName = config.provider \n ? config.provider.charAt(0).toUpperCase() + config.provider.slice(1)\n : 'Custom Provider';\n \n logger.debug(`AI config parsed: provider=${providerId}, model=${config.model}`);\n \n return { \n success: true, \n message: `已识别 AI 配置:${displayName}${config.model ? ` (${config.model})` : ''}。请在设置中确认保存。` \n };\n}\n"]}
|
package/dist/api/ApiServer.d.ts
CHANGED
|
@@ -16,8 +16,9 @@ export interface Route {
|
|
|
16
16
|
public?: boolean;
|
|
17
17
|
}
|
|
18
18
|
export interface ApiServerOptions {
|
|
19
|
-
port
|
|
19
|
+
port?: number;
|
|
20
20
|
host?: string;
|
|
21
|
+
socketPath?: string;
|
|
21
22
|
authMiddleware: AuthMiddleware;
|
|
22
23
|
corsOrigins?: string[];
|
|
23
24
|
}
|
|
@@ -28,6 +29,7 @@ export declare class ApiServer {
|
|
|
28
29
|
private readonly logger;
|
|
29
30
|
private readonly port;
|
|
30
31
|
private readonly host;
|
|
32
|
+
private readonly socketPath?;
|
|
31
33
|
private readonly authMiddleware;
|
|
32
34
|
private readonly corsOrigins;
|
|
33
35
|
private readonly routes;
|
package/dist/api/ApiServer.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ApiServer = void 0;
|
|
4
4
|
const node_http_1 = require("node:http");
|
|
5
5
|
const global_logger_factory_1 = require("global-logger-factory");
|
|
6
|
+
const socket_utils_1 = require("../runtime/socket-utils");
|
|
6
7
|
/**
|
|
7
8
|
* Standalone API Server
|
|
8
9
|
*/
|
|
@@ -10,8 +11,9 @@ class ApiServer {
|
|
|
10
11
|
constructor(options) {
|
|
11
12
|
this.logger = (0, global_logger_factory_1.getLoggerFor)(this);
|
|
12
13
|
this.routes = [];
|
|
13
|
-
this.port = options.port;
|
|
14
|
+
this.port = options.port ?? 0;
|
|
14
15
|
this.host = options.host ?? '0.0.0.0';
|
|
16
|
+
this.socketPath = options.socketPath;
|
|
15
17
|
this.authMiddleware = options.authMiddleware;
|
|
16
18
|
this.corsOrigins = options.corsOrigins ?? ['*'];
|
|
17
19
|
}
|
|
@@ -63,6 +65,14 @@ class ApiServer {
|
|
|
63
65
|
});
|
|
64
66
|
});
|
|
65
67
|
this.server.on('error', reject);
|
|
68
|
+
if (this.socketPath) {
|
|
69
|
+
(0, socket_utils_1.prepareSocketPath)(this.socketPath);
|
|
70
|
+
this.server.listen(this.socketPath, () => {
|
|
71
|
+
this.logger.info(`API Server listening on unix://${this.socketPath}`);
|
|
72
|
+
resolve();
|
|
73
|
+
});
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
66
76
|
this.server.listen(this.port, this.host, () => {
|
|
67
77
|
this.logger.info(`API Server listening on ${this.host}:${this.port}`);
|
|
68
78
|
resolve();
|
|
@@ -83,6 +93,9 @@ class ApiServer {
|
|
|
83
93
|
reject(error);
|
|
84
94
|
}
|
|
85
95
|
else {
|
|
96
|
+
if (this.socketPath) {
|
|
97
|
+
(0, socket_utils_1.removeSocketPath)(this.socketPath);
|
|
98
|
+
}
|
|
86
99
|
this.logger.info('API Server stopped');
|
|
87
100
|
resolve();
|
|
88
101
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiServer.js","sourceRoot":"","sources":["../../src/api/ApiServer.ts"],"names":[],"mappings":"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","sourcesContent":["import { createServer, type Server, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { AuthMiddleware, AuthenticatedRequest } from './middleware/AuthMiddleware';\n\n/**\n * Route handler function\n */\nexport type RouteHandler = (\n request: AuthenticatedRequest,\n response: ServerResponse,\n params: Record<string, string>,\n) => Promise<void>;\n\n/**\n * Route definition\n */\nexport interface Route {\n method: string;\n pattern: RegExp;\n paramNames: string[];\n handler: RouteHandler;\n /** If true, skip authentication */\n public?: boolean;\n}\n\nexport interface ApiServerOptions {\n port: number;\n host?: string;\n authMiddleware: AuthMiddleware;\n corsOrigins?: string[];\n}\n\n/**\n * Standalone API Server\n */\nexport class ApiServer {\n private readonly logger = getLoggerFor(this);\n private readonly port: number;\n private readonly host: string;\n private readonly authMiddleware: AuthMiddleware;\n private readonly corsOrigins: string[];\n private readonly routes: Route[] = [];\n private server?: Server;\n\n public constructor(options: ApiServerOptions) {\n this.port = options.port;\n this.host = options.host ?? '0.0.0.0';\n this.authMiddleware = options.authMiddleware;\n this.corsOrigins = options.corsOrigins ?? ['*'];\n }\n\n /**\n * Register a route\n */\n public route(\n method: string,\n path: string,\n handler: RouteHandler,\n options?: {\n /** If true, skip authentication for this route */\n public?: boolean;\n },\n ): void {\n const { pattern, paramNames } = this.pathToRegex(path);\n this.routes.push({\n method: method.toUpperCase(),\n pattern,\n paramNames,\n handler,\n public: options?.public,\n });\n this.logger.debug(`Registered route: ${method.toUpperCase()} ${path}${options?.public ? ' (public)' : ''}`);\n }\n\n /**\n * Convenience methods for common HTTP methods\n */\n public get(path: string, handler: RouteHandler, options?: { public?: boolean }): void {\n this.route('GET', path, handler, options);\n }\n\n public post(path: string, handler: RouteHandler, options?: { public?: boolean }): void {\n this.route('POST', path, handler, options);\n }\n\n public put(path: string, handler: RouteHandler, options?: { public?: boolean }): void {\n this.route('PUT', path, handler, options);\n }\n\n public delete(path: string, handler: RouteHandler, options?: { public?: boolean }): void {\n this.route('DELETE', path, handler, options);\n }\n\n public patch(path: string, handler: RouteHandler, options?: { public?: boolean }): void {\n this.route('PATCH', path, handler, options);\n }\n\n /**\n * Start the server\n */\n public async start(): Promise<void> {\n return new Promise((resolve, reject) => {\n this.server = createServer((req, res) => {\n this.handleRequest(req, res).catch((error) => {\n this.logger.error(`Unhandled error: ${error}`);\n if (!res.headersSent) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Internal Server Error' }));\n }\n });\n });\n\n this.server.on('error', reject);\n\n this.server.listen(this.port, this.host, () => {\n this.logger.info(`API Server listening on ${this.host}:${this.port}`);\n resolve();\n });\n });\n }\n\n /**\n * Stop the server\n */\n public async stop(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!this.server) {\n resolve();\n return;\n }\n\n this.server.close((error) => {\n if (error) {\n reject(error);\n } else {\n this.logger.info('API Server stopped');\n resolve();\n }\n });\n });\n }\n\n /**\n * Get the underlying HTTP server (for WebSocket upgrade)\n */\n public getHttpServer(): Server | undefined {\n return this.server;\n }\n\n private async handleRequest(request: IncomingMessage, response: ServerResponse): Promise<void> {\n const method = request.method?.toUpperCase() ?? 'GET';\n const url = new URL(request.url ?? '/', `http://${request.headers.host ?? 'localhost'}`);\n const path = url.pathname;\n\n // Handle CORS preflight\n if (method === 'OPTIONS') {\n this.handleCors(request, response);\n response.statusCode = 204;\n response.end();\n return;\n }\n\n // Add CORS headers\n this.handleCors(request, response);\n\n // Find matching route\n const match = this.findRoute(method, path);\n if (!match) {\n response.statusCode = 404;\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify({ error: 'Not Found' }));\n return;\n }\n\n const { route, params } = match;\n const authRequest = request as AuthenticatedRequest;\n\n // Run auth middleware unless route is public\n if (!route.public) {\n const authOk = await this.authMiddleware.process(authRequest, response);\n if (!authOk) {\n return;\n }\n }\n\n // Execute handler\n try {\n await route.handler(authRequest, response, params);\n } catch (error) {\n this.logger.error(`Route handler error: ${error}`);\n if (!response.headersSent) {\n response.statusCode = 500;\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify({ error: 'Internal Server Error' }));\n }\n }\n }\n\n private findRoute(method: string, path: string): { route: Route; params: Record<string, string> } | undefined {\n for (const route of this.routes) {\n if (route.method !== method) {\n continue;\n }\n\n const match = route.pattern.exec(path);\n if (match) {\n const params: Record<string, string> = {};\n route.paramNames.forEach((name, index) => {\n params[name] = match[index + 1];\n });\n return { route, params };\n }\n }\n return undefined;\n }\n\n private pathToRegex(path: string): { pattern: RegExp; paramNames: string[] } {\n const paramNames: string[] = [];\n let regexStr = path\n // 先处理通配符 *path 或 * (匹配剩余所有路径)\n .replace(/\\*([a-zA-Z0-9_]*)/g, (_, name) => {\n paramNames.push(name || 'wildcard');\n return '(.*)';\n })\n // 再处理普通参数 :param (只匹配单段)\n .replace(/:([a-zA-Z0-9_]+)/g, (_, name) => {\n paramNames.push(name);\n return '([^/]+)';\n })\n .replace(/\\//g, '\\\\/');\n return {\n pattern: new RegExp(`^${regexStr}$`),\n paramNames,\n };\n }\n\n private handleCors(request: IncomingMessage, response: ServerResponse): void {\n const origin = request.headers.origin;\n\n if (this.corsOrigins.includes('*')) {\n response.setHeader('Access-Control-Allow-Origin', '*');\n } else if (origin && this.corsOrigins.includes(origin)) {\n response.setHeader('Access-Control-Allow-Origin', origin);\n response.setHeader('Vary', 'Origin');\n }\n\n response.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');\n response.setHeader('Access-Control-Allow-Headers', '*');\n response.setHeader('Access-Control-Max-Age', '86400');\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ApiServer.js","sourceRoot":"","sources":["../../src/api/ApiServer.ts"],"names":[],"mappings":"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","sourcesContent":["import { createServer, type Server, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { AuthMiddleware, AuthenticatedRequest } from './middleware/AuthMiddleware';\nimport { prepareSocketPath, removeSocketPath } from '../runtime/socket-utils';\n\n/**\n * Route handler function\n */\nexport type RouteHandler = (\n request: AuthenticatedRequest,\n response: ServerResponse,\n params: Record<string, string>,\n) => Promise<void>;\n\n/**\n * Route definition\n */\nexport interface Route {\n method: string;\n pattern: RegExp;\n paramNames: string[];\n handler: RouteHandler;\n /** If true, skip authentication */\n public?: boolean;\n}\n\nexport interface ApiServerOptions {\n port?: number;\n host?: string;\n socketPath?: string;\n authMiddleware: AuthMiddleware;\n corsOrigins?: string[];\n}\n\n/**\n * Standalone API Server\n */\nexport class ApiServer {\n private readonly logger = getLoggerFor(this);\n private readonly port: number;\n private readonly host: string;\n private readonly socketPath?: string;\n private readonly authMiddleware: AuthMiddleware;\n private readonly corsOrigins: string[];\n private readonly routes: Route[] = [];\n private server?: Server;\n\n public constructor(options: ApiServerOptions) {\n this.port = options.port ?? 0;\n this.host = options.host ?? '0.0.0.0';\n this.socketPath = options.socketPath;\n this.authMiddleware = options.authMiddleware;\n this.corsOrigins = options.corsOrigins ?? ['*'];\n }\n\n /**\n * Register a route\n */\n public route(\n method: string,\n path: string,\n handler: RouteHandler,\n options?: {\n /** If true, skip authentication for this route */\n public?: boolean;\n },\n ): void {\n const { pattern, paramNames } = this.pathToRegex(path);\n this.routes.push({\n method: method.toUpperCase(),\n pattern,\n paramNames,\n handler,\n public: options?.public,\n });\n this.logger.debug(`Registered route: ${method.toUpperCase()} ${path}${options?.public ? ' (public)' : ''}`);\n }\n\n /**\n * Convenience methods for common HTTP methods\n */\n public get(path: string, handler: RouteHandler, options?: { public?: boolean }): void {\n this.route('GET', path, handler, options);\n }\n\n public post(path: string, handler: RouteHandler, options?: { public?: boolean }): void {\n this.route('POST', path, handler, options);\n }\n\n public put(path: string, handler: RouteHandler, options?: { public?: boolean }): void {\n this.route('PUT', path, handler, options);\n }\n\n public delete(path: string, handler: RouteHandler, options?: { public?: boolean }): void {\n this.route('DELETE', path, handler, options);\n }\n\n public patch(path: string, handler: RouteHandler, options?: { public?: boolean }): void {\n this.route('PATCH', path, handler, options);\n }\n\n /**\n * Start the server\n */\n public async start(): Promise<void> {\n return new Promise((resolve, reject) => {\n this.server = createServer((req, res) => {\n this.handleRequest(req, res).catch((error) => {\n this.logger.error(`Unhandled error: ${error}`);\n if (!res.headersSent) {\n res.statusCode = 500;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ error: 'Internal Server Error' }));\n }\n });\n });\n\n this.server.on('error', reject);\n\n if (this.socketPath) {\n prepareSocketPath(this.socketPath);\n this.server.listen(this.socketPath, () => {\n this.logger.info(`API Server listening on unix://${this.socketPath}`);\n resolve();\n });\n return;\n }\n\n this.server.listen(this.port, this.host, () => {\n this.logger.info(`API Server listening on ${this.host}:${this.port}`);\n resolve();\n });\n });\n }\n\n /**\n * Stop the server\n */\n public async stop(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!this.server) {\n resolve();\n return;\n }\n\n this.server.close((error) => {\n if (error) {\n reject(error);\n } else {\n if (this.socketPath) {\n removeSocketPath(this.socketPath);\n }\n this.logger.info('API Server stopped');\n resolve();\n }\n });\n });\n }\n\n /**\n * Get the underlying HTTP server (for WebSocket upgrade)\n */\n public getHttpServer(): Server | undefined {\n return this.server;\n }\n\n private async handleRequest(request: IncomingMessage, response: ServerResponse): Promise<void> {\n const method = request.method?.toUpperCase() ?? 'GET';\n const url = new URL(request.url ?? '/', `http://${request.headers.host ?? 'localhost'}`);\n const path = url.pathname;\n\n // Handle CORS preflight\n if (method === 'OPTIONS') {\n this.handleCors(request, response);\n response.statusCode = 204;\n response.end();\n return;\n }\n\n // Add CORS headers\n this.handleCors(request, response);\n\n // Find matching route\n const match = this.findRoute(method, path);\n if (!match) {\n response.statusCode = 404;\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify({ error: 'Not Found' }));\n return;\n }\n\n const { route, params } = match;\n const authRequest = request as AuthenticatedRequest;\n\n // Run auth middleware unless route is public\n if (!route.public) {\n const authOk = await this.authMiddleware.process(authRequest, response);\n if (!authOk) {\n return;\n }\n }\n\n // Execute handler\n try {\n await route.handler(authRequest, response, params);\n } catch (error) {\n this.logger.error(`Route handler error: ${error}`);\n if (!response.headersSent) {\n response.statusCode = 500;\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify({ error: 'Internal Server Error' }));\n }\n }\n }\n\n private findRoute(method: string, path: string): { route: Route; params: Record<string, string> } | undefined {\n for (const route of this.routes) {\n if (route.method !== method) {\n continue;\n }\n\n const match = route.pattern.exec(path);\n if (match) {\n const params: Record<string, string> = {};\n route.paramNames.forEach((name, index) => {\n params[name] = match[index + 1];\n });\n return { route, params };\n }\n }\n return undefined;\n }\n\n private pathToRegex(path: string): { pattern: RegExp; paramNames: string[] } {\n const paramNames: string[] = [];\n let regexStr = path\n // 先处理通配符 *path 或 * (匹配剩余所有路径)\n .replace(/\\*([a-zA-Z0-9_]*)/g, (_, name) => {\n paramNames.push(name || 'wildcard');\n return '(.*)';\n })\n // 再处理普通参数 :param (只匹配单段)\n .replace(/:([a-zA-Z0-9_]+)/g, (_, name) => {\n paramNames.push(name);\n return '([^/]+)';\n })\n .replace(/\\//g, '\\\\/');\n return {\n pattern: new RegExp(`^${regexStr}$`),\n paramNames,\n };\n }\n\n private handleCors(request: IncomingMessage, response: ServerResponse): void {\n const origin = request.headers.origin;\n\n if (this.corsOrigins.includes('*')) {\n response.setHeader('Access-Control-Allow-Origin', '*');\n } else if (origin && this.corsOrigins.includes(origin)) {\n response.setHeader('Access-Control-Allow-Origin', origin);\n response.setHeader('Vary', 'Origin');\n }\n\n response.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');\n response.setHeader('Access-Control-Allow-Headers', '*');\n response.setHeader('Access-Control-Max-Age', '86400');\n }\n}\n"]}
|
|
@@ -23,7 +23,13 @@ export interface NodeAuthContext {
|
|
|
23
23
|
nodeId: string;
|
|
24
24
|
accountId?: string;
|
|
25
25
|
}
|
|
26
|
-
export
|
|
26
|
+
export interface ServiceAuthContext {
|
|
27
|
+
type: 'service';
|
|
28
|
+
serviceType: 'local' | 'business' | 'cloud' | 'compute';
|
|
29
|
+
serviceId: string;
|
|
30
|
+
scopes: string[];
|
|
31
|
+
}
|
|
32
|
+
export type AuthContext = SolidAuthContext | NodeAuthContext | ServiceAuthContext;
|
|
27
33
|
export declare function isSolidAuth(ctx: AuthContext): ctx is SolidAuthContext;
|
|
28
34
|
export declare function isNodeAuth(ctx: AuthContext): ctx is NodeAuthContext;
|
|
29
35
|
/**
|
|
@@ -39,3 +45,8 @@ export declare function getDisplayName(ctx: AuthContext): string | undefined;
|
|
|
39
45
|
*/
|
|
40
46
|
export declare function getAccountId(ctx: AuthContext): string | undefined;
|
|
41
47
|
export declare function getNodeId(ctx: AuthContext): string | undefined;
|
|
48
|
+
export declare function isServiceAuth(ctx: AuthContext): ctx is ServiceAuthContext;
|
|
49
|
+
/**
|
|
50
|
+
* Check if a service auth context has the required scope
|
|
51
|
+
*/
|
|
52
|
+
export declare function hasScope(ctx: AuthContext, scope: string): boolean;
|
|
@@ -14,6 +14,8 @@ exports.getWebId = getWebId;
|
|
|
14
14
|
exports.getDisplayName = getDisplayName;
|
|
15
15
|
exports.getAccountId = getAccountId;
|
|
16
16
|
exports.getNodeId = getNodeId;
|
|
17
|
+
exports.isServiceAuth = isServiceAuth;
|
|
18
|
+
exports.hasScope = hasScope;
|
|
17
19
|
function isSolidAuth(ctx) {
|
|
18
20
|
return ctx.type === 'solid';
|
|
19
21
|
}
|
|
@@ -36,9 +38,24 @@ function getDisplayName(ctx) {
|
|
|
36
38
|
* Get accountId from auth context (if available)
|
|
37
39
|
*/
|
|
38
40
|
function getAccountId(ctx) {
|
|
39
|
-
|
|
41
|
+
if (ctx.type === 'solid') {
|
|
42
|
+
return ctx.accountId;
|
|
43
|
+
}
|
|
44
|
+
if (ctx.type === 'node') {
|
|
45
|
+
return ctx.accountId;
|
|
46
|
+
}
|
|
47
|
+
return undefined;
|
|
40
48
|
}
|
|
41
49
|
function getNodeId(ctx) {
|
|
42
50
|
return ctx.type === 'node' ? ctx.nodeId : undefined;
|
|
43
51
|
}
|
|
52
|
+
function isServiceAuth(ctx) {
|
|
53
|
+
return ctx.type === 'service';
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Check if a service auth context has the required scope
|
|
57
|
+
*/
|
|
58
|
+
function hasScope(ctx, scope) {
|
|
59
|
+
return ctx.type === 'service' && ctx.scopes.includes(scope);
|
|
60
|
+
}
|
|
44
61
|
//# sourceMappingURL=AuthContext.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthContext.js","sourceRoot":"","sources":["../../../src/api/auth/AuthContext.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;
|
|
1
|
+
{"version":3,"file":"AuthContext.js","sourceRoot":"","sources":["../../../src/api/auth/AuthContext.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AA8BH,kCAEC;AAED,gCAEC;AAKD,4BAEC;AAKD,wCAEC;AAKD,oCAQC;AAED,8BAEC;AAED,sCAEC;AAKD,4BAEC;AAhDD,SAAgB,WAAW,CAAC,GAAgB;IAC1C,OAAO,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC;AAC9B,CAAC;AAED,SAAgB,UAAU,CAAC,GAAgB;IACzC,OAAO,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,SAAgB,QAAQ,CAAC,GAAgB;IACvC,OAAO,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,GAAgB;IAC7C,OAAO,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY,CAAC,GAAgB;IAC3C,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO,GAAG,CAAC,SAAS,CAAC;IACvB,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO,GAAG,CAAC,SAAS,CAAC;IACvB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAgB,SAAS,CAAC,GAAgB;IACxC,OAAO,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACtD,CAAC;AAED,SAAgB,aAAa,CAAC,GAAgB;IAC5C,OAAO,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,SAAgB,QAAQ,CAAC,GAAgB,EAAE,KAAa;IACtD,OAAO,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC9D,CAAC","sourcesContent":["/**\n * Authentication context representing the authenticated caller\n * \n * Authenticated caller context.\n * - Solid Token: user provides Bearer or DPoP token\n * - API Key: third-party provides client_id, API Server exchanges for token\n * - Node Token: edge node provides node API key\n */\n\nexport interface SolidAuthContext {\n type: 'solid';\n webId: string;\n accountId?: string;\n clientId?: string;\n clientSecret?: string; // For client credentials auth\n displayName?: string;\n accessToken?: string;\n tokenType?: 'Bearer' | 'DPoP';\n /** Whether this was authenticated via API Key (client credentials) */\n viaApiKey?: boolean;\n}\n\nexport interface NodeAuthContext {\n type: 'node';\n nodeId: string;\n accountId?: string;\n}\n\nexport interface ServiceAuthContext {\n type: 'service';\n serviceType: 'local' | 'business' | 'cloud' | 'compute';\n serviceId: string;\n scopes: string[];\n}\n\nexport type AuthContext = SolidAuthContext | NodeAuthContext | ServiceAuthContext;\n\nexport function isSolidAuth(ctx: AuthContext): ctx is SolidAuthContext {\n return ctx.type === 'solid';\n}\n\nexport function isNodeAuth(ctx: AuthContext): ctx is NodeAuthContext {\n return ctx.type === 'node';\n}\n\n/**\n * Get webId from auth context\n */\nexport function getWebId(ctx: AuthContext): string | undefined {\n return ctx.type === 'solid' ? ctx.webId : undefined;\n}\n\n/**\n * Get display name from auth context\n */\nexport function getDisplayName(ctx: AuthContext): string | undefined {\n return ctx.type === 'solid' ? ctx.displayName : undefined;\n}\n\n/**\n * Get accountId from auth context (if available)\n */\nexport function getAccountId(ctx: AuthContext): string | undefined {\n if (ctx.type === 'solid') {\n return ctx.accountId;\n }\n if (ctx.type === 'node') {\n return ctx.accountId;\n }\n return undefined;\n}\n\nexport function getNodeId(ctx: AuthContext): string | undefined {\n return ctx.type === 'node' ? ctx.nodeId : undefined;\n}\n\nexport function isServiceAuth(ctx: AuthContext): ctx is ServiceAuthContext {\n return ctx.type === 'service';\n}\n\n/**\n * Check if a service auth context has the required scope\n */\nexport function hasScope(ctx: AuthContext, scope: string): boolean {\n return ctx.type === 'service' && ctx.scopes.includes(scope);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientCredentialsAuthenticator.js","sourceRoot":"","sources":["../../../src/api/auth/ClientCredentialsAuthenticator.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { Authenticator, AuthResult } from './Authenticator';\nimport type { SolidAuthContext } from './AuthContext';\n\n/**\n * Interface for token cache\n */\nexport interface TokenCache {\n get(clientId: string): Promise<{ token: string; webId: string; expiresAt: Date } | undefined>;\n set(clientId: string, token: string, webId: string, expiresAt: Date): Promise<void>;\n}\n\nexport interface ClientCredentialsAuthenticatorOptions {\n tokenCache?: TokenCache;\n /**\n * CSS token endpoint URL\n */\n tokenEndpoint: string;\n}\n\n/**\n * Authenticator for API Keys in sk-xxx format.\n * \n * Format: sk-base64(client_id:client_secret)\n * \n * This authenticator:\n * 1. Decodes the API Key to get client_id and client_secret\n * 2. Exchanges them for a Solid Token via CSS token endpoint\n * 3. Extracts webId from the token response\n * 4. Returns a SolidAuthContext\n */\nexport class ClientCredentialsAuthenticator implements Authenticator {\n private readonly logger = getLoggerFor(this);\n private readonly tokenCache?: TokenCache;\n private readonly tokenEndpoint: string;\n\n public constructor(options: ClientCredentialsAuthenticatorOptions) {\n this.tokenCache = options.tokenCache;\n this.tokenEndpoint = options.tokenEndpoint;\n }\n\n public canAuthenticate(request: IncomingMessage): boolean {\n const auth = request.headers.authorization;\n if (!auth?.startsWith('Bearer ')) {\n return false;\n }\n // If there's a DPoP header, it's a Solid Token, not an API Key\n if (request.headers.dpop) {\n return false;\n }\n const token = auth.slice(7).trim();\n if (!token) {\n return false;\n }\n // Only handle sk-xxx format or non-JWT tokens\n return token.startsWith('sk-') || !this.isJwt(token);\n }\n\n public async authenticate(request: IncomingMessage): Promise<AuthResult> {\n const authorization = request.headers.authorization;\n if (!authorization?.startsWith('Bearer ')) {\n return { success: false, error: 'Missing Bearer token' };\n }\n\n const token = authorization.slice(7).trim();\n if (!token) {\n return { success: false, error: 'Empty API Key' };\n }\n\n try {\n let clientId: string;\n let clientSecret: string;\n\n // Parse sk-xxx format (base64 encoded client_id:client_secret)\n if (token.startsWith('sk-')) {\n const base64 = token.slice(3);\n try {\n const decoded = Buffer.from(base64, 'base64').toString('utf-8');\n const colonIndex = decoded.indexOf(':');\n if (colonIndex === -1) {\n return { success: false, error: 'Invalid API Key format: missing colon separator' };\n }\n clientId = decoded.slice(0, colonIndex);\n clientSecret = decoded.slice(colonIndex + 1);\n \n if (!clientId || !clientSecret) {\n return { success: false, error: 'Invalid API Key format: empty client_id or client_secret' };\n }\n } catch {\n return { success: false, error: 'Invalid API Key encoding' };\n }\n } else {\n // Non sk- format not supported without database lookup\n return { success: false, error: 'Invalid API Key format: must start with sk-' };\n }\n\n // Check cache first\n if (this.tokenCache) {\n const cached = await this.tokenCache.get(clientId);\n if (cached && cached.expiresAt > new Date()) {\n this.logger.debug(`Using cached token for ${clientId.slice(0, 8)}...`);\n return {\n success: true,\n context: {\n type: 'solid',\n webId: cached.webId,\n accountId: cached.webId,\n clientId,\n clientSecret,\n viaApiKey: true,\n },\n };\n }\n }\n\n // Exchange for token at CSS endpoint\n console.log(`[ClientCredentialsAuthenticator] Exchanging credentials at ${this.tokenEndpoint}`);\n const tokenResult = await this.exchangeForToken(clientId, clientSecret);\n console.log(`[ClientCredentialsAuthenticator] Token exchange result: success=${tokenResult.success}, webId=${tokenResult.webId}, error=${tokenResult.error}`);\n \n if (!tokenResult.success || !tokenResult.webId) {\n return { success: false, error: tokenResult.error || 'Token exchange failed' };\n }\n\n // Cache the token\n if (this.tokenCache && tokenResult.expiresAt) {\n await this.tokenCache.set(clientId, tokenResult.token!, tokenResult.webId, tokenResult.expiresAt);\n }\n\n const context: SolidAuthContext = {\n type: 'solid',\n webId: tokenResult.webId,\n accountId: tokenResult.webId,\n clientId,\n clientSecret,\n viaApiKey: true,\n };\n\n this.logger.debug(`Authenticated API Key for webId: ${tokenResult.webId}`);\n return { success: true, context };\n } catch (error) {\n console.error(`[ClientCredentialsAuthenticator] API Key authentication error:`, error);\n this.logger.error(`API Key authentication error: ${error}`);\n return { success: false, error: 'Authentication failed' };\n }\n }\n\n private async exchangeForToken(clientId: string, clientSecret: string): Promise<{\n success: boolean;\n token?: string;\n webId?: string;\n expiresAt?: Date;\n error?: string;\n }> {\n // 开发模式:跳过 CSS token exchange\n if (process.env.NODE_ENV === 'development') {\n this.logger.warn(`[DEV] Skipping token exchange for ${clientId.slice(0, 8)}...`);\n return {\n success: true,\n token: `dev-token-${clientId}`,\n expiresAt: new Date(Date.now() + 3600000),\n };\n }\n\n try {\n const response = await fetch(this.tokenEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: clientId,\n client_secret: clientSecret,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n this.logger.warn(`Token exchange failed: ${response.status} ${error}`);\n return { success: false, error: `Token exchange failed: ${response.status}` };\n }\n\n const data = await response.json() as {\n access_token: string;\n expires_in?: number;\n token_type: string;\n webid?: string; // CSS returns webid in response\n };\n\n // Extract webId from token response or decode from JWT\n let webId = data.webid;\n if (!webId && data.access_token) {\n webId = this.extractWebIdFromJwt(data.access_token);\n }\n\n if (!webId) {\n return { success: false, error: 'Could not determine webId from token response' };\n }\n\n const expiresAt = data.expires_in\n ? new Date(Date.now() + data.expires_in * 1000 - 60000) // 1 min buffer\n : new Date(Date.now() + 3600000); // Default 1 hour\n\n return {\n success: true,\n token: data.access_token,\n webId,\n expiresAt,\n };\n } catch (error) {\n this.logger.error(`Token exchange error: ${error}`);\n return { success: false, error: 'Token exchange failed' };\n }\n }\n\n /**\n * Extract webId from JWT access token\n */\n private extractWebIdFromJwt(jwt: string): string | undefined {\n try {\n const parts = jwt.split('.');\n if (parts.length !== 3) {\n return undefined;\n }\n const payload = JSON.parse(Buffer.from(parts[1], 'base64').toString('utf-8'));\n return payload.webid || payload.webId || payload.sub;\n } catch {\n return undefined;\n }\n }\n\n private isJwt(token: string): boolean {\n return /^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/.test(token);\n }\n}\n\n// Re-export for backwards compatibility (these are no longer needed but keep for other code)\nexport interface ClientCredentialsRecord {\n clientId: string;\n clientSecret: string;\n webId: string;\n accountId: string;\n displayName?: string;\n createdAt: Date;\n}\n\nexport interface ClientCredentialsStore {\n findByClientId(clientId: string): Promise<ClientCredentialsRecord | undefined>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ClientCredentialsAuthenticator.js","sourceRoot":"","sources":["../../../src/api/auth/ClientCredentialsAuthenticator.ts"],"names":[],"mappings":";;;AACA,iEAAqD;AAoBrD;;;;;;;;;;GAUG;AACH,MAAa,8BAA8B;IAKzC,YAAmB,OAA8C;QAJhD,WAAM,GAAG,IAAA,oCAAY,EAAC,IAAI,CAAC,CAAC;QAK3C,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAC7C,CAAC;IAEM,eAAe,CAAC,OAAwB;QAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACjC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,+DAA+D;QAC/D,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,KAAK,CAAC;QACf,CAAC;QACD,8CAA8C;QAC9C,OAAO,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvD,CAAC;IAEM,KAAK,CAAC,YAAY,CAAC,OAAwB;QAChD,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;QACpD,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC;QAC3D,CAAC;QAED,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;QACpD,CAAC;QAED,IAAI,CAAC;YACH,IAAI,QAAgB,CAAC;YACrB,IAAI,YAAoB,CAAC;YAEzB,+DAA+D;YAC/D,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC9B,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;oBAChE,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;oBACxC,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;wBACtB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,iDAAiD,EAAE,CAAC;oBACtF,CAAC;oBACD,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;oBACxC,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;oBAE7C,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;wBAC/B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,0DAA0D,EAAE,CAAC;oBAC/F,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC;gBAC/D,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,uDAAuD;gBACvD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,6CAA6C,EAAE,CAAC;YAClF,CAAC;YAED,oBAAoB;YACpB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBACpB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACnD,IAAI,MAAM,IAAI,MAAM,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;oBAC5C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;oBACvE,OAAO;wBACL,OAAO,EAAE,IAAI;wBACb,OAAO,EAAE;4BACP,IAAI,EAAE,OAAO;4BACb,KAAK,EAAE,MAAM,CAAC,KAAK;4BACnB,SAAS,EAAE,MAAM,CAAC,KAAK;4BACvB,QAAQ;4BACR,YAAY;4BACZ,SAAS,EAAE,IAAI;yBAChB;qBACF,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,qCAAqC;YACrC,OAAO,CAAC,GAAG,CAAC,8DAA8D,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;YAChG,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YACxE,OAAO,CAAC,GAAG,CAAC,mEAAmE,WAAW,CAAC,OAAO,WAAW,WAAW,CAAC,KAAK,WAAW,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC;YAE9J,IAAI,CAAC,WAAW,CAAC,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;gBAC/C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,IAAI,uBAAuB,EAAE,CAAC;YACjF,CAAC;YAED,kBAAkB;YAClB,IAAI,IAAI,CAAC,UAAU,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;gBAC7C,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC,KAAM,EAAE,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;YACpG,CAAC;YAED,MAAM,OAAO,GAAqB;gBAChC,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,WAAW,CAAC,KAAK;gBACxB,SAAS,EAAE,WAAW,CAAC,KAAK;gBAC5B,QAAQ;gBACR,YAAY;gBACZ,SAAS,EAAE,IAAI;aAChB,CAAC;YAEF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC;YAC3E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,gEAAgE,EAAE,KAAK,CAAC,CAAC;YACvF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,KAAK,EAAE,CAAC,CAAC;YAC5D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;QAC5D,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,QAAgB,EAAE,YAAoB;QAOnE,6BAA6B;QAC7B,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;YAC3C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,qCAAqC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YACjF,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,aAAa,QAAQ,EAAE;gBAC9B,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;aAC1C,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE;gBAC/C,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,mCAAmC;iBACpD;gBACD,IAAI,EAAE,IAAI,eAAe,CAAC;oBACxB,UAAU,EAAE,oBAAoB;oBAChC,SAAS,EAAE,QAAQ;oBACnB,aAAa,EAAE,YAAY;iBAC5B,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACpC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,0BAA0B,QAAQ,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC,CAAC;gBACvE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,0BAA0B,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAChF,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAK/B,CAAC;YAEF,uDAAuD;YACvD,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YACvB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBAChC,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACtD,CAAC;YAED,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,+CAA+C,EAAE,CAAC;YACpF,CAAC;YAED,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU;gBAC/B,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,GAAG,IAAI,GAAG,KAAK,CAAC,CAAC,eAAe;gBACvE,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,iBAAiB;YAErD,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,IAAI,CAAC,YAAY;gBACxB,KAAK;gBACL,SAAS;aACV,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,KAAK,EAAE,CAAC,CAAC;YACpD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;QAC5D,CAAC;IACH,CAAC;IAED;;OAEG;IACK,mBAAmB,CAAC,GAAW;QACrC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YAC9E,OAAO,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,KAAa;QACzB,OAAO,kDAAkD,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxE,CAAC;CACF;AA5MD,wEA4MC","sourcesContent":["import type { IncomingMessage } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { Authenticator, AuthResult } from './Authenticator';\nimport type { SolidAuthContext } from './AuthContext';\n\n/**\n * Interface for token cache\n */\nexport interface TokenCache {\n get(clientId: string): Promise<{ token: string; webId: string; expiresAt: Date } | undefined>;\n set(clientId: string, token: string, webId: string, expiresAt: Date): Promise<void>;\n}\n\nexport interface ClientCredentialsAuthenticatorOptions {\n tokenCache?: TokenCache;\n /**\n * CSS token endpoint URL\n */\n tokenEndpoint: string;\n}\n\n/**\n * Authenticator for API Keys in sk-xxx format.\n * \n * Format: sk-base64(client_id:client_secret)\n * \n * This authenticator:\n * 1. Decodes the API Key to get client_id and client_secret\n * 2. Exchanges them for a Solid Token via CSS token endpoint\n * 3. Extracts webId from the token response\n * 4. Returns a SolidAuthContext\n */\nexport class ClientCredentialsAuthenticator implements Authenticator {\n private readonly logger = getLoggerFor(this);\n private readonly tokenCache?: TokenCache;\n private readonly tokenEndpoint: string;\n\n public constructor(options: ClientCredentialsAuthenticatorOptions) {\n this.tokenCache = options.tokenCache;\n this.tokenEndpoint = options.tokenEndpoint;\n }\n\n public canAuthenticate(request: IncomingMessage): boolean {\n const auth = request.headers.authorization;\n if (!auth?.startsWith('Bearer ')) {\n return false;\n }\n // If there's a DPoP header, it's a Solid Token, not an API Key\n if (request.headers.dpop) {\n return false;\n }\n const token = auth.slice(7).trim();\n if (!token) {\n return false;\n }\n // Only handle sk-xxx format or non-JWT tokens\n return token.startsWith('sk-') || !this.isJwt(token);\n }\n\n public async authenticate(request: IncomingMessage): Promise<AuthResult> {\n const authorization = request.headers.authorization;\n if (!authorization?.startsWith('Bearer ')) {\n return { success: false, error: 'Missing Bearer token' };\n }\n\n const token = authorization.slice(7).trim();\n if (!token) {\n return { success: false, error: 'Empty API Key' };\n }\n\n try {\n let clientId: string;\n let clientSecret: string;\n\n // Parse sk-xxx format (base64 encoded client_id:client_secret)\n if (token.startsWith('sk-')) {\n const base64 = token.slice(3);\n try {\n const decoded = Buffer.from(base64, 'base64').toString('utf-8');\n const colonIndex = decoded.indexOf(':');\n if (colonIndex === -1) {\n return { success: false, error: 'Invalid API Key format: missing colon separator' };\n }\n clientId = decoded.slice(0, colonIndex);\n clientSecret = decoded.slice(colonIndex + 1);\n \n if (!clientId || !clientSecret) {\n return { success: false, error: 'Invalid API Key format: empty client_id or client_secret' };\n }\n } catch {\n return { success: false, error: 'Invalid API Key encoding' };\n }\n } else {\n // Non sk- format not supported without database lookup\n return { success: false, error: 'Invalid API Key format: must start with sk-' };\n }\n\n // Check cache first\n if (this.tokenCache) {\n const cached = await this.tokenCache.get(clientId);\n if (cached && cached.expiresAt > new Date()) {\n this.logger.debug(`Using cached token for ${clientId.slice(0, 8)}...`);\n return {\n success: true,\n context: {\n type: 'solid',\n webId: cached.webId,\n accountId: cached.webId,\n clientId,\n clientSecret,\n viaApiKey: true,\n },\n };\n }\n }\n\n // Exchange for token at CSS endpoint\n console.log(`[ClientCredentialsAuthenticator] Exchanging credentials at ${this.tokenEndpoint}`);\n const tokenResult = await this.exchangeForToken(clientId, clientSecret);\n console.log(`[ClientCredentialsAuthenticator] Token exchange result: success=${tokenResult.success}, webId=${tokenResult.webId}, error=${tokenResult.error}`);\n \n if (!tokenResult.success || !tokenResult.webId) {\n return { success: false, error: tokenResult.error || 'Token exchange failed' };\n }\n\n // Cache the token\n if (this.tokenCache && tokenResult.expiresAt) {\n await this.tokenCache.set(clientId, tokenResult.token!, tokenResult.webId, tokenResult.expiresAt);\n }\n\n const context: SolidAuthContext = {\n type: 'solid',\n webId: tokenResult.webId,\n accountId: tokenResult.webId,\n clientId,\n clientSecret,\n viaApiKey: true,\n };\n\n this.logger.debug(`Authenticated API Key for webId: ${tokenResult.webId}`);\n return { success: true, context };\n } catch (error) {\n console.error(`[ClientCredentialsAuthenticator] API Key authentication error:`, error);\n this.logger.error(`API Key authentication error: ${error}`);\n return { success: false, error: 'Authentication failed' };\n }\n }\n\n private async exchangeForToken(clientId: string, clientSecret: string): Promise<{\n success: boolean;\n token?: string;\n webId?: string;\n expiresAt?: Date;\n error?: string;\n }> {\n // 开发模式:跳过 CSS token exchange\n if (process.env.NODE_ENV === 'development') {\n this.logger.warn(`[DEV] Skipping token exchange for ${clientId.slice(0, 8)}...`);\n return {\n success: true,\n token: `dev-token-${clientId}`,\n expiresAt: new Date(Date.now() + 3600000),\n };\n }\n\n try {\n const response = await fetch(this.tokenEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: clientId,\n client_secret: clientSecret,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n this.logger.warn(`Token exchange failed: ${response.status} ${error}`);\n return { success: false, error: `Token exchange failed: ${response.status}` };\n }\n\n const data = await response.json() as {\n access_token: string;\n expires_in?: number;\n token_type: string;\n webid?: string; // CSS returns webid in response\n };\n\n // Extract webId from token response or decode from JWT\n let webId = data.webid;\n if (!webId && data.access_token) {\n webId = this.extractWebIdFromJwt(data.access_token);\n }\n\n if (!webId) {\n return { success: false, error: 'Could not determine webId from token response' };\n }\n\n const expiresAt = data.expires_in\n ? new Date(Date.now() + data.expires_in * 1000 - 60000) // 1 min buffer\n : new Date(Date.now() + 3600000); // Default 1 hour\n\n return {\n success: true,\n token: data.access_token,\n webId,\n expiresAt,\n };\n } catch (error) {\n this.logger.error(`Token exchange error: ${error}`);\n return { success: false, error: 'Token exchange failed' };\n }\n }\n\n /**\n * Extract webId from JWT access token\n */\n private extractWebIdFromJwt(jwt: string): string | undefined {\n try {\n const parts = jwt.split('.');\n if (parts.length !== 3) {\n return undefined;\n }\n const payload = JSON.parse(Buffer.from(parts[1], 'base64').toString('utf-8'));\n return payload.webid || payload.webId || payload.sub;\n } catch {\n return undefined;\n }\n }\n\n private isJwt(token: string): boolean {\n return /^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/.test(token);\n }\n}\n\n// Re-export for backwards compatibility (these are no longer needed but keep for other code)\nexport interface ClientCredentialsRecord {\n clientId: string;\n webId: string;\n accountId: string;\n displayName?: string;\n createdAt: Date;\n}\n\nexport interface ClientCredentialsStore {\n findByClientId(clientId: string): Promise<ClientCredentialsRecord | undefined>;\n}\n"]}
|