@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,130 @@
1
+ import { type Sha256Hex } from "./canonical";
2
+ import { type OhCloudflareEmbeddingClientV1 } from "./cloudflare-embedding";
3
+ import type { OhLibSqlClientV1 } from "./libsql";
4
+ export declare const OH_LIBSQL_SEMANTIC_LIMITS_V1: Readonly<{
5
+ chunksPerDocument: 64;
6
+ chunksPerGeneration: 4096;
7
+ documentsPerGeneration: 512;
8
+ embeddingBatch: 16;
9
+ searchLimit: 100;
10
+ searchPage: 128;
11
+ }>;
12
+ export declare class OhLibSqlSemanticError extends Error {
13
+ readonly code: "conflict" | "integrity" | "invalid-input" | "purged" | "schema-unavailable";
14
+ constructor(code: OhLibSqlSemanticError["code"], message: string);
15
+ }
16
+ export type OhSemanticAuthorityRefV1 = Readonly<{
17
+ authorityId: string;
18
+ authoritySha256: Sha256Hex;
19
+ generation: number;
20
+ records: readonly Readonly<{
21
+ key: string;
22
+ recordSha256: Sha256Hex;
23
+ }>[];
24
+ v: 1;
25
+ }>;
26
+ export type OhSemanticDocumentV1 = Readonly<{
27
+ content: string;
28
+ key: string;
29
+ recordSha256: Sha256Hex;
30
+ title: string;
31
+ v: 1;
32
+ }>;
33
+ export type OhSemanticStageResultV1 = Readonly<{
34
+ authorityId: string;
35
+ chunks: number;
36
+ documents: number;
37
+ embedded: number;
38
+ generation: number;
39
+ generationSha256: Sha256Hex;
40
+ membershipSha256: Sha256Hex;
41
+ reused: number;
42
+ status: "staged";
43
+ v: 1;
44
+ }>;
45
+ export type OhSemanticPublishResultV1 = Readonly<{
46
+ authorityId: string;
47
+ generation: number;
48
+ generationSha256: Sha256Hex;
49
+ published: boolean;
50
+ v: 1;
51
+ }>;
52
+ /** The exact, currently published cache pointer for one semantic authority. */
53
+ export type OhSemanticPublishedHeadV1 = Readonly<{
54
+ authorityId: string;
55
+ authoritySha256: Sha256Hex;
56
+ generation: number;
57
+ generationSha256: Sha256Hex;
58
+ membershipSha256: Sha256Hex;
59
+ profileSha256: Sha256Hex;
60
+ publishedAt: string;
61
+ rendererSha256: Sha256Hex;
62
+ v: 1;
63
+ }>;
64
+ export type OhSemanticSearchResultV1 = Readonly<{
65
+ chunkOrdinal: number;
66
+ key: string;
67
+ recordSha256: Sha256Hex;
68
+ score: number;
69
+ v: 1;
70
+ }>;
71
+ export type OhSemanticPurgeResultV1 = Readonly<{
72
+ authorityId: string;
73
+ generations: number;
74
+ memberships: number;
75
+ orphanVectors: number;
76
+ purgedAt: string;
77
+ v: 1;
78
+ }>;
79
+ export declare function bootstrapOhLibSqlSemanticCacheV1(client: OhLibSqlClientV1, options?: Readonly<{
80
+ appliedAt?: string;
81
+ }>): Promise<Readonly<{
82
+ schemaSha256: Sha256Hex;
83
+ schemaVersion: 1;
84
+ v: 1;
85
+ }>>;
86
+ export declare class OhLibSqlSemanticCacheV1 {
87
+ #private;
88
+ private constructor();
89
+ /** @internal Public callers should use `openOhLibSqlSemanticCacheV1`. */
90
+ static open(client: OhLibSqlClientV1, closeClient: boolean): Promise<OhLibSqlSemanticCacheV1>;
91
+ close(): Promise<void>;
92
+ /**
93
+ * Reads the current compare-and-swap base without exposing cache rows or
94
+ * private source text. An absent or purged authority has no published head.
95
+ */
96
+ publishedHead(input: Readonly<{
97
+ authorityId: string;
98
+ }>): Promise<OhSemanticPublishedHeadV1 | null>;
99
+ stage(input: Readonly<{
100
+ authorityId: string;
101
+ authoritySha256: Sha256Hex;
102
+ createdAt?: string;
103
+ documents: readonly OhSemanticDocumentV1[];
104
+ embeddingClient: OhCloudflareEmbeddingClientV1;
105
+ generation: number;
106
+ maximumChunksPerDocument?: number;
107
+ signal?: AbortSignal;
108
+ }>): Promise<OhSemanticStageResultV1>;
109
+ publish(input: Readonly<{
110
+ authorityId: string;
111
+ expectedPublishedGeneration: number | null;
112
+ generation: number;
113
+ publishedAt?: string;
114
+ }>): Promise<OhSemanticPublishResultV1>;
115
+ search(input: Readonly<{
116
+ authority: OhSemanticAuthorityRefV1;
117
+ embeddingClient: OhCloudflareEmbeddingClientV1;
118
+ limit?: number;
119
+ query: string;
120
+ signal?: AbortSignal;
121
+ }>): Promise<readonly OhSemanticSearchResultV1[]>;
122
+ purgeAuthority(input: Readonly<{
123
+ authorityId: string;
124
+ purgedAt?: string;
125
+ }>): Promise<OhSemanticPurgeResultV1>;
126
+ }
127
+ export declare function openOhLibSqlSemanticCacheV1(client: OhLibSqlClientV1, options?: Readonly<{
128
+ closeClient?: boolean;
129
+ }>): Promise<OhLibSqlSemanticCacheV1>;
130
+ //# sourceMappingURL=libsql-semantic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"libsql-semantic.d.ts","sourceRoot":"","sources":["../src/libsql-semantic.ts"],"names":[],"mappings":"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"}
package/dist/libsql.js CHANGED
@@ -60,17 +60,27 @@ function encodeCanonical(value, path, ancestors) {
60
60
  ancestors.add(value);
61
61
  try {
62
62
  if (Array.isArray(value)) {
63
- const encoded = [];
64
- for (let index = 0;index < value.length; index += 1) {
65
- if (!Object.hasOwn(value, index)) {
66
- throw new OhValidationError("sparse-array", `${path}[${index}]`, "must not contain holes");
67
- }
68
- encoded.push(encodeCanonical(value[index], `${path}[${index}]`, ancestors));
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");
69
67
  }
70
- const extraKeys = Reflect.ownKeys(value).filter((key) => key !== "length" && (typeof key !== "string" || !/^(?:0|[1-9][0-9]*)$/u.test(key) || Number(key) >= value.length));
71
- if (extraKeys.length > 0) {
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))) {
72
70
  throw new OhValidationError("non-json-property", path, "array has non-index properties");
73
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));
74
84
  return `[${encoded.join(",")}]`;
75
85
  }
76
86
  if (!isPlainRecord(value)) {
@@ -80,19 +90,21 @@ function encodeCanonical(value, path, ancestors) {
80
90
  if (ownKeys.some((key) => typeof key !== "string")) {
81
91
  throw new OhValidationError("non-json-property", path, "object has a symbol property");
82
92
  }
93
+ const entries = [];
83
94
  const keys = ownKeys;
84
95
  for (const key of keys) {
85
96
  const descriptor = Object.getOwnPropertyDescriptor(value, key);
86
97
  if (descriptor === undefined || !descriptor.enumerable || descriptor.get !== undefined || descriptor.set !== undefined) {
87
98
  throw new OhValidationError("non-json-property", `${path}.${key}`, "must be an enumerable data property");
88
99
  }
100
+ entries.push([key, descriptor.value]);
89
101
  }
90
- keys.sort();
91
- const entries = keys.map((key) => {
102
+ entries.sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0);
103
+ const encodedEntries = entries.map(([key, entryValue]) => {
92
104
  assertUnicodeScalarString(key, `${path}.<key>`);
93
- return `${JSON.stringify(key)}:${encodeCanonical(value[key], `${path}.${key}`, ancestors)}`;
105
+ return `${JSON.stringify(key)}:${encodeCanonical(entryValue, `${path}.${key}`, ancestors)}`;
94
106
  });
95
- return `{${entries.join(",")}}`;
107
+ return `{${encodedEntries.join(",")}}`;
96
108
  } finally {
97
109
  ancestors.delete(value);
98
110
  }
@@ -140,6 +152,21 @@ function canonicalNow() {
140
152
  function safeCode(value, maximumLength = 128) {
141
153
  return typeof value === "string" && value.length <= maximumLength && /^[a-z][a-z0-9]*(?:[._:/-][a-z0-9]+)*$/u.test(value) ? value : null;
142
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
+ }
143
170
  function orderedUnique(values, key) {
144
171
  return values.every((value, index) => index === 0 || key(values[index - 1]) < key(value));
145
172
  }
@@ -183,17 +210,70 @@ var OH_KNOWLEDGE_GRAPH_RECORD_KINDS_V1 = [
183
210
  "view",
184
211
  "vocabulary"
185
212
  ];
213
+ var KNOWLEDGE_GRAPH_RECORD_KEYS_V1 = [
214
+ "dependencies",
215
+ "key",
216
+ "kind",
217
+ "recordSha256",
218
+ "v",
219
+ "value"
220
+ ];
221
+ function exactKnowledgeGraphRecordEnvelopeV1(value) {
222
+ try {
223
+ if (!isPlainRecord(value))
224
+ return null;
225
+ const ownKeys = Reflect.ownKeys(value);
226
+ 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)))
227
+ return null;
228
+ const detached = {};
229
+ for (const key of KNOWLEDGE_GRAPH_RECORD_KEYS_V1) {
230
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
231
+ if (descriptor === undefined || !descriptor.enumerable || descriptor.get !== undefined || descriptor.set !== undefined)
232
+ return null;
233
+ detached[key] = descriptor.value;
234
+ }
235
+ return detached;
236
+ } catch {
237
+ return null;
238
+ }
239
+ }
240
+ function exactGraphDependenciesV1(value) {
241
+ try {
242
+ if (!Array.isArray(value))
243
+ return null;
244
+ const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length");
245
+ const length = lengthDescriptor?.value;
246
+ if (typeof length !== "number" || !Number.isSafeInteger(length) || length < 0 || length > OH_GRAPH_LIMITS_V1.dependenciesPerRecord)
247
+ return null;
248
+ const ownKeys = Reflect.ownKeys(value);
249
+ 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)))
250
+ return null;
251
+ const detached = [];
252
+ for (let index = 0;index < length; index += 1) {
253
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
254
+ if (descriptor === undefined || !descriptor.enumerable || descriptor.get !== undefined || descriptor.set !== undefined)
255
+ return null;
256
+ detached.push(descriptor.value);
257
+ }
258
+ return detached;
259
+ } catch {
260
+ return null;
261
+ }
262
+ }
186
263
  function recordKey(value) {
187
264
  return typeof value === "string" && value.length <= 512 && /^[a-z][a-z0-9]*(?:[._:/-][a-z0-9]+)*$/u.test(value) ? value : null;
188
265
  }
189
266
  function createKnowledgeGraphRecordV1(input) {
190
- if (!isPlainRecord(input) || !hasExactKeys(input, ["dependencies", "key", "kind", "v", "value"]) || input.v !== 1 || !Array.isArray(input.dependencies))
267
+ if (!isPlainRecord(input) || !hasExactKeys(input, ["dependencies", "key", "kind", "v", "value"]) || input.v !== 1)
191
268
  throw new TypeError("Invalid graph record input.");
269
+ const dependencyInput = exactGraphDependenciesV1(input.dependencies);
270
+ if (dependencyInput === null)
271
+ throw new TypeError("Invalid graph record dependencies.");
192
272
  const key = recordKey(input.key);
193
273
  const kind = OH_KNOWLEDGE_GRAPH_RECORD_KINDS_V1.find((candidate) => candidate === input.kind);
194
- if (key === null || kind === undefined || input.dependencies.length > OH_GRAPH_LIMITS_V1.dependenciesPerRecord)
274
+ if (key === null || kind === undefined)
195
275
  throw new TypeError("Invalid graph record identity.");
196
- const dependencies = input.dependencies.map(recordKey);
276
+ const dependencies = dependencyInput.map(recordKey);
197
277
  if (dependencies.some((dependency) => dependency === null) || !orderedUnique(dependencies, String) || dependencies.includes(key)) {
198
278
  throw new TypeError("Graph dependencies must be ordered, unique, and non-reflexive.");
199
279
  }
@@ -205,10 +285,17 @@ function createKnowledgeGraphRecordV1(input) {
205
285
  return { ...payload, recordSha256: canonicalSha256(payload) };
206
286
  }
207
287
  function parseKnowledgeGraphRecordV1(value) {
208
- if (!isPlainRecord(value) || !Object.hasOwn(value, "recordSha256"))
288
+ const envelope = exactKnowledgeGraphRecordEnvelopeV1(value);
289
+ if (envelope === null)
209
290
  return null;
210
- const recordSha256 = parseSha256Hex(value.recordSha256);
211
- const { recordSha256: _digest, ...input } = value;
291
+ const recordSha256 = parseSha256Hex(envelope.recordSha256);
292
+ const input = {
293
+ dependencies: envelope.dependencies,
294
+ key: envelope.key,
295
+ kind: envelope.kind,
296
+ v: envelope.v,
297
+ value: envelope.value
298
+ };
212
299
  try {
213
300
  const created = createKnowledgeGraphRecordV1(input);
214
301
  return recordSha256 !== null && created.recordSha256 === recordSha256 ? { ...created, recordSha256 } : null;
@@ -0,0 +1,2 @@
1
+ export * from "./memory-pages";
2
+ //# sourceMappingURL=memory-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-page.d.ts","sourceRoot":"","sources":["../src/memory-page.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}