@hanzo/dev 0.6.92 → 0.6.93
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 +27 -9
- package/bin/codex.js +58 -2
- package/package.json +6 -6
- package/postinstall.js +35 -8
package/bin/coder.js
CHANGED
|
@@ -6,6 +6,7 @@ import { fileURLToPath } from "url";
|
|
|
6
6
|
import { platform as nodePlatform, arch as nodeArch } from "os";
|
|
7
7
|
import { execSync } from "child_process";
|
|
8
8
|
import { get as httpsGet } from "https";
|
|
9
|
+
import { runPostinstall } from "../postinstall.js";
|
|
9
10
|
|
|
10
11
|
// __dirname equivalent in ESM
|
|
11
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -17,7 +18,7 @@ const { platform, arch } = process;
|
|
|
17
18
|
// When users run via `npx @hanzo/dev`, we must always execute our
|
|
18
19
|
// packaged native binary by absolute path to avoid PATH collisions.
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
function isWSL() {
|
|
21
22
|
if (platform !== "linux") return false;
|
|
22
23
|
try {
|
|
23
24
|
const txt = readFileSync("/proc/version", "utf8").toLowerCase();
|
|
@@ -25,7 +26,7 @@ const isWSL = () => {
|
|
|
25
26
|
} catch {
|
|
26
27
|
return false;
|
|
27
28
|
}
|
|
28
|
-
}
|
|
29
|
+
}
|
|
29
30
|
|
|
30
31
|
let targetTriple = null;
|
|
31
32
|
switch (platform) {
|
|
@@ -270,12 +271,26 @@ const tryBootstrapBinary = async () => {
|
|
|
270
271
|
};
|
|
271
272
|
|
|
272
273
|
// If missing, attempt to bootstrap into place (helps when Bun blocks postinstall)
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
274
|
+
let binaryReady = existsSync(binaryPath) || existsSync(legacyBinaryPath);
|
|
275
|
+
if (!binaryReady) {
|
|
276
|
+
let runtimePostinstallError = null;
|
|
277
|
+
try {
|
|
278
|
+
await runPostinstall({ invokedByRuntime: true, skipGlobalAlias: true });
|
|
279
|
+
} catch (err) {
|
|
280
|
+
runtimePostinstallError = err;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
binaryReady = existsSync(binaryPath) || existsSync(legacyBinaryPath);
|
|
284
|
+
if (!binaryReady) {
|
|
285
|
+
const ok = await tryBootstrapBinary();
|
|
286
|
+
if (!ok) {
|
|
287
|
+
if (runtimePostinstallError && !lastBootstrapError) {
|
|
288
|
+
lastBootstrapError = runtimePostinstallError;
|
|
289
|
+
}
|
|
290
|
+
// retry legacy name in case archive provided coder-*
|
|
291
|
+
if (existsSync(legacyBinaryPath) && !existsSync(binaryPath)) {
|
|
292
|
+
binaryPath = legacyBinaryPath;
|
|
293
|
+
}
|
|
279
294
|
}
|
|
280
295
|
}
|
|
281
296
|
}
|
|
@@ -379,9 +394,12 @@ try {
|
|
|
379
394
|
// receives a fatal signal, both processes exit in a predictable manner.
|
|
380
395
|
const { spawn } = await import("child_process");
|
|
381
396
|
|
|
397
|
+
// Make the resolved native binary path visible to spawned agents/subprocesses.
|
|
398
|
+
process.env.CODE_BINARY_PATH = binaryPath;
|
|
399
|
+
|
|
382
400
|
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
383
401
|
stdio: "inherit",
|
|
384
|
-
env: { ...process.env, CODER_MANAGED_BY_NPM: "1", CODEX_MANAGED_BY_NPM: "1" },
|
|
402
|
+
env: { ...process.env, CODER_MANAGED_BY_NPM: "1", CODEX_MANAGED_BY_NPM: "1", CODE_BINARY_PATH: binaryPath },
|
|
385
403
|
});
|
|
386
404
|
|
|
387
405
|
child.on("error", (err) => {
|
package/bin/codex.js
CHANGED
|
@@ -3,12 +3,24 @@
|
|
|
3
3
|
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
5
|
import { existsSync } from "fs";
|
|
6
|
+
import { createRequire } from "node:module";
|
|
6
7
|
import path from "path";
|
|
7
8
|
import { fileURLToPath } from "url";
|
|
8
9
|
|
|
9
10
|
// __dirname equivalent in ESM
|
|
10
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
12
|
const __dirname = path.dirname(__filename);
|
|
13
|
+
const require = createRequire(import.meta.url);
|
|
14
|
+
const codexPackageRoot = realpathSync(path.join(__dirname, ".."));
|
|
15
|
+
|
|
16
|
+
const PLATFORM_PACKAGE_BY_TARGET = {
|
|
17
|
+
"x86_64-unknown-linux-musl": "@openai/codex-linux-x64",
|
|
18
|
+
"aarch64-unknown-linux-musl": "@openai/codex-linux-arm64",
|
|
19
|
+
"x86_64-apple-darwin": "@openai/codex-darwin-x64",
|
|
20
|
+
"aarch64-apple-darwin": "@openai/codex-darwin-arm64",
|
|
21
|
+
"x86_64-pc-windows-msvc": "@openai/codex-win32-x64",
|
|
22
|
+
"aarch64-pc-windows-msvc": "@openai/codex-win32-arm64",
|
|
23
|
+
};
|
|
12
24
|
|
|
13
25
|
const { platform, arch } = process;
|
|
14
26
|
|
|
@@ -59,9 +71,53 @@ if (!targetTriple) {
|
|
|
59
71
|
throw new Error(`Unsupported platform: ${platform} (${arch})`);
|
|
60
72
|
}
|
|
61
73
|
|
|
62
|
-
const
|
|
63
|
-
|
|
74
|
+
const platformPackage = PLATFORM_PACKAGE_BY_TARGET[targetTriple];
|
|
75
|
+
if (!platformPackage) {
|
|
76
|
+
throw new Error(`Unsupported target triple: ${targetTriple}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
64
79
|
const codexBinaryName = process.platform === "win32" ? "codex.exe" : "codex";
|
|
80
|
+
const localVendorRoot = path.join(__dirname, "..", "vendor");
|
|
81
|
+
const localBinaryPath = path.join(
|
|
82
|
+
localVendorRoot,
|
|
83
|
+
targetTriple,
|
|
84
|
+
"codex",
|
|
85
|
+
codexBinaryName,
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
let vendorRoot;
|
|
89
|
+
try {
|
|
90
|
+
const packageJsonPath = require.resolve(`${platformPackage}/package.json`);
|
|
91
|
+
vendorRoot = path.join(path.dirname(packageJsonPath), "vendor");
|
|
92
|
+
} catch {
|
|
93
|
+
if (existsSync(localBinaryPath)) {
|
|
94
|
+
vendorRoot = localVendorRoot;
|
|
95
|
+
} else {
|
|
96
|
+
const packageManager = detectPackageManager();
|
|
97
|
+
const updateCommand =
|
|
98
|
+
packageManager === "bun"
|
|
99
|
+
? "bun install -g @openai/codex@latest"
|
|
100
|
+
: "npm install -g @openai/codex@latest";
|
|
101
|
+
throw new Error(
|
|
102
|
+
`Missing optional dependency ${platformPackage}. Reinstall Codex: ${updateCommand}`,
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!vendorRoot) {
|
|
108
|
+
const packageManager = detectPackageManager();
|
|
109
|
+
const updateCommand =
|
|
110
|
+
packageManager === "bun"
|
|
111
|
+
? "bun install -g @openai/codex@latest"
|
|
112
|
+
: packageManager === "pnpm"
|
|
113
|
+
? "pnpm add -g @openai/codex@latest"
|
|
114
|
+
: "npm install -g @openai/codex@latest";
|
|
115
|
+
throw new Error(
|
|
116
|
+
`Missing optional dependency ${platformPackage}. Reinstall Codex: ${updateCommand}`,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const archRoot = path.join(vendorRoot, targetTriple);
|
|
65
121
|
const binaryPath = path.join(archRoot, "codex", codexBinaryName);
|
|
66
122
|
|
|
67
123
|
// Use an asynchronous spawn instead of spawnSync so that Node is able to
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/dev",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.93",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Local AI coding agent for your terminal, powered by Hanzo AI",
|
|
6
6
|
"bin": {
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"prettier": "^3.3.3"
|
|
36
36
|
},
|
|
37
37
|
"optionalDependencies": {
|
|
38
|
-
"@hanzo/dev-darwin-arm64": "0.6.
|
|
39
|
-
"@hanzo/dev-darwin-x64": "0.6.
|
|
40
|
-
"@hanzo/dev-linux-x64-musl": "0.6.
|
|
41
|
-
"@hanzo/dev-linux-arm64-musl": "0.6.
|
|
42
|
-
"@hanzo/dev-win32-x64": "0.6.
|
|
38
|
+
"@hanzo/dev-darwin-arm64": "0.6.93",
|
|
39
|
+
"@hanzo/dev-darwin-x64": "0.6.93",
|
|
40
|
+
"@hanzo/dev-linux-x64-musl": "0.6.93",
|
|
41
|
+
"@hanzo/dev-linux-arm64-musl": "0.6.93",
|
|
42
|
+
"@hanzo/dev-win32-x64": "0.6.93"
|
|
43
43
|
}
|
|
44
44
|
}
|
package/postinstall.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Non-functional change to trigger release workflow
|
|
3
3
|
|
|
4
4
|
import { existsSync, mkdirSync, createWriteStream, chmodSync, readFileSync, readSync, writeFileSync, unlinkSync, statSync, openSync, closeSync, copyFileSync, fsyncSync, renameSync, realpathSync } from 'fs';
|
|
5
|
-
import { join, dirname } from 'path';
|
|
5
|
+
import { join, dirname, resolve } from 'path';
|
|
6
6
|
import { fileURLToPath } from 'url';
|
|
7
7
|
import { get } from 'https';
|
|
8
8
|
import { platform, arch, tmpdir } from 'os';
|
|
@@ -289,13 +289,21 @@ function validateDownloadedBinary(p) {
|
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
-
async function
|
|
292
|
+
export async function runPostinstall(options = {}) {
|
|
293
|
+
const { skipGlobalAlias = false, invokedByRuntime = false } = options;
|
|
294
|
+
if (process.env.CODE_POSTINSTALL_DRY_RUN === '1') {
|
|
295
|
+
return { skipped: true };
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (invokedByRuntime) {
|
|
299
|
+
process.env.CODE_RUNTIME_POSTINSTALL = process.env.CODE_RUNTIME_POSTINSTALL || '1';
|
|
300
|
+
}
|
|
293
301
|
// Detect potential PATH conflict with an existing `code` command (e.g., VS Code)
|
|
294
302
|
// Only relevant for global installs; skip for npx/local installs to keep postinstall fast.
|
|
295
303
|
const ua = process.env.npm_config_user_agent || '';
|
|
296
304
|
const isNpx = ua.includes('npx');
|
|
297
305
|
const isGlobal = process.env.npm_config_global === 'true';
|
|
298
|
-
if (isGlobal && !isNpx) {
|
|
306
|
+
if (!skipGlobalAlias && isGlobal && !isNpx) {
|
|
299
307
|
try {
|
|
300
308
|
const whichCmd = process.platform === 'win32' ? 'where code' : 'command -v code || which code || true';
|
|
301
309
|
const resolved = execSync(whichCmd, { stdio: ['ignore', 'pipe', 'ignore'], shell: process.platform !== 'win32' }).toString().split(/\r?\n/).filter(Boolean)[0];
|
|
@@ -421,8 +429,15 @@ async function main() {
|
|
|
421
429
|
// - Windows: .zip
|
|
422
430
|
// - macOS/Linux: prefer .zst if `zstd` CLI is available; otherwise use .tar.gz
|
|
423
431
|
const isWin = isWindows;
|
|
432
|
+
const detectedWSL = (() => {
|
|
433
|
+
if (platform() !== 'linux') return false;
|
|
434
|
+
try {
|
|
435
|
+
const ver = readFileSync('/proc/version', 'utf8').toLowerCase();
|
|
436
|
+
return ver.includes('microsoft') || !!process.env.WSL_DISTRO_NAME;
|
|
437
|
+
} catch { return false; }
|
|
438
|
+
})();
|
|
424
439
|
const binDirReal = (() => { try { return realpathSync(binDir); } catch { return binDir; } })();
|
|
425
|
-
const mirrorToLocal = !(isWin || (
|
|
440
|
+
const mirrorToLocal = !(isWin || (detectedWSL && isPathOnWindowsFs(binDirReal)));
|
|
426
441
|
let useZst = false;
|
|
427
442
|
if (!isWin) {
|
|
428
443
|
try {
|
|
@@ -755,7 +770,19 @@ async function main() {
|
|
|
755
770
|
}
|
|
756
771
|
}
|
|
757
772
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
773
|
+
function isExecutedDirectly() {
|
|
774
|
+
const entry = process.argv[1];
|
|
775
|
+
if (!entry) return false;
|
|
776
|
+
try {
|
|
777
|
+
return resolve(entry) === fileURLToPath(import.meta.url);
|
|
778
|
+
} catch {
|
|
779
|
+
return false;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
if (isExecutedDirectly()) {
|
|
784
|
+
runPostinstall().catch(error => {
|
|
785
|
+
console.error('Installation failed:', error);
|
|
786
|
+
process.exit(1);
|
|
787
|
+
});
|
|
788
|
+
}
|