@anuma/sdk 6.26.0 → 6.26.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/expo/index.cjs +72 -2
- package/dist/expo/index.d.mts +93 -1
- package/dist/expo/index.d.ts +93 -1
- package/dist/expo/index.mjs +68 -2
- package/dist/index.cjs +68 -0
- package/dist/index.d.mts +80 -1
- package/dist/index.d.ts +80 -1
- package/dist/index.mjs +64 -0
- package/dist/react/index.cjs +523 -127
- package/dist/react/index.d.mts +333 -206
- package/dist/react/index.d.ts +333 -206
- package/dist/react/index.mjs +519 -127
- package/dist/server/index.cjs +440 -121
- package/dist/server/index.d.mts +85 -7
- package/dist/server/index.d.ts +85 -7
- package/dist/server/index.mjs +439 -121
- package/package.json +1 -1
package/dist/server/index.mjs
CHANGED
|
@@ -18539,6 +18539,15 @@ async function assembleDecryptedMessage(message, address) {
|
|
|
18539
18539
|
// src/lib/db/chat/types.ts
|
|
18540
18540
|
import { v7 as uuidv7 } from "uuid";
|
|
18541
18541
|
|
|
18542
|
+
// src/lib/chat/fileContext.ts
|
|
18543
|
+
var ATTACHED_FILES_OPEN_TAG = "<attached_files>";
|
|
18544
|
+
var ATTACHED_FILES_CLOSE_TAG = "</attached_files>";
|
|
18545
|
+
var ATTACHED_FILES_PREFIX = `${ATTACHED_FILES_OPEN_TAG}
|
|
18546
|
+
The user attached the following file(s) to this message. Their extracted contents are below; when the user refers to "the attached file", "this file" or "the document", they mean these.`;
|
|
18547
|
+
function isAttachedFilesText(text12) {
|
|
18548
|
+
return typeof text12 === "string" && text12.startsWith(ATTACHED_FILES_PREFIX) && text12.endsWith(ATTACHED_FILES_CLOSE_TAG);
|
|
18549
|
+
}
|
|
18550
|
+
|
|
18542
18551
|
// src/lib/chat/useChat/strategies/types.ts
|
|
18543
18552
|
function isChatCompletionResponse(r) {
|
|
18544
18553
|
if (r.object === "response") return false;
|
|
@@ -32166,14 +32175,37 @@ var WalletPoller = class {
|
|
|
32166
32175
|
if (typeof process !== "undefined" && typeof process.umask !== "function") {
|
|
32167
32176
|
process.umask = (_mask) => 18;
|
|
32168
32177
|
}
|
|
32178
|
+
var MAX_ROWS_PER_SHEET = 2e3;
|
|
32179
|
+
function csvField(value) {
|
|
32180
|
+
return /[",\r\n]/.test(value) ? `"${value.replace(/"/g, '""')}"` : value;
|
|
32181
|
+
}
|
|
32182
|
+
function uniqueHeaders(raw, columnCount) {
|
|
32183
|
+
const bases = [];
|
|
32184
|
+
for (let col = 1; col <= columnCount; col++) bases.push(raw[col]?.trim() || `Column${col}`);
|
|
32185
|
+
const taken = new Set(bases);
|
|
32186
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
32187
|
+
return bases.map((base) => {
|
|
32188
|
+
if (!emitted.has(base)) {
|
|
32189
|
+
emitted.add(base);
|
|
32190
|
+
return base;
|
|
32191
|
+
}
|
|
32192
|
+
let n = 2;
|
|
32193
|
+
while (taken.has(`${base}_${n}`)) n++;
|
|
32194
|
+
const name = `${base}_${n}`;
|
|
32195
|
+
taken.add(name);
|
|
32196
|
+
emitted.add(name);
|
|
32197
|
+
return name;
|
|
32198
|
+
});
|
|
32199
|
+
}
|
|
32169
32200
|
var ExcelProcessor = class {
|
|
32170
|
-
constructor() {
|
|
32201
|
+
constructor(options = {}) {
|
|
32171
32202
|
this.name = "excel";
|
|
32172
32203
|
this.supportedMimeTypes = [
|
|
32173
32204
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
32174
32205
|
// .xlsx
|
|
32175
32206
|
];
|
|
32176
32207
|
this.supportedExtensions = [".xlsx"];
|
|
32208
|
+
this.maxRowsPerSheet = options.maxRowsPerSheet ?? MAX_ROWS_PER_SHEET;
|
|
32177
32209
|
}
|
|
32178
32210
|
async loadExcelJS() {
|
|
32179
32211
|
const mod = await import("exceljs");
|
|
@@ -32188,31 +32220,51 @@ var ExcelProcessor = class {
|
|
|
32188
32220
|
if (workbook.worksheets.length === 0) {
|
|
32189
32221
|
return null;
|
|
32190
32222
|
}
|
|
32191
|
-
|
|
32223
|
+
let truncated = false;
|
|
32224
|
+
const sections = [];
|
|
32192
32225
|
for (const worksheet of workbook.worksheets) {
|
|
32193
|
-
const
|
|
32194
|
-
|
|
32195
|
-
|
|
32196
|
-
|
|
32197
|
-
|
|
32226
|
+
const rawHeaders = [];
|
|
32227
|
+
let columnCount = 0;
|
|
32228
|
+
worksheet.getRow(1).eachCell({ includeEmpty: true }, (cell, colNumber) => {
|
|
32229
|
+
rawHeaders[colNumber] = cell.text;
|
|
32230
|
+
columnCount = Math.max(columnCount, colNumber);
|
|
32198
32231
|
});
|
|
32232
|
+
const rows = [];
|
|
32233
|
+
let totalRows = 0;
|
|
32199
32234
|
worksheet.eachRow({ includeEmpty: false }, (row, rowNumber) => {
|
|
32200
32235
|
if (rowNumber === 1) return;
|
|
32201
|
-
|
|
32236
|
+
totalRows++;
|
|
32237
|
+
if (rows.length >= this.maxRowsPerSheet) return;
|
|
32238
|
+
const values = [];
|
|
32202
32239
|
row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
|
|
32203
|
-
|
|
32204
|
-
|
|
32240
|
+
values[colNumber - 1] = String(this.resolveCellValue(cell.value));
|
|
32241
|
+
columnCount = Math.max(columnCount, colNumber);
|
|
32205
32242
|
});
|
|
32206
|
-
rows.push(
|
|
32243
|
+
rows.push(values);
|
|
32207
32244
|
});
|
|
32208
|
-
|
|
32245
|
+
const headers = uniqueHeaders(rawHeaders, columnCount);
|
|
32246
|
+
const lines = [headers, ...rows].map(
|
|
32247
|
+
(values) => headers.map((_, i) => csvField(values[i] ?? "")).join(",")
|
|
32248
|
+
);
|
|
32249
|
+
let section = `## Sheet: ${worksheet.name}
|
|
32250
|
+
|
|
32251
|
+
\`\`\`csv
|
|
32252
|
+
${lines.join("\n")}
|
|
32253
|
+
\`\`\``;
|
|
32254
|
+
if (totalRows > rows.length) {
|
|
32255
|
+
truncated = true;
|
|
32256
|
+
section += `
|
|
32257
|
+
[truncated: showing the first ${rows.length} of ${totalRows} data rows of sheet "${worksheet.name}"]`;
|
|
32258
|
+
}
|
|
32259
|
+
sections.push(section);
|
|
32209
32260
|
}
|
|
32210
32261
|
return {
|
|
32211
|
-
extractedText:
|
|
32212
|
-
format: "
|
|
32262
|
+
extractedText: sections.join("\n\n"),
|
|
32263
|
+
format: "markdown",
|
|
32213
32264
|
metadata: {
|
|
32214
32265
|
sheetCount: workbook.worksheets.length,
|
|
32215
|
-
sheetNames: workbook.worksheets.map((ws) => ws.name)
|
|
32266
|
+
sheetNames: workbook.worksheets.map((ws) => ws.name),
|
|
32267
|
+
truncated
|
|
32216
32268
|
}
|
|
32217
32269
|
};
|
|
32218
32270
|
} catch (error) {
|
|
@@ -32238,6 +32290,9 @@ var ExcelProcessor = class {
|
|
|
32238
32290
|
// src/lib/pdf.ts
|
|
32239
32291
|
var pdfjsModule = null;
|
|
32240
32292
|
var workerConfigured = false;
|
|
32293
|
+
var RENDER_SCALE = 1.5;
|
|
32294
|
+
var MAX_RENDER_SIDE_PX = 1600;
|
|
32295
|
+
var JPEG_QUALITY = 0.8;
|
|
32241
32296
|
async function getPdfjs() {
|
|
32242
32297
|
if (!pdfjsModule) {
|
|
32243
32298
|
pdfjsModule = await import("pdfjs-dist");
|
|
@@ -32248,46 +32303,126 @@ async function getPdfjs() {
|
|
|
32248
32303
|
}
|
|
32249
32304
|
return pdfjsModule;
|
|
32250
32305
|
}
|
|
32251
|
-
async function
|
|
32306
|
+
async function withPdfDocument(pdfDataUrl, fn) {
|
|
32252
32307
|
const pdfjs = await getPdfjs();
|
|
32253
32308
|
const loadingTask = pdfjs.getDocument(pdfDataUrl);
|
|
32254
|
-
|
|
32255
|
-
|
|
32256
|
-
|
|
32257
|
-
|
|
32258
|
-
|
|
32259
|
-
|
|
32260
|
-
|
|
32261
|
-
|
|
32262
|
-
|
|
32309
|
+
let pdf;
|
|
32310
|
+
try {
|
|
32311
|
+
pdf = await loadingTask.promise;
|
|
32312
|
+
} catch (error) {
|
|
32313
|
+
await loadingTask.destroy().catch(() => void 0);
|
|
32314
|
+
throw error;
|
|
32315
|
+
}
|
|
32316
|
+
try {
|
|
32317
|
+
return await fn(pdf);
|
|
32318
|
+
} finally {
|
|
32319
|
+
await pdf.destroy().catch(() => void 0);
|
|
32263
32320
|
}
|
|
32264
|
-
return textParts.join("\n\n");
|
|
32265
32321
|
}
|
|
32266
|
-
|
|
32267
|
-
|
|
32268
|
-
const
|
|
32269
|
-
|
|
32270
|
-
|
|
32271
|
-
|
|
32272
|
-
|
|
32273
|
-
|
|
32274
|
-
|
|
32275
|
-
|
|
32276
|
-
|
|
32277
|
-
|
|
32278
|
-
|
|
32279
|
-
|
|
32280
|
-
|
|
32281
|
-
|
|
32282
|
-
|
|
32283
|
-
|
|
32284
|
-
|
|
32285
|
-
|
|
32286
|
-
|
|
32322
|
+
function joinPdfTextItems(items) {
|
|
32323
|
+
let text12 = "";
|
|
32324
|
+
for (const item of items) {
|
|
32325
|
+
if (!("str" in item)) continue;
|
|
32326
|
+
const { str, hasEOL } = item;
|
|
32327
|
+
text12 += str + (hasEOL ? "\n" : " ");
|
|
32328
|
+
}
|
|
32329
|
+
return text12.replace(/[ \t]+\n/g, "\n").trim();
|
|
32330
|
+
}
|
|
32331
|
+
function computeRenderScale(width, height) {
|
|
32332
|
+
const longest = Math.max(width, height);
|
|
32333
|
+
if (!(longest > 0)) return RENDER_SCALE;
|
|
32334
|
+
return Math.min(RENDER_SCALE, MAX_RENDER_SIDE_PX / longest);
|
|
32335
|
+
}
|
|
32336
|
+
async function extractPdfPageTexts(pdfDataUrl) {
|
|
32337
|
+
return withPdfDocument(pdfDataUrl, async (pdf) => {
|
|
32338
|
+
const pageTexts = [];
|
|
32339
|
+
for (let i = 1; i <= pdf.numPages; i++) {
|
|
32340
|
+
const page = await pdf.getPage(i);
|
|
32341
|
+
const textContent = await page.getTextContent();
|
|
32342
|
+
pageTexts.push(joinPdfTextItems(textContent.items));
|
|
32343
|
+
}
|
|
32344
|
+
return pageTexts;
|
|
32345
|
+
});
|
|
32346
|
+
}
|
|
32347
|
+
async function renderPdfPages(pdfDataUrl, maxPages, pageNumbers) {
|
|
32348
|
+
return withPdfDocument(pdfDataUrl, async (pdf) => {
|
|
32349
|
+
const requested = pageNumbers?.filter((n) => n >= 1 && n <= pdf.numPages) ?? Array.from(
|
|
32350
|
+
{ length: maxPages !== void 0 ? Math.min(maxPages, pdf.numPages) : pdf.numPages },
|
|
32351
|
+
(_, i) => i + 1
|
|
32352
|
+
);
|
|
32353
|
+
const pages = [];
|
|
32354
|
+
for (const pageNumber of requested) {
|
|
32355
|
+
const page = await pdf.getPage(pageNumber);
|
|
32356
|
+
const base = page.getViewport({ scale: 1 });
|
|
32357
|
+
const viewport = page.getViewport({ scale: computeRenderScale(base.width, base.height) });
|
|
32358
|
+
const canvas = document.createElement("canvas");
|
|
32359
|
+
const context = canvas.getContext("2d");
|
|
32360
|
+
if (!context) continue;
|
|
32361
|
+
canvas.height = Math.floor(viewport.height);
|
|
32362
|
+
canvas.width = Math.floor(viewport.width);
|
|
32363
|
+
context.fillStyle = "#ffffff";
|
|
32364
|
+
context.fillRect(0, 0, canvas.width, canvas.height);
|
|
32365
|
+
await page.render({
|
|
32366
|
+
canvasContext: context,
|
|
32367
|
+
viewport,
|
|
32368
|
+
background: "#ffffff"
|
|
32369
|
+
}).promise;
|
|
32370
|
+
pages.push({ pageNumber, dataUrl: canvas.toDataURL("image/jpeg", JPEG_QUALITY) });
|
|
32371
|
+
canvas.width = 0;
|
|
32372
|
+
canvas.height = 0;
|
|
32373
|
+
}
|
|
32374
|
+
return { pages, pageCount: pdf.numPages };
|
|
32375
|
+
});
|
|
32287
32376
|
}
|
|
32288
32377
|
|
|
32289
32378
|
// src/lib/processors/PdfProcessor.ts
|
|
32290
32379
|
var MAX_IMAGE_PAGES = 20;
|
|
32380
|
+
var MIN_PAGE_TEXT_CHARS = 20;
|
|
32381
|
+
function selectPdfImagePages(pageTexts, maxImagePages = MAX_IMAGE_PAGES) {
|
|
32382
|
+
const needImage = [];
|
|
32383
|
+
pageTexts.forEach((text12, index) => {
|
|
32384
|
+
if (text12.trim().length < MIN_PAGE_TEXT_CHARS) needImage.push(index + 1);
|
|
32385
|
+
});
|
|
32386
|
+
const limit = Math.max(0, maxImagePages);
|
|
32387
|
+
return { rendered: needImage.slice(0, limit), omitted: needImage.slice(limit) };
|
|
32388
|
+
}
|
|
32389
|
+
function formatPageList(pages) {
|
|
32390
|
+
const ranges = [];
|
|
32391
|
+
for (let i = 0; i < pages.length; i++) {
|
|
32392
|
+
const start = pages[i];
|
|
32393
|
+
let end = start;
|
|
32394
|
+
while (i + 1 < pages.length && pages[i + 1] === end + 1) end = pages[++i];
|
|
32395
|
+
ranges.push(start === end ? `${start}` : `${start}-${end}`);
|
|
32396
|
+
}
|
|
32397
|
+
return `${pages.length === 1 ? "page" : "pages"} ${ranges.join(", ")}`;
|
|
32398
|
+
}
|
|
32399
|
+
function buildPdfImageNote(fileName, includedPages, omittedPages, pageCount) {
|
|
32400
|
+
const imageOnlyCount = includedPages.length + omittedPages.length;
|
|
32401
|
+
const allPages = [...includedPages, ...omittedPages].sort((a, b) => a - b);
|
|
32402
|
+
const subject = pageCount === void 0 || imageOnlyCount >= pageCount ? `${fileName}: scanned/image-based PDF (no extractable text)` : `${fileName}: ${imageOnlyCount} of ${pageCount} pages have no extractable text (${formatPageList(allPages)})`;
|
|
32403
|
+
if (includedPages.length === 0) {
|
|
32404
|
+
return `[${subject} \u2014 ${formatPageList(omittedPages)} could not be included as images because of the image limit, so their content is not available]`;
|
|
32405
|
+
}
|
|
32406
|
+
const included = `${formatPageList(includedPages)} rendered as images and included in this message for visual analysis`;
|
|
32407
|
+
if (omittedPages.length === 0) return `[${subject} \u2014 ${included}]`;
|
|
32408
|
+
return `[${subject} \u2014 ${included}; ${formatPageList(omittedPages)} not included because of the image limit, so their content is not available]`;
|
|
32409
|
+
}
|
|
32410
|
+
function rewriteImageNote(result, fileName, keptImages) {
|
|
32411
|
+
const images = result.imageDataUrls ?? [];
|
|
32412
|
+
const note = result.metadata?.imageNote;
|
|
32413
|
+
if (!note || keptImages >= images.length) return result.extractedText;
|
|
32414
|
+
const imagePages = result.metadata?.imagePages ?? [];
|
|
32415
|
+
const omittedPages = result.metadata?.omittedImagePages ?? [];
|
|
32416
|
+
const pageCount = result.metadata?.pageCount;
|
|
32417
|
+
const kept = Math.max(0, keptImages);
|
|
32418
|
+
const newNote = buildPdfImageNote(
|
|
32419
|
+
fileName,
|
|
32420
|
+
imagePages.slice(0, kept),
|
|
32421
|
+
[...imagePages.slice(kept), ...omittedPages].sort((a, b) => a - b),
|
|
32422
|
+
pageCount
|
|
32423
|
+
);
|
|
32424
|
+
return result.extractedText.replace(note, () => newNote);
|
|
32425
|
+
}
|
|
32291
32426
|
var PdfProcessor = class {
|
|
32292
32427
|
constructor() {
|
|
32293
32428
|
this.name = "pdf";
|
|
@@ -32296,43 +32431,65 @@ var PdfProcessor = class {
|
|
|
32296
32431
|
}
|
|
32297
32432
|
async process(file) {
|
|
32298
32433
|
const logger = getLogger();
|
|
32434
|
+
let pageTexts = null;
|
|
32299
32435
|
try {
|
|
32300
|
-
|
|
32301
|
-
if (text12 && text12.trim().length > 0) {
|
|
32302
|
-
return {
|
|
32303
|
-
extractedText: text12,
|
|
32304
|
-
format: "plain"
|
|
32305
|
-
};
|
|
32306
|
-
}
|
|
32307
|
-
logger.info(
|
|
32308
|
-
`[PdfProcessor] Text extraction returned empty for "${file.name}" \u2014 falling back to image conversion`
|
|
32309
|
-
);
|
|
32436
|
+
pageTexts = await extractPdfPageTexts(file.dataUrl);
|
|
32310
32437
|
} catch (textError) {
|
|
32311
32438
|
logger.warn(
|
|
32312
|
-
|
|
32439
|
+
"[PdfProcessor] Text extraction failed \u2014 falling back to image conversion:",
|
|
32313
32440
|
textError
|
|
32314
32441
|
);
|
|
32315
32442
|
}
|
|
32443
|
+
const text12 = (pageTexts ?? []).filter((t) => t.trim()).join("\n\n");
|
|
32444
|
+
const { rendered, omitted } = pageTexts ? selectPdfImagePages(pageTexts) : { rendered: [], omitted: [] };
|
|
32445
|
+
if (pageTexts && rendered.length === 0 && omitted.length === 0) {
|
|
32446
|
+
return text12.trim() ? { extractedText: text12, format: "plain" } : null;
|
|
32447
|
+
}
|
|
32448
|
+
let renderedPages;
|
|
32449
|
+
let pageCount = pageTexts?.length;
|
|
32316
32450
|
try {
|
|
32317
|
-
|
|
32318
|
-
|
|
32319
|
-
|
|
32320
|
-
|
|
32451
|
+
if (pageTexts) {
|
|
32452
|
+
renderedPages = (await renderPdfPages(file.dataUrl, void 0, rendered)).pages;
|
|
32453
|
+
} else {
|
|
32454
|
+
const result = await renderPdfPages(file.dataUrl, MAX_IMAGE_PAGES);
|
|
32455
|
+
renderedPages = result.pages;
|
|
32456
|
+
pageCount = result.pageCount;
|
|
32321
32457
|
}
|
|
32322
|
-
logger.info(`[PdfProcessor] Converted ${images.length} page(s) of "${file.name}" to images`);
|
|
32323
|
-
return {
|
|
32324
|
-
// Contextual note for the LLM — keep it self-contained since the
|
|
32325
|
-
// images are only injected in the current request and not persisted
|
|
32326
|
-
// for follow-up turns.
|
|
32327
|
-
extractedText: `[${file.name}: scanned/image-based PDF \u2014 ${images.length} page(s) rendered as images and included in this message for visual analysis]`,
|
|
32328
|
-
format: "plain",
|
|
32329
|
-
imageDataUrls: images,
|
|
32330
|
-
metadata: { pageCount: images.length }
|
|
32331
|
-
};
|
|
32332
32458
|
} catch (imageError) {
|
|
32333
|
-
|
|
32334
|
-
|
|
32459
|
+
if (!text12.trim()) {
|
|
32460
|
+
logger.error("[PdfProcessor] Image conversion also failed:", imageError);
|
|
32461
|
+
throw imageError;
|
|
32462
|
+
}
|
|
32463
|
+
logger.warn("[PdfProcessor] Image conversion failed \u2014 keeping text only:", imageError);
|
|
32464
|
+
renderedPages = [];
|
|
32465
|
+
}
|
|
32466
|
+
const images = renderedPages.map((p) => p.dataUrl);
|
|
32467
|
+
const imagePages = renderedPages.map((p) => p.pageNumber);
|
|
32468
|
+
const included = new Set(imagePages);
|
|
32469
|
+
const needImage = pageTexts ? [...rendered, ...omitted] : Array.from({ length: pageCount ?? 0 }, (_, i) => i + 1);
|
|
32470
|
+
const omittedPages = needImage.filter((n) => !included.has(n)).sort((a, b) => a - b);
|
|
32471
|
+
if (images.length === 0 && !text12.trim()) {
|
|
32472
|
+
logger.warn("[PdfProcessor] Image conversion also returned empty");
|
|
32473
|
+
return null;
|
|
32335
32474
|
}
|
|
32475
|
+
logger.info(
|
|
32476
|
+
`[PdfProcessor] Rendered ${images.length} page(s) as images, ${omittedPages.length} image-only page(s) omitted`
|
|
32477
|
+
);
|
|
32478
|
+
const imageNote = buildPdfImageNote(file.name, imagePages, omittedPages, pageCount);
|
|
32479
|
+
return {
|
|
32480
|
+
extractedText: text12.trim() ? `${imageNote}
|
|
32481
|
+
|
|
32482
|
+
${text12}` : imageNote,
|
|
32483
|
+
format: "plain",
|
|
32484
|
+
imageDataUrls: images.length > 0 ? images : void 0,
|
|
32485
|
+
metadata: {
|
|
32486
|
+
pageCount,
|
|
32487
|
+
imageNote,
|
|
32488
|
+
imagePages,
|
|
32489
|
+
omittedImagePages: omittedPages,
|
|
32490
|
+
truncated: omittedPages.length > 0
|
|
32491
|
+
}
|
|
32492
|
+
};
|
|
32336
32493
|
}
|
|
32337
32494
|
};
|
|
32338
32495
|
|
|
@@ -32373,6 +32530,21 @@ var EXT = {
|
|
|
32373
32530
|
CFG: ".cfg",
|
|
32374
32531
|
CONF: ".conf"
|
|
32375
32532
|
};
|
|
32533
|
+
function decodeText(bytes) {
|
|
32534
|
+
if (bytes[0] === 255 && bytes[1] === 254) {
|
|
32535
|
+
return new TextDecoder("utf-16le", { fatal: false }).decode(bytes.subarray(2));
|
|
32536
|
+
}
|
|
32537
|
+
if (bytes[0] === 254 && bytes[1] === 255) {
|
|
32538
|
+
const swapped = new Uint8Array(bytes.length - 2);
|
|
32539
|
+
for (let i = 2; i + 1 < bytes.length; i += 2) {
|
|
32540
|
+
swapped[i - 2] = bytes[i + 1];
|
|
32541
|
+
swapped[i - 1] = bytes[i];
|
|
32542
|
+
}
|
|
32543
|
+
return new TextDecoder("utf-16le", { fatal: false }).decode(swapped);
|
|
32544
|
+
}
|
|
32545
|
+
const hasUtf8Bom = bytes[0] === 239 && bytes[1] === 187 && bytes[2] === 191;
|
|
32546
|
+
return new TextDecoder("utf-8", { fatal: false }).decode(hasUtf8Bom ? bytes.subarray(3) : bytes);
|
|
32547
|
+
}
|
|
32376
32548
|
var TextProcessor = class {
|
|
32377
32549
|
constructor() {
|
|
32378
32550
|
this.name = "text";
|
|
@@ -32382,7 +32554,7 @@ var TextProcessor = class {
|
|
|
32382
32554
|
async process(file) {
|
|
32383
32555
|
try {
|
|
32384
32556
|
const arrayBuffer = await dataUrlToArrayBuffer(file.dataUrl);
|
|
32385
|
-
const text12 = new
|
|
32557
|
+
const text12 = decodeText(new Uint8Array(arrayBuffer));
|
|
32386
32558
|
if (!text12.trim()) {
|
|
32387
32559
|
return null;
|
|
32388
32560
|
}
|
|
@@ -32405,7 +32577,7 @@ var TextProcessor = class {
|
|
|
32405
32577
|
* rather than prose).
|
|
32406
32578
|
*/
|
|
32407
32579
|
resolveFormat(file) {
|
|
32408
|
-
const type = file.type?.toLowerCase() ?? "";
|
|
32580
|
+
const type = file.type?.split(";")[0].trim().toLowerCase() ?? "";
|
|
32409
32581
|
const name = file.name?.toLowerCase() ?? "";
|
|
32410
32582
|
if (type === MIME.MARKDOWN || type === MIME.X_MARKDOWN || name.endsWith(EXT.MD) || name.endsWith(EXT.MARKDOWN)) {
|
|
32411
32583
|
return "markdown";
|
|
@@ -32461,6 +32633,12 @@ var WordProcessor = class {
|
|
|
32461
32633
|
|
|
32462
32634
|
// src/lib/processors/ZipProcessor.ts
|
|
32463
32635
|
import JSZip from "jszip";
|
|
32636
|
+
var MAX_ZIP_ENTRIES = 1e3;
|
|
32637
|
+
var MAX_TOTAL_UNCOMPRESSED_BYTES = 50 * 1024 * 1024;
|
|
32638
|
+
function declaredUncompressedSize(zipObject) {
|
|
32639
|
+
const size = zipObject._data?.uncompressedSize;
|
|
32640
|
+
return typeof size === "number" ? size : void 0;
|
|
32641
|
+
}
|
|
32464
32642
|
var ZipProcessor = class {
|
|
32465
32643
|
constructor(options = {}) {
|
|
32466
32644
|
this.name = "zip";
|
|
@@ -32495,14 +32673,35 @@ var ZipProcessor = class {
|
|
|
32495
32673
|
zipObject: zipEntry
|
|
32496
32674
|
});
|
|
32497
32675
|
});
|
|
32498
|
-
const
|
|
32499
|
-
|
|
32676
|
+
const visibleEntries = this.includeHidden ? entries : entries.filter((entry) => !this.isHidden(entry.path));
|
|
32677
|
+
visibleEntries.sort((a, b) => {
|
|
32500
32678
|
if (a.isDirectory !== b.isDirectory) {
|
|
32501
32679
|
return a.isDirectory ? -1 : 1;
|
|
32502
32680
|
}
|
|
32503
32681
|
return a.path.localeCompare(b.path);
|
|
32504
32682
|
});
|
|
32505
|
-
|
|
32683
|
+
const visibleDirs = visibleEntries.filter((e) => e.isDirectory);
|
|
32684
|
+
const visibleFiles = visibleEntries.filter((e) => !e.isDirectory);
|
|
32685
|
+
const listedDirs = visibleDirs.slice(0, MAX_ZIP_ENTRIES);
|
|
32686
|
+
const listedFiles = visibleFiles.slice(0, MAX_ZIP_ENTRIES);
|
|
32687
|
+
const filteredEntries = [...listedDirs, ...listedFiles];
|
|
32688
|
+
const notes = [];
|
|
32689
|
+
if (visibleFiles.length > listedFiles.length) {
|
|
32690
|
+
notes.push(
|
|
32691
|
+
`[truncated: the archive has ${visibleFiles.length} files; only the first ${listedFiles.length} were listed and considered for extraction, the other ${visibleFiles.length - listedFiles.length} files were dropped]`
|
|
32692
|
+
);
|
|
32693
|
+
}
|
|
32694
|
+
if (visibleDirs.length > listedDirs.length) {
|
|
32695
|
+
notes.push(
|
|
32696
|
+
`[truncated: listing the first ${listedDirs.length} of ${visibleDirs.length} directories]`
|
|
32697
|
+
);
|
|
32698
|
+
}
|
|
32699
|
+
let totalBytes = 0;
|
|
32700
|
+
let byteBudgetHit = false;
|
|
32701
|
+
let truncated = notes.length > 0;
|
|
32702
|
+
const logger = getLogger();
|
|
32703
|
+
for (let index = 0; index < filteredEntries.length; index++) {
|
|
32704
|
+
const entry = filteredEntries[index];
|
|
32506
32705
|
if (entry.isDirectory) continue;
|
|
32507
32706
|
const fileName = entry.path.split("/").pop() || entry.path;
|
|
32508
32707
|
const extension = this.getFileExtension(fileName);
|
|
@@ -32516,9 +32715,20 @@ var ZipProcessor = class {
|
|
|
32516
32715
|
};
|
|
32517
32716
|
const processor = this.registry?.findProcessor(fileMetadata);
|
|
32518
32717
|
if (!processor || processor.name === "zip") continue;
|
|
32718
|
+
const declared = declaredUncompressedSize(entry.zipObject);
|
|
32719
|
+
if (declared !== void 0 && declared > this.maxFileSize) continue;
|
|
32720
|
+
if (totalBytes + (declared ?? 0) > MAX_TOTAL_UNCOMPRESSED_BYTES) {
|
|
32721
|
+
byteBudgetHit = true;
|
|
32722
|
+
break;
|
|
32723
|
+
}
|
|
32519
32724
|
try {
|
|
32520
32725
|
const data = await entry.zipObject.async("uint8array");
|
|
32726
|
+
totalBytes += data.length;
|
|
32521
32727
|
if (data.length > this.maxFileSize) continue;
|
|
32728
|
+
if (totalBytes > MAX_TOTAL_UNCOMPRESSED_BYTES) {
|
|
32729
|
+
byteBudgetHit = true;
|
|
32730
|
+
break;
|
|
32731
|
+
}
|
|
32522
32732
|
const base64 = uint8ArrayToBase64(data);
|
|
32523
32733
|
const dataUrl = `data:${mimeType};base64,${base64}`;
|
|
32524
32734
|
const fileWithData = {
|
|
@@ -32528,23 +32738,36 @@ var ZipProcessor = class {
|
|
|
32528
32738
|
};
|
|
32529
32739
|
const result = await processor.process(fileWithData);
|
|
32530
32740
|
if (result && result.extractedText.trim()) {
|
|
32741
|
+
if (result.metadata?.truncated || result.imageDataUrls?.length) truncated = true;
|
|
32531
32742
|
processedContents.push({
|
|
32532
32743
|
path: entry.path,
|
|
32533
32744
|
processorName: processor.name,
|
|
32534
|
-
|
|
32745
|
+
// Page images of nested files are not forwarded, so their note must not claim them.
|
|
32746
|
+
result: { ...result, extractedText: rewriteImageNote(result, fileName, 0) }
|
|
32535
32747
|
});
|
|
32536
32748
|
}
|
|
32537
|
-
} catch {
|
|
32749
|
+
} catch (error) {
|
|
32750
|
+
logger.warn(
|
|
32751
|
+
`[ZipProcessor] Failed to process archive entry #${index + 1} (${processor.name}, ${mimeType})`,
|
|
32752
|
+
error
|
|
32753
|
+
);
|
|
32538
32754
|
}
|
|
32539
32755
|
}
|
|
32540
|
-
|
|
32756
|
+
if (byteBudgetHit) {
|
|
32757
|
+
truncated = true;
|
|
32758
|
+
notes.push(
|
|
32759
|
+
`[truncated: stopped reading the archive after ${Math.round(MAX_TOTAL_UNCOMPRESSED_BYTES / 1024 / 1024)} MB of decompressed content; later files were not extracted]`
|
|
32760
|
+
);
|
|
32761
|
+
}
|
|
32762
|
+
const output = [this.formatOutput(filteredEntries, processedContents), ...notes].join("\n");
|
|
32541
32763
|
return {
|
|
32542
32764
|
extractedText: output,
|
|
32543
32765
|
format: "markdown",
|
|
32544
32766
|
metadata: {
|
|
32545
32767
|
fileCount: filteredEntries.filter((e) => !e.isDirectory).length,
|
|
32546
32768
|
directoryCount: filteredEntries.filter((e) => e.isDirectory).length,
|
|
32547
|
-
processedFiles: processedContents.length
|
|
32769
|
+
processedFiles: processedContents.length,
|
|
32770
|
+
truncated
|
|
32548
32771
|
}
|
|
32549
32772
|
};
|
|
32550
32773
|
} catch (error) {
|
|
@@ -32646,9 +32869,10 @@ var ProcessorRegistry = class {
|
|
|
32646
32869
|
* @returns The matching processor, or null if none found
|
|
32647
32870
|
*/
|
|
32648
32871
|
findProcessor(file) {
|
|
32649
|
-
|
|
32872
|
+
const mimeType = file.type?.split(";")[0].trim().toLowerCase();
|
|
32873
|
+
if (mimeType) {
|
|
32650
32874
|
for (const processor of this.processors.values()) {
|
|
32651
|
-
if (processor.supportedMimeTypes.includes(
|
|
32875
|
+
if (processor.supportedMimeTypes.includes(mimeType)) {
|
|
32652
32876
|
return processor;
|
|
32653
32877
|
}
|
|
32654
32878
|
}
|
|
@@ -32715,8 +32939,54 @@ var ProcessorRegistry = class {
|
|
|
32715
32939
|
}
|
|
32716
32940
|
};
|
|
32717
32941
|
|
|
32942
|
+
// src/lib/processors/fileStatusNotes.ts
|
|
32943
|
+
var DEFAULT_MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;
|
|
32944
|
+
function formatMegabytes(bytes) {
|
|
32945
|
+
const mb = bytes / (1024 * 1024);
|
|
32946
|
+
return `${Number.isInteger(mb) ? mb : mb.toFixed(1)} MB`;
|
|
32947
|
+
}
|
|
32948
|
+
function formatFileProcessingNotes(statuses, options = {}) {
|
|
32949
|
+
const maxFileSizeBytes = options.maxFileSizeBytes ?? DEFAULT_MAX_FILE_SIZE_BYTES;
|
|
32950
|
+
const why = {
|
|
32951
|
+
too_large: `the file is larger than ${formatMegabytes(maxFileSizeBytes)}`,
|
|
32952
|
+
unsupported_type: "its file type is not supported for reading",
|
|
32953
|
+
no_data: "its contents were not available to the app",
|
|
32954
|
+
empty: "no text or images could be extracted from it (it may be blank)",
|
|
32955
|
+
timeout: "reading it took too long and was stopped",
|
|
32956
|
+
error: "its text could not be extracted (it may be password-protected or damaged)"
|
|
32957
|
+
};
|
|
32958
|
+
const lines = statuses.filter((s) => s.status === "skipped" || s.status === "failed").map((s) => `[${s.fileName} could not be read: ${why[s.reason ?? "error"]}]`);
|
|
32959
|
+
return lines.length > 0 ? lines.join("\n") : null;
|
|
32960
|
+
}
|
|
32961
|
+
|
|
32718
32962
|
// src/lib/processors/preprocessor.ts
|
|
32719
32963
|
var MAX_TOTAL_IMAGES = 20;
|
|
32964
|
+
var DEFAULT_MAX_EXTRACTED_CHARS_PER_FILE = 1e5;
|
|
32965
|
+
var DEFAULT_MAX_EXTRACTED_CHARS_TOTAL = 2e5;
|
|
32966
|
+
var ProcessingTimeoutError = class extends Error {
|
|
32967
|
+
constructor(timeoutMs) {
|
|
32968
|
+
super(`Timed out processing file after ${timeoutMs}ms`);
|
|
32969
|
+
this.name = "ProcessingTimeoutError";
|
|
32970
|
+
}
|
|
32971
|
+
};
|
|
32972
|
+
function truncationMarker(kept, total, fileName) {
|
|
32973
|
+
return `
|
|
32974
|
+
[truncated: showing the first ${kept} of ${total} characters of ${fileName}]`;
|
|
32975
|
+
}
|
|
32976
|
+
function truncateText(text12, limit, fileName) {
|
|
32977
|
+
if (text12.length <= limit) return { text: text12, truncated: false };
|
|
32978
|
+
let end = Math.max(0, limit);
|
|
32979
|
+
const code = text12.charCodeAt(end - 1);
|
|
32980
|
+
if (end > 0 && code >= 55296 && code <= 56319) end--;
|
|
32981
|
+
return {
|
|
32982
|
+
text: `${text12.slice(0, end)}${truncationMarker(end, text12.length, fileName)}`,
|
|
32983
|
+
truncated: true
|
|
32984
|
+
};
|
|
32985
|
+
}
|
|
32986
|
+
var FILE_SEPARATOR = "\n\n---\n\n";
|
|
32987
|
+
function isImageFile(file) {
|
|
32988
|
+
return (file.type ?? "").trim().toLowerCase().startsWith("image/");
|
|
32989
|
+
}
|
|
32720
32990
|
function createDefaultRegistry() {
|
|
32721
32991
|
const registry = new ProcessorRegistry();
|
|
32722
32992
|
registry.register(new PdfProcessor());
|
|
@@ -32766,10 +33036,11 @@ async function preprocessFiles(files, options = {}) {
|
|
|
32766
33036
|
processors = void 0,
|
|
32767
33037
|
// undefined means use defaults
|
|
32768
33038
|
keepOriginalFiles = true,
|
|
32769
|
-
maxFileSizeBytes =
|
|
32770
|
-
// 10MB
|
|
33039
|
+
maxFileSizeBytes = DEFAULT_MAX_FILE_SIZE_BYTES,
|
|
32771
33040
|
timeoutMs = 3e4,
|
|
32772
33041
|
// 30s per file
|
|
33042
|
+
maxExtractedCharsPerFile = DEFAULT_MAX_EXTRACTED_CHARS_PER_FILE,
|
|
33043
|
+
maxExtractedCharsTotal = DEFAULT_MAX_EXTRACTED_CHARS_TOTAL,
|
|
32773
33044
|
onProgress,
|
|
32774
33045
|
onError
|
|
32775
33046
|
} = options;
|
|
@@ -32779,23 +33050,23 @@ async function preprocessFiles(files, options = {}) {
|
|
|
32779
33050
|
extractedContent: null,
|
|
32780
33051
|
originalFiles: files,
|
|
32781
33052
|
preprocessedFileIds: [],
|
|
33053
|
+
fileStatuses: [],
|
|
32782
33054
|
metadata: { processedCount: 0, skippedCount: 0, errorCount: 0 }
|
|
32783
33055
|
};
|
|
32784
33056
|
}
|
|
32785
|
-
if (processors
|
|
32786
|
-
|
|
32787
|
-
|
|
32788
|
-
|
|
32789
|
-
|
|
32790
|
-
|
|
32791
|
-
};
|
|
32792
|
-
}
|
|
32793
|
-
if (processors === null) {
|
|
33057
|
+
if (processors === null || processors?.length === 0) {
|
|
33058
|
+
const fileStatuses2 = files.filter((file) => !isImageFile(file)).map((file) => ({
|
|
33059
|
+
fileId: file.id,
|
|
33060
|
+
fileName: file.name,
|
|
33061
|
+
status: "skipped",
|
|
33062
|
+
reason: "unsupported_type"
|
|
33063
|
+
}));
|
|
32794
33064
|
return {
|
|
32795
33065
|
extractedContent: null,
|
|
32796
33066
|
originalFiles: files,
|
|
32797
33067
|
preprocessedFileIds: [],
|
|
32798
|
-
|
|
33068
|
+
fileStatuses: fileStatuses2,
|
|
33069
|
+
metadata: { processedCount: 0, skippedCount: fileStatuses2.length, errorCount: 0 }
|
|
32799
33070
|
};
|
|
32800
33071
|
}
|
|
32801
33072
|
let registry;
|
|
@@ -32813,28 +33084,38 @@ async function preprocessFiles(files, options = {}) {
|
|
|
32813
33084
|
const extractedTexts = [];
|
|
32814
33085
|
const allImageUrls = [];
|
|
32815
33086
|
const preprocessedFileIds = [];
|
|
33087
|
+
const fileStatuses = [];
|
|
32816
33088
|
let processedCount = 0;
|
|
32817
33089
|
let skippedCount = 0;
|
|
32818
33090
|
let errorCount = 0;
|
|
33091
|
+
let totalChars = 0;
|
|
33092
|
+
const overBudgetFiles = [];
|
|
32819
33093
|
for (let i = 0; i < files.length; i++) {
|
|
32820
33094
|
const file = files[i];
|
|
33095
|
+
const label = `#${i + 1} (${file.type || "unknown type"}, ${file.size} bytes)`;
|
|
33096
|
+
const skip = (reason) => {
|
|
33097
|
+
skippedCount++;
|
|
33098
|
+
fileStatuses.push({ fileId: file.id, fileName: file.name, status: "skipped", reason });
|
|
33099
|
+
};
|
|
32821
33100
|
onProgress?.(i + 1, files.length, file.name);
|
|
33101
|
+
const processor = registry.findProcessor(file);
|
|
33102
|
+
if (!processor && isImageFile(file)) continue;
|
|
32822
33103
|
if (file.size > maxFileSizeBytes) {
|
|
32823
33104
|
logger.info(
|
|
32824
|
-
`[preprocessFiles] Skipping
|
|
33105
|
+
`[preprocessFiles] Skipping file ${label} \u2014 exceeds ${maxFileSizeBytes} byte limit`
|
|
32825
33106
|
);
|
|
32826
|
-
|
|
33107
|
+
skip("too_large");
|
|
32827
33108
|
continue;
|
|
32828
33109
|
}
|
|
32829
|
-
const processor = registry.findProcessor(file);
|
|
32830
33110
|
if (!processor) {
|
|
32831
|
-
|
|
33111
|
+
skip("unsupported_type");
|
|
32832
33112
|
continue;
|
|
32833
33113
|
}
|
|
33114
|
+
let timer;
|
|
32834
33115
|
try {
|
|
32835
33116
|
if (!file.url) {
|
|
32836
|
-
logger.info(`[preprocessFiles] Skipping
|
|
32837
|
-
|
|
33117
|
+
logger.info(`[preprocessFiles] Skipping file ${label} \u2014 no data URL available`);
|
|
33118
|
+
skip("no_data");
|
|
32838
33119
|
continue;
|
|
32839
33120
|
}
|
|
32840
33121
|
const fileWithData = {
|
|
@@ -32843,40 +33124,76 @@ async function preprocessFiles(files, options = {}) {
|
|
|
32843
33124
|
};
|
|
32844
33125
|
const result = await Promise.race([
|
|
32845
33126
|
processor.process(fileWithData),
|
|
32846
|
-
new Promise(
|
|
32847
|
-
|
|
32848
|
-
)
|
|
33127
|
+
new Promise((_, reject) => {
|
|
33128
|
+
timer = setTimeout(() => reject(new ProcessingTimeoutError(timeoutMs)), timeoutMs);
|
|
33129
|
+
})
|
|
32849
33130
|
]);
|
|
32850
33131
|
if (result && result.extractedText.trim()) {
|
|
32851
|
-
const
|
|
32852
|
-
|
|
32853
|
-
result.extractedText,
|
|
32854
|
-
result.format
|
|
32855
|
-
);
|
|
32856
|
-
extractedTexts.push(formattedContent);
|
|
33132
|
+
const separatorLength = extractedTexts.length > 0 ? FILE_SEPARATOR.length : 0;
|
|
33133
|
+
const remaining = maxExtractedCharsTotal - totalChars - separatorLength - formatExtractedContent(file.name, "", result.format).length;
|
|
32857
33134
|
preprocessedFileIds.push(file.id);
|
|
32858
33135
|
processedCount++;
|
|
32859
|
-
|
|
32860
|
-
|
|
32861
|
-
|
|
32862
|
-
|
|
32863
|
-
|
|
33136
|
+
const fullLength = result.extractedText.length;
|
|
33137
|
+
if (fullLength > remaining && remaining - truncationMarker(fullLength, fullLength, file.name).length <= 0) {
|
|
33138
|
+
overBudgetFiles.push(file.name);
|
|
33139
|
+
fileStatuses.push({ fileId: file.id, fileName: file.name, status: "truncated" });
|
|
33140
|
+
continue;
|
|
32864
33141
|
}
|
|
33142
|
+
const images = result.imageDataUrls ?? [];
|
|
33143
|
+
const keptImages = Math.min(
|
|
33144
|
+
images.length,
|
|
33145
|
+
Math.max(0, MAX_TOTAL_IMAGES - allImageUrls.length)
|
|
33146
|
+
);
|
|
33147
|
+
allImageUrls.push(...images.slice(0, keptImages));
|
|
33148
|
+
const text12 = rewriteImageNote(result, file.name, keptImages);
|
|
33149
|
+
const fitsWhole = text12.length <= Math.min(maxExtractedCharsPerFile, remaining);
|
|
33150
|
+
const limit = fitsWhole ? text12.length : Math.min(
|
|
33151
|
+
maxExtractedCharsPerFile,
|
|
33152
|
+
remaining - truncationMarker(text12.length, text12.length, file.name).length
|
|
33153
|
+
);
|
|
33154
|
+
const capped = truncateText(text12, Math.max(0, limit), file.name);
|
|
33155
|
+
const formattedContent = formatExtractedContent(file.name, capped.text, result.format);
|
|
33156
|
+
totalChars += separatorLength + formattedContent.length;
|
|
33157
|
+
extractedTexts.push(formattedContent);
|
|
33158
|
+
const truncated = capped.truncated || keptImages < images.length || result.metadata?.truncated === true;
|
|
33159
|
+
fileStatuses.push({
|
|
33160
|
+
fileId: file.id,
|
|
33161
|
+
fileName: file.name,
|
|
33162
|
+
status: truncated ? "truncated" : keptImages > 0 ? "rendered_as_images" : "extracted"
|
|
33163
|
+
});
|
|
32865
33164
|
} else {
|
|
32866
|
-
|
|
33165
|
+
skip("empty");
|
|
32867
33166
|
}
|
|
32868
33167
|
} catch (error) {
|
|
32869
33168
|
errorCount++;
|
|
32870
|
-
|
|
33169
|
+
const timedOut = error instanceof ProcessingTimeoutError;
|
|
33170
|
+
fileStatuses.push({
|
|
33171
|
+
fileId: file.id,
|
|
33172
|
+
fileName: file.name,
|
|
33173
|
+
status: "failed",
|
|
33174
|
+
reason: timedOut ? "timeout" : "error"
|
|
33175
|
+
});
|
|
33176
|
+
logger.error(
|
|
33177
|
+
`[preprocessFiles] Error processing file ${label} with ${processor.name}:`,
|
|
33178
|
+
error
|
|
33179
|
+
);
|
|
32871
33180
|
onError?.(file.name, error instanceof Error ? error : new Error(String(error)));
|
|
33181
|
+
} finally {
|
|
33182
|
+
clearTimeout(timer);
|
|
32872
33183
|
}
|
|
32873
33184
|
}
|
|
32874
|
-
|
|
33185
|
+
if (overBudgetFiles.length > 0) {
|
|
33186
|
+
extractedTexts.push(
|
|
33187
|
+
`[truncated: the attachment text limit (${maxExtractedCharsTotal} characters) was reached; the contents of ${overBudgetFiles.join(", ")} were not included]`
|
|
33188
|
+
);
|
|
33189
|
+
}
|
|
33190
|
+
const extractedContent = extractedTexts.length > 0 ? extractedTexts.join(FILE_SEPARATOR) : null;
|
|
32875
33191
|
return {
|
|
32876
33192
|
extractedContent,
|
|
32877
33193
|
imageContentUrls: allImageUrls.length > 0 ? allImageUrls : void 0,
|
|
32878
33194
|
originalFiles: keepOriginalFiles ? files : void 0,
|
|
32879
33195
|
preprocessedFileIds,
|
|
33196
|
+
fileStatuses,
|
|
32880
33197
|
metadata: { processedCount, skippedCount, errorCount }
|
|
32881
33198
|
};
|
|
32882
33199
|
}
|
|
@@ -35025,7 +35342,7 @@ function extractLastUserText(messages) {
|
|
|
35025
35342
|
const content = lastUserMsg.content;
|
|
35026
35343
|
if (typeof content === "string") return content;
|
|
35027
35344
|
if (Array.isArray(content)) {
|
|
35028
|
-
return content.filter((c) => c?.type === "text").map((c) => c.text ?? "").join(" ");
|
|
35345
|
+
return content.filter((c) => c?.type === "text" && !isAttachedFilesText(c.text)).map((c) => c.text ?? "").join(" ");
|
|
35029
35346
|
}
|
|
35030
35347
|
return "";
|
|
35031
35348
|
}
|
|
@@ -36699,6 +37016,7 @@ export {
|
|
|
36699
37016
|
extractEntitiesForMemories,
|
|
36700
37017
|
extractFacts,
|
|
36701
37018
|
findMatchingTools,
|
|
37019
|
+
formatFileProcessingNotes,
|
|
36702
37020
|
generateConversationId,
|
|
36703
37021
|
generateEmbedding,
|
|
36704
37022
|
generateEmbeddings,
|