@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.mjs CHANGED
@@ -1527,10 +1527,6 @@ import JSZip2 from "jszip";
1527
1527
  var pageCitationAssetsMetadataKey = "pageAssets";
1528
1528
  var defaultImageContentType = "application/octet-stream";
1529
1529
  var tableContentType = "text/html; charset=utf-8";
1530
- var snapshotManifestKey = "manifest/current.json";
1531
- var snapshotIndexKey = "index.json";
1532
- var defaultSnapshotChunkPageSize = 200;
1533
- var snapshotJsonContentType = "application/json; charset=utf-8";
1534
1530
  async function storeParseResultAssets(result, options) {
1535
1531
  if (!options) {
1536
1532
  return {
@@ -1548,148 +1544,11 @@ async function storeParseResultAssets(result, options) {
1548
1544
  }
1549
1545
  }
1550
1546
  const normalizedResult = Object.keys(assetUrlsByFilePath).length === 0 ? result : rewriteResultAssetUrls(result, assetUrlsByFilePath);
1551
- const snapshot = await storeParsedSnapshot({
1552
- result: normalizedResult,
1553
- assetUrlsByFilePath,
1554
- keyPrefix: normalizedKeyPrefix,
1555
- options
1556
- });
1557
1547
  return {
1558
1548
  result: normalizedResult,
1559
- assetUrlsByFilePath,
1560
- snapshot
1561
- };
1562
- }
1563
- async function storeParsedSnapshot(input) {
1564
- const pageSize = normalizeSnapshotChunkPageSize(input.options.chunkPageSize);
1565
- const totalChunks = input.result.chunks.length;
1566
- const totalPages = Math.max(1, Math.ceil(totalChunks / pageSize));
1567
- const chunkPageReferences = [];
1568
- const chunkPageUrlsByPage = {};
1569
- for (let page = 1; page <= totalPages; page += 1) {
1570
- const pageChunks = input.result.chunks.slice((page - 1) * pageSize, page * pageSize);
1571
- const pageKey = `${input.keyPrefix}/chunks/page-${page}.json`;
1572
- const chunkPage = {
1573
- version: 1,
1574
- jobId: input.result.jobId,
1575
- revisionKey: input.options.revisionKey ?? input.result.jobId,
1576
- documentId: input.result.documentId,
1577
- namespace: input.result.namespace,
1578
- sourceFileName: input.result.manifest.sourceFileName,
1579
- page,
1580
- pageSize,
1581
- total: totalChunks,
1582
- totalPages,
1583
- chunks: pageChunks.map(
1584
- (chunk, index) => toSnapshotChunk(chunk, (page - 1) * pageSize + index + 1)
1585
- )
1586
- };
1587
- const pageUrl = await writeJsonObject({
1588
- key: pageKey,
1589
- value: chunkPage,
1590
- adapter: input.options.adapter
1591
- });
1592
- if (pageUrl) chunkPageUrlsByPage[page] = pageUrl;
1593
- chunkPageReferences.push({
1594
- page,
1595
- pageSize,
1596
- chunkCount: pageChunks.length,
1597
- key: pageKey,
1598
- url: pageUrl
1599
- });
1600
- }
1601
- const manifest = {
1602
- version: 1,
1603
- kind: "knowhere-parsed-result-snapshot",
1604
- jobId: input.result.jobId,
1605
- revisionKey: input.options.revisionKey ?? input.result.jobId,
1606
- documentId: input.result.documentId,
1607
- namespace: input.result.namespace,
1608
- sourceFileName: input.result.manifest.sourceFileName,
1609
- totalChunks,
1610
- typeCounts: countSnapshotChunkTypes(input.result.chunks),
1611
- chunkPageSize: pageSize,
1612
- chunkPages: chunkPageReferences,
1613
- assetUrlsByFilePath: input.assetUrlsByFilePath,
1614
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
1615
- };
1616
- const manifestKey = `${input.keyPrefix}/${snapshotManifestKey}`;
1617
- const indexKey = `${input.keyPrefix}/${snapshotIndexKey}`;
1618
- const manifestUrl = await writeJsonObject({
1619
- key: manifestKey,
1620
- value: manifest,
1621
- adapter: input.options.adapter
1622
- });
1623
- const indexUrl = await writeJsonObject({
1624
- key: indexKey,
1625
- value: manifest,
1626
- adapter: input.options.adapter
1627
- });
1628
- return {
1629
- manifest,
1630
- manifestKey,
1631
- manifestUrl,
1632
- indexKey,
1633
- indexUrl,
1634
- chunkPageUrlsByPage
1635
- };
1636
- }
1637
- function countSnapshotChunkTypes(chunks) {
1638
- return chunks.reduce(
1639
- (counts, chunk) => {
1640
- counts[chunk.type] += 1;
1641
- return counts;
1642
- },
1643
- { text: 0, image: 0, table: 0, page: 0 }
1644
- );
1645
- }
1646
- async function writeJsonObject(input) {
1647
- const result = await input.adapter.writeObject({
1648
- key: input.key,
1649
- body: Buffer.from(JSON.stringify(input.value, null, 2), "utf8"),
1650
- contentType: snapshotJsonContentType,
1651
- metadata: {
1652
- kind: "knowhere-parsed-result-snapshot"
1653
- }
1654
- });
1655
- return result.url ?? await input.adapter.getObjectUrl?.(result.key) ?? void 0;
1656
- }
1657
- function normalizeSnapshotChunkPageSize(value) {
1658
- if (!Number.isInteger(value) || value === void 0) return defaultSnapshotChunkPageSize;
1659
- return Math.min(Math.max(value, 1), 1e3);
1660
- }
1661
- function toSnapshotChunk(chunk, position) {
1662
- const filePath = getSnapshotChunkFilePath(chunk);
1663
- return {
1664
- id: chunk.chunkId,
1665
- chunkId: chunk.chunkId,
1666
- chunkType: chunk.type,
1667
- contentSource: chunk.contentSource,
1668
- content: chunk.content,
1669
- sectionPath: normalizeSnapshotSectionPath(chunk.path),
1670
- sourceChunkPath: chunk.path,
1671
- filePath,
1672
- sortOrder: position,
1673
- metadata: cloneChunkMetadata(chunk.metadata),
1674
- assetUrl: getSnapshotChunkAssetUrl(chunk)
1549
+ assetUrlsByFilePath
1675
1550
  };
1676
1551
  }
1677
- function normalizeSnapshotSectionPath(path4) {
1678
- return path4.length > 0 ? path4 : void 0;
1679
- }
1680
- function getSnapshotChunkFilePath(chunk) {
1681
- if (chunk.type === "image" || chunk.type === "table") {
1682
- return chunk.filePath;
1683
- }
1684
- const filePath = chunk.metadata.filePath;
1685
- return typeof filePath === "string" ? filePath : void 0;
1686
- }
1687
- function getSnapshotChunkAssetUrl(chunk) {
1688
- return chunk.type === "image" || chunk.type === "table" ? chunk.assetUrl : void 0;
1689
- }
1690
- function cloneChunkMetadata(metadata) {
1691
- return { ...metadata };
1692
- }
1693
1552
  async function collectStorageAssets(result, keyPrefix) {
1694
1553
  const resultZip = await loadResultZipForPageCitationAssets(result);
1695
1554
  return [
@@ -1926,108 +1785,212 @@ function isRecord(value) {
1926
1785
  }
1927
1786
 
1928
1787
  // src/storage/parsed-document-storage.ts
1929
- var parsedStorageKeyPrefix = "parsed";
1930
- var manifestStoragePath = "manifest/current.json";
1931
- var indexStoragePath = "index.json";
1932
- var chunkPagePathPattern = /^chunks\/page-(\d+)\.json$/;
1788
+ import JSZip3 from "jszip";
1789
+ var parsedDocumentCommitPath = ".knowhere-sdk/commit.json";
1790
+ var jsonContentType = "application/json; charset=utf-8";
1791
+ var markdownContentType = "text/markdown; charset=utf-8";
1792
+ var csvContentType = "text/csv; charset=utf-8";
1793
+ var htmlContentType = "text/html; charset=utf-8";
1794
+ var binaryContentType = "application/octet-stream";
1933
1795
  async function syncParseResultToParsedDocumentStorage(params) {
1934
1796
  const documentId = params.documentId ?? params.result.documentId ?? params.result.jobId;
1935
1797
  const revisionKey = params.revisionKey ?? params.result.jobId;
1936
- const adapter = createParsedDocumentObjectStorageAdapter({
1937
- storage: params.storage,
1798
+ const objects = await collectResultLayoutObjects(params.result);
1799
+ for (const object of objects) {
1800
+ await params.storage.writeObject({
1801
+ documentId,
1802
+ revisionKey,
1803
+ ...object
1804
+ });
1805
+ }
1806
+ const commit = {
1807
+ version: 1,
1938
1808
  documentId,
1939
- revisionKey
1940
- });
1941
- const stored = await storeParseResultAssets(params.result, {
1942
- adapter,
1943
- keyPrefix: parsedStorageKeyPrefix,
1944
- chunkPageSize: params.chunkPageSize,
1945
- revisionKey
1809
+ revisionKey,
1810
+ source: params.source ?? "resultZip",
1811
+ committedAt: (/* @__PURE__ */ new Date()).toISOString()
1812
+ };
1813
+ await writeParsedDocumentJsonObject(params.storage, {
1814
+ documentId,
1815
+ revisionKey,
1816
+ path: parsedDocumentCommitPath,
1817
+ value: commit
1946
1818
  });
1947
1819
  return {
1948
- result: stored.result,
1949
- snapshot: stored.snapshot,
1820
+ result: params.result,
1950
1821
  documentId,
1951
- revisionKey
1822
+ revisionKey,
1823
+ commit
1952
1824
  };
1953
1825
  }
1954
- function createParsedDocumentObjectStorageAdapter(params) {
1955
- return {
1956
- writeObject: (input) => writeParsedStorageObject(params, input),
1957
- headObject: (key) => headParsedStorageObject(params, key),
1958
- getObjectUrl: (key) => getParsedStorageObjectUrl(params, key)
1959
- };
1826
+ async function readParsedDocumentCommit(params) {
1827
+ const object = await params.storage.readObject({
1828
+ documentId: params.documentId,
1829
+ revisionKey: params.revisionKey,
1830
+ path: parsedDocumentCommitPath
1831
+ });
1832
+ if (!object) {
1833
+ return null;
1834
+ }
1835
+ const commit = readJsonObject(object);
1836
+ return commit.revisionKey === params.revisionKey && commit.documentId === params.documentId ? commit : null;
1960
1837
  }
1961
- async function writeParsedStorageObject(params, input) {
1962
- const storagePath = stripParsedStorageKeyPrefix(input.key);
1963
- if (storagePath === manifestStoragePath) {
1964
- const manifest = JSON.parse(
1965
- Buffer.from(input.body).toString("utf8")
1966
- );
1967
- await params.storage.writeManifest({
1968
- documentId: params.documentId,
1969
- revisionKey: params.revisionKey,
1970
- manifest
1971
- });
1972
- return { key: input.key };
1838
+ function readJsonObject(object) {
1839
+ return JSON.parse(Buffer.from(object.body).toString("utf8"));
1840
+ }
1841
+ async function collectResultLayoutObjects(result) {
1842
+ const objectsByPath = /* @__PURE__ */ new Map();
1843
+ const rawZipObjects = await collectRawZipObjects(result.rawZip);
1844
+ for (const object of rawZipObjects) {
1845
+ objectsByPath.set(object.path, object);
1846
+ }
1847
+ for (const object of collectGeneratedResultObjects(result)) {
1848
+ if (!objectsByPath.has(object.path)) {
1849
+ objectsByPath.set(object.path, object);
1850
+ }
1851
+ }
1852
+ return [...objectsByPath.values()].filter((object) => !isSdkMetadataPath(object.path));
1853
+ }
1854
+ async function collectRawZipObjects(rawZip) {
1855
+ try {
1856
+ const zip = await JSZip3.loadAsync(rawZip);
1857
+ const objects = [];
1858
+ for (const entry of Object.values(zip.files)) {
1859
+ if (entry.dir || entry.name === "result.zip") {
1860
+ continue;
1861
+ }
1862
+ objects.push({
1863
+ path: normalizeResultPath(entry.name),
1864
+ body: new Uint8Array(await entry.async("nodebuffer")),
1865
+ contentType: inferContentTypeFromPath(entry.name)
1866
+ });
1867
+ }
1868
+ return objects;
1869
+ } catch {
1870
+ return [];
1973
1871
  }
1974
- if (storagePath === indexStoragePath) {
1975
- return { key: input.key };
1872
+ }
1873
+ function collectGeneratedResultObjects(result) {
1874
+ const objects = [
1875
+ createJsonObject("manifest.json", result.manifest),
1876
+ createJsonObject("chunks.json", keysToSnake(serializeChunks2(result.chunks)))
1877
+ ];
1878
+ if (result.docNav) {
1879
+ objects.push(createJsonObject("doc_nav.json", result.docNav));
1880
+ }
1881
+ if (result.fullMarkdown) {
1882
+ objects.push(createTextObject("full.md", result.fullMarkdown, markdownContentType));
1883
+ }
1884
+ if (result.chunksSlim) {
1885
+ objects.push(createJsonObject("chunks_slim.json", { chunks: result.chunksSlim }));
1886
+ }
1887
+ if (result.hierarchy) {
1888
+ objects.push(createJsonObject("hierarchy.json", result.hierarchy));
1889
+ }
1890
+ if (result.tocHierarchies) {
1891
+ objects.push(createJsonObject("toc_hierarchies.json", result.tocHierarchies));
1892
+ }
1893
+ if (result.kbCsv) {
1894
+ objects.push(createTextObject("kb.csv", result.kbCsv, csvContentType));
1976
1895
  }
1977
- const chunkPageMatch = storagePath.match(chunkPagePathPattern);
1978
- if (chunkPageMatch) {
1979
- const page = JSON.parse(
1980
- Buffer.from(input.body).toString("utf8")
1896
+ if (result.hierarchyViewHtml) {
1897
+ objects.push(
1898
+ createTextObject("hierarchy_view.html", result.hierarchyViewHtml, htmlContentType)
1981
1899
  );
1982
- await params.storage.writeChunkPage({
1983
- documentId: params.documentId,
1984
- revisionKey: params.revisionKey,
1985
- page
1900
+ }
1901
+ for (const chunk of result.imageChunks) {
1902
+ objects.push({
1903
+ path: normalizeResultPath(chunk.filePath),
1904
+ body: new Uint8Array(chunk.data),
1905
+ contentType: inferContentTypeFromPath(chunk.filePath),
1906
+ metadata: {
1907
+ chunkId: chunk.chunkId,
1908
+ chunkType: chunk.type,
1909
+ sourcePath: chunk.filePath
1910
+ }
1986
1911
  });
1987
- return { key: input.key };
1988
1912
  }
1989
- const stored = await params.storage.writeAsset({
1990
- documentId: params.documentId,
1991
- revisionKey: params.revisionKey,
1992
- sourcePath: storagePath,
1993
- body: input.body,
1994
- contentType: input.contentType,
1995
- metadata: input.metadata
1996
- });
1913
+ for (const chunk of result.tableChunks) {
1914
+ objects.push({
1915
+ path: normalizeResultPath(chunk.filePath),
1916
+ body: Buffer.from(chunk.html, "utf8"),
1917
+ contentType: htmlContentType,
1918
+ metadata: {
1919
+ chunkId: chunk.chunkId,
1920
+ chunkType: chunk.type,
1921
+ sourcePath: chunk.filePath
1922
+ }
1923
+ });
1924
+ }
1925
+ return objects;
1926
+ }
1927
+ function serializeChunks2(chunks) {
1997
1928
  return {
1998
- key: input.key,
1999
- url: stored.url
1929
+ chunks: chunks.map((chunk) => {
1930
+ const rawChunk = {
1931
+ chunkId: chunk.chunkId,
1932
+ type: chunk.type,
1933
+ contentSource: chunk.contentSource,
1934
+ content: chunk.content,
1935
+ path: chunk.path,
1936
+ metadata: chunk.metadata
1937
+ };
1938
+ if (chunk.type === "image" || chunk.type === "table") {
1939
+ return {
1940
+ ...rawChunk,
1941
+ filePath: chunk.filePath,
1942
+ assetUrl: chunk.assetUrl
1943
+ };
1944
+ }
1945
+ return rawChunk;
1946
+ })
2000
1947
  };
2001
1948
  }
2002
- async function headParsedStorageObject(params, key) {
2003
- const storagePath = stripParsedStorageKeyPrefix(key);
2004
- if (storagePath === manifestStoragePath || storagePath === indexStoragePath || chunkPagePathPattern.test(storagePath)) {
2005
- return null;
2006
- }
2007
- const url = await params.storage.getAssetUrl({
1949
+ async function writeParsedDocumentJsonObject(storage, params) {
1950
+ await storage.writeObject({
2008
1951
  documentId: params.documentId,
2009
1952
  revisionKey: params.revisionKey,
2010
- sourcePath: storagePath
1953
+ path: params.path,
1954
+ body: Buffer.from(JSON.stringify(params.value, null, 2), "utf8"),
1955
+ contentType: jsonContentType
2011
1956
  });
2012
- return url ? {
2013
- key,
2014
- url
2015
- } : null;
2016
- }
2017
- async function getParsedStorageObjectUrl(params, key) {
2018
- const storagePath = stripParsedStorageKeyPrefix(key);
2019
- if (storagePath === manifestStoragePath || storagePath === indexStoragePath || chunkPagePathPattern.test(storagePath)) {
2020
- return null;
1957
+ }
1958
+ function createJsonObject(path4, value) {
1959
+ return {
1960
+ path: path4,
1961
+ body: Buffer.from(JSON.stringify(value, null, 2), "utf8"),
1962
+ contentType: jsonContentType
1963
+ };
1964
+ }
1965
+ function createTextObject(path4, value, contentType) {
1966
+ return {
1967
+ path: path4,
1968
+ body: Buffer.from(value, "utf8"),
1969
+ contentType
1970
+ };
1971
+ }
1972
+ function inferContentTypeFromPath(filePath) {
1973
+ const lower = filePath.toLowerCase();
1974
+ if (lower.endsWith(".json")) return jsonContentType;
1975
+ if (lower.endsWith(".md")) return markdownContentType;
1976
+ if (lower.endsWith(".csv")) return csvContentType;
1977
+ if (lower.endsWith(".html") || lower.endsWith(".htm")) return htmlContentType;
1978
+ if (lower.endsWith(".png")) return "image/png";
1979
+ if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
1980
+ if (lower.endsWith(".gif")) return "image/gif";
1981
+ if (lower.endsWith(".webp")) return "image/webp";
1982
+ if (lower.endsWith(".svg")) return "image/svg+xml";
1983
+ return binaryContentType;
1984
+ }
1985
+ function normalizeResultPath(value) {
1986
+ const normalized = value.replaceAll("\\", "/").replace(/^\.\/+/, "");
1987
+ if (normalized.length === 0 || normalized.includes("\0") || normalized.startsWith("/") || normalized.split("/").some((part) => part.length === 0 || part === "." || part === "..")) {
1988
+ throw new Error(`Invalid parsed result path: ${value}`);
2021
1989
  }
2022
- return params.storage.getAssetUrl({
2023
- documentId: params.documentId,
2024
- revisionKey: params.revisionKey,
2025
- sourcePath: storagePath
2026
- });
1990
+ return normalized;
2027
1991
  }
2028
- function stripParsedStorageKeyPrefix(key) {
2029
- const prefix = `${parsedStorageKeyPrefix}/`;
2030
- return key.startsWith(prefix) ? key.slice(prefix.length) : key;
1992
+ function isSdkMetadataPath(path4) {
1993
+ return path4 === ".knowhere-sdk" || path4.startsWith(".knowhere-sdk/");
2031
1994
  }
2032
1995
 
2033
1996
  // src/knowledge/local-store.ts
@@ -2262,7 +2225,6 @@ var MAX_GREP_LIMIT = 50;
2262
2225
  var DEFAULT_CONTEXT_CHARS = 80;
2263
2226
  var DEFAULT_REMOTE_SCAN_PAGE_SIZE = 100;
2264
2227
  var DEFAULT_MAX_SYNC_PAGES = 10;
2265
- var DEFAULT_MAX_SYNC_ASSETS = 20;
2266
2228
  var DEFAULT_SYNC_DEADLINE_MS = 8e3;
2267
2229
  var DEFAULT_GREP_MAX_PAGES = 50;
2268
2230
  var DEFAULT_GREP_DEADLINE_MS = 8e3;
@@ -2270,6 +2232,7 @@ var DEFAULT_OUTLINE_MAX_PAGES = 50;
2270
2232
  var DEFAULT_OUTLINE_DEADLINE_MS = 8e3;
2271
2233
  var SAFE_LOCAL_DOCUMENT_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
2272
2234
  var REMOTE_DOCUMENT_ID_PATTERN = /^doc[_-]/;
2235
+ var remoteReconstructionPageDirectory = ".knowhere-sdk/remote-reconstruction/pages";
2273
2236
  var Knowledge = class _Knowledge {
2274
2237
  client;
2275
2238
  store;
@@ -2304,8 +2267,7 @@ var Knowledge = class _Knowledge {
2304
2267
  return {
2305
2268
  document,
2306
2269
  result,
2307
- assetUrlsByFilePath: storedAssets.assetUrlsByFilePath,
2308
- parsedSnapshot: storedAssets.snapshot
2270
+ assetUrlsByFilePath: storedAssets.assetUrlsByFilePath
2309
2271
  };
2310
2272
  }
2311
2273
  /** @deprecated Use parseToLocalCache for local cache imports or the top-level client.parse for server-safe parsing. */
@@ -2350,8 +2312,7 @@ var Knowledge = class _Knowledge {
2350
2312
  const result = syncedStorage.result;
2351
2313
  return {
2352
2314
  result,
2353
- assetUrlsByFilePath: storedAssets.assetUrlsByFilePath,
2354
- parsedSnapshot: syncedStorage.snapshot ?? storedAssets.snapshot
2315
+ assetUrlsByFilePath: storedAssets.assetUrlsByFilePath
2355
2316
  };
2356
2317
  }
2357
2318
  async importJobResult(params) {
@@ -2363,8 +2324,7 @@ var Knowledge = class _Knowledge {
2363
2324
  return {
2364
2325
  document,
2365
2326
  result,
2366
- assetUrlsByFilePath: stored.assetUrlsByFilePath,
2367
- parsedSnapshot: stored.parsedSnapshot
2327
+ assetUrlsByFilePath: stored.assetUrlsByFilePath
2368
2328
  };
2369
2329
  }
2370
2330
  /** @deprecated Use importJobResult for local cache imports or loadJobResult for server-safe loads. */
@@ -2387,14 +2347,13 @@ var Knowledge = class _Knowledge {
2387
2347
  result: loadedResult,
2388
2348
  storage: parsedStorageConfig.storage,
2389
2349
  documentId: loadedResult.documentId ?? normalized.localDocumentId ?? normalized.jobId,
2390
- revisionKey: params.revisionKey ?? normalized.jobId,
2391
- chunkPageSize: parsedStorageConfig.limits?.chunkPageSize
2350
+ revisionKey: params.revisionKey ?? normalized.jobId
2392
2351
  });
2393
2352
  return {
2394
2353
  documentId: synced2.documentId,
2395
2354
  revisionKey: synced2.revisionKey,
2396
2355
  completed: true,
2397
- manifest: synced2.snapshot?.manifest
2356
+ commit: synced2.commit
2398
2357
  };
2399
2358
  }
2400
2359
  if (!normalized.localDocumentId) {
@@ -2405,14 +2364,13 @@ var Knowledge = class _Knowledge {
2405
2364
  result,
2406
2365
  storage: parsedStorageConfig.storage,
2407
2366
  documentId: result.documentId ?? normalized.localDocumentId,
2408
- revisionKey: params.revisionKey ?? result.jobId,
2409
- chunkPageSize: parsedStorageConfig.limits?.chunkPageSize
2367
+ revisionKey: params.revisionKey ?? result.jobId
2410
2368
  });
2411
2369
  return {
2412
2370
  documentId: synced.documentId,
2413
2371
  revisionKey: synced.revisionKey,
2414
2372
  completed: true,
2415
- manifest: synced.snapshot?.manifest
2373
+ commit: synced.commit
2416
2374
  };
2417
2375
  }
2418
2376
  async syncParseResultToConfiguredStorage(result) {
@@ -2422,12 +2380,11 @@ var Knowledge = class _Knowledge {
2422
2380
  }
2423
2381
  const synced = await syncParseResultToParsedDocumentStorage({
2424
2382
  result,
2425
- storage: parsedStorageConfig.storage,
2426
- chunkPageSize: parsedStorageConfig.limits?.chunkPageSize
2383
+ storage: parsedStorageConfig.storage
2427
2384
  });
2428
2385
  return {
2429
2386
  result: synced.result,
2430
- snapshot: synced.snapshot
2387
+ commit: synced.commit
2431
2388
  };
2432
2389
  }
2433
2390
  async parseWithoutClientStorageAdapter(params) {
@@ -2678,10 +2635,7 @@ var Knowledge = class _Knowledge {
2678
2635
  page: pageParams.page,
2679
2636
  pageSize: pageParams.pageSize,
2680
2637
  chunkType: params.chunkType,
2681
- includeAssetUrls: shouldRequestRemoteAssetUrls(
2682
- params.assetUrlPolicy,
2683
- this.parsedStorageConfig
2684
- )
2638
+ includeAssetUrls: true
2685
2639
  });
2686
2640
  const revisionKey = getRemoteRevisionKey(remotePage);
2687
2641
  const stored = await this.tryReadChunksFromParsedStorage({
@@ -2692,12 +2646,7 @@ var Knowledge = class _Knowledge {
2692
2646
  if (stored) {
2693
2647
  return stored;
2694
2648
  }
2695
- const chunks = await this.toRemoteReadChunks({
2696
- documentId,
2697
- revisionKey,
2698
- chunks: remotePage.chunks,
2699
- assetUrlPolicy: params.assetUrlPolicy
2700
- });
2649
+ const chunks = remotePage.chunks.map((chunk) => toRemoteReadChunk(chunk));
2701
2650
  this.scheduleParsedStorageSync(documentId, revisionKey);
2702
2651
  return {
2703
2652
  document: createRemoteKnowledgeDocument({
@@ -2730,10 +2679,7 @@ var Knowledge = class _Knowledge {
2730
2679
  page: 1,
2731
2680
  pageSize: limits.remotePageSize,
2732
2681
  chunkType: params.chunkType,
2733
- includeAssetUrls: shouldRequestRemoteAssetUrls(
2734
- params.assetUrlPolicy,
2735
- this.parsedStorageConfig
2736
- )
2682
+ includeAssetUrls: true
2737
2683
  });
2738
2684
  const revisionKey = getRemoteRevisionKey(firstPage);
2739
2685
  const stored = await this.tryReadChunksFromParsedStorage({
@@ -2760,18 +2706,10 @@ var Knowledge = class _Knowledge {
2760
2706
  page,
2761
2707
  pageSize: limits.remotePageSize,
2762
2708
  chunkType: params.chunkType,
2763
- includeAssetUrls: shouldRequestRemoteAssetUrls(
2764
- params.assetUrlPolicy,
2765
- this.parsedStorageConfig
2766
- )
2709
+ includeAssetUrls: true
2767
2710
  });
2768
2711
  }
2769
- const chunks = await this.toRemoteReadChunks({
2770
- documentId,
2771
- revisionKey,
2772
- chunks: selected.slice(0, limit),
2773
- assetUrlPolicy: params.assetUrlPolicy
2774
- });
2712
+ const chunks = selected.slice(0, limit).map((chunk) => toRemoteReadChunk(chunk));
2775
2713
  this.scheduleParsedStorageSync(documentId, revisionKey);
2776
2714
  return {
2777
2715
  document: createRemoteKnowledgeDocument({
@@ -2807,7 +2745,7 @@ var Knowledge = class _Knowledge {
2807
2745
  page: startPage,
2808
2746
  pageSize: limits.remotePageSize,
2809
2747
  chunkType: params.chunkType,
2810
- includeAssetUrls: false
2748
+ includeAssetUrls: true
2811
2749
  });
2812
2750
  const revisionKey = getRemoteRevisionKey(firstPage);
2813
2751
  const stored = startPage === 1 ? await this.tryGrepChunksFromParsedStorage({
@@ -2904,7 +2842,7 @@ var Knowledge = class _Knowledge {
2904
2842
  page,
2905
2843
  pageSize: limits.remotePageSize,
2906
2844
  chunkType: params.chunkType,
2907
- includeAssetUrls: false
2845
+ includeAssetUrls: true
2908
2846
  });
2909
2847
  }
2910
2848
  }
@@ -2919,7 +2857,7 @@ var Knowledge = class _Knowledge {
2919
2857
  const firstPage = await this.client.documents.listChunks(documentId, {
2920
2858
  page: 1,
2921
2859
  pageSize: limits.remotePageSize,
2922
- includeAssetUrls: false
2860
+ includeAssetUrls: true
2923
2861
  });
2924
2862
  const revisionKey = getRemoteRevisionKey(firstPage);
2925
2863
  const stored = await this.tryReadOutlineFromParsedStorage(documentId, revisionKey);
@@ -2941,7 +2879,7 @@ var Knowledge = class _Knowledge {
2941
2879
  response = await this.client.documents.listChunks(documentId, {
2942
2880
  page,
2943
2881
  pageSize: limits.remotePageSize,
2944
- includeAssetUrls: false
2882
+ includeAssetUrls: true
2945
2883
  });
2946
2884
  }
2947
2885
  const truncated = response.pagination.page < response.pagination.totalPages;
@@ -2967,28 +2905,13 @@ var Knowledge = class _Knowledge {
2967
2905
  };
2968
2906
  }
2969
2907
  async tryReadChunksFromParsedStorage(params) {
2970
- const parsedStorageConfig = this.parsedStorageConfig;
2971
- if (!parsedStorageConfig) {
2972
- return null;
2973
- }
2974
- const manifest = await this.readFreshParsedStorageManifest(
2908
+ const storedResult = await this.readCommittedParsedStorageResult(
2975
2909
  params.documentId,
2976
2910
  params.revisionKey
2977
2911
  );
2978
- if (!manifest) {
2979
- return null;
2980
- }
2912
+ if (!storedResult) return null;
2981
2913
  const pageParams = getReadPageParams(params.params);
2982
- const indexedChunks = await this.readStoredSnapshotChunks({
2983
- documentId: params.documentId,
2984
- revisionKey: params.revisionKey,
2985
- manifest,
2986
- chunkType: params.params.chunkType
2987
- });
2988
- if (!indexedChunks) {
2989
- return null;
2990
- }
2991
- const scopedChunks = indexedChunks.filter((chunk) => matchesReadScope(chunk, params.params));
2914
+ const scopedChunks = storedResult.chunks.filter((chunk) => !params.params.chunkType || chunk.chunkType === params.params.chunkType).filter((chunk) => matchesReadScope(chunk, params.params));
2992
2915
  const selected = hasScanReadFilters(params.params) ? selectReadWindow(
2993
2916
  scopedChunks,
2994
2917
  params.params,
@@ -2997,17 +2920,18 @@ var Knowledge = class _Knowledge {
2997
2920
  (pageParams.page - 1) * pageParams.pageSize,
2998
2921
  pageParams.page * pageParams.pageSize
2999
2922
  );
3000
- const visibleChunks = applyAssetUrlPolicyToReadChunks(
3001
- selected.map(toReadChunk),
3002
- params.params.assetUrlPolicy
3003
- );
2923
+ const visibleChunks = await applyStoredAssetUrlsToReadChunks({
2924
+ storageConfig: this.requireParsedStorageConfig(),
2925
+ documentId: params.documentId,
2926
+ revisionKey: params.revisionKey,
2927
+ chunks: selected.map(toReadChunk)
2928
+ });
3004
2929
  const totalChunks = scopedChunks.length;
3005
2930
  return {
3006
2931
  document: createStoredKnowledgeDocument({
3007
2932
  documentId: params.documentId,
3008
- manifest,
3009
- revisionKey: params.revisionKey,
3010
- typeCounts: countIndexedTypes(indexedChunks)
2933
+ storedResult,
2934
+ revisionKey: params.revisionKey
3011
2935
  }),
3012
2936
  chunks: visibleChunks,
3013
2937
  page: hasScanReadFilters(params.params) ? void 0 : pageParams.page,
@@ -3018,30 +2942,15 @@ var Knowledge = class _Knowledge {
3018
2942
  };
3019
2943
  }
3020
2944
  async tryGrepChunksFromParsedStorage(params) {
3021
- const parsedStorageConfig = this.parsedStorageConfig;
3022
- if (!parsedStorageConfig) {
3023
- return null;
3024
- }
3025
- const manifest = await this.readFreshParsedStorageManifest(
2945
+ const storedResult = await this.readCommittedParsedStorageResult(
3026
2946
  params.documentId,
3027
2947
  params.revisionKey
3028
2948
  );
3029
- if (!manifest) {
3030
- return null;
3031
- }
3032
- const indexedChunks = await this.readStoredSnapshotChunks({
3033
- documentId: params.documentId,
3034
- revisionKey: params.revisionKey,
3035
- manifest,
3036
- chunkType: params.params.chunkType
3037
- });
3038
- if (!indexedChunks) {
3039
- return null;
3040
- }
2949
+ if (!storedResult) return null;
3041
2950
  const maxResults = clampLimit(params.params.maxResults, DEFAULT_GREP_LIMIT, MAX_GREP_LIMIT);
3042
2951
  const contextChars = params.params.contextChars ?? DEFAULT_CONTEXT_CHARS;
3043
2952
  const matcher = createMatcher(params.params);
3044
- const scopedChunks = indexedChunks.filter((chunk) => matchesGrepScope(chunk, params.params));
2953
+ const scopedChunks = storedResult.chunks.filter((chunk) => !params.params.chunkType || chunk.chunkType === params.params.chunkType).filter((chunk) => matchesGrepScope(chunk, params.params));
3045
2954
  const matches = [];
3046
2955
  let scannedChunks = 0;
3047
2956
  for (const chunk of scopedChunks) {
@@ -3062,9 +2971,8 @@ var Knowledge = class _Knowledge {
3062
2971
  return {
3063
2972
  document: createStoredKnowledgeDocument({
3064
2973
  documentId: params.documentId,
3065
- manifest,
3066
- revisionKey: params.revisionKey,
3067
- typeCounts: countIndexedTypes(indexedChunks)
2974
+ storedResult,
2975
+ revisionKey: params.revisionKey
3068
2976
  }),
3069
2977
  matches,
3070
2978
  scannedChunks,
@@ -3076,9 +2984,8 @@ var Knowledge = class _Knowledge {
3076
2984
  return {
3077
2985
  document: createStoredKnowledgeDocument({
3078
2986
  documentId: params.documentId,
3079
- manifest,
3080
- revisionKey: params.revisionKey,
3081
- typeCounts: countIndexedTypes(indexedChunks)
2987
+ storedResult,
2988
+ revisionKey: params.revisionKey
3082
2989
  }),
3083
2990
  matches,
3084
2991
  scannedChunks,
@@ -3086,98 +2993,80 @@ var Knowledge = class _Knowledge {
3086
2993
  };
3087
2994
  }
3088
2995
  async tryReadOutlineFromParsedStorage(documentId, revisionKey) {
3089
- const manifest = await this.readFreshParsedStorageManifest(documentId, revisionKey);
3090
- if (!manifest) {
3091
- return null;
3092
- }
3093
- const indexedChunks = await this.readStoredSnapshotChunks({
3094
- documentId,
3095
- revisionKey,
3096
- manifest
3097
- });
3098
- if (!indexedChunks) {
3099
- return null;
3100
- }
3101
- const sections = buildFlatSectionsFromIndexedChunks(indexedChunks);
3102
- const typeCounts = countIndexedTypes(indexedChunks);
2996
+ const storedResult = await this.readCommittedParsedStorageResult(documentId, revisionKey);
2997
+ if (!storedResult) return null;
2998
+ const sections = storedResult.docNav?.sections && storedResult.docNav.sections.length > 0 ? flattenSections(
2999
+ storedResult.docNav.sections.map(
3000
+ (section) => toKnowledgeSection(
3001
+ section,
3002
+ storedResult.chunks,
3003
+ storedResult.manifest.sourceFileName
3004
+ )
3005
+ )
3006
+ ) : buildFlatSectionsFromIndexedChunks(storedResult.chunks);
3103
3007
  return {
3104
3008
  document: createStoredKnowledgeDocument({
3105
3009
  documentId,
3106
- manifest,
3107
- revisionKey,
3108
- typeCounts
3010
+ storedResult,
3011
+ revisionKey
3109
3012
  }),
3110
- totalChunks: manifest.totalChunks,
3111
- typeCounts,
3013
+ totalChunks: storedResult.chunks.length,
3014
+ typeCounts: storedResult.typeCounts,
3112
3015
  sections,
3113
- sectionTree: nestSections(sections),
3016
+ sectionTree: storedResult.docNav?.sections && storedResult.docNav.sections.length > 0 ? storedResult.docNav.sections.map(
3017
+ (section) => toKnowledgeSection(
3018
+ section,
3019
+ storedResult.chunks,
3020
+ storedResult.manifest.sourceFileName
3021
+ )
3022
+ ) : nestSections(sections),
3114
3023
  truncated: false
3115
3024
  };
3116
3025
  }
3117
- async readFreshParsedStorageManifest(documentId, revisionKey) {
3026
+ async readCommittedParsedStorageResult(documentId, revisionKey) {
3118
3027
  const parsedStorageConfig = this.parsedStorageConfig;
3119
3028
  if (!parsedStorageConfig) {
3120
3029
  return null;
3121
3030
  }
3122
- const manifest = await parsedStorageConfig.storage.readManifest({
3031
+ const commit = await readParsedDocumentCommit({
3032
+ storage: parsedStorageConfig.storage,
3123
3033
  documentId,
3124
3034
  revisionKey
3125
3035
  });
3126
- if (!manifest || !isFreshManifest(manifest, revisionKey)) {
3036
+ if (!commit) {
3127
3037
  return null;
3128
3038
  }
3129
- return manifest;
3130
- }
3131
- async readStoredSnapshotChunks(params) {
3132
- const parsedStorageConfig = this.parsedStorageConfig;
3133
- if (!parsedStorageConfig) {
3039
+ const manifestObject = await parsedStorageConfig.storage.readObject({
3040
+ documentId,
3041
+ revisionKey,
3042
+ path: "manifest.json"
3043
+ });
3044
+ const chunksObject = await parsedStorageConfig.storage.readObject({
3045
+ documentId,
3046
+ revisionKey,
3047
+ path: "chunks.json"
3048
+ });
3049
+ if (!manifestObject || !chunksObject) {
3134
3050
  return null;
3135
3051
  }
3136
- const chunks = [];
3137
- for (const pageReference of params.manifest.chunkPages) {
3138
- const page = await parsedStorageConfig.storage.readChunkPage({
3139
- documentId: params.documentId,
3140
- revisionKey: params.revisionKey,
3141
- page: pageReference.page,
3142
- chunkType: params.chunkType
3143
- });
3144
- if (!page) {
3145
- return null;
3146
- }
3147
- chunks.push(
3148
- ...page.chunks.filter((chunk) => !params.chunkType || chunk.chunkType === params.chunkType).map(toIndexedSnapshotChunk)
3149
- );
3150
- }
3151
- return chunks.sort((left, right) => left.position - right.position);
3152
- }
3153
- async toRemoteReadChunks(params) {
3154
- const readChunks = params.chunks.map((chunk) => toRemoteReadChunk(chunk));
3155
- if (params.assetUrlPolicy === "durable") {
3156
- return this.hardenReadChunkAssetUrls({
3157
- documentId: params.documentId,
3158
- revisionKey: params.revisionKey,
3159
- chunks: readChunks
3160
- });
3161
- }
3162
- return applyAssetUrlPolicyToReadChunks(readChunks, params.assetUrlPolicy);
3163
- }
3164
- async hardenReadChunkAssetUrls(params) {
3165
- const parsedStorageConfig = this.parsedStorageConfig;
3166
- if (!parsedStorageConfig) {
3167
- return applyAssetUrlPolicyToReadChunks(params.chunks, "none");
3168
- }
3169
- const hardenedChunks = [];
3170
- for (const chunk of params.chunks) {
3171
- hardenedChunks.push(
3172
- await hardenReadChunkAssetUrls({
3173
- storageConfig: parsedStorageConfig,
3174
- documentId: params.documentId,
3175
- revisionKey: params.revisionKey,
3176
- chunk
3177
- })
3178
- );
3179
- }
3180
- return hardenedChunks;
3052
+ const manifest = readJsonObject(manifestObject);
3053
+ const chunks = parseStoredResultChunks({
3054
+ payload: readJsonObject(chunksObject),
3055
+ sourceFileName: manifest.sourceFileName
3056
+ });
3057
+ const docNavObject = await parsedStorageConfig.storage.readObject({
3058
+ documentId,
3059
+ revisionKey,
3060
+ path: "doc_nav.json"
3061
+ });
3062
+ const docNav = docNavObject ? readJsonObject(docNavObject) : void 0;
3063
+ return {
3064
+ commit,
3065
+ manifest,
3066
+ chunks,
3067
+ docNav: docNav?.sections ? { sections: docNav.sections } : void 0,
3068
+ typeCounts: countIndexedTypes(chunks)
3069
+ };
3181
3070
  }
3182
3071
  scheduleParsedStorageSync(documentId, revisionKey) {
3183
3072
  const parsedStorageConfig = this.parsedStorageConfig;
@@ -3197,7 +3086,6 @@ var Knowledge = class _Knowledge {
3197
3086
  documentId,
3198
3087
  revisionKey,
3199
3088
  nextChunkPage: 1,
3200
- nextAssetIndex: 0,
3201
3089
  status: "failed",
3202
3090
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3203
3091
  error: error instanceof Error ? error.message : String(error)
@@ -3207,28 +3095,63 @@ var Knowledge = class _Knowledge {
3207
3095
  void Promise.resolve(scheduler.schedule(task)).catch(() => void 0);
3208
3096
  }
3209
3097
  async syncRemoteDocumentToParsedStorage(params) {
3210
- const limits = getParsedStorageLimits(params.parsedStorageConfig.limits);
3211
- const existingProgress = params.revisionKey ? await params.parsedStorageConfig.storage.readSyncProgress({
3212
- documentId: params.documentId,
3213
- revisionKey: params.revisionKey
3214
- }) : null;
3215
- let nextPage = existingProgress?.status === "running" ? existingProgress.nextChunkPage : 1;
3216
- let response = await this.client.documents.listChunks(params.documentId, {
3217
- page: nextPage,
3218
- pageSize: limits.remotePageSize,
3098
+ const firstPage = await this.client.documents.listChunks(params.documentId, {
3099
+ page: 1,
3100
+ pageSize: 1,
3219
3101
  includeAssetUrls: true
3220
3102
  });
3221
- const revisionKey = params.revisionKey ?? getRemoteRevisionKey(response);
3222
- if (params.revisionKey && getRemoteRevisionKey(response) !== params.revisionKey) {
3223
- response = await this.client.documents.listChunks(params.documentId, {
3224
- page: 1,
3225
- pageSize: limits.remotePageSize,
3226
- includeAssetUrls: true
3103
+ const revisionKey = params.revisionKey ?? getRemoteRevisionKey(firstPage);
3104
+ if (params.revisionKey && getRemoteRevisionKey(firstPage) !== params.revisionKey) {
3105
+ return this.syncRemoteDocumentToParsedStorage({
3106
+ documentId: params.documentId,
3107
+ parsedStorageConfig: params.parsedStorageConfig
3227
3108
  });
3228
- nextPage = 1;
3229
3109
  }
3110
+ if (firstPage.jobId) {
3111
+ try {
3112
+ const loadedResult = await this.client.jobs.load(firstPage.jobId);
3113
+ const synced = await syncParseResultToParsedDocumentStorage({
3114
+ result: loadedResult,
3115
+ storage: params.parsedStorageConfig.storage,
3116
+ documentId: params.documentId,
3117
+ revisionKey,
3118
+ source: "resultZip"
3119
+ });
3120
+ await params.parsedStorageConfig.storage.writeSyncProgress({
3121
+ documentId: params.documentId,
3122
+ revisionKey,
3123
+ status: "completed",
3124
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
3125
+ });
3126
+ return {
3127
+ documentId: synced.documentId,
3128
+ revisionKey: synced.revisionKey,
3129
+ completed: true,
3130
+ commit: synced.commit
3131
+ };
3132
+ } catch {
3133
+ }
3134
+ }
3135
+ return this.syncRemoteDocumentChunksToParsedStorage({
3136
+ documentId: params.documentId,
3137
+ revisionKey,
3138
+ firstPage,
3139
+ parsedStorageConfig: params.parsedStorageConfig
3140
+ });
3141
+ }
3142
+ async syncRemoteDocumentChunksToParsedStorage(params) {
3143
+ const limits = getParsedStorageLimits(params.parsedStorageConfig.limits);
3144
+ const existingProgress = await params.parsedStorageConfig.storage.readSyncProgress({
3145
+ documentId: params.documentId,
3146
+ revisionKey: params.revisionKey
3147
+ });
3148
+ let nextPage = existingProgress?.status === "running" ? existingProgress.nextChunkPage ?? 1 : 1;
3149
+ let response = nextPage === 1 && params.firstPage.pagination.pageSize === limits.remotePageSize ? params.firstPage : await this.client.documents.listChunks(params.documentId, {
3150
+ page: nextPage,
3151
+ pageSize: limits.remotePageSize,
3152
+ includeAssetUrls: true
3153
+ });
3230
3154
  const totalPages = response.pagination.totalPages;
3231
- const chunkPages = [];
3232
3155
  let syncedPages = 0;
3233
3156
  const startedAt = Date.now();
3234
3157
  while (nextPage <= totalPages) {
@@ -3239,65 +3162,88 @@ var Knowledge = class _Knowledge {
3239
3162
  includeAssetUrls: true
3240
3163
  });
3241
3164
  }
3242
- const readChunks = await this.hardenReadChunkAssetUrls({
3243
- documentId: params.documentId,
3244
- revisionKey,
3245
- chunks: response.chunks.map(toRemoteReadChunk)
3246
- });
3247
- const page = toSnapshotChunkPageFromReadChunks({
3248
- response,
3249
- revisionKey,
3250
- chunks: readChunks
3251
- });
3252
- await params.parsedStorageConfig.storage.writeChunkPage({
3165
+ await params.parsedStorageConfig.storage.writeObject({
3253
3166
  documentId: params.documentId,
3254
- revisionKey,
3255
- page
3167
+ revisionKey: params.revisionKey,
3168
+ path: getRemoteReconstructionPagePath(response.pagination.page),
3169
+ body: Buffer.from(JSON.stringify({ chunks: response.chunks }), "utf8"),
3170
+ contentType: "application/json; charset=utf-8"
3256
3171
  });
3257
- chunkPages.push(page);
3258
3172
  nextPage += 1;
3259
3173
  syncedPages += 1;
3260
3174
  await params.parsedStorageConfig.storage.writeSyncProgress({
3261
3175
  documentId: params.documentId,
3262
- revisionKey,
3176
+ revisionKey: params.revisionKey,
3263
3177
  nextChunkPage: nextPage,
3264
- nextAssetIndex: 0,
3265
3178
  status: "running",
3266
3179
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
3267
3180
  });
3268
3181
  if (syncedPages >= limits.maxPagesPerSync || Date.now() - startedAt >= limits.syncDeadlineMs) {
3269
3182
  return {
3270
3183
  documentId: params.documentId,
3271
- revisionKey,
3184
+ revisionKey: params.revisionKey,
3272
3185
  completed: false
3273
3186
  };
3274
3187
  }
3275
3188
  }
3276
- const manifest = createRemoteSnapshotManifest({
3277
- response,
3278
- revisionKey,
3279
- chunkPages
3189
+ const chunks = await this.readRemoteReconstructionChunks({
3190
+ documentId: params.documentId,
3191
+ revisionKey: params.revisionKey,
3192
+ totalPages,
3193
+ parsedStorageConfig: params.parsedStorageConfig
3280
3194
  });
3281
- await params.parsedStorageConfig.storage.writeManifest({
3195
+ if (!chunks) {
3196
+ return {
3197
+ documentId: params.documentId,
3198
+ revisionKey: params.revisionKey,
3199
+ completed: false
3200
+ };
3201
+ }
3202
+ const synced = await syncParseResultToParsedDocumentStorage({
3203
+ result: createMinimalParseResultFromRemoteChunks({
3204
+ documentId: params.documentId,
3205
+ revisionKey: params.revisionKey,
3206
+ response,
3207
+ chunks
3208
+ }),
3209
+ storage: params.parsedStorageConfig.storage,
3282
3210
  documentId: params.documentId,
3283
- revisionKey,
3284
- manifest
3211
+ revisionKey: params.revisionKey,
3212
+ source: "remoteReconstruction"
3285
3213
  });
3286
3214
  await params.parsedStorageConfig.storage.writeSyncProgress({
3287
3215
  documentId: params.documentId,
3288
- revisionKey,
3216
+ revisionKey: params.revisionKey,
3289
3217
  nextChunkPage: totalPages + 1,
3290
- nextAssetIndex: 0,
3291
3218
  status: "completed",
3292
3219
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
3293
3220
  });
3294
3221
  return {
3295
3222
  documentId: params.documentId,
3296
- revisionKey,
3223
+ revisionKey: params.revisionKey,
3297
3224
  completed: true,
3298
- manifest
3225
+ commit: synced.commit
3299
3226
  };
3300
3227
  }
3228
+ async readRemoteReconstructionChunks(params) {
3229
+ const chunks = [];
3230
+ for (let page = 1; page <= params.totalPages; page += 1) {
3231
+ const object = await params.parsedStorageConfig.storage.readObject({
3232
+ documentId: params.documentId,
3233
+ revisionKey: params.revisionKey,
3234
+ path: getRemoteReconstructionPagePath(page)
3235
+ });
3236
+ if (!object) {
3237
+ return null;
3238
+ }
3239
+ const payload = readJsonObject(object);
3240
+ if (!isDocumentChunkArray(payload.chunks)) {
3241
+ return null;
3242
+ }
3243
+ chunks.push(...payload.chunks);
3244
+ }
3245
+ return chunks;
3246
+ }
3301
3247
  requireParsedStorageConfig() {
3302
3248
  if (!this.parsedStorageConfig) {
3303
3249
  throw new ValidationError("parsed document storage is not configured");
@@ -3311,7 +3257,8 @@ var Knowledge = class _Knowledge {
3311
3257
  async getPublishedDocumentJobId(documentId) {
3312
3258
  const response = await this.client.documents.listChunks(documentId, {
3313
3259
  page: 1,
3314
- pageSize: 1
3260
+ pageSize: 1,
3261
+ includeAssetUrls: true
3315
3262
  });
3316
3263
  if (!response.jobId) {
3317
3264
  throw new Error(
@@ -3344,14 +3291,12 @@ var defaultParsedStorageScheduler = {
3344
3291
  };
3345
3292
  function getParsedStorageLimits(limits) {
3346
3293
  return {
3347
- chunkPageSize: clampLimit(limits?.chunkPageSize, DEFAULT_REMOTE_SCAN_PAGE_SIZE, MAX_PAGE_SIZE),
3348
3294
  remotePageSize: clampLimit(
3349
3295
  limits?.remotePageSize,
3350
3296
  DEFAULT_REMOTE_SCAN_PAGE_SIZE,
3351
3297
  MAX_PAGE_SIZE
3352
3298
  ),
3353
3299
  maxPagesPerSync: clampLimit(limits?.maxPagesPerSync, DEFAULT_MAX_SYNC_PAGES, 1e3),
3354
- maxAssetsPerSync: clampLimit(limits?.maxAssetsPerSync, DEFAULT_MAX_SYNC_ASSETS, 1e3),
3355
3300
  syncDeadlineMs: clampLimit(limits?.syncDeadlineMs, DEFAULT_SYNC_DEADLINE_MS, 6e4),
3356
3301
  grepMaxPages: clampLimit(limits?.grepMaxPages, DEFAULT_GREP_MAX_PAGES, 1e3),
3357
3302
  grepDeadlineMs: clampLimit(limits?.grepDeadlineMs, DEFAULT_GREP_DEADLINE_MS, 6e4),
@@ -3360,13 +3305,13 @@ function getParsedStorageLimits(limits) {
3360
3305
  };
3361
3306
  }
3362
3307
  function validateReadParams(params) {
3363
- const usesPagedDisplay = params.page !== void 0 || params.pageSize !== void 0 || params.assetUrlPolicy !== void 0;
3308
+ const usesPagedDisplay = params.page !== void 0 || params.pageSize !== void 0;
3364
3309
  if (!usesPagedDisplay) {
3365
3310
  return;
3366
3311
  }
3367
3312
  if (params.sectionPath !== void 0 || params.startChunk !== void 0 || params.endChunk !== void 0 || params.chunkId !== void 0) {
3368
3313
  throw new ValidationError(
3369
- "page, pageSize, and assetUrlPolicy cannot be combined with sectionPath, startChunk, endChunk, or chunkId"
3314
+ "page and pageSize cannot be combined with sectionPath, startChunk, endChunk, or chunkId"
3370
3315
  );
3371
3316
  }
3372
3317
  }
@@ -3379,9 +3324,6 @@ function getReadPageParams(params) {
3379
3324
  pageSize: clampLimit(params.pageSize ?? params.limit, DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE)
3380
3325
  };
3381
3326
  }
3382
- function shouldRequestRemoteAssetUrls(assetUrlPolicy, parsedStorageConfig) {
3383
- return assetUrlPolicy === "durable" && parsedStorageConfig !== void 0;
3384
- }
3385
3327
  function getRemoteRevisionKey(response) {
3386
3328
  const revisionKey = response.jobResultId ?? response.jobId;
3387
3329
  if (!revisionKey) {
@@ -3391,6 +3333,9 @@ function getRemoteRevisionKey(response) {
3391
3333
  }
3392
3334
  return revisionKey;
3393
3335
  }
3336
+ function getRemoteReconstructionPagePath(page) {
3337
+ return `${remoteReconstructionPageDirectory}/page-${page}.json`;
3338
+ }
3394
3339
  function createRemoteKnowledgeDocument(params) {
3395
3340
  return {
3396
3341
  localDocumentId: params.documentId,
@@ -3405,23 +3350,103 @@ function createRemoteKnowledgeDocument(params) {
3405
3350
  updatedAt: /* @__PURE__ */ new Date(0)
3406
3351
  };
3407
3352
  }
3353
+ function createMinimalParseResultFromRemoteChunks(params) {
3354
+ const chunks = params.chunks.map(toMinimalChunkFromRemoteChunk);
3355
+ const typeCounts = countRemoteChunkTypes(params.chunks);
3356
+ return {
3357
+ manifest: {
3358
+ version: "2.0",
3359
+ jobId: params.response.jobId ?? params.revisionKey,
3360
+ sourceFileName: params.documentId,
3361
+ statistics: {
3362
+ totalChunks: chunks.length,
3363
+ textChunks: typeCounts.text,
3364
+ imageChunks: typeCounts.image,
3365
+ tableChunks: typeCounts.table,
3366
+ pageChunks: typeCounts.page
3367
+ }
3368
+ },
3369
+ chunks,
3370
+ rawZip: Buffer.from(""),
3371
+ namespace: params.response.namespace,
3372
+ documentId: params.documentId,
3373
+ textChunks: chunks.filter(
3374
+ (chunk) => chunk.type === "text"
3375
+ ),
3376
+ imageChunks: chunks.filter(
3377
+ (chunk) => chunk.type === "image"
3378
+ ),
3379
+ tableChunks: chunks.filter(
3380
+ (chunk) => chunk.type === "table"
3381
+ ),
3382
+ pageChunks: chunks.filter(
3383
+ (chunk) => chunk.type === "page"
3384
+ ),
3385
+ jobId: params.response.jobId ?? params.revisionKey,
3386
+ statistics: {
3387
+ totalChunks: chunks.length,
3388
+ textChunks: typeCounts.text,
3389
+ imageChunks: typeCounts.image,
3390
+ tableChunks: typeCounts.table,
3391
+ pageChunks: typeCounts.page
3392
+ },
3393
+ getChunk: (chunkId) => chunks.find((chunk) => chunk.chunkId === chunkId),
3394
+ save: () => Promise.reject(new Error("Minimal remote reconstruction cannot be saved directly."))
3395
+ };
3396
+ }
3397
+ function toMinimalChunkFromRemoteChunk(chunk) {
3398
+ const baseChunk = {
3399
+ chunkId: chunk.chunkId,
3400
+ contentSource: chunk.contentSource ?? void 0,
3401
+ content: chunk.content ?? "",
3402
+ path: chunk.sourceChunkPath ?? chunk.sectionPath ?? "",
3403
+ metadata: cloneMetadata(chunk.metadata)
3404
+ };
3405
+ if (chunk.chunkType === "image") {
3406
+ return {
3407
+ ...baseChunk,
3408
+ type: "image",
3409
+ filePath: chunk.filePath ?? "",
3410
+ assetUrl: chunk.assetUrl ?? void 0,
3411
+ data: Buffer.alloc(0),
3412
+ format: inferContentTypeFromPath2(chunk.filePath ?? "").replace("image/", ""),
3413
+ save: () => Promise.resolve(chunk.filePath ?? "")
3414
+ };
3415
+ }
3416
+ if (chunk.chunkType === "table") {
3417
+ return {
3418
+ ...baseChunk,
3419
+ type: "table",
3420
+ filePath: chunk.filePath ?? "",
3421
+ assetUrl: chunk.assetUrl ?? void 0,
3422
+ html: chunk.content ?? "",
3423
+ save: () => Promise.resolve(chunk.filePath ?? "")
3424
+ };
3425
+ }
3426
+ if (chunk.chunkType === "page") {
3427
+ return {
3428
+ ...baseChunk,
3429
+ type: "page"
3430
+ };
3431
+ }
3432
+ return {
3433
+ ...baseChunk,
3434
+ type: "text"
3435
+ };
3436
+ }
3408
3437
  function createStoredKnowledgeDocument(params) {
3409
3438
  return {
3410
3439
  localDocumentId: params.documentId,
3411
- jobId: params.manifest.jobId || params.revisionKey,
3412
- documentId: params.manifest.documentId ?? params.documentId,
3413
- namespace: params.manifest.namespace,
3414
- sourceFileName: params.manifest.sourceFileName,
3415
- chunkCount: params.manifest.totalChunks,
3416
- typeCounts: params.typeCounts,
3440
+ jobId: params.storedResult.manifest.jobId || params.revisionKey,
3441
+ documentId: params.documentId,
3442
+ sourceFileName: params.storedResult.manifest.sourceFileName,
3443
+ chunkCount: params.storedResult.chunks.length,
3444
+ typeCounts: params.storedResult.typeCounts,
3417
3445
  resultDirectoryPath: `parsed-storage:${params.documentId}`,
3418
- createdAt: new Date(params.manifest.createdAt),
3419
- updatedAt: new Date(params.manifest.createdAt)
3446
+ createdAt: new Date(params.storedResult.commit.committedAt),
3447
+ updatedAt: new Date(params.storedResult.commit.committedAt)
3420
3448
  };
3421
3449
  }
3422
- function isFreshManifest(manifest, revisionKey) {
3423
- return (manifest.revisionKey ?? manifest.jobId) === revisionKey;
3424
- }
3425
3450
  function toRemoteReadChunk(chunk) {
3426
3451
  const metadata = cloneMetadata(chunk.metadata);
3427
3452
  return {
@@ -3450,22 +3475,60 @@ function toIndexedRemoteChunk(chunk) {
3450
3475
  const readChunk = toRemoteReadChunk(chunk);
3451
3476
  return toIndexedReadChunk(readChunk);
3452
3477
  }
3453
- function toIndexedSnapshotChunk(chunk) {
3454
- return toIndexedReadChunk({
3455
- position: chunk.sortOrder,
3456
- chunkId: chunk.chunkId,
3457
- chunkType: chunk.chunkType,
3458
- contentSource: chunk.contentSource,
3459
- content: chunk.content,
3460
- readableContent: chunk.chunkType === "page" && typeof chunk.metadata.summary === "string" && chunk.metadata.summary.trim().length > 0 ? chunk.metadata.summary : chunk.content,
3461
- sectionPath: chunk.sectionPath ?? "",
3462
- sourceChunkPath: chunk.sourceChunkPath,
3463
- filePath: chunk.filePath,
3464
- assetUrl: chunk.assetUrl,
3465
- pageNumbers: getChunkPageNumbers(chunk.metadata),
3466
- metadata: cloneMetadata(chunk.metadata)
3478
+ function parseStoredResultChunks(params) {
3479
+ const rawChunks = extractStoredChunkRecords(params.payload);
3480
+ return rawChunks.map((record, index) => {
3481
+ const metadata = readRecordMetadata(record);
3482
+ const chunkType = readRecordString(record, "type", "chunkType", "chunk_type");
3483
+ const content = readRecordString(record, "content") ?? "";
3484
+ const sourceChunkPath = readRecordString(record, "path", "sourceChunkPath", "source_chunk_path") ?? "";
3485
+ const chunk = {
3486
+ position: index + 1,
3487
+ chunkId: readRecordString(record, "chunkId", "chunk_id") ?? "",
3488
+ chunkType: isKnowledgeChunkType(chunkType) ? chunkType : "text",
3489
+ contentSource: readRecordString(record, "contentSource", "content_source"),
3490
+ content,
3491
+ readableContent: chunkType === "page" && typeof metadata.summary === "string" && metadata.summary.trim().length > 0 ? metadata.summary : content,
3492
+ sectionPath: normalizeSectionPath(sourceChunkPath, params.sourceFileName),
3493
+ sourceChunkPath,
3494
+ filePath: readRecordString(record, "filePath", "file_path") ?? (typeof metadata.filePath === "string" ? metadata.filePath : void 0),
3495
+ assetUrl: readRecordString(record, "assetUrl", "asset_url"),
3496
+ pageNumbers: getChunkPageNumbers(metadata),
3497
+ metadata
3498
+ };
3499
+ return toIndexedReadChunk(chunk);
3467
3500
  });
3468
3501
  }
3502
+ function extractStoredChunkRecords(payload) {
3503
+ if (Array.isArray(payload)) {
3504
+ return payload.filter(isRecord2);
3505
+ }
3506
+ if (isRecord2(payload) && Array.isArray(payload.chunks)) {
3507
+ return payload.chunks.filter(isRecord2);
3508
+ }
3509
+ return [];
3510
+ }
3511
+ function readRecordString(record, ...keys) {
3512
+ for (const key of keys) {
3513
+ const value = record[key];
3514
+ if (typeof value === "string") return value;
3515
+ }
3516
+ return void 0;
3517
+ }
3518
+ function readRecordNumber(record, ...keys) {
3519
+ for (const key of keys) {
3520
+ const value = record[key];
3521
+ if (typeof value === "number") return value;
3522
+ }
3523
+ return void 0;
3524
+ }
3525
+ function readRecordMetadata(record) {
3526
+ const metadata = record.metadata;
3527
+ return isRecord2(metadata) ? keysToCamel(metadata) : {};
3528
+ }
3529
+ function isKnowledgeChunkType(value) {
3530
+ return value === "text" || value === "image" || value === "table" || value === "page";
3531
+ }
3469
3532
  function toIndexedReadChunk(chunk) {
3470
3533
  return {
3471
3534
  source: createSyntheticChunk(chunk),
@@ -3519,204 +3582,105 @@ function getNextChunkPosition(chunks, selected) {
3519
3582
  }
3520
3583
  return chunks[chunks.indexOf(lastSelected) + 1]?.position;
3521
3584
  }
3522
- function applyAssetUrlPolicyToReadChunks(chunks, assetUrlPolicy) {
3523
- if (assetUrlPolicy !== "none") {
3524
- return chunks.map((chunk) => ({
3525
- ...chunk,
3526
- metadata: cloneMetadata(chunk.metadata)
3527
- }));
3528
- }
3529
- return chunks.map((chunk) => ({
3530
- ...chunk,
3531
- assetUrl: void 0,
3532
- metadata: removeAssetUrlsFromMetadata(chunk.metadata)
3533
- }));
3585
+ async function applyStoredAssetUrlsToReadChunks(params) {
3586
+ return Promise.all(
3587
+ params.chunks.map(
3588
+ (chunk) => applyStoredAssetUrlsToReadChunk({
3589
+ ...params,
3590
+ chunk
3591
+ })
3592
+ )
3593
+ );
3534
3594
  }
3535
- async function hardenReadChunkAssetUrls(params) {
3595
+ async function applyStoredAssetUrlsToReadChunk(params) {
3536
3596
  const metadata = cloneMetadata(params.chunk.metadata);
3537
- const assetUrl = await hardenPrimaryAssetUrl(params, metadata);
3538
- const pageAssets = await hardenPageAssetUrls(params, metadata);
3539
- if (pageAssets) {
3540
- metadata.pageAssets = pageAssets;
3541
- }
3542
- return {
3543
- ...params.chunk,
3544
- assetUrl,
3545
- metadata
3546
- };
3547
- }
3548
- async function hardenPrimaryAssetUrl(params, metadata) {
3549
- if (!params.chunk.assetUrl || !params.chunk.filePath) {
3550
- return void 0;
3551
- }
3552
- return writeDurableAssetUrl({
3597
+ const storedAssetUrl = await getStoredObjectUrl({
3553
3598
  storageConfig: params.storageConfig,
3554
3599
  documentId: params.documentId,
3555
3600
  revisionKey: params.revisionKey,
3556
- sourcePath: params.chunk.filePath,
3557
- sourceUrl: params.chunk.assetUrl,
3558
- fallbackContentType: inferContentTypeFromPath(params.chunk.filePath),
3559
- metadata: {
3560
- chunkId: params.chunk.chunkId,
3561
- chunkType: params.chunk.chunkType,
3562
- sourcePath: params.chunk.filePath,
3563
- ...stringifyFlatMetadata(metadata)
3564
- }
3601
+ path: params.chunk.filePath
3565
3602
  });
3566
- }
3567
- async function hardenPageAssetUrls(params, metadata) {
3568
- const pageAssets = toUnknownArray(metadata.pageAssets);
3569
- if (!pageAssets) {
3570
- return void 0;
3571
- }
3572
- const hardenedAssets = [];
3573
- for (const pageAsset of pageAssets) {
3574
- if (!isRecord2(pageAsset)) {
3575
- hardenedAssets.push(pageAsset);
3576
- continue;
3577
- }
3578
- const artifactRef = pageAsset.artifactRef;
3579
- const sourceUrl = pageAsset.assetUrl;
3580
- if (typeof artifactRef !== "string" || typeof sourceUrl !== "string") {
3581
- hardenedAssets.push(removeAssetUrlField(pageAsset));
3582
- continue;
3583
- }
3584
- const durableUrl = await writeDurableAssetUrl({
3585
- storageConfig: params.storageConfig,
3586
- documentId: params.documentId,
3587
- revisionKey: params.revisionKey,
3588
- sourcePath: artifactRef,
3589
- sourceUrl,
3590
- fallbackContentType: typeof pageAsset.contentType === "string" ? pageAsset.contentType : inferContentTypeFromPath(artifactRef),
3591
- metadata: {
3592
- chunkId: params.chunk.chunkId,
3593
- chunkType: params.chunk.chunkType,
3594
- sourcePath: artifactRef
3595
- }
3596
- });
3597
- const rest = removeAssetUrlField(pageAsset);
3598
- hardenedAssets.push(durableUrl ? { ...rest, assetUrl: durableUrl } : rest);
3599
- }
3600
- return hardenedAssets;
3601
- }
3602
- async function writeDurableAssetUrl(params) {
3603
- const existingUrl = await params.storageConfig.storage.getAssetUrl({
3603
+ const pageAssets = await applyStoredPageAssetUrls({
3604
+ storageConfig: params.storageConfig,
3604
3605
  documentId: params.documentId,
3605
3606
  revisionKey: params.revisionKey,
3606
- sourcePath: params.sourcePath
3607
+ metadata
3607
3608
  });
3608
- if (existingUrl) {
3609
- return existingUrl;
3610
- }
3611
- try {
3612
- const fetched = await fetchAsset(params.sourceUrl, params.fallbackContentType);
3613
- const written = await params.storageConfig.storage.writeAsset({
3614
- documentId: params.documentId,
3615
- revisionKey: params.revisionKey,
3616
- sourcePath: params.sourcePath,
3617
- body: fetched.body,
3618
- contentType: fetched.contentType,
3619
- metadata: params.metadata
3620
- });
3621
- return written.url ?? await params.storageConfig.storage.getAssetUrl({
3622
- documentId: params.documentId,
3623
- revisionKey: params.revisionKey,
3624
- sourcePath: params.sourcePath
3625
- }) ?? void 0;
3626
- } catch {
3627
- return void 0;
3628
- }
3629
- }
3630
- async function fetchAsset(sourceUrl, fallbackContentType) {
3631
- const response = await fetch(sourceUrl);
3632
- if (!response.ok) {
3633
- throw new Error(`Unable to fetch parsed asset: ${response.status}`);
3609
+ if (pageAssets) {
3610
+ metadata.pageAssets = pageAssets;
3611
+ delete metadata.page_assets;
3634
3612
  }
3635
3613
  return {
3636
- body: new Uint8Array(await response.arrayBuffer()),
3637
- contentType: response.headers.get("content-type") ?? fallbackContentType
3614
+ ...params.chunk,
3615
+ assetUrl: storedAssetUrl ?? params.chunk.assetUrl,
3616
+ metadata
3638
3617
  };
3639
3618
  }
3640
- function removeAssetUrlsFromMetadata(metadata) {
3641
- const cloned = cloneMetadata(metadata);
3642
- const pageAssets = toUnknownArray(cloned.pageAssets);
3619
+ async function applyStoredPageAssetUrls(params) {
3620
+ const pageAssets = getStoredPageAssets(params.metadata);
3643
3621
  if (!pageAssets) {
3644
- return cloned;
3622
+ return void 0;
3645
3623
  }
3646
- cloned.pageAssets = pageAssets.map((pageAsset) => {
3647
- if (!isRecord2(pageAsset)) {
3624
+ return Promise.all(
3625
+ pageAssets.map(async (pageAsset) => {
3626
+ if (!isRecord2(pageAsset)) {
3627
+ return pageAsset;
3628
+ }
3629
+ const artifactRef = readRecordString(pageAsset, "artifactRef", "artifact_ref");
3630
+ if (typeof artifactRef !== "string") {
3631
+ return pageAsset;
3632
+ }
3633
+ const storedAssetUrl = await getStoredObjectUrl({
3634
+ storageConfig: params.storageConfig,
3635
+ documentId: params.documentId,
3636
+ revisionKey: params.revisionKey,
3637
+ path: artifactRef
3638
+ });
3639
+ if (storedAssetUrl) {
3640
+ return {
3641
+ ...pageAsset,
3642
+ artifactRef,
3643
+ assetUrl: storedAssetUrl
3644
+ };
3645
+ }
3648
3646
  return pageAsset;
3649
- }
3650
- return removeAssetUrlField(pageAsset);
3651
- });
3652
- return cloned;
3653
- }
3654
- function removeAssetUrlField(value) {
3655
- const cloned = { ...value };
3656
- delete cloned.assetUrl;
3657
- return cloned;
3658
- }
3659
- function toSnapshotChunkPageFromReadChunks(params) {
3660
- return {
3661
- version: 1,
3662
- jobId: params.response.jobId ?? params.revisionKey,
3663
- revisionKey: params.revisionKey,
3664
- documentId: params.response.documentId,
3665
- namespace: params.response.namespace,
3666
- sourceFileName: params.response.documentId,
3667
- page: params.response.pagination.page,
3668
- pageSize: params.response.pagination.pageSize,
3669
- total: params.response.pagination.total,
3670
- totalPages: params.response.pagination.totalPages,
3671
- chunks: params.chunks.map(toSnapshotChunkFromReadChunk)
3672
- };
3647
+ })
3648
+ );
3673
3649
  }
3674
- function toSnapshotChunkFromReadChunk(chunk) {
3650
+ function getStoredPageAssets(metadata) {
3651
+ const pageAssets = toUnknownArray(metadata.pageAssets) ?? toUnknownArray(metadata.page_assets) ?? void 0;
3652
+ return pageAssets?.map(normalizeStoredPageAsset);
3653
+ }
3654
+ function normalizeStoredPageAsset(pageAsset) {
3655
+ if (!isRecord2(pageAsset)) {
3656
+ return pageAsset;
3657
+ }
3658
+ const normalizedPageAsset = { ...pageAsset };
3659
+ delete normalizedPageAsset.page_num;
3660
+ delete normalizedPageAsset.artifact_ref;
3661
+ delete normalizedPageAsset.asset_url;
3662
+ delete normalizedPageAsset.content_type;
3663
+ const pageNum = readRecordNumber(pageAsset, "pageNum", "page_num");
3664
+ const artifactRef = readRecordString(pageAsset, "artifactRef", "artifact_ref");
3665
+ const assetUrl = readRecordString(pageAsset, "assetUrl", "asset_url");
3666
+ const contentType = readRecordString(pageAsset, "contentType", "content_type");
3675
3667
  return {
3676
- id: chunk.chunkId,
3677
- chunkId: chunk.chunkId,
3678
- chunkType: chunk.chunkType,
3679
- contentSource: chunk.contentSource,
3680
- content: chunk.content,
3681
- sectionPath: chunk.sectionPath,
3682
- sourceChunkPath: chunk.sourceChunkPath,
3683
- filePath: chunk.filePath,
3684
- sortOrder: chunk.position,
3685
- metadata: cloneMetadata(chunk.metadata),
3686
- assetUrl: chunk.assetUrl
3668
+ ...normalizedPageAsset,
3669
+ ...pageNum === void 0 ? {} : { pageNum },
3670
+ ...artifactRef === void 0 ? {} : { artifactRef },
3671
+ ...assetUrl === void 0 ? {} : { assetUrl },
3672
+ ...contentType === void 0 ? {} : { contentType }
3687
3673
  };
3688
3674
  }
3689
- function createRemoteSnapshotManifest(params) {
3690
- return {
3691
- version: 1,
3692
- kind: "knowhere-parsed-result-snapshot",
3693
- jobId: params.response.jobId ?? params.revisionKey,
3675
+ async function getStoredObjectUrl(params) {
3676
+ if (!params.path) {
3677
+ return void 0;
3678
+ }
3679
+ return await params.storageConfig.storage.getObjectUrl?.({
3680
+ documentId: params.documentId,
3694
3681
  revisionKey: params.revisionKey,
3695
- documentId: params.response.documentId,
3696
- namespace: params.response.namespace,
3697
- sourceFileName: params.response.documentId,
3698
- totalChunks: params.response.pagination.total,
3699
- typeCounts: countSnapshotPagesTypes(params.chunkPages),
3700
- chunkPageSize: params.response.pagination.pageSize,
3701
- chunkPages: Array.from({ length: params.response.pagination.totalPages }, (_, index) => ({
3702
- page: index + 1,
3703
- pageSize: params.response.pagination.pageSize,
3704
- chunkCount: index + 1 === params.response.pagination.totalPages ? params.response.pagination.total - params.response.pagination.pageSize * (params.response.pagination.totalPages - 1) : params.response.pagination.pageSize,
3705
- key: `parsed/chunks/page-${index + 1}.json`
3706
- })),
3707
- assetUrlsByFilePath: {},
3708
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
3709
- };
3710
- }
3711
- function countSnapshotPagesTypes(pages) {
3712
- return pages.flatMap((page) => page.chunks).reduce(
3713
- (counts, chunk) => {
3714
- const chunkType = chunk.chunkType;
3715
- counts[chunkType] += 1;
3716
- return counts;
3717
- },
3718
- { text: 0, image: 0, table: 0, page: 0 }
3719
- );
3682
+ path: params.path
3683
+ }) ?? void 0;
3720
3684
  }
3721
3685
  function countRemoteChunkTypes(chunks) {
3722
3686
  return chunks.reduce(
@@ -3794,22 +3758,10 @@ function isOptionalNonNegativeInteger(value) {
3794
3758
  function cloneMetadata(metadata) {
3795
3759
  return { ...metadata };
3796
3760
  }
3797
- function stringifyFlatMetadata(metadata) {
3798
- const entries = Object.entries(metadata).flatMap(([key, value]) => {
3799
- if (typeof value === "string") {
3800
- return [[key, value]];
3801
- }
3802
- if (typeof value === "number" || typeof value === "boolean") {
3803
- return [[key, String(value)]];
3804
- }
3805
- return [];
3806
- });
3807
- return Object.fromEntries(entries);
3808
- }
3809
3761
  function toUnknownArray(value) {
3810
3762
  return Array.isArray(value) ? value : null;
3811
3763
  }
3812
- function inferContentTypeFromPath(filePath) {
3764
+ function inferContentTypeFromPath2(filePath) {
3813
3765
  const extension = filePath.split(".").at(-1)?.toLowerCase();
3814
3766
  if (extension === "png") return "image/png";
3815
3767
  if (extension === "jpg" || extension === "jpeg") return "image/jpeg";
@@ -3819,6 +3771,9 @@ function inferContentTypeFromPath(filePath) {
3819
3771
  function isRecord2(value) {
3820
3772
  return typeof value === "object" && value !== null && !Array.isArray(value);
3821
3773
  }
3774
+ function isDocumentChunkArray(value) {
3775
+ return Array.isArray(value) && value.every(isRecord2);
3776
+ }
3822
3777
  function indexChunks(result) {
3823
3778
  return result.chunks.map((chunk, index) => {
3824
3779
  const filePath = getChunkFilePath2(chunk);
@@ -4264,51 +4219,59 @@ var Knowhere = class {
4264
4219
  import { createHash as createHash3 } from "crypto";
4265
4220
  import { promises as fs4 } from "fs";
4266
4221
  import path3 from "path";
4222
+ var syncProgressPath = ".knowhere-sdk/sync-progress.json";
4267
4223
  var DiskParsedDocumentStorage = class {
4268
4224
  rootDirectory;
4269
4225
  constructor(rootDirectory) {
4270
4226
  this.rootDirectory = rootDirectory;
4271
4227
  }
4272
- async readManifest(params) {
4273
- return this.readOptionalJson(
4274
- this.getManifestPath(params.documentId, params.revisionKey)
4275
- );
4276
- }
4277
- async writeManifest(params) {
4278
- await this.writeJson(
4279
- this.getManifestPath(params.documentId, params.revisionKey),
4280
- params.manifest
4281
- );
4282
- }
4283
- async readChunkPage(params) {
4284
- return this.readOptionalJson(
4285
- this.getChunkPagePath(params.documentId, params.revisionKey, params.page)
4286
- );
4287
- }
4288
- async writeChunkPage(params) {
4289
- await this.writeJson(
4290
- this.getChunkPagePath(params.documentId, params.revisionKey, params.page.page),
4291
- params.page
4292
- );
4228
+ async readObject(params) {
4229
+ const objectPath = this.getObjectPath(params);
4230
+ try {
4231
+ const body = await fs4.readFile(objectPath);
4232
+ const metadata = await this.readObjectMetadata(objectPath);
4233
+ return {
4234
+ ...params,
4235
+ body,
4236
+ contentType: metadata?.contentType,
4237
+ contentLength: body.byteLength,
4238
+ metadata: metadata?.metadata,
4239
+ url: toFileUrl(objectPath)
4240
+ };
4241
+ } catch (error) {
4242
+ if (isMissingFileError3(error)) {
4243
+ return null;
4244
+ }
4245
+ throw error;
4246
+ }
4293
4247
  }
4294
- async writeAsset(params) {
4295
- const assetPath = this.getAssetPath(params.documentId, params.revisionKey, params.sourcePath);
4296
- await fs4.mkdir(path3.dirname(assetPath), { recursive: true });
4297
- await fs4.writeFile(assetPath, params.body);
4298
- await this.writeJson(`${assetPath}.metadata.json`, {
4248
+ async writeObject(params) {
4249
+ const objectPath = this.getObjectPath(params);
4250
+ await fs4.mkdir(path3.dirname(objectPath), { recursive: true });
4251
+ await fs4.writeFile(objectPath, params.body);
4252
+ await this.writeObjectMetadata(objectPath, {
4299
4253
  contentType: params.contentType,
4300
- metadata: params.metadata ?? {}
4254
+ metadata: params.metadata
4301
4255
  });
4302
4256
  return {
4303
- sourcePath: params.sourcePath,
4304
- url: toFileUrl(assetPath)
4257
+ documentId: params.documentId,
4258
+ revisionKey: params.revisionKey,
4259
+ path: params.path,
4260
+ url: toFileUrl(objectPath)
4305
4261
  };
4306
4262
  }
4307
- async getAssetUrl(params) {
4308
- const assetPath = this.getAssetPath(params.documentId, params.revisionKey, params.sourcePath);
4263
+ async headObject(params) {
4264
+ const objectPath = this.getObjectPath(params);
4309
4265
  try {
4310
- await fs4.access(assetPath);
4311
- return toFileUrl(assetPath);
4266
+ const stat = await fs4.stat(objectPath);
4267
+ const metadata = await this.readObjectMetadata(objectPath);
4268
+ return {
4269
+ ...params,
4270
+ contentType: metadata?.contentType,
4271
+ contentLength: stat.size,
4272
+ metadata: metadata?.metadata,
4273
+ url: toFileUrl(objectPath)
4274
+ };
4312
4275
  } catch (error) {
4313
4276
  if (isMissingFileError3(error)) {
4314
4277
  return null;
@@ -4316,53 +4279,54 @@ var DiskParsedDocumentStorage = class {
4316
4279
  throw error;
4317
4280
  }
4318
4281
  }
4319
- async readSyncProgress(params) {
4320
- return this.readOptionalJson(
4321
- this.getProgressPath(params.documentId, params.revisionKey)
4322
- );
4323
- }
4324
- async writeSyncProgress(params) {
4325
- await this.writeJson(this.getProgressPath(params.documentId, params.revisionKey), params);
4282
+ async getObjectUrl(params) {
4283
+ const head = await this.headObject(params);
4284
+ return head?.url ?? null;
4326
4285
  }
4327
- getManifestPath(documentId, revisionKey) {
4328
- return path3.join(
4329
- this.getRevisionDirectory(documentId, revisionKey),
4330
- "manifest",
4331
- "current.json"
4332
- );
4286
+ async deletePrefix(params) {
4287
+ await fs4.rm(this.getRevisionDirectory(params.documentId, params.revisionKey), {
4288
+ recursive: true,
4289
+ force: true
4290
+ });
4333
4291
  }
4334
- getChunkPagePath(documentId, revisionKey, page) {
4335
- return path3.join(
4336
- this.getRevisionDirectory(documentId, revisionKey),
4337
- "chunks",
4338
- `page-${page}.json`
4339
- );
4292
+ async readSyncProgress(params) {
4293
+ return this.readOptionalJson({
4294
+ ...params,
4295
+ path: syncProgressPath
4296
+ });
4340
4297
  }
4341
- getProgressPath(documentId, revisionKey) {
4342
- return path3.join(this.getRevisionDirectory(documentId, revisionKey), "sync-progress.json");
4298
+ async writeSyncProgress(params) {
4299
+ await this.writeObject({
4300
+ documentId: params.documentId,
4301
+ revisionKey: params.revisionKey,
4302
+ path: syncProgressPath,
4303
+ body: Buffer.from(JSON.stringify(params, null, 2), "utf8"),
4304
+ contentType: "application/json; charset=utf-8"
4305
+ });
4343
4306
  }
4344
- getAssetPath(documentId, revisionKey, sourcePath) {
4345
- const normalizedSourcePath = normalizeRelativeStoragePath(sourcePath);
4346
- const assetPath = path3.resolve(
4347
- this.getRevisionDirectory(documentId, revisionKey),
4348
- "assets",
4349
- normalizedSourcePath
4350
- );
4351
- const assetsDirectory = path3.resolve(
4352
- this.getRevisionDirectory(documentId, revisionKey),
4353
- "assets"
4354
- );
4355
- if (!isPathInsideDirectory2(assetPath, assetsDirectory)) {
4356
- throw new Error(`Parsed asset path resolves outside storage: ${sourcePath}`);
4307
+ getObjectPath(params) {
4308
+ const revisionDirectory = this.getRevisionDirectory(params.documentId, params.revisionKey);
4309
+ const objectPath = path3.resolve(revisionDirectory, normalizeRelativeStoragePath(params.path));
4310
+ if (!isPathInsideDirectory2(objectPath, revisionDirectory)) {
4311
+ throw new Error(`Parsed document object path resolves outside storage: ${params.path}`);
4357
4312
  }
4358
- return assetPath;
4313
+ return objectPath;
4359
4314
  }
4360
4315
  getRevisionDirectory(documentId, revisionKey) {
4361
4316
  return path3.join(this.rootDirectory, hashPathPart(documentId), hashPathPart(revisionKey));
4362
4317
  }
4363
- async readOptionalJson(filePath) {
4318
+ async readOptionalJson(params) {
4319
+ const object = await this.readObject(params);
4320
+ if (!object) {
4321
+ return null;
4322
+ }
4323
+ return JSON.parse(Buffer.from(object.body).toString("utf8"));
4324
+ }
4325
+ async readObjectMetadata(filePath) {
4364
4326
  try {
4365
- return JSON.parse(await fs4.readFile(filePath, "utf8"));
4327
+ return JSON.parse(
4328
+ await fs4.readFile(getMetadataPath(filePath), "utf8")
4329
+ );
4366
4330
  } catch (error) {
4367
4331
  if (isMissingFileError3(error)) {
4368
4332
  return null;
@@ -4370,16 +4334,22 @@ var DiskParsedDocumentStorage = class {
4370
4334
  throw error;
4371
4335
  }
4372
4336
  }
4373
- async writeJson(filePath, value) {
4374
- await fs4.mkdir(path3.dirname(filePath), { recursive: true });
4375
- await fs4.writeFile(filePath, JSON.stringify(value, null, 2), {
4337
+ async writeObjectMetadata(filePath, metadata) {
4338
+ await fs4.writeFile(getMetadataPath(filePath), JSON.stringify(metadata, null, 2), {
4376
4339
  encoding: "utf8",
4377
4340
  flag: "w"
4378
4341
  });
4379
4342
  }
4380
4343
  };
4344
+ function getMetadataPath(filePath) {
4345
+ return `${filePath}.metadata.json`;
4346
+ }
4381
4347
  function hashPathPart(value) {
4382
- return createHash3("sha256").update(value).digest("hex").slice(0, 24);
4348
+ const normalized = value.trim();
4349
+ if (normalized.length === 0) {
4350
+ throw new Error("Parsed document storage path part must be a non-empty value.");
4351
+ }
4352
+ return createHash3("sha256").update(normalized).digest("hex").slice(0, 24);
4383
4353
  }
4384
4354
  function normalizeRelativeStoragePath(value) {
4385
4355
  const normalized = value.replaceAll("\\", "/").replace(/^\.\/+/, "");