@cogenta/agents 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/dist/assist/chat.d.ts +69 -0
  2. package/dist/assist/chat.d.ts.map +1 -0
  3. package/dist/assist/chat.js +108 -0
  4. package/dist/assist/chat.js.map +1 -0
  5. package/dist/assist/classify.d.ts +101 -0
  6. package/dist/assist/classify.d.ts.map +1 -0
  7. package/dist/assist/classify.js +233 -0
  8. package/dist/assist/classify.js.map +1 -0
  9. package/dist/assist/faq.d.ts +61 -0
  10. package/dist/assist/faq.d.ts.map +1 -0
  11. package/dist/assist/faq.js +136 -0
  12. package/dist/assist/faq.js.map +1 -0
  13. package/dist/assist/images.d.ts +45 -0
  14. package/dist/assist/images.d.ts.map +1 -0
  15. package/dist/assist/images.js +79 -0
  16. package/dist/assist/images.js.map +1 -0
  17. package/dist/assist/runtime.d.ts +58 -0
  18. package/dist/assist/runtime.d.ts.map +1 -0
  19. package/dist/assist/runtime.js +84 -0
  20. package/dist/assist/runtime.js.map +1 -0
  21. package/dist/assist/suggestion.d.ts +20 -0
  22. package/dist/assist/suggestion.d.ts.map +1 -0
  23. package/dist/assist/suggestion.js +28 -0
  24. package/dist/assist/suggestion.js.map +1 -0
  25. package/dist/assist/toolset.d.ts +76 -0
  26. package/dist/assist/toolset.d.ts.map +1 -0
  27. package/dist/assist/toolset.js +72 -0
  28. package/dist/assist/toolset.js.map +1 -0
  29. package/dist/assist/writing.d.ts +74 -0
  30. package/dist/assist/writing.d.ts.map +1 -0
  31. package/dist/assist/writing.js +429 -0
  32. package/dist/assist/writing.js.map +1 -0
  33. package/dist/documents/docx.d.ts +6 -0
  34. package/dist/documents/docx.d.ts.map +1 -0
  35. package/dist/documents/docx.js +169 -0
  36. package/dist/documents/docx.js.map +1 -0
  37. package/dist/documents/extract-text.d.ts +35 -0
  38. package/dist/documents/extract-text.d.ts.map +1 -0
  39. package/dist/documents/extract-text.js +134 -0
  40. package/dist/documents/extract-text.js.map +1 -0
  41. package/dist/documents/extract-tool.d.ts +40 -0
  42. package/dist/documents/extract-tool.d.ts.map +1 -0
  43. package/dist/documents/extract-tool.js +65 -0
  44. package/dist/documents/extract-tool.js.map +1 -0
  45. package/dist/documents/limits.d.ts +23 -0
  46. package/dist/documents/limits.d.ts.map +1 -0
  47. package/dist/documents/limits.js +23 -0
  48. package/dist/documents/limits.js.map +1 -0
  49. package/dist/documents/pdf.d.ts +26 -0
  50. package/dist/documents/pdf.d.ts.map +1 -0
  51. package/dist/documents/pdf.js +478 -0
  52. package/dist/documents/pdf.js.map +1 -0
  53. package/dist/documents/zip.d.ts +18 -0
  54. package/dist/documents/zip.d.ts.map +1 -0
  55. package/dist/documents/zip.js +113 -0
  56. package/dist/documents/zip.js.map +1 -0
  57. package/dist/index.d.ts +50 -0
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +25 -0
  60. package/dist/index.js.map +1 -1
  61. package/dist/providers/image/openai.d.ts +28 -0
  62. package/dist/providers/image/openai.d.ts.map +1 -0
  63. package/dist/providers/image/openai.js +80 -0
  64. package/dist/providers/image/openai.js.map +1 -0
  65. package/dist/providers/image/registry.d.ts +30 -0
  66. package/dist/providers/image/registry.d.ts.map +1 -0
  67. package/dist/providers/image/registry.js +36 -0
  68. package/dist/providers/image/registry.js.map +1 -0
  69. package/dist/providers/image/stability.d.ts +39 -0
  70. package/dist/providers/image/stability.d.ts.map +1 -0
  71. package/dist/providers/image/stability.js +88 -0
  72. package/dist/providers/image/stability.js.map +1 -0
  73. package/dist/providers/image/types.d.ts +50 -0
  74. package/dist/providers/image/types.d.ts.map +1 -0
  75. package/dist/providers/image/types.js +33 -0
  76. package/dist/providers/image/types.js.map +1 -0
  77. package/dist/rag/semantic/search.d.ts +84 -0
  78. package/dist/rag/semantic/search.d.ts.map +1 -0
  79. package/dist/rag/semantic/search.js +113 -0
  80. package/dist/rag/semantic/search.js.map +1 -0
  81. package/dist/rag/vector/file.d.ts +23 -0
  82. package/dist/rag/vector/file.d.ts.map +1 -0
  83. package/dist/rag/vector/file.js +170 -0
  84. package/dist/rag/vector/file.js.map +1 -0
  85. package/dist/rag/vector/index.d.ts +24 -0
  86. package/dist/rag/vector/index.d.ts.map +1 -0
  87. package/dist/rag/vector/index.js +27 -0
  88. package/dist/rag/vector/index.js.map +1 -0
  89. package/dist/rag/vector/memory.d.ts +16 -0
  90. package/dist/rag/vector/memory.d.ts.map +1 -0
  91. package/dist/rag/vector/memory.js +107 -0
  92. package/dist/rag/vector/memory.js.map +1 -0
  93. package/dist/rag/vector/pgvector.d.ts +34 -0
  94. package/dist/rag/vector/pgvector.d.ts.map +1 -0
  95. package/dist/rag/vector/pgvector.js +273 -0
  96. package/dist/rag/vector/pgvector.js.map +1 -0
  97. package/dist/rag/vector/types.d.ts +113 -0
  98. package/dist/rag/vector/types.d.ts.map +1 -0
  99. package/dist/rag/vector/types.js +51 -0
  100. package/dist/rag/vector/types.js.map +1 -0
  101. package/dist/site-plan/analyse-brief.d.ts +23 -0
  102. package/dist/site-plan/analyse-brief.d.ts.map +1 -0
  103. package/dist/site-plan/analyse-brief.js +207 -0
  104. package/dist/site-plan/analyse-brief.js.map +1 -0
  105. package/dist/site-plan/approval.d.ts +80 -0
  106. package/dist/site-plan/approval.d.ts.map +1 -0
  107. package/dist/site-plan/approval.js +201 -0
  108. package/dist/site-plan/approval.js.map +1 -0
  109. package/dist/site-plan/constraints.d.ts +45 -0
  110. package/dist/site-plan/constraints.d.ts.map +1 -0
  111. package/dist/site-plan/constraints.js +213 -0
  112. package/dist/site-plan/constraints.js.map +1 -0
  113. package/dist/site-plan/content-model.d.ts +22 -0
  114. package/dist/site-plan/content-model.d.ts.map +1 -0
  115. package/dist/site-plan/content-model.js +385 -0
  116. package/dist/site-plan/content-model.js.map +1 -0
  117. package/dist/site-plan/demo-content.d.ts +27 -0
  118. package/dist/site-plan/demo-content.d.ts.map +1 -0
  119. package/dist/site-plan/demo-content.js +170 -0
  120. package/dist/site-plan/demo-content.js.map +1 -0
  121. package/dist/site-plan/draft-store.d.ts +37 -0
  122. package/dist/site-plan/draft-store.d.ts.map +1 -0
  123. package/dist/site-plan/draft-store.js +117 -0
  124. package/dist/site-plan/draft-store.js.map +1 -0
  125. package/dist/site-plan/enforce.d.ts +17 -0
  126. package/dist/site-plan/enforce.d.ts.map +1 -0
  127. package/dist/site-plan/enforce.js +120 -0
  128. package/dist/site-plan/enforce.js.map +1 -0
  129. package/dist/site-plan/json.d.ts +9 -0
  130. package/dist/site-plan/json.d.ts.map +1 -0
  131. package/dist/site-plan/json.js +29 -0
  132. package/dist/site-plan/json.js.map +1 -0
  133. package/dist/site-plan/propose-plan.d.ts +43 -0
  134. package/dist/site-plan/propose-plan.d.ts.map +1 -0
  135. package/dist/site-plan/propose-plan.js +65 -0
  136. package/dist/site-plan/propose-plan.js.map +1 -0
  137. package/dist/site-plan/skin-candidates.d.ts +61 -0
  138. package/dist/site-plan/skin-candidates.d.ts.map +1 -0
  139. package/dist/site-plan/skin-candidates.js +99 -0
  140. package/dist/site-plan/skin-candidates.js.map +1 -0
  141. package/dist/site-plan/types.d.ts +93 -0
  142. package/dist/site-plan/types.d.ts.map +1 -0
  143. package/dist/site-plan/types.js +2 -0
  144. package/dist/site-plan/types.js.map +1 -0
  145. 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"}