nuwax-codex 0.16.7 → 0.16.15
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/nuwax-codex.js +178 -69
- package/package.json +1 -9
package/bin/nuwax-codex.js
CHANGED
|
@@ -1,95 +1,204 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// Launcher for the nuwax-codex npm package.
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// the forwarded argv. Both the npm command and the native binary are named
|
|
6
|
-
// "nuwax-codex".
|
|
2
|
+
// Launcher for the nuwax-codex-ts npm package.
|
|
3
|
+
// Downloads the native `nuwax-codex` binary from GitHub Releases on first
|
|
4
|
+
// run and caches it locally. No platform-specific npm packages needed.
|
|
7
5
|
|
|
8
6
|
import { spawnSync } from "node:child_process";
|
|
9
|
-
import { existsSync } from "node:fs";
|
|
10
|
-
import {
|
|
7
|
+
import { createWriteStream, existsSync, mkdirSync, chmodSync } from "node:fs";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
import { join, dirname } from "node:path";
|
|
10
|
+
import { pipeline } from "node:stream/promises";
|
|
11
|
+
import { createGunzip } from "node:zlib";
|
|
11
12
|
import { familySync } from "detect-libc";
|
|
13
|
+
import { createRequire } from "node:module";
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const arch = process.arch;
|
|
17
|
-
|
|
18
|
-
const platformMap = {
|
|
19
|
-
darwin: {
|
|
20
|
-
arm64: "nuwax-codex-darwin-arm64",
|
|
21
|
-
x64: "nuwax-codex-darwin-x64",
|
|
22
|
-
},
|
|
23
|
-
linux: {
|
|
24
|
-
// arm64 Linux is not shipped (GitHub arm64 runners are too flaky to build
|
|
25
|
-
// it reliably); only x64 Linux is supported for now.
|
|
26
|
-
x64: familySync() === "musl"
|
|
27
|
-
? "nuwax-codex-linux-x64-musl"
|
|
28
|
-
: "nuwax-codex-linux-x64",
|
|
29
|
-
},
|
|
30
|
-
win32: {
|
|
31
|
-
arm64: "nuwax-codex-win32-arm64",
|
|
32
|
-
x64: "nuwax-codex-win32-x64",
|
|
33
|
-
},
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const packages = platformMap[platform];
|
|
37
|
-
if (!packages) {
|
|
38
|
-
console.error(`Unsupported platform: ${platform}`);
|
|
39
|
-
process.exit(1);
|
|
40
|
-
}
|
|
15
|
+
const require = createRequire(import.meta.url);
|
|
16
|
+
const VERSION = require("../package.json").version;
|
|
17
|
+
const OSS_CDN_BASE = "https://nuwa-packages.oss-rg-china-mainland.aliyuncs.com/nuwax-codex";
|
|
41
18
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
19
|
+
// -- platform helpers -------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
function getTargetTriple() {
|
|
22
|
+
const p = process.platform;
|
|
23
|
+
const a = process.arch;
|
|
24
|
+
|
|
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
|
+
return familySync() === "musl"
|
|
31
|
+
? "x86_64-unknown-linux-musl"
|
|
32
|
+
: "x86_64-unknown-linux-gnu";
|
|
46
33
|
}
|
|
34
|
+
if (p === "win32") {
|
|
35
|
+
return a === "arm64" ? "aarch64-pc-windows-msvc" : "x86_64-pc-windows-msvc";
|
|
36
|
+
}
|
|
37
|
+
throw new Error(`Unsupported platform: ${p}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function getArchiveExt() {
|
|
41
|
+
return process.platform === "win32" ? "zip" : "tar.gz";
|
|
42
|
+
}
|
|
47
43
|
|
|
48
|
-
|
|
44
|
+
function getBinaryName() {
|
|
45
|
+
return process.platform === "win32" ? "nuwax-codex.exe" : "nuwax-codex";
|
|
49
46
|
}
|
|
50
47
|
|
|
51
|
-
//
|
|
52
|
-
function getBinaryPath() {
|
|
53
|
-
const packageName = getPlatformPackage();
|
|
54
|
-
const binaryName =
|
|
55
|
-
process.platform === "win32" ? "nuwax-codex.exe" : "nuwax-codex";
|
|
48
|
+
// -- download & cache -------------------------------------------------------
|
|
56
49
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
50
|
+
function cacheDir() {
|
|
51
|
+
return join(homedir(), ".nuwax-codex-cache", VERSION);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function cachedBinaryPath() {
|
|
55
|
+
return join(cacheDir(), getBinaryName());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function downloadBinary(url, outPath) {
|
|
59
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
60
|
+
|
|
61
|
+
const res = await fetch(url, { redirect: "follow" });
|
|
62
|
+
if (!res.ok) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`Failed to download binary: HTTP ${res.status} ${res.statusText}\nURL: ${url}`,
|
|
60
65
|
);
|
|
66
|
+
}
|
|
61
67
|
|
|
62
|
-
|
|
63
|
-
|
|
68
|
+
const total = parseInt(res.headers.get("content-length") || "0", 10);
|
|
69
|
+
let downloaded = 0;
|
|
70
|
+
const reader = res.body.getReader();
|
|
71
|
+
const ws = createWriteStream(outPath);
|
|
72
|
+
const logInterval = setInterval(() => {
|
|
73
|
+
if (total > 0) {
|
|
74
|
+
process.stderr.write(
|
|
75
|
+
`\r Downloading nuwax-codex ${VERSION} … ${((downloaded / total) * 100).toFixed(0)}%`,
|
|
76
|
+
);
|
|
64
77
|
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
78
|
+
}, 500);
|
|
79
|
+
|
|
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();
|
|
68
90
|
}
|
|
91
|
+
process.stderr.write("\n");
|
|
92
|
+
|
|
93
|
+
if (process.platform !== "win32") {
|
|
94
|
+
chmodSync(outPath, 0o755);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
69
97
|
|
|
70
|
-
|
|
71
|
-
|
|
98
|
+
async function extractTarGz(archivePath, destDir) {
|
|
99
|
+
// Simple tar.gz extraction: members are listed sequentially as
|
|
100
|
+
// [header(512B)][content(padded to 512B)]...
|
|
101
|
+
const { createReadStream } = await import("node:fs");
|
|
102
|
+
const { createGunzip } = await import("node:zlib");
|
|
103
|
+
const { pipeline } = await import("node:stream/promises");
|
|
104
|
+
const { Transform } = await import("node:stream");
|
|
105
|
+
const { writeFileSync } = await import("node:fs");
|
|
106
|
+
|
|
107
|
+
const gunzip = createGunzip();
|
|
108
|
+
const rs = createReadStream(archivePath);
|
|
109
|
+
let buffer = Buffer.alloc(0);
|
|
110
|
+
|
|
111
|
+
await pipeline(
|
|
112
|
+
rs,
|
|
113
|
+
gunzip,
|
|
114
|
+
new Transform({
|
|
115
|
+
transform(chunk, _enc, cb) {
|
|
116
|
+
buffer = Buffer.concat([buffer, chunk]);
|
|
117
|
+
while (buffer.length >= 512) {
|
|
118
|
+
// Parse tar header
|
|
119
|
+
const name = buffer.toString("utf8", 0, 100).replace(/\0.*$/, "");
|
|
120
|
+
const sizeStr = buffer.toString("utf8", 124, 136).replace(/\0.*$/, "");
|
|
121
|
+
const size = parseInt(sizeStr, 8);
|
|
122
|
+
if (isNaN(size) || size < 0) break;
|
|
123
|
+
|
|
124
|
+
const totalSize = Math.ceil((512 + size) / 512) * 512;
|
|
125
|
+
if (buffer.length < totalSize) break;
|
|
126
|
+
|
|
127
|
+
if (name && !name.endsWith("/") && size > 0) {
|
|
128
|
+
const fileData = buffer.subarray(512, 512 + size);
|
|
129
|
+
const outPath = join(destDir, name);
|
|
130
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
131
|
+
writeFileSync(outPath, fileData);
|
|
132
|
+
if (process.platform !== "win32") {
|
|
133
|
+
chmodSync(outPath, 0o755);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
buffer = buffer.subarray(totalSize);
|
|
138
|
+
}
|
|
139
|
+
cb();
|
|
140
|
+
},
|
|
141
|
+
}),
|
|
72
142
|
);
|
|
73
|
-
console.error(`Platform: ${process.platform}, Architecture: ${process.arch}`);
|
|
74
|
-
process.exit(1);
|
|
75
143
|
}
|
|
76
144
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
145
|
+
async function extractZip(archivePath, destDir) {
|
|
146
|
+
// Use unzip command; Node.js has no built-in zip support.
|
|
147
|
+
const { execSync } = await import("node:child_process");
|
|
148
|
+
execSync(`unzip -q -o "${archivePath}" -d "${destDir}"`, { stdio: "inherit" });
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// -- main -------------------------------------------------------------------
|
|
152
|
+
|
|
153
|
+
async function ensureBinary() {
|
|
154
|
+
const cached = cachedBinaryPath();
|
|
155
|
+
if (existsSync(cached)) {
|
|
156
|
+
return cached;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const target = getTargetTriple();
|
|
160
|
+
const ext = getArchiveExt();
|
|
161
|
+
const url = `${OSS_CDN_BASE}/v${VERSION}/nuwax-codex-${VERSION}-${target}.${ext}`;
|
|
84
162
|
|
|
85
|
-
|
|
86
|
-
|
|
163
|
+
console.error(`Downloading nuwax-codex ${VERSION} for ${target} …`);
|
|
164
|
+
console.error(` ${url}`);
|
|
165
|
+
|
|
166
|
+
const dir = cacheDir();
|
|
167
|
+
mkdirSync(dir, { recursive: true });
|
|
168
|
+
const archivePath = join(dir, `nuwax-codex.${ext}`);
|
|
169
|
+
|
|
170
|
+
await downloadBinary(url, archivePath);
|
|
171
|
+
|
|
172
|
+
console.error(" Extracting …");
|
|
173
|
+
if (ext === "tar.gz") {
|
|
174
|
+
await extractTarGz(archivePath, dir);
|
|
175
|
+
} else {
|
|
176
|
+
await extractZip(archivePath, dir);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (!existsSync(cached)) {
|
|
180
|
+
console.error(" Error: binary not found after extraction at", cached);
|
|
87
181
|
process.exit(1);
|
|
88
182
|
}
|
|
89
183
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
184
|
+
return cached;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function run() {
|
|
188
|
+
ensureBinary().then((binaryPath) => {
|
|
189
|
+
const result = spawnSync(binaryPath, process.argv.slice(2), {
|
|
190
|
+
stdio: "inherit",
|
|
191
|
+
windowsHide: true,
|
|
192
|
+
});
|
|
193
|
+
if (result.error) {
|
|
194
|
+
console.error(`Failed to execute ${binaryPath}:`, result.error);
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
process.exit(result.status ?? 1);
|
|
198
|
+
}).catch((err) => {
|
|
199
|
+
console.error(err.message);
|
|
200
|
+
process.exit(1);
|
|
201
|
+
});
|
|
93
202
|
}
|
|
94
203
|
|
|
95
204
|
run();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuwax-codex",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.15",
|
|
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",
|
|
@@ -33,13 +33,5 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"detect-libc": "^2.0.0"
|
|
36
|
-
},
|
|
37
|
-
"optionalDependencies": {
|
|
38
|
-
"nuwax-codex-darwin-arm64": "0.16.7",
|
|
39
|
-
"nuwax-codex-darwin-x64": "0.16.7",
|
|
40
|
-
"nuwax-codex-linux-x64": "0.16.7",
|
|
41
|
-
"nuwax-codex-linux-x64-musl": "0.16.7",
|
|
42
|
-
"nuwax-codex-win32-arm64": "0.16.7",
|
|
43
|
-
"nuwax-codex-win32-x64": "0.16.7"
|
|
44
36
|
}
|
|
45
37
|
}
|