pikelet-wasm 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/CHANGELOG.md +19 -3
  2. package/NOTICE +5 -0
  3. package/README.md +397 -454
  4. package/complete/builder.d.ts +4 -4
  5. package/complete/builder.mjs +8 -8
  6. package/complete/encoder-kernels/encoder.node.wasm +0 -0
  7. package/complete/encoder-kernels/encoder.wasm +0 -0
  8. package/complete/index.d.ts +11 -7
  9. package/complete/index.mjs +161 -112
  10. package/complete/inline-transformer.mjs +22 -9
  11. package/complete/lexical.mjs +11 -11
  12. package/complete/retrieval-abstention.mjs +18 -6
  13. package/complete/sources.mjs +22 -1
  14. package/dist/engine.js +1 -1
  15. package/dist/engine.scalar.js +1 -1
  16. package/dist/engine.scalar.wasm +0 -0
  17. package/dist/engine.wasm +0 -0
  18. package/package.json +58 -51
  19. package/{pancake-artifact-common.js → pikelet-artifact-common.js} +42 -42
  20. package/{pancake-artifact-range.js → pikelet-artifact-range.js} +36 -36
  21. package/{pancake-artifact-sketch.js → pikelet-artifact-sketch.js} +76 -66
  22. package/{pancake-artifact.d.ts → pikelet-artifact.d.ts} +11 -11
  23. package/{pancake-artifact.js → pikelet-artifact.js} +10 -10
  24. package/{pancake-core.js → pikelet-core.js} +136 -136
  25. package/{pancake-errors.js → pikelet-errors.js} +9 -8
  26. package/{pancake.d.ts → pikelet.d.ts} +55 -55
  27. package/{pancake.js → pikelet.js} +44 -44
  28. package/{pancake.node.mjs → pikelet.node.mjs} +46 -46
  29. package/{pancake.web.d.ts → pikelet.web.d.ts} +13 -13
  30. package/{pancake.web.mjs → pikelet.web.mjs} +20 -20
  31. package/{pancake.workerd.mjs → pikelet.workerd.mjs} +18 -18
  32. /package/{pancake-loader.js → pikelet-loader.js} +0 -0
package/package.json CHANGED
@@ -1,67 +1,67 @@
1
1
  {
2
2
  "name": "pikelet-wasm",
3
- "version": "0.7.0",
4
- "description": "HNSW vector search in WebAssembly. Runs in Node.js, browsers, and Cloudflare Workers with no native dependencies.",
5
- "main": "pancake.js",
6
- "types": "pancake.d.ts",
3
+ "version": "0.8.0",
4
+ "description": "Vector search engine and .pikelet artifact readers/builders, in WebAssembly. Compile a corpus into one self-contained, hash-verified search file, or use the underlying HNSW engine directly. Runs in Node.js, browsers, and Cloudflare Workers with no native dependencies.",
5
+ "main": "pikelet.js",
6
+ "types": "pikelet.d.ts",
7
7
  "exports": {
8
8
  ".": {
9
9
  "workerd": {
10
- "types": "./pancake.web.d.ts",
11
- "default": "./pancake.workerd.mjs"
10
+ "types": "./pikelet.web.d.ts",
11
+ "default": "./pikelet.workerd.mjs"
12
12
  },
13
13
  "browser": {
14
- "types": "./pancake.web.d.ts",
15
- "default": "./pancake.web.mjs"
14
+ "types": "./pikelet.web.d.ts",
15
+ "default": "./pikelet.web.mjs"
16
16
  },
17
17
  "import": {
18
- "types": "./pancake.d.ts",
19
- "default": "./pancake.node.mjs"
18
+ "types": "./pikelet.d.ts",
19
+ "default": "./pikelet.node.mjs"
20
20
  },
21
21
  "require": {
22
- "types": "./pancake.d.ts",
23
- "default": "./pancake.js"
22
+ "types": "./pikelet.d.ts",
23
+ "default": "./pikelet.js"
24
24
  },
25
25
  "default": {
26
- "types": "./pancake.d.ts",
27
- "default": "./pancake.js"
26
+ "types": "./pikelet.d.ts",
27
+ "default": "./pikelet.js"
28
28
  }
29
29
  },
30
30
  "./web": {
31
31
  "workerd": {
32
- "types": "./pancake.web.d.ts",
33
- "default": "./pancake.workerd.mjs"
32
+ "types": "./pikelet.web.d.ts",
33
+ "default": "./pikelet.workerd.mjs"
34
34
  },
35
35
  "browser": {
36
- "types": "./pancake.web.d.ts",
37
- "default": "./pancake.web.mjs"
36
+ "types": "./pikelet.web.d.ts",
37
+ "default": "./pikelet.web.mjs"
38
38
  },
39
39
  "import": {
40
- "types": "./pancake.web.d.ts",
41
- "default": "./pancake.web.mjs"
40
+ "types": "./pikelet.web.d.ts",
41
+ "default": "./pikelet.web.mjs"
42
42
  },
43
43
  "default": {
44
- "types": "./pancake.web.d.ts",
45
- "default": "./pancake.web.mjs"
44
+ "types": "./pikelet.web.d.ts",
45
+ "default": "./pikelet.web.mjs"
46
46
  }
47
47
  },
48
48
  "./node": {
49
49
  "import": {
50
- "types": "./pancake.d.ts",
51
- "default": "./pancake.node.mjs"
50
+ "types": "./pikelet.d.ts",
51
+ "default": "./pikelet.node.mjs"
52
52
  },
53
53
  "require": {
54
- "types": "./pancake.d.ts",
55
- "default": "./pancake.js"
54
+ "types": "./pikelet.d.ts",
55
+ "default": "./pikelet.js"
56
56
  },
57
57
  "default": {
58
- "types": "./pancake.d.ts",
59
- "default": "./pancake.js"
58
+ "types": "./pikelet.d.ts",
59
+ "default": "./pikelet.js"
60
60
  }
61
61
  },
62
62
  "./artifact": {
63
- "types": "./pancake-artifact.d.ts",
64
- "default": "./pancake-artifact.js"
63
+ "types": "./pikelet-artifact.d.ts",
64
+ "default": "./pikelet-artifact.js"
65
65
  },
66
66
  "./complete": {
67
67
  "types": "./complete/index.d.ts",
@@ -75,27 +75,28 @@
75
75
  },
76
76
  "files": [
77
77
  "complete",
78
- "pancake.js",
79
- "pancake-artifact.js",
80
- "pancake-artifact-common.js",
81
- "pancake-artifact-range.js",
82
- "pancake-artifact-sketch.js",
83
- "pancake.node.mjs",
84
- "pancake.web.mjs",
85
- "pancake.workerd.mjs",
86
- "pancake-core.js",
87
- "pancake-errors.js",
88
- "pancake-loader.js",
89
- "pancake.d.ts",
90
- "pancake.web.d.ts",
91
- "pancake-artifact.d.ts",
78
+ "pikelet.js",
79
+ "pikelet-artifact.js",
80
+ "pikelet-artifact-common.js",
81
+ "pikelet-artifact-range.js",
82
+ "pikelet-artifact-sketch.js",
83
+ "pikelet.node.mjs",
84
+ "pikelet.web.mjs",
85
+ "pikelet.workerd.mjs",
86
+ "pikelet-core.js",
87
+ "pikelet-errors.js",
88
+ "pikelet-loader.js",
89
+ "pikelet.d.ts",
90
+ "pikelet.web.d.ts",
91
+ "pikelet-artifact.d.ts",
92
92
  "dist/engine.js",
93
93
  "dist/engine.wasm",
94
94
  "dist/engine.scalar.js",
95
95
  "dist/engine.scalar.wasm",
96
96
  "LICENSE",
97
97
  "README.md",
98
- "CHANGELOG.md"
98
+ "CHANGELOG.md",
99
+ "NOTICE"
99
100
  ],
100
101
  "scripts": {
101
102
  "build": "node scripts/build-engine.mjs",
@@ -103,19 +104,19 @@
103
104
  "build:all": "node scripts/build-all.mjs",
104
105
  "bench": "node benchmarks/run.js",
105
106
  "demo:data": "node scripts/make-demo-vectors.mjs",
106
- "demo": "npm run demo:data && node examples/legacy/technical-demo/technical_demo_cli.js",
107
+ "demo:veyra": "node examples/05-one-file-search/web/veyra-corpus/fetch-veyra.mjs",
107
108
  "demo:artifact": "node examples/legacy/range-artifact-demo/demo.js --compact",
108
109
  "demo:sketch": "node examples/legacy/range-artifact-demo/sketch_demo.js --compact",
109
110
  "demo:artifact:browser:build": "vite build examples/legacy/range-artifact-demo/static",
110
111
  "demo:artifact:browser": "vite preview examples/legacy/range-artifact-demo/static --host 127.0.0.1",
111
- "build:pages-demo": "node examples/03-edge-docs-search/pages-ui/build.mjs",
112
+ "build:pages-demo": "node examples/legacy/03-edge-docs-search/pages-ui/build.mjs",
112
113
  "test": "node run_tests.js && node test/model_c_loader.js && node test/sketch_profile.js && node test/sketch_staged.js && node test/sketch_row_integrity.js && node test/artifact_hardening.js && node test/complete_profile.mjs && node test/mcp_conformance.mjs && node test/ingestion/run.mjs && npm run test:types",
113
114
  "test:types": "tsc -p test/types/tsconfig.json",
114
115
  "test:browser": "node test/browser_smoke.js",
115
116
  "test:worker-web": "node test/test_worker_web_entry.js",
116
117
  "test:simd": "node test/simd_parity.js",
117
118
  "test:fuzz": "node test/fuzz_import.js",
118
- "test:worker-example": "cd examples/03-edge-docs-search && npx wrangler deploy --dry-run --outdir ../../.tmp-test-work/student-worker-distilled && cd ../.. && node examples/03-edge-docs-search/test_worker.mjs",
119
+ "test:worker-example": "cd examples/legacy/03-edge-docs-search && npx wrangler deploy --dry-run --outdir ../../../.tmp-test-work/student-worker-distilled && cd ../../.. && node examples/legacy/03-edge-docs-search/test_worker.mjs",
119
120
  "test:scaffold": "node scripts/test-scaffold-e2e.mjs",
120
121
  "bench:range-storage": "node scripts/benchmark-range-storage.mjs",
121
122
  "pack:dry-run": "node scripts/pack-dry-run.mjs",
@@ -123,6 +124,12 @@
123
124
  },
124
125
  "keywords": [
125
126
  "vector-search",
127
+ "search-artifact",
128
+ "knowledge-pack",
129
+ "retrieval",
130
+ "rag",
131
+ "mcp",
132
+ "model-context-protocol",
126
133
  "ann",
127
134
  "hnsw",
128
135
  "wasm",
@@ -140,12 +147,12 @@
140
147
  ],
141
148
  "repository": {
142
149
  "type": "git",
143
- "url": "git+https://github.com/mcn92/pancake.git"
150
+ "url": "git+https://github.com/mcn92/pikelet.git"
144
151
  },
145
152
  "bugs": {
146
- "url": "https://github.com/mcn92/pancake/issues"
153
+ "url": "https://github.com/mcn92/pikelet/issues"
147
154
  },
148
- "homepage": "https://github.com/mcn92/pancake#readme",
155
+ "homepage": "https://github.com/mcn92/pikelet#readme",
149
156
  "author": "Matthew Noonan",
150
157
  "license": "Apache-2.0",
151
158
  "publishConfig": {
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
  // Shared by the range and sketch artifact readers/builders: read budgets and
3
3
  // range validation, range sources, the result heap, snapshot parsing, and
4
- // SHA-256 helpers. Not a public entry; pancake-artifact.js re-exports what is public.
5
- // Split out of pancake-artifact.js (the public entry, which re-exports the
4
+ // SHA-256 helpers. Not a public entry; pikelet-artifact.js re-exports what is public.
5
+ // Split out of pikelet-artifact.js (the public entry, which re-exports the
6
6
  // three parts); see that file for the module map.
7
7
 
8
- const { pancakeError, PANCAKE_ERROR_CODES } = require('./pancake-errors.js');
8
+ const { pikeletError, PIKELET_ERROR_CODES } = require('./pikelet-errors.js');
9
9
 
10
- const PANCAKE_MAGIC = 0x504E434B;
10
+ const PIKELET_MAGIC = 0x504E434B;
11
11
  const V1_ENVELOPE_HEADER_SIZE = 24;
12
12
  const V2_ENVELOPE_HEADER_SIZE = 20;
13
13
  const V3_ENVELOPE_HEADER_SIZE = 32;
@@ -54,16 +54,16 @@ async function mapLimit(items, limit, fn) {
54
54
  function checkArtifactRange(source, offset, length, label, limit = MAX_ARTIFACT_READ_BYTES) {
55
55
  if (!Number.isSafeInteger(offset) || !Number.isSafeInteger(length)
56
56
  || offset < 0 || length < 0 || !Number.isSafeInteger(offset + length)) {
57
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID,
57
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID,
58
58
  `Artifact ${label} range is out of bounds`, { offset, length });
59
59
  }
60
60
  const max = Math.min(limit, MAX_ARTIFACT_READ_BYTES);
61
61
  if (length > max) {
62
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID,
62
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID,
63
63
  `Artifact ${label} range exceeds the maximum read size`, { length, max });
64
64
  }
65
65
  if (source && Number.isSafeInteger(source.size) && offset + length > source.size) {
66
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID,
66
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID,
67
67
  `Artifact ${label} range extends past the source size`, { offset, length, size: source.size });
68
68
  }
69
69
  return length;
@@ -84,7 +84,7 @@ function resolveMaxReadBytes(value) {
84
84
  if (value === undefined) return DEFAULT_OPEN_READ_BYTES;
85
85
  if (value === Infinity) return MAX_ARTIFACT_READ_BYTES;
86
86
  if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
87
- throw pancakeError(PANCAKE_ERROR_CODES.INVALID_ARGUMENT,
87
+ throw pikeletError(PIKELET_ERROR_CODES.INVALID_ARGUMENT,
88
88
  'maxReadBytes must be a positive number or Infinity', { maxReadBytes: value });
89
89
  }
90
90
  return value;
@@ -95,7 +95,7 @@ function asUint8Array(bytes) {
95
95
  if (ArrayBuffer.isView(bytes)) {
96
96
  return new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength);
97
97
  }
98
- throw pancakeError(PANCAKE_ERROR_CODES.INVALID_ARGUMENT, 'Range source returned a non-binary value');
98
+ throw pikeletError(PIKELET_ERROR_CODES.INVALID_ARGUMENT, 'Range source returned a non-binary value');
99
99
  }
100
100
 
101
101
  // Both readers accept a maxCacheBytes option: undefined keeps the default,
@@ -106,7 +106,7 @@ function resolveMaxCacheBytes(value, floorBytes, defaultBytes) {
106
106
  if (value === undefined) return defaultBytes;
107
107
  if (value === Infinity) return Infinity;
108
108
  if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
109
- throw pancakeError(PANCAKE_ERROR_CODES.INVALID_ARGUMENT, 'maxCacheBytes must be a positive number or Infinity', { maxCacheBytes: value });
109
+ throw pikeletError(PIKELET_ERROR_CODES.INVALID_ARGUMENT, 'maxCacheBytes must be a positive number or Infinity', { maxCacheBytes: value });
110
110
  }
111
111
  return Math.max(value, floorBytes);
112
112
  }
@@ -213,7 +213,7 @@ class NodeFileRangeSource {
213
213
 
214
214
  async read(offset, length) {
215
215
  if (this.fd === null) {
216
- throw pancakeError(PANCAKE_ERROR_CODES.INVALID_ARGUMENT, 'NodeFileRangeSource is closed', { filePath: this.filePath });
216
+ throw pikeletError(PIKELET_ERROR_CODES.INVALID_ARGUMENT, 'NodeFileRangeSource is closed', { filePath: this.filePath });
217
217
  }
218
218
  // Defense in depth: the callers validate artifact-derived ranges, but
219
219
  // a future caller must not be able to drive a giant Buffer.alloc or a
@@ -221,7 +221,7 @@ class NodeFileRangeSource {
221
221
  if (!Number.isSafeInteger(offset) || !Number.isSafeInteger(length)
222
222
  || offset < 0 || length < 0 || length > MAX_ARTIFACT_READ_BYTES
223
223
  || offset + length > this.size) {
224
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID,
224
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID,
225
225
  'NodeFileRangeSource.read() range is out of bounds', { offset, length, size: this.size });
226
226
  }
227
227
  const buffer = Buffer.alloc(length);
@@ -245,7 +245,7 @@ class NodeFileRangeSource {
245
245
  }
246
246
 
247
247
  // The artifact readers apply the same query-vector contract as the core
248
- // engine (pancake-core.js assertNumericVector / validateVectorValues): a
248
+ // engine (pikelet-core.js assertNumericVector / validateVectorValues): a
249
249
  // plain array must hold real numbers (Float32Array.from would coerce '1',
250
250
  // '', true silently), every component must be finite for every metric (an
251
251
  // L2 search over NaN would otherwise return distance: NaN results), and a
@@ -253,31 +253,31 @@ class NodeFileRangeSource {
253
253
  function normalizeQuery(query, dim, metric = 0) {
254
254
  if (!(query instanceof Float32Array)) {
255
255
  if (!Array.isArray(query)) {
256
- throw pancakeError(PANCAKE_ERROR_CODES.INVALID_VECTOR, 'search() query must be a Float32Array or number[]');
256
+ throw pikeletError(PIKELET_ERROR_CODES.INVALID_VECTOR, 'search() query must be a Float32Array or number[]');
257
257
  }
258
258
  for (let i = 0; i < query.length; i++) {
259
259
  if (typeof query[i] !== 'number') {
260
- throw pancakeError(PANCAKE_ERROR_CODES.INVALID_VECTOR,
260
+ throw pikeletError(PIKELET_ERROR_CODES.INVALID_VECTOR,
261
261
  `search() query must contain only numbers; found ${typeof query[i]} at index ${i}`, { index: i, actualType: typeof query[i] });
262
262
  }
263
263
  }
264
264
  query = Float32Array.from(query);
265
265
  }
266
266
  if (query.length !== dim) {
267
- throw pancakeError(PANCAKE_ERROR_CODES.DIMENSION_MISMATCH, `search() query dimension ${query.length} does not match artifact dimension ${dim}`, { queryDim: query.length, dim });
267
+ throw pikeletError(PIKELET_ERROR_CODES.DIMENSION_MISMATCH, `search() query dimension ${query.length} does not match artifact dimension ${dim}`, { queryDim: query.length, dim });
268
268
  }
269
269
  let norm = 0;
270
270
  for (let i = 0; i < query.length; i++) {
271
271
  const value = query[i];
272
272
  if (!Number.isFinite(value)) {
273
- throw pancakeError(PANCAKE_ERROR_CODES.INVALID_VECTOR, 'search() query contains non-finite value (NaN or Infinity)', { index: i, reason: 'non_finite' });
273
+ throw pikeletError(PIKELET_ERROR_CODES.INVALID_VECTOR, 'search() query contains non-finite value (NaN or Infinity)', { index: i, reason: 'non_finite' });
274
274
  }
275
275
  norm += value * value;
276
276
  }
277
277
  if (metric === 1) {
278
278
  norm = Math.sqrt(norm);
279
279
  if (!Number.isFinite(norm) || norm <= 1e-30) {
280
- throw pancakeError(PANCAKE_ERROR_CODES.INVALID_VECTOR, 'search() query has invalid cosine norm', { reason: 'invalid_cosine_norm' });
280
+ throw pikeletError(PIKELET_ERROR_CODES.INVALID_VECTOR, 'search() query has invalid cosine norm', { reason: 'invalid_cosine_norm' });
281
281
  }
282
282
  const normalized = new Float32Array(query.length);
283
283
  for (let i = 0; i < query.length; i++) normalized[i] = query[i] / norm;
@@ -292,7 +292,7 @@ function normalizeQuery(query, dim, metric = 0) {
292
292
  // count results, so a k of 1e9 over 300 rows must not allocate 1e9 slots.
293
293
  function resolveSearchK(k, count) {
294
294
  if (!Number.isSafeInteger(k) || k < 1) {
295
- throw pancakeError(PANCAKE_ERROR_CODES.INVALID_ARGUMENT, 'search() k must be a positive integer', { k });
295
+ throw pikeletError(PIKELET_ERROR_CODES.INVALID_ARGUMENT, 'search() k must be a positive integer', { k });
296
296
  }
297
297
  return Math.min(k, count);
298
298
  }
@@ -302,41 +302,41 @@ function resolveSearchK(k, count) {
302
302
  function resolveOptionalPositiveInt(value, name, fallback) {
303
303
  if (value === undefined || value === null || value === 0) return fallback;
304
304
  if (!Number.isSafeInteger(value) || value < 1) {
305
- throw pancakeError(PANCAKE_ERROR_CODES.INVALID_ARGUMENT, `search() ${name} must be a positive integer (0 or undefined selects the default)`, { [name]: value });
305
+ throw pikeletError(PIKELET_ERROR_CODES.INVALID_ARGUMENT, `search() ${name} must be a positive integer (0 or undefined selects the default)`, { [name]: value });
306
306
  }
307
307
  return value;
308
308
  }
309
309
 
310
310
  function unwrapSnapshot(bytes) {
311
311
  const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
312
- if (bytes.byteLength < 4 || view.getUint32(0, true) !== PANCAKE_MAGIC) return bytes;
312
+ if (bytes.byteLength < 4 || view.getUint32(0, true) !== PIKELET_MAGIC) return bytes;
313
313
  // Envelope fields are untrusted: every size read from them must be
314
314
  // checked against the actual buffer before slicing, so a corrupt
315
315
  // envelope fails closed with a coded error instead of a raw RangeError.
316
316
  if (bytes.byteLength < 8) {
317
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, 'Pancake envelope is truncated', { byteLength: bytes.byteLength });
317
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, 'Pikelet envelope is truncated', { byteLength: bytes.byteLength });
318
318
  }
319
319
  const version = view.getUint32(4, true);
320
320
  if (version === 1 || version === 2) {
321
321
  const headerSize = version === 1 ? V1_ENVELOPE_HEADER_SIZE : V2_ENVELOPE_HEADER_SIZE;
322
322
  if (bytes.byteLength < headerSize) {
323
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, 'Pancake envelope is truncated', { version, byteLength: bytes.byteLength });
323
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, 'Pikelet envelope is truncated', { version, byteLength: bytes.byteLength });
324
324
  }
325
325
  return bytes.subarray(headerSize);
326
326
  }
327
327
  if (version === 3) {
328
328
  if (bytes.byteLength < V3_ENVELOPE_HEADER_SIZE) {
329
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, 'Pancake envelope is truncated', { version, byteLength: bytes.byteLength });
329
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, 'Pikelet envelope is truncated', { version, byteLength: bytes.byteLength });
330
330
  }
331
331
  const mappingCount = view.getUint32(24, true);
332
332
  const rawSize = view.getUint32(28, true);
333
333
  const rawOffset = V3_ENVELOPE_HEADER_SIZE + mappingCount * MAPPING_ENTRY_SIZE;
334
334
  if (rawOffset + rawSize > bytes.byteLength) {
335
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, 'Pancake envelope declares more data than the snapshot contains', { mappingCount, rawSize, byteLength: bytes.byteLength });
335
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, 'Pikelet envelope declares more data than the snapshot contains', { mappingCount, rawSize, byteLength: bytes.byteLength });
336
336
  }
337
337
  return bytes.subarray(rawOffset, rawOffset + rawSize);
338
338
  }
339
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, `Unsupported Pancake envelope version ${version}`, { version });
339
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, `Unsupported Pikelet envelope version ${version}`, { version });
340
340
  }
341
341
 
342
342
  function parseUint8Snapshot(bytes) {
@@ -346,7 +346,7 @@ function parseUint8Snapshot(bytes) {
346
346
  // Snapshot bytes are untrusted: sizes read from the header drive every
347
347
  // subsequent read, so each read checks the remaining buffer and fails
348
348
  // closed with a coded error instead of a raw RangeError.
349
- const truncated = () => pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, 'uint8 snapshot is truncated', { offset, byteLength: raw.byteLength });
349
+ const truncated = () => pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, 'uint8 snapshot is truncated', { offset, byteLength: raw.byteLength });
350
350
  const u32 = () => {
351
351
  if (raw.byteLength - offset < 4) throw truncated();
352
352
  const value = view.getUint32(offset, true);
@@ -371,22 +371,22 @@ function parseUint8Snapshot(bytes) {
371
371
  const metric = u32();
372
372
  const efConstruction = u32();
373
373
  if (magic !== UINT8_HNSW_MAGIC_V1) {
374
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, 'Search Artifact export currently supports uint8 Pancake snapshots only');
374
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, 'Search Artifact export currently supports uint8 Pikelet snapshots only');
375
375
  }
376
376
  // Contract §6: reject unknown future versions instead of parsing them
377
377
  // as v2 — a changed layout must fail closed, not misparse.
378
378
  if (version > 2) {
379
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, 'Unsupported uint8 snapshot format version', { version });
379
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, 'Unsupported uint8 snapshot format version', { version });
380
380
  }
381
381
  if (metric !== 0 && metric !== 1) {
382
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, 'Unsupported uint8 snapshot metric', { metric });
382
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, 'Unsupported uint8 snapshot metric', { metric });
383
383
  }
384
384
  // Same structural sanity the engine's own deserialize enforces; the
385
385
  // level cap mirrors MAX_DESERIALIZE_LEVEL in src/uint8_float_hnsw.hpp.
386
386
  if (dim < 1 || count < 1 || entryPoint >= count || maxLevel > 64
387
387
  || !Number.isSafeInteger(count * dim)
388
388
  || raw.byteLength - offset < count * 8 + count * dim) {
389
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, 'uint8 snapshot header is inconsistent', { dim, count, entryPoint, maxLevel, byteLength: raw.byteLength });
389
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, 'uint8 snapshot header is inconsistent', { dim, count, entryPoint, maxLevel, byteLength: raw.byteLength });
390
390
  }
391
391
 
392
392
  const scales = new Float32Array(count);
@@ -405,7 +405,7 @@ function parseUint8Snapshot(bytes) {
405
405
  // Same envelope as the engine: create() accepts M in [2, 128] and fixes
406
406
  // M0 = 2*M, and its own import rejects M outside that range.
407
407
  if (!(M >= 2 && M <= 128) || !(M0 >= M && M0 <= 256)) {
408
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, 'uint8 snapshot graph parameters are implausible', { M, M0 });
408
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, 'uint8 snapshot graph parameters are implausible', { M, M0 });
409
409
  }
410
410
  // Edge layout follows the engine's deserializer (uint8_float_hnsw.hpp):
411
411
  // version >= 2 stores {u32 id, f32 distance} per edge, version 1 stores
@@ -418,21 +418,21 @@ function parseUint8Snapshot(bytes) {
418
418
  for (let id = 0; id < count; id++) {
419
419
  const level = u32();
420
420
  if (level > maxLevel) {
421
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, 'uint8 snapshot node level exceeds header maxLevel', { id, level, maxLevel });
421
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, 'uint8 snapshot node level exceeds header maxLevel', { id, level, maxLevel });
422
422
  }
423
423
  levels[id] = level;
424
424
  for (let l = 0; l <= level; l++) {
425
425
  const size = u32();
426
426
  const cap = l === 0 ? M0 : M;
427
427
  if (size > cap) {
428
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, 'uint8 snapshot adjacency exceeds the graph parameter bound', { id, level: l, size, cap });
428
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, 'uint8 snapshot adjacency exceeds the graph parameter bound', { id, level: l, size, cap });
429
429
  }
430
430
  if (raw.byteLength - offset < size * edgeBytes) throw truncated();
431
431
  const edges = new Uint32Array(size);
432
432
  for (let e = 0; e < size; e++) {
433
433
  const neighbor = u32();
434
434
  if (neighbor >= count) {
435
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, 'uint8 snapshot neighbor id is out of range', { id, level: l, neighbor, count });
435
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, 'uint8 snapshot neighbor id is out of range', { id, level: l, neighbor, count });
436
436
  }
437
437
  edges[e] = neighbor;
438
438
  if (version >= 2) offset += 4; // the serialized float edge distance, unused here
@@ -468,12 +468,12 @@ async function sha256BytesAsync(bytes) {
468
468
  async function verifySha256(bytes, expected, label) {
469
469
  const digest = await sha256BytesAsync(bytes);
470
470
  if (!digest) {
471
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID,
471
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID,
472
472
  'Artifact verification requested but no crypto backend is available; pass verify:false to skip');
473
473
  }
474
474
  for (let b = 0; b < 32; b++) {
475
475
  if (digest[b] !== expected[b]) {
476
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, `${label} failed hash verification`);
476
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, `${label} failed hash verification`);
477
477
  }
478
478
  }
479
479
  }
@@ -498,7 +498,7 @@ async function verifySegmentSha256(source, offset, totalBytes, expected, label,
498
498
  const len = Math.min(chunkBytes, totalBytes - done);
499
499
  const bytes = await readChecked(source, offset + done, len, label);
500
500
  if (bytes.byteLength !== len) {
501
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID,
501
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID,
502
502
  `Artifact ${label} is truncated`, { offset: offset + done, expected: len, actual: bytes.byteLength });
503
503
  }
504
504
  hash.update(bytes);
@@ -507,20 +507,20 @@ async function verifySegmentSha256(source, offset, totalBytes, expected, label,
507
507
  const digest = new Uint8Array(hash.digest());
508
508
  for (let b = 0; b < 32; b++) {
509
509
  if (digest[b] !== expected[b]) {
510
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID, `${label} failed hash verification`);
510
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID, `${label} failed hash verification`);
511
511
  }
512
512
  }
513
513
  return;
514
514
  }
515
515
  const oneShotLimit = options.oneShotLimit || DEFAULT_OPEN_READ_BYTES;
516
516
  if (totalBytes > oneShotLimit) {
517
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID,
517
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID,
518
518
  `Artifact ${label} is too large to verify without a streaming crypto backend`,
519
519
  { totalBytes, oneShotLimit });
520
520
  }
521
521
  const bytes = await readChecked(source, offset, totalBytes, label, oneShotLimit);
522
522
  if (bytes.byteLength !== totalBytes) {
523
- throw pancakeError(PANCAKE_ERROR_CODES.SNAPSHOT_INVALID,
523
+ throw pikeletError(PIKELET_ERROR_CODES.SNAPSHOT_INVALID,
524
524
  `Artifact ${label} is truncated`, { offset, expected: totalBytes, actual: bytes.byteLength });
525
525
  }
526
526
  await verifySha256(bytes, expected, label);
@@ -529,7 +529,7 @@ async function verifySegmentSha256(source, offset, totalBytes, expected, label,
529
529
  module.exports = {
530
530
  resolveSearchK,
531
531
  resolveOptionalPositiveInt,
532
- PANCAKE_MAGIC,
532
+ PIKELET_MAGIC,
533
533
  V1_ENVELOPE_HEADER_SIZE,
534
534
  V2_ENVELOPE_HEADER_SIZE,
535
535
  V3_ENVELOPE_HEADER_SIZE,