@mcp-abap-adt/qdrant-rag 26.0.0 → 28.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +22 -0
  2. package/dist/__tests__/catalog.test.d.ts +2 -0
  3. package/dist/__tests__/catalog.test.d.ts.map +1 -0
  4. package/dist/__tests__/catalog.test.js +241 -0
  5. package/dist/__tests__/catalog.test.js.map +1 -0
  6. package/dist/__tests__/credential.test.d.ts +2 -0
  7. package/dist/__tests__/credential.test.d.ts.map +1 -0
  8. package/dist/__tests__/credential.test.js +93 -0
  9. package/dist/__tests__/credential.test.js.map +1 -0
  10. package/dist/__tests__/qdrant-stub.d.ts +52 -0
  11. package/dist/__tests__/qdrant-stub.d.ts.map +1 -0
  12. package/dist/__tests__/qdrant-stub.js +206 -0
  13. package/dist/__tests__/qdrant-stub.js.map +1 -0
  14. package/dist/__tests__/rag-filter-conformance.test.d.ts +2 -0
  15. package/dist/__tests__/rag-filter-conformance.test.d.ts.map +1 -0
  16. package/dist/__tests__/rag-filter-conformance.test.js +25 -0
  17. package/dist/__tests__/rag-filter-conformance.test.js.map +1 -0
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/qdrant-rag-provider.d.ts +41 -11
  23. package/dist/qdrant-rag-provider.d.ts.map +1 -1
  24. package/dist/qdrant-rag-provider.js +296 -29
  25. package/dist/qdrant-rag-provider.js.map +1 -1
  26. package/dist/qdrant-rag-provider.test.js +0 -11
  27. package/dist/qdrant-rag-provider.test.js.map +1 -1
  28. package/dist/qdrant-rag.d.ts +23 -2
  29. package/dist/qdrant-rag.d.ts.map +1 -1
  30. package/dist/qdrant-rag.js +45 -19
  31. package/dist/qdrant-rag.js.map +1 -1
  32. package/dist/qdrant-rag.test.js +51 -3
  33. package/dist/qdrant-rag.test.js.map +1 -1
  34. package/package.json +5 -4
package/README.md CHANGED
@@ -7,6 +7,28 @@ QdrantRag vector store and QdrantRagProvider for @mcp-abap-adt/llm-agent.
7
7
 
8
8
  Provides vector search capabilities using Qdrant as the backend.
9
9
 
10
+ Requires Qdrant 1.17 or later: the collection catalog is written with an insert-only operation.
11
+
12
+ ## Catalog, rights, and the Qdrant version
13
+
14
+ `QdrantRagProvider` keeps one record per collection in a catalog collection of its own
15
+ (`rag_collection_catalog` by default, `catalogCollection` to rename it): one point per collection,
16
+ the record in its payload. `createCollection` embeds one probe string to learn the vector size,
17
+ creates the collection, and then writes its record; `deleteCollection` deletes the record first, then
18
+ the collection; `describeCollections` reads the catalog back.
19
+
20
+ - **Qdrant 1.17 or later is required** for a catalogued store: the record is written with
21
+ `update_mode: "insert_only"`, which exists from 1.17.
22
+ - **The key must be able to manage collections**: create collections (the catalog on first use, one
23
+ per collection), write, read and delete points in the catalog, and delete collections. A
24
+ `read-only-api-key`, or a JWT restricted to named collections, is not enough.
25
+ - A standalone `QdrantRag` (a store configured directly, not through the provider) keeps creating
26
+ its collection on the first write (`autoCreateCollection`, default `true`); the provider's handles
27
+ never create theirs.
28
+
29
+ A collection created before this release has a collection and no record: take it over once with
30
+ `createCollection(..., { adoptExisting: true })`.
31
+
10
32
  ## License
11
33
 
12
34
  **GNU Lesser General Public License v3.0 only** (`LGPL-3.0-only`) — see
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=catalog.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/catalog.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,241 @@
1
+ import assert from 'node:assert/strict';
2
+ import { describe, it } from 'node:test';
3
+ import { CatalogRecordDeleteError } from '@mcp-abap-adt/llm-agent';
4
+ import { deterministicUUID, QdrantRag } from '../qdrant-rag.js';
5
+ import { QdrantRagProvider } from '../qdrant-rag-provider.js';
6
+ import { startQdrantStub, } from './qdrant-stub.js';
7
+ const CATALOG = 'rag_collection_catalog';
8
+ const STORE = 'my_notes_a1b2c3d4e5f6';
9
+ const createOpts = {
10
+ scope: 'user',
11
+ userId: 'u-1',
12
+ collectionName: 'my notes',
13
+ attributes: { role: 'analyst' },
14
+ };
15
+ class CountingEmbedder {
16
+ dim;
17
+ calls = 0;
18
+ constructor(dim = 3) {
19
+ this.dim = dim;
20
+ }
21
+ async embed() {
22
+ this.calls++;
23
+ return { vector: Array.from({ length: this.dim }, () => 0.5) };
24
+ }
25
+ }
26
+ function providerOn(stub, embedder = new CountingEmbedder()) {
27
+ return new QdrantRagProvider({ name: 'q', url: stub.baseUrl, embedder });
28
+ }
29
+ async function withStub(run) {
30
+ const stub = await startQdrantStub();
31
+ try {
32
+ await run(stub);
33
+ }
34
+ finally {
35
+ await stub.close();
36
+ }
37
+ }
38
+ const is = (method, path) => (r) => r.method === method && r.path === path;
39
+ const indexOf = (stub, method, path) => stub.requests.findIndex(is(method, path));
40
+ async function seedRecord(stub, storeName, payload) {
41
+ if (!stub.collections.has(CATALOG))
42
+ stub.collections.set(CATALOG, { size: 1, points: new Map() });
43
+ const id = await deterministicUUID(storeName);
44
+ stub.collections.get(CATALOG)?.points.set(id, { id, vector: [1], payload });
45
+ }
46
+ describe('qdrant catalog: createCollection', () => {
47
+ it('creates the collection with the probe size, then records it last, spending one embedding', () => withStub(async (stub) => {
48
+ const embedder = new CountingEmbedder(3);
49
+ const res = await providerOn(stub, embedder).createCollection(STORE, createOpts);
50
+ assert.ok(res.ok);
51
+ assert.ok(res.value.rag instanceof QdrantRag);
52
+ assert.equal(embedder.calls, 1, 'one probe embedding per collection created');
53
+ assert.equal(stub.collections.get(STORE)?.size, 3);
54
+ const createdAt = indexOf(stub, 'PUT', `/collections/${STORE}`);
55
+ const recordAt = indexOf(stub, 'PUT', `/collections/${CATALOG}/points`);
56
+ assert.ok(createdAt >= 0 && recordAt > createdAt, 'store first, record last');
57
+ const described = await providerOn(stub).describeCollections();
58
+ assert.ok(described.ok);
59
+ assert.deepEqual(described.value, {
60
+ records: [
61
+ {
62
+ scope: 'user',
63
+ userId: 'u-1',
64
+ storeName: STORE,
65
+ name: 'my notes',
66
+ attributes: { role: 'analyst' },
67
+ },
68
+ ],
69
+ rejected: [],
70
+ });
71
+ }));
72
+ it('refuses a collection whose record exists, and creates nothing', () => withStub(async (stub) => {
73
+ await seedRecord(stub, STORE, {
74
+ store_name: STORE,
75
+ collection_name: 'x',
76
+ scope: 'global',
77
+ attributes_json: null,
78
+ write_id: 'w',
79
+ });
80
+ const res = await providerOn(stub).createCollection(STORE, createOpts);
81
+ assert.equal(!res.ok && res.error.code, 'RAG_DUPLICATE_COLLECTION');
82
+ assert.equal(indexOf(stub, 'PUT', `/collections/${STORE}`), -1);
83
+ }));
84
+ it('refuses a collection that exists without a record, naming it, and adopts it on request', () => withStub(async (stub) => {
85
+ stub.collections.set(STORE, { size: 3, points: new Map() });
86
+ const refused = await providerOn(stub).createCollection(STORE, createOpts);
87
+ assert.equal(!refused.ok && refused.error.code, 'RAG_ORPHAN_STORE');
88
+ assert.match(!refused.ok ? refused.error.message : '', new RegExp(STORE));
89
+ const embedder = new CountingEmbedder();
90
+ const adopted = await providerOn(stub, embedder).createCollection(STORE, {
91
+ ...createOpts,
92
+ adoptExisting: true,
93
+ });
94
+ assert.equal(adopted.ok, true);
95
+ assert.equal(embedder.calls, 0, 'adoption creates nothing, so it embeds nothing');
96
+ const records = await providerOn(stub).describeCollections();
97
+ assert.ok(records.ok && records.value.records.length === 1);
98
+ }));
99
+ it('refuses adoptExisting for a collection that is not there, and creates nothing', () => withStub(async (stub) => {
100
+ const res = await providerOn(stub).createCollection(STORE, {
101
+ ...createOpts,
102
+ adoptExisting: true,
103
+ });
104
+ assert.equal(!res.ok && res.error.code, 'RAG_CREATE_ERROR');
105
+ assert.ok(!stub.collections.has(STORE));
106
+ }));
107
+ it('leaves the collection in place, named, when the record cannot be written', () => withStub(async (stub) => {
108
+ stub.failOn = is('PUT', `/collections/${CATALOG}/points`);
109
+ const res = await providerOn(stub).createCollection(STORE, createOpts);
110
+ assert.equal(!res.ok && res.error.code, 'RAG_ORPHAN_STORE');
111
+ assert.ok(stub.collections.has(STORE));
112
+ assert.equal(indexOf(stub, 'DELETE', `/collections/${STORE}`), -1);
113
+ }));
114
+ it('loses cleanly when another registry recorded the same collection first', () => withStub(async (stub) => {
115
+ // computed before the race: the hook is synchronous and must land the
116
+ // winner's point before the stub applies this call's insert_only write
117
+ const winnerId = await deterministicUUID(STORE);
118
+ stub.beforeCatalogWrite = () => {
119
+ stub.beforeCatalogWrite = undefined;
120
+ stub.collections.get(CATALOG)?.points.set(winnerId, {
121
+ id: winnerId,
122
+ vector: [1],
123
+ payload: {
124
+ store_name: STORE,
125
+ collection_name: 'my notes',
126
+ scope: 'user',
127
+ user_id: 'u-1',
128
+ attributes_json: null,
129
+ write_id: 'the-winner',
130
+ },
131
+ });
132
+ };
133
+ const res = await providerOn(stub).createCollection(STORE, createOpts);
134
+ assert.equal(!res.ok && res.error.code, 'RAG_DUPLICATE_COLLECTION');
135
+ assert.ok(stub.collections.has(STORE), "the winner's record points at it");
136
+ }));
137
+ it('refuses an owner without its key before any request', () => withStub(async (stub) => {
138
+ const res = await providerOn(stub).createCollection(STORE, {
139
+ scope: 'user',
140
+ });
141
+ assert.equal(!res.ok && res.error.code, 'RAG_INVALID_OWNER');
142
+ assert.deepEqual(stub.requests, []);
143
+ }));
144
+ });
145
+ describe('qdrant catalog: no handle creates its collection', () => {
146
+ it('openCollection issues no request, and a write to a missing collection fails instead of creating it', () => withStub(async (stub) => {
147
+ const record = {
148
+ storeName: STORE,
149
+ name: 'n',
150
+ scope: 'global',
151
+ };
152
+ const opened = await providerOn(stub).openCollection(record);
153
+ assert.ok(opened.ok);
154
+ assert.deepEqual(stub.requests, []);
155
+ assert.equal((await opened.value.editor.upsert('hello', { id: 'r1' })).ok, false);
156
+ assert.ok(!stub.collections.has(STORE));
157
+ assert.equal(indexOf(stub, 'PUT', `/collections/${STORE}`), -1);
158
+ }));
159
+ it('openCollection answers a failed Result, never a rejection, when building a handle throws', async () => {
160
+ const provider = new QdrantRagProvider({
161
+ name: 'q',
162
+ url: 'http://127.0.0.1:9', // never contacted: no request is made
163
+ embedder: new CountingEmbedder(),
164
+ idStrategyFactory: () => {
165
+ throw new Error('id strategy refused');
166
+ },
167
+ });
168
+ const opened = await provider.openCollection({
169
+ storeName: STORE,
170
+ name: 'n',
171
+ scope: 'global',
172
+ });
173
+ assert.equal(opened.ok, false);
174
+ assert.ok(!opened.ok && opened.error.code === 'RAG_OPEN_ERROR');
175
+ assert.match(!opened.ok ? opened.error.message : '', /id strategy refused/);
176
+ });
177
+ it('a handle whose collection was deleted elsewhere fails rather than recreating it', () => withStub(async (stub) => {
178
+ const created = await providerOn(stub).createCollection(STORE, createOpts);
179
+ assert.ok(created.ok);
180
+ stub.collections.delete(STORE);
181
+ assert.equal((await created.value.editor.upsert('hello', { id: 'r1' })).ok, false);
182
+ assert.ok(!stub.collections.has(STORE));
183
+ }));
184
+ });
185
+ describe('qdrant catalog: describeCollections', () => {
186
+ it('returns nothing, and creates nothing, when no catalog exists yet', () => withStub(async (stub) => {
187
+ assert.deepEqual(await providerOn(stub).describeCollections(), {
188
+ ok: true,
189
+ value: { records: [], rejected: [] },
190
+ });
191
+ assert.equal(indexOf(stub, 'PUT', `/collections/${CATALOG}`), -1);
192
+ }));
193
+ it('pages through the catalog and rejects malformed points', () => withStub(async (stub) => {
194
+ for (let i = 0; i < 257; i++) {
195
+ await seedRecord(stub, `s_${i}`, {
196
+ store_name: `s_${i}`,
197
+ collection_name: `c${i}`,
198
+ scope: 'global',
199
+ attributes_json: null,
200
+ write_id: 'w',
201
+ });
202
+ }
203
+ await seedRecord(stub, 'bad_1', {
204
+ store_name: 'bad_1',
205
+ collection_name: 'c',
206
+ scope: 'session',
207
+ attributes_json: null,
208
+ write_id: 'w',
209
+ });
210
+ const res = await providerOn(stub).describeCollections();
211
+ assert.ok(res.ok);
212
+ assert.equal(res.value.records.length, 257);
213
+ assert.deepEqual(res.value.rejected.map((r) => r.storeName), ['bad_1']);
214
+ }));
215
+ });
216
+ describe('qdrant catalog: deleteCollection', () => {
217
+ it('deletes the record before the collection', () => withStub(async (stub) => {
218
+ assert.ok((await providerOn(stub).createCollection(STORE, createOpts)).ok);
219
+ assert.equal((await providerOn(stub).deleteCollection(STORE)).ok, true);
220
+ const recordAt = indexOf(stub, 'POST', `/collections/${CATALOG}/points/delete`);
221
+ const dataAt = indexOf(stub, 'DELETE', `/collections/${STORE}`);
222
+ assert.ok(recordAt >= 0 && dataAt > recordAt);
223
+ const records = await providerOn(stub).describeCollections();
224
+ assert.ok(records.ok && records.value.records.length === 0);
225
+ }));
226
+ it('stops with CatalogRecordDeleteError, touching nothing, when the record cannot be deleted', () => withStub(async (stub) => {
227
+ assert.ok((await providerOn(stub).createCollection(STORE, createOpts)).ok);
228
+ stub.failOn = is('POST', `/collections/${CATALOG}/points/delete`);
229
+ const res = await providerOn(stub).deleteCollection(STORE);
230
+ assert.ok(!res.ok && res.error instanceof CatalogRecordDeleteError);
231
+ assert.equal(indexOf(stub, 'DELETE', `/collections/${STORE}`), -1);
232
+ assert.ok(stub.collections.has(STORE));
233
+ }));
234
+ it('reports a collection failure after the record is gone as a plain delete error', () => withStub(async (stub) => {
235
+ assert.ok((await providerOn(stub).createCollection(STORE, createOpts)).ok);
236
+ stub.failOn = is('DELETE', `/collections/${STORE}`);
237
+ const res = await providerOn(stub).deleteCollection(STORE);
238
+ assert.equal(!res.ok && res.error.code, 'RAG_DELETE_ERROR');
239
+ }));
240
+ });
241
+ //# sourceMappingURL=catalog.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.test.js","sourceRoot":"","sources":["../../src/__tests__/catalog.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=credential.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/credential.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,93 @@
1
+ import assert from 'node:assert/strict';
2
+ import http from 'node:http';
3
+ import { after, before, describe, it } from 'node:test';
4
+ import { staticApiKey } from '@mcp-abap-adt/llm-agent';
5
+ import { QdrantRag } from '../qdrant-rag.js';
6
+ function makeEmbedder(dim = 3) {
7
+ return {
8
+ async embed(text) {
9
+ let hash = 0;
10
+ for (const ch of text)
11
+ hash = (hash * 31 + ch.charCodeAt(0)) | 0;
12
+ return {
13
+ vector: Array.from({ length: dim }, (_, i) => ((hash >> i) & 0xff) / 255),
14
+ };
15
+ },
16
+ };
17
+ }
18
+ describe('QdrantRag credential', () => {
19
+ let server;
20
+ let baseUrl;
21
+ const receivedApiKeyHeaders = [];
22
+ before(async () => {
23
+ server = http.createServer((req, res) => {
24
+ receivedApiKeyHeaders.push(req.headers['api-key']);
25
+ if (req.url?.match(/^\/collections\/[^/]+$/) && req.method === 'GET') {
26
+ res.writeHead(200, { 'Content-Type': 'application/json' });
27
+ res.end(JSON.stringify({ result: { status: 'green' } }));
28
+ return;
29
+ }
30
+ res.writeHead(404);
31
+ res.end();
32
+ });
33
+ await new Promise((resolve) => {
34
+ server.listen(0, '127.0.0.1', resolve);
35
+ });
36
+ const addr = server.address();
37
+ if (typeof addr === 'object' && addr) {
38
+ baseUrl = `http://127.0.0.1:${addr.port}`;
39
+ }
40
+ });
41
+ after(async () => {
42
+ await new Promise((resolve, reject) => {
43
+ server.close((err) => (err ? reject(err) : resolve()));
44
+ });
45
+ });
46
+ it('asks the credential for the secret on every request, not once at construction', async () => {
47
+ let calls = 0;
48
+ const credential = {
49
+ kind: 'api-key',
50
+ secret: async () => {
51
+ calls++;
52
+ return `key-${calls}`;
53
+ },
54
+ };
55
+ const rag = new QdrantRag({
56
+ url: baseUrl,
57
+ collectionName: 'test-cred',
58
+ embedder: makeEmbedder(),
59
+ credential,
60
+ });
61
+ assert.equal(calls, 0, 'constructing the store must not resolve the secret');
62
+ const first = await rag.healthCheck();
63
+ const second = await rag.healthCheck();
64
+ assert.ok(first.ok);
65
+ assert.ok(second.ok);
66
+ assert.equal(calls, 2, 'the secret is asked once per request, not cached');
67
+ assert.deepEqual(receivedApiKeyHeaders, ['key-1', 'key-2']);
68
+ });
69
+ it('sends the api-key header built from staticApiKey', async () => {
70
+ receivedApiKeyHeaders.length = 0;
71
+ const rag = new QdrantRag({
72
+ url: baseUrl,
73
+ collectionName: 'test-cred-static',
74
+ embedder: makeEmbedder(),
75
+ credential: staticApiKey('static-secret'),
76
+ });
77
+ const result = await rag.healthCheck();
78
+ assert.ok(result.ok);
79
+ assert.deepEqual(receivedApiKeyHeaders, ['static-secret']);
80
+ });
81
+ it('omits the api-key header when no credential is configured', async () => {
82
+ receivedApiKeyHeaders.length = 0;
83
+ const rag = new QdrantRag({
84
+ url: baseUrl,
85
+ collectionName: 'test-cred-none',
86
+ embedder: makeEmbedder(),
87
+ });
88
+ const result = await rag.healthCheck();
89
+ assert.ok(result.ok);
90
+ assert.deepEqual(receivedApiKeyHeaders, [undefined]);
91
+ });
92
+ });
93
+ //# sourceMappingURL=credential.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential.test.js","sourceRoot":"","sources":["../../src/__tests__/credential.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ export type StubPoint = {
2
+ id: string;
3
+ vector: number[];
4
+ payload: Record<string, unknown>;
5
+ };
6
+ export type StubRequest = {
7
+ method: string;
8
+ path: string;
9
+ body: unknown;
10
+ };
11
+ export type StubCollection = {
12
+ size: number;
13
+ points: Map<string, StubPoint>;
14
+ };
15
+ /** The Qdrant REST surface the provider uses, with the documented semantics:
16
+ * a repeated collection PUT is 409, and insert_only skips an existing id. */
17
+ export type QdrantStub = {
18
+ readonly baseUrl: string;
19
+ readonly collections: Map<string, StubCollection>;
20
+ readonly requests: StubRequest[];
21
+ failOn?: (r: StubRequest) => boolean;
22
+ /** Runs inside a points PUT to the catalog, before it is applied — a racing writer. */
23
+ beforeCatalogWrite?: () => void;
24
+ close(): Promise<void>;
25
+ };
26
+ export declare function startQdrantStub(catalog?: string): Promise<QdrantStub>;
27
+ type QdrantCondition = {
28
+ key: string;
29
+ match: {
30
+ value: unknown;
31
+ };
32
+ } | {
33
+ is_empty: {
34
+ key: string;
35
+ };
36
+ } | {
37
+ key: string;
38
+ range: {
39
+ gt?: number;
40
+ gte?: number;
41
+ lt?: number;
42
+ lte?: number;
43
+ };
44
+ } | QdrantFilter;
45
+ export type QdrantFilter = {
46
+ must?: QdrantCondition[];
47
+ should?: QdrantCondition[];
48
+ must_not?: QdrantCondition[];
49
+ };
50
+ export declare function matchesFilter(payload: Record<string, unknown>, filter: QdrantFilter): boolean;
51
+ export {};
52
+ //# sourceMappingURL=qdrant-stub.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qdrant-stub.d.ts","sourceRoot":"","sources":["../../src/__tests__/qdrant-stub.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAC;AACF,MAAM,MAAM,WAAW,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAC1E,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;CAAE,CAAC;AAE9E;8EAC8E;AAC9E,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAClD,QAAQ,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC;IACjC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC;IACrC,uFAAuF;IACvF,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAEF,wBAAsB,eAAe,CACnC,OAAO,SAA2B,GACjC,OAAO,CAAC,UAAU,CAAC,CA4KrB;AAUD,KAAK,eAAe,GAChB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,GAC1C;IAAE,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAC7B;IACE,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACjE,GACD,YAAY,CAAC;AAEjB,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,CAAC,EAAE,eAAe,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;CAC9B,CAAC;AA6BF,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,MAAM,EAAE,YAAY,GACnB,OAAO,CAUT"}