返回 DeepSeek-Reasonix
sessionAttachmentRead.ts
根目录 / desktop / frontend / src / lib / sessionAttachmentRead.ts
1 export interface SessionAttachmentChunk {
2 data?: string;
3 nextOffset: number;
4 done: boolean;
5 }
6
7 const previewBudgetBytes = 64 << 20;
8
9 export async function readSessionAttachmentDataURL(
10 tabId: string,
11 digest: string,
12 mime: string,
13 read: (tabId: string, digest: string, offset: number) => Promise<SessionAttachmentChunk>,
14 ): Promise<string> {
15 const chunks: Uint8Array[] = [];
16 let offset = 0;
17 let total = 0;
18 for (;;) {
19 const chunk = await read(tabId, digest, offset);
20 if (chunk.data) {
21 const bytes = Uint8Array.from(atob(chunk.data), (c) => c.charCodeAt(0));
22 total += bytes.length;
23 if (total > previewBudgetBytes) {
24 throw new Error("attachment preview exceeds preview budget");
25 }
26 chunks.push(bytes);
27 }
28 if (chunk.done) break;
29 if (!Number.isFinite(chunk.nextOffset) || chunk.nextOffset <= offset) {
30 throw new Error("attachment read did not advance");
31 }
32 offset = chunk.nextOffset;
33 }
34 const merged = new Uint8Array(total);
35 let cursor = 0;
36 for (const part of chunks) {
37 merged.set(part, cursor);
38 cursor += part.length;
39 }
40 const binary: string[] = [];
41 for (let i = 0; i < merged.length; i += 32768) binary.push(String.fromCharCode(...merged.subarray(i, i + 32768)));
42 return `data:${mime || "image/png"};base64,${btoa(binary.join(""))}`;
43 }
44
44 lines TYPESCRIPT