@opensaas/stack-rag 0.1.6
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/.turbo/turbo-build.log +4 -0
- package/CHANGELOG.md +10 -0
- package/CLAUDE.md +565 -0
- package/LICENSE +21 -0
- package/README.md +406 -0
- package/dist/config/index.d.ts +63 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +94 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/plugin.d.ts +38 -0
- package/dist/config/plugin.d.ts.map +1 -0
- package/dist/config/plugin.js +215 -0
- package/dist/config/plugin.js.map +1 -0
- package/dist/config/plugin.test.d.ts +2 -0
- package/dist/config/plugin.test.d.ts.map +1 -0
- package/dist/config/plugin.test.js +554 -0
- package/dist/config/plugin.test.js.map +1 -0
- package/dist/config/types.d.ts +249 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +5 -0
- package/dist/config/types.js.map +1 -0
- package/dist/fields/embedding.d.ts +85 -0
- package/dist/fields/embedding.d.ts.map +1 -0
- package/dist/fields/embedding.js +81 -0
- package/dist/fields/embedding.js.map +1 -0
- package/dist/fields/embedding.test.d.ts +2 -0
- package/dist/fields/embedding.test.d.ts.map +1 -0
- package/dist/fields/embedding.test.js +323 -0
- package/dist/fields/embedding.test.js.map +1 -0
- package/dist/fields/index.d.ts +6 -0
- package/dist/fields/index.d.ts.map +1 -0
- package/dist/fields/index.js +5 -0
- package/dist/fields/index.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.d.ts +19 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +18 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/providers/index.d.ts +38 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +68 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/ollama.d.ts +49 -0
- package/dist/providers/ollama.d.ts.map +1 -0
- package/dist/providers/ollama.js +151 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/openai.d.ts +41 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +126 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/providers.test.d.ts +2 -0
- package/dist/providers/providers.test.d.ts.map +1 -0
- package/dist/providers/providers.test.js +224 -0
- package/dist/providers/providers.test.js.map +1 -0
- package/dist/providers/types.d.ts +88 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +2 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/runtime/batch.d.ts +183 -0
- package/dist/runtime/batch.d.ts.map +1 -0
- package/dist/runtime/batch.js +240 -0
- package/dist/runtime/batch.js.map +1 -0
- package/dist/runtime/batch.test.d.ts +2 -0
- package/dist/runtime/batch.test.d.ts.map +1 -0
- package/dist/runtime/batch.test.js +251 -0
- package/dist/runtime/batch.test.js.map +1 -0
- package/dist/runtime/chunking.d.ts +42 -0
- package/dist/runtime/chunking.d.ts.map +1 -0
- package/dist/runtime/chunking.js +264 -0
- package/dist/runtime/chunking.js.map +1 -0
- package/dist/runtime/chunking.test.d.ts +2 -0
- package/dist/runtime/chunking.test.d.ts.map +1 -0
- package/dist/runtime/chunking.test.js +212 -0
- package/dist/runtime/chunking.test.js.map +1 -0
- package/dist/runtime/embeddings.d.ts +147 -0
- package/dist/runtime/embeddings.d.ts.map +1 -0
- package/dist/runtime/embeddings.js +201 -0
- package/dist/runtime/embeddings.js.map +1 -0
- package/dist/runtime/embeddings.test.d.ts +2 -0
- package/dist/runtime/embeddings.test.d.ts.map +1 -0
- package/dist/runtime/embeddings.test.js +366 -0
- package/dist/runtime/embeddings.test.js.map +1 -0
- package/dist/runtime/index.d.ts +14 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +18 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/search.d.ts +135 -0
- package/dist/runtime/search.d.ts.map +1 -0
- package/dist/runtime/search.js +101 -0
- package/dist/runtime/search.js.map +1 -0
- package/dist/storage/index.d.ts +41 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +73 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/json.d.ts +34 -0
- package/dist/storage/json.d.ts.map +1 -0
- package/dist/storage/json.js +82 -0
- package/dist/storage/json.js.map +1 -0
- package/dist/storage/pgvector.d.ts +53 -0
- package/dist/storage/pgvector.d.ts.map +1 -0
- package/dist/storage/pgvector.js +168 -0
- package/dist/storage/pgvector.js.map +1 -0
- package/dist/storage/sqlite-vss.d.ts +49 -0
- package/dist/storage/sqlite-vss.d.ts.map +1 -0
- package/dist/storage/sqlite-vss.js +148 -0
- package/dist/storage/sqlite-vss.js.map +1 -0
- package/dist/storage/storage.test.d.ts +2 -0
- package/dist/storage/storage.test.d.ts.map +1 -0
- package/dist/storage/storage.test.js +440 -0
- package/dist/storage/storage.test.js.map +1 -0
- package/dist/storage/types.d.ts +79 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +49 -0
- package/dist/storage/types.js.map +1 -0
- package/package.json +82 -0
- package/src/config/index.ts +116 -0
- package/src/config/plugin.test.ts +664 -0
- package/src/config/plugin.ts +257 -0
- package/src/config/types.ts +283 -0
- package/src/fields/embedding.test.ts +408 -0
- package/src/fields/embedding.ts +150 -0
- package/src/fields/index.ts +6 -0
- package/src/index.ts +33 -0
- package/src/mcp/index.ts +21 -0
- package/src/providers/index.ts +81 -0
- package/src/providers/ollama.ts +186 -0
- package/src/providers/openai.ts +161 -0
- package/src/providers/providers.test.ts +275 -0
- package/src/providers/types.ts +100 -0
- package/src/runtime/batch.test.ts +332 -0
- package/src/runtime/batch.ts +424 -0
- package/src/runtime/chunking.test.ts +258 -0
- package/src/runtime/chunking.ts +334 -0
- package/src/runtime/embeddings.test.ts +441 -0
- package/src/runtime/embeddings.ts +380 -0
- package/src/runtime/index.ts +51 -0
- package/src/runtime/search.ts +243 -0
- package/src/storage/index.ts +86 -0
- package/src/storage/json.ts +106 -0
- package/src/storage/pgvector.ts +206 -0
- package/src/storage/sqlite-vss.ts +193 -0
- package/src/storage/storage.test.ts +521 -0
- package/src/storage/types.ts +126 -0
- package/tsconfig.json +13 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +18 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { VectorStorage } from './types.js';
|
|
2
|
+
import type { VectorStorageConfig } from '../config/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Register a custom vector storage backend
|
|
5
|
+
* Use this to add support for custom storage backends (e.g., Pinecone, Qdrant)
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { registerVectorStorage } from '@opensaas/stack-rag/storage'
|
|
10
|
+
*
|
|
11
|
+
* registerVectorStorage('pinecone', (config) => {
|
|
12
|
+
* return new PineconeVectorStorage(config)
|
|
13
|
+
* })
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function registerVectorStorage(type: string, factory: (config: VectorStorageConfig) => VectorStorage): void;
|
|
17
|
+
/**
|
|
18
|
+
* Create a vector storage instance from configuration
|
|
19
|
+
* Automatically selects the correct backend based on config.type
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* import { createVectorStorage } from '@opensaas/stack-rag/storage'
|
|
24
|
+
*
|
|
25
|
+
* const storage = createVectorStorage({
|
|
26
|
+
* type: 'pgvector',
|
|
27
|
+
* distanceFunction: 'cosine'
|
|
28
|
+
* })
|
|
29
|
+
*
|
|
30
|
+
* const results = await storage.search('Article', 'contentEmbedding', queryVector, {
|
|
31
|
+
* limit: 10,
|
|
32
|
+
* context
|
|
33
|
+
* })
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function createVectorStorage(config: VectorStorageConfig): VectorStorage;
|
|
37
|
+
export * from './types.js';
|
|
38
|
+
export { JsonVectorStorage, createJsonStorage } from './json.js';
|
|
39
|
+
export { PgVectorStorage, createPgVectorStorage } from './pgvector.js';
|
|
40
|
+
export { SqliteVssStorage, createSqliteVssStorage } from './sqlite-vss.js';
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AA4B7D;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,aAAa,GACtD,IAAI,CAEN;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,aAAa,CAW9E;AAGD,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AACtE,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { createJsonStorage } from './json.js';
|
|
2
|
+
import { createPgVectorStorage } from './pgvector.js';
|
|
3
|
+
import { createSqliteVssStorage } from './sqlite-vss.js';
|
|
4
|
+
/**
|
|
5
|
+
* Storage backend factory registry
|
|
6
|
+
* Maps storage types to factory functions
|
|
7
|
+
*/
|
|
8
|
+
const storageFactories = new Map();
|
|
9
|
+
/**
|
|
10
|
+
* Register the built-in storage backends
|
|
11
|
+
*/
|
|
12
|
+
storageFactories.set('json', () => createJsonStorage());
|
|
13
|
+
storageFactories.set('pgvector', (config) => {
|
|
14
|
+
if (config.type !== 'pgvector') {
|
|
15
|
+
throw new Error('Invalid config type for pgvector storage');
|
|
16
|
+
}
|
|
17
|
+
return createPgVectorStorage(config);
|
|
18
|
+
});
|
|
19
|
+
storageFactories.set('sqlite-vss', (config) => {
|
|
20
|
+
if (config.type !== 'sqlite-vss') {
|
|
21
|
+
throw new Error('Invalid config type for sqlite-vss storage');
|
|
22
|
+
}
|
|
23
|
+
return createSqliteVssStorage(config);
|
|
24
|
+
});
|
|
25
|
+
/**
|
|
26
|
+
* Register a custom vector storage backend
|
|
27
|
+
* Use this to add support for custom storage backends (e.g., Pinecone, Qdrant)
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* import { registerVectorStorage } from '@opensaas/stack-rag/storage'
|
|
32
|
+
*
|
|
33
|
+
* registerVectorStorage('pinecone', (config) => {
|
|
34
|
+
* return new PineconeVectorStorage(config)
|
|
35
|
+
* })
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export function registerVectorStorage(type, factory) {
|
|
39
|
+
storageFactories.set(type, factory);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create a vector storage instance from configuration
|
|
43
|
+
* Automatically selects the correct backend based on config.type
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* import { createVectorStorage } from '@opensaas/stack-rag/storage'
|
|
48
|
+
*
|
|
49
|
+
* const storage = createVectorStorage({
|
|
50
|
+
* type: 'pgvector',
|
|
51
|
+
* distanceFunction: 'cosine'
|
|
52
|
+
* })
|
|
53
|
+
*
|
|
54
|
+
* const results = await storage.search('Article', 'contentEmbedding', queryVector, {
|
|
55
|
+
* limit: 10,
|
|
56
|
+
* context
|
|
57
|
+
* })
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export function createVectorStorage(config) {
|
|
61
|
+
const factory = storageFactories.get(config.type);
|
|
62
|
+
if (!factory) {
|
|
63
|
+
throw new Error(`Unknown vector storage type: ${config.type}. ` +
|
|
64
|
+
`Available backends: ${Array.from(storageFactories.keys()).join(', ')}`);
|
|
65
|
+
}
|
|
66
|
+
return factory(config);
|
|
67
|
+
}
|
|
68
|
+
// Export types and individual storage backends
|
|
69
|
+
export * from './types.js';
|
|
70
|
+
export { JsonVectorStorage, createJsonStorage } from './json.js';
|
|
71
|
+
export { PgVectorStorage, createPgVectorStorage } from './pgvector.js';
|
|
72
|
+
export { SqliteVssStorage, createSqliteVssStorage } from './sqlite-vss.js';
|
|
73
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAExD;;;GAGG;AACH,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAA0D,CAAA;AAE1F;;GAEG;AACH,gBAAgB,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAA;AACvD,gBAAgB,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,EAAE;IAC1C,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;IAC7D,CAAC;IACD,OAAO,qBAAqB,CAAC,MAA4D,CAAC,CAAA;AAC5F,CAAC,CAAC,CAAA;AACF,gBAAgB,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,EAAE;IAC5C,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IAC/D,CAAC;IACD,OAAO,sBAAsB,CAAC,MAA6D,CAAC,CAAA;AAC9F,CAAC,CAAC,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAY,EACZ,OAAuD;IAEvD,gBAAgB,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;AACrC,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAA2B;IAC7D,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAEjD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,gCAAgC,MAAM,CAAC,IAAI,IAAI;YAC7C,uBAAuB,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC1E,CAAA;IACH,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,CAAC,CAAA;AACxB,CAAC;AAED,+CAA+C;AAC/C,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AACtE,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { VectorStorage, SearchOptions } from './types.js';
|
|
2
|
+
import type { SearchResult } from '../config/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* JSON-based vector storage
|
|
5
|
+
* Stores vectors as JSON in the database and performs similarity search in JavaScript
|
|
6
|
+
* Good for development and small datasets, doesn't require special database extensions
|
|
7
|
+
*/
|
|
8
|
+
export declare class JsonVectorStorage implements VectorStorage {
|
|
9
|
+
readonly type = "json";
|
|
10
|
+
/**
|
|
11
|
+
* Search for similar vectors using JavaScript-based cosine similarity
|
|
12
|
+
*/
|
|
13
|
+
search<T = unknown>(listKey: string, fieldName: string, queryVector: number[], options: SearchOptions): Promise<SearchResult<T>[]>;
|
|
14
|
+
/**
|
|
15
|
+
* Calculate cosine similarity between two vectors
|
|
16
|
+
*/
|
|
17
|
+
cosineSimilarity(a: number[], b: number[]): number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Create a JSON vector storage instance
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { createJsonStorage } from '@opensaas/stack-rag/storage'
|
|
25
|
+
*
|
|
26
|
+
* const storage = createJsonStorage()
|
|
27
|
+
* const results = await storage.search('Article', 'contentEmbedding', queryVector, {
|
|
28
|
+
* limit: 10,
|
|
29
|
+
* context
|
|
30
|
+
* })
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function createJsonStorage(): JsonVectorStorage;
|
|
34
|
+
//# sourceMappingURL=json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/storage/json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,oBAAoB,CAAA;AAIvE;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,aAAa;IACrD,QAAQ,CAAC,IAAI,UAAS;IAEtB;;OAEG;IACG,MAAM,CAAC,CAAC,GAAG,OAAO,EACtB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EAAE,EACrB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IA4D7B;;OAEG;IACH,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM;CAGnD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,IAAI,iBAAiB,CAErD"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { cosineSimilarity as calculateCosineSimilarity } from './types.js';
|
|
2
|
+
import { getDbKey } from '@opensaas/stack-core';
|
|
3
|
+
/**
|
|
4
|
+
* JSON-based vector storage
|
|
5
|
+
* Stores vectors as JSON in the database and performs similarity search in JavaScript
|
|
6
|
+
* Good for development and small datasets, doesn't require special database extensions
|
|
7
|
+
*/
|
|
8
|
+
export class JsonVectorStorage {
|
|
9
|
+
type = 'json';
|
|
10
|
+
/**
|
|
11
|
+
* Search for similar vectors using JavaScript-based cosine similarity
|
|
12
|
+
*/
|
|
13
|
+
async search(listKey, fieldName, queryVector, options) {
|
|
14
|
+
const { limit = 10, minScore = 0.0, context, where = {} } = options;
|
|
15
|
+
const dbKey = getDbKey(listKey);
|
|
16
|
+
const model = context.db[dbKey];
|
|
17
|
+
if (!model) {
|
|
18
|
+
throw new Error(`List '${listKey}' not found in context.db`);
|
|
19
|
+
}
|
|
20
|
+
// Fetch all items with embeddings (access control applied via context)
|
|
21
|
+
// We need to fetch all items because we're doing similarity scoring in JS
|
|
22
|
+
const items = await model.findMany({
|
|
23
|
+
where: {
|
|
24
|
+
...where,
|
|
25
|
+
[fieldName]: {
|
|
26
|
+
not: null,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
// Calculate similarity for each item
|
|
31
|
+
const results = [];
|
|
32
|
+
for (const item of items) {
|
|
33
|
+
const embeddingData = item[fieldName];
|
|
34
|
+
if (!embeddingData || !embeddingData.vector) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const storedVector = embeddingData.vector;
|
|
38
|
+
// Validate vector dimensions
|
|
39
|
+
if (storedVector.length !== queryVector.length) {
|
|
40
|
+
console.warn(`Vector dimension mismatch for ${listKey}.${item.id}.${fieldName}: ` +
|
|
41
|
+
`expected ${queryVector.length}, got ${storedVector.length}. Skipping.`);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
// Calculate cosine similarity
|
|
45
|
+
const score = this.cosineSimilarity(queryVector, storedVector);
|
|
46
|
+
if (score >= minScore) {
|
|
47
|
+
results.push({
|
|
48
|
+
item: item,
|
|
49
|
+
score,
|
|
50
|
+
distance: 1 - score, // Convert similarity to distance
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Sort by score (descending) and limit results
|
|
55
|
+
results.sort((a, b) => b.score - a.score);
|
|
56
|
+
return results.slice(0, limit);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Calculate cosine similarity between two vectors
|
|
60
|
+
*/
|
|
61
|
+
cosineSimilarity(a, b) {
|
|
62
|
+
return calculateCosineSimilarity(a, b);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Create a JSON vector storage instance
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* import { createJsonStorage } from '@opensaas/stack-rag/storage'
|
|
71
|
+
*
|
|
72
|
+
* const storage = createJsonStorage()
|
|
73
|
+
* const results = await storage.search('Article', 'contentEmbedding', queryVector, {
|
|
74
|
+
* limit: 10,
|
|
75
|
+
* context
|
|
76
|
+
* })
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export function createJsonStorage() {
|
|
80
|
+
return new JsonVectorStorage();
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/storage/json.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,IAAI,yBAAyB,EAAE,MAAM,YAAY,CAAA;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAE/C;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;IACnB,IAAI,GAAG,MAAM,CAAA;IAEtB;;OAEG;IACH,KAAK,CAAC,MAAM,CACV,OAAe,EACf,SAAiB,EACjB,WAAqB,EACrB,OAAsB;QAEtB,MAAM,EAAE,KAAK,GAAG,EAAE,EAAE,QAAQ,GAAG,GAAG,EAAE,OAAO,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,OAAO,CAAA;QAEnE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,CAAA;QAE/B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,SAAS,OAAO,2BAA2B,CAAC,CAAA;QAC9D,CAAC;QAED,uEAAuE;QACvE,0EAA0E;QAC1E,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC;YACjC,KAAK,EAAE;gBACL,GAAG,KAAK;gBACR,CAAC,SAAS,CAAC,EAAE;oBACX,GAAG,EAAE,IAAI;iBACV;aACF;SACF,CAAC,CAAA;QAEF,qCAAqC;QACrC,MAAM,OAAO,GAAwD,EAAE,CAAA;QAEvE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAA2B,CAAA;YAE/D,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;gBAC5C,SAAQ;YACV,CAAC;YAED,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,CAAA;YAEzC,6BAA6B;YAC7B,IAAI,YAAY,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM,EAAE,CAAC;gBAC/C,OAAO,CAAC,IAAI,CACV,iCAAiC,OAAO,IAAI,IAAI,CAAC,EAAE,IAAI,SAAS,IAAI;oBAClE,YAAY,WAAW,CAAC,MAAM,SAAS,YAAY,CAAC,MAAM,aAAa,CAC1E,CAAA;gBACD,SAAQ;YACV,CAAC;YAED,8BAA8B;YAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAA;YAE9D,IAAI,KAAK,IAAI,QAAQ,EAAE,CAAC;gBACtB,OAAO,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,IAAS;oBACf,KAAK;oBACL,QAAQ,EAAE,CAAC,GAAG,KAAK,EAAE,iCAAiC;iBACvD,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QAED,+CAA+C;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAA;QAEzC,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IAChC,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,CAAW,EAAE,CAAW;QACvC,OAAO,yBAAyB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACxC,CAAC;CACF;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,IAAI,iBAAiB,EAAE,CAAA;AAChC,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { VectorStorage, SearchOptions } from './types.js';
|
|
2
|
+
import type { SearchResult } from '../config/types.js';
|
|
3
|
+
import type { PgVectorStorageConfig } from '../config/types.js';
|
|
4
|
+
/**
|
|
5
|
+
* pgvector storage backend
|
|
6
|
+
* Uses PostgreSQL with pgvector extension for efficient vector similarity search
|
|
7
|
+
* Requires: CREATE EXTENSION vector;
|
|
8
|
+
*/
|
|
9
|
+
export declare class PgVectorStorage implements VectorStorage {
|
|
10
|
+
readonly type = "pgvector";
|
|
11
|
+
private distanceFunction;
|
|
12
|
+
constructor(config: PgVectorStorageConfig);
|
|
13
|
+
/**
|
|
14
|
+
* Get the appropriate distance operator for pgvector
|
|
15
|
+
*/
|
|
16
|
+
private getDistanceOperator;
|
|
17
|
+
/**
|
|
18
|
+
* Convert distance to similarity score (0-1, higher is more similar)
|
|
19
|
+
*/
|
|
20
|
+
private distanceToScore;
|
|
21
|
+
/**
|
|
22
|
+
* Search for similar vectors using pgvector
|
|
23
|
+
*/
|
|
24
|
+
search<T = unknown>(listKey: string, fieldName: string, queryVector: number[], options: SearchOptions): Promise<SearchResult<T>[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Fallback to JSON-based search if we can't access Prisma directly
|
|
27
|
+
*/
|
|
28
|
+
private fallbackSearch;
|
|
29
|
+
/**
|
|
30
|
+
* Calculate cosine similarity between two vectors
|
|
31
|
+
*/
|
|
32
|
+
cosineSimilarity(a: number[], b: number[]): number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Create a pgvector storage instance
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* import { createPgVectorStorage } from '@opensaas/stack-rag/storage'
|
|
40
|
+
*
|
|
41
|
+
* const storage = createPgVectorStorage({
|
|
42
|
+
* type: 'pgvector',
|
|
43
|
+
* distanceFunction: 'cosine'
|
|
44
|
+
* })
|
|
45
|
+
*
|
|
46
|
+
* const results = await storage.search('Article', 'contentEmbedding', queryVector, {
|
|
47
|
+
* limit: 10,
|
|
48
|
+
* context
|
|
49
|
+
* })
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function createPgVectorStorage(config: PgVectorStorageConfig): PgVectorStorage;
|
|
53
|
+
//# sourceMappingURL=pgvector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pgvector.d.ts","sourceRoot":"","sources":["../../src/storage/pgvector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAI/D;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,aAAa;IACnD,QAAQ,CAAC,IAAI,cAAa;IAC1B,OAAO,CAAC,gBAAgB,CAAmC;gBAE/C,MAAM,EAAE,qBAAqB;IAIzC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAa3B;;OAEG;IACH,OAAO,CAAC,eAAe;IAiBvB;;OAEG;IACG,MAAM,CAAC,CAAC,GAAG,OAAO,EACtB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EAAE,EACrB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAoG7B;;OAEG;YACW,cAAc;IAW5B;;OAEG;IACH,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM;CAGnD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,eAAe,CAEpF"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { cosineSimilarity as calculateCosineSimilarity } from './types.js';
|
|
2
|
+
import { getDbKey } from '@opensaas/stack-core';
|
|
3
|
+
/**
|
|
4
|
+
* pgvector storage backend
|
|
5
|
+
* Uses PostgreSQL with pgvector extension for efficient vector similarity search
|
|
6
|
+
* Requires: CREATE EXTENSION vector;
|
|
7
|
+
*/
|
|
8
|
+
export class PgVectorStorage {
|
|
9
|
+
type = 'pgvector';
|
|
10
|
+
distanceFunction;
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.distanceFunction = config.distanceFunction || 'cosine';
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get the appropriate distance operator for pgvector
|
|
16
|
+
*/
|
|
17
|
+
getDistanceOperator() {
|
|
18
|
+
switch (this.distanceFunction) {
|
|
19
|
+
case 'cosine':
|
|
20
|
+
return '<=>'; // Cosine distance
|
|
21
|
+
case 'l2':
|
|
22
|
+
return '<->'; // L2 distance
|
|
23
|
+
case 'inner_product':
|
|
24
|
+
return '<#>'; // Inner product (negative, so smaller is more similar)
|
|
25
|
+
default:
|
|
26
|
+
return '<=>'; // Default to cosine
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Convert distance to similarity score (0-1, higher is more similar)
|
|
31
|
+
*/
|
|
32
|
+
distanceToScore(distance) {
|
|
33
|
+
switch (this.distanceFunction) {
|
|
34
|
+
case 'cosine':
|
|
35
|
+
// Cosine distance is 1 - similarity, so similarity = 1 - distance
|
|
36
|
+
return 1 - distance;
|
|
37
|
+
case 'l2':
|
|
38
|
+
// L2 distance: convert to similarity using 1 / (1 + distance)
|
|
39
|
+
return 1 / (1 + distance);
|
|
40
|
+
case 'inner_product':
|
|
41
|
+
// Inner product: larger (less negative) is more similar
|
|
42
|
+
// Convert to 0-1 range
|
|
43
|
+
return -distance;
|
|
44
|
+
default:
|
|
45
|
+
return 1 - distance;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Search for similar vectors using pgvector
|
|
50
|
+
*/
|
|
51
|
+
async search(listKey, fieldName, queryVector, options) {
|
|
52
|
+
const { limit = 10, minScore = 0.0, context, where = {} } = options;
|
|
53
|
+
const dbKey = getDbKey(listKey);
|
|
54
|
+
const model = context.db[dbKey];
|
|
55
|
+
if (!model) {
|
|
56
|
+
throw new Error(`List '${listKey}' not found in context.db`);
|
|
57
|
+
}
|
|
58
|
+
const distanceOp = this.getDistanceOperator();
|
|
59
|
+
// Build the vector string for Prisma raw query
|
|
60
|
+
// pgvector expects vectors in format: '[1,2,3]'
|
|
61
|
+
const vectorString = `[${queryVector.join(',')}]`;
|
|
62
|
+
// We need to use Prisma.$queryRaw to access pgvector operators
|
|
63
|
+
// The access-controlled context.db doesn't expose $queryRaw directly,
|
|
64
|
+
// so we need to use a two-step approach:
|
|
65
|
+
// 1. Get all matching IDs using raw query
|
|
66
|
+
// 2. Fetch full items via access-controlled context
|
|
67
|
+
try {
|
|
68
|
+
// Get the underlying Prisma client
|
|
69
|
+
// Note: This bypasses access control for the similarity search,
|
|
70
|
+
// but we enforce it in the second query
|
|
71
|
+
const prisma = context.prisma;
|
|
72
|
+
if (!prisma) {
|
|
73
|
+
// Fallback: if we can't access Prisma directly, use JSON storage approach
|
|
74
|
+
console.warn('pgvector: Could not access Prisma client directly. ' +
|
|
75
|
+
'Falling back to JSON-based search. ' +
|
|
76
|
+
'For full pgvector support, ensure the context exposes _prisma.');
|
|
77
|
+
return this.fallbackSearch(listKey, fieldName, queryVector, options);
|
|
78
|
+
}
|
|
79
|
+
// Raw query to get IDs and distances
|
|
80
|
+
// We extract the vector from the JSON field and cast it to vector type
|
|
81
|
+
const tableName = listKey.toLowerCase(); // Prisma table names are lowercase
|
|
82
|
+
const results = (await prisma.$queryRawUnsafe(`
|
|
83
|
+
SELECT id,
|
|
84
|
+
(("${fieldName}"->>'vector')::vector ${distanceOp} '${vectorString}'::vector) as distance
|
|
85
|
+
FROM "${tableName}"
|
|
86
|
+
WHERE "${fieldName}" IS NOT NULL
|
|
87
|
+
AND "${fieldName}"->>'vector' IS NOT NULL
|
|
88
|
+
ORDER BY distance
|
|
89
|
+
LIMIT ${limit * 2}
|
|
90
|
+
`));
|
|
91
|
+
// Get IDs of items within score threshold
|
|
92
|
+
const itemIds = results
|
|
93
|
+
.map((r) => ({
|
|
94
|
+
id: r.id,
|
|
95
|
+
distance: Number(r.distance),
|
|
96
|
+
score: this.distanceToScore(Number(r.distance)),
|
|
97
|
+
}))
|
|
98
|
+
.filter((r) => r.score >= minScore)
|
|
99
|
+
.slice(0, limit)
|
|
100
|
+
.map((r) => ({ id: r.id, distance: r.distance, score: r.score }));
|
|
101
|
+
if (itemIds.length === 0) {
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
// Fetch full items via access-controlled context
|
|
105
|
+
const items = await model.findMany({
|
|
106
|
+
where: {
|
|
107
|
+
...where,
|
|
108
|
+
id: {
|
|
109
|
+
in: itemIds.map((r) => r.id),
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
// Match items with their scores and sort by score
|
|
114
|
+
const searchResults = [];
|
|
115
|
+
for (const idInfo of itemIds) {
|
|
116
|
+
const item = items.find((i) => i.id === idInfo.id);
|
|
117
|
+
if (item) {
|
|
118
|
+
searchResults.push({
|
|
119
|
+
item: item,
|
|
120
|
+
score: idInfo.score,
|
|
121
|
+
distance: idInfo.distance,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return searchResults;
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
throw new Error(`pgvector search failed: ${error.message}\n` +
|
|
129
|
+
'Ensure pgvector extension is installed: CREATE EXTENSION vector;');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Fallback to JSON-based search if we can't access Prisma directly
|
|
134
|
+
*/
|
|
135
|
+
async fallbackSearch(listKey, fieldName, queryVector, options) {
|
|
136
|
+
const { JsonVectorStorage } = await import('./json.js');
|
|
137
|
+
const jsonStorage = new JsonVectorStorage();
|
|
138
|
+
return jsonStorage.search(listKey, fieldName, queryVector, options);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Calculate cosine similarity between two vectors
|
|
142
|
+
*/
|
|
143
|
+
cosineSimilarity(a, b) {
|
|
144
|
+
return calculateCosineSimilarity(a, b);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Create a pgvector storage instance
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```typescript
|
|
152
|
+
* import { createPgVectorStorage } from '@opensaas/stack-rag/storage'
|
|
153
|
+
*
|
|
154
|
+
* const storage = createPgVectorStorage({
|
|
155
|
+
* type: 'pgvector',
|
|
156
|
+
* distanceFunction: 'cosine'
|
|
157
|
+
* })
|
|
158
|
+
*
|
|
159
|
+
* const results = await storage.search('Article', 'contentEmbedding', queryVector, {
|
|
160
|
+
* limit: 10,
|
|
161
|
+
* context
|
|
162
|
+
* })
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
export function createPgVectorStorage(config) {
|
|
166
|
+
return new PgVectorStorage(config);
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=pgvector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pgvector.js","sourceRoot":"","sources":["../../src/storage/pgvector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { VectorStorage, SearchOptions } from './types.js';
|
|
2
|
+
import type { SearchResult } from '../config/types.js';
|
|
3
|
+
import type { SqliteVssStorageConfig } from '../config/types.js';
|
|
4
|
+
/**
|
|
5
|
+
* SQLite VSS storage backend
|
|
6
|
+
* Uses sqlite-vss extension for vector similarity search
|
|
7
|
+
* Requires: sqlite-vss extension to be loaded
|
|
8
|
+
*/
|
|
9
|
+
export declare class SqliteVssStorage implements VectorStorage {
|
|
10
|
+
readonly type = "sqlite-vss";
|
|
11
|
+
private distanceFunction;
|
|
12
|
+
constructor(config: SqliteVssStorageConfig);
|
|
13
|
+
/**
|
|
14
|
+
* Convert distance to similarity score (0-1, higher is more similar)
|
|
15
|
+
*/
|
|
16
|
+
private distanceToScore;
|
|
17
|
+
/**
|
|
18
|
+
* Search for similar vectors using sqlite-vss
|
|
19
|
+
*/
|
|
20
|
+
search<T = unknown>(listKey: string, fieldName: string, queryVector: number[], options: SearchOptions): Promise<SearchResult<T>[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Fallback to JSON-based search if we can't access Prisma directly
|
|
23
|
+
*/
|
|
24
|
+
private fallbackSearch;
|
|
25
|
+
/**
|
|
26
|
+
* Calculate cosine similarity between two vectors
|
|
27
|
+
*/
|
|
28
|
+
cosineSimilarity(a: number[], b: number[]): number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Create a SQLite VSS storage instance
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* import { createSqliteVssStorage } from '@opensaas/stack-rag/storage'
|
|
36
|
+
*
|
|
37
|
+
* const storage = createSqliteVssStorage({
|
|
38
|
+
* type: 'sqlite-vss',
|
|
39
|
+
* distanceFunction: 'cosine'
|
|
40
|
+
* })
|
|
41
|
+
*
|
|
42
|
+
* const results = await storage.search('Article', 'contentEmbedding', queryVector, {
|
|
43
|
+
* limit: 10,
|
|
44
|
+
* context
|
|
45
|
+
* })
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function createSqliteVssStorage(config: SqliteVssStorageConfig): SqliteVssStorage;
|
|
49
|
+
//# sourceMappingURL=sqlite-vss.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-vss.d.ts","sourceRoot":"","sources":["../../src/storage/sqlite-vss.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAIhE;;;;GAIG;AACH,qBAAa,gBAAiB,YAAW,aAAa;IACpD,QAAQ,CAAC,IAAI,gBAAe;IAC5B,OAAO,CAAC,gBAAgB,CAAiB;gBAE7B,MAAM,EAAE,sBAAsB;IAI1C;;OAEG;IACH,OAAO,CAAC,eAAe;IAUvB;;OAEG;IACG,MAAM,CAAC,CAAC,GAAG,OAAO,EACtB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EAAE,EACrB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IA8G7B;;OAEG;YACW,cAAc;IAW5B;;OAEG;IACH,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM;CAGnD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,sBAAsB,GAAG,gBAAgB,CAEvF"}
|