wiki-graph-sdk 0.9.0 → 0.9.2

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 (51) hide show
  1. package/dist/archives.cjs +316 -142
  2. package/dist/archives.cjs.map +1 -1
  3. package/dist/archives.js +326 -148
  4. package/dist/archives.js.map +1 -1
  5. package/dist/conversions.cjs +268 -99
  6. package/dist/conversions.cjs.map +1 -1
  7. package/dist/conversions.js +274 -103
  8. package/dist/conversions.js.map +1 -1
  9. package/dist/default-worker.cjs +258 -101
  10. package/dist/default-worker.cjs.map +1 -1
  11. package/dist/default-worker.js +264 -105
  12. package/dist/default-worker.js.map +1 -1
  13. package/dist/embedding.cjs +214 -54
  14. package/dist/embedding.cjs.map +1 -1
  15. package/dist/embedding.js +214 -54
  16. package/dist/embedding.js.map +1 -1
  17. package/dist/gc.cjs +214 -54
  18. package/dist/gc.cjs.map +1 -1
  19. package/dist/gc.js +214 -54
  20. package/dist/gc.js.map +1 -1
  21. package/dist/index.cjs +354 -174
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +369 -184
  25. package/dist/index.js.map +1 -1
  26. package/dist/local-config.cjs +214 -54
  27. package/dist/local-config.cjs.map +1 -1
  28. package/dist/local-config.js +214 -54
  29. package/dist/local-config.js.map +1 -1
  30. package/dist/maintenance.cjs +264 -97
  31. package/dist/maintenance.cjs.map +1 -1
  32. package/dist/maintenance.js +270 -101
  33. package/dist/maintenance.js.map +1 -1
  34. package/dist/node-platform.cjs +214 -54
  35. package/dist/node-platform.cjs.map +1 -1
  36. package/dist/node-platform.d.ts +2 -0
  37. package/dist/node-platform.js +214 -54
  38. package/dist/node-platform.js.map +1 -1
  39. package/dist/runtime-config.cjs +214 -54
  40. package/dist/runtime-config.cjs.map +1 -1
  41. package/dist/runtime-config.js +214 -54
  42. package/dist/runtime-config.js.map +1 -1
  43. package/dist/stage.cjs +214 -54
  44. package/dist/stage.cjs.map +1 -1
  45. package/dist/stage.js +214 -54
  46. package/dist/stage.js.map +1 -1
  47. package/dist/worker.cjs +257 -96
  48. package/dist/worker.cjs.map +1 -1
  49. package/dist/worker.js +263 -100
  50. package/dist/worker.js.map +1 -1
  51. package/package.json +2 -2
package/dist/archives.cjs CHANGED
@@ -151,6 +151,15 @@ var NodeFile = class {
151
151
  this.name = name;
152
152
  }
153
153
  path;
154
+ async getPhysicalIdentity() {
155
+ const value = await fsPromises.stat(this.path).catch((error) => {
156
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT")
157
+ return void 0;
158
+ throw error;
159
+ });
160
+ if (value === void 0) return void 0;
161
+ return `${value.dev}:${value.ino}`;
162
+ }
154
163
  kind = "file";
155
164
  [NODE_RESOURCE_KIND] = "file";
156
165
  identity;
@@ -275,6 +284,15 @@ var NodeDirectory = class _NodeDirectory {
275
284
  this.name = pathModule.basename(path);
276
285
  }
277
286
  path;
287
+ async getPhysicalIdentity() {
288
+ const value = await fsPromises.stat(this.path).catch((error) => {
289
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT")
290
+ return void 0;
291
+ throw error;
292
+ });
293
+ if (value === void 0) return void 0;
294
+ return `${value.dev}:${value.ino}`;
295
+ }
278
296
  kind = "directory";
279
297
  [NODE_RESOURCE_KIND] = "directory";
280
298
  identity;
@@ -284,8 +302,10 @@ var NodeDirectory = class _NodeDirectory {
284
302
  const file = new NodeFile(pathModule.join(this.path, name));
285
303
  try {
286
304
  return (await fsPromises.stat(file.path)).isFile() ? file : void 0;
287
- } catch {
288
- return void 0;
305
+ } catch (error) {
306
+ if (typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR"))
307
+ return void 0;
308
+ throw error;
289
309
  }
290
310
  }
291
311
  async getLastModified() {
@@ -303,8 +323,10 @@ var NodeDirectory = class _NodeDirectory {
303
323
  const directory = new _NodeDirectory(pathModule.join(this.path, name));
304
324
  try {
305
325
  return (await fsPromises.stat(directory.path)).isDirectory() ? directory : void 0;
306
- } catch {
307
- return void 0;
326
+ } catch (error) {
327
+ if (typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR"))
328
+ return void 0;
329
+ throw error;
308
330
  }
309
331
  }
310
332
  async list() {
@@ -428,14 +450,23 @@ async function openNativeNodeDatabase(file, flags) {
428
450
  });
429
451
  });
430
452
  }
431
- async function openNodeZip(file) {
453
+ async function openNodeZip(file, options = {}) {
432
454
  const path = getBrandedNodeResourcePath(file, "file");
433
455
  if (path === void 0) {
434
456
  throw new TypeError("The Node ZIP adapter requires a NodeFile");
435
457
  }
436
- const zipFile = await new Promise((resolve4, reject) => {
437
- yauzl.open(
438
- path,
458
+ const handle = await fsPromises.open(path, "r");
459
+ let size;
460
+ try {
461
+ size = (await handle.stat()).size;
462
+ } catch (error) {
463
+ await handle.close();
464
+ throw error;
465
+ }
466
+ const open2 = () => new Promise((resolve4, reject) => {
467
+ yauzl.fromRandomAccessReader(
468
+ new NodeZipSource(handle),
469
+ size,
439
470
  { autoClose: false, lazyEntries: true },
440
471
  (error, opened) => {
441
472
  if (error || opened === void 0)
@@ -444,63 +475,192 @@ async function openNodeZip(file) {
444
475
  }
445
476
  );
446
477
  });
447
- const entries = await new Promise(
448
- (resolve4, reject) => {
449
- const discovered = /* @__PURE__ */ new Map();
450
- const rejectAndClose = (error) => {
451
- zipFile.close();
452
- reject(
453
- error instanceof Error ? error : new Error("Cannot scan ZIP central directory")
454
- );
455
- };
456
- const resolveEntries = () => {
457
- zipFile.off("error", rejectAndClose);
458
- resolve4(discovered);
459
- };
460
- zipFile.on("entry", (entry) => {
461
- if (!entry.fileName.endsWith("/")) {
462
- discovered.set(entry.fileName, entry);
463
- }
464
- zipFile.readEntry();
465
- });
466
- zipFile.once("error", rejectAndClose);
467
- zipFile.once("end", resolveEntries);
468
- zipFile.readEntry();
469
- }
470
- );
478
+ try {
479
+ (await open2()).close();
480
+ } catch (error) {
481
+ await handle.close();
482
+ throw error;
483
+ }
471
484
  let closed = false;
485
+ let pending = Promise.resolve();
486
+ let closing;
487
+ const run = (operation) => {
488
+ if (closed)
489
+ return Promise.reject(new Error("Cannot read a closed ZIP archive"));
490
+ const result = pending.then(async () => {
491
+ const zip = await open2();
492
+ try {
493
+ return await operation(zip);
494
+ } finally {
495
+ zip.close();
496
+ }
497
+ });
498
+ pending = result.then(
499
+ () => void 0,
500
+ () => void 0
501
+ );
502
+ return result;
503
+ };
504
+ const withEntry = (name, operation) => run(async (zip) => {
505
+ let exact;
506
+ let alias;
507
+ let aliasCollision = false;
508
+ await scanNodeZip(zip, (entry) => {
509
+ if (entry.fileName === name) exact = entry;
510
+ if (normalizeNodeZipName(entry.fileName) === name) {
511
+ if (alias !== void 0 && alias.fileName !== entry.fileName)
512
+ aliasCollision = true;
513
+ alias = entry;
514
+ }
515
+ });
516
+ if ((exact === void 0 || options.entryNameMode === "normalized") && aliasCollision) {
517
+ let bestPosition = -1;
518
+ const candidates = await open2();
519
+ try {
520
+ await scanNodeZip(candidates, async (entry) => {
521
+ if (normalizeNodeZipName(entry.fileName) !== name) return;
522
+ const probe = await open2();
523
+ let position = 0;
524
+ try {
525
+ await scanNodeZip(probe, (candidate) => {
526
+ if (candidate.fileName === entry.fileName) return false;
527
+ position++;
528
+ });
529
+ } finally {
530
+ probe.close();
531
+ }
532
+ if (position >= bestPosition) {
533
+ bestPosition = position;
534
+ alias = entry;
535
+ }
536
+ });
537
+ return await operation(candidates, alias);
538
+ } finally {
539
+ candidates.close();
540
+ }
541
+ }
542
+ return await operation(
543
+ zip,
544
+ options.entryNameMode === "normalized" ? alias : exact ?? alias
545
+ );
546
+ });
472
547
  return {
473
548
  close: () => {
474
- if (!closed) zipFile.close();
475
549
  closed = true;
476
- return Promise.resolve();
550
+ closing ??= pending.then(() => handle.close());
551
+ return closing;
477
552
  },
478
- copyEntry: async (name, target) => {
479
- if (closed) throw new Error("Cannot read a closed ZIP archive");
480
- const entry = entries.get(name);
553
+ copyEntry: (name, target) => withEntry(name, async (zip, entry) => {
481
554
  if (entry === void 0) return false;
482
- await copyNodeZipEntry(zipFile, entry, target);
555
+ await copyNodeZipEntry(zip, entry, target);
483
556
  return true;
484
- },
485
- getEntrySize: (name) => {
486
- if (closed) throw new Error("Cannot read a closed ZIP archive");
487
- return Promise.resolve(entries.get(name)?.uncompressedSize);
488
- },
489
- listEntries: () => Promise.resolve([...entries.keys()]),
490
- readEntryRange: async (name, offset, length) => {
491
- if (closed) throw new Error("Cannot read a closed ZIP archive");
492
- const entry = entries.get(name);
557
+ }),
558
+ getEntrySize: (name) => withEntry(
559
+ name,
560
+ (_zip, entry) => Promise.resolve(entry?.uncompressedSize)
561
+ ),
562
+ listEntries: () => run(async (zip) => {
563
+ const names = /* @__PURE__ */ new Set();
564
+ await scanNodeZip(zip, (entry) => {
565
+ names.add(entry.fileName);
566
+ });
567
+ return [...names];
568
+ }),
569
+ readEntryRange: (name, offset, length) => withEntry(name, async (zip, entry) => {
493
570
  if (entry === void 0) return void 0;
494
- return await readNodeZipEntryRange(zipFile, entry, offset, length);
495
- },
496
- readEntry: async (name) => {
497
- if (closed) throw new Error("Cannot read a closed ZIP archive");
498
- const entry = entries.get(name);
571
+ return await readNodeZipEntryRange(zip, entry, offset, length);
572
+ }),
573
+ readEntry: (name) => withEntry(name, async (zip, entry) => {
499
574
  if (entry === void 0) return void 0;
500
- return await readNodeZipEntry(zipFile, entry);
501
- }
575
+ return await readNodeZipEntry(zip, entry);
576
+ })
502
577
  };
503
578
  }
579
+ var NodeZipSource = class extends yauzl.RandomAccessReader {
580
+ constructor(handle) {
581
+ super();
582
+ this.handle = handle;
583
+ }
584
+ handle;
585
+ read(buffer, offset, length, position, callback) {
586
+ const read2 = (written) => {
587
+ if (written === length) {
588
+ callback(null);
589
+ return;
590
+ }
591
+ fs.read(
592
+ this.handle.fd,
593
+ buffer,
594
+ offset + written,
595
+ length - written,
596
+ position + written,
597
+ (error, bytesRead) => {
598
+ if (error) callback(error);
599
+ else if (bytesRead === 0)
600
+ callback(new Error("Unexpected end of ZIP file"));
601
+ else read2(written + bytesRead);
602
+ }
603
+ );
604
+ };
605
+ read2(0);
606
+ }
607
+ _readStreamForRange(start, end) {
608
+ const handle = this.handle;
609
+ return import_node_stream.Readable.from(
610
+ (async function* () {
611
+ for (let position = start; position < end; ) {
612
+ const buffer = Buffer.allocUnsafe(
613
+ Math.min(64 * 1024, end - position)
614
+ );
615
+ const { bytesRead } = await handle.read(
616
+ buffer,
617
+ 0,
618
+ buffer.length,
619
+ position
620
+ );
621
+ if (bytesRead === 0) return;
622
+ position += bytesRead;
623
+ yield buffer.subarray(0, bytesRead);
624
+ }
625
+ })()
626
+ );
627
+ }
628
+ };
629
+ function normalizeNodeZipName(name) {
630
+ const normalized = name.replaceAll("\\", "/").trim().split("/").filter((part) => part !== "" && part !== ".").join("/");
631
+ return normalized.split("/").includes("..") ? void 0 : normalized;
632
+ }
633
+ async function scanNodeZip(zip, visit) {
634
+ await new Promise((resolve4, reject) => {
635
+ const cleanup = () => {
636
+ zip.off("entry", onEntry);
637
+ zip.off("end", onEnd);
638
+ zip.off("error", onError);
639
+ };
640
+ const onError = (error) => {
641
+ cleanup();
642
+ reject(error);
643
+ };
644
+ const onEnd = () => {
645
+ cleanup();
646
+ resolve4();
647
+ };
648
+ const onEntry = (entry) => {
649
+ void Promise.resolve().then(() => entry.fileName.endsWith("/") ? void 0 : visit(entry)).then((keepReading) => {
650
+ if (keepReading === false) onEnd();
651
+ else zip.readEntry();
652
+ }).catch(
653
+ (error) => onError(
654
+ error instanceof Error ? error : new Error("Cannot scan ZIP", { cause: error })
655
+ )
656
+ );
657
+ };
658
+ zip.on("entry", onEntry);
659
+ zip.once("end", onEnd);
660
+ zip.once("error", onError);
661
+ zip.readEntry();
662
+ });
663
+ }
504
664
  async function copyNodeZipEntry(zipFile, entry, target) {
505
665
  const writer = await target.openWriter();
506
666
  try {
@@ -1273,6 +1433,16 @@ function resolveWikiGraphRuntimePath(path) {
1273
1433
  var import_promises3 = require("fs/promises");
1274
1434
  var import_path3 = require("path");
1275
1435
  var import_wiki_graph_core2 = require("wiki-graph-core");
1436
+ function rethrowArchiveSchemaError(error, target) {
1437
+ if ((0, import_wiki_graph_core2.isWikiGraphSchemaVersionError)(error) && error.target.kind === "archive") {
1438
+ throw new import_wiki_graph_core2.WikiGraphSchemaVersionError(
1439
+ target.kind === "standalone" ? { kind: "archive", path: resolveWikiGraphRuntimePath(target.path) } : { kind: "library", uri: target.uri.split("/arc/")[0] },
1440
+ error.actualVersion,
1441
+ error.supportedVersion
1442
+ );
1443
+ }
1444
+ throw error;
1445
+ }
1276
1446
  function requireWikiGraphArchiveFile(location) {
1277
1447
  return location.archiveFile;
1278
1448
  }
@@ -1293,12 +1463,7 @@ async function assertStandaloneWikiGraphArchivePath(inputPath) {
1293
1463
  const path = resolveWikiGraphRuntimePath(inputPath);
1294
1464
  const candidate = await canonicalPath(path);
1295
1465
  const candidateIdentity = await readFileIdentity(path);
1296
- const libraries = await (0, import_wiki_graph_core2.listWikiGraphLibraries)();
1297
- const matches = await findMatchingMembers(
1298
- libraries,
1299
- candidate,
1300
- candidateIdentity
1301
- );
1466
+ const matches = await findMatchingMembers(candidate, candidateIdentity);
1302
1467
  if (matches.length > 0) {
1303
1468
  const match = requireUnambiguousManagedMatch(path, matches);
1304
1469
  throw new WikiGraphArchiveOwnershipError(
@@ -1307,15 +1472,26 @@ async function assertStandaloneWikiGraphArchivePath(inputPath) {
1307
1472
  )}: ${path}. Use the library UUID URI ${match.archive.uri} instead.`
1308
1473
  );
1309
1474
  }
1310
- for (const library of libraries) {
1311
- const rootPath = getNodeResourcePath(library.folder);
1312
- const root = await canonicalPath(rootPath);
1313
- if (!isWithin(root, candidate)) continue;
1314
- throw new WikiGraphArchiveOwnershipError(
1315
- `Standalone archive path belongs to registered library ${(0, import_wiki_graph_core2.formatWikiGraphLibraryUri)(
1316
- library.isDefault ? void 0 : library.publicId
1317
- )}: ${path}. Scan the library, then address the archive by its library UUID URI.`
1475
+ const ancestors = /* @__PURE__ */ new Set();
1476
+ for (const start of [candidate, (0, import_path3.resolve)(path)]) {
1477
+ for (let parent = (0, import_path3.dirname)(start); ; parent = (0, import_path3.dirname)(parent)) {
1478
+ ancestors.add(parent);
1479
+ if ((0, import_path3.dirname)(parent) === parent) break;
1480
+ }
1481
+ }
1482
+ for (const parent of ancestors) {
1483
+ const identity = await readFileIdentity(parent);
1484
+ const library = await (0, import_wiki_graph_core2.findWikiGraphLibraryByPhysicalIdentity)(
1485
+ identity,
1486
+ new NodeDirectory(parent).identity
1318
1487
  );
1488
+ if (library !== void 0) {
1489
+ throw new WikiGraphArchiveOwnershipError(
1490
+ `Standalone archive path belongs to registered library ${(0, import_wiki_graph_core2.formatWikiGraphLibraryUri)(
1491
+ library.isDefault ? void 0 : library.publicId
1492
+ )}: ${path}. Scan the library, then address the archive by its library UUID URI.`
1493
+ );
1494
+ }
1319
1495
  }
1320
1496
  return path;
1321
1497
  }
@@ -1373,48 +1549,35 @@ async function resolveLibraryLocation(target) {
1373
1549
  async function canonicalPath(path) {
1374
1550
  try {
1375
1551
  return await (0, import_promises3.realpath)(path);
1376
- } catch {
1552
+ } catch (error) {
1553
+ if (!(typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR")))
1554
+ throw error;
1377
1555
  const absolute = (0, import_path3.resolve)(path);
1378
1556
  const parent = (0, import_path3.dirname)(absolute);
1379
1557
  return parent === absolute ? absolute : (0, import_path3.join)(await canonicalPath(parent), (0, import_path3.basename)(absolute));
1380
1558
  }
1381
1559
  }
1382
- function isWithin(root, candidate) {
1383
- const child = (0, import_path3.relative)(root, candidate);
1384
- return child === "" || !child.startsWith("..") && !(0, import_path3.isAbsolute)(child);
1385
- }
1386
- async function findMatchingMembers(libraries, candidate, candidateIdentity) {
1560
+ async function findMatchingMembers(candidate, candidateIdentity) {
1561
+ if (candidateIdentity === void 0) return [];
1562
+ const archives = await (0, import_wiki_graph_core2.findWikiGraphLibraryArchivePhysicalAliases)(candidateIdentity);
1387
1563
  const members = [];
1388
- for (const library of libraries) {
1389
- const archives = await (0, import_wiki_graph_core2.listWikiGraphLibraryArchives)({
1390
- isDefault: library.isDefault,
1391
- kind: "scope",
1392
- ...library.isDefault ? {} : { publicId: library.publicId }
1393
- });
1394
- for (const archive of archives) {
1395
- const physical = archive.file ?? archive.directory;
1396
- if (physical === void 0) continue;
1564
+ for (const archive of archives) {
1565
+ const parsed = (0, import_wiki_graph_core2.parseWikiGraphLibraryUri)(archive.libraryUri);
1566
+ const library = await (0, import_wiki_graph_core2.resolveWikiGraphLibrary)(parsed);
1567
+ const physical = archive.file ?? archive.directory;
1568
+ if (library !== void 0 && physical !== void 0)
1397
1569
  members.push({
1398
1570
  archive,
1399
1571
  library,
1400
1572
  memberPath: getNodeResourcePath(physical)
1401
1573
  });
1402
- }
1403
1574
  }
1404
1575
  const exact = [];
1405
1576
  for (const member of members) {
1406
- if (await canonicalPath(member.memberPath) === candidate) {
1577
+ if (await canonicalPath(member.memberPath) === candidate)
1407
1578
  exact.push(member);
1408
- }
1409
1579
  }
1410
- if (exact.length > 0 || candidateIdentity === void 0) return exact;
1411
- const identityMatches = [];
1412
- for (const member of members) {
1413
- if (await readFileIdentity(member.memberPath) === candidateIdentity) {
1414
- identityMatches.push(member);
1415
- }
1416
- }
1417
- return identityMatches;
1580
+ return exact.length > 0 ? exact : members;
1418
1581
  }
1419
1582
  function requireUnambiguousManagedMatch(path, matches) {
1420
1583
  if (matches.length === 1) return matches[0];
@@ -1426,8 +1589,10 @@ async function readFileIdentity(path) {
1426
1589
  try {
1427
1590
  const value = await (0, import_promises3.stat)(path);
1428
1591
  return `${value.dev}:${value.ino}`;
1429
- } catch {
1430
- return void 0;
1592
+ } catch (error) {
1593
+ if (typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR"))
1594
+ return void 0;
1595
+ throw error;
1431
1596
  }
1432
1597
  }
1433
1598
 
@@ -1489,11 +1654,15 @@ var WikiGraphConversionManager = class {
1489
1654
  if (!("path" in options.input)) {
1490
1655
  throw new Error("wikg input requires a file path.");
1491
1656
  }
1657
+ const inputPath = options.input.path;
1492
1658
  await app.openSession(
1493
- new NodeFile(
1494
- await assertStandaloneWikiGraphArchivePath(options.input.path)
1495
- ),
1659
+ new NodeFile(await assertStandaloneWikiGraphArchivePath(inputPath)),
1496
1660
  write
1661
+ ).catch(
1662
+ (error) => rethrowArchiveSchemaError(error, {
1663
+ kind: "standalone",
1664
+ path: inputPath
1665
+ })
1497
1666
  );
1498
1667
  } else if ("stream" in options.input) {
1499
1668
  await app.digestTextStreamSession(
@@ -1884,6 +2053,12 @@ var import_wiki_graph_core6 = require("wiki-graph-core");
1884
2053
  async function writeWikiGraphArchiveLocation(location, operation, options = {}) {
1885
2054
  const cacheOnly = options.searchIndexWritebackPolicy === "cache";
1886
2055
  const write = async (archiveFile = location.archiveFile) => {
2056
+ if (cacheOnly) {
2057
+ return await new import_wiki_graph_core6.WikiGraphArchiveFile(archiveFile).readDocument(
2058
+ operation,
2059
+ { searchIndexWritebackPolicy: "cache" }
2060
+ );
2061
+ }
1887
2062
  const writeOptions = {
1888
2063
  ...cacheOnly ? {} : { derivedStateKeys: [location.archiveKey, location.archivePath] },
1889
2064
  ...options.invalidateContinuationCursors === void 0 ? {} : {
@@ -2201,10 +2376,15 @@ var WikiGraphArchiveManager = class {
2201
2376
  }, options.signal);
2202
2377
  }
2203
2378
  async open(target, options = {}) {
2204
- const location = await this.#runtime.run(
2205
- async () => await resolveWikiGraphArchiveLocation(target),
2206
- options.signal
2207
- );
2379
+ const location = await this.#runtime.run(async () => {
2380
+ const location2 = await resolveWikiGraphArchiveLocation(target);
2381
+ try {
2382
+ await (0, import_wiki_graph_core7.ensureWikiGraphArchiveSchemaCurrent)(location2.archiveFile);
2383
+ } catch (error) {
2384
+ rethrowArchiveSchemaError(error, target);
2385
+ }
2386
+ return location2;
2387
+ }, options.signal);
2208
2388
  return new WikiGraphArchiveHandle(this.#runtime, location);
2209
2389
  }
2210
2390
  };
@@ -2255,15 +2435,11 @@ var WikiGraphArchiveHandle = class {
2255
2435
  options.queryMode,
2256
2436
  options.signal
2257
2437
  );
2258
- const result = await this.#writeDocument(
2438
+ const result = await this.#readDocument(
2259
2439
  async (document) => {
2260
2440
  const chapters = await this.#resolveQueryChapters(document, options, {
2261
2441
  embeddingProvider
2262
2442
  });
2263
- await ensureArchiveSearchIndex(document, {
2264
- ...chapters === void 0 ? {} : { chapters },
2265
- ...embeddingProvider === void 0 ? {} : { embeddingProvider }
2266
- });
2267
2443
  return await (0, import_wiki_graph_core7.findArchiveObjects)(document, query, {
2268
2444
  ...withoutOperationAndScope(options),
2269
2445
  archiveKey: this.archiveKey,
@@ -2272,7 +2448,6 @@ var WikiGraphArchiveHandle = class {
2272
2448
  });
2273
2449
  },
2274
2450
  {
2275
- searchIndexWritebackPolicy: "cache",
2276
2451
  ...options.signal === void 0 ? {} : { signal: options.signal }
2277
2452
  }
2278
2453
  );
@@ -2377,6 +2552,7 @@ var WikiGraphArchiveHandle = class {
2377
2552
  async (document) => {
2378
2553
  const chapters = await this.#resolveScope(document, options);
2379
2554
  await ensureArchiveSearchIndex(document, {
2555
+ rebuild: true,
2380
2556
  ...chapters === void 0 ? {} : { chapters },
2381
2557
  ...embeddingProvider === void 0 ? {} : { embeddingProvider }
2382
2558
  });
@@ -2627,13 +2803,16 @@ var WikiGraphArchiveHandle = class {
2627
2803
  return await this.#runtime.run(
2628
2804
  async () => await withConfiguredWikimediaResolver(
2629
2805
  objectUri,
2630
- async (wikimediaOptions) => await this.#readDocument(
2631
- async (document) => await (0, import_wiki_graph_core7.readArchivePage)(document, objectUri, {
2632
- ...options,
2633
- ...wikimediaOptions
2634
- }),
2635
- options
2636
- )
2806
+ async (wikimediaOptions) => {
2807
+ const read2 = await this.#readDocument(
2808
+ async (document) => await (0, import_wiki_graph_core7.prepareArchivePage)(document, objectUri, {
2809
+ ...options,
2810
+ ...wikimediaOptions
2811
+ }),
2812
+ options
2813
+ );
2814
+ return await read2();
2815
+ }
2637
2816
  ),
2638
2817
  options.signal
2639
2818
  );
@@ -2666,15 +2845,11 @@ var WikiGraphArchiveHandle = class {
2666
2845
  options.queryMode,
2667
2846
  options.signal
2668
2847
  );
2669
- const result = await this.#writeDocument(
2848
+ const result = await this.#readDocument(
2670
2849
  async (document) => {
2671
2850
  const chapters = await this.#resolveQueryChapters(document, options, {
2672
2851
  embeddingProvider
2673
2852
  });
2674
- await ensureArchiveSearchIndex(document, {
2675
- ...chapters === void 0 ? {} : { chapters },
2676
- ...embeddingProvider === void 0 ? {} : { embeddingProvider }
2677
- });
2678
2853
  return await (0, import_wiki_graph_core7.listRelatedArchiveObjects)(document, objectUri, {
2679
2854
  ...withoutOperation(options),
2680
2855
  ...embeddingProvider === void 0 ? {} : { embeddingProvider },
@@ -2682,7 +2857,6 @@ var WikiGraphArchiveHandle = class {
2682
2857
  });
2683
2858
  },
2684
2859
  {
2685
- searchIndexWritebackPolicy: "cache",
2686
2860
  ...options.signal === void 0 ? {} : { signal: options.signal }
2687
2861
  }
2688
2862
  );
@@ -2726,15 +2900,11 @@ var WikiGraphArchiveHandle = class {
2726
2900
  options.queryMode,
2727
2901
  options.signal
2728
2902
  );
2729
- const result = await this.#writeDocument(
2903
+ const result = await this.#readDocument(
2730
2904
  async (document) => {
2731
2905
  const chapters = await this.#resolveQueryChapters(document, options, {
2732
2906
  embeddingProvider
2733
2907
  });
2734
- await ensureArchiveSearchIndex(document, {
2735
- ...chapters === void 0 ? {} : { chapters },
2736
- ...embeddingProvider === void 0 ? {} : { embeddingProvider }
2737
- });
2738
2908
  return await (0, import_wiki_graph_core7.listArchiveEvidence)(document, objectUri, {
2739
2909
  ...withoutOperation(options),
2740
2910
  ...embeddingProvider === void 0 ? {} : { embeddingProvider },
@@ -2742,7 +2912,6 @@ var WikiGraphArchiveHandle = class {
2742
2912
  });
2743
2913
  },
2744
2914
  {
2745
- searchIndexWritebackPolicy: "cache",
2746
2915
  ...options.signal === void 0 ? {} : { signal: options.signal }
2747
2916
  }
2748
2917
  );
@@ -2859,6 +3028,8 @@ var WikiGraphArchiveHandle = class {
2859
3028
  this.#location.archiveFile
2860
3029
  ).readDocument(operation),
2861
3030
  options.signal
3031
+ ).catch(
3032
+ (error) => rethrowArchiveSchemaError(error, this.#location.target)
2862
3033
  );
2863
3034
  }
2864
3035
  async #writeDocument(operation, options = {}) {
@@ -2870,33 +3041,32 @@ var WikiGraphArchiveHandle = class {
2870
3041
  searchIndexWritebackPolicy: options.searchIndexWritebackPolicy
2871
3042
  }
2872
3043
  });
2873
- }, options.signal);
3044
+ }, options.signal).catch(
3045
+ (error) => rethrowArchiveSchemaError(error, this.#location.target)
3046
+ );
2874
3047
  }
2875
3048
  async #resolveScope(document, options) {
2876
3049
  if (options.chapters !== void 0) return options.chapters;
2877
3050
  return (await resolveArchiveScope(document, this.objectUri, options.depth))?.chapterIds;
2878
3051
  }
2879
3052
  async #resolveQueryChapters(document, options, capabilities) {
2880
- const chapters = await this.#resolveScope(document, options);
3053
+ const parsed = parseChapterScopePath(this.objectUri);
3054
+ const chapters = options.chapters ?? (parsed === void 0 || parsed.kind === "collection" && options.depth === void 0 ? void 0 : await (0, import_wiki_graph_core7.resolveIndexedArchiveChapterScope)(
3055
+ document,
3056
+ parsed.kind === "chapter" ? parsed.chapterPath : void 0,
3057
+ options.depth
3058
+ ));
2881
3059
  const coverageOptions = {
2882
3060
  ...chapters === void 0 ? {} : { chapters },
2883
3061
  ...capabilities.embeddingProvider === void 0 ? {} : { embeddingProvider: capabilities.embeddingProvider },
2884
3062
  requireEmbeddingProvider: true,
2885
3063
  ...options.queryMode === void 0 ? {} : { queryMode: options.queryMode }
2886
3064
  };
2887
- if (options.skipUnindexed !== true) {
2888
- await (0, import_wiki_graph_core7.assertArchiveIndexArtifactsReady)(document, coverageOptions);
2889
- return chapters;
2890
- }
2891
- const queryable = await (0, import_wiki_graph_core7.listArchiveQueryableChapterIds)(document, {
2892
- ...coverageOptions
3065
+ await (0, import_wiki_graph_core7.assertArchiveQueryReady)(document, {
3066
+ ...coverageOptions,
3067
+ ...options.skipUnindexed === void 0 ? {} : { skipUnindexed: options.skipUnindexed }
2893
3068
  });
2894
- if (queryable.length === 0) {
2895
- throw new Error(
2896
- "Wiki Graph query is not ready. No chapters in this scope have a current FTS artifact or source embedding artifact."
2897
- );
2898
- }
2899
- return queryable;
3069
+ return chapters;
2900
3070
  }
2901
3071
  async #resolveQueryEmbeddingProvider(queryMode, signal) {
2902
3072
  if (queryMode === "fts") return void 0;
@@ -2915,6 +3085,10 @@ var WikiGraphArchiveHandle = class {
2915
3085
  async function ensureArchiveSearchIndex(document, options = {}) {
2916
3086
  const scope = options.chapters === void 0 ? {} : { chapters: options.chapters };
2917
3087
  if (await (0, import_wiki_graph_core7.isArchiveSearchIndexCurrent)(document, scope)) return;
3088
+ if (options.rebuild !== true)
3089
+ throw new Error(
3090
+ "Archive search index is missing or dirty. Run `wg <archive-uri>/index sync` explicitly before querying."
3091
+ );
2918
3092
  await (0, import_wiki_graph_core7.rebuildArchiveSearchIndex)(document, void 0, {
2919
3093
  ...scope,
2920
3094
  ...options.embeddingProvider === void 0 ? {} : { embeddingProvider: options.embeddingProvider }