@just-every/code 0.2.48 → 0.2.50

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.
Files changed (2) hide show
  1. package/bin/coder.js +190 -3
  2. package/package.json +6 -6
package/bin/coder.js CHANGED
@@ -3,6 +3,9 @@
3
3
 
4
4
  import path from "path";
5
5
  import { fileURLToPath } from "url";
6
+ import { platform as nodePlatform, arch as nodeArch } from "os";
7
+ import { execSync } from "child_process";
8
+ import { get as httpsGet } from "https";
6
9
 
7
10
  // __dirname equivalent in ESM
8
11
  const __filename = fileURLToPath(import.meta.url);
@@ -76,12 +79,196 @@ if (!targetTriple) {
76
79
 
77
80
  // Prefer new 'code-*' binary names; fall back to legacy 'coder-*' if missing.
78
81
  let binaryPath = path.join(__dirname, "..", "bin", `code-${targetTriple}`);
79
- if (!existsSync(binaryPath)) {
80
- binaryPath = path.join(__dirname, "..", "bin", `coder-${targetTriple}`);
82
+ let legacyBinaryPath = path.join(__dirname, "..", "bin", `coder-${targetTriple}`);
83
+
84
+ // --- Bootstrap helper (runs if the binary is missing, e.g. Bun blocked postinstall) ---
85
+ import { existsSync, chmodSync, statSync, openSync, readSync, closeSync, mkdirSync, copyFileSync, readFileSync, unlinkSync } from "fs";
86
+
87
+ const validateBinary = (p) => {
88
+ try {
89
+ const st = statSync(p);
90
+ if (!st.isFile() || st.size === 0) {
91
+ return { ok: false, reason: "empty or not a regular file" };
92
+ }
93
+ const fd = openSync(p, "r");
94
+ try {
95
+ const buf = Buffer.alloc(4);
96
+ const n = readSync(fd, buf, 0, 4, 0);
97
+ if (n < 2) return { ok: false, reason: "too short" };
98
+ if (platform === "win32") {
99
+ if (!(buf[0] === 0x4d && buf[1] === 0x5a)) return { ok: false, reason: "invalid PE header (missing MZ)" };
100
+ } else if (platform === "linux" || platform === "android") {
101
+ if (!(buf[0] === 0x7f && buf[1] === 0x45 && buf[2] === 0x4c && buf[3] === 0x46)) return { ok: false, reason: "invalid ELF header" };
102
+ } else if (platform === "darwin") {
103
+ const isMachO = (buf[0] === 0xcf && buf[1] === 0xfa && buf[2] === 0xed && buf[3] === 0xfe) ||
104
+ (buf[0] === 0xca && buf[1] === 0xfe && buf[2] === 0xba && buf[3] === 0xbe);
105
+ if (!isMachO) return { ok: false, reason: "invalid Mach-O header" };
106
+ }
107
+ } finally {
108
+ closeSync(fd);
109
+ }
110
+ return { ok: true };
111
+ } catch (e) {
112
+ return { ok: false, reason: e.message };
113
+ }
114
+ };
115
+
116
+ const getCacheDir = (version) => {
117
+ const plt = nodePlatform();
118
+ const home = process.env.HOME || process.env.USERPROFILE || "";
119
+ let base = "";
120
+ if (plt === "win32") {
121
+ base = process.env.LOCALAPPDATA || path.join(home, "AppData", "Local");
122
+ } else if (plt === "darwin") {
123
+ base = path.join(home, "Library", "Caches");
124
+ } else {
125
+ base = process.env.XDG_CACHE_HOME || path.join(home, ".cache");
126
+ }
127
+ const dir = path.join(base, "just-every", "code", version);
128
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
129
+ return dir;
130
+ };
131
+
132
+ const getCachedBinaryPath = (version) => {
133
+ const isWin = nodePlatform() === "win32";
134
+ const ext = isWin ? ".exe" : "";
135
+ const cacheDir = getCacheDir(version);
136
+ return path.join(cacheDir, `code-${targetTriple}${ext}`);
137
+ };
138
+
139
+ const httpsDownload = (url, dest) => new Promise((resolve, reject) => {
140
+ const req = httpsGet(url, (res) => {
141
+ const status = res.statusCode || 0;
142
+ if (status >= 300 && status < 400 && res.headers.location) {
143
+ // follow one redirect recursively
144
+ return resolve(httpsDownload(res.headers.location, dest));
145
+ }
146
+ if (status !== 200) {
147
+ return reject(new Error(`HTTP ${status}`));
148
+ }
149
+ const out = require("fs").createWriteStream(dest);
150
+ res.pipe(out);
151
+ out.on("finish", () => out.close(resolve));
152
+ out.on("error", (e) => {
153
+ try { unlinkSync(dest); } catch {}
154
+ reject(e);
155
+ });
156
+ });
157
+ req.on("error", (e) => {
158
+ try { unlinkSync(dest); } catch {}
159
+ reject(e);
160
+ });
161
+ req.setTimeout(120000, () => {
162
+ req.destroy(new Error("download timed out"));
163
+ });
164
+ });
165
+
166
+ const tryBootstrapBinary = async () => {
167
+ try {
168
+ // 1) Read our published version
169
+ const pkg = JSON.parse(readFileSync(path.join(__dirname, "..", "package.json"), "utf8"));
170
+ const version = pkg.version;
171
+
172
+ const binDir = path.join(__dirname, "..", "bin");
173
+ if (!existsSync(binDir)) mkdirSync(binDir, { recursive: true });
174
+
175
+ // 2) Fast path: user cache
176
+ const cachePath = getCachedBinaryPath(version);
177
+ if (existsSync(cachePath)) {
178
+ const v = validateBinary(cachePath);
179
+ if (v.ok) {
180
+ copyFileSync(cachePath, binaryPath);
181
+ if (platform !== "win32") chmodSync(binaryPath, 0o755);
182
+ return existsSync(binaryPath);
183
+ }
184
+ }
185
+
186
+ // 3) Try platform package (if present)
187
+ try {
188
+ const req = (await import("module")).createRequire(import.meta.url);
189
+ const name = (() => {
190
+ if (platform === "win32") return "@just-every/code-win32-x64"; // may be unpublished; falls through
191
+ const plt = nodePlatform();
192
+ const cpu = nodeArch();
193
+ if (plt === "darwin" && cpu === "arm64") return "@just-every/code-darwin-arm64";
194
+ if (plt === "darwin" && cpu === "x64") return "@just-every/code-darwin-x64";
195
+ if (plt === "linux" && cpu === "x64") return "@just-every/code-linux-x64-musl";
196
+ if (plt === "linux" && cpu === "arm64") return "@just-every/code-linux-arm64-musl";
197
+ return null;
198
+ })();
199
+ if (name) {
200
+ try {
201
+ const pkgJson = req.resolve(`${name}/package.json`);
202
+ const pkgDir = path.dirname(pkgJson);
203
+ const src = path.join(pkgDir, "bin", `code-${targetTriple}${platform === "win32" ? ".exe" : ""}`);
204
+ if (existsSync(src)) {
205
+ copyFileSync(src, binaryPath);
206
+ if (platform !== "win32") chmodSync(binaryPath, 0o755);
207
+ // refresh cache
208
+ try { copyFileSync(binaryPath, cachePath); } catch {}
209
+ return existsSync(binaryPath);
210
+ }
211
+ } catch { /* ignore and fall back */ }
212
+ }
213
+ } catch { /* ignore */ }
214
+
215
+ // 4) Download from GitHub release
216
+ const isWin = platform === "win32";
217
+ const archiveName = isWin
218
+ ? `code-${targetTriple}.zip`
219
+ : (() => { try { execSync("zstd --version", { stdio: "ignore", shell: true }); return `code-${targetTriple}.zst`; } catch { return `code-${targetTriple}.tar.gz`; } })();
220
+ const url = `https://github.com/just-every/code/releases/download/v${version}/${archiveName}`;
221
+ const tmp = path.join(binDir, `.${archiveName}.part`);
222
+ return httpsDownload(url, tmp)
223
+ .then(() => {
224
+ if (isWin) {
225
+ try {
226
+ const ps = `powershell -NoProfile -NonInteractive -Command "Expand-Archive -Path '${tmp}' -DestinationPath '${binDir}' -Force"`;
227
+ execSync(ps, { stdio: "ignore" });
228
+ } catch (e) {
229
+ throw new Error(`failed to unzip: ${e.message}`);
230
+ } finally { try { unlinkSync(tmp); } catch {} }
231
+ } else {
232
+ if (archiveName.endsWith(".zst")) {
233
+ try { execSync(`zstd -d '${tmp}' -o '${binaryPath}'`, { stdio: 'ignore', shell: true }); }
234
+ catch (e) { try { unlinkSync(tmp); } catch {}; throw new Error(`failed to decompress zst: ${e.message}`); }
235
+ try { unlinkSync(tmp); } catch {}
236
+ } else {
237
+ try { execSync(`tar -xzf '${tmp}' -C '${binDir}'`, { stdio: 'ignore', shell: true }); }
238
+ catch (e) { try { unlinkSync(tmp); } catch {}; throw new Error(`failed to extract tar.gz: ${e.message}`); }
239
+ try { unlinkSync(tmp); } catch {}
240
+ }
241
+ }
242
+ const v = validateBinary(binaryPath);
243
+ if (!v.ok) throw new Error(`invalid binary (${v.reason})`);
244
+ if (platform !== "win32") chmodSync(binaryPath, 0o755);
245
+ try { copyFileSync(binaryPath, cachePath); } catch {}
246
+ return true;
247
+ })
248
+ .catch((_e) => false);
249
+ } catch {
250
+ return false;
251
+ }
252
+ };
253
+
254
+ // If missing, attempt to bootstrap into place (helps when Bun blocks postinstall)
255
+ if (!existsSync(binaryPath) && !existsSync(legacyBinaryPath)) {
256
+ const ok = await tryBootstrapBinary();
257
+ if (!ok) {
258
+ // retry legacy name in case archive provided coder-*
259
+ if (existsSync(legacyBinaryPath) && !existsSync(binaryPath)) {
260
+ binaryPath = legacyBinaryPath;
261
+ }
262
+ }
263
+ }
264
+
265
+ // Fall back to legacy name if primary is still missing
266
+ if (!existsSync(binaryPath) && existsSync(legacyBinaryPath)) {
267
+ binaryPath = legacyBinaryPath;
81
268
  }
82
269
 
83
270
  // Check if binary exists and try to fix permissions if needed
84
- import { existsSync, chmodSync, statSync, openSync, readSync, closeSync } from "fs";
271
+ // fs imports are above; keep for readability if tree-shaken by bundlers
85
272
  import { spawnSync } from "child_process";
86
273
  if (existsSync(binaryPath)) {
87
274
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@just-every/code",
3
- "version": "0.2.48",
3
+ "version": "0.2.50",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Lightweight coding agent that runs in your terminal - fork of OpenAI Codex",
6
6
  "bin": {
@@ -34,10 +34,10 @@
34
34
  "prettier": "^3.3.3"
35
35
  },
36
36
  "optionalDependencies": {
37
- "@just-every/code-darwin-arm64": "0.2.48",
38
- "@just-every/code-darwin-x64": "0.2.48",
39
- "@just-every/code-linux-x64-musl": "0.2.48",
40
- "@just-every/code-linux-arm64-musl": "0.2.48",
41
- "@just-every/code-win32-x64": "0.2.48"
37
+ "@just-every/code-darwin-arm64": "0.2.50",
38
+ "@just-every/code-darwin-x64": "0.2.50",
39
+ "@just-every/code-linux-x64-musl": "0.2.50",
40
+ "@just-every/code-linux-arm64-musl": "0.2.50",
41
+ "@just-every/code-win32-x64": "0.2.50"
42
42
  }
43
43
  }