@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css-account.js","sourceRoot":"","sources":["../../../src/cli/lib/css-account.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * CSS Account API helpers for CLI commands.\n *\n * Wraps the CSS .account/* endpoints used by login, credential management, etc.\n */\n\nexport interface AccountControls {\n pod?: string;\n clientCredentials?: string;\n webId?: string[];\n}\n\nexport interface ClientCredential {\n id: string;\n secret?: string;\n label?: string;\n webId?: string;\n}\n\nfunction resolveBaseUrl(url?: string): string {\n const raw = url ?? process.env.CSS_BASE_URL ?? 'http://localhost:3000';\n return raw.endsWith('/') ? raw : `${raw}/`;\n}\n\n/**\n * Check if the CSS server is reachable.\n */\nexport async function checkServer(baseUrl?: string): Promise<boolean> {\n try {\n const res = await fetch(`${resolveBaseUrl(baseUrl)}.account/`, {\n headers: { Accept: 'application/json' },\n });\n return res.ok;\n } catch {\n return false;\n }\n}\n\n/**\n * Login with email/password, returns a CSS account token.\n */\nexport async function login(\n email: string,\n password: string,\n baseUrl?: string,\n): Promise<string | null> {\n const base = resolveBaseUrl(baseUrl);\n try {\n const res = await fetch(`${base}.account/login/password/`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\n body: JSON.stringify({ email, password }),\n });\n if (!res.ok) return null;\n const data = (await res.json()) as { authorization?: string };\n return data.authorization ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Fetch account controls (endpoints for pod/credential management).\n */\nexport async function getAccountControls(\n token: string,\n baseUrl?: string,\n): Promise<AccountControls | null> {\n const base = resolveBaseUrl(baseUrl);\n try {\n const res = await fetch(`${base}.account/`, {\n headers: {\n Accept: 'application/json',\n Authorization: `CSS-Account-Token ${token}`,\n },\n });\n if (!res.ok) return null;\n const data = (await res.json()) as {\n controls?: {\n account?: {\n pod?: string;\n clientCredentials?: string;\n webId?: string;\n };\n };\n };\n return {\n pod: data.controls?.account?.pod,\n clientCredentials: data.controls?.account?.clientCredentials,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Create a new client credential bound to a WebID.\n */\nexport async function createClientCredentials(\n token: string,\n credentialsUrl: string,\n webId: string,\n name?: string,\n): Promise<ClientCredential | null> {\n try {\n const res = await fetch(credentialsUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n Authorization: `CSS-Account-Token ${token}`,\n },\n body: JSON.stringify({\n name: name ?? `xpod-cli-${Date.now()}`,\n webId,\n }),\n });\n if (!res.ok) return null;\n return (await res.json()) as ClientCredential;\n } catch {\n return null;\n }\n}\n\n/**\n * List all client credentials for the account.\n */\nexport async function listClientCredentials(\n token: string,\n baseUrl?: string,\n): Promise<ClientCredential[]> {\n const base = resolveBaseUrl(baseUrl);\n try {\n const res = await fetch(`${base}.account/`, {\n headers: {\n Accept: 'application/json',\n Authorization: `CSS-Account-Token ${token}`,\n },\n });\n if (!res.ok) return [];\n const data = (await res.json()) as {\n controls?: {\n account?: {\n clientCredentials?: string;\n };\n };\n clientCredentials?: Record<string, string>;\n };\n\n // CSS returns clientCredentials as { [credentialUrl]: webId }\n const creds = data.clientCredentials;\n if (!creds || typeof creds !== 'object') return [];\n\n return Object.entries(creds).map(([url, webId]) => {\n // Extract credential ID from URL (last path segment)\n const id = url.split('/').filter(Boolean).pop() ?? url;\n return { id, webId: typeof webId === 'string' ? webId : undefined };\n });\n } catch {\n return [];\n }\n}\n\n/**\n * Revoke (delete) a client credential by its ID.\n */\nexport async function revokeClientCredential(\n token: string,\n credentialId: string,\n baseUrl?: string,\n): Promise<boolean> {\n const base = resolveBaseUrl(baseUrl);\n try {\n const url = `${base}.account/client-credentials/${credentialId}/`;\n const res = await fetch(url, {\n method: 'DELETE',\n headers: {\n Authorization: `CSS-Account-Token ${token}`,\n },\n });\n return res.ok;\n } catch {\n return false;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"css-account.js","sourceRoot":"","sources":["../../../src/cli/lib/css-account.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * CSS Account API helpers for CLI commands.\n *\n * Wraps the CSS .account/* endpoints used by login, credential management, etc.\n */\n\nexport interface AccountControls {\n pod?: string;\n clientCredentials?: string;\n webId?: string[];\n}\n\nexport interface AccountData {\n controls: AccountControls;\n pods: Record<string, string>;\n webIds: Record<string, string>;\n clientCredentials: Record<string, string>;\n}\n\nexport interface ClientCredential {\n id: string;\n secret?: string;\n label?: string;\n webId?: string;\n}\n\nfunction resolveBaseUrl(url?: string): string {\n const raw = url ?? process.env.CSS_BASE_URL ?? 'http://localhost:3000';\n return raw.endsWith('/') ? raw : `${raw}/`;\n}\n\n/**\n * Check if the CSS server is reachable.\n */\nexport async function checkServer(baseUrl?: string): Promise<boolean> {\n try {\n const res = await fetch(`${resolveBaseUrl(baseUrl)}.account/`, {\n headers: { Accept: 'application/json' },\n });\n return res.ok;\n } catch {\n return false;\n }\n}\n\n/**\n * Login with email/password, returns a CSS account token.\n */\nexport async function login(\n email: string,\n password: string,\n baseUrl?: string,\n): Promise<string | null> {\n const base = resolveBaseUrl(baseUrl);\n try {\n const res = await fetch(`${base}.account/login/password/`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\n body: JSON.stringify({ email, password }),\n });\n if (!res.ok) return null;\n const data = (await res.json()) as { authorization?: string };\n return data.authorization ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Fetch account controls (endpoints for pod/credential management).\n */\nexport async function getAccountControls(\n token: string,\n baseUrl?: string,\n): Promise<AccountControls | null> {\n const base = resolveBaseUrl(baseUrl);\n try {\n const res = await fetch(`${base}.account/`, {\n headers: {\n Accept: 'application/json',\n Authorization: `CSS-Account-Token ${token}`,\n },\n });\n if (!res.ok) return null;\n const data = (await res.json()) as {\n controls?: {\n account?: {\n pod?: string;\n clientCredentials?: string;\n webId?: string;\n };\n };\n };\n return {\n pod: data.controls?.account?.pod,\n clientCredentials: data.controls?.account?.clientCredentials,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Fetch full account data including pods, webIds, and credentials.\n */\nexport async function getAccountData(\n token: string,\n baseUrl?: string,\n): Promise<AccountData | null> {\n const base = resolveBaseUrl(baseUrl);\n try {\n const res = await fetch(`${base}.account/`, {\n headers: {\n Accept: 'application/json',\n Authorization: `CSS-Account-Token ${token}`,\n },\n });\n if (!res.ok) return null;\n const data = (await res.json()) as {\n controls?: {\n account?: {\n pod?: string;\n clientCredentials?: string;\n webId?: string;\n };\n };\n pods?: Record<string, string>;\n webIds?: Record<string, string>;\n clientCredentials?: Record<string, string>;\n };\n return {\n controls: {\n pod: data.controls?.account?.pod,\n clientCredentials: data.controls?.account?.clientCredentials,\n },\n pods: data.pods ?? {},\n webIds: data.webIds ?? {},\n clientCredentials: data.clientCredentials ?? {},\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Create a new pod for the account.\n */\nexport async function createPod(\n token: string,\n podEndpoint: string,\n podName: string,\n): Promise<{ podUrl: string; webId: string } | null> {\n try {\n const res = await fetch(podEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n Authorization: `CSS-Account-Token ${token}`,\n },\n body: JSON.stringify({ name: podName }),\n });\n if (!res.ok) return null;\n const data = (await res.json()) as { pod?: string; webId?: string };\n if (!data.pod || !data.webId) return null;\n return { podUrl: data.pod, webId: data.webId };\n } catch {\n return null;\n }\n}\n\n/**\n * Create a new client credential bound to a WebID.\n */\nexport async function createClientCredentials(\n token: string,\n credentialsUrl: string,\n webId: string,\n name?: string,\n): Promise<ClientCredential | null> {\n try {\n const res = await fetch(credentialsUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n Authorization: `CSS-Account-Token ${token}`,\n },\n body: JSON.stringify({\n name: name ?? `xpod-cli-${Date.now()}`,\n webId,\n }),\n });\n if (!res.ok) return null;\n return (await res.json()) as ClientCredential;\n } catch {\n return null;\n }\n}\n\n/**\n * List all client credentials for the account.\n */\nexport async function listClientCredentials(\n token: string,\n baseUrl?: string,\n): Promise<ClientCredential[]> {\n const base = resolveBaseUrl(baseUrl);\n try {\n const res = await fetch(`${base}.account/`, {\n headers: {\n Accept: 'application/json',\n Authorization: `CSS-Account-Token ${token}`,\n },\n });\n if (!res.ok) return [];\n const data = (await res.json()) as {\n controls?: {\n account?: {\n clientCredentials?: string;\n };\n };\n clientCredentials?: Record<string, string>;\n };\n\n // CSS returns clientCredentials as { [credentialUrl]: webId }\n const creds = data.clientCredentials;\n if (!creds || typeof creds !== 'object') return [];\n\n return Object.entries(creds).map(([url, webId]) => {\n // Extract credential ID from URL (last path segment)\n const id = url.split('/').filter(Boolean).pop() ?? url;\n return { id, webId: typeof webId === 'string' ? webId : undefined };\n });\n } catch {\n return [];\n }\n}\n\n/**\n * Revoke (delete) a client credential by its ID.\n */\nexport async function revokeClientCredential(\n token: string,\n credentialId: string,\n baseUrl?: string,\n): Promise<boolean> {\n const base = resolveBaseUrl(baseUrl);\n try {\n const url = `${base}.account/client-credentials/${credentialId}/`;\n const res = await fetch(url, {\n method: 'DELETE',\n headers: {\n Authorization: `CSS-Account-Token ${token}`,\n },\n });\n return res.ok;\n } catch {\n return false;\n }\n}\n"]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation thread storage backed by the user's Solid Pod.
|
|
3
|
+
*
|
|
4
|
+
* Uses drizzle-solid to operate on Chat + Thread + Message tables,
|
|
5
|
+
* following the same protocol as API/ChatKit.
|
|
6
|
+
*
|
|
7
|
+
* Data model:
|
|
8
|
+
* - Chat = 通讯录(跟谁聊):由 participants 决定,不再由 cwd hash 生成
|
|
9
|
+
* - Thread = 对话实例(聊什么、在哪聊):workspace 是一级字段
|
|
10
|
+
*/
|
|
11
|
+
import type { Session } from '@inrupt/solid-client-authn-node';
|
|
12
|
+
export interface ThreadMessage {
|
|
13
|
+
role: 'user' | 'assistant' | 'system';
|
|
14
|
+
content: string;
|
|
15
|
+
timestamp: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ThreadData {
|
|
18
|
+
id: string;
|
|
19
|
+
title?: string;
|
|
20
|
+
workspace?: string;
|
|
21
|
+
createdAt: string;
|
|
22
|
+
updatedAt: string;
|
|
23
|
+
messages: ThreadMessage[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get or create the default 1v1 Chat for CLI (user ↔ SecretaryAI).
|
|
27
|
+
* Returns the chatId (bare ID, not URI).
|
|
28
|
+
*/
|
|
29
|
+
export declare function getOrCreateDefaultChat(session: Session): Promise<string>;
|
|
30
|
+
/**
|
|
31
|
+
* List thread IDs (most-recent first) for a given chatId.
|
|
32
|
+
* Uses direct SPARQL because eq() on optional uri() fields still has issues.
|
|
33
|
+
*/
|
|
34
|
+
export declare function listThreads(session: Session, chatId: string): Promise<string[]>;
|
|
35
|
+
/**
|
|
36
|
+
* Load a thread by ID with all its messages.
|
|
37
|
+
*/
|
|
38
|
+
export declare function loadThread(session: Session, chatId: string, threadId: string): Promise<ThreadData | null>;
|
|
39
|
+
/**
|
|
40
|
+
* Save a message to a thread.
|
|
41
|
+
*/
|
|
42
|
+
export declare function saveMessage(session: Session, chatId: string, threadId: string, message: ThreadMessage): Promise<boolean>;
|
|
43
|
+
/**
|
|
44
|
+
* Save a tool call as a message with metadata.
|
|
45
|
+
*/
|
|
46
|
+
export declare function saveToolCall(session: Session, chatId: string, threadId: string, toolCall: {
|
|
47
|
+
toolName: string;
|
|
48
|
+
toolCallId: string;
|
|
49
|
+
arguments: any;
|
|
50
|
+
output?: string;
|
|
51
|
+
status: 'pending' | 'completed' | 'failed';
|
|
52
|
+
}): Promise<boolean>;
|
|
53
|
+
/**
|
|
54
|
+
* Create a fresh thread.
|
|
55
|
+
* workspace is stored as a first-class field on Thread.
|
|
56
|
+
*/
|
|
57
|
+
export declare function createThread(session: Session, chatId: string, workspace?: string, title?: string): Promise<string>;
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Conversation thread storage backed by the user's Solid Pod.
|
|
4
|
+
*
|
|
5
|
+
* Uses drizzle-solid to operate on Chat + Thread + Message tables,
|
|
6
|
+
* following the same protocol as API/ChatKit.
|
|
7
|
+
*
|
|
8
|
+
* Data model:
|
|
9
|
+
* - Chat = 通讯录(跟谁聊):由 participants 决定,不再由 cwd hash 生成
|
|
10
|
+
* - Thread = 对话实例(聊什么、在哪聊):workspace 是一级字段
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.getOrCreateDefaultChat = getOrCreateDefaultChat;
|
|
14
|
+
exports.listThreads = listThreads;
|
|
15
|
+
exports.loadThread = loadThread;
|
|
16
|
+
exports.saveMessage = saveMessage;
|
|
17
|
+
exports.saveToolCall = saveToolCall;
|
|
18
|
+
exports.createThread = createThread;
|
|
19
|
+
const drizzle_solid_1 = require("@undefineds.co/drizzle-solid");
|
|
20
|
+
const schema_1 = require("../../api/chatkit/schema");
|
|
21
|
+
/** Default Chat ID for CLI 1v1 conversations with SecretaryAI */
|
|
22
|
+
const DEFAULT_CLI_CHAT_ID = 'cli-default';
|
|
23
|
+
/**
|
|
24
|
+
* Create a drizzle-solid database instance from an authenticated Session.
|
|
25
|
+
*/
|
|
26
|
+
function createDb(session) {
|
|
27
|
+
return (0, drizzle_solid_1.drizzle)({
|
|
28
|
+
fetch: session.fetch,
|
|
29
|
+
info: session.info,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get or create the default 1v1 Chat for CLI (user ↔ SecretaryAI).
|
|
34
|
+
* Returns the chatId (bare ID, not URI).
|
|
35
|
+
*/
|
|
36
|
+
async function getOrCreateDefaultChat(session) {
|
|
37
|
+
const chatId = DEFAULT_CLI_CHAT_ID;
|
|
38
|
+
try {
|
|
39
|
+
const db = createDb(session);
|
|
40
|
+
await ensureChat(db, chatId, session.info.webId);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
console.error('Failed to ensure default chat:', error);
|
|
44
|
+
}
|
|
45
|
+
return chatId;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* List thread IDs (most-recent first) for a given chatId.
|
|
49
|
+
* Uses direct SPARQL because eq() on optional uri() fields still has issues.
|
|
50
|
+
*/
|
|
51
|
+
async function listThreads(session, chatId) {
|
|
52
|
+
try {
|
|
53
|
+
const podBaseUrl = session.info.webId.replace('/profile/card#me', '');
|
|
54
|
+
const endpoint = `${podBaseUrl}/.data/chat/-/sparql`;
|
|
55
|
+
const chatSubject = `<${podBaseUrl}/.data/chat/${chatId}/index.ttl#this>`;
|
|
56
|
+
// Note: Removed OPTIONAL to avoid filtering out threads without createdAt
|
|
57
|
+
// OPTIONAL in GRAPH ?g context can cause incomplete results (40 vs 57 threads)
|
|
58
|
+
const query = `
|
|
59
|
+
PREFIX sioc: <http://rdfs.org/sioc/ns#>
|
|
60
|
+
PREFIX udfs: <https://undefineds.co/ns#>
|
|
61
|
+
SELECT ?thread ?createdAt
|
|
62
|
+
WHERE {
|
|
63
|
+
?thread a sioc:Thread ;
|
|
64
|
+
sioc:has_parent ${chatSubject} ;
|
|
65
|
+
udfs:createdAt ?createdAt .
|
|
66
|
+
}
|
|
67
|
+
ORDER BY DESC(?createdAt)
|
|
68
|
+
`;
|
|
69
|
+
const res = await session.fetch(endpoint, {
|
|
70
|
+
method: 'POST',
|
|
71
|
+
headers: {
|
|
72
|
+
'Content-Type': 'application/sparql-query',
|
|
73
|
+
'Accept': 'application/sparql-results+json',
|
|
74
|
+
},
|
|
75
|
+
body: query,
|
|
76
|
+
});
|
|
77
|
+
if (!res.ok)
|
|
78
|
+
return [];
|
|
79
|
+
const json = await res.json();
|
|
80
|
+
const bindings = json.results?.bindings || [];
|
|
81
|
+
// Extract thread ID from URI fragment: ...index.ttl#thread-xxx → thread-xxx
|
|
82
|
+
return bindings
|
|
83
|
+
.map((b) => {
|
|
84
|
+
const uri = b.thread?.value || '';
|
|
85
|
+
const hash = uri.lastIndexOf('#');
|
|
86
|
+
return hash >= 0 ? uri.slice(hash + 1) : '';
|
|
87
|
+
})
|
|
88
|
+
.filter((id) => id.length > 0);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
console.error('Failed to list threads:', error);
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Load a thread by ID with all its messages.
|
|
97
|
+
*/
|
|
98
|
+
async function loadThread(session, chatId, threadId) {
|
|
99
|
+
try {
|
|
100
|
+
const db = createDb(session);
|
|
101
|
+
const podBaseUrl = session.info.webId.replace('/profile/card#me', '');
|
|
102
|
+
const threadUri = `${podBaseUrl}/.data/chat/${chatId}/index.ttl#${threadId}`;
|
|
103
|
+
// Query thread by full URI
|
|
104
|
+
const thread = await db.findByIri(schema_1.Thread, threadUri);
|
|
105
|
+
if (!thread)
|
|
106
|
+
return null;
|
|
107
|
+
// Query messages using direct SPARQL
|
|
108
|
+
// Note: OPTIONAL works correctly with date-grouped files (messages.ttl)
|
|
109
|
+
const endpoint = `${podBaseUrl}/.data/chat/-/sparql`;
|
|
110
|
+
const threadSubject = `<${threadUri}>`;
|
|
111
|
+
const messagesQuery = `
|
|
112
|
+
PREFIX meeting: <http://www.w3.org/ns/pim/meeting#>
|
|
113
|
+
PREFIX sioc: <http://rdfs.org/sioc/ns#>
|
|
114
|
+
PREFIX udfs: <https://undefineds.co/ns#>
|
|
115
|
+
SELECT ?role ?content ?createdAt
|
|
116
|
+
WHERE {
|
|
117
|
+
?msg a meeting:Message ;
|
|
118
|
+
sioc:has_container ${threadSubject} .
|
|
119
|
+
OPTIONAL { ?msg udfs:role ?role . }
|
|
120
|
+
OPTIONAL { ?msg sioc:content ?content . }
|
|
121
|
+
OPTIONAL { ?msg udfs:createdAt ?createdAt . }
|
|
122
|
+
}
|
|
123
|
+
ORDER BY ?createdAt
|
|
124
|
+
`;
|
|
125
|
+
const messagesRes = await session.fetch(endpoint, {
|
|
126
|
+
method: 'POST',
|
|
127
|
+
headers: {
|
|
128
|
+
'Content-Type': 'application/sparql-query',
|
|
129
|
+
'Accept': 'application/sparql-results+json',
|
|
130
|
+
},
|
|
131
|
+
body: messagesQuery,
|
|
132
|
+
});
|
|
133
|
+
const messagesJson = messagesRes.ok ? await messagesRes.json() : { results: { bindings: [] } };
|
|
134
|
+
const messageBindings = messagesJson.results?.bindings || [];
|
|
135
|
+
// Extract bare ID from thread.id
|
|
136
|
+
const bareId = typeof thread.id === 'string' && thread.id.includes('#')
|
|
137
|
+
? thread.id.split('#').pop() || threadId
|
|
138
|
+
: thread.id;
|
|
139
|
+
return {
|
|
140
|
+
id: bareId,
|
|
141
|
+
title: thread.title || undefined,
|
|
142
|
+
workspace: thread.workspace || undefined,
|
|
143
|
+
createdAt: thread.createdAt?.toISOString() || new Date().toISOString(),
|
|
144
|
+
updatedAt: thread.updatedAt?.toISOString() || new Date().toISOString(),
|
|
145
|
+
messages: messageBindings.map((m) => ({
|
|
146
|
+
role: m.role?.value || 'user',
|
|
147
|
+
content: m.content?.value || '',
|
|
148
|
+
timestamp: m.createdAt?.value || new Date().toISOString(),
|
|
149
|
+
})),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
console.error('Failed to load thread:', error);
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Save a message to a thread.
|
|
159
|
+
*/
|
|
160
|
+
async function saveMessage(session, chatId, threadId, message) {
|
|
161
|
+
try {
|
|
162
|
+
const db = createDb(session);
|
|
163
|
+
// Ensure chat exists
|
|
164
|
+
await ensureChat(db, chatId, session.info.webId);
|
|
165
|
+
// Ensure thread exists
|
|
166
|
+
await ensureThread(db, chatId, threadId, session.info.webId);
|
|
167
|
+
// 构建完整的 Thread URI(用于 RDF 引用)
|
|
168
|
+
const podBaseUrl = session.info.webId.replace('/profile/card#me', '');
|
|
169
|
+
const threadUri = `${podBaseUrl}/.data/chat/${chatId}/index.ttl#${threadId}`;
|
|
170
|
+
// Insert message
|
|
171
|
+
// Note: yyyy/MM/dd are automatically extracted from createdAt by drizzle-solid
|
|
172
|
+
const messageId = `msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
173
|
+
await db.insert(schema_1.Message).values({
|
|
174
|
+
id: messageId,
|
|
175
|
+
chatId,
|
|
176
|
+
threadId: threadUri, // 传入完整 URI
|
|
177
|
+
maker: session.info.webId,
|
|
178
|
+
role: message.role,
|
|
179
|
+
content: message.content,
|
|
180
|
+
status: 'completed',
|
|
181
|
+
createdAt: new Date(message.timestamp),
|
|
182
|
+
});
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
console.error('Failed to save message:', error);
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Save a tool call as a message with metadata.
|
|
192
|
+
*/
|
|
193
|
+
async function saveToolCall(session, chatId, threadId, toolCall) {
|
|
194
|
+
try {
|
|
195
|
+
const db = createDb(session);
|
|
196
|
+
// Ensure chat and thread exist
|
|
197
|
+
await ensureChat(db, chatId, session.info.webId);
|
|
198
|
+
await ensureThread(db, chatId, threadId, session.info.webId);
|
|
199
|
+
// 构建完整的 Thread URI(用于 RDF 引用)
|
|
200
|
+
const podBaseUrl = session.info.webId.replace('/profile/card#me', '');
|
|
201
|
+
const threadUri = `${podBaseUrl}/.data/chat/${chatId}/index.ttl#${threadId}`;
|
|
202
|
+
// Insert tool call message
|
|
203
|
+
// Note: yyyy/MM/dd are automatically extracted from createdAt by drizzle-solid
|
|
204
|
+
const messageId = `tool-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
205
|
+
await db.insert(schema_1.Message).values({
|
|
206
|
+
id: messageId,
|
|
207
|
+
chatId,
|
|
208
|
+
threadId: threadUri, // 传入完整 URI
|
|
209
|
+
maker: session.info.webId,
|
|
210
|
+
role: 'tool_call',
|
|
211
|
+
content: `Executed ${toolCall.toolName}`,
|
|
212
|
+
status: toolCall.status,
|
|
213
|
+
toolName: toolCall.toolName,
|
|
214
|
+
toolCallId: toolCall.toolCallId,
|
|
215
|
+
metadata: JSON.stringify({
|
|
216
|
+
type: 'tool_call',
|
|
217
|
+
toolName: toolCall.toolName,
|
|
218
|
+
toolCallId: toolCall.toolCallId,
|
|
219
|
+
arguments: toolCall.arguments,
|
|
220
|
+
output: toolCall.output,
|
|
221
|
+
status: toolCall.status,
|
|
222
|
+
}),
|
|
223
|
+
createdAt: new Date(),
|
|
224
|
+
});
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
console.error('Failed to save tool call:', error);
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Create a fresh thread.
|
|
234
|
+
* workspace is stored as a first-class field on Thread.
|
|
235
|
+
*/
|
|
236
|
+
async function createThread(session, chatId, workspace, title) {
|
|
237
|
+
const threadId = `thread-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
238
|
+
try {
|
|
239
|
+
const db = createDb(session);
|
|
240
|
+
// Ensure chat exists
|
|
241
|
+
await ensureChat(db, chatId, session.info.webId);
|
|
242
|
+
// Create thread with workspace as first-class field
|
|
243
|
+
const now = new Date();
|
|
244
|
+
await db.insert(schema_1.Thread).values({
|
|
245
|
+
id: threadId,
|
|
246
|
+
chatId,
|
|
247
|
+
title: title || 'CLI Conversation',
|
|
248
|
+
workspace: workspace || null,
|
|
249
|
+
status: 'active',
|
|
250
|
+
metadata: JSON.stringify({ source: 'cli' }),
|
|
251
|
+
createdAt: now,
|
|
252
|
+
updatedAt: now,
|
|
253
|
+
});
|
|
254
|
+
return threadId;
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
console.error('Failed to create thread:', error);
|
|
258
|
+
return threadId; // Return ID anyway, will be created on first message
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
// ============================================================================
|
|
262
|
+
// Internal Helpers
|
|
263
|
+
// ============================================================================
|
|
264
|
+
async function ensureChat(db, chatId, webId) {
|
|
265
|
+
try {
|
|
266
|
+
// Use findByIri to avoid OPTIONAL bug in SPARQL queries
|
|
267
|
+
const podBaseUrl = webId.replace('/profile/card#me', '');
|
|
268
|
+
const chatUri = `${podBaseUrl}/.data/chat/${chatId}/index.ttl#this`;
|
|
269
|
+
const chat = await db.findByIri(schema_1.Chat, chatUri);
|
|
270
|
+
if (!chat) {
|
|
271
|
+
const now = new Date();
|
|
272
|
+
await db.insert(schema_1.Chat).values({
|
|
273
|
+
id: chatId,
|
|
274
|
+
title: 'CLI Chat',
|
|
275
|
+
author: webId,
|
|
276
|
+
participants: [],
|
|
277
|
+
status: 'active',
|
|
278
|
+
createdAt: now,
|
|
279
|
+
updatedAt: now,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
// Ignore if already exists
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
async function ensureThread(db, chatId, threadId, webId) {
|
|
288
|
+
try {
|
|
289
|
+
// Use findByIri to avoid OPTIONAL bug in SPARQL queries
|
|
290
|
+
const podBaseUrl = webId.replace('/profile/card#me', '');
|
|
291
|
+
const threadUri = `${podBaseUrl}/.data/chat/${chatId}/index.ttl#${threadId}`;
|
|
292
|
+
const thread = await db.findByIri(schema_1.Thread, threadUri);
|
|
293
|
+
if (!thread) {
|
|
294
|
+
const now = new Date();
|
|
295
|
+
await db.insert(schema_1.Thread).values({
|
|
296
|
+
id: threadId,
|
|
297
|
+
chatId,
|
|
298
|
+
title: 'CLI Conversation',
|
|
299
|
+
status: 'active',
|
|
300
|
+
metadata: JSON.stringify({ source: 'cli' }),
|
|
301
|
+
createdAt: now,
|
|
302
|
+
updatedAt: now,
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
// Ignore if already exists
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=pod-thread-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pod-thread-store.js","sourceRoot":"","sources":["../../../src/cli/lib/pod-thread-store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Conversation thread storage backed by the user's Solid Pod.\n *\n * Uses drizzle-solid to operate on Chat + Thread + Message tables,\n * following the same protocol as API/ChatKit.\n *\n * Data model:\n * - Chat = 通讯录(跟谁聊):由 participants 决定,不再由 cwd hash 生成\n * - Thread = 对话实例(聊什么、在哪聊):workspace 是一级字段\n */\n\nimport { drizzle, eq } from '@undefineds.co/drizzle-solid';\nimport { Chat, Thread, Message } from '../../api/chatkit/schema';\nimport type { Session } from '@inrupt/solid-client-authn-node';\n\n/** Default Chat ID for CLI 1v1 conversations with SecretaryAI */\nconst DEFAULT_CLI_CHAT_ID = 'cli-default';\n\nexport interface ThreadMessage {\n role: 'user' | 'assistant' | 'system';\n content: string;\n timestamp: string;\n}\n\nexport interface ThreadData {\n id: string;\n title?: string;\n workspace?: string;\n createdAt: string;\n updatedAt: string;\n messages: ThreadMessage[];\n}\n\n/**\n * Create a drizzle-solid database instance from an authenticated Session.\n */\nfunction createDb(session: Session) {\n return drizzle({\n fetch: session.fetch,\n info: session.info,\n } as any);\n}\n\n/**\n * Get or create the default 1v1 Chat for CLI (user ↔ SecretaryAI).\n * Returns the chatId (bare ID, not URI).\n */\nexport async function getOrCreateDefaultChat(session: Session): Promise<string> {\n const chatId = DEFAULT_CLI_CHAT_ID;\n try {\n const db = createDb(session);\n await ensureChat(db, chatId, session.info.webId!);\n } catch (error) {\n console.error('Failed to ensure default chat:', error);\n }\n return chatId;\n}\n\n/**\n * List thread IDs (most-recent first) for a given chatId.\n * Uses direct SPARQL because eq() on optional uri() fields still has issues.\n */\nexport async function listThreads(session: Session, chatId: string): Promise<string[]> {\n try {\n const podBaseUrl = session.info.webId!.replace('/profile/card#me', '');\n const endpoint = `${podBaseUrl}/.data/chat/-/sparql`;\n const chatSubject = `<${podBaseUrl}/.data/chat/${chatId}/index.ttl#this>`;\n\n // Note: Removed OPTIONAL to avoid filtering out threads without createdAt\n // OPTIONAL in GRAPH ?g context can cause incomplete results (40 vs 57 threads)\n const query = `\n PREFIX sioc: <http://rdfs.org/sioc/ns#>\n PREFIX udfs: <https://undefineds.co/ns#>\n SELECT ?thread ?createdAt\n WHERE {\n ?thread a sioc:Thread ;\n sioc:has_parent ${chatSubject} ;\n udfs:createdAt ?createdAt .\n }\n ORDER BY DESC(?createdAt)\n `;\n\n const res = await session.fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/sparql-query',\n 'Accept': 'application/sparql-results+json',\n },\n body: query,\n });\n\n if (!res.ok) return [];\n\n const json = await res.json();\n const bindings = json.results?.bindings || [];\n\n // Extract thread ID from URI fragment: ...index.ttl#thread-xxx → thread-xxx\n return bindings\n .map((b: any) => {\n const uri = b.thread?.value || '';\n const hash = uri.lastIndexOf('#');\n return hash >= 0 ? uri.slice(hash + 1) : '';\n })\n .filter((id: string) => id.length > 0);\n } catch (error) {\n console.error('Failed to list threads:', error);\n return [];\n }\n}\n\n/**\n * Load a thread by ID with all its messages.\n */\nexport async function loadThread(\n session: Session,\n chatId: string,\n threadId: string,\n): Promise<ThreadData | null> {\n try {\n const db = createDb(session);\n const podBaseUrl = session.info.webId!.replace('/profile/card#me', '');\n const threadUri = `${podBaseUrl}/.data/chat/${chatId}/index.ttl#${threadId}`;\n\n // Query thread by full URI\n const thread = await db.findByIri(Thread, threadUri);\n if (!thread) return null;\n\n // Query messages using direct SPARQL\n // Note: OPTIONAL works correctly with date-grouped files (messages.ttl)\n const endpoint = `${podBaseUrl}/.data/chat/-/sparql`;\n const threadSubject = `<${threadUri}>`;\n\n const messagesQuery = `\n PREFIX meeting: <http://www.w3.org/ns/pim/meeting#>\n PREFIX sioc: <http://rdfs.org/sioc/ns#>\n PREFIX udfs: <https://undefineds.co/ns#>\n SELECT ?role ?content ?createdAt\n WHERE {\n ?msg a meeting:Message ;\n sioc:has_container ${threadSubject} .\n OPTIONAL { ?msg udfs:role ?role . }\n OPTIONAL { ?msg sioc:content ?content . }\n OPTIONAL { ?msg udfs:createdAt ?createdAt . }\n }\n ORDER BY ?createdAt\n `;\n\n const messagesRes = await session.fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/sparql-query',\n 'Accept': 'application/sparql-results+json',\n },\n body: messagesQuery,\n });\n\n const messagesJson = messagesRes.ok ? await messagesRes.json() : { results: { bindings: [] } };\n const messageBindings = messagesJson.results?.bindings || [];\n\n // Extract bare ID from thread.id\n const bareId = typeof thread.id === 'string' && thread.id.includes('#')\n ? thread.id.split('#').pop() || threadId\n : thread.id;\n\n return {\n id: bareId,\n title: thread.title || undefined,\n workspace: thread.workspace || undefined,\n createdAt: thread.createdAt?.toISOString() || new Date().toISOString(),\n updatedAt: thread.updatedAt?.toISOString() || new Date().toISOString(),\n messages: messageBindings.map((m: any) => ({\n role: m.role?.value || 'user',\n content: m.content?.value || '',\n timestamp: m.createdAt?.value || new Date().toISOString(),\n })),\n };\n } catch (error) {\n console.error('Failed to load thread:', error);\n return null;\n }\n}\n\n/**\n * Save a message to a thread.\n */\nexport async function saveMessage(\n session: Session,\n chatId: string,\n threadId: string,\n message: ThreadMessage,\n): Promise<boolean> {\n try {\n const db = createDb(session);\n\n // Ensure chat exists\n await ensureChat(db, chatId, session.info.webId!);\n\n // Ensure thread exists\n await ensureThread(db, chatId, threadId, session.info.webId!);\n\n // 构建完整的 Thread URI(用于 RDF 引用)\n const podBaseUrl = session.info.webId!.replace('/profile/card#me', '');\n const threadUri = `${podBaseUrl}/.data/chat/${chatId}/index.ttl#${threadId}`;\n\n // Insert message\n // Note: yyyy/MM/dd are automatically extracted from createdAt by drizzle-solid\n const messageId = `msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n await db.insert(Message).values({\n id: messageId,\n chatId,\n threadId: threadUri, // 传入完整 URI\n maker: session.info.webId!,\n role: message.role,\n content: message.content,\n status: 'completed',\n createdAt: new Date(message.timestamp),\n });\n\n return true;\n } catch (error) {\n console.error('Failed to save message:', error);\n return false;\n }\n}\n\n/**\n * Save a tool call as a message with metadata.\n */\nexport async function saveToolCall(\n session: Session,\n chatId: string,\n threadId: string,\n toolCall: {\n toolName: string;\n toolCallId: string;\n arguments: any;\n output?: string;\n status: 'pending' | 'completed' | 'failed';\n },\n): Promise<boolean> {\n try {\n const db = createDb(session);\n\n // Ensure chat and thread exist\n await ensureChat(db, chatId, session.info.webId!);\n await ensureThread(db, chatId, threadId, session.info.webId!);\n\n // 构建完整的 Thread URI(用于 RDF 引用)\n const podBaseUrl = session.info.webId!.replace('/profile/card#me', '');\n const threadUri = `${podBaseUrl}/.data/chat/${chatId}/index.ttl#${threadId}`;\n\n // Insert tool call message\n // Note: yyyy/MM/dd are automatically extracted from createdAt by drizzle-solid\n const messageId = `tool-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n await db.insert(Message).values({\n id: messageId,\n chatId,\n threadId: threadUri, // 传入完整 URI\n maker: session.info.webId!,\n role: 'tool_call',\n content: `Executed ${toolCall.toolName}`,\n status: toolCall.status,\n toolName: toolCall.toolName,\n toolCallId: toolCall.toolCallId,\n metadata: JSON.stringify({\n type: 'tool_call',\n toolName: toolCall.toolName,\n toolCallId: toolCall.toolCallId,\n arguments: toolCall.arguments,\n output: toolCall.output,\n status: toolCall.status,\n }),\n createdAt: new Date(),\n });\n\n return true;\n } catch (error) {\n console.error('Failed to save tool call:', error);\n return false;\n }\n}\n\n/**\n * Create a fresh thread.\n * workspace is stored as a first-class field on Thread.\n */\nexport async function createThread(\n session: Session,\n chatId: string,\n workspace?: string,\n title?: string,\n): Promise<string> {\n const threadId = `thread-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n\n try {\n const db = createDb(session);\n\n // Ensure chat exists\n await ensureChat(db, chatId, session.info.webId!);\n\n // Create thread with workspace as first-class field\n const now = new Date();\n await db.insert(Thread).values({\n id: threadId,\n chatId,\n title: title || 'CLI Conversation',\n workspace: workspace || null,\n status: 'active',\n metadata: JSON.stringify({ source: 'cli' }),\n createdAt: now,\n updatedAt: now,\n });\n\n return threadId;\n } catch (error) {\n console.error('Failed to create thread:', error);\n return threadId; // Return ID anyway, will be created on first message\n }\n}\n\n// ============================================================================\n// Internal Helpers\n// ============================================================================\n\nasync function ensureChat(db: any, chatId: string, webId: string): Promise<void> {\n try {\n // Use findByIri to avoid OPTIONAL bug in SPARQL queries\n const podBaseUrl = webId.replace('/profile/card#me', '');\n const chatUri = `${podBaseUrl}/.data/chat/${chatId}/index.ttl#this`;\n const chat = await db.findByIri(Chat, chatUri);\n\n if (!chat) {\n const now = new Date();\n await db.insert(Chat).values({\n id: chatId,\n title: 'CLI Chat',\n author: webId,\n participants: [],\n status: 'active',\n createdAt: now,\n updatedAt: now,\n });\n }\n } catch (error) {\n // Ignore if already exists\n }\n}\n\nasync function ensureThread(db: any, chatId: string, threadId: string, webId: string): Promise<void> {\n try {\n // Use findByIri to avoid OPTIONAL bug in SPARQL queries\n const podBaseUrl = webId.replace('/profile/card#me', '');\n const threadUri = `${podBaseUrl}/.data/chat/${chatId}/index.ttl#${threadId}`;\n const thread = await db.findByIri(Thread, threadUri);\n\n if (!thread) {\n const now = new Date();\n await db.insert(Thread).values({\n id: threadId,\n chatId,\n title: 'CLI Conversation',\n status: 'active',\n metadata: JSON.stringify({ source: 'cli' }),\n createdAt: now,\n updatedAt: now,\n });\n }\n } catch (error) {\n // Ignore if already exists\n }\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Solid OIDC authentication helpers for CLI.
|
|
3
|
+
*
|
|
4
|
+
* Uses client_credentials grant to obtain an access token from the
|
|
5
|
+
* CSS OIDC token endpoint, so CLI commands can access Pod resources
|
|
6
|
+
* without email/password.
|
|
7
|
+
*/
|
|
8
|
+
export interface SolidTokenResult {
|
|
9
|
+
accessToken: string;
|
|
10
|
+
tokenType: string;
|
|
11
|
+
expiresAt: Date;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Exchange client credentials for an access token via the OIDC token endpoint.
|
|
15
|
+
*/
|
|
16
|
+
export declare function getAccessToken(clientId: string, clientSecret: string, baseUrl: string): Promise<SolidTokenResult | null>;
|
|
17
|
+
/**
|
|
18
|
+
* Perform an authenticated fetch using a Bearer access token.
|
|
19
|
+
*/
|
|
20
|
+
export declare function authenticatedFetch(url: string, token: string, init?: RequestInit): Promise<Response>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Solid OIDC authentication helpers for CLI.
|
|
4
|
+
*
|
|
5
|
+
* Uses client_credentials grant to obtain an access token from the
|
|
6
|
+
* CSS OIDC token endpoint, so CLI commands can access Pod resources
|
|
7
|
+
* without email/password.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.getAccessToken = getAccessToken;
|
|
11
|
+
exports.authenticatedFetch = authenticatedFetch;
|
|
12
|
+
/**
|
|
13
|
+
* Discover the OIDC token endpoint from the server's openid-configuration.
|
|
14
|
+
*/
|
|
15
|
+
async function discoverTokenEndpoint(baseUrl) {
|
|
16
|
+
try {
|
|
17
|
+
const res = await fetch(`${baseUrl}.well-known/openid-configuration`);
|
|
18
|
+
if (!res.ok)
|
|
19
|
+
return null;
|
|
20
|
+
const data = (await res.json());
|
|
21
|
+
return data.token_endpoint ?? null;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Exchange client credentials for an access token via the OIDC token endpoint.
|
|
29
|
+
*/
|
|
30
|
+
async function getAccessToken(clientId, clientSecret, baseUrl) {
|
|
31
|
+
const tokenEndpoint = await discoverTokenEndpoint(baseUrl);
|
|
32
|
+
if (!tokenEndpoint) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const params = new URLSearchParams({
|
|
37
|
+
grant_type: 'client_credentials',
|
|
38
|
+
client_id: clientId,
|
|
39
|
+
client_secret: clientSecret,
|
|
40
|
+
});
|
|
41
|
+
const res = await fetch(tokenEndpoint, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
44
|
+
body: params.toString(),
|
|
45
|
+
});
|
|
46
|
+
if (!res.ok)
|
|
47
|
+
return null;
|
|
48
|
+
const data = (await res.json());
|
|
49
|
+
if (!data.access_token)
|
|
50
|
+
return null;
|
|
51
|
+
const expiresIn = data.expires_in ?? 3600;
|
|
52
|
+
return {
|
|
53
|
+
accessToken: data.access_token,
|
|
54
|
+
tokenType: data.token_type ?? 'Bearer',
|
|
55
|
+
expiresAt: new Date(Date.now() + expiresIn * 1000),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Perform an authenticated fetch using a Bearer access token.
|
|
64
|
+
*/
|
|
65
|
+
async function authenticatedFetch(url, token, init) {
|
|
66
|
+
const headers = new Headers(init?.headers);
|
|
67
|
+
headers.set('Authorization', `Bearer ${token}`);
|
|
68
|
+
return fetch(url, { ...init, headers });
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=solid-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solid-auth.js","sourceRoot":"","sources":["../../../src/cli/lib/solid-auth.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAyBH,wCA0CC;AAKD,gDAQC;AAxED;;GAEG;AACH,KAAK,UAAU,qBAAqB,CAAC,OAAe;IAClD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,kCAAkC,CAAC,CAAC;QACtE,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QACzB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAgC,CAAC;QAC/D,OAAO,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,cAAc,CAClC,QAAgB,EAChB,YAAoB,EACpB,OAAe;IAEf,MAAM,aAAa,GAAG,MAAM,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC3D,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;YACjC,UAAU,EAAE,oBAAoB;YAChC,SAAS,EAAE,QAAQ;YACnB,aAAa,EAAE,YAAY;SAC5B,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,aAAa,EAAE;YACrC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;YAChE,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE;SACxB,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QAEzB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAI7B,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC;QAEpC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC;QAC1C,OAAO;YACL,WAAW,EAAE,IAAI,CAAC,YAAY;YAC9B,SAAS,EAAE,IAAI,CAAC,UAAU,IAAI,QAAQ;YACtC,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,IAAI,CAAC;SACnD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,kBAAkB,CACtC,GAAW,EACX,KAAa,EACb,IAAkB;IAElB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,KAAK,EAAE,CAAC,CAAC;IAChD,OAAO,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAC1C,CAAC","sourcesContent":["/**\n * Solid OIDC authentication helpers for CLI.\n *\n * Uses client_credentials grant to obtain an access token from the\n * CSS OIDC token endpoint, so CLI commands can access Pod resources\n * without email/password.\n */\n\nexport interface SolidTokenResult {\n accessToken: string;\n tokenType: string;\n expiresAt: Date;\n}\n\n/**\n * Discover the OIDC token endpoint from the server's openid-configuration.\n */\nasync function discoverTokenEndpoint(baseUrl: string): Promise<string | null> {\n try {\n const res = await fetch(`${baseUrl}.well-known/openid-configuration`);\n if (!res.ok) return null;\n const data = (await res.json()) as { token_endpoint?: string };\n return data.token_endpoint ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Exchange client credentials for an access token via the OIDC token endpoint.\n */\nexport async function getAccessToken(\n clientId: string,\n clientSecret: string,\n baseUrl: string,\n): Promise<SolidTokenResult | null> {\n const tokenEndpoint = await discoverTokenEndpoint(baseUrl);\n if (!tokenEndpoint) {\n return null;\n }\n\n try {\n const params = new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: clientId,\n client_secret: clientSecret,\n });\n\n const res = await fetch(tokenEndpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: params.toString(),\n });\n\n if (!res.ok) return null;\n\n const data = (await res.json()) as {\n access_token?: string;\n token_type?: string;\n expires_in?: number;\n };\n\n if (!data.access_token) return null;\n\n const expiresIn = data.expires_in ?? 3600;\n return {\n accessToken: data.access_token,\n tokenType: data.token_type ?? 'Bearer',\n expiresAt: new Date(Date.now() + expiresIn * 1000),\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Perform an authenticated fetch using a Bearer access token.\n */\nexport async function authenticatedFetch(\n url: string,\n token: string,\n init?: RequestInit,\n): Promise<Response> {\n const headers = new Headers(init?.headers);\n headers.set('Authorization', `Bearer ${token}`);\n return fetch(url, { ...init, headers });\n}\n"]}
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
"requireName": "@undefineds.co/xpod",
|
|
8
8
|
"import": [
|
|
9
9
|
"undefineds:dist/storage/sparql/SubgraphQueryEngine.jsonld",
|
|
10
|
-
"undefineds:dist/storage/MigratableDataAccessor.jsonld",
|
|
11
10
|
"undefineds:dist/dns/DnsProvider.jsonld",
|
|
12
11
|
"undefineds:dist/edge/EdgeNodeCertificateProvisioner.jsonld",
|
|
13
12
|
"undefineds:dist/edge/interfaces/EdgeNodeTunnelManager.jsonld",
|
|
@@ -24,12 +23,10 @@
|
|
|
24
23
|
"undefineds:dist/storage/SparqlUpdateResourceStore.jsonld",
|
|
25
24
|
"undefineds:dist/http/SubgraphSparqlHttpHandler.jsonld",
|
|
26
25
|
"undefineds:dist/http/quota/QuotaAdminHttpHandler.jsonld",
|
|
27
|
-
"undefineds:dist/http/admin/EdgeNodeSignalHttpHandler.jsonld",
|
|
28
26
|
"undefineds:dist/http/ClusterIngressRouter.jsonld",
|
|
29
27
|
"undefineds:dist/http/ClusterWebSocketConfigurator.jsonld",
|
|
30
28
|
"undefineds:dist/http/EdgeNodeDirectDebugHttpHandler.jsonld",
|
|
31
29
|
"undefineds:dist/http/EdgeNodeProxyHttpHandler.jsonld",
|
|
32
|
-
"undefineds:dist/http/SignalInterceptHttpHandler.jsonld",
|
|
33
30
|
"undefineds:dist/http/RouterHttpHandler.jsonld",
|
|
34
31
|
"undefineds:dist/http/RouterHttpRoute.jsonld",
|
|
35
32
|
"undefineds:dist/http/TracingHandler.jsonld",
|
|
@@ -40,7 +37,6 @@
|
|
|
40
37
|
"undefineds:dist/storage/keyvalue/PostgresKeyValueStorage.jsonld",
|
|
41
38
|
"undefineds:dist/storage/keyvalue/RedisKeyValueStorage.jsonld",
|
|
42
39
|
"undefineds:dist/storage/keyvalue/SqliteKeyValueStorage.jsonld",
|
|
43
|
-
"undefineds:dist/quota/DefaultQuotaService.jsonld",
|
|
44
40
|
"undefineds:dist/quota/DrizzleQuotaService.jsonld",
|
|
45
41
|
"undefineds:dist/quota/NoopQuotaService.jsonld",
|
|
46
42
|
"undefineds:dist/storage/quota/PerAccountQuotaStrategy.jsonld",
|
|
@@ -58,9 +54,6 @@
|
|
|
58
54
|
"undefineds:dist/storage/quota/UsageTrackingStore.jsonld",
|
|
59
55
|
"undefineds:dist/identity/CenterNodeRegistrationService.jsonld",
|
|
60
56
|
"undefineds:dist/http/PodRoutingHttpHandler.jsonld",
|
|
61
|
-
"undefineds:dist/storage/accessors/TieredMinioDataAccessor.jsonld",
|
|
62
|
-
"undefineds:dist/http/cluster/PodMigrationHttpHandler.jsonld",
|
|
63
|
-
"undefineds:dist/service/PodMigrationService.jsonld",
|
|
64
57
|
"undefineds:dist/identity/ReactAppViewHandler.jsonld",
|
|
65
58
|
"undefineds:dist/storage/quint/types.jsonld",
|
|
66
59
|
"undefineds:dist/storage/quint/SqliteQuintStore.jsonld",
|
|
@@ -83,6 +76,10 @@
|
|
|
83
76
|
"undefineds:dist/identity/oidc/DisabledOidcHandler.jsonld",
|
|
84
77
|
"undefineds:dist/identity/oidc/DisabledIdentityProviderHandler.jsonld",
|
|
85
78
|
"undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld",
|
|
86
|
-
"undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld"
|
|
79
|
+
"undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld",
|
|
80
|
+
"undefineds:dist/storage/locking/UrlAwareRedisLocker.jsonld",
|
|
81
|
+
"undefineds:dist/provision/ProvisionPodCreator.jsonld",
|
|
82
|
+
"undefineds:dist/provision/ProvisionCodeCodec.jsonld",
|
|
83
|
+
"undefineds:dist/authorization/AuthModeSelector.jsonld"
|
|
87
84
|
]
|
|
88
85
|
}
|