@cogenta/agents 0.1.2 → 0.2.1
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/assist/chat.d.ts +69 -0
- package/dist/assist/chat.d.ts.map +1 -0
- package/dist/assist/chat.js +108 -0
- package/dist/assist/chat.js.map +1 -0
- package/dist/assist/classify.d.ts +101 -0
- package/dist/assist/classify.d.ts.map +1 -0
- package/dist/assist/classify.js +233 -0
- package/dist/assist/classify.js.map +1 -0
- package/dist/assist/faq.d.ts +61 -0
- package/dist/assist/faq.d.ts.map +1 -0
- package/dist/assist/faq.js +136 -0
- package/dist/assist/faq.js.map +1 -0
- package/dist/assist/images.d.ts +45 -0
- package/dist/assist/images.d.ts.map +1 -0
- package/dist/assist/images.js +79 -0
- package/dist/assist/images.js.map +1 -0
- package/dist/assist/runtime.d.ts +58 -0
- package/dist/assist/runtime.d.ts.map +1 -0
- package/dist/assist/runtime.js +84 -0
- package/dist/assist/runtime.js.map +1 -0
- package/dist/assist/suggestion.d.ts +20 -0
- package/dist/assist/suggestion.d.ts.map +1 -0
- package/dist/assist/suggestion.js +28 -0
- package/dist/assist/suggestion.js.map +1 -0
- package/dist/assist/toolset.d.ts +76 -0
- package/dist/assist/toolset.d.ts.map +1 -0
- package/dist/assist/toolset.js +72 -0
- package/dist/assist/toolset.js.map +1 -0
- package/dist/assist/writing.d.ts +74 -0
- package/dist/assist/writing.d.ts.map +1 -0
- package/dist/assist/writing.js +429 -0
- package/dist/assist/writing.js.map +1 -0
- package/dist/documents/docx.d.ts +6 -0
- package/dist/documents/docx.d.ts.map +1 -0
- package/dist/documents/docx.js +169 -0
- package/dist/documents/docx.js.map +1 -0
- package/dist/documents/extract-text.d.ts +35 -0
- package/dist/documents/extract-text.d.ts.map +1 -0
- package/dist/documents/extract-text.js +134 -0
- package/dist/documents/extract-text.js.map +1 -0
- package/dist/documents/extract-tool.d.ts +40 -0
- package/dist/documents/extract-tool.d.ts.map +1 -0
- package/dist/documents/extract-tool.js +65 -0
- package/dist/documents/extract-tool.js.map +1 -0
- package/dist/documents/limits.d.ts +23 -0
- package/dist/documents/limits.d.ts.map +1 -0
- package/dist/documents/limits.js +23 -0
- package/dist/documents/limits.js.map +1 -0
- package/dist/documents/pdf.d.ts +26 -0
- package/dist/documents/pdf.d.ts.map +1 -0
- package/dist/documents/pdf.js +478 -0
- package/dist/documents/pdf.js.map +1 -0
- package/dist/documents/zip.d.ts +18 -0
- package/dist/documents/zip.d.ts.map +1 -0
- package/dist/documents/zip.js +113 -0
- package/dist/documents/zip.js.map +1 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/image/openai.d.ts +28 -0
- package/dist/providers/image/openai.d.ts.map +1 -0
- package/dist/providers/image/openai.js +80 -0
- package/dist/providers/image/openai.js.map +1 -0
- package/dist/providers/image/registry.d.ts +30 -0
- package/dist/providers/image/registry.d.ts.map +1 -0
- package/dist/providers/image/registry.js +36 -0
- package/dist/providers/image/registry.js.map +1 -0
- package/dist/providers/image/stability.d.ts +39 -0
- package/dist/providers/image/stability.d.ts.map +1 -0
- package/dist/providers/image/stability.js +88 -0
- package/dist/providers/image/stability.js.map +1 -0
- package/dist/providers/image/types.d.ts +50 -0
- package/dist/providers/image/types.d.ts.map +1 -0
- package/dist/providers/image/types.js +33 -0
- package/dist/providers/image/types.js.map +1 -0
- package/dist/rag/semantic/search.d.ts +84 -0
- package/dist/rag/semantic/search.d.ts.map +1 -0
- package/dist/rag/semantic/search.js +113 -0
- package/dist/rag/semantic/search.js.map +1 -0
- package/dist/rag/vector/file.d.ts +23 -0
- package/dist/rag/vector/file.d.ts.map +1 -0
- package/dist/rag/vector/file.js +170 -0
- package/dist/rag/vector/file.js.map +1 -0
- package/dist/rag/vector/index.d.ts +24 -0
- package/dist/rag/vector/index.d.ts.map +1 -0
- package/dist/rag/vector/index.js +27 -0
- package/dist/rag/vector/index.js.map +1 -0
- package/dist/rag/vector/memory.d.ts +16 -0
- package/dist/rag/vector/memory.d.ts.map +1 -0
- package/dist/rag/vector/memory.js +107 -0
- package/dist/rag/vector/memory.js.map +1 -0
- package/dist/rag/vector/pgvector.d.ts +34 -0
- package/dist/rag/vector/pgvector.d.ts.map +1 -0
- package/dist/rag/vector/pgvector.js +273 -0
- package/dist/rag/vector/pgvector.js.map +1 -0
- package/dist/rag/vector/types.d.ts +113 -0
- package/dist/rag/vector/types.d.ts.map +1 -0
- package/dist/rag/vector/types.js +51 -0
- package/dist/rag/vector/types.js.map +1 -0
- package/dist/site-plan/analyse-brief.d.ts +23 -0
- package/dist/site-plan/analyse-brief.d.ts.map +1 -0
- package/dist/site-plan/analyse-brief.js +207 -0
- package/dist/site-plan/analyse-brief.js.map +1 -0
- package/dist/site-plan/approval.d.ts +80 -0
- package/dist/site-plan/approval.d.ts.map +1 -0
- package/dist/site-plan/approval.js +201 -0
- package/dist/site-plan/approval.js.map +1 -0
- package/dist/site-plan/constraints.d.ts +45 -0
- package/dist/site-plan/constraints.d.ts.map +1 -0
- package/dist/site-plan/constraints.js +213 -0
- package/dist/site-plan/constraints.js.map +1 -0
- package/dist/site-plan/content-model.d.ts +22 -0
- package/dist/site-plan/content-model.d.ts.map +1 -0
- package/dist/site-plan/content-model.js +385 -0
- package/dist/site-plan/content-model.js.map +1 -0
- package/dist/site-plan/demo-content.d.ts +27 -0
- package/dist/site-plan/demo-content.d.ts.map +1 -0
- package/dist/site-plan/demo-content.js +170 -0
- package/dist/site-plan/demo-content.js.map +1 -0
- package/dist/site-plan/draft-store.d.ts +37 -0
- package/dist/site-plan/draft-store.d.ts.map +1 -0
- package/dist/site-plan/draft-store.js +117 -0
- package/dist/site-plan/draft-store.js.map +1 -0
- package/dist/site-plan/enforce.d.ts +17 -0
- package/dist/site-plan/enforce.d.ts.map +1 -0
- package/dist/site-plan/enforce.js +120 -0
- package/dist/site-plan/enforce.js.map +1 -0
- package/dist/site-plan/json.d.ts +9 -0
- package/dist/site-plan/json.d.ts.map +1 -0
- package/dist/site-plan/json.js +29 -0
- package/dist/site-plan/json.js.map +1 -0
- package/dist/site-plan/propose-plan.d.ts +43 -0
- package/dist/site-plan/propose-plan.d.ts.map +1 -0
- package/dist/site-plan/propose-plan.js +65 -0
- package/dist/site-plan/propose-plan.js.map +1 -0
- package/dist/site-plan/skin-candidates.d.ts +61 -0
- package/dist/site-plan/skin-candidates.d.ts.map +1 -0
- package/dist/site-plan/skin-candidates.js +99 -0
- package/dist/site-plan/skin-candidates.js.map +1 -0
- package/dist/site-plan/types.d.ts +93 -0
- package/dist/site-plan/types.d.ts.map +1 -0
- package/dist/site-plan/types.js +2 -0
- package/dist/site-plan/types.js.map +1 -0
- package/package.json +4 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/rag/vector/memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type DatabaseHandle, type Driver } from '@cogenta/core';
|
|
2
|
+
import { type VectorConfig, type VectorStore } from './types.js';
|
|
3
|
+
export interface PgVectorOptions {
|
|
4
|
+
readonly db: DatabaseHandle;
|
|
5
|
+
readonly dimensions: number;
|
|
6
|
+
readonly table?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A pgvector literal.
|
|
10
|
+
*
|
|
11
|
+
* Bound as a parameter and cast in SQL (`$1::vector`), never interpolated: the
|
|
12
|
+
* numbers come from an embedding provider, which is code, but "it came from code
|
|
13
|
+
* this time" is not a property that survives a refactor. Non-finite values are
|
|
14
|
+
* refused rather than serialised — `NaN` in a vector column silently poisons
|
|
15
|
+
* every distance it takes part in.
|
|
16
|
+
*/
|
|
17
|
+
export declare function vectorLiteral(vector: readonly number[]): string;
|
|
18
|
+
/**
|
|
19
|
+
* The optimal tier for the `vector` need — the row `docs/02-architecture.md`
|
|
20
|
+
* already named ("pgvector") and nothing implemented until L18.
|
|
21
|
+
*
|
|
22
|
+
* Distance is cosine (`<=>`), and the score handed back is `1 - distance`, so
|
|
23
|
+
* it is the same cosine similarity the memory and file drivers return: the
|
|
24
|
+
* shared contract suite compares the *same* numbers across all three, which is
|
|
25
|
+
* the only way "swap the driver, change nothing else" is a claim rather than a
|
|
26
|
+
* hope.
|
|
27
|
+
*/
|
|
28
|
+
export declare function createPgVectorStore(options: PgVectorOptions): Promise<VectorStore>;
|
|
29
|
+
export interface PgVectorDriverOptions {
|
|
30
|
+
/** Absent means "this site has no database handle to lend", and the driver simply is not available. */
|
|
31
|
+
readonly db?: DatabaseHandle;
|
|
32
|
+
}
|
|
33
|
+
export declare function pgVectorDriver(options?: PgVectorDriverOptions): Driver<VectorStore, VectorConfig>;
|
|
34
|
+
//# sourceMappingURL=pgvector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pgvector.d.ts","sourceRoot":"","sources":["../../../src/rag/vector/pgvector.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,MAAM,EAOZ,MAAM,eAAe,CAAA;AACtB,OAAO,EAEL,KAAK,YAAY,EAKjB,KAAK,WAAW,EACjB,MAAM,YAAY,CAAA;AAInB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACxB;AAgBD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAW/D;AA+CD;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC,CA0JxF;AAED,MAAM,WAAW,qBAAqB;IACpC,uGAAuG;IACvG,QAAQ,CAAC,EAAE,CAAC,EAAE,cAAc,CAAA;CAC7B;AAED,wBAAgB,cAAc,CAC5B,OAAO,GAAE,qBAA0B,GAClC,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,CAiDnC"}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { CogentaError, identifier, sql, limit as sqlLimit, unsafeRaw, } from '@cogenta/core';
|
|
2
|
+
import { VECTOR_DEFAULTS, } from './types.js';
|
|
3
|
+
const DEFAULT_TABLE = 'cogenta_vectors';
|
|
4
|
+
/**
|
|
5
|
+
* A pgvector literal.
|
|
6
|
+
*
|
|
7
|
+
* Bound as a parameter and cast in SQL (`$1::vector`), never interpolated: the
|
|
8
|
+
* numbers come from an embedding provider, which is code, but "it came from code
|
|
9
|
+
* this time" is not a property that survives a refactor. Non-finite values are
|
|
10
|
+
* refused rather than serialised — `NaN` in a vector column silently poisons
|
|
11
|
+
* every distance it takes part in.
|
|
12
|
+
*/
|
|
13
|
+
export function vectorLiteral(vector) {
|
|
14
|
+
for (const value of vector) {
|
|
15
|
+
if (!Number.isFinite(value)) {
|
|
16
|
+
throw new CogentaError({
|
|
17
|
+
code: 'VECTOR_DIMENSION_MISMATCH',
|
|
18
|
+
message: 'An embedding contains a value that is not a finite number.',
|
|
19
|
+
hint: 'The embedding provider returned NaN or Infinity — re-embed the text, and check the provider response.',
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return `[${vector.join(',')}]`;
|
|
24
|
+
}
|
|
25
|
+
function whereFrom(filter) {
|
|
26
|
+
if (filter === undefined)
|
|
27
|
+
return sql `true`;
|
|
28
|
+
const clauses = [sql `true`];
|
|
29
|
+
if (filter.siteId !== undefined)
|
|
30
|
+
clauses.push(sql `site_id = ${filter.siteId}`);
|
|
31
|
+
if (filter.collections !== undefined) {
|
|
32
|
+
clauses.push(filter.collections.length === 0
|
|
33
|
+
? sql `false`
|
|
34
|
+
: sql `collection = any(${asTextArray(filter.collections)})`);
|
|
35
|
+
}
|
|
36
|
+
if (filter.locales !== undefined) {
|
|
37
|
+
clauses.push(filter.locales.length === 0 ? sql `false` : sql `locale = any(${asTextArray(filter.locales)})`);
|
|
38
|
+
}
|
|
39
|
+
if (filter.statuses !== undefined) {
|
|
40
|
+
clauses.push(filter.statuses.length === 0
|
|
41
|
+
? sql `false`
|
|
42
|
+
: sql `status = any(${asTextArray(filter.statuses)})`);
|
|
43
|
+
}
|
|
44
|
+
if (filter.excludeEntryIds !== undefined && filter.excludeEntryIds.length > 0) {
|
|
45
|
+
clauses.push(sql `not (entry_id = any(${asTextArray(filter.excludeEntryIds)}))`);
|
|
46
|
+
}
|
|
47
|
+
let combined = clauses[0] ?? sql `true`;
|
|
48
|
+
for (const clause of clauses.slice(1))
|
|
49
|
+
combined = sql `${combined} and ${clause}`;
|
|
50
|
+
return combined;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* `text[]` for `= any(…)`.
|
|
54
|
+
*
|
|
55
|
+
* `encodeValue` turns any array into JSON text, which Postgres will not accept
|
|
56
|
+
* as an array, so the values are bound one by one into an `array[…]`
|
|
57
|
+
* constructor instead. Still bound — no value ever reaches the SQL text.
|
|
58
|
+
*/
|
|
59
|
+
function asTextArray(values) {
|
|
60
|
+
let inner = sql `${values[0] ?? ''}::text`;
|
|
61
|
+
for (const value of values.slice(1))
|
|
62
|
+
inner = sql `${inner}, ${value}::text`;
|
|
63
|
+
return sql `array[${inner}]`;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The optimal tier for the `vector` need — the row `docs/02-architecture.md`
|
|
67
|
+
* already named ("pgvector") and nothing implemented until L18.
|
|
68
|
+
*
|
|
69
|
+
* Distance is cosine (`<=>`), and the score handed back is `1 - distance`, so
|
|
70
|
+
* it is the same cosine similarity the memory and file drivers return: the
|
|
71
|
+
* shared contract suite compares the *same* numbers across all three, which is
|
|
72
|
+
* the only way "swap the driver, change nothing else" is a claim rather than a
|
|
73
|
+
* hope.
|
|
74
|
+
*/
|
|
75
|
+
export async function createPgVectorStore(options) {
|
|
76
|
+
const { db, dimensions } = options;
|
|
77
|
+
const table = options.table ?? DEFAULT_TABLE;
|
|
78
|
+
if (db.dialect !== 'postgres') {
|
|
79
|
+
throw new CogentaError({
|
|
80
|
+
code: 'DB_DIALECT_UNSUPPORTED',
|
|
81
|
+
message: `The pgvector store needs Postgres and this site is on ${db.dialect}.`,
|
|
82
|
+
hint: 'Use the file or memory vector driver, or move the site to Postgres with the pgvector extension.',
|
|
83
|
+
details: { dialect: db.dialect },
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
const name = identifier(table, 'postgres');
|
|
87
|
+
await db.query(sql `create extension if not exists vector`);
|
|
88
|
+
await db.query(sql `
|
|
89
|
+
create table if not exists ${name} (
|
|
90
|
+
chunk_id text primary key,
|
|
91
|
+
site_id text not null,
|
|
92
|
+
collection text not null,
|
|
93
|
+
entry_id text not null,
|
|
94
|
+
locale text not null,
|
|
95
|
+
status text not null,
|
|
96
|
+
document_id text not null,
|
|
97
|
+
block_ids text not null,
|
|
98
|
+
chunk_text text not null,
|
|
99
|
+
chunk_hash text not null,
|
|
100
|
+
embedding vector(${unsafeRaw(String(Math.trunc(dimensions)))}) not null
|
|
101
|
+
)
|
|
102
|
+
`);
|
|
103
|
+
await db.query(sql `
|
|
104
|
+
create index if not exists ${identifier(`${table}_scope`, 'postgres')}
|
|
105
|
+
on ${name} (site_id, collection, entry_id)
|
|
106
|
+
`);
|
|
107
|
+
function assertDimensions(record) {
|
|
108
|
+
if (record.vector.length === dimensions)
|
|
109
|
+
return;
|
|
110
|
+
throw new CogentaError({
|
|
111
|
+
code: 'VECTOR_DIMENSION_MISMATCH',
|
|
112
|
+
message: `This store holds ${dimensions}-dimension vectors and was handed one of ${record.vector.length}.`,
|
|
113
|
+
hint: 'Changing embedding model means a new, parallel index — never mixing two models in one store. Re-index from scratch after a model change.',
|
|
114
|
+
details: { expected: dimensions, received: record.vector.length, chunkId: record.chunk.id },
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function toRecord(row) {
|
|
118
|
+
return {
|
|
119
|
+
siteId: row.site_id,
|
|
120
|
+
collection: row.collection,
|
|
121
|
+
entryId: row.entry_id,
|
|
122
|
+
locale: row.locale,
|
|
123
|
+
status: row.status,
|
|
124
|
+
chunk: {
|
|
125
|
+
id: row.chunk_id,
|
|
126
|
+
documentId: row.document_id,
|
|
127
|
+
blockIds: JSON.parse(row.block_ids),
|
|
128
|
+
text: row.chunk_text,
|
|
129
|
+
hash: row.chunk_hash,
|
|
130
|
+
},
|
|
131
|
+
// Not selected: a search result is used for its text and its score, and
|
|
132
|
+
// pulling every embedding back over the wire to hand it to a caller that
|
|
133
|
+
// discards it is pure cost. `upsert` is the only thing that needs the
|
|
134
|
+
// numbers, and it already has them.
|
|
135
|
+
vector: [],
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
dimensions,
|
|
140
|
+
async upsert(records) {
|
|
141
|
+
for (const record of records)
|
|
142
|
+
assertDimensions(record);
|
|
143
|
+
if (records.length === 0)
|
|
144
|
+
return;
|
|
145
|
+
await db.transaction(async (tx) => {
|
|
146
|
+
for (const record of records) {
|
|
147
|
+
await tx.query(sql `
|
|
148
|
+
insert into ${name}
|
|
149
|
+
(chunk_id, site_id, collection, entry_id, locale, status,
|
|
150
|
+
document_id, block_ids, chunk_text, chunk_hash, embedding)
|
|
151
|
+
values (
|
|
152
|
+
${record.chunk.id}, ${record.siteId}, ${record.collection}, ${record.entryId},
|
|
153
|
+
${record.locale}, ${record.status}, ${record.chunk.documentId},
|
|
154
|
+
${JSON.stringify([...record.chunk.blockIds])}, ${record.chunk.text},
|
|
155
|
+
${record.chunk.hash}, ${vectorLiteral([...record.vector])}::vector
|
|
156
|
+
)
|
|
157
|
+
on conflict (chunk_id) do update set
|
|
158
|
+
site_id = excluded.site_id,
|
|
159
|
+
collection = excluded.collection,
|
|
160
|
+
entry_id = excluded.entry_id,
|
|
161
|
+
locale = excluded.locale,
|
|
162
|
+
status = excluded.status,
|
|
163
|
+
document_id = excluded.document_id,
|
|
164
|
+
block_ids = excluded.block_ids,
|
|
165
|
+
chunk_text = excluded.chunk_text,
|
|
166
|
+
chunk_hash = excluded.chunk_hash,
|
|
167
|
+
embedding = excluded.embedding
|
|
168
|
+
`);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
},
|
|
172
|
+
async remove(chunkIds) {
|
|
173
|
+
if (chunkIds.length === 0)
|
|
174
|
+
return;
|
|
175
|
+
await db.query(sql `delete from ${name} where chunk_id = any(${asTextArray([...chunkIds])})`);
|
|
176
|
+
},
|
|
177
|
+
async removeEntries(scope) {
|
|
178
|
+
if (scope.entryIds.length === 0)
|
|
179
|
+
return;
|
|
180
|
+
await db.query(sql `
|
|
181
|
+
delete from ${name}
|
|
182
|
+
where site_id = ${scope.siteId}
|
|
183
|
+
and collection = ${scope.collection}
|
|
184
|
+
and entry_id = any(${asTextArray([...scope.entryIds])})
|
|
185
|
+
`);
|
|
186
|
+
},
|
|
187
|
+
async search(queryVector, searchOptions) {
|
|
188
|
+
const count = searchOptions?.limit ?? VECTOR_DEFAULTS.limit;
|
|
189
|
+
const literal = vectorLiteral([...queryVector]);
|
|
190
|
+
const result = await db.query(sql `
|
|
191
|
+
select chunk_id, site_id, collection, entry_id, locale, status,
|
|
192
|
+
document_id, block_ids, chunk_text, chunk_hash,
|
|
193
|
+
1 - (embedding <=> ${literal}::vector) as score
|
|
194
|
+
from ${name}
|
|
195
|
+
where ${whereFrom(searchOptions?.filter)}
|
|
196
|
+
order by embedding <=> ${literal}::vector
|
|
197
|
+
limit ${sqlLimit(count)}
|
|
198
|
+
`);
|
|
199
|
+
const minScore = searchOptions?.minScore;
|
|
200
|
+
const matches = [];
|
|
201
|
+
for (const row of result.rows) {
|
|
202
|
+
const score = Number(row.score);
|
|
203
|
+
// The memory driver drops a zero or negative similarity; matching that
|
|
204
|
+
// here is what keeps the contract suite's expectations identical.
|
|
205
|
+
if (score <= 0)
|
|
206
|
+
continue;
|
|
207
|
+
if (minScore !== undefined && score < minScore)
|
|
208
|
+
continue;
|
|
209
|
+
matches.push({ record: toRecord(row), score });
|
|
210
|
+
}
|
|
211
|
+
return matches;
|
|
212
|
+
},
|
|
213
|
+
async count(filter) {
|
|
214
|
+
const result = await db.query(sql `select count(*) as total from ${name} where ${whereFrom(filter)}`);
|
|
215
|
+
return Number(result.rows[0]?.total ?? 0);
|
|
216
|
+
},
|
|
217
|
+
async clear() {
|
|
218
|
+
await db.query(sql `delete from ${name}`);
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
export function pgVectorDriver(options = {}) {
|
|
223
|
+
let store = null;
|
|
224
|
+
return {
|
|
225
|
+
name: 'pgvector',
|
|
226
|
+
tier: 'optimal',
|
|
227
|
+
available: async () => {
|
|
228
|
+
const db = options.db;
|
|
229
|
+
if (db === undefined || db.dialect !== 'postgres')
|
|
230
|
+
return false;
|
|
231
|
+
// "Does the service actually answer?", not "is a URL configured?" — the
|
|
232
|
+
// extension has to be installable, which on a managed Postgres it may
|
|
233
|
+
// well not be, and finding that out at `create table` time would be a
|
|
234
|
+
// startup crash instead of a fallback.
|
|
235
|
+
try {
|
|
236
|
+
await db.query(sql `create extension if not exists vector`);
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
init: async (config) => {
|
|
244
|
+
const db = options.db;
|
|
245
|
+
if (db === undefined) {
|
|
246
|
+
throw new CogentaError({
|
|
247
|
+
code: 'DRIVER_INIT_FAILED',
|
|
248
|
+
message: 'The pgvector driver was selected without a database handle.',
|
|
249
|
+
hint: 'Pass the site database to pgVectorDriver({ db }) when building the vector registry.',
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
store = await createPgVectorStore({
|
|
253
|
+
db,
|
|
254
|
+
dimensions: config.dimensions,
|
|
255
|
+
...(config.table === undefined ? {} : { table: config.table }),
|
|
256
|
+
});
|
|
257
|
+
return store;
|
|
258
|
+
},
|
|
259
|
+
dispose: async () => {
|
|
260
|
+
// The handle belongs to the site, not to this driver: closing it here
|
|
261
|
+
// would take the whole CMS down with the vector index.
|
|
262
|
+
store = null;
|
|
263
|
+
},
|
|
264
|
+
health: async () => ({
|
|
265
|
+
status: 'ok',
|
|
266
|
+
driver: 'pgvector',
|
|
267
|
+
tier: 'optimal',
|
|
268
|
+
message: 'Embeddings are stored in Postgres with the pgvector extension.',
|
|
269
|
+
...(store === null ? {} : { details: { records: await store.count() } }),
|
|
270
|
+
}),
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=pgvector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pgvector.js","sourceRoot":"","sources":["../../../src/rag/vector/pgvector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `vector` driver need — L18 task 1 and task 5.
|
|
3
|
+
*
|
|
4
|
+
* **Task 1 was to check what already exists before writing anything, and the
|
|
5
|
+
* answer changed the shape of this file.** What was found:
|
|
6
|
+
*
|
|
7
|
+
* - `docs/02-architecture.md` names `vector` in the driver row ("pgvector,
|
|
8
|
+
* MariaDB VECTOR | Cosinus exact en mémoire") and in the driver list of the
|
|
9
|
+
* layer diagram — planned, never implemented.
|
|
10
|
+
* - `packages/core/src/drivers/` has the generic registry (`Driver`,
|
|
11
|
+
* `createDriverRegistry`) that cache/queue/storage/database are all built on,
|
|
12
|
+
* but **no** `vector` need registered anywhere.
|
|
13
|
+
* - `@cogenta/agents` already ships, from L4, the *retrieval* half: an
|
|
14
|
+
* `EmbeddingProvider` interface with a real local implementation
|
|
15
|
+
* (`createHashingEmbeddingProvider`), and a whole hybrid index —
|
|
16
|
+
* `createMemoryRagIndex`, `bm25Rank`, `vectorRank`, `reciprocalRankFusion`,
|
|
17
|
+
* with query-time permission filtering.
|
|
18
|
+
* - `packages/core/src/config/schema.ts` already has an `embeddings` section
|
|
19
|
+
* (`provider`/`model`/`dimensions`).
|
|
20
|
+
*
|
|
21
|
+
* So the missing piece was never "a way to rank vectors" — that exists and is
|
|
22
|
+
* tested. It was **a place to keep them that outlives the process**, and a
|
|
23
|
+
* driver registry to pick between such places. That is exactly what this
|
|
24
|
+
* interface is, and nothing here re-implements cosine similarity: the memory
|
|
25
|
+
* driver calls the existing `vectorRank`.
|
|
26
|
+
*
|
|
27
|
+
* The interface is async where `RagIndex` is sync, because a store that reaches
|
|
28
|
+
* a database cannot be anything else. `RagIndex` is deliberately left alone: it
|
|
29
|
+
* is the in-request ranking primitive, this is the persistence one.
|
|
30
|
+
*/
|
|
31
|
+
import type { Chunk } from '../chunking/types.js';
|
|
32
|
+
/**
|
|
33
|
+
* The scope every record carries, and the only thing a store may filter on.
|
|
34
|
+
*
|
|
35
|
+
* Deliberately not "any metadata": a store that accepts arbitrary filter
|
|
36
|
+
* predicates has to implement them per backend, and the ones that matter for a
|
|
37
|
+
* CMS are exactly these. Anything finer is the caller's `canAccess` predicate,
|
|
38
|
+
* applied above the store, where the real permission layer lives.
|
|
39
|
+
*/
|
|
40
|
+
export interface VectorScope {
|
|
41
|
+
readonly siteId: string;
|
|
42
|
+
readonly collection: string;
|
|
43
|
+
readonly entryId: string;
|
|
44
|
+
readonly locale: string;
|
|
45
|
+
/** `draft` / `published` / … — mirrors `ContentStatus` without importing `@cogenta/schema`. */
|
|
46
|
+
readonly status: string;
|
|
47
|
+
}
|
|
48
|
+
export interface VectorRecord extends VectorScope {
|
|
49
|
+
readonly chunk: Chunk;
|
|
50
|
+
readonly vector: readonly number[];
|
|
51
|
+
}
|
|
52
|
+
export interface VectorFilter {
|
|
53
|
+
readonly siteId?: string;
|
|
54
|
+
readonly collections?: readonly string[];
|
|
55
|
+
readonly locales?: readonly string[];
|
|
56
|
+
readonly statuses?: readonly string[];
|
|
57
|
+
/** Excludes one entry from its own results — what duplicate detection needs. */
|
|
58
|
+
readonly excludeEntryIds?: readonly string[];
|
|
59
|
+
}
|
|
60
|
+
export interface VectorMatch {
|
|
61
|
+
readonly record: VectorRecord;
|
|
62
|
+
/** Cosine similarity in `[-1, 1]`, comparable across backends because every backend computes cosine. */
|
|
63
|
+
readonly score: number;
|
|
64
|
+
}
|
|
65
|
+
export interface VectorSearchOptions {
|
|
66
|
+
readonly limit?: number;
|
|
67
|
+
readonly filter?: VectorFilter;
|
|
68
|
+
/**
|
|
69
|
+
* Discards matches below this cosine similarity. Absent means "keep
|
|
70
|
+
* everything the limit allows" — a threshold is a product decision (how close
|
|
71
|
+
* is "a duplicate"?), never a default this layer invents.
|
|
72
|
+
*/
|
|
73
|
+
readonly minScore?: number;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Where embeddings live between requests.
|
|
77
|
+
*
|
|
78
|
+
* `dimensions` is on the store, not on each call, and `upsert` refuses a vector
|
|
79
|
+
* of any other length: an index holding two models' vectors ranks nonsense with
|
|
80
|
+
* no error anywhere, which is the single worst failure mode of this subsystem.
|
|
81
|
+
* The L4 rule stands unchanged — changing model means a parallel index, not a
|
|
82
|
+
* mixed one.
|
|
83
|
+
*/
|
|
84
|
+
export interface VectorStore {
|
|
85
|
+
readonly dimensions: number;
|
|
86
|
+
upsert(records: readonly VectorRecord[]): Promise<void>;
|
|
87
|
+
/** By chunk id. Unknown ids are ignored, not an error — a re-ingest must be idempotent. */
|
|
88
|
+
remove(chunkIds: readonly string[]): Promise<void>;
|
|
89
|
+
/** Everything belonging to these entries, whatever their chunk ids are. */
|
|
90
|
+
removeEntries(scope: {
|
|
91
|
+
readonly siteId: string;
|
|
92
|
+
readonly collection: string;
|
|
93
|
+
readonly entryIds: readonly string[];
|
|
94
|
+
}): Promise<void>;
|
|
95
|
+
search(queryVector: readonly number[], options?: VectorSearchOptions): Promise<readonly VectorMatch[]>;
|
|
96
|
+
count(filter?: VectorFilter): Promise<number>;
|
|
97
|
+
clear(): Promise<void>;
|
|
98
|
+
}
|
|
99
|
+
/** The resolved `vector` section of the configuration — same shape family as `CacheConfig`. */
|
|
100
|
+
export interface VectorConfig {
|
|
101
|
+
readonly driver?: string;
|
|
102
|
+
readonly dimensions: number;
|
|
103
|
+
/** Where the `file` driver keeps its records. */
|
|
104
|
+
readonly path?: string;
|
|
105
|
+
/** Table name for the `pgvector` driver. */
|
|
106
|
+
readonly table?: string;
|
|
107
|
+
}
|
|
108
|
+
export declare const VECTOR_DEFAULTS: Readonly<{
|
|
109
|
+
limit: 10;
|
|
110
|
+
}>;
|
|
111
|
+
/** Shared by every driver so "which records are in scope" cannot drift between them. */
|
|
112
|
+
export declare function matchesFilter(record: VectorRecord, filter?: VectorFilter): boolean;
|
|
113
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/rag/vector/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAEjD;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,+FAA+F;IAC/F,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CACnC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACxC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC,gFAAgF;IAChF,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC7C;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;IAC7B,wGAAwG;IACxG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAA;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,MAAM,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACvD,2FAA2F;IAC3F,MAAM,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAClD,2EAA2E;IAC3E,aAAa,CAAC,KAAK,EAAE;QACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;QACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;QAC3B,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;KACrC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjB,MAAM,CACJ,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAAA;IAClC,KAAK,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED,+FAA+F;AAC/F,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACxB;AAID,eAAO,MAAM,eAAe;;EAA0C,CAAA;AAEtE,wFAAwF;AACxF,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAYlF"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `vector` driver need — L18 task 1 and task 5.
|
|
3
|
+
*
|
|
4
|
+
* **Task 1 was to check what already exists before writing anything, and the
|
|
5
|
+
* answer changed the shape of this file.** What was found:
|
|
6
|
+
*
|
|
7
|
+
* - `docs/02-architecture.md` names `vector` in the driver row ("pgvector,
|
|
8
|
+
* MariaDB VECTOR | Cosinus exact en mémoire") and in the driver list of the
|
|
9
|
+
* layer diagram — planned, never implemented.
|
|
10
|
+
* - `packages/core/src/drivers/` has the generic registry (`Driver`,
|
|
11
|
+
* `createDriverRegistry`) that cache/queue/storage/database are all built on,
|
|
12
|
+
* but **no** `vector` need registered anywhere.
|
|
13
|
+
* - `@cogenta/agents` already ships, from L4, the *retrieval* half: an
|
|
14
|
+
* `EmbeddingProvider` interface with a real local implementation
|
|
15
|
+
* (`createHashingEmbeddingProvider`), and a whole hybrid index —
|
|
16
|
+
* `createMemoryRagIndex`, `bm25Rank`, `vectorRank`, `reciprocalRankFusion`,
|
|
17
|
+
* with query-time permission filtering.
|
|
18
|
+
* - `packages/core/src/config/schema.ts` already has an `embeddings` section
|
|
19
|
+
* (`provider`/`model`/`dimensions`).
|
|
20
|
+
*
|
|
21
|
+
* So the missing piece was never "a way to rank vectors" — that exists and is
|
|
22
|
+
* tested. It was **a place to keep them that outlives the process**, and a
|
|
23
|
+
* driver registry to pick between such places. That is exactly what this
|
|
24
|
+
* interface is, and nothing here re-implements cosine similarity: the memory
|
|
25
|
+
* driver calls the existing `vectorRank`.
|
|
26
|
+
*
|
|
27
|
+
* The interface is async where `RagIndex` is sync, because a store that reaches
|
|
28
|
+
* a database cannot be anything else. `RagIndex` is deliberately left alone: it
|
|
29
|
+
* is the in-request ranking primitive, this is the persistence one.
|
|
30
|
+
*/
|
|
31
|
+
const DEFAULT_LIMIT = 10;
|
|
32
|
+
export const VECTOR_DEFAULTS = Object.freeze({ limit: DEFAULT_LIMIT });
|
|
33
|
+
/** Shared by every driver so "which records are in scope" cannot drift between them. */
|
|
34
|
+
export function matchesFilter(record, filter) {
|
|
35
|
+
if (filter === undefined)
|
|
36
|
+
return true;
|
|
37
|
+
if (filter.siteId !== undefined && record.siteId !== filter.siteId)
|
|
38
|
+
return false;
|
|
39
|
+
if (filter.collections !== undefined && !filter.collections.includes(record.collection)) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
if (filter.locales !== undefined && !filter.locales.includes(record.locale))
|
|
43
|
+
return false;
|
|
44
|
+
if (filter.statuses !== undefined && !filter.statuses.includes(record.status))
|
|
45
|
+
return false;
|
|
46
|
+
if (filter.excludeEntryIds !== undefined && filter.excludeEntryIds.includes(record.entryId)) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/rag/vector/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AA0FH,MAAM,aAAa,GAAG,EAAE,CAAA;AAExB,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAA;AAEtE,wFAAwF;AACxF,MAAM,UAAU,aAAa,CAAC,MAAoB,EAAE,MAAqB;IACvE,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IACrC,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IAChF,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;QACxF,OAAO,KAAK,CAAA;IACd,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAA;IACzF,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAA;IAC3F,IAAI,MAAM,CAAC,eAAe,KAAK,SAAS,IAAI,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5F,OAAO,KAAK,CAAA;IACd,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ExtractedDocument } from '../documents/extract-text.js';
|
|
2
|
+
import type { ProviderClient } from '../providers/types.js';
|
|
3
|
+
import type { SiteBrief } from './types.js';
|
|
4
|
+
export interface AnalyseBriefOptions {
|
|
5
|
+
readonly client: ProviderClient;
|
|
6
|
+
readonly model: string;
|
|
7
|
+
readonly documents: readonly ExtractedDocument[];
|
|
8
|
+
/** Shown to the model as context; never used to grant it anything. */
|
|
9
|
+
readonly siteName?: string;
|
|
10
|
+
/** "Trois tentatives" by default, the same budget `generateSkin` uses. */
|
|
11
|
+
readonly maxAttempts?: number;
|
|
12
|
+
}
|
|
13
|
+
export type AnalyseBriefResult = {
|
|
14
|
+
readonly ok: true;
|
|
15
|
+
readonly brief: SiteBrief;
|
|
16
|
+
readonly attempts: number;
|
|
17
|
+
} | {
|
|
18
|
+
readonly ok: false;
|
|
19
|
+
readonly attempts: number;
|
|
20
|
+
readonly reason: string;
|
|
21
|
+
};
|
|
22
|
+
export declare function analyseBrief(options: AnalyseBriefOptions): Promise<AnalyseBriefResult>;
|
|
23
|
+
//# sourceMappingURL=analyse-brief.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyse-brief.d.ts","sourceRoot":"","sources":["../../src/site-plan/analyse-brief.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAErE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAK3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAgD3C,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,SAAS,EAAE,SAAS,iBAAiB,EAAE,CAAA;IAChD,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,0EAA0E;IAC1E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC3E;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAwE9E,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA2G5F"}
|