mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-11-13 06:31:47 +00:00
* feat(frontend): improve file attachment recovery and artifact presentation * feat(extensions): add Office artifact previews with search and navigation * fix: preserve public viewers and HTTP Office previews * fix: address file preview and upload review findings * fix: use typed upload errors and linear bookmark allocation * fix(office-preview): isolate parsing and bound preview resources * fix(ci): install Office preview fixture dependencies for E2E * fix(ci): provision matching Playwright browsers before E2E tests * fix(ci): isolate Python libraries and include Office documentation * test(frontend): wait for download status to finish rendering
58 lines
2.0 KiB
JavaScript
58 lines
2.0 KiB
JavaScript
/** Resolve only package-local relationships, with the same POSIX path semantics as OOXML. */
|
|
export function resolvePartPath(base, target) {
|
|
const segments = target.startsWith("/") ? [] : base.split("/").slice(0, -1);
|
|
for (const part of target.split("/")) {
|
|
if (part === "..") segments.pop();
|
|
else if (part && part !== ".") segments.push(part);
|
|
}
|
|
return segments.join("/");
|
|
}
|
|
|
|
/** Reject amplified parser output before structured clone or DOM creation. */
|
|
export function checkModelBudget(value) {
|
|
const seen = new Set(),
|
|
stack = [value];
|
|
let nodes = 0,
|
|
bytes = 0;
|
|
while (stack.length) {
|
|
const item = stack.pop();
|
|
if (typeof item === "string") bytes += item.length * 2;
|
|
else if (item && typeof item === "object" && !seen.has(item)) {
|
|
seen.add(item);
|
|
if (++nodes > 100000) throw new Error("Office model node limit exceeded");
|
|
if (item instanceof ArrayBuffer) bytes += item.byteLength;
|
|
else if (ArrayBuffer.isView(item)) {
|
|
if (!seen.has(item.buffer)) {
|
|
seen.add(item.buffer);
|
|
bytes += item.buffer.byteLength;
|
|
}
|
|
} else {
|
|
if (Array.isArray(item) && item.length > 100000)
|
|
throw new Error("Office model array limit exceeded");
|
|
for (const [key, child] of Object.entries(item)) {
|
|
bytes += key.length * 2;
|
|
stack.push(child);
|
|
}
|
|
}
|
|
}
|
|
if (bytes > 32 * 1024 * 1024)
|
|
throw new Error("Office model size limit exceeded");
|
|
}
|
|
}
|
|
|
|
/** Transfer each resource once; do not clone validated image bytes back to the UI. */
|
|
export function transferBuffers(value) {
|
|
const seen = new Set(),
|
|
buffers = new Set(),
|
|
stack = [value];
|
|
while (stack.length) {
|
|
const item = stack.pop();
|
|
if (!item || typeof item !== "object" || seen.has(item)) continue;
|
|
seen.add(item);
|
|
if (item instanceof ArrayBuffer) buffers.add(item);
|
|
else if (ArrayBuffer.isView(item)) buffers.add(item.buffer);
|
|
else stack.push(...Object.values(item));
|
|
}
|
|
return [...buffers];
|
|
}
|