wiki-graph-sdk 0.7.1 → 0.8.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 (58) hide show
  1. package/README.md +22 -1
  2. package/dist/archives.cjs +494 -656
  3. package/dist/archives.cjs.map +1 -1
  4. package/dist/archives.d.ts +48 -80
  5. package/dist/archives.js +431 -585
  6. package/dist/archives.js.map +1 -1
  7. package/dist/conversions.cjs +183 -33
  8. package/dist/conversions.cjs.map +1 -1
  9. package/dist/conversions.d.ts +8 -1
  10. package/dist/conversions.js +188 -29
  11. package/dist/conversions.js.map +1 -1
  12. package/dist/default-worker.cjs +322 -62
  13. package/dist/default-worker.cjs.map +1 -1
  14. package/dist/default-worker.d.ts +1 -0
  15. package/dist/default-worker.js +336 -60
  16. package/dist/default-worker.js.map +1 -1
  17. package/dist/embedding.cjs +2 -1
  18. package/dist/embedding.cjs.map +1 -1
  19. package/dist/embedding.d.ts +4 -4
  20. package/dist/embedding.js +2 -1
  21. package/dist/embedding.js.map +1 -1
  22. package/dist/index.cjs +1295 -949
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.ts +58 -24
  25. package/dist/index.js +1164 -805
  26. package/dist/index.js.map +1 -1
  27. package/dist/{jobs-Dd5PMSId.d.ts → jobs-CRK-DZ40.d.ts} +27 -14
  28. package/dist/local-config.cjs +2 -1
  29. package/dist/local-config.cjs.map +1 -1
  30. package/dist/local-config.js +2 -1
  31. package/dist/local-config.js.map +1 -1
  32. package/dist/maintenance.cjs +140 -30
  33. package/dist/maintenance.cjs.map +1 -1
  34. package/dist/maintenance.d.ts +5 -1
  35. package/dist/maintenance.js +145 -26
  36. package/dist/maintenance.js.map +1 -1
  37. package/dist/runtime-config.cjs +4 -3
  38. package/dist/runtime-config.cjs.map +1 -1
  39. package/dist/runtime-config.d.ts +4 -1
  40. package/dist/runtime-config.js +4 -3
  41. package/dist/runtime-config.js.map +1 -1
  42. package/dist/stage-BnWI3Rqt.d.ts +33 -0
  43. package/dist/stage.cjs +22 -12
  44. package/dist/stage.cjs.map +1 -1
  45. package/dist/stage.d.ts +2 -14
  46. package/dist/stage.js +22 -12
  47. package/dist/stage.js.map +1 -1
  48. package/dist/target-CZ7elwmj.d.ts +14 -0
  49. package/dist/wikispine.cjs +14 -10
  50. package/dist/wikispine.cjs.map +1 -1
  51. package/dist/wikispine.js +14 -10
  52. package/dist/wikispine.js.map +1 -1
  53. package/dist/worker.cjs +295 -25
  54. package/dist/worker.cjs.map +1 -1
  55. package/dist/worker.d.ts +28 -5
  56. package/dist/worker.js +313 -28
  57. package/dist/worker.js.map +1 -1
  58. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -4,20 +4,20 @@ globalThis.__WIKIGRAPH_DATA_DIR__ ??= __WIKIGRAPH_RESOLVE__(__WIKIGRAPH_FILE_URL
4
4
 
5
5
  // src/archive/archive.ts
6
6
  import { randomUUID as randomUUID2 } from "crypto";
7
- import { link, mkdtemp, rename as rename2, rm as rm3, stat as stat2 } from "fs/promises";
7
+ import { link, mkdtemp, rename as rename2, rm as rm3, stat as stat3 } from "fs/promises";
8
8
  import { tmpdir } from "os";
9
- import { basename as basename3, dirname as dirname2, join as join3 } from "path";
9
+ import { basename as basename4, dirname as dirname3, join as join4 } from "path";
10
10
  import { Readable as Readable2 } from "stream";
11
11
  import {
12
12
  addChapter,
13
13
  applyChapterTree,
14
+ assertArchiveIndexArtifactsReady,
14
15
  assertNoActiveBuildJobConflicts,
15
16
  assertNoActiveBuildJobs,
16
17
  deleteArchiveSearchSessions,
17
18
  DirectoryDocument,
18
- finalizeWikiGraphLibraryArchiveWrite,
19
19
  findArchiveObjects,
20
- formatLocatedWikiGraphUri,
20
+ formatLocatedWikiGraphUri as formatLocatedWikiGraphUri2,
21
21
  isArchiveSearchIndexCurrent as isArchiveSearchIndexCurrent2,
22
22
  isSourceLocatorScopeUri,
23
23
  listArchiveCollection,
@@ -28,23 +28,19 @@ import {
28
28
  listRelatedArchiveObjects,
29
29
  moveChapter,
30
30
  packArchiveContext,
31
- parseLocatedWikiGraphUri,
32
- parseWikiGraphLibraryUri,
31
+ parseLocatedWikiGraphUri as parseLocatedWikiGraphUri2,
33
32
  readArchivePage,
34
33
  readSearchIndexCapabilityStatus,
35
- readWikiGraphLibraryIndexState,
36
34
  rebuildArchiveSearchIndex,
37
- rebuildWikiGraphLibraryIndex,
38
35
  removeChapter,
39
36
  resetChapter,
40
37
  resolveChapterPathReadonly,
41
- resolveWikiGraphLibraryArchiveFile,
42
38
  setChapterSource,
43
39
  setChapterSummary,
44
40
  setChapterTitle,
45
41
  getChapterTree,
46
42
  WikiGraph as WikiGraph2,
47
- WikiGraphArchiveFile,
43
+ WikiGraphArchiveFile as WikiGraphArchiveFile2,
48
44
  TOC_FILE_VERSION,
49
45
  writeWikgArchive,
50
46
  ObjectMetadataKind
@@ -54,7 +50,7 @@ import {
54
50
  import { createHash } from "crypto";
55
51
  import { createReadStream } from "fs";
56
52
  import { rm as rm2 } from "fs/promises";
57
- import { basename as basename2 } from "path";
53
+ import { basename as basename3 } from "path";
58
54
  import {
59
55
  WikiGraph
60
56
  } from "wiki-graph-core";
@@ -383,42 +379,42 @@ var NodeDatabaseConnection = class {
383
379
  }
384
380
  database;
385
381
  async close() {
386
- await new Promise((resolve3, reject) => {
382
+ await new Promise((resolve4, reject) => {
387
383
  this.database.close((error) => {
388
384
  if (error) reject(error);
389
- else resolve3();
385
+ else resolve4();
390
386
  });
391
387
  });
392
388
  }
393
389
  async execute(sql) {
394
- await new Promise((resolve3, reject) => {
390
+ await new Promise((resolve4, reject) => {
395
391
  this.database.exec(sql, (error) => {
396
392
  if (error) reject(error);
397
- else resolve3();
393
+ else resolve4();
398
394
  });
399
395
  });
400
396
  }
401
397
  async queryAll(sql, params = []) {
402
- return await new Promise((resolve3, reject) => {
398
+ return await new Promise((resolve4, reject) => {
403
399
  this.database.all(sql, [...params], (error, rows) => {
404
400
  if (error) reject(error);
405
- else resolve3(rows);
401
+ else resolve4(rows);
406
402
  });
407
403
  });
408
404
  }
409
405
  async queryOne(sql, params = []) {
410
- return await new Promise((resolve3, reject) => {
406
+ return await new Promise((resolve4, reject) => {
411
407
  this.database.get(sql, [...params], (error, row) => {
412
408
  if (error) reject(error);
413
- else resolve3(row);
409
+ else resolve4(row);
414
410
  });
415
411
  });
416
412
  }
417
413
  async run(sql, params = []) {
418
- await new Promise((resolve3, reject) => {
414
+ await new Promise((resolve4, reject) => {
419
415
  this.database.run(sql, [...params], (error) => {
420
416
  if (error) reject(error);
421
- else resolve3();
417
+ else resolve4();
422
418
  });
423
419
  });
424
420
  }
@@ -432,10 +428,10 @@ async function openNativeNodeDatabase(file, flags) {
432
428
  if (path === void 0) {
433
429
  throw new TypeError("The Node database adapter requires a NodeFile");
434
430
  }
435
- return await new Promise((resolve3, reject) => {
431
+ return await new Promise((resolve4, reject) => {
436
432
  const database = new nodeSqlite3.Database(path, flags, (error) => {
437
433
  if (error) reject(error);
438
- else resolve3(database);
434
+ else resolve4(database);
439
435
  });
440
436
  });
441
437
  }
@@ -444,19 +440,19 @@ async function openNodeZip(file) {
444
440
  if (path === void 0) {
445
441
  throw new TypeError("The Node ZIP adapter requires a NodeFile");
446
442
  }
447
- const zipFile = await new Promise((resolve3, reject) => {
443
+ const zipFile = await new Promise((resolve4, reject) => {
448
444
  yauzl.open(
449
445
  path,
450
446
  { autoClose: false, lazyEntries: true },
451
447
  (error, opened) => {
452
448
  if (error || opened === void 0)
453
449
  reject(error ?? new Error("Cannot open ZIP"));
454
- else resolve3(opened);
450
+ else resolve4(opened);
455
451
  }
456
452
  );
457
453
  });
458
454
  const entries = await new Promise(
459
- (resolve3, reject) => {
455
+ (resolve4, reject) => {
460
456
  const discovered = /* @__PURE__ */ new Map();
461
457
  const rejectAndClose = (error) => {
462
458
  zipFile.close();
@@ -466,7 +462,7 @@ async function openNodeZip(file) {
466
462
  };
467
463
  const resolveEntries = () => {
468
464
  zipFile.off("error", rejectAndClose);
469
- resolve3(discovered);
465
+ resolve4(discovered);
470
466
  };
471
467
  zipFile.on("entry", (entry) => {
472
468
  if (!entry.fileName.endsWith("/")) {
@@ -576,12 +572,12 @@ async function collectDecodedNodeStreamRange(input, offset, length) {
576
572
  return Buffer.concat(chunks, collected);
577
573
  }
578
574
  async function openNodeZipEntryStream(zipFile, entry, options) {
579
- return await new Promise((resolve3, reject) => {
575
+ return await new Promise((resolve4, reject) => {
580
576
  const callback = (error, opened) => {
581
577
  if (error || opened === void 0) {
582
578
  reject(error ?? new Error(`Cannot read ZIP entry: ${entry.fileName}`));
583
579
  } else {
584
- resolve3(opened);
580
+ resolve4(opened);
585
581
  }
586
582
  };
587
583
  if (options === void 0) zipFile.openReadStream(entry, callback);
@@ -712,11 +708,11 @@ async function writeNodeStream(input, writer) {
712
708
  );
713
709
  }
714
710
  async function collectNodeStream(input) {
715
- return await new Promise((resolve3, reject) => {
711
+ return await new Promise((resolve4, reject) => {
716
712
  const chunks = [];
717
713
  input.on("data", (chunk) => chunks.push(chunk));
718
714
  input.once("error", reject);
719
- input.once("end", () => resolve3(Buffer.concat(chunks)));
715
+ input.once("end", () => resolve4(Buffer.concat(chunks)));
720
716
  });
721
717
  }
722
718
  var nodeWikiGraphPlatform = {
@@ -870,12 +866,16 @@ function getWikiGraphSDKRuntimeContext() {
870
866
  return runtimeContext.getStore() ?? {
871
867
  cwd: process.cwd(),
872
868
  env: process.env,
873
- envPolicy: "production"
869
+ envPolicy: "production",
870
+ providers: {}
874
871
  };
875
872
  }
876
873
  function getWikiGraphSDKStateDir() {
877
874
  return getWikiGraphSDKRuntimeContext().stateDir;
878
875
  }
876
+ function getWikiGraphSDKProviders() {
877
+ return getWikiGraphSDKRuntimeContext().providers ?? {};
878
+ }
879
879
 
880
880
  // src/local-config.ts
881
881
  import { join as join2 } from "path";
@@ -1176,8 +1176,8 @@ var inlineLLMConfigSchema = z.object({
1176
1176
  });
1177
1177
  async function loadWikiGraphRuntimeConfig(options) {
1178
1178
  const [embedding, localLLM, concurrent, wikimedia, wikispine] = await Promise.all([
1179
- readLocalConfigSection("embeddings"),
1180
- readLocalConfigSection("llm"),
1179
+ options?.skipEmbeddingConfig === true ? Promise.resolve({}) : readLocalConfigSection("embeddings"),
1180
+ options?.skipLLMConfig === true ? Promise.resolve({}) : readLocalConfigSection("llm"),
1181
1181
  readLocalConfigSection("concurrent"),
1182
1182
  readLocalConfigSection("wikimedia"),
1183
1183
  readLocalConfigSection("wikispine")
@@ -1373,6 +1373,14 @@ function formatError2(error) {
1373
1373
  return error instanceof Error ? error.message : String(error);
1374
1374
  }
1375
1375
 
1376
+ // src/providers.ts
1377
+ function resolveWikiGraphLLMJSON(options) {
1378
+ if (options.llm !== void 0 && options.llmJSON !== void 0) {
1379
+ throw new Error("Pass either llm or llmJSON, not both.");
1380
+ }
1381
+ return options.llm === void 0 ? options.llmJSON : JSON.stringify(options.llm);
1382
+ }
1383
+
1376
1384
  // src/runtime-path.ts
1377
1385
  import { homedir as homedir3 } from "os";
1378
1386
  import { isAbsolute as isAbsolute2, resolve as resolve2 } from "path";
@@ -1385,6 +1393,203 @@ function resolveWikiGraphRuntimePath(path) {
1385
1393
  return isAbsolute2(path) ? path : resolve2(context.cwd, path);
1386
1394
  }
1387
1395
 
1396
+ // src/archive/target.ts
1397
+ import { realpath, stat as stat2 } from "fs/promises";
1398
+ import { basename as basename2, dirname as dirname2, isAbsolute as isAbsolute3, join as join3, relative, resolve as resolve3 } from "path";
1399
+ import {
1400
+ formatLocatedWikiGraphUri,
1401
+ formatWikiGraphLibraryUri,
1402
+ listWikiGraphLibraries,
1403
+ listWikiGraphLibraryArchives,
1404
+ parseLocatedWikiGraphUri,
1405
+ parseWikiGraphLibraryUri,
1406
+ resolveWikiGraphLibrary,
1407
+ resolveWikiGraphLibraryArchiveFile
1408
+ } from "wiki-graph-core";
1409
+ var WikiGraphArchiveOwnershipError = class extends Error {
1410
+ code = "WIKI_GRAPH_ARCHIVE_OWNERSHIP_MISMATCH";
1411
+ constructor(message) {
1412
+ super(message);
1413
+ this.name = "WikiGraphArchiveOwnershipError";
1414
+ }
1415
+ };
1416
+ async function resolveWikiGraphArchiveLocation(target) {
1417
+ if (target.kind === "standalone") {
1418
+ return await resolveStandaloneLocation(target);
1419
+ }
1420
+ return await resolveLibraryLocation(target);
1421
+ }
1422
+ async function assertStandaloneWikiGraphArchivePath(inputPath) {
1423
+ const path = resolveWikiGraphRuntimePath(inputPath);
1424
+ const candidate = await canonicalPath(path);
1425
+ const candidateIdentity = await readFileIdentity(path);
1426
+ const libraries = await listWikiGraphLibraries();
1427
+ const matches = await findMatchingMembers(
1428
+ libraries,
1429
+ candidate,
1430
+ candidateIdentity
1431
+ );
1432
+ if (matches.length > 0) {
1433
+ const match = requireUnambiguousManagedMatch(path, matches);
1434
+ throw new WikiGraphArchiveOwnershipError(
1435
+ `Standalone archive path belongs to registered library ${formatWikiGraphLibraryUri(
1436
+ match.library.isDefault ? void 0 : match.library.publicId
1437
+ )}: ${path}. Use the library UUID URI ${match.archive.uri} instead.`
1438
+ );
1439
+ }
1440
+ for (const library of libraries) {
1441
+ const rootPath = getNodeResourcePath(library.folder);
1442
+ const root = await canonicalPath(rootPath);
1443
+ if (!isWithin(root, candidate)) continue;
1444
+ throw new WikiGraphArchiveOwnershipError(
1445
+ `Standalone archive path belongs to registered library ${formatWikiGraphLibraryUri(
1446
+ library.isDefault ? void 0 : library.publicId
1447
+ )}: ${path}. Scan the library, then address the archive by its library UUID URI.`
1448
+ );
1449
+ }
1450
+ return path;
1451
+ }
1452
+ function archiveTargetFromLogicalLocator(locator, objectUri) {
1453
+ if (locator.startsWith("wikg://lib/")) {
1454
+ return { kind: "library", uri: withObjectUri(locator, objectUri) };
1455
+ }
1456
+ return {
1457
+ kind: "standalone",
1458
+ path: locator,
1459
+ ...objectUri === void 0 ? {} : { objectUri }
1460
+ };
1461
+ }
1462
+ async function resolveWikiGraphArchiveTarget(file) {
1463
+ const path = getNodeResourcePath(file);
1464
+ const candidate = await canonicalPath(path);
1465
+ const candidateIdentity = await readFileIdentity(path);
1466
+ const matches = await findMatchingMembers(
1467
+ await listWikiGraphLibraries(),
1468
+ candidate,
1469
+ candidateIdentity
1470
+ );
1471
+ if (matches.length > 0) {
1472
+ const match = requireUnambiguousManagedMatch(path, matches);
1473
+ return { kind: "library", uri: match.archive.uri };
1474
+ }
1475
+ return { kind: "standalone", path: getNodeResourcePath(file) };
1476
+ }
1477
+ async function resolveStandaloneLocation(target) {
1478
+ if (target.path.startsWith("wikg://lib/")) {
1479
+ throw new WikiGraphArchiveOwnershipError(
1480
+ `A library archive URI cannot be used as a standalone path: ${target.path}`
1481
+ );
1482
+ }
1483
+ const path = await assertStandaloneWikiGraphArchivePath(target.path);
1484
+ const normalized = {
1485
+ kind: "standalone",
1486
+ path,
1487
+ ...target.objectUri === void 0 ? {} : { objectUri: target.objectUri }
1488
+ };
1489
+ return {
1490
+ archiveFile: new NodeFile(path),
1491
+ archiveKey: path,
1492
+ archivePath: path,
1493
+ indexScope: { archiveKey: path, archivePath: path, kind: "archive-index" },
1494
+ locatedUri: formatLocatedWikiGraphUri(path, target.objectUri),
1495
+ target: normalized
1496
+ };
1497
+ }
1498
+ async function resolveLibraryLocation(target) {
1499
+ const parsedLocated = parseLocatedWikiGraphUri(target.uri);
1500
+ const archiveUri = parsedLocated.archivePath ?? target.uri;
1501
+ const parsed = parseWikiGraphLibraryUri(archiveUri);
1502
+ if (parsed?.kind !== "archive") {
1503
+ throw new WikiGraphArchiveOwnershipError(
1504
+ `Library archive target must be a UUID archive URI: ${target.uri}`
1505
+ );
1506
+ }
1507
+ await resolveWikiGraphLibrary(parsed);
1508
+ const archiveFile = await resolveWikiGraphLibraryArchiveFile(archiveUri);
1509
+ const normalized = {
1510
+ kind: "library",
1511
+ uri: target.uri
1512
+ };
1513
+ return {
1514
+ archiveFile,
1515
+ archiveKey: archiveUri,
1516
+ archivePath: archiveUri,
1517
+ indexScope: {
1518
+ archiveKey: archiveUri,
1519
+ archivePath: archiveUri,
1520
+ kind: "archive-index"
1521
+ },
1522
+ libraryArchiveTarget: parsed,
1523
+ locatedUri: target.uri,
1524
+ publicArchiveUri: archiveUri,
1525
+ target: normalized
1526
+ };
1527
+ }
1528
+ function withObjectUri(archiveLocator, objectUri) {
1529
+ if (objectUri === void 0) return archiveLocator;
1530
+ const path = objectUri.replace(/^wikg:\/\//u, "");
1531
+ return `${archiveLocator.replace(/\/$/u, "")}/${path}`;
1532
+ }
1533
+ async function canonicalPath(path) {
1534
+ try {
1535
+ return await realpath(path);
1536
+ } catch {
1537
+ const absolute = resolve3(path);
1538
+ const parent = dirname2(absolute);
1539
+ return parent === absolute ? absolute : join3(await canonicalPath(parent), basename2(absolute));
1540
+ }
1541
+ }
1542
+ function isWithin(root, candidate) {
1543
+ const child = relative(root, candidate);
1544
+ return child === "" || !child.startsWith("..") && !isAbsolute3(child);
1545
+ }
1546
+ async function findMatchingMembers(libraries, candidate, candidateIdentity) {
1547
+ const members = [];
1548
+ for (const library of libraries) {
1549
+ const archives = await listWikiGraphLibraryArchives({
1550
+ isDefault: library.isDefault,
1551
+ kind: "scope",
1552
+ ...library.isDefault ? {} : { publicId: library.publicId }
1553
+ });
1554
+ for (const archive of archives) {
1555
+ if (archive.file === void 0) continue;
1556
+ members.push({
1557
+ archive,
1558
+ library,
1559
+ memberPath: getNodeResourcePath(archive.file)
1560
+ });
1561
+ }
1562
+ }
1563
+ const exact = [];
1564
+ for (const member of members) {
1565
+ if (await canonicalPath(member.memberPath) === candidate) {
1566
+ exact.push(member);
1567
+ }
1568
+ }
1569
+ if (exact.length > 0 || candidateIdentity === void 0) return exact;
1570
+ const identityMatches = [];
1571
+ for (const member of members) {
1572
+ if (await readFileIdentity(member.memberPath) === candidateIdentity) {
1573
+ identityMatches.push(member);
1574
+ }
1575
+ }
1576
+ return identityMatches;
1577
+ }
1578
+ function requireUnambiguousManagedMatch(path, matches) {
1579
+ if (matches.length === 1) return matches[0];
1580
+ throw new WikiGraphArchiveOwnershipError(
1581
+ `Archive file identity is ambiguous across managed archives: ${path}. Use an explicit library UUID URI (${matches.map((match) => match.archive.uri).join(", ")}).`
1582
+ );
1583
+ }
1584
+ async function readFileIdentity(path) {
1585
+ try {
1586
+ const value = await stat2(path);
1587
+ return `${value.dev}:${value.ino}`;
1588
+ } catch {
1589
+ return void 0;
1590
+ }
1591
+ }
1592
+
1388
1593
  // src/conversions.ts
1389
1594
  var WikiGraphConversionManager = class {
1390
1595
  #runtime;
@@ -1409,23 +1614,33 @@ var WikiGraphConversionManager = class {
1409
1614
  }
1410
1615
  const requiresDigest = options.input.format !== "wikg";
1411
1616
  const requiresLLM = requiresDigest && targetStage !== "planned" && targetStage !== "sourced";
1617
+ const llmJSON = resolveWikiGraphLLMJSON(options);
1618
+ const injectedLLM = llmJSON === void 0 ? getWikiGraphSDKProviders().llm : void 0;
1412
1619
  const config = await loadWikiGraphRuntimeConfig({
1413
- ...options.llmJSON === void 0 ? {} : { llmJSON: options.llmJSON }
1620
+ ...llmJSON === void 0 ? {} : { llmJSON },
1621
+ ...injectedLLM === void 0 ? {} : { skipLLMConfig: true },
1622
+ ...getWikiGraphSDKProviders().embedding === void 0 ? {} : { skipEmbeddingConfig: true }
1414
1623
  });
1415
1624
  const app = new WikiGraph({
1416
1625
  ...options.verbose === true ? { verbose: true } : {},
1417
- ...requiresLLM ? { llm: buildWikiGraphLLMOptions(config) } : {}
1626
+ ...requiresLLM ? {
1627
+ llm: injectedLLM === void 0 ? buildWikiGraphLLMOptions(config) : { streamProvider: injectedLLM }
1628
+ } : {}
1418
1629
  });
1419
1630
  const documentDirectory = await prepareDigestDirectory(
1420
1631
  options.digestDirectory,
1421
1632
  requiresDigest
1422
1633
  );
1423
1634
  let chapterCount;
1635
+ let chapterPaths;
1424
1636
  const write = async (archive) => {
1425
1637
  if (requiresDigest) await options.onSourceImported?.();
1426
1638
  if (typeof archive.readToc === "function") {
1427
1639
  const toc = await archive.readToc();
1428
1640
  chapterCount = toc === void 0 ? void 0 : countTocChapters(toc.items);
1641
+ if (options.output.format === "wikg") {
1642
+ chapterPaths = toc === void 0 ? [] : collectTocChapterPaths(toc.items);
1643
+ }
1429
1644
  }
1430
1645
  await writeArchive(archive, options.output.path, options.output.format);
1431
1646
  };
@@ -1434,7 +1649,9 @@ var WikiGraphConversionManager = class {
1434
1649
  throw new Error("wikg input requires a file path.");
1435
1650
  }
1436
1651
  await app.openSession(
1437
- new NodeFile(resolveWikiGraphRuntimePath(options.input.path)),
1652
+ new NodeFile(
1653
+ await assertStandaloneWikiGraphArchivePath(options.input.path)
1654
+ ),
1438
1655
  write
1439
1656
  );
1440
1657
  } else if ("stream" in options.input) {
@@ -1477,6 +1694,7 @@ var WikiGraphConversionManager = class {
1477
1694
  const sourceArtifact = await resolveSourceArtifact(options.input);
1478
1695
  return {
1479
1696
  ...chapterCount === void 0 ? {} : { chapterCount },
1697
+ ...chapterPaths === void 0 ? {} : { chapterPaths },
1480
1698
  inputFormat: options.input.format,
1481
1699
  outputFormat: options.output.format,
1482
1700
  outputPath: options.output.path,
@@ -1493,7 +1711,8 @@ async function prepareDigestDirectory(path, required) {
1493
1711
  return new NodeDirectory(resolved);
1494
1712
  }
1495
1713
  async function writeArchive(archive, path, format) {
1496
- const file = new NodeFile(resolveWikiGraphRuntimePath(path));
1714
+ const outputPath = format === "wikg" ? await assertStandaloneWikiGraphArchivePath(path) : resolveWikiGraphRuntimePath(path);
1715
+ const file = new NodeFile(outputPath);
1497
1716
  if (format === "epub") await archive.exportEpub(file);
1498
1717
  else if (format === "wikg") await archive.saveAs(file);
1499
1718
  else if (format === "pcex") throw new Error("pcex output is not supported.");
@@ -1522,7 +1741,7 @@ async function resolveSourceArtifact(input) {
1522
1741
  return {
1523
1742
  digest: hash.digest("hex"),
1524
1743
  mediaType: "application/epub+zip",
1525
- name: basename2(path)
1744
+ name: basename3(path)
1526
1745
  };
1527
1746
  }
1528
1747
  function isNodeErrorCode(error, code) {
@@ -1538,6 +1757,21 @@ function countTocChapters(items) {
1538
1757
  }
1539
1758
  return count;
1540
1759
  }
1760
+ function collectTocChapterPaths(items, ancestorKeys = []) {
1761
+ const paths = [];
1762
+ for (const item of items) {
1763
+ const key = item.key ?? `chapter-${item.serialId ?? "group"}`;
1764
+ const chapterPath = [...ancestorKeys, key];
1765
+ if (item.serialId !== void 0) paths.push(chapterPath.join("/"));
1766
+ paths.push(
1767
+ ...collectTocChapterPaths(
1768
+ item.children,
1769
+ chapterPath
1770
+ )
1771
+ );
1772
+ }
1773
+ return paths;
1774
+ }
1541
1775
 
1542
1776
  // src/query-runtime.ts
1543
1777
  import {
@@ -1706,6 +1940,8 @@ function createOpenAICompatibleName2(baseURL) {
1706
1940
 
1707
1941
  // src/query-runtime.ts
1708
1942
  async function createConfiguredEmbeddingProvider() {
1943
+ const injected = getWikiGraphSDKProviders().embedding;
1944
+ if (injected !== void 0) return injected;
1709
1945
  const config = await readWikiGraphEmbeddingConfig();
1710
1946
  if (config.provider === void 0 || config.model === void 0 || config.provider === "openai-compatible" && config.baseURL === void 0 || config.provider === "openai" && config.baseURL !== void 0) {
1711
1947
  return void 0;
@@ -1734,499 +1970,130 @@ import {
1734
1970
  isArchiveSearchIndexCurrent,
1735
1971
  listChapters
1736
1972
  } from "wiki-graph-core";
1737
-
1738
- // src/planning.ts
1739
- var DEFAULT_GENERATION_JOB_CONCURRENCY = 3;
1740
- var DEFAULT_GENERATION_REQUEST_CONCURRENCY = 6;
1741
- function planGenerationTask(task, words, chapters, concurrent, model) {
1742
- const profile = getGenerationPlanningProfile(task);
1743
- const calls = Math.max(chapters, Math.ceil(words / profile.wordsPerCall));
1744
- const effectiveConcurrency = Math.max(
1745
- 1,
1746
- task === "reading-graph" ? 1 : concurrent.request
1747
- );
1748
- const callBatches = Math.ceil(calls / effectiveConcurrency);
1749
- const wordSeconds = words * profile.secondsPerWord;
1750
- return {
1751
- model,
1752
- timeSeconds: {
1753
- max: Math.ceil(callBatches * profile.maxSecondsPerCall + wordSeconds),
1754
- min: Math.ceil(callBatches * profile.minSecondsPerCall + wordSeconds)
1755
- },
1756
- tokens: {
1757
- cacheableInput: Math.ceil(words * profile.cacheableInputTokenPerWord),
1758
- input: Math.ceil(words * profile.inputTokenPerWord),
1759
- output: Math.ceil(words * profile.outputTokenPerWord)
1760
- }
1761
- };
1762
- }
1763
- function createGenerationPerformanceHints(input) {
1764
- if (!input.hasJobWork) {
1765
- return [];
1766
- }
1767
- const hints = [];
1768
- const recommendedRequest = input.concurrent.request < 4 ? DEFAULT_GENERATION_REQUEST_CONCURRENCY : input.concurrent.request < 8 ? 8 : void 0;
1769
- if (input.hasRequestWork && recommendedRequest !== void 0) {
1770
- hints.push({
1771
- configKey: "request",
1772
- configValue: recommendedRequest,
1773
- current: input.concurrent.request,
1774
- kind: "request",
1775
- message: "LLM request concurrency can often be higher. Use at least 4; 6-8 is usually faster when the provider allows it.",
1776
- recommended: recommendedRequest
1777
- });
1778
- }
1779
- if (input.concurrent.job < 4 && input.chapters > 1) {
1780
- hints.push({
1781
- configKey: "job",
1782
- configValue: 4,
1783
- current: input.concurrent.job,
1784
- kind: "job",
1785
- message: "Multiple chapters need work and job concurrency is below 4. Raising it lets chapter jobs run in parallel.",
1786
- recommended: 4
1787
- });
1788
- }
1789
- return hints;
1790
- }
1791
- function formatGenerationPlanningModel(llm) {
1792
- if (llm?.model === void 0) {
1793
- return "not configured";
1794
- }
1795
- return llm.provider === void 0 ? llm.model : `${llm.provider}/${llm.model}`;
1796
- }
1797
- function formatGenerationPlanningDuration(seconds) {
1798
- if (seconds < 60) {
1799
- return `${seconds}s`;
1800
- }
1801
- const minutes = Math.round(seconds / 60);
1802
- if (minutes < 60) {
1803
- return `${minutes}m`;
1804
- }
1805
- return `${Math.round(minutes / 60)}h`;
1806
- }
1807
- function getGenerationPlanningProfile(task) {
1808
- switch (task) {
1809
- case "index-fts":
1810
- return {
1811
- cacheableInputTokenPerWord: 0,
1812
- inputTokenPerWord: 0,
1813
- maxSecondsPerCall: 1,
1814
- minSecondsPerCall: 0,
1815
- outputTokenPerWord: 0,
1816
- secondsPerWord: 5e-4,
1817
- wordsPerCall: 1e5
1818
- };
1819
- case "index-embedding-source":
1820
- case "index-embedding-summary":
1821
- return {
1822
- cacheableInputTokenPerWord: 0,
1823
- inputTokenPerWord: 0,
1824
- maxSecondsPerCall: 10,
1825
- minSecondsPerCall: 1,
1826
- outputTokenPerWord: 0,
1827
- secondsPerWord: 2e-3,
1828
- wordsPerCall: 1e4
1829
- };
1830
- case "knowledge-graph":
1831
- return {
1832
- cacheableInputTokenPerWord: 60,
1833
- inputTokenPerWord: 80,
1834
- maxSecondsPerCall: 35,
1835
- minSecondsPerCall: 15,
1836
- outputTokenPerWord: 25,
1837
- secondsPerWord: 0.02,
1838
- wordsPerCall: 35
1839
- };
1840
- case "reading-graph":
1841
- return {
1842
- cacheableInputTokenPerWord: 20,
1843
- inputTokenPerWord: 25,
1844
- maxSecondsPerCall: 45,
1845
- minSecondsPerCall: 15,
1846
- outputTokenPerWord: 4,
1847
- secondsPerWord: 0.01,
1848
- wordsPerCall: 160
1849
- };
1850
- case "reading-summary":
1851
- return {
1852
- cacheableInputTokenPerWord: 45,
1853
- inputTokenPerWord: 55,
1854
- maxSecondsPerCall: 25,
1855
- minSecondsPerCall: 10,
1856
- outputTokenPerWord: 4,
1857
- secondsPerWord: 0.01,
1858
- wordsPerCall: 110
1859
- };
1860
- }
1861
- }
1862
-
1863
- // src/archive/inspect.ts
1864
- async function createWikiGraphArchiveInspectReport(document, options) {
1865
- const { archiveUri } = options;
1866
- const [
1867
- chapters,
1868
- summaryWords,
1869
- indexCacheCurrent,
1870
- config,
1871
- ftsArtifactCoverage,
1872
- sourceEmbeddingArtifactCoverage,
1873
- summaryEmbeddingArtifactCoverage
1874
- ] = await Promise.all([
1875
- readInspectChapters(document, options.chapterId),
1876
- readSummaryWords(document, options.chapterId),
1973
+ async function inspectWikiGraphArchive(document, options) {
1974
+ const [allChapters, indexCacheCurrent, summaryWords, ...coverage] = await Promise.all([
1975
+ listChapters(document),
1877
1976
  isArchiveSearchIndexCurrent(document),
1878
- loadWikiGraphRuntimeConfig(),
1879
- readIndexArtifactCoverage(document, "fts", options.chapterId),
1880
- readIndexArtifactCoverage(document, "embedding-source", options.chapterId),
1881
- readIndexArtifactCoverage(document, "embedding-summary", options.chapterId)
1977
+ readSummaryWords(document),
1978
+ document.indexArtifacts.listCoverage("fts"),
1979
+ document.indexArtifacts.listCoverage("embedding-source"),
1980
+ document.indexArtifacts.listCoverage("embedding-summary")
1882
1981
  ]);
1883
- const selectedChapter = options.chapterId === void 0 ? void 0 : chapters[0];
1884
- const scopeUri = selectedChapter === void 0 ? archiveUri : formatInspectLocatedChapterUri(archiveUri, selectedChapter);
1885
- const concurrent = {
1886
- job: config.concurrent?.job ?? DEFAULT_GENERATION_JOB_CONCURRENCY,
1887
- request: config.concurrent?.request ?? DEFAULT_GENERATION_REQUEST_CONCURRENCY
1982
+ const chapters = selectChapters(allChapters, options.chapterId);
1983
+ const coverageByKind = {
1984
+ fts: byChapterId(coverage[0]),
1985
+ sourceEmbedding: byChapterId(coverage[1]),
1986
+ summaryEmbedding: byChapterId(coverage[2])
1888
1987
  };
1889
- const planningModel = formatGenerationPlanningModel(config.llm);
1890
- const contentChapters = chapters.filter(
1891
- (chapter) => chapter.stage !== "planned"
1892
- );
1893
- const sourceWords = sumWords(contentChapters);
1894
- const readingGraphCovered = contentChapters.filter(
1895
- (chapter) => chapter.readingGraphReady
1896
- );
1897
- const knowledgeGraphCovered = contentChapters.filter(
1898
- (chapter) => chapter.knowledgeGraphReady
1899
- );
1900
- const summaryCovered = contentChapters.filter(
1901
- (chapter) => chapter.summaryReady
1902
- );
1903
- const ftsArtifactCovered = filterChaptersByCurrentIndexArtifact(
1904
- contentChapters,
1905
- ftsArtifactCoverage
1906
- );
1907
- const sourceEmbeddingArtifactCovered = filterChaptersByCurrentIndexArtifact(
1908
- contentChapters,
1909
- sourceEmbeddingArtifactCoverage
1910
- );
1911
- const summaryEmbeddingArtifactCovered = filterChaptersByCurrentIndexArtifact(
1912
- contentChapters,
1913
- summaryEmbeddingArtifactCoverage
1914
- );
1915
- const queryBlockedContentChapters = contentChapters.filter(
1916
- (chapter) => !ftsArtifactCovered.includes(chapter) && !sourceEmbeddingArtifactCovered.includes(chapter)
1917
- );
1918
- const queryBlockedChapters = queryBlockedContentChapters.map(
1919
- (chapter) => createInspectChapterReference(archiveUri, chapter)
1988
+ const inspections = await Promise.all(
1989
+ chapters.map(async (chapter) => {
1990
+ const serial = await document.serials.getById(chapter.chapterId);
1991
+ return {
1992
+ capabilities: {
1993
+ knowledgeGraph: {
1994
+ completed: serial?.knowledgeGraphReady === true
1995
+ },
1996
+ readingGraph: { completed: serial?.topologyReady === true },
1997
+ readingSummary: { completed: chapter.stage === "summarized" }
1998
+ },
1999
+ chapter,
2000
+ indexes: {
2001
+ fts: inspectArtifact(
2002
+ "fts",
2003
+ coverageByKind.fts.get(chapter.chapterId)
2004
+ ),
2005
+ sourceEmbedding: inspectArtifact(
2006
+ "embedding-source",
2007
+ coverageByKind.sourceEmbedding.get(chapter.chapterId)
2008
+ ),
2009
+ summaryEmbedding: inspectArtifact(
2010
+ "embedding-summary",
2011
+ coverageByKind.summaryEmbedding.get(chapter.chapterId)
2012
+ )
2013
+ },
2014
+ revision: serial?.revision ?? 0,
2015
+ summaryWords: summaryWords.get(chapter.chapterId) ?? 0
2016
+ };
2017
+ })
1920
2018
  );
1921
- const queryReady = queryBlockedChapters.length === 0;
1922
- const improvements = createInspectImprovements({
1923
- concurrent,
1924
- contentChapters,
1925
- indexCacheCurrent,
1926
- planningModel,
1927
- queryBlockedChapters: queryBlockedContentChapters,
1928
- summaryCovered,
1929
- knowledgeGraphCovered,
1930
- readingGraphCovered
1931
- });
1932
- const performanceHints = createGenerationPerformanceHints({
1933
- chapters: Math.max(
1934
- 0,
1935
- ...improvements.map((improvement) => improvement.missingChapters ?? 0)
1936
- ),
1937
- concurrent,
1938
- hasJobWork: improvements.some(
1939
- (improvement) => improvement.planning !== void 0
1940
- ),
1941
- hasRequestWork: improvements.some(
1942
- (improvement) => improvement.planning !== void 0
1943
- )
1944
- });
2019
+ const selected = inspections[0];
1945
2020
  return {
1946
- archiveUri,
1947
- uri: scopeUri,
2021
+ archiveUri: options.archiveUri,
2022
+ chapters: inspections,
2023
+ localIndexCache: { current: indexCacheCurrent },
1948
2024
  scope: options.chapterId === void 0 ? { type: "archive" } : { chapterId: options.chapterId, type: "chapter" },
1949
- content: {
1950
- chapters: {
1951
- content: contentChapters.length,
1952
- planned: chapters.length - contentChapters.length,
1953
- total: chapters.length
1954
- },
1955
- sourceWords,
1956
- summaryWords
1957
- },
1958
- localIndexCache: {
1959
- current: indexCacheCurrent,
1960
- ...!queryReady ? {
1961
- blockedBy: "missing-search-artifacts",
1962
- impact: "The cache cannot be built until every content chapter has a current FTS or source embedding artifact."
1963
- } : indexCacheCurrent ? {} : {
1964
- impact: "The next archive query may need to sync index cache first.",
1965
- resource: "local CPU/disk time only; no provider calls."
1966
- },
1967
- status: !queryReady ? "blocked" : indexCacheCurrent ? "current" : "missing-or-outdated",
1968
- syncAvailable: queryReady && !indexCacheCurrent
1969
- },
1970
- coverage: {
1971
- ftsIndexArtifact: createInspectCoverage(
1972
- ftsArtifactCovered,
1973
- contentChapters
1974
- ),
1975
- knowledgeGraph: createInspectCoverage(
1976
- knowledgeGraphCovered,
1977
- contentChapters
1978
- ),
1979
- readingGraph: createInspectCoverage(readingGraphCovered, contentChapters),
1980
- summary: createInspectCoverage(summaryCovered, contentChapters),
1981
- sourceEmbeddingIndexArtifact: createInspectCoverage(
1982
- sourceEmbeddingArtifactCovered,
1983
- contentChapters
1984
- ),
1985
- summaryEmbeddingIndexArtifact: createInspectCoverage(
1986
- summaryEmbeddingArtifactCovered,
1987
- contentChapters
1988
- )
1989
- },
1990
- query: {
1991
- ready: queryReady
1992
- },
1993
- searchArtifacts: {
1994
- blockedChapters: queryBlockedChapters,
1995
- ...!queryReady ? {
1996
- resource: "local CPU/disk time only; no provider calls."
1997
- } : {},
1998
- ready: queryReady,
1999
- status: queryReady ? "ready" : "incomplete"
2000
- },
2001
- retrievalGuidance: formatRetrievalGuidance({
2002
- indexCacheCurrent,
2003
- knowledgeGraphCovered,
2004
- readingGraphCovered,
2005
- contentChapters,
2006
- queryReady,
2007
- sourceWords
2008
- }),
2009
- improvements,
2010
- performanceHints,
2011
- summaryCoverageNote: "Summary coverage means a current summary artifact exists for the chapter; it does not guarantee that every source topic is represented in the summary text."
2012
- };
2013
- }
2014
- function createInspectChapterReference(archiveUri, chapter) {
2015
- return {
2016
- chapterId: chapter.chapterId,
2017
- locatedUri: formatInspectLocatedChapterUri(archiveUri, chapter),
2018
- title: chapter.title,
2019
- uri: chapter.uri
2025
+ uri: selected === void 0 || options.chapterId === void 0 ? options.archiveUri : formatLocatedChapterUri(options.archiveUri, selected.chapter)
2020
2026
  };
2021
2027
  }
2022
- function formatInspectLocatedChapterUri(archiveUri, chapter) {
2023
- return `${archiveUri.replace(/\/+$/u, "")}/${chapter.uri.replace(/^wikg:\/\//u, "")}`;
2024
- }
2025
- async function readInspectChapters(document, chapterId) {
2026
- const chapters = chapterId === void 0 ? await listChapters(document) : (await listChapters(document)).filter(
2028
+ function selectChapters(chapters, chapterId) {
2029
+ if (chapterId === void 0) return chapters;
2030
+ const selected = chapters.filter(
2027
2031
  (chapter) => chapter.chapterId === chapterId
2028
2032
  );
2029
- if (chapterId !== void 0 && chapters.length === 0) {
2033
+ if (selected.length === 0) {
2030
2034
  throw new Error(`Chapter ${chapterId} does not exist.`);
2031
2035
  }
2032
- return await Promise.all(
2033
- chapters.map(async (chapter) => {
2034
- const serial = await document.serials.getById(chapter.chapterId);
2035
- return {
2036
- ...chapter,
2037
- knowledgeGraphReady: serial?.knowledgeGraphReady === true,
2038
- readingGraphReady: serial?.topologyReady === true,
2039
- summaryReady: chapter.stage === "summarized"
2040
- };
2041
- })
2042
- );
2036
+ return selected;
2043
2037
  }
2044
- async function readSummaryWords(document, chapterId) {
2045
- return await document.readDatabase(
2046
- async (database) => await database.queryOne(
2047
- `
2048
- SELECT COALESCE(SUM(words_count), 0) AS words
2049
- FROM text_sentence_records
2050
- WHERE kind = 2
2051
- ${chapterId === void 0 ? "" : "AND chapter_id = ?"}
2052
- `,
2053
- chapterId === void 0 ? void 0 : [chapterId],
2054
- (row) => Number(row.words)
2055
- ) ?? 0
2056
- );
2038
+ function byChapterId(coverage) {
2039
+ return new Map(coverage.map((item) => [item.serialId, item]));
2057
2040
  }
2058
- async function readIndexArtifactCoverage(document, kind, chapterId) {
2059
- const coverage = await document.indexArtifacts.listCoverage(kind);
2060
- return chapterId === void 0 ? coverage : coverage.filter((item) => item.serialId === chapterId);
2061
- }
2062
- function filterChaptersByCurrentIndexArtifact(chapters, coverage) {
2063
- const currentChapterIds = new Set(
2064
- coverage.filter((item) => item.current).map((item) => item.serialId)
2065
- );
2066
- return chapters.filter((chapter) => currentChapterIds.has(chapter.chapterId));
2067
- }
2068
- function createInspectCoverage(covered, total) {
2069
- const coveredWords = sumWords(covered);
2070
- const totalWords = sumWords(total);
2041
+ function inspectArtifact(kind, coverage) {
2071
2042
  return {
2072
- coveredChapters: covered.length,
2073
- coveredWords,
2074
- percent: formatPercent(coveredWords, totalWords),
2075
- totalChapters: total.length,
2076
- totalWords
2043
+ current: coverage?.current === true,
2044
+ exists: coverage?.sourceRevision !== void 0,
2045
+ kind,
2046
+ ...coverage?.sourceRevision === void 0 ? {} : { sourceRevision: coverage.sourceRevision }
2077
2047
  };
2078
2048
  }
2079
- function formatRetrievalGuidance(input) {
2080
- if (input.sourceWords === 0 || input.contentChapters.length === 0) {
2081
- return [
2082
- "Source content: empty.",
2083
- "Add source text before using query coverage or graph-based retrieval."
2084
- ];
2085
- }
2086
- const lines = [
2087
- input.queryReady ? `Query: available; local index cache is ${input.indexCacheCurrent ? "current" : "missing or outdated and can be synced from artifacts"}.` : "Query: unavailable until every content chapter has a current FTS or source embedding artifact."
2088
- ];
2089
- lines.push(
2090
- formatObjectSearchGuidance(
2091
- "Reading Graph object retrieval",
2092
- input.readingGraphCovered,
2093
- input.contentChapters
2094
- )
2095
- );
2096
- lines.push(
2097
- formatObjectSearchGuidance(
2098
- "Entity/triple retrieval",
2099
- input.knowledgeGraphCovered,
2100
- input.contentChapters
2049
+ async function readSummaryWords(document) {
2050
+ const rows = await document.readDatabase(
2051
+ async (database) => await database.queryAll(
2052
+ `
2053
+ SELECT chapter_id, COALESCE(SUM(words_count), 0) AS words
2054
+ FROM text_sentence_records
2055
+ WHERE kind = 2
2056
+ GROUP BY chapter_id
2057
+ `,
2058
+ void 0,
2059
+ (row) => ({
2060
+ chapterId: Number(row.chapter_id),
2061
+ words: Number(row.words)
2062
+ })
2101
2063
  )
2102
2064
  );
2103
- return lines;
2104
- }
2105
- function formatObjectSearchGuidance(label, covered, total) {
2106
- const coveredWords = sumWords(covered);
2107
- const totalWords = sumWords(total);
2108
- const ratio = totalWords === 0 ? 0 : coveredWords / totalWords;
2109
- const coverage = formatPercent(coveredWords, totalWords);
2110
- if (ratio >= 1) {
2111
- return `${label}: covers all source content; it can represent the full scope for object retrieval.`;
2112
- }
2113
- if (ratio >= 0.9) {
2114
- return `${label}: covers ${coverage}; use it as the main path, but source --query is needed for uncovered content.`;
2115
- }
2116
- if (ratio >= 0.5) {
2117
- return `${label}: covers ${coverage}; use it as leads, not as a full-scope substitute for source --query.`;
2118
- }
2119
- return `${label}: covers ${coverage}; build missing graph coverage before relying on object retrieval.`;
2120
- }
2121
- function createInspectImprovements(input) {
2122
- const improvements = [];
2123
- if (input.contentChapters.length === 0) {
2124
- improvements.push({
2125
- kind: "add-source",
2126
- recommendation: "No source content is available yet; add or import source text before graph or summary generation.",
2127
- title: "Add source content"
2128
- });
2129
- return improvements;
2130
- }
2131
- if (input.queryBlockedChapters.length > 0) {
2132
- improvements.push({
2133
- kind: "build",
2134
- missingChapters: input.queryBlockedChapters.length,
2135
- missingWords: sumWords(input.queryBlockedChapters),
2136
- recommendation: "Build local FTS artifacts to make this scope queryable. This does not call a provider.",
2137
- task: "index-fts",
2138
- title: "Enable query with local FTS"
2139
- });
2140
- } else if (!input.indexCacheCurrent) {
2141
- improvements.push({
2142
- kind: "sync-index",
2143
- recommendation: "Sync the index cache from chapter index artifacts so query starts without a lazy cache rebuild.",
2144
- title: "Sync index cache"
2145
- });
2146
- }
2147
- improvements.push(
2148
- ...createGraphImprovement({
2149
- concurrent: input.concurrent,
2150
- covered: input.readingGraphCovered,
2151
- planningModel: input.planningModel,
2152
- task: "reading-graph",
2153
- title: "Complete Reading Graph coverage",
2154
- total: input.contentChapters
2155
- })
2156
- );
2157
- improvements.push(
2158
- ...createGraphImprovement({
2159
- concurrent: input.concurrent,
2160
- covered: input.knowledgeGraphCovered,
2161
- planningModel: input.planningModel,
2162
- task: "knowledge-graph",
2163
- title: "Complete Knowledge Graph coverage",
2164
- total: input.contentChapters
2165
- })
2166
- );
2167
- improvements.push(
2168
- ...createGraphImprovement({
2169
- concurrent: input.concurrent,
2170
- covered: input.summaryCovered,
2171
- planningModel: input.planningModel,
2172
- task: "reading-summary",
2173
- title: "Complete Summary coverage",
2174
- total: input.contentChapters
2175
- })
2176
- );
2177
- return improvements;
2178
- }
2179
- function createGraphImprovement(input) {
2180
- const coveredIds = new Set(input.covered.map((chapter) => chapter.chapterId));
2181
- const missing = input.total.filter(
2182
- (chapter) => !coveredIds.has(chapter.chapterId)
2183
- );
2184
- if (missing.length === 0) {
2185
- return [];
2186
- }
2187
- const missingWords = sumWords(missing);
2188
- return [
2189
- {
2190
- kind: "build",
2191
- missingChapters: missing.length,
2192
- missingWords,
2193
- planning: planGenerationTask(
2194
- input.task,
2195
- missingWords,
2196
- missing.length,
2197
- input.concurrent,
2198
- input.planningModel
2199
- ),
2200
- recommendation: formatImprovementRecommendation(
2201
- input.covered,
2202
- input.total,
2203
- missingWords
2204
- ),
2205
- task: input.task,
2206
- title: input.title
2207
- }
2208
- ];
2209
- }
2210
- function formatImprovementRecommendation(covered, total, missingWords) {
2211
- const totalWords = sumWords(total);
2212
- const coveredWords = sumWords(covered);
2213
- if (totalWords === 0) {
2214
- return "No source content is available.";
2215
- }
2216
- if (total.length === 1 || coveredWords / totalWords >= 0.9 || missingWords <= 1e3) {
2217
- return "Queue the full scope to finish the remaining gap.";
2218
- }
2219
- return "Queue selected chapters first if only part of the scope matters.";
2065
+ return new Map(rows.map((row) => [row.chapterId, row.words]));
2220
2066
  }
2221
- function sumWords(chapters) {
2222
- return chapters.reduce((total, chapter) => total + chapter.words, 0);
2067
+ function formatLocatedChapterUri(archiveUri, chapter) {
2068
+ return `${archiveUri.replace(/\/+$/u, "")}/${chapter.uri.replace(/^wikg:\/\//u, "")}`;
2223
2069
  }
2224
- function formatPercent(numerator, denominator) {
2225
- if (denominator === 0) {
2226
- return "n/a";
2070
+
2071
+ // src/archive/write.ts
2072
+ import {
2073
+ WikiGraphArchiveFile,
2074
+ writeWikiGraphLibraryArchive
2075
+ } from "wiki-graph-core";
2076
+ async function writeWikiGraphArchiveLocation(location, operation, options = {}) {
2077
+ const cacheOnly = options.searchIndexWritebackPolicy === "cache";
2078
+ const write = async (archiveFile = location.archiveFile) => await new WikiGraphArchiveFile(archiveFile).write(operation, {
2079
+ ...cacheOnly ? {} : { derivedStateKeys: [location.archiveKey, location.archivePath] },
2080
+ ...options.invalidateContinuationCursors === void 0 ? {} : {
2081
+ invalidateContinuationCursors: options.invalidateContinuationCursors
2082
+ },
2083
+ ...options.searchIndexWritebackPolicy === void 0 ? {} : { searchIndexWritebackPolicy: options.searchIndexWritebackPolicy }
2084
+ });
2085
+ if (location.libraryArchiveTarget === void 0 || cacheOnly || options.refreshLibraryIndex === false) {
2086
+ return await write();
2227
2087
  }
2228
- const percent = numerator / denominator * 100;
2229
- return `${Number.isInteger(percent) ? percent.toFixed(0) : percent.toFixed(1)}%`;
2088
+ return await writeWikiGraphLibraryArchive({
2089
+ additionalDerivedStateKeys: [location.archiveKey, location.archivePath],
2090
+ ...options.invalidateContinuationCursors === void 0 ? {} : {
2091
+ invalidateContinuationCursors: options.invalidateContinuationCursors
2092
+ },
2093
+ ...options.onIndexSyncError === void 0 ? {} : { onIndexSyncError: options.onIndexSyncError },
2094
+ operation: async (archiveFile) => await write(archiveFile),
2095
+ target: location.libraryArchiveTarget
2096
+ });
2230
2097
  }
2231
2098
 
2232
2099
  // src/archive/archive.ts
@@ -2246,13 +2113,13 @@ var WikiGraphArchiveManager = class {
2246
2113
  }
2247
2114
  async create(options) {
2248
2115
  return await this.#runtime.run(async () => {
2249
- const path = resolveWikiGraphRuntimePath(options.path);
2116
+ const path = await assertStandaloneWikiGraphArchivePath(options.path);
2250
2117
  if (options.replace !== true && await nodePathExists(path)) {
2251
2118
  throw new WikiGraphArchiveExistsError(path);
2252
2119
  }
2253
- const outputPath = join3(
2254
- dirname2(path),
2255
- `.${basename3(path)}.${randomUUID2()}.tmp.wikg`
2120
+ const outputPath = join4(
2121
+ dirname3(path),
2122
+ `.${basename4(path)}.${randomUUID2()}.tmp.wikg`
2256
2123
  );
2257
2124
  try {
2258
2125
  if (options.importPath === void 0) {
@@ -2277,15 +2144,15 @@ var WikiGraphArchiveManager = class {
2277
2144
  throw error;
2278
2145
  }
2279
2146
  }
2280
- return { locatedUri: formatLocatedWikiGraphUri(path), path };
2147
+ return { locatedUri: formatLocatedWikiGraphUri2(path), path };
2281
2148
  } finally {
2282
2149
  await rm3(outputPath, { force: true, recursive: true });
2283
2150
  }
2284
2151
  }, options.signal);
2285
2152
  }
2286
- async open(uriOrPath, options = {}) {
2153
+ async open(target, options = {}) {
2287
2154
  const location = await this.#runtime.run(
2288
- async () => await resolveWikiGraphArchiveLocation(uriOrPath),
2155
+ async () => await resolveWikiGraphArchiveLocation(target),
2289
2156
  options.signal
2290
2157
  );
2291
2158
  return new WikiGraphArchiveHandle(this.#runtime, location);
@@ -2308,14 +2175,17 @@ var WikiGraphArchiveHandle = class {
2308
2175
  return this.#location.locatedUri;
2309
2176
  }
2310
2177
  get objectUri() {
2311
- return parseLocatedWikiGraphUri(this.#location.locatedUri).objectUri ?? "wikg://";
2178
+ return parseLocatedWikiGraphUri2(this.#location.locatedUri).objectUri ?? "wikg://";
2312
2179
  }
2313
2180
  get path() {
2314
2181
  return this.#location.archivePath;
2315
2182
  }
2183
+ get target() {
2184
+ return this.#location.target;
2185
+ }
2316
2186
  async inspect(options = {}) {
2317
2187
  return await this.#readDocument(
2318
- async (document) => await createWikiGraphArchiveInspectReport(document, {
2188
+ async (document) => await inspectWikiGraphArchive(document, {
2319
2189
  archiveUri: this.#location.publicArchiveUri ?? this.locatedUri,
2320
2190
  ...options.chapterId === void 0 ? {} : { chapterId: options.chapterId }
2321
2191
  }),
@@ -2323,13 +2193,15 @@ var WikiGraphArchiveHandle = class {
2323
2193
  );
2324
2194
  }
2325
2195
  async search(query, options = {}) {
2326
- const embeddingProvider = await this.#runtime.run(
2327
- createConfiguredEmbeddingProvider,
2196
+ const embeddingProvider = await this.#resolveQueryEmbeddingProvider(
2197
+ options.queryMode,
2328
2198
  options.signal
2329
2199
  );
2330
2200
  return await this.#writeDocument(
2331
2201
  async (document) => {
2332
- const chapters = await this.#resolveQueryChapters(document, options);
2202
+ const chapters = await this.#resolveQueryChapters(document, options, {
2203
+ embeddingProvider
2204
+ });
2333
2205
  await ensureArchiveSearchIndex(document, {
2334
2206
  ...chapters === void 0 ? {} : { chapters },
2335
2207
  ...embeddingProvider === void 0 ? {} : { embeddingProvider }
@@ -2616,7 +2488,7 @@ var WikiGraphArchiveHandle = class {
2616
2488
  objectUri,
2617
2489
  async (wikimediaOptions) => await this.#readDocument(
2618
2490
  async (document) => await readArchivePage(document, objectUri, {
2619
- ...withoutOperation(options),
2491
+ ...options,
2620
2492
  ...wikimediaOptions
2621
2493
  }),
2622
2494
  options
@@ -2627,6 +2499,9 @@ var WikiGraphArchiveHandle = class {
2627
2499
  }
2628
2500
  async related(objectUri = this.objectUri, options = {}) {
2629
2501
  if (options.query === void 0) {
2502
+ if (options.queryMode !== void 0) {
2503
+ throw new Error("`queryMode` requires `query`.");
2504
+ }
2630
2505
  return await this.#readDocument(async (document) => {
2631
2506
  const chapters = await this.#resolveScope(document, {});
2632
2507
  return await listRelatedArchiveObjects(document, objectUri, {
@@ -2635,19 +2510,22 @@ var WikiGraphArchiveHandle = class {
2635
2510
  });
2636
2511
  }, options);
2637
2512
  }
2638
- const embeddingProvider = await this.#runtime.run(
2639
- createConfiguredEmbeddingProvider,
2513
+ const embeddingProvider = await this.#resolveQueryEmbeddingProvider(
2514
+ options.queryMode,
2640
2515
  options.signal
2641
2516
  );
2642
2517
  return await this.#writeDocument(
2643
2518
  async (document) => {
2644
- const chapters = await this.#resolveQueryChapters(document, options);
2519
+ const chapters = await this.#resolveQueryChapters(document, options, {
2520
+ embeddingProvider
2521
+ });
2645
2522
  await ensureArchiveSearchIndex(document, {
2646
2523
  ...chapters === void 0 ? {} : { chapters },
2647
2524
  ...embeddingProvider === void 0 ? {} : { embeddingProvider }
2648
2525
  });
2649
2526
  return await listRelatedArchiveObjects(document, objectUri, {
2650
2527
  ...withoutOperation(options),
2528
+ ...embeddingProvider === void 0 ? {} : { embeddingProvider },
2651
2529
  ...chapters === void 0 ? {} : { chapters }
2652
2530
  });
2653
2531
  },
@@ -2659,6 +2537,9 @@ var WikiGraphArchiveHandle = class {
2659
2537
  }
2660
2538
  async evidence(objectUri = this.objectUri, options = {}) {
2661
2539
  if (options.query === void 0) {
2540
+ if (options.queryMode !== void 0) {
2541
+ throw new Error("`queryMode` requires `query`.");
2542
+ }
2662
2543
  return await this.#readDocument(async (document) => {
2663
2544
  const chapters = await this.#resolveScope(document, {});
2664
2545
  return await listArchiveEvidence(document, objectUri, {
@@ -2667,19 +2548,22 @@ var WikiGraphArchiveHandle = class {
2667
2548
  });
2668
2549
  }, options);
2669
2550
  }
2670
- const embeddingProvider = await this.#runtime.run(
2671
- createConfiguredEmbeddingProvider,
2551
+ const embeddingProvider = await this.#resolveQueryEmbeddingProvider(
2552
+ options.queryMode,
2672
2553
  options.signal
2673
2554
  );
2674
2555
  return await this.#writeDocument(
2675
2556
  async (document) => {
2676
- const chapters = await this.#resolveQueryChapters(document, options);
2557
+ const chapters = await this.#resolveQueryChapters(document, options, {
2558
+ embeddingProvider
2559
+ });
2677
2560
  await ensureArchiveSearchIndex(document, {
2678
2561
  ...chapters === void 0 ? {} : { chapters },
2679
2562
  ...embeddingProvider === void 0 ? {} : { embeddingProvider }
2680
2563
  });
2681
2564
  return await listArchiveEvidence(document, objectUri, {
2682
2565
  ...withoutOperation(options),
2566
+ ...embeddingProvider === void 0 ? {} : { embeddingProvider },
2683
2567
  ...chapters === void 0 ? {} : { chapters }
2684
2568
  });
2685
2569
  },
@@ -2713,6 +2597,24 @@ var WikiGraphArchiveHandle = class {
2713
2597
  return meta;
2714
2598
  }, options);
2715
2599
  }
2600
+ async setArchiveTitle(title, options = {}) {
2601
+ const normalized = title?.trim() ?? null;
2602
+ if (title !== null && normalized === "") {
2603
+ throw new Error("Archive title cannot be empty.");
2604
+ }
2605
+ return await this.#writeDocument(async (document) => {
2606
+ if (normalized === null) {
2607
+ await document.metadata.deleteKey("", "title");
2608
+ } else {
2609
+ await document.metadata.put(
2610
+ { kind: ObjectMetadataKind.Archive, objectPath: "" },
2611
+ "title",
2612
+ normalized
2613
+ );
2614
+ }
2615
+ return normalized;
2616
+ }, options);
2617
+ }
2716
2618
  async readCover(options = {}) {
2717
2619
  const app = new WikiGraph2({});
2718
2620
  return await this.#runtime.run(
@@ -2762,7 +2664,7 @@ var WikiGraphArchiveHandle = class {
2762
2664
  }
2763
2665
  async #readDocument(operation, options = {}) {
2764
2666
  return await this.#runtime.run(
2765
- async () => await new WikiGraphArchiveFile(this.#location.archiveFile).readDocument(
2667
+ async () => await new WikiGraphArchiveFile2(this.#location.archiveFile).readDocument(
2766
2668
  operation
2767
2669
  ),
2768
2670
  options.signal
@@ -2770,28 +2672,33 @@ var WikiGraphArchiveHandle = class {
2770
2672
  }
2771
2673
  async #writeDocument(operation, options = {}) {
2772
2674
  return await this.#runtime.run(async () => {
2773
- const result = await new WikiGraphArchiveFile(
2774
- this.#location.archiveFile
2775
- ).write(operation, {
2675
+ return await writeWikiGraphArchiveLocation(this.#location, operation, {
2676
+ ...options.onIndexSyncError === void 0 ? {} : { onIndexSyncError: options.onIndexSyncError },
2677
+ ...options.refreshLibraryIndex === void 0 ? {} : { refreshLibraryIndex: options.refreshLibraryIndex },
2776
2678
  ...options.searchIndexWritebackPolicy === void 0 ? {} : {
2777
2679
  searchIndexWritebackPolicy: options.searchIndexWritebackPolicy
2778
2680
  }
2779
2681
  });
2780
- if (options.refreshLibraryIndex !== false) {
2781
- await this.#refreshLibraryIndex(options.onIndexSyncError);
2782
- }
2783
- return result;
2784
2682
  }, options.signal);
2785
2683
  }
2786
2684
  async #resolveScope(document, options) {
2787
2685
  if (options.chapters !== void 0) return options.chapters;
2788
2686
  return (await resolveArchiveScope(document, this.objectUri, options.depth))?.chapterIds;
2789
2687
  }
2790
- async #resolveQueryChapters(document, options) {
2688
+ async #resolveQueryChapters(document, options, capabilities) {
2791
2689
  const chapters = await this.#resolveScope(document, options);
2792
- if (options.skipUnindexed !== true) return chapters;
2690
+ const coverageOptions = {
2691
+ ...chapters === void 0 ? {} : { chapters },
2692
+ ...capabilities.embeddingProvider === void 0 ? {} : { embeddingProvider: capabilities.embeddingProvider },
2693
+ requireEmbeddingProvider: true,
2694
+ ...options.queryMode === void 0 ? {} : { queryMode: options.queryMode }
2695
+ };
2696
+ if (options.skipUnindexed !== true) {
2697
+ await assertArchiveIndexArtifactsReady(document, coverageOptions);
2698
+ return chapters;
2699
+ }
2793
2700
  const queryable = await listArchiveQueryableChapterIds(document, {
2794
- ...chapters === void 0 ? {} : { chapters }
2701
+ ...coverageOptions
2795
2702
  });
2796
2703
  if (queryable.length === 0) {
2797
2704
  throw new Error(
@@ -2800,52 +2707,20 @@ var WikiGraphArchiveHandle = class {
2800
2707
  }
2801
2708
  return queryable;
2802
2709
  }
2803
- async #refreshLibraryIndex(onError) {
2804
- if (this.#location.libraryDirtyTarget === void 0) return;
2805
- if (this.#location.libraryArchiveTarget !== void 0) {
2806
- await finalizeWikiGraphLibraryArchiveWrite({
2807
- target: this.#location.libraryArchiveTarget
2808
- });
2809
- }
2810
- try {
2811
- const state = await readWikiGraphLibraryIndexState(
2812
- this.#location.libraryDirtyTarget
2710
+ async #resolveQueryEmbeddingProvider(queryMode, signal) {
2711
+ if (queryMode === "fts") return void 0;
2712
+ const provider = await this.#runtime.run(
2713
+ createConfiguredEmbeddingProvider,
2714
+ signal
2715
+ );
2716
+ if (queryMode === "embedding" && provider === void 0) {
2717
+ throw new Error(
2718
+ "Embedding query mode requires embeddings configuration at `wikg://local/config/embeddings`."
2813
2719
  );
2814
- if (state.status !== "missing") {
2815
- await rebuildWikiGraphLibraryIndex(this.#location.libraryDirtyTarget);
2816
- }
2817
- } catch (error) {
2818
- onError?.(error);
2819
2720
  }
2721
+ return provider;
2820
2722
  }
2821
2723
  };
2822
- async function resolveWikiGraphArchiveLocation(uriOrPath) {
2823
- if (!uriOrPath.startsWith("wikg://")) {
2824
- return createPathLocation(resolveWikiGraphRuntimePath(uriOrPath));
2825
- }
2826
- const parsed = parseLocatedWikiGraphUri(uriOrPath);
2827
- const portableArchiveLocator = parsed.archivePath ?? uriOrPath;
2828
- const archiveLocator = portableArchiveLocator.startsWith("wikg://lib/") ? portableArchiveLocator : resolveWikiGraphRuntimePath(portableArchiveLocator);
2829
- const libraryArchiveTarget = archiveLocator.startsWith("wikg://lib/") ? parseWikiGraphLibraryUri(archiveLocator) : void 0;
2830
- const archiveFile = libraryArchiveTarget?.kind === "archive" ? await resolveWikiGraphLibraryArchiveFile(archiveLocator) : new NodeFile(archiveLocator);
2831
- const archivePath = getNodeResourcePath(archiveFile);
2832
- return {
2833
- archiveFile,
2834
- archiveKey: archivePath,
2835
- archivePath,
2836
- indexScope: { archiveKey: archivePath, archivePath, kind: "archive-index" },
2837
- ...libraryArchiveTarget?.kind === "archive" ? {
2838
- libraryArchiveTarget,
2839
- libraryDirtyTarget: {
2840
- isDefault: libraryArchiveTarget.isDefault,
2841
- kind: "scope",
2842
- ...libraryArchiveTarget.publicId === void 0 ? {} : { publicId: libraryArchiveTarget.publicId }
2843
- },
2844
- publicArchiveUri: portableArchiveLocator
2845
- } : {},
2846
- locatedUri: formatLocatedWikiGraphUri(archivePath, parsed.objectUri)
2847
- };
2848
- }
2849
2724
  async function ensureArchiveSearchIndex(document, options = {}) {
2850
2725
  const scope = options.chapters === void 0 ? {} : { chapters: options.chapters };
2851
2726
  if (await isArchiveSearchIndexCurrent2(document, scope)) return;
@@ -2884,18 +2759,9 @@ function selectChapterSubtree(chapters, rootChapterId, depth) {
2884
2759
  (chapter) => chapter.chapterId === root.chapterId || chapter.path.startsWith(prefix) && (depth === void 0 || chapter.depth - root.depth <= depth)
2885
2760
  );
2886
2761
  }
2887
- function createPathLocation(path) {
2888
- return {
2889
- archiveFile: new NodeFile(path),
2890
- archiveKey: path,
2891
- archivePath: path,
2892
- indexScope: { archiveKey: path, archivePath: path, kind: "archive-index" },
2893
- locatedUri: formatLocatedWikiGraphUri(path)
2894
- };
2895
- }
2896
2762
  async function createEmptyArchiveFile(path) {
2897
2763
  const directoryPath = await mkdtemp(
2898
- join3(tmpdir(), "wikigraph-archive-write-")
2764
+ join4(tmpdir(), "wikigraph-archive-write-")
2899
2765
  );
2900
2766
  try {
2901
2767
  const directory = new NodeDirectory(directoryPath);
@@ -2917,7 +2783,7 @@ function isNodeEEXISTError(error) {
2917
2783
  }
2918
2784
  async function nodePathExists(path) {
2919
2785
  try {
2920
- await stat2(path);
2786
+ await stat3(path);
2921
2787
  return true;
2922
2788
  } catch (error) {
2923
2789
  if (isNodeENOENTError(error)) return false;
@@ -3023,12 +2889,13 @@ async function assertChapterResetAllowed(archive, chapterId, stage) {
3023
2889
  // src/wikispine.ts
3024
2890
  import { spawn } from "child_process";
3025
2891
  var nodeWikispineCommandRunner = {
3026
- run: async ({ args, command, input, onStdout, signal }) => await new Promise((resolve3, reject) => {
2892
+ run: async ({ args, command, input, onStdout, signal }) => await new Promise((resolve4, reject) => {
3027
2893
  signal?.throwIfAborted();
3028
2894
  const child = spawn(command, [...args], {
3029
2895
  stdio: ["pipe", "pipe", "pipe"]
3030
2896
  });
3031
2897
  const stderr = [];
2898
+ let stdoutQueue = Promise.resolve();
3032
2899
  let settled = false;
3033
2900
  const settle = (operation) => {
3034
2901
  if (settled) return;
@@ -3044,14 +2911,15 @@ var nodeWikispineCommandRunner = {
3044
2911
  child.stdout.setEncoding("utf8");
3045
2912
  child.stdout.on("data", (chunk) => {
3046
2913
  if (settled) return;
3047
- try {
3048
- onStdout(chunk);
3049
- } catch (error) {
2914
+ child.stdout.pause();
2915
+ stdoutQueue = stdoutQueue.then(async () => await onStdout(chunk)).then(() => {
2916
+ child.stdout.resume();
2917
+ }).catch((error) => {
3050
2918
  child.kill();
3051
2919
  settle(
3052
2920
  () => reject(error instanceof Error ? error : new Error(String(error)))
3053
2921
  );
3054
- }
2922
+ });
3055
2923
  });
3056
2924
  child.stderr.on("data", (chunk) => stderr.push(chunk));
3057
2925
  child.on("error", (error) => {
@@ -3062,12 +2930,14 @@ var nodeWikispineCommandRunner = {
3062
2930
  );
3063
2931
  });
3064
2932
  child.on("close", (exitCode) => {
3065
- settle(
3066
- () => resolve3({
3067
- exitCode,
3068
- stderr: Buffer.concat(stderr).toString("utf8")
3069
- })
3070
- );
2933
+ void stdoutQueue.then(() => {
2934
+ settle(
2935
+ () => resolve4({
2936
+ exitCode,
2937
+ stderr: Buffer.concat(stderr).toString("utf8")
2938
+ })
2939
+ );
2940
+ });
3071
2941
  });
3072
2942
  child.stdin.end(input);
3073
2943
  })
@@ -3199,7 +3069,7 @@ import {
3199
3069
  listWikiGraphLibraryObjects,
3200
3070
  readContinuationCursor,
3201
3071
  resolveWikiGraphLibraryQueryTargetById,
3202
- WikiGraphArchiveFile as WikiGraphArchiveFile2
3072
+ WikiGraphArchiveFile as WikiGraphArchiveFile3
3203
3073
  } from "wiki-graph-core";
3204
3074
  var WikiGraphContinuationManager = class {
3205
3075
  #runtime;
@@ -3245,10 +3115,11 @@ var WikiGraphContinuationManager = class {
3245
3115
  }
3246
3116
  };
3247
3117
  async function continueArchiveCursor(cursor, limit) {
3118
+ const embeddingProvider = cursor.kind === "evidence" || cursor.kind === "related" ? await resolveCursorEmbeddingProvider(cursor) : void 0;
3248
3119
  const location = await resolveWikiGraphArchiveLocation(
3249
- getCursorArchivePath(cursor)
3120
+ archiveTargetFromLogicalLocator(getCursorArchivePath(cursor))
3250
3121
  );
3251
- return await new WikiGraphArchiveFile2(location.archiveFile).readDocument(
3122
+ return await new WikiGraphArchiveFile3(location.archiveFile).readDocument(
3252
3123
  async (document) => {
3253
3124
  switch (cursor.kind) {
3254
3125
  case "source-locators":
@@ -3274,6 +3145,8 @@ async function continueArchiveCursor(cursor, limit) {
3274
3145
  limit,
3275
3146
  order: cursor.order,
3276
3147
  ...cursor.query === void 0 ? {} : { query: cursor.query },
3148
+ ...cursor.queryMode === void 0 ? {} : { queryMode: cursor.queryMode },
3149
+ ...embeddingProvider === void 0 ? {} : { embeddingProvider },
3277
3150
  ...cursor.skipUnindexed === void 0 ? {} : { skipUnindexed: cursor.skipUnindexed },
3278
3151
  ...cursor.sourceContext === void 0 ? {} : { sourceContext: cursor.sourceContext }
3279
3152
  });
@@ -3285,6 +3158,8 @@ async function continueArchiveCursor(cursor, limit) {
3285
3158
  limit,
3286
3159
  order: cursor.order,
3287
3160
  ...cursor.query === void 0 ? {} : { query: cursor.query },
3161
+ ...cursor.queryMode === void 0 ? {} : { queryMode: cursor.queryMode },
3162
+ ...embeddingProvider === void 0 ? {} : { embeddingProvider },
3288
3163
  ...cursor.role === void 0 ? {} : { role: cursor.role },
3289
3164
  ...cursor.skipUnindexed === void 0 ? {} : { skipUnindexed: cursor.skipUnindexed },
3290
3165
  ...cursor.sourceContext === void 0 ? {} : { sourceContext: cursor.sourceContext }
@@ -3294,6 +3169,7 @@ async function continueArchiveCursor(cursor, limit) {
3294
3169
  );
3295
3170
  }
3296
3171
  async function continueLibraryCursor(cursor, limit) {
3172
+ const embeddingProvider = cursor.kind === "evidence" || cursor.kind === "related" ? await resolveCursorEmbeddingProvider(cursor) : void 0;
3297
3173
  if (cursor.kind === "source-locators") {
3298
3174
  throw new Error(
3299
3175
  "Source locator cursors do not use the aggregate library index."
@@ -3330,6 +3206,8 @@ async function continueLibraryCursor(cursor, limit) {
3330
3206
  limit,
3331
3207
  order: cursor.order,
3332
3208
  ...cursor.query === void 0 ? {} : { query: cursor.query },
3209
+ ...cursor.queryMode === void 0 ? {} : { queryMode: cursor.queryMode },
3210
+ ...embeddingProvider === void 0 ? {} : { embeddingProvider },
3333
3211
  ...cursor.skipUnindexed === void 0 ? {} : { skipUnindexed: cursor.skipUnindexed },
3334
3212
  ...cursor.sourceContext === void 0 ? {} : { sourceContext: cursor.sourceContext }
3335
3213
  });
@@ -3343,6 +3221,8 @@ async function continueLibraryCursor(cursor, limit) {
3343
3221
  limit,
3344
3222
  order: cursor.order,
3345
3223
  ...cursor.query === void 0 ? {} : { query: cursor.query },
3224
+ ...cursor.queryMode === void 0 ? {} : { queryMode: cursor.queryMode },
3225
+ ...embeddingProvider === void 0 ? {} : { embeddingProvider },
3346
3226
  ...cursor.role === void 0 ? {} : { role: cursor.role },
3347
3227
  ...cursor.skipUnindexed === void 0 ? {} : { skipUnindexed: cursor.skipUnindexed },
3348
3228
  ...cursor.sourceContext === void 0 ? {} : { sourceContext: cursor.sourceContext }
@@ -3367,7 +3247,7 @@ function createCollectionOptions(cursor, limit) {
3367
3247
  };
3368
3248
  }
3369
3249
  async function createFindOptions(cursor, limit) {
3370
- const embeddingProvider = await createConfiguredEmbeddingProvider();
3250
+ const embeddingProvider = await resolveCursorEmbeddingProvider(cursor);
3371
3251
  return {
3372
3252
  archiveKey: cursor.archiveKey,
3373
3253
  ...cursor.backlinks === void 0 ? {} : { backlinks: cursor.backlinks },
@@ -3375,6 +3255,7 @@ async function createFindOptions(cursor, limit) {
3375
3255
  cursor: cursor.cursor,
3376
3256
  ...cursor.evidenceLimit === void 0 ? {} : { evidenceLimit: cursor.evidenceLimit },
3377
3257
  limit,
3258
+ ...cursor.queryMode === void 0 ? {} : { queryMode: cursor.queryMode },
3378
3259
  ...cursor.skipUnindexed === void 0 ? {} : { skipUnindexed: cursor.skipUnindexed },
3379
3260
  ...cursor.sourceContext === void 0 ? {} : { sourceContext: cursor.sourceContext },
3380
3261
  ...cursor.triplePattern === void 0 ? {} : { triplePattern: cursor.triplePattern },
@@ -3424,6 +3305,7 @@ function createContinuationPayload(context, cursor) {
3424
3305
  kind: "evidence",
3425
3306
  order: context.order ?? "doc-asc",
3426
3307
  ...context.query === void 0 ? {} : { query: context.query },
3308
+ ...context.queryMode === void 0 ? {} : { queryMode: context.queryMode },
3427
3309
  ...context.skipUnindexed === void 0 ? {} : { skipUnindexed: context.skipUnindexed },
3428
3310
  ...context.sourceContext === void 0 ? {} : { sourceContext: context.sourceContext },
3429
3311
  targetUri: requireTargetUri(context, "Evidence")
@@ -3440,6 +3322,7 @@ function createContinuationPayload(context, cursor) {
3440
3322
  kind: "related",
3441
3323
  order: context.order ?? "doc-asc",
3442
3324
  ...context.query === void 0 ? {} : { query: context.query },
3325
+ ...context.queryMode === void 0 ? {} : { queryMode: context.queryMode },
3443
3326
  ...context.role === void 0 ? {} : { role: context.role },
3444
3327
  ...context.skipUnindexed === void 0 ? {} : { skipUnindexed: context.skipUnindexed },
3445
3328
  ...context.sourceContext === void 0 ? {} : { sourceContext: context.sourceContext },
@@ -3476,6 +3359,7 @@ function createContinuationPayload(context, cursor) {
3476
3359
  kind: "search",
3477
3360
  ...createLibraryQueryPayload(context),
3478
3361
  ...context.query === void 0 ? {} : { query: context.query },
3362
+ ...context.queryMode === void 0 ? {} : { queryMode: context.queryMode },
3479
3363
  ...context.skipUnindexed === void 0 ? {} : { skipUnindexed: context.skipUnindexed },
3480
3364
  ...context.sourceContext === void 0 ? {} : { sourceContext: context.sourceContext },
3481
3365
  ...context.triplePattern === void 0 ? {} : { triplePattern: context.triplePattern },
@@ -3483,6 +3367,17 @@ function createContinuationPayload(context, cursor) {
3483
3367
  };
3484
3368
  }
3485
3369
  }
3370
+ async function resolveCursorEmbeddingProvider(cursor) {
3371
+ if (cursor.kind !== "search" && cursor.query === void 0) return void 0;
3372
+ if (cursor.queryMode === "fts") return void 0;
3373
+ const provider = await createConfiguredEmbeddingProvider();
3374
+ if (cursor.queryMode === "embedding" && provider === void 0) {
3375
+ throw new Error(
3376
+ "Embedding query mode requires embeddings configuration at `wikg://local/config/embeddings`."
3377
+ );
3378
+ }
3379
+ return provider;
3380
+ }
3486
3381
  function requireTargetUri(context, label) {
3487
3382
  if (context.targetUri !== void 0) return context.targetUri;
3488
3383
  throw new Error(`${label} continuation cursors require a target URI.`);
@@ -3503,14 +3398,14 @@ import {
3503
3398
  getChapterDetails,
3504
3399
  openWikimediaResolver as openWikimediaResolver2,
3505
3400
  recordBuildJobInputRevision,
3506
- WikiGraphArchiveFile as WikiGraphArchiveFile4,
3401
+ WikiGraphArchiveFile as WikiGraphArchiveFile5,
3507
3402
  WikiGraphScope,
3508
3403
  withLoggingContext
3509
3404
  } from "wiki-graph-core";
3510
3405
  import {
3511
3406
  applyChapterJobArtifactFile as applyChapterJobArtifactFile3,
3512
3407
  createLocalChapterJobFileExecutor as createLocalChapterJobFileExecutor2,
3513
- writeChapterJobInputFile as writeChapterJobInputFile2
3408
+ writeChapterJobInputFile as writeChapterJobInputFile3
3514
3409
  } from "wiki-graph-core/worker";
3515
3410
 
3516
3411
  // src/stage.ts
@@ -3523,7 +3418,10 @@ import {
3523
3418
  import { createDefaultWikiGraphSampling } from "wiki-graph-core";
3524
3419
  import { LLM } from "wiki-graph-core";
3525
3420
  function createStageLLM(config, options) {
3526
- const llmOptions = buildWikiGraphLLMOptions(config);
3421
+ const llmOptions = options?.provider === void 0 ? buildWikiGraphLLMOptions(config) : {
3422
+ ...config.concurrent?.request === void 0 ? {} : { concurrent: config.concurrent.request },
3423
+ streamProvider: options.provider
3424
+ };
3527
3425
  return new LLM({
3528
3426
  sampling: createDefaultWikiGraphSampling({
3529
3427
  ...llmOptions.temperature === void 0 ? {} : { temperature: llmOptions.temperature },
@@ -3537,10 +3435,13 @@ function createStageLLM(config, options) {
3537
3435
  });
3538
3436
  }
3539
3437
  async function loadRequiredStageConfig(options) {
3438
+ const injected = options.llmJSON === void 0 ? getWikiGraphSDKProviders().llm : void 0;
3540
3439
  const config = await loadWikiGraphRuntimeConfig({
3541
- ...options.llmJSON === void 0 ? {} : { llmJSON: options.llmJSON }
3440
+ ...options.llmJSON === void 0 ? {} : { llmJSON: options.llmJSON },
3441
+ ...options.llmJSON === void 0 && injected !== void 0 ? { skipLLMConfig: true } : {},
3442
+ ...getWikiGraphSDKProviders().embedding === void 0 ? {} : { skipEmbeddingConfig: true }
3542
3443
  });
3543
- if (config.llm?.provider === void 0 || config.llm.model === void 0) {
3444
+ if (injected === void 0 && (config.llm?.provider === void 0 || config.llm.model === void 0)) {
3544
3445
  throw new Error(
3545
3446
  "Missing LLM configuration. Set --llm for one run, or configure `wikg://local/config/llm` with provider and model."
3546
3447
  );
@@ -3548,16 +3449,145 @@ async function loadRequiredStageConfig(options) {
3548
3449
  return config;
3549
3450
  }
3550
3451
 
3452
+ // src/planning.ts
3453
+ var DEFAULT_GENERATION_JOB_CONCURRENCY = 3;
3454
+ var DEFAULT_GENERATION_REQUEST_CONCURRENCY = 6;
3455
+ function planGenerationTask(task, words, chapters, concurrent, model) {
3456
+ const profile = getGenerationPlanningProfile(task);
3457
+ const calls = Math.max(chapters, Math.ceil(words / profile.wordsPerCall));
3458
+ const effectiveConcurrency = Math.max(
3459
+ 1,
3460
+ task === "reading-graph" ? 1 : concurrent.request
3461
+ );
3462
+ const callBatches = Math.ceil(calls / effectiveConcurrency);
3463
+ const wordSeconds = words * profile.secondsPerWord;
3464
+ return {
3465
+ model,
3466
+ timeSeconds: {
3467
+ max: Math.ceil(callBatches * profile.maxSecondsPerCall + wordSeconds),
3468
+ min: Math.ceil(callBatches * profile.minSecondsPerCall + wordSeconds)
3469
+ },
3470
+ tokens: {
3471
+ cacheableInput: Math.ceil(words * profile.cacheableInputTokenPerWord),
3472
+ input: Math.ceil(words * profile.inputTokenPerWord),
3473
+ output: Math.ceil(words * profile.outputTokenPerWord)
3474
+ }
3475
+ };
3476
+ }
3477
+ function createGenerationPerformanceHints(input) {
3478
+ if (!input.hasJobWork) {
3479
+ return [];
3480
+ }
3481
+ const hints = [];
3482
+ const recommendedRequest = input.concurrent.request < 4 ? DEFAULT_GENERATION_REQUEST_CONCURRENCY : input.concurrent.request < 8 ? 8 : void 0;
3483
+ if (input.hasRequestWork && recommendedRequest !== void 0) {
3484
+ hints.push({
3485
+ configKey: "request",
3486
+ configValue: recommendedRequest,
3487
+ current: input.concurrent.request,
3488
+ kind: "request",
3489
+ message: "LLM request concurrency can often be higher. Use at least 4; 6-8 is usually faster when the provider allows it.",
3490
+ recommended: recommendedRequest
3491
+ });
3492
+ }
3493
+ if (input.concurrent.job < 4 && input.chapters > 1) {
3494
+ hints.push({
3495
+ configKey: "job",
3496
+ configValue: 4,
3497
+ current: input.concurrent.job,
3498
+ kind: "job",
3499
+ message: "Multiple chapters need work and job concurrency is below 4. Raising it lets chapter jobs run in parallel.",
3500
+ recommended: 4
3501
+ });
3502
+ }
3503
+ return hints;
3504
+ }
3505
+ function formatGenerationPlanningModel(llm) {
3506
+ if (llm?.model === void 0) {
3507
+ return "not configured";
3508
+ }
3509
+ return llm.provider === void 0 ? llm.model : `${llm.provider}/${llm.model}`;
3510
+ }
3511
+ function formatGenerationPlanningDuration(seconds) {
3512
+ if (seconds < 60) {
3513
+ return `${seconds}s`;
3514
+ }
3515
+ const minutes = Math.round(seconds / 60);
3516
+ if (minutes < 60) {
3517
+ return `${minutes}m`;
3518
+ }
3519
+ return `${Math.round(minutes / 60)}h`;
3520
+ }
3521
+ function getGenerationPlanningProfile(task) {
3522
+ switch (task) {
3523
+ case "index-fts":
3524
+ return {
3525
+ cacheableInputTokenPerWord: 0,
3526
+ inputTokenPerWord: 0,
3527
+ maxSecondsPerCall: 1,
3528
+ minSecondsPerCall: 0,
3529
+ outputTokenPerWord: 0,
3530
+ secondsPerWord: 5e-4,
3531
+ wordsPerCall: 1e5
3532
+ };
3533
+ case "index-embedding-source":
3534
+ case "index-embedding-summary":
3535
+ return {
3536
+ cacheableInputTokenPerWord: 0,
3537
+ inputTokenPerWord: 0,
3538
+ maxSecondsPerCall: 10,
3539
+ minSecondsPerCall: 1,
3540
+ outputTokenPerWord: 0,
3541
+ secondsPerWord: 2e-3,
3542
+ wordsPerCall: 1e4
3543
+ };
3544
+ case "knowledge-graph":
3545
+ return {
3546
+ cacheableInputTokenPerWord: 60,
3547
+ inputTokenPerWord: 80,
3548
+ maxSecondsPerCall: 35,
3549
+ minSecondsPerCall: 15,
3550
+ outputTokenPerWord: 25,
3551
+ secondsPerWord: 0.02,
3552
+ wordsPerCall: 35
3553
+ };
3554
+ case "reading-graph":
3555
+ return {
3556
+ cacheableInputTokenPerWord: 20,
3557
+ inputTokenPerWord: 25,
3558
+ maxSecondsPerCall: 45,
3559
+ minSecondsPerCall: 15,
3560
+ outputTokenPerWord: 4,
3561
+ secondsPerWord: 0.01,
3562
+ wordsPerCall: 160
3563
+ };
3564
+ case "reading-summary":
3565
+ return {
3566
+ cacheableInputTokenPerWord: 45,
3567
+ inputTokenPerWord: 55,
3568
+ maxSecondsPerCall: 25,
3569
+ minSecondsPerCall: 10,
3570
+ outputTokenPerWord: 4,
3571
+ secondsPerWord: 0.01,
3572
+ wordsPerCall: 110
3573
+ };
3574
+ }
3575
+ }
3576
+
3551
3577
  // src/worker.ts
3552
3578
  import {
3553
3579
  applyChapterJobArtifactFile,
3554
- runBuildJobWorker as runCoreBuildJobWorker
3580
+ runBuildJobWorker as runCoreBuildJobWorker,
3581
+ writeChapterJobInputFile
3555
3582
  } from "wiki-graph-core/worker";
3556
- import { WikiGraphArchiveFile as WikiGraphArchiveFile3 } from "wiki-graph-core";
3583
+ import {
3584
+ resolveChapterPathReadonly as resolveChapterPathReadonly2,
3585
+ WikiGraphArchiveFile as WikiGraphArchiveFile4
3586
+ } from "wiki-graph-core";
3557
3587
  import {
3558
3588
  applyChapterJobArtifactFile as applyChapterJobArtifactFile2,
3559
3589
  createLocalChapterJobFileExecutor,
3560
- writeChapterJobInputFile
3590
+ writeChapterJobInputFile as writeChapterJobInputFile2
3561
3591
  } from "wiki-graph-core/worker";
3562
3592
  async function runBuildJobWorker(options) {
3563
3593
  installNodeWikiGraphPlatform();
@@ -3570,7 +3600,11 @@ async function runBuildJobWorker(options) {
3570
3600
 
3571
3601
  // src/default-worker.ts
3572
3602
  async function runWikiGraphQueueWorker(options = {}) {
3573
- const config = await loadWikiGraphRuntimeConfig();
3603
+ const providers = getWikiGraphSDKProviders();
3604
+ const config = await loadWikiGraphRuntimeConfig({
3605
+ ...providers.embedding === void 0 ? {} : { skipEmbeddingConfig: true },
3606
+ ...providers.llm === void 0 ? {} : { skipLLMConfig: true }
3607
+ });
3574
3608
  await runBuildJobWorker({
3575
3609
  concurrency: config.concurrent?.job ?? DEFAULT_GENERATION_JOB_CONCURRENCY,
3576
3610
  executeJob: async (job, reporter, context) => {
@@ -3579,12 +3613,16 @@ async function runWikiGraphQueueWorker(options = {}) {
3579
3613
  async () => await executeBuildJob(job, reporter, context)
3580
3614
  );
3581
3615
  },
3616
+ ...options.idleTimeoutMs === void 0 ? {} : { idleTimeoutMs: options.idleTimeoutMs },
3582
3617
  ...options.signal === void 0 ? {} : { signal: options.signal }
3583
3618
  });
3584
3619
  }
3585
3620
  async function executeBuildJob(job, reporter, context) {
3621
+ const providers = getWikiGraphSDKProviders();
3586
3622
  const config = await loadWikiGraphRuntimeConfig({
3587
- ...job.llmJSON === void 0 ? {} : { llmJSON: job.llmJSON }
3623
+ ...job.llmJSON === void 0 ? {} : { llmJSON: job.llmJSON },
3624
+ ...providers.embedding === void 0 ? {} : { skipEmbeddingConfig: true },
3625
+ ...job.llmJSON === void 0 && providers.llm !== void 0 ? { skipLLMConfig: true } : {}
3588
3626
  });
3589
3627
  const execution = await openJobExecutor(
3590
3628
  job,
@@ -3646,10 +3684,10 @@ async function executeStep(job, kind, execution, reporter, context, inputOptions
3646
3684
  const stepWorkspace = await resetStepWorkspace(job.workspace, kind);
3647
3685
  const inputFile = await stepWorkspace.createFile("input.jsonl");
3648
3686
  const outputWorkspace = await stepWorkspace.createDirectory("output");
3649
- const revision = await new WikiGraphArchiveFile4(job.archive).readDocument(
3687
+ const revision = await new WikiGraphArchiveFile5(job.archive).readDocument(
3650
3688
  async (document) => {
3651
3689
  await getChapterDetails(document, job.chapterId);
3652
- return await writeChapterJobInputFile2(
3690
+ return await writeChapterJobInputFile3(
3653
3691
  document,
3654
3692
  job.chapterId,
3655
3693
  kind,
@@ -3688,16 +3726,23 @@ async function executeStep(job, kind, execution, reporter, context, inputOptions
3688
3726
  total: 1,
3689
3727
  unit: "item"
3690
3728
  });
3691
- await new WikiGraphArchiveFile4(job.archive).write(async (document) => {
3692
- assertJobStillRunning(await getBuildJob(job.jobId));
3693
- await applyChapterJobArtifactFile3(
3694
- document,
3695
- job.chapterId,
3696
- kind,
3697
- revision,
3698
- result.artifactFile
3699
- );
3700
- });
3729
+ const target = await resolveWikiGraphArchiveTarget(job.archive);
3730
+ const resolvedLocation = await resolveWikiGraphArchiveLocation(target);
3731
+ const location = target.kind === "standalone" ? { ...resolvedLocation, archiveFile: job.archive } : resolvedLocation;
3732
+ await writeWikiGraphArchiveLocation(
3733
+ location,
3734
+ async (document) => {
3735
+ assertJobStillRunning(await getBuildJob(job.jobId));
3736
+ await applyChapterJobArtifactFile3(
3737
+ document,
3738
+ job.chapterId,
3739
+ kind,
3740
+ revision,
3741
+ result.artifactFile
3742
+ );
3743
+ },
3744
+ { invalidateContinuationCursors: true }
3745
+ );
3701
3746
  await reporter.updatePhase({
3702
3747
  done: 1,
3703
3748
  phase: "committing",
@@ -3712,12 +3757,17 @@ async function openJobExecutor(job, config, signal, reporter) {
3712
3757
  const stageConfig = generation ? await loadRequiredStageConfig({
3713
3758
  ...job.llmJSON === void 0 ? {} : { llmJSON: job.llmJSON }
3714
3759
  }) : void 0;
3760
+ const injectedLLM = job.llmJSON === void 0 ? getWikiGraphSDKProviders().llm : void 0;
3715
3761
  const llm = stageConfig === void 0 ? void 0 : createStageLLM(stageConfig, {
3716
3762
  cacheDirectory: job.cache,
3717
3763
  logDirectory: job.log,
3718
3764
  onTokenUsage: async (usage) => {
3719
3765
  await reporter.addTokenUsage(usage);
3720
- }
3766
+ },
3767
+ onStreamProgress: async ({ outputCharacters }) => {
3768
+ await reporter.addOutputCharacters(outputCharacters);
3769
+ },
3770
+ ...injectedLLM === void 0 ? {} : { provider: injectedLLM }
3721
3771
  });
3722
3772
  const promptSource = job.prompt ?? stageConfig?.prompt;
3723
3773
  const wikispine = job.target === "knowledge-graph" ? requireKnowledgeGraphWikispineConfig(config) : void 0;
@@ -3736,6 +3786,10 @@ async function openJobExecutor(job, config, signal, reporter) {
3736
3786
  llmRequest: requireValue(
3737
3787
  request,
3738
3788
  "Local Wikimedia resolution requires an LLM."
3789
+ ),
3790
+ llmModelId: requireValue(
3791
+ stageConfig?.llm?.model ?? injectedLLM?.model,
3792
+ "Local Wikimedia resolution requires an LLM model."
3739
3793
  )
3740
3794
  } : {
3741
3795
  endpoint: config.wikimedia.endpoint,
@@ -3743,7 +3797,7 @@ async function openJobExecutor(job, config, signal, reporter) {
3743
3797
  token: config.wikimedia.token
3744
3798
  }
3745
3799
  );
3746
- const embeddingProvider = job.target === "index-embedding-source" || job.target === "index-embedding-summary" ? buildSearchIndexEmbeddingProvider(requireEmbeddingConfig(config)) : void 0;
3800
+ const embeddingProvider = job.target === "index-embedding-source" || job.target === "index-embedding-summary" ? getWikiGraphSDKProviders().embedding ?? buildSearchIndexEmbeddingProvider(requireEmbeddingConfig(config)) : void 0;
3747
3801
  return {
3748
3802
  async close() {
3749
3803
  await wikimediaResolver?.close();
@@ -3773,12 +3827,12 @@ async function resetStepWorkspace(workspace, kind) {
3773
3827
  return await workspace.createDirectory(name);
3774
3828
  }
3775
3829
  async function readChapterStage(job) {
3776
- return await new WikiGraphArchiveFile4(job.archive).readDocument(
3830
+ return await new WikiGraphArchiveFile5(job.archive).readDocument(
3777
3831
  async (document) => (await getChapterDetails(document, job.chapterId)).stage
3778
3832
  );
3779
3833
  }
3780
3834
  async function assertCurrentFtsArtifact(job) {
3781
- await new WikiGraphArchiveFile4(job.archive).readDocument(async (document) => {
3835
+ await new WikiGraphArchiveFile5(job.archive).readDocument(async (document) => {
3782
3836
  const revision = await document.serials.getRevision(job.chapterId);
3783
3837
  const artifact = await document.indexArtifacts.get(job.chapterId, "fts");
3784
3838
  if (artifact?.sourceRevision !== revision) {
@@ -3882,7 +3936,7 @@ import {
3882
3936
  boostBuildJob,
3883
3937
  cancelBuildJob,
3884
3938
  cleanBuildJobs,
3885
- formatLocatedChapterUri,
3939
+ formatLocatedChapterUri as formatLocatedChapterUri2,
3886
3940
  getBuildJob as getBuildJob2,
3887
3941
  listBuildJobs,
3888
3942
  listChapters as listChapters3,
@@ -3891,8 +3945,9 @@ import {
3891
3945
  resolveBuildJobId,
3892
3946
  resumeBuildJob,
3893
3947
  updateBuildJobTarget,
3894
- resolveChapterPathReadonly as resolveChapterPathReadonly2,
3895
- WikiGraphArchiveFile as WikiGraphArchiveFile5
3948
+ withArchiveBuildJobCreationLock,
3949
+ resolveChapterPathReadonly as resolveChapterPathReadonly3,
3950
+ WikiGraphArchiveFile as WikiGraphArchiveFile6
3896
3951
  } from "wiki-graph-core";
3897
3952
  var TERMINAL_STATES = /* @__PURE__ */ new Set(["canceled", "failed", "succeeded"]);
3898
3953
  var TERMINAL_EVENT_GRACE_READS = 3;
@@ -3937,20 +3992,30 @@ var WikiGraphJobManager = class {
3937
3992
  this.#backend = backend;
3938
3993
  }
3939
3994
  async create(options) {
3940
- const job = await this.#runtime.run(
3941
- async () => await this.#backend.add({
3942
- ...options,
3943
- archive: typeof options.archive === "string" ? new NodeFile(resolveWikiGraphRuntimePath(options.archive)) : options.archive
3944
- })
3945
- );
3946
- return this.#createHandle(job);
3995
+ const resolved = await this.#runtime.run(async () => {
3996
+ const location = await resolveWikiGraphArchiveLocation(options.archive);
3997
+ return {
3998
+ job: await this.#backend.add({
3999
+ ...options,
4000
+ archive: location.archiveFile
4001
+ }),
4002
+ target: location.target
4003
+ };
4004
+ });
4005
+ return await this.#createHandle(resolved.job, resolved.target);
3947
4006
  }
3948
4007
  async clean() {
3949
4008
  return await this.#runtime.run(async () => await cleanBuildJobs());
3950
4009
  }
4010
+ async runWorker(options = {}) {
4011
+ await this.#runtime.run(
4012
+ async () => await runWikiGraphQueueWorker(options),
4013
+ options.signal
4014
+ );
4015
+ }
3951
4016
  async get(jobId) {
3952
- return this.#createHandle(
3953
- await this.#runtime.run(async () => await this.#backend.get(jobId))
4017
+ return await this.#runtime.run(
4018
+ async () => await this.#createHandle(await this.#backend.get(jobId))
3954
4019
  );
3955
4020
  }
3956
4021
  async resolveId(reference) {
@@ -3959,23 +4024,25 @@ var WikiGraphJobManager = class {
3959
4024
  );
3960
4025
  }
3961
4026
  async list(options = {}) {
3962
- const jobs = await this.#runtime.run(async () => {
4027
+ return await this.#runtime.run(async () => {
3963
4028
  const normalized = {
3964
4029
  ...options.activeOnly === void 0 ? {} : { activeOnly: options.activeOnly },
3965
4030
  ...options.all === void 0 ? {} : { all: options.all },
3966
4031
  ...options.archive === void 0 ? {} : {
3967
- archive: typeof options.archive === "string" ? new NodeFile(resolveWikiGraphRuntimePath(options.archive)) : options.archive
4032
+ archive: (await resolveWikiGraphArchiveLocation(options.archive)).archiveFile
3968
4033
  }
3969
4034
  };
3970
- return await this.#backend.list(normalized);
4035
+ const jobs = await this.#backend.list(normalized);
4036
+ return await Promise.all(
4037
+ jobs.map(async (job) => await this.#createHandle(job))
4038
+ );
3971
4039
  });
3972
- return jobs.map((job) => this.#createHandle(job));
3973
4040
  }
3974
4041
  async resolveChapters(jobs) {
3975
4042
  return await this.#runtime.run(async () => {
3976
4043
  const jobsByArchive = /* @__PURE__ */ new Map();
3977
4044
  for (const job of jobs) {
3978
- const archivePath = getBuildJobArchivePath(job);
4045
+ const archivePath = getJobArchiveLocator(job);
3979
4046
  const grouped = jobsByArchive.get(archivePath) ?? [];
3980
4047
  grouped.push(job);
3981
4048
  jobsByArchive.set(archivePath, grouped);
@@ -3983,8 +4050,11 @@ var WikiGraphJobManager = class {
3983
4050
  const entries = (await Promise.all(
3984
4051
  [...jobsByArchive].map(async ([archivePath, archiveJobs]) => {
3985
4052
  try {
3986
- const chapters = await new WikiGraphArchiveFile5(
3987
- new NodeFile(archivePath)
4053
+ const location = await resolveWikiGraphArchiveLocation(
4054
+ archiveJobs[0].archive
4055
+ );
4056
+ const chapters = await new WikiGraphArchiveFile6(
4057
+ location.archiveFile
3988
4058
  ).readDocument(async (document) => await listChapters3(document));
3989
4059
  const chaptersById = new Map(
3990
4060
  chapters.map((chapter) => [chapter.chapterId, chapter])
@@ -3995,7 +4065,7 @@ var WikiGraphJobManager = class {
3995
4065
  [
3996
4066
  job.jobId,
3997
4067
  {
3998
- locatedUri: formatLocatedChapterUri(
4068
+ locatedUri: formatLocatedChapterUri2(
3999
4069
  archivePath,
4000
4070
  chapter.path
4001
4071
  ),
@@ -4018,72 +4088,90 @@ var WikiGraphJobManager = class {
4018
4088
  }
4019
4089
  async enqueue(options) {
4020
4090
  return await this.#runtime.run(async () => {
4091
+ const llmJSON = resolveWikiGraphLLMJSON(options);
4021
4092
  const location = await resolveWikiGraphArchiveLocation(options.archive);
4022
- const target = options.target ?? "reading-summary";
4023
- await validateQueueTargetConfig(target, options.llmJSON);
4024
- const selectedExplicitly = options.chapterId !== void 0 || options.chapterIds !== void 0 || options.chapterPath !== void 0 || options.depth !== void 0;
4025
- const candidates = await new WikiGraphArchiveFile5(
4026
- location.archiveFile
4027
- ).readDocument(async (document) => {
4028
- const chapters = await listChapters3(document);
4029
- const selected = await selectQueueChapters(document, chapters, options);
4030
- const checked = await Promise.all(
4031
- selected.map(async (chapter) => ({
4032
- chapter,
4033
- reason: await readQueueReadinessReason(document, chapter, target)
4034
- }))
4035
- );
4036
- return checked;
4037
- });
4038
- const created = [];
4039
- const skipped = [];
4040
- for (const candidate of candidates) {
4041
- if (candidate.reason !== void 0) {
4042
- if (selectedExplicitly && candidates.length === 1) {
4043
- throw new Error(
4044
- formatQueueReadinessError(
4045
- candidate.chapter,
4046
- target,
4047
- candidate.reason
4048
- )
4093
+ return await withArchiveBuildJobCreationLock(
4094
+ location.archiveFile,
4095
+ async () => {
4096
+ const target = options.target ?? "reading-summary";
4097
+ await validateQueueTargetConfig(target, llmJSON);
4098
+ const selectedExplicitly = options.chapterId !== void 0 || options.chapterIds !== void 0 || options.chapterPath !== void 0 || options.depth !== void 0;
4099
+ const candidates = await new WikiGraphArchiveFile6(
4100
+ location.archiveFile
4101
+ ).readDocument(async (document) => {
4102
+ const chapters = await listChapters3(document);
4103
+ const selected = await selectQueueChapters(
4104
+ document,
4105
+ chapters,
4106
+ options
4049
4107
  );
4050
- }
4051
- skipped.push({
4052
- chapter: candidate.chapter,
4053
- reason: candidate.reason
4054
- });
4055
- continue;
4056
- }
4057
- try {
4058
- created.push({
4059
- chapter: candidate.chapter,
4060
- job: await this.create({
4061
- archive: location.archiveFile,
4062
- boost: options.boost ?? false,
4063
- chapterId: candidate.chapter.chapterId,
4064
- ...options.llmJSON === void 0 ? {} : { llmJSON: options.llmJSON },
4065
- ...options.prompt === void 0 ? {} : { prompt: options.prompt },
4066
- target
4067
- })
4068
- });
4069
- } catch (error) {
4070
- if (selectedExplicitly && candidates.length === 1) throw error;
4071
- skipped.push({
4072
- chapter: candidate.chapter,
4073
- reason: error instanceof Error ? error.message : String(error)
4108
+ const checked = await Promise.all(
4109
+ selected.map(async (chapter) => ({
4110
+ chapter,
4111
+ reason: await readQueueReadinessReason(
4112
+ document,
4113
+ chapter,
4114
+ target
4115
+ )
4116
+ }))
4117
+ );
4118
+ return checked;
4074
4119
  });
4120
+ const created = [];
4121
+ const skipped = [];
4122
+ for (const candidate of candidates) {
4123
+ if (candidate.reason !== void 0) {
4124
+ if (selectedExplicitly && candidates.length === 1) {
4125
+ throw new Error(
4126
+ formatQueueReadinessError(
4127
+ candidate.chapter,
4128
+ target,
4129
+ candidate.reason
4130
+ )
4131
+ );
4132
+ }
4133
+ skipped.push({
4134
+ chapter: candidate.chapter,
4135
+ reason: candidate.reason
4136
+ });
4137
+ continue;
4138
+ }
4139
+ try {
4140
+ created.push({
4141
+ chapter: candidate.chapter,
4142
+ job: await this.#createHandle(
4143
+ await this.#backend.add({
4144
+ archive: location.archiveFile,
4145
+ boost: options.boost ?? false,
4146
+ chapterId: candidate.chapter.chapterId,
4147
+ ...llmJSON === void 0 ? {} : { llmJSON },
4148
+ ...options.prompt === void 0 ? {} : { prompt: options.prompt },
4149
+ target
4150
+ }),
4151
+ location.target
4152
+ )
4153
+ });
4154
+ } catch (error) {
4155
+ if (selectedExplicitly && candidates.length === 1) throw error;
4156
+ skipped.push({
4157
+ chapter: candidate.chapter,
4158
+ reason: error instanceof Error ? error.message : String(error)
4159
+ });
4160
+ }
4161
+ }
4162
+ return { created, skipped };
4075
4163
  }
4076
- }
4077
- return { created, skipped };
4164
+ );
4078
4165
  });
4079
4166
  }
4080
4167
  async planEnqueue(options) {
4081
4168
  return await this.#runtime.run(async () => {
4169
+ const llmJSON = resolveWikiGraphLLMJSON(options);
4082
4170
  const location = await resolveWikiGraphArchiveLocation(options.archive);
4083
4171
  const target = options.target ?? "reading-summary";
4084
- await validateQueueTargetConfig(target, options.llmJSON);
4172
+ await validateQueueTargetConfig(target, llmJSON);
4085
4173
  const selectedExplicitly = options.chapterId !== void 0 || options.chapterIds !== void 0 || options.chapterPath !== void 0 || options.depth !== void 0;
4086
- const candidates = await new WikiGraphArchiveFile5(
4174
+ const candidates = await new WikiGraphArchiveFile6(
4087
4175
  location.archiveFile
4088
4176
  ).readDocument(async (document) => {
4089
4177
  const chapters = await listChapters3(document);
@@ -4120,34 +4208,39 @@ var WikiGraphJobManager = class {
4120
4208
  this.#subscriptions.add(controller);
4121
4209
  return () => this.#subscriptions.delete(controller);
4122
4210
  }
4123
- #createHandle(snapshot) {
4124
- return new WikiGraphJob(this, this.#runtime, this.#backend, snapshot);
4211
+ async #createHandle(snapshot, target) {
4212
+ const legacy = snapshot;
4213
+ const resolvedTarget = target ?? (snapshot.archive === void 0 ? archiveTargetFromLogicalLocator(legacy.archivePath ?? "unknown.wikg") : await resolveWikiGraphArchiveTarget(snapshot.archive));
4214
+ return new WikiGraphJob(
4215
+ this,
4216
+ this.#runtime,
4217
+ this.#backend,
4218
+ snapshot,
4219
+ cloneWikiGraphArchiveTarget(resolvedTarget)
4220
+ );
4125
4221
  }
4126
4222
  };
4127
- function getBuildJobArchivePath(job) {
4128
- const record = job;
4129
- if (record.archive !== void 0) {
4130
- return getNodeResourcePath(record.archive);
4131
- }
4132
- if (typeof record.archivePath === "string") return record.archivePath;
4133
- throw new TypeError("Build job is missing archive");
4223
+ function getJobArchiveLocator(job) {
4224
+ return job.archive.kind === "library" ? job.archive.uri : job.archive.path;
4134
4225
  }
4135
4226
  var WikiGraphJob = class {
4136
4227
  #manager;
4137
4228
  #runtime;
4138
4229
  #backend;
4230
+ #archiveTarget;
4139
4231
  #snapshot;
4140
- constructor(manager, runtime, backend, snapshot) {
4232
+ constructor(manager, runtime, backend, snapshot, archiveTarget) {
4141
4233
  this.#manager = manager;
4142
4234
  this.#runtime = runtime;
4143
4235
  this.#backend = backend;
4144
4236
  this.#snapshot = snapshot;
4237
+ this.#archiveTarget = archiveTarget;
4145
4238
  }
4146
4239
  get id() {
4147
4240
  return this.#snapshot.jobId;
4148
4241
  }
4149
4242
  get snapshot() {
4150
- return this.#snapshot;
4243
+ return toPublicJobSnapshot(this.#snapshot, this.#archiveTarget);
4151
4244
  }
4152
4245
  async status() {
4153
4246
  return await this.#update(async () => await this.#backend.get(this.id));
@@ -4174,7 +4267,8 @@ var WikiGraphJob = class {
4174
4267
  let cursor = 0;
4175
4268
  let job = this.#snapshot;
4176
4269
  if (options.from === "now") {
4177
- job = await this.status();
4270
+ await this.status();
4271
+ job = this.#snapshot;
4178
4272
  const chunk = await this.#readEventChunkSafely(job, cursor);
4179
4273
  const events = chunk.events;
4180
4274
  cursor = chunk.cursor;
@@ -4194,7 +4288,8 @@ var WikiGraphJob = class {
4194
4288
  yield event;
4195
4289
  }
4196
4290
  if (sawTerminalEvent) return;
4197
- job = await this.status();
4291
+ await this.status();
4292
+ job = this.#snapshot;
4198
4293
  if (isTerminalState(job.state)) {
4199
4294
  terminalReadsWithoutEvent += 1;
4200
4295
  if (terminalReadsWithoutEvent >= TERMINAL_EVENT_GRACE_READS) return;
@@ -4231,7 +4326,7 @@ var WikiGraphJob = class {
4231
4326
  }
4232
4327
  async #update(operation) {
4233
4328
  this.#snapshot = await this.#runtime.run(operation);
4234
- return this.#snapshot;
4329
+ return this.snapshot;
4235
4330
  }
4236
4331
  async #readEventChunk(job, cursor) {
4237
4332
  return await this.#runtime.run(async () => {
@@ -4250,6 +4345,54 @@ var WikiGraphJob = class {
4250
4345
  }
4251
4346
  }
4252
4347
  };
4348
+ function toPublicJobSnapshot(job, archive) {
4349
+ const legacy = job;
4350
+ return {
4351
+ archive: cloneWikiGraphArchiveTarget(archive),
4352
+ archiveKey: archive.kind === "library" ? archive.uri : job.archiveKey,
4353
+ ...getJobResourcePath(job.cache, legacy.cachePath) === void 0 ? {} : { cachePath: getJobResourcePath(job.cache, legacy.cachePath) },
4354
+ chapterId: job.chapterId,
4355
+ createdAt: job.createdAt,
4356
+ ...job.currentStep === void 0 ? {} : { currentStep: job.currentStep },
4357
+ ...job.errorJSON === void 0 ? {} : { errorJSON: job.errorJSON },
4358
+ ...getJobResourcePath(job.events, legacy.eventsPath) === void 0 ? {} : { eventsPath: getJobResourcePath(job.events, legacy.eventsPath) },
4359
+ ...job.finishedAt === void 0 ? {} : { finishedAt: job.finishedAt },
4360
+ jobId: job.jobId,
4361
+ ...job.inputRevision === void 0 ? {} : { inputRevision: job.inputRevision },
4362
+ ...getJobResourcePath(job.log, legacy.logPath) === void 0 ? {} : { logPath: getJobResourcePath(job.log, legacy.logPath) },
4363
+ ...job.llmJSON === void 0 ? {} : { llmJSON: job.llmJSON },
4364
+ ...job.ownerId === void 0 ? {} : { ownerId: job.ownerId },
4365
+ ...job.prompt === void 0 ? {} : { prompt: job.prompt },
4366
+ queueRank: job.queueRank,
4367
+ ...job.readingSummaryStartedAt === void 0 ? {} : { readingSummaryStartedAt: job.readingSummaryStartedAt },
4368
+ state: job.state,
4369
+ target: job.target,
4370
+ updatedAt: job.updatedAt,
4371
+ ...getJobResourcePath(job.workspace, legacy.workspacePath) === void 0 ? {} : {
4372
+ workspacePath: getJobResourcePath(
4373
+ job.workspace,
4374
+ legacy.workspacePath
4375
+ )
4376
+ }
4377
+ };
4378
+ }
4379
+ function cloneWikiGraphArchiveTarget(target) {
4380
+ return target.kind === "library" ? Object.freeze({ kind: "library", uri: target.uri }) : Object.freeze({
4381
+ kind: "standalone",
4382
+ path: target.path,
4383
+ ...target.objectUri === void 0 ? {} : { objectUri: target.objectUri }
4384
+ });
4385
+ }
4386
+ function getJobResourcePath(resource, legacy) {
4387
+ if (resource === void 0) return legacy;
4388
+ try {
4389
+ return getNodeResourcePath(resource);
4390
+ } catch {
4391
+ const identity = resource.identity;
4392
+ if (typeof identity === "string") return identity;
4393
+ throw new TypeError("Expected a Node File or Directory resource");
4394
+ }
4395
+ }
4253
4396
  async function selectQueueChapters(document, chapters, options) {
4254
4397
  const ids = options.chapterIds ?? (options.chapterId === void 0 ? void 0 : [options.chapterId]);
4255
4398
  if (ids !== void 0) {
@@ -4260,7 +4403,7 @@ async function selectQueueChapters(document, chapters, options) {
4260
4403
  if (options.chapterPath === void 0) {
4261
4404
  return options.depth === void 0 ? chapters : chapters.filter((chapter) => chapter.depth <= options.depth);
4262
4405
  }
4263
- const rootId = await resolveChapterPathReadonly2(
4406
+ const rootId = await resolveChapterPathReadonly3(
4264
4407
  document,
4265
4408
  options.chapterPath
4266
4409
  );
@@ -4271,12 +4414,15 @@ async function selectQueueChapters(document, chapters, options) {
4271
4414
  );
4272
4415
  }
4273
4416
  async function validateQueueTargetConfig(target, llmJSON) {
4417
+ const providers = getWikiGraphSDKProviders();
4274
4418
  const config = target === "knowledge-graph" || target === "reading-graph" || target === "reading-summary" ? await loadRequiredStageConfig({
4275
4419
  ...llmJSON === void 0 ? {} : { llmJSON }
4276
4420
  }) : await loadWikiGraphRuntimeConfig({
4277
- ...llmJSON === void 0 ? {} : { llmJSON }
4421
+ ...llmJSON === void 0 ? {} : { llmJSON },
4422
+ ...providers.embedding === void 0 ? {} : { skipEmbeddingConfig: true },
4423
+ ...llmJSON === void 0 && providers.llm !== void 0 ? { skipLLMConfig: true } : {}
4278
4424
  });
4279
- if ((target === "index-embedding-source" || target === "index-embedding-summary") && config.embedding === void 0) {
4425
+ if ((target === "index-embedding-source" || target === "index-embedding-summary") && config.embedding === void 0 && providers.embedding === void 0) {
4280
4426
  throw new Error(
4281
4427
  "Missing embeddings configuration. Configure `wikg://local/config/embeddings` before queueing embedding index artifact jobs."
4282
4428
  );
@@ -4325,14 +4471,14 @@ function formatQueueReadinessError(chapter, target, reason) {
4325
4471
  }
4326
4472
  async function wait(milliseconds, signal) {
4327
4473
  if (signal?.aborted === true) return;
4328
- await new Promise((resolve3) => {
4474
+ await new Promise((resolve4) => {
4329
4475
  let settled = false;
4330
4476
  const complete = () => {
4331
4477
  if (settled) return;
4332
4478
  settled = true;
4333
4479
  clearTimeout(timeout);
4334
4480
  signal?.removeEventListener("abort", complete);
4335
- resolve3();
4481
+ resolve4();
4336
4482
  };
4337
4483
  const timeout = setTimeout(complete, milliseconds);
4338
4484
  signal?.addEventListener("abort", complete, { once: true });
@@ -4363,12 +4509,12 @@ import {
4363
4509
  deleteWikiGraphLibraryMetadataKey,
4364
4510
  findWikiGraphLibraryObjects as findWikiGraphLibraryObjects2,
4365
4511
  findWikiGraphLibraryArchiveMembers as findWikiGraphLibraryArchiveMembers2,
4366
- formatWikiGraphLibraryUri,
4512
+ formatWikiGraphLibraryUri as formatWikiGraphLibraryUri2,
4367
4513
  getWikiGraphLibraryArchive,
4368
4514
  getWikiGraphLibraryMetadata,
4369
4515
  listRelatedWikiGraphLibraryObjects as listRelatedWikiGraphLibraryObjects2,
4370
- listWikiGraphLibraries,
4371
- listWikiGraphLibraryArchives,
4516
+ listWikiGraphLibraries as listWikiGraphLibraries2,
4517
+ listWikiGraphLibraryArchives as listWikiGraphLibraryArchives2,
4372
4518
  listWikiGraphLibraryArchiveMembers as listWikiGraphLibraryArchiveMembers2,
4373
4519
  listWikiGraphLibraryEvidence as listWikiGraphLibraryEvidence2,
4374
4520
  listWikiGraphLibraryObjects as listWikiGraphLibraryObjects2,
@@ -4376,17 +4522,29 @@ import {
4376
4522
  packWikiGraphLibraryContext,
4377
4523
  parseWikiGraphLibraryUri as parseWikiGraphLibraryUri2,
4378
4524
  putWikiGraphLibraryMetadata,
4379
- readWikiGraphLibraryIndexState as readWikiGraphLibraryIndexState2,
4525
+ readWikiGraphLibraryIndexState,
4380
4526
  readWikiGraphLibraryPage,
4381
- rebuildWikiGraphLibraryIndex as rebuildWikiGraphLibraryIndex2,
4527
+ rebuildWikiGraphLibraryIndex,
4382
4528
  rebindWikiGraphLibrary,
4383
4529
  removeWikiGraphLibrary,
4384
4530
  removeWikiGraphLibraryArchive,
4531
+ replaceWikiGraphLibraryArchive,
4385
4532
  replaceWikiGraphLibraryMetadata,
4386
- resolveWikiGraphLibrary,
4387
- scanWikiGraphLibrary
4533
+ resolveWikiGraphLibrary as resolveWikiGraphLibrary2,
4534
+ scanWikiGraphLibrary,
4535
+ withWikiGraphLibraryLock
4388
4536
  } from "wiki-graph-core";
4389
4537
  import { mkdir as mkdir2 } from "fs/promises";
4538
+ async function resolveQueryEmbeddingProvider(queryMode) {
4539
+ if (queryMode === "fts") return void 0;
4540
+ const provider = await createConfiguredEmbeddingProvider();
4541
+ if (queryMode === "embedding" && provider === void 0) {
4542
+ throw new Error(
4543
+ "Embedding query mode requires embeddings configuration at `wikg://local/config/embeddings`."
4544
+ );
4545
+ }
4546
+ return provider;
4547
+ }
4390
4548
  var WikiGraphLibraryManager = class {
4391
4549
  #runtime;
4392
4550
  constructor(runtime) {
@@ -4400,22 +4558,24 @@ var WikiGraphLibraryManager = class {
4400
4558
  });
4401
4559
  return new WikiGraphLibrary(this.#runtime, record);
4402
4560
  }
4403
- async get(uri = formatWikiGraphLibraryUri()) {
4561
+ async get(uri = formatWikiGraphLibraryUri2()) {
4404
4562
  const target = requireLibraryTarget(uri);
4405
4563
  const record = await this.#runtime.run(
4406
- async () => await resolveWikiGraphLibrary(target)
4564
+ async () => await resolveWikiGraphLibrary2(target)
4407
4565
  );
4408
4566
  return new WikiGraphLibrary(this.#runtime, record);
4409
4567
  }
4410
4568
  async addArchive(options) {
4411
- return await this.#runtime.run(
4412
- async () => await addWikiGraphLibraryArchive({
4413
- inputFile: new NodeFile(
4414
- resolveWikiGraphRuntimePath(options.inputPath)
4415
- ),
4416
- target: requireLibraryTarget(options.target),
4417
- ...options.to === void 0 ? {} : { to: options.to }
4418
- })
4569
+ return toArchiveSnapshot(
4570
+ await this.#runtime.run(
4571
+ async () => await addWikiGraphLibraryArchive({
4572
+ inputFile: new NodeFile(
4573
+ await assertStandaloneWikiGraphArchivePath(options.inputPath)
4574
+ ),
4575
+ target: requireLibraryTarget(options.target),
4576
+ ...options.to === void 0 ? {} : { to: options.to }
4577
+ })
4578
+ )
4419
4579
  );
4420
4580
  }
4421
4581
  async assertCurrent(target) {
@@ -4424,51 +4584,115 @@ var WikiGraphLibraryManager = class {
4424
4584
  );
4425
4585
  }
4426
4586
  async rebind(target, folder) {
4427
- return await this.#runtime.run(
4428
- async () => await rebindWikiGraphLibrary({
4429
- folder: new NodeDirectory(resolveWikiGraphRuntimePath(folder)),
4430
- target: requireLibraryTarget(target)
4431
- })
4587
+ return toScanSnapshot(
4588
+ await this.#runtime.run(
4589
+ async () => await rebindWikiGraphLibrary({
4590
+ folder: new NodeDirectory(resolveWikiGraphRuntimePath(folder)),
4591
+ target: requireLibraryTarget(target)
4592
+ })
4593
+ )
4432
4594
  );
4433
4595
  }
4434
4596
  async remove(target) {
4435
- return await this.#runtime.run(
4436
- async () => await removeWikiGraphLibrary(requireLibraryTarget(target))
4597
+ return toLibrarySnapshot(
4598
+ await this.#runtime.run(
4599
+ async () => await removeWikiGraphLibrary(requireLibraryTarget(target))
4600
+ )
4437
4601
  );
4438
4602
  }
4439
4603
  async scan(target) {
4440
- return await this.#runtime.run(
4441
- async () => await scanWikiGraphLibrary(requireLibraryTarget(target))
4604
+ return toScanSnapshot(
4605
+ await this.#runtime.run(
4606
+ async () => await scanWikiGraphLibrary(requireLibraryTarget(target))
4607
+ )
4442
4608
  );
4443
4609
  }
4444
4610
  async getArchive(target) {
4445
- return await this.#runtime.run(
4446
- async () => await getWikiGraphLibraryArchive(requireLibraryTarget(target))
4611
+ return toArchiveSnapshot(
4612
+ await this.#runtime.run(
4613
+ async () => await getWikiGraphLibraryArchive(requireLibraryTarget(target))
4614
+ )
4447
4615
  );
4448
4616
  }
4617
+ async readArchive(target, consume, options = {}) {
4618
+ return await this.#runtime.run(async () => {
4619
+ const parsedTarget = requireLibraryArchiveTarget(target);
4620
+ const library = await resolveWikiGraphLibrary2(parsedTarget);
4621
+ return await withWikiGraphLibraryLock(
4622
+ library.id,
4623
+ "read",
4624
+ async () => {
4625
+ throwIfAborted(options.signal);
4626
+ const archive = await getWikiGraphLibraryArchive(parsedTarget);
4627
+ const file = requireReadableLibraryArchiveFile(archive);
4628
+ const reader = await file.openReader();
4629
+ let active = true;
4630
+ try {
4631
+ const content = {
4632
+ mediaType: "application/vnd.wiki-graph.archive",
4633
+ size: reader.size,
4634
+ stream: createCallbackScopedArchiveStream(
4635
+ reader,
4636
+ () => active,
4637
+ options.signal
4638
+ ),
4639
+ uri: archive.uri
4640
+ };
4641
+ return await runAbortableCallback(
4642
+ async () => await consume(content),
4643
+ options.signal
4644
+ );
4645
+ } finally {
4646
+ active = false;
4647
+ await reader.close();
4648
+ }
4649
+ },
4650
+ options.signal === void 0 ? {} : { signal: options.signal }
4651
+ );
4652
+ }, options.signal);
4653
+ }
4449
4654
  async moveArchive(options) {
4450
- return await this.#runtime.run(
4451
- async () => await moveWikiGraphLibraryArchive({
4452
- target: requireLibraryTarget(options.target),
4453
- to: options.to
4454
- })
4655
+ return toArchiveSnapshot(
4656
+ await this.#runtime.run(
4657
+ async () => await moveWikiGraphLibraryArchive({
4658
+ target: requireLibraryTarget(options.target),
4659
+ to: options.to
4660
+ })
4661
+ )
4455
4662
  );
4456
4663
  }
4457
4664
  async removeArchive(target) {
4458
- return await this.#runtime.run(
4459
- async () => await removeWikiGraphLibraryArchive({
4460
- target: requireLibraryTarget(target)
4665
+ return toArchiveSnapshot(
4666
+ await this.#runtime.run(
4667
+ async () => await removeWikiGraphLibraryArchive({
4668
+ target: requireLibraryTarget(target)
4669
+ })
4670
+ )
4671
+ );
4672
+ }
4673
+ async replaceArchive(options) {
4674
+ return toArchiveSnapshot(
4675
+ await this.#runtime.run(async () => {
4676
+ const target = requireLibraryTarget(options.target);
4677
+ const current = await getWikiGraphLibraryArchive(target);
4678
+ return await replaceWikiGraphLibraryArchive({
4679
+ additionalDerivedStateKeys: current.file === void 0 ? [] : [getNodeResourcePath(current.file)],
4680
+ inputFile: new NodeFile(
4681
+ await assertStandaloneWikiGraphArchivePath(options.inputPath)
4682
+ ),
4683
+ target
4684
+ });
4461
4685
  })
4462
4686
  );
4463
4687
  }
4464
4688
  async indexState(target) {
4465
4689
  return await this.#runtime.run(
4466
- async () => await readWikiGraphLibraryIndexState2(requireLibraryTarget(target))
4690
+ async () => await readWikiGraphLibraryIndexState(requireLibraryTarget(target))
4467
4691
  );
4468
4692
  }
4469
4693
  async rebuildIndex(target, onProgress) {
4470
4694
  return await this.#runtime.run(
4471
- async () => await rebuildWikiGraphLibraryIndex2(
4695
+ async () => await rebuildWikiGraphLibraryIndex(
4472
4696
  requireLibraryTarget(target),
4473
4697
  onProgress
4474
4698
  )
@@ -4516,7 +4740,9 @@ var WikiGraphLibraryManager = class {
4516
4740
  }
4517
4741
  async search(target, query, options = {}) {
4518
4742
  return await this.#runtime.run(async () => {
4519
- const embeddingProvider = await createConfiguredEmbeddingProvider();
4743
+ const embeddingProvider = await resolveQueryEmbeddingProvider(
4744
+ options.queryMode
4745
+ );
4520
4746
  return await findWikiGraphLibraryObjects2(
4521
4747
  requireLibraryTarget(target),
4522
4748
  query,
@@ -4529,7 +4755,9 @@ var WikiGraphLibraryManager = class {
4529
4755
  }
4530
4756
  async searchArchiveMembers(target, query, options = {}) {
4531
4757
  return await this.#runtime.run(async () => {
4532
- const embeddingProvider = await createConfiguredEmbeddingProvider();
4758
+ const embeddingProvider = await resolveQueryEmbeddingProvider(
4759
+ options.queryMode
4760
+ );
4533
4761
  return await findWikiGraphLibraryArchiveMembers2(
4534
4762
  requireLibraryTarget(target),
4535
4763
  query,
@@ -4565,26 +4793,41 @@ var WikiGraphLibraryManager = class {
4565
4793
  objectUri,
4566
4794
  { ...options, ...wikimediaOptions }
4567
4795
  )
4568
- )
4796
+ ),
4797
+ options.signal
4569
4798
  );
4570
4799
  }
4571
4800
  async related(target, objectUri, options = {}) {
4572
- return await this.#runtime.run(
4573
- async () => await listRelatedWikiGraphLibraryObjects2(
4801
+ return await this.#runtime.run(async () => {
4802
+ if (options.query === void 0 && options.queryMode !== void 0) {
4803
+ throw new Error("`queryMode` requires `query`.");
4804
+ }
4805
+ const embeddingProvider = options.query === void 0 ? void 0 : await resolveQueryEmbeddingProvider(options.queryMode);
4806
+ return await listRelatedWikiGraphLibraryObjects2(
4574
4807
  requireLibraryTarget(target),
4575
4808
  objectUri,
4576
- options
4577
- )
4578
- );
4809
+ {
4810
+ ...options,
4811
+ ...embeddingProvider === void 0 ? {} : { embeddingProvider }
4812
+ }
4813
+ );
4814
+ });
4579
4815
  }
4580
4816
  async evidence(target, objectUri, options = {}) {
4581
- return await this.#runtime.run(
4582
- async () => await listWikiGraphLibraryEvidence2(
4817
+ return await this.#runtime.run(async () => {
4818
+ if (options.query === void 0 && options.queryMode !== void 0) {
4819
+ throw new Error("`queryMode` requires `query`.");
4820
+ }
4821
+ const embeddingProvider = options.query === void 0 ? void 0 : await resolveQueryEmbeddingProvider(options.queryMode);
4822
+ return await listWikiGraphLibraryEvidence2(
4583
4823
  requireLibraryTarget(target),
4584
4824
  objectUri,
4585
- options
4586
- )
4587
- );
4825
+ {
4826
+ ...options,
4827
+ ...embeddingProvider === void 0 ? {} : { embeddingProvider }
4828
+ }
4829
+ );
4830
+ });
4588
4831
  }
4589
4832
  async pack(target, objectUri, budget = 5e3) {
4590
4833
  return await this.#runtime.run(
@@ -4597,7 +4840,7 @@ var WikiGraphLibraryManager = class {
4597
4840
  }
4598
4841
  async list() {
4599
4842
  const records = await this.#runtime.run(
4600
- async () => await listWikiGraphLibraries()
4843
+ async () => await listWikiGraphLibraries2()
4601
4844
  );
4602
4845
  return records.map((record) => new WikiGraphLibrary(this.#runtime, record));
4603
4846
  }
@@ -4610,32 +4853,54 @@ var WikiGraphLibrary = class {
4610
4853
  this.#record = record;
4611
4854
  }
4612
4855
  get snapshot() {
4613
- return this.#record;
4856
+ return toLibrarySnapshot(this.#record);
4614
4857
  }
4615
4858
  get uri() {
4616
- return formatWikiGraphLibraryUri(
4859
+ return formatWikiGraphLibraryUri2(
4617
4860
  this.#record.isDefault ? void 0 : this.#record.publicId
4618
4861
  );
4619
4862
  }
4620
4863
  async archives() {
4621
4864
  const target = requireLibraryTarget(this.uri);
4622
- return await this.#runtime.run(
4623
- async () => await listWikiGraphLibraryArchives(target)
4624
- );
4865
+ return (await this.#runtime.run(
4866
+ async () => await listWikiGraphLibraryArchives2(target)
4867
+ )).map(toArchiveSnapshot);
4625
4868
  }
4626
4869
  async scan() {
4627
4870
  const target = requireLibraryTarget(this.uri);
4628
- return await this.#runtime.run(
4629
- async () => await scanWikiGraphLibrary(target)
4871
+ return toScanSnapshot(
4872
+ await this.#runtime.run(async () => await scanWikiGraphLibrary(target))
4630
4873
  );
4631
4874
  }
4632
4875
  async remove() {
4633
4876
  const target = requireLibraryTarget(this.uri);
4634
- return await this.#runtime.run(
4635
- async () => await removeWikiGraphLibrary(target)
4877
+ return toLibrarySnapshot(
4878
+ await this.#runtime.run(async () => await removeWikiGraphLibrary(target))
4636
4879
  );
4637
4880
  }
4638
4881
  };
4882
+ function toLibrarySnapshot(record) {
4883
+ const compatible = record;
4884
+ return {
4885
+ id: record.id,
4886
+ publicId: record.publicId,
4887
+ uri: record.uri,
4888
+ folderPath: compatible.folderPath ?? (record.folder === void 0 ? "" : getNodeResourcePath(record.folder)),
4889
+ isDefault: record.isDefault,
4890
+ createdAt: record.createdAt,
4891
+ updatedAt: record.updatedAt
4892
+ };
4893
+ }
4894
+ function toArchiveSnapshot(record) {
4895
+ const { file: _file, ...snapshot } = record;
4896
+ return snapshot;
4897
+ }
4898
+ function toScanSnapshot(result) {
4899
+ return {
4900
+ ...result.library === void 0 ? {} : { library: toLibrarySnapshot(result.library) },
4901
+ archives: result.archives.map(toArchiveSnapshot)
4902
+ };
4903
+ }
4639
4904
  function requireLibraryTarget(value) {
4640
4905
  if (typeof value !== "string") return value;
4641
4906
  const target = parseWikiGraphLibraryUri2(value);
@@ -4644,6 +4909,97 @@ function requireLibraryTarget(value) {
4644
4909
  }
4645
4910
  return target;
4646
4911
  }
4912
+ function requireLibraryArchiveTarget(value) {
4913
+ const target = requireLibraryTarget(value);
4914
+ if (target.kind !== "archive" || target.archivePublicId === void 0 || target.objectUri !== void 0) {
4915
+ throw new TypeError("Expected a Wiki Graph library archive URI.");
4916
+ }
4917
+ return target;
4918
+ }
4919
+ function requireReadableLibraryArchiveFile(archive) {
4920
+ if (!archive.exists || archive.status === "missing") {
4921
+ throw new Error(`Wiki Graph library archive is missing: ${archive.uri}`);
4922
+ }
4923
+ if (archive.status === "conflict") {
4924
+ throw new Error(
4925
+ `Wiki Graph library archive has a conflict and cannot be read: ${archive.uri}`
4926
+ );
4927
+ }
4928
+ if (archive.file === void 0) {
4929
+ throw new Error(
4930
+ `Wiki Graph library archive is unavailable: ${archive.uri}`
4931
+ );
4932
+ }
4933
+ return archive.file;
4934
+ }
4935
+ var ARCHIVE_STREAM_CHUNK_SIZE = 64 * 1024;
4936
+ function createCallbackScopedArchiveStream(reader, isActive, signal) {
4937
+ let consumed = false;
4938
+ return {
4939
+ [Symbol.asyncIterator]() {
4940
+ assertArchiveReadSessionActive(isActive, signal);
4941
+ if (consumed) {
4942
+ throw new Error(
4943
+ "The library archive stream has already been consumed."
4944
+ );
4945
+ }
4946
+ consumed = true;
4947
+ let offset = 0;
4948
+ let finished = false;
4949
+ return {
4950
+ async next() {
4951
+ if (finished) return { done: true, value: void 0 };
4952
+ assertArchiveReadSessionActive(isActive, signal);
4953
+ if (offset >= reader.size) {
4954
+ finished = true;
4955
+ return { done: true, value: void 0 };
4956
+ }
4957
+ const length = Math.min(
4958
+ ARCHIVE_STREAM_CHUNK_SIZE,
4959
+ reader.size - offset
4960
+ );
4961
+ const chunk = await reader.read(offset, length);
4962
+ assertArchiveReadSessionActive(isActive, signal);
4963
+ offset += chunk.byteLength;
4964
+ return { done: false, value: chunk };
4965
+ },
4966
+ return() {
4967
+ finished = true;
4968
+ return Promise.resolve({ done: true, value: void 0 });
4969
+ }
4970
+ };
4971
+ }
4972
+ };
4973
+ }
4974
+ function assertArchiveReadSessionActive(isActive, signal) {
4975
+ if (!isActive()) {
4976
+ throw new Error(
4977
+ "The library archive stream cannot be read after its callback has finished."
4978
+ );
4979
+ }
4980
+ throwIfAborted(signal);
4981
+ }
4982
+ async function runAbortableCallback(operation, signal) {
4983
+ if (signal === void 0) return await operation();
4984
+ throwIfAborted(signal);
4985
+ let rejectAbort;
4986
+ const aborted = new Promise((_resolve, reject) => {
4987
+ rejectAbort = reject;
4988
+ });
4989
+ const onAbort = () => rejectAbort(abortReason(signal));
4990
+ signal.addEventListener("abort", onAbort, { once: true });
4991
+ try {
4992
+ return await Promise.race([operation(), aborted]);
4993
+ } finally {
4994
+ signal.removeEventListener("abort", onAbort);
4995
+ }
4996
+ }
4997
+ function throwIfAborted(signal) {
4998
+ if (signal?.aborted === true) throw abortReason(signal);
4999
+ }
5000
+ function abortReason(signal) {
5001
+ return signal.reason ?? new DOMException("The operation was aborted.", "AbortError");
5002
+ }
4647
5003
 
4648
5004
  // src/maintenance.ts
4649
5005
  import {
@@ -4651,7 +5007,7 @@ import {
4651
5007
  parseWikiGraphLibraryUri as parseWikiGraphLibraryUri3,
4652
5008
  upgradeWikiGraphMaintenanceTarget
4653
5009
  } from "wiki-graph-core";
4654
- import { basename as basename4 } from "path";
5010
+ import { basename as basename5 } from "path";
4655
5011
  var WikiGraphMaintenanceManager = class {
4656
5012
  #runtime;
4657
5013
  constructor(runtime) {
@@ -4675,7 +5031,7 @@ var WikiGraphMaintenanceManager = class {
4675
5031
  target: parsed
4676
5032
  });
4677
5033
  }
4678
- const path = resolveWikiGraphRuntimePath(target.path);
5034
+ const path = await assertStandaloneWikiGraphArchivePath(target.path);
4679
5035
  return await upgradeWikiGraphMaintenanceTarget({
4680
5036
  file: new NodeFile(path),
4681
5037
  kind: "archive"
@@ -4691,7 +5047,7 @@ var WikiGraphMaintenanceManager = class {
4691
5047
  const resolvedOutputPath = resolveWikiGraphRuntimePath(outputPath);
4692
5048
  await migrateLegacySdpubToWikg(
4693
5049
  new NodeFile(resolvedInputPath),
4694
- new NodeFile(resolvedOutputPath, basename4(resolvedOutputPath))
5050
+ new NodeFile(resolvedOutputPath, basename5(resolvedOutputPath))
4695
5051
  );
4696
5052
  return {
4697
5053
  inputPath: resolvedInputPath,
@@ -4722,6 +5078,7 @@ var WikiGraphSDK = class {
4722
5078
  cwd: options.cwd ?? process.cwd(),
4723
5079
  env: { ...process.env, ...options.env },
4724
5080
  envPolicy: options.envPolicy ?? "production",
5081
+ providers: { ...options.providers },
4725
5082
  ...options.stateDir === void 0 ? {} : { stateDir: options.stateDir }
4726
5083
  };
4727
5084
  this.archives = new WikiGraphArchiveManager(this);
@@ -4733,7 +5090,7 @@ var WikiGraphSDK = class {
4733
5090
  this.maintenance = new WikiGraphMaintenanceManager(this);
4734
5091
  }
4735
5092
  async run(operation, signal, options = {}) {
4736
- throwIfAborted(signal);
5093
+ throwIfAborted2(signal);
4737
5094
  const runWithContext = async () => await withWikiGraphSDKRuntimeContext(this.#context, async () => {
4738
5095
  if (options.skipHomeBootstrap !== true) {
4739
5096
  this.#homeReady ??= ensureWikiGraphHomeSchemaCurrent().catch(
@@ -4750,14 +5107,14 @@ var WikiGraphSDK = class {
4750
5107
  this.#context.stateDir,
4751
5108
  runWithContext
4752
5109
  );
4753
- throwIfAborted(signal);
5110
+ throwIfAborted2(signal);
4754
5111
  return result;
4755
5112
  }
4756
5113
  close() {
4757
5114
  this.jobs.close();
4758
5115
  }
4759
5116
  };
4760
- function throwIfAborted(signal) {
5117
+ function throwIfAborted2(signal) {
4761
5118
  if (signal?.aborted !== true) return;
4762
5119
  throw signal.reason instanceof Error ? signal.reason : new Error("The Wiki Graph SDK operation was aborted.");
4763
5120
  }
@@ -4773,16 +5130,16 @@ import {
4773
5130
  formatError as formatError3,
4774
5131
  formatLocatedChapterResourceUri,
4775
5132
  formatLocatedChapterSourceCollectionUri,
4776
- formatLocatedChapterUri as formatLocatedChapterUri2,
4777
- formatLocatedWikiGraphUri as formatLocatedWikiGraphUri2,
5133
+ formatLocatedChapterUri as formatLocatedChapterUri3,
5134
+ formatLocatedWikiGraphUri as formatLocatedWikiGraphUri3,
4778
5135
  formatWikiGraphCommandUri,
4779
- formatWikiGraphLibraryUri as formatWikiGraphLibraryUri2,
5136
+ formatWikiGraphLibraryUri as formatWikiGraphLibraryUri3,
4780
5137
  isSourceLocatorScopeUri as isSourceLocatorScopeUri2,
4781
5138
  isWikiGraphLibraryUri,
4782
5139
  parseChapterPath,
4783
5140
  parseChapterTreeInput,
4784
5141
  parseChapterUriPath,
4785
- parseLocatedWikiGraphUri as parseLocatedWikiGraphUri2,
5142
+ parseLocatedWikiGraphUri as parseLocatedWikiGraphUri3,
4786
5143
  parseSourceTextJsonl,
4787
5144
  parseWikiGraphLibraryUri as parseWikiGraphLibraryUri4,
4788
5145
  parseWikiGraphUriSyntax
@@ -4801,6 +5158,7 @@ export {
4801
5158
  WikiGraphArchiveExistsError,
4802
5159
  WikiGraphArchiveHandle,
4803
5160
  WikiGraphArchiveManager,
5161
+ WikiGraphArchiveOwnershipError,
4804
5162
  WikiGraphConfigManager,
4805
5163
  WikiGraphContinuationManager,
4806
5164
  WikiGraphConversionManager,
@@ -4819,7 +5177,6 @@ export {
4819
5177
  createNodeTemplateEnvironment,
4820
5178
  createNodeWikiGraphStorage,
4821
5179
  createStageLLM,
4822
- createWikiGraphArchiveInspectReport,
4823
5180
  createWikiGraphSDK,
4824
5181
  deleteLocalConfigValue,
4825
5182
  embedQueryText,
@@ -4830,13 +5187,15 @@ export {
4830
5187
  formatGenerationPlanningModel,
4831
5188
  formatLocatedChapterResourceUri,
4832
5189
  formatLocatedChapterSourceCollectionUri,
4833
- formatLocatedChapterUri2 as formatLocatedChapterUri,
4834
- formatLocatedWikiGraphUri2 as formatLocatedWikiGraphUri,
5190
+ formatLocatedChapterUri3 as formatLocatedChapterUri,
5191
+ formatLocatedWikiGraphUri3 as formatLocatedWikiGraphUri,
4835
5192
  formatWikiGraphCommandUri,
4836
- formatWikiGraphLibraryUri2 as formatWikiGraphLibraryUri,
5193
+ formatWikiGraphLibraryUri3 as formatWikiGraphLibraryUri,
4837
5194
  getNodeResourcePath,
5195
+ getWikiGraphSDKProviders,
4838
5196
  getWikiGraphSDKRuntimeContext,
4839
5197
  getWikiGraphSDKStateDir,
5198
+ inspectWikiGraphArchive,
4840
5199
  installNodeWikiGraphPlatform,
4841
5200
  isSourceLocatorScopeUri2 as isSourceLocatorScopeUri,
4842
5201
  isWikiGraphLibraryUri,
@@ -4850,7 +5209,7 @@ export {
4850
5209
  parseChapterTreeInput,
4851
5210
  parseChapterUriPath,
4852
5211
  parseLocalConfigSection,
4853
- parseLocatedWikiGraphUri2 as parseLocatedWikiGraphUri,
5212
+ parseLocatedWikiGraphUri3 as parseLocatedWikiGraphUri,
4854
5213
  parseSourceTextJsonl,
4855
5214
  parseWikiGraphLibraryUri4 as parseWikiGraphLibraryUri,
4856
5215
  parseWikiGraphUriSyntax,
@@ -4863,7 +5222,7 @@ export {
4863
5222
  resolveExtractionPrompt,
4864
5223
  resolveHostedProviderEndpoint,
4865
5224
  resolveKnowledgeGraphRecallPrompt,
4866
- resolveWikiGraphArchiveLocation,
5225
+ resolveWikiGraphLLMJSON,
4867
5226
  resolveWikispineConfig,
4868
5227
  runWikiGraphQueueWorker,
4869
5228
  validateLocalConfigSection,