@just-every/code 0.2.4 → 0.2.5

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/bin/coder.js CHANGED
@@ -10,6 +10,20 @@ const __dirname = path.dirname(__filename);
10
10
 
11
11
  const { platform, arch } = process;
12
12
 
13
+ const isWSL = () => {
14
+ if (platform !== "linux") return false;
15
+ try {
16
+ const os = require("os");
17
+ const rel = os.release().toLowerCase();
18
+ if (rel.includes("microsoft")) return true;
19
+ const fs = require("fs");
20
+ const txt = fs.readFileSync("/proc/version", "utf8").toLowerCase();
21
+ return txt.includes("microsoft");
22
+ } catch {
23
+ return false;
24
+ }
25
+ };
26
+
13
27
  let targetTriple = null;
14
28
  switch (platform) {
15
29
  case "linux":
@@ -78,6 +92,11 @@ if (existsSync(binaryPath)) {
78
92
  console.error(`Please try reinstalling the package:`);
79
93
  console.error(` npm uninstall -g @just-every/code`);
80
94
  console.error(` npm install -g @just-every/code`);
95
+ if (isWSL()) {
96
+ console.error("Detected WSL. Install inside WSL (Ubuntu) separately:");
97
+ console.error(" npx -y @just-every/code@latest (run inside WSL)");
98
+ console.error("If installed globally on Windows, those binaries are not usable from WSL.");
99
+ }
81
100
  process.exit(1);
82
101
  }
83
102
 
@@ -122,6 +141,10 @@ if (!validation.ok) {
122
141
  console.error("If the issue persists, clear npm cache and disable antivirus temporarily:");
123
142
  console.error(" npm cache clean --force");
124
143
  }
144
+ if (isWSL()) {
145
+ console.error("Detected WSL. Ensure you install/run inside WSL, not Windows:");
146
+ console.error(" npx -y @just-every/code@latest (inside WSL)");
147
+ }
125
148
  process.exit(1);
126
149
  }
127
150
 
@@ -152,6 +175,10 @@ child.on("error", (err) => {
152
175
  console.error("On Windows, ensure the .exe downloaded correctly (proxy/AV can interfere).");
153
176
  console.error("Try clearing cache: npm cache clean --force");
154
177
  }
178
+ if (isWSL()) {
179
+ console.error("Detected WSL. Windows binaries cannot be executed from WSL.");
180
+ console.error("Install inside WSL and run there: npx -y @just-every/code@latest");
181
+ }
155
182
  } else {
156
183
  console.error(err);
157
184
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@just-every/code",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Lightweight coding agent that runs in your terminal - fork of OpenAI Codex",
6
6
  "bin": {
package/postinstall.js CHANGED
@@ -29,10 +29,12 @@ function getTargetTriple() {
29
29
  return `${rustArch}-${rustPlatform}`;
30
30
  }
31
31
 
32
- async function downloadBinary(url, dest, maxRedirects = 5) {
33
- return new Promise((resolve, reject) => {
32
+ async function downloadBinary(url, dest, maxRedirects = 5, maxRetries = 3) {
33
+ const sleep = (ms) => new Promise(r => setTimeout(r, ms));
34
+
35
+ const doAttempt = () => new Promise((resolve, reject) => {
34
36
  const attempt = (currentUrl, redirectsLeft) => {
35
- get(currentUrl, (response) => {
37
+ const req = get(currentUrl, (response) => {
36
38
  const status = response.statusCode || 0;
37
39
  const location = response.headers.location;
38
40
 
@@ -46,28 +48,74 @@ async function downloadBinary(url, dest, maxRedirects = 5) {
46
48
  }
47
49
 
48
50
  if (status === 200) {
49
- // Only create the file stream after we know it's a successful response
51
+ const expected = parseInt(response.headers['content-length'] || '0', 10) || 0;
52
+ let bytes = 0;
53
+ let timer;
54
+ const timeoutMs = 30000; // 30s inactivity timeout
55
+
56
+ const resetTimer = () => {
57
+ if (timer) clearTimeout(timer);
58
+ timer = setTimeout(() => {
59
+ req.destroy(new Error('download stalled'));
60
+ }, timeoutMs);
61
+ };
62
+
63
+ resetTimer();
64
+ response.on('data', (chunk) => {
65
+ bytes += chunk.length;
66
+ resetTimer();
67
+ });
68
+
50
69
  const file = createWriteStream(dest);
51
70
  response.pipe(file);
52
71
  file.on('finish', () => {
72
+ if (timer) clearTimeout(timer);
53
73
  file.close();
54
- resolve();
74
+ if (expected && bytes !== expected) {
75
+ try { unlinkSync(dest); } catch {}
76
+ reject(new Error(`incomplete download: got ${bytes} of ${expected} bytes`));
77
+ } else if (bytes === 0) {
78
+ try { unlinkSync(dest); } catch {}
79
+ reject(new Error('empty download'));
80
+ } else {
81
+ resolve();
82
+ }
55
83
  });
56
84
  file.on('error', (err) => {
85
+ if (timer) clearTimeout(timer);
57
86
  try { unlinkSync(dest); } catch {}
58
87
  reject(err);
59
88
  });
60
89
  } else {
61
90
  reject(new Error(`Failed to download: HTTP ${status}`));
62
91
  }
63
- }).on('error', (err) => {
92
+ });
93
+
94
+ req.on('error', (err) => {
64
95
  try { unlinkSync(dest); } catch {}
65
96
  reject(err);
66
97
  });
98
+
99
+ // Absolute request timeout to avoid hanging forever
100
+ req.setTimeout(120000, () => {
101
+ req.destroy(new Error('download timed out'));
102
+ });
67
103
  };
68
104
 
69
105
  attempt(url, maxRedirects);
70
106
  });
107
+
108
+ let attemptNum = 0;
109
+ while (true) {
110
+ try {
111
+ return await doAttempt();
112
+ } catch (e) {
113
+ attemptNum += 1;
114
+ if (attemptNum > maxRetries) throw e;
115
+ const backoff = Math.min(2000, 200 * attemptNum);
116
+ await sleep(backoff);
117
+ }
118
+ }
71
119
  }
72
120
 
73
121
  function validateDownloadedBinary(p) {