Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Download ZIP from the Code button; a slimmer lifecycle panel; agent steps say what was done, not sandbox paths | 1 | /** |
| 2 | * A zip archive of files, made in memory: each file deflated when that makes | |
| 3 | * it smaller, stored otherwise, with UTF-8 names. Enough for downloading a | |
| 4 | * commit; no zip64, so the archive and each file stay under 4 GB (the caller | |
| Merge branch 'worktree-agent-a19b06d959c105bf7' into claude/cool-newton-7nm8r9 | 5 | * caps them far below that). Each file's Unix mode is kept, so an |
| 6 | * executable stays one and a symlink (its target as its bytes) unzips as | |
| 7 | * a link. | |
| Download ZIP from the Code button; a slimmer lifecycle panel; agent steps say what was done, not sandbox paths | 8 | */ |
| 9 | ||
| 10 | const CRC_TABLE = (() => { | |
| 11 | const table = new Uint32Array(256); | |
| 12 | for (let n = 0; n < 256; n++) { | |
| 13 | let c = n; | |
| 14 | for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1; | |
| 15 | table[n] = c >>> 0; | |
| 16 | } | |
| 17 | return table; | |
| 18 | })(); | |
| 19 | ||
| 20 | export function crc32(data: Uint8Array): number { | |
| 21 | let crc = 0xffffffff; | |
| 22 | for (let i = 0; i < data.length; i++) crc = CRC_TABLE[(crc ^ data[i]!) & 0xff]! ^ (crc >>> 8); | |
| 23 | return (crc ^ 0xffffffff) >>> 0; | |
| 24 | } | |
| 25 | ||
| 26 | async function deflate(data: Uint8Array): Promise<Uint8Array> { | |
| 27 | const stream = new Blob([data as Uint8Array<ArrayBuffer>]).stream().pipeThrough(new CompressionStream("deflate-raw")); | |
| 28 | return new Uint8Array(await new Response(stream).arrayBuffer()); | |
| 29 | } | |
| 30 | ||
| Merge branch 'worktree-agent-a19b06d959c105bf7' into claude/cool-newton-7nm8r9 | 31 | /** A file's Unix mode in a zip: a plain file, an executable, a symlink. */ |
| 32 | export const ZIP_MODES = { blob: 0o100644, exec: 0o100755, symlink: 0o120777 } as const; | |
| 33 | ||
| 34 | /** The archive of `files`, in the order given; `mode` is a plain file's unless given. */ | |
| 35 | export async function zip(files: { path: string; data: Uint8Array; mode?: number }[]): Promise<Uint8Array<ArrayBuffer>> { | |
| Download ZIP from the Code button; a slimmer lifecycle panel; agent steps say what was done, not sandbox paths | 36 | const encoder = new TextEncoder(); |
| 37 | const parts: Uint8Array[] = []; | |
| 38 | const central: Uint8Array[] = []; | |
| 39 | let offset = 0; | |
| Download ZIP deflates sixteen files at a time, within a Worker's memory | 40 | // Sixteen files deflating at a time: quicker than one by one, without |
| 41 | // every file's stream held at once. | |
| 42 | const deflatedAll: Uint8Array[] = new Array(files.length); | |
| 43 | let next = 0; | |
| 44 | const worker = async () => { | |
| 45 | for (let index = next++; index < files.length; index = next++) { | |
| 46 | const data = files[index]!.data; | |
| 47 | deflatedAll[index] = data.length > 0 ? await deflate(data) : data; | |
| 48 | } | |
| 49 | }; | |
| 50 | await Promise.all(Array.from({ length: Math.min(16, files.length) }, worker)); | |
| Download ZIP reads blobs eight batches at a time and deflates files together | 51 | for (const [index, file] of files.entries()) { |
| Download ZIP from the Code button; a slimmer lifecycle panel; agent steps say what was done, not sandbox paths | 52 | const name = encoder.encode(file.path); |
| 53 | const crc = crc32(file.data); | |
| Download ZIP reads blobs eight batches at a time and deflates files together | 54 | const deflated = deflatedAll[index]!; |
| Download ZIP from the Code button; a slimmer lifecycle panel; agent steps say what was done, not sandbox paths | 55 | const [method, body] = deflated.length < file.data.length ? [8, deflated] : [0, file.data]; |
| 56 | const header = (central: boolean) => { | |
| 57 | const out = new Uint8Array((central ? 46 : 30) + name.length); | |
| 58 | const view = new DataView(out.buffer); | |
| 59 | let at = 0; | |
| 60 | const u16 = (v: number) => { | |
| 61 | view.setUint16(at, v, true); | |
| 62 | at += 2; | |
| 63 | }; | |
| 64 | const u32 = (v: number) => { | |
| 65 | view.setUint32(at, v >>> 0, true); | |
| 66 | at += 4; | |
| 67 | }; | |
| 68 | u32(central ? 0x02014b50 : 0x04034b50); | |
| 69 | if (central) u16(0x031e); // made by: Unix, 3.0 | |
| 70 | u16(20); // version needed | |
| 71 | u16(0x0800); // UTF-8 names | |
| 72 | u16(method); | |
| 73 | u16(0); // time | |
| 74 | u16(0x0021); // date: 1980-01-01 | |
| 75 | u32(crc); | |
| 76 | u32(body.length); | |
| 77 | u32(file.data.length); | |
| 78 | u16(name.length); | |
| 79 | u16(0); // extra | |
| 80 | if (central) { | |
| 81 | u16(0); // comment | |
| 82 | u16(0); // disk | |
| 83 | u16(0); // internal attributes | |
| Merge branch 'worktree-agent-a19b06d959c105bf7' into claude/cool-newton-7nm8r9 | 84 | u32((file.mode ?? ZIP_MODES.blob) * 0x10000); |
| Download ZIP from the Code button; a slimmer lifecycle panel; agent steps say what was done, not sandbox paths | 85 | u32(offset); |
| 86 | } | |
| 87 | out.set(name, at); | |
| 88 | return out; | |
| 89 | }; | |
| 90 | const local = header(false); | |
| 91 | parts.push(local, body); | |
| 92 | central.push(header(true)); | |
| 93 | offset += local.length + body.length; | |
| 94 | } | |
| 95 | const centralSize = central.reduce((sum, part) => sum + part.length, 0); | |
| 96 | const end = new Uint8Array(22); | |
| 97 | const view = new DataView(end.buffer); | |
| 98 | view.setUint32(0, 0x06054b50, true); | |
| 99 | view.setUint16(8, files.length, true); | |
| 100 | view.setUint16(10, files.length, true); | |
| 101 | view.setUint32(12, centralSize, true); | |
| 102 | view.setUint32(16, offset, true); | |
| 103 | const all = [...parts, ...central, end]; | |
| 104 | const out = new Uint8Array(all.reduce((sum, part) => sum + part.length, 0)); | |
| 105 | let at = 0; | |
| 106 | for (const part of all) { | |
| 107 | out.set(part, at); | |
| 108 | at += part.length; | |
| 109 | } | |
| 110 | return out; | |
| 111 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.