@undefineds.co/xpod 0.3.32 → 0.3.34
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/dist/api/chatkit/pod-store.d.ts +3 -0
- package/dist/api/chatkit/pod-store.js +93 -59
- package/dist/api/chatkit/pod-store.js.map +1 -1
- package/dist/api/chatkit/schema.d.ts +5 -6
- package/dist/api/matrix/PodMatrixStore.js +26 -21
- package/dist/api/matrix/PodMatrixStore.js.map +1 -1
- package/dist/api/runs/InngestRunExecutionBackend.d.ts +2 -2
- package/dist/api/runs/schema.d.ts +5 -7
- package/dist/api/runs/store.js +6 -4
- package/dist/api/runs/store.js.map +1 -1
- package/dist/api/tasks/InngestTaskScheduler.d.ts +4 -4
- package/dist/api/tasks/schema.d.ts +17 -13
- package/dist/api/tasks/schema.js +7 -2
- package/dist/api/tasks/schema.js.map +1 -1
- package/dist/api/tasks/store.js +1 -2
- package/dist/api/tasks/store.js.map +1 -1
- package/dist/http/search/SearchHttpHandler.js +2 -2
- package/dist/http/search/SearchHttpHandler.js.map +1 -1
- package/dist/storage/SparqlUpdateResourceStore.d.ts +1 -0
- package/dist/storage/SparqlUpdateResourceStore.js +5 -0
- package/dist/storage/SparqlUpdateResourceStore.js.map +1 -1
- package/dist/storage/SparqlUpdateResourceStore.jsonld +4 -0
- package/dist/storage/vector/VectorIndexingListener.js +2 -2
- package/dist/storage/vector/VectorIndexingListener.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/exact-records.d.ts +21 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/exact-records.d.ts.map +1 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/exact-records.js +85 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/exact-records.js.map +1 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/default-id-template.d.ts +10 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/default-id-template.d.ts.map +1 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/default-id-template.js +365 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/default-id-template.js.map +1 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/index.d.ts +1 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/index.d.ts.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/index.js +3 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/index.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/insert-query-builder.d.ts.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/insert-query-builder.js +5 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/insert-query-builder.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/repository.d.ts +2 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/repository.d.ts.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/repository.js +2 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/repository.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/resource-reference.d.ts +18 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/resource-reference.d.ts.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/resource-reference.js +234 -10
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/resource-reference.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/schema/pod-table.d.ts +13 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/schema/pod-table.d.ts.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/schema/pod-table.js +19 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/schema/pod-table.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/exact-records.d.ts +21 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/exact-records.d.ts.map +1 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/exact-records.js +78 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/exact-records.js.map +1 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/default-id-template.d.ts +10 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/default-id-template.d.ts.map +1 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/default-id-template.js +362 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/default-id-template.js.map +1 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/index.d.ts +1 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/index.d.ts.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/index.js +1 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/index.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/insert-query-builder.d.ts.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/insert-query-builder.js +5 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/insert-query-builder.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/repository.d.ts +2 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/repository.d.ts.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/repository.js +1 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/repository.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/resource-reference.d.ts +18 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/resource-reference.d.ts.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/resource-reference.js +225 -10
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/resource-reference.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/schema/pod-table.d.ts +13 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/schema/pod-table.d.ts.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/schema/pod-table.js +19 -0
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/schema/pod-table.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/index.d.ts +5 -4
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/index.d.ts.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/index.js +4 -3
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/index.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/index.d.ts +5 -4
- package/node_modules/@undefineds.co/drizzle-solid/dist/index.d.ts.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/index.js +20 -3
- package/node_modules/@undefineds.co/drizzle-solid/dist/index.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/package.json +1 -1
- package/package.json +3 -3
package/dist/api/tasks/schema.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.TaskStatus = exports.TaskTriggerKind = exports.Task = void 0;
|
|
4
4
|
const models_1 = require("@undefineds.co/models");
|
|
5
5
|
Object.defineProperty(exports, "TaskStatus", { enumerable: true, get: function () { return models_1.TaskStatus; } });
|
|
6
|
-
Object.defineProperty(exports, "TaskTriggerKind", { enumerable: true, get: function () { return models_1.TaskTriggerKind; } });
|
|
7
6
|
exports.Task = models_1.taskResource;
|
|
7
|
+
exports.TaskTriggerKind = {
|
|
8
|
+
ONCE: 'once',
|
|
9
|
+
INTERVAL: 'interval',
|
|
10
|
+
CRON: 'cron',
|
|
11
|
+
EVENT: 'event',
|
|
12
|
+
};
|
|
8
13
|
//# sourceMappingURL=schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/api/tasks/schema.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/api/tasks/schema.ts"],"names":[],"mappings":";;;AAAA,kDAK+B;AAatB,2FAjBP,mBAAU,OAiBO;AAXN,QAAA,IAAI,GAAG,qBAAY,CAAC;AAEpB,QAAA,eAAe,GAAG;IAC7B,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,UAAU;IACpB,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;CACN,CAAC","sourcesContent":["import {\n TaskStatus,\n taskResource,\n type TaskRow,\n type TaskStatusType,\n} from '@undefineds.co/models';\n\nexport const Task = taskResource;\n\nexport const TaskTriggerKind = {\n ONCE: 'once',\n INTERVAL: 'interval',\n CRON: 'cron',\n EVENT: 'event',\n} as const;\n\nexport type TaskTriggerKindType = (typeof TaskTriggerKind)[keyof typeof TaskTriggerKind];\n\nexport { TaskStatus };\n\nexport type TaskRecord = TaskRow;\nexport type {\n TaskStatusType,\n};\n"]}
|
package/dist/api/tasks/store.js
CHANGED
|
@@ -6,7 +6,6 @@ exports.generateTaskResourceId = generateTaskResourceId;
|
|
|
6
6
|
exports.generateDefaultTaskResourceId = generateDefaultTaskResourceId;
|
|
7
7
|
exports.resolveTaskResource = resolveTaskResource;
|
|
8
8
|
exports.resolveTaskUrn = resolveTaskUrn;
|
|
9
|
-
const models_1 = require("@undefineds.co/models");
|
|
10
9
|
function isTaskResourceId(value) {
|
|
11
10
|
return typeof value === 'string'
|
|
12
11
|
&& /^index\.ttl#[^#/]+$/.test(value);
|
|
@@ -25,7 +24,7 @@ function generateTaskResourceId(input) {
|
|
|
25
24
|
if (/\.ttl(?:#|$)/i.test(key) || key.includes('/') || key.includes('#')) {
|
|
26
25
|
throw new Error(`Task id generator requires a local key: ${key}`);
|
|
27
26
|
}
|
|
28
|
-
return
|
|
27
|
+
return `index.ttl#${key}`;
|
|
29
28
|
}
|
|
30
29
|
function generateDefaultTaskResourceId(key) {
|
|
31
30
|
return generateTaskResourceId(key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/api/tasks/store.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/api/tasks/store.ts"],"names":[],"mappings":";;AAwCA,4CAGC;AAED,kDAKC;AAED,wDAaC;AAED,sEAEC;AAED,kDAOC;AAED,wCAEC;AA1CD,SAAgB,gBAAgB,CAAC,KAAgC;IAC/D,OAAO,OAAO,KAAK,KAAK,QAAQ;WAC3B,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC;AAED,SAAgB,mBAAmB,CAAC,EAAU;IAC5C,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,gEAAgE,EAAE,EAAE,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAgB,sBAAsB,CAAC,KAItC;IACC,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;IAC1D,IAAI,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,4DAA4D,GAAG,EAAE,CAAC,CAAC;IACrF,CAAC;IACD,IAAI,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CAAC,2CAA2C,GAAG,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,aAAa,GAAG,EAAE,CAAC;AAC5B,CAAC;AAED,SAAgB,6BAA6B,CAAC,GAAW;IACvD,OAAO,sBAAsB,CAAC,GAAG,CAAC,CAAC;AACrC,CAAC;AAED,SAAgB,mBAAmB,CAAC,UAAkB,EAAE,MAAc;IACpE,IAAI,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACjE,OAAO,GAAG,IAAI,eAAe,QAAQ,EAAE,CAAC;AAC1C,CAAC;AAED,SAAgB,cAAc,CAAC,MAAc;IAC3C,OAAO,iBAAiB,kBAAkB,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;AAC5E,CAAC","sourcesContent":["import type { WorkspaceRef } from '../workspace/types';\nimport type { TaskAuthBindingSnapshot } from './TaskAuthBinding';\nimport type { TaskStatusType, TaskTriggerKindType } from './schema';\n\nexport interface TaskRecordData {\n /** Base-relative Solid resource id, e.g. `index.ttl#task_x`. */\n id: string;\n surfaceId: string;\n title?: string;\n prompt: string;\n thread: string;\n workspace: WorkspaceRef;\n runner: string;\n status: TaskStatusType;\n triggerKind: TaskTriggerKindType;\n cron?: string;\n intervalSeconds?: number;\n eventName?: string;\n nextRunAt?: number;\n lastRunAt?: number;\n authBinding?: TaskAuthBindingSnapshot;\n metadata?: Record<string, unknown>;\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface TaskListOptions {\n status?: TaskStatusType;\n triggerKind?: TaskTriggerKindType;\n eventName?: string;\n dueAt?: number;\n limit?: number;\n}\n\nexport interface TaskStore<TContext> {\n saveTask(task: TaskRecordData, context: TContext): Promise<void>;\n loadTask(taskId: string, context: TContext): Promise<TaskRecordData>;\n listTasks(options: TaskListOptions, context: TContext): Promise<TaskRecordData[]>;\n}\n\nexport function isTaskResourceId(value: string | null | undefined): value is string {\n return typeof value === 'string'\n && /^index\\.ttl#[^#/]+$/.test(value);\n}\n\nexport function buildTaskResourceId(id: string): string {\n if (!isTaskResourceId(id)) {\n throw new Error(`Task id must be a complete Task resource id under index.ttl: ${id}`);\n }\n return id;\n}\n\nexport function generateTaskResourceId(input: string | {\n key: string;\n surfaceId: string;\n createdAt?: number;\n}): string {\n const key = typeof input === 'string' ? input : input.key;\n if (/^index\\.ttl#[^#/]+$/.test(key)) {\n throw new Error(`Task id generator requires a local key, got resource id: ${key}`);\n }\n if (/\\.ttl(?:#|$)/i.test(key) || key.includes('/') || key.includes('#')) {\n throw new Error(`Task id generator requires a local key: ${key}`);\n }\n return `index.ttl#${key}`;\n}\n\nexport function generateDefaultTaskResourceId(key: string): string {\n return generateTaskResourceId(key);\n}\n\nexport function resolveTaskResource(podBaseUrl: string, taskId: string): string {\n if (/^https?:\\/\\//.test(taskId)) {\n return taskId;\n }\n const base = podBaseUrl.replace(/\\/$/, '');\n const relative = buildTaskResourceId(taskId).replace(/^\\/+/, '');\n return `${base}/.data/task/${relative}`;\n}\n\nexport function resolveTaskUrn(taskId: string): string {\n return `urn:xpod:task:${encodeURIComponent(buildTaskResourceId(taskId))}`;\n}\n"]}
|
|
@@ -173,8 +173,8 @@ class SearchHttpHandler extends community_server_1.HttpHandler {
|
|
|
173
173
|
async getAiCredential(podBaseUrl) {
|
|
174
174
|
try {
|
|
175
175
|
const query = `
|
|
176
|
-
PREFIX cred: <${models_1.
|
|
177
|
-
PREFIX ai: <${models_1.
|
|
176
|
+
PREFIX cred: <${models_1.UDFS.NAMESPACE}>
|
|
177
|
+
PREFIX ai: <${models_1.UDFS.NAMESPACE}>
|
|
178
178
|
SELECT ?apiKey ?baseUrl ?provider ?proxyUrl WHERE {
|
|
179
179
|
?cred a cred:Credential ;
|
|
180
180
|
cred:service "ai" ;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchHttpHandler.js","sourceRoot":"","sources":["../../../src/http/search/SearchHttpHandler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SearchHttpHandler - 语义搜索 HTTP 处理器\n *\n * 提供 /-/search 端点,支持基于向量的语义搜索。\n *\n * 端点:\n * - GET {path}/-/search?q=... 简单搜索\n * - POST {path}/-/search 复杂搜索(支持 filter 等)\n */\n\nimport { getLoggerFor } from 'global-logger-factory';\nimport { HttpHandler } from '@solid/community-server';\nimport type { HttpHandlerInput, HttpRequest, HttpResponse } from '@solid/community-server';\nimport {\n NotImplementedHttpError,\n MethodNotAllowedHttpError,\n HttpError,\n IdentifierSetMultiMap,\n} from '@solid/community-server';\nimport { PERMISSIONS } from '@solidlab/policy-engine';\nimport type { CredentialsExtractor, PermissionReader, Authorizer, ResourceIdentifier } from '@solid/community-server';\nimport type { VectorStore } from '../../storage/vector/VectorStore';\nimport type { EmbeddingService } from '../../ai/service/EmbeddingService';\nimport type { SparqlEngine } from '../../storage/sparql/SubgraphQueryEngine';\nimport type { AiCredential } from '../../ai/service/types';\nimport type { VectorSearchOptions } from '../../storage/vector/types';\nimport { XPOD_AI, XPOD_CREDENTIAL, normalizeAIConfigProviderId } from '@undefineds.co/models';\n\nconst ALLOWED_METHODS = ['GET', 'POST', 'OPTIONS'];\n\n// ============================================\n// 请求/响应类型\n// ============================================\n\ninterface SearchRequest {\n /** 查询文本 */\n query?: string;\n /** 预计算的查询向量 */\n vector?: number[];\n /** 返回结果数量,默认 10 */\n limit?: number;\n /** 相似度阈值 (0-1) */\n threshold?: number;\n /** 过滤条件 */\n filter?: {\n type?: string;\n graphPrefix?: string;\n subjectPrefix?: string;\n };\n /** embedding 模型 */\n model?: string;\n}\n\ninterface SearchResult {\n /** 资源 URI */\n subject: string;\n /** 相似度分数 (0-1) */\n score: number;\n /** 距离 */\n distance?: number;\n /** 文本片段 */\n snippet?: string;\n}\n\ninterface SearchResponse {\n results: SearchResult[];\n model: string;\n took_ms: number;\n}\n\n// ============================================\n// 错误处理\n// ============================================\n\ntype SearchErrorCode =\n | 'INVALID_REQUEST'\n | 'UNAUTHORIZED'\n | 'FORBIDDEN'\n | 'NO_CREDENTIAL'\n | 'EMBEDDING_ERROR'\n | 'SEARCH_ERROR';\n\nclass SearchApiError extends Error {\n constructor(\n public readonly code: SearchErrorCode,\n public readonly statusCode: number,\n message: string,\n ) {\n super(message);\n this.name = 'SearchApiError';\n }\n\n static invalidRequest(message: string): SearchApiError {\n return new SearchApiError('INVALID_REQUEST', 400, message);\n }\n\n static noCredential(): SearchApiError {\n return new SearchApiError('NO_CREDENTIAL', 400, 'No AI credential found. Please configure AI credentials in your Pod settings.');\n }\n\n static embeddingError(message: string): SearchApiError {\n return new SearchApiError('EMBEDDING_ERROR', 502, `Embedding generation failed: ${message}`);\n }\n\n static searchError(message: string): SearchApiError {\n return new SearchApiError('SEARCH_ERROR', 500, `Search failed: ${message}`);\n }\n}\n\n// ============================================\n// Handler\n// ============================================\n\nexport interface SearchHttpHandlerOptions {\n sidecarPath?: string;\n defaultModel?: string;\n defaultLimit?: number;\n}\n\nexport class SearchHttpHandler extends HttpHandler {\n protected readonly logger = getLoggerFor(this);\n\n private readonly vectorStore: VectorStore;\n private readonly embeddingService: EmbeddingService;\n private readonly sparqlEngine: SparqlEngine;\n private readonly credentialsExtractor: CredentialsExtractor;\n private readonly permissionReader: PermissionReader;\n private readonly authorizer: Authorizer;\n private readonly sidecarPath: string;\n private readonly defaultModel: string;\n private readonly defaultLimit: number;\n\n public constructor(\n vectorStore: VectorStore,\n embeddingService: EmbeddingService,\n sparqlEngine: SparqlEngine,\n credentialsExtractor: CredentialsExtractor,\n permissionReader: PermissionReader,\n authorizer: Authorizer,\n options: SearchHttpHandlerOptions = {},\n ) {\n super();\n this.vectorStore = vectorStore;\n this.embeddingService = embeddingService;\n this.sparqlEngine = sparqlEngine;\n this.credentialsExtractor = credentialsExtractor;\n this.permissionReader = permissionReader;\n this.authorizer = authorizer;\n this.sidecarPath = options.sidecarPath ?? '/-/search';\n this.defaultModel = options.defaultModel ?? 'text-embedding-004';\n this.defaultLimit = options.defaultLimit ?? 10;\n }\n\n public override async canHandle({ request }: HttpHandlerInput): Promise<void> {\n const path = this.parseUrl(request).pathname;\n if (!path.includes(this.sidecarPath)) {\n throw new NotImplementedHttpError('Request is not targeting a search endpoint.');\n }\n }\n\n public override async handle({ request, response }: HttpHandlerInput): Promise<void> {\n const method = (request.method ?? 'GET').toUpperCase();\n\n if (method === 'OPTIONS') {\n this.writeOptions(response);\n return;\n }\n\n if (!ALLOWED_METHODS.includes(method)) {\n throw new MethodNotAllowedHttpError(ALLOWED_METHODS);\n }\n\n try {\n const url = this.parseUrl(request);\n const path = decodeURIComponent(url.pathname);\n\n const sidecarIndex = path.indexOf(this.sidecarPath);\n if (sidecarIndex === -1) {\n throw new NotImplementedHttpError('Request is not targeting a search endpoint.');\n }\n\n // 提取 base path(sidecar 之前的路径)\n let basePath = path.slice(0, sidecarIndex);\n if (!basePath.endsWith('/')) {\n basePath = `${basePath}/`;\n }\n\n const origin = `${url.protocol}//${url.host}`;\n const baseUrl = `${origin}${basePath}`;\n\n this.logger.debug(`Search request: ${method} ${path}, baseUrl=${baseUrl}`);\n\n // 鉴权\n await this.authorizeFor(baseUrl, request, [PERMISSIONS.Read]);\n\n // 解析请求\n const searchRequest = await this.parseSearchRequest(request, url);\n\n // 执行搜索\n const result = await this.executeSearch(searchRequest, baseUrl);\n\n this.sendJsonResponse(response, result);\n } catch (error: unknown) {\n this.handleError(response, error);\n }\n }\n\n /**\n * 解析搜索请求\n */\n private async parseSearchRequest(request: HttpRequest, url: URL): Promise<SearchRequest> {\n const method = (request.method ?? 'GET').toUpperCase();\n\n if (method === 'GET') {\n // GET 请求从 query string 解析\n const query = url.searchParams.get('q') || url.searchParams.get('query');\n const limit = url.searchParams.get('limit');\n const threshold = url.searchParams.get('threshold');\n const model = url.searchParams.get('model');\n\n if (!query) {\n throw SearchApiError.invalidRequest('Missing query parameter \"q\"');\n }\n\n return {\n query,\n limit: limit ? parseInt(limit, 10) : undefined,\n threshold: threshold ? parseFloat(threshold) : undefined,\n model: model || undefined,\n };\n }\n\n // POST 请求从 body 解析\n const body = await this.readJsonBody<SearchRequest>(request);\n\n if (!body.query && !body.vector) {\n throw SearchApiError.invalidRequest('Either \"query\" or \"vector\" is required');\n }\n\n return body;\n }\n\n /**\n * 执行搜索\n */\n private async executeSearch(request: SearchRequest, baseUrl: string): Promise<SearchResponse> {\n const startTime = Date.now();\n const model = request.model || this.defaultModel;\n\n let queryVector = request.vector;\n\n // 如果提供了 query 文本,需要生成 embedding\n if (request.query && !queryVector) {\n // 获取 AI 凭据\n const credential = await this.getAiCredential(baseUrl);\n if (!credential) {\n throw SearchApiError.noCredential();\n }\n\n try {\n queryVector = await this.embeddingService.embed(request.query, credential, model);\n } catch (error) {\n throw SearchApiError.embeddingError(error instanceof Error ? error.message : String(error));\n }\n }\n\n if (!queryVector) {\n throw SearchApiError.invalidRequest('Failed to generate query vector');\n }\n\n // 执行向量搜索\n const searchOptions: VectorSearchOptions = {\n limit: request.limit ?? this.defaultLimit,\n threshold: request.threshold,\n };\n\n try {\n const vectorResults = await this.vectorStore.search(model, queryVector, searchOptions);\n\n // 转换结果\n const results: SearchResult[] = vectorResults.map((r) => ({\n subject: this.vectorIdToSubject(r.id, baseUrl),\n score: r.score,\n distance: r.distance,\n }));\n\n return {\n results,\n model,\n took_ms: Date.now() - startTime,\n };\n } catch (error) {\n throw SearchApiError.searchError(error instanceof Error ? error.message : String(error));\n }\n }\n\n /**\n * 获取 AI 凭据\n */\n private async getAiCredential(podBaseUrl: string): Promise<AiCredential | null> {\n try {\n const query = `\n PREFIX cred: <${XPOD_CREDENTIAL.NAMESPACE}>\n PREFIX ai: <${XPOD_AI.NAMESPACE}>\n SELECT ?apiKey ?baseUrl ?provider ?proxyUrl WHERE {\n ?cred a cred:Credential ;\n cred:service \"ai\" ;\n cred:status \"active\" ;\n cred:apiKey ?apiKey .\n OPTIONAL { ?cred cred:provider ?provider }\n OPTIONAL {\n ?cred cred:provider ?provider .\n ?provider ai:baseUrl ?baseUrl .\n }\n OPTIONAL {\n ?cred cred:provider ?provider .\n ?provider ai:proxyUrl ?proxyUrl .\n }\n } LIMIT 1\n `;\n\n const bindingsStream = await this.sparqlEngine.queryBindings(query, podBaseUrl);\n\n for await (const binding of bindingsStream) {\n const apiKey = binding.get('apiKey');\n const baseUrl = binding.get('baseUrl');\n const provider = binding.get('provider');\n const proxyUrl = binding.get('proxyUrl');\n\n if (apiKey) {\n const providerName = normalizeAIConfigProviderId(provider?.value || 'google') || 'google';\n\n return {\n apiKey: apiKey.value,\n baseUrl: baseUrl?.value,\n provider: providerName,\n proxyUrl: proxyUrl?.value,\n };\n }\n }\n\n return null;\n } catch (error) {\n this.logger.error(`Failed to query AI credential: ${error}`);\n return null;\n }\n }\n\n /**\n * 将向量 ID 转换回 subject URI\n * 注意:这是一个简化实现,实际需要维护 ID -> URI 的映射\n */\n private vectorIdToSubject(id: number, baseUrl: string): string {\n // TODO: 实现 ID -> URI 映射查询\n // 目前返回占位符\n return `${baseUrl}#vector-${id}`;\n }\n\n // ============================================\n // 辅助方法\n // ============================================\n\n private handleError(response: HttpResponse, error: unknown): void {\n if (error instanceof SearchApiError) {\n this.logger.error(`Search API error [${error.code}]: ${error.message}`);\n this.sendErrorResponse(response, error.statusCode, error.code, error.message);\n return;\n }\n\n if (error instanceof HttpError) {\n const errorMsg = error.message || error.name || `HTTP ${error.statusCode}`;\n this.logger.error(`HTTP error ${error.statusCode}: ${errorMsg}`);\n this.sendErrorResponse(response, error.statusCode, 'HTTP_ERROR', errorMsg);\n return;\n }\n\n const errorMsg = error instanceof Error ? error.message : String(error);\n this.logger.error(`Unexpected error: ${errorMsg}`);\n this.sendErrorResponse(response, 500, 'INTERNAL_ERROR', errorMsg || 'Internal server error');\n }\n\n private async authorizeFor(\n baseUrl: string,\n request: HttpRequest,\n permissions: typeof PERMISSIONS[keyof typeof PERMISSIONS][],\n ): Promise<void> {\n const credentials = await this.credentialsExtractor.handleSafe(request);\n const identifier: ResourceIdentifier = { path: baseUrl };\n const requestedModes = new IdentifierSetMultiMap([[identifier, permissions]] as any);\n\n const availablePermissions = await this.permissionReader.handleSafe({\n credentials,\n identifier,\n requestedModes,\n } as any);\n\n this.logger.debug(`authorizeFor: baseUrl=${baseUrl}, webId=${credentials.agent?.webId}`);\n\n await this.authorizer.handleSafe({\n credentials,\n identifier,\n requestedModes,\n availablePermissions,\n } as any);\n }\n\n private parseUrl(request: HttpRequest): URL {\n const protocol = request.headers['x-forwarded-proto'] || 'http';\n const host = request.headers['x-forwarded-host'] || request.headers.host || 'localhost';\n return new URL(request.url!, `${protocol}://${host}`);\n }\n\n private async readJsonBody<T>(request: HttpRequest): Promise<T> {\n const chunks: Buffer[] = [];\n for await (const chunk of request) {\n chunks.push(chunk);\n }\n const body = Buffer.concat(chunks).toString('utf8');\n try {\n return JSON.parse(body) as T;\n } catch {\n throw SearchApiError.invalidRequest('Invalid JSON body');\n }\n }\n\n private sendJsonResponse(response: HttpResponse, data: unknown, status = 200): void {\n response.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache',\n });\n response.end(JSON.stringify(data));\n }\n\n private sendErrorResponse(\n response: HttpResponse,\n status: number,\n code: string,\n message: string,\n ): void {\n response.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache',\n });\n response.end(\n JSON.stringify({\n error: true,\n code,\n message,\n }),\n );\n }\n\n private writeOptions(response: HttpResponse): void {\n response.writeHead(204, {\n 'Access-Control-Allow-Methods': ALLOWED_METHODS.join(', '),\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization',\n });\n response.end();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SearchHttpHandler.js","sourceRoot":"","sources":["../../../src/http/search/SearchHttpHandler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SearchHttpHandler - 语义搜索 HTTP 处理器\n *\n * 提供 /-/search 端点,支持基于向量的语义搜索。\n *\n * 端点:\n * - GET {path}/-/search?q=... 简单搜索\n * - POST {path}/-/search 复杂搜索(支持 filter 等)\n */\n\nimport { getLoggerFor } from 'global-logger-factory';\nimport { HttpHandler } from '@solid/community-server';\nimport type { HttpHandlerInput, HttpRequest, HttpResponse } from '@solid/community-server';\nimport {\n NotImplementedHttpError,\n MethodNotAllowedHttpError,\n HttpError,\n IdentifierSetMultiMap,\n} from '@solid/community-server';\nimport { PERMISSIONS } from '@solidlab/policy-engine';\nimport type { CredentialsExtractor, PermissionReader, Authorizer, ResourceIdentifier } from '@solid/community-server';\nimport type { VectorStore } from '../../storage/vector/VectorStore';\nimport type { EmbeddingService } from '../../ai/service/EmbeddingService';\nimport type { SparqlEngine } from '../../storage/sparql/SubgraphQueryEngine';\nimport type { AiCredential } from '../../ai/service/types';\nimport type { VectorSearchOptions } from '../../storage/vector/types';\nimport { UDFS, normalizeAIConfigProviderId } from '@undefineds.co/models';\n\nconst ALLOWED_METHODS = ['GET', 'POST', 'OPTIONS'];\n\n// ============================================\n// 请求/响应类型\n// ============================================\n\ninterface SearchRequest {\n /** 查询文本 */\n query?: string;\n /** 预计算的查询向量 */\n vector?: number[];\n /** 返回结果数量,默认 10 */\n limit?: number;\n /** 相似度阈值 (0-1) */\n threshold?: number;\n /** 过滤条件 */\n filter?: {\n type?: string;\n graphPrefix?: string;\n subjectPrefix?: string;\n };\n /** embedding 模型 */\n model?: string;\n}\n\ninterface SearchResult {\n /** 资源 URI */\n subject: string;\n /** 相似度分数 (0-1) */\n score: number;\n /** 距离 */\n distance?: number;\n /** 文本片段 */\n snippet?: string;\n}\n\ninterface SearchResponse {\n results: SearchResult[];\n model: string;\n took_ms: number;\n}\n\n// ============================================\n// 错误处理\n// ============================================\n\ntype SearchErrorCode =\n | 'INVALID_REQUEST'\n | 'UNAUTHORIZED'\n | 'FORBIDDEN'\n | 'NO_CREDENTIAL'\n | 'EMBEDDING_ERROR'\n | 'SEARCH_ERROR';\n\nclass SearchApiError extends Error {\n constructor(\n public readonly code: SearchErrorCode,\n public readonly statusCode: number,\n message: string,\n ) {\n super(message);\n this.name = 'SearchApiError';\n }\n\n static invalidRequest(message: string): SearchApiError {\n return new SearchApiError('INVALID_REQUEST', 400, message);\n }\n\n static noCredential(): SearchApiError {\n return new SearchApiError('NO_CREDENTIAL', 400, 'No AI credential found. Please configure AI credentials in your Pod settings.');\n }\n\n static embeddingError(message: string): SearchApiError {\n return new SearchApiError('EMBEDDING_ERROR', 502, `Embedding generation failed: ${message}`);\n }\n\n static searchError(message: string): SearchApiError {\n return new SearchApiError('SEARCH_ERROR', 500, `Search failed: ${message}`);\n }\n}\n\n// ============================================\n// Handler\n// ============================================\n\nexport interface SearchHttpHandlerOptions {\n sidecarPath?: string;\n defaultModel?: string;\n defaultLimit?: number;\n}\n\nexport class SearchHttpHandler extends HttpHandler {\n protected readonly logger = getLoggerFor(this);\n\n private readonly vectorStore: VectorStore;\n private readonly embeddingService: EmbeddingService;\n private readonly sparqlEngine: SparqlEngine;\n private readonly credentialsExtractor: CredentialsExtractor;\n private readonly permissionReader: PermissionReader;\n private readonly authorizer: Authorizer;\n private readonly sidecarPath: string;\n private readonly defaultModel: string;\n private readonly defaultLimit: number;\n\n public constructor(\n vectorStore: VectorStore,\n embeddingService: EmbeddingService,\n sparqlEngine: SparqlEngine,\n credentialsExtractor: CredentialsExtractor,\n permissionReader: PermissionReader,\n authorizer: Authorizer,\n options: SearchHttpHandlerOptions = {},\n ) {\n super();\n this.vectorStore = vectorStore;\n this.embeddingService = embeddingService;\n this.sparqlEngine = sparqlEngine;\n this.credentialsExtractor = credentialsExtractor;\n this.permissionReader = permissionReader;\n this.authorizer = authorizer;\n this.sidecarPath = options.sidecarPath ?? '/-/search';\n this.defaultModel = options.defaultModel ?? 'text-embedding-004';\n this.defaultLimit = options.defaultLimit ?? 10;\n }\n\n public override async canHandle({ request }: HttpHandlerInput): Promise<void> {\n const path = this.parseUrl(request).pathname;\n if (!path.includes(this.sidecarPath)) {\n throw new NotImplementedHttpError('Request is not targeting a search endpoint.');\n }\n }\n\n public override async handle({ request, response }: HttpHandlerInput): Promise<void> {\n const method = (request.method ?? 'GET').toUpperCase();\n\n if (method === 'OPTIONS') {\n this.writeOptions(response);\n return;\n }\n\n if (!ALLOWED_METHODS.includes(method)) {\n throw new MethodNotAllowedHttpError(ALLOWED_METHODS);\n }\n\n try {\n const url = this.parseUrl(request);\n const path = decodeURIComponent(url.pathname);\n\n const sidecarIndex = path.indexOf(this.sidecarPath);\n if (sidecarIndex === -1) {\n throw new NotImplementedHttpError('Request is not targeting a search endpoint.');\n }\n\n // 提取 base path(sidecar 之前的路径)\n let basePath = path.slice(0, sidecarIndex);\n if (!basePath.endsWith('/')) {\n basePath = `${basePath}/`;\n }\n\n const origin = `${url.protocol}//${url.host}`;\n const baseUrl = `${origin}${basePath}`;\n\n this.logger.debug(`Search request: ${method} ${path}, baseUrl=${baseUrl}`);\n\n // 鉴权\n await this.authorizeFor(baseUrl, request, [PERMISSIONS.Read]);\n\n // 解析请求\n const searchRequest = await this.parseSearchRequest(request, url);\n\n // 执行搜索\n const result = await this.executeSearch(searchRequest, baseUrl);\n\n this.sendJsonResponse(response, result);\n } catch (error: unknown) {\n this.handleError(response, error);\n }\n }\n\n /**\n * 解析搜索请求\n */\n private async parseSearchRequest(request: HttpRequest, url: URL): Promise<SearchRequest> {\n const method = (request.method ?? 'GET').toUpperCase();\n\n if (method === 'GET') {\n // GET 请求从 query string 解析\n const query = url.searchParams.get('q') || url.searchParams.get('query');\n const limit = url.searchParams.get('limit');\n const threshold = url.searchParams.get('threshold');\n const model = url.searchParams.get('model');\n\n if (!query) {\n throw SearchApiError.invalidRequest('Missing query parameter \"q\"');\n }\n\n return {\n query,\n limit: limit ? parseInt(limit, 10) : undefined,\n threshold: threshold ? parseFloat(threshold) : undefined,\n model: model || undefined,\n };\n }\n\n // POST 请求从 body 解析\n const body = await this.readJsonBody<SearchRequest>(request);\n\n if (!body.query && !body.vector) {\n throw SearchApiError.invalidRequest('Either \"query\" or \"vector\" is required');\n }\n\n return body;\n }\n\n /**\n * 执行搜索\n */\n private async executeSearch(request: SearchRequest, baseUrl: string): Promise<SearchResponse> {\n const startTime = Date.now();\n const model = request.model || this.defaultModel;\n\n let queryVector = request.vector;\n\n // 如果提供了 query 文本,需要生成 embedding\n if (request.query && !queryVector) {\n // 获取 AI 凭据\n const credential = await this.getAiCredential(baseUrl);\n if (!credential) {\n throw SearchApiError.noCredential();\n }\n\n try {\n queryVector = await this.embeddingService.embed(request.query, credential, model);\n } catch (error) {\n throw SearchApiError.embeddingError(error instanceof Error ? error.message : String(error));\n }\n }\n\n if (!queryVector) {\n throw SearchApiError.invalidRequest('Failed to generate query vector');\n }\n\n // 执行向量搜索\n const searchOptions: VectorSearchOptions = {\n limit: request.limit ?? this.defaultLimit,\n threshold: request.threshold,\n };\n\n try {\n const vectorResults = await this.vectorStore.search(model, queryVector, searchOptions);\n\n // 转换结果\n const results: SearchResult[] = vectorResults.map((r) => ({\n subject: this.vectorIdToSubject(r.id, baseUrl),\n score: r.score,\n distance: r.distance,\n }));\n\n return {\n results,\n model,\n took_ms: Date.now() - startTime,\n };\n } catch (error) {\n throw SearchApiError.searchError(error instanceof Error ? error.message : String(error));\n }\n }\n\n /**\n * 获取 AI 凭据\n */\n private async getAiCredential(podBaseUrl: string): Promise<AiCredential | null> {\n try {\n const query = `\n PREFIX cred: <${UDFS.NAMESPACE}>\n PREFIX ai: <${UDFS.NAMESPACE}>\n SELECT ?apiKey ?baseUrl ?provider ?proxyUrl WHERE {\n ?cred a cred:Credential ;\n cred:service \"ai\" ;\n cred:status \"active\" ;\n cred:apiKey ?apiKey .\n OPTIONAL { ?cred cred:provider ?provider }\n OPTIONAL {\n ?cred cred:provider ?provider .\n ?provider ai:baseUrl ?baseUrl .\n }\n OPTIONAL {\n ?cred cred:provider ?provider .\n ?provider ai:proxyUrl ?proxyUrl .\n }\n } LIMIT 1\n `;\n\n const bindingsStream = await this.sparqlEngine.queryBindings(query, podBaseUrl);\n\n for await (const binding of bindingsStream) {\n const apiKey = binding.get('apiKey');\n const baseUrl = binding.get('baseUrl');\n const provider = binding.get('provider');\n const proxyUrl = binding.get('proxyUrl');\n\n if (apiKey) {\n const providerName = normalizeAIConfigProviderId(provider?.value || 'google') || 'google';\n\n return {\n apiKey: apiKey.value,\n baseUrl: baseUrl?.value,\n provider: providerName,\n proxyUrl: proxyUrl?.value,\n };\n }\n }\n\n return null;\n } catch (error) {\n this.logger.error(`Failed to query AI credential: ${error}`);\n return null;\n }\n }\n\n /**\n * 将向量 ID 转换回 subject URI\n * 注意:这是一个简化实现,实际需要维护 ID -> URI 的映射\n */\n private vectorIdToSubject(id: number, baseUrl: string): string {\n // TODO: 实现 ID -> URI 映射查询\n // 目前返回占位符\n return `${baseUrl}#vector-${id}`;\n }\n\n // ============================================\n // 辅助方法\n // ============================================\n\n private handleError(response: HttpResponse, error: unknown): void {\n if (error instanceof SearchApiError) {\n this.logger.error(`Search API error [${error.code}]: ${error.message}`);\n this.sendErrorResponse(response, error.statusCode, error.code, error.message);\n return;\n }\n\n if (error instanceof HttpError) {\n const errorMsg = error.message || error.name || `HTTP ${error.statusCode}`;\n this.logger.error(`HTTP error ${error.statusCode}: ${errorMsg}`);\n this.sendErrorResponse(response, error.statusCode, 'HTTP_ERROR', errorMsg);\n return;\n }\n\n const errorMsg = error instanceof Error ? error.message : String(error);\n this.logger.error(`Unexpected error: ${errorMsg}`);\n this.sendErrorResponse(response, 500, 'INTERNAL_ERROR', errorMsg || 'Internal server error');\n }\n\n private async authorizeFor(\n baseUrl: string,\n request: HttpRequest,\n permissions: typeof PERMISSIONS[keyof typeof PERMISSIONS][],\n ): Promise<void> {\n const credentials = await this.credentialsExtractor.handleSafe(request);\n const identifier: ResourceIdentifier = { path: baseUrl };\n const requestedModes = new IdentifierSetMultiMap([[identifier, permissions]] as any);\n\n const availablePermissions = await this.permissionReader.handleSafe({\n credentials,\n identifier,\n requestedModes,\n } as any);\n\n this.logger.debug(`authorizeFor: baseUrl=${baseUrl}, webId=${credentials.agent?.webId}`);\n\n await this.authorizer.handleSafe({\n credentials,\n identifier,\n requestedModes,\n availablePermissions,\n } as any);\n }\n\n private parseUrl(request: HttpRequest): URL {\n const protocol = request.headers['x-forwarded-proto'] || 'http';\n const host = request.headers['x-forwarded-host'] || request.headers.host || 'localhost';\n return new URL(request.url!, `${protocol}://${host}`);\n }\n\n private async readJsonBody<T>(request: HttpRequest): Promise<T> {\n const chunks: Buffer[] = [];\n for await (const chunk of request) {\n chunks.push(chunk);\n }\n const body = Buffer.concat(chunks).toString('utf8');\n try {\n return JSON.parse(body) as T;\n } catch {\n throw SearchApiError.invalidRequest('Invalid JSON body');\n }\n }\n\n private sendJsonResponse(response: HttpResponse, data: unknown, status = 200): void {\n response.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache',\n });\n response.end(JSON.stringify(data));\n }\n\n private sendErrorResponse(\n response: HttpResponse,\n status: number,\n code: string,\n message: string,\n ): void {\n response.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache',\n });\n response.end(\n JSON.stringify({\n error: true,\n code,\n message,\n }),\n );\n }\n\n private writeOptions(response: HttpResponse): void {\n response.writeHead(204, {\n 'Access-Control-Allow-Methods': ALLOWED_METHODS.join(', '),\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization',\n });\n response.end();\n }\n}\n"]}
|
|
@@ -15,6 +15,7 @@ export declare class SparqlUpdateResourceStore extends DataAccessorBasedStore {
|
|
|
15
15
|
private readonly generator;
|
|
16
16
|
private readonly parser;
|
|
17
17
|
private readonly localFirstRdfRepresentationResolver;
|
|
18
|
+
private readonly metadataAuxiliaryStrategy;
|
|
18
19
|
protected readonly logger: import("global-logger-factory").Logger<unknown>;
|
|
19
20
|
constructor(options: SparqlUpdateResourceStoreOptions);
|
|
20
21
|
getRepresentation(identifier: ResourceIdentifier): Promise<Representation>;
|
|
@@ -18,6 +18,7 @@ class SparqlUpdateResourceStore extends community_server_1.DataAccessorBasedStor
|
|
|
18
18
|
this.generator = new sparqljs_1.Generator();
|
|
19
19
|
this.parser = new sparqljs_1.Parser();
|
|
20
20
|
this.logger = (0, global_logger_factory_1.getLoggerFor)(this);
|
|
21
|
+
this.metadataAuxiliaryStrategy = options.metadataStrategy;
|
|
21
22
|
this.localFirstRdfRepresentationResolver = options.localFirstRdfRepresentationResolver ??
|
|
22
23
|
new LocalFirstRdfRepresentationResolver_1.LocalFirstRdfRepresentationResolver({
|
|
23
24
|
accessor: options.accessor,
|
|
@@ -56,6 +57,10 @@ class SparqlUpdateResourceStore extends community_server_1.DataAccessorBasedStor
|
|
|
56
57
|
}
|
|
57
58
|
this.validateConditions(conditions, metadata);
|
|
58
59
|
}
|
|
60
|
+
if (this.metadataAuxiliaryStrategy.isAuxiliaryIdentifier(identifier)) {
|
|
61
|
+
this.logger.debug(`Metadata PATCH for ${identifier.path} falls back to CSS metadata patcher`);
|
|
62
|
+
throw new community_server_1.NotImplementedHttpError('Metadata resources must be patched by the CSS metadata patcher');
|
|
63
|
+
}
|
|
59
64
|
const sparqlUpdate = await this.toSparqlUpdate(patch, identifier);
|
|
60
65
|
if (!sparqlUpdate) {
|
|
61
66
|
this.logger.debug(`toSparqlUpdate returned undefined for ${identifier.path}, falling back to CSS handler`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SparqlUpdateResourceStore.js","sourceRoot":"","sources":["../../src/storage/SparqlUpdateResourceStore.ts"],"names":[],"mappings":"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","sourcesContent":["import { DataFactory } from 'n3';\nimport { Generator as SparqlGenerator, Parser as SparqlParser, type GraphQuads, type UpdateOperation, type Update as SparqlUpdate } from 'sparqljs';\nimport {\n DataAccessorBasedStore,\n type ChangeMap,\n type ResourceIdentifier,\n type Patch,\n NotImplementedHttpError,\n type Conditions,\n NotFoundHttpError,\n RepresentationMetadata,\n AS,\n SOLID_AS,\n BadRequestHttpError,\n ForbiddenHttpError,\n HttpError,\n type DataAccessor,\n type IdentifierStrategy,\n type AuxiliaryStrategy,\n type Representation,\n} from '@solid/community-server';\nimport type { SparqlUpdatePatch } from '@solid/community-server';\nimport { readableToString } from '@solid/community-server/dist/util/StreamUtil';\nimport { getLoggerFor } from 'global-logger-factory';\nimport {\n LocalFirstRdfRepresentationResolver,\n type LocalFirstRdfRepresentationResolverLike,\n} from '../solidfs/LocalFirstRdfRepresentationResolver';\nimport { DisabledSparqlFeatureError, UnsupportedSparqlQueryError } from './rdf/RdfSparqlAdapter';\n\nexport interface SparqlUpdateResourceStoreOptions {\n accessor: DataAccessor;\n identifierStrategy: IdentifierStrategy;\n auxiliaryStrategy: AuxiliaryStrategy;\n metadataStrategy: AuxiliaryStrategy;\n localFirstRdfRepresentationResolver?: LocalFirstRdfRepresentationResolverLike;\n}\n\n/**\n * ResourceStore that short-circuits PATCH into direct SPARQL UPDATE\n * when the underlying DataAccessor supports it.\n */\nexport class SparqlUpdateResourceStore extends DataAccessorBasedStore {\n private readonly generator = new SparqlGenerator();\n private readonly parser = new SparqlParser();\n private readonly localFirstRdfRepresentationResolver: LocalFirstRdfRepresentationResolverLike;\n protected override readonly logger = getLoggerFor(this);\n\n public constructor(options: SparqlUpdateResourceStoreOptions) {\n super(options.accessor, options.identifierStrategy, options.auxiliaryStrategy, options.metadataStrategy);\n this.localFirstRdfRepresentationResolver = options.localFirstRdfRepresentationResolver ??\n new LocalFirstRdfRepresentationResolver({\n accessor: options.accessor,\n metadataStrategy: options.metadataStrategy,\n });\n // Check if identifierStrategy has baseUrl property (SingleRootIdentifierStrategy)\n const strategy = options.identifierStrategy as unknown as { baseUrl?: string };\n this.logger.info(`SparqlUpdateResourceStore initialized with identifierStrategy: ${options.identifierStrategy.constructor.name}, baseUrl: ${strategy.baseUrl ?? 'N/A'}`);\n }\n\n public override async getRepresentation(identifier: ResourceIdentifier): Promise<Representation> {\n const localRepresentation = await this.localFirstRdfRepresentationResolver.resolve(identifier);\n if (localRepresentation) {\n return localRepresentation;\n }\n\n return super.getRepresentation(identifier);\n }\n\n // @ts-expect-error Upstream signature returns never; we return ChangeMap for successful PATCH.\n public override async modifyResource(identifier: ResourceIdentifier, patch: Patch, conditions?: Conditions): Promise<ChangeMap> {\n this.logger.debug(`SparqlUpdateResourceStore.modifyResource called for ${identifier.path}`);\n this.logger.debug(`Patch has algebra: ${typeof (patch as SparqlUpdatePatch).algebra === 'object'}, metadata.contentType: ${patch.metadata?.contentType}`);\n\n const accessor = (this as unknown as { accessor: unknown }).accessor as unknown;\n if (!this.isSparqlCapable(accessor)) {\n this.logger.debug('Accessor is not SPARQL capable');\n throw new NotImplementedHttpError('SPARQL UPDATE not supported by this accessor');\n }\n\n // Keep the default condition validation semantics\n if (conditions) {\n let metadata: RepresentationMetadata | undefined;\n try {\n metadata = await accessor.getMetadata(identifier);\n } catch (error: unknown) {\n if (!NotFoundHttpError.isInstance(error)) {\n throw error;\n }\n }\n this.validateConditions(conditions, metadata);\n }\n\n const sparqlUpdate = await this.toSparqlUpdate(patch, identifier);\n if (!sparqlUpdate) {\n this.logger.debug(`toSparqlUpdate returned undefined for ${identifier.path}, falling back to CSS handler`);\n throw new NotImplementedHttpError('Unsupported PATCH payload for SPARQL conversion');\n }\n\n this.logger.debug(`Applying SPARQL PATCH to ${identifier.path}: ${sparqlUpdate}`);\n try {\n await accessor.executeSparqlUpdate(sparqlUpdate, identifier.path);\n } catch (error: unknown) {\n if (error instanceof DisabledSparqlFeatureError) {\n throw new ForbiddenHttpError(error.message, { cause: error });\n }\n if (error instanceof UnsupportedSparqlQueryError) {\n throw new BadRequestHttpError(error.message, { cause: error });\n }\n throw error;\n }\n\n // PATCH does not affect containment; mark the target resource as updated.\n const changes = new Map() as ChangeMap;\n changes.set(identifier, new RepresentationMetadata(identifier, { [SOLID_AS.activity]: AS.terms.Update }));\n return changes;\n }\n\n /**\n * 只处理 SPARQL UPDATE (application/sparql-update)。\n * N3 Patch 和其他类型返回 undefined,让 CSS PatchingStore 回退到 get-patch-set 逻辑。\n */\n private async toSparqlUpdate(patch: Patch, identifier: ResourceIdentifier): Promise<string | undefined> {\n // 只处理 SPARQL UPDATE,其他类型(包括 N3 Patch)回退到 CSS 默认处理\n if (!this.isSparqlUpdatePatch(patch)) {\n return undefined;\n }\n\n const updateText = await readableToString(patch.data);\n return this.normalizeGraphs(updateText, identifier);\n }\n\n /**\n * Ensure SPARQL UPDATE targets the resource graph (CSS stores documents in named graphs).\n */\n private normalizeGraphs(updateText: string, identifier: ResourceIdentifier): string | undefined {\n const graph = DataFactory.namedNode(identifier.path);\n const identifierStrategy = (this as unknown as { identifierStrategy: { supportsIdentifier: (id: ResourceIdentifier) => boolean }}).identifierStrategy;\n\n const assertGraphAllowed = (value: unknown): void => {\n if (!value || typeof value !== 'object') {\n return;\n }\n const term = value as { termType?: string; value?: string };\n if (term.termType === 'NamedNode' && term.value && !identifierStrategy.supportsIdentifier({ path: term.value })) {\n throw new BadRequestHttpError(`GRAPH ${term.value} is outside the configured identifier space.`);\n }\n };\n const wrapDefaultGraph = (text: string): string => {\n const insert = /INSERT\\s+DATA\\s*{\\s*([^}]*)}/is;\n const del = /DELETE\\s+DATA\\s*{\\s*([^}]*)}/is;\n const rewrite = (regex: RegExp, label: string, input: string): string =>\n input.replace(regex, (_match, body) => `${label} { GRAPH <${graph.value}> { ${body} } }`);\n let out = text;\n if (insert.test(out)) {\n out = rewrite(insert, 'INSERT DATA', out);\n }\n if (del.test(out)) {\n out = rewrite(del, 'DELETE DATA', out);\n }\n return out;\n };\n\n const rewriteTriples = (triples?: any[], targetGraph = graph): any[] => {\n if (!triples) return [];\n return triples.map((triple: any): any => ({\n ...triple,\n graph: (!triple.graph || triple.graph.termType === 'DefaultGraph') ? targetGraph : triple.graph,\n }));\n };\n\n const triplesFromTemplateBlock = (item: any): any[] => {\n if (Array.isArray(item?.triples)) {\n return item.triples;\n }\n if (!Array.isArray(item?.patterns)) {\n return [];\n }\n return item.patterns.flatMap((pattern: any): any[] =>\n pattern?.type === 'bgp' && Array.isArray(pattern.triples) ? pattern.triples : []);\n };\n\n const rewriteQuadBlocks = (items?: any[]): any[] | undefined => {\n if (!items) return items;\n return items.flatMap((item: any): any[] => {\n if (item?.type === 'graph') {\n assertGraphAllowed(item.name);\n const targetGraph = item.name ?? graph;\n return [{\n ...item,\n name: targetGraph,\n triples: rewriteTriples(triplesFromTemplateBlock(item), targetGraph),\n patterns: undefined,\n }];\n }\n if (item?.type === 'bgp') {\n return [{\n type: 'graph',\n name: graph,\n triples: rewriteTriples(item.triples, graph),\n }];\n }\n return [{\n type: 'graph',\n name: graph,\n triples: rewriteTriples([ item ], graph),\n }];\n });\n };\n\n const rewritePattern = (pattern: any): any => {\n if (pattern.type === 'bgp') {\n return { ...pattern, triples: rewriteTriples(pattern.triples, graph) };\n }\n if (pattern.type === 'graph') {\n assertGraphAllowed(pattern.name);\n return {\n ...pattern,\n name: pattern.name ?? graph,\n patterns: pattern.patterns?.map(rewritePattern) ?? [],\n };\n }\n if (pattern.type === 'group') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'optional') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'union') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'minus') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'filter') {\n return pattern; // FILTER doesn't contain triples, pass through\n }\n if (pattern.type === 'bind') {\n return pattern; // BIND doesn't contain triples, pass through\n }\n if (pattern.type === 'values') {\n return pattern; // VALUES doesn't contain triples, pass through\n }\n if (pattern.type === 'service') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n return pattern;\n };\n\n const rewriteWherePatterns = (patterns?: any[]): any[] =>\n (patterns ?? []).map((pattern: any): any => {\n if (pattern?.type === 'bgp') {\n return {\n type: 'graph',\n name: graph,\n patterns: [{\n ...pattern,\n triples: rewriteTriples(pattern.triples, graph),\n }],\n };\n }\n return rewritePattern(pattern);\n });\n\n const toGraphQuads = (items?: any[]): GraphQuads[] | undefined =>\n rewriteQuadBlocks(items) as GraphQuads[] | undefined;\n\n try {\n const parsed = this.parser.parse(updateText) as unknown as SparqlUpdate;\n\n // Explicitly reject SPARQL Queries (SELECT, ASK, CONSTRUCT) in PATCH\n if ((parsed as any).type === 'query') {\n this.logger.warn(`Received SPARQL Query in PATCH request for ${identifier.path}. SPARQL PATCH only supports UPDATE operations.`);\n return undefined;\n }\n\n const collect = (ops: any[], key: 'delete' | 'insert'): any[] =>\n ops.flatMap((op): any[] => {\n const entries = op[key];\n if (!entries) return [];\n if (Array.isArray(entries)) {\n return entries.flatMap((entry: any): any[] => {\n if (entry?.type === 'graph') {\n assertGraphAllowed(entry.name);\n return (entry.triples ?? []).map((triple: any): any => ({\n ...triple,\n graph: entry.name ?? graph,\n }));\n }\n return entry.triples ? entry.triples : (entry.quads ?? []);\n });\n }\n return [];\n });\n const deleteTriples = collect(parsed.updates as any[], 'delete');\n const insertTriples = collect(parsed.updates as any[], 'insert');\n const hasVariables = [...deleteTriples, ...insertTriples].some((t: any): boolean =>\n t.subject?.termType === 'Variable' || t.predicate?.termType === 'Variable' || t.object?.termType === 'Variable');\n\n const simpleOps = parsed.updates.every((op: any): boolean =>\n [ 'delete', 'insert', 'insertdelete', 'deleteinsert' ].includes(op.updateType) &&\n (!op.where || op.where.length === 0) &&\n !hasVariables);\n\n this.logger.debug(`[normalizeGraphs] simpleOps=${simpleOps}, hasVariables=${hasVariables}, deleteTriples=${deleteTriples.length}, insertTriples=${insertTriples.length}`);\n this.logger.debug(`[normalizeGraphs] updateTypes: ${parsed.updates.map((op: any) => op.updateType).join(', ')}`);\n\n if (simpleOps && deleteTriples.length + insertTriples.length > 0) {\n const termToString = (term: any): string => {\n if (term.termType === 'NamedNode') {\n return `<${term.value}>`;\n }\n if (term.termType === 'Literal') {\n // Escape special characters in literal values\n const hasQuotes = term.value.includes('\"');\n const hasNewlines = term.value.includes('\\n') || term.value.includes('\\r');\n\n let escaped: string;\n let useTripleQuotes = false;\n\n if (hasQuotes || hasNewlines) {\n // Use triple-quoted strings for values with quotes or newlines\n useTripleQuotes = true;\n escaped = term.value;\n // Escape triple-quote sequences\n escaped = escaped.replace(/\"\"\"/g, '\"\\\\\"\\\\\"\"');\n // Escape trailing quotes to avoid \"\"\"content\"\"\"\" sequences\n if (escaped.endsWith('\"')) {\n const match = escaped.match(/\"*$/);\n const trailingQuotes = match ? match[0].length : 0;\n if (trailingQuotes > 0) {\n escaped = escaped.slice(0, -trailingQuotes) + '\\\\\"'.repeat(trailingQuotes);\n }\n }\n } else {\n // Regular escaping for simple strings\n escaped = term.value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n }\n\n const quote = useTripleQuotes ? '\"\"\"' : '\"';\n\n // Handle language tags and datatypes\n if (term.language) {\n return `${quote}${escaped}${quote}@${term.language}`;\n }\n if (term.datatype && term.datatype.value !== 'http://www.w3.org/2001/XMLSchema#string') {\n return `${quote}${escaped}${quote}^^<${term.datatype.value}>`;\n }\n return `${quote}${escaped}${quote}`;\n }\n if (term.termType === 'BlankNode') {\n return `_:${term.value}`;\n }\n // Fallback for unknown term types\n return `<${term.value}>`;\n };\n const toTripleStr = (triples: any[]): string =>\n triples.map((t): string => `${termToString(t.subject)} ${termToString(t.predicate)} ${termToString(t.object)} .`).join(' ');\n let parts: string[] = [];\n if (deleteTriples.length > 0) {\n parts.push(`DELETE DATA { GRAPH <${graph.value}> { ${toTripleStr(deleteTriples)} } }`);\n }\n if (insertTriples.length > 0) {\n parts.push(`INSERT DATA { GRAPH <${graph.value}> { ${toTripleStr(insertTriples)} } }`);\n }\n const normalizedSimple = parts.join(';\\n');\n this.logger.verbose(`Normalized SPARQL UPDATE for ${identifier.path}: ${normalizedSimple}`);\n return normalizedSimple;\n }\n\n parsed.updates = parsed.updates.map((op: any): UpdateOperation => {\n switch (op.updateType) {\n case 'deletewhere':\n return {\n ...op,\n delete: toGraphQuads(op.delete),\n };\n case 'deleteinsert':\n case 'insertdelete':\n return {\n ...op,\n delete: toGraphQuads(op.delete),\n insert: toGraphQuads(op.insert),\n where: rewriteWherePatterns(op.where),\n };\n case 'delete':\n return {\n ...op,\n delete: toGraphQuads(op.delete),\n };\n case 'insert':\n return {\n ...op,\n insert: toGraphQuads(op.insert),\n };\n default:\n return op;\n }\n });\n const normalized = this.generator.stringify(parsed);\n this.logger.verbose(`Normalized SPARQL UPDATE for ${identifier.path}: ${normalized}`);\n return normalized;\n } catch (error: unknown) {\n if (HttpError.isInstance(error)) {\n throw error;\n }\n this.logger.debug(`Could not parse SPARQL UPDATE for ${identifier.path}; applying default graph text fallback: ${error}`);\n const fallbackResult = wrapDefaultGraph(updateText);\n return fallbackResult;\n }\n }\n\n private isSparqlUpdatePatch(patch: Patch): patch is SparqlUpdatePatch {\n return typeof (patch as SparqlUpdatePatch).algebra === 'object';\n }\n\n private isSparqlCapable(accessor: unknown): accessor is {\n executeSparqlUpdate: (query: string, baseIri?: string) => Promise<void>;\n getMetadata: (identifier: ResourceIdentifier) => Promise<RepresentationMetadata>;\n } {\n return typeof accessor === 'object' &&\n accessor !== null &&\n typeof (accessor as { executeSparqlUpdate?: unknown }).executeSparqlUpdate === 'function' &&\n typeof (accessor as { getMetadata?: unknown }).getMetadata === 'function';\n }\n\n public override async setRepresentation(identifier: ResourceIdentifier, representation: Representation, conditions?: Conditions): Promise<ChangeMap> {\n return super.setRepresentation(identifier, representation, conditions);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SparqlUpdateResourceStore.js","sourceRoot":"","sources":["../../src/storage/SparqlUpdateResourceStore.ts"],"names":[],"mappings":"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","sourcesContent":["import { DataFactory } from 'n3';\nimport { Generator as SparqlGenerator, Parser as SparqlParser, type GraphQuads, type UpdateOperation, type Update as SparqlUpdate } from 'sparqljs';\nimport {\n DataAccessorBasedStore,\n type ChangeMap,\n type ResourceIdentifier,\n type Patch,\n NotImplementedHttpError,\n type Conditions,\n NotFoundHttpError,\n RepresentationMetadata,\n AS,\n SOLID_AS,\n BadRequestHttpError,\n ForbiddenHttpError,\n HttpError,\n type DataAccessor,\n type IdentifierStrategy,\n type AuxiliaryStrategy,\n type Representation,\n} from '@solid/community-server';\nimport type { SparqlUpdatePatch } from '@solid/community-server';\nimport { readableToString } from '@solid/community-server/dist/util/StreamUtil';\nimport { getLoggerFor } from 'global-logger-factory';\nimport {\n LocalFirstRdfRepresentationResolver,\n type LocalFirstRdfRepresentationResolverLike,\n} from '../solidfs/LocalFirstRdfRepresentationResolver';\nimport { DisabledSparqlFeatureError, UnsupportedSparqlQueryError } from './rdf/RdfSparqlAdapter';\n\nexport interface SparqlUpdateResourceStoreOptions {\n accessor: DataAccessor;\n identifierStrategy: IdentifierStrategy;\n auxiliaryStrategy: AuxiliaryStrategy;\n metadataStrategy: AuxiliaryStrategy;\n localFirstRdfRepresentationResolver?: LocalFirstRdfRepresentationResolverLike;\n}\n\n/**\n * ResourceStore that short-circuits PATCH into direct SPARQL UPDATE\n * when the underlying DataAccessor supports it.\n */\nexport class SparqlUpdateResourceStore extends DataAccessorBasedStore {\n private readonly generator = new SparqlGenerator();\n private readonly parser = new SparqlParser();\n private readonly localFirstRdfRepresentationResolver: LocalFirstRdfRepresentationResolverLike;\n private readonly metadataAuxiliaryStrategy: AuxiliaryStrategy;\n protected override readonly logger = getLoggerFor(this);\n\n public constructor(options: SparqlUpdateResourceStoreOptions) {\n super(options.accessor, options.identifierStrategy, options.auxiliaryStrategy, options.metadataStrategy);\n this.metadataAuxiliaryStrategy = options.metadataStrategy;\n this.localFirstRdfRepresentationResolver = options.localFirstRdfRepresentationResolver ??\n new LocalFirstRdfRepresentationResolver({\n accessor: options.accessor,\n metadataStrategy: options.metadataStrategy,\n });\n // Check if identifierStrategy has baseUrl property (SingleRootIdentifierStrategy)\n const strategy = options.identifierStrategy as unknown as { baseUrl?: string };\n this.logger.info(`SparqlUpdateResourceStore initialized with identifierStrategy: ${options.identifierStrategy.constructor.name}, baseUrl: ${strategy.baseUrl ?? 'N/A'}`);\n }\n\n public override async getRepresentation(identifier: ResourceIdentifier): Promise<Representation> {\n const localRepresentation = await this.localFirstRdfRepresentationResolver.resolve(identifier);\n if (localRepresentation) {\n return localRepresentation;\n }\n\n return super.getRepresentation(identifier);\n }\n\n // @ts-expect-error Upstream signature returns never; we return ChangeMap for successful PATCH.\n public override async modifyResource(identifier: ResourceIdentifier, patch: Patch, conditions?: Conditions): Promise<ChangeMap> {\n this.logger.debug(`SparqlUpdateResourceStore.modifyResource called for ${identifier.path}`);\n this.logger.debug(`Patch has algebra: ${typeof (patch as SparqlUpdatePatch).algebra === 'object'}, metadata.contentType: ${patch.metadata?.contentType}`);\n\n const accessor = (this as unknown as { accessor: unknown }).accessor as unknown;\n if (!this.isSparqlCapable(accessor)) {\n this.logger.debug('Accessor is not SPARQL capable');\n throw new NotImplementedHttpError('SPARQL UPDATE not supported by this accessor');\n }\n\n // Keep the default condition validation semantics\n if (conditions) {\n let metadata: RepresentationMetadata | undefined;\n try {\n metadata = await accessor.getMetadata(identifier);\n } catch (error: unknown) {\n if (!NotFoundHttpError.isInstance(error)) {\n throw error;\n }\n }\n this.validateConditions(conditions, metadata);\n }\n\n if (this.metadataAuxiliaryStrategy.isAuxiliaryIdentifier(identifier)) {\n this.logger.debug(`Metadata PATCH for ${identifier.path} falls back to CSS metadata patcher`);\n throw new NotImplementedHttpError('Metadata resources must be patched by the CSS metadata patcher');\n }\n\n const sparqlUpdate = await this.toSparqlUpdate(patch, identifier);\n if (!sparqlUpdate) {\n this.logger.debug(`toSparqlUpdate returned undefined for ${identifier.path}, falling back to CSS handler`);\n throw new NotImplementedHttpError('Unsupported PATCH payload for SPARQL conversion');\n }\n\n this.logger.debug(`Applying SPARQL PATCH to ${identifier.path}: ${sparqlUpdate}`);\n try {\n await accessor.executeSparqlUpdate(sparqlUpdate, identifier.path);\n } catch (error: unknown) {\n if (error instanceof DisabledSparqlFeatureError) {\n throw new ForbiddenHttpError(error.message, { cause: error });\n }\n if (error instanceof UnsupportedSparqlQueryError) {\n throw new BadRequestHttpError(error.message, { cause: error });\n }\n throw error;\n }\n\n // PATCH does not affect containment; mark the target resource as updated.\n const changes = new Map() as ChangeMap;\n changes.set(identifier, new RepresentationMetadata(identifier, { [SOLID_AS.activity]: AS.terms.Update }));\n return changes;\n }\n\n /**\n * 只处理 SPARQL UPDATE (application/sparql-update)。\n * N3 Patch 和其他类型返回 undefined,让 CSS PatchingStore 回退到 get-patch-set 逻辑。\n */\n private async toSparqlUpdate(patch: Patch, identifier: ResourceIdentifier): Promise<string | undefined> {\n // 只处理 SPARQL UPDATE,其他类型(包括 N3 Patch)回退到 CSS 默认处理\n if (!this.isSparqlUpdatePatch(patch)) {\n return undefined;\n }\n\n const updateText = await readableToString(patch.data);\n return this.normalizeGraphs(updateText, identifier);\n }\n\n /**\n * Ensure SPARQL UPDATE targets the resource graph (CSS stores documents in named graphs).\n */\n private normalizeGraphs(updateText: string, identifier: ResourceIdentifier): string | undefined {\n const graph = DataFactory.namedNode(identifier.path);\n const identifierStrategy = (this as unknown as { identifierStrategy: { supportsIdentifier: (id: ResourceIdentifier) => boolean }}).identifierStrategy;\n\n const assertGraphAllowed = (value: unknown): void => {\n if (!value || typeof value !== 'object') {\n return;\n }\n const term = value as { termType?: string; value?: string };\n if (term.termType === 'NamedNode' && term.value && !identifierStrategy.supportsIdentifier({ path: term.value })) {\n throw new BadRequestHttpError(`GRAPH ${term.value} is outside the configured identifier space.`);\n }\n };\n const wrapDefaultGraph = (text: string): string => {\n const insert = /INSERT\\s+DATA\\s*{\\s*([^}]*)}/is;\n const del = /DELETE\\s+DATA\\s*{\\s*([^}]*)}/is;\n const rewrite = (regex: RegExp, label: string, input: string): string =>\n input.replace(regex, (_match, body) => `${label} { GRAPH <${graph.value}> { ${body} } }`);\n let out = text;\n if (insert.test(out)) {\n out = rewrite(insert, 'INSERT DATA', out);\n }\n if (del.test(out)) {\n out = rewrite(del, 'DELETE DATA', out);\n }\n return out;\n };\n\n const rewriteTriples = (triples?: any[], targetGraph = graph): any[] => {\n if (!triples) return [];\n return triples.map((triple: any): any => ({\n ...triple,\n graph: (!triple.graph || triple.graph.termType === 'DefaultGraph') ? targetGraph : triple.graph,\n }));\n };\n\n const triplesFromTemplateBlock = (item: any): any[] => {\n if (Array.isArray(item?.triples)) {\n return item.triples;\n }\n if (!Array.isArray(item?.patterns)) {\n return [];\n }\n return item.patterns.flatMap((pattern: any): any[] =>\n pattern?.type === 'bgp' && Array.isArray(pattern.triples) ? pattern.triples : []);\n };\n\n const rewriteQuadBlocks = (items?: any[]): any[] | undefined => {\n if (!items) return items;\n return items.flatMap((item: any): any[] => {\n if (item?.type === 'graph') {\n assertGraphAllowed(item.name);\n const targetGraph = item.name ?? graph;\n return [{\n ...item,\n name: targetGraph,\n triples: rewriteTriples(triplesFromTemplateBlock(item), targetGraph),\n patterns: undefined,\n }];\n }\n if (item?.type === 'bgp') {\n return [{\n type: 'graph',\n name: graph,\n triples: rewriteTriples(item.triples, graph),\n }];\n }\n return [{\n type: 'graph',\n name: graph,\n triples: rewriteTriples([ item ], graph),\n }];\n });\n };\n\n const rewritePattern = (pattern: any): any => {\n if (pattern.type === 'bgp') {\n return { ...pattern, triples: rewriteTriples(pattern.triples, graph) };\n }\n if (pattern.type === 'graph') {\n assertGraphAllowed(pattern.name);\n return {\n ...pattern,\n name: pattern.name ?? graph,\n patterns: pattern.patterns?.map(rewritePattern) ?? [],\n };\n }\n if (pattern.type === 'group') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'optional') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'union') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'minus') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'filter') {\n return pattern; // FILTER doesn't contain triples, pass through\n }\n if (pattern.type === 'bind') {\n return pattern; // BIND doesn't contain triples, pass through\n }\n if (pattern.type === 'values') {\n return pattern; // VALUES doesn't contain triples, pass through\n }\n if (pattern.type === 'service') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n return pattern;\n };\n\n const rewriteWherePatterns = (patterns?: any[]): any[] =>\n (patterns ?? []).map((pattern: any): any => {\n if (pattern?.type === 'bgp') {\n return {\n type: 'graph',\n name: graph,\n patterns: [{\n ...pattern,\n triples: rewriteTriples(pattern.triples, graph),\n }],\n };\n }\n return rewritePattern(pattern);\n });\n\n const toGraphQuads = (items?: any[]): GraphQuads[] | undefined =>\n rewriteQuadBlocks(items) as GraphQuads[] | undefined;\n\n try {\n const parsed = this.parser.parse(updateText) as unknown as SparqlUpdate;\n\n // Explicitly reject SPARQL Queries (SELECT, ASK, CONSTRUCT) in PATCH\n if ((parsed as any).type === 'query') {\n this.logger.warn(`Received SPARQL Query in PATCH request for ${identifier.path}. SPARQL PATCH only supports UPDATE operations.`);\n return undefined;\n }\n\n const collect = (ops: any[], key: 'delete' | 'insert'): any[] =>\n ops.flatMap((op): any[] => {\n const entries = op[key];\n if (!entries) return [];\n if (Array.isArray(entries)) {\n return entries.flatMap((entry: any): any[] => {\n if (entry?.type === 'graph') {\n assertGraphAllowed(entry.name);\n return (entry.triples ?? []).map((triple: any): any => ({\n ...triple,\n graph: entry.name ?? graph,\n }));\n }\n return entry.triples ? entry.triples : (entry.quads ?? []);\n });\n }\n return [];\n });\n const deleteTriples = collect(parsed.updates as any[], 'delete');\n const insertTriples = collect(parsed.updates as any[], 'insert');\n const hasVariables = [...deleteTriples, ...insertTriples].some((t: any): boolean =>\n t.subject?.termType === 'Variable' || t.predicate?.termType === 'Variable' || t.object?.termType === 'Variable');\n\n const simpleOps = parsed.updates.every((op: any): boolean =>\n [ 'delete', 'insert', 'insertdelete', 'deleteinsert' ].includes(op.updateType) &&\n (!op.where || op.where.length === 0) &&\n !hasVariables);\n\n this.logger.debug(`[normalizeGraphs] simpleOps=${simpleOps}, hasVariables=${hasVariables}, deleteTriples=${deleteTriples.length}, insertTriples=${insertTriples.length}`);\n this.logger.debug(`[normalizeGraphs] updateTypes: ${parsed.updates.map((op: any) => op.updateType).join(', ')}`);\n\n if (simpleOps && deleteTriples.length + insertTriples.length > 0) {\n const termToString = (term: any): string => {\n if (term.termType === 'NamedNode') {\n return `<${term.value}>`;\n }\n if (term.termType === 'Literal') {\n // Escape special characters in literal values\n const hasQuotes = term.value.includes('\"');\n const hasNewlines = term.value.includes('\\n') || term.value.includes('\\r');\n\n let escaped: string;\n let useTripleQuotes = false;\n\n if (hasQuotes || hasNewlines) {\n // Use triple-quoted strings for values with quotes or newlines\n useTripleQuotes = true;\n escaped = term.value;\n // Escape triple-quote sequences\n escaped = escaped.replace(/\"\"\"/g, '\"\\\\\"\\\\\"\"');\n // Escape trailing quotes to avoid \"\"\"content\"\"\"\" sequences\n if (escaped.endsWith('\"')) {\n const match = escaped.match(/\"*$/);\n const trailingQuotes = match ? match[0].length : 0;\n if (trailingQuotes > 0) {\n escaped = escaped.slice(0, -trailingQuotes) + '\\\\\"'.repeat(trailingQuotes);\n }\n }\n } else {\n // Regular escaping for simple strings\n escaped = term.value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n }\n\n const quote = useTripleQuotes ? '\"\"\"' : '\"';\n\n // Handle language tags and datatypes\n if (term.language) {\n return `${quote}${escaped}${quote}@${term.language}`;\n }\n if (term.datatype && term.datatype.value !== 'http://www.w3.org/2001/XMLSchema#string') {\n return `${quote}${escaped}${quote}^^<${term.datatype.value}>`;\n }\n return `${quote}${escaped}${quote}`;\n }\n if (term.termType === 'BlankNode') {\n return `_:${term.value}`;\n }\n // Fallback for unknown term types\n return `<${term.value}>`;\n };\n const toTripleStr = (triples: any[]): string =>\n triples.map((t): string => `${termToString(t.subject)} ${termToString(t.predicate)} ${termToString(t.object)} .`).join(' ');\n let parts: string[] = [];\n if (deleteTriples.length > 0) {\n parts.push(`DELETE DATA { GRAPH <${graph.value}> { ${toTripleStr(deleteTriples)} } }`);\n }\n if (insertTriples.length > 0) {\n parts.push(`INSERT DATA { GRAPH <${graph.value}> { ${toTripleStr(insertTriples)} } }`);\n }\n const normalizedSimple = parts.join(';\\n');\n this.logger.verbose(`Normalized SPARQL UPDATE for ${identifier.path}: ${normalizedSimple}`);\n return normalizedSimple;\n }\n\n parsed.updates = parsed.updates.map((op: any): UpdateOperation => {\n switch (op.updateType) {\n case 'deletewhere':\n return {\n ...op,\n delete: toGraphQuads(op.delete),\n };\n case 'deleteinsert':\n case 'insertdelete':\n return {\n ...op,\n delete: toGraphQuads(op.delete),\n insert: toGraphQuads(op.insert),\n where: rewriteWherePatterns(op.where),\n };\n case 'delete':\n return {\n ...op,\n delete: toGraphQuads(op.delete),\n };\n case 'insert':\n return {\n ...op,\n insert: toGraphQuads(op.insert),\n };\n default:\n return op;\n }\n });\n const normalized = this.generator.stringify(parsed);\n this.logger.verbose(`Normalized SPARQL UPDATE for ${identifier.path}: ${normalized}`);\n return normalized;\n } catch (error: unknown) {\n if (HttpError.isInstance(error)) {\n throw error;\n }\n this.logger.debug(`Could not parse SPARQL UPDATE for ${identifier.path}; applying default graph text fallback: ${error}`);\n const fallbackResult = wrapDefaultGraph(updateText);\n return fallbackResult;\n }\n }\n\n private isSparqlUpdatePatch(patch: Patch): patch is SparqlUpdatePatch {\n return typeof (patch as SparqlUpdatePatch).algebra === 'object';\n }\n\n private isSparqlCapable(accessor: unknown): accessor is {\n executeSparqlUpdate: (query: string, baseIri?: string) => Promise<void>;\n getMetadata: (identifier: ResourceIdentifier) => Promise<RepresentationMetadata>;\n } {\n return typeof accessor === 'object' &&\n accessor !== null &&\n typeof (accessor as { executeSparqlUpdate?: unknown }).executeSparqlUpdate === 'function' &&\n typeof (accessor as { getMetadata?: unknown }).getMetadata === 'function';\n }\n\n public override async setRepresentation(identifier: ResourceIdentifier, representation: Representation, conditions?: Conditions): Promise<ChangeMap> {\n return super.setRepresentation(identifier, representation, conditions);\n }\n}\n"]}
|
|
@@ -56,6 +56,10 @@
|
|
|
56
56
|
"@id": "undefineds:dist/storage/SparqlUpdateResourceStore.jsonld#SparqlUpdateResourceStore__member_localFirstRdfRepresentationResolver",
|
|
57
57
|
"memberFieldName": "localFirstRdfRepresentationResolver"
|
|
58
58
|
},
|
|
59
|
+
{
|
|
60
|
+
"@id": "undefineds:dist/storage/SparqlUpdateResourceStore.jsonld#SparqlUpdateResourceStore__member_metadataAuxiliaryStrategy",
|
|
61
|
+
"memberFieldName": "metadataAuxiliaryStrategy"
|
|
62
|
+
},
|
|
59
63
|
{
|
|
60
64
|
"@id": "undefineds:dist/storage/SparqlUpdateResourceStore.jsonld#SparqlUpdateResourceStore__member_logger",
|
|
61
65
|
"memberFieldName": "logger",
|
|
@@ -207,8 +207,8 @@ class VectorIndexingListener {
|
|
|
207
207
|
try {
|
|
208
208
|
// Credential -> Provider 关联,从 Provider 获取 baseUrl 和 proxyUrl
|
|
209
209
|
const query = `
|
|
210
|
-
PREFIX cred: <${models_1.
|
|
211
|
-
PREFIX ai: <${models_1.
|
|
210
|
+
PREFIX cred: <${models_1.UDFS.NAMESPACE}>
|
|
211
|
+
PREFIX ai: <${models_1.UDFS.NAMESPACE}>
|
|
212
212
|
SELECT ?apiKey ?baseUrl ?provider ?proxyUrl WHERE {
|
|
213
213
|
?cred a cred:Credential ;
|
|
214
214
|
cred:service "ai" ;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VectorIndexingListener.js","sourceRoot":"","sources":["../../../src/storage/vector/VectorIndexingListener.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * VectorIndexingListener - 向量索引监听器\n *\n * 监听资源变更事件,自动触发向量索引更新。\n *\n * 工作流程:\n * 1. 收到资源变更事件\n * 2. 检查资源是否在某个 VectorStore 的 scope 内\n * 3. 如果是,读取资源内容,生成 embedding,存入向量库\n */\n\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { ResourceChangeEvent, ResourceChangeListener } from '../ObservableResourceStore';\nimport type { VectorStore } from '../vector/VectorStore';\nimport type { EmbeddingService } from '../../ai/service/EmbeddingService';\nimport type { SparqlEngine } from '../sparql/SubgraphQueryEngine';\nimport type { AiCredential } from '../../ai/service/types';\nimport type { ResourceStore, RepresentationPreferences } from '@solid/community-server';\nimport { XPOD_AI, XPOD_CREDENTIAL, normalizeAIConfigProviderId } from '@undefineds.co/models';\n\n/**\n * VectorStore 定义(从 RDF 读取)\n */\nexport interface VectorStoreDefinition {\n /** VectorStore resource */\n resource: string;\n /** 索引范围(Container resource) */\n scope: string;\n /** embedding 模型 */\n model: string;\n /** 状态 */\n status: 'active' | 'paused';\n /** 分块大小 */\n chunkSize?: number;\n /** 分块重叠 */\n chunkOverlap?: number;\n}\n\nexport interface VectorIndexingListenerOptions {\n /** SPARQL 引擎(用于查询 VectorStore 定义和 AI 凭据) */\n sparqlEngine: SparqlEngine;\n /** 向量存储 */\n vectorStore: VectorStore;\n /** Embedding 服务 */\n embeddingService: EmbeddingService;\n /** 资源存储(用于读取资源内容) */\n resourceStore: ResourceStore;\n /** 默认 embedding 模型 */\n defaultModel?: string;\n /** 支持的文件扩展名 */\n supportedExtensions?: string[];\n}\n\n/**\n * VectorIndexingListener - 自动向量索引\n */\nexport class VectorIndexingListener implements ResourceChangeListener {\n protected readonly logger = getLoggerFor(this);\n\n private readonly sparqlEngine: SparqlEngine;\n private readonly vectorStore: VectorStore;\n private readonly embeddingService: EmbeddingService;\n private readonly resourceStore: ResourceStore;\n private readonly defaultModel: string;\n private readonly supportedExtensions: Set<string>;\n\n // 缓存 VectorStore 定义,避免频繁查询\n private vectorStoreCache = new Map<string, VectorStoreDefinition[]>();\n private cacheExpiry = 0;\n private readonly cacheTtlMs = 60000; // 1 分钟缓存\n\n public constructor(options: VectorIndexingListenerOptions) {\n this.sparqlEngine = options.sparqlEngine;\n this.vectorStore = options.vectorStore;\n this.embeddingService = options.embeddingService;\n this.resourceStore = options.resourceStore;\n this.defaultModel = options.defaultModel ?? 'text-embedding-004';\n this.supportedExtensions = new Set(\n options.supportedExtensions ?? ['.txt', '.md', '.html', '.json', '.ttl', '.jsonld'],\n );\n }\n\n /**\n * 处理资源变更事件\n */\n public async onResourceChanged(event: ResourceChangeEvent): Promise<void> {\n const { path, action, isContainer } = event;\n\n // 跳过容器变更\n if (isContainer) {\n this.logger.debug(`Skipping container: ${path}`);\n return;\n }\n\n // 检查文件扩展名\n if (!this.isSupportedFile(path)) {\n this.logger.debug(`Skipping unsupported file type: ${path}`);\n return;\n }\n\n // 获取 Pod base URL\n const podBaseUrl = this.getPodBaseUrl(path);\n if (!podBaseUrl) {\n this.logger.debug(`Cannot determine pod base URL for: ${path}`);\n return;\n }\n\n // 如果是 VectorStore 配置文件或 Credential 配置文件更新,清除缓存\n if (path.includes('vector-stores') || path.includes('credentials')) {\n this.logger.debug(`Configuration file updated, clearing cache for ${podBaseUrl}`);\n this.vectorStoreCache.delete(podBaseUrl);\n // 配置文件本身不需要索引,直接返回\n return;\n }\n\n try {\n // 查找覆盖此路径的 VectorStore\n const vectorStores = await this.findVectorStoresForPath(path, podBaseUrl);\n if (vectorStores.length === 0) {\n this.logger.debug(`No VectorStore configured for: ${path}`);\n return;\n }\n\n this.logger.info(`Processing ${action} for ${path}, matched ${vectorStores.length} VectorStore(s)`);\n\n // 根据 action 执行索引操作\n if (action === 'delete') {\n await this.handleDelete(path, vectorStores);\n } else {\n await this.handleCreateOrUpdate(path, podBaseUrl, vectorStores);\n }\n } catch (error) {\n this.logger.error(`Failed to process ${action} for ${path}: ${error}`);\n }\n }\n\n /**\n * 处理删除操作\n */\n private async handleDelete(path: string, vectorStores: VectorStoreDefinition[]): Promise<void> {\n const vectorId = this.pathToVectorId(path);\n\n for (const vs of vectorStores) {\n try {\n await this.vectorStore.deleteVector(vs.model, vectorId);\n this.logger.info(`Deleted vector for ${path} from model ${vs.model}`);\n } catch (error) {\n this.logger.error(`Failed to delete vector for ${path}: ${error}`);\n }\n }\n }\n\n /**\n * 处理创建或更新操作\n */\n private async handleCreateOrUpdate(\n path: string,\n podBaseUrl: string,\n vectorStores: VectorStoreDefinition[],\n ): Promise<void> {\n // 读取资源内容\n const content = await this.getResourceContent(path);\n if (!content || content.trim().length === 0) {\n this.logger.debug(`Empty content for ${path}, skipping`);\n return;\n }\n\n // 获取 AI 凭据\n const credential = await this.getAiCredential(podBaseUrl);\n if (!credential) {\n this.logger.warn(`No AI credential found for ${podBaseUrl}, skipping indexing`);\n return;\n }\n\n // 为每个 VectorStore 生成 embedding 并存储\n // 注意:如果多个 VectorStore 使用相同的 model,只需要生成一次 embedding\n const modelEmbeddings = new Map<string, number[]>();\n\n for (const vs of vectorStores) {\n if (vs.status !== 'active') {\n this.logger.debug(`VectorStore ${vs.resource} is ${vs.status}, skipping`);\n continue;\n }\n\n const model = vs.model || this.defaultModel;\n\n try {\n // 检查是否已经生成过这个 model 的 embedding\n let embedding = modelEmbeddings.get(model);\n if (!embedding) {\n embedding = await this.embeddingService.embed(content, credential, model);\n modelEmbeddings.set(model, embedding);\n }\n\n // 确保向量表存在\n await this.vectorStore.ensureVectorTable(model);\n\n // 存储向量\n const vectorId = this.pathToVectorId(path);\n await this.vectorStore.upsertVector(model, vectorId, embedding);\n\n this.logger.info(`Indexed ${path} to model ${model}, vectorId=${vectorId}`);\n } catch (error) {\n this.logger.error(`Failed to index ${path} to model ${model}: ${error}`);\n }\n }\n }\n\n /**\n * 查找覆盖指定路径的 VectorStore\n */\n private async findVectorStoresForPath(\n path: string,\n podBaseUrl: string,\n ): Promise<VectorStoreDefinition[]> {\n const allStores = await this.getVectorStoreDefinitions(podBaseUrl);\n\n return allStores.filter((vs) => {\n // 检查 path 是否在 scope 内\n const scope = vs.scope.endsWith('/') ? vs.scope : `${vs.scope}/`;\n return path.startsWith(scope);\n });\n }\n\n /**\n * 获取 Pod 的所有 VectorStore 定义\n */\n private async getVectorStoreDefinitions(podBaseUrl: string): Promise<VectorStoreDefinition[]> {\n // 检查缓存\n if (Date.now() < this.cacheExpiry && this.vectorStoreCache.has(podBaseUrl)) {\n return this.vectorStoreCache.get(podBaseUrl)!;\n }\n\n try {\n // 使用 undefineds.co/ns# 命名空间,与 drizzle-solid schema 一致\n const query = `\n PREFIX udfs: <https://undefineds.co/ns#>\n SELECT ?vs ?scope ?model ?status ?chunkSize ?chunkOverlap WHERE {\n ?vs a udfs:VectorStore ;\n udfs:container ?scope .\n OPTIONAL { ?vs udfs:chunkingStrategy ?model }\n OPTIONAL { ?vs udfs:status ?status }\n OPTIONAL { ?vs udfs:chunkSize ?chunkSize }\n OPTIONAL { ?vs udfs:chunkOverlap ?chunkOverlap }\n }\n `;\n\n const bindingsStream = await this.sparqlEngine.queryBindings(query, podBaseUrl);\n const definitions: VectorStoreDefinition[] = [];\n\n for await (const binding of bindingsStream) {\n const vs = binding.get('vs');\n const scope = binding.get('scope');\n const model = binding.get('model');\n const status = binding.get('status');\n const chunkSize = binding.get('chunkSize');\n const chunkOverlap = binding.get('chunkOverlap');\n\n if (vs && scope) {\n definitions.push({\n resource: vs.value,\n scope: this.resolveResource(scope.value, podBaseUrl),\n model: model?.value || this.defaultModel,\n status: (status?.value as 'active' | 'paused') || 'active',\n chunkSize: chunkSize ? parseInt(chunkSize.value, 10) : undefined,\n chunkOverlap: chunkOverlap ? parseInt(chunkOverlap.value, 10) : undefined,\n });\n }\n }\n\n // 更新缓存\n this.vectorStoreCache.set(podBaseUrl, definitions);\n this.cacheExpiry = Date.now() + this.cacheTtlMs;\n\n this.logger.debug(`Found ${definitions.length} VectorStore(s) for ${podBaseUrl}`);\n return definitions;\n } catch (error) {\n this.logger.error(`Failed to query VectorStore definitions: ${error}`);\n return [];\n }\n }\n\n /**\n * 获取 AI 凭据\n */\n private async getAiCredential(podBaseUrl: string): Promise<AiCredential | null> {\n try {\n // Credential -> Provider 关联,从 Provider 获取 baseUrl 和 proxyUrl\n const query = `\n PREFIX cred: <${XPOD_CREDENTIAL.NAMESPACE}>\n PREFIX ai: <${XPOD_AI.NAMESPACE}>\n SELECT ?apiKey ?baseUrl ?provider ?proxyUrl WHERE {\n ?cred a cred:Credential ;\n cred:service \"ai\" ;\n cred:status \"active\" ;\n cred:apiKey ?apiKey .\n OPTIONAL { ?cred cred:provider ?provider }\n OPTIONAL { \n ?cred cred:provider ?provider .\n ?provider ai:baseUrl ?baseUrl .\n }\n OPTIONAL { \n ?cred cred:provider ?provider .\n ?provider ai:proxyUrl ?proxyUrl .\n }\n } LIMIT 1\n `;\n\n const bindingsStream = await this.sparqlEngine.queryBindings(query, podBaseUrl);\n\n for await (const binding of bindingsStream) {\n const apiKey = binding.get('apiKey');\n const baseUrl = binding.get('baseUrl');\n const provider = binding.get('provider');\n const proxyUrl = binding.get('proxyUrl');\n\n if (apiKey) {\n const providerName = normalizeAIConfigProviderId(provider?.value || 'google') || 'google';\n \n return {\n apiKey: apiKey.value,\n baseUrl: baseUrl?.value,\n provider: providerName,\n proxyUrl: proxyUrl?.value,\n };\n }\n }\n\n return null;\n } catch (error) {\n this.logger.error(`Failed to query AI credential: ${error}`);\n return null;\n }\n }\n\n /**\n * 读取资源内容\n */\n private async getResourceContent(path: string): Promise<string | null> {\n try {\n const preferences: RepresentationPreferences = {\n type: { 'text/plain': 1, 'text/markdown': 0.9, 'text/turtle': 0.8, '*/*': 0.1 },\n };\n\n const representation = await this.resourceStore.getRepresentation({ path }, preferences);\n const chunks: Buffer[] = [];\n\n for await (const chunk of representation.data) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n\n return Buffer.concat(chunks).toString('utf-8');\n } catch (error) {\n this.logger.error(`Failed to read resource ${path}: ${error}`);\n return null;\n }\n }\n\n /**\n * 检查是否为支持的文件类型\n */\n private isSupportedFile(path: string): boolean {\n const ext = this.getExtension(path);\n return this.supportedExtensions.has(ext);\n }\n\n /**\n * 获取文件扩展名\n */\n private getExtension(path: string): string {\n const lastDot = path.lastIndexOf('.');\n if (lastDot === -1) return '';\n return path.slice(lastDot).toLowerCase();\n }\n\n /**\n * 从路径提取 Pod base URL\n */\n private getPodBaseUrl(path: string): string | null {\n // 假设路径格式为 /username/... 或 https://pod.example.com/username/...\n try {\n const url = new URL(path, 'http://localhost');\n const parts = url.pathname.split('/').filter(Boolean);\n if (parts.length > 0) {\n return `${url.origin}/${parts[0]}/`;\n }\n } catch {\n // 相对路径\n const parts = path.split('/').filter(Boolean);\n if (parts.length > 0) {\n return `/${parts[0]}/`;\n }\n }\n return null;\n }\n\n /**\n * 解析相对资源引用\n */\n private resolveResource(resource: string, baseUrl: string): string {\n if (resource.startsWith('http://') || resource.startsWith('https://')) {\n return resource;\n }\n if (resource.startsWith('/')) {\n try {\n const base = new URL(baseUrl);\n return `${base.origin}${resource}`;\n } catch {\n return resource;\n }\n }\n return `${baseUrl}${resource}`;\n }\n\n /**\n * 将路径转换为向量 ID(使用 hash)\n */\n private pathToVectorId(path: string): number {\n let hash = 2166136261; // FNV offset basis\n for (let i = 0; i < path.length; i++) {\n hash ^= path.charCodeAt(i);\n hash = Math.imul(hash, 16777619); // FNV prime\n }\n return Math.abs(hash);\n }\n\n /**\n * 清除缓存\n */\n public clearCache(): void {\n this.vectorStoreCache.clear();\n this.cacheExpiry = 0;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"VectorIndexingListener.js","sourceRoot":"","sources":["../../../src/storage/vector/VectorIndexingListener.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * VectorIndexingListener - 向量索引监听器\n *\n * 监听资源变更事件,自动触发向量索引更新。\n *\n * 工作流程:\n * 1. 收到资源变更事件\n * 2. 检查资源是否在某个 VectorStore 的 scope 内\n * 3. 如果是,读取资源内容,生成 embedding,存入向量库\n */\n\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { ResourceChangeEvent, ResourceChangeListener } from '../ObservableResourceStore';\nimport type { VectorStore } from '../vector/VectorStore';\nimport type { EmbeddingService } from '../../ai/service/EmbeddingService';\nimport type { SparqlEngine } from '../sparql/SubgraphQueryEngine';\nimport type { AiCredential } from '../../ai/service/types';\nimport type { ResourceStore, RepresentationPreferences } from '@solid/community-server';\nimport { UDFS, normalizeAIConfigProviderId } from '@undefineds.co/models';\n\n/**\n * VectorStore 定义(从 RDF 读取)\n */\nexport interface VectorStoreDefinition {\n /** VectorStore resource */\n resource: string;\n /** 索引范围(Container resource) */\n scope: string;\n /** embedding 模型 */\n model: string;\n /** 状态 */\n status: 'active' | 'paused';\n /** 分块大小 */\n chunkSize?: number;\n /** 分块重叠 */\n chunkOverlap?: number;\n}\n\nexport interface VectorIndexingListenerOptions {\n /** SPARQL 引擎(用于查询 VectorStore 定义和 AI 凭据) */\n sparqlEngine: SparqlEngine;\n /** 向量存储 */\n vectorStore: VectorStore;\n /** Embedding 服务 */\n embeddingService: EmbeddingService;\n /** 资源存储(用于读取资源内容) */\n resourceStore: ResourceStore;\n /** 默认 embedding 模型 */\n defaultModel?: string;\n /** 支持的文件扩展名 */\n supportedExtensions?: string[];\n}\n\n/**\n * VectorIndexingListener - 自动向量索引\n */\nexport class VectorIndexingListener implements ResourceChangeListener {\n protected readonly logger = getLoggerFor(this);\n\n private readonly sparqlEngine: SparqlEngine;\n private readonly vectorStore: VectorStore;\n private readonly embeddingService: EmbeddingService;\n private readonly resourceStore: ResourceStore;\n private readonly defaultModel: string;\n private readonly supportedExtensions: Set<string>;\n\n // 缓存 VectorStore 定义,避免频繁查询\n private vectorStoreCache = new Map<string, VectorStoreDefinition[]>();\n private cacheExpiry = 0;\n private readonly cacheTtlMs = 60000; // 1 分钟缓存\n\n public constructor(options: VectorIndexingListenerOptions) {\n this.sparqlEngine = options.sparqlEngine;\n this.vectorStore = options.vectorStore;\n this.embeddingService = options.embeddingService;\n this.resourceStore = options.resourceStore;\n this.defaultModel = options.defaultModel ?? 'text-embedding-004';\n this.supportedExtensions = new Set(\n options.supportedExtensions ?? ['.txt', '.md', '.html', '.json', '.ttl', '.jsonld'],\n );\n }\n\n /**\n * 处理资源变更事件\n */\n public async onResourceChanged(event: ResourceChangeEvent): Promise<void> {\n const { path, action, isContainer } = event;\n\n // 跳过容器变更\n if (isContainer) {\n this.logger.debug(`Skipping container: ${path}`);\n return;\n }\n\n // 检查文件扩展名\n if (!this.isSupportedFile(path)) {\n this.logger.debug(`Skipping unsupported file type: ${path}`);\n return;\n }\n\n // 获取 Pod base URL\n const podBaseUrl = this.getPodBaseUrl(path);\n if (!podBaseUrl) {\n this.logger.debug(`Cannot determine pod base URL for: ${path}`);\n return;\n }\n\n // 如果是 VectorStore 配置文件或 Credential 配置文件更新,清除缓存\n if (path.includes('vector-stores') || path.includes('credentials')) {\n this.logger.debug(`Configuration file updated, clearing cache for ${podBaseUrl}`);\n this.vectorStoreCache.delete(podBaseUrl);\n // 配置文件本身不需要索引,直接返回\n return;\n }\n\n try {\n // 查找覆盖此路径的 VectorStore\n const vectorStores = await this.findVectorStoresForPath(path, podBaseUrl);\n if (vectorStores.length === 0) {\n this.logger.debug(`No VectorStore configured for: ${path}`);\n return;\n }\n\n this.logger.info(`Processing ${action} for ${path}, matched ${vectorStores.length} VectorStore(s)`);\n\n // 根据 action 执行索引操作\n if (action === 'delete') {\n await this.handleDelete(path, vectorStores);\n } else {\n await this.handleCreateOrUpdate(path, podBaseUrl, vectorStores);\n }\n } catch (error) {\n this.logger.error(`Failed to process ${action} for ${path}: ${error}`);\n }\n }\n\n /**\n * 处理删除操作\n */\n private async handleDelete(path: string, vectorStores: VectorStoreDefinition[]): Promise<void> {\n const vectorId = this.pathToVectorId(path);\n\n for (const vs of vectorStores) {\n try {\n await this.vectorStore.deleteVector(vs.model, vectorId);\n this.logger.info(`Deleted vector for ${path} from model ${vs.model}`);\n } catch (error) {\n this.logger.error(`Failed to delete vector for ${path}: ${error}`);\n }\n }\n }\n\n /**\n * 处理创建或更新操作\n */\n private async handleCreateOrUpdate(\n path: string,\n podBaseUrl: string,\n vectorStores: VectorStoreDefinition[],\n ): Promise<void> {\n // 读取资源内容\n const content = await this.getResourceContent(path);\n if (!content || content.trim().length === 0) {\n this.logger.debug(`Empty content for ${path}, skipping`);\n return;\n }\n\n // 获取 AI 凭据\n const credential = await this.getAiCredential(podBaseUrl);\n if (!credential) {\n this.logger.warn(`No AI credential found for ${podBaseUrl}, skipping indexing`);\n return;\n }\n\n // 为每个 VectorStore 生成 embedding 并存储\n // 注意:如果多个 VectorStore 使用相同的 model,只需要生成一次 embedding\n const modelEmbeddings = new Map<string, number[]>();\n\n for (const vs of vectorStores) {\n if (vs.status !== 'active') {\n this.logger.debug(`VectorStore ${vs.resource} is ${vs.status}, skipping`);\n continue;\n }\n\n const model = vs.model || this.defaultModel;\n\n try {\n // 检查是否已经生成过这个 model 的 embedding\n let embedding = modelEmbeddings.get(model);\n if (!embedding) {\n embedding = await this.embeddingService.embed(content, credential, model);\n modelEmbeddings.set(model, embedding);\n }\n\n // 确保向量表存在\n await this.vectorStore.ensureVectorTable(model);\n\n // 存储向量\n const vectorId = this.pathToVectorId(path);\n await this.vectorStore.upsertVector(model, vectorId, embedding);\n\n this.logger.info(`Indexed ${path} to model ${model}, vectorId=${vectorId}`);\n } catch (error) {\n this.logger.error(`Failed to index ${path} to model ${model}: ${error}`);\n }\n }\n }\n\n /**\n * 查找覆盖指定路径的 VectorStore\n */\n private async findVectorStoresForPath(\n path: string,\n podBaseUrl: string,\n ): Promise<VectorStoreDefinition[]> {\n const allStores = await this.getVectorStoreDefinitions(podBaseUrl);\n\n return allStores.filter((vs) => {\n // 检查 path 是否在 scope 内\n const scope = vs.scope.endsWith('/') ? vs.scope : `${vs.scope}/`;\n return path.startsWith(scope);\n });\n }\n\n /**\n * 获取 Pod 的所有 VectorStore 定义\n */\n private async getVectorStoreDefinitions(podBaseUrl: string): Promise<VectorStoreDefinition[]> {\n // 检查缓存\n if (Date.now() < this.cacheExpiry && this.vectorStoreCache.has(podBaseUrl)) {\n return this.vectorStoreCache.get(podBaseUrl)!;\n }\n\n try {\n // 使用 undefineds.co/ns# 命名空间,与 drizzle-solid schema 一致\n const query = `\n PREFIX udfs: <https://undefineds.co/ns#>\n SELECT ?vs ?scope ?model ?status ?chunkSize ?chunkOverlap WHERE {\n ?vs a udfs:VectorStore ;\n udfs:container ?scope .\n OPTIONAL { ?vs udfs:chunkingStrategy ?model }\n OPTIONAL { ?vs udfs:status ?status }\n OPTIONAL { ?vs udfs:chunkSize ?chunkSize }\n OPTIONAL { ?vs udfs:chunkOverlap ?chunkOverlap }\n }\n `;\n\n const bindingsStream = await this.sparqlEngine.queryBindings(query, podBaseUrl);\n const definitions: VectorStoreDefinition[] = [];\n\n for await (const binding of bindingsStream) {\n const vs = binding.get('vs');\n const scope = binding.get('scope');\n const model = binding.get('model');\n const status = binding.get('status');\n const chunkSize = binding.get('chunkSize');\n const chunkOverlap = binding.get('chunkOverlap');\n\n if (vs && scope) {\n definitions.push({\n resource: vs.value,\n scope: this.resolveResource(scope.value, podBaseUrl),\n model: model?.value || this.defaultModel,\n status: (status?.value as 'active' | 'paused') || 'active',\n chunkSize: chunkSize ? parseInt(chunkSize.value, 10) : undefined,\n chunkOverlap: chunkOverlap ? parseInt(chunkOverlap.value, 10) : undefined,\n });\n }\n }\n\n // 更新缓存\n this.vectorStoreCache.set(podBaseUrl, definitions);\n this.cacheExpiry = Date.now() + this.cacheTtlMs;\n\n this.logger.debug(`Found ${definitions.length} VectorStore(s) for ${podBaseUrl}`);\n return definitions;\n } catch (error) {\n this.logger.error(`Failed to query VectorStore definitions: ${error}`);\n return [];\n }\n }\n\n /**\n * 获取 AI 凭据\n */\n private async getAiCredential(podBaseUrl: string): Promise<AiCredential | null> {\n try {\n // Credential -> Provider 关联,从 Provider 获取 baseUrl 和 proxyUrl\n const query = `\n PREFIX cred: <${UDFS.NAMESPACE}>\n PREFIX ai: <${UDFS.NAMESPACE}>\n SELECT ?apiKey ?baseUrl ?provider ?proxyUrl WHERE {\n ?cred a cred:Credential ;\n cred:service \"ai\" ;\n cred:status \"active\" ;\n cred:apiKey ?apiKey .\n OPTIONAL { ?cred cred:provider ?provider }\n OPTIONAL { \n ?cred cred:provider ?provider .\n ?provider ai:baseUrl ?baseUrl .\n }\n OPTIONAL { \n ?cred cred:provider ?provider .\n ?provider ai:proxyUrl ?proxyUrl .\n }\n } LIMIT 1\n `;\n\n const bindingsStream = await this.sparqlEngine.queryBindings(query, podBaseUrl);\n\n for await (const binding of bindingsStream) {\n const apiKey = binding.get('apiKey');\n const baseUrl = binding.get('baseUrl');\n const provider = binding.get('provider');\n const proxyUrl = binding.get('proxyUrl');\n\n if (apiKey) {\n const providerName = normalizeAIConfigProviderId(provider?.value || 'google') || 'google';\n \n return {\n apiKey: apiKey.value,\n baseUrl: baseUrl?.value,\n provider: providerName,\n proxyUrl: proxyUrl?.value,\n };\n }\n }\n\n return null;\n } catch (error) {\n this.logger.error(`Failed to query AI credential: ${error}`);\n return null;\n }\n }\n\n /**\n * 读取资源内容\n */\n private async getResourceContent(path: string): Promise<string | null> {\n try {\n const preferences: RepresentationPreferences = {\n type: { 'text/plain': 1, 'text/markdown': 0.9, 'text/turtle': 0.8, '*/*': 0.1 },\n };\n\n const representation = await this.resourceStore.getRepresentation({ path }, preferences);\n const chunks: Buffer[] = [];\n\n for await (const chunk of representation.data) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n\n return Buffer.concat(chunks).toString('utf-8');\n } catch (error) {\n this.logger.error(`Failed to read resource ${path}: ${error}`);\n return null;\n }\n }\n\n /**\n * 检查是否为支持的文件类型\n */\n private isSupportedFile(path: string): boolean {\n const ext = this.getExtension(path);\n return this.supportedExtensions.has(ext);\n }\n\n /**\n * 获取文件扩展名\n */\n private getExtension(path: string): string {\n const lastDot = path.lastIndexOf('.');\n if (lastDot === -1) return '';\n return path.slice(lastDot).toLowerCase();\n }\n\n /**\n * 从路径提取 Pod base URL\n */\n private getPodBaseUrl(path: string): string | null {\n // 假设路径格式为 /username/... 或 https://pod.example.com/username/...\n try {\n const url = new URL(path, 'http://localhost');\n const parts = url.pathname.split('/').filter(Boolean);\n if (parts.length > 0) {\n return `${url.origin}/${parts[0]}/`;\n }\n } catch {\n // 相对路径\n const parts = path.split('/').filter(Boolean);\n if (parts.length > 0) {\n return `/${parts[0]}/`;\n }\n }\n return null;\n }\n\n /**\n * 解析相对资源引用\n */\n private resolveResource(resource: string, baseUrl: string): string {\n if (resource.startsWith('http://') || resource.startsWith('https://')) {\n return resource;\n }\n if (resource.startsWith('/')) {\n try {\n const base = new URL(baseUrl);\n return `${base.origin}${resource}`;\n } catch {\n return resource;\n }\n }\n return `${baseUrl}${resource}`;\n }\n\n /**\n * 将路径转换为向量 ID(使用 hash)\n */\n private pathToVectorId(path: string): number {\n let hash = 2166136261; // FNV offset basis\n for (let i = 0; i < path.length; i++) {\n hash ^= path.charCodeAt(i);\n hash = Math.imul(hash, 16777619); // FNV prime\n }\n return Math.abs(hash);\n }\n\n /**\n * 清除缓存\n */\n public clearCache(): void {\n this.vectorStoreCache.clear();\n this.cacheExpiry = 0;\n }\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PodTable } from './schema';
|
|
2
|
+
type ExactRecordTarget = string | Record<string, unknown> | null | undefined;
|
|
3
|
+
type ExactRecordResolvedTarget = string | Record<string, unknown>;
|
|
4
|
+
type ExactPodTable = PodTable<any>;
|
|
5
|
+
export type ExactRecordDatabase = {
|
|
6
|
+
findByResource?: <TResource extends ExactPodTable>(resource: TResource, target: ExactRecordResolvedTarget) => Promise<unknown | null>;
|
|
7
|
+
updateByResource?: <TResource extends ExactPodTable>(resource: TResource, target: ExactRecordResolvedTarget, data: any) => Promise<unknown | null>;
|
|
8
|
+
deleteByResource?: <TResource extends ExactPodTable>(resource: TResource, target: ExactRecordResolvedTarget) => Promise<unknown>;
|
|
9
|
+
insert?: <TResource extends ExactPodTable>(resource: TResource) => {
|
|
10
|
+
values(value: any): {
|
|
11
|
+
execute(): Promise<unknown>;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export declare function findExactRecord<T>(db: ExactRecordDatabase, resource: ExactPodTable, target: ExactRecordTarget): Promise<T | null>;
|
|
16
|
+
export declare function updateExactRecord(db: ExactRecordDatabase, resource: ExactPodTable, target: ExactRecordTarget, updates: Record<string, unknown>): Promise<void>;
|
|
17
|
+
export declare function upsertExactRecord(db: ExactRecordDatabase, resource: ExactPodTable, target: ExactRecordTarget, row: Record<string, unknown>, updates: Record<string, unknown>): Promise<'inserted' | 'updated'>;
|
|
18
|
+
export declare function insertExactRecordOnce(db: ExactRecordDatabase, resource: ExactPodTable, target: ExactRecordTarget, row: Record<string, unknown>): Promise<boolean>;
|
|
19
|
+
export declare function deleteExactRecord(db: ExactRecordDatabase, resource: ExactPodTable, target: ExactRecordTarget): Promise<void>;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=exact-records.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exact-records.d.ts","sourceRoot":"","sources":["../../src/core/exact-records.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,KAAK,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;AAC7E,KAAK,yBAAyB,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAClE,KAAK,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;AAEnC,MAAM,MAAM,mBAAmB,GAAG;IAChC,cAAc,CAAC,EAAE,CAAC,SAAS,SAAS,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,yBAAyB,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACtI,gBAAgB,CAAC,EAAE,CAAC,SAAS,SAAS,aAAa,EACjD,QAAQ,EAAE,SAAS,EACnB,MAAM,EAAE,yBAAyB,EACjC,IAAI,EAAE,GAAG,KACN,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAC7B,gBAAgB,CAAC,EAAE,CAAC,SAAS,SAAS,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,yBAAyB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACjI,MAAM,CAAC,EAAE,CAAC,SAAS,SAAS,aAAa,EAAE,QAAQ,EAAE,SAAS,KAAK;QACjE,MAAM,CAAC,KAAK,EAAE,GAAG,GAAG;YAClB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;SAC7B,CAAC;KACH,CAAC;CACH,CAAC;AAIF,wBAAsB,eAAe,CAAC,CAAC,EACrC,EAAE,EAAE,mBAAmB,EACvB,QAAQ,EAAE,aAAa,EACvB,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAMnB;AAED,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,mBAAmB,EACvB,QAAQ,EAAE,aAAa,EACvB,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,mBAAmB,EACvB,QAAQ,EAAE,aAAa,EACvB,MAAM,EAAE,iBAAiB,EACzB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAejC;AAED,wBAAsB,qBAAqB,CACzC,EAAE,EAAE,mBAAmB,EACvB,QAAQ,EAAE,aAAa,EACvB,MAAM,EAAE,iBAAiB,EACzB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,OAAO,CAAC,OAAO,CAAC,CAWlB;AAED,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,mBAAmB,EACvB,QAAQ,EAAE,aAAa,EACvB,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,IAAI,CAAC,CAMf"}
|