@ontos-ai/knowhere-sdk 0.10.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +119 -25
- package/dist/index.d.mts +756 -390
- package/dist/index.d.ts +756 -390
- package/dist/index.js +2057 -56
- package/dist/index.mjs +2053 -55
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -35,6 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
BadRequestError: () => BadRequestError,
|
|
36
36
|
ChecksumError: () => ChecksumError,
|
|
37
37
|
ConflictError: () => ConflictError,
|
|
38
|
+
DiskParsedDocumentStorage: () => DiskParsedDocumentStorage,
|
|
38
39
|
Documents: () => Documents,
|
|
39
40
|
GatewayTimeoutError: () => GatewayTimeoutError,
|
|
40
41
|
InternalServerError: () => InternalServerError,
|
|
@@ -56,7 +57,9 @@ __export(index_exports, {
|
|
|
56
57
|
TimeoutError: () => TimeoutError,
|
|
57
58
|
VERSION: () => VERSION,
|
|
58
59
|
ValidationError: () => ValidationError,
|
|
59
|
-
default: () => Knowhere
|
|
60
|
+
default: () => Knowhere,
|
|
61
|
+
storeParseResultAssets: () => storeParseResultAssets,
|
|
62
|
+
syncParseResultToParsedDocumentStorage: () => syncParseResultToParsedDocumentStorage
|
|
60
63
|
});
|
|
61
64
|
module.exports = __toCommonJS(index_exports);
|
|
62
65
|
|
|
@@ -369,8 +372,8 @@ function enrichParseResult(parseResult2, scope) {
|
|
|
369
372
|
}
|
|
370
373
|
return parseResult2;
|
|
371
374
|
}
|
|
372
|
-
function sanitizePath(
|
|
373
|
-
let sanitized =
|
|
375
|
+
function sanitizePath(path4) {
|
|
376
|
+
let sanitized = path4.replace(/^\/+/, "");
|
|
374
377
|
sanitized = sanitized.replace(/\.\.(\/|\\)/g, "");
|
|
375
378
|
sanitized = sanitized.replace(/\\/g, "/");
|
|
376
379
|
return sanitized;
|
|
@@ -756,6 +759,9 @@ var BaseResource = class {
|
|
|
756
759
|
constructor(httpClient) {
|
|
757
760
|
this.httpClient = httpClient;
|
|
758
761
|
}
|
|
762
|
+
endpoint(path4) {
|
|
763
|
+
return `/v2${path4.startsWith("/") ? path4 : `/${path4}`}`;
|
|
764
|
+
}
|
|
759
765
|
};
|
|
760
766
|
|
|
761
767
|
// src/lib/upload.ts
|
|
@@ -806,7 +812,7 @@ async function pollJobStatus(httpClient, jobId, options) {
|
|
|
806
812
|
if (signal?.aborted) {
|
|
807
813
|
throw new Error("Polling aborted");
|
|
808
814
|
}
|
|
809
|
-
const jobResult = await httpClient.get(`/
|
|
815
|
+
const jobResult = await httpClient.get(`/v2/jobs/${jobId}`);
|
|
810
816
|
enrichJobResult(jobResult);
|
|
811
817
|
const elapsed = Date.now() - startTime;
|
|
812
818
|
const elapsedSeconds = Math.floor(elapsed / 1e3);
|
|
@@ -970,17 +976,28 @@ async function saveExpandedParseResult(result, directory) {
|
|
|
970
976
|
if (result.rawZip.length > 0) {
|
|
971
977
|
const didExtractZip = await tryExtractRawZip(result.rawZip, directory);
|
|
972
978
|
if (didExtractZip) {
|
|
979
|
+
await writeExpandedParseResultMetadata(result, directory);
|
|
973
980
|
return directory;
|
|
974
981
|
}
|
|
975
982
|
}
|
|
976
983
|
await import_fs2.promises.mkdir(directory, { recursive: true });
|
|
984
|
+
await writeExpandedParseResultMetadata(result, directory);
|
|
985
|
+
for (const imageChunk of result.imageChunks) {
|
|
986
|
+
await writeBinaryAsset(directory, imageChunk.filePath, imageChunk.data);
|
|
987
|
+
}
|
|
988
|
+
for (const tableChunk of result.tableChunks) {
|
|
989
|
+
await writeTextAsset(directory, tableChunk.filePath, tableChunk.html);
|
|
990
|
+
}
|
|
991
|
+
return directory;
|
|
992
|
+
}
|
|
993
|
+
async function writeExpandedParseResultMetadata(result, directory) {
|
|
977
994
|
await import_fs2.promises.writeFile((0, import_path.join)(directory, "manifest.json"), JSON.stringify(result.manifest, null, 2));
|
|
978
995
|
if (result.docNav) {
|
|
979
996
|
await import_fs2.promises.writeFile((0, import_path.join)(directory, "doc_nav.json"), JSON.stringify(result.docNav, null, 2));
|
|
980
997
|
}
|
|
981
998
|
await import_fs2.promises.writeFile(
|
|
982
999
|
(0, import_path.join)(directory, "chunks.json"),
|
|
983
|
-
JSON.stringify(serializeChunks(result.chunks), null, 2)
|
|
1000
|
+
JSON.stringify(keysToSnake(serializeChunks(result.chunks)), null, 2)
|
|
984
1001
|
);
|
|
985
1002
|
if (result.chunksSlim) {
|
|
986
1003
|
await import_fs2.promises.writeFile(
|
|
@@ -1009,13 +1026,6 @@ async function saveExpandedParseResult(result, directory) {
|
|
|
1009
1026
|
if (result.hierarchyViewHtml) {
|
|
1010
1027
|
await import_fs2.promises.writeFile((0, import_path.join)(directory, "hierarchy_view.html"), result.hierarchyViewHtml);
|
|
1011
1028
|
}
|
|
1012
|
-
for (const imageChunk of result.imageChunks) {
|
|
1013
|
-
await writeBinaryAsset(directory, imageChunk.filePath, imageChunk.data);
|
|
1014
|
-
}
|
|
1015
|
-
for (const tableChunk of result.tableChunks) {
|
|
1016
|
-
await writeTextAsset(directory, tableChunk.filePath, tableChunk.html);
|
|
1017
|
-
}
|
|
1018
|
-
return directory;
|
|
1019
1029
|
}
|
|
1020
1030
|
async function tryExtractRawZip(zipBuffer, directory) {
|
|
1021
1031
|
try {
|
|
@@ -1067,6 +1077,9 @@ function createParseResult(parts) {
|
|
|
1067
1077
|
get tableChunks() {
|
|
1068
1078
|
return chunks.filter((c) => c.type === "table");
|
|
1069
1079
|
},
|
|
1080
|
+
get pageChunks() {
|
|
1081
|
+
return chunks.filter((c) => c.type === "page");
|
|
1082
|
+
},
|
|
1070
1083
|
get jobId() {
|
|
1071
1084
|
return manifest.jobId;
|
|
1072
1085
|
},
|
|
@@ -1144,18 +1157,32 @@ function buildTextChunk(chunkData) {
|
|
|
1144
1157
|
return {
|
|
1145
1158
|
chunkId: chunkData.chunkId ?? "",
|
|
1146
1159
|
type: "text",
|
|
1160
|
+
contentSource: chunkData.contentSource ?? "content",
|
|
1147
1161
|
content: chunkData.content ?? "",
|
|
1148
1162
|
path: chunkData.path ?? "",
|
|
1149
1163
|
metadata: chunkData.metadata ?? {}
|
|
1150
1164
|
};
|
|
1151
1165
|
}
|
|
1166
|
+
function buildPageChunk(chunkData) {
|
|
1167
|
+
const metadata = chunkData.metadata ?? {};
|
|
1168
|
+
return {
|
|
1169
|
+
chunkId: chunkData.chunkId ?? "",
|
|
1170
|
+
type: "page",
|
|
1171
|
+
contentSource: chunkData.contentSource ?? "summary",
|
|
1172
|
+
content: chunkData.content ?? "",
|
|
1173
|
+
path: chunkData.path ?? "",
|
|
1174
|
+
metadata
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
1152
1177
|
function buildImageChunk(chunkData, filePath, imageBuffer) {
|
|
1153
1178
|
return {
|
|
1154
1179
|
chunkId: chunkData.chunkId ?? "",
|
|
1155
1180
|
type: "image",
|
|
1181
|
+
contentSource: chunkData.contentSource,
|
|
1156
1182
|
content: chunkData.content ?? "",
|
|
1157
1183
|
path: chunkData.path ?? "",
|
|
1158
1184
|
filePath,
|
|
1185
|
+
assetUrl: chunkData.assetUrl,
|
|
1159
1186
|
data: imageBuffer,
|
|
1160
1187
|
metadata: chunkData.metadata ?? {},
|
|
1161
1188
|
get format() {
|
|
@@ -1170,9 +1197,11 @@ function buildTableChunk(chunkData, filePath, html) {
|
|
|
1170
1197
|
return {
|
|
1171
1198
|
chunkId: chunkData.chunkId ?? "",
|
|
1172
1199
|
type: "table",
|
|
1200
|
+
contentSource: chunkData.contentSource,
|
|
1173
1201
|
content: chunkData.content ?? "",
|
|
1174
1202
|
path: chunkData.path ?? "",
|
|
1175
1203
|
filePath,
|
|
1204
|
+
assetUrl: chunkData.assetUrl,
|
|
1176
1205
|
html,
|
|
1177
1206
|
metadata: chunkData.metadata ?? {},
|
|
1178
1207
|
async save(directory) {
|
|
@@ -1184,6 +1213,9 @@ async function processChunk(zip, chunkData) {
|
|
|
1184
1213
|
if (chunkData.type === "text") {
|
|
1185
1214
|
return buildTextChunk(chunkData);
|
|
1186
1215
|
}
|
|
1216
|
+
if (chunkData.type === "page") {
|
|
1217
|
+
return buildPageChunk(chunkData);
|
|
1218
|
+
}
|
|
1187
1219
|
if (chunkData.type === "image") {
|
|
1188
1220
|
const filePath = getChunkFilePath(chunkData);
|
|
1189
1221
|
if (!filePath) {
|
|
@@ -1216,6 +1248,9 @@ async function processDirectoryChunk(directory, chunkData) {
|
|
|
1216
1248
|
if (chunkData.type === "text") {
|
|
1217
1249
|
return buildTextChunk(chunkData);
|
|
1218
1250
|
}
|
|
1251
|
+
if (chunkData.type === "page") {
|
|
1252
|
+
return buildPageChunk(chunkData);
|
|
1253
|
+
}
|
|
1219
1254
|
if (chunkData.type === "image") {
|
|
1220
1255
|
const filePath = getChunkFilePath(chunkData);
|
|
1221
1256
|
if (!filePath) {
|
|
@@ -1254,12 +1289,14 @@ function serializeChunks(chunks) {
|
|
|
1254
1289
|
const rawChunk = {
|
|
1255
1290
|
chunkId: chunk.chunkId,
|
|
1256
1291
|
type: chunk.type,
|
|
1292
|
+
contentSource: chunk.contentSource,
|
|
1257
1293
|
content: chunk.content,
|
|
1258
1294
|
path: chunk.path,
|
|
1259
1295
|
metadata: chunk.metadata
|
|
1260
1296
|
};
|
|
1261
1297
|
if (chunk.type === "image" || chunk.type === "table") {
|
|
1262
1298
|
rawChunk.filePath = chunk.filePath;
|
|
1299
|
+
rawChunk.assetUrl = chunk.assetUrl;
|
|
1263
1300
|
}
|
|
1264
1301
|
return rawChunk;
|
|
1265
1302
|
})
|
|
@@ -1322,7 +1359,7 @@ var Jobs = class extends BaseResource {
|
|
|
1322
1359
|
* Create a new parsing job
|
|
1323
1360
|
*/
|
|
1324
1361
|
async create(params) {
|
|
1325
|
-
const job = await this.httpClient.post("/
|
|
1362
|
+
const job = await this.httpClient.post(this.endpoint("/jobs"), params);
|
|
1326
1363
|
if (job.uploadUrl) {
|
|
1327
1364
|
this.pendingUploadJobs.set(job.jobId, job);
|
|
1328
1365
|
}
|
|
@@ -1332,7 +1369,7 @@ var Jobs = class extends BaseResource {
|
|
|
1332
1369
|
* Get job status
|
|
1333
1370
|
*/
|
|
1334
1371
|
async get(jobId) {
|
|
1335
|
-
const jobResult = await this.httpClient.get(`/
|
|
1372
|
+
const jobResult = await this.httpClient.get(this.endpoint(`/jobs/${jobId}`));
|
|
1336
1373
|
enrichJobResult(jobResult);
|
|
1337
1374
|
return jobResult;
|
|
1338
1375
|
}
|
|
@@ -1428,7 +1465,7 @@ var Retrieval = class extends BaseResource {
|
|
|
1428
1465
|
* Query published documents.
|
|
1429
1466
|
*/
|
|
1430
1467
|
async query(params) {
|
|
1431
|
-
return this.httpClient.post("/
|
|
1468
|
+
return this.httpClient.post(this.endpoint("/retrieval/query"), params);
|
|
1432
1469
|
}
|
|
1433
1470
|
};
|
|
1434
1471
|
|
|
@@ -1439,7 +1476,7 @@ var Documents = class extends BaseResource {
|
|
|
1439
1476
|
*/
|
|
1440
1477
|
async list(params) {
|
|
1441
1478
|
const response = await this.httpClient.get(
|
|
1442
|
-
"/
|
|
1479
|
+
this.endpoint("/documents"),
|
|
1443
1480
|
this.createDocumentListRequestConfig(params)
|
|
1444
1481
|
);
|
|
1445
1482
|
return this.normalizeDocumentListResponse(response);
|
|
@@ -1448,14 +1485,14 @@ var Documents = class extends BaseResource {
|
|
|
1448
1485
|
* Get one canonical document by ID.
|
|
1449
1486
|
*/
|
|
1450
1487
|
async get(documentId) {
|
|
1451
|
-
return this.httpClient.get(`/
|
|
1488
|
+
return this.httpClient.get(this.endpoint(`/documents/${documentId}`));
|
|
1452
1489
|
}
|
|
1453
1490
|
/**
|
|
1454
1491
|
* List current-revision chunks for one canonical document.
|
|
1455
1492
|
*/
|
|
1456
1493
|
async listChunks(documentId, params) {
|
|
1457
1494
|
return this.httpClient.get(
|
|
1458
|
-
`/
|
|
1495
|
+
this.endpoint(`/documents/${documentId}/chunks`),
|
|
1459
1496
|
this.createChunkListRequestConfig(params)
|
|
1460
1497
|
);
|
|
1461
1498
|
}
|
|
@@ -1464,15 +1501,23 @@ var Documents = class extends BaseResource {
|
|
|
1464
1501
|
*/
|
|
1465
1502
|
async getChunk(documentId, documentChunkId, params) {
|
|
1466
1503
|
return this.httpClient.get(
|
|
1467
|
-
`/
|
|
1504
|
+
this.endpoint(`/documents/${documentId}/chunks/${documentChunkId}`),
|
|
1468
1505
|
this.createChunkGetRequestConfig(params)
|
|
1469
1506
|
);
|
|
1470
1507
|
}
|
|
1508
|
+
/**
|
|
1509
|
+
* Get a signed normalized source-file URL for compatibility and debugging.
|
|
1510
|
+
*/
|
|
1511
|
+
async getPageCitationSource(documentId) {
|
|
1512
|
+
return this.httpClient.get(
|
|
1513
|
+
this.endpoint(`/documents/${documentId}/files/page-citation-source`)
|
|
1514
|
+
);
|
|
1515
|
+
}
|
|
1471
1516
|
/**
|
|
1472
1517
|
* Archive one canonical document by ID.
|
|
1473
1518
|
*/
|
|
1474
1519
|
async archive(documentId) {
|
|
1475
|
-
return this.httpClient.post(`/
|
|
1520
|
+
return this.httpClient.post(this.endpoint(`/documents/${documentId}/archive`));
|
|
1476
1521
|
}
|
|
1477
1522
|
createDocumentListRequestConfig(params) {
|
|
1478
1523
|
if (!params) {
|
|
@@ -1540,6 +1585,514 @@ var Documents = class extends BaseResource {
|
|
|
1540
1585
|
// src/knowledge/knowledge.ts
|
|
1541
1586
|
var import_crypto2 = require("crypto");
|
|
1542
1587
|
|
|
1588
|
+
// src/storage/asset-storage.ts
|
|
1589
|
+
var import_jszip2 = __toESM(require("jszip"));
|
|
1590
|
+
var pageCitationAssetsMetadataKey = "pageAssets";
|
|
1591
|
+
var defaultImageContentType = "application/octet-stream";
|
|
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
|
+
async function storeParseResultAssets(result, options) {
|
|
1598
|
+
if (!options) {
|
|
1599
|
+
return {
|
|
1600
|
+
result,
|
|
1601
|
+
assetUrlsByFilePath: {}
|
|
1602
|
+
};
|
|
1603
|
+
}
|
|
1604
|
+
const normalizedKeyPrefix = normalizeStorageKeyPrefix(options.keyPrefix);
|
|
1605
|
+
const assets = dedupeStorageAssets(await collectStorageAssets(result, normalizedKeyPrefix));
|
|
1606
|
+
const assetUrlsByFilePath = {};
|
|
1607
|
+
for (const asset of assets) {
|
|
1608
|
+
const storedUrl = await storeAsset(asset, options.adapter, options.skipExisting ?? true);
|
|
1609
|
+
if (storedUrl) {
|
|
1610
|
+
assetUrlsByFilePath[asset.sourcePath] = storedUrl;
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
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
|
+
return {
|
|
1621
|
+
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)
|
|
1738
|
+
};
|
|
1739
|
+
}
|
|
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
|
+
async function collectStorageAssets(result, keyPrefix) {
|
|
1757
|
+
const resultZip = await loadResultZipForPageCitationAssets(result);
|
|
1758
|
+
return [
|
|
1759
|
+
...result.imageChunks.flatMap((chunk) => collectImageStorageAsset(chunk, keyPrefix)),
|
|
1760
|
+
...result.tableChunks.flatMap((chunk) => collectTableStorageAsset(chunk, keyPrefix)),
|
|
1761
|
+
...resultZip ? await collectPageCitationStorageAssets(result.pageChunks, keyPrefix, resultZip) : []
|
|
1762
|
+
];
|
|
1763
|
+
}
|
|
1764
|
+
function collectImageStorageAsset(chunk, keyPrefix) {
|
|
1765
|
+
const sourcePath = normalizeResultAssetPath(chunk.filePath);
|
|
1766
|
+
if (!sourcePath) return [];
|
|
1767
|
+
return [
|
|
1768
|
+
{
|
|
1769
|
+
sourcePath,
|
|
1770
|
+
storageKey: `${keyPrefix}/${sourcePath}`,
|
|
1771
|
+
body: chunk.data,
|
|
1772
|
+
contentType: getImageContentType(chunk.filePath),
|
|
1773
|
+
metadata: {
|
|
1774
|
+
chunkId: chunk.chunkId,
|
|
1775
|
+
chunkType: chunk.type,
|
|
1776
|
+
sourcePath
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
];
|
|
1780
|
+
}
|
|
1781
|
+
function collectTableStorageAsset(chunk, keyPrefix) {
|
|
1782
|
+
const sourcePath = normalizeResultAssetPath(chunk.filePath);
|
|
1783
|
+
if (!sourcePath) return [];
|
|
1784
|
+
return [
|
|
1785
|
+
{
|
|
1786
|
+
sourcePath,
|
|
1787
|
+
storageKey: `${keyPrefix}/${sourcePath}`,
|
|
1788
|
+
body: Buffer.from(chunk.html, "utf8"),
|
|
1789
|
+
contentType: tableContentType,
|
|
1790
|
+
metadata: {
|
|
1791
|
+
chunkId: chunk.chunkId,
|
|
1792
|
+
chunkType: chunk.type,
|
|
1793
|
+
sourcePath
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
];
|
|
1797
|
+
}
|
|
1798
|
+
async function collectPageCitationStorageAssets(chunks, keyPrefix, resultZip) {
|
|
1799
|
+
const assets = [];
|
|
1800
|
+
for (const chunk of chunks) {
|
|
1801
|
+
const pageAssets = parsePageCitationAssets(chunk.metadata[pageCitationAssetsMetadataKey]);
|
|
1802
|
+
for (const pageAsset of pageAssets) {
|
|
1803
|
+
const sourcePath = normalizeResultAssetPath(pageAsset.artifactRef);
|
|
1804
|
+
if (!sourcePath) continue;
|
|
1805
|
+
const zipEntry = resultZip.file(sourcePath);
|
|
1806
|
+
if (!zipEntry) continue;
|
|
1807
|
+
assets.push({
|
|
1808
|
+
sourcePath,
|
|
1809
|
+
storageKey: `${keyPrefix}/${sourcePath}`,
|
|
1810
|
+
body: await zipEntry.async("uint8array"),
|
|
1811
|
+
contentType: pageAsset.contentType,
|
|
1812
|
+
metadata: getPageCitationAssetMetadata(chunk, pageAsset, sourcePath)
|
|
1813
|
+
});
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
return assets;
|
|
1817
|
+
}
|
|
1818
|
+
function getPageCitationAssetMetadata(chunk, pageAsset, sourcePath) {
|
|
1819
|
+
return {
|
|
1820
|
+
chunkId: chunk.chunkId,
|
|
1821
|
+
chunkType: chunk.type,
|
|
1822
|
+
pageNum: String(pageAsset.pageNum),
|
|
1823
|
+
sourcePath
|
|
1824
|
+
};
|
|
1825
|
+
}
|
|
1826
|
+
async function loadResultZipForPageCitationAssets(result) {
|
|
1827
|
+
if (!hasPageCitationAssetReferences(result) || result.rawZip.length === 0) {
|
|
1828
|
+
return null;
|
|
1829
|
+
}
|
|
1830
|
+
try {
|
|
1831
|
+
return await import_jszip2.default.loadAsync(result.rawZip);
|
|
1832
|
+
} catch (cause) {
|
|
1833
|
+
throw new Error("Unable to read page citation assets from the Knowhere result ZIP.", {
|
|
1834
|
+
cause
|
|
1835
|
+
});
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
function hasPageCitationAssetReferences(result) {
|
|
1839
|
+
return result.pageChunks.some(
|
|
1840
|
+
(chunk) => parsePageCitationAssets(chunk.metadata[pageCitationAssetsMetadataKey]).length > 0
|
|
1841
|
+
);
|
|
1842
|
+
}
|
|
1843
|
+
function dedupeStorageAssets(assets) {
|
|
1844
|
+
const assetsBySourcePath = /* @__PURE__ */ new Map();
|
|
1845
|
+
for (const asset of assets) {
|
|
1846
|
+
if (!assetsBySourcePath.has(asset.sourcePath)) {
|
|
1847
|
+
assetsBySourcePath.set(asset.sourcePath, asset);
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
return [...assetsBySourcePath.values()];
|
|
1851
|
+
}
|
|
1852
|
+
async function storeAsset(asset, adapter, skipExisting) {
|
|
1853
|
+
if (skipExisting && adapter.headObject) {
|
|
1854
|
+
const existing = await adapter.headObject(asset.storageKey);
|
|
1855
|
+
if (existing) {
|
|
1856
|
+
const existingUrl = existing.url ?? await adapter.getObjectUrl?.(asset.storageKey);
|
|
1857
|
+
if (existingUrl) return existingUrl;
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
const writeResult = await adapter.writeObject({
|
|
1861
|
+
key: asset.storageKey,
|
|
1862
|
+
body: asset.body,
|
|
1863
|
+
contentType: asset.contentType,
|
|
1864
|
+
metadata: asset.metadata
|
|
1865
|
+
});
|
|
1866
|
+
return writeResult.url ?? await adapter.getObjectUrl?.(writeResult.key) ?? null;
|
|
1867
|
+
}
|
|
1868
|
+
function rewriteResultAssetUrls(result, assetUrlsByFilePath) {
|
|
1869
|
+
const chunks = result.chunks.map((chunk) => rewriteChunkAssetUrls(chunk, assetUrlsByFilePath));
|
|
1870
|
+
result.chunks.splice(0, result.chunks.length, ...chunks);
|
|
1871
|
+
refreshStaticChunkCollections(result);
|
|
1872
|
+
return result;
|
|
1873
|
+
}
|
|
1874
|
+
function rewriteChunkAssetUrls(chunk, assetUrlsByPath) {
|
|
1875
|
+
if (chunk.type === "image" || chunk.type === "table") {
|
|
1876
|
+
const sourcePath = normalizeResultAssetPath(chunk.filePath);
|
|
1877
|
+
const assetUrl = sourcePath ? assetUrlsByPath[sourcePath] : void 0;
|
|
1878
|
+
if (!assetUrl) return chunk;
|
|
1879
|
+
return {
|
|
1880
|
+
...chunk,
|
|
1881
|
+
assetUrl
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1884
|
+
if (chunk.type === "page") {
|
|
1885
|
+
const pageAssets = parsePageCitationAssets(chunk.metadata[pageCitationAssetsMetadataKey]);
|
|
1886
|
+
if (pageAssets.length === 0) return chunk;
|
|
1887
|
+
const rewrittenPageAssets = pageAssets.map((pageAsset) => {
|
|
1888
|
+
const sourcePath = normalizeResultAssetPath(pageAsset.artifactRef);
|
|
1889
|
+
const assetUrl = sourcePath ? assetUrlsByPath[sourcePath] : void 0;
|
|
1890
|
+
return assetUrl ? { ...pageAsset, assetUrl } : pageAsset;
|
|
1891
|
+
});
|
|
1892
|
+
return {
|
|
1893
|
+
...chunk,
|
|
1894
|
+
metadata: {
|
|
1895
|
+
...chunk.metadata,
|
|
1896
|
+
[pageCitationAssetsMetadataKey]: rewrittenPageAssets
|
|
1897
|
+
}
|
|
1898
|
+
};
|
|
1899
|
+
}
|
|
1900
|
+
return chunk;
|
|
1901
|
+
}
|
|
1902
|
+
function parsePageCitationAssets(value) {
|
|
1903
|
+
if (!Array.isArray(value)) return [];
|
|
1904
|
+
return value.flatMap((item) => {
|
|
1905
|
+
if (!isRecord(item)) return [];
|
|
1906
|
+
const pageNum = item.pageNum;
|
|
1907
|
+
const artifactRef = item.artifactRef;
|
|
1908
|
+
const contentType = item.contentType;
|
|
1909
|
+
const source = item.source;
|
|
1910
|
+
if (typeof pageNum !== "number" || !Number.isSafeInteger(pageNum) || pageNum <= 0) return [];
|
|
1911
|
+
if (typeof artifactRef !== "string") return [];
|
|
1912
|
+
if (contentType !== "image/png" && contentType !== "image/jpeg") return [];
|
|
1913
|
+
if (source !== "knowhere-rendered-page-citation-source") return [];
|
|
1914
|
+
return [
|
|
1915
|
+
{
|
|
1916
|
+
pageNum,
|
|
1917
|
+
artifactRef,
|
|
1918
|
+
assetUrl: typeof item.assetUrl === "string" ? item.assetUrl : void 0,
|
|
1919
|
+
contentType,
|
|
1920
|
+
width: typeof item.width === "number" ? item.width : void 0,
|
|
1921
|
+
height: typeof item.height === "number" ? item.height : void 0,
|
|
1922
|
+
source
|
|
1923
|
+
}
|
|
1924
|
+
];
|
|
1925
|
+
});
|
|
1926
|
+
}
|
|
1927
|
+
function normalizeStorageKeyPrefix(value) {
|
|
1928
|
+
const normalized = normalizeStoragePath(value, { allowDotPrefix: false });
|
|
1929
|
+
if (!normalized) {
|
|
1930
|
+
throw new Error("storageAdapter keyPrefix must be a non-empty relative POSIX path.");
|
|
1931
|
+
}
|
|
1932
|
+
return normalized;
|
|
1933
|
+
}
|
|
1934
|
+
function normalizeResultAssetPath(value) {
|
|
1935
|
+
return normalizeStoragePath(value, { allowDotPrefix: true });
|
|
1936
|
+
}
|
|
1937
|
+
function normalizeStoragePath(value, options) {
|
|
1938
|
+
if (!value) return null;
|
|
1939
|
+
const trimmed = value.trim();
|
|
1940
|
+
if (trimmed.length === 0 || trimmed.includes("\0")) return null;
|
|
1941
|
+
if (trimmed.startsWith("/") || /^[A-Za-z]:/.test(trimmed)) return null;
|
|
1942
|
+
const normalized = options.allowDotPrefix ? trimmed.replaceAll("\\", "/").replace(/^\.\/+/, "") : trimmed.replaceAll("\\", "/");
|
|
1943
|
+
if (normalized.length === 0) return null;
|
|
1944
|
+
const parts = normalized.split("/");
|
|
1945
|
+
if (parts.some((part) => part.length === 0 || part === "." || part === "..")) return null;
|
|
1946
|
+
return parts.join("/");
|
|
1947
|
+
}
|
|
1948
|
+
function refreshStaticChunkCollections(result) {
|
|
1949
|
+
replaceStaticChunkCollection(
|
|
1950
|
+
result,
|
|
1951
|
+
"textChunks",
|
|
1952
|
+
result.chunks.filter((chunk) => chunk.type === "text")
|
|
1953
|
+
);
|
|
1954
|
+
replaceStaticChunkCollection(
|
|
1955
|
+
result,
|
|
1956
|
+
"imageChunks",
|
|
1957
|
+
result.chunks.filter((chunk) => chunk.type === "image")
|
|
1958
|
+
);
|
|
1959
|
+
replaceStaticChunkCollection(
|
|
1960
|
+
result,
|
|
1961
|
+
"tableChunks",
|
|
1962
|
+
result.chunks.filter((chunk) => chunk.type === "table")
|
|
1963
|
+
);
|
|
1964
|
+
replaceStaticChunkCollection(
|
|
1965
|
+
result,
|
|
1966
|
+
"pageChunks",
|
|
1967
|
+
result.chunks.filter((chunk) => chunk.type === "page")
|
|
1968
|
+
);
|
|
1969
|
+
}
|
|
1970
|
+
function replaceStaticChunkCollection(result, property, value) {
|
|
1971
|
+
const descriptor = Object.getOwnPropertyDescriptor(result, property);
|
|
1972
|
+
if (!descriptor || descriptor.get || descriptor.writable !== true) return;
|
|
1973
|
+
Object.defineProperty(result, property, {
|
|
1974
|
+
...descriptor,
|
|
1975
|
+
value
|
|
1976
|
+
});
|
|
1977
|
+
}
|
|
1978
|
+
function getImageContentType(filePath) {
|
|
1979
|
+
const extension = filePath.split(".").at(-1)?.toLowerCase();
|
|
1980
|
+
if (extension === "jpg" || extension === "jpeg") return "image/jpeg";
|
|
1981
|
+
if (extension === "png") return "image/png";
|
|
1982
|
+
if (extension === "webp") return "image/webp";
|
|
1983
|
+
if (extension === "gif") return "image/gif";
|
|
1984
|
+
if (extension === "svg") return "image/svg+xml";
|
|
1985
|
+
return defaultImageContentType;
|
|
1986
|
+
}
|
|
1987
|
+
function isRecord(value) {
|
|
1988
|
+
return typeof value === "object" && value !== null;
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1991
|
+
// 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$/;
|
|
1996
|
+
async function syncParseResultToParsedDocumentStorage(params) {
|
|
1997
|
+
const documentId = params.documentId ?? params.result.documentId ?? params.result.jobId;
|
|
1998
|
+
const revisionKey = params.revisionKey ?? params.result.jobId;
|
|
1999
|
+
const adapter = createParsedDocumentObjectStorageAdapter({
|
|
2000
|
+
storage: params.storage,
|
|
2001
|
+
documentId,
|
|
2002
|
+
revisionKey
|
|
2003
|
+
});
|
|
2004
|
+
const stored = await storeParseResultAssets(params.result, {
|
|
2005
|
+
adapter,
|
|
2006
|
+
keyPrefix: parsedStorageKeyPrefix,
|
|
2007
|
+
chunkPageSize: params.chunkPageSize,
|
|
2008
|
+
revisionKey
|
|
2009
|
+
});
|
|
2010
|
+
return {
|
|
2011
|
+
result: stored.result,
|
|
2012
|
+
snapshot: stored.snapshot,
|
|
2013
|
+
documentId,
|
|
2014
|
+
revisionKey
|
|
2015
|
+
};
|
|
2016
|
+
}
|
|
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
|
+
};
|
|
2023
|
+
}
|
|
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 };
|
|
2036
|
+
}
|
|
2037
|
+
if (storagePath === indexStoragePath) {
|
|
2038
|
+
return { key: input.key };
|
|
2039
|
+
}
|
|
2040
|
+
const chunkPageMatch = storagePath.match(chunkPagePathPattern);
|
|
2041
|
+
if (chunkPageMatch) {
|
|
2042
|
+
const page = JSON.parse(
|
|
2043
|
+
Buffer.from(input.body).toString("utf8")
|
|
2044
|
+
);
|
|
2045
|
+
await params.storage.writeChunkPage({
|
|
2046
|
+
documentId: params.documentId,
|
|
2047
|
+
revisionKey: params.revisionKey,
|
|
2048
|
+
page
|
|
2049
|
+
});
|
|
2050
|
+
return { key: input.key };
|
|
2051
|
+
}
|
|
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
|
+
});
|
|
2060
|
+
return {
|
|
2061
|
+
key: input.key,
|
|
2062
|
+
url: stored.url
|
|
2063
|
+
};
|
|
2064
|
+
}
|
|
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({
|
|
2071
|
+
documentId: params.documentId,
|
|
2072
|
+
revisionKey: params.revisionKey,
|
|
2073
|
+
sourcePath: storagePath
|
|
2074
|
+
});
|
|
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;
|
|
2084
|
+
}
|
|
2085
|
+
return params.storage.getAssetUrl({
|
|
2086
|
+
documentId: params.documentId,
|
|
2087
|
+
revisionKey: params.revisionKey,
|
|
2088
|
+
sourcePath: storagePath
|
|
2089
|
+
});
|
|
2090
|
+
}
|
|
2091
|
+
function stripParsedStorageKeyPrefix(key) {
|
|
2092
|
+
const prefix = `${parsedStorageKeyPrefix}/`;
|
|
2093
|
+
return key.startsWith(prefix) ? key.slice(prefix.length) : key;
|
|
2094
|
+
}
|
|
2095
|
+
|
|
1543
2096
|
// src/knowledge/local-store.ts
|
|
1544
2097
|
var import_crypto = require("crypto");
|
|
1545
2098
|
var import_os = __toESM(require("os"));
|
|
@@ -1734,7 +2287,7 @@ function countChunkTypes(result) {
|
|
|
1734
2287
|
counts[chunk.type] += 1;
|
|
1735
2288
|
return counts;
|
|
1736
2289
|
},
|
|
1737
|
-
{ text: 0, image: 0, table: 0 }
|
|
2290
|
+
{ text: 0, image: 0, table: 0, page: 0 }
|
|
1738
2291
|
);
|
|
1739
2292
|
}
|
|
1740
2293
|
function toLocalKnowledgeDocument(stored) {
|
|
@@ -1765,27 +2318,62 @@ function isMissingFileError2(error) {
|
|
|
1765
2318
|
// src/knowledge/knowledge.ts
|
|
1766
2319
|
var DEFAULT_READ_LIMIT = 12;
|
|
1767
2320
|
var MAX_READ_LIMIT = 40;
|
|
2321
|
+
var DEFAULT_PAGE_SIZE = 20;
|
|
2322
|
+
var MAX_PAGE_SIZE = 200;
|
|
1768
2323
|
var DEFAULT_GREP_LIMIT = 20;
|
|
1769
2324
|
var MAX_GREP_LIMIT = 50;
|
|
1770
2325
|
var DEFAULT_CONTEXT_CHARS = 80;
|
|
2326
|
+
var DEFAULT_REMOTE_SCAN_PAGE_SIZE = 100;
|
|
2327
|
+
var DEFAULT_MAX_SYNC_PAGES = 10;
|
|
2328
|
+
var DEFAULT_MAX_SYNC_ASSETS = 20;
|
|
2329
|
+
var DEFAULT_SYNC_DEADLINE_MS = 8e3;
|
|
2330
|
+
var DEFAULT_GREP_MAX_PAGES = 50;
|
|
2331
|
+
var DEFAULT_GREP_DEADLINE_MS = 8e3;
|
|
2332
|
+
var DEFAULT_OUTLINE_MAX_PAGES = 50;
|
|
2333
|
+
var DEFAULT_OUTLINE_DEADLINE_MS = 8e3;
|
|
1771
2334
|
var SAFE_LOCAL_DOCUMENT_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
1772
2335
|
var REMOTE_DOCUMENT_ID_PATTERN = /^doc[_-]/;
|
|
1773
2336
|
var Knowledge = class _Knowledge {
|
|
1774
2337
|
client;
|
|
1775
2338
|
store;
|
|
2339
|
+
cacheDirectory;
|
|
2340
|
+
parsedStorageConfig;
|
|
1776
2341
|
constructor(client, options) {
|
|
1777
2342
|
this.client = client;
|
|
2343
|
+
this.cacheDirectory = options?.cacheDirectory;
|
|
2344
|
+
this.parsedStorageConfig = options?.parsedStorage;
|
|
1778
2345
|
this.store = new LocalKnowledgeStore(options?.cacheDirectory);
|
|
1779
2346
|
}
|
|
1780
2347
|
withCacheDirectory(cacheDirectory) {
|
|
1781
|
-
return new _Knowledge(this.client, {
|
|
2348
|
+
return new _Knowledge(this.client, {
|
|
2349
|
+
cacheDirectory,
|
|
2350
|
+
parsedStorage: this.parsedStorageConfig
|
|
2351
|
+
});
|
|
1782
2352
|
}
|
|
1783
|
-
|
|
1784
|
-
|
|
2353
|
+
withParsedStorage(parsedStorage) {
|
|
2354
|
+
return new _Knowledge(this.client, {
|
|
2355
|
+
cacheDirectory: this.cacheDirectory,
|
|
2356
|
+
parsedStorage
|
|
2357
|
+
});
|
|
2358
|
+
}
|
|
2359
|
+
async parseToLocalCache(params) {
|
|
2360
|
+
const loadedResult = params.storageAdapter ? await this.parseWithoutClientStorageAdapter(params) : await this.client.parse(params);
|
|
2361
|
+
const storedAssets = await storeParseResultAssets(loadedResult, params.storageAdapter);
|
|
2362
|
+
const syncedStorage = await this.syncParseResultToConfiguredStorage(storedAssets.result);
|
|
2363
|
+
const result = syncedStorage.result;
|
|
1785
2364
|
const document = await this.store.saveResult(result, {
|
|
1786
2365
|
localDocumentId: params.localDocumentId
|
|
1787
2366
|
});
|
|
1788
|
-
return {
|
|
2367
|
+
return {
|
|
2368
|
+
document,
|
|
2369
|
+
result,
|
|
2370
|
+
assetUrlsByFilePath: storedAssets.assetUrlsByFilePath,
|
|
2371
|
+
parsedSnapshot: storedAssets.snapshot
|
|
2372
|
+
};
|
|
2373
|
+
}
|
|
2374
|
+
/** @deprecated Use parseToLocalCache for local cache imports or the top-level client.parse for server-safe parsing. */
|
|
2375
|
+
async parse(params) {
|
|
2376
|
+
return this.parseToLocalCache(params);
|
|
1789
2377
|
}
|
|
1790
2378
|
async startParse(params) {
|
|
1791
2379
|
const job = await this.client.startParse(params);
|
|
@@ -1816,14 +2404,100 @@ var Knowledge = class _Knowledge {
|
|
|
1816
2404
|
results
|
|
1817
2405
|
};
|
|
1818
2406
|
}
|
|
1819
|
-
async
|
|
1820
|
-
const
|
|
2407
|
+
async loadJobResult(params) {
|
|
2408
|
+
const loadedResult = await this.client.jobs.load(params.jobId, {
|
|
1821
2409
|
verifyChecksum: params.verifyChecksum
|
|
1822
2410
|
});
|
|
2411
|
+
const storedAssets = await storeParseResultAssets(loadedResult, params.storageAdapter);
|
|
2412
|
+
const syncedStorage = await this.syncParseResultToConfiguredStorage(storedAssets.result);
|
|
2413
|
+
const result = syncedStorage.result;
|
|
2414
|
+
return {
|
|
2415
|
+
result,
|
|
2416
|
+
assetUrlsByFilePath: storedAssets.assetUrlsByFilePath,
|
|
2417
|
+
parsedSnapshot: syncedStorage.snapshot ?? storedAssets.snapshot
|
|
2418
|
+
};
|
|
2419
|
+
}
|
|
2420
|
+
async importJobResult(params) {
|
|
2421
|
+
const stored = await this.loadJobResult(params);
|
|
2422
|
+
const result = stored.result;
|
|
1823
2423
|
const document = await this.store.saveResult(result, {
|
|
1824
2424
|
localDocumentId: params.localDocumentId
|
|
1825
2425
|
});
|
|
1826
|
-
return {
|
|
2426
|
+
return {
|
|
2427
|
+
document,
|
|
2428
|
+
result,
|
|
2429
|
+
assetUrlsByFilePath: stored.assetUrlsByFilePath,
|
|
2430
|
+
parsedSnapshot: stored.parsedSnapshot
|
|
2431
|
+
};
|
|
2432
|
+
}
|
|
2433
|
+
/** @deprecated Use importJobResult for local cache imports or loadJobResult for server-safe loads. */
|
|
2434
|
+
async cacheJobResult(params) {
|
|
2435
|
+
return this.importJobResult(params);
|
|
2436
|
+
}
|
|
2437
|
+
async syncParsedDocument(params) {
|
|
2438
|
+
const normalized = normalizeDocumentReference(params);
|
|
2439
|
+
const parsedStorageConfig = this.requireParsedStorageConfig();
|
|
2440
|
+
if (normalized.documentId) {
|
|
2441
|
+
return this.syncRemoteDocumentToParsedStorage({
|
|
2442
|
+
documentId: normalized.documentId,
|
|
2443
|
+
revisionKey: params.revisionKey,
|
|
2444
|
+
parsedStorageConfig
|
|
2445
|
+
});
|
|
2446
|
+
}
|
|
2447
|
+
if (normalized.jobId) {
|
|
2448
|
+
const loadedResult = await this.client.jobs.load(normalized.jobId);
|
|
2449
|
+
const synced2 = await syncParseResultToParsedDocumentStorage({
|
|
2450
|
+
result: loadedResult,
|
|
2451
|
+
storage: parsedStorageConfig.storage,
|
|
2452
|
+
documentId: loadedResult.documentId ?? normalized.localDocumentId ?? normalized.jobId,
|
|
2453
|
+
revisionKey: params.revisionKey ?? normalized.jobId,
|
|
2454
|
+
chunkPageSize: parsedStorageConfig.limits?.chunkPageSize
|
|
2455
|
+
});
|
|
2456
|
+
return {
|
|
2457
|
+
documentId: synced2.documentId,
|
|
2458
|
+
revisionKey: synced2.revisionKey,
|
|
2459
|
+
completed: true,
|
|
2460
|
+
manifest: synced2.snapshot?.manifest
|
|
2461
|
+
};
|
|
2462
|
+
}
|
|
2463
|
+
if (!normalized.localDocumentId) {
|
|
2464
|
+
throw new ValidationError("localDocumentId, documentId, or jobId is required");
|
|
2465
|
+
}
|
|
2466
|
+
const { result } = await this.store.loadResult(normalized.localDocumentId);
|
|
2467
|
+
const synced = await syncParseResultToParsedDocumentStorage({
|
|
2468
|
+
result,
|
|
2469
|
+
storage: parsedStorageConfig.storage,
|
|
2470
|
+
documentId: result.documentId ?? normalized.localDocumentId,
|
|
2471
|
+
revisionKey: params.revisionKey ?? result.jobId,
|
|
2472
|
+
chunkPageSize: parsedStorageConfig.limits?.chunkPageSize
|
|
2473
|
+
});
|
|
2474
|
+
return {
|
|
2475
|
+
documentId: synced.documentId,
|
|
2476
|
+
revisionKey: synced.revisionKey,
|
|
2477
|
+
completed: true,
|
|
2478
|
+
manifest: synced.snapshot?.manifest
|
|
2479
|
+
};
|
|
2480
|
+
}
|
|
2481
|
+
async syncParseResultToConfiguredStorage(result) {
|
|
2482
|
+
const parsedStorageConfig = this.parsedStorageConfig;
|
|
2483
|
+
if (!parsedStorageConfig) {
|
|
2484
|
+
return { result };
|
|
2485
|
+
}
|
|
2486
|
+
const synced = await syncParseResultToParsedDocumentStorage({
|
|
2487
|
+
result,
|
|
2488
|
+
storage: parsedStorageConfig.storage,
|
|
2489
|
+
chunkPageSize: parsedStorageConfig.limits?.chunkPageSize
|
|
2490
|
+
});
|
|
2491
|
+
return {
|
|
2492
|
+
result: synced.result,
|
|
2493
|
+
snapshot: synced.snapshot
|
|
2494
|
+
};
|
|
2495
|
+
}
|
|
2496
|
+
async parseWithoutClientStorageAdapter(params) {
|
|
2497
|
+
const parseParams = { ...params };
|
|
2498
|
+
delete parseParams.localDocumentId;
|
|
2499
|
+
delete parseParams.storageAdapter;
|
|
2500
|
+
return this.client.parse(parseParams);
|
|
1827
2501
|
}
|
|
1828
2502
|
async cacheDocument(params) {
|
|
1829
2503
|
if (!params.documentId) {
|
|
@@ -1833,7 +2507,7 @@ var Knowledge = class _Knowledge {
|
|
|
1833
2507
|
params.documentId
|
|
1834
2508
|
);
|
|
1835
2509
|
const jobId = await this.getPublishedDocumentJobId(params.documentId);
|
|
1836
|
-
return this.
|
|
2510
|
+
return this.importJobResult({
|
|
1837
2511
|
jobId,
|
|
1838
2512
|
localDocumentId: params.localDocumentId ?? existing?.localDocumentId ?? createLocalDocumentIdForRemote(params.documentId)
|
|
1839
2513
|
});
|
|
@@ -1870,7 +2544,7 @@ var Knowledge = class _Knowledge {
|
|
|
1870
2544
|
};
|
|
1871
2545
|
}
|
|
1872
2546
|
try {
|
|
1873
|
-
const cached = await this.
|
|
2547
|
+
const cached = await this.importJobResult({
|
|
1874
2548
|
jobId,
|
|
1875
2549
|
localDocumentId: trackedJob.localDocumentId
|
|
1876
2550
|
});
|
|
@@ -1895,6 +2569,13 @@ var Knowledge = class _Knowledge {
|
|
|
1895
2569
|
return this.store.listDocuments();
|
|
1896
2570
|
}
|
|
1897
2571
|
async getDocumentOutline(reference) {
|
|
2572
|
+
const normalized = normalizeDocumentReference(reference);
|
|
2573
|
+
if (normalized.documentId) {
|
|
2574
|
+
return this.getRemoteDocumentOutline(normalized.documentId, normalized.revisionKey);
|
|
2575
|
+
}
|
|
2576
|
+
if (normalized.localDocumentId && looksLikeRemoteDocumentId(normalized.localDocumentId) && !await this.store.getDocument(normalized.localDocumentId)) {
|
|
2577
|
+
return this.getRemoteDocumentOutline(normalized.localDocumentId, normalized.revisionKey);
|
|
2578
|
+
}
|
|
1898
2579
|
const { document, result } = await this.loadReadableResult(reference);
|
|
1899
2580
|
const chunks = indexChunks(result);
|
|
1900
2581
|
const sections = buildFlatSections(result, chunks);
|
|
@@ -1910,6 +2591,14 @@ var Knowledge = class _Knowledge {
|
|
|
1910
2591
|
};
|
|
1911
2592
|
}
|
|
1912
2593
|
async readChunks(params) {
|
|
2594
|
+
validateReadParams(params);
|
|
2595
|
+
const normalized = normalizeDocumentReference(params);
|
|
2596
|
+
if (normalized.documentId) {
|
|
2597
|
+
return this.readRemoteDocumentChunks(normalized.documentId, params);
|
|
2598
|
+
}
|
|
2599
|
+
if (normalized.localDocumentId && looksLikeRemoteDocumentId(normalized.localDocumentId) && !await this.store.getDocument(normalized.localDocumentId)) {
|
|
2600
|
+
return this.readRemoteDocumentChunks(normalized.localDocumentId, params);
|
|
2601
|
+
}
|
|
1913
2602
|
const { document, result } = await this.loadReadableResult(params);
|
|
1914
2603
|
const limit = clampLimit(params.limit, DEFAULT_READ_LIMIT, MAX_READ_LIMIT);
|
|
1915
2604
|
const chunks = indexChunks(result).filter((chunk) => matchesReadScope(chunk, params));
|
|
@@ -1926,6 +2615,13 @@ var Knowledge = class _Knowledge {
|
|
|
1926
2615
|
if (!params.pattern) {
|
|
1927
2616
|
throw new ValidationError("pattern is required");
|
|
1928
2617
|
}
|
|
2618
|
+
const normalized = normalizeDocumentReference(params);
|
|
2619
|
+
if (normalized.documentId) {
|
|
2620
|
+
return this.grepRemoteDocumentChunks(normalized.documentId, params);
|
|
2621
|
+
}
|
|
2622
|
+
if (normalized.localDocumentId && looksLikeRemoteDocumentId(normalized.localDocumentId) && !await this.store.getDocument(normalized.localDocumentId)) {
|
|
2623
|
+
return this.grepRemoteDocumentChunks(normalized.localDocumentId, params);
|
|
2624
|
+
}
|
|
1929
2625
|
const { document, result } = await this.loadReadableResult(params);
|
|
1930
2626
|
const maxResults = clampLimit(params.maxResults, DEFAULT_GREP_LIMIT, MAX_GREP_LIMIT);
|
|
1931
2627
|
const contextChars = params.contextChars ?? DEFAULT_CONTEXT_CHARS;
|
|
@@ -2005,7 +2701,7 @@ var Knowledge = class _Knowledge {
|
|
|
2005
2701
|
});
|
|
2006
2702
|
}
|
|
2007
2703
|
if (normalized.jobId) {
|
|
2008
|
-
return this.
|
|
2704
|
+
return this.importJobResult({
|
|
2009
2705
|
jobId: normalized.jobId,
|
|
2010
2706
|
localDocumentId: normalized.localDocumentId
|
|
2011
2707
|
});
|
|
@@ -2025,24 +2721,670 @@ var Knowledge = class _Knowledge {
|
|
|
2025
2721
|
}
|
|
2026
2722
|
throw new Error(`Local Knowhere document not found: ${normalized.localDocumentId}`);
|
|
2027
2723
|
}
|
|
2028
|
-
async
|
|
2029
|
-
const
|
|
2030
|
-
|
|
2724
|
+
async readRemoteDocumentChunks(documentId, params) {
|
|
2725
|
+
const explicitRevisionKey = params.revisionKey ?? params.jobId;
|
|
2726
|
+
if (explicitRevisionKey) {
|
|
2727
|
+
const stored2 = await this.tryReadChunksFromParsedStorage({
|
|
2728
|
+
documentId,
|
|
2729
|
+
revisionKey: explicitRevisionKey,
|
|
2730
|
+
params
|
|
2731
|
+
});
|
|
2732
|
+
if (stored2) {
|
|
2733
|
+
return stored2;
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
if (hasScanReadFilters(params)) {
|
|
2737
|
+
return this.scanRemoteDocumentChunks(documentId, params);
|
|
2738
|
+
}
|
|
2739
|
+
const pageParams = getReadPageParams(params);
|
|
2740
|
+
const remotePage = await this.client.documents.listChunks(documentId, {
|
|
2741
|
+
page: pageParams.page,
|
|
2742
|
+
pageSize: pageParams.pageSize,
|
|
2743
|
+
chunkType: params.chunkType,
|
|
2744
|
+
includeAssetUrls: shouldRequestRemoteAssetUrls(
|
|
2745
|
+
params.assetUrlPolicy,
|
|
2746
|
+
this.parsedStorageConfig
|
|
2747
|
+
)
|
|
2748
|
+
});
|
|
2749
|
+
const revisionKey = getRemoteRevisionKey(remotePage);
|
|
2750
|
+
const stored = await this.tryReadChunksFromParsedStorage({
|
|
2751
|
+
documentId,
|
|
2752
|
+
revisionKey,
|
|
2753
|
+
params
|
|
2754
|
+
});
|
|
2755
|
+
if (stored) {
|
|
2756
|
+
return stored;
|
|
2757
|
+
}
|
|
2758
|
+
const chunks = await this.toRemoteReadChunks({
|
|
2759
|
+
documentId,
|
|
2760
|
+
revisionKey,
|
|
2761
|
+
chunks: remotePage.chunks,
|
|
2762
|
+
assetUrlPolicy: params.assetUrlPolicy
|
|
2763
|
+
});
|
|
2764
|
+
this.scheduleParsedStorageSync(documentId, revisionKey);
|
|
2765
|
+
return {
|
|
2766
|
+
document: createRemoteKnowledgeDocument({
|
|
2767
|
+
documentId,
|
|
2768
|
+
response: remotePage,
|
|
2769
|
+
revisionKey
|
|
2770
|
+
}),
|
|
2771
|
+
chunks,
|
|
2772
|
+
page: remotePage.pagination.page,
|
|
2773
|
+
pageSize: remotePage.pagination.pageSize,
|
|
2774
|
+
totalChunks: remotePage.pagination.total,
|
|
2775
|
+
totalPages: remotePage.pagination.totalPages
|
|
2776
|
+
};
|
|
2031
2777
|
}
|
|
2032
|
-
async
|
|
2033
|
-
const
|
|
2778
|
+
async scanRemoteDocumentChunks(documentId, params) {
|
|
2779
|
+
const explicitRevisionKey = params.revisionKey ?? params.jobId;
|
|
2780
|
+
if (explicitRevisionKey) {
|
|
2781
|
+
const stored2 = await this.tryReadChunksFromParsedStorage({
|
|
2782
|
+
documentId,
|
|
2783
|
+
revisionKey: explicitRevisionKey,
|
|
2784
|
+
params
|
|
2785
|
+
});
|
|
2786
|
+
if (stored2) {
|
|
2787
|
+
return stored2;
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2790
|
+
const limit = clampLimit(params.limit, DEFAULT_READ_LIMIT, MAX_READ_LIMIT);
|
|
2791
|
+
const limits = getParsedStorageLimits(this.parsedStorageConfig?.limits);
|
|
2792
|
+
const firstPage = await this.client.documents.listChunks(documentId, {
|
|
2034
2793
|
page: 1,
|
|
2035
|
-
pageSize:
|
|
2794
|
+
pageSize: limits.remotePageSize,
|
|
2795
|
+
chunkType: params.chunkType,
|
|
2796
|
+
includeAssetUrls: shouldRequestRemoteAssetUrls(
|
|
2797
|
+
params.assetUrlPolicy,
|
|
2798
|
+
this.parsedStorageConfig
|
|
2799
|
+
)
|
|
2036
2800
|
});
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2801
|
+
const revisionKey = getRemoteRevisionKey(firstPage);
|
|
2802
|
+
const stored = await this.tryReadChunksFromParsedStorage({
|
|
2803
|
+
documentId,
|
|
2804
|
+
revisionKey,
|
|
2805
|
+
params
|
|
2806
|
+
});
|
|
2807
|
+
if (stored) {
|
|
2808
|
+
return stored;
|
|
2041
2809
|
}
|
|
2042
|
-
|
|
2810
|
+
const selected = [];
|
|
2811
|
+
let scannedPages = 0;
|
|
2812
|
+
let page = 1;
|
|
2813
|
+
let response = firstPage;
|
|
2814
|
+
const startedAt = Date.now();
|
|
2815
|
+
while (true) {
|
|
2816
|
+
scannedPages += 1;
|
|
2817
|
+
selected.push(...response.chunks.filter((chunk) => matchesRemoteReadScope(chunk, params)));
|
|
2818
|
+
if (selected.length >= limit || response.pagination.page >= response.pagination.totalPages || scannedPages >= limits.outlineMaxPages || Date.now() - startedAt >= limits.outlineDeadlineMs) {
|
|
2819
|
+
break;
|
|
2820
|
+
}
|
|
2821
|
+
page += 1;
|
|
2822
|
+
response = await this.client.documents.listChunks(documentId, {
|
|
2823
|
+
page,
|
|
2824
|
+
pageSize: limits.remotePageSize,
|
|
2825
|
+
chunkType: params.chunkType,
|
|
2826
|
+
includeAssetUrls: shouldRequestRemoteAssetUrls(
|
|
2827
|
+
params.assetUrlPolicy,
|
|
2828
|
+
this.parsedStorageConfig
|
|
2829
|
+
)
|
|
2830
|
+
});
|
|
2831
|
+
}
|
|
2832
|
+
const chunks = await this.toRemoteReadChunks({
|
|
2833
|
+
documentId,
|
|
2834
|
+
revisionKey,
|
|
2835
|
+
chunks: selected.slice(0, limit),
|
|
2836
|
+
assetUrlPolicy: params.assetUrlPolicy
|
|
2837
|
+
});
|
|
2838
|
+
this.scheduleParsedStorageSync(documentId, revisionKey);
|
|
2839
|
+
return {
|
|
2840
|
+
document: createRemoteKnowledgeDocument({
|
|
2841
|
+
documentId,
|
|
2842
|
+
response: firstPage,
|
|
2843
|
+
revisionKey
|
|
2844
|
+
}),
|
|
2845
|
+
chunks,
|
|
2846
|
+
nextChunk: selected.length > limit ? toChunkPosition(selected[limit]) : void 0,
|
|
2847
|
+
totalChunks: firstPage.pagination.total,
|
|
2848
|
+
totalPages: firstPage.pagination.totalPages
|
|
2849
|
+
};
|
|
2043
2850
|
}
|
|
2044
|
-
|
|
2045
|
-
|
|
2851
|
+
async grepRemoteDocumentChunks(documentId, params) {
|
|
2852
|
+
const explicitRevisionKey = params.revisionKey ?? params.jobId;
|
|
2853
|
+
if (explicitRevisionKey && !params.continuationCursor) {
|
|
2854
|
+
const stored2 = await this.tryGrepChunksFromParsedStorage({
|
|
2855
|
+
documentId,
|
|
2856
|
+
revisionKey: explicitRevisionKey,
|
|
2857
|
+
params
|
|
2858
|
+
});
|
|
2859
|
+
if (stored2) {
|
|
2860
|
+
return stored2;
|
|
2861
|
+
}
|
|
2862
|
+
}
|
|
2863
|
+
const maxResults = clampLimit(params.maxResults, DEFAULT_GREP_LIMIT, MAX_GREP_LIMIT);
|
|
2864
|
+
const contextChars = params.contextChars ?? DEFAULT_CONTEXT_CHARS;
|
|
2865
|
+
const matcher = createMatcher(params);
|
|
2866
|
+
const limits = getParsedStorageLimits(this.parsedStorageConfig?.limits);
|
|
2867
|
+
const cursor = parseContinuationCursor(params.continuationCursor);
|
|
2868
|
+
const startPage = cursor?.documentId === documentId ? cursor.nextPage : 1;
|
|
2869
|
+
const firstPage = await this.client.documents.listChunks(documentId, {
|
|
2870
|
+
page: startPage,
|
|
2871
|
+
pageSize: limits.remotePageSize,
|
|
2872
|
+
chunkType: params.chunkType,
|
|
2873
|
+
includeAssetUrls: false
|
|
2874
|
+
});
|
|
2875
|
+
const revisionKey = getRemoteRevisionKey(firstPage);
|
|
2876
|
+
const stored = startPage === 1 ? await this.tryGrepChunksFromParsedStorage({
|
|
2877
|
+
documentId,
|
|
2878
|
+
revisionKey,
|
|
2879
|
+
params
|
|
2880
|
+
}) : null;
|
|
2881
|
+
if (stored) {
|
|
2882
|
+
return stored;
|
|
2883
|
+
}
|
|
2884
|
+
const matches = [];
|
|
2885
|
+
let scannedChunks = 0;
|
|
2886
|
+
let scannedPages = 0;
|
|
2887
|
+
let response = firstPage;
|
|
2888
|
+
let page = startPage;
|
|
2889
|
+
const startedAt = Date.now();
|
|
2890
|
+
while (true) {
|
|
2891
|
+
scannedPages += 1;
|
|
2892
|
+
for (const [chunkIndex, chunk] of response.chunks.entries()) {
|
|
2893
|
+
if (response.pagination.page === startPage && cursor?.nextChunkIndex !== void 0 && chunkIndex < cursor.nextChunkIndex) {
|
|
2894
|
+
continue;
|
|
2895
|
+
}
|
|
2896
|
+
if (!matchesGrepScope(toIndexedRemoteChunk(chunk), params)) {
|
|
2897
|
+
continue;
|
|
2898
|
+
}
|
|
2899
|
+
scannedChunks += 1;
|
|
2900
|
+
const chunkMatches = matcher(chunk.content ?? "");
|
|
2901
|
+
for (const [matchIndex, match] of chunkMatches.entries()) {
|
|
2902
|
+
if (response.pagination.page === startPage && cursor?.nextChunkIndex === chunkIndex && cursor.nextMatchIndex !== void 0 && matchIndex < cursor.nextMatchIndex) {
|
|
2903
|
+
continue;
|
|
2904
|
+
}
|
|
2905
|
+
matches.push({
|
|
2906
|
+
position: toChunkPosition(chunk),
|
|
2907
|
+
chunkId: chunk.chunkId,
|
|
2908
|
+
chunkType: chunk.chunkType,
|
|
2909
|
+
sectionPath: chunk.sectionPath ?? "",
|
|
2910
|
+
sourceChunkPath: chunk.sourceChunkPath ?? chunk.sectionPath ?? "",
|
|
2911
|
+
filePath: chunk.filePath ?? void 0,
|
|
2912
|
+
startOffset: match.startOffset,
|
|
2913
|
+
endOffset: match.endOffset,
|
|
2914
|
+
snippet: buildSnippet(
|
|
2915
|
+
chunk.content ?? "",
|
|
2916
|
+
match.startOffset,
|
|
2917
|
+
match.endOffset,
|
|
2918
|
+
contextChars
|
|
2919
|
+
)
|
|
2920
|
+
});
|
|
2921
|
+
if (matches.length >= maxResults) {
|
|
2922
|
+
const continuationCursor = createGrepContinuationCursor({
|
|
2923
|
+
documentId,
|
|
2924
|
+
revisionKey,
|
|
2925
|
+
response,
|
|
2926
|
+
chunkIndex,
|
|
2927
|
+
matchIndex,
|
|
2928
|
+
chunkMatchCount: chunkMatches.length
|
|
2929
|
+
});
|
|
2930
|
+
this.scheduleParsedStorageSync(documentId, revisionKey);
|
|
2931
|
+
return {
|
|
2932
|
+
document: createRemoteKnowledgeDocument({
|
|
2933
|
+
documentId,
|
|
2934
|
+
response: firstPage,
|
|
2935
|
+
revisionKey
|
|
2936
|
+
}),
|
|
2937
|
+
matches,
|
|
2938
|
+
scannedChunks,
|
|
2939
|
+
truncated: continuationCursor !== void 0,
|
|
2940
|
+
continuationCursor
|
|
2941
|
+
};
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
const shouldStop = response.pagination.page >= response.pagination.totalPages || scannedPages >= limits.grepMaxPages || Date.now() - startedAt >= limits.grepDeadlineMs;
|
|
2946
|
+
if (shouldStop) {
|
|
2947
|
+
const truncated = response.pagination.page < response.pagination.totalPages;
|
|
2948
|
+
this.scheduleParsedStorageSync(documentId, revisionKey);
|
|
2949
|
+
return {
|
|
2950
|
+
document: createRemoteKnowledgeDocument({
|
|
2951
|
+
documentId,
|
|
2952
|
+
response: firstPage,
|
|
2953
|
+
revisionKey
|
|
2954
|
+
}),
|
|
2955
|
+
matches,
|
|
2956
|
+
scannedChunks,
|
|
2957
|
+
truncated,
|
|
2958
|
+
continuationCursor: truncated ? createContinuationCursor({
|
|
2959
|
+
documentId,
|
|
2960
|
+
revisionKey,
|
|
2961
|
+
nextPage: response.pagination.page + 1
|
|
2962
|
+
}) : void 0
|
|
2963
|
+
};
|
|
2964
|
+
}
|
|
2965
|
+
page += 1;
|
|
2966
|
+
response = await this.client.documents.listChunks(documentId, {
|
|
2967
|
+
page,
|
|
2968
|
+
pageSize: limits.remotePageSize,
|
|
2969
|
+
chunkType: params.chunkType,
|
|
2970
|
+
includeAssetUrls: false
|
|
2971
|
+
});
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
async getRemoteDocumentOutline(documentId, revisionKeyOverride) {
|
|
2975
|
+
if (revisionKeyOverride) {
|
|
2976
|
+
const stored2 = await this.tryReadOutlineFromParsedStorage(documentId, revisionKeyOverride);
|
|
2977
|
+
if (stored2) {
|
|
2978
|
+
return stored2;
|
|
2979
|
+
}
|
|
2980
|
+
}
|
|
2981
|
+
const limits = getParsedStorageLimits(this.parsedStorageConfig?.limits);
|
|
2982
|
+
const firstPage = await this.client.documents.listChunks(documentId, {
|
|
2983
|
+
page: 1,
|
|
2984
|
+
pageSize: limits.remotePageSize,
|
|
2985
|
+
includeAssetUrls: false
|
|
2986
|
+
});
|
|
2987
|
+
const revisionKey = getRemoteRevisionKey(firstPage);
|
|
2988
|
+
const stored = await this.tryReadOutlineFromParsedStorage(documentId, revisionKey);
|
|
2989
|
+
if (stored) {
|
|
2990
|
+
return stored;
|
|
2991
|
+
}
|
|
2992
|
+
const chunks = [];
|
|
2993
|
+
let page = 1;
|
|
2994
|
+
let response = firstPage;
|
|
2995
|
+
let scannedPages = 0;
|
|
2996
|
+
const startedAt = Date.now();
|
|
2997
|
+
while (true) {
|
|
2998
|
+
scannedPages += 1;
|
|
2999
|
+
chunks.push(...response.chunks.map(toIndexedRemoteChunk));
|
|
3000
|
+
if (response.pagination.page >= response.pagination.totalPages || scannedPages >= limits.outlineMaxPages || Date.now() - startedAt >= limits.outlineDeadlineMs) {
|
|
3001
|
+
break;
|
|
3002
|
+
}
|
|
3003
|
+
page += 1;
|
|
3004
|
+
response = await this.client.documents.listChunks(documentId, {
|
|
3005
|
+
page,
|
|
3006
|
+
pageSize: limits.remotePageSize,
|
|
3007
|
+
includeAssetUrls: false
|
|
3008
|
+
});
|
|
3009
|
+
}
|
|
3010
|
+
const truncated = response.pagination.page < response.pagination.totalPages;
|
|
3011
|
+
const sections = buildFlatSectionsFromIndexedChunks(chunks);
|
|
3012
|
+
this.scheduleParsedStorageSync(documentId, revisionKey);
|
|
3013
|
+
return {
|
|
3014
|
+
document: createRemoteKnowledgeDocument({
|
|
3015
|
+
documentId,
|
|
3016
|
+
response: firstPage,
|
|
3017
|
+
revisionKey,
|
|
3018
|
+
typeCounts: countIndexedTypes(chunks)
|
|
3019
|
+
}),
|
|
3020
|
+
totalChunks: firstPage.pagination.total,
|
|
3021
|
+
typeCounts: countIndexedTypes(chunks),
|
|
3022
|
+
sections,
|
|
3023
|
+
sectionTree: nestSections(sections),
|
|
3024
|
+
truncated,
|
|
3025
|
+
continuationCursor: truncated ? createContinuationCursor({
|
|
3026
|
+
documentId,
|
|
3027
|
+
revisionKey,
|
|
3028
|
+
nextPage: response.pagination.page + 1
|
|
3029
|
+
}) : void 0
|
|
3030
|
+
};
|
|
3031
|
+
}
|
|
3032
|
+
async tryReadChunksFromParsedStorage(params) {
|
|
3033
|
+
const parsedStorageConfig = this.parsedStorageConfig;
|
|
3034
|
+
if (!parsedStorageConfig) {
|
|
3035
|
+
return null;
|
|
3036
|
+
}
|
|
3037
|
+
const manifest = await this.readFreshParsedStorageManifest(
|
|
3038
|
+
params.documentId,
|
|
3039
|
+
params.revisionKey
|
|
3040
|
+
);
|
|
3041
|
+
if (!manifest) {
|
|
3042
|
+
return null;
|
|
3043
|
+
}
|
|
3044
|
+
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));
|
|
3055
|
+
const selected = hasScanReadFilters(params.params) ? selectReadWindow(
|
|
3056
|
+
scopedChunks,
|
|
3057
|
+
params.params,
|
|
3058
|
+
clampLimit(params.params.limit, DEFAULT_READ_LIMIT, MAX_READ_LIMIT)
|
|
3059
|
+
) : scopedChunks.slice(
|
|
3060
|
+
(pageParams.page - 1) * pageParams.pageSize,
|
|
3061
|
+
pageParams.page * pageParams.pageSize
|
|
3062
|
+
);
|
|
3063
|
+
const visibleChunks = applyAssetUrlPolicyToReadChunks(
|
|
3064
|
+
selected.map(toReadChunk),
|
|
3065
|
+
params.params.assetUrlPolicy
|
|
3066
|
+
);
|
|
3067
|
+
const totalChunks = scopedChunks.length;
|
|
3068
|
+
return {
|
|
3069
|
+
document: createStoredKnowledgeDocument({
|
|
3070
|
+
documentId: params.documentId,
|
|
3071
|
+
manifest,
|
|
3072
|
+
revisionKey: params.revisionKey,
|
|
3073
|
+
typeCounts: countIndexedTypes(indexedChunks)
|
|
3074
|
+
}),
|
|
3075
|
+
chunks: visibleChunks,
|
|
3076
|
+
page: hasScanReadFilters(params.params) ? void 0 : pageParams.page,
|
|
3077
|
+
pageSize: hasScanReadFilters(params.params) ? void 0 : pageParams.pageSize,
|
|
3078
|
+
totalChunks,
|
|
3079
|
+
totalPages: Math.max(1, Math.ceil(totalChunks / pageParams.pageSize)),
|
|
3080
|
+
nextChunk: getNextChunkPosition(scopedChunks, selected)
|
|
3081
|
+
};
|
|
3082
|
+
}
|
|
3083
|
+
async tryGrepChunksFromParsedStorage(params) {
|
|
3084
|
+
const parsedStorageConfig = this.parsedStorageConfig;
|
|
3085
|
+
if (!parsedStorageConfig) {
|
|
3086
|
+
return null;
|
|
3087
|
+
}
|
|
3088
|
+
const manifest = await this.readFreshParsedStorageManifest(
|
|
3089
|
+
params.documentId,
|
|
3090
|
+
params.revisionKey
|
|
3091
|
+
);
|
|
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
|
+
}
|
|
3104
|
+
const maxResults = clampLimit(params.params.maxResults, DEFAULT_GREP_LIMIT, MAX_GREP_LIMIT);
|
|
3105
|
+
const contextChars = params.params.contextChars ?? DEFAULT_CONTEXT_CHARS;
|
|
3106
|
+
const matcher = createMatcher(params.params);
|
|
3107
|
+
const scopedChunks = indexedChunks.filter((chunk) => matchesGrepScope(chunk, params.params));
|
|
3108
|
+
const matches = [];
|
|
3109
|
+
let scannedChunks = 0;
|
|
3110
|
+
for (const chunk of scopedChunks) {
|
|
3111
|
+
scannedChunks += 1;
|
|
3112
|
+
for (const match of matcher(chunk.content)) {
|
|
3113
|
+
matches.push({
|
|
3114
|
+
position: chunk.position,
|
|
3115
|
+
chunkId: chunk.chunkId,
|
|
3116
|
+
chunkType: chunk.chunkType,
|
|
3117
|
+
sectionPath: chunk.sectionPath,
|
|
3118
|
+
sourceChunkPath: chunk.sourceChunkPath,
|
|
3119
|
+
filePath: chunk.filePath,
|
|
3120
|
+
startOffset: match.startOffset,
|
|
3121
|
+
endOffset: match.endOffset,
|
|
3122
|
+
snippet: buildSnippet(chunk.content, match.startOffset, match.endOffset, contextChars)
|
|
3123
|
+
});
|
|
3124
|
+
if (matches.length >= maxResults) {
|
|
3125
|
+
return {
|
|
3126
|
+
document: createStoredKnowledgeDocument({
|
|
3127
|
+
documentId: params.documentId,
|
|
3128
|
+
manifest,
|
|
3129
|
+
revisionKey: params.revisionKey,
|
|
3130
|
+
typeCounts: countIndexedTypes(indexedChunks)
|
|
3131
|
+
}),
|
|
3132
|
+
matches,
|
|
3133
|
+
scannedChunks,
|
|
3134
|
+
truncated: true
|
|
3135
|
+
};
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
3139
|
+
return {
|
|
3140
|
+
document: createStoredKnowledgeDocument({
|
|
3141
|
+
documentId: params.documentId,
|
|
3142
|
+
manifest,
|
|
3143
|
+
revisionKey: params.revisionKey,
|
|
3144
|
+
typeCounts: countIndexedTypes(indexedChunks)
|
|
3145
|
+
}),
|
|
3146
|
+
matches,
|
|
3147
|
+
scannedChunks,
|
|
3148
|
+
truncated: false
|
|
3149
|
+
};
|
|
3150
|
+
}
|
|
3151
|
+
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);
|
|
3166
|
+
return {
|
|
3167
|
+
document: createStoredKnowledgeDocument({
|
|
3168
|
+
documentId,
|
|
3169
|
+
manifest,
|
|
3170
|
+
revisionKey,
|
|
3171
|
+
typeCounts
|
|
3172
|
+
}),
|
|
3173
|
+
totalChunks: manifest.totalChunks,
|
|
3174
|
+
typeCounts,
|
|
3175
|
+
sections,
|
|
3176
|
+
sectionTree: nestSections(sections),
|
|
3177
|
+
truncated: false
|
|
3178
|
+
};
|
|
3179
|
+
}
|
|
3180
|
+
async readFreshParsedStorageManifest(documentId, revisionKey) {
|
|
3181
|
+
const parsedStorageConfig = this.parsedStorageConfig;
|
|
3182
|
+
if (!parsedStorageConfig) {
|
|
3183
|
+
return null;
|
|
3184
|
+
}
|
|
3185
|
+
const manifest = await parsedStorageConfig.storage.readManifest({
|
|
3186
|
+
documentId,
|
|
3187
|
+
revisionKey
|
|
3188
|
+
});
|
|
3189
|
+
if (!manifest || !isFreshManifest(manifest, revisionKey)) {
|
|
3190
|
+
return null;
|
|
3191
|
+
}
|
|
3192
|
+
return manifest;
|
|
3193
|
+
}
|
|
3194
|
+
async readStoredSnapshotChunks(params) {
|
|
3195
|
+
const parsedStorageConfig = this.parsedStorageConfig;
|
|
3196
|
+
if (!parsedStorageConfig) {
|
|
3197
|
+
return null;
|
|
3198
|
+
}
|
|
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;
|
|
3244
|
+
}
|
|
3245
|
+
scheduleParsedStorageSync(documentId, revisionKey) {
|
|
3246
|
+
const parsedStorageConfig = this.parsedStorageConfig;
|
|
3247
|
+
if (!parsedStorageConfig) {
|
|
3248
|
+
return;
|
|
3249
|
+
}
|
|
3250
|
+
const scheduler = parsedStorageConfig.scheduler ?? defaultParsedStorageScheduler;
|
|
3251
|
+
const task = async () => {
|
|
3252
|
+
try {
|
|
3253
|
+
await this.syncRemoteDocumentToParsedStorage({
|
|
3254
|
+
documentId,
|
|
3255
|
+
revisionKey,
|
|
3256
|
+
parsedStorageConfig
|
|
3257
|
+
});
|
|
3258
|
+
} catch (error) {
|
|
3259
|
+
await parsedStorageConfig.storage.writeSyncProgress({
|
|
3260
|
+
documentId,
|
|
3261
|
+
revisionKey,
|
|
3262
|
+
nextChunkPage: 1,
|
|
3263
|
+
nextAssetIndex: 0,
|
|
3264
|
+
status: "failed",
|
|
3265
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3266
|
+
error: error instanceof Error ? error.message : String(error)
|
|
3267
|
+
});
|
|
3268
|
+
}
|
|
3269
|
+
};
|
|
3270
|
+
void Promise.resolve(scheduler.schedule(task)).catch(() => void 0);
|
|
3271
|
+
}
|
|
3272
|
+
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,
|
|
3282
|
+
includeAssetUrls: true
|
|
3283
|
+
});
|
|
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
|
|
3290
|
+
});
|
|
3291
|
+
nextPage = 1;
|
|
3292
|
+
}
|
|
3293
|
+
const totalPages = response.pagination.totalPages;
|
|
3294
|
+
const chunkPages = [];
|
|
3295
|
+
let syncedPages = 0;
|
|
3296
|
+
const startedAt = Date.now();
|
|
3297
|
+
while (nextPage <= totalPages) {
|
|
3298
|
+
if (syncedPages > 0) {
|
|
3299
|
+
response = await this.client.documents.listChunks(params.documentId, {
|
|
3300
|
+
page: nextPage,
|
|
3301
|
+
pageSize: limits.remotePageSize,
|
|
3302
|
+
includeAssetUrls: true
|
|
3303
|
+
});
|
|
3304
|
+
}
|
|
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({
|
|
3316
|
+
documentId: params.documentId,
|
|
3317
|
+
revisionKey,
|
|
3318
|
+
page
|
|
3319
|
+
});
|
|
3320
|
+
chunkPages.push(page);
|
|
3321
|
+
nextPage += 1;
|
|
3322
|
+
syncedPages += 1;
|
|
3323
|
+
await params.parsedStorageConfig.storage.writeSyncProgress({
|
|
3324
|
+
documentId: params.documentId,
|
|
3325
|
+
revisionKey,
|
|
3326
|
+
nextChunkPage: nextPage,
|
|
3327
|
+
nextAssetIndex: 0,
|
|
3328
|
+
status: "running",
|
|
3329
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3330
|
+
});
|
|
3331
|
+
if (syncedPages >= limits.maxPagesPerSync || Date.now() - startedAt >= limits.syncDeadlineMs) {
|
|
3332
|
+
return {
|
|
3333
|
+
documentId: params.documentId,
|
|
3334
|
+
revisionKey,
|
|
3335
|
+
completed: false
|
|
3336
|
+
};
|
|
3337
|
+
}
|
|
3338
|
+
}
|
|
3339
|
+
const manifest = createRemoteSnapshotManifest({
|
|
3340
|
+
response,
|
|
3341
|
+
revisionKey,
|
|
3342
|
+
chunkPages
|
|
3343
|
+
});
|
|
3344
|
+
await params.parsedStorageConfig.storage.writeManifest({
|
|
3345
|
+
documentId: params.documentId,
|
|
3346
|
+
revisionKey,
|
|
3347
|
+
manifest
|
|
3348
|
+
});
|
|
3349
|
+
await params.parsedStorageConfig.storage.writeSyncProgress({
|
|
3350
|
+
documentId: params.documentId,
|
|
3351
|
+
revisionKey,
|
|
3352
|
+
nextChunkPage: totalPages + 1,
|
|
3353
|
+
nextAssetIndex: 0,
|
|
3354
|
+
status: "completed",
|
|
3355
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3356
|
+
});
|
|
3357
|
+
return {
|
|
3358
|
+
documentId: params.documentId,
|
|
3359
|
+
revisionKey,
|
|
3360
|
+
completed: true,
|
|
3361
|
+
manifest
|
|
3362
|
+
};
|
|
3363
|
+
}
|
|
3364
|
+
requireParsedStorageConfig() {
|
|
3365
|
+
if (!this.parsedStorageConfig) {
|
|
3366
|
+
throw new ValidationError("parsed document storage is not configured");
|
|
3367
|
+
}
|
|
3368
|
+
return this.parsedStorageConfig;
|
|
3369
|
+
}
|
|
3370
|
+
async findLocalDocumentByRemoteId(documentId) {
|
|
3371
|
+
const documents = await this.store.listDocuments();
|
|
3372
|
+
return documents.find((document) => document.documentId === documentId);
|
|
3373
|
+
}
|
|
3374
|
+
async getPublishedDocumentJobId(documentId) {
|
|
3375
|
+
const response = await this.client.documents.listChunks(documentId, {
|
|
3376
|
+
page: 1,
|
|
3377
|
+
pageSize: 1
|
|
3378
|
+
});
|
|
3379
|
+
if (!response.jobId) {
|
|
3380
|
+
throw new Error(
|
|
3381
|
+
`Cannot sync server document ${documentId}: current published job id was not returned.`
|
|
3382
|
+
);
|
|
3383
|
+
}
|
|
3384
|
+
return response.jobId;
|
|
3385
|
+
}
|
|
3386
|
+
};
|
|
3387
|
+
function normalizeDocumentReference(reference) {
|
|
2046
3388
|
if (typeof reference === "string") {
|
|
2047
3389
|
return { localDocumentId: reference };
|
|
2048
3390
|
}
|
|
@@ -2058,22 +3400,525 @@ function createLocalDocumentIdForRemote(documentId) {
|
|
|
2058
3400
|
const hash = (0, import_crypto2.createHash)("sha256").update(documentId).digest("hex").slice(0, 16);
|
|
2059
3401
|
return `remote_${hash}`;
|
|
2060
3402
|
}
|
|
3403
|
+
var defaultParsedStorageScheduler = {
|
|
3404
|
+
schedule(task) {
|
|
3405
|
+
void task();
|
|
3406
|
+
}
|
|
3407
|
+
};
|
|
3408
|
+
function getParsedStorageLimits(limits) {
|
|
3409
|
+
return {
|
|
3410
|
+
chunkPageSize: clampLimit(limits?.chunkPageSize, DEFAULT_REMOTE_SCAN_PAGE_SIZE, MAX_PAGE_SIZE),
|
|
3411
|
+
remotePageSize: clampLimit(
|
|
3412
|
+
limits?.remotePageSize,
|
|
3413
|
+
DEFAULT_REMOTE_SCAN_PAGE_SIZE,
|
|
3414
|
+
MAX_PAGE_SIZE
|
|
3415
|
+
),
|
|
3416
|
+
maxPagesPerSync: clampLimit(limits?.maxPagesPerSync, DEFAULT_MAX_SYNC_PAGES, 1e3),
|
|
3417
|
+
maxAssetsPerSync: clampLimit(limits?.maxAssetsPerSync, DEFAULT_MAX_SYNC_ASSETS, 1e3),
|
|
3418
|
+
syncDeadlineMs: clampLimit(limits?.syncDeadlineMs, DEFAULT_SYNC_DEADLINE_MS, 6e4),
|
|
3419
|
+
grepMaxPages: clampLimit(limits?.grepMaxPages, DEFAULT_GREP_MAX_PAGES, 1e3),
|
|
3420
|
+
grepDeadlineMs: clampLimit(limits?.grepDeadlineMs, DEFAULT_GREP_DEADLINE_MS, 6e4),
|
|
3421
|
+
outlineMaxPages: clampLimit(limits?.outlineMaxPages, DEFAULT_OUTLINE_MAX_PAGES, 1e3),
|
|
3422
|
+
outlineDeadlineMs: clampLimit(limits?.outlineDeadlineMs, DEFAULT_OUTLINE_DEADLINE_MS, 6e4)
|
|
3423
|
+
};
|
|
3424
|
+
}
|
|
3425
|
+
function validateReadParams(params) {
|
|
3426
|
+
const usesPagedDisplay = params.page !== void 0 || params.pageSize !== void 0 || params.assetUrlPolicy !== void 0;
|
|
3427
|
+
if (!usesPagedDisplay) {
|
|
3428
|
+
return;
|
|
3429
|
+
}
|
|
3430
|
+
if (params.sectionPath !== void 0 || params.startChunk !== void 0 || params.endChunk !== void 0 || params.chunkId !== void 0) {
|
|
3431
|
+
throw new ValidationError(
|
|
3432
|
+
"page, pageSize, and assetUrlPolicy cannot be combined with sectionPath, startChunk, endChunk, or chunkId"
|
|
3433
|
+
);
|
|
3434
|
+
}
|
|
3435
|
+
}
|
|
3436
|
+
function hasScanReadFilters(params) {
|
|
3437
|
+
return params.sectionPath !== void 0 || params.startChunk !== void 0 || params.endChunk !== void 0 || params.chunkId !== void 0;
|
|
3438
|
+
}
|
|
3439
|
+
function getReadPageParams(params) {
|
|
3440
|
+
return {
|
|
3441
|
+
page: clampLimit(params.page, 1, Number.MAX_SAFE_INTEGER),
|
|
3442
|
+
pageSize: clampLimit(params.pageSize ?? params.limit, DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE)
|
|
3443
|
+
};
|
|
3444
|
+
}
|
|
3445
|
+
function shouldRequestRemoteAssetUrls(assetUrlPolicy, parsedStorageConfig) {
|
|
3446
|
+
return assetUrlPolicy === "durable" && parsedStorageConfig !== void 0;
|
|
3447
|
+
}
|
|
3448
|
+
function getRemoteRevisionKey(response) {
|
|
3449
|
+
const revisionKey = response.jobResultId ?? response.jobId;
|
|
3450
|
+
if (!revisionKey) {
|
|
3451
|
+
throw new Error(
|
|
3452
|
+
`Cannot read server document ${response.documentId}: current published revision was not returned.`
|
|
3453
|
+
);
|
|
3454
|
+
}
|
|
3455
|
+
return revisionKey;
|
|
3456
|
+
}
|
|
3457
|
+
function createRemoteKnowledgeDocument(params) {
|
|
3458
|
+
return {
|
|
3459
|
+
localDocumentId: params.documentId,
|
|
3460
|
+
jobId: params.response.jobId ?? params.revisionKey,
|
|
3461
|
+
documentId: params.documentId,
|
|
3462
|
+
namespace: params.response.namespace,
|
|
3463
|
+
sourceFileName: params.documentId,
|
|
3464
|
+
chunkCount: params.response.pagination.total,
|
|
3465
|
+
typeCounts: params.typeCounts ?? countRemoteChunkTypes(params.response.chunks),
|
|
3466
|
+
resultDirectoryPath: `remote:${params.documentId}`,
|
|
3467
|
+
createdAt: /* @__PURE__ */ new Date(0),
|
|
3468
|
+
updatedAt: /* @__PURE__ */ new Date(0)
|
|
3469
|
+
};
|
|
3470
|
+
}
|
|
3471
|
+
function createStoredKnowledgeDocument(params) {
|
|
3472
|
+
return {
|
|
3473
|
+
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,
|
|
3480
|
+
resultDirectoryPath: `parsed-storage:${params.documentId}`,
|
|
3481
|
+
createdAt: new Date(params.manifest.createdAt),
|
|
3482
|
+
updatedAt: new Date(params.manifest.createdAt)
|
|
3483
|
+
};
|
|
3484
|
+
}
|
|
3485
|
+
function isFreshManifest(manifest, revisionKey) {
|
|
3486
|
+
return (manifest.revisionKey ?? manifest.jobId) === revisionKey;
|
|
3487
|
+
}
|
|
3488
|
+
function toRemoteReadChunk(chunk) {
|
|
3489
|
+
const metadata = cloneMetadata(chunk.metadata);
|
|
3490
|
+
return {
|
|
3491
|
+
position: toChunkPosition(chunk),
|
|
3492
|
+
chunkId: chunk.chunkId,
|
|
3493
|
+
chunkType: chunk.chunkType,
|
|
3494
|
+
contentSource: chunk.contentSource ?? void 0,
|
|
3495
|
+
content: chunk.content ?? "",
|
|
3496
|
+
readableContent: getReadableRemoteChunkContent(chunk, metadata),
|
|
3497
|
+
sectionPath: chunk.sectionPath ?? "",
|
|
3498
|
+
sourceChunkPath: chunk.sourceChunkPath ?? chunk.sectionPath ?? "",
|
|
3499
|
+
filePath: chunk.filePath ?? void 0,
|
|
3500
|
+
assetUrl: chunk.assetUrl ?? void 0,
|
|
3501
|
+
pageNumbers: getChunkPageNumbers(metadata),
|
|
3502
|
+
metadata
|
|
3503
|
+
};
|
|
3504
|
+
}
|
|
3505
|
+
function getReadableRemoteChunkContent(chunk, metadata) {
|
|
3506
|
+
if (chunk.chunkType !== "page") {
|
|
3507
|
+
return chunk.content ?? "";
|
|
3508
|
+
}
|
|
3509
|
+
const summary = metadata.summary;
|
|
3510
|
+
return typeof summary === "string" && summary.trim().length > 0 ? summary : chunk.content ?? "";
|
|
3511
|
+
}
|
|
3512
|
+
function toIndexedRemoteChunk(chunk) {
|
|
3513
|
+
const readChunk = toRemoteReadChunk(chunk);
|
|
3514
|
+
return toIndexedReadChunk(readChunk);
|
|
3515
|
+
}
|
|
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)
|
|
3530
|
+
});
|
|
3531
|
+
}
|
|
3532
|
+
function toIndexedReadChunk(chunk) {
|
|
3533
|
+
return {
|
|
3534
|
+
source: createSyntheticChunk(chunk),
|
|
3535
|
+
position: chunk.position,
|
|
3536
|
+
chunkId: chunk.chunkId,
|
|
3537
|
+
chunkType: chunk.chunkType,
|
|
3538
|
+
contentSource: chunk.contentSource,
|
|
3539
|
+
content: chunk.content,
|
|
3540
|
+
readableContent: chunk.readableContent,
|
|
3541
|
+
sectionPath: chunk.sectionPath,
|
|
3542
|
+
sourceChunkPath: chunk.sourceChunkPath,
|
|
3543
|
+
filePath: chunk.filePath,
|
|
3544
|
+
assetUrl: chunk.assetUrl,
|
|
3545
|
+
pageNumbers: chunk.pageNumbers,
|
|
3546
|
+
metadata: chunk.metadata
|
|
3547
|
+
};
|
|
3548
|
+
}
|
|
3549
|
+
function createSyntheticChunk(chunk) {
|
|
3550
|
+
return {
|
|
3551
|
+
chunkId: chunk.chunkId,
|
|
3552
|
+
type: chunk.chunkType,
|
|
3553
|
+
contentSource: chunk.contentSource,
|
|
3554
|
+
content: chunk.content,
|
|
3555
|
+
path: chunk.sourceChunkPath,
|
|
3556
|
+
metadata: chunk.metadata
|
|
3557
|
+
};
|
|
3558
|
+
}
|
|
3559
|
+
function toChunkPosition(chunk) {
|
|
3560
|
+
return chunk ? chunk.sortOrder + 1 : 1;
|
|
3561
|
+
}
|
|
3562
|
+
function buildFlatSectionsFromIndexedChunks(chunks) {
|
|
3563
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
3564
|
+
for (const chunk of chunks) {
|
|
3565
|
+
const path4 = chunk.sectionPath || chunk.sourceChunkPath;
|
|
3566
|
+
const existing = byPath.get(path4);
|
|
3567
|
+
if (existing) {
|
|
3568
|
+
addChunkToSection(existing, chunk);
|
|
3569
|
+
} else {
|
|
3570
|
+
byPath.set(path4, createSectionFromChunk(path4, chunk));
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
return [...byPath.values()].sort(compareSections);
|
|
3574
|
+
}
|
|
3575
|
+
function matchesRemoteReadScope(chunk, params) {
|
|
3576
|
+
return matchesReadScope(toIndexedRemoteChunk(chunk), params);
|
|
3577
|
+
}
|
|
3578
|
+
function getNextChunkPosition(chunks, selected) {
|
|
3579
|
+
const lastSelected = selected[selected.length - 1];
|
|
3580
|
+
if (!lastSelected || selected.length >= chunks.length) {
|
|
3581
|
+
return void 0;
|
|
3582
|
+
}
|
|
3583
|
+
return chunks[chunks.indexOf(lastSelected) + 1]?.position;
|
|
3584
|
+
}
|
|
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
|
+
}));
|
|
3597
|
+
}
|
|
3598
|
+
async function hardenReadChunkAssetUrls(params) {
|
|
3599
|
+
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({
|
|
3616
|
+
storageConfig: params.storageConfig,
|
|
3617
|
+
documentId: params.documentId,
|
|
3618
|
+
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
|
+
}
|
|
3628
|
+
});
|
|
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({
|
|
3667
|
+
documentId: params.documentId,
|
|
3668
|
+
revisionKey: params.revisionKey,
|
|
3669
|
+
sourcePath: params.sourcePath
|
|
3670
|
+
});
|
|
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}`);
|
|
3697
|
+
}
|
|
3698
|
+
return {
|
|
3699
|
+
body: new Uint8Array(await response.arrayBuffer()),
|
|
3700
|
+
contentType: response.headers.get("content-type") ?? fallbackContentType
|
|
3701
|
+
};
|
|
3702
|
+
}
|
|
3703
|
+
function removeAssetUrlsFromMetadata(metadata) {
|
|
3704
|
+
const cloned = cloneMetadata(metadata);
|
|
3705
|
+
const pageAssets = toUnknownArray(cloned.pageAssets);
|
|
3706
|
+
if (!pageAssets) {
|
|
3707
|
+
return cloned;
|
|
3708
|
+
}
|
|
3709
|
+
cloned.pageAssets = pageAssets.map((pageAsset) => {
|
|
3710
|
+
if (!isRecord2(pageAsset)) {
|
|
3711
|
+
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
|
+
};
|
|
3736
|
+
}
|
|
3737
|
+
function toSnapshotChunkFromReadChunk(chunk) {
|
|
3738
|
+
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
|
|
3750
|
+
};
|
|
3751
|
+
}
|
|
3752
|
+
function createRemoteSnapshotManifest(params) {
|
|
3753
|
+
return {
|
|
3754
|
+
version: 1,
|
|
3755
|
+
kind: "knowhere-parsed-result-snapshot",
|
|
3756
|
+
jobId: params.response.jobId ?? params.revisionKey,
|
|
3757
|
+
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
|
+
);
|
|
3783
|
+
}
|
|
3784
|
+
function countRemoteChunkTypes(chunks) {
|
|
3785
|
+
return chunks.reduce(
|
|
3786
|
+
(counts, chunk) => {
|
|
3787
|
+
counts[chunk.chunkType] += 1;
|
|
3788
|
+
return counts;
|
|
3789
|
+
},
|
|
3790
|
+
{ text: 0, image: 0, table: 0, page: 0 }
|
|
3791
|
+
);
|
|
3792
|
+
}
|
|
3793
|
+
function createContinuationCursor(cursor) {
|
|
3794
|
+
return Buffer.from(JSON.stringify(cursor), "utf8").toString("base64url");
|
|
3795
|
+
}
|
|
3796
|
+
function createGrepContinuationCursor(params) {
|
|
3797
|
+
if (params.matchIndex + 1 < params.chunkMatchCount) {
|
|
3798
|
+
return createContinuationCursor({
|
|
3799
|
+
documentId: params.documentId,
|
|
3800
|
+
revisionKey: params.revisionKey,
|
|
3801
|
+
nextPage: params.response.pagination.page,
|
|
3802
|
+
nextChunkIndex: params.chunkIndex,
|
|
3803
|
+
nextMatchIndex: params.matchIndex + 1
|
|
3804
|
+
});
|
|
3805
|
+
}
|
|
3806
|
+
if (params.chunkIndex + 1 < params.response.chunks.length) {
|
|
3807
|
+
return createContinuationCursor({
|
|
3808
|
+
documentId: params.documentId,
|
|
3809
|
+
revisionKey: params.revisionKey,
|
|
3810
|
+
nextPage: params.response.pagination.page,
|
|
3811
|
+
nextChunkIndex: params.chunkIndex + 1,
|
|
3812
|
+
nextMatchIndex: 0
|
|
3813
|
+
});
|
|
3814
|
+
}
|
|
3815
|
+
if (params.response.pagination.page < params.response.pagination.totalPages) {
|
|
3816
|
+
return createContinuationCursor({
|
|
3817
|
+
documentId: params.documentId,
|
|
3818
|
+
revisionKey: params.revisionKey,
|
|
3819
|
+
nextPage: params.response.pagination.page + 1,
|
|
3820
|
+
nextChunkIndex: 0,
|
|
3821
|
+
nextMatchIndex: 0
|
|
3822
|
+
});
|
|
3823
|
+
}
|
|
3824
|
+
return void 0;
|
|
3825
|
+
}
|
|
3826
|
+
function parseContinuationCursor(value) {
|
|
3827
|
+
if (!value) {
|
|
3828
|
+
return null;
|
|
3829
|
+
}
|
|
3830
|
+
try {
|
|
3831
|
+
const parsed = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
|
|
3832
|
+
if (!isRecord2(parsed)) {
|
|
3833
|
+
return null;
|
|
3834
|
+
}
|
|
3835
|
+
const documentId = parsed.documentId;
|
|
3836
|
+
const revisionKey = parsed.revisionKey;
|
|
3837
|
+
const nextPage = parsed.nextPage;
|
|
3838
|
+
const nextChunkIndex = parsed.nextChunkIndex;
|
|
3839
|
+
const nextMatchIndex = parsed.nextMatchIndex;
|
|
3840
|
+
if (typeof documentId !== "string" || typeof revisionKey !== "string" || typeof nextPage !== "number" || !Number.isInteger(nextPage) || nextPage < 1 || !isOptionalNonNegativeInteger(nextChunkIndex) || !isOptionalNonNegativeInteger(nextMatchIndex)) {
|
|
3841
|
+
return null;
|
|
3842
|
+
}
|
|
3843
|
+
return {
|
|
3844
|
+
documentId,
|
|
3845
|
+
revisionKey,
|
|
3846
|
+
nextPage,
|
|
3847
|
+
nextChunkIndex,
|
|
3848
|
+
nextMatchIndex
|
|
3849
|
+
};
|
|
3850
|
+
} catch {
|
|
3851
|
+
return null;
|
|
3852
|
+
}
|
|
3853
|
+
}
|
|
3854
|
+
function isOptionalNonNegativeInteger(value) {
|
|
3855
|
+
return value === void 0 || typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
3856
|
+
}
|
|
3857
|
+
function cloneMetadata(metadata) {
|
|
3858
|
+
return { ...metadata };
|
|
3859
|
+
}
|
|
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
|
+
function toUnknownArray(value) {
|
|
3873
|
+
return Array.isArray(value) ? value : null;
|
|
3874
|
+
}
|
|
3875
|
+
function inferContentTypeFromPath(filePath) {
|
|
3876
|
+
const extension = filePath.split(".").at(-1)?.toLowerCase();
|
|
3877
|
+
if (extension === "png") return "image/png";
|
|
3878
|
+
if (extension === "jpg" || extension === "jpeg") return "image/jpeg";
|
|
3879
|
+
if (extension === "html" || extension === "htm") return "text/html; charset=utf-8";
|
|
3880
|
+
return "application/octet-stream";
|
|
3881
|
+
}
|
|
3882
|
+
function isRecord2(value) {
|
|
3883
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3884
|
+
}
|
|
2061
3885
|
function indexChunks(result) {
|
|
2062
3886
|
return result.chunks.map((chunk, index) => {
|
|
2063
3887
|
const filePath = getChunkFilePath2(chunk);
|
|
3888
|
+
const readableContent = getReadableChunkContent(chunk);
|
|
2064
3889
|
return {
|
|
2065
3890
|
source: chunk,
|
|
2066
3891
|
position: index + 1,
|
|
2067
3892
|
chunkId: chunk.chunkId,
|
|
2068
3893
|
chunkType: chunk.type,
|
|
3894
|
+
contentSource: chunk.contentSource,
|
|
2069
3895
|
content: chunk.content,
|
|
3896
|
+
readableContent,
|
|
2070
3897
|
sectionPath: normalizeSectionPath(chunk.path, result.manifest.sourceFileName),
|
|
2071
3898
|
sourceChunkPath: chunk.path,
|
|
2072
3899
|
filePath,
|
|
3900
|
+
assetUrl: getChunkAssetUrl(chunk),
|
|
3901
|
+
pageNumbers: getChunkPageNumbers(chunk.metadata),
|
|
2073
3902
|
metadata: chunk.metadata
|
|
2074
3903
|
};
|
|
2075
3904
|
});
|
|
2076
3905
|
}
|
|
3906
|
+
function getReadableChunkContent(chunk) {
|
|
3907
|
+
if (chunk.type !== "page") {
|
|
3908
|
+
return chunk.content;
|
|
3909
|
+
}
|
|
3910
|
+
const summary = chunk.metadata.summary;
|
|
3911
|
+
return typeof summary === "string" && summary.trim().length > 0 ? summary : chunk.content;
|
|
3912
|
+
}
|
|
3913
|
+
function getChunkPageNumbers(metadata) {
|
|
3914
|
+
const values = [metadata.pageNums, metadata.page_nums].filter(Array.isArray);
|
|
3915
|
+
const pageNumbers = values.flatMap(
|
|
3916
|
+
(value) => value.filter(
|
|
3917
|
+
(pageNumber) => Number.isInteger(pageNumber) && pageNumber > 0
|
|
3918
|
+
)
|
|
3919
|
+
);
|
|
3920
|
+
return pageNumbers.length > 0 ? [...new Set(pageNumbers)].sort((left, right) => left - right) : void 0;
|
|
3921
|
+
}
|
|
2077
3922
|
function getChunkFilePath2(chunk) {
|
|
2078
3923
|
if (chunk.type === "image" || chunk.type === "table") {
|
|
2079
3924
|
return chunk.filePath;
|
|
@@ -2081,14 +3926,17 @@ function getChunkFilePath2(chunk) {
|
|
|
2081
3926
|
const filePath = chunk.metadata.filePath;
|
|
2082
3927
|
return typeof filePath === "string" ? filePath : void 0;
|
|
2083
3928
|
}
|
|
2084
|
-
function
|
|
2085
|
-
|
|
3929
|
+
function getChunkAssetUrl(chunk) {
|
|
3930
|
+
return chunk.type === "image" || chunk.type === "table" ? chunk.assetUrl : void 0;
|
|
3931
|
+
}
|
|
3932
|
+
function normalizeSectionPath(path4, sourceFileName) {
|
|
3933
|
+
if (!path4) {
|
|
2086
3934
|
return "";
|
|
2087
3935
|
}
|
|
2088
|
-
if (
|
|
2089
|
-
return
|
|
3936
|
+
if (path4.startsWith("images/") || path4.startsWith("tables/")) {
|
|
3937
|
+
return path4;
|
|
2090
3938
|
}
|
|
2091
|
-
const parts =
|
|
3939
|
+
const parts = path4.split("/").filter(Boolean);
|
|
2092
3940
|
if (sourceFileName) {
|
|
2093
3941
|
const fileNameIndex = parts.indexOf(sourceFileName);
|
|
2094
3942
|
if (fileNameIndex >= 0) {
|
|
@@ -2110,12 +3958,12 @@ function buildFlatSections(result, chunks) {
|
|
|
2110
3958
|
}
|
|
2111
3959
|
const byPath = /* @__PURE__ */ new Map();
|
|
2112
3960
|
for (const chunk of chunks) {
|
|
2113
|
-
const
|
|
2114
|
-
const existing = byPath.get(
|
|
3961
|
+
const path4 = chunk.sectionPath || chunk.sourceChunkPath;
|
|
3962
|
+
const existing = byPath.get(path4);
|
|
2115
3963
|
if (existing) {
|
|
2116
3964
|
addChunkToSection(existing, chunk);
|
|
2117
3965
|
} else {
|
|
2118
|
-
byPath.set(
|
|
3966
|
+
byPath.set(path4, createSectionFromChunk(path4, chunk));
|
|
2119
3967
|
}
|
|
2120
3968
|
}
|
|
2121
3969
|
return [...byPath.values()].sort(compareSections);
|
|
@@ -2147,7 +3995,7 @@ function createSectionFromChunk(pathValue, chunk) {
|
|
|
2147
3995
|
startChunk: chunk.position,
|
|
2148
3996
|
endChunk: chunk.position,
|
|
2149
3997
|
chunkCount: 1,
|
|
2150
|
-
typeCounts: { text: 0, image: 0, table: 0, [chunk.chunkType]: 1 },
|
|
3998
|
+
typeCounts: { text: 0, image: 0, table: 0, page: 0, [chunk.chunkType]: 1 },
|
|
2151
3999
|
children: []
|
|
2152
4000
|
};
|
|
2153
4001
|
}
|
|
@@ -2206,7 +4054,7 @@ function countIndexedTypes(chunks) {
|
|
|
2206
4054
|
counts[chunk.chunkType] += 1;
|
|
2207
4055
|
return counts;
|
|
2208
4056
|
},
|
|
2209
|
-
{ text: 0, image: 0, table: 0 }
|
|
4057
|
+
{ text: 0, image: 0, table: 0, page: 0 }
|
|
2210
4058
|
);
|
|
2211
4059
|
}
|
|
2212
4060
|
function isInSection(chunkSectionPath, sectionPath) {
|
|
@@ -2243,10 +4091,14 @@ function toReadChunk(chunk) {
|
|
|
2243
4091
|
position: chunk.position,
|
|
2244
4092
|
chunkId: chunk.chunkId,
|
|
2245
4093
|
chunkType: chunk.chunkType,
|
|
4094
|
+
contentSource: chunk.contentSource,
|
|
2246
4095
|
content: chunk.content,
|
|
4096
|
+
readableContent: chunk.readableContent,
|
|
2247
4097
|
sectionPath: chunk.sectionPath,
|
|
2248
4098
|
sourceChunkPath: chunk.sourceChunkPath,
|
|
2249
4099
|
filePath: chunk.filePath,
|
|
4100
|
+
assetUrl: chunk.assetUrl,
|
|
4101
|
+
pageNumbers: chunk.pageNumbers,
|
|
2250
4102
|
metadata: chunk.metadata
|
|
2251
4103
|
};
|
|
2252
4104
|
}
|
|
@@ -2298,6 +4150,7 @@ function toResultReference(result, documentByServerId) {
|
|
|
2298
4150
|
return {
|
|
2299
4151
|
localDocumentId: documentId ? documentByServerId.get(documentId)?.localDocumentId : void 0,
|
|
2300
4152
|
documentId,
|
|
4153
|
+
chunkId: result.chunkId,
|
|
2301
4154
|
sectionPath: result.source.sectionPath ?? void 0,
|
|
2302
4155
|
chunkType: result.chunkType,
|
|
2303
4156
|
score: result.score
|
|
@@ -2308,6 +4161,7 @@ function toRemoteSearchResult(result, documentByServerId) {
|
|
|
2308
4161
|
return {
|
|
2309
4162
|
localDocumentId: documentId ? documentByServerId.get(documentId)?.localDocumentId : void 0,
|
|
2310
4163
|
documentId,
|
|
4164
|
+
chunkId: result.chunkId,
|
|
2311
4165
|
chunkType: result.chunkType,
|
|
2312
4166
|
content: result.content,
|
|
2313
4167
|
score: result.score,
|
|
@@ -2420,7 +4274,12 @@ var Knowhere = class {
|
|
|
2420
4274
|
const result = await this.jobs.load(jobResult, {
|
|
2421
4275
|
verifyChecksum: params.verifyChecksum
|
|
2422
4276
|
});
|
|
2423
|
-
|
|
4277
|
+
const enrichedResult = enrichParseResult(result, {
|
|
4278
|
+
namespace: jobResult.namespace,
|
|
4279
|
+
documentId: jobResult.documentId ?? params.documentId
|
|
4280
|
+
});
|
|
4281
|
+
const storedResult = await storeParseResultAssets(enrichedResult, params.storageAdapter);
|
|
4282
|
+
return storedResult.result;
|
|
2424
4283
|
}
|
|
2425
4284
|
/**
|
|
2426
4285
|
* Start a parse job and return immediately after the URL job is created or
|
|
@@ -2463,6 +4322,145 @@ var Knowhere = class {
|
|
|
2463
4322
|
return job;
|
|
2464
4323
|
}
|
|
2465
4324
|
};
|
|
4325
|
+
|
|
4326
|
+
// src/storage/disk-parsed-document-storage.ts
|
|
4327
|
+
var import_crypto3 = require("crypto");
|
|
4328
|
+
var import_fs4 = require("fs");
|
|
4329
|
+
var import_path4 = __toESM(require("path"));
|
|
4330
|
+
var DiskParsedDocumentStorage = class {
|
|
4331
|
+
rootDirectory;
|
|
4332
|
+
constructor(rootDirectory) {
|
|
4333
|
+
this.rootDirectory = rootDirectory;
|
|
4334
|
+
}
|
|
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
|
+
);
|
|
4356
|
+
}
|
|
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`, {
|
|
4362
|
+
contentType: params.contentType,
|
|
4363
|
+
metadata: params.metadata ?? {}
|
|
4364
|
+
});
|
|
4365
|
+
return {
|
|
4366
|
+
sourcePath: params.sourcePath,
|
|
4367
|
+
url: toFileUrl(assetPath)
|
|
4368
|
+
};
|
|
4369
|
+
}
|
|
4370
|
+
async getAssetUrl(params) {
|
|
4371
|
+
const assetPath = this.getAssetPath(params.documentId, params.revisionKey, params.sourcePath);
|
|
4372
|
+
try {
|
|
4373
|
+
await import_fs4.promises.access(assetPath);
|
|
4374
|
+
return toFileUrl(assetPath);
|
|
4375
|
+
} catch (error) {
|
|
4376
|
+
if (isMissingFileError3(error)) {
|
|
4377
|
+
return null;
|
|
4378
|
+
}
|
|
4379
|
+
throw error;
|
|
4380
|
+
}
|
|
4381
|
+
}
|
|
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);
|
|
4389
|
+
}
|
|
4390
|
+
getManifestPath(documentId, revisionKey) {
|
|
4391
|
+
return import_path4.default.join(
|
|
4392
|
+
this.getRevisionDirectory(documentId, revisionKey),
|
|
4393
|
+
"manifest",
|
|
4394
|
+
"current.json"
|
|
4395
|
+
);
|
|
4396
|
+
}
|
|
4397
|
+
getChunkPagePath(documentId, revisionKey, page) {
|
|
4398
|
+
return import_path4.default.join(
|
|
4399
|
+
this.getRevisionDirectory(documentId, revisionKey),
|
|
4400
|
+
"chunks",
|
|
4401
|
+
`page-${page}.json`
|
|
4402
|
+
);
|
|
4403
|
+
}
|
|
4404
|
+
getProgressPath(documentId, revisionKey) {
|
|
4405
|
+
return import_path4.default.join(this.getRevisionDirectory(documentId, revisionKey), "sync-progress.json");
|
|
4406
|
+
}
|
|
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}`);
|
|
4420
|
+
}
|
|
4421
|
+
return assetPath;
|
|
4422
|
+
}
|
|
4423
|
+
getRevisionDirectory(documentId, revisionKey) {
|
|
4424
|
+
return import_path4.default.join(this.rootDirectory, hashPathPart(documentId), hashPathPart(revisionKey));
|
|
4425
|
+
}
|
|
4426
|
+
async readOptionalJson(filePath) {
|
|
4427
|
+
try {
|
|
4428
|
+
return JSON.parse(await import_fs4.promises.readFile(filePath, "utf8"));
|
|
4429
|
+
} catch (error) {
|
|
4430
|
+
if (isMissingFileError3(error)) {
|
|
4431
|
+
return null;
|
|
4432
|
+
}
|
|
4433
|
+
throw error;
|
|
4434
|
+
}
|
|
4435
|
+
}
|
|
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), {
|
|
4439
|
+
encoding: "utf8",
|
|
4440
|
+
flag: "w"
|
|
4441
|
+
});
|
|
4442
|
+
}
|
|
4443
|
+
};
|
|
4444
|
+
function hashPathPart(value) {
|
|
4445
|
+
return (0, import_crypto3.createHash)("sha256").update(value).digest("hex").slice(0, 24);
|
|
4446
|
+
}
|
|
4447
|
+
function normalizeRelativeStoragePath(value) {
|
|
4448
|
+
const normalized = value.replaceAll("\\", "/").replace(/^\.\/+/, "");
|
|
4449
|
+
if (normalized.length === 0 || normalized.includes("\0") || normalized.startsWith("/") || normalized.split("/").some((part) => part.length === 0 || part === "." || part === "..")) {
|
|
4450
|
+
throw new Error(`Invalid parsed storage path: ${value}`);
|
|
4451
|
+
}
|
|
4452
|
+
return normalized;
|
|
4453
|
+
}
|
|
4454
|
+
function isPathInsideDirectory2(filePath, directory) {
|
|
4455
|
+
const relative = import_path4.default.relative(directory, filePath);
|
|
4456
|
+
return relative === "" || !relative.startsWith("..") && !import_path4.default.isAbsolute(relative);
|
|
4457
|
+
}
|
|
4458
|
+
function toFileUrl(filePath) {
|
|
4459
|
+
return `file://${filePath}`;
|
|
4460
|
+
}
|
|
4461
|
+
function isMissingFileError3(error) {
|
|
4462
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
4463
|
+
}
|
|
2466
4464
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2467
4465
|
0 && (module.exports = {
|
|
2468
4466
|
APIError,
|
|
@@ -2470,6 +4468,7 @@ var Knowhere = class {
|
|
|
2470
4468
|
BadRequestError,
|
|
2471
4469
|
ChecksumError,
|
|
2472
4470
|
ConflictError,
|
|
4471
|
+
DiskParsedDocumentStorage,
|
|
2473
4472
|
Documents,
|
|
2474
4473
|
GatewayTimeoutError,
|
|
2475
4474
|
InternalServerError,
|
|
@@ -2490,5 +4489,7 @@ var Knowhere = class {
|
|
|
2490
4489
|
ServiceUnavailableError,
|
|
2491
4490
|
TimeoutError,
|
|
2492
4491
|
VERSION,
|
|
2493
|
-
ValidationError
|
|
4492
|
+
ValidationError,
|
|
4493
|
+
storeParseResultAssets,
|
|
4494
|
+
syncParseResultToParsedDocumentStorage
|
|
2494
4495
|
});
|