@hraness/oh 0.2.7 → 0.3.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.
Files changed (55) hide show
  1. package/README.md +119 -12
  2. package/dist/canonical.d.ts.map +1 -1
  3. package/dist/cli.d.ts +1 -1
  4. package/dist/cli.js +91 -19
  5. package/dist/cloudflare-embedding.d.ts +104 -0
  6. package/dist/cloudflare-embedding.d.ts.map +1 -0
  7. package/dist/graph.d.ts.map +1 -1
  8. package/dist/index.js +90 -18
  9. package/dist/libsql-semantic.d.ts +130 -0
  10. package/dist/libsql-semantic.d.ts.map +1 -0
  11. package/dist/libsql.js +105 -18
  12. package/dist/memory-page.d.ts +2 -0
  13. package/dist/memory-page.d.ts.map +1 -0
  14. package/dist/memory-page.js +725 -0
  15. package/dist/memory-pages.d.ts +76 -0
  16. package/dist/memory-pages.d.ts.map +1 -0
  17. package/dist/memory.d.ts +1 -0
  18. package/dist/memory.d.ts.map +1 -1
  19. package/dist/memory.js +478 -18
  20. package/dist/projection-public.js +105 -18
  21. package/dist/projection-suss.js +105 -18
  22. package/dist/sdk.js +90 -18
  23. package/dist/semantic-cloud.d.ts +3 -0
  24. package/dist/semantic-cloud.d.ts.map +1 -0
  25. package/dist/semantic-cloud.js +1870 -0
  26. package/dist/semantic.d.ts.map +1 -1
  27. package/dist/semantic.js +104 -21
  28. package/dist/sqlite/index.js +90 -18
  29. package/dist/store.js +105 -18
  30. package/dist/sync.js +90 -18
  31. package/package.json +10 -2
  32. package/skills/oh/SKILL.md +28 -2
  33. package/spec/README.md +11 -3
  34. package/spec/manifest.json +9 -1
  35. package/spec/v1/cloudflare-embedding-profile.json +13 -0
  36. package/spec/v1/cloudflare-embedding-renderer.json +8 -0
  37. package/spec/v1/memory-page.md +153 -0
  38. package/spec/v1/memory-page.schema.json +154 -0
  39. package/spec/v1/memory.md +18 -0
  40. package/spec/v1/migration.md +13 -0
  41. package/spec/v1/semantic-cloud.md +96 -0
  42. package/src/canonical.ts +28 -13
  43. package/src/cli.ts +1 -1
  44. package/src/cloudflare-embedding.test.ts +306 -0
  45. package/src/cloudflare-embedding.ts +385 -0
  46. package/src/contracts.test.ts +20 -0
  47. package/src/graph.ts +63 -6
  48. package/src/libsql-semantic.test.ts +585 -0
  49. package/src/libsql-semantic.ts +1168 -0
  50. package/src/memory-page.ts +1 -0
  51. package/src/memory-pages.test.ts +277 -0
  52. package/src/memory-pages.ts +440 -0
  53. package/src/memory.ts +2 -0
  54. package/src/semantic-cloud.ts +2 -0
  55. package/src/semantic.ts +14 -3
@@ -0,0 +1,1870 @@
1
+ // src/canonical.ts
2
+ import { createHash, randomBytes } from "node:crypto";
3
+
4
+ class OhValidationError extends Error {
5
+ code;
6
+ path;
7
+ constructor(code, path, message) {
8
+ super(`${path}: ${message}`);
9
+ this.name = "OhValidationError";
10
+ this.code = code;
11
+ this.path = path;
12
+ }
13
+ }
14
+ function isPlainRecord(value) {
15
+ if (typeof value !== "object" || value === null || Array.isArray(value))
16
+ return false;
17
+ const prototype = Object.getPrototypeOf(value);
18
+ return prototype === Object.prototype || prototype === null;
19
+ }
20
+ function hasExactKeys(value, keys) {
21
+ const actual = Object.keys(value);
22
+ return actual.length === keys.length && keys.every((key) => Object.hasOwn(value, key));
23
+ }
24
+ function assertUnicodeScalarString(value, path) {
25
+ for (let index = 0;index < value.length; index += 1) {
26
+ const code = value.charCodeAt(index);
27
+ if (code >= 55296 && code <= 56319) {
28
+ const next = value.charCodeAt(index + 1);
29
+ if (!(next >= 56320 && next <= 57343)) {
30
+ throw new OhValidationError("invalid-unicode", path, "contains an unpaired surrogate");
31
+ }
32
+ index += 1;
33
+ } else if (code >= 56320 && code <= 57343) {
34
+ throw new OhValidationError("invalid-unicode", path, "contains an unpaired surrogate");
35
+ }
36
+ }
37
+ }
38
+ function encodeCanonical(value, path, ancestors) {
39
+ if (value === null || typeof value === "boolean")
40
+ return JSON.stringify(value);
41
+ if (typeof value === "string") {
42
+ assertUnicodeScalarString(value, path);
43
+ return JSON.stringify(value);
44
+ }
45
+ if (typeof value === "number") {
46
+ if (!Number.isFinite(value)) {
47
+ throw new OhValidationError("non-json-number", path, "must be finite");
48
+ }
49
+ if (Object.is(value, -0)) {
50
+ throw new OhValidationError("noncanonical-number", path, "negative zero is not canonical");
51
+ }
52
+ return JSON.stringify(value);
53
+ }
54
+ if (typeof value !== "object" || value === null) {
55
+ throw new OhValidationError("non-json-value", path, `cannot encode ${typeof value}`);
56
+ }
57
+ if (ancestors.has(value)) {
58
+ throw new OhValidationError("cycle", path, "contains a cycle");
59
+ }
60
+ ancestors.add(value);
61
+ try {
62
+ if (Array.isArray(value)) {
63
+ const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length");
64
+ const length = lengthDescriptor?.value;
65
+ if (typeof length !== "number" || !Number.isSafeInteger(length) || length < 0) {
66
+ throw new OhValidationError("non-json-property", path, "array has an invalid length descriptor");
67
+ }
68
+ const ownKeys2 = Reflect.ownKeys(value);
69
+ if (!ownKeys2.includes("length") || ownKeys2.some((key) => key !== "length" && (typeof key !== "string" || !/^(?:0|[1-9][0-9]*)$/u.test(key) || Number(key) >= length))) {
70
+ throw new OhValidationError("non-json-property", path, "array has non-index properties");
71
+ }
72
+ const elements = [];
73
+ for (let index = 0;index < length; index += 1) {
74
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
75
+ if (descriptor === undefined) {
76
+ throw new OhValidationError("sparse-array", `${path}[${index}]`, "must not contain holes");
77
+ }
78
+ if (!descriptor.enumerable || descriptor.get !== undefined || descriptor.set !== undefined) {
79
+ throw new OhValidationError("non-json-property", `${path}[${index}]`, "must be an enumerable data property");
80
+ }
81
+ elements.push(descriptor.value);
82
+ }
83
+ const encoded = elements.map((element, index) => encodeCanonical(element, `${path}[${index}]`, ancestors));
84
+ return `[${encoded.join(",")}]`;
85
+ }
86
+ if (!isPlainRecord(value)) {
87
+ throw new OhValidationError("non-plain-object", path, "must be a plain object");
88
+ }
89
+ const ownKeys = Reflect.ownKeys(value);
90
+ if (ownKeys.some((key) => typeof key !== "string")) {
91
+ throw new OhValidationError("non-json-property", path, "object has a symbol property");
92
+ }
93
+ const entries = [];
94
+ const keys = ownKeys;
95
+ for (const key of keys) {
96
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
97
+ if (descriptor === undefined || !descriptor.enumerable || descriptor.get !== undefined || descriptor.set !== undefined) {
98
+ throw new OhValidationError("non-json-property", `${path}.${key}`, "must be an enumerable data property");
99
+ }
100
+ entries.push([key, descriptor.value]);
101
+ }
102
+ entries.sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0);
103
+ const encodedEntries = entries.map(([key, entryValue]) => {
104
+ assertUnicodeScalarString(key, `${path}.<key>`);
105
+ return `${JSON.stringify(key)}:${encodeCanonical(entryValue, `${path}.${key}`, ancestors)}`;
106
+ });
107
+ return `{${encodedEntries.join(",")}}`;
108
+ } finally {
109
+ ancestors.delete(value);
110
+ }
111
+ }
112
+ function canonicalJson(value) {
113
+ return encodeCanonical(value, "$", new Set);
114
+ }
115
+ function parseCanonicalJson(text, maximumBytes = 16 * 1024 * 1024) {
116
+ if (utf8ByteLength(text) > maximumBytes) {
117
+ throw new OhValidationError("limit-exceeded", "$", "canonical JSON exceeds its byte limit");
118
+ }
119
+ let value;
120
+ try {
121
+ value = JSON.parse(text);
122
+ } catch {
123
+ throw new OhValidationError("invalid-json", "$", "is not valid JSON");
124
+ }
125
+ if (canonicalJson(value) !== text) {
126
+ throw new OhValidationError("noncanonical-json", "$", "keys or values are not canonical");
127
+ }
128
+ return value;
129
+ }
130
+ function utf8ByteLength(value) {
131
+ return Buffer.byteLength(value, "utf8");
132
+ }
133
+ function sha256Hex(value) {
134
+ return createHash("sha256").update(value).digest("hex");
135
+ }
136
+ function canonicalSha256(value) {
137
+ return sha256Hex(canonicalJson(value));
138
+ }
139
+ function parseSha256Hex(value) {
140
+ return typeof value === "string" && /^[a-f0-9]{64}$/u.test(value) ? value : null;
141
+ }
142
+ function parseCanonicalInstantV1(value) {
143
+ if (typeof value !== "string" || !/^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d\.\d{3}Z$/u.test(value)) {
144
+ return null;
145
+ }
146
+ const timestamp = Date.parse(value);
147
+ return Number.isFinite(timestamp) && new Date(timestamp).toISOString() === value ? value : null;
148
+ }
149
+ function canonicalNow() {
150
+ return new Date().toISOString();
151
+ }
152
+ function safeCode(value, maximumLength = 128) {
153
+ return typeof value === "string" && value.length <= maximumLength && /^[a-z][a-z0-9]*(?:[._:/-][a-z0-9]+)*$/u.test(value) ? value : null;
154
+ }
155
+ function boundedText(value, maximumBytes = 64 * 1024) {
156
+ if (typeof value !== "string" || value.length === 0 || value.normalize("NFC") !== value || utf8ByteLength(value) > maximumBytes)
157
+ return null;
158
+ try {
159
+ assertUnicodeScalarString(value, "$text");
160
+ } catch {
161
+ return null;
162
+ }
163
+ for (const character of value) {
164
+ const code = character.codePointAt(0) ?? 0;
165
+ if (code <= 8 || code >= 11 && code <= 12 || code >= 14 && code <= 31 || code >= 127 && code <= 159)
166
+ return null;
167
+ }
168
+ return value;
169
+ }
170
+ function orderedUnique(values, key) {
171
+ return values.every((value, index) => index === 0 || key(values[index - 1]) < key(value));
172
+ }
173
+ function sortUnique(values, key) {
174
+ const sorted = [...values].sort((left, right) => {
175
+ const leftKey = key(left);
176
+ const rightKey = key(right);
177
+ return leftKey < rightKey ? -1 : leftKey > rightKey ? 1 : 0;
178
+ });
179
+ if (!orderedUnique(sorted, key)) {
180
+ throw new OhValidationError("duplicate", "$", "contains duplicate canonical values");
181
+ }
182
+ return sorted;
183
+ }
184
+
185
+ // src/semantic.ts
186
+ import { mkdir, readFile, readdir, rename, unlink, writeFile } from "node:fs/promises";
187
+ import { join, resolve } from "node:path";
188
+
189
+ // src/graph.ts
190
+ var OH_GRAPH_FORMAT_VERSION_V1 = 1;
191
+ var OH_GRAPH_LIMITS_V1 = Object.freeze({
192
+ changesPerOperation: 8192,
193
+ dependenciesPerRecord: 4096,
194
+ recordBytes: 1024 * 1024,
195
+ recordsPerSnapshot: 65536
196
+ });
197
+ var OH_KNOWLEDGE_GRAPH_RECORD_KINDS_V1 = [
198
+ "activity",
199
+ "assertion",
200
+ "context",
201
+ "dependency-manifest",
202
+ "edition",
203
+ "entity",
204
+ "evidence",
205
+ "identity-operation",
206
+ "inquiry",
207
+ "inquiry-event",
208
+ "review-decision",
209
+ "rights-decision",
210
+ "schema",
211
+ "shape",
212
+ "statement",
213
+ "type-membership",
214
+ "view",
215
+ "vocabulary"
216
+ ];
217
+ var KNOWLEDGE_GRAPH_RECORD_KEYS_V1 = [
218
+ "dependencies",
219
+ "key",
220
+ "kind",
221
+ "recordSha256",
222
+ "v",
223
+ "value"
224
+ ];
225
+ function exactKnowledgeGraphRecordEnvelopeV1(value) {
226
+ try {
227
+ if (!isPlainRecord(value))
228
+ return null;
229
+ const ownKeys = Reflect.ownKeys(value);
230
+ if (ownKeys.length !== KNOWLEDGE_GRAPH_RECORD_KEYS_V1.length || ownKeys.some((key) => typeof key !== "string") || KNOWLEDGE_GRAPH_RECORD_KEYS_V1.some((key) => !ownKeys.includes(key)))
231
+ return null;
232
+ const detached = {};
233
+ for (const key of KNOWLEDGE_GRAPH_RECORD_KEYS_V1) {
234
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
235
+ if (descriptor === undefined || !descriptor.enumerable || descriptor.get !== undefined || descriptor.set !== undefined)
236
+ return null;
237
+ detached[key] = descriptor.value;
238
+ }
239
+ return detached;
240
+ } catch {
241
+ return null;
242
+ }
243
+ }
244
+ function exactGraphDependenciesV1(value) {
245
+ try {
246
+ if (!Array.isArray(value))
247
+ return null;
248
+ const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length");
249
+ const length = lengthDescriptor?.value;
250
+ if (typeof length !== "number" || !Number.isSafeInteger(length) || length < 0 || length > OH_GRAPH_LIMITS_V1.dependenciesPerRecord)
251
+ return null;
252
+ const ownKeys = Reflect.ownKeys(value);
253
+ if (ownKeys.length !== length + 1 || !ownKeys.includes("length") || ownKeys.some((key) => key !== "length" && (typeof key !== "string" || !/^(?:0|[1-9][0-9]*)$/u.test(key) || Number(key) >= length)))
254
+ return null;
255
+ const detached = [];
256
+ for (let index = 0;index < length; index += 1) {
257
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
258
+ if (descriptor === undefined || !descriptor.enumerable || descriptor.get !== undefined || descriptor.set !== undefined)
259
+ return null;
260
+ detached.push(descriptor.value);
261
+ }
262
+ return detached;
263
+ } catch {
264
+ return null;
265
+ }
266
+ }
267
+ function recordKey(value) {
268
+ return typeof value === "string" && value.length <= 512 && /^[a-z][a-z0-9]*(?:[._:/-][a-z0-9]+)*$/u.test(value) ? value : null;
269
+ }
270
+ function createKnowledgeGraphRecordV1(input) {
271
+ if (!isPlainRecord(input) || !hasExactKeys(input, ["dependencies", "key", "kind", "v", "value"]) || input.v !== 1)
272
+ throw new TypeError("Invalid graph record input.");
273
+ const dependencyInput = exactGraphDependenciesV1(input.dependencies);
274
+ if (dependencyInput === null)
275
+ throw new TypeError("Invalid graph record dependencies.");
276
+ const key = recordKey(input.key);
277
+ const kind = OH_KNOWLEDGE_GRAPH_RECORD_KINDS_V1.find((candidate) => candidate === input.kind);
278
+ if (key === null || kind === undefined)
279
+ throw new TypeError("Invalid graph record identity.");
280
+ const dependencies = dependencyInput.map(recordKey);
281
+ if (dependencies.some((dependency) => dependency === null) || !orderedUnique(dependencies, String) || dependencies.includes(key)) {
282
+ throw new TypeError("Graph dependencies must be ordered, unique, and non-reflexive.");
283
+ }
284
+ const valueJson = canonicalJson(input.value);
285
+ if (Buffer.byteLength(valueJson, "utf8") > OH_GRAPH_LIMITS_V1.recordBytes) {
286
+ throw new RangeError("Graph record value exceeds its canonical byte limit.");
287
+ }
288
+ const payload = { dependencies, key, kind, v: 1, value: input.value };
289
+ return { ...payload, recordSha256: canonicalSha256(payload) };
290
+ }
291
+ function parseKnowledgeGraphRecordV1(value) {
292
+ const envelope = exactKnowledgeGraphRecordEnvelopeV1(value);
293
+ if (envelope === null)
294
+ return null;
295
+ const recordSha256 = parseSha256Hex(envelope.recordSha256);
296
+ const input = {
297
+ dependencies: envelope.dependencies,
298
+ key: envelope.key,
299
+ kind: envelope.kind,
300
+ v: envelope.v,
301
+ value: envelope.value
302
+ };
303
+ try {
304
+ const created = createKnowledgeGraphRecordV1(input);
305
+ return recordSha256 !== null && created.recordSha256 === recordSha256 ? { ...created, recordSha256 } : null;
306
+ } catch {
307
+ return null;
308
+ }
309
+ }
310
+ function knowledgeGraphRecordRefV1(record) {
311
+ return {
312
+ dependencies: record.dependencies,
313
+ key: record.key,
314
+ kind: record.kind,
315
+ sha256: record.recordSha256,
316
+ v: 1
317
+ };
318
+ }
319
+ function changeKey(change) {
320
+ return change.kind === "put" ? change.record.key : change.key;
321
+ }
322
+ function canonicalKnowledgeGraphChangesV1(changes) {
323
+ const normalized = [];
324
+ for (const change of changes) {
325
+ if (!isPlainRecord(change) || change.v !== 1)
326
+ throw new TypeError("Invalid graph change.");
327
+ if (change.kind === "put") {
328
+ const record = parseKnowledgeGraphRecordV1(change.record);
329
+ if (record === null)
330
+ throw new TypeError("Invalid graph record in change.");
331
+ normalized.push({ kind: "put", record, v: 1 });
332
+ } else if (change.kind === "tombstone") {
333
+ const key = recordKey(change.key);
334
+ const priorSha256 = parseSha256Hex(change.priorSha256);
335
+ if (key === null || priorSha256 === null)
336
+ throw new TypeError("Invalid graph tombstone.");
337
+ normalized.push({ key, kind: "tombstone", priorSha256, v: 1 });
338
+ } else
339
+ throw new TypeError("Unknown graph change kind.");
340
+ }
341
+ return sortUnique(normalized, changeKey);
342
+ }
343
+ function graphRevisionSha256V1(input) {
344
+ const changes = canonicalKnowledgeGraphChangesV1(input.changes);
345
+ const operationId = safeCode(input.operationId);
346
+ const parentGraphRevisionSha256 = input.parentGraphRevisionSha256 === null ? null : parseSha256Hex(input.parentGraphRevisionSha256);
347
+ const recordsSha256 = parseSha256Hex(input.recordsSha256);
348
+ const revision = Number.isSafeInteger(input.revision) && input.revision > 0 ? input.revision : null;
349
+ if (changes.length === 0 || changes.length > OH_GRAPH_LIMITS_V1.changesPerOperation || operationId === null || recordsSha256 === null || revision === null || input.parentGraphRevisionSha256 !== null && parentGraphRevisionSha256 === null || revision === 1 !== (parentGraphRevisionSha256 === null)) {
350
+ throw new TypeError("Invalid graph revision digest input.");
351
+ }
352
+ return canonicalSha256({ changes, operationId, parentGraphRevisionSha256, recordsSha256, revision, v: 1 });
353
+ }
354
+
355
+ // src/semantic.ts
356
+ var OH_EMBEDDING_PROFILE_V1 = Object.freeze({
357
+ dimensions: 768,
358
+ distance: "cosine",
359
+ documentation: "https://ai.google.dev/gemma/docs/embeddinggemma",
360
+ documentFormat: "title: {title} | text: {content}",
361
+ engine: "@tobilu/qmd@2.5.3",
362
+ model: "hf:ggml-org/embeddinggemma-300M-GGUF/embeddinggemma-300M-Q8_0.gguf",
363
+ normalization: "l2",
364
+ queryFormat: "task: search result | query: {query}",
365
+ v: 1
366
+ });
367
+ function normalizeOhEmbeddingV1(vector) {
368
+ if (vector.length !== OH_EMBEDDING_PROFILE_V1.dimensions || vector.some((component) => !Number.isFinite(component))) {
369
+ throw new TypeError(`Embedding vectors must contain ${OH_EMBEDDING_PROFILE_V1.dimensions} finite values.`);
370
+ }
371
+ const scale = vector.reduce((maximum, component) => Math.max(maximum, Math.abs(component)), 0);
372
+ if (scale === 0)
373
+ throw new TypeError("Embedding vectors must have nonzero magnitude.");
374
+ const scaledMagnitude = Math.sqrt(vector.reduce((sum, component) => {
375
+ const scaled = component / scale;
376
+ return sum + scaled * scaled;
377
+ }, 0));
378
+ if (!Number.isFinite(scaledMagnitude) || scaledMagnitude === 0) {
379
+ throw new TypeError("Embedding vectors must have finite nonzero magnitude.");
380
+ }
381
+ const normalized = vector.map((component) => component / scale / scaledMagnitude);
382
+ if (normalized.some((component) => !Number.isFinite(component))) {
383
+ throw new TypeError("Embedding vectors must normalize to finite values.");
384
+ }
385
+ return normalized;
386
+ }
387
+ var qmdModuleSpecifier = "@tobilu/qmd";
388
+ async function defaultQmdStoreFactory(options) {
389
+ let module;
390
+ try {
391
+ module = await import(qmdModuleSpecifier);
392
+ } catch {
393
+ throw new Error("Semantic search needs the optional @tobilu/qmd@2.5.3 package.");
394
+ }
395
+ const createStore = module.createStore;
396
+ if (typeof createStore !== "function")
397
+ throw new Error("The installed QMD package has no compatible createStore export.");
398
+ return await createStore(options);
399
+ }
400
+ function recordDocument(record) {
401
+ return `# ${record.key}
402
+
403
+ kind: ${record.kind}
404
+
405
+ ${canonicalJson(record.value)}
406
+ `;
407
+ }
408
+ var QMD_VECTOR_RESULT_KEYS = [
409
+ "body",
410
+ "bodyLength",
411
+ "chunkPos",
412
+ "collectionName",
413
+ "context",
414
+ "displayPath",
415
+ "docid",
416
+ "filepath",
417
+ "hash",
418
+ "modifiedAt",
419
+ "score",
420
+ "source",
421
+ "title"
422
+ ];
423
+ function semanticManifest(entries) {
424
+ const immutableEntries = {};
425
+ for (const [filename, entry] of Object.entries(entries)) {
426
+ immutableEntries[filename] = Object.freeze({ ...entry });
427
+ }
428
+ return Object.freeze({
429
+ entries: Object.freeze(immutableEntries),
430
+ profileSha256: canonicalSha256(OH_EMBEDDING_PROFILE_V1),
431
+ v: 1
432
+ });
433
+ }
434
+ function parseQmdVectorResult(value) {
435
+ if (!isPlainRecord(value) || !hasExactKeys(value, QMD_VECTOR_RESULT_KEYS))
436
+ return null;
437
+ const pathMatch = typeof value.filepath === "string" ? /^qmd:\/\/oh\/([a-f0-9]{64}\.md)$/u.exec(value.filepath) : null;
438
+ const filename = pathMatch?.[1];
439
+ const hash = parseSha256Hex(value.hash);
440
+ const title = safeCode(value.title, 512);
441
+ if (filename === undefined || value.displayPath !== `oh/${filename}` || value.collectionName !== "oh" || value.source !== "vec" || value.context !== null || value.modifiedAt !== "" || hash === null || value.docid !== hash.slice(0, 6) || title === null || typeof value.body !== "string" || typeof value.bodyLength !== "number" || !Number.isSafeInteger(value.bodyLength) || value.bodyLength < 0 || value.bodyLength > OH_GRAPH_LIMITS_V1.recordBytes + 4096 || value.body.length !== value.bodyLength || hash !== sha256Hex(value.body) || typeof value.chunkPos !== "number" || !Number.isSafeInteger(value.chunkPos) || value.chunkPos < 0 || typeof value.score !== "number" || !Number.isFinite(value.score) || value.score < 0 || value.score > 1) {
442
+ return null;
443
+ }
444
+ return { body: value.body, filename, hash, score: value.score, title };
445
+ }
446
+ function parseQmdVectorResults(value) {
447
+ if (!Array.isArray(value) || value.length > 100) {
448
+ throw new Error("QMD returned an invalid vector result batch.");
449
+ }
450
+ return value.map(parseQmdVectorResult).filter((result) => result !== null);
451
+ }
452
+
453
+ class OhQmdSemanticBackendV1 {
454
+ profile = OH_EMBEDDING_PROFILE_V1;
455
+ #cacheDirectory;
456
+ #databasePath;
457
+ #factory;
458
+ #manifest = semanticManifest({});
459
+ #manifestLoad = null;
460
+ #store = null;
461
+ #storeClose = null;
462
+ #closure = null;
463
+ #indexQueue = Promise.resolve();
464
+ #activeSearches = new Set;
465
+ #closed = false;
466
+ constructor(options) {
467
+ this.#cacheDirectory = resolve(options.cacheDirectory);
468
+ this.#databasePath = resolve(options.databasePath ?? join(this.#cacheDirectory, "qmd.sqlite"));
469
+ this.#factory = options.storeFactory ?? defaultQmdStoreFactory;
470
+ }
471
+ async#open() {
472
+ if (this.#closed)
473
+ throw new Error("The semantic backend is closed.");
474
+ this.#store ??= this.#initializeStore();
475
+ const store = await this.#store;
476
+ if (this.#closed) {
477
+ await this.#closeStore(store);
478
+ throw new Error("The semantic backend is closed.");
479
+ }
480
+ return store;
481
+ }
482
+ async#initializeStore() {
483
+ const documents = join(this.#cacheDirectory, "documents");
484
+ await mkdir(documents, { recursive: true });
485
+ await this.#loadManifest();
486
+ if (this.#closed)
487
+ throw new Error("The semantic backend is closed.");
488
+ const store = await this.#factory({
489
+ dbPath: this.#databasePath,
490
+ config: {
491
+ collections: { oh: { path: documents, pattern: "*.md" } },
492
+ models: { embed: OH_EMBEDDING_PROFILE_V1.model }
493
+ }
494
+ });
495
+ if (this.#closed) {
496
+ await this.#closeStore(store);
497
+ throw new Error("The semantic backend is closed.");
498
+ }
499
+ return store;
500
+ }
501
+ #closeStore(store) {
502
+ this.#storeClose ??= Promise.resolve().then(() => store.close());
503
+ return this.#storeClose;
504
+ }
505
+ #loadManifest() {
506
+ this.#manifestLoad ??= this.#readManifest();
507
+ return this.#manifestLoad;
508
+ }
509
+ async#readManifest() {
510
+ let text;
511
+ try {
512
+ text = await readFile(join(this.#cacheDirectory, "manifest.json"), "utf8");
513
+ } catch (error) {
514
+ if (error.code === "ENOENT")
515
+ return;
516
+ throw error;
517
+ }
518
+ let value;
519
+ try {
520
+ value = JSON.parse(text);
521
+ } catch {
522
+ throw new Error("The semantic manifest is not JSON.");
523
+ }
524
+ if (canonicalJson(value) !== text || !isPlainRecord(value) || !hasExactKeys(value, ["entries", "profileSha256", "v"]) || value.v !== 1 || value.profileSha256 !== canonicalSha256(OH_EMBEDDING_PROFILE_V1) || !isPlainRecord(value.entries) || Object.keys(value.entries).length > 65536)
525
+ throw new Error("The semantic manifest is incompatible or invalid.");
526
+ const entries = {};
527
+ for (const [filename, candidate] of Object.entries(value.entries)) {
528
+ if (!/^[a-f0-9]{64}\.md$/u.test(filename) || !isPlainRecord(candidate) || !hasExactKeys(candidate, ["key", "recordSha256"]))
529
+ throw new Error("The semantic manifest has an invalid entry.");
530
+ const key = safeCode(candidate.key, 512);
531
+ const recordSha256 = parseSha256Hex(candidate.recordSha256);
532
+ if (key === null || recordSha256 === null || filename !== `${sha256Hex(key)}.md`) {
533
+ throw new Error("The semantic manifest entry identity is invalid.");
534
+ }
535
+ entries[filename] = { key, recordSha256 };
536
+ }
537
+ this.#manifest = semanticManifest(entries);
538
+ }
539
+ index(records) {
540
+ if (records.length > 65536) {
541
+ return Promise.reject(new RangeError("A semantic snapshot may contain at most 65,536 records."));
542
+ }
543
+ if (this.#closed)
544
+ return Promise.reject(new Error("The semantic backend is closed."));
545
+ const snapshot = [...records];
546
+ const operation = this.#indexQueue.then(() => this.#indexSnapshot(snapshot));
547
+ this.#indexQueue = operation.then(() => {
548
+ return;
549
+ }, () => {
550
+ return;
551
+ });
552
+ return operation;
553
+ }
554
+ async#indexSnapshot(records) {
555
+ if (this.#closed)
556
+ throw new Error("The semantic backend is closed.");
557
+ const documents = join(this.#cacheDirectory, "documents");
558
+ await mkdir(documents, { recursive: true });
559
+ await this.#loadManifest();
560
+ const entries = {};
561
+ for (const record of records) {
562
+ const filename = `${sha256Hex(record.key)}.md`;
563
+ entries[filename] = { key: record.key, recordSha256: record.recordSha256 };
564
+ const path = join(documents, filename);
565
+ const temporary = `${path}.${process.pid}.tmp`;
566
+ await writeFile(temporary, recordDocument(record), { encoding: "utf8", mode: 384 });
567
+ await rename(temporary, path);
568
+ }
569
+ const retained = new Set(Object.keys(entries));
570
+ for (const filename of await readdir(documents)) {
571
+ if (/^[a-f0-9]{64}\.md$/u.test(filename) && !retained.has(filename))
572
+ await unlink(join(documents, filename));
573
+ }
574
+ const nextManifest = semanticManifest(entries);
575
+ const store = await this.#open();
576
+ await store.update({ collections: ["oh"] });
577
+ await store.embed({ collection: "oh", model: OH_EMBEDDING_PROFILE_V1.model });
578
+ const manifestPath = join(this.#cacheDirectory, "manifest.json");
579
+ const temporaryManifest = `${manifestPath}.${process.pid}.tmp`;
580
+ await writeFile(temporaryManifest, canonicalJson(nextManifest), { encoding: "utf8", mode: 384 });
581
+ await rename(temporaryManifest, manifestPath);
582
+ this.#manifest = nextManifest;
583
+ return { indexed: records.length, v: 1 };
584
+ }
585
+ search(query, limit, authority) {
586
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100) {
587
+ return Promise.reject(new RangeError("Semantic limit must be 1 through 100."));
588
+ }
589
+ if (this.#closed)
590
+ return Promise.reject(new Error("The semantic backend is closed."));
591
+ const operation = this.#searchSnapshot(query, limit, authority);
592
+ this.#activeSearches.add(operation);
593
+ operation.then(() => {
594
+ this.#activeSearches.delete(operation);
595
+ }, () => {
596
+ this.#activeSearches.delete(operation);
597
+ });
598
+ return operation;
599
+ }
600
+ async#searchSnapshot(query, limit, authority) {
601
+ const store = await this.#open();
602
+ const manifest = this.#manifest;
603
+ const results = parseQmdVectorResults(await store.searchVector(query, { collection: "oh", limit: Math.min(100, limit * 3) }));
604
+ const output = [];
605
+ const seen = new Set;
606
+ for (const result of results) {
607
+ const entry = manifest.entries[result.filename];
608
+ if (entry === undefined || result.title !== entry.key || seen.has(entry.key))
609
+ continue;
610
+ const current = authority.get(entry.key);
611
+ if (current === null || current.recordSha256 !== entry.recordSha256)
612
+ continue;
613
+ const expectedDocument = recordDocument(current);
614
+ if (result.body !== expectedDocument || result.hash !== sha256Hex(expectedDocument))
615
+ continue;
616
+ seen.add(entry.key);
617
+ output.push({ key: entry.key, recordSha256: entry.recordSha256, score: result.score, v: 1 });
618
+ if (output.length === limit)
619
+ break;
620
+ }
621
+ return output;
622
+ }
623
+ async#finishClose() {
624
+ await this.#indexQueue;
625
+ await Promise.allSettled([...this.#activeSearches]);
626
+ if (this.#store === null)
627
+ return;
628
+ try {
629
+ const store = await this.#store;
630
+ await this.#closeStore(store);
631
+ } catch {
632
+ if (this.#storeClose !== null)
633
+ await this.#storeClose;
634
+ }
635
+ }
636
+ close() {
637
+ this.#closed = true;
638
+ this.#closure ??= this.#finishClose();
639
+ return this.#closure;
640
+ }
641
+ }
642
+
643
+ // src/cloudflare-embedding.ts
644
+ var cloudflareEmbeddingProfilePayload = Object.freeze({
645
+ dimensions: 768,
646
+ distance: "cosine",
647
+ documentFormat: "title: {title} | text: {content}",
648
+ inputUtf8Bytes: 448,
649
+ model: "@cf/google/embeddinggemma-300m",
650
+ normalization: "l2",
651
+ profileId: "oh.cloudflare.embeddinggemma.v1",
652
+ provider: "cloudflare.workers-ai",
653
+ queryFormat: "task: search result | query: {query}",
654
+ v: 1
655
+ });
656
+ var OH_CLOUDFLARE_EMBEDDING_PROFILE_V1 = Object.freeze({
657
+ ...cloudflareEmbeddingProfilePayload,
658
+ profileSha256: canonicalSha256(cloudflareEmbeddingProfilePayload)
659
+ });
660
+ var semanticRendererPayload = Object.freeze({
661
+ documentFormat: cloudflareEmbeddingProfilePayload.documentFormat,
662
+ inputUtf8Bytes: cloudflareEmbeddingProfilePayload.inputUtf8Bytes,
663
+ rendererId: "oh.embedding-input.utf8-chunks.v1",
664
+ split: "unicode-scalar-greedy",
665
+ v: 1
666
+ });
667
+ var OH_SEMANTIC_RENDERER_V1 = Object.freeze({
668
+ ...semanticRendererPayload,
669
+ rendererSha256: canonicalSha256(semanticRendererPayload)
670
+ });
671
+ var OH_CLOUDFLARE_EMBEDDING_LIMITS_V1 = Object.freeze({
672
+ batchInputs: 32,
673
+ deadlineMs: 30000,
674
+ documentBytes: 8 * 1024 * 1024,
675
+ inputUtf8Bytes: 448,
676
+ responseBytes: 8 * 1024 * 1024,
677
+ renderedChunks: 256,
678
+ titleBytes: 16 * 1024
679
+ });
680
+
681
+ class OhCloudflareEmbeddingError extends Error {
682
+ code;
683
+ status;
684
+ constructor(code, message, status = null) {
685
+ super(message);
686
+ this.name = "OhCloudflareEmbeddingError";
687
+ this.code = code;
688
+ this.status = status;
689
+ }
690
+ }
691
+ var renderedEmbeddingInputs = new WeakSet;
692
+ function formattedInput(kind, input) {
693
+ const utf8Bytes = utf8ByteLength(input);
694
+ if (utf8Bytes > OH_CLOUDFLARE_EMBEDDING_LIMITS_V1.inputUtf8Bytes) {
695
+ throw new OhCloudflareEmbeddingError("invalid-input", `A formatted embedding input exceeds ${OH_CLOUDFLARE_EMBEDDING_LIMITS_V1.inputUtf8Bytes} UTF-8 bytes.`);
696
+ }
697
+ const rendered = {
698
+ input,
699
+ inputSha256: sha256Hex(input),
700
+ kind,
701
+ utf8Bytes,
702
+ v: 1
703
+ };
704
+ renderedEmbeddingInputs.add(rendered);
705
+ return Object.freeze(rendered);
706
+ }
707
+ function renderOhCloudflareEmbeddingQueryV1(query) {
708
+ const parsed = boundedText(query, OH_CLOUDFLARE_EMBEDDING_LIMITS_V1.inputUtf8Bytes);
709
+ if (parsed === null) {
710
+ throw new OhCloudflareEmbeddingError("invalid-input", "An embedding query must be bounded NFC text.");
711
+ }
712
+ return formattedInput("query", `task: search result | query: ${parsed}`);
713
+ }
714
+ function prefixForTitle(title) {
715
+ return `title: ${title} | text: `;
716
+ }
717
+ function renderOhCloudflareEmbeddingDocumentV1(input) {
718
+ const title = boundedText(input.title, OH_CLOUDFLARE_EMBEDDING_LIMITS_V1.titleBytes);
719
+ const content = input.content === "" ? "" : boundedText(input.content, OH_CLOUDFLARE_EMBEDDING_LIMITS_V1.documentBytes);
720
+ const maximumChunks = input.maximumChunks ?? OH_CLOUDFLARE_EMBEDDING_LIMITS_V1.renderedChunks;
721
+ if (title === null || content === null || !Number.isSafeInteger(maximumChunks) || maximumChunks < 1 || maximumChunks > OH_CLOUDFLARE_EMBEDDING_LIMITS_V1.renderedChunks) {
722
+ throw new OhCloudflareEmbeddingError("invalid-input", "A semantic document needs bounded NFC title/content and a valid chunk limit.");
723
+ }
724
+ const sourceUtf8Bytes = utf8ByteLength(content);
725
+ const prefix = prefixForTitle(title);
726
+ const capacity = OH_CLOUDFLARE_EMBEDDING_LIMITS_V1.inputUtf8Bytes - utf8ByteLength(prefix);
727
+ if (capacity < 1) {
728
+ return Object.freeze({
729
+ chunks: Object.freeze([]),
730
+ diagnostic: Object.freeze({
731
+ code: "oversize-prefix",
732
+ maximumChunks,
733
+ omittedUtf8Bytes: sourceUtf8Bytes,
734
+ v: 1
735
+ }),
736
+ sourceUtf8Bytes,
737
+ status: "oversize",
738
+ v: 1
739
+ });
740
+ }
741
+ const chunks = [];
742
+ let cursor = 0;
743
+ let emittedBytes = 0;
744
+ chunks:
745
+ while ((cursor < content.length || content.length === 0 && chunks.length === 0) && chunks.length < maximumChunks) {
746
+ const start = cursor;
747
+ let bytes = 0;
748
+ while (cursor < content.length) {
749
+ const codePoint = content.codePointAt(cursor);
750
+ if (codePoint === undefined)
751
+ break;
752
+ const scalar = String.fromCodePoint(codePoint);
753
+ const scalarBytes = utf8ByteLength(scalar);
754
+ if (bytes + scalarBytes > capacity)
755
+ break;
756
+ bytes += scalarBytes;
757
+ cursor += scalar.length;
758
+ }
759
+ if (cursor === start && content.length > 0) {
760
+ break chunks;
761
+ }
762
+ const chunkContent = content.slice(start, cursor);
763
+ const rendered = formattedInput("document", `${prefix}${chunkContent}`);
764
+ chunks.push(Object.freeze({
765
+ content: chunkContent,
766
+ input: rendered,
767
+ ordinal: chunks.length,
768
+ title,
769
+ v: 1
770
+ }));
771
+ emittedBytes += bytes;
772
+ }
773
+ const omittedUtf8Bytes = sourceUtf8Bytes - emittedBytes;
774
+ const partial = cursor < content.length;
775
+ const oversize = partial && chunks.length === 0;
776
+ return Object.freeze({
777
+ chunks: Object.freeze(chunks),
778
+ diagnostic: partial ? Object.freeze({
779
+ code: oversize ? "oversize-prefix" : "partial",
780
+ maximumChunks,
781
+ omittedUtf8Bytes,
782
+ v: 1
783
+ }) : null,
784
+ sourceUtf8Bytes,
785
+ status: oversize ? "oversize" : partial ? "partial" : "complete",
786
+ v: 1
787
+ });
788
+ }
789
+ function exactPositiveInteger(value, maximum, label) {
790
+ if (!Number.isSafeInteger(value) || value < 1 || value > maximum) {
791
+ throw new RangeError(`${label} must be an integer from 1 through ${maximum}.`);
792
+ }
793
+ return value;
794
+ }
795
+ async function boundedResponseText(response, maximumBytes) {
796
+ const declaredLength = response.headers.get("content-length");
797
+ if (declaredLength !== null) {
798
+ const parsed = Number(declaredLength);
799
+ if (!Number.isSafeInteger(parsed) || parsed < 0 || parsed > maximumBytes) {
800
+ throw new OhCloudflareEmbeddingError("invalid-response", "The embedding response exceeds its byte limit.");
801
+ }
802
+ }
803
+ if (response.body === null)
804
+ return "";
805
+ const reader = response.body.getReader();
806
+ const parts = [];
807
+ let size = 0;
808
+ try {
809
+ while (true) {
810
+ const next = await reader.read();
811
+ if (next.done)
812
+ break;
813
+ size += next.value.byteLength;
814
+ if (size > maximumBytes) {
815
+ await reader.cancel();
816
+ throw new OhCloudflareEmbeddingError("invalid-response", "The embedding response exceeds its byte limit.");
817
+ }
818
+ parts.push(next.value);
819
+ }
820
+ } finally {
821
+ reader.releaseLock();
822
+ }
823
+ const bytes = new Uint8Array(size);
824
+ let offset = 0;
825
+ for (const part of parts) {
826
+ bytes.set(part, offset);
827
+ offset += part.byteLength;
828
+ }
829
+ return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
830
+ }
831
+ function parseCloudflareVectors(value, count) {
832
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
833
+ throw new OhCloudflareEmbeddingError("invalid-response", "The embedding provider returned an invalid envelope.");
834
+ }
835
+ const envelope = value;
836
+ if (envelope.success !== true || typeof envelope.result !== "object" || envelope.result === null || Array.isArray(envelope.result)) {
837
+ throw new OhCloudflareEmbeddingError("invalid-response", "The embedding provider returned an unsuccessful envelope.");
838
+ }
839
+ const result = envelope.result;
840
+ if (!Array.isArray(result.data) || result.data.length !== count || !Array.isArray(result.shape) || result.shape.length !== 2 || result.shape[0] !== count || result.shape[1] !== OH_CLOUDFLARE_EMBEDDING_PROFILE_V1.dimensions) {
841
+ throw new OhCloudflareEmbeddingError("invalid-response", "The embedding provider returned an incompatible shape.");
842
+ }
843
+ const vectors = result.data.map((candidate) => {
844
+ if (!Array.isArray(candidate) || candidate.length !== OH_CLOUDFLARE_EMBEDDING_PROFILE_V1.dimensions || candidate.some((component) => typeof component !== "number" || !Number.isFinite(component))) {
845
+ throw new OhCloudflareEmbeddingError("invalid-response", "The embedding provider returned an invalid vector.");
846
+ }
847
+ try {
848
+ return Object.freeze([...normalizeOhEmbeddingV1(candidate)]);
849
+ } catch {
850
+ throw new OhCloudflareEmbeddingError("invalid-response", "The embedding provider returned an invalid vector.");
851
+ }
852
+ });
853
+ return Object.freeze(vectors);
854
+ }
855
+
856
+ class OhCloudflareEmbeddingClientV1 {
857
+ profile = OH_CLOUDFLARE_EMBEDDING_PROFILE_V1;
858
+ #accountId;
859
+ #apiToken;
860
+ #deadlineMs;
861
+ #fetch;
862
+ #maximumBatchInputs;
863
+ #maximumResponseBytes;
864
+ constructor(options) {
865
+ if (!/^[a-f0-9]{32}$/iu.test(options.accountId) || options.apiToken.length < 16 || options.apiToken.length > 4096 || /[\r\n]/u.test(options.apiToken)) {
866
+ throw new OhCloudflareEmbeddingError("invalid-input", "Cloudflare credentials are malformed.");
867
+ }
868
+ this.#accountId = options.accountId.toLowerCase();
869
+ this.#apiToken = options.apiToken;
870
+ this.#deadlineMs = exactPositiveInteger(options.deadlineMs ?? 15000, OH_CLOUDFLARE_EMBEDDING_LIMITS_V1.deadlineMs, "deadlineMs");
871
+ this.#maximumBatchInputs = exactPositiveInteger(options.maximumBatchInputs ?? 16, OH_CLOUDFLARE_EMBEDDING_LIMITS_V1.batchInputs, "maximumBatchInputs");
872
+ this.#maximumResponseBytes = exactPositiveInteger(options.maximumResponseBytes ?? OH_CLOUDFLARE_EMBEDDING_LIMITS_V1.responseBytes, OH_CLOUDFLARE_EMBEDDING_LIMITS_V1.responseBytes, "maximumResponseBytes");
873
+ this.#fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
874
+ }
875
+ async embed(inputs, options = {}) {
876
+ if (!Array.isArray(inputs) || inputs.length < 1 || inputs.length > this.#maximumBatchInputs) {
877
+ throw new OhCloudflareEmbeddingError("invalid-input", `An embedding batch must contain 1 through ${this.#maximumBatchInputs} inputs.`);
878
+ }
879
+ const text = inputs.map((candidate) => {
880
+ if (!renderedEmbeddingInputs.has(candidate) || candidate.v !== 1 || candidate.kind !== "document" && candidate.kind !== "query" || candidate.utf8Bytes !== utf8ByteLength(candidate.input) || candidate.utf8Bytes > OH_CLOUDFLARE_EMBEDDING_LIMITS_V1.inputUtf8Bytes || parseSha256Hex(candidate.inputSha256) === null || candidate.inputSha256 !== sha256Hex(candidate.input)) {
881
+ throw new OhCloudflareEmbeddingError("invalid-input", "A rendered embedding input is invalid.");
882
+ }
883
+ return candidate.input;
884
+ });
885
+ const deadline = AbortSignal.timeout(this.#deadlineMs);
886
+ const signal = options.signal === undefined ? deadline : AbortSignal.any([options.signal, deadline]);
887
+ let response;
888
+ try {
889
+ response = await this.#fetch(`https://api.cloudflare.com/client/v4/accounts/${this.#accountId}/ai/run/${OH_CLOUDFLARE_EMBEDDING_PROFILE_V1.model}`, {
890
+ body: JSON.stringify({ text }),
891
+ headers: {
892
+ authorization: `Bearer ${this.#apiToken}`,
893
+ "content-type": "application/json"
894
+ },
895
+ method: "POST",
896
+ redirect: "error",
897
+ signal
898
+ });
899
+ } catch {
900
+ if (signal.aborted) {
901
+ throw new OhCloudflareEmbeddingError("aborted", "The embedding request was aborted.");
902
+ }
903
+ throw new OhCloudflareEmbeddingError("provider-unavailable", "The embedding provider is unavailable.");
904
+ }
905
+ if (!response.ok) {
906
+ try {
907
+ await response.body?.cancel();
908
+ } catch {}
909
+ throw new OhCloudflareEmbeddingError("provider-unavailable", `The embedding provider rejected the request with HTTP ${response.status}.`, response.status);
910
+ }
911
+ let value;
912
+ try {
913
+ value = JSON.parse(await boundedResponseText(response, this.#maximumResponseBytes));
914
+ } catch (error) {
915
+ if (error instanceof OhCloudflareEmbeddingError)
916
+ throw error;
917
+ if (signal.aborted) {
918
+ throw new OhCloudflareEmbeddingError("aborted", "The embedding request was aborted.");
919
+ }
920
+ throw new OhCloudflareEmbeddingError("invalid-response", "The embedding provider returned invalid JSON.");
921
+ }
922
+ return parseCloudflareVectors(value, inputs.length);
923
+ }
924
+ }
925
+ // src/libsql-semantic.ts
926
+ var OH_LIBSQL_SEMANTIC_LIMITS_V1 = Object.freeze({
927
+ chunksPerDocument: 64,
928
+ chunksPerGeneration: 4096,
929
+ documentsPerGeneration: 512,
930
+ embeddingBatch: 16,
931
+ searchLimit: 100,
932
+ searchPage: 128
933
+ });
934
+
935
+ class OhLibSqlSemanticError extends Error {
936
+ code;
937
+ constructor(code, message) {
938
+ super(message);
939
+ this.name = "OhLibSqlSemanticError";
940
+ this.code = code;
941
+ }
942
+ }
943
+ var SCHEMA_NAME = "oh.libsql-semantic-cache.v1";
944
+ var SCHEMA_VERSION = 1;
945
+ var VECTOR_BYTES = OH_CLOUDFLARE_EMBEDDING_PROFILE_V1.dimensions * 4;
946
+ var SCHEMA_TABLE = `CREATE TABLE IF NOT EXISTS oh_semantic_schemas (
947
+ version INTEGER PRIMARY KEY,
948
+ name TEXT NOT NULL UNIQUE,
949
+ schema_sha256 TEXT NOT NULL,
950
+ applied_at TEXT NOT NULL
951
+ ) STRICT`;
952
+ var SCHEMA_STATEMENTS = Object.freeze([
953
+ `CREATE TABLE IF NOT EXISTS oh_semantic_vectors (
954
+ profile_sha256 TEXT NOT NULL,
955
+ renderer_sha256 TEXT NOT NULL,
956
+ input_sha256 TEXT NOT NULL,
957
+ vector_sha256 TEXT NOT NULL,
958
+ vector BLOB NOT NULL,
959
+ created_at TEXT NOT NULL,
960
+ PRIMARY KEY(profile_sha256, renderer_sha256, input_sha256)
961
+ ) STRICT`,
962
+ `CREATE TABLE IF NOT EXISTS oh_semantic_generations (
963
+ authority_id TEXT NOT NULL,
964
+ generation INTEGER NOT NULL CHECK(generation >= 0),
965
+ authority_sha256 TEXT NOT NULL,
966
+ profile_sha256 TEXT NOT NULL,
967
+ renderer_sha256 TEXT NOT NULL,
968
+ membership_sha256 TEXT NOT NULL,
969
+ generation_sha256 TEXT NOT NULL UNIQUE,
970
+ document_count INTEGER NOT NULL CHECK(document_count >= 0),
971
+ chunk_count INTEGER NOT NULL CHECK(chunk_count >= 0),
972
+ created_at TEXT NOT NULL,
973
+ PRIMARY KEY(authority_id, generation)
974
+ ) STRICT`,
975
+ `CREATE TABLE IF NOT EXISTS oh_semantic_memberships (
976
+ authority_id TEXT NOT NULL,
977
+ generation INTEGER NOT NULL CHECK(generation >= 0),
978
+ generation_sha256 TEXT NOT NULL,
979
+ record_key TEXT NOT NULL,
980
+ record_sha256 TEXT NOT NULL,
981
+ ordinal INTEGER NOT NULL CHECK(ordinal >= 0),
982
+ input_sha256 TEXT NOT NULL,
983
+ PRIMARY KEY(authority_id, generation, record_key, ordinal)
984
+ ) STRICT`,
985
+ `CREATE TABLE IF NOT EXISTS oh_semantic_heads (
986
+ authority_id TEXT PRIMARY KEY,
987
+ generation INTEGER NOT NULL CHECK(generation >= 0),
988
+ authority_sha256 TEXT NOT NULL,
989
+ profile_sha256 TEXT NOT NULL,
990
+ renderer_sha256 TEXT NOT NULL,
991
+ membership_sha256 TEXT NOT NULL,
992
+ generation_sha256 TEXT NOT NULL,
993
+ published_at TEXT NOT NULL
994
+ ) STRICT`,
995
+ `CREATE TABLE IF NOT EXISTS oh_semantic_purges (
996
+ authority_id TEXT PRIMARY KEY,
997
+ purged_at TEXT NOT NULL
998
+ ) STRICT`,
999
+ `CREATE INDEX IF NOT EXISTS oh_semantic_memberships_generation
1000
+ ON oh_semantic_memberships(authority_id, generation, record_key, ordinal)`,
1001
+ `CREATE INDEX IF NOT EXISTS oh_semantic_memberships_input
1002
+ ON oh_semantic_memberships(input_sha256)`,
1003
+ `CREATE TRIGGER IF NOT EXISTS oh_semantic_vectors_no_update
1004
+ BEFORE UPDATE ON oh_semantic_vectors
1005
+ BEGIN SELECT RAISE(ABORT, 'Oh semantic vectors are immutable'); END`,
1006
+ `CREATE TRIGGER IF NOT EXISTS oh_semantic_generations_no_update
1007
+ BEFORE UPDATE ON oh_semantic_generations
1008
+ BEGIN SELECT RAISE(ABORT, 'Oh semantic generations are immutable'); END`,
1009
+ `CREATE TRIGGER IF NOT EXISTS oh_semantic_memberships_no_update
1010
+ BEFORE UPDATE ON oh_semantic_memberships
1011
+ BEGIN SELECT RAISE(ABORT, 'Oh semantic memberships are immutable'); END`,
1012
+ `CREATE TRIGGER IF NOT EXISTS oh_semantic_generations_purge_guard
1013
+ BEFORE INSERT ON oh_semantic_generations
1014
+ WHEN EXISTS (SELECT 1 FROM oh_semantic_purges WHERE authority_id = NEW.authority_id)
1015
+ BEGIN SELECT RAISE(ABORT, 'Oh semantic authority was purged'); END`,
1016
+ `CREATE TRIGGER IF NOT EXISTS oh_semantic_memberships_purge_guard
1017
+ BEFORE INSERT ON oh_semantic_memberships
1018
+ WHEN EXISTS (SELECT 1 FROM oh_semantic_purges WHERE authority_id = NEW.authority_id)
1019
+ BEGIN SELECT RAISE(ABORT, 'Oh semantic authority was purged'); END`,
1020
+ `CREATE TRIGGER IF NOT EXISTS oh_semantic_memberships_published_guard
1021
+ BEFORE INSERT ON oh_semantic_memberships
1022
+ WHEN EXISTS (SELECT 1 FROM oh_semantic_heads
1023
+ WHERE authority_id = NEW.authority_id AND generation = NEW.generation)
1024
+ AND NOT EXISTS (SELECT 1 FROM oh_semantic_memberships
1025
+ WHERE authority_id = NEW.authority_id AND generation = NEW.generation
1026
+ AND generation_sha256 = NEW.generation_sha256
1027
+ AND record_key = NEW.record_key AND record_sha256 = NEW.record_sha256
1028
+ AND ordinal = NEW.ordinal AND input_sha256 = NEW.input_sha256)
1029
+ BEGIN SELECT RAISE(ABORT, 'Oh semantic generation is published'); END`,
1030
+ `CREATE TRIGGER IF NOT EXISTS oh_semantic_heads_insert_purge_guard
1031
+ BEFORE INSERT ON oh_semantic_heads
1032
+ WHEN EXISTS (SELECT 1 FROM oh_semantic_purges WHERE authority_id = NEW.authority_id)
1033
+ BEGIN SELECT RAISE(ABORT, 'Oh semantic authority was purged'); END`,
1034
+ `CREATE TRIGGER IF NOT EXISTS oh_semantic_heads_update_purge_guard
1035
+ BEFORE UPDATE ON oh_semantic_heads
1036
+ WHEN EXISTS (SELECT 1 FROM oh_semantic_purges WHERE authority_id = NEW.authority_id)
1037
+ BEGIN SELECT RAISE(ABORT, 'Oh semantic authority was purged'); END`,
1038
+ `CREATE TRIGGER IF NOT EXISTS oh_semantic_purges_no_update
1039
+ BEFORE UPDATE ON oh_semantic_purges
1040
+ BEGIN SELECT RAISE(ABORT, 'Oh semantic purge markers are immutable'); END`,
1041
+ `CREATE TRIGGER IF NOT EXISTS oh_semantic_purges_no_delete
1042
+ BEFORE DELETE ON oh_semantic_purges
1043
+ BEGIN SELECT RAISE(ABORT, 'Oh semantic purge markers are immutable'); END`
1044
+ ]);
1045
+ function normalizedSchemaSql(sql) {
1046
+ return sql.replace(/\bIF\s+NOT\s+EXISTS\b/giu, "").replace(/\s+/gu, " ").trim();
1047
+ }
1048
+ function expectedSchemaObject(statement) {
1049
+ const match = /^CREATE\s+(TABLE|INDEX|TRIGGER)(?:\s+IF\s+NOT\s+EXISTS)?\s+([a-z0-9_]+)/iu.exec(statement.trim());
1050
+ if (match === null)
1051
+ throw new Error("Invalid compiled semantic schema statement.");
1052
+ const declared = match[1]?.toLowerCase();
1053
+ const type = declared === "index" ? "index" : declared === "trigger" ? "trigger" : "table";
1054
+ const name = match[2];
1055
+ const owner = type === "table" ? name : /\bON\s+([a-z0-9_]+)/iu.exec(statement)?.[1];
1056
+ if (owner === undefined)
1057
+ throw new Error("Invalid compiled semantic schema owner.");
1058
+ return { name, sql: normalizedSchemaSql(statement), tableName: owner, type };
1059
+ }
1060
+ var EXPECTED_SCHEMA_OBJECTS = Object.freeze([SCHEMA_TABLE, ...SCHEMA_STATEMENTS].map(expectedSchemaObject).sort((left, right) => canonicalJson([left.type, left.name]).localeCompare(canonicalJson([right.type, right.name]))));
1061
+ var SCHEMA_SHA256 = canonicalSha256(EXPECTED_SCHEMA_OBJECTS);
1062
+ function rowValue(row, key, index) {
1063
+ return Array.isArray(row) ? row[index] : row[key];
1064
+ }
1065
+ function integer(value) {
1066
+ if (typeof value === "number")
1067
+ return Number.isSafeInteger(value) ? value : null;
1068
+ if (typeof value === "bigint") {
1069
+ const converted = Number(value);
1070
+ return Number.isSafeInteger(converted) ? converted : null;
1071
+ }
1072
+ return null;
1073
+ }
1074
+ function rowsAffected(result) {
1075
+ return typeof result.rowsAffected === "number" && Number.isSafeInteger(result.rowsAffected) && result.rowsAffected >= 0 ? result.rowsAffected : 0;
1076
+ }
1077
+ function parseAuthorityId(value) {
1078
+ const parsed = safeCode(value, 256);
1079
+ if (parsed === null)
1080
+ throw new OhLibSqlSemanticError("invalid-input", "Invalid semantic authority ID.");
1081
+ return parsed;
1082
+ }
1083
+ function parseRecordKey(value) {
1084
+ const parsed = safeCode(value, 512);
1085
+ if (parsed === null)
1086
+ throw new OhLibSqlSemanticError("invalid-input", "Invalid semantic record key.");
1087
+ return parsed;
1088
+ }
1089
+ function parseGeneration(value) {
1090
+ if (!Number.isSafeInteger(value) || value < 0) {
1091
+ throw new OhLibSqlSemanticError("invalid-input", "Invalid semantic authority generation.");
1092
+ }
1093
+ return value;
1094
+ }
1095
+ function parseDigest(value, label) {
1096
+ const digest = parseSha256Hex(value);
1097
+ if (digest === null)
1098
+ throw new OhLibSqlSemanticError("invalid-input", `Invalid ${label} digest.`);
1099
+ return digest;
1100
+ }
1101
+ function parseInstant(value) {
1102
+ const instant = parseCanonicalInstantV1(value);
1103
+ if (instant === null)
1104
+ throw new OhLibSqlSemanticError("invalid-input", "Invalid semantic instant.");
1105
+ return instant;
1106
+ }
1107
+ async function schemaObjects(client) {
1108
+ const result = await client.execute(`SELECT type, name, tbl_name, sql FROM sqlite_schema
1109
+ WHERE sql IS NOT NULL AND (name GLOB 'oh_semantic_*' OR tbl_name GLOB 'oh_semantic_*')
1110
+ ORDER BY type, name`);
1111
+ return result.rows.map((row) => {
1112
+ const type = rowValue(row, "type", 0);
1113
+ const name = rowValue(row, "name", 1);
1114
+ const tableName = rowValue(row, "tbl_name", 2);
1115
+ const sql = rowValue(row, "sql", 3);
1116
+ if (type !== "index" && type !== "table" && type !== "trigger" || typeof name !== "string" || typeof tableName !== "string" || typeof sql !== "string") {
1117
+ throw new OhLibSqlSemanticError("integrity", "The semantic schema inventory is malformed.");
1118
+ }
1119
+ const schemaType = type;
1120
+ return { name, sql: normalizedSchemaSql(sql), tableName, type: schemaType };
1121
+ }).sort((left, right) => canonicalJson([left.type, left.name]).localeCompare(canonicalJson([right.type, right.name])));
1122
+ }
1123
+ async function verifySchema(client) {
1124
+ let marker;
1125
+ try {
1126
+ marker = await client.execute({
1127
+ args: [SCHEMA_VERSION],
1128
+ sql: "SELECT name, schema_sha256 FROM oh_semantic_schemas WHERE version = ?"
1129
+ });
1130
+ } catch {
1131
+ throw new OhLibSqlSemanticError("schema-unavailable", "The semantic cache schema is unavailable.");
1132
+ }
1133
+ const row = marker.rows[0];
1134
+ if (marker.rows.length !== 1 || row === undefined || rowValue(row, "name", 0) !== SCHEMA_NAME || rowValue(row, "schema_sha256", 1) !== SCHEMA_SHA256) {
1135
+ throw new OhLibSqlSemanticError("schema-unavailable", "The semantic cache schema marker is invalid.");
1136
+ }
1137
+ if (canonicalJson(await schemaObjects(client)) !== canonicalJson(EXPECTED_SCHEMA_OBJECTS)) {
1138
+ throw new OhLibSqlSemanticError("integrity", "The semantic cache schema has drifted.");
1139
+ }
1140
+ }
1141
+ async function bootstrapOhLibSqlSemanticCacheV1(client, options = {}) {
1142
+ const appliedAt = parseInstant(options.appliedAt ?? canonicalNow());
1143
+ const existing = await schemaObjects(client);
1144
+ if (existing.length === 0) {
1145
+ await client.batch([
1146
+ { sql: SCHEMA_TABLE },
1147
+ ...SCHEMA_STATEMENTS.map((sql) => ({ sql })),
1148
+ {
1149
+ args: [SCHEMA_VERSION, SCHEMA_NAME, SCHEMA_SHA256, appliedAt],
1150
+ sql: `INSERT INTO oh_semantic_schemas(version, name, schema_sha256, applied_at)
1151
+ VALUES (?, ?, ?, ?) ON CONFLICT(version) DO NOTHING`
1152
+ }
1153
+ ], "write");
1154
+ } else if (canonicalJson(existing) !== canonicalJson(EXPECTED_SCHEMA_OBJECTS)) {
1155
+ throw new OhLibSqlSemanticError("integrity", "Refusing to bless a partial or drifted semantic schema.");
1156
+ }
1157
+ await verifySchema(client);
1158
+ return Object.freeze({ schemaSha256: SCHEMA_SHA256, schemaVersion: 1, v: 1 });
1159
+ }
1160
+ function vectorBytes(vector) {
1161
+ const normalized = normalizeOhEmbeddingV1(vector);
1162
+ const bytes = new Uint8Array(VECTOR_BYTES);
1163
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
1164
+ for (const [index, component] of normalized.entries())
1165
+ view.setFloat32(index * 4, component, true);
1166
+ return bytes;
1167
+ }
1168
+ function storedBytes(value) {
1169
+ if (value instanceof Uint8Array)
1170
+ return new Uint8Array(value);
1171
+ if (value instanceof ArrayBuffer)
1172
+ return new Uint8Array(value.slice(0));
1173
+ return null;
1174
+ }
1175
+ function decodeVector(value, expectedSha256) {
1176
+ const bytes = storedBytes(value);
1177
+ const digest = parseSha256Hex(expectedSha256);
1178
+ if (bytes === null || bytes.byteLength !== VECTOR_BYTES || digest === null || sha256Hex(bytes) !== digest) {
1179
+ throw new OhLibSqlSemanticError("integrity", "A cached semantic vector is corrupt.");
1180
+ }
1181
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
1182
+ const vector = Array.from({ length: OH_CLOUDFLARE_EMBEDDING_PROFILE_V1.dimensions }, (_, index) => view.getFloat32(index * 4, true));
1183
+ try {
1184
+ return Object.freeze([...normalizeOhEmbeddingV1(vector)]);
1185
+ } catch {
1186
+ throw new OhLibSqlSemanticError("integrity", "A cached semantic vector is invalid.");
1187
+ }
1188
+ }
1189
+ function prepareGeneration(input) {
1190
+ const authorityId = parseAuthorityId(input.authorityId);
1191
+ const authoritySha256 = parseDigest(input.authoritySha256, "authority");
1192
+ const generation = parseGeneration(input.generation);
1193
+ const createdAt = parseInstant(input.createdAt ?? canonicalNow());
1194
+ const maximumChunks = input.maximumChunksPerDocument ?? OH_LIBSQL_SEMANTIC_LIMITS_V1.chunksPerDocument;
1195
+ if (!Number.isSafeInteger(maximumChunks) || maximumChunks < 1 || maximumChunks > OH_LIBSQL_SEMANTIC_LIMITS_V1.chunksPerDocument || !Array.isArray(input.documents) || input.documents.length < 1 || input.documents.length > OH_LIBSQL_SEMANTIC_LIMITS_V1.documentsPerGeneration) {
1196
+ throw new OhLibSqlSemanticError("invalid-input", "Invalid semantic generation bounds.");
1197
+ }
1198
+ const documents = input.documents.map((document) => {
1199
+ if (document.v !== 1)
1200
+ throw new OhLibSqlSemanticError("invalid-input", "Invalid semantic document version.");
1201
+ return {
1202
+ ...document,
1203
+ key: parseRecordKey(document.key),
1204
+ recordSha256: parseDigest(document.recordSha256, "record")
1205
+ };
1206
+ }).sort((left, right) => left.key < right.key ? -1 : left.key > right.key ? 1 : 0);
1207
+ if (new Set(documents.map(({ key }) => key)).size !== documents.length) {
1208
+ throw new OhLibSqlSemanticError("invalid-input", "Semantic document keys must be unique.");
1209
+ }
1210
+ const memberships = [];
1211
+ for (const document of documents) {
1212
+ const rendered = renderOhCloudflareEmbeddingDocumentV1({
1213
+ content: document.content,
1214
+ maximumChunks,
1215
+ title: document.title
1216
+ });
1217
+ if (rendered.status !== "complete") {
1218
+ throw new OhLibSqlSemanticError("invalid-input", "A semantic document exceeds the complete renderer bound.");
1219
+ }
1220
+ for (const chunk of rendered.chunks) {
1221
+ memberships.push(Object.freeze({
1222
+ input: chunk.input,
1223
+ inputSha256: chunk.input.inputSha256,
1224
+ ordinal: chunk.ordinal,
1225
+ recordKey: document.key,
1226
+ recordSha256: document.recordSha256
1227
+ }));
1228
+ }
1229
+ }
1230
+ if (memberships.length < 1 || memberships.length > OH_LIBSQL_SEMANTIC_LIMITS_V1.chunksPerGeneration) {
1231
+ throw new OhLibSqlSemanticError("invalid-input", "The semantic generation exceeds its chunk bound.");
1232
+ }
1233
+ const membershipSha256 = canonicalSha256(memberships.map((membership) => ({
1234
+ inputSha256: membership.inputSha256,
1235
+ ordinal: membership.ordinal,
1236
+ recordKey: membership.recordKey,
1237
+ recordSha256: membership.recordSha256
1238
+ })));
1239
+ const generationSha256 = canonicalSha256({
1240
+ authorityId,
1241
+ authoritySha256,
1242
+ chunkCount: memberships.length,
1243
+ documentCount: documents.length,
1244
+ generation,
1245
+ membershipSha256,
1246
+ profileSha256: OH_CLOUDFLARE_EMBEDDING_PROFILE_V1.profileSha256,
1247
+ rendererSha256: OH_SEMANTIC_RENDERER_V1.rendererSha256,
1248
+ v: 1
1249
+ });
1250
+ return Object.freeze({
1251
+ authorityId,
1252
+ authoritySha256,
1253
+ chunkCount: memberships.length,
1254
+ createdAt,
1255
+ documentCount: documents.length,
1256
+ generation,
1257
+ generationSha256,
1258
+ membershipSha256,
1259
+ memberships: Object.freeze(memberships)
1260
+ });
1261
+ }
1262
+ function parseStoredGeneration(row) {
1263
+ const authorityId = safeCode(rowValue(row, "authority_id", 0), 256);
1264
+ const generation = integer(rowValue(row, "generation", 1));
1265
+ const authoritySha256 = parseSha256Hex(rowValue(row, "authority_sha256", 2));
1266
+ const profileSha256 = parseSha256Hex(rowValue(row, "profile_sha256", 3));
1267
+ const rendererSha256 = parseSha256Hex(rowValue(row, "renderer_sha256", 4));
1268
+ const membershipSha256 = parseSha256Hex(rowValue(row, "membership_sha256", 5));
1269
+ const generationSha256 = parseSha256Hex(rowValue(row, "generation_sha256", 6));
1270
+ const documentCount = integer(rowValue(row, "document_count", 7));
1271
+ const chunkCount = integer(rowValue(row, "chunk_count", 8));
1272
+ const createdAtValue = rowValue(row, "created_at", 9);
1273
+ const createdAt = parseCanonicalInstantV1(createdAtValue);
1274
+ if (authorityId === null || generation === null || generation < 0 || authoritySha256 === null || profileSha256 === null || rendererSha256 === null || membershipSha256 === null || generationSha256 === null || documentCount === null || documentCount < 1 || documentCount > OH_LIBSQL_SEMANTIC_LIMITS_V1.documentsPerGeneration || chunkCount === null || chunkCount < 1 || chunkCount > OH_LIBSQL_SEMANTIC_LIMITS_V1.chunksPerGeneration || createdAt === null) {
1275
+ throw new OhLibSqlSemanticError("integrity", "A stored semantic generation is invalid.");
1276
+ }
1277
+ return Object.freeze({
1278
+ authorityId,
1279
+ authoritySha256,
1280
+ chunkCount,
1281
+ createdAt,
1282
+ documentCount,
1283
+ generation,
1284
+ generationSha256,
1285
+ membershipSha256,
1286
+ profileSha256,
1287
+ rendererSha256
1288
+ });
1289
+ }
1290
+ function generationMatches(left, right) {
1291
+ return left.authorityId === right.authorityId && left.authoritySha256 === right.authoritySha256 && left.chunkCount === right.chunkCount && left.documentCount === right.documentCount && left.generation === right.generation && left.generationSha256 === right.generationSha256 && left.membershipSha256 === right.membershipSha256 && left.profileSha256 === OH_CLOUDFLARE_EMBEDDING_PROFILE_V1.profileSha256 && left.rendererSha256 === OH_SEMANTIC_RENDERER_V1.rendererSha256;
1292
+ }
1293
+ function parseStoredHead(row) {
1294
+ const authorityId = safeCode(rowValue(row, "authority_id", 0), 256);
1295
+ const generation = integer(rowValue(row, "generation", 1));
1296
+ const authoritySha256 = parseSha256Hex(rowValue(row, "authority_sha256", 2));
1297
+ const profileSha256 = parseSha256Hex(rowValue(row, "profile_sha256", 3));
1298
+ const rendererSha256 = parseSha256Hex(rowValue(row, "renderer_sha256", 4));
1299
+ const membershipSha256 = parseSha256Hex(rowValue(row, "membership_sha256", 5));
1300
+ const generationSha256 = parseSha256Hex(rowValue(row, "generation_sha256", 6));
1301
+ const publishedAtValue = rowValue(row, "published_at", 7);
1302
+ const publishedAt = parseCanonicalInstantV1(publishedAtValue);
1303
+ if (authorityId === null || generation === null || generation < 0 || authoritySha256 === null || profileSha256 === null || rendererSha256 === null || membershipSha256 === null || generationSha256 === null || publishedAt === null) {
1304
+ throw new OhLibSqlSemanticError("integrity", "A stored semantic head is invalid.");
1305
+ }
1306
+ return Object.freeze({
1307
+ authorityId,
1308
+ authoritySha256,
1309
+ generation,
1310
+ generationSha256,
1311
+ membershipSha256,
1312
+ profileSha256,
1313
+ publishedAt,
1314
+ rendererSha256
1315
+ });
1316
+ }
1317
+ function headMatchesGeneration(head, generation) {
1318
+ return head.authorityId === generation.authorityId && head.authoritySha256 === generation.authoritySha256 && head.generation === generation.generation && head.generationSha256 === generation.generationSha256 && head.membershipSha256 === generation.membershipSha256 && head.profileSha256 === generation.profileSha256 && head.rendererSha256 === generation.rendererSha256;
1319
+ }
1320
+ var GENERATION_SELECT = `SELECT authority_id, generation, authority_sha256,
1321
+ profile_sha256, renderer_sha256, membership_sha256, generation_sha256,
1322
+ document_count, chunk_count, created_at
1323
+ FROM oh_semantic_generations WHERE authority_id = ? AND generation = ?`;
1324
+ var HEAD_SELECT = `SELECT authority_id, generation, authority_sha256,
1325
+ profile_sha256, renderer_sha256, membership_sha256, generation_sha256, published_at
1326
+ FROM oh_semantic_heads WHERE authority_id = ?`;
1327
+ async function readGeneration(client, authorityId, generation) {
1328
+ const result = await client.execute({ args: [authorityId, generation], sql: GENERATION_SELECT });
1329
+ if (result.rows.length > 1)
1330
+ throw new OhLibSqlSemanticError("integrity", "Duplicate semantic generations.");
1331
+ const row = result.rows[0];
1332
+ return row === undefined ? null : parseStoredGeneration(row);
1333
+ }
1334
+ async function readHead(client, authorityId) {
1335
+ const result = await client.execute({ args: [authorityId], sql: HEAD_SELECT });
1336
+ if (result.rows.length > 1)
1337
+ throw new OhLibSqlSemanticError("integrity", "Duplicate semantic heads.");
1338
+ const row = result.rows[0];
1339
+ return row === undefined ? null : parseStoredHead(row);
1340
+ }
1341
+ async function readPurge(client, authorityId) {
1342
+ const result = await client.execute({
1343
+ args: [authorityId],
1344
+ sql: "SELECT purged_at FROM oh_semantic_purges WHERE authority_id = ?"
1345
+ });
1346
+ if (result.rows.length > 1)
1347
+ throw new OhLibSqlSemanticError("integrity", "Duplicate semantic purge markers.");
1348
+ const row = result.rows[0];
1349
+ if (row === undefined)
1350
+ return null;
1351
+ const purgedAt = parseCanonicalInstantV1(rowValue(row, "purged_at", 0));
1352
+ if (purgedAt === null)
1353
+ throw new OhLibSqlSemanticError("integrity", "The semantic purge marker is invalid.");
1354
+ return purgedAt;
1355
+ }
1356
+ async function readMemberships(client, generation) {
1357
+ const memberships = [];
1358
+ for (let offset = 0;offset < generation.chunkCount; offset += OH_LIBSQL_SEMANTIC_LIMITS_V1.searchPage) {
1359
+ const result = await client.execute({
1360
+ args: [
1361
+ generation.authorityId,
1362
+ generation.generation,
1363
+ OH_LIBSQL_SEMANTIC_LIMITS_V1.searchPage,
1364
+ offset
1365
+ ],
1366
+ sql: `SELECT generation_sha256, record_key, record_sha256, ordinal, input_sha256
1367
+ FROM oh_semantic_memberships
1368
+ WHERE authority_id = ? AND generation = ?
1369
+ ORDER BY record_key, ordinal LIMIT ? OFFSET ?`
1370
+ });
1371
+ for (const row of result.rows) {
1372
+ const generationSha256 = parseSha256Hex(rowValue(row, "generation_sha256", 0));
1373
+ const recordKey2 = safeCode(rowValue(row, "record_key", 1), 512);
1374
+ const recordSha256 = parseSha256Hex(rowValue(row, "record_sha256", 2));
1375
+ const ordinal = integer(rowValue(row, "ordinal", 3));
1376
+ const inputSha256 = parseSha256Hex(rowValue(row, "input_sha256", 4));
1377
+ if (generationSha256 !== generation.generationSha256 || recordKey2 === null || recordSha256 === null || ordinal === null || ordinal < 0 || ordinal >= OH_LIBSQL_SEMANTIC_LIMITS_V1.chunksPerDocument || inputSha256 === null) {
1378
+ throw new OhLibSqlSemanticError("integrity", "A semantic generation membership is invalid.");
1379
+ }
1380
+ memberships.push(Object.freeze({ inputSha256, ordinal, recordKey: recordKey2, recordSha256 }));
1381
+ }
1382
+ }
1383
+ if (memberships.length !== generation.chunkCount || canonicalSha256(memberships.map((membership) => ({
1384
+ inputSha256: membership.inputSha256,
1385
+ ordinal: membership.ordinal,
1386
+ recordKey: membership.recordKey,
1387
+ recordSha256: membership.recordSha256
1388
+ }))) !== generation.membershipSha256) {
1389
+ throw new OhLibSqlSemanticError("integrity", "A semantic generation membership digest is invalid.");
1390
+ }
1391
+ return Object.freeze(memberships);
1392
+ }
1393
+ async function readVectors(client, inputSha256s) {
1394
+ const vectors = new Map;
1395
+ for (let offset = 0;offset < inputSha256s.length; offset += 64) {
1396
+ const page = inputSha256s.slice(offset, offset + 64);
1397
+ if (page.length === 0)
1398
+ continue;
1399
+ const placeholders = page.map(() => "?").join(", ");
1400
+ const result = await client.execute({
1401
+ args: [
1402
+ OH_CLOUDFLARE_EMBEDDING_PROFILE_V1.profileSha256,
1403
+ OH_SEMANTIC_RENDERER_V1.rendererSha256,
1404
+ ...page
1405
+ ],
1406
+ sql: `SELECT input_sha256, vector_sha256, vector FROM oh_semantic_vectors
1407
+ WHERE profile_sha256 = ? AND renderer_sha256 = ?
1408
+ AND input_sha256 IN (${placeholders}) ORDER BY input_sha256`
1409
+ });
1410
+ for (const row of result.rows) {
1411
+ const inputSha256 = parseSha256Hex(rowValue(row, "input_sha256", 0));
1412
+ const vectorSha256 = parseSha256Hex(rowValue(row, "vector_sha256", 1));
1413
+ if (inputSha256 === null || vectorSha256 === null || !page.includes(inputSha256) || vectors.has(inputSha256)) {
1414
+ throw new OhLibSqlSemanticError("integrity", "A cached semantic vector identity is invalid.");
1415
+ }
1416
+ const bytes = storedBytes(rowValue(row, "vector", 2));
1417
+ if (bytes === null) {
1418
+ throw new OhLibSqlSemanticError("integrity", "A cached semantic vector is corrupt.");
1419
+ }
1420
+ decodeVector(bytes, vectorSha256);
1421
+ vectors.set(inputSha256, Object.freeze({
1422
+ bytes,
1423
+ inputSha256,
1424
+ vectorSha256
1425
+ }));
1426
+ }
1427
+ }
1428
+ return vectors;
1429
+ }
1430
+ function validateEmbeddingClient(client) {
1431
+ if (client.profile.profileSha256 !== OH_CLOUDFLARE_EMBEDDING_PROFILE_V1.profileSha256) {
1432
+ throw new OhLibSqlSemanticError("invalid-input", "The embedding client profile is incompatible.");
1433
+ }
1434
+ }
1435
+
1436
+ class OhLibSqlSemanticCacheV1 {
1437
+ #client;
1438
+ #closeClient;
1439
+ #closed = false;
1440
+ constructor(client, closeClient) {
1441
+ this.#client = client;
1442
+ this.#closeClient = closeClient;
1443
+ }
1444
+ static async open(client, closeClient) {
1445
+ await verifySchema(client);
1446
+ return new OhLibSqlSemanticCacheV1(client, closeClient);
1447
+ }
1448
+ #open() {
1449
+ if (this.#closed)
1450
+ throw new OhLibSqlSemanticError("schema-unavailable", "The semantic cache is closed.");
1451
+ }
1452
+ async close() {
1453
+ if (this.#closed)
1454
+ return;
1455
+ this.#closed = true;
1456
+ if (this.#closeClient)
1457
+ this.#client.close?.();
1458
+ }
1459
+ async publishedHead(input) {
1460
+ this.#open();
1461
+ const authorityId = parseAuthorityId(input.authorityId);
1462
+ if (await readPurge(this.#client, authorityId) !== null)
1463
+ return null;
1464
+ const head = await readHead(this.#client, authorityId);
1465
+ if (head === null)
1466
+ return null;
1467
+ const generation = await readGeneration(this.#client, authorityId, head.generation);
1468
+ if (generation === null || !headMatchesGeneration(head, generation)) {
1469
+ if (await readPurge(this.#client, authorityId) !== null)
1470
+ return null;
1471
+ throw new OhLibSqlSemanticError("integrity", "The semantic published head does not match its immutable generation.");
1472
+ }
1473
+ if (await readPurge(this.#client, authorityId) !== null)
1474
+ return null;
1475
+ const finalHead = await readHead(this.#client, authorityId);
1476
+ if (finalHead === null) {
1477
+ if (await readPurge(this.#client, authorityId) !== null)
1478
+ return null;
1479
+ throw new OhLibSqlSemanticError("integrity", "The semantic published head disappeared during its read.");
1480
+ }
1481
+ if (canonicalJson(finalHead) !== canonicalJson(head)) {
1482
+ throw new OhLibSqlSemanticError("conflict", "The semantic published head changed during its read.");
1483
+ }
1484
+ return Object.freeze({ ...head, v: 1 });
1485
+ }
1486
+ async stage(input) {
1487
+ this.#open();
1488
+ validateEmbeddingClient(input.embeddingClient);
1489
+ const prepared = prepareGeneration(input);
1490
+ if (await readPurge(this.#client, prepared.authorityId) !== null) {
1491
+ throw new OhLibSqlSemanticError("purged", "The semantic authority was purged.");
1492
+ }
1493
+ const uniqueInputs = new Map;
1494
+ for (const membership of prepared.memberships)
1495
+ uniqueInputs.set(membership.inputSha256, membership.input);
1496
+ const orderedInputs = [...uniqueInputs.entries()].sort(([left], [right]) => left < right ? -1 : 1);
1497
+ const existingVectors = await readVectors(this.#client, orderedInputs.map(([digest]) => digest));
1498
+ const missing = orderedInputs.filter(([digest]) => !existingVectors.has(digest));
1499
+ const candidateVectors = new Map(existingVectors);
1500
+ for (let offset = 0;offset < missing.length; offset += OH_LIBSQL_SEMANTIC_LIMITS_V1.embeddingBatch) {
1501
+ const page = missing.slice(offset, offset + OH_LIBSQL_SEMANTIC_LIMITS_V1.embeddingBatch);
1502
+ const vectors = await input.embeddingClient.embed(page.map(([, rendered]) => rendered), input.signal === undefined ? {} : { signal: input.signal });
1503
+ if (vectors.length !== page.length) {
1504
+ throw new OhLibSqlSemanticError("integrity", "The embedding client returned a mismatched vector batch.");
1505
+ }
1506
+ for (const [index, [inputSha256]] of page.entries()) {
1507
+ const vector = vectors[index];
1508
+ if (vector === undefined)
1509
+ throw new OhLibSqlSemanticError("integrity", "A semantic vector is missing.");
1510
+ const bytes = vectorBytes(vector);
1511
+ const vectorSha256 = sha256Hex(bytes);
1512
+ decodeVector(bytes, vectorSha256);
1513
+ candidateVectors.set(inputSha256, Object.freeze({ bytes, inputSha256, vectorSha256 }));
1514
+ }
1515
+ }
1516
+ const statements = [{
1517
+ args: [
1518
+ prepared.authorityId,
1519
+ prepared.generation,
1520
+ prepared.authoritySha256,
1521
+ OH_CLOUDFLARE_EMBEDDING_PROFILE_V1.profileSha256,
1522
+ OH_SEMANTIC_RENDERER_V1.rendererSha256,
1523
+ prepared.membershipSha256,
1524
+ prepared.generationSha256,
1525
+ prepared.documentCount,
1526
+ prepared.chunkCount,
1527
+ prepared.createdAt,
1528
+ prepared.authorityId
1529
+ ],
1530
+ sql: `INSERT INTO oh_semantic_generations(authority_id, generation,
1531
+ authority_sha256, profile_sha256, renderer_sha256, membership_sha256,
1532
+ generation_sha256, document_count, chunk_count, created_at)
1533
+ SELECT ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
1534
+ WHERE NOT EXISTS (SELECT 1 FROM oh_semantic_purges WHERE authority_id = ?)
1535
+ ON CONFLICT DO NOTHING`
1536
+ }];
1537
+ for (const [inputSha256] of orderedInputs) {
1538
+ const candidate = candidateVectors.get(inputSha256);
1539
+ if (candidate === undefined) {
1540
+ throw new OhLibSqlSemanticError("integrity", "A semantic vector candidate is missing.");
1541
+ }
1542
+ statements.push({
1543
+ args: [
1544
+ OH_CLOUDFLARE_EMBEDDING_PROFILE_V1.profileSha256,
1545
+ OH_SEMANTIC_RENDERER_V1.rendererSha256,
1546
+ inputSha256,
1547
+ candidate.vectorSha256,
1548
+ candidate.bytes,
1549
+ prepared.createdAt,
1550
+ prepared.authorityId,
1551
+ prepared.generation,
1552
+ prepared.generationSha256,
1553
+ prepared.authorityId
1554
+ ],
1555
+ sql: `INSERT INTO oh_semantic_vectors(profile_sha256, renderer_sha256,
1556
+ input_sha256, vector_sha256, vector, created_at)
1557
+ SELECT ?, ?, ?, ?, ?, ?
1558
+ WHERE EXISTS (SELECT 1 FROM oh_semantic_generations
1559
+ WHERE authority_id = ? AND generation = ? AND generation_sha256 = ?)
1560
+ AND NOT EXISTS (SELECT 1 FROM oh_semantic_purges WHERE authority_id = ?)
1561
+ ON CONFLICT DO NOTHING`
1562
+ });
1563
+ }
1564
+ for (const membership of prepared.memberships) {
1565
+ statements.push({
1566
+ args: [
1567
+ prepared.authorityId,
1568
+ prepared.generation,
1569
+ prepared.generationSha256,
1570
+ membership.recordKey,
1571
+ membership.recordSha256,
1572
+ membership.ordinal,
1573
+ membership.inputSha256,
1574
+ prepared.authorityId,
1575
+ prepared.generation,
1576
+ prepared.generationSha256,
1577
+ prepared.authorityId
1578
+ ],
1579
+ sql: `INSERT INTO oh_semantic_memberships(authority_id, generation,
1580
+ generation_sha256, record_key, record_sha256, ordinal, input_sha256)
1581
+ SELECT ?, ?, ?, ?, ?, ?, ?
1582
+ WHERE EXISTS (SELECT 1 FROM oh_semantic_generations
1583
+ WHERE authority_id = ? AND generation = ? AND generation_sha256 = ?)
1584
+ AND NOT EXISTS (SELECT 1 FROM oh_semantic_purges WHERE authority_id = ?)
1585
+ ON CONFLICT DO NOTHING`
1586
+ });
1587
+ }
1588
+ await this.#client.batch(statements, "write");
1589
+ const completeVectors = await readVectors(this.#client, orderedInputs.map(([digest]) => digest));
1590
+ if (completeVectors.size !== orderedInputs.length) {
1591
+ if (await readPurge(this.#client, prepared.authorityId) !== null) {
1592
+ throw new OhLibSqlSemanticError("purged", "The semantic authority was purged.");
1593
+ }
1594
+ throw new OhLibSqlSemanticError("integrity", "The semantic vector cache did not converge.");
1595
+ }
1596
+ const stored = await readGeneration(this.#client, prepared.authorityId, prepared.generation);
1597
+ if (await readPurge(this.#client, prepared.authorityId) !== null) {
1598
+ throw new OhLibSqlSemanticError("purged", "The semantic authority was purged.");
1599
+ }
1600
+ if (stored === null || !generationMatches(stored, prepared)) {
1601
+ throw new OhLibSqlSemanticError("conflict", "The semantic generation identity conflicts.");
1602
+ }
1603
+ const memberships = await readMemberships(this.#client, stored);
1604
+ if (canonicalJson(memberships) !== canonicalJson(prepared.memberships.map((membership) => ({
1605
+ inputSha256: membership.inputSha256,
1606
+ ordinal: membership.ordinal,
1607
+ recordKey: membership.recordKey,
1608
+ recordSha256: membership.recordSha256
1609
+ })))) {
1610
+ throw new OhLibSqlSemanticError("conflict", "The semantic generation membership conflicts.");
1611
+ }
1612
+ return Object.freeze({
1613
+ authorityId: prepared.authorityId,
1614
+ chunks: prepared.chunkCount,
1615
+ documents: prepared.documentCount,
1616
+ embedded: missing.length,
1617
+ generation: prepared.generation,
1618
+ generationSha256: prepared.generationSha256,
1619
+ membershipSha256: prepared.membershipSha256,
1620
+ reused: orderedInputs.length - missing.length,
1621
+ status: "staged",
1622
+ v: 1
1623
+ });
1624
+ }
1625
+ async publish(input) {
1626
+ this.#open();
1627
+ const authorityId = parseAuthorityId(input.authorityId);
1628
+ const generationNumber = parseGeneration(input.generation);
1629
+ const expected = input.expectedPublishedGeneration === null ? null : parseGeneration(input.expectedPublishedGeneration);
1630
+ const publishedAt = parseInstant(input.publishedAt ?? canonicalNow());
1631
+ if (await readPurge(this.#client, authorityId) !== null) {
1632
+ throw new OhLibSqlSemanticError("purged", "The semantic authority was purged.");
1633
+ }
1634
+ const generation = await readGeneration(this.#client, authorityId, generationNumber);
1635
+ if (generation === null) {
1636
+ throw new OhLibSqlSemanticError("conflict", "The semantic generation is not staged.");
1637
+ }
1638
+ await readMemberships(this.#client, generation);
1639
+ const before = await readHead(this.#client, authorityId);
1640
+ if (before !== null && headMatchesGeneration(before, generation)) {
1641
+ return Object.freeze({
1642
+ authorityId,
1643
+ generation: generationNumber,
1644
+ generationSha256: generation.generationSha256,
1645
+ published: false,
1646
+ v: 1
1647
+ });
1648
+ }
1649
+ if (before === null !== (expected === null) || before !== null && before.generation !== expected || before !== null && generationNumber < before.generation) {
1650
+ throw new OhLibSqlSemanticError("conflict", "The semantic published-head precondition failed.");
1651
+ }
1652
+ let result;
1653
+ const values = [
1654
+ generation.authorityId,
1655
+ generation.generation,
1656
+ generation.authoritySha256,
1657
+ generation.profileSha256,
1658
+ generation.rendererSha256,
1659
+ generation.membershipSha256,
1660
+ generation.generationSha256,
1661
+ publishedAt
1662
+ ];
1663
+ if (expected === null) {
1664
+ result = await this.#client.execute({
1665
+ args: [
1666
+ ...values,
1667
+ generation.authorityId,
1668
+ generation.generation,
1669
+ generation.generationSha256,
1670
+ authorityId,
1671
+ authorityId
1672
+ ],
1673
+ sql: `INSERT INTO oh_semantic_heads(authority_id, generation,
1674
+ authority_sha256, profile_sha256, renderer_sha256, membership_sha256,
1675
+ generation_sha256, published_at)
1676
+ SELECT ?, ?, ?, ?, ?, ?, ?, ?
1677
+ WHERE EXISTS (SELECT 1 FROM oh_semantic_generations
1678
+ WHERE authority_id = ? AND generation = ? AND generation_sha256 = ?)
1679
+ AND NOT EXISTS (SELECT 1 FROM oh_semantic_purges WHERE authority_id = ?)
1680
+ AND NOT EXISTS (SELECT 1 FROM oh_semantic_heads WHERE authority_id = ?)
1681
+ ON CONFLICT DO NOTHING`
1682
+ });
1683
+ } else {
1684
+ result = await this.#client.execute({
1685
+ args: [
1686
+ generation.generation,
1687
+ generation.authoritySha256,
1688
+ generation.profileSha256,
1689
+ generation.rendererSha256,
1690
+ generation.membershipSha256,
1691
+ generation.generationSha256,
1692
+ publishedAt,
1693
+ authorityId,
1694
+ expected,
1695
+ generation.authorityId,
1696
+ generation.generation,
1697
+ generation.generationSha256,
1698
+ authorityId
1699
+ ],
1700
+ sql: `UPDATE oh_semantic_heads SET generation = ?, authority_sha256 = ?,
1701
+ profile_sha256 = ?, renderer_sha256 = ?, membership_sha256 = ?,
1702
+ generation_sha256 = ?, published_at = ?
1703
+ WHERE authority_id = ? AND generation = ?
1704
+ AND EXISTS (SELECT 1 FROM oh_semantic_generations
1705
+ WHERE authority_id = ? AND generation = ? AND generation_sha256 = ?)
1706
+ AND NOT EXISTS (SELECT 1 FROM oh_semantic_purges WHERE authority_id = ?)`
1707
+ });
1708
+ }
1709
+ if (await readPurge(this.#client, authorityId) !== null) {
1710
+ throw new OhLibSqlSemanticError("purged", "The semantic authority was purged.");
1711
+ }
1712
+ const after = await readHead(this.#client, authorityId);
1713
+ if (after === null || !headMatchesGeneration(after, generation)) {
1714
+ throw new OhLibSqlSemanticError("conflict", "The semantic published head did not converge.");
1715
+ }
1716
+ return Object.freeze({
1717
+ authorityId,
1718
+ generation: generationNumber,
1719
+ generationSha256: generation.generationSha256,
1720
+ published: rowsAffected(result) > 0,
1721
+ v: 1
1722
+ });
1723
+ }
1724
+ async search(input) {
1725
+ this.#open();
1726
+ validateEmbeddingClient(input.embeddingClient);
1727
+ const authorityId = parseAuthorityId(input.authority.authorityId);
1728
+ const authoritySha256 = parseDigest(input.authority.authoritySha256, "authority");
1729
+ const authorityGeneration = parseGeneration(input.authority.generation);
1730
+ const limit = input.limit ?? 10;
1731
+ if (input.authority.v !== 1 || !Number.isSafeInteger(limit) || limit < 1 || limit > OH_LIBSQL_SEMANTIC_LIMITS_V1.searchLimit || !Array.isArray(input.authority.records) || input.authority.records.length > OH_LIBSQL_SEMANTIC_LIMITS_V1.documentsPerGeneration) {
1732
+ throw new OhLibSqlSemanticError("invalid-input", "Invalid semantic search authority or limit.");
1733
+ }
1734
+ const records = new Map;
1735
+ for (const record of input.authority.records) {
1736
+ const key = parseRecordKey(record.key);
1737
+ const recordSha256 = parseDigest(record.recordSha256, "record");
1738
+ if (records.has(key))
1739
+ throw new OhLibSqlSemanticError("invalid-input", "Duplicate authority record key.");
1740
+ records.set(key, recordSha256);
1741
+ }
1742
+ if (await readPurge(this.#client, authorityId) !== null)
1743
+ return Object.freeze([]);
1744
+ const head = await readHead(this.#client, authorityId);
1745
+ if (head === null || head.authoritySha256 !== authoritySha256 || head.generation !== authorityGeneration || head.profileSha256 !== OH_CLOUDFLARE_EMBEDDING_PROFILE_V1.profileSha256 || head.rendererSha256 !== OH_SEMANTIC_RENDERER_V1.rendererSha256) {
1746
+ return Object.freeze([]);
1747
+ }
1748
+ const generation = await readGeneration(this.#client, authorityId, authorityGeneration);
1749
+ if (generation === null || !headMatchesGeneration(head, generation))
1750
+ return Object.freeze([]);
1751
+ const renderedQuery = renderOhCloudflareEmbeddingQueryV1(input.query);
1752
+ const queryVectors = await input.embeddingClient.embed([renderedQuery], input.signal === undefined ? {} : { signal: input.signal });
1753
+ const queryVector = queryVectors[0];
1754
+ if (queryVectors.length !== 1 || queryVector === undefined) {
1755
+ throw new OhLibSqlSemanticError("integrity", "The query embedding response is invalid.");
1756
+ }
1757
+ const normalizedQuery = normalizeOhEmbeddingV1(queryVector);
1758
+ const best = new Map;
1759
+ let scanned = 0;
1760
+ for (let offset = 0;offset < generation.chunkCount; offset += OH_LIBSQL_SEMANTIC_LIMITS_V1.searchPage) {
1761
+ const result = await this.#client.execute({
1762
+ args: [
1763
+ OH_CLOUDFLARE_EMBEDDING_PROFILE_V1.profileSha256,
1764
+ OH_SEMANTIC_RENDERER_V1.rendererSha256,
1765
+ authorityId,
1766
+ authorityGeneration,
1767
+ OH_LIBSQL_SEMANTIC_LIMITS_V1.searchPage,
1768
+ offset
1769
+ ],
1770
+ sql: `SELECT membership.generation_sha256, membership.record_key,
1771
+ membership.record_sha256, membership.ordinal, membership.input_sha256,
1772
+ vector.vector_sha256, vector.vector
1773
+ FROM oh_semantic_memberships AS membership
1774
+ JOIN oh_semantic_vectors AS vector
1775
+ ON vector.input_sha256 = membership.input_sha256
1776
+ AND vector.profile_sha256 = ? AND vector.renderer_sha256 = ?
1777
+ WHERE membership.authority_id = ? AND membership.generation = ?
1778
+ ORDER BY membership.record_key, membership.ordinal LIMIT ? OFFSET ?`
1779
+ });
1780
+ for (const row of result.rows) {
1781
+ scanned += 1;
1782
+ const generationSha256 = parseSha256Hex(rowValue(row, "generation_sha256", 0));
1783
+ const key = safeCode(rowValue(row, "record_key", 1), 512);
1784
+ const recordSha256 = parseSha256Hex(rowValue(row, "record_sha256", 2));
1785
+ const ordinal = integer(rowValue(row, "ordinal", 3));
1786
+ const inputSha256 = parseSha256Hex(rowValue(row, "input_sha256", 4));
1787
+ const vectorSha256 = parseSha256Hex(rowValue(row, "vector_sha256", 5));
1788
+ if (generationSha256 !== generation.generationSha256 || key === null || recordSha256 === null || ordinal === null || ordinal < 0 || ordinal >= OH_LIBSQL_SEMANTIC_LIMITS_V1.chunksPerDocument || inputSha256 === null || vectorSha256 === null) {
1789
+ throw new OhLibSqlSemanticError("integrity", "A semantic search row is invalid.");
1790
+ }
1791
+ if (records.get(key) !== recordSha256)
1792
+ continue;
1793
+ const vector = decodeVector(rowValue(row, "vector", 6), vectorSha256);
1794
+ let score = 0;
1795
+ for (let index = 0;index < normalizedQuery.length; index += 1) {
1796
+ score += normalizedQuery[index] * vector[index];
1797
+ }
1798
+ score = Math.max(-1, Math.min(1, score));
1799
+ const previous = best.get(key);
1800
+ if (previous === undefined || score > previous.score || score === previous.score && ordinal < previous.chunkOrdinal) {
1801
+ best.set(key, Object.freeze({ chunkOrdinal: ordinal, key, recordSha256, score, v: 1 }));
1802
+ }
1803
+ }
1804
+ }
1805
+ if (scanned !== generation.chunkCount) {
1806
+ throw new OhLibSqlSemanticError("integrity", "The semantic search scan is incomplete.");
1807
+ }
1808
+ const finalHead = await readHead(this.#client, authorityId);
1809
+ if (finalHead === null || canonicalJson(finalHead) !== canonicalJson(head) || await readPurge(this.#client, authorityId) !== null)
1810
+ return Object.freeze([]);
1811
+ return Object.freeze([...best.values()].sort((left, right) => right.score - left.score || (left.key < right.key ? -1 : left.key > right.key ? 1 : 0)).slice(0, limit));
1812
+ }
1813
+ async purgeAuthority(input) {
1814
+ this.#open();
1815
+ const authorityId = parseAuthorityId(input.authorityId);
1816
+ const requestedAt = parseInstant(input.purgedAt ?? canonicalNow());
1817
+ const previous = await readPurge(this.#client, authorityId);
1818
+ const results = await this.#client.batch([
1819
+ {
1820
+ args: [authorityId, requestedAt],
1821
+ sql: `INSERT INTO oh_semantic_purges(authority_id, purged_at)
1822
+ VALUES (?, ?) ON CONFLICT DO NOTHING`
1823
+ },
1824
+ { args: [authorityId], sql: "DELETE FROM oh_semantic_heads WHERE authority_id = ?" },
1825
+ { args: [authorityId], sql: "DELETE FROM oh_semantic_memberships WHERE authority_id = ?" },
1826
+ { args: [authorityId], sql: "DELETE FROM oh_semantic_generations WHERE authority_id = ?" },
1827
+ {
1828
+ sql: `DELETE FROM oh_semantic_vectors AS vector
1829
+ WHERE NOT EXISTS (SELECT 1 FROM oh_semantic_memberships AS membership
1830
+ WHERE membership.input_sha256 = vector.input_sha256)`
1831
+ }
1832
+ ], "write");
1833
+ const purgedAt = await readPurge(this.#client, authorityId);
1834
+ if (purgedAt === null || previous !== null && purgedAt !== previous) {
1835
+ throw new OhLibSqlSemanticError("integrity", "The semantic purge did not converge.");
1836
+ }
1837
+ if (await readHead(this.#client, authorityId) !== null || (await this.#client.execute({
1838
+ args: [authorityId, authorityId],
1839
+ sql: `SELECT authority_id FROM oh_semantic_generations WHERE authority_id = ?
1840
+ UNION ALL SELECT authority_id FROM oh_semantic_memberships WHERE authority_id = ? LIMIT 1`
1841
+ })).rows.length !== 0) {
1842
+ throw new OhLibSqlSemanticError("integrity", "The semantic authority purge is incomplete.");
1843
+ }
1844
+ return Object.freeze({
1845
+ authorityId,
1846
+ generations: rowsAffected(results[3] ?? { rows: [] }),
1847
+ memberships: rowsAffected(results[2] ?? { rows: [] }),
1848
+ orphanVectors: rowsAffected(results[4] ?? { rows: [] }),
1849
+ purgedAt,
1850
+ v: 1
1851
+ });
1852
+ }
1853
+ }
1854
+ async function openOhLibSqlSemanticCacheV1(client, options = {}) {
1855
+ return await OhLibSqlSemanticCacheV1.open(client, options.closeClient ?? false);
1856
+ }
1857
+ export {
1858
+ renderOhCloudflareEmbeddingQueryV1,
1859
+ renderOhCloudflareEmbeddingDocumentV1,
1860
+ openOhLibSqlSemanticCacheV1,
1861
+ bootstrapOhLibSqlSemanticCacheV1,
1862
+ OhLibSqlSemanticError,
1863
+ OhLibSqlSemanticCacheV1,
1864
+ OhCloudflareEmbeddingError,
1865
+ OhCloudflareEmbeddingClientV1,
1866
+ OH_SEMANTIC_RENDERER_V1,
1867
+ OH_LIBSQL_SEMANTIC_LIMITS_V1,
1868
+ OH_CLOUDFLARE_EMBEDDING_PROFILE_V1,
1869
+ OH_CLOUDFLARE_EMBEDDING_LIMITS_V1
1870
+ };