@hanzo/dev 0.6.91 → 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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // Unified entry point for the Hanzo Dev CLI.
2
+ // Unified entry point for the Code CLI.
3
3
 
4
4
  import path from "path";
5
5
  import { fileURLToPath } from "url";
@@ -14,6 +14,10 @@ const __dirname = path.dirname(__filename);
14
14
 
15
15
  const { platform, arch } = process;
16
16
 
17
+ // Important: Never delegate to another system's `code` binary (e.g., VS Code).
18
+ // When users run via `npx @hanzo/dev`, we must always execute our
19
+ // packaged native binary by absolute path to avoid PATH collisions.
20
+
17
21
  function isWSL() {
18
22
  if (platform !== "linux") return false;
19
23
  try {
@@ -70,10 +74,11 @@ if (!targetTriple) {
70
74
  throw new Error(`Unsupported platform: ${platform} (${arch})`);
71
75
  }
72
76
 
73
- // Binary names for Hanzo dev
77
+ // Prefer new 'dev-*' binary names; fall back to legacy 'coder-*' if missing.
74
78
  let binaryPath = path.join(__dirname, "..", "bin", `dev-${targetTriple}`);
75
- let legacyBinaryPath = path.join(__dirname, "..", "bin", `dev-${targetTriple}`);
79
+ let legacyBinaryPath = path.join(__dirname, "..", "bin", `coder-${targetTriple}`);
76
80
 
81
+ // --- Bootstrap helper (runs if the binary is missing, e.g. Bun blocked postinstall) ---
77
82
  import { existsSync, chmodSync, statSync, openSync, readSync, closeSync, mkdirSync, copyFileSync, readFileSync, unlinkSync, createWriteStream } from "fs";
78
83
 
79
84
  const validateBinary = (p) => {
@@ -116,12 +121,14 @@ const getCacheDir = (version) => {
116
121
  } else {
117
122
  base = process.env.XDG_CACHE_HOME || path.join(home, ".cache");
118
123
  }
119
- const dir = path.join(base, "hanzo", "dev", version);
124
+ const dir = path.join(base, "hanzoai", "dev", version);
120
125
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
121
126
  return dir;
122
127
  };
123
128
 
124
129
  const getCachedBinaryPath = (version) => {
130
+ // targetTriple already includes the proper extension on Windows ("...msvc.exe").
131
+ // Do not append another suffix; just use the exact targetTriple-derived name.
125
132
  const cacheDir = getCacheDir(version);
126
133
  return path.join(cacheDir, `dev-${targetTriple}`);
127
134
  };
@@ -132,6 +139,7 @@ const httpsDownload = (url, dest) => new Promise((resolve, reject) => {
132
139
  const req = httpsGet(url, (res) => {
133
140
  const status = res.statusCode || 0;
134
141
  if (status >= 300 && status < 400 && res.headers.location) {
142
+ // follow one redirect recursively
135
143
  return resolve(httpsDownload(res.headers.location, dest));
136
144
  }
137
145
  if (status !== 200) {
@@ -156,17 +164,19 @@ const httpsDownload = (url, dest) => new Promise((resolve, reject) => {
156
164
 
157
165
  const tryBootstrapBinary = async () => {
158
166
  try {
167
+ // 1) Read our published version
159
168
  const pkg = JSON.parse(readFileSync(path.join(__dirname, "..", "package.json"), "utf8"));
160
169
  const version = pkg.version;
161
170
 
162
171
  const binDir = path.join(__dirname, "..", "bin");
163
172
  if (!existsSync(binDir)) mkdirSync(binDir, { recursive: true });
164
173
 
165
- // Fast path: user cache
174
+ // 2) Fast path: user cache
166
175
  const cachePath = getCachedBinaryPath(version);
167
176
  if (existsSync(cachePath)) {
168
177
  const v = validateBinary(cachePath);
169
178
  if (v.ok) {
179
+ // Prefer running directly from cache; mirror into node_modules on Unix
170
180
  if (platform !== "win32") {
171
181
  copyFileSync(cachePath, binaryPath);
172
182
  try { chmodSync(binaryPath, 0o755); } catch {}
@@ -175,11 +185,11 @@ const tryBootstrapBinary = async () => {
175
185
  }
176
186
  }
177
187
 
178
- // Try platform package (if present)
188
+ // 3) Try platform package (if present)
179
189
  try {
180
190
  const req = (await import("module")).createRequire(import.meta.url);
181
191
  const name = (() => {
182
- if (platform === "win32") return "@hanzo/dev-win32-x64";
192
+ if (platform === "win32") return "@hanzo/dev-win32-x64"; // may be unpublished; falls through
183
193
  const plt = nodePlatform();
184
194
  const cpu = nodeArch();
185
195
  if (plt === "darwin" && cpu === "arm64") return "@hanzo/dev-darwin-arm64";
@@ -194,6 +204,7 @@ const tryBootstrapBinary = async () => {
194
204
  const pkgDir = path.dirname(pkgJson);
195
205
  const src = path.join(pkgDir, "bin", `dev-${targetTriple}`);
196
206
  if (existsSync(src)) {
207
+ // Always ensure cache has the binary; on Unix mirror into node_modules
197
208
  copyFileSync(src, cachePath);
198
209
  if (platform !== "win32") {
199
210
  copyFileSync(cachePath, binaryPath);
@@ -205,22 +216,21 @@ const tryBootstrapBinary = async () => {
205
216
  }
206
217
  } catch { /* ignore */ }
207
218
 
208
- // Download from GitHub release
219
+ // 4) Download from GitHub release
209
220
  const isWin = platform === "win32";
210
- // Use 'dev-*' binary names matching the release artifacts
211
- const binaryName = `dev-${targetTriple}`;
212
221
  const archiveName = isWin
213
- ? `${binaryName}.zip`
214
- : (() => { try { execSync("zstd --version", { stdio: "ignore", shell: true }); return `${binaryName}.zst`; } catch { return `${binaryName}.tar.gz`; } })();
222
+ ? `dev-${targetTriple}.zip`
223
+ : (() => { try { execSync("zstd --version", { stdio: "ignore", shell: true }); return `dev-${targetTriple}.zst`; } catch { return `dev-${targetTriple}.tar.gz`; } })();
215
224
  const url = `https://github.com/hanzoai/dev/releases/download/v${version}/${archiveName}`;
216
225
  const tmp = path.join(binDir, `.${archiveName}.part`);
217
226
  return httpsDownload(url, tmp)
218
227
  .then(() => {
219
228
  if (isWin) {
229
+ // Extract zip with robust fallbacks and use a safe temp dir, then move to cache
220
230
  try {
221
- const sysRoot = process.env.SystemRoot || process.env.windir || 'C:\\Windows';
231
+ const sysRoot = process.env.SystemRoot || process.env.windir || 'C:\\\Windows';
222
232
  const psFull = path.join(sysRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe');
223
- const unzipDest = getCacheDir(version);
233
+ const unzipDest = getCacheDir(version); // extract directly to cache location
224
234
  const psCmd = `Expand-Archive -Path '${tmp}' -DestinationPath '${unzipDest}' -Force`;
225
235
  let ok = false;
226
236
  try { execSync(`"${psFull}" -NoProfile -NonInteractive -Command "${psCmd}"`, { stdio: 'ignore' }); ok = true; } catch {}
@@ -241,7 +251,11 @@ const tryBootstrapBinary = async () => {
241
251
  try { unlinkSync(tmp); } catch {}
242
252
  }
243
253
  }
244
- if (platform !== "win32") {
254
+ // On Windows, the file was extracted directly into the cache dir
255
+ if (platform === "win32") {
256
+ // Ensure the expected filename exists in cache; Expand-Archive extracts exact name
257
+ // No action required here; validation occurs below against cachePath
258
+ } else {
245
259
  try { copyFileSync(binaryPath, cachePath); } catch {}
246
260
  }
247
261
 
@@ -256,7 +270,7 @@ const tryBootstrapBinary = async () => {
256
270
  }
257
271
  };
258
272
 
259
- // If missing, attempt to bootstrap into place
273
+ // If missing, attempt to bootstrap into place (helps when Bun blocks postinstall)
260
274
  let binaryReady = existsSync(binaryPath) || existsSync(legacyBinaryPath);
261
275
  if (!binaryReady) {
262
276
  let runtimePostinstallError = null;
@@ -273,6 +287,7 @@ if (!binaryReady) {
273
287
  if (runtimePostinstallError && !lastBootstrapError) {
274
288
  lastBootstrapError = runtimePostinstallError;
275
289
  }
290
+ // retry legacy name in case archive provided coder-*
276
291
  if (existsSync(legacyBinaryPath) && !existsSync(binaryPath)) {
277
292
  binaryPath = legacyBinaryPath;
278
293
  }
@@ -295,14 +310,17 @@ try {
295
310
  // ignore
296
311
  }
297
312
 
313
+ // Check if binary exists and try to fix permissions if needed
314
+ // fs imports are above; keep for readability if tree-shaken by bundlers
298
315
  import { spawnSync } from "child_process";
299
316
  if (existsSync(binaryPath)) {
300
317
  try {
318
+ // Ensure binary is executable on Unix-like systems
301
319
  if (platform !== "win32") {
302
320
  chmodSync(binaryPath, 0o755);
303
321
  }
304
322
  } catch (e) {
305
- // Ignore permission errors
323
+ // Ignore permission errors, will be caught below if it's a real problem
306
324
  }
307
325
  } else {
308
326
  console.error(`Binary not found: ${binaryPath}`);
@@ -321,6 +339,9 @@ if (existsSync(binaryPath)) {
321
339
  process.exit(1);
322
340
  }
323
341
 
342
+ // Lightweight header validation to provide clearer errors before spawn
343
+ // Reuse the validateBinary helper defined above in the bootstrap section.
344
+
324
345
  const validation = validateBinary(binaryPath);
325
346
  if (!validation.ok) {
326
347
  console.error(`The native binary at ${binaryPath} appears invalid: ${validation.reason}`);
@@ -339,25 +360,50 @@ if (!validation.ok) {
339
360
  process.exit(1);
340
361
  }
341
362
 
342
- // If running under npx/npm, emit a concise notice
363
+ // If running under npx/npm, emit a concise notice about which binary path is used
343
364
  try {
344
365
  const ua = process.env.npm_config_user_agent || "";
345
366
  const isNpx = ua.includes("npx");
346
367
  if (isNpx && process.stderr && process.stderr.isTTY) {
347
- console.error(`@hanzo/dev: running bundled binary -> ${binaryPath}`);
368
+ // Best-effort discovery of another 'code' on PATH for user clarity
369
+ let otherCode = "";
370
+ try {
371
+ const cmd = process.platform === "win32" ? "where code" : "command -v code || which code || true";
372
+ const out = spawnSync(process.platform === "win32" ? "cmd" : "bash", [
373
+ process.platform === "win32" ? "/c" : "-lc",
374
+ cmd,
375
+ ], { encoding: "utf8" });
376
+ const line = (out.stdout || "").split(/\r?\n/).map((s) => s.trim()).filter(Boolean)[0];
377
+ if (line && !line.includes("@hanzo/dev")) {
378
+ otherCode = line;
379
+ }
380
+ } catch {}
381
+ if (otherCode) {
382
+ console.error(`@hanzo/dev: running bundled binary -> ${binaryPath}`);
383
+ console.error(`Note: a different 'code' exists at ${otherCode}; not delegating.`);
384
+ } else {
385
+ console.error(`@hanzo/dev: running bundled binary -> ${binaryPath}`);
386
+ }
348
387
  }
349
388
  } catch {}
350
389
 
390
+ // Use an asynchronous spawn instead of spawnSync so that Node is able to
391
+ // respond to signals (e.g. Ctrl-C / SIGINT) while the native binary is
392
+ // executing. This allows us to forward those signals to the child process
393
+ // and guarantees that when either the child terminates or the parent
394
+ // receives a fatal signal, both processes exit in a predictable manner.
351
395
  const { spawn } = await import("child_process");
352
396
 
353
- process.env.DEV_BINARY_PATH = binaryPath;
397
+ // Make the resolved native binary path visible to spawned agents/subprocesses.
398
+ process.env.CODE_BINARY_PATH = binaryPath;
354
399
 
355
400
  const child = spawn(binaryPath, process.argv.slice(2), {
356
401
  stdio: "inherit",
357
- env: { ...process.env, DEV_MANAGED_BY_NPM: "1", DEV_BINARY_PATH: binaryPath },
402
+ env: { ...process.env, CODER_MANAGED_BY_NPM: "1", CODEX_MANAGED_BY_NPM: "1", CODE_BINARY_PATH: binaryPath },
358
403
  });
359
404
 
360
405
  child.on("error", (err) => {
406
+ // Typically triggered when the binary is missing or not executable.
361
407
  const code = err && err.code;
362
408
  if (code === 'EACCES') {
363
409
  console.error(`Permission denied: ${binaryPath}`);
@@ -381,6 +427,10 @@ child.on("error", (err) => {
381
427
  process.exit(1);
382
428
  });
383
429
 
430
+ // Forward common termination signals to the child so that it shuts down
431
+ // gracefully. In the handler we temporarily disable the default behavior of
432
+ // exiting immediately; once the child has been signaled we simply wait for
433
+ // its exit event which will in turn terminate the parent (see below).
384
434
  const forwardSignal = (signal) => {
385
435
  if (child.killed) {
386
436
  return;
@@ -396,6 +446,11 @@ const forwardSignal = (signal) => {
396
446
  process.on(sig, () => forwardSignal(sig));
397
447
  });
398
448
 
449
+ // When the child exits, mirror its termination reason in the parent so that
450
+ // shell scripts and other tooling observe the correct exit status.
451
+ // Wrap the lifetime of the child process in a Promise so that we can await
452
+ // its termination in a structured way. The Promise resolves with an object
453
+ // describing how the child exited: either via exit code or due to a signal.
399
454
  const childResult = await new Promise((resolve) => {
400
455
  child.on("exit", (code, signal) => {
401
456
  if (signal) {
@@ -407,6 +462,8 @@ const childResult = await new Promise((resolve) => {
407
462
  });
408
463
 
409
464
  if (childResult.type === "signal") {
465
+ // Re-emit the same signal so that the parent terminates with the expected
466
+ // semantics (this also sets the correct exit code of 128 + n).
410
467
  process.kill(process.pid, childResult.signal);
411
468
  } else {
412
469
  process.exit(childResult.exitCode);
package/bin/codex.js ADDED
@@ -0,0 +1,200 @@
1
+ #!/usr/bin/env node
2
+ // Unified entry point for the Codex CLI.
3
+
4
+ import { spawn } from "node:child_process";
5
+ import { existsSync } from "fs";
6
+ import { createRequire } from "node:module";
7
+ import path from "path";
8
+ import { fileURLToPath } from "url";
9
+
10
+ // __dirname equivalent in ESM
11
+ const __filename = fileURLToPath(import.meta.url);
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
+ };
24
+
25
+ const { platform, arch } = process;
26
+
27
+ let targetTriple = null;
28
+ switch (platform) {
29
+ case "linux":
30
+ case "android":
31
+ switch (arch) {
32
+ case "x64":
33
+ targetTriple = "x86_64-unknown-linux-musl";
34
+ break;
35
+ case "arm64":
36
+ targetTriple = "aarch64-unknown-linux-musl";
37
+ break;
38
+ default:
39
+ break;
40
+ }
41
+ break;
42
+ case "darwin":
43
+ switch (arch) {
44
+ case "x64":
45
+ targetTriple = "x86_64-apple-darwin";
46
+ break;
47
+ case "arm64":
48
+ targetTriple = "aarch64-apple-darwin";
49
+ break;
50
+ default:
51
+ break;
52
+ }
53
+ break;
54
+ case "win32":
55
+ switch (arch) {
56
+ case "x64":
57
+ targetTriple = "x86_64-pc-windows-msvc";
58
+ break;
59
+ case "arm64":
60
+ targetTriple = "aarch64-pc-windows-msvc";
61
+ break;
62
+ default:
63
+ break;
64
+ }
65
+ break;
66
+ default:
67
+ break;
68
+ }
69
+
70
+ if (!targetTriple) {
71
+ throw new Error(`Unsupported platform: ${platform} (${arch})`);
72
+ }
73
+
74
+ const platformPackage = PLATFORM_PACKAGE_BY_TARGET[targetTriple];
75
+ if (!platformPackage) {
76
+ throw new Error(`Unsupported target triple: ${targetTriple}`);
77
+ }
78
+
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);
121
+ const binaryPath = path.join(archRoot, "codex", codexBinaryName);
122
+
123
+ // Use an asynchronous spawn instead of spawnSync so that Node is able to
124
+ // respond to signals (e.g. Ctrl-C / SIGINT) while the native binary is
125
+ // executing. This allows us to forward those signals to the child process
126
+ // and guarantees that when either the child terminates or the parent
127
+ // receives a fatal signal, both processes exit in a predictable manner.
128
+
129
+ function getUpdatedPath(newDirs) {
130
+ const pathSep = process.platform === "win32" ? ";" : ":";
131
+ const existingPath = process.env.PATH || "";
132
+ const updatedPath = [
133
+ ...newDirs,
134
+ ...existingPath.split(pathSep).filter(Boolean),
135
+ ].join(pathSep);
136
+ return updatedPath;
137
+ }
138
+
139
+ const additionalDirs = [];
140
+ const pathDir = path.join(archRoot, "path");
141
+ if (existsSync(pathDir)) {
142
+ additionalDirs.push(pathDir);
143
+ }
144
+ const updatedPath = getUpdatedPath(additionalDirs);
145
+
146
+ const child = spawn(binaryPath, process.argv.slice(2), {
147
+ stdio: "inherit",
148
+ env: { ...process.env, PATH: updatedPath, CODEX_MANAGED_BY_NPM: "1" },
149
+ });
150
+
151
+ child.on("error", (err) => {
152
+ // Typically triggered when the binary is missing or not executable.
153
+ // Re-throwing here will terminate the parent with a non-zero exit code
154
+ // while still printing a helpful stack trace.
155
+ // eslint-disable-next-line no-console
156
+ console.error(err);
157
+ process.exit(1);
158
+ });
159
+
160
+ // Forward common termination signals to the child so that it shuts down
161
+ // gracefully. In the handler we temporarily disable the default behavior of
162
+ // exiting immediately; once the child has been signaled we simply wait for
163
+ // its exit event which will in turn terminate the parent (see below).
164
+ const forwardSignal = (signal) => {
165
+ if (child.killed) {
166
+ return;
167
+ }
168
+ try {
169
+ child.kill(signal);
170
+ } catch {
171
+ /* ignore */
172
+ }
173
+ };
174
+
175
+ ["SIGINT", "SIGTERM", "SIGHUP"].forEach((sig) => {
176
+ process.on(sig, () => forwardSignal(sig));
177
+ });
178
+
179
+ // When the child exits, mirror its termination reason in the parent so that
180
+ // shell scripts and other tooling observe the correct exit status.
181
+ // Wrap the lifetime of the child process in a Promise so that we can await
182
+ // its termination in a structured way. The Promise resolves with an object
183
+ // describing how the child exited: either via exit code or due to a signal.
184
+ const childResult = await new Promise((resolve) => {
185
+ child.on("exit", (code, signal) => {
186
+ if (signal) {
187
+ resolve({ type: "signal", signal });
188
+ } else {
189
+ resolve({ type: "code", exitCode: code ?? 1 });
190
+ }
191
+ });
192
+ });
193
+
194
+ if (childResult.type === "signal") {
195
+ // Re-emit the same signal so that the parent terminates with the expected
196
+ // semantics (this also sets the correct exit code of 128 + n).
197
+ process.kill(process.pid, childResult.signal);
198
+ } else {
199
+ process.exit(childResult.exitCode);
200
+ }
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@hanzo/dev",
3
- "version": "0.6.91",
3
+ "version": "0.6.93",
4
4
  "license": "Apache-2.0",
5
- "description": "Hanzo AI coding assistant - intelligent CLI for developers",
5
+ "description": "Local AI coding agent for your terminal, powered by Hanzo AI",
6
6
  "bin": {
7
- "dev": "bin/dev.js",
8
- "hanzo": "bin/dev.js"
7
+ "dev": "bin/coder.js"
9
8
  },
10
9
  "type": "module",
11
10
  "engines": {
12
11
  "node": ">=16"
13
12
  },
14
13
  "files": [
15
- "bin/dev.js",
14
+ "bin/coder.js",
15
+ "bin/codex.js",
16
16
  "postinstall.js",
17
17
  "scripts/preinstall.js",
18
18
  "scripts/windows-cleanup.ps1",
@@ -21,7 +21,7 @@
21
21
  "scripts": {
22
22
  "preinstall": "node scripts/preinstall.js",
23
23
  "postinstall": "node postinstall.js",
24
- "prepublishOnly": "node -e \"const fs=require('fs'),path=require('path'); const repoGit=path.join(__dirname,'..','.git'); const inCi=process.env.GITHUB_ACTIONS==='true'||process.env.CI==='true'; if(fs.existsSync(repoGit) && !inCi){ console.error('Refusing to publish from dev-cli. Publishing happens via release.yml.'); process.exit(1);} else { console.log(inCi ? 'CI publish detected.' : 'Publishing staged package...'); }\""
24
+ "prepublishOnly": "node -e \"const fs=require('fs'),path=require('path'); const repoGit=path.join(__dirname,'..','.git'); const inCi=process.env.GITHUB_ACTIONS==='true'||process.env.CI==='true'; if(fs.existsSync(repoGit) && !inCi){ console.error('Refusing to publish from codex-cli. Publishing happens via release.yml.'); process.exit(1);} else { console.log(inCi ? 'CI publish detected.' : 'Publishing staged package...'); }\""
25
25
  },
26
26
  "repository": {
27
27
  "type": "git",
@@ -35,10 +35,10 @@
35
35
  "prettier": "^3.3.3"
36
36
  },
37
37
  "optionalDependencies": {
38
- "@hanzo/dev-darwin-arm64": "0.6.91",
39
- "@hanzo/dev-darwin-x64": "0.6.91",
40
- "@hanzo/dev-linux-x64-musl": "0.6.91",
41
- "@hanzo/dev-linux-arm64-musl": "0.6.91",
42
- "@hanzo/dev-win32-x64": "0.6.91"
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
  }