@autorag/librarian 2.10.1 → 2.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/NOTICE +0 -3
  2. package/README.md +76 -33
  3. package/dist/agent/agent.d.ts +96 -18
  4. package/dist/agent/evidence-ledger.d.ts +54 -5
  5. package/dist/agent/evidence-persistence.d.ts +24 -0
  6. package/dist/agent/jev-extension.d.ts +5 -3
  7. package/dist/agent/search-documents.d.ts +1 -1
  8. package/dist/agent/system-prompt.d.ts +0 -2
  9. package/dist/agent/tool-burst-guard.d.ts +26 -0
  10. package/dist/cli/config.d.ts +37 -23
  11. package/dist/cli/index.js +2095 -1151
  12. package/dist/cloud/config.d.ts +16 -10
  13. package/dist/cloud/credential.d.ts +17 -0
  14. package/dist/cloud/errors.d.ts +6 -6
  15. package/dist/cloud/index.d.ts +5 -4
  16. package/dist/cloud/jev-backend.d.ts +15 -13
  17. package/dist/cloud/models.d.ts +4 -4
  18. package/dist/cloud/oauth-login.d.ts +3 -3
  19. package/dist/cloud/provider.d.ts +16 -11
  20. package/dist/cloud/token.d.ts +2 -2
  21. package/dist/core.d.ts +2 -1
  22. package/dist/core.js +2237 -1310
  23. package/dist/datasource/aliased-skill.d.ts +2 -2
  24. package/dist/datasource/connector-skill.d.ts +2 -2
  25. package/dist/datasource/crawler-skill.d.ts +2 -2
  26. package/dist/datasource/described-skill.d.ts +2 -2
  27. package/dist/datasource/index.d.ts +1 -1
  28. package/dist/datasource/retry.d.ts +49 -0
  29. package/dist/datasource/skills/clawgallery/skill.d.ts +4 -4
  30. package/dist/datasource/skills/discrawl/skill.d.ts +5 -5
  31. package/dist/datasource/skills/github-gist/skill.d.ts +2 -2
  32. package/dist/datasource/skills/lazykatok/skill.d.ts +5 -5
  33. package/dist/datasource/skills/mailcrawl/skill.d.ts +2 -2
  34. package/dist/datasource/skills/obsidian/skill.d.ts +5 -5
  35. package/dist/datasource/types.d.ts +13 -1
  36. package/dist/embedding-runtime/cache.d.ts +9 -0
  37. package/dist/index.d.ts +1 -2
  38. package/dist/index.js +2301 -1375
  39. package/dist/jikji/client.d.ts +13 -2
  40. package/dist/jikji/index.d.ts +1 -1
  41. package/dist/jikji/path-map.d.ts +9 -0
  42. package/dist/jikji/prepare-budget.d.ts +18 -0
  43. package/dist/jikji/serial-queue.d.ts +17 -0
  44. package/dist/jikji/types.d.ts +17 -0
  45. package/dist/mcp/index.js +2281 -1354
  46. package/dist/minsync/client.d.ts +3 -1
  47. package/dist/minsync/method.d.ts +1 -1
  48. package/dist/minsync/types.d.ts +1 -1
  49. package/dist/mirror/atomic-write.d.ts +6 -0
  50. package/dist/mirror/index-store.d.ts +8 -1
  51. package/dist/mirror/index.d.ts +2 -2
  52. package/dist/mirror/sync.d.ts +57 -1
  53. package/dist/p2p/simplex-server.d.ts +0 -1
  54. package/dist/parser/defaults.d.ts +8 -0
  55. package/dist/parser/errors.d.ts +10 -0
  56. package/dist/parser/isolated.d.ts +77 -0
  57. package/dist/parser/kordoc.d.ts +1 -0
  58. package/dist/parser/parse-worker.d.ts +1 -0
  59. package/dist/parser/parse-worker.js +780 -0
  60. package/dist/parser/types.d.ts +5 -0
  61. package/dist/process/abort-reason.d.ts +2 -0
  62. package/dist/retrieval/index.d.ts +1 -1
  63. package/dist/retrieval/rerank.d.ts +16 -10
  64. package/package.json +5 -5
  65. package/skills/autorag/SKILL.md +2 -1
  66. package/skills/autorag-doctor/SKILL.md +6 -0
  67. package/skills/autorag-lite-setup/SKILL.md +1 -1
  68. package/skills/autorag-setup/SKILL.md +41 -16
  69. package/dist/manifest/index.d.ts +0 -2
  70. package/dist/manifest/loader.d.ts +0 -3
  71. package/dist/manifest/types.d.ts +0 -8
@@ -0,0 +1,780 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __returnValue = (v) => v;
3
+ function __exportSetter(name, newValue) {
4
+ this[name] = __returnValue.bind(null, newValue);
5
+ }
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, {
9
+ get: all[name],
10
+ enumerable: true,
11
+ configurable: true,
12
+ set: __exportSetter.bind(all, name)
13
+ });
14
+ };
15
+ var __esm = (fn, res, err) => () => {
16
+ if (fn)
17
+ try {
18
+ res = fn(fn = 0);
19
+ } catch (e) {
20
+ err = [e];
21
+ }
22
+ if (err)
23
+ throw err[0];
24
+ return res;
25
+ };
26
+
27
+ // src/language.ts
28
+ function supportedList() {
29
+ return AUTORAG_LANGUAGE_TAGS.join(", ");
30
+ }
31
+ function toTag(raw) {
32
+ const tag = raw.trim().toLowerCase();
33
+ if (!AUTORAG_LANGUAGE_TAGS.includes(tag)) {
34
+ throw new LanguageError(`Unsupported language "${raw.trim()}". Supported: ${supportedList()}.`);
35
+ }
36
+ return tag;
37
+ }
38
+ function dedupe(tags) {
39
+ return [...new Set(tags)];
40
+ }
41
+ function normalizeLanguages(raw) {
42
+ if (raw === undefined || raw === null)
43
+ return [...DEFAULT_LANGUAGES];
44
+ if (typeof raw === "string")
45
+ return parseLanguageList(raw);
46
+ if (!Array.isArray(raw)) {
47
+ throw new LanguageError(`languages must be a string or an array of language tags; received ${typeof raw}.`);
48
+ }
49
+ const entries = raw.map((entry, index) => {
50
+ if (typeof entry !== "string") {
51
+ throw new LanguageError(`languages[${index}] must be a string language tag; received ${typeof entry}.`);
52
+ }
53
+ return entry;
54
+ });
55
+ const tags = entries.filter((entry) => entry.trim() !== "").map(toTag);
56
+ if (tags.length === 0) {
57
+ throw new LanguageError(`languages must list at least one language. Supported: ${supportedList()}.`);
58
+ }
59
+ return dedupe(tags);
60
+ }
61
+ function parseLanguageList(value) {
62
+ const tags = value.split(",").map((entry) => entry.trim()).filter((entry) => entry !== "").map(toTag);
63
+ if (tags.length === 0) {
64
+ throw new LanguageError(`languages must list at least one language. Supported: ${supportedList()}.`);
65
+ }
66
+ return dedupe(tags);
67
+ }
68
+ var AUTORAG_LANGUAGE_TAGS, DEFAULT_LANGUAGES, LanguageError;
69
+ var init_language = __esm(() => {
70
+ AUTORAG_LANGUAGE_TAGS = [
71
+ "ko",
72
+ "en",
73
+ "ja",
74
+ "zh-hans",
75
+ "zh-hant",
76
+ "fr",
77
+ "de",
78
+ "es",
79
+ "ru",
80
+ "it",
81
+ "pt",
82
+ "vi",
83
+ "th",
84
+ "ar",
85
+ "hi"
86
+ ];
87
+ DEFAULT_LANGUAGES = ["ko", "en"];
88
+ LanguageError = class LanguageError extends Error {
89
+ name = "LanguageError";
90
+ };
91
+ });
92
+
93
+ // src/parser/errors.ts
94
+ function messageFrom(cause) {
95
+ if (cause instanceof Error)
96
+ return cause.message;
97
+ if (typeof cause === "string")
98
+ return cause;
99
+ return "unknown parser failure";
100
+ }
101
+ var ParseError, ParseIsolationError;
102
+ var init_errors = __esm(() => {
103
+ ParseError = class ParseError extends Error {
104
+ parserName;
105
+ virtualPath;
106
+ constructor(parserName, virtualPath, cause) {
107
+ super(`Parser "${parserName}" failed for ${virtualPath}: ${messageFrom(cause)}`);
108
+ this.name = "ParseError";
109
+ this.parserName = parserName;
110
+ this.virtualPath = virtualPath;
111
+ this.cause = cause;
112
+ }
113
+ };
114
+ ParseIsolationError = class ParseIsolationError extends Error {
115
+ code;
116
+ constructor(code, message) {
117
+ super(message);
118
+ this.name = "ParseIsolationError";
119
+ this.code = code;
120
+ }
121
+ };
122
+ });
123
+
124
+ // src/parser/text.ts
125
+ import { detect } from "chardet";
126
+ import iconv from "iconv-lite";
127
+ function decodeText(bytes) {
128
+ const buffer = Buffer.from(bytes);
129
+ if (isPureAscii(bytes)) {
130
+ return iconv.decode(buffer, "ascii");
131
+ }
132
+ const utf8 = iconv.decode(buffer, "utf8");
133
+ if (replacementCount(utf8) > 0) {
134
+ const cp949 = iconv.decode(buffer, "cp949");
135
+ if (replacementCount(cp949) < replacementCount(utf8))
136
+ return cp949.normalize("NFC");
137
+ }
138
+ const detected = detect(buffer);
139
+ const encoding = detected && WINDOWS_949_LABELS.has(detected) ? "cp949" : detected ?? "utf8";
140
+ return iconv.decode(buffer, encoding).normalize("NFC");
141
+ }
142
+ function normalizeMarkdown(markdown) {
143
+ return markdown.normalize("NFC");
144
+ }
145
+ function replacementCount(value) {
146
+ return [...value].filter((character) => character === "�").length;
147
+ }
148
+ function isPureAscii(bytes) {
149
+ if (bytes.length === 0)
150
+ return true;
151
+ if (bytes.length < 4)
152
+ return false;
153
+ for (let i = 0;i < bytes.length; i += 1) {
154
+ const byte = bytes[i];
155
+ if (byte < 1 || byte === 27 || byte > 127)
156
+ return false;
157
+ }
158
+ return true;
159
+ }
160
+ var WINDOWS_949_LABELS;
161
+ var init_text = __esm(() => {
162
+ WINDOWS_949_LABELS = new Set(["EUC-KR", "ISO-2022-KR", "windows-949", "CP949"]);
163
+ });
164
+
165
+ // src/parser/types.ts
166
+ class Parser {
167
+ version = "1";
168
+ }
169
+
170
+ // src/parser/eml.ts
171
+ import { simpleParser } from "mailparser";
172
+ function addressText(address) {
173
+ if (address === undefined)
174
+ return;
175
+ if (Array.isArray(address)) {
176
+ return address.map((item) => item.text).filter((text) => text.length > 0).join(", ");
177
+ }
178
+ return address.text;
179
+ }
180
+ var EmlParser;
181
+ var init_eml = __esm(() => {
182
+ init_errors();
183
+ init_text();
184
+ EmlParser = class EmlParser extends Parser {
185
+ name = "eml";
186
+ extensions = [".eml"];
187
+ async parse(input) {
188
+ try {
189
+ const parsed = await simpleParser(Buffer.from(input.bytes));
190
+ const from = addressText(parsed.from);
191
+ const to = addressText(parsed.to);
192
+ const lines = [
193
+ parsed.subject ? `# ${parsed.subject}` : undefined,
194
+ from ? `From: ${from}` : undefined,
195
+ to ? `To: ${to}` : undefined,
196
+ parsed.date ? `Date: ${parsed.date.toISOString()}` : undefined,
197
+ parsed.text?.trim()
198
+ ].filter((line) => line !== undefined && line.length > 0);
199
+ return {
200
+ markdown: normalizeMarkdown(lines.join(`
201
+
202
+ `)),
203
+ metadata: {
204
+ parser: this.name,
205
+ subject: parsed.subject,
206
+ from,
207
+ to,
208
+ date: parsed.date?.toISOString()
209
+ }
210
+ };
211
+ } catch (cause) {
212
+ throw new ParseError(this.name, input.virtualPath, cause);
213
+ }
214
+ }
215
+ };
216
+ });
217
+
218
+ // src/parser/kordoc.ts
219
+ import { readFileSync } from "node:fs";
220
+ import { createRequire } from "node:module";
221
+ import { dirname, join } from "node:path";
222
+ import { parse as kordocParse } from "kordoc";
223
+ function installedKordocVersion() {
224
+ try {
225
+ const entry = createRequire(import.meta.url).resolve("kordoc");
226
+ const manifest = JSON.parse(readFileSync(join(dirname(dirname(entry)), "package.json"), "utf8"));
227
+ if (manifest.name === "kordoc" && typeof manifest.version === "string")
228
+ return manifest.version;
229
+ } catch {}
230
+ return "unknown";
231
+ }
232
+ function toKordocInput(bytes) {
233
+ return Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
234
+ }
235
+ var KORDOC_VERSION, KORDOC_EXTENSIONS, KORDOC_IMAGE_EXTENSIONS, defaultParse = async (bytes, options) => {
236
+ const result = await kordocParse(toKordocInput(bytes), {
237
+ plain: true,
238
+ ...options.ocr === undefined ? {} : { ocr: options.ocr }
239
+ });
240
+ if (result.success) {
241
+ return {
242
+ success: true,
243
+ fileType: result.fileType,
244
+ markdown: result.markdown,
245
+ warnings: result.warnings
246
+ };
247
+ }
248
+ return { success: false, fileType: result.fileType, error: result.error, code: result.code };
249
+ }, KordocParser;
250
+ var init_kordoc = __esm(() => {
251
+ init_errors();
252
+ KORDOC_VERSION = installedKordocVersion();
253
+ KORDOC_EXTENSIONS = [".hwp", ".hwpx", ".hml", ".hwpml", ".pdf", ".docx", ".xlsx", ".xls"];
254
+ KORDOC_IMAGE_EXTENSIONS = [".png", ".jpg", ".jpeg", ".webp"];
255
+ KordocParser = class KordocParser extends Parser {
256
+ name = "kordoc";
257
+ version = KORDOC_VERSION;
258
+ extensions;
259
+ #parse;
260
+ #ocr;
261
+ constructor(options = {}) {
262
+ super();
263
+ this.#parse = options.parse ?? defaultParse;
264
+ this.#ocr = options.ocr;
265
+ this.extensions = options.images === true ? [...KORDOC_EXTENSIONS, ...KORDOC_IMAGE_EXTENSIONS] : KORDOC_EXTENSIONS;
266
+ }
267
+ async parse(input) {
268
+ let result;
269
+ try {
270
+ result = await this.#parse(input.bytes, { ocr: this.#ocr });
271
+ } catch (cause) {
272
+ throw new ParseError(this.name, input.virtualPath, cause);
273
+ }
274
+ if (!result.success) {
275
+ throw new ParseError(this.name, input.virtualPath, new Error(`${result.code ?? "PARSE_ERROR"}: ${result.error}`));
276
+ }
277
+ const diagnostics = (result.warnings ?? []).map((warning) => ({
278
+ code: "parser-warning",
279
+ severity: "warning",
280
+ message: warning.code ? `${warning.code}: ${warning.message}` : warning.message
281
+ }));
282
+ return {
283
+ markdown: result.markdown,
284
+ metadata: { parser: this.name, format: result.fileType ?? "unknown" },
285
+ ...diagnostics.length > 0 ? { diagnostics } : {}
286
+ };
287
+ }
288
+ };
289
+ });
290
+
291
+ // src/parser/ocr-engines.ts
292
+ import { mkdir } from "node:fs/promises";
293
+ import { createWorker } from "tesseract.js";
294
+ function tesseractLanguageListFor(tags) {
295
+ const languages = [...new Set(tags)].map((tag) => TESSERACT_LANGUAGES[tag]);
296
+ if (languages.length === 0) {
297
+ throw new Error("OCR provider requires at least one language.");
298
+ }
299
+ return languages;
300
+ }
301
+ function tesseractLanguageFor(tags) {
302
+ return tesseractLanguageListFor(tags).join("+");
303
+ }
304
+ function createTesseractOcrProvider(options) {
305
+ const language = tesseractLanguageFor(options.languages);
306
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TESSERACT_TIMEOUT_MS;
307
+ const engine = options.engine ?? ((resolvedLanguage, pageImage) => recognizeWithTesseract({
308
+ language: resolvedLanguage,
309
+ bytes: pageImage,
310
+ timeoutMs,
311
+ cachePath: options.cachePath
312
+ }));
313
+ return (pageImage, pageNumber, mimeType) => engine(language, pageImage, pageNumber, mimeType);
314
+ }
315
+ function recognizeWithTesseract(recognition) {
316
+ const controller = new AbortController;
317
+ const operation = startTesseract(recognition, controller.signal);
318
+ return withTimeout(operation, recognition.timeoutMs, () => controller.abort());
319
+ }
320
+ function startTesseract(recognition, signal) {
321
+ let cleanupResolve = () => {
322
+ return;
323
+ };
324
+ let cleanupReject = () => {
325
+ return;
326
+ };
327
+ const cleanup = new Promise((resolve, reject) => {
328
+ cleanupResolve = resolve;
329
+ cleanupReject = reject;
330
+ });
331
+ const result = runTesseract(recognition, signal, cleanupResolve, cleanupReject);
332
+ return { result, cleanup };
333
+ }
334
+ async function runTesseract(recognition, signal, cleanupResolve, cleanupReject) {
335
+ let worker;
336
+ let termination;
337
+ const terminate = async () => {
338
+ if (worker === undefined)
339
+ return;
340
+ termination ??= worker.terminate().then(() => {
341
+ return;
342
+ });
343
+ await termination;
344
+ };
345
+ const abort = () => {
346
+ if (worker !== undefined) {
347
+ terminate().then(cleanupResolve, cleanupReject);
348
+ }
349
+ };
350
+ signal.addEventListener("abort", abort, { once: true });
351
+ try {
352
+ const tooSmall = ocrImageTooSmallMessage(recognition.bytes);
353
+ if (tooSmall !== undefined)
354
+ throw new Error(tooSmall);
355
+ const { cachePath } = recognition;
356
+ if (cachePath !== undefined)
357
+ await mkdir(cachePath, { recursive: true });
358
+ worker = await createWorker(recognition.language, undefined, {
359
+ ...cachePath === undefined ? {} : { cachePath },
360
+ errorHandler: containTesseractWorkerError
361
+ });
362
+ if (signal.aborted)
363
+ throw new Error("OCR aborted before worker was ready");
364
+ const result = await worker.recognize(Buffer.from(recognition.bytes));
365
+ return result.data.text;
366
+ } finally {
367
+ signal.removeEventListener("abort", abort);
368
+ await terminate().then(cleanupResolve, cleanupReject);
369
+ }
370
+ }
371
+ function containTesseractWorkerError(_payload) {}
372
+ function ocrImageTooSmallMessage(bytes) {
373
+ const size = readImagePixelSize(bytes);
374
+ if (size === undefined || size.width >= MIN_LEPTONICA_SIDE_PIXELS && size.height >= MIN_LEPTONICA_SIDE_PIXELS) {
375
+ return;
376
+ }
377
+ return `Image is too small to scale (${size.width}x${size.height} vs minimum of ${MIN_LEPTONICA_SIDE_PIXELS} pixels).`;
378
+ }
379
+ function readImagePixelSize(bytes) {
380
+ if (bytes.length >= 8 && bytes[0] === 137 && bytes[1] === 80)
381
+ return readPngSize(bytes);
382
+ if (bytes.length >= 2 && bytes[0] === 255 && bytes[1] === 216)
383
+ return readJpegSize(bytes);
384
+ if (bytes.length >= 12 && bytes[0] === 82 && bytes[1] === 73)
385
+ return readWebpSize(bytes);
386
+ return;
387
+ }
388
+ function readPngSize(bytes) {
389
+ if (bytes.length < 24)
390
+ return;
391
+ if (bytes[0] !== 137 || bytes[1] !== 80 || bytes[2] !== 78 || bytes[3] !== 71 || bytes[4] !== 13 || bytes[5] !== 10 || bytes[6] !== 26 || bytes[7] !== 10) {
392
+ return;
393
+ }
394
+ if (bytes[12] !== 73 || bytes[13] !== 72 || bytes[14] !== 68 || bytes[15] !== 82)
395
+ return;
396
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
397
+ return { width: view.getUint32(16), height: view.getUint32(20) };
398
+ }
399
+ function readJpegSize(bytes) {
400
+ if (bytes.length < 4 || bytes[0] !== 255 || bytes[1] !== 216)
401
+ return;
402
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
403
+ let offset = 2;
404
+ while (offset + 1 < bytes.length) {
405
+ if (bytes[offset] !== 255)
406
+ return;
407
+ offset += 1;
408
+ while (offset < bytes.length && bytes[offset] === 255)
409
+ offset += 1;
410
+ if (offset >= bytes.length)
411
+ return;
412
+ const marker = bytes[offset] ?? 0;
413
+ offset += 1;
414
+ if (marker === 0)
415
+ return;
416
+ if (marker === 1 || marker === 217 || marker >= 208 && marker <= 216)
417
+ continue;
418
+ if (offset + 2 > bytes.length)
419
+ return;
420
+ const segmentLength = view.getUint16(offset);
421
+ if (segmentLength < 2)
422
+ return;
423
+ if (isJpegStartOfFrame(marker)) {
424
+ if (segmentLength < 7 || offset + 7 > bytes.length)
425
+ return;
426
+ return { width: view.getUint16(offset + 5), height: view.getUint16(offset + 3) };
427
+ }
428
+ if (marker === 218)
429
+ return;
430
+ const next = offset + segmentLength;
431
+ if (next <= offset || next > bytes.length)
432
+ return;
433
+ offset = next;
434
+ }
435
+ return;
436
+ }
437
+ function isJpegStartOfFrame(marker) {
438
+ return marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204;
439
+ }
440
+ function readWebpSize(bytes) {
441
+ if (bytes.length < 20 || !asciiAt(bytes, 0, "RIFF") || !asciiAt(bytes, 8, "WEBP"))
442
+ return;
443
+ const chunkSize = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(16, true);
444
+ if (asciiAt(bytes, 12, "VP8X"))
445
+ return readVp8xSize(bytes, chunkSize);
446
+ if (asciiAt(bytes, 12, "VP8L"))
447
+ return readVp8lSize(bytes, chunkSize);
448
+ if (asciiAt(bytes, 12, "VP8 "))
449
+ return readVp8Size(bytes, chunkSize);
450
+ return;
451
+ }
452
+ function readVp8xSize(bytes, chunkSize) {
453
+ if (!webpPayloadFits(bytes, chunkSize, 10))
454
+ return;
455
+ const payload = 20;
456
+ const width = 1 + readU24LE(bytes, payload + 4);
457
+ const height = 1 + readU24LE(bytes, payload + 7);
458
+ return { width, height };
459
+ }
460
+ function readVp8lSize(bytes, chunkSize) {
461
+ if (!webpPayloadFits(bytes, chunkSize, 5) || bytes[20] !== 47)
462
+ return;
463
+ const b1 = bytes[21] ?? 0;
464
+ const b2 = bytes[22] ?? 0;
465
+ const b3 = bytes[23] ?? 0;
466
+ const b4 = bytes[24] ?? 0;
467
+ const width = 1 + (b1 | (b2 & 63) << 8);
468
+ const height = 1 + (b2 >> 6 | b3 << 2 | (b4 & 15) << 10);
469
+ return { width, height };
470
+ }
471
+ function readVp8Size(bytes, chunkSize) {
472
+ if (!webpPayloadFits(bytes, chunkSize, 10) || (bytes[20] & 1) !== 0)
473
+ return;
474
+ if (bytes[23] !== 157 || bytes[24] !== 1 || bytes[25] !== 42)
475
+ return;
476
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
477
+ return { width: view.getUint16(26, true) & 16383, height: view.getUint16(28, true) & 16383 };
478
+ }
479
+ function webpPayloadFits(bytes, chunkSize, needed) {
480
+ return chunkSize >= needed && bytes.length >= 20 + needed;
481
+ }
482
+ function readU24LE(bytes, offset) {
483
+ return (bytes[offset] ?? 0) | (bytes[offset + 1] ?? 0) << 8 | (bytes[offset + 2] ?? 0) << 16;
484
+ }
485
+ function asciiAt(bytes, offset, text) {
486
+ if (offset + text.length > bytes.length)
487
+ return false;
488
+ for (let index = 0;index < text.length; index += 1) {
489
+ if (bytes[offset + index] !== text.charCodeAt(index))
490
+ return false;
491
+ }
492
+ return true;
493
+ }
494
+ function withTimeout(operation, timeoutMs, onTimeout) {
495
+ return new Promise((resolve, reject) => {
496
+ const timeout = setTimeout(() => {
497
+ onTimeout();
498
+ operation.cleanup.finally(() => reject(new Error(`OCR timed out after ${timeoutMs}ms`)));
499
+ }, timeoutMs);
500
+ operation.result.then((value) => {
501
+ clearTimeout(timeout);
502
+ resolve(value);
503
+ }, (error) => {
504
+ clearTimeout(timeout);
505
+ operation.cleanup.then(() => reject(error), (cleanupError) => reject(cleanupError));
506
+ });
507
+ });
508
+ }
509
+ var TESSERACT_LANGUAGES, BUILTIN_OCR_LANGUAGES, DEFAULT_TESSERACT_TIMEOUT_MS = 30000, MIN_LEPTONICA_SIDE_PIXELS = 3;
510
+ var init_ocr_engines = __esm(() => {
511
+ TESSERACT_LANGUAGES = {
512
+ ko: "kor",
513
+ en: "eng",
514
+ ja: "jpn",
515
+ "zh-hans": "chi_sim",
516
+ "zh-hant": "chi_tra",
517
+ fr: "fra",
518
+ de: "deu",
519
+ es: "spa",
520
+ ru: "rus",
521
+ it: "ita",
522
+ pt: "por",
523
+ vi: "vie",
524
+ th: "tha",
525
+ ar: "ara",
526
+ hi: "hin"
527
+ };
528
+ BUILTIN_OCR_LANGUAGES = new Set(["ko", "en"]);
529
+ });
530
+
531
+ // src/parser/xml-text.ts
532
+ import { Buffer as Buffer2 } from "node:buffer";
533
+ import { XMLParser } from "fast-xml-parser";
534
+ import JSZip from "jszip";
535
+ async function readZipXmlText(bytes, pathPattern) {
536
+ const zip = await JSZip.loadAsync(bytes);
537
+ const files = Object.values(zip.files).filter((file) => !file.dir && pathPattern.test(file.name)).sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true }));
538
+ if (files.length > MAX_XML_FILES) {
539
+ throw new Error(`archive XML file count exceeds limit of ${MAX_XML_FILES}`);
540
+ }
541
+ const chunks = [];
542
+ let totalXmlBytes = 0;
543
+ for (const file of files) {
544
+ const declaredSize = uncompressedSize(file);
545
+ if (declaredSize !== undefined && totalXmlBytes + declaredSize > MAX_XML_BYTES) {
546
+ throw new Error(`archive XML content exceeds limit of ${MAX_XML_BYTES} bytes`);
547
+ }
548
+ const xml = await readXmlFile(file, MAX_XML_BYTES - totalXmlBytes);
549
+ totalXmlBytes += Buffer2.byteLength(xml);
550
+ if (totalXmlBytes > MAX_XML_BYTES) {
551
+ throw new Error(`archive XML content exceeds limit of ${MAX_XML_BYTES} bytes`);
552
+ }
553
+ chunks.push(...extractTextFromXml(xml));
554
+ if (chunks.length > MAX_TEXT_CHUNKS) {
555
+ throw new Error(`archive text chunk count exceeds limit of ${MAX_TEXT_CHUNKS}`);
556
+ }
557
+ }
558
+ return chunks;
559
+ }
560
+ async function readXmlFile(file, remainingBytes) {
561
+ const stream = file.nodeStream("nodebuffer");
562
+ return new Promise((resolve, reject) => {
563
+ const chunks = [];
564
+ let totalBytes = 0;
565
+ stream.on("data", (chunk) => {
566
+ const buffer = Buffer2.isBuffer(chunk) ? chunk : Buffer2.from(chunk);
567
+ totalBytes += buffer.byteLength;
568
+ if (totalBytes > remainingBytes) {
569
+ destroyStream(stream);
570
+ reject(new Error(`archive XML content exceeds limit of ${MAX_XML_BYTES} bytes`));
571
+ return;
572
+ }
573
+ chunks.push(buffer);
574
+ });
575
+ stream.on("error", reject);
576
+ stream.on("end", () => resolve(Buffer2.concat(chunks).toString("utf8")));
577
+ });
578
+ }
579
+ function uncompressedSize(file) {
580
+ const data = Reflect.get(file, "_data");
581
+ if (!isRecord(data))
582
+ return;
583
+ const size = data.uncompressedSize;
584
+ return typeof size === "number" ? size : undefined;
585
+ }
586
+ function destroyStream(stream) {
587
+ if ("destroy" in stream && typeof stream.destroy === "function") {
588
+ stream.destroy();
589
+ }
590
+ }
591
+ function extractTextFromXml(xml) {
592
+ return collectText(parser.parse(xml));
593
+ }
594
+ function collectText(value) {
595
+ if (typeof value === "string") {
596
+ const trimmed = value.trim();
597
+ return trimmed.length > 0 ? [trimmed] : [];
598
+ }
599
+ if (Array.isArray(value))
600
+ return value.flatMap((item) => collectText(item));
601
+ if (!isRecord(value))
602
+ return [];
603
+ const chunks = [];
604
+ for (const [key, child] of Object.entries(value)) {
605
+ if (key.startsWith("@_"))
606
+ continue;
607
+ if (isTextElement(key)) {
608
+ chunks.push(...collectText(child));
609
+ continue;
610
+ }
611
+ chunks.push(...collectText(child));
612
+ }
613
+ return chunks;
614
+ }
615
+ function isTextElement(key) {
616
+ return key === "t" || key.endsWith(":t");
617
+ }
618
+ function isRecord(value) {
619
+ return typeof value === "object" && value !== null;
620
+ }
621
+ var parser, MAX_XML_FILES = 64, MAX_XML_BYTES = 5000000, MAX_TEXT_CHUNKS = 20000;
622
+ var init_xml_text = __esm(() => {
623
+ parser = new XMLParser({
624
+ ignoreAttributes: false,
625
+ parseTagValue: false,
626
+ processEntities: true,
627
+ trimValues: false
628
+ });
629
+ });
630
+
631
+ // src/parser/office.ts
632
+ var PptxParser;
633
+ var init_office = __esm(() => {
634
+ init_errors();
635
+ init_text();
636
+ init_xml_text();
637
+ PptxParser = class PptxParser extends Parser {
638
+ name = "pptx";
639
+ extensions = [".pptx"];
640
+ async parse(input) {
641
+ try {
642
+ const chunks = await readZipXmlText(input.bytes, /^ppt\/(?:slides\/slide\d+|notesSlides\/notesSlide\d+)\.xml$/);
643
+ const markdown = normalizeMarkdown(chunks.filter((chunk) => chunk.trim().length > 0).join(`
644
+
645
+ `));
646
+ return { markdown, metadata: { parser: this.name } };
647
+ } catch (cause) {
648
+ throw new ParseError(this.name, input.virtualPath, cause);
649
+ }
650
+ }
651
+ };
652
+ });
653
+
654
+ // src/parser/plain-text.ts
655
+ var PlainTextParser;
656
+ var init_plain_text = __esm(() => {
657
+ init_text();
658
+ PlainTextParser = class PlainTextParser extends Parser {
659
+ name = "plain-text";
660
+ extensions = [".txt", ".text", ".md", ".markdown"];
661
+ async parse(input) {
662
+ return { markdown: decodeText(input.bytes), metadata: { parser: this.name } };
663
+ }
664
+ };
665
+ });
666
+
667
+ // src/parser/registry.ts
668
+ import { extname } from "node:path";
669
+
670
+ class ParserRegistry {
671
+ parsersByExtension = new Map;
672
+ constructor(parsers = []) {
673
+ for (const parser of parsers) {
674
+ this.register(parser);
675
+ }
676
+ }
677
+ register(parser) {
678
+ for (const extension of parser.extensions) {
679
+ const normalized = normalizeExtension(extension);
680
+ if (this.parsersByExtension.has(normalized)) {
681
+ throw new Error(`Parser extension "${normalized}" is already registered`);
682
+ }
683
+ this.parsersByExtension.set(normalized, parser);
684
+ }
685
+ }
686
+ getForVirtualPath(virtualPath) {
687
+ return this.parsersByExtension.get(normalizeExtension(extname(virtualPath)));
688
+ }
689
+ list() {
690
+ return Array.from(new Set(this.parsersByExtension.values()));
691
+ }
692
+ }
693
+ function normalizeExtension(extension) {
694
+ const lower = extension.toLowerCase();
695
+ return lower.startsWith(".") ? lower : `.${lower}`;
696
+ }
697
+ var init_registry = () => {};
698
+
699
+ // src/parser/defaults.ts
700
+ import { join as join2 } from "node:path";
701
+ function tesseractCachePathFor(workspacePath) {
702
+ return join2(workspacePath, ".autorag", "models", "tessdata");
703
+ }
704
+ function resolveParserOptions(parserOptions, languages, workspacePath) {
705
+ const resolved = { ...parserOptions, languages: parserOptions?.languages ?? languages };
706
+ if (workspacePath === undefined || parserOptions?.ocr === undefined || parserOptions.ocr.cachePath !== undefined) {
707
+ return resolved;
708
+ }
709
+ return { ...resolved, ocr: { ...parserOptions.ocr, cachePath: tesseractCachePathFor(workspacePath) } };
710
+ }
711
+ function createDefaultParserRegistry(options = {}) {
712
+ const languages = options.languages ?? DEFAULT_LANGUAGES;
713
+ const ocrEnabled = options.ocr?.enabled === true;
714
+ const builtinCovers = languages.every((language) => BUILTIN_OCR_LANGUAGES.has(language));
715
+ const kordocOptions = {
716
+ ...options.kordoc,
717
+ images: ocrEnabled,
718
+ ...options.kordoc?.ocr === undefined ? {
719
+ ocr: !ocrEnabled ? false : builtinCovers ? true : createTesseractOcrProvider({
720
+ languages,
721
+ timeoutMs: options.ocr?.timeoutMs,
722
+ cachePath: options.ocr?.cachePath
723
+ })
724
+ } : {}
725
+ };
726
+ return new ParserRegistry([
727
+ new PlainTextParser,
728
+ new KordocParser(kordocOptions),
729
+ new PptxParser,
730
+ new EmlParser
731
+ ]);
732
+ }
733
+ var init_defaults = __esm(() => {
734
+ init_language();
735
+ init_eml();
736
+ init_kordoc();
737
+ init_ocr_engines();
738
+ init_office();
739
+ init_plain_text();
740
+ init_registry();
741
+ });
742
+
743
+ // src/parser/parse-worker.ts
744
+ init_defaults();
745
+ init_errors();
746
+ import { parentPort, workerData } from "node:worker_threads";
747
+ var registry = createDefaultParserRegistry(workerData);
748
+ function describe(error) {
749
+ if (error instanceof Error)
750
+ return { message: error.message, ...error.stack === undefined ? {} : { stack: error.stack } };
751
+ return { message: typeof error === "string" ? error : "unknown parser failure" };
752
+ }
753
+ async function handle(request) {
754
+ const parser = registry.list().find((candidate) => candidate.name === request.parserName);
755
+ if (parser === undefined) {
756
+ return { id: request.id, ok: false, kind: "error", message: `Unknown parser "${request.parserName}"` };
757
+ }
758
+ try {
759
+ const output = await parser.parse({
760
+ virtualPath: request.virtualPath,
761
+ ...request.sourcePath === undefined ? {} : { sourcePath: request.sourcePath },
762
+ bytes: request.bytes
763
+ });
764
+ return { id: request.id, ok: true, output };
765
+ } catch (error) {
766
+ if (error instanceof ParseError) {
767
+ return {
768
+ id: request.id,
769
+ ok: false,
770
+ kind: "parse-error",
771
+ parserName: error.parserName,
772
+ ...describe(error.cause)
773
+ };
774
+ }
775
+ return { id: request.id, ok: false, kind: "error", ...describe(error) };
776
+ }
777
+ }
778
+ parentPort?.on("message", (request) => {
779
+ handle(request).then((response) => parentPort?.postMessage(response));
780
+ });