makecoder 5.0.22 → 5.0.23
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/claude-sidecar-release.json +3 -2
- package/dist/coder.js +375 -376
- package/dist/cowork.js +375 -376
- package/package.json +16 -21
- package/scripts/claude-cell-segmenter-shim.js +172 -0
- package/scripts/postinstall.js +52 -44
- package/scripts/assemble-claude-native.mjs +0 -142
- package/scripts/claude-native-runtime.mjs +0 -230
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Keep Anthropic's runtime and replace only its standalone entry module.
|
|
3
|
-
* No sections move, no public Bun compiler rewrites private runtime metadata,
|
|
4
|
-
* and all original embedded assets remain available. Unknown layouts fail
|
|
5
|
-
* closed. The on-disk cc.js and its sidecars retain their existing semantics.
|
|
6
|
-
*/
|
|
7
|
-
import { createHash } from "node:crypto";
|
|
8
|
-
|
|
9
|
-
const TRAILER = Buffer.from("\n---- Bun! ----\n");
|
|
10
|
-
const MODULE_SIZE = 52;
|
|
11
|
-
const OFFSETS_SIZE = 32;
|
|
12
|
-
|
|
13
|
-
function check(condition, message) {
|
|
14
|
-
if (!condition) throw new Error(`Unsupported Claude native runtime: ${message}`);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function range(buffer, offset, size, label) {
|
|
18
|
-
check(Number.isSafeInteger(offset) && Number.isSafeInteger(size) &&
|
|
19
|
-
offset >= 0 && size >= 0 && offset <= buffer.length - size,
|
|
20
|
-
`${label} is outside the binary`);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function u64(buffer, offset) {
|
|
24
|
-
range(buffer, offset, 8, "uint64");
|
|
25
|
-
const value = Number(buffer.readBigUInt64LE(offset));
|
|
26
|
-
check(Number.isSafeInteger(value), "uint64 exceeds safe integer range");
|
|
27
|
-
return value;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function name(buffer, offset, size) {
|
|
31
|
-
range(buffer, offset, size, "section name");
|
|
32
|
-
const bytes = buffer.subarray(offset, offset + size);
|
|
33
|
-
return bytes.subarray(0, bytes.indexOf(0) < 0 ? size : bytes.indexOf(0)).toString();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** Locate the file-backed Bun section using platform headers, not byte scans. */
|
|
37
|
-
export function inspectExecutable(buffer) {
|
|
38
|
-
range(buffer, 0, 64, "executable header");
|
|
39
|
-
let platform;
|
|
40
|
-
let signatureDirectory;
|
|
41
|
-
let checksumOffset;
|
|
42
|
-
const sections = [];
|
|
43
|
-
if (buffer.readUInt32LE(0) === 0xfeedfacf) {
|
|
44
|
-
const cpu = buffer.readUInt32LE(4);
|
|
45
|
-
check(cpu === 0x100000c || cpu === 0x1000007, "unknown Mach-O CPU");
|
|
46
|
-
platform = cpu === 0x100000c ? "darwin-arm64" : "darwin-x64";
|
|
47
|
-
check(buffer.readUInt32LE(12) === 2, "Mach-O is not executable");
|
|
48
|
-
const end = 32 + buffer.readUInt32LE(20);
|
|
49
|
-
range(buffer, 32, end - 32, "Mach-O commands");
|
|
50
|
-
let cursor = 32;
|
|
51
|
-
for (let i = 0; i < buffer.readUInt32LE(16); i++) {
|
|
52
|
-
check(cursor + 8 <= end, "truncated Mach-O command");
|
|
53
|
-
const cmd = buffer.readUInt32LE(cursor);
|
|
54
|
-
const size = buffer.readUInt32LE(cursor + 4);
|
|
55
|
-
check(size >= 8 && size % 8 === 0 && cursor + size <= end, "invalid Mach-O command size");
|
|
56
|
-
if (cmd === 0x19) {
|
|
57
|
-
check(size >= 72, "truncated segment command");
|
|
58
|
-
const count = buffer.readUInt32LE(cursor + 64);
|
|
59
|
-
check(size === 72 + count * 80, "unexpected segment command layout");
|
|
60
|
-
if (name(buffer, cursor + 8, 16) === "__BUN") {
|
|
61
|
-
check(count === 1, "expected one __BUN section");
|
|
62
|
-
const offset = u64(buffer, cursor + 40);
|
|
63
|
-
const length = u64(buffer, cursor + 48);
|
|
64
|
-
check(buffer.readUInt32LE(cursor + 72 + 48) === offset &&
|
|
65
|
-
u64(buffer, cursor + 72 + 40) <= length, "__BUN section/segment mismatch");
|
|
66
|
-
sections.push({ offset, length });
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
cursor += size;
|
|
70
|
-
}
|
|
71
|
-
check(cursor === end, "Mach-O command count mismatch");
|
|
72
|
-
} else if (buffer.subarray(0, 4).equals(Buffer.from([0x7f, 0x45, 0x4c, 0x46]))) {
|
|
73
|
-
check(buffer[4] === 2 && buffer[5] === 1 && buffer[6] === 1,
|
|
74
|
-
"expected little-endian ELF64");
|
|
75
|
-
const cpu = buffer.readUInt16LE(18);
|
|
76
|
-
check(cpu === 62 || cpu === 183, "unknown ELF CPU");
|
|
77
|
-
check([2, 3].includes(buffer.readUInt16LE(16)), "ELF is not executable");
|
|
78
|
-
platform = cpu === 183 ? "linux-arm64" : "linux-x64";
|
|
79
|
-
const table = u64(buffer, 40);
|
|
80
|
-
const count = buffer.readUInt16LE(60);
|
|
81
|
-
const stringsIndex = buffer.readUInt16LE(62);
|
|
82
|
-
check(buffer.readUInt16LE(58) === 64 && count > 0 && stringsIndex < count,
|
|
83
|
-
"unsupported ELF section table");
|
|
84
|
-
range(buffer, table, count * 64, "ELF sections");
|
|
85
|
-
const stringsHeader = table + stringsIndex * 64;
|
|
86
|
-
const strings = u64(buffer, stringsHeader + 24);
|
|
87
|
-
const stringsSize = u64(buffer, stringsHeader + 32);
|
|
88
|
-
range(buffer, strings, stringsSize, "ELF section names");
|
|
89
|
-
for (let i = 0; i < count; i++) {
|
|
90
|
-
const header = table + i * 64;
|
|
91
|
-
const nameOffset = buffer.readUInt32LE(header);
|
|
92
|
-
check(nameOffset < stringsSize, "ELF section name outside string table");
|
|
93
|
-
if (name(buffer, strings + nameOffset, Math.min(5, stringsSize - nameOffset)) === ".bun" &&
|
|
94
|
-
buffer[strings + nameOffset + 4] === 0) {
|
|
95
|
-
check(buffer.readUInt32LE(header + 4) === 1, ".bun is not PROGBITS");
|
|
96
|
-
sections.push({ offset: u64(buffer, header + 24), length: u64(buffer, header + 32) });
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
} else if (buffer.readUInt16LE(0) === 0x5a4d) {
|
|
100
|
-
const pe = buffer.readUInt32LE(0x3c);
|
|
101
|
-
range(buffer, pe, 24, "PE header");
|
|
102
|
-
check(buffer.readUInt32LE(pe) === 0x4550 && buffer.readUInt16LE(pe + 4) === 0x8664,
|
|
103
|
-
"expected x64 PE");
|
|
104
|
-
platform = "win32-x64";
|
|
105
|
-
const optional = pe + 24;
|
|
106
|
-
const optionalSize = buffer.readUInt16LE(pe + 20);
|
|
107
|
-
range(buffer, optional, optionalSize, "PE optional header");
|
|
108
|
-
check(optionalSize >= 152 && buffer.readUInt16LE(optional) === 0x20b &&
|
|
109
|
-
buffer.readUInt32LE(optional + 108) >= 5, "unsupported PE optional header");
|
|
110
|
-
signatureDirectory = optional + 112 + 4 * 8;
|
|
111
|
-
checksumOffset = optional + 64;
|
|
112
|
-
const table = optional + optionalSize;
|
|
113
|
-
const count = buffer.readUInt16LE(pe + 6);
|
|
114
|
-
range(buffer, table, count * 40, "PE sections");
|
|
115
|
-
for (let i = 0; i < count; i++) {
|
|
116
|
-
const header = table + i * 40;
|
|
117
|
-
if (name(buffer, header, 8) === ".bun") {
|
|
118
|
-
sections.push({ offset: buffer.readUInt32LE(header + 20), length: buffer.readUInt32LE(header + 16) });
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
} else {
|
|
122
|
-
throw new Error("Unsupported Claude native runtime: expected Mach-O, ELF64 or PE64");
|
|
123
|
-
}
|
|
124
|
-
check(sections.length === 1, "expected exactly one Bun section");
|
|
125
|
-
const section = sections[0];
|
|
126
|
-
range(buffer, section.offset, section.length, "Bun section");
|
|
127
|
-
check(section.length >= 8 + OFFSETS_SIZE + TRAILER.length, "Bun section is too short");
|
|
128
|
-
return { platform, ...section, signatureDirectory, checksumOffset };
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export function inspectModuleGraph(buffer) {
|
|
132
|
-
const executable = inspectExecutable(buffer);
|
|
133
|
-
const { offset, length } = executable;
|
|
134
|
-
const graphSize = u64(buffer, offset);
|
|
135
|
-
check(graphSize >= OFFSETS_SIZE + TRAILER.length && graphSize <= length - 8,
|
|
136
|
-
"invalid Bun graph size");
|
|
137
|
-
const start = offset + 8;
|
|
138
|
-
const trailer = start + graphSize - TRAILER.length;
|
|
139
|
-
check(buffer.subarray(trailer, trailer + TRAILER.length).equals(TRAILER), "Bun trailer mismatch");
|
|
140
|
-
const offsets = trailer - OFFSETS_SIZE;
|
|
141
|
-
check(u64(buffer, offsets) === offsets - start, "Bun byte count mismatch");
|
|
142
|
-
const table = start + buffer.readUInt32LE(offsets + 8);
|
|
143
|
-
const tableSize = buffer.readUInt32LE(offsets + 12);
|
|
144
|
-
const entryIndex = buffer.readUInt32LE(offsets + 16);
|
|
145
|
-
check(tableSize > 0 && tableSize % MODULE_SIZE === 0 && table >= start &&
|
|
146
|
-
table + tableSize <= offsets, "unsupported Bun module table");
|
|
147
|
-
check(entryIndex < tableSize / MODULE_SIZE, "entry index outside module table");
|
|
148
|
-
const entry = table + entryIndex * MODULE_SIZE;
|
|
149
|
-
const regions = [];
|
|
150
|
-
for (let row = table; row < table + tableSize; row += MODULE_SIZE) {
|
|
151
|
-
// path, source, sourcemap, bytecode, bytecode module map, module path.
|
|
152
|
-
for (const field of [0, 8, 16, 24, 32, 40]) {
|
|
153
|
-
const pos = buffer.readUInt32LE(row + field);
|
|
154
|
-
const size = buffer.readUInt32LE(row + field + 4);
|
|
155
|
-
check(pos <= table - start && size <= table - start - pos,
|
|
156
|
-
"module data overlaps metadata or exceeds graph");
|
|
157
|
-
if (size > 0) regions.push({ row, field, start: start + pos, end: start + pos + size });
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
const sourceOffset = start + buffer.readUInt32LE(entry + 8);
|
|
161
|
-
const sourceSize = buffer.readUInt32LE(entry + 12);
|
|
162
|
-
check(sourceSize > 0 && buffer[sourceOffset + sourceSize] === 0, "entry source is not null terminated");
|
|
163
|
-
for (const region of regions) {
|
|
164
|
-
if (region.row === entry && region.field === 8) continue;
|
|
165
|
-
check(region.end <= sourceOffset || region.start > sourceOffset + sourceSize,
|
|
166
|
-
"entry source overlaps another module field");
|
|
167
|
-
}
|
|
168
|
-
check(buffer.subarray(entry + 48, entry + 52).equals(Buffer.from([1, 1, 1, 0])),
|
|
169
|
-
"expected UTF-8 JavaScript ESM entry (module ABI changed)");
|
|
170
|
-
const pathOffset = start + buffer.readUInt32LE(entry);
|
|
171
|
-
const entryPath = buffer.subarray(pathOffset, pathOffset + buffer.readUInt32LE(entry + 4)).toString();
|
|
172
|
-
check(/^(\/\$bunfs\/root\/|B:\/~BUN\/root\/|file:\/\/\/B:\/%7EBUN\/root\/)/.test(entryPath),
|
|
173
|
-
"unexpected standalone entry path");
|
|
174
|
-
return { ...executable, start, offsets, table, tableSize, entry, entryPath, sourceOffset, sourceSize };
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
export function sha256(buffer) {
|
|
178
|
-
return createHash("sha256").update(buffer).digest("hex");
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/** The hash binds the native entry to exactly the patched bundle we packaged. */
|
|
182
|
-
export function bootstrapSource(bundleSha256, version) {
|
|
183
|
-
check(/^[a-f0-9]{64}$/.test(bundleSha256), "invalid bundle SHA-256");
|
|
184
|
-
// Native graph entries carry an upstream builtin-import map. A dynamic
|
|
185
|
-
// filesystem import enters Bun's normal loader without reusing that map.
|
|
186
|
-
return `if (typeof Bun.ant?.CellSegmenter !== "function") throw new Error("Claude requires Anthropic's private Bun.ant.CellSegmenter runtime");
|
|
187
|
-
if (process.argv[2] === "--coder-runtime-info") {
|
|
188
|
-
console.log(JSON.stringify({version:${JSON.stringify(version)},bun:Bun.version,platform:process.platform,arch:process.arch,cellSegmenter:typeof Bun.ant.CellSegmenter,bundleSha256:${JSON.stringify(bundleSha256)}}));
|
|
189
|
-
} else {
|
|
190
|
-
globalThis[Symbol.for("coder.claude.bundleSha256")] = ${JSON.stringify(bundleSha256)};
|
|
191
|
-
await import(process.execPath + ".mjs");
|
|
192
|
-
}
|
|
193
|
-
`;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export function loaderSource(bundleSha256) {
|
|
197
|
-
check(/^[a-f0-9]{64}$/.test(bundleSha256), "invalid bundle SHA-256");
|
|
198
|
-
return `import { dirname, join } from "node:path";
|
|
199
|
-
import { pathToFileURL } from "node:url";
|
|
200
|
-
import { readFileSync } from "node:fs";
|
|
201
|
-
import { createHash } from "node:crypto";
|
|
202
|
-
const bundle = join(dirname(process.execPath), "cc.js");
|
|
203
|
-
if (globalThis[Symbol.for("coder.claude.bundleSha256")] !== ${JSON.stringify(bundleSha256)}) throw new Error("Claude native runtime / loader hash mismatch; reinstall the complete platform artifact");
|
|
204
|
-
if (createHash("sha256").update(readFileSync(bundle)).digest("hex") !== ${JSON.stringify(bundleSha256)}) throw new Error("Claude native runtime / cc.js hash mismatch; rebuild and copy the complete platform artifact");
|
|
205
|
-
await import(pathToFileURL(bundle).href);
|
|
206
|
-
`;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
export function replaceEntry(buffer, source, expectedPlatform) {
|
|
210
|
-
const graph = inspectModuleGraph(buffer);
|
|
211
|
-
check(graph.platform === expectedPlatform, `expected ${expectedPlatform}, found ${graph.platform}`);
|
|
212
|
-
const code = Buffer.from(source);
|
|
213
|
-
check(code.length > 0 && code.length <= graph.sourceSize, "replacement exceeds entry source allocation");
|
|
214
|
-
const result = Buffer.from(buffer);
|
|
215
|
-
result.fill(0, graph.sourceOffset, graph.sourceOffset + graph.sourceSize);
|
|
216
|
-
code.copy(result, graph.sourceOffset);
|
|
217
|
-
result.writeUInt32LE(code.length, graph.entry + 12);
|
|
218
|
-
// Invalidate the entry's source map, compiled bytecode and bytecode module
|
|
219
|
-
// map; otherwise JSC can execute the old Claude entry despite the new source.
|
|
220
|
-
result.fill(0, graph.entry + 16, graph.entry + 40);
|
|
221
|
-
if (graph.signatureDirectory !== undefined) {
|
|
222
|
-
// The upstream Authenticode signature is no longer valid. Leave overlay
|
|
223
|
-
// bytes in place, detach its certificate table, and let release signing
|
|
224
|
-
// apply the project's identity. A zero PE checksum is valid for user apps.
|
|
225
|
-
result.fill(0, graph.signatureDirectory, graph.signatureDirectory + 8);
|
|
226
|
-
result.writeUInt32LE(0, graph.checksumOffset);
|
|
227
|
-
}
|
|
228
|
-
inspectModuleGraph(result);
|
|
229
|
-
return result;
|
|
230
|
-
}
|