@autorag/librarian 2.13.4 → 2.13.6

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 (91) hide show
  1. package/NOTICE +3 -0
  2. package/README.md +50 -18
  3. package/dist/agent/agent.d.ts +111 -40
  4. package/dist/agent/cloud-release-extension.d.ts +43 -0
  5. package/dist/agent/decision-backends.d.ts +49 -0
  6. package/dist/agent/decision-model-check.d.ts +92 -0
  7. package/dist/agent/dupey-tool.d.ts +2 -0
  8. package/dist/agent/everything-search-tool.d.ts +1 -0
  9. package/dist/agent/fsearch-search-tool.d.ts +1 -0
  10. package/dist/agent/index.d.ts +4 -1
  11. package/dist/agent/jev-extension.d.ts +27 -32
  12. package/dist/agent/jikji-find-tool.d.ts +5 -0
  13. package/dist/agent/name-candidates.d.ts +88 -0
  14. package/dist/agent/permission-gate.d.ts +2 -5
  15. package/dist/agent/query-routing.d.ts +1 -1
  16. package/dist/agent/search-documents.d.ts +1 -1
  17. package/dist/agent/sllm-decision.d.ts +34 -0
  18. package/dist/cli/commands/duplicates.d.ts +3 -2
  19. package/dist/cli/commands/models.d.ts +2 -0
  20. package/dist/cli/commands/search.d.ts +2 -0
  21. package/dist/cli/config.d.ts +49 -30
  22. package/dist/cli/index.js +13522 -10169
  23. package/dist/cli/setup.d.ts +27 -1
  24. package/dist/cloud/jev-backend.d.ts +26 -4
  25. package/dist/core.js +6079 -2840
  26. package/dist/datasource/index.d.ts +2 -2
  27. package/dist/datasource/skills/obsidian/index.d.ts +1 -1
  28. package/dist/datasource/skills/obsidian/methods.d.ts +1 -1
  29. package/dist/datasource/skills/obsidian/skill.d.ts +1 -0
  30. package/dist/datasource/skills/obsidian/vault-index.d.ts +1 -1
  31. package/dist/datasource/skills/wombat/client.d.ts +17 -0
  32. package/dist/datasource/skills/wombat/index.d.ts +4 -0
  33. package/dist/datasource/skills/wombat/methods.d.ts +15 -0
  34. package/dist/datasource/skills/wombat/skill.d.ts +38 -0
  35. package/dist/datasource/skills/wombat/types.d.ts +89 -0
  36. package/dist/dupey/cli.d.ts +21 -1
  37. package/dist/dupey/filter.d.ts +8 -1
  38. package/dist/dupey/index.d.ts +1 -0
  39. package/dist/dupey/scan-plan.d.ts +23 -0
  40. package/dist/embedding/index.d.ts +3 -1
  41. package/dist/everything/client.d.ts +1 -2
  42. package/dist/filesystem/cloud-placeholder.d.ts +313 -21
  43. package/dist/filesystem/shared-exclusive-queue.d.ts +16 -0
  44. package/dist/fsearch/client.d.ts +3 -2
  45. package/dist/index.d.ts +1 -1
  46. package/dist/index.js +6184 -2905
  47. package/dist/jikji/answer-pack.d.ts +7 -1
  48. package/dist/jikji/client.d.ts +28 -14
  49. package/dist/jikji/diagnostics.d.ts +16 -2
  50. package/dist/jikji/index.d.ts +3 -3
  51. package/dist/jikji/installer.d.ts +11 -5
  52. package/dist/jikji/retry-command.d.ts +10 -0
  53. package/dist/jikji/types.d.ts +47 -1
  54. package/dist/jikji/version.d.ts +20 -0
  55. package/dist/mcp/index.js +6154 -2902
  56. package/dist/mcp/server.d.ts +3 -0
  57. package/dist/minsync/binary.d.ts +10 -5
  58. package/dist/minsync/client.d.ts +7 -10
  59. package/dist/minsync/embedder-config.d.ts +11 -10
  60. package/dist/minsync/errors.d.ts +3 -0
  61. package/dist/minsync/index.d.ts +1 -1
  62. package/dist/minsync/installer.d.ts +1 -1
  63. package/dist/minsync/method.d.ts +1 -0
  64. package/dist/minsync/types.d.ts +0 -9
  65. package/dist/minsync/version.d.ts +20 -0
  66. package/dist/mirror/cloud-fingerprints.d.ts +30 -0
  67. package/dist/mirror/cloud.d.ts +79 -0
  68. package/dist/mirror/index.d.ts +4 -0
  69. package/dist/mirror/sync.d.ts +79 -1
  70. package/dist/parser/csv.d.ts +26 -0
  71. package/dist/parser/defaults.d.ts +1 -1
  72. package/dist/parser/index.d.ts +2 -0
  73. package/dist/parser/kordoc.d.ts +6 -3
  74. package/dist/parser/parse-worker.js +668 -28
  75. package/dist/parser/spreadsheet-render.d.ts +53 -0
  76. package/dist/parser/spreadsheet.d.ts +27 -0
  77. package/dist/profiles/loop-guard.d.ts +8 -2
  78. package/dist/profiles/retrieval-tools.d.ts +2 -1
  79. package/dist/profiles.js +13520 -10280
  80. package/dist/retrieval/skip.d.ts +1 -1
  81. package/dist/retrieval/types.d.ts +1 -1
  82. package/package.json +3 -3
  83. package/skills/autorag/SKILL.md +7 -4
  84. package/skills/autorag-doctor/SKILL.md +8 -3
  85. package/skills/autorag-lite-setup/SKILL.md +4 -4
  86. package/skills/autorag-setup/SKILL.md +53 -30
  87. package/dist/datasource/skills/cloud-drive/index.d.ts +0 -2
  88. package/dist/datasource/skills/cloud-drive/rclone-connector.d.ts +0 -49
  89. package/dist/datasource/skills/cloud-drive/skill.d.ts +0 -14
  90. package/dist/minsync/kiwi.d.ts +0 -17
  91. package/dist/minsync/lexical-language.d.ts +0 -18
@@ -90,35 +90,340 @@ var init_language = __esm(() => {
90
90
  };
91
91
  });
92
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";
93
+ // src/parser/spreadsheet-render.ts
94
+ function estimateLineTokens(text) {
95
+ let halves = 0;
96
+ for (const char of text) {
97
+ const code = char.codePointAt(0) ?? 0;
98
+ halves += code < 128 ? 1 : code < 2048 ? 2 : 4;
99
+ }
100
+ return Math.ceil(halves / 2);
100
101
  }
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;
102
+ function classifyText(text) {
103
+ const trimmed = text.trim();
104
+ if (NUMBER_TEXT.test(trimmed))
105
+ return "number";
106
+ if (DATE_TEXT.test(trimmed))
107
+ return "date";
108
+ return "text";
109
+ }
110
+ function renderWorkbook(sheets) {
111
+ return sheets.map(renderSheet).join(`
112
+
113
+ `);
114
+ }
115
+
116
+ class SheetView {
117
+ rowCount;
118
+ colCount;
119
+ #grid;
120
+ #merges = new Map;
121
+ constructor(grid) {
122
+ this.#grid = grid;
123
+ this.rowCount = grid.rows.length;
124
+ const widest = grid.rows.reduce((max, row) => Math.max(max, row?.length ?? 0), 0);
125
+ const merges = (grid.merges ?? []).filter((merge) => merge.top < this.rowCount && merge.left < widest);
126
+ this.colCount = merges.reduce((max, merge) => Math.max(max, Math.min(merge.right, MAX_COLUMNS - 1) + 1), widest);
127
+ for (const merge of merges) {
128
+ const bottom = Math.min(merge.bottom, this.rowCount - 1);
129
+ const right = Math.min(merge.right, this.colCount - 1);
130
+ for (let row = merge.top;row <= bottom; row++) {
131
+ for (let col = merge.left;col <= right; col++)
132
+ this.#merges.set(row * COLUMN_STRIDE + col, merge);
133
+ }
112
134
  }
113
- };
114
- ParseIsolationError = class ParseIsolationError extends Error {
115
- code;
116
- constructor(code, message) {
117
- super(message);
118
- this.name = "ParseIsolationError";
119
- this.code = code;
135
+ }
136
+ resolve(row, col) {
137
+ const merge = this.#merges.get(row * COLUMN_STRIDE + col);
138
+ const anchorRow = merge?.top ?? row;
139
+ const anchorCol = merge?.left ?? col;
140
+ const cell = this.#grid.rows[anchorRow]?.[anchorCol];
141
+ if (cell === undefined || clean(cell.text) === "")
142
+ return;
143
+ return { cell, row: anchorRow, col: anchorCol, merge };
144
+ }
145
+ }
146
+ function renderSheet(grid) {
147
+ const view = new SheetView(grid);
148
+ const heading = `## ${grid.name}${grid.hidden === true ? " (hidden)" : ""}`;
149
+ const blocks = [];
150
+ let pendingCaptions = [];
151
+ let previous;
152
+ const bands = findBands(view);
153
+ for (const [index, band] of bands.entries()) {
154
+ const rows = range(band.top, band.bottom);
155
+ if (rows.every((row) => singleValue(view, row, band) !== undefined)) {
156
+ const next = bands[index + 1];
157
+ const captionsNext = next !== undefined && rows.length <= MAX_CAPTION_BLOCK_ROWS && next.top - band.bottom - 1 <= MAX_CAPTION_GAP_ROWS && !range(next.top, next.bottom).every((row) => singleValue(view, row, next) !== undefined);
158
+ if (captionsNext) {
159
+ pendingCaptions = rows.map((row) => singleValue(view, row, band));
160
+ continue;
161
+ }
162
+ blocks.push(rows.map((row) => `[${grid.name}!${cellRange(band.left, band.right, row)}] ${singleValue(view, row, band)}`).join(`
163
+ `));
164
+ continue;
165
+ }
166
+ let start = 0;
167
+ const ownCaptions = [];
168
+ while (start < rows.length && singleValue(view, rows[start], band) !== undefined) {
169
+ ownCaptions.push(singleValue(view, rows[start], band));
170
+ start++;
171
+ }
172
+ const body = rows.slice(start);
173
+ let captions = [...pendingCaptions, ...ownCaptions];
174
+ pendingCaptions = [];
175
+ const detected = detectHeader(view, band, body);
176
+ let header = detected?.header;
177
+ let dataRows = detected === undefined ? body : body.slice(detected.headerRows);
178
+ if (header === undefined && previous !== undefined && continuesTable(view, band, body, previous)) {
179
+ header = previous.header;
180
+ dataRows = body;
181
+ if (captions.length === 0)
182
+ captions = [...previous.captions];
183
+ }
184
+ if (header !== undefined)
185
+ previous = { band, header, captions };
186
+ const lines = dataRows.flatMap((row) => renderRow(grid.name, view, band, row, dataRows[0], header, captions));
187
+ if (lines.length > 0)
188
+ blocks.push(lines.join(`
189
+ `));
190
+ }
191
+ return [heading, ...blocks].join(`
192
+
193
+ `);
194
+ }
195
+ function findBands(view) {
196
+ const bands = [];
197
+ let current;
198
+ for (let row = 0;row < view.rowCount; row++) {
199
+ let left = Number.POSITIVE_INFINITY;
200
+ let right = Number.NEGATIVE_INFINITY;
201
+ for (let col = 0;col < view.colCount; col++) {
202
+ if (view.resolve(row, col) === undefined)
203
+ continue;
204
+ left = Math.min(left, col);
205
+ right = Math.max(right, col);
206
+ }
207
+ if (right < left) {
208
+ if (current !== undefined)
209
+ bands.push(current);
210
+ current = undefined;
211
+ continue;
212
+ }
213
+ if (current === undefined)
214
+ current = { top: row, bottom: row, left, right };
215
+ else {
216
+ current.bottom = row;
217
+ current.left = Math.min(current.left, left);
218
+ current.right = Math.max(current.right, right);
120
219
  }
220
+ }
221
+ if (current !== undefined)
222
+ bands.push(current);
223
+ return bands;
224
+ }
225
+ function rowValues(view, row, band) {
226
+ const values = [];
227
+ const seen = new Set;
228
+ for (let col = band.left;col <= band.right; col++) {
229
+ const resolved = view.resolve(row, col);
230
+ if (resolved === undefined)
231
+ continue;
232
+ const key = resolved.row * COLUMN_STRIDE + resolved.col;
233
+ if (seen.has(key))
234
+ continue;
235
+ seen.add(key);
236
+ values.push(resolved);
237
+ }
238
+ return values;
239
+ }
240
+ function singleValue(view, row, band) {
241
+ const values = rowValues(view, row, band);
242
+ return values.length === 1 ? clean(values[0].cell.text) : undefined;
243
+ }
244
+ function detectHeader(view, band, body) {
245
+ const [first, second] = body;
246
+ if (first === undefined)
247
+ return;
248
+ const firstValues = rowValues(view, first, band);
249
+ if (firstValues.length < 2 || !firstValues.every((value) => headerLike(value.cell)))
250
+ return;
251
+ const grouped = firstValues.some((value) => value.row === first && value.merge !== undefined && value.merge.right > value.merge.left);
252
+ if (grouped && second !== undefined && body.length >= 3) {
253
+ const childValues = rowValues(view, second, band).filter((value) => value.row === second);
254
+ if (childValues.length >= 2 && childValues.every((value) => headerLike(value.cell))) {
255
+ const labels = new Map;
256
+ for (let col = band.left;col <= band.right; col++) {
257
+ const parent = labelAt(view, first, col);
258
+ const child = labelAt(view, second, col);
259
+ const label = child !== "" && child !== parent ? parent === "" ? child : `${parent} > ${child}` : parent;
260
+ if (label !== "")
261
+ labels.set(col, label);
262
+ }
263
+ const data = body.slice(2);
264
+ return { header: { labels, typedColumns: typedColumns(view, band, data, MIN_TYPED_SHARE, 1) }, headerRows: 2 };
265
+ }
266
+ }
267
+ const data = body.slice(1);
268
+ if (data.length < MIN_HEADER_DATA_ROWS)
269
+ return;
270
+ const typed = typedColumns(view, band, data, MIN_TYPED_SHARE, MIN_HEADER_DATA_ROWS);
271
+ if (typed.length === 0)
272
+ return;
273
+ const labels = new Map;
274
+ for (let col = band.left;col <= band.right; col++) {
275
+ const label = labelAt(view, first, col);
276
+ if (label !== "")
277
+ labels.set(col, label);
278
+ }
279
+ return { header: { labels, typedColumns: typed }, headerRows: 1 };
280
+ }
281
+ function headerLike(cell) {
282
+ const text = clean(cell.text);
283
+ if (cell.kind === "number")
284
+ return YEAR_TEXT.test(text);
285
+ return cell.kind === "text" && text.length <= MAX_HEADER_CELL_CHARS;
286
+ }
287
+ function labelAt(view, row, col) {
288
+ const resolved = view.resolve(row, col);
289
+ return resolved === undefined ? "" : clean(resolved.cell.text);
290
+ }
291
+ function typedColumns(view, band, rows, share, minimum) {
292
+ const columns = [];
293
+ for (let col = band.left;col <= band.right; col++) {
294
+ let filled = 0;
295
+ let typed = 0;
296
+ for (const row of rows) {
297
+ const resolved = view.resolve(row, col);
298
+ if (resolved === undefined || resolved.col !== col)
299
+ continue;
300
+ filled++;
301
+ if (resolved.cell.kind !== "text")
302
+ typed++;
303
+ }
304
+ if (filled >= minimum && typed / filled >= share)
305
+ columns.push(col);
306
+ }
307
+ return columns;
308
+ }
309
+ function continuesTable(view, band, body, previous) {
310
+ if (band.left < previous.band.left || band.right > previous.band.right)
311
+ return false;
312
+ const columns = previous.header.typedColumns.filter((col) => col >= band.left && col <= band.right);
313
+ if (columns.length === 0)
314
+ return false;
315
+ const typed = typedColumns(view, band, body, MIN_TYPED_SHARE, 1);
316
+ return columns.every((col) => typed.includes(col));
317
+ }
318
+ function renderRow(sheet, view, band, row, firstDataRow, header, captions) {
319
+ const items = [];
320
+ let spanning;
321
+ for (let col = band.left;col <= band.right; col++) {
322
+ const resolved = view.resolve(row, col);
323
+ if (resolved === undefined || resolved.col !== col)
324
+ continue;
325
+ if (resolved.row !== row && (resolved.row < firstDataRow || !fillsDown(resolved.merge)))
326
+ continue;
327
+ const comment = resolved.row === row && resolved.cell.comment !== undefined ? clean(resolved.cell.comment) : "";
328
+ const text = clean(resolved.cell.text);
329
+ const value = comment === "" ? text : `${text} (comment: ${comment})`;
330
+ if (resolved.merge !== undefined && resolved.merge.right > resolved.merge.left)
331
+ spanning = col;
332
+ items.push(header === undefined ? { col, value } : { col, label: header.labels.get(col) ?? columnName(col), value });
333
+ }
334
+ if (items.length === 0)
335
+ return [];
336
+ const [only] = items;
337
+ if (items.length === 1 && only !== undefined && only.col === spanning)
338
+ items[0] = { col: only.col, value: only.value };
339
+ const caption = captionText(captions);
340
+ const prefix = (left, right) => `[${sheet}!${cellRange(left, right, row)}${caption}] `;
341
+ const whole = prefix(band.left, band.right) + items.map(itemText).join(" | ");
342
+ if (estimateLineTokens(whole) <= MAX_LINE_TOKENS)
343
+ return [whole];
344
+ return splitRow(items, prefix);
345
+ }
346
+ function splitRow(items, prefix) {
347
+ const [key, ...rest] = items;
348
+ const keyText = itemText(key);
349
+ const lines = [];
350
+ let piece = [];
351
+ const flush = () => {
352
+ if (piece.length === 0)
353
+ return;
354
+ const head = lines.length === 0 ? "" : `${keyText} | `;
355
+ const first = lines.length === 0 ? key : piece[0];
356
+ lines.push(prefix(first.col, piece.at(-1).col) + head + piece.map(itemText).join(" | "));
357
+ piece = [];
121
358
  };
359
+ piece.push(key);
360
+ for (const item of rest) {
361
+ for (const part of fitItem(item, prefix, keyText)) {
362
+ const candidate = [...piece, part];
363
+ const head = lines.length === 0 ? "" : `${keyText} | `;
364
+ const start = lines.length === 0 ? key : candidate[0];
365
+ const text = prefix(start.col, part.col) + head + candidate.map(itemText).join(" | ");
366
+ if (piece.length > 0 && estimateLineTokens(text) > MAX_LINE_TOKENS)
367
+ flush();
368
+ piece.push(part);
369
+ }
370
+ }
371
+ flush();
372
+ return lines;
373
+ }
374
+ function fitItem(item, prefix, keyText) {
375
+ const overhead = estimateLineTokens(`${prefix(item.col, item.col)}${keyText} | ${item.label ?? ""}: `);
376
+ const budget = Math.max(16, MAX_LINE_TOKENS - overhead);
377
+ if (estimateLineTokens(item.value) <= budget)
378
+ return [item];
379
+ const parts = [];
380
+ let current = "";
381
+ for (const char of item.value) {
382
+ if (current !== "" && estimateLineTokens(current + char) > budget) {
383
+ parts.push({ ...item, value: current });
384
+ current = "";
385
+ }
386
+ current += char;
387
+ }
388
+ if (current !== "")
389
+ parts.push({ ...item, value: current });
390
+ return parts;
391
+ }
392
+ function fillsDown(merge) {
393
+ return merge !== undefined && merge.left === merge.right;
394
+ }
395
+ function itemText(item) {
396
+ return item.label === undefined ? item.value : `${item.label}: ${item.value}`;
397
+ }
398
+ function captionText(captions) {
399
+ if (captions.length === 0)
400
+ return "";
401
+ const joined = captions.join(" · ");
402
+ return ` · ${joined.length > MAX_CAPTION_CHARS ? `${joined.slice(0, MAX_CAPTION_CHARS - 1)}…` : joined}`;
403
+ }
404
+ function clean(text) {
405
+ return text.trim().replace(/\s*(?:\r\n|\r|\n)\s*/g, " / ").replace(/[\t\f\v]+/g, " ").replace(/\p{Cc}/gu, "");
406
+ }
407
+ function cellRange(left, right, row) {
408
+ const start = `${columnName(left)}${row + 1}`;
409
+ return left === right ? start : `${start}:${columnName(right)}${row + 1}`;
410
+ }
411
+ function columnName(col) {
412
+ let name = "";
413
+ for (let rest = col + 1;rest > 0; rest = Math.floor((rest - 1) / 26)) {
414
+ name = String.fromCharCode(65 + (rest - 1) % 26) + name;
415
+ }
416
+ return name;
417
+ }
418
+ function range(first, last) {
419
+ return Array.from({ length: last - first + 1 }, (_, index) => first + index);
420
+ }
421
+ var MAX_LINE_TOKENS = 768, MIN_HEADER_DATA_ROWS = 3, MIN_TYPED_SHARE = 0.8, MAX_COLUMNS = 16384, MAX_HEADER_CELL_CHARS = 60, MAX_CAPTION_CHARS = 120, MAX_CAPTION_BLOCK_ROWS = 3, MAX_CAPTION_GAP_ROWS = 2, COLUMN_STRIDE, NUMBER_TEXT, DATE_TEXT, YEAR_TEXT;
422
+ var init_spreadsheet_render = __esm(() => {
423
+ COLUMN_STRIDE = 1 << 20;
424
+ NUMBER_TEXT = /^[-+]?[₩$€£¥]?\s?(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?\s?(?:%|원|천원|만원|백만원|억원)?$|^[-+]?\.\d+%?$/;
425
+ DATE_TEXT = /^\d{4}[-./]\d{1,2}(?:[-./]\d{1,2})?\.?$/;
426
+ YEAR_TEXT = /^(?:19|20)\d{2}$/;
122
427
  });
123
428
 
124
429
  // src/parser/text.ts
@@ -167,6 +472,194 @@ class Parser {
167
472
  version = "1";
168
473
  }
169
474
 
475
+ // src/parser/csv.ts
476
+ import { basename, extname } from "node:path";
477
+ function toCell(text) {
478
+ return text.trim() === "" ? undefined : { text, kind: classifyText(text) };
479
+ }
480
+ function parseRows(text, delimiter, maxRows) {
481
+ const rows = [];
482
+ let total = 0;
483
+ let row = [];
484
+ let index = 0;
485
+ while (index < text.length) {
486
+ let field;
487
+ if (text[index] === '"') {
488
+ const quoted = readQuoted(text, index + 1);
489
+ const end = nextBoundary(text, quoted.end, delimiter);
490
+ field = quoted.value + text.slice(quoted.end, end);
491
+ index = end;
492
+ } else {
493
+ const end = nextBoundary(text, index, delimiter);
494
+ field = text.slice(index, end);
495
+ index = end;
496
+ }
497
+ row.push(field);
498
+ if (index >= text.length)
499
+ break;
500
+ if (text[index] === delimiter) {
501
+ index++;
502
+ if (index >= text.length)
503
+ row.push("");
504
+ continue;
505
+ }
506
+ index += text[index] === "\r" && text[index + 1] === `
507
+ ` ? 2 : 1;
508
+ if (total < maxRows)
509
+ rows.push(row);
510
+ total++;
511
+ row = [];
512
+ }
513
+ if (row.length > 0) {
514
+ if (total < maxRows)
515
+ rows.push(row);
516
+ total++;
517
+ }
518
+ return { rows, total };
519
+ }
520
+ function readQuoted(text, start) {
521
+ let value = "";
522
+ let cursor = start;
523
+ for (;; ) {
524
+ const quote = text.indexOf('"', cursor);
525
+ if (quote === -1)
526
+ return { value: value + text.slice(cursor), end: text.length };
527
+ value += text.slice(cursor, quote);
528
+ if (text[quote + 1] !== '"')
529
+ return { value, end: quote + 1 };
530
+ value += '"';
531
+ cursor = quote + 2;
532
+ }
533
+ }
534
+ function nextBoundary(text, from, delimiter) {
535
+ for (let index = from;index < text.length; index++) {
536
+ const char = text[index];
537
+ if (char === delimiter || char === `
538
+ ` || char === "\r")
539
+ return index;
540
+ }
541
+ return text.length;
542
+ }
543
+ function sniffDelimiter(text) {
544
+ const lines = leadingLines(text);
545
+ let best = CSV_DELIMITERS[0];
546
+ let bestScore = 0;
547
+ for (const candidate of CSV_DELIMITERS) {
548
+ const counts = lines.map((line) => countOutsideQuotes(line, candidate));
549
+ const first = counts[0] ?? 0;
550
+ if (first === 0)
551
+ continue;
552
+ const score = counts.filter((count) => count === first).length;
553
+ if (score > bestScore) {
554
+ best = candidate;
555
+ bestScore = score;
556
+ }
557
+ }
558
+ return best;
559
+ }
560
+ function leadingLines(text) {
561
+ const lines = [];
562
+ let start = 0;
563
+ let quoted = false;
564
+ for (let index = 0;index < text.length && lines.length < SNIFF_LINES; index++) {
565
+ const char = text[index];
566
+ if (char === '"')
567
+ quoted = !quoted;
568
+ else if (!quoted && (char === `
569
+ ` || char === "\r")) {
570
+ if (index > start)
571
+ lines.push(text.slice(start, index));
572
+ start = index + 1;
573
+ }
574
+ }
575
+ if (lines.length < SNIFF_LINES && start < text.length)
576
+ lines.push(text.slice(start));
577
+ return lines;
578
+ }
579
+ function countOutsideQuotes(line, delimiter) {
580
+ let count = 0;
581
+ let quoted = false;
582
+ for (const char of line) {
583
+ if (char === '"')
584
+ quoted = !quoted;
585
+ else if (!quoted && char === delimiter)
586
+ count++;
587
+ }
588
+ return count;
589
+ }
590
+ var DELIMITED_EXTENSIONS, DEFAULT_MAX_ROWS = 1e5, SNIFF_LINES = 50, CSV_DELIMITERS, SEPARATOR_DIRECTIVE, CsvParser;
591
+ var init_csv = __esm(() => {
592
+ init_spreadsheet_render();
593
+ init_text();
594
+ DELIMITED_EXTENSIONS = [".csv", ".tsv"];
595
+ CSV_DELIMITERS = [",", ";", "\t", "|"];
596
+ SEPARATOR_DIRECTIVE = /^sep=(.)\r?\n/i;
597
+ CsvParser = class CsvParser extends Parser {
598
+ name = "csv";
599
+ extensions = DELIMITED_EXTENSIONS;
600
+ version = "2";
601
+ #maxRows;
602
+ constructor(options = {}) {
603
+ super();
604
+ this.#maxRows = options.maxRows ?? DEFAULT_MAX_ROWS;
605
+ }
606
+ async parse(input) {
607
+ const extension = extname(input.virtualPath);
608
+ const format = extension.slice(1).toLowerCase();
609
+ let text = decodeText(input.bytes).replace(/^\uFEFF/, "");
610
+ const directive = SEPARATOR_DIRECTIVE.exec(text);
611
+ if (directive !== null)
612
+ text = text.slice(directive[0].length);
613
+ const delimiter = directive?.[1] ?? (format === "tsv" ? "\t" : sniffDelimiter(text));
614
+ const { rows, total } = parseRows(text, delimiter, this.#maxRows);
615
+ const diagnostics = total > this.#maxRows ? [
616
+ {
617
+ code: "parser-warning",
618
+ severity: "warning",
619
+ message: `"${basename(input.virtualPath)}": indexed the first ${this.#maxRows} of ${total} rows`
620
+ }
621
+ ] : [];
622
+ const grid = { name: basename(input.virtualPath, extension), rows: rows.map((row) => row.map(toCell)) };
623
+ return {
624
+ markdown: normalizeMarkdown(renderWorkbook([grid])),
625
+ metadata: { parser: this.name, format },
626
+ ...diagnostics.length > 0 ? { diagnostics } : {}
627
+ };
628
+ }
629
+ };
630
+ });
631
+
632
+ // src/parser/errors.ts
633
+ function messageFrom(cause) {
634
+ if (cause instanceof Error)
635
+ return cause.message;
636
+ if (typeof cause === "string")
637
+ return cause;
638
+ return "unknown parser failure";
639
+ }
640
+ var ParseError, ParseIsolationError;
641
+ var init_errors = __esm(() => {
642
+ ParseError = class ParseError extends Error {
643
+ parserName;
644
+ virtualPath;
645
+ constructor(parserName, virtualPath, cause) {
646
+ super(`Parser "${parserName}" failed for ${virtualPath}: ${messageFrom(cause)}`);
647
+ this.name = "ParseError";
648
+ this.parserName = parserName;
649
+ this.virtualPath = virtualPath;
650
+ this.cause = cause;
651
+ }
652
+ };
653
+ ParseIsolationError = class ParseIsolationError extends Error {
654
+ code;
655
+ constructor(code, message) {
656
+ super(message);
657
+ this.name = "ParseIsolationError";
658
+ this.code = code;
659
+ }
660
+ };
661
+ });
662
+
170
663
  // src/parser/eml.ts
171
664
  import { simpleParser } from "mailparser";
172
665
  function addressText(address) {
@@ -250,7 +743,7 @@ var KORDOC_VERSION, KORDOC_EXTENSIONS, KORDOC_IMAGE_EXTENSIONS, defaultParse = a
250
743
  var init_kordoc = __esm(() => {
251
744
  init_errors();
252
745
  KORDOC_VERSION = installedKordocVersion();
253
- KORDOC_EXTENSIONS = [".hwp", ".hwpx", ".hml", ".hwpml", ".pdf", ".docx", ".xlsx", ".xls"];
746
+ KORDOC_EXTENSIONS = [".hwp", ".hwpx", ".hml", ".hwpml", ".pdf", ".docx"];
254
747
  KORDOC_IMAGE_EXTENSIONS = [".png", ".jpg", ".jpeg", ".webp"];
255
748
  KordocParser = class KordocParser extends Parser {
256
749
  name = "kordoc";
@@ -665,7 +1158,7 @@ var init_plain_text = __esm(() => {
665
1158
  });
666
1159
 
667
1160
  // src/parser/registry.ts
668
- import { extname } from "node:path";
1161
+ import { extname as extname2 } from "node:path";
669
1162
 
670
1163
  class ParserRegistry {
671
1164
  parsersByExtension = new Map;
@@ -684,7 +1177,7 @@ class ParserRegistry {
684
1177
  }
685
1178
  }
686
1179
  getForVirtualPath(virtualPath) {
687
- return this.parsersByExtension.get(normalizeExtension(extname(virtualPath)));
1180
+ return this.parsersByExtension.get(normalizeExtension(extname2(virtualPath)));
688
1181
  }
689
1182
  list() {
690
1183
  return Array.from(new Set(this.parsersByExtension.values()));
@@ -696,6 +1189,149 @@ function normalizeExtension(extension) {
696
1189
  }
697
1190
  var init_registry = () => {};
698
1191
 
1192
+ // src/parser/spreadsheet.ts
1193
+ import { extname as extname3 } from "node:path";
1194
+ import * as XLSX from "xlsx";
1195
+ function assertWorkbookSignature(format, bytes) {
1196
+ if (startsWith(bytes, ZIP_SIGNATURE) || startsWith(bytes, OLE_SIGNATURE))
1197
+ return;
1198
+ const head = new TextDecoder().decode(bytes.subarray(0, 64)).replace(/^\uFEFF/, "").trimStart();
1199
+ if (!head.startsWith("<")) {
1200
+ throw new Error(`not a ${format} workbook: neither a ZIP or OLE2 file nor HTML/XML markup`);
1201
+ }
1202
+ }
1203
+ function startsWith(bytes, prefix) {
1204
+ return prefix.every((byte, index) => bytes[index] === byte);
1205
+ }
1206
+ function toGrid(name, sheet, hidden, date1904) {
1207
+ const data = sheet?.["!data"] ?? [];
1208
+ return {
1209
+ name,
1210
+ hidden: hidden !== undefined && hidden !== 0,
1211
+ rows: data.map((row) => row?.map((cell) => cell === undefined ? undefined : toCell2(cell, date1904))),
1212
+ merges: (sheet?.["!merges"] ?? []).map((merge) => ({
1213
+ top: merge.s.r,
1214
+ left: merge.s.c,
1215
+ bottom: merge.e.r,
1216
+ right: merge.e.c
1217
+ }))
1218
+ };
1219
+ }
1220
+ function toCell2(cell, date1904) {
1221
+ const comment = (cell.c ?? []).map((note) => note.t?.trim() ?? "").filter((text) => text !== "").join(" / ");
1222
+ const shown = displayed(cell, date1904);
1223
+ if (shown === undefined)
1224
+ return;
1225
+ return comment === "" ? shown : { ...shown, comment };
1226
+ }
1227
+ function displayed(cell, date1904) {
1228
+ if (cell.v === undefined || cell.v === null) {
1229
+ return cell.f === undefined ? undefined : { text: `=${cell.f}`, kind: "formula" };
1230
+ }
1231
+ switch (cell.t) {
1232
+ case "n":
1233
+ return typeof cell.v === "number" ? formatNumber(cell.v, cell.z, date1904) : textCell(String(cell.v));
1234
+ case "b":
1235
+ return { text: cell.v === true ? "TRUE" : "FALSE", kind: "boolean" };
1236
+ case "e":
1237
+ return { text: cell.w ?? "#ERROR", kind: "error" };
1238
+ case "d":
1239
+ return { text: cell.w ?? String(cell.v), kind: "date" };
1240
+ case "z":
1241
+ return;
1242
+ default:
1243
+ return textCell(String(cell.v));
1244
+ }
1245
+ }
1246
+ function textCell(text) {
1247
+ return text.trim() === "" ? undefined : { text, kind: classifyText(text) };
1248
+ }
1249
+ function formatNumber(value, format, date1904) {
1250
+ const plain = formatGeneral(value);
1251
+ const code = typeof format === "string" ? format : format === undefined ? "General" : XLSX.SSF.get_table()[format];
1252
+ if (code === undefined || code === "General" || /\[DBNum\d\]/i.test(code))
1253
+ return { text: plain, kind: "number" };
1254
+ const kind = XLSX.SSF.is_date(code) ? "date" : "number";
1255
+ let shown;
1256
+ try {
1257
+ shown = XLSX.SSF.format(code, value, { date1904 }).trim();
1258
+ } catch {
1259
+ return { text: plain, kind };
1260
+ }
1261
+ if (shown === "")
1262
+ return { text: plain, kind };
1263
+ return { text: kind === "number" && hidesMagnitude(code) ? `${shown} (${plain})` : shown, kind };
1264
+ }
1265
+ function formatGeneral(value) {
1266
+ if (Number.isInteger(value))
1267
+ return String(value);
1268
+ return String(Number(value.toPrecision(15)));
1269
+ }
1270
+ function hidesMagnitude(code) {
1271
+ const bare = code.replace(/"[^"]*"/g, "").replace(/\\./g, "").replace(/\[[^\]]*\]/g, "");
1272
+ return /[0#?],+(?![0#?,])/.test(bare);
1273
+ }
1274
+ var SPREADSHEET_EXTENSIONS, DEFAULT_MAX_ROWS_PER_SHEET = 1e5, ZIP_SIGNATURE, OLE_SIGNATURE, SpreadsheetParser;
1275
+ var init_spreadsheet = __esm(() => {
1276
+ init_errors();
1277
+ init_spreadsheet_render();
1278
+ init_text();
1279
+ SPREADSHEET_EXTENSIONS = [".xlsx", ".xlsm", ".xlsb", ".xls", ".ods"];
1280
+ ZIP_SIGNATURE = [80, 75];
1281
+ OLE_SIGNATURE = [208, 207, 17, 224, 161, 177, 26, 225];
1282
+ SpreadsheetParser = class SpreadsheetParser extends Parser {
1283
+ name = "spreadsheet";
1284
+ extensions = SPREADSHEET_EXTENSIONS;
1285
+ version = `2+sheetjs-${XLSX.version}`;
1286
+ #maxRowsPerSheet;
1287
+ constructor(options = {}) {
1288
+ super();
1289
+ this.#maxRowsPerSheet = options.maxRowsPerSheet ?? DEFAULT_MAX_ROWS_PER_SHEET;
1290
+ }
1291
+ async parse(input) {
1292
+ const format = extname3(input.virtualPath).slice(1).toLowerCase();
1293
+ let workbook;
1294
+ try {
1295
+ assertWorkbookSignature(format, input.bytes);
1296
+ workbook = XLSX.read(input.bytes, {
1297
+ type: "array",
1298
+ dense: true,
1299
+ cellFormula: true,
1300
+ cellNF: true,
1301
+ cellDates: false,
1302
+ sheetRows: this.#maxRowsPerSheet,
1303
+ raw: true
1304
+ });
1305
+ } catch (cause) {
1306
+ throw new ParseError(this.name, input.virtualPath, cause);
1307
+ }
1308
+ const date1904 = workbook.Workbook?.WBProps?.date1904 === true;
1309
+ const diagnostics = [];
1310
+ const grids = workbook.SheetNames.map((name, index) => {
1311
+ const sheet = workbook.Sheets[name];
1312
+ const fullRef = sheet?.["!fullref"];
1313
+ if (fullRef !== undefined) {
1314
+ const full = XLSX.utils.decode_range(fullRef);
1315
+ const total = full.e.r - full.s.r + 1;
1316
+ if (total > this.#maxRowsPerSheet) {
1317
+ diagnostics.push({
1318
+ code: "parser-warning",
1319
+ severity: "warning",
1320
+ message: `sheet "${name}": indexed the first ${this.#maxRowsPerSheet} of ${total} rows`
1321
+ });
1322
+ }
1323
+ }
1324
+ return toGrid(name, sheet, workbook.Workbook?.Sheets?.[index]?.Hidden, date1904);
1325
+ });
1326
+ return {
1327
+ markdown: normalizeMarkdown(renderWorkbook(grids)),
1328
+ metadata: { parser: this.name, format },
1329
+ ...diagnostics.length > 0 ? { diagnostics } : {}
1330
+ };
1331
+ }
1332
+ };
1333
+ });
1334
+
699
1335
  // src/parser/defaults.ts
700
1336
  import { join as join2 } from "node:path";
701
1337
  function tesseractCachePathFor(workspacePath) {
@@ -726,18 +1362,22 @@ function createDefaultParserRegistry(options = {}) {
726
1362
  return new ParserRegistry([
727
1363
  new PlainTextParser,
728
1364
  new KordocParser(kordocOptions),
1365
+ new SpreadsheetParser,
1366
+ new CsvParser,
729
1367
  new PptxParser,
730
1368
  new EmlParser
731
1369
  ]);
732
1370
  }
733
1371
  var init_defaults = __esm(() => {
734
1372
  init_language();
1373
+ init_csv();
735
1374
  init_eml();
736
1375
  init_kordoc();
737
1376
  init_ocr_engines();
738
1377
  init_office();
739
1378
  init_plain_text();
740
1379
  init_registry();
1380
+ init_spreadsheet();
741
1381
  });
742
1382
 
743
1383
  // src/parser/parse-worker.ts