@ontos-ai/knowhere-sdk 2.1.1 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1590,10 +1590,6 @@ var import_jszip2 = __toESM(require("jszip"));
1590
1590
  var pageCitationAssetsMetadataKey = "pageAssets";
1591
1591
  var defaultImageContentType = "application/octet-stream";
1592
1592
  var tableContentType = "text/html; charset=utf-8";
1593
- var snapshotManifestKey = "manifest/current.json";
1594
- var snapshotIndexKey = "index.json";
1595
- var defaultSnapshotChunkPageSize = 200;
1596
- var snapshotJsonContentType = "application/json; charset=utf-8";
1597
1593
  async function storeParseResultAssets(result, options) {
1598
1594
  if (!options) {
1599
1595
  return {
@@ -1611,148 +1607,11 @@ async function storeParseResultAssets(result, options) {
1611
1607
  }
1612
1608
  }
1613
1609
  const normalizedResult = Object.keys(assetUrlsByFilePath).length === 0 ? result : rewriteResultAssetUrls(result, assetUrlsByFilePath);
1614
- const snapshot = await storeParsedSnapshot({
1615
- result: normalizedResult,
1616
- assetUrlsByFilePath,
1617
- keyPrefix: normalizedKeyPrefix,
1618
- options
1619
- });
1620
1610
  return {
1621
1611
  result: normalizedResult,
1622
- assetUrlsByFilePath,
1623
- snapshot
1624
- };
1625
- }
1626
- async function storeParsedSnapshot(input) {
1627
- const pageSize = normalizeSnapshotChunkPageSize(input.options.chunkPageSize);
1628
- const totalChunks = input.result.chunks.length;
1629
- const totalPages = Math.max(1, Math.ceil(totalChunks / pageSize));
1630
- const chunkPageReferences = [];
1631
- const chunkPageUrlsByPage = {};
1632
- for (let page = 1; page <= totalPages; page += 1) {
1633
- const pageChunks = input.result.chunks.slice((page - 1) * pageSize, page * pageSize);
1634
- const pageKey = `${input.keyPrefix}/chunks/page-${page}.json`;
1635
- const chunkPage = {
1636
- version: 1,
1637
- jobId: input.result.jobId,
1638
- revisionKey: input.options.revisionKey ?? input.result.jobId,
1639
- documentId: input.result.documentId,
1640
- namespace: input.result.namespace,
1641
- sourceFileName: input.result.manifest.sourceFileName,
1642
- page,
1643
- pageSize,
1644
- total: totalChunks,
1645
- totalPages,
1646
- chunks: pageChunks.map(
1647
- (chunk, index) => toSnapshotChunk(chunk, (page - 1) * pageSize + index + 1)
1648
- )
1649
- };
1650
- const pageUrl = await writeJsonObject({
1651
- key: pageKey,
1652
- value: chunkPage,
1653
- adapter: input.options.adapter
1654
- });
1655
- if (pageUrl) chunkPageUrlsByPage[page] = pageUrl;
1656
- chunkPageReferences.push({
1657
- page,
1658
- pageSize,
1659
- chunkCount: pageChunks.length,
1660
- key: pageKey,
1661
- url: pageUrl
1662
- });
1663
- }
1664
- const manifest = {
1665
- version: 1,
1666
- kind: "knowhere-parsed-result-snapshot",
1667
- jobId: input.result.jobId,
1668
- revisionKey: input.options.revisionKey ?? input.result.jobId,
1669
- documentId: input.result.documentId,
1670
- namespace: input.result.namespace,
1671
- sourceFileName: input.result.manifest.sourceFileName,
1672
- totalChunks,
1673
- typeCounts: countSnapshotChunkTypes(input.result.chunks),
1674
- chunkPageSize: pageSize,
1675
- chunkPages: chunkPageReferences,
1676
- assetUrlsByFilePath: input.assetUrlsByFilePath,
1677
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
1678
- };
1679
- const manifestKey = `${input.keyPrefix}/${snapshotManifestKey}`;
1680
- const indexKey = `${input.keyPrefix}/${snapshotIndexKey}`;
1681
- const manifestUrl = await writeJsonObject({
1682
- key: manifestKey,
1683
- value: manifest,
1684
- adapter: input.options.adapter
1685
- });
1686
- const indexUrl = await writeJsonObject({
1687
- key: indexKey,
1688
- value: manifest,
1689
- adapter: input.options.adapter
1690
- });
1691
- return {
1692
- manifest,
1693
- manifestKey,
1694
- manifestUrl,
1695
- indexKey,
1696
- indexUrl,
1697
- chunkPageUrlsByPage
1698
- };
1699
- }
1700
- function countSnapshotChunkTypes(chunks) {
1701
- return chunks.reduce(
1702
- (counts, chunk) => {
1703
- counts[chunk.type] += 1;
1704
- return counts;
1705
- },
1706
- { text: 0, image: 0, table: 0, page: 0 }
1707
- );
1708
- }
1709
- async function writeJsonObject(input) {
1710
- const result = await input.adapter.writeObject({
1711
- key: input.key,
1712
- body: Buffer.from(JSON.stringify(input.value, null, 2), "utf8"),
1713
- contentType: snapshotJsonContentType,
1714
- metadata: {
1715
- kind: "knowhere-parsed-result-snapshot"
1716
- }
1717
- });
1718
- return result.url ?? await input.adapter.getObjectUrl?.(result.key) ?? void 0;
1719
- }
1720
- function normalizeSnapshotChunkPageSize(value) {
1721
- if (!Number.isInteger(value) || value === void 0) return defaultSnapshotChunkPageSize;
1722
- return Math.min(Math.max(value, 1), 1e3);
1723
- }
1724
- function toSnapshotChunk(chunk, position) {
1725
- const filePath = getSnapshotChunkFilePath(chunk);
1726
- return {
1727
- id: chunk.chunkId,
1728
- chunkId: chunk.chunkId,
1729
- chunkType: chunk.type,
1730
- contentSource: chunk.contentSource,
1731
- content: chunk.content,
1732
- sectionPath: normalizeSnapshotSectionPath(chunk.path),
1733
- sourceChunkPath: chunk.path,
1734
- filePath,
1735
- sortOrder: position,
1736
- metadata: cloneChunkMetadata(chunk.metadata),
1737
- assetUrl: getSnapshotChunkAssetUrl(chunk)
1612
+ assetUrlsByFilePath
1738
1613
  };
1739
1614
  }
1740
- function normalizeSnapshotSectionPath(path4) {
1741
- return path4.length > 0 ? path4 : void 0;
1742
- }
1743
- function getSnapshotChunkFilePath(chunk) {
1744
- if (chunk.type === "image" || chunk.type === "table") {
1745
- return chunk.filePath;
1746
- }
1747
- const filePath = chunk.metadata.filePath;
1748
- return typeof filePath === "string" ? filePath : void 0;
1749
- }
1750
- function getSnapshotChunkAssetUrl(chunk) {
1751
- return chunk.type === "image" || chunk.type === "table" ? chunk.assetUrl : void 0;
1752
- }
1753
- function cloneChunkMetadata(metadata) {
1754
- return { ...metadata };
1755
- }
1756
1615
  async function collectStorageAssets(result, keyPrefix) {
1757
1616
  const resultZip = await loadResultZipForPageCitationAssets(result);
1758
1617
  return [
@@ -1989,108 +1848,212 @@ function isRecord(value) {
1989
1848
  }
1990
1849
 
1991
1850
  // src/storage/parsed-document-storage.ts
1992
- var parsedStorageKeyPrefix = "parsed";
1993
- var manifestStoragePath = "manifest/current.json";
1994
- var indexStoragePath = "index.json";
1995
- var chunkPagePathPattern = /^chunks\/page-(\d+)\.json$/;
1851
+ var import_jszip3 = __toESM(require("jszip"));
1852
+ var parsedDocumentCommitPath = ".knowhere-sdk/commit.json";
1853
+ var jsonContentType = "application/json; charset=utf-8";
1854
+ var markdownContentType = "text/markdown; charset=utf-8";
1855
+ var csvContentType = "text/csv; charset=utf-8";
1856
+ var htmlContentType = "text/html; charset=utf-8";
1857
+ var binaryContentType = "application/octet-stream";
1996
1858
  async function syncParseResultToParsedDocumentStorage(params) {
1997
1859
  const documentId = params.documentId ?? params.result.documentId ?? params.result.jobId;
1998
1860
  const revisionKey = params.revisionKey ?? params.result.jobId;
1999
- const adapter = createParsedDocumentObjectStorageAdapter({
2000
- storage: params.storage,
1861
+ const objects = await collectResultLayoutObjects(params.result);
1862
+ for (const object of objects) {
1863
+ await params.storage.writeObject({
1864
+ documentId,
1865
+ revisionKey,
1866
+ ...object
1867
+ });
1868
+ }
1869
+ const commit = {
1870
+ version: 1,
2001
1871
  documentId,
2002
- revisionKey
2003
- });
2004
- const stored = await storeParseResultAssets(params.result, {
2005
- adapter,
2006
- keyPrefix: parsedStorageKeyPrefix,
2007
- chunkPageSize: params.chunkPageSize,
2008
- revisionKey
1872
+ revisionKey,
1873
+ source: params.source ?? "resultZip",
1874
+ committedAt: (/* @__PURE__ */ new Date()).toISOString()
1875
+ };
1876
+ await writeParsedDocumentJsonObject(params.storage, {
1877
+ documentId,
1878
+ revisionKey,
1879
+ path: parsedDocumentCommitPath,
1880
+ value: commit
2009
1881
  });
2010
1882
  return {
2011
- result: stored.result,
2012
- snapshot: stored.snapshot,
1883
+ result: params.result,
2013
1884
  documentId,
2014
- revisionKey
1885
+ revisionKey,
1886
+ commit
2015
1887
  };
2016
1888
  }
2017
- function createParsedDocumentObjectStorageAdapter(params) {
2018
- return {
2019
- writeObject: (input) => writeParsedStorageObject(params, input),
2020
- headObject: (key) => headParsedStorageObject(params, key),
2021
- getObjectUrl: (key) => getParsedStorageObjectUrl(params, key)
2022
- };
1889
+ async function readParsedDocumentCommit(params) {
1890
+ const object = await params.storage.readObject({
1891
+ documentId: params.documentId,
1892
+ revisionKey: params.revisionKey,
1893
+ path: parsedDocumentCommitPath
1894
+ });
1895
+ if (!object) {
1896
+ return null;
1897
+ }
1898
+ const commit = readJsonObject(object);
1899
+ return commit.revisionKey === params.revisionKey && commit.documentId === params.documentId ? commit : null;
2023
1900
  }
2024
- async function writeParsedStorageObject(params, input) {
2025
- const storagePath = stripParsedStorageKeyPrefix(input.key);
2026
- if (storagePath === manifestStoragePath) {
2027
- const manifest = JSON.parse(
2028
- Buffer.from(input.body).toString("utf8")
2029
- );
2030
- await params.storage.writeManifest({
2031
- documentId: params.documentId,
2032
- revisionKey: params.revisionKey,
2033
- manifest
2034
- });
2035
- return { key: input.key };
1901
+ function readJsonObject(object) {
1902
+ return JSON.parse(Buffer.from(object.body).toString("utf8"));
1903
+ }
1904
+ async function collectResultLayoutObjects(result) {
1905
+ const objectsByPath = /* @__PURE__ */ new Map();
1906
+ const rawZipObjects = await collectRawZipObjects(result.rawZip);
1907
+ for (const object of rawZipObjects) {
1908
+ objectsByPath.set(object.path, object);
1909
+ }
1910
+ for (const object of collectGeneratedResultObjects(result)) {
1911
+ if (!objectsByPath.has(object.path)) {
1912
+ objectsByPath.set(object.path, object);
1913
+ }
1914
+ }
1915
+ return [...objectsByPath.values()].filter((object) => !isSdkMetadataPath(object.path));
1916
+ }
1917
+ async function collectRawZipObjects(rawZip) {
1918
+ try {
1919
+ const zip = await import_jszip3.default.loadAsync(rawZip);
1920
+ const objects = [];
1921
+ for (const entry of Object.values(zip.files)) {
1922
+ if (entry.dir || entry.name === "result.zip") {
1923
+ continue;
1924
+ }
1925
+ objects.push({
1926
+ path: normalizeResultPath(entry.name),
1927
+ body: new Uint8Array(await entry.async("nodebuffer")),
1928
+ contentType: inferContentTypeFromPath(entry.name)
1929
+ });
1930
+ }
1931
+ return objects;
1932
+ } catch {
1933
+ return [];
2036
1934
  }
2037
- if (storagePath === indexStoragePath) {
2038
- return { key: input.key };
1935
+ }
1936
+ function collectGeneratedResultObjects(result) {
1937
+ const objects = [
1938
+ createJsonObject("manifest.json", result.manifest),
1939
+ createJsonObject("chunks.json", keysToSnake(serializeChunks2(result.chunks)))
1940
+ ];
1941
+ if (result.docNav) {
1942
+ objects.push(createJsonObject("doc_nav.json", result.docNav));
1943
+ }
1944
+ if (result.fullMarkdown) {
1945
+ objects.push(createTextObject("full.md", result.fullMarkdown, markdownContentType));
1946
+ }
1947
+ if (result.chunksSlim) {
1948
+ objects.push(createJsonObject("chunks_slim.json", { chunks: result.chunksSlim }));
1949
+ }
1950
+ if (result.hierarchy) {
1951
+ objects.push(createJsonObject("hierarchy.json", result.hierarchy));
1952
+ }
1953
+ if (result.tocHierarchies) {
1954
+ objects.push(createJsonObject("toc_hierarchies.json", result.tocHierarchies));
1955
+ }
1956
+ if (result.kbCsv) {
1957
+ objects.push(createTextObject("kb.csv", result.kbCsv, csvContentType));
2039
1958
  }
2040
- const chunkPageMatch = storagePath.match(chunkPagePathPattern);
2041
- if (chunkPageMatch) {
2042
- const page = JSON.parse(
2043
- Buffer.from(input.body).toString("utf8")
1959
+ if (result.hierarchyViewHtml) {
1960
+ objects.push(
1961
+ createTextObject("hierarchy_view.html", result.hierarchyViewHtml, htmlContentType)
2044
1962
  );
2045
- await params.storage.writeChunkPage({
2046
- documentId: params.documentId,
2047
- revisionKey: params.revisionKey,
2048
- page
1963
+ }
1964
+ for (const chunk of result.imageChunks) {
1965
+ objects.push({
1966
+ path: normalizeResultPath(chunk.filePath),
1967
+ body: new Uint8Array(chunk.data),
1968
+ contentType: inferContentTypeFromPath(chunk.filePath),
1969
+ metadata: {
1970
+ chunkId: chunk.chunkId,
1971
+ chunkType: chunk.type,
1972
+ sourcePath: chunk.filePath
1973
+ }
2049
1974
  });
2050
- return { key: input.key };
2051
1975
  }
2052
- const stored = await params.storage.writeAsset({
2053
- documentId: params.documentId,
2054
- revisionKey: params.revisionKey,
2055
- sourcePath: storagePath,
2056
- body: input.body,
2057
- contentType: input.contentType,
2058
- metadata: input.metadata
2059
- });
1976
+ for (const chunk of result.tableChunks) {
1977
+ objects.push({
1978
+ path: normalizeResultPath(chunk.filePath),
1979
+ body: Buffer.from(chunk.html, "utf8"),
1980
+ contentType: htmlContentType,
1981
+ metadata: {
1982
+ chunkId: chunk.chunkId,
1983
+ chunkType: chunk.type,
1984
+ sourcePath: chunk.filePath
1985
+ }
1986
+ });
1987
+ }
1988
+ return objects;
1989
+ }
1990
+ function serializeChunks2(chunks) {
2060
1991
  return {
2061
- key: input.key,
2062
- url: stored.url
1992
+ chunks: chunks.map((chunk) => {
1993
+ const rawChunk = {
1994
+ chunkId: chunk.chunkId,
1995
+ type: chunk.type,
1996
+ contentSource: chunk.contentSource,
1997
+ content: chunk.content,
1998
+ path: chunk.path,
1999
+ metadata: chunk.metadata
2000
+ };
2001
+ if (chunk.type === "image" || chunk.type === "table") {
2002
+ return {
2003
+ ...rawChunk,
2004
+ filePath: chunk.filePath,
2005
+ assetUrl: chunk.assetUrl
2006
+ };
2007
+ }
2008
+ return rawChunk;
2009
+ })
2063
2010
  };
2064
2011
  }
2065
- async function headParsedStorageObject(params, key) {
2066
- const storagePath = stripParsedStorageKeyPrefix(key);
2067
- if (storagePath === manifestStoragePath || storagePath === indexStoragePath || chunkPagePathPattern.test(storagePath)) {
2068
- return null;
2069
- }
2070
- const url = await params.storage.getAssetUrl({
2012
+ async function writeParsedDocumentJsonObject(storage, params) {
2013
+ await storage.writeObject({
2071
2014
  documentId: params.documentId,
2072
2015
  revisionKey: params.revisionKey,
2073
- sourcePath: storagePath
2016
+ path: params.path,
2017
+ body: Buffer.from(JSON.stringify(params.value, null, 2), "utf8"),
2018
+ contentType: jsonContentType
2074
2019
  });
2075
- return url ? {
2076
- key,
2077
- url
2078
- } : null;
2079
- }
2080
- async function getParsedStorageObjectUrl(params, key) {
2081
- const storagePath = stripParsedStorageKeyPrefix(key);
2082
- if (storagePath === manifestStoragePath || storagePath === indexStoragePath || chunkPagePathPattern.test(storagePath)) {
2083
- return null;
2020
+ }
2021
+ function createJsonObject(path4, value) {
2022
+ return {
2023
+ path: path4,
2024
+ body: Buffer.from(JSON.stringify(value, null, 2), "utf8"),
2025
+ contentType: jsonContentType
2026
+ };
2027
+ }
2028
+ function createTextObject(path4, value, contentType) {
2029
+ return {
2030
+ path: path4,
2031
+ body: Buffer.from(value, "utf8"),
2032
+ contentType
2033
+ };
2034
+ }
2035
+ function inferContentTypeFromPath(filePath) {
2036
+ const lower = filePath.toLowerCase();
2037
+ if (lower.endsWith(".json")) return jsonContentType;
2038
+ if (lower.endsWith(".md")) return markdownContentType;
2039
+ if (lower.endsWith(".csv")) return csvContentType;
2040
+ if (lower.endsWith(".html") || lower.endsWith(".htm")) return htmlContentType;
2041
+ if (lower.endsWith(".png")) return "image/png";
2042
+ if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
2043
+ if (lower.endsWith(".gif")) return "image/gif";
2044
+ if (lower.endsWith(".webp")) return "image/webp";
2045
+ if (lower.endsWith(".svg")) return "image/svg+xml";
2046
+ return binaryContentType;
2047
+ }
2048
+ function normalizeResultPath(value) {
2049
+ const normalized = value.replaceAll("\\", "/").replace(/^\.\/+/, "");
2050
+ if (normalized.length === 0 || normalized.includes("\0") || normalized.startsWith("/") || normalized.split("/").some((part) => part.length === 0 || part === "." || part === "..")) {
2051
+ throw new Error(`Invalid parsed result path: ${value}`);
2084
2052
  }
2085
- return params.storage.getAssetUrl({
2086
- documentId: params.documentId,
2087
- revisionKey: params.revisionKey,
2088
- sourcePath: storagePath
2089
- });
2053
+ return normalized;
2090
2054
  }
2091
- function stripParsedStorageKeyPrefix(key) {
2092
- const prefix = `${parsedStorageKeyPrefix}/`;
2093
- return key.startsWith(prefix) ? key.slice(prefix.length) : key;
2055
+ function isSdkMetadataPath(path4) {
2056
+ return path4 === ".knowhere-sdk" || path4.startsWith(".knowhere-sdk/");
2094
2057
  }
2095
2058
 
2096
2059
  // src/knowledge/local-store.ts
@@ -2325,7 +2288,6 @@ var MAX_GREP_LIMIT = 50;
2325
2288
  var DEFAULT_CONTEXT_CHARS = 80;
2326
2289
  var DEFAULT_REMOTE_SCAN_PAGE_SIZE = 100;
2327
2290
  var DEFAULT_MAX_SYNC_PAGES = 10;
2328
- var DEFAULT_MAX_SYNC_ASSETS = 20;
2329
2291
  var DEFAULT_SYNC_DEADLINE_MS = 8e3;
2330
2292
  var DEFAULT_GREP_MAX_PAGES = 50;
2331
2293
  var DEFAULT_GREP_DEADLINE_MS = 8e3;
@@ -2333,6 +2295,7 @@ var DEFAULT_OUTLINE_MAX_PAGES = 50;
2333
2295
  var DEFAULT_OUTLINE_DEADLINE_MS = 8e3;
2334
2296
  var SAFE_LOCAL_DOCUMENT_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
2335
2297
  var REMOTE_DOCUMENT_ID_PATTERN = /^doc[_-]/;
2298
+ var remoteReconstructionPageDirectory = ".knowhere-sdk/remote-reconstruction/pages";
2336
2299
  var Knowledge = class _Knowledge {
2337
2300
  client;
2338
2301
  store;
@@ -2367,8 +2330,7 @@ var Knowledge = class _Knowledge {
2367
2330
  return {
2368
2331
  document,
2369
2332
  result,
2370
- assetUrlsByFilePath: storedAssets.assetUrlsByFilePath,
2371
- parsedSnapshot: storedAssets.snapshot
2333
+ assetUrlsByFilePath: storedAssets.assetUrlsByFilePath
2372
2334
  };
2373
2335
  }
2374
2336
  /** @deprecated Use parseToLocalCache for local cache imports or the top-level client.parse for server-safe parsing. */
@@ -2413,8 +2375,7 @@ var Knowledge = class _Knowledge {
2413
2375
  const result = syncedStorage.result;
2414
2376
  return {
2415
2377
  result,
2416
- assetUrlsByFilePath: storedAssets.assetUrlsByFilePath,
2417
- parsedSnapshot: syncedStorage.snapshot ?? storedAssets.snapshot
2378
+ assetUrlsByFilePath: storedAssets.assetUrlsByFilePath
2418
2379
  };
2419
2380
  }
2420
2381
  async importJobResult(params) {
@@ -2426,8 +2387,7 @@ var Knowledge = class _Knowledge {
2426
2387
  return {
2427
2388
  document,
2428
2389
  result,
2429
- assetUrlsByFilePath: stored.assetUrlsByFilePath,
2430
- parsedSnapshot: stored.parsedSnapshot
2390
+ assetUrlsByFilePath: stored.assetUrlsByFilePath
2431
2391
  };
2432
2392
  }
2433
2393
  /** @deprecated Use importJobResult for local cache imports or loadJobResult for server-safe loads. */
@@ -2450,14 +2410,13 @@ var Knowledge = class _Knowledge {
2450
2410
  result: loadedResult,
2451
2411
  storage: parsedStorageConfig.storage,
2452
2412
  documentId: loadedResult.documentId ?? normalized.localDocumentId ?? normalized.jobId,
2453
- revisionKey: params.revisionKey ?? normalized.jobId,
2454
- chunkPageSize: parsedStorageConfig.limits?.chunkPageSize
2413
+ revisionKey: params.revisionKey ?? normalized.jobId
2455
2414
  });
2456
2415
  return {
2457
2416
  documentId: synced2.documentId,
2458
2417
  revisionKey: synced2.revisionKey,
2459
2418
  completed: true,
2460
- manifest: synced2.snapshot?.manifest
2419
+ commit: synced2.commit
2461
2420
  };
2462
2421
  }
2463
2422
  if (!normalized.localDocumentId) {
@@ -2468,14 +2427,13 @@ var Knowledge = class _Knowledge {
2468
2427
  result,
2469
2428
  storage: parsedStorageConfig.storage,
2470
2429
  documentId: result.documentId ?? normalized.localDocumentId,
2471
- revisionKey: params.revisionKey ?? result.jobId,
2472
- chunkPageSize: parsedStorageConfig.limits?.chunkPageSize
2430
+ revisionKey: params.revisionKey ?? result.jobId
2473
2431
  });
2474
2432
  return {
2475
2433
  documentId: synced.documentId,
2476
2434
  revisionKey: synced.revisionKey,
2477
2435
  completed: true,
2478
- manifest: synced.snapshot?.manifest
2436
+ commit: synced.commit
2479
2437
  };
2480
2438
  }
2481
2439
  async syncParseResultToConfiguredStorage(result) {
@@ -2485,12 +2443,11 @@ var Knowledge = class _Knowledge {
2485
2443
  }
2486
2444
  const synced = await syncParseResultToParsedDocumentStorage({
2487
2445
  result,
2488
- storage: parsedStorageConfig.storage,
2489
- chunkPageSize: parsedStorageConfig.limits?.chunkPageSize
2446
+ storage: parsedStorageConfig.storage
2490
2447
  });
2491
2448
  return {
2492
2449
  result: synced.result,
2493
- snapshot: synced.snapshot
2450
+ commit: synced.commit
2494
2451
  };
2495
2452
  }
2496
2453
  async parseWithoutClientStorageAdapter(params) {
@@ -2741,10 +2698,7 @@ var Knowledge = class _Knowledge {
2741
2698
  page: pageParams.page,
2742
2699
  pageSize: pageParams.pageSize,
2743
2700
  chunkType: params.chunkType,
2744
- includeAssetUrls: shouldRequestRemoteAssetUrls(
2745
- params.assetUrlPolicy,
2746
- this.parsedStorageConfig
2747
- )
2701
+ includeAssetUrls: true
2748
2702
  });
2749
2703
  const revisionKey = getRemoteRevisionKey(remotePage);
2750
2704
  const stored = await this.tryReadChunksFromParsedStorage({
@@ -2755,12 +2709,7 @@ var Knowledge = class _Knowledge {
2755
2709
  if (stored) {
2756
2710
  return stored;
2757
2711
  }
2758
- const chunks = await this.toRemoteReadChunks({
2759
- documentId,
2760
- revisionKey,
2761
- chunks: remotePage.chunks,
2762
- assetUrlPolicy: params.assetUrlPolicy
2763
- });
2712
+ const chunks = remotePage.chunks.map((chunk) => toRemoteReadChunk(chunk));
2764
2713
  this.scheduleParsedStorageSync(documentId, revisionKey);
2765
2714
  return {
2766
2715
  document: createRemoteKnowledgeDocument({
@@ -2793,10 +2742,7 @@ var Knowledge = class _Knowledge {
2793
2742
  page: 1,
2794
2743
  pageSize: limits.remotePageSize,
2795
2744
  chunkType: params.chunkType,
2796
- includeAssetUrls: shouldRequestRemoteAssetUrls(
2797
- params.assetUrlPolicy,
2798
- this.parsedStorageConfig
2799
- )
2745
+ includeAssetUrls: true
2800
2746
  });
2801
2747
  const revisionKey = getRemoteRevisionKey(firstPage);
2802
2748
  const stored = await this.tryReadChunksFromParsedStorage({
@@ -2823,18 +2769,10 @@ var Knowledge = class _Knowledge {
2823
2769
  page,
2824
2770
  pageSize: limits.remotePageSize,
2825
2771
  chunkType: params.chunkType,
2826
- includeAssetUrls: shouldRequestRemoteAssetUrls(
2827
- params.assetUrlPolicy,
2828
- this.parsedStorageConfig
2829
- )
2772
+ includeAssetUrls: true
2830
2773
  });
2831
2774
  }
2832
- const chunks = await this.toRemoteReadChunks({
2833
- documentId,
2834
- revisionKey,
2835
- chunks: selected.slice(0, limit),
2836
- assetUrlPolicy: params.assetUrlPolicy
2837
- });
2775
+ const chunks = selected.slice(0, limit).map((chunk) => toRemoteReadChunk(chunk));
2838
2776
  this.scheduleParsedStorageSync(documentId, revisionKey);
2839
2777
  return {
2840
2778
  document: createRemoteKnowledgeDocument({
@@ -2870,7 +2808,7 @@ var Knowledge = class _Knowledge {
2870
2808
  page: startPage,
2871
2809
  pageSize: limits.remotePageSize,
2872
2810
  chunkType: params.chunkType,
2873
- includeAssetUrls: false
2811
+ includeAssetUrls: true
2874
2812
  });
2875
2813
  const revisionKey = getRemoteRevisionKey(firstPage);
2876
2814
  const stored = startPage === 1 ? await this.tryGrepChunksFromParsedStorage({
@@ -2967,7 +2905,7 @@ var Knowledge = class _Knowledge {
2967
2905
  page,
2968
2906
  pageSize: limits.remotePageSize,
2969
2907
  chunkType: params.chunkType,
2970
- includeAssetUrls: false
2908
+ includeAssetUrls: true
2971
2909
  });
2972
2910
  }
2973
2911
  }
@@ -2982,7 +2920,7 @@ var Knowledge = class _Knowledge {
2982
2920
  const firstPage = await this.client.documents.listChunks(documentId, {
2983
2921
  page: 1,
2984
2922
  pageSize: limits.remotePageSize,
2985
- includeAssetUrls: false
2923
+ includeAssetUrls: true
2986
2924
  });
2987
2925
  const revisionKey = getRemoteRevisionKey(firstPage);
2988
2926
  const stored = await this.tryReadOutlineFromParsedStorage(documentId, revisionKey);
@@ -3004,7 +2942,7 @@ var Knowledge = class _Knowledge {
3004
2942
  response = await this.client.documents.listChunks(documentId, {
3005
2943
  page,
3006
2944
  pageSize: limits.remotePageSize,
3007
- includeAssetUrls: false
2945
+ includeAssetUrls: true
3008
2946
  });
3009
2947
  }
3010
2948
  const truncated = response.pagination.page < response.pagination.totalPages;
@@ -3030,28 +2968,13 @@ var Knowledge = class _Knowledge {
3030
2968
  };
3031
2969
  }
3032
2970
  async tryReadChunksFromParsedStorage(params) {
3033
- const parsedStorageConfig = this.parsedStorageConfig;
3034
- if (!parsedStorageConfig) {
3035
- return null;
3036
- }
3037
- const manifest = await this.readFreshParsedStorageManifest(
2971
+ const storedResult = await this.readCommittedParsedStorageResult(
3038
2972
  params.documentId,
3039
2973
  params.revisionKey
3040
2974
  );
3041
- if (!manifest) {
3042
- return null;
3043
- }
2975
+ if (!storedResult) return null;
3044
2976
  const pageParams = getReadPageParams(params.params);
3045
- const indexedChunks = await this.readStoredSnapshotChunks({
3046
- documentId: params.documentId,
3047
- revisionKey: params.revisionKey,
3048
- manifest,
3049
- chunkType: params.params.chunkType
3050
- });
3051
- if (!indexedChunks) {
3052
- return null;
3053
- }
3054
- const scopedChunks = indexedChunks.filter((chunk) => matchesReadScope(chunk, params.params));
2977
+ const scopedChunks = storedResult.chunks.filter((chunk) => !params.params.chunkType || chunk.chunkType === params.params.chunkType).filter((chunk) => matchesReadScope(chunk, params.params));
3055
2978
  const selected = hasScanReadFilters(params.params) ? selectReadWindow(
3056
2979
  scopedChunks,
3057
2980
  params.params,
@@ -3060,17 +2983,18 @@ var Knowledge = class _Knowledge {
3060
2983
  (pageParams.page - 1) * pageParams.pageSize,
3061
2984
  pageParams.page * pageParams.pageSize
3062
2985
  );
3063
- const visibleChunks = applyAssetUrlPolicyToReadChunks(
3064
- selected.map(toReadChunk),
3065
- params.params.assetUrlPolicy
3066
- );
2986
+ const visibleChunks = await applyStoredAssetUrlsToReadChunks({
2987
+ storageConfig: this.requireParsedStorageConfig(),
2988
+ documentId: params.documentId,
2989
+ revisionKey: params.revisionKey,
2990
+ chunks: selected.map(toReadChunk)
2991
+ });
3067
2992
  const totalChunks = scopedChunks.length;
3068
2993
  return {
3069
2994
  document: createStoredKnowledgeDocument({
3070
2995
  documentId: params.documentId,
3071
- manifest,
3072
- revisionKey: params.revisionKey,
3073
- typeCounts: countIndexedTypes(indexedChunks)
2996
+ storedResult,
2997
+ revisionKey: params.revisionKey
3074
2998
  }),
3075
2999
  chunks: visibleChunks,
3076
3000
  page: hasScanReadFilters(params.params) ? void 0 : pageParams.page,
@@ -3081,30 +3005,15 @@ var Knowledge = class _Knowledge {
3081
3005
  };
3082
3006
  }
3083
3007
  async tryGrepChunksFromParsedStorage(params) {
3084
- const parsedStorageConfig = this.parsedStorageConfig;
3085
- if (!parsedStorageConfig) {
3086
- return null;
3087
- }
3088
- const manifest = await this.readFreshParsedStorageManifest(
3008
+ const storedResult = await this.readCommittedParsedStorageResult(
3089
3009
  params.documentId,
3090
3010
  params.revisionKey
3091
3011
  );
3092
- if (!manifest) {
3093
- return null;
3094
- }
3095
- const indexedChunks = await this.readStoredSnapshotChunks({
3096
- documentId: params.documentId,
3097
- revisionKey: params.revisionKey,
3098
- manifest,
3099
- chunkType: params.params.chunkType
3100
- });
3101
- if (!indexedChunks) {
3102
- return null;
3103
- }
3012
+ if (!storedResult) return null;
3104
3013
  const maxResults = clampLimit(params.params.maxResults, DEFAULT_GREP_LIMIT, MAX_GREP_LIMIT);
3105
3014
  const contextChars = params.params.contextChars ?? DEFAULT_CONTEXT_CHARS;
3106
3015
  const matcher = createMatcher(params.params);
3107
- const scopedChunks = indexedChunks.filter((chunk) => matchesGrepScope(chunk, params.params));
3016
+ const scopedChunks = storedResult.chunks.filter((chunk) => !params.params.chunkType || chunk.chunkType === params.params.chunkType).filter((chunk) => matchesGrepScope(chunk, params.params));
3108
3017
  const matches = [];
3109
3018
  let scannedChunks = 0;
3110
3019
  for (const chunk of scopedChunks) {
@@ -3125,9 +3034,8 @@ var Knowledge = class _Knowledge {
3125
3034
  return {
3126
3035
  document: createStoredKnowledgeDocument({
3127
3036
  documentId: params.documentId,
3128
- manifest,
3129
- revisionKey: params.revisionKey,
3130
- typeCounts: countIndexedTypes(indexedChunks)
3037
+ storedResult,
3038
+ revisionKey: params.revisionKey
3131
3039
  }),
3132
3040
  matches,
3133
3041
  scannedChunks,
@@ -3139,9 +3047,8 @@ var Knowledge = class _Knowledge {
3139
3047
  return {
3140
3048
  document: createStoredKnowledgeDocument({
3141
3049
  documentId: params.documentId,
3142
- manifest,
3143
- revisionKey: params.revisionKey,
3144
- typeCounts: countIndexedTypes(indexedChunks)
3050
+ storedResult,
3051
+ revisionKey: params.revisionKey
3145
3052
  }),
3146
3053
  matches,
3147
3054
  scannedChunks,
@@ -3149,98 +3056,80 @@ var Knowledge = class _Knowledge {
3149
3056
  };
3150
3057
  }
3151
3058
  async tryReadOutlineFromParsedStorage(documentId, revisionKey) {
3152
- const manifest = await this.readFreshParsedStorageManifest(documentId, revisionKey);
3153
- if (!manifest) {
3154
- return null;
3155
- }
3156
- const indexedChunks = await this.readStoredSnapshotChunks({
3157
- documentId,
3158
- revisionKey,
3159
- manifest
3160
- });
3161
- if (!indexedChunks) {
3162
- return null;
3163
- }
3164
- const sections = buildFlatSectionsFromIndexedChunks(indexedChunks);
3165
- const typeCounts = countIndexedTypes(indexedChunks);
3059
+ const storedResult = await this.readCommittedParsedStorageResult(documentId, revisionKey);
3060
+ if (!storedResult) return null;
3061
+ const sections = storedResult.docNav?.sections && storedResult.docNav.sections.length > 0 ? flattenSections(
3062
+ storedResult.docNav.sections.map(
3063
+ (section) => toKnowledgeSection(
3064
+ section,
3065
+ storedResult.chunks,
3066
+ storedResult.manifest.sourceFileName
3067
+ )
3068
+ )
3069
+ ) : buildFlatSectionsFromIndexedChunks(storedResult.chunks);
3166
3070
  return {
3167
3071
  document: createStoredKnowledgeDocument({
3168
3072
  documentId,
3169
- manifest,
3170
- revisionKey,
3171
- typeCounts
3073
+ storedResult,
3074
+ revisionKey
3172
3075
  }),
3173
- totalChunks: manifest.totalChunks,
3174
- typeCounts,
3076
+ totalChunks: storedResult.chunks.length,
3077
+ typeCounts: storedResult.typeCounts,
3175
3078
  sections,
3176
- sectionTree: nestSections(sections),
3079
+ sectionTree: storedResult.docNav?.sections && storedResult.docNav.sections.length > 0 ? storedResult.docNav.sections.map(
3080
+ (section) => toKnowledgeSection(
3081
+ section,
3082
+ storedResult.chunks,
3083
+ storedResult.manifest.sourceFileName
3084
+ )
3085
+ ) : nestSections(sections),
3177
3086
  truncated: false
3178
3087
  };
3179
3088
  }
3180
- async readFreshParsedStorageManifest(documentId, revisionKey) {
3089
+ async readCommittedParsedStorageResult(documentId, revisionKey) {
3181
3090
  const parsedStorageConfig = this.parsedStorageConfig;
3182
3091
  if (!parsedStorageConfig) {
3183
3092
  return null;
3184
3093
  }
3185
- const manifest = await parsedStorageConfig.storage.readManifest({
3094
+ const commit = await readParsedDocumentCommit({
3095
+ storage: parsedStorageConfig.storage,
3186
3096
  documentId,
3187
3097
  revisionKey
3188
3098
  });
3189
- if (!manifest || !isFreshManifest(manifest, revisionKey)) {
3099
+ if (!commit) {
3190
3100
  return null;
3191
3101
  }
3192
- return manifest;
3193
- }
3194
- async readStoredSnapshotChunks(params) {
3195
- const parsedStorageConfig = this.parsedStorageConfig;
3196
- if (!parsedStorageConfig) {
3102
+ const manifestObject = await parsedStorageConfig.storage.readObject({
3103
+ documentId,
3104
+ revisionKey,
3105
+ path: "manifest.json"
3106
+ });
3107
+ const chunksObject = await parsedStorageConfig.storage.readObject({
3108
+ documentId,
3109
+ revisionKey,
3110
+ path: "chunks.json"
3111
+ });
3112
+ if (!manifestObject || !chunksObject) {
3197
3113
  return null;
3198
3114
  }
3199
- const chunks = [];
3200
- for (const pageReference of params.manifest.chunkPages) {
3201
- const page = await parsedStorageConfig.storage.readChunkPage({
3202
- documentId: params.documentId,
3203
- revisionKey: params.revisionKey,
3204
- page: pageReference.page,
3205
- chunkType: params.chunkType
3206
- });
3207
- if (!page) {
3208
- return null;
3209
- }
3210
- chunks.push(
3211
- ...page.chunks.filter((chunk) => !params.chunkType || chunk.chunkType === params.chunkType).map(toIndexedSnapshotChunk)
3212
- );
3213
- }
3214
- return chunks.sort((left, right) => left.position - right.position);
3215
- }
3216
- async toRemoteReadChunks(params) {
3217
- const readChunks = params.chunks.map((chunk) => toRemoteReadChunk(chunk));
3218
- if (params.assetUrlPolicy === "durable") {
3219
- return this.hardenReadChunkAssetUrls({
3220
- documentId: params.documentId,
3221
- revisionKey: params.revisionKey,
3222
- chunks: readChunks
3223
- });
3224
- }
3225
- return applyAssetUrlPolicyToReadChunks(readChunks, params.assetUrlPolicy);
3226
- }
3227
- async hardenReadChunkAssetUrls(params) {
3228
- const parsedStorageConfig = this.parsedStorageConfig;
3229
- if (!parsedStorageConfig) {
3230
- return applyAssetUrlPolicyToReadChunks(params.chunks, "none");
3231
- }
3232
- const hardenedChunks = [];
3233
- for (const chunk of params.chunks) {
3234
- hardenedChunks.push(
3235
- await hardenReadChunkAssetUrls({
3236
- storageConfig: parsedStorageConfig,
3237
- documentId: params.documentId,
3238
- revisionKey: params.revisionKey,
3239
- chunk
3240
- })
3241
- );
3242
- }
3243
- return hardenedChunks;
3115
+ const manifest = readJsonObject(manifestObject);
3116
+ const chunks = parseStoredResultChunks({
3117
+ payload: readJsonObject(chunksObject),
3118
+ sourceFileName: manifest.sourceFileName
3119
+ });
3120
+ const docNavObject = await parsedStorageConfig.storage.readObject({
3121
+ documentId,
3122
+ revisionKey,
3123
+ path: "doc_nav.json"
3124
+ });
3125
+ const docNav = docNavObject ? readJsonObject(docNavObject) : void 0;
3126
+ return {
3127
+ commit,
3128
+ manifest,
3129
+ chunks,
3130
+ docNav: docNav?.sections ? { sections: docNav.sections } : void 0,
3131
+ typeCounts: countIndexedTypes(chunks)
3132
+ };
3244
3133
  }
3245
3134
  scheduleParsedStorageSync(documentId, revisionKey) {
3246
3135
  const parsedStorageConfig = this.parsedStorageConfig;
@@ -3260,7 +3149,6 @@ var Knowledge = class _Knowledge {
3260
3149
  documentId,
3261
3150
  revisionKey,
3262
3151
  nextChunkPage: 1,
3263
- nextAssetIndex: 0,
3264
3152
  status: "failed",
3265
3153
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3266
3154
  error: error instanceof Error ? error.message : String(error)
@@ -3270,28 +3158,63 @@ var Knowledge = class _Knowledge {
3270
3158
  void Promise.resolve(scheduler.schedule(task)).catch(() => void 0);
3271
3159
  }
3272
3160
  async syncRemoteDocumentToParsedStorage(params) {
3273
- const limits = getParsedStorageLimits(params.parsedStorageConfig.limits);
3274
- const existingProgress = params.revisionKey ? await params.parsedStorageConfig.storage.readSyncProgress({
3275
- documentId: params.documentId,
3276
- revisionKey: params.revisionKey
3277
- }) : null;
3278
- let nextPage = existingProgress?.status === "running" ? existingProgress.nextChunkPage : 1;
3279
- let response = await this.client.documents.listChunks(params.documentId, {
3280
- page: nextPage,
3281
- pageSize: limits.remotePageSize,
3161
+ const firstPage = await this.client.documents.listChunks(params.documentId, {
3162
+ page: 1,
3163
+ pageSize: 1,
3282
3164
  includeAssetUrls: true
3283
3165
  });
3284
- const revisionKey = params.revisionKey ?? getRemoteRevisionKey(response);
3285
- if (params.revisionKey && getRemoteRevisionKey(response) !== params.revisionKey) {
3286
- response = await this.client.documents.listChunks(params.documentId, {
3287
- page: 1,
3288
- pageSize: limits.remotePageSize,
3289
- includeAssetUrls: true
3166
+ const revisionKey = params.revisionKey ?? getRemoteRevisionKey(firstPage);
3167
+ if (params.revisionKey && getRemoteRevisionKey(firstPage) !== params.revisionKey) {
3168
+ return this.syncRemoteDocumentToParsedStorage({
3169
+ documentId: params.documentId,
3170
+ parsedStorageConfig: params.parsedStorageConfig
3290
3171
  });
3291
- nextPage = 1;
3292
3172
  }
3173
+ if (firstPage.jobId) {
3174
+ try {
3175
+ const loadedResult = await this.client.jobs.load(firstPage.jobId);
3176
+ const synced = await syncParseResultToParsedDocumentStorage({
3177
+ result: loadedResult,
3178
+ storage: params.parsedStorageConfig.storage,
3179
+ documentId: params.documentId,
3180
+ revisionKey,
3181
+ source: "resultZip"
3182
+ });
3183
+ await params.parsedStorageConfig.storage.writeSyncProgress({
3184
+ documentId: params.documentId,
3185
+ revisionKey,
3186
+ status: "completed",
3187
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
3188
+ });
3189
+ return {
3190
+ documentId: synced.documentId,
3191
+ revisionKey: synced.revisionKey,
3192
+ completed: true,
3193
+ commit: synced.commit
3194
+ };
3195
+ } catch {
3196
+ }
3197
+ }
3198
+ return this.syncRemoteDocumentChunksToParsedStorage({
3199
+ documentId: params.documentId,
3200
+ revisionKey,
3201
+ firstPage,
3202
+ parsedStorageConfig: params.parsedStorageConfig
3203
+ });
3204
+ }
3205
+ async syncRemoteDocumentChunksToParsedStorage(params) {
3206
+ const limits = getParsedStorageLimits(params.parsedStorageConfig.limits);
3207
+ const existingProgress = await params.parsedStorageConfig.storage.readSyncProgress({
3208
+ documentId: params.documentId,
3209
+ revisionKey: params.revisionKey
3210
+ });
3211
+ let nextPage = existingProgress?.status === "running" ? existingProgress.nextChunkPage ?? 1 : 1;
3212
+ let response = nextPage === 1 && params.firstPage.pagination.pageSize === limits.remotePageSize ? params.firstPage : await this.client.documents.listChunks(params.documentId, {
3213
+ page: nextPage,
3214
+ pageSize: limits.remotePageSize,
3215
+ includeAssetUrls: true
3216
+ });
3293
3217
  const totalPages = response.pagination.totalPages;
3294
- const chunkPages = [];
3295
3218
  let syncedPages = 0;
3296
3219
  const startedAt = Date.now();
3297
3220
  while (nextPage <= totalPages) {
@@ -3302,65 +3225,88 @@ var Knowledge = class _Knowledge {
3302
3225
  includeAssetUrls: true
3303
3226
  });
3304
3227
  }
3305
- const readChunks = await this.hardenReadChunkAssetUrls({
3306
- documentId: params.documentId,
3307
- revisionKey,
3308
- chunks: response.chunks.map(toRemoteReadChunk)
3309
- });
3310
- const page = toSnapshotChunkPageFromReadChunks({
3311
- response,
3312
- revisionKey,
3313
- chunks: readChunks
3314
- });
3315
- await params.parsedStorageConfig.storage.writeChunkPage({
3228
+ await params.parsedStorageConfig.storage.writeObject({
3316
3229
  documentId: params.documentId,
3317
- revisionKey,
3318
- page
3230
+ revisionKey: params.revisionKey,
3231
+ path: getRemoteReconstructionPagePath(response.pagination.page),
3232
+ body: Buffer.from(JSON.stringify({ chunks: response.chunks }), "utf8"),
3233
+ contentType: "application/json; charset=utf-8"
3319
3234
  });
3320
- chunkPages.push(page);
3321
3235
  nextPage += 1;
3322
3236
  syncedPages += 1;
3323
3237
  await params.parsedStorageConfig.storage.writeSyncProgress({
3324
3238
  documentId: params.documentId,
3325
- revisionKey,
3239
+ revisionKey: params.revisionKey,
3326
3240
  nextChunkPage: nextPage,
3327
- nextAssetIndex: 0,
3328
3241
  status: "running",
3329
3242
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
3330
3243
  });
3331
3244
  if (syncedPages >= limits.maxPagesPerSync || Date.now() - startedAt >= limits.syncDeadlineMs) {
3332
3245
  return {
3333
3246
  documentId: params.documentId,
3334
- revisionKey,
3247
+ revisionKey: params.revisionKey,
3335
3248
  completed: false
3336
3249
  };
3337
3250
  }
3338
3251
  }
3339
- const manifest = createRemoteSnapshotManifest({
3340
- response,
3341
- revisionKey,
3342
- chunkPages
3252
+ const chunks = await this.readRemoteReconstructionChunks({
3253
+ documentId: params.documentId,
3254
+ revisionKey: params.revisionKey,
3255
+ totalPages,
3256
+ parsedStorageConfig: params.parsedStorageConfig
3343
3257
  });
3344
- await params.parsedStorageConfig.storage.writeManifest({
3258
+ if (!chunks) {
3259
+ return {
3260
+ documentId: params.documentId,
3261
+ revisionKey: params.revisionKey,
3262
+ completed: false
3263
+ };
3264
+ }
3265
+ const synced = await syncParseResultToParsedDocumentStorage({
3266
+ result: createMinimalParseResultFromRemoteChunks({
3267
+ documentId: params.documentId,
3268
+ revisionKey: params.revisionKey,
3269
+ response,
3270
+ chunks
3271
+ }),
3272
+ storage: params.parsedStorageConfig.storage,
3345
3273
  documentId: params.documentId,
3346
- revisionKey,
3347
- manifest
3274
+ revisionKey: params.revisionKey,
3275
+ source: "remoteReconstruction"
3348
3276
  });
3349
3277
  await params.parsedStorageConfig.storage.writeSyncProgress({
3350
3278
  documentId: params.documentId,
3351
- revisionKey,
3279
+ revisionKey: params.revisionKey,
3352
3280
  nextChunkPage: totalPages + 1,
3353
- nextAssetIndex: 0,
3354
3281
  status: "completed",
3355
3282
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
3356
3283
  });
3357
3284
  return {
3358
3285
  documentId: params.documentId,
3359
- revisionKey,
3286
+ revisionKey: params.revisionKey,
3360
3287
  completed: true,
3361
- manifest
3288
+ commit: synced.commit
3362
3289
  };
3363
3290
  }
3291
+ async readRemoteReconstructionChunks(params) {
3292
+ const chunks = [];
3293
+ for (let page = 1; page <= params.totalPages; page += 1) {
3294
+ const object = await params.parsedStorageConfig.storage.readObject({
3295
+ documentId: params.documentId,
3296
+ revisionKey: params.revisionKey,
3297
+ path: getRemoteReconstructionPagePath(page)
3298
+ });
3299
+ if (!object) {
3300
+ return null;
3301
+ }
3302
+ const payload = readJsonObject(object);
3303
+ if (!isDocumentChunkArray(payload.chunks)) {
3304
+ return null;
3305
+ }
3306
+ chunks.push(...payload.chunks);
3307
+ }
3308
+ return chunks;
3309
+ }
3364
3310
  requireParsedStorageConfig() {
3365
3311
  if (!this.parsedStorageConfig) {
3366
3312
  throw new ValidationError("parsed document storage is not configured");
@@ -3374,7 +3320,8 @@ var Knowledge = class _Knowledge {
3374
3320
  async getPublishedDocumentJobId(documentId) {
3375
3321
  const response = await this.client.documents.listChunks(documentId, {
3376
3322
  page: 1,
3377
- pageSize: 1
3323
+ pageSize: 1,
3324
+ includeAssetUrls: true
3378
3325
  });
3379
3326
  if (!response.jobId) {
3380
3327
  throw new Error(
@@ -3407,14 +3354,12 @@ var defaultParsedStorageScheduler = {
3407
3354
  };
3408
3355
  function getParsedStorageLimits(limits) {
3409
3356
  return {
3410
- chunkPageSize: clampLimit(limits?.chunkPageSize, DEFAULT_REMOTE_SCAN_PAGE_SIZE, MAX_PAGE_SIZE),
3411
3357
  remotePageSize: clampLimit(
3412
3358
  limits?.remotePageSize,
3413
3359
  DEFAULT_REMOTE_SCAN_PAGE_SIZE,
3414
3360
  MAX_PAGE_SIZE
3415
3361
  ),
3416
3362
  maxPagesPerSync: clampLimit(limits?.maxPagesPerSync, DEFAULT_MAX_SYNC_PAGES, 1e3),
3417
- maxAssetsPerSync: clampLimit(limits?.maxAssetsPerSync, DEFAULT_MAX_SYNC_ASSETS, 1e3),
3418
3363
  syncDeadlineMs: clampLimit(limits?.syncDeadlineMs, DEFAULT_SYNC_DEADLINE_MS, 6e4),
3419
3364
  grepMaxPages: clampLimit(limits?.grepMaxPages, DEFAULT_GREP_MAX_PAGES, 1e3),
3420
3365
  grepDeadlineMs: clampLimit(limits?.grepDeadlineMs, DEFAULT_GREP_DEADLINE_MS, 6e4),
@@ -3423,13 +3368,13 @@ function getParsedStorageLimits(limits) {
3423
3368
  };
3424
3369
  }
3425
3370
  function validateReadParams(params) {
3426
- const usesPagedDisplay = params.page !== void 0 || params.pageSize !== void 0 || params.assetUrlPolicy !== void 0;
3371
+ const usesPagedDisplay = params.page !== void 0 || params.pageSize !== void 0;
3427
3372
  if (!usesPagedDisplay) {
3428
3373
  return;
3429
3374
  }
3430
3375
  if (params.sectionPath !== void 0 || params.startChunk !== void 0 || params.endChunk !== void 0 || params.chunkId !== void 0) {
3431
3376
  throw new ValidationError(
3432
- "page, pageSize, and assetUrlPolicy cannot be combined with sectionPath, startChunk, endChunk, or chunkId"
3377
+ "page and pageSize cannot be combined with sectionPath, startChunk, endChunk, or chunkId"
3433
3378
  );
3434
3379
  }
3435
3380
  }
@@ -3442,9 +3387,6 @@ function getReadPageParams(params) {
3442
3387
  pageSize: clampLimit(params.pageSize ?? params.limit, DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE)
3443
3388
  };
3444
3389
  }
3445
- function shouldRequestRemoteAssetUrls(assetUrlPolicy, parsedStorageConfig) {
3446
- return assetUrlPolicy === "durable" && parsedStorageConfig !== void 0;
3447
- }
3448
3390
  function getRemoteRevisionKey(response) {
3449
3391
  const revisionKey = response.jobResultId ?? response.jobId;
3450
3392
  if (!revisionKey) {
@@ -3454,6 +3396,9 @@ function getRemoteRevisionKey(response) {
3454
3396
  }
3455
3397
  return revisionKey;
3456
3398
  }
3399
+ function getRemoteReconstructionPagePath(page) {
3400
+ return `${remoteReconstructionPageDirectory}/page-${page}.json`;
3401
+ }
3457
3402
  function createRemoteKnowledgeDocument(params) {
3458
3403
  return {
3459
3404
  localDocumentId: params.documentId,
@@ -3468,23 +3413,103 @@ function createRemoteKnowledgeDocument(params) {
3468
3413
  updatedAt: /* @__PURE__ */ new Date(0)
3469
3414
  };
3470
3415
  }
3416
+ function createMinimalParseResultFromRemoteChunks(params) {
3417
+ const chunks = params.chunks.map(toMinimalChunkFromRemoteChunk);
3418
+ const typeCounts = countRemoteChunkTypes(params.chunks);
3419
+ return {
3420
+ manifest: {
3421
+ version: "2.0",
3422
+ jobId: params.response.jobId ?? params.revisionKey,
3423
+ sourceFileName: params.documentId,
3424
+ statistics: {
3425
+ totalChunks: chunks.length,
3426
+ textChunks: typeCounts.text,
3427
+ imageChunks: typeCounts.image,
3428
+ tableChunks: typeCounts.table,
3429
+ pageChunks: typeCounts.page
3430
+ }
3431
+ },
3432
+ chunks,
3433
+ rawZip: Buffer.from(""),
3434
+ namespace: params.response.namespace,
3435
+ documentId: params.documentId,
3436
+ textChunks: chunks.filter(
3437
+ (chunk) => chunk.type === "text"
3438
+ ),
3439
+ imageChunks: chunks.filter(
3440
+ (chunk) => chunk.type === "image"
3441
+ ),
3442
+ tableChunks: chunks.filter(
3443
+ (chunk) => chunk.type === "table"
3444
+ ),
3445
+ pageChunks: chunks.filter(
3446
+ (chunk) => chunk.type === "page"
3447
+ ),
3448
+ jobId: params.response.jobId ?? params.revisionKey,
3449
+ statistics: {
3450
+ totalChunks: chunks.length,
3451
+ textChunks: typeCounts.text,
3452
+ imageChunks: typeCounts.image,
3453
+ tableChunks: typeCounts.table,
3454
+ pageChunks: typeCounts.page
3455
+ },
3456
+ getChunk: (chunkId) => chunks.find((chunk) => chunk.chunkId === chunkId),
3457
+ save: () => Promise.reject(new Error("Minimal remote reconstruction cannot be saved directly."))
3458
+ };
3459
+ }
3460
+ function toMinimalChunkFromRemoteChunk(chunk) {
3461
+ const baseChunk = {
3462
+ chunkId: chunk.chunkId,
3463
+ contentSource: chunk.contentSource ?? void 0,
3464
+ content: chunk.content ?? "",
3465
+ path: chunk.sourceChunkPath ?? chunk.sectionPath ?? "",
3466
+ metadata: cloneMetadata(chunk.metadata)
3467
+ };
3468
+ if (chunk.chunkType === "image") {
3469
+ return {
3470
+ ...baseChunk,
3471
+ type: "image",
3472
+ filePath: chunk.filePath ?? "",
3473
+ assetUrl: chunk.assetUrl ?? void 0,
3474
+ data: Buffer.alloc(0),
3475
+ format: inferContentTypeFromPath2(chunk.filePath ?? "").replace("image/", ""),
3476
+ save: () => Promise.resolve(chunk.filePath ?? "")
3477
+ };
3478
+ }
3479
+ if (chunk.chunkType === "table") {
3480
+ return {
3481
+ ...baseChunk,
3482
+ type: "table",
3483
+ filePath: chunk.filePath ?? "",
3484
+ assetUrl: chunk.assetUrl ?? void 0,
3485
+ html: chunk.content ?? "",
3486
+ save: () => Promise.resolve(chunk.filePath ?? "")
3487
+ };
3488
+ }
3489
+ if (chunk.chunkType === "page") {
3490
+ return {
3491
+ ...baseChunk,
3492
+ type: "page"
3493
+ };
3494
+ }
3495
+ return {
3496
+ ...baseChunk,
3497
+ type: "text"
3498
+ };
3499
+ }
3471
3500
  function createStoredKnowledgeDocument(params) {
3472
3501
  return {
3473
3502
  localDocumentId: params.documentId,
3474
- jobId: params.manifest.jobId || params.revisionKey,
3475
- documentId: params.manifest.documentId ?? params.documentId,
3476
- namespace: params.manifest.namespace,
3477
- sourceFileName: params.manifest.sourceFileName,
3478
- chunkCount: params.manifest.totalChunks,
3479
- typeCounts: params.typeCounts,
3503
+ jobId: params.storedResult.manifest.jobId || params.revisionKey,
3504
+ documentId: params.documentId,
3505
+ sourceFileName: params.storedResult.manifest.sourceFileName,
3506
+ chunkCount: params.storedResult.chunks.length,
3507
+ typeCounts: params.storedResult.typeCounts,
3480
3508
  resultDirectoryPath: `parsed-storage:${params.documentId}`,
3481
- createdAt: new Date(params.manifest.createdAt),
3482
- updatedAt: new Date(params.manifest.createdAt)
3509
+ createdAt: new Date(params.storedResult.commit.committedAt),
3510
+ updatedAt: new Date(params.storedResult.commit.committedAt)
3483
3511
  };
3484
3512
  }
3485
- function isFreshManifest(manifest, revisionKey) {
3486
- return (manifest.revisionKey ?? manifest.jobId) === revisionKey;
3487
- }
3488
3513
  function toRemoteReadChunk(chunk) {
3489
3514
  const metadata = cloneMetadata(chunk.metadata);
3490
3515
  return {
@@ -3513,22 +3538,60 @@ function toIndexedRemoteChunk(chunk) {
3513
3538
  const readChunk = toRemoteReadChunk(chunk);
3514
3539
  return toIndexedReadChunk(readChunk);
3515
3540
  }
3516
- function toIndexedSnapshotChunk(chunk) {
3517
- return toIndexedReadChunk({
3518
- position: chunk.sortOrder,
3519
- chunkId: chunk.chunkId,
3520
- chunkType: chunk.chunkType,
3521
- contentSource: chunk.contentSource,
3522
- content: chunk.content,
3523
- readableContent: chunk.chunkType === "page" && typeof chunk.metadata.summary === "string" && chunk.metadata.summary.trim().length > 0 ? chunk.metadata.summary : chunk.content,
3524
- sectionPath: chunk.sectionPath ?? "",
3525
- sourceChunkPath: chunk.sourceChunkPath,
3526
- filePath: chunk.filePath,
3527
- assetUrl: chunk.assetUrl,
3528
- pageNumbers: getChunkPageNumbers(chunk.metadata),
3529
- metadata: cloneMetadata(chunk.metadata)
3541
+ function parseStoredResultChunks(params) {
3542
+ const rawChunks = extractStoredChunkRecords(params.payload);
3543
+ return rawChunks.map((record, index) => {
3544
+ const metadata = readRecordMetadata(record);
3545
+ const chunkType = readRecordString(record, "type", "chunkType", "chunk_type");
3546
+ const content = readRecordString(record, "content") ?? "";
3547
+ const sourceChunkPath = readRecordString(record, "path", "sourceChunkPath", "source_chunk_path") ?? "";
3548
+ const chunk = {
3549
+ position: index + 1,
3550
+ chunkId: readRecordString(record, "chunkId", "chunk_id") ?? "",
3551
+ chunkType: isKnowledgeChunkType(chunkType) ? chunkType : "text",
3552
+ contentSource: readRecordString(record, "contentSource", "content_source"),
3553
+ content,
3554
+ readableContent: chunkType === "page" && typeof metadata.summary === "string" && metadata.summary.trim().length > 0 ? metadata.summary : content,
3555
+ sectionPath: normalizeSectionPath(sourceChunkPath, params.sourceFileName),
3556
+ sourceChunkPath,
3557
+ filePath: readRecordString(record, "filePath", "file_path") ?? (typeof metadata.filePath === "string" ? metadata.filePath : void 0),
3558
+ assetUrl: readRecordString(record, "assetUrl", "asset_url"),
3559
+ pageNumbers: getChunkPageNumbers(metadata),
3560
+ metadata
3561
+ };
3562
+ return toIndexedReadChunk(chunk);
3530
3563
  });
3531
3564
  }
3565
+ function extractStoredChunkRecords(payload) {
3566
+ if (Array.isArray(payload)) {
3567
+ return payload.filter(isRecord2);
3568
+ }
3569
+ if (isRecord2(payload) && Array.isArray(payload.chunks)) {
3570
+ return payload.chunks.filter(isRecord2);
3571
+ }
3572
+ return [];
3573
+ }
3574
+ function readRecordString(record, ...keys) {
3575
+ for (const key of keys) {
3576
+ const value = record[key];
3577
+ if (typeof value === "string") return value;
3578
+ }
3579
+ return void 0;
3580
+ }
3581
+ function readRecordNumber(record, ...keys) {
3582
+ for (const key of keys) {
3583
+ const value = record[key];
3584
+ if (typeof value === "number") return value;
3585
+ }
3586
+ return void 0;
3587
+ }
3588
+ function readRecordMetadata(record) {
3589
+ const metadata = record.metadata;
3590
+ return isRecord2(metadata) ? keysToCamel(metadata) : {};
3591
+ }
3592
+ function isKnowledgeChunkType(value) {
3593
+ return value === "text" || value === "image" || value === "table" || value === "page";
3594
+ }
3532
3595
  function toIndexedReadChunk(chunk) {
3533
3596
  return {
3534
3597
  source: createSyntheticChunk(chunk),
@@ -3582,204 +3645,105 @@ function getNextChunkPosition(chunks, selected) {
3582
3645
  }
3583
3646
  return chunks[chunks.indexOf(lastSelected) + 1]?.position;
3584
3647
  }
3585
- function applyAssetUrlPolicyToReadChunks(chunks, assetUrlPolicy) {
3586
- if (assetUrlPolicy !== "none") {
3587
- return chunks.map((chunk) => ({
3588
- ...chunk,
3589
- metadata: cloneMetadata(chunk.metadata)
3590
- }));
3591
- }
3592
- return chunks.map((chunk) => ({
3593
- ...chunk,
3594
- assetUrl: void 0,
3595
- metadata: removeAssetUrlsFromMetadata(chunk.metadata)
3596
- }));
3648
+ async function applyStoredAssetUrlsToReadChunks(params) {
3649
+ return Promise.all(
3650
+ params.chunks.map(
3651
+ (chunk) => applyStoredAssetUrlsToReadChunk({
3652
+ ...params,
3653
+ chunk
3654
+ })
3655
+ )
3656
+ );
3597
3657
  }
3598
- async function hardenReadChunkAssetUrls(params) {
3658
+ async function applyStoredAssetUrlsToReadChunk(params) {
3599
3659
  const metadata = cloneMetadata(params.chunk.metadata);
3600
- const assetUrl = await hardenPrimaryAssetUrl(params, metadata);
3601
- const pageAssets = await hardenPageAssetUrls(params, metadata);
3602
- if (pageAssets) {
3603
- metadata.pageAssets = pageAssets;
3604
- }
3605
- return {
3606
- ...params.chunk,
3607
- assetUrl,
3608
- metadata
3609
- };
3610
- }
3611
- async function hardenPrimaryAssetUrl(params, metadata) {
3612
- if (!params.chunk.assetUrl || !params.chunk.filePath) {
3613
- return void 0;
3614
- }
3615
- return writeDurableAssetUrl({
3660
+ const storedAssetUrl = await getStoredObjectUrl({
3616
3661
  storageConfig: params.storageConfig,
3617
3662
  documentId: params.documentId,
3618
3663
  revisionKey: params.revisionKey,
3619
- sourcePath: params.chunk.filePath,
3620
- sourceUrl: params.chunk.assetUrl,
3621
- fallbackContentType: inferContentTypeFromPath(params.chunk.filePath),
3622
- metadata: {
3623
- chunkId: params.chunk.chunkId,
3624
- chunkType: params.chunk.chunkType,
3625
- sourcePath: params.chunk.filePath,
3626
- ...stringifyFlatMetadata(metadata)
3627
- }
3664
+ path: params.chunk.filePath
3628
3665
  });
3629
- }
3630
- async function hardenPageAssetUrls(params, metadata) {
3631
- const pageAssets = toUnknownArray(metadata.pageAssets);
3632
- if (!pageAssets) {
3633
- return void 0;
3634
- }
3635
- const hardenedAssets = [];
3636
- for (const pageAsset of pageAssets) {
3637
- if (!isRecord2(pageAsset)) {
3638
- hardenedAssets.push(pageAsset);
3639
- continue;
3640
- }
3641
- const artifactRef = pageAsset.artifactRef;
3642
- const sourceUrl = pageAsset.assetUrl;
3643
- if (typeof artifactRef !== "string" || typeof sourceUrl !== "string") {
3644
- hardenedAssets.push(removeAssetUrlField(pageAsset));
3645
- continue;
3646
- }
3647
- const durableUrl = await writeDurableAssetUrl({
3648
- storageConfig: params.storageConfig,
3649
- documentId: params.documentId,
3650
- revisionKey: params.revisionKey,
3651
- sourcePath: artifactRef,
3652
- sourceUrl,
3653
- fallbackContentType: typeof pageAsset.contentType === "string" ? pageAsset.contentType : inferContentTypeFromPath(artifactRef),
3654
- metadata: {
3655
- chunkId: params.chunk.chunkId,
3656
- chunkType: params.chunk.chunkType,
3657
- sourcePath: artifactRef
3658
- }
3659
- });
3660
- const rest = removeAssetUrlField(pageAsset);
3661
- hardenedAssets.push(durableUrl ? { ...rest, assetUrl: durableUrl } : rest);
3662
- }
3663
- return hardenedAssets;
3664
- }
3665
- async function writeDurableAssetUrl(params) {
3666
- const existingUrl = await params.storageConfig.storage.getAssetUrl({
3666
+ const pageAssets = await applyStoredPageAssetUrls({
3667
+ storageConfig: params.storageConfig,
3667
3668
  documentId: params.documentId,
3668
3669
  revisionKey: params.revisionKey,
3669
- sourcePath: params.sourcePath
3670
+ metadata
3670
3671
  });
3671
- if (existingUrl) {
3672
- return existingUrl;
3673
- }
3674
- try {
3675
- const fetched = await fetchAsset(params.sourceUrl, params.fallbackContentType);
3676
- const written = await params.storageConfig.storage.writeAsset({
3677
- documentId: params.documentId,
3678
- revisionKey: params.revisionKey,
3679
- sourcePath: params.sourcePath,
3680
- body: fetched.body,
3681
- contentType: fetched.contentType,
3682
- metadata: params.metadata
3683
- });
3684
- return written.url ?? await params.storageConfig.storage.getAssetUrl({
3685
- documentId: params.documentId,
3686
- revisionKey: params.revisionKey,
3687
- sourcePath: params.sourcePath
3688
- }) ?? void 0;
3689
- } catch {
3690
- return void 0;
3691
- }
3692
- }
3693
- async function fetchAsset(sourceUrl, fallbackContentType) {
3694
- const response = await fetch(sourceUrl);
3695
- if (!response.ok) {
3696
- throw new Error(`Unable to fetch parsed asset: ${response.status}`);
3672
+ if (pageAssets) {
3673
+ metadata.pageAssets = pageAssets;
3674
+ delete metadata.page_assets;
3697
3675
  }
3698
3676
  return {
3699
- body: new Uint8Array(await response.arrayBuffer()),
3700
- contentType: response.headers.get("content-type") ?? fallbackContentType
3677
+ ...params.chunk,
3678
+ assetUrl: storedAssetUrl ?? params.chunk.assetUrl,
3679
+ metadata
3701
3680
  };
3702
3681
  }
3703
- function removeAssetUrlsFromMetadata(metadata) {
3704
- const cloned = cloneMetadata(metadata);
3705
- const pageAssets = toUnknownArray(cloned.pageAssets);
3682
+ async function applyStoredPageAssetUrls(params) {
3683
+ const pageAssets = getStoredPageAssets(params.metadata);
3706
3684
  if (!pageAssets) {
3707
- return cloned;
3685
+ return void 0;
3708
3686
  }
3709
- cloned.pageAssets = pageAssets.map((pageAsset) => {
3710
- if (!isRecord2(pageAsset)) {
3687
+ return Promise.all(
3688
+ pageAssets.map(async (pageAsset) => {
3689
+ if (!isRecord2(pageAsset)) {
3690
+ return pageAsset;
3691
+ }
3692
+ const artifactRef = readRecordString(pageAsset, "artifactRef", "artifact_ref");
3693
+ if (typeof artifactRef !== "string") {
3694
+ return pageAsset;
3695
+ }
3696
+ const storedAssetUrl = await getStoredObjectUrl({
3697
+ storageConfig: params.storageConfig,
3698
+ documentId: params.documentId,
3699
+ revisionKey: params.revisionKey,
3700
+ path: artifactRef
3701
+ });
3702
+ if (storedAssetUrl) {
3703
+ return {
3704
+ ...pageAsset,
3705
+ artifactRef,
3706
+ assetUrl: storedAssetUrl
3707
+ };
3708
+ }
3711
3709
  return pageAsset;
3712
- }
3713
- return removeAssetUrlField(pageAsset);
3714
- });
3715
- return cloned;
3716
- }
3717
- function removeAssetUrlField(value) {
3718
- const cloned = { ...value };
3719
- delete cloned.assetUrl;
3720
- return cloned;
3721
- }
3722
- function toSnapshotChunkPageFromReadChunks(params) {
3723
- return {
3724
- version: 1,
3725
- jobId: params.response.jobId ?? params.revisionKey,
3726
- revisionKey: params.revisionKey,
3727
- documentId: params.response.documentId,
3728
- namespace: params.response.namespace,
3729
- sourceFileName: params.response.documentId,
3730
- page: params.response.pagination.page,
3731
- pageSize: params.response.pagination.pageSize,
3732
- total: params.response.pagination.total,
3733
- totalPages: params.response.pagination.totalPages,
3734
- chunks: params.chunks.map(toSnapshotChunkFromReadChunk)
3735
- };
3710
+ })
3711
+ );
3736
3712
  }
3737
- function toSnapshotChunkFromReadChunk(chunk) {
3713
+ function getStoredPageAssets(metadata) {
3714
+ const pageAssets = toUnknownArray(metadata.pageAssets) ?? toUnknownArray(metadata.page_assets) ?? void 0;
3715
+ return pageAssets?.map(normalizeStoredPageAsset);
3716
+ }
3717
+ function normalizeStoredPageAsset(pageAsset) {
3718
+ if (!isRecord2(pageAsset)) {
3719
+ return pageAsset;
3720
+ }
3721
+ const normalizedPageAsset = { ...pageAsset };
3722
+ delete normalizedPageAsset.page_num;
3723
+ delete normalizedPageAsset.artifact_ref;
3724
+ delete normalizedPageAsset.asset_url;
3725
+ delete normalizedPageAsset.content_type;
3726
+ const pageNum = readRecordNumber(pageAsset, "pageNum", "page_num");
3727
+ const artifactRef = readRecordString(pageAsset, "artifactRef", "artifact_ref");
3728
+ const assetUrl = readRecordString(pageAsset, "assetUrl", "asset_url");
3729
+ const contentType = readRecordString(pageAsset, "contentType", "content_type");
3738
3730
  return {
3739
- id: chunk.chunkId,
3740
- chunkId: chunk.chunkId,
3741
- chunkType: chunk.chunkType,
3742
- contentSource: chunk.contentSource,
3743
- content: chunk.content,
3744
- sectionPath: chunk.sectionPath,
3745
- sourceChunkPath: chunk.sourceChunkPath,
3746
- filePath: chunk.filePath,
3747
- sortOrder: chunk.position,
3748
- metadata: cloneMetadata(chunk.metadata),
3749
- assetUrl: chunk.assetUrl
3731
+ ...normalizedPageAsset,
3732
+ ...pageNum === void 0 ? {} : { pageNum },
3733
+ ...artifactRef === void 0 ? {} : { artifactRef },
3734
+ ...assetUrl === void 0 ? {} : { assetUrl },
3735
+ ...contentType === void 0 ? {} : { contentType }
3750
3736
  };
3751
3737
  }
3752
- function createRemoteSnapshotManifest(params) {
3753
- return {
3754
- version: 1,
3755
- kind: "knowhere-parsed-result-snapshot",
3756
- jobId: params.response.jobId ?? params.revisionKey,
3738
+ async function getStoredObjectUrl(params) {
3739
+ if (!params.path) {
3740
+ return void 0;
3741
+ }
3742
+ return await params.storageConfig.storage.getObjectUrl?.({
3743
+ documentId: params.documentId,
3757
3744
  revisionKey: params.revisionKey,
3758
- documentId: params.response.documentId,
3759
- namespace: params.response.namespace,
3760
- sourceFileName: params.response.documentId,
3761
- totalChunks: params.response.pagination.total,
3762
- typeCounts: countSnapshotPagesTypes(params.chunkPages),
3763
- chunkPageSize: params.response.pagination.pageSize,
3764
- chunkPages: Array.from({ length: params.response.pagination.totalPages }, (_, index) => ({
3765
- page: index + 1,
3766
- pageSize: params.response.pagination.pageSize,
3767
- chunkCount: index + 1 === params.response.pagination.totalPages ? params.response.pagination.total - params.response.pagination.pageSize * (params.response.pagination.totalPages - 1) : params.response.pagination.pageSize,
3768
- key: `parsed/chunks/page-${index + 1}.json`
3769
- })),
3770
- assetUrlsByFilePath: {},
3771
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
3772
- };
3773
- }
3774
- function countSnapshotPagesTypes(pages) {
3775
- return pages.flatMap((page) => page.chunks).reduce(
3776
- (counts, chunk) => {
3777
- const chunkType = chunk.chunkType;
3778
- counts[chunkType] += 1;
3779
- return counts;
3780
- },
3781
- { text: 0, image: 0, table: 0, page: 0 }
3782
- );
3745
+ path: params.path
3746
+ }) ?? void 0;
3783
3747
  }
3784
3748
  function countRemoteChunkTypes(chunks) {
3785
3749
  return chunks.reduce(
@@ -3857,22 +3821,10 @@ function isOptionalNonNegativeInteger(value) {
3857
3821
  function cloneMetadata(metadata) {
3858
3822
  return { ...metadata };
3859
3823
  }
3860
- function stringifyFlatMetadata(metadata) {
3861
- const entries = Object.entries(metadata).flatMap(([key, value]) => {
3862
- if (typeof value === "string") {
3863
- return [[key, value]];
3864
- }
3865
- if (typeof value === "number" || typeof value === "boolean") {
3866
- return [[key, String(value)]];
3867
- }
3868
- return [];
3869
- });
3870
- return Object.fromEntries(entries);
3871
- }
3872
3824
  function toUnknownArray(value) {
3873
3825
  return Array.isArray(value) ? value : null;
3874
3826
  }
3875
- function inferContentTypeFromPath(filePath) {
3827
+ function inferContentTypeFromPath2(filePath) {
3876
3828
  const extension = filePath.split(".").at(-1)?.toLowerCase();
3877
3829
  if (extension === "png") return "image/png";
3878
3830
  if (extension === "jpg" || extension === "jpeg") return "image/jpeg";
@@ -3882,6 +3834,9 @@ function inferContentTypeFromPath(filePath) {
3882
3834
  function isRecord2(value) {
3883
3835
  return typeof value === "object" && value !== null && !Array.isArray(value);
3884
3836
  }
3837
+ function isDocumentChunkArray(value) {
3838
+ return Array.isArray(value) && value.every(isRecord2);
3839
+ }
3885
3840
  function indexChunks(result) {
3886
3841
  return result.chunks.map((chunk, index) => {
3887
3842
  const filePath = getChunkFilePath2(chunk);
@@ -4327,51 +4282,59 @@ var Knowhere = class {
4327
4282
  var import_crypto3 = require("crypto");
4328
4283
  var import_fs4 = require("fs");
4329
4284
  var import_path4 = __toESM(require("path"));
4285
+ var syncProgressPath = ".knowhere-sdk/sync-progress.json";
4330
4286
  var DiskParsedDocumentStorage = class {
4331
4287
  rootDirectory;
4332
4288
  constructor(rootDirectory) {
4333
4289
  this.rootDirectory = rootDirectory;
4334
4290
  }
4335
- async readManifest(params) {
4336
- return this.readOptionalJson(
4337
- this.getManifestPath(params.documentId, params.revisionKey)
4338
- );
4339
- }
4340
- async writeManifest(params) {
4341
- await this.writeJson(
4342
- this.getManifestPath(params.documentId, params.revisionKey),
4343
- params.manifest
4344
- );
4345
- }
4346
- async readChunkPage(params) {
4347
- return this.readOptionalJson(
4348
- this.getChunkPagePath(params.documentId, params.revisionKey, params.page)
4349
- );
4350
- }
4351
- async writeChunkPage(params) {
4352
- await this.writeJson(
4353
- this.getChunkPagePath(params.documentId, params.revisionKey, params.page.page),
4354
- params.page
4355
- );
4291
+ async readObject(params) {
4292
+ const objectPath = this.getObjectPath(params);
4293
+ try {
4294
+ const body = await import_fs4.promises.readFile(objectPath);
4295
+ const metadata = await this.readObjectMetadata(objectPath);
4296
+ return {
4297
+ ...params,
4298
+ body,
4299
+ contentType: metadata?.contentType,
4300
+ contentLength: body.byteLength,
4301
+ metadata: metadata?.metadata,
4302
+ url: toFileUrl(objectPath)
4303
+ };
4304
+ } catch (error) {
4305
+ if (isMissingFileError3(error)) {
4306
+ return null;
4307
+ }
4308
+ throw error;
4309
+ }
4356
4310
  }
4357
- async writeAsset(params) {
4358
- const assetPath = this.getAssetPath(params.documentId, params.revisionKey, params.sourcePath);
4359
- await import_fs4.promises.mkdir(import_path4.default.dirname(assetPath), { recursive: true });
4360
- await import_fs4.promises.writeFile(assetPath, params.body);
4361
- await this.writeJson(`${assetPath}.metadata.json`, {
4311
+ async writeObject(params) {
4312
+ const objectPath = this.getObjectPath(params);
4313
+ await import_fs4.promises.mkdir(import_path4.default.dirname(objectPath), { recursive: true });
4314
+ await import_fs4.promises.writeFile(objectPath, params.body);
4315
+ await this.writeObjectMetadata(objectPath, {
4362
4316
  contentType: params.contentType,
4363
- metadata: params.metadata ?? {}
4317
+ metadata: params.metadata
4364
4318
  });
4365
4319
  return {
4366
- sourcePath: params.sourcePath,
4367
- url: toFileUrl(assetPath)
4320
+ documentId: params.documentId,
4321
+ revisionKey: params.revisionKey,
4322
+ path: params.path,
4323
+ url: toFileUrl(objectPath)
4368
4324
  };
4369
4325
  }
4370
- async getAssetUrl(params) {
4371
- const assetPath = this.getAssetPath(params.documentId, params.revisionKey, params.sourcePath);
4326
+ async headObject(params) {
4327
+ const objectPath = this.getObjectPath(params);
4372
4328
  try {
4373
- await import_fs4.promises.access(assetPath);
4374
- return toFileUrl(assetPath);
4329
+ const stat = await import_fs4.promises.stat(objectPath);
4330
+ const metadata = await this.readObjectMetadata(objectPath);
4331
+ return {
4332
+ ...params,
4333
+ contentType: metadata?.contentType,
4334
+ contentLength: stat.size,
4335
+ metadata: metadata?.metadata,
4336
+ url: toFileUrl(objectPath)
4337
+ };
4375
4338
  } catch (error) {
4376
4339
  if (isMissingFileError3(error)) {
4377
4340
  return null;
@@ -4379,53 +4342,54 @@ var DiskParsedDocumentStorage = class {
4379
4342
  throw error;
4380
4343
  }
4381
4344
  }
4382
- async readSyncProgress(params) {
4383
- return this.readOptionalJson(
4384
- this.getProgressPath(params.documentId, params.revisionKey)
4385
- );
4386
- }
4387
- async writeSyncProgress(params) {
4388
- await this.writeJson(this.getProgressPath(params.documentId, params.revisionKey), params);
4345
+ async getObjectUrl(params) {
4346
+ const head = await this.headObject(params);
4347
+ return head?.url ?? null;
4389
4348
  }
4390
- getManifestPath(documentId, revisionKey) {
4391
- return import_path4.default.join(
4392
- this.getRevisionDirectory(documentId, revisionKey),
4393
- "manifest",
4394
- "current.json"
4395
- );
4349
+ async deletePrefix(params) {
4350
+ await import_fs4.promises.rm(this.getRevisionDirectory(params.documentId, params.revisionKey), {
4351
+ recursive: true,
4352
+ force: true
4353
+ });
4396
4354
  }
4397
- getChunkPagePath(documentId, revisionKey, page) {
4398
- return import_path4.default.join(
4399
- this.getRevisionDirectory(documentId, revisionKey),
4400
- "chunks",
4401
- `page-${page}.json`
4402
- );
4355
+ async readSyncProgress(params) {
4356
+ return this.readOptionalJson({
4357
+ ...params,
4358
+ path: syncProgressPath
4359
+ });
4403
4360
  }
4404
- getProgressPath(documentId, revisionKey) {
4405
- return import_path4.default.join(this.getRevisionDirectory(documentId, revisionKey), "sync-progress.json");
4361
+ async writeSyncProgress(params) {
4362
+ await this.writeObject({
4363
+ documentId: params.documentId,
4364
+ revisionKey: params.revisionKey,
4365
+ path: syncProgressPath,
4366
+ body: Buffer.from(JSON.stringify(params, null, 2), "utf8"),
4367
+ contentType: "application/json; charset=utf-8"
4368
+ });
4406
4369
  }
4407
- getAssetPath(documentId, revisionKey, sourcePath) {
4408
- const normalizedSourcePath = normalizeRelativeStoragePath(sourcePath);
4409
- const assetPath = import_path4.default.resolve(
4410
- this.getRevisionDirectory(documentId, revisionKey),
4411
- "assets",
4412
- normalizedSourcePath
4413
- );
4414
- const assetsDirectory = import_path4.default.resolve(
4415
- this.getRevisionDirectory(documentId, revisionKey),
4416
- "assets"
4417
- );
4418
- if (!isPathInsideDirectory2(assetPath, assetsDirectory)) {
4419
- throw new Error(`Parsed asset path resolves outside storage: ${sourcePath}`);
4370
+ getObjectPath(params) {
4371
+ const revisionDirectory = this.getRevisionDirectory(params.documentId, params.revisionKey);
4372
+ const objectPath = import_path4.default.resolve(revisionDirectory, normalizeRelativeStoragePath(params.path));
4373
+ if (!isPathInsideDirectory2(objectPath, revisionDirectory)) {
4374
+ throw new Error(`Parsed document object path resolves outside storage: ${params.path}`);
4420
4375
  }
4421
- return assetPath;
4376
+ return objectPath;
4422
4377
  }
4423
4378
  getRevisionDirectory(documentId, revisionKey) {
4424
4379
  return import_path4.default.join(this.rootDirectory, hashPathPart(documentId), hashPathPart(revisionKey));
4425
4380
  }
4426
- async readOptionalJson(filePath) {
4381
+ async readOptionalJson(params) {
4382
+ const object = await this.readObject(params);
4383
+ if (!object) {
4384
+ return null;
4385
+ }
4386
+ return JSON.parse(Buffer.from(object.body).toString("utf8"));
4387
+ }
4388
+ async readObjectMetadata(filePath) {
4427
4389
  try {
4428
- return JSON.parse(await import_fs4.promises.readFile(filePath, "utf8"));
4390
+ return JSON.parse(
4391
+ await import_fs4.promises.readFile(getMetadataPath(filePath), "utf8")
4392
+ );
4429
4393
  } catch (error) {
4430
4394
  if (isMissingFileError3(error)) {
4431
4395
  return null;
@@ -4433,16 +4397,22 @@ var DiskParsedDocumentStorage = class {
4433
4397
  throw error;
4434
4398
  }
4435
4399
  }
4436
- async writeJson(filePath, value) {
4437
- await import_fs4.promises.mkdir(import_path4.default.dirname(filePath), { recursive: true });
4438
- await import_fs4.promises.writeFile(filePath, JSON.stringify(value, null, 2), {
4400
+ async writeObjectMetadata(filePath, metadata) {
4401
+ await import_fs4.promises.writeFile(getMetadataPath(filePath), JSON.stringify(metadata, null, 2), {
4439
4402
  encoding: "utf8",
4440
4403
  flag: "w"
4441
4404
  });
4442
4405
  }
4443
4406
  };
4407
+ function getMetadataPath(filePath) {
4408
+ return `${filePath}.metadata.json`;
4409
+ }
4444
4410
  function hashPathPart(value) {
4445
- return (0, import_crypto3.createHash)("sha256").update(value).digest("hex").slice(0, 24);
4411
+ const normalized = value.trim();
4412
+ if (normalized.length === 0) {
4413
+ throw new Error("Parsed document storage path part must be a non-empty value.");
4414
+ }
4415
+ return (0, import_crypto3.createHash)("sha256").update(normalized).digest("hex").slice(0, 24);
4446
4416
  }
4447
4417
  function normalizeRelativeStoragePath(value) {
4448
4418
  const normalized = value.replaceAll("\\", "/").replace(/^\.\/+/, "");