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/archives.cjs CHANGED
@@ -34,25 +34,25 @@ __export(archive_exports, {
34
34
  WikiGraphArchiveExistsError: () => WikiGraphArchiveExistsError,
35
35
  WikiGraphArchiveHandle: () => WikiGraphArchiveHandle,
36
36
  WikiGraphArchiveManager: () => WikiGraphArchiveManager,
37
- createWikiGraphArchiveInspectReport: () => createWikiGraphArchiveInspectReport,
38
- resolveWikiGraphArchiveLocation: () => resolveWikiGraphArchiveLocation
37
+ WikiGraphArchiveOwnershipError: () => WikiGraphArchiveOwnershipError,
38
+ inspectWikiGraphArchive: () => inspectWikiGraphArchive
39
39
  });
40
40
  module.exports = __toCommonJS(archive_exports);
41
41
 
42
42
  // src/archive/archive.ts
43
43
  var import_crypto2 = require("crypto");
44
- var import_promises3 = require("fs/promises");
44
+ var import_promises4 = require("fs/promises");
45
45
  var import_os3 = require("os");
46
- var import_path4 = require("path");
46
+ var import_path5 = require("path");
47
47
  var import_stream = require("stream");
48
- var import_wiki_graph_core5 = require("wiki-graph-core");
48
+ var import_wiki_graph_core7 = require("wiki-graph-core");
49
49
 
50
50
  // src/conversions.ts
51
51
  var import_crypto = require("crypto");
52
52
  var import_fs = require("fs");
53
- var import_promises2 = require("fs/promises");
54
- var import_path3 = require("path");
55
- var import_wiki_graph_core2 = require("wiki-graph-core");
53
+ var import_promises3 = require("fs/promises");
54
+ var import_path4 = require("path");
55
+ var import_wiki_graph_core3 = require("wiki-graph-core");
56
56
 
57
57
  // src/llm.ts
58
58
  var import_anthropic = require("@ai-sdk/anthropic");
@@ -372,42 +372,42 @@ var NodeDatabaseConnection = class {
372
372
  }
373
373
  database;
374
374
  async close() {
375
- await new Promise((resolve3, reject) => {
375
+ await new Promise((resolve4, reject) => {
376
376
  this.database.close((error) => {
377
377
  if (error) reject(error);
378
- else resolve3();
378
+ else resolve4();
379
379
  });
380
380
  });
381
381
  }
382
382
  async execute(sql) {
383
- await new Promise((resolve3, reject) => {
383
+ await new Promise((resolve4, reject) => {
384
384
  this.database.exec(sql, (error) => {
385
385
  if (error) reject(error);
386
- else resolve3();
386
+ else resolve4();
387
387
  });
388
388
  });
389
389
  }
390
390
  async queryAll(sql, params = []) {
391
- return await new Promise((resolve3, reject) => {
391
+ return await new Promise((resolve4, reject) => {
392
392
  this.database.all(sql, [...params], (error, rows) => {
393
393
  if (error) reject(error);
394
- else resolve3(rows);
394
+ else resolve4(rows);
395
395
  });
396
396
  });
397
397
  }
398
398
  async queryOne(sql, params = []) {
399
- return await new Promise((resolve3, reject) => {
399
+ return await new Promise((resolve4, reject) => {
400
400
  this.database.get(sql, [...params], (error, row) => {
401
401
  if (error) reject(error);
402
- else resolve3(row);
402
+ else resolve4(row);
403
403
  });
404
404
  });
405
405
  }
406
406
  async run(sql, params = []) {
407
- await new Promise((resolve3, reject) => {
407
+ await new Promise((resolve4, reject) => {
408
408
  this.database.run(sql, [...params], (error) => {
409
409
  if (error) reject(error);
410
- else resolve3();
410
+ else resolve4();
411
411
  });
412
412
  });
413
413
  }
@@ -421,10 +421,10 @@ async function openNativeNodeDatabase(file, flags) {
421
421
  if (path === void 0) {
422
422
  throw new TypeError("The Node database adapter requires a NodeFile");
423
423
  }
424
- return await new Promise((resolve3, reject) => {
424
+ return await new Promise((resolve4, reject) => {
425
425
  const database = new nodeSqlite3.Database(path, flags, (error) => {
426
426
  if (error) reject(error);
427
- else resolve3(database);
427
+ else resolve4(database);
428
428
  });
429
429
  });
430
430
  }
@@ -433,19 +433,19 @@ async function openNodeZip(file) {
433
433
  if (path === void 0) {
434
434
  throw new TypeError("The Node ZIP adapter requires a NodeFile");
435
435
  }
436
- const zipFile = await new Promise((resolve3, reject) => {
436
+ const zipFile = await new Promise((resolve4, reject) => {
437
437
  yauzl.open(
438
438
  path,
439
439
  { autoClose: false, lazyEntries: true },
440
440
  (error, opened) => {
441
441
  if (error || opened === void 0)
442
442
  reject(error ?? new Error("Cannot open ZIP"));
443
- else resolve3(opened);
443
+ else resolve4(opened);
444
444
  }
445
445
  );
446
446
  });
447
447
  const entries = await new Promise(
448
- (resolve3, reject) => {
448
+ (resolve4, reject) => {
449
449
  const discovered = /* @__PURE__ */ new Map();
450
450
  const rejectAndClose = (error) => {
451
451
  zipFile.close();
@@ -455,7 +455,7 @@ async function openNodeZip(file) {
455
455
  };
456
456
  const resolveEntries = () => {
457
457
  zipFile.off("error", rejectAndClose);
458
- resolve3(discovered);
458
+ resolve4(discovered);
459
459
  };
460
460
  zipFile.on("entry", (entry) => {
461
461
  if (!entry.fileName.endsWith("/")) {
@@ -565,12 +565,12 @@ async function collectDecodedNodeStreamRange(input, offset, length) {
565
565
  return Buffer.concat(chunks, collected);
566
566
  }
567
567
  async function openNodeZipEntryStream(zipFile, entry, options) {
568
- return await new Promise((resolve3, reject) => {
568
+ return await new Promise((resolve4, reject) => {
569
569
  const callback = (error, opened) => {
570
570
  if (error || opened === void 0) {
571
571
  reject(error ?? new Error(`Cannot read ZIP entry: ${entry.fileName}`));
572
572
  } else {
573
- resolve3(opened);
573
+ resolve4(opened);
574
574
  }
575
575
  };
576
576
  if (options === void 0) zipFile.openReadStream(entry, callback);
@@ -701,11 +701,11 @@ async function writeNodeStream(input, writer) {
701
701
  );
702
702
  }
703
703
  async function collectNodeStream(input) {
704
- return await new Promise((resolve3, reject) => {
704
+ return await new Promise((resolve4, reject) => {
705
705
  const chunks = [];
706
706
  input.on("data", (chunk) => chunks.push(chunk));
707
707
  input.once("error", reject);
708
- input.once("end", () => resolve3(Buffer.concat(chunks)));
708
+ input.once("end", () => resolve4(Buffer.concat(chunks)));
709
709
  });
710
710
  }
711
711
  var nodeWikiGraphPlatform = {
@@ -826,12 +826,16 @@ function getWikiGraphSDKRuntimeContext() {
826
826
  return runtimeContext.getStore() ?? {
827
827
  cwd: process.cwd(),
828
828
  env: process.env,
829
- envPolicy: "production"
829
+ envPolicy: "production",
830
+ providers: {}
830
831
  };
831
832
  }
832
833
  function getWikiGraphSDKStateDir() {
833
834
  return getWikiGraphSDKRuntimeContext().stateDir;
834
835
  }
836
+ function getWikiGraphSDKProviders() {
837
+ return getWikiGraphSDKRuntimeContext().providers ?? {};
838
+ }
835
839
 
836
840
  // src/local-config.ts
837
841
  var import_path = require("path");
@@ -1049,8 +1053,8 @@ var inlineLLMConfigSchema = import_zod.z.object({
1049
1053
  });
1050
1054
  async function loadWikiGraphRuntimeConfig(options) {
1051
1055
  const [embedding, localLLM, concurrent, wikimedia, wikispine] = await Promise.all([
1052
- readLocalConfigSection("embeddings"),
1053
- readLocalConfigSection("llm"),
1056
+ options?.skipEmbeddingConfig === true ? Promise.resolve({}) : readLocalConfigSection("embeddings"),
1057
+ options?.skipLLMConfig === true ? Promise.resolve({}) : readLocalConfigSection("llm"),
1054
1058
  readLocalConfigSection("concurrent"),
1055
1059
  readLocalConfigSection("wikimedia"),
1056
1060
  readLocalConfigSection("wikispine")
@@ -1246,6 +1250,14 @@ function formatError2(error) {
1246
1250
  return error instanceof Error ? error.message : String(error);
1247
1251
  }
1248
1252
 
1253
+ // src/providers.ts
1254
+ function resolveWikiGraphLLMJSON(options) {
1255
+ if (options.llm !== void 0 && options.llmJSON !== void 0) {
1256
+ throw new Error("Pass either llm or llmJSON, not both.");
1257
+ }
1258
+ return options.llm === void 0 ? options.llmJSON : JSON.stringify(options.llm);
1259
+ }
1260
+
1249
1261
  // src/runtime-path.ts
1250
1262
  var import_os2 = require("os");
1251
1263
  var import_path2 = require("path");
@@ -1258,6 +1270,164 @@ function resolveWikiGraphRuntimePath(path) {
1258
1270
  return (0, import_path2.isAbsolute)(path) ? path : (0, import_path2.resolve)(context.cwd, path);
1259
1271
  }
1260
1272
 
1273
+ // src/archive/target.ts
1274
+ var import_promises2 = require("fs/promises");
1275
+ var import_path3 = require("path");
1276
+ var import_wiki_graph_core2 = require("wiki-graph-core");
1277
+ var WikiGraphArchiveOwnershipError = class extends Error {
1278
+ code = "WIKI_GRAPH_ARCHIVE_OWNERSHIP_MISMATCH";
1279
+ constructor(message) {
1280
+ super(message);
1281
+ this.name = "WikiGraphArchiveOwnershipError";
1282
+ }
1283
+ };
1284
+ async function resolveWikiGraphArchiveLocation(target) {
1285
+ if (target.kind === "standalone") {
1286
+ return await resolveStandaloneLocation(target);
1287
+ }
1288
+ return await resolveLibraryLocation(target);
1289
+ }
1290
+ async function assertStandaloneWikiGraphArchivePath(inputPath) {
1291
+ const path = resolveWikiGraphRuntimePath(inputPath);
1292
+ const candidate = await canonicalPath(path);
1293
+ const candidateIdentity = await readFileIdentity(path);
1294
+ const libraries = await (0, import_wiki_graph_core2.listWikiGraphLibraries)();
1295
+ const matches = await findMatchingMembers(
1296
+ libraries,
1297
+ candidate,
1298
+ candidateIdentity
1299
+ );
1300
+ if (matches.length > 0) {
1301
+ const match = requireUnambiguousManagedMatch(path, matches);
1302
+ throw new WikiGraphArchiveOwnershipError(
1303
+ `Standalone archive path belongs to registered library ${(0, import_wiki_graph_core2.formatWikiGraphLibraryUri)(
1304
+ match.library.isDefault ? void 0 : match.library.publicId
1305
+ )}: ${path}. Use the library UUID URI ${match.archive.uri} instead.`
1306
+ );
1307
+ }
1308
+ for (const library of libraries) {
1309
+ const rootPath = getNodeResourcePath(library.folder);
1310
+ const root = await canonicalPath(rootPath);
1311
+ if (!isWithin(root, candidate)) continue;
1312
+ throw new WikiGraphArchiveOwnershipError(
1313
+ `Standalone archive path belongs to registered library ${(0, import_wiki_graph_core2.formatWikiGraphLibraryUri)(
1314
+ library.isDefault ? void 0 : library.publicId
1315
+ )}: ${path}. Scan the library, then address the archive by its library UUID URI.`
1316
+ );
1317
+ }
1318
+ return path;
1319
+ }
1320
+ async function resolveStandaloneLocation(target) {
1321
+ if (target.path.startsWith("wikg://lib/")) {
1322
+ throw new WikiGraphArchiveOwnershipError(
1323
+ `A library archive URI cannot be used as a standalone path: ${target.path}`
1324
+ );
1325
+ }
1326
+ const path = await assertStandaloneWikiGraphArchivePath(target.path);
1327
+ const normalized = {
1328
+ kind: "standalone",
1329
+ path,
1330
+ ...target.objectUri === void 0 ? {} : { objectUri: target.objectUri }
1331
+ };
1332
+ return {
1333
+ archiveFile: new NodeFile(path),
1334
+ archiveKey: path,
1335
+ archivePath: path,
1336
+ indexScope: { archiveKey: path, archivePath: path, kind: "archive-index" },
1337
+ locatedUri: (0, import_wiki_graph_core2.formatLocatedWikiGraphUri)(path, target.objectUri),
1338
+ target: normalized
1339
+ };
1340
+ }
1341
+ async function resolveLibraryLocation(target) {
1342
+ const parsedLocated = (0, import_wiki_graph_core2.parseLocatedWikiGraphUri)(target.uri);
1343
+ const archiveUri = parsedLocated.archivePath ?? target.uri;
1344
+ const parsed = (0, import_wiki_graph_core2.parseWikiGraphLibraryUri)(archiveUri);
1345
+ if (parsed?.kind !== "archive") {
1346
+ throw new WikiGraphArchiveOwnershipError(
1347
+ `Library archive target must be a UUID archive URI: ${target.uri}`
1348
+ );
1349
+ }
1350
+ await (0, import_wiki_graph_core2.resolveWikiGraphLibrary)(parsed);
1351
+ const archiveFile = await (0, import_wiki_graph_core2.resolveWikiGraphLibraryArchiveFile)(archiveUri);
1352
+ const normalized = {
1353
+ kind: "library",
1354
+ uri: target.uri
1355
+ };
1356
+ return {
1357
+ archiveFile,
1358
+ archiveKey: archiveUri,
1359
+ archivePath: archiveUri,
1360
+ indexScope: {
1361
+ archiveKey: archiveUri,
1362
+ archivePath: archiveUri,
1363
+ kind: "archive-index"
1364
+ },
1365
+ libraryArchiveTarget: parsed,
1366
+ locatedUri: target.uri,
1367
+ publicArchiveUri: archiveUri,
1368
+ target: normalized
1369
+ };
1370
+ }
1371
+ async function canonicalPath(path) {
1372
+ try {
1373
+ return await (0, import_promises2.realpath)(path);
1374
+ } catch {
1375
+ const absolute = (0, import_path3.resolve)(path);
1376
+ const parent = (0, import_path3.dirname)(absolute);
1377
+ return parent === absolute ? absolute : (0, import_path3.join)(await canonicalPath(parent), (0, import_path3.basename)(absolute));
1378
+ }
1379
+ }
1380
+ function isWithin(root, candidate) {
1381
+ const child = (0, import_path3.relative)(root, candidate);
1382
+ return child === "" || !child.startsWith("..") && !(0, import_path3.isAbsolute)(child);
1383
+ }
1384
+ async function findMatchingMembers(libraries, candidate, candidateIdentity) {
1385
+ const members = [];
1386
+ for (const library of libraries) {
1387
+ const archives = await (0, import_wiki_graph_core2.listWikiGraphLibraryArchives)({
1388
+ isDefault: library.isDefault,
1389
+ kind: "scope",
1390
+ ...library.isDefault ? {} : { publicId: library.publicId }
1391
+ });
1392
+ for (const archive of archives) {
1393
+ if (archive.file === void 0) continue;
1394
+ members.push({
1395
+ archive,
1396
+ library,
1397
+ memberPath: getNodeResourcePath(archive.file)
1398
+ });
1399
+ }
1400
+ }
1401
+ const exact = [];
1402
+ for (const member of members) {
1403
+ if (await canonicalPath(member.memberPath) === candidate) {
1404
+ exact.push(member);
1405
+ }
1406
+ }
1407
+ if (exact.length > 0 || candidateIdentity === void 0) return exact;
1408
+ const identityMatches = [];
1409
+ for (const member of members) {
1410
+ if (await readFileIdentity(member.memberPath) === candidateIdentity) {
1411
+ identityMatches.push(member);
1412
+ }
1413
+ }
1414
+ return identityMatches;
1415
+ }
1416
+ function requireUnambiguousManagedMatch(path, matches) {
1417
+ if (matches.length === 1) return matches[0];
1418
+ throw new WikiGraphArchiveOwnershipError(
1419
+ `Archive file identity is ambiguous across managed archives: ${path}. Use an explicit library UUID URI (${matches.map((match) => match.archive.uri).join(", ")}).`
1420
+ );
1421
+ }
1422
+ async function readFileIdentity(path) {
1423
+ try {
1424
+ const value = await (0, import_promises2.stat)(path);
1425
+ return `${value.dev}:${value.ino}`;
1426
+ } catch {
1427
+ return void 0;
1428
+ }
1429
+ }
1430
+
1261
1431
  // src/conversions.ts
1262
1432
  var WikiGraphConversionManager = class {
1263
1433
  #runtime;
@@ -1282,23 +1452,33 @@ var WikiGraphConversionManager = class {
1282
1452
  }
1283
1453
  const requiresDigest = options.input.format !== "wikg";
1284
1454
  const requiresLLM = requiresDigest && targetStage !== "planned" && targetStage !== "sourced";
1455
+ const llmJSON = resolveWikiGraphLLMJSON(options);
1456
+ const injectedLLM = llmJSON === void 0 ? getWikiGraphSDKProviders().llm : void 0;
1285
1457
  const config = await loadWikiGraphRuntimeConfig({
1286
- ...options.llmJSON === void 0 ? {} : { llmJSON: options.llmJSON }
1458
+ ...llmJSON === void 0 ? {} : { llmJSON },
1459
+ ...injectedLLM === void 0 ? {} : { skipLLMConfig: true },
1460
+ ...getWikiGraphSDKProviders().embedding === void 0 ? {} : { skipEmbeddingConfig: true }
1287
1461
  });
1288
- const app = new import_wiki_graph_core2.WikiGraph({
1462
+ const app = new import_wiki_graph_core3.WikiGraph({
1289
1463
  ...options.verbose === true ? { verbose: true } : {},
1290
- ...requiresLLM ? { llm: buildWikiGraphLLMOptions(config) } : {}
1464
+ ...requiresLLM ? {
1465
+ llm: injectedLLM === void 0 ? buildWikiGraphLLMOptions(config) : { streamProvider: injectedLLM }
1466
+ } : {}
1291
1467
  });
1292
1468
  const documentDirectory = await prepareDigestDirectory(
1293
1469
  options.digestDirectory,
1294
1470
  requiresDigest
1295
1471
  );
1296
1472
  let chapterCount;
1473
+ let chapterPaths;
1297
1474
  const write = async (archive) => {
1298
1475
  if (requiresDigest) await options.onSourceImported?.();
1299
1476
  if (typeof archive.readToc === "function") {
1300
1477
  const toc = await archive.readToc();
1301
1478
  chapterCount = toc === void 0 ? void 0 : countTocChapters(toc.items);
1479
+ if (options.output.format === "wikg") {
1480
+ chapterPaths = toc === void 0 ? [] : collectTocChapterPaths(toc.items);
1481
+ }
1302
1482
  }
1303
1483
  await writeArchive(archive, options.output.path, options.output.format);
1304
1484
  };
@@ -1307,7 +1487,9 @@ var WikiGraphConversionManager = class {
1307
1487
  throw new Error("wikg input requires a file path.");
1308
1488
  }
1309
1489
  await app.openSession(
1310
- new NodeFile(resolveWikiGraphRuntimePath(options.input.path)),
1490
+ new NodeFile(
1491
+ await assertStandaloneWikiGraphArchivePath(options.input.path)
1492
+ ),
1311
1493
  write
1312
1494
  );
1313
1495
  } else if ("stream" in options.input) {
@@ -1350,6 +1532,7 @@ var WikiGraphConversionManager = class {
1350
1532
  const sourceArtifact = await resolveSourceArtifact(options.input);
1351
1533
  return {
1352
1534
  ...chapterCount === void 0 ? {} : { chapterCount },
1535
+ ...chapterPaths === void 0 ? {} : { chapterPaths },
1353
1536
  inputFormat: options.input.format,
1354
1537
  outputFormat: options.output.format,
1355
1538
  outputPath: options.output.path,
@@ -1362,11 +1545,12 @@ async function prepareDigestDirectory(path, required) {
1362
1545
  if (!required || normalized === void 0 || normalized === "")
1363
1546
  return void 0;
1364
1547
  const resolved = resolveWikiGraphRuntimePath(normalized);
1365
- await (0, import_promises2.rm)(resolved, { force: true, recursive: true });
1548
+ await (0, import_promises3.rm)(resolved, { force: true, recursive: true });
1366
1549
  return new NodeDirectory(resolved);
1367
1550
  }
1368
1551
  async function writeArchive(archive, path, format) {
1369
- const file = new NodeFile(resolveWikiGraphRuntimePath(path));
1552
+ const outputPath = format === "wikg" ? await assertStandaloneWikiGraphArchivePath(path) : resolveWikiGraphRuntimePath(path);
1553
+ const file = new NodeFile(outputPath);
1370
1554
  if (format === "epub") await archive.exportEpub(file);
1371
1555
  else if (format === "wikg") await archive.saveAs(file);
1372
1556
  else if (format === "pcex") throw new Error("pcex output is not supported.");
@@ -1395,7 +1579,7 @@ async function resolveSourceArtifact(input) {
1395
1579
  return {
1396
1580
  digest: hash.digest("hex"),
1397
1581
  mediaType: "application/epub+zip",
1398
- name: (0, import_path3.basename)(path)
1582
+ name: (0, import_path4.basename)(path)
1399
1583
  };
1400
1584
  }
1401
1585
  function isNodeErrorCode(error, code) {
@@ -1411,9 +1595,24 @@ function countTocChapters(items) {
1411
1595
  }
1412
1596
  return count;
1413
1597
  }
1598
+ function collectTocChapterPaths(items, ancestorKeys = []) {
1599
+ const paths = [];
1600
+ for (const item of items) {
1601
+ const key = item.key ?? `chapter-${item.serialId ?? "group"}`;
1602
+ const chapterPath = [...ancestorKeys, key];
1603
+ if (item.serialId !== void 0) paths.push(chapterPath.join("/"));
1604
+ paths.push(
1605
+ ...collectTocChapterPaths(
1606
+ item.children,
1607
+ chapterPath
1608
+ )
1609
+ );
1610
+ }
1611
+ return paths;
1612
+ }
1414
1613
 
1415
1614
  // src/query-runtime.ts
1416
- var import_wiki_graph_core3 = require("wiki-graph-core");
1615
+ var import_wiki_graph_core4 = require("wiki-graph-core");
1417
1616
 
1418
1617
  // src/embedding.ts
1419
1618
  var import_ai = require("ai");
@@ -1552,6 +1751,8 @@ function createOpenAICompatibleName2(baseURL) {
1552
1751
 
1553
1752
  // src/query-runtime.ts
1554
1753
  async function createConfiguredEmbeddingProvider() {
1754
+ const injected = getWikiGraphSDKProviders().embedding;
1755
+ if (injected !== void 0) return injected;
1555
1756
  const config = await readWikiGraphEmbeddingConfig();
1556
1757
  if (config.provider === void 0 || config.model === void 0 || config.provider === "openai-compatible" && config.baseURL === void 0 || config.provider === "openai" && config.baseURL !== void 0) {
1557
1758
  return void 0;
@@ -1561,7 +1762,7 @@ async function createConfiguredEmbeddingProvider() {
1561
1762
  async function withConfiguredWikimediaResolver(objectUri, operation) {
1562
1763
  if (!objectUri.endsWith("/wikipage")) return await operation({});
1563
1764
  const config = await loadWikiGraphRuntimeConfig();
1564
- const resolver = await (0, import_wiki_graph_core3.openWikimediaResolver)(
1765
+ const resolver = await (0, import_wiki_graph_core4.openWikimediaResolver)(
1565
1766
  config.wikimedia === void 0 ? { kind: "local" } : {
1566
1767
  endpoint: config.wikimedia.endpoint,
1567
1768
  kind: "remote",
@@ -1576,490 +1777,128 @@ async function withConfiguredWikimediaResolver(objectUri, operation) {
1576
1777
  }
1577
1778
 
1578
1779
  // src/archive/inspect.ts
1579
- var import_wiki_graph_core4 = require("wiki-graph-core");
1580
-
1581
- // src/planning.ts
1582
- var DEFAULT_GENERATION_JOB_CONCURRENCY = 3;
1583
- var DEFAULT_GENERATION_REQUEST_CONCURRENCY = 6;
1584
- function planGenerationTask(task, words, chapters, concurrent, model) {
1585
- const profile = getGenerationPlanningProfile(task);
1586
- const calls = Math.max(chapters, Math.ceil(words / profile.wordsPerCall));
1587
- const effectiveConcurrency = Math.max(
1588
- 1,
1589
- task === "reading-graph" ? 1 : concurrent.request
1590
- );
1591
- const callBatches = Math.ceil(calls / effectiveConcurrency);
1592
- const wordSeconds = words * profile.secondsPerWord;
1593
- return {
1594
- model,
1595
- timeSeconds: {
1596
- max: Math.ceil(callBatches * profile.maxSecondsPerCall + wordSeconds),
1597
- min: Math.ceil(callBatches * profile.minSecondsPerCall + wordSeconds)
1598
- },
1599
- tokens: {
1600
- cacheableInput: Math.ceil(words * profile.cacheableInputTokenPerWord),
1601
- input: Math.ceil(words * profile.inputTokenPerWord),
1602
- output: Math.ceil(words * profile.outputTokenPerWord)
1603
- }
1780
+ var import_wiki_graph_core5 = require("wiki-graph-core");
1781
+ async function inspectWikiGraphArchive(document, options) {
1782
+ const [allChapters, indexCacheCurrent, summaryWords, ...coverage] = await Promise.all([
1783
+ (0, import_wiki_graph_core5.listChapters)(document),
1784
+ (0, import_wiki_graph_core5.isArchiveSearchIndexCurrent)(document),
1785
+ readSummaryWords(document),
1786
+ document.indexArtifacts.listCoverage("fts"),
1787
+ document.indexArtifacts.listCoverage("embedding-source"),
1788
+ document.indexArtifacts.listCoverage("embedding-summary")
1789
+ ]);
1790
+ const chapters = selectChapters(allChapters, options.chapterId);
1791
+ const coverageByKind = {
1792
+ fts: byChapterId(coverage[0]),
1793
+ sourceEmbedding: byChapterId(coverage[1]),
1794
+ summaryEmbedding: byChapterId(coverage[2])
1604
1795
  };
1605
- }
1606
- function createGenerationPerformanceHints(input) {
1607
- if (!input.hasJobWork) {
1608
- return [];
1609
- }
1610
- const hints = [];
1611
- const recommendedRequest = input.concurrent.request < 4 ? DEFAULT_GENERATION_REQUEST_CONCURRENCY : input.concurrent.request < 8 ? 8 : void 0;
1612
- if (input.hasRequestWork && recommendedRequest !== void 0) {
1613
- hints.push({
1614
- configKey: "request",
1615
- configValue: recommendedRequest,
1616
- current: input.concurrent.request,
1617
- kind: "request",
1618
- message: "LLM request concurrency can often be higher. Use at least 4; 6-8 is usually faster when the provider allows it.",
1619
- recommended: recommendedRequest
1620
- });
1621
- }
1622
- if (input.concurrent.job < 4 && input.chapters > 1) {
1623
- hints.push({
1624
- configKey: "job",
1625
- configValue: 4,
1626
- current: input.concurrent.job,
1627
- kind: "job",
1628
- message: "Multiple chapters need work and job concurrency is below 4. Raising it lets chapter jobs run in parallel.",
1629
- recommended: 4
1630
- });
1631
- }
1632
- return hints;
1633
- }
1634
- function formatGenerationPlanningModel(llm) {
1635
- if (llm?.model === void 0) {
1636
- return "not configured";
1637
- }
1638
- return llm.provider === void 0 ? llm.model : `${llm.provider}/${llm.model}`;
1639
- }
1640
- function getGenerationPlanningProfile(task) {
1641
- switch (task) {
1642
- case "index-fts":
1643
- return {
1644
- cacheableInputTokenPerWord: 0,
1645
- inputTokenPerWord: 0,
1646
- maxSecondsPerCall: 1,
1647
- minSecondsPerCall: 0,
1648
- outputTokenPerWord: 0,
1649
- secondsPerWord: 5e-4,
1650
- wordsPerCall: 1e5
1651
- };
1652
- case "index-embedding-source":
1653
- case "index-embedding-summary":
1654
- return {
1655
- cacheableInputTokenPerWord: 0,
1656
- inputTokenPerWord: 0,
1657
- maxSecondsPerCall: 10,
1658
- minSecondsPerCall: 1,
1659
- outputTokenPerWord: 0,
1660
- secondsPerWord: 2e-3,
1661
- wordsPerCall: 1e4
1662
- };
1663
- case "knowledge-graph":
1664
- return {
1665
- cacheableInputTokenPerWord: 60,
1666
- inputTokenPerWord: 80,
1667
- maxSecondsPerCall: 35,
1668
- minSecondsPerCall: 15,
1669
- outputTokenPerWord: 25,
1670
- secondsPerWord: 0.02,
1671
- wordsPerCall: 35
1672
- };
1673
- case "reading-graph":
1674
- return {
1675
- cacheableInputTokenPerWord: 20,
1676
- inputTokenPerWord: 25,
1677
- maxSecondsPerCall: 45,
1678
- minSecondsPerCall: 15,
1679
- outputTokenPerWord: 4,
1680
- secondsPerWord: 0.01,
1681
- wordsPerCall: 160
1682
- };
1683
- case "reading-summary":
1796
+ const inspections = await Promise.all(
1797
+ chapters.map(async (chapter) => {
1798
+ const serial = await document.serials.getById(chapter.chapterId);
1684
1799
  return {
1685
- cacheableInputTokenPerWord: 45,
1686
- inputTokenPerWord: 55,
1687
- maxSecondsPerCall: 25,
1688
- minSecondsPerCall: 10,
1689
- outputTokenPerWord: 4,
1690
- secondsPerWord: 0.01,
1691
- wordsPerCall: 110
1800
+ capabilities: {
1801
+ knowledgeGraph: {
1802
+ completed: serial?.knowledgeGraphReady === true
1803
+ },
1804
+ readingGraph: { completed: serial?.topologyReady === true },
1805
+ readingSummary: { completed: chapter.stage === "summarized" }
1806
+ },
1807
+ chapter,
1808
+ indexes: {
1809
+ fts: inspectArtifact(
1810
+ "fts",
1811
+ coverageByKind.fts.get(chapter.chapterId)
1812
+ ),
1813
+ sourceEmbedding: inspectArtifact(
1814
+ "embedding-source",
1815
+ coverageByKind.sourceEmbedding.get(chapter.chapterId)
1816
+ ),
1817
+ summaryEmbedding: inspectArtifact(
1818
+ "embedding-summary",
1819
+ coverageByKind.summaryEmbedding.get(chapter.chapterId)
1820
+ )
1821
+ },
1822
+ revision: serial?.revision ?? 0,
1823
+ summaryWords: summaryWords.get(chapter.chapterId) ?? 0
1692
1824
  };
1693
- }
1694
- }
1695
-
1696
- // src/archive/inspect.ts
1697
- async function createWikiGraphArchiveInspectReport(document, options) {
1698
- const { archiveUri } = options;
1699
- const [
1700
- chapters,
1701
- summaryWords,
1702
- indexCacheCurrent,
1703
- config,
1704
- ftsArtifactCoverage,
1705
- sourceEmbeddingArtifactCoverage,
1706
- summaryEmbeddingArtifactCoverage
1707
- ] = await Promise.all([
1708
- readInspectChapters(document, options.chapterId),
1709
- readSummaryWords(document, options.chapterId),
1710
- (0, import_wiki_graph_core4.isArchiveSearchIndexCurrent)(document),
1711
- loadWikiGraphRuntimeConfig(),
1712
- readIndexArtifactCoverage(document, "fts", options.chapterId),
1713
- readIndexArtifactCoverage(document, "embedding-source", options.chapterId),
1714
- readIndexArtifactCoverage(document, "embedding-summary", options.chapterId)
1715
- ]);
1716
- const selectedChapter = options.chapterId === void 0 ? void 0 : chapters[0];
1717
- const scopeUri = selectedChapter === void 0 ? archiveUri : formatInspectLocatedChapterUri(archiveUri, selectedChapter);
1718
- const concurrent = {
1719
- job: config.concurrent?.job ?? DEFAULT_GENERATION_JOB_CONCURRENCY,
1720
- request: config.concurrent?.request ?? DEFAULT_GENERATION_REQUEST_CONCURRENCY
1721
- };
1722
- const planningModel = formatGenerationPlanningModel(config.llm);
1723
- const contentChapters = chapters.filter(
1724
- (chapter) => chapter.stage !== "planned"
1725
- );
1726
- const sourceWords = sumWords(contentChapters);
1727
- const readingGraphCovered = contentChapters.filter(
1728
- (chapter) => chapter.readingGraphReady
1729
- );
1730
- const knowledgeGraphCovered = contentChapters.filter(
1731
- (chapter) => chapter.knowledgeGraphReady
1732
- );
1733
- const summaryCovered = contentChapters.filter(
1734
- (chapter) => chapter.summaryReady
1735
- );
1736
- const ftsArtifactCovered = filterChaptersByCurrentIndexArtifact(
1737
- contentChapters,
1738
- ftsArtifactCoverage
1739
- );
1740
- const sourceEmbeddingArtifactCovered = filterChaptersByCurrentIndexArtifact(
1741
- contentChapters,
1742
- sourceEmbeddingArtifactCoverage
1743
- );
1744
- const summaryEmbeddingArtifactCovered = filterChaptersByCurrentIndexArtifact(
1745
- contentChapters,
1746
- summaryEmbeddingArtifactCoverage
1747
- );
1748
- const queryBlockedContentChapters = contentChapters.filter(
1749
- (chapter) => !ftsArtifactCovered.includes(chapter) && !sourceEmbeddingArtifactCovered.includes(chapter)
1750
- );
1751
- const queryBlockedChapters = queryBlockedContentChapters.map(
1752
- (chapter) => createInspectChapterReference(archiveUri, chapter)
1825
+ })
1753
1826
  );
1754
- const queryReady = queryBlockedChapters.length === 0;
1755
- const improvements = createInspectImprovements({
1756
- concurrent,
1757
- contentChapters,
1758
- indexCacheCurrent,
1759
- planningModel,
1760
- queryBlockedChapters: queryBlockedContentChapters,
1761
- summaryCovered,
1762
- knowledgeGraphCovered,
1763
- readingGraphCovered
1764
- });
1765
- const performanceHints = createGenerationPerformanceHints({
1766
- chapters: Math.max(
1767
- 0,
1768
- ...improvements.map((improvement) => improvement.missingChapters ?? 0)
1769
- ),
1770
- concurrent,
1771
- hasJobWork: improvements.some(
1772
- (improvement) => improvement.planning !== void 0
1773
- ),
1774
- hasRequestWork: improvements.some(
1775
- (improvement) => improvement.planning !== void 0
1776
- )
1777
- });
1827
+ const selected = inspections[0];
1778
1828
  return {
1779
- archiveUri,
1780
- uri: scopeUri,
1829
+ archiveUri: options.archiveUri,
1830
+ chapters: inspections,
1831
+ localIndexCache: { current: indexCacheCurrent },
1781
1832
  scope: options.chapterId === void 0 ? { type: "archive" } : { chapterId: options.chapterId, type: "chapter" },
1782
- content: {
1783
- chapters: {
1784
- content: contentChapters.length,
1785
- planned: chapters.length - contentChapters.length,
1786
- total: chapters.length
1787
- },
1788
- sourceWords,
1789
- summaryWords
1790
- },
1791
- localIndexCache: {
1792
- current: indexCacheCurrent,
1793
- ...!queryReady ? {
1794
- blockedBy: "missing-search-artifacts",
1795
- impact: "The cache cannot be built until every content chapter has a current FTS or source embedding artifact."
1796
- } : indexCacheCurrent ? {} : {
1797
- impact: "The next archive query may need to sync index cache first.",
1798
- resource: "local CPU/disk time only; no provider calls."
1799
- },
1800
- status: !queryReady ? "blocked" : indexCacheCurrent ? "current" : "missing-or-outdated",
1801
- syncAvailable: queryReady && !indexCacheCurrent
1802
- },
1803
- coverage: {
1804
- ftsIndexArtifact: createInspectCoverage(
1805
- ftsArtifactCovered,
1806
- contentChapters
1807
- ),
1808
- knowledgeGraph: createInspectCoverage(
1809
- knowledgeGraphCovered,
1810
- contentChapters
1811
- ),
1812
- readingGraph: createInspectCoverage(readingGraphCovered, contentChapters),
1813
- summary: createInspectCoverage(summaryCovered, contentChapters),
1814
- sourceEmbeddingIndexArtifact: createInspectCoverage(
1815
- sourceEmbeddingArtifactCovered,
1816
- contentChapters
1817
- ),
1818
- summaryEmbeddingIndexArtifact: createInspectCoverage(
1819
- summaryEmbeddingArtifactCovered,
1820
- contentChapters
1821
- )
1822
- },
1823
- query: {
1824
- ready: queryReady
1825
- },
1826
- searchArtifacts: {
1827
- blockedChapters: queryBlockedChapters,
1828
- ...!queryReady ? {
1829
- resource: "local CPU/disk time only; no provider calls."
1830
- } : {},
1831
- ready: queryReady,
1832
- status: queryReady ? "ready" : "incomplete"
1833
- },
1834
- retrievalGuidance: formatRetrievalGuidance({
1835
- indexCacheCurrent,
1836
- knowledgeGraphCovered,
1837
- readingGraphCovered,
1838
- contentChapters,
1839
- queryReady,
1840
- sourceWords
1841
- }),
1842
- improvements,
1843
- performanceHints,
1844
- 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."
1833
+ uri: selected === void 0 || options.chapterId === void 0 ? options.archiveUri : formatLocatedChapterUri(options.archiveUri, selected.chapter)
1845
1834
  };
1846
1835
  }
1847
- function createInspectChapterReference(archiveUri, chapter) {
1848
- return {
1849
- chapterId: chapter.chapterId,
1850
- locatedUri: formatInspectLocatedChapterUri(archiveUri, chapter),
1851
- title: chapter.title,
1852
- uri: chapter.uri
1853
- };
1854
- }
1855
- function formatInspectLocatedChapterUri(archiveUri, chapter) {
1856
- return `${archiveUri.replace(/\/+$/u, "")}/${chapter.uri.replace(/^wikg:\/\//u, "")}`;
1857
- }
1858
- async function readInspectChapters(document, chapterId) {
1859
- const chapters = chapterId === void 0 ? await (0, import_wiki_graph_core4.listChapters)(document) : (await (0, import_wiki_graph_core4.listChapters)(document)).filter(
1836
+ function selectChapters(chapters, chapterId) {
1837
+ if (chapterId === void 0) return chapters;
1838
+ const selected = chapters.filter(
1860
1839
  (chapter) => chapter.chapterId === chapterId
1861
1840
  );
1862
- if (chapterId !== void 0 && chapters.length === 0) {
1841
+ if (selected.length === 0) {
1863
1842
  throw new Error(`Chapter ${chapterId} does not exist.`);
1864
1843
  }
1865
- return await Promise.all(
1866
- chapters.map(async (chapter) => {
1867
- const serial = await document.serials.getById(chapter.chapterId);
1868
- return {
1869
- ...chapter,
1870
- knowledgeGraphReady: serial?.knowledgeGraphReady === true,
1871
- readingGraphReady: serial?.topologyReady === true,
1872
- summaryReady: chapter.stage === "summarized"
1873
- };
1874
- })
1875
- );
1876
- }
1877
- async function readSummaryWords(document, chapterId) {
1878
- return await document.readDatabase(
1879
- async (database) => await database.queryOne(
1880
- `
1881
- SELECT COALESCE(SUM(words_count), 0) AS words
1882
- FROM text_sentence_records
1883
- WHERE kind = 2
1884
- ${chapterId === void 0 ? "" : "AND chapter_id = ?"}
1885
- `,
1886
- chapterId === void 0 ? void 0 : [chapterId],
1887
- (row) => Number(row.words)
1888
- ) ?? 0
1889
- );
1844
+ return selected;
1890
1845
  }
1891
- async function readIndexArtifactCoverage(document, kind, chapterId) {
1892
- const coverage = await document.indexArtifacts.listCoverage(kind);
1893
- return chapterId === void 0 ? coverage : coverage.filter((item) => item.serialId === chapterId);
1894
- }
1895
- function filterChaptersByCurrentIndexArtifact(chapters, coverage) {
1896
- const currentChapterIds = new Set(
1897
- coverage.filter((item) => item.current).map((item) => item.serialId)
1898
- );
1899
- return chapters.filter((chapter) => currentChapterIds.has(chapter.chapterId));
1846
+ function byChapterId(coverage) {
1847
+ return new Map(coverage.map((item) => [item.serialId, item]));
1900
1848
  }
1901
- function createInspectCoverage(covered, total) {
1902
- const coveredWords = sumWords(covered);
1903
- const totalWords = sumWords(total);
1849
+ function inspectArtifact(kind, coverage) {
1904
1850
  return {
1905
- coveredChapters: covered.length,
1906
- coveredWords,
1907
- percent: formatPercent(coveredWords, totalWords),
1908
- totalChapters: total.length,
1909
- totalWords
1851
+ current: coverage?.current === true,
1852
+ exists: coverage?.sourceRevision !== void 0,
1853
+ kind,
1854
+ ...coverage?.sourceRevision === void 0 ? {} : { sourceRevision: coverage.sourceRevision }
1910
1855
  };
1911
1856
  }
1912
- function formatRetrievalGuidance(input) {
1913
- if (input.sourceWords === 0 || input.contentChapters.length === 0) {
1914
- return [
1915
- "Source content: empty.",
1916
- "Add source text before using query coverage or graph-based retrieval."
1917
- ];
1918
- }
1919
- const lines = [
1920
- 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."
1921
- ];
1922
- lines.push(
1923
- formatObjectSearchGuidance(
1924
- "Reading Graph object retrieval",
1925
- input.readingGraphCovered,
1926
- input.contentChapters
1927
- )
1928
- );
1929
- lines.push(
1930
- formatObjectSearchGuidance(
1931
- "Entity/triple retrieval",
1932
- input.knowledgeGraphCovered,
1933
- input.contentChapters
1857
+ async function readSummaryWords(document) {
1858
+ const rows = await document.readDatabase(
1859
+ async (database) => await database.queryAll(
1860
+ `
1861
+ SELECT chapter_id, COALESCE(SUM(words_count), 0) AS words
1862
+ FROM text_sentence_records
1863
+ WHERE kind = 2
1864
+ GROUP BY chapter_id
1865
+ `,
1866
+ void 0,
1867
+ (row) => ({
1868
+ chapterId: Number(row.chapter_id),
1869
+ words: Number(row.words)
1870
+ })
1934
1871
  )
1935
1872
  );
1936
- return lines;
1937
- }
1938
- function formatObjectSearchGuidance(label, covered, total) {
1939
- const coveredWords = sumWords(covered);
1940
- const totalWords = sumWords(total);
1941
- const ratio = totalWords === 0 ? 0 : coveredWords / totalWords;
1942
- const coverage = formatPercent(coveredWords, totalWords);
1943
- if (ratio >= 1) {
1944
- return `${label}: covers all source content; it can represent the full scope for object retrieval.`;
1945
- }
1946
- if (ratio >= 0.9) {
1947
- return `${label}: covers ${coverage}; use it as the main path, but source --query is needed for uncovered content.`;
1948
- }
1949
- if (ratio >= 0.5) {
1950
- return `${label}: covers ${coverage}; use it as leads, not as a full-scope substitute for source --query.`;
1951
- }
1952
- return `${label}: covers ${coverage}; build missing graph coverage before relying on object retrieval.`;
1953
- }
1954
- function createInspectImprovements(input) {
1955
- const improvements = [];
1956
- if (input.contentChapters.length === 0) {
1957
- improvements.push({
1958
- kind: "add-source",
1959
- recommendation: "No source content is available yet; add or import source text before graph or summary generation.",
1960
- title: "Add source content"
1961
- });
1962
- return improvements;
1963
- }
1964
- if (input.queryBlockedChapters.length > 0) {
1965
- improvements.push({
1966
- kind: "build",
1967
- missingChapters: input.queryBlockedChapters.length,
1968
- missingWords: sumWords(input.queryBlockedChapters),
1969
- recommendation: "Build local FTS artifacts to make this scope queryable. This does not call a provider.",
1970
- task: "index-fts",
1971
- title: "Enable query with local FTS"
1972
- });
1973
- } else if (!input.indexCacheCurrent) {
1974
- improvements.push({
1975
- kind: "sync-index",
1976
- recommendation: "Sync the index cache from chapter index artifacts so query starts without a lazy cache rebuild.",
1977
- title: "Sync index cache"
1978
- });
1979
- }
1980
- improvements.push(
1981
- ...createGraphImprovement({
1982
- concurrent: input.concurrent,
1983
- covered: input.readingGraphCovered,
1984
- planningModel: input.planningModel,
1985
- task: "reading-graph",
1986
- title: "Complete Reading Graph coverage",
1987
- total: input.contentChapters
1988
- })
1989
- );
1990
- improvements.push(
1991
- ...createGraphImprovement({
1992
- concurrent: input.concurrent,
1993
- covered: input.knowledgeGraphCovered,
1994
- planningModel: input.planningModel,
1995
- task: "knowledge-graph",
1996
- title: "Complete Knowledge Graph coverage",
1997
- total: input.contentChapters
1998
- })
1999
- );
2000
- improvements.push(
2001
- ...createGraphImprovement({
2002
- concurrent: input.concurrent,
2003
- covered: input.summaryCovered,
2004
- planningModel: input.planningModel,
2005
- task: "reading-summary",
2006
- title: "Complete Summary coverage",
2007
- total: input.contentChapters
2008
- })
2009
- );
2010
- return improvements;
1873
+ return new Map(rows.map((row) => [row.chapterId, row.words]));
2011
1874
  }
2012
- function createGraphImprovement(input) {
2013
- const coveredIds = new Set(input.covered.map((chapter) => chapter.chapterId));
2014
- const missing = input.total.filter(
2015
- (chapter) => !coveredIds.has(chapter.chapterId)
2016
- );
2017
- if (missing.length === 0) {
2018
- return [];
2019
- }
2020
- const missingWords = sumWords(missing);
2021
- return [
2022
- {
2023
- kind: "build",
2024
- missingChapters: missing.length,
2025
- missingWords,
2026
- planning: planGenerationTask(
2027
- input.task,
2028
- missingWords,
2029
- missing.length,
2030
- input.concurrent,
2031
- input.planningModel
2032
- ),
2033
- recommendation: formatImprovementRecommendation(
2034
- input.covered,
2035
- input.total,
2036
- missingWords
2037
- ),
2038
- task: input.task,
2039
- title: input.title
2040
- }
2041
- ];
2042
- }
2043
- function formatImprovementRecommendation(covered, total, missingWords) {
2044
- const totalWords = sumWords(total);
2045
- const coveredWords = sumWords(covered);
2046
- if (totalWords === 0) {
2047
- return "No source content is available.";
2048
- }
2049
- if (total.length === 1 || coveredWords / totalWords >= 0.9 || missingWords <= 1e3) {
2050
- return "Queue the full scope to finish the remaining gap.";
2051
- }
2052
- return "Queue selected chapters first if only part of the scope matters.";
2053
- }
2054
- function sumWords(chapters) {
2055
- return chapters.reduce((total, chapter) => total + chapter.words, 0);
1875
+ function formatLocatedChapterUri(archiveUri, chapter) {
1876
+ return `${archiveUri.replace(/\/+$/u, "")}/${chapter.uri.replace(/^wikg:\/\//u, "")}`;
2056
1877
  }
2057
- function formatPercent(numerator, denominator) {
2058
- if (denominator === 0) {
2059
- return "n/a";
1878
+
1879
+ // src/archive/write.ts
1880
+ var import_wiki_graph_core6 = require("wiki-graph-core");
1881
+ async function writeWikiGraphArchiveLocation(location, operation, options = {}) {
1882
+ const cacheOnly = options.searchIndexWritebackPolicy === "cache";
1883
+ const write = async (archiveFile = location.archiveFile) => await new import_wiki_graph_core6.WikiGraphArchiveFile(archiveFile).write(operation, {
1884
+ ...cacheOnly ? {} : { derivedStateKeys: [location.archiveKey, location.archivePath] },
1885
+ ...options.invalidateContinuationCursors === void 0 ? {} : {
1886
+ invalidateContinuationCursors: options.invalidateContinuationCursors
1887
+ },
1888
+ ...options.searchIndexWritebackPolicy === void 0 ? {} : { searchIndexWritebackPolicy: options.searchIndexWritebackPolicy }
1889
+ });
1890
+ if (location.libraryArchiveTarget === void 0 || cacheOnly || options.refreshLibraryIndex === false) {
1891
+ return await write();
2060
1892
  }
2061
- const percent = numerator / denominator * 100;
2062
- return `${Number.isInteger(percent) ? percent.toFixed(0) : percent.toFixed(1)}%`;
1893
+ return await (0, import_wiki_graph_core6.writeWikiGraphLibraryArchive)({
1894
+ additionalDerivedStateKeys: [location.archiveKey, location.archivePath],
1895
+ ...options.invalidateContinuationCursors === void 0 ? {} : {
1896
+ invalidateContinuationCursors: options.invalidateContinuationCursors
1897
+ },
1898
+ ...options.onIndexSyncError === void 0 ? {} : { onIndexSyncError: options.onIndexSyncError },
1899
+ operation: async (archiveFile) => await write(archiveFile),
1900
+ target: location.libraryArchiveTarget
1901
+ });
2063
1902
  }
2064
1903
 
2065
1904
  // src/archive/archive.ts
@@ -2079,13 +1918,13 @@ var WikiGraphArchiveManager = class {
2079
1918
  }
2080
1919
  async create(options) {
2081
1920
  return await this.#runtime.run(async () => {
2082
- const path = resolveWikiGraphRuntimePath(options.path);
1921
+ const path = await assertStandaloneWikiGraphArchivePath(options.path);
2083
1922
  if (options.replace !== true && await nodePathExists(path)) {
2084
1923
  throw new WikiGraphArchiveExistsError(path);
2085
1924
  }
2086
- const outputPath = (0, import_path4.join)(
2087
- (0, import_path4.dirname)(path),
2088
- `.${(0, import_path4.basename)(path)}.${(0, import_crypto2.randomUUID)()}.tmp.wikg`
1925
+ const outputPath = (0, import_path5.join)(
1926
+ (0, import_path5.dirname)(path),
1927
+ `.${(0, import_path5.basename)(path)}.${(0, import_crypto2.randomUUID)()}.tmp.wikg`
2089
1928
  );
2090
1929
  try {
2091
1930
  if (options.importPath === void 0) {
@@ -2099,10 +1938,10 @@ var WikiGraphArchiveManager = class {
2099
1938
  });
2100
1939
  }
2101
1940
  if (options.replace === true) {
2102
- await (0, import_promises3.rename)(outputPath, path);
1941
+ await (0, import_promises4.rename)(outputPath, path);
2103
1942
  } else {
2104
1943
  try {
2105
- await (0, import_promises3.link)(outputPath, path);
1944
+ await (0, import_promises4.link)(outputPath, path);
2106
1945
  } catch (error) {
2107
1946
  if (isNodeEEXISTError(error)) {
2108
1947
  throw new WikiGraphArchiveExistsError(path);
@@ -2110,15 +1949,15 @@ var WikiGraphArchiveManager = class {
2110
1949
  throw error;
2111
1950
  }
2112
1951
  }
2113
- return { locatedUri: (0, import_wiki_graph_core5.formatLocatedWikiGraphUri)(path), path };
1952
+ return { locatedUri: (0, import_wiki_graph_core7.formatLocatedWikiGraphUri)(path), path };
2114
1953
  } finally {
2115
- await (0, import_promises3.rm)(outputPath, { force: true, recursive: true });
1954
+ await (0, import_promises4.rm)(outputPath, { force: true, recursive: true });
2116
1955
  }
2117
1956
  }, options.signal);
2118
1957
  }
2119
- async open(uriOrPath, options = {}) {
1958
+ async open(target, options = {}) {
2120
1959
  const location = await this.#runtime.run(
2121
- async () => await resolveWikiGraphArchiveLocation(uriOrPath),
1960
+ async () => await resolveWikiGraphArchiveLocation(target),
2122
1961
  options.signal
2123
1962
  );
2124
1963
  return new WikiGraphArchiveHandle(this.#runtime, location);
@@ -2141,14 +1980,17 @@ var WikiGraphArchiveHandle = class {
2141
1980
  return this.#location.locatedUri;
2142
1981
  }
2143
1982
  get objectUri() {
2144
- return (0, import_wiki_graph_core5.parseLocatedWikiGraphUri)(this.#location.locatedUri).objectUri ?? "wikg://";
1983
+ return (0, import_wiki_graph_core7.parseLocatedWikiGraphUri)(this.#location.locatedUri).objectUri ?? "wikg://";
2145
1984
  }
2146
1985
  get path() {
2147
1986
  return this.#location.archivePath;
2148
1987
  }
1988
+ get target() {
1989
+ return this.#location.target;
1990
+ }
2149
1991
  async inspect(options = {}) {
2150
1992
  return await this.#readDocument(
2151
- async (document) => await createWikiGraphArchiveInspectReport(document, {
1993
+ async (document) => await inspectWikiGraphArchive(document, {
2152
1994
  archiveUri: this.#location.publicArchiveUri ?? this.locatedUri,
2153
1995
  ...options.chapterId === void 0 ? {} : { chapterId: options.chapterId }
2154
1996
  }),
@@ -2156,18 +1998,20 @@ var WikiGraphArchiveHandle = class {
2156
1998
  );
2157
1999
  }
2158
2000
  async search(query, options = {}) {
2159
- const embeddingProvider = await this.#runtime.run(
2160
- createConfiguredEmbeddingProvider,
2001
+ const embeddingProvider = await this.#resolveQueryEmbeddingProvider(
2002
+ options.queryMode,
2161
2003
  options.signal
2162
2004
  );
2163
2005
  return await this.#writeDocument(
2164
2006
  async (document) => {
2165
- const chapters = await this.#resolveQueryChapters(document, options);
2007
+ const chapters = await this.#resolveQueryChapters(document, options, {
2008
+ embeddingProvider
2009
+ });
2166
2010
  await ensureArchiveSearchIndex(document, {
2167
2011
  ...chapters === void 0 ? {} : { chapters },
2168
2012
  ...embeddingProvider === void 0 ? {} : { embeddingProvider }
2169
2013
  });
2170
- return await (0, import_wiki_graph_core5.findArchiveObjects)(document, query, {
2014
+ return await (0, import_wiki_graph_core7.findArchiveObjects)(document, query, {
2171
2015
  ...withoutOperationAndScope(options),
2172
2016
  archiveKey: this.archiveKey,
2173
2017
  ...chapters === void 0 ? {} : { chapters },
@@ -2182,14 +2026,14 @@ var WikiGraphArchiveHandle = class {
2182
2026
  }
2183
2027
  async list(options = {}) {
2184
2028
  return await this.#readDocument(async (document) => {
2185
- if ((0, import_wiki_graph_core5.isSourceLocatorScopeUri)(this.objectUri)) {
2186
- return await (0, import_wiki_graph_core5.listArchiveSourceLocators)(document, this.objectUri, {
2029
+ if ((0, import_wiki_graph_core7.isSourceLocatorScopeUri)(this.objectUri)) {
2030
+ return await (0, import_wiki_graph_core7.listArchiveSourceLocators)(document, this.objectUri, {
2187
2031
  ...options.cursor === void 0 ? {} : { cursor: options.cursor },
2188
2032
  ...options.limit === void 0 ? {} : { limit: options.limit }
2189
2033
  });
2190
2034
  }
2191
2035
  const chapters = await this.#resolveScope(document, options);
2192
- return await (0, import_wiki_graph_core5.listArchiveCollection)(document, {
2036
+ return await (0, import_wiki_graph_core7.listArchiveCollection)(document, {
2193
2037
  ...withoutOperationAndScope(options),
2194
2038
  ...chapters === void 0 ? {} : { chapters }
2195
2039
  });
@@ -2217,8 +2061,8 @@ var WikiGraphArchiveHandle = class {
2217
2061
  async getSearchIndexStatus(options = {}) {
2218
2062
  return await this.#readDocument(
2219
2063
  async (document) => ({
2220
- capabilities: await (0, import_wiki_graph_core5.readSearchIndexCapabilityStatus)(document),
2221
- current: await (0, import_wiki_graph_core5.isArchiveSearchIndexCurrent)(document)
2064
+ capabilities: await (0, import_wiki_graph_core7.readSearchIndexCapabilityStatus)(document),
2065
+ current: await (0, import_wiki_graph_core7.isArchiveSearchIndexCurrent)(document)
2222
2066
  }),
2223
2067
  options
2224
2068
  );
@@ -2226,14 +2070,14 @@ var WikiGraphArchiveHandle = class {
2226
2070
  async syncSearchIndex(options = {}) {
2227
2071
  const rebuilt = await this.#writeDocument(
2228
2072
  async (document) => {
2229
- const scope = options.skipUnindexed === true ? { chapters: await (0, import_wiki_graph_core5.listArchiveQueryableChapterIds)(document) } : {};
2073
+ const scope = options.skipUnindexed === true ? { chapters: await (0, import_wiki_graph_core7.listArchiveQueryableChapterIds)(document) } : {};
2230
2074
  if (scope.chapters?.length === 0) {
2231
2075
  throw new Error(
2232
2076
  "Wiki Graph index cache is not ready. No chapters have a current FTS artifact or source embedding artifact."
2233
2077
  );
2234
2078
  }
2235
- if (await (0, import_wiki_graph_core5.isArchiveSearchIndexCurrent)(document, scope)) return false;
2236
- await (0, import_wiki_graph_core5.rebuildArchiveSearchIndex)(document, options.onProgress, scope);
2079
+ if (await (0, import_wiki_graph_core7.isArchiveSearchIndexCurrent)(document, scope)) return false;
2080
+ await (0, import_wiki_graph_core7.rebuildArchiveSearchIndex)(document, options.onProgress, scope);
2237
2081
  return true;
2238
2082
  },
2239
2083
  {
@@ -2242,7 +2086,7 @@ var WikiGraphArchiveHandle = class {
2242
2086
  }
2243
2087
  );
2244
2088
  await this.#runtime.run(
2245
- async () => await (0, import_wiki_graph_core5.deleteArchiveSearchSessions)(this.path),
2089
+ async () => await (0, import_wiki_graph_core7.deleteArchiveSearchSessions)(this.path),
2246
2090
  options.signal
2247
2091
  );
2248
2092
  return { rebuilt };
@@ -2265,21 +2109,21 @@ var WikiGraphArchiveHandle = class {
2265
2109
  }
2266
2110
  );
2267
2111
  await this.#runtime.run(
2268
- async () => await (0, import_wiki_graph_core5.deleteArchiveSearchSessions)(this.path),
2112
+ async () => await (0, import_wiki_graph_core7.deleteArchiveSearchSessions)(this.path),
2269
2113
  options.signal
2270
2114
  );
2271
2115
  return status;
2272
2116
  }
2273
2117
  async listChapters(options = {}) {
2274
2118
  return await this.#readDocument(
2275
- async (document) => await (0, import_wiki_graph_core5.listChapters)(document),
2119
+ async (document) => await (0, import_wiki_graph_core7.listChapters)(document),
2276
2120
  options
2277
2121
  );
2278
2122
  }
2279
2123
  async getChapter(path, options = {}) {
2280
2124
  return await this.#readDocument(async (document) => {
2281
- const chapterId = await (0, import_wiki_graph_core5.resolveChapterPathReadonly)(document, path);
2282
- return requireChapter(await (0, import_wiki_graph_core5.listChapters)(document), chapterId);
2125
+ const chapterId = await (0, import_wiki_graph_core7.resolveChapterPathReadonly)(document, path);
2126
+ return requireChapter(await (0, import_wiki_graph_core7.listChapters)(document), chapterId);
2283
2127
  }, options);
2284
2128
  }
2285
2129
  async addChapter(options) {
@@ -2288,17 +2132,17 @@ var WikiGraphArchiveHandle = class {
2288
2132
  document,
2289
2133
  options.parentPath
2290
2134
  );
2291
- await (0, import_wiki_graph_core5.assertNoActiveBuildJobConflicts)({
2135
+ await (0, import_wiki_graph_core7.assertNoActiveBuildJobConflicts)({
2292
2136
  archive: this.#location.archiveFile,
2293
2137
  operation: "Adding chapter",
2294
2138
  scope: { kind: "archive" }
2295
2139
  });
2296
- let details = await (0, import_wiki_graph_core5.addChapter)(document, {
2140
+ let details = await (0, import_wiki_graph_core7.addChapter)(document, {
2297
2141
  ...parentChapterId === void 0 ? {} : { parentChapterId },
2298
2142
  ...options.title === void 0 ? {} : { title: options.title }
2299
2143
  });
2300
2144
  if (options.source !== void 0) {
2301
- details = await (0, import_wiki_graph_core5.setChapterSource)(
2145
+ details = await (0, import_wiki_graph_core7.setChapterSource)(
2302
2146
  document,
2303
2147
  details.chapterId,
2304
2148
  asTextStream(options.source)
@@ -2309,7 +2153,7 @@ var WikiGraphArchiveHandle = class {
2309
2153
  }
2310
2154
  async getChapterArtifact(path, kind) {
2311
2155
  return await this.#readDocument(async (document) => {
2312
- const chapterId = await (0, import_wiki_graph_core5.resolveChapterPathReadonly)(document, path);
2156
+ const chapterId = await (0, import_wiki_graph_core7.resolveChapterPathReadonly)(document, path);
2313
2157
  const [artifact, revision] = await Promise.all([
2314
2158
  document.indexArtifacts.get(chapterId, kind),
2315
2159
  document.serials.getRevision(chapterId)
@@ -2332,25 +2176,25 @@ var WikiGraphArchiveHandle = class {
2332
2176
  }
2333
2177
  async deleteChapterArtifact(path, kind) {
2334
2178
  return await this.#writeDocument(async (document) => {
2335
- const chapterId = await (0, import_wiki_graph_core5.resolveChapterPathReadonly)(document, path);
2179
+ const chapterId = await (0, import_wiki_graph_core7.resolveChapterPathReadonly)(document, path);
2336
2180
  await document.indexArtifacts.delete(chapterId, kind);
2337
2181
  return { chapterId, deleted: true, kind };
2338
2182
  });
2339
2183
  }
2340
2184
  async moveChapter(path, options) {
2341
2185
  return await this.#writeDocument(async (document) => {
2342
- const chapterId = await (0, import_wiki_graph_core5.resolveChapterPathReadonly)(document, path);
2186
+ const chapterId = await (0, import_wiki_graph_core7.resolveChapterPathReadonly)(document, path);
2343
2187
  const [afterChapterId, beforeChapterId, parentChapterId] = await Promise.all([
2344
2188
  resolveOptionalChapterPath(document, options.afterPath),
2345
2189
  resolveOptionalChapterPath(document, options.beforePath),
2346
2190
  resolveOptionalChapterPath(document, options.parentPath)
2347
2191
  ]);
2348
- await (0, import_wiki_graph_core5.assertNoActiveBuildJobConflicts)({
2192
+ await (0, import_wiki_graph_core7.assertNoActiveBuildJobConflicts)({
2349
2193
  archive: this.#location.archiveFile,
2350
2194
  operation: "Moving chapter",
2351
2195
  scope: { kind: "archive" }
2352
2196
  });
2353
- return await (0, import_wiki_graph_core5.moveChapter)(document, chapterId, {
2197
+ return await (0, import_wiki_graph_core7.moveChapter)(document, chapterId, {
2354
2198
  ...afterChapterId === void 0 ? {} : { afterChapterId },
2355
2199
  ...beforeChapterId === void 0 ? {} : { beforeChapterId },
2356
2200
  ...parentChapterId === void 0 ? {} : { parentChapterId },
@@ -2362,35 +2206,35 @@ var WikiGraphArchiveHandle = class {
2362
2206
  }
2363
2207
  async removeChapter(path, recursive = false) {
2364
2208
  await this.#writeDocument(async (document) => {
2365
- const chapterId = await (0, import_wiki_graph_core5.resolveChapterPathReadonly)(document, path);
2366
- await (0, import_wiki_graph_core5.assertNoActiveBuildJobConflicts)({
2209
+ const chapterId = await (0, import_wiki_graph_core7.resolveChapterPathReadonly)(document, path);
2210
+ await (0, import_wiki_graph_core7.assertNoActiveBuildJobConflicts)({
2367
2211
  archive: this.#location.archiveFile,
2368
2212
  operation: "Removing chapter",
2369
2213
  scope: { kind: "archive" }
2370
2214
  });
2371
- await (0, import_wiki_graph_core5.removeChapter)(document, chapterId, { recursive });
2215
+ await (0, import_wiki_graph_core7.removeChapter)(document, chapterId, { recursive });
2372
2216
  });
2373
2217
  }
2374
2218
  async resetChapter(path, stage) {
2375
2219
  return await this.#writeDocument(async (document) => {
2376
- const chapterId = await (0, import_wiki_graph_core5.resolveChapterPathReadonly)(document, path);
2220
+ const chapterId = await (0, import_wiki_graph_core7.resolveChapterPathReadonly)(document, path);
2377
2221
  await assertChapterResetAllowed(
2378
2222
  this.#location.archiveFile,
2379
2223
  chapterId,
2380
2224
  stage
2381
2225
  );
2382
- return await (0, import_wiki_graph_core5.resetChapter)(document, chapterId, stage);
2226
+ return await (0, import_wiki_graph_core7.resetChapter)(document, chapterId, stage);
2383
2227
  });
2384
2228
  }
2385
2229
  async setChapterSource(path, source, options = {}) {
2386
2230
  return await this.#writeDocument(async (document) => {
2387
- const chapterId = await (0, import_wiki_graph_core5.resolveChapterPathReadonly)(document, path);
2388
- await (0, import_wiki_graph_core5.assertNoActiveBuildJobs)({
2231
+ const chapterId = await (0, import_wiki_graph_core7.resolveChapterPathReadonly)(document, path);
2232
+ await (0, import_wiki_graph_core7.assertNoActiveBuildJobs)({
2389
2233
  archive: this.#location.archiveFile,
2390
2234
  chapterIds: [chapterId],
2391
2235
  operation: "Setting chapter source"
2392
2236
  });
2393
- return await (0, import_wiki_graph_core5.setChapterSource)(
2237
+ return await (0, import_wiki_graph_core7.setChapterSource)(
2394
2238
  document,
2395
2239
  chapterId,
2396
2240
  asTextStream(source),
@@ -2400,43 +2244,43 @@ var WikiGraphArchiveHandle = class {
2400
2244
  }
2401
2245
  async setChapterSummary(path, summary) {
2402
2246
  return await this.#writeDocument(async (document) => {
2403
- const chapterId = await (0, import_wiki_graph_core5.resolveChapterPathReadonly)(document, path);
2404
- await (0, import_wiki_graph_core5.assertNoActiveBuildJobs)({
2247
+ const chapterId = await (0, import_wiki_graph_core7.resolveChapterPathReadonly)(document, path);
2248
+ await (0, import_wiki_graph_core7.assertNoActiveBuildJobs)({
2405
2249
  archive: this.#location.archiveFile,
2406
2250
  chapterIds: [chapterId],
2407
2251
  operation: "Setting chapter summary",
2408
2252
  requiresTarget: "reading-summary"
2409
2253
  });
2410
- return await (0, import_wiki_graph_core5.setChapterSummary)(document, chapterId, summary);
2254
+ return await (0, import_wiki_graph_core7.setChapterSummary)(document, chapterId, summary);
2411
2255
  });
2412
2256
  }
2413
2257
  async setChapterTitle(path, title) {
2414
2258
  return await this.#writeDocument(async (document) => {
2415
- const chapterId = await (0, import_wiki_graph_core5.resolveChapterPathReadonly)(document, path);
2416
- await (0, import_wiki_graph_core5.assertNoActiveBuildJobs)({
2259
+ const chapterId = await (0, import_wiki_graph_core7.resolveChapterPathReadonly)(document, path);
2260
+ await (0, import_wiki_graph_core7.assertNoActiveBuildJobs)({
2417
2261
  archive: this.#location.archiveFile,
2418
2262
  chapterIds: [chapterId],
2419
2263
  operation: "Setting chapter title"
2420
2264
  });
2421
- return await (0, import_wiki_graph_core5.setChapterTitle)(document, chapterId, title);
2265
+ return await (0, import_wiki_graph_core7.setChapterTitle)(document, chapterId, title);
2422
2266
  });
2423
2267
  }
2424
2268
  async getChapterTree() {
2425
2269
  return await this.#readDocument(
2426
- async (document) => await (0, import_wiki_graph_core5.getChapterTree)(document)
2270
+ async (document) => await (0, import_wiki_graph_core7.getChapterTree)(document)
2427
2271
  );
2428
2272
  }
2429
2273
  async applyChapterTree(tree, options = {}) {
2430
2274
  return await this.#writeDocument(
2431
2275
  async (document) => {
2432
2276
  if (options.dryRun !== true) {
2433
- await (0, import_wiki_graph_core5.assertNoActiveBuildJobConflicts)({
2277
+ await (0, import_wiki_graph_core7.assertNoActiveBuildJobConflicts)({
2434
2278
  archive: this.#location.archiveFile,
2435
2279
  operation: "Changing chapter tree",
2436
2280
  scope: { kind: "archive" }
2437
2281
  });
2438
2282
  }
2439
- return await (0, import_wiki_graph_core5.applyChapterTree)(document, tree, {
2283
+ return await (0, import_wiki_graph_core7.applyChapterTree)(document, tree, {
2440
2284
  dryRun: options.dryRun ?? false
2441
2285
  });
2442
2286
  },
@@ -2448,8 +2292,8 @@ var WikiGraphArchiveHandle = class {
2448
2292
  async () => await withConfiguredWikimediaResolver(
2449
2293
  objectUri,
2450
2294
  async (wikimediaOptions) => await this.#readDocument(
2451
- async (document) => await (0, import_wiki_graph_core5.readArchivePage)(document, objectUri, {
2452
- ...withoutOperation(options),
2295
+ async (document) => await (0, import_wiki_graph_core7.readArchivePage)(document, objectUri, {
2296
+ ...options,
2453
2297
  ...wikimediaOptions
2454
2298
  }),
2455
2299
  options
@@ -2460,27 +2304,33 @@ var WikiGraphArchiveHandle = class {
2460
2304
  }
2461
2305
  async related(objectUri = this.objectUri, options = {}) {
2462
2306
  if (options.query === void 0) {
2307
+ if (options.queryMode !== void 0) {
2308
+ throw new Error("`queryMode` requires `query`.");
2309
+ }
2463
2310
  return await this.#readDocument(async (document) => {
2464
2311
  const chapters = await this.#resolveScope(document, {});
2465
- return await (0, import_wiki_graph_core5.listRelatedArchiveObjects)(document, objectUri, {
2312
+ return await (0, import_wiki_graph_core7.listRelatedArchiveObjects)(document, objectUri, {
2466
2313
  ...withoutOperation(options),
2467
2314
  ...chapters === void 0 ? {} : { chapters }
2468
2315
  });
2469
2316
  }, options);
2470
2317
  }
2471
- const embeddingProvider = await this.#runtime.run(
2472
- createConfiguredEmbeddingProvider,
2318
+ const embeddingProvider = await this.#resolveQueryEmbeddingProvider(
2319
+ options.queryMode,
2473
2320
  options.signal
2474
2321
  );
2475
2322
  return await this.#writeDocument(
2476
2323
  async (document) => {
2477
- const chapters = await this.#resolveQueryChapters(document, options);
2324
+ const chapters = await this.#resolveQueryChapters(document, options, {
2325
+ embeddingProvider
2326
+ });
2478
2327
  await ensureArchiveSearchIndex(document, {
2479
2328
  ...chapters === void 0 ? {} : { chapters },
2480
2329
  ...embeddingProvider === void 0 ? {} : { embeddingProvider }
2481
2330
  });
2482
- return await (0, import_wiki_graph_core5.listRelatedArchiveObjects)(document, objectUri, {
2331
+ return await (0, import_wiki_graph_core7.listRelatedArchiveObjects)(document, objectUri, {
2483
2332
  ...withoutOperation(options),
2333
+ ...embeddingProvider === void 0 ? {} : { embeddingProvider },
2484
2334
  ...chapters === void 0 ? {} : { chapters }
2485
2335
  });
2486
2336
  },
@@ -2492,27 +2342,33 @@ var WikiGraphArchiveHandle = class {
2492
2342
  }
2493
2343
  async evidence(objectUri = this.objectUri, options = {}) {
2494
2344
  if (options.query === void 0) {
2345
+ if (options.queryMode !== void 0) {
2346
+ throw new Error("`queryMode` requires `query`.");
2347
+ }
2495
2348
  return await this.#readDocument(async (document) => {
2496
2349
  const chapters = await this.#resolveScope(document, {});
2497
- return await (0, import_wiki_graph_core5.listArchiveEvidence)(document, objectUri, {
2350
+ return await (0, import_wiki_graph_core7.listArchiveEvidence)(document, objectUri, {
2498
2351
  ...withoutOperation(options),
2499
2352
  ...chapters === void 0 ? {} : { chapters }
2500
2353
  });
2501
2354
  }, options);
2502
2355
  }
2503
- const embeddingProvider = await this.#runtime.run(
2504
- createConfiguredEmbeddingProvider,
2356
+ const embeddingProvider = await this.#resolveQueryEmbeddingProvider(
2357
+ options.queryMode,
2505
2358
  options.signal
2506
2359
  );
2507
2360
  return await this.#writeDocument(
2508
2361
  async (document) => {
2509
- const chapters = await this.#resolveQueryChapters(document, options);
2362
+ const chapters = await this.#resolveQueryChapters(document, options, {
2363
+ embeddingProvider
2364
+ });
2510
2365
  await ensureArchiveSearchIndex(document, {
2511
2366
  ...chapters === void 0 ? {} : { chapters },
2512
2367
  ...embeddingProvider === void 0 ? {} : { embeddingProvider }
2513
2368
  });
2514
- return await (0, import_wiki_graph_core5.listArchiveEvidence)(document, objectUri, {
2369
+ return await (0, import_wiki_graph_core7.listArchiveEvidence)(document, objectUri, {
2515
2370
  ...withoutOperation(options),
2371
+ ...embeddingProvider === void 0 ? {} : { embeddingProvider },
2516
2372
  ...chapters === void 0 ? {} : { chapters }
2517
2373
  });
2518
2374
  },
@@ -2524,7 +2380,7 @@ var WikiGraphArchiveHandle = class {
2524
2380
  }
2525
2381
  async pack(objectUri = this.objectUri, budget = 5e3, options = {}) {
2526
2382
  return await this.#readDocument(
2527
- async (document) => await (0, import_wiki_graph_core5.packArchiveContext)(document, objectUri, budget),
2383
+ async (document) => await (0, import_wiki_graph_core7.packArchiveContext)(document, objectUri, budget),
2528
2384
  options
2529
2385
  );
2530
2386
  }
@@ -2546,8 +2402,26 @@ var WikiGraphArchiveHandle = class {
2546
2402
  return meta;
2547
2403
  }, options);
2548
2404
  }
2405
+ async setArchiveTitle(title, options = {}) {
2406
+ const normalized = title?.trim() ?? null;
2407
+ if (title !== null && normalized === "") {
2408
+ throw new Error("Archive title cannot be empty.");
2409
+ }
2410
+ return await this.#writeDocument(async (document) => {
2411
+ if (normalized === null) {
2412
+ await document.metadata.deleteKey("", "title");
2413
+ } else {
2414
+ await document.metadata.put(
2415
+ { kind: import_wiki_graph_core7.ObjectMetadataKind.Archive, objectPath: "" },
2416
+ "title",
2417
+ normalized
2418
+ );
2419
+ }
2420
+ return normalized;
2421
+ }, options);
2422
+ }
2549
2423
  async readCover(options = {}) {
2550
- const app = new import_wiki_graph_core5.WikiGraph({});
2424
+ const app = new import_wiki_graph_core7.WikiGraph({});
2551
2425
  return await this.#runtime.run(
2552
2426
  async () => await app.openSession(
2553
2427
  this.#location.archiveFile,
@@ -2595,7 +2469,7 @@ var WikiGraphArchiveHandle = class {
2595
2469
  }
2596
2470
  async #readDocument(operation, options = {}) {
2597
2471
  return await this.#runtime.run(
2598
- async () => await new import_wiki_graph_core5.WikiGraphArchiveFile(this.#location.archiveFile).readDocument(
2472
+ async () => await new import_wiki_graph_core7.WikiGraphArchiveFile(this.#location.archiveFile).readDocument(
2599
2473
  operation
2600
2474
  ),
2601
2475
  options.signal
@@ -2603,28 +2477,33 @@ var WikiGraphArchiveHandle = class {
2603
2477
  }
2604
2478
  async #writeDocument(operation, options = {}) {
2605
2479
  return await this.#runtime.run(async () => {
2606
- const result = await new import_wiki_graph_core5.WikiGraphArchiveFile(
2607
- this.#location.archiveFile
2608
- ).write(operation, {
2480
+ return await writeWikiGraphArchiveLocation(this.#location, operation, {
2481
+ ...options.onIndexSyncError === void 0 ? {} : { onIndexSyncError: options.onIndexSyncError },
2482
+ ...options.refreshLibraryIndex === void 0 ? {} : { refreshLibraryIndex: options.refreshLibraryIndex },
2609
2483
  ...options.searchIndexWritebackPolicy === void 0 ? {} : {
2610
2484
  searchIndexWritebackPolicy: options.searchIndexWritebackPolicy
2611
2485
  }
2612
2486
  });
2613
- if (options.refreshLibraryIndex !== false) {
2614
- await this.#refreshLibraryIndex(options.onIndexSyncError);
2615
- }
2616
- return result;
2617
2487
  }, options.signal);
2618
2488
  }
2619
2489
  async #resolveScope(document, options) {
2620
2490
  if (options.chapters !== void 0) return options.chapters;
2621
2491
  return (await resolveArchiveScope(document, this.objectUri, options.depth))?.chapterIds;
2622
2492
  }
2623
- async #resolveQueryChapters(document, options) {
2493
+ async #resolveQueryChapters(document, options, capabilities) {
2624
2494
  const chapters = await this.#resolveScope(document, options);
2625
- if (options.skipUnindexed !== true) return chapters;
2626
- const queryable = await (0, import_wiki_graph_core5.listArchiveQueryableChapterIds)(document, {
2627
- ...chapters === void 0 ? {} : { chapters }
2495
+ const coverageOptions = {
2496
+ ...chapters === void 0 ? {} : { chapters },
2497
+ ...capabilities.embeddingProvider === void 0 ? {} : { embeddingProvider: capabilities.embeddingProvider },
2498
+ requireEmbeddingProvider: true,
2499
+ ...options.queryMode === void 0 ? {} : { queryMode: options.queryMode }
2500
+ };
2501
+ if (options.skipUnindexed !== true) {
2502
+ await (0, import_wiki_graph_core7.assertArchiveIndexArtifactsReady)(document, coverageOptions);
2503
+ return chapters;
2504
+ }
2505
+ const queryable = await (0, import_wiki_graph_core7.listArchiveQueryableChapterIds)(document, {
2506
+ ...coverageOptions
2628
2507
  });
2629
2508
  if (queryable.length === 0) {
2630
2509
  throw new Error(
@@ -2633,56 +2512,24 @@ var WikiGraphArchiveHandle = class {
2633
2512
  }
2634
2513
  return queryable;
2635
2514
  }
2636
- async #refreshLibraryIndex(onError) {
2637
- if (this.#location.libraryDirtyTarget === void 0) return;
2638
- if (this.#location.libraryArchiveTarget !== void 0) {
2639
- await (0, import_wiki_graph_core5.finalizeWikiGraphLibraryArchiveWrite)({
2640
- target: this.#location.libraryArchiveTarget
2641
- });
2642
- }
2643
- try {
2644
- const state = await (0, import_wiki_graph_core5.readWikiGraphLibraryIndexState)(
2645
- this.#location.libraryDirtyTarget
2515
+ async #resolveQueryEmbeddingProvider(queryMode, signal) {
2516
+ if (queryMode === "fts") return void 0;
2517
+ const provider = await this.#runtime.run(
2518
+ createConfiguredEmbeddingProvider,
2519
+ signal
2520
+ );
2521
+ if (queryMode === "embedding" && provider === void 0) {
2522
+ throw new Error(
2523
+ "Embedding query mode requires embeddings configuration at `wikg://local/config/embeddings`."
2646
2524
  );
2647
- if (state.status !== "missing") {
2648
- await (0, import_wiki_graph_core5.rebuildWikiGraphLibraryIndex)(this.#location.libraryDirtyTarget);
2649
- }
2650
- } catch (error) {
2651
- onError?.(error);
2652
2525
  }
2526
+ return provider;
2653
2527
  }
2654
2528
  };
2655
- async function resolveWikiGraphArchiveLocation(uriOrPath) {
2656
- if (!uriOrPath.startsWith("wikg://")) {
2657
- return createPathLocation(resolveWikiGraphRuntimePath(uriOrPath));
2658
- }
2659
- const parsed = (0, import_wiki_graph_core5.parseLocatedWikiGraphUri)(uriOrPath);
2660
- const portableArchiveLocator = parsed.archivePath ?? uriOrPath;
2661
- const archiveLocator = portableArchiveLocator.startsWith("wikg://lib/") ? portableArchiveLocator : resolveWikiGraphRuntimePath(portableArchiveLocator);
2662
- const libraryArchiveTarget = archiveLocator.startsWith("wikg://lib/") ? (0, import_wiki_graph_core5.parseWikiGraphLibraryUri)(archiveLocator) : void 0;
2663
- const archiveFile = libraryArchiveTarget?.kind === "archive" ? await (0, import_wiki_graph_core5.resolveWikiGraphLibraryArchiveFile)(archiveLocator) : new NodeFile(archiveLocator);
2664
- const archivePath = getNodeResourcePath(archiveFile);
2665
- return {
2666
- archiveFile,
2667
- archiveKey: archivePath,
2668
- archivePath,
2669
- indexScope: { archiveKey: archivePath, archivePath, kind: "archive-index" },
2670
- ...libraryArchiveTarget?.kind === "archive" ? {
2671
- libraryArchiveTarget,
2672
- libraryDirtyTarget: {
2673
- isDefault: libraryArchiveTarget.isDefault,
2674
- kind: "scope",
2675
- ...libraryArchiveTarget.publicId === void 0 ? {} : { publicId: libraryArchiveTarget.publicId }
2676
- },
2677
- publicArchiveUri: portableArchiveLocator
2678
- } : {},
2679
- locatedUri: (0, import_wiki_graph_core5.formatLocatedWikiGraphUri)(archivePath, parsed.objectUri)
2680
- };
2681
- }
2682
2529
  async function ensureArchiveSearchIndex(document, options = {}) {
2683
2530
  const scope = options.chapters === void 0 ? {} : { chapters: options.chapters };
2684
- if (await (0, import_wiki_graph_core5.isArchiveSearchIndexCurrent)(document, scope)) return;
2685
- await (0, import_wiki_graph_core5.rebuildArchiveSearchIndex)(document, void 0, {
2531
+ if (await (0, import_wiki_graph_core7.isArchiveSearchIndexCurrent)(document, scope)) return;
2532
+ await (0, import_wiki_graph_core7.rebuildArchiveSearchIndex)(document, void 0, {
2686
2533
  ...scope,
2687
2534
  ...options.embeddingProvider === void 0 ? {} : { embeddingProvider: options.embeddingProvider }
2688
2535
  });
@@ -2692,10 +2539,10 @@ async function resolveArchiveScope(document, objectUri, depth) {
2692
2539
  if (parsed === void 0 || parsed.kind === "collection" && depth === void 0) {
2693
2540
  return void 0;
2694
2541
  }
2695
- const chapters = await (0, import_wiki_graph_core5.listChapters)(document);
2542
+ const chapters = await (0, import_wiki_graph_core7.listChapters)(document);
2696
2543
  const entries = parsed.kind === "collection" ? chapters.filter((chapter) => chapter.depth <= depth) : selectChapterSubtree(
2697
2544
  chapters,
2698
- await (0, import_wiki_graph_core5.resolveChapterPathReadonly)(document, parsed.chapterPath),
2545
+ await (0, import_wiki_graph_core7.resolveChapterPathReadonly)(document, parsed.chapterPath),
2699
2546
  depth
2700
2547
  );
2701
2548
  return { chapterIds: entries.map((entry) => entry.chapterId), entries };
@@ -2717,32 +2564,23 @@ function selectChapterSubtree(chapters, rootChapterId, depth) {
2717
2564
  (chapter) => chapter.chapterId === root.chapterId || chapter.path.startsWith(prefix) && (depth === void 0 || chapter.depth - root.depth <= depth)
2718
2565
  );
2719
2566
  }
2720
- function createPathLocation(path) {
2721
- return {
2722
- archiveFile: new NodeFile(path),
2723
- archiveKey: path,
2724
- archivePath: path,
2725
- indexScope: { archiveKey: path, archivePath: path, kind: "archive-index" },
2726
- locatedUri: (0, import_wiki_graph_core5.formatLocatedWikiGraphUri)(path)
2727
- };
2728
- }
2729
2567
  async function createEmptyArchiveFile(path) {
2730
- const directoryPath = await (0, import_promises3.mkdtemp)(
2731
- (0, import_path4.join)((0, import_os3.tmpdir)(), "wikigraph-archive-write-")
2568
+ const directoryPath = await (0, import_promises4.mkdtemp)(
2569
+ (0, import_path5.join)((0, import_os3.tmpdir)(), "wikigraph-archive-write-")
2732
2570
  );
2733
2571
  try {
2734
2572
  const directory = new NodeDirectory(directoryPath);
2735
- const document = await import_wiki_graph_core5.DirectoryDocument.open(directory);
2573
+ const document = await import_wiki_graph_core7.DirectoryDocument.open(directory);
2736
2574
  try {
2737
2575
  await document.openSession(async (openedDocument) => {
2738
- await openedDocument.writeToc({ items: [], version: import_wiki_graph_core5.TOC_FILE_VERSION });
2576
+ await openedDocument.writeToc({ items: [], version: import_wiki_graph_core7.TOC_FILE_VERSION });
2739
2577
  });
2740
2578
  } finally {
2741
2579
  await document.release();
2742
2580
  }
2743
- await (0, import_wiki_graph_core5.writeWikgArchive)(directory, new NodeFile(path));
2581
+ await (0, import_wiki_graph_core7.writeWikgArchive)(directory, new NodeFile(path));
2744
2582
  } finally {
2745
- await (0, import_promises3.rm)(directoryPath, { force: true, recursive: true });
2583
+ await (0, import_promises4.rm)(directoryPath, { force: true, recursive: true });
2746
2584
  }
2747
2585
  }
2748
2586
  function isNodeEEXISTError(error) {
@@ -2750,7 +2588,7 @@ function isNodeEEXISTError(error) {
2750
2588
  }
2751
2589
  async function nodePathExists(path) {
2752
2590
  try {
2753
- await (0, import_promises3.stat)(path);
2591
+ await (0, import_promises4.stat)(path);
2754
2592
  return true;
2755
2593
  } catch (error) {
2756
2594
  if (isNodeENOENTError(error)) return false;
@@ -2762,13 +2600,13 @@ function isNodeENOENTError(error) {
2762
2600
  }
2763
2601
  function parseObjectMetadataTarget(objectPath) {
2764
2602
  if (objectPath === "") {
2765
- return { kind: import_wiki_graph_core5.ObjectMetadataKind.Archive, objectPath };
2603
+ return { kind: import_wiki_graph_core7.ObjectMetadataKind.Archive, objectPath };
2766
2604
  }
2767
2605
  const chapter = /^chapter\/([1-9][0-9]*)(?:\/.*)?$/u.exec(objectPath);
2768
2606
  if (chapter?.[1] !== void 0) {
2769
2607
  return {
2770
2608
  chapterId: Number(chapter[1]),
2771
- kind: import_wiki_graph_core5.ObjectMetadataKind.Chapter,
2609
+ kind: import_wiki_graph_core7.ObjectMetadataKind.Chapter,
2772
2610
  objectPath
2773
2611
  };
2774
2612
  }
@@ -2776,7 +2614,7 @@ function parseObjectMetadataTarget(objectPath) {
2776
2614
  if (chunk?.[1] !== void 0) {
2777
2615
  return {
2778
2616
  chunkId: Number(chunk[1]),
2779
- kind: import_wiki_graph_core5.ObjectMetadataKind.Chunk,
2617
+ kind: import_wiki_graph_core7.ObjectMetadataKind.Chunk,
2780
2618
  objectPath
2781
2619
  };
2782
2620
  }
@@ -2784,7 +2622,7 @@ function parseObjectMetadataTarget(objectPath) {
2784
2622
  if (entity?.[1] !== void 0) {
2785
2623
  return {
2786
2624
  entityQid: entity[1],
2787
- kind: import_wiki_graph_core5.ObjectMetadataKind.Entity,
2625
+ kind: import_wiki_graph_core7.ObjectMetadataKind.Entity,
2788
2626
  objectPath
2789
2627
  };
2790
2628
  }
@@ -2793,14 +2631,14 @@ function parseObjectMetadataTarget(objectPath) {
2793
2631
  );
2794
2632
  if (triple?.[1] !== void 0) {
2795
2633
  return {
2796
- kind: import_wiki_graph_core5.ObjectMetadataKind.Triple,
2634
+ kind: import_wiki_graph_core7.ObjectMetadataKind.Triple,
2797
2635
  objectPath,
2798
2636
  tripleObjectQid: triple[3],
2799
2637
  triplePredicate: decodeURIComponent(triple[2]),
2800
2638
  tripleSubjectQid: triple[1]
2801
2639
  };
2802
2640
  }
2803
- return { kind: import_wiki_graph_core5.ObjectMetadataKind.Object, objectPath };
2641
+ return { kind: import_wiki_graph_core7.ObjectMetadataKind.Object, objectPath };
2804
2642
  }
2805
2643
  function withoutOperation(options) {
2806
2644
  const { signal: _signal, ...rest } = options;
@@ -2816,7 +2654,7 @@ function withoutOperationAndScope(options) {
2816
2654
  return rest;
2817
2655
  }
2818
2656
  async function resolveOptionalChapterPath(document, path) {
2819
- return path === void 0 ? void 0 : await (0, import_wiki_graph_core5.resolveChapterPathReadonly)(document, path);
2657
+ return path === void 0 ? void 0 : await (0, import_wiki_graph_core7.resolveChapterPathReadonly)(document, path);
2820
2658
  }
2821
2659
  function requireChapter(chapters, chapterId) {
2822
2660
  const chapter = chapters.find((entry) => entry.chapterId === chapterId);
@@ -2830,7 +2668,7 @@ function asTextStream(text) {
2830
2668
  }
2831
2669
  async function assertChapterResetAllowed(archive, chapterId, stage) {
2832
2670
  if (stage === "planned") {
2833
- await (0, import_wiki_graph_core5.assertNoActiveBuildJobs)({
2671
+ await (0, import_wiki_graph_core7.assertNoActiveBuildJobs)({
2834
2672
  archive,
2835
2673
  chapterIds: [chapterId],
2836
2674
  operation: "Resetting chapter to planned"
@@ -2838,14 +2676,14 @@ async function assertChapterResetAllowed(archive, chapterId, stage) {
2838
2676
  return;
2839
2677
  }
2840
2678
  if (stage === "sourced") {
2841
- await (0, import_wiki_graph_core5.assertNoActiveBuildJobs)({
2679
+ await (0, import_wiki_graph_core7.assertNoActiveBuildJobs)({
2842
2680
  archive,
2843
2681
  chapterIds: [chapterId],
2844
2682
  operation: "Resetting chapter graph",
2845
2683
  requiresTarget: "reading-graph"
2846
2684
  });
2847
2685
  }
2848
- await (0, import_wiki_graph_core5.assertNoActiveBuildJobs)({
2686
+ await (0, import_wiki_graph_core7.assertNoActiveBuildJobs)({
2849
2687
  archive,
2850
2688
  chapterIds: [chapterId],
2851
2689
  operation: "Resetting chapter summary",
@@ -2857,7 +2695,7 @@ async function assertChapterResetAllowed(archive, chapterId, stage) {
2857
2695
  WikiGraphArchiveExistsError,
2858
2696
  WikiGraphArchiveHandle,
2859
2697
  WikiGraphArchiveManager,
2860
- createWikiGraphArchiveInspectReport,
2861
- resolveWikiGraphArchiveLocation
2698
+ WikiGraphArchiveOwnershipError,
2699
+ inspectWikiGraphArchive
2862
2700
  });
2863
2701
  //# sourceMappingURL=archives.cjs.map