nuwax-codex 0.16.13 → 0.17.2-beta.1

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.
@@ -143,9 +143,15 @@ async function extractTarGz(archivePath, destDir) {
143
143
  }
144
144
 
145
145
  async function extractZip(archivePath, destDir) {
146
- // Use unzip command; Node.js has no built-in zip support.
146
+ // extractZip 仅在 Windows 上触发(getArchiveExt 对 win32 返回 zip)。
147
+ // Windows 没有内置 `unzip` 命令,改用 PowerShell 的 Expand-Archive 解压。
147
148
  const { execSync } = await import("node:child_process");
148
- execSync(`unzip -q -o "${archivePath}" -d "${destDir}"`, { stdio: "inherit" });
149
+ const psArchive = archivePath.replace(/'/g, "''");
150
+ const psDest = destDir.replace(/'/g, "''");
151
+ execSync(
152
+ `powershell -NoProfile -NonInteractive -Command "Expand-Archive -LiteralPath '${psArchive}' -DestinationPath '${psDest}' -Force"`,
153
+ { stdio: "inherit" },
154
+ );
149
155
  }
150
156
 
151
157
  // -- main -------------------------------------------------------------------
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env node
2
+ // Postinstall script: pre-downloads the native `nuwax-codex` binary from
3
+ // Alibaba Cloud OSS so the first CLI invocation is instant.
4
+
5
+ import { createWriteStream, existsSync, mkdirSync, chmodSync, writeFileSync } from "node:fs";
6
+ import { homedir } from "node:os";
7
+ import { join, dirname } from "node:path";
8
+ import { createGunzip } from "node:zlib";
9
+ import { pipeline } from "node:stream/promises";
10
+ import { Transform } from "node:stream";
11
+ import { createReadStream } from "node:fs";
12
+ import { createRequire } from "node:module";
13
+
14
+ const require = createRequire(import.meta.url);
15
+ const VERSION = require("../package.json").version;
16
+ const OSS_CDN_BASE = "https://nuwa-packages.oss-rg-china-mainland.aliyuncs.com/nuwax-codex";
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Platform helpers
20
+ // ---------------------------------------------------------------------------
21
+
22
+ function getTargetTriple() {
23
+ const p = process.platform;
24
+ const a = process.arch;
25
+ if (p === "darwin") {
26
+ return a === "arm64" ? "aarch64-apple-darwin" : "x86_64-apple-darwin";
27
+ }
28
+ if (p === "linux") {
29
+ if (a !== "x64") throw new Error(`Unsupported Linux arch: ${a}`);
30
+ const { familySync } = require("detect-libc");
31
+ return familySync() === "musl"
32
+ ? "x86_64-unknown-linux-musl"
33
+ : "x86_64-unknown-linux-gnu";
34
+ }
35
+ if (p === "win32") {
36
+ return a === "arm64" ? "aarch64-pc-windows-msvc" : "x86_64-pc-windows-msvc";
37
+ }
38
+ throw new Error(`Unsupported platform: ${p}`);
39
+ }
40
+
41
+ function getArchiveExt() {
42
+ return process.platform === "win32" ? "zip" : "tar.gz";
43
+ }
44
+
45
+ function getBinaryName() {
46
+ return process.platform === "win32" ? "nuwax-codex.exe" : "nuwax-codex";
47
+ }
48
+
49
+ function cacheDir() {
50
+ return join(homedir(), ".nuwax-codex-cache", VERSION);
51
+ }
52
+
53
+ function cachedBinaryPath() {
54
+ return join(cacheDir(), getBinaryName());
55
+ }
56
+
57
+ // ---------------------------------------------------------------------------
58
+ // Download
59
+ // ---------------------------------------------------------------------------
60
+
61
+ async function downloadBinary(url, outPath) {
62
+ mkdirSync(dirname(outPath), { recursive: true });
63
+ const res = await fetch(url, { redirect: "follow" });
64
+ if (!res.ok) {
65
+ throw new Error(
66
+ `Failed to download binary: HTTP ${res.status} ${res.statusText}\nURL: ${url}`,
67
+ );
68
+ }
69
+ const total = parseInt(res.headers.get("content-length") || "0", 10);
70
+ let downloaded = 0;
71
+ const reader = res.body.getReader();
72
+ const ws = createWriteStream(outPath);
73
+ const logInterval = setInterval(() => {
74
+ if (total > 0) {
75
+ process.stderr.write(
76
+ `\r Downloading nuwax-codex ${VERSION} … ${((downloaded / total) * 100).toFixed(0)}%`,
77
+ );
78
+ }
79
+ }, 500);
80
+ try {
81
+ while (true) {
82
+ const { done, value } = await reader.read();
83
+ if (done) break;
84
+ ws.write(value);
85
+ downloaded += value.length;
86
+ }
87
+ } finally {
88
+ clearInterval(logInterval);
89
+ ws.end();
90
+ }
91
+ process.stderr.write("\n");
92
+ if (process.platform !== "win32") {
93
+ chmodSync(outPath, 0o755);
94
+ }
95
+ }
96
+
97
+ // ---------------------------------------------------------------------------
98
+ // Extraction
99
+ // ---------------------------------------------------------------------------
100
+
101
+ async function extractTarGz(archivePath, destDir) {
102
+ const gunzip = createGunzip();
103
+ const rs = createReadStream(archivePath);
104
+ let buffer = Buffer.alloc(0);
105
+
106
+ await pipeline(
107
+ rs,
108
+ gunzip,
109
+ new Transform({
110
+ transform(chunk, _enc, cb) {
111
+ buffer = Buffer.concat([buffer, chunk]);
112
+ while (buffer.length >= 512) {
113
+ const name = buffer.toString("utf8", 0, 100).replace(/\0.*$/, "");
114
+ const sizeStr = buffer.toString("utf8", 124, 136).replace(/\0.*$/, "");
115
+ const size = parseInt(sizeStr, 8);
116
+ if (isNaN(size) || size < 0) break;
117
+ const totalSize = Math.ceil((512 + size) / 512) * 512;
118
+ if (buffer.length < totalSize) break;
119
+ if (name && !name.endsWith("/") && size > 0) {
120
+ const fileData = buffer.subarray(512, 512 + size);
121
+ const outPath = join(destDir, name);
122
+ mkdirSync(dirname(outPath), { recursive: true });
123
+ writeFileSync(outPath, fileData);
124
+ if (process.platform !== "win32") {
125
+ chmodSync(outPath, 0o755);
126
+ }
127
+ }
128
+ buffer = buffer.subarray(totalSize);
129
+ }
130
+ cb();
131
+ },
132
+ }),
133
+ );
134
+ }
135
+
136
+ async function extractZip(archivePath, destDir) {
137
+ // extractZip 仅在 Windows 上触发(getArchiveExt 对 win32 返回 zip)。
138
+ // Windows 没有内置 `unzip` 命令,改用 PowerShell 的 Expand-Archive 解压,
139
+ // 否则 Windows 用户安装后预下载会被静默吞掉、首次运行 CLI 直接报错退出。
140
+ const { execSync } = await import("node:child_process");
141
+ const psArchive = archivePath.replace(/'/g, "''");
142
+ const psDest = destDir.replace(/'/g, "''");
143
+ execSync(
144
+ `powershell -NoProfile -NonInteractive -Command "Expand-Archive -LiteralPath '${psArchive}' -DestinationPath '${psDest}' -Force"`,
145
+ { stdio: "inherit" },
146
+ );
147
+ }
148
+
149
+ // ---------------------------------------------------------------------------
150
+ // Main
151
+ // ---------------------------------------------------------------------------
152
+
153
+ async function main() {
154
+ const cached = cachedBinaryPath();
155
+ if (existsSync(cached)) {
156
+ process.stderr.write(`nuwax-codex ${VERSION} binary already cached, skipping download.\n`);
157
+ return;
158
+ }
159
+
160
+ const target = getTargetTriple();
161
+ const ext = getArchiveExt();
162
+ const url = `${OSS_CDN_BASE}/v${VERSION}/nuwax-codex-${VERSION}-${target}.${ext}`;
163
+
164
+ process.stderr.write(`Pre-downloading nuwax-codex ${VERSION} for ${target} …\n`);
165
+ process.stderr.write(` ${url}\n`);
166
+
167
+ const dir = cacheDir();
168
+ mkdirSync(dir, { recursive: true });
169
+ const archivePath = join(dir, `nuwax-codex.${ext}`);
170
+
171
+ await downloadBinary(url, archivePath);
172
+
173
+ process.stderr.write(" Extracting …\n");
174
+ if (ext === "tar.gz") {
175
+ await extractTarGz(archivePath, dir);
176
+ } else {
177
+ await extractZip(archivePath, dir);
178
+ }
179
+
180
+ if (existsSync(cached)) {
181
+ process.stderr.write(`✓ nuwax-codex ${VERSION} ready at ${cached}\n`);
182
+ } else {
183
+ process.stderr.write(`⚠ nuwax-codex ${VERSION} download completed but binary not found at ${cached}\n`);
184
+ }
185
+ }
186
+
187
+ main().catch((err) => {
188
+ process.stderr.write(`nuwax-codex postinstall: ${err.message}\n`);
189
+ // Never fail the install — binary will be downloaded on first run instead
190
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuwax-codex",
3
- "version": "0.16.13",
3
+ "version": "0.17.2-beta.1",
4
4
  "type": "module",
5
5
  "description": "Fork of OpenAI Codex CLI with domestic (Chinese) LLM support via genai",
6
6
  "license": "Apache-2.0",