zcf 3.3.2 → 3.3.3
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/README.md +9 -1
- package/dist/chunks/simple-config.mjs +107 -18
- package/dist/i18n/locales/en/codex.json +1 -0
- package/dist/i18n/locales/en/installation.json +1 -0
- package/dist/i18n/locales/zh-CN/codex.json +1 -0
- package/dist/i18n/locales/zh-CN/installation.json +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,6 +29,13 @@
|
|
|
29
29
|
|
|
30
30
|
---
|
|
31
31
|
|
|
32
|
+
[](https://z.ai/subscribe?ic=8JVLJQFSKB)
|
|
33
|
+
This project is sponsored by Z.ai, supporting us with their GLM CODING PLAN.
|
|
34
|
+
GLM CODING PLAN is a subscription service designed for AI coding, starting at just $3/month. It provides access to their flagship GLM-4.6 model across 10+ popular AI coding tools (Claude Code, Cline, Roo Code, etc.), offering developers top-tier, fast, and stable coding experiences.
|
|
35
|
+
Get 10% OFF GLM CODING PLAN:https://z.ai/subscribe?ic=8JVLJQFSKB
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
32
39
|
<table>
|
|
33
40
|
<tr>
|
|
34
41
|
<td width="180"><a href="https://www.packyapi.com/register?aff=zcf"><img src="./src/assets/packycode.png" alt="PackyCode" width="150"></a></td>
|
|
@@ -164,7 +171,7 @@ ZCF now supports API provider presets that automatically configure baseUrl and m
|
|
|
164
171
|
**Supported Providers:**
|
|
165
172
|
- `302ai` - [302.AI](https://share.302.ai/gAT9VG) API Service
|
|
166
173
|
- `packycode` - [PackyCode](https://www.packyapi.com/register?aff=zcf) API Service
|
|
167
|
-
- `glm` - GLM
|
|
174
|
+
- `glm` - [GLM](https://z.ai/subscribe?ic=8JVLJQFSKB) API Service
|
|
168
175
|
- `minimax` - MiniMax API Service
|
|
169
176
|
- `kimi` - Kimi (Moonshot AI)
|
|
170
177
|
- `custom` - Custom API endpoint (requires manual URL configuration)
|
|
@@ -944,6 +951,7 @@ If you find this project helpful, please consider sponsoring its development. Yo
|
|
|
944
951
|
|
|
945
952
|
A huge thank you to all our sponsors for their generous support!
|
|
946
953
|
- [302.AI](https://share.302.ai/gAT9VG) (first corporate sponsorship 🤠)
|
|
954
|
+
- [GLM](https://z.ai/subscribe?ic=8JVLJQFSKB) (first AI model sponsorship 🤖)
|
|
947
955
|
- [PackyCode](https://www.packyapi.com/register?aff=zcf) (first API proxy service sponsor 🧝🏻♀️)
|
|
948
956
|
- Tc (first sponsor)
|
|
949
957
|
- Argolinhas (first ko-fi sponsor ٩(•̤̀ᵕ•̤́๑))
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as nodeFs from 'node:fs';
|
|
2
|
+
import { existsSync, mkdirSync, copyFileSync, readFileSync, writeFileSync, rmSync, rmdirSync, readdirSync, statSync, unlinkSync, renameSync } from 'node:fs';
|
|
2
3
|
import process from 'node:process';
|
|
3
4
|
import ansis from 'ansis';
|
|
4
5
|
import inquirer from 'inquirer';
|
|
@@ -16,7 +17,7 @@ import { rm, mkdir, copyFile as copyFile$1 } from 'node:fs/promises';
|
|
|
16
17
|
import i18next from 'i18next';
|
|
17
18
|
import Backend from 'i18next-fs-backend';
|
|
18
19
|
|
|
19
|
-
const version = "3.3.
|
|
20
|
+
const version = "3.3.3";
|
|
20
21
|
const homepage = "https://github.com/UfoMiao/zcf";
|
|
21
22
|
|
|
22
23
|
const i18n = i18next.createInstance();
|
|
@@ -523,7 +524,7 @@ function getPlatform() {
|
|
|
523
524
|
return "linux";
|
|
524
525
|
}
|
|
525
526
|
function isTermux() {
|
|
526
|
-
return !!(process.env.PREFIX && process.env.PREFIX.includes("com.termux")) || !!process.env.TERMUX_VERSION || existsSync("/data/data/com.termux/files/usr");
|
|
527
|
+
return !!(process.env.PREFIX && process.env.PREFIX.includes("com.termux")) || !!process.env.TERMUX_VERSION || nodeFs.existsSync("/data/data/com.termux/files/usr");
|
|
527
528
|
}
|
|
528
529
|
function getTermuxPrefix() {
|
|
529
530
|
return process.env.PREFIX || "/data/data/com.termux/files/usr";
|
|
@@ -535,16 +536,16 @@ function isWSL() {
|
|
|
535
536
|
if (process.env.WSL_DISTRO_NAME) {
|
|
536
537
|
return true;
|
|
537
538
|
}
|
|
538
|
-
if (existsSync("/proc/version")) {
|
|
539
|
+
if (nodeFs.existsSync("/proc/version")) {
|
|
539
540
|
try {
|
|
540
|
-
const version = readFileSync("/proc/version", "utf8");
|
|
541
|
+
const version = nodeFs.readFileSync("/proc/version", "utf8");
|
|
541
542
|
if (version.includes("Microsoft") || version.includes("WSL")) {
|
|
542
543
|
return true;
|
|
543
544
|
}
|
|
544
545
|
} catch {
|
|
545
546
|
}
|
|
546
547
|
}
|
|
547
|
-
if (existsSync("/mnt/c")) {
|
|
548
|
+
if (nodeFs.existsSync("/mnt/c")) {
|
|
548
549
|
return true;
|
|
549
550
|
}
|
|
550
551
|
return false;
|
|
@@ -553,9 +554,9 @@ function getWSLDistro() {
|
|
|
553
554
|
if (process.env.WSL_DISTRO_NAME) {
|
|
554
555
|
return process.env.WSL_DISTRO_NAME;
|
|
555
556
|
}
|
|
556
|
-
if (existsSync("/etc/os-release")) {
|
|
557
|
+
if (nodeFs.existsSync("/etc/os-release")) {
|
|
557
558
|
try {
|
|
558
|
-
const osRelease = readFileSync("/etc/os-release", "utf8");
|
|
559
|
+
const osRelease = nodeFs.readFileSync("/etc/os-release", "utf8");
|
|
559
560
|
const nameMatch = osRelease.match(/^PRETTY_NAME="(.+)"$/m);
|
|
560
561
|
if (nameMatch) {
|
|
561
562
|
return nameMatch[1];
|
|
@@ -570,9 +571,9 @@ function getWSLInfo() {
|
|
|
570
571
|
return null;
|
|
571
572
|
}
|
|
572
573
|
let version = null;
|
|
573
|
-
if (existsSync("/proc/version")) {
|
|
574
|
+
if (nodeFs.existsSync("/proc/version")) {
|
|
574
575
|
try {
|
|
575
|
-
version = readFileSync("/proc/version", "utf8").trim();
|
|
576
|
+
version = nodeFs.readFileSync("/proc/version", "utf8").trim();
|
|
576
577
|
} catch {
|
|
577
578
|
}
|
|
578
579
|
}
|
|
@@ -599,6 +600,71 @@ function getSystemRoot() {
|
|
|
599
600
|
systemRoot = env.SystemRoot;
|
|
600
601
|
return systemRoot.replace(/\\+/g, "/").replace(/\/+/g, "/");
|
|
601
602
|
}
|
|
603
|
+
function shouldUseSudoForGlobalInstall() {
|
|
604
|
+
if (isTermux())
|
|
605
|
+
return false;
|
|
606
|
+
if (getPlatform() !== "linux")
|
|
607
|
+
return false;
|
|
608
|
+
const npmPrefix = getGlobalNpmPrefix();
|
|
609
|
+
if (npmPrefix) {
|
|
610
|
+
if (isPathInsideHome(npmPrefix) || canWriteToPath(npmPrefix))
|
|
611
|
+
return false;
|
|
612
|
+
}
|
|
613
|
+
const getuid = process.getuid;
|
|
614
|
+
if (typeof getuid !== "function")
|
|
615
|
+
return false;
|
|
616
|
+
try {
|
|
617
|
+
return getuid() !== 0;
|
|
618
|
+
} catch {
|
|
619
|
+
return false;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
function wrapCommandWithSudo(command, args) {
|
|
623
|
+
if (shouldUseSudoForGlobalInstall()) {
|
|
624
|
+
return {
|
|
625
|
+
command: "sudo",
|
|
626
|
+
args: [command, ...args],
|
|
627
|
+
usedSudo: true
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
return {
|
|
631
|
+
command,
|
|
632
|
+
args,
|
|
633
|
+
usedSudo: false
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
const WRITE_CHECK_FLAG = 2;
|
|
637
|
+
function normalizePath(path) {
|
|
638
|
+
return path.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
639
|
+
}
|
|
640
|
+
function isPathInsideHome(path) {
|
|
641
|
+
const home = process.env.HOME;
|
|
642
|
+
if (!home)
|
|
643
|
+
return false;
|
|
644
|
+
const normalizedHome = normalizePath(home);
|
|
645
|
+
const normalizedPath = normalizePath(path);
|
|
646
|
+
return normalizedPath === normalizedHome || normalizedPath.startsWith(`${normalizedHome}/`);
|
|
647
|
+
}
|
|
648
|
+
function canWriteToPath(path) {
|
|
649
|
+
try {
|
|
650
|
+
nodeFs.accessSync(path, WRITE_CHECK_FLAG);
|
|
651
|
+
return true;
|
|
652
|
+
} catch {
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
function getGlobalNpmPrefix() {
|
|
657
|
+
const env = process.env;
|
|
658
|
+
const envPrefix = env.npm_config_prefix || env.NPM_CONFIG_PREFIX || env.PREFIX;
|
|
659
|
+
if (envPrefix)
|
|
660
|
+
return envPrefix;
|
|
661
|
+
const execPath = process.execPath;
|
|
662
|
+
if (execPath) {
|
|
663
|
+
const binDir = dirname(execPath);
|
|
664
|
+
return dirname(binDir);
|
|
665
|
+
}
|
|
666
|
+
return null;
|
|
667
|
+
}
|
|
602
668
|
async function commandExists(command) {
|
|
603
669
|
try {
|
|
604
670
|
const cmd = getPlatform() === "windows" ? "where" : "which";
|
|
@@ -616,7 +682,7 @@ async function commandExists(command) {
|
|
|
616
682
|
`/data/data/com.termux/files/usr/bin/${command}`
|
|
617
683
|
];
|
|
618
684
|
for (const path of possiblePaths) {
|
|
619
|
-
if (existsSync(path)) {
|
|
685
|
+
if (nodeFs.existsSync(path)) {
|
|
620
686
|
return true;
|
|
621
687
|
}
|
|
622
688
|
}
|
|
@@ -629,7 +695,7 @@ async function commandExists(command) {
|
|
|
629
695
|
`${process.env.HOME}/.local/bin/${command}`
|
|
630
696
|
];
|
|
631
697
|
for (const path of commonPaths) {
|
|
632
|
-
if (existsSync(path)) {
|
|
698
|
+
if (nodeFs.existsSync(path)) {
|
|
633
699
|
return true;
|
|
634
700
|
}
|
|
635
701
|
}
|
|
@@ -2219,7 +2285,12 @@ async function installCcr() {
|
|
|
2219
2285
|
}
|
|
2220
2286
|
console.log(ansis.cyan(`\u{1F4E6} ${i18n.t("ccr:installingCcr")}`));
|
|
2221
2287
|
try {
|
|
2222
|
-
|
|
2288
|
+
const installArgs = ["install", "-g", "@musistudio/claude-code-router", "--force"];
|
|
2289
|
+
const { command, args, usedSudo } = wrapCommandWithSudo("npm", installArgs);
|
|
2290
|
+
if (usedSudo) {
|
|
2291
|
+
console.log(ansis.yellow(`\u2139 ${i18n.t("installation:usingSudo")}`));
|
|
2292
|
+
}
|
|
2293
|
+
await execAsync$1([command, ...args].join(" "));
|
|
2223
2294
|
console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrInstallSuccess")}`));
|
|
2224
2295
|
} catch (error) {
|
|
2225
2296
|
if (error.message?.includes("EEXIST")) {
|
|
@@ -2938,7 +3009,10 @@ async function executeCodexInstallation(isUpdate) {
|
|
|
2938
3009
|
} else {
|
|
2939
3010
|
console.log(ansis.cyan(i18n.t("codex:installingCli")));
|
|
2940
3011
|
}
|
|
2941
|
-
const
|
|
3012
|
+
const { command, args, usedSudo } = wrapCommandWithSudo("npm", ["install", "-g", "@openai/codex"]);
|
|
3013
|
+
if (usedSudo)
|
|
3014
|
+
console.log(ansis.yellow(i18n.t("codex:usingSudo")));
|
|
3015
|
+
const result = await x(command, args);
|
|
2942
3016
|
if (result.exitCode !== 0) {
|
|
2943
3017
|
throw new Error(`Failed to ${action} codex CLI: exit code ${result.exitCode}`);
|
|
2944
3018
|
}
|
|
@@ -3970,7 +4044,10 @@ async function runCodexUpdate(force = false, skipPrompt = false) {
|
|
|
3970
4044
|
async function runCodexUninstall() {
|
|
3971
4045
|
ensureI18nInitialized();
|
|
3972
4046
|
const { CodexUninstaller } = await import('./codex-uninstaller.mjs');
|
|
3973
|
-
const
|
|
4047
|
+
const zcfConfig = readZcfConfig();
|
|
4048
|
+
const preferredLang = zcfConfig?.preferredLang;
|
|
4049
|
+
const uninstallLang = preferredLang && SUPPORTED_LANGS.includes(preferredLang) ? preferredLang : "en";
|
|
4050
|
+
const uninstaller = new CodexUninstaller(uninstallLang);
|
|
3974
4051
|
const { mode } = await inquirer.prompt([{
|
|
3975
4052
|
type: "list",
|
|
3976
4053
|
name: "mode",
|
|
@@ -4284,12 +4361,20 @@ async function isCometixLineInstalled() {
|
|
|
4284
4361
|
}
|
|
4285
4362
|
async function installCometixLine() {
|
|
4286
4363
|
ensureI18nInitialized();
|
|
4364
|
+
const runInstallCommand = async () => {
|
|
4365
|
+
const installArgs = ["install", "-g", COMETIX_PACKAGE_NAME];
|
|
4366
|
+
const { command, args, usedSudo } = wrapCommandWithSudo("npm", installArgs);
|
|
4367
|
+
if (usedSudo) {
|
|
4368
|
+
console.log(ansis.yellow(`\u2139 ${i18n.t("installation:usingSudo")}`));
|
|
4369
|
+
}
|
|
4370
|
+
await execAsync([command, ...args].join(" "));
|
|
4371
|
+
};
|
|
4287
4372
|
const isInstalled = await isCometixLineInstalled();
|
|
4288
4373
|
if (isInstalled) {
|
|
4289
4374
|
console.log(ansis.green(`\u2714 ${i18n.t("cometix:cometixAlreadyInstalled")}`));
|
|
4290
4375
|
try {
|
|
4291
4376
|
console.log(ansis.blue(`${i18n.t("cometix:installingOrUpdating")}`));
|
|
4292
|
-
await
|
|
4377
|
+
await runInstallCommand();
|
|
4293
4378
|
console.log(ansis.green(`\u2714 ${i18n.t("cometix:installUpdateSuccess")}`));
|
|
4294
4379
|
} catch (error) {
|
|
4295
4380
|
console.log(ansis.yellow(`\u26A0 ${i18n.t("cometix:installUpdateFailed")}: ${error}`));
|
|
@@ -4308,7 +4393,7 @@ async function installCometixLine() {
|
|
|
4308
4393
|
}
|
|
4309
4394
|
try {
|
|
4310
4395
|
console.log(ansis.blue(`${i18n.t("cometix:installingCometix")}`));
|
|
4311
|
-
await
|
|
4396
|
+
await runInstallCommand();
|
|
4312
4397
|
console.log(ansis.green(`\u2714 ${i18n.t("cometix:cometixInstallSuccess")}`));
|
|
4313
4398
|
try {
|
|
4314
4399
|
addCCometixLineConfig();
|
|
@@ -4789,7 +4874,11 @@ async function installClaudeCode() {
|
|
|
4789
4874
|
}
|
|
4790
4875
|
console.log(i18n.t("installation:installing"));
|
|
4791
4876
|
try {
|
|
4792
|
-
|
|
4877
|
+
const { command, args, usedSudo } = wrapCommandWithSudo("npm", ["install", "-g", "@anthropic-ai/claude-code"]);
|
|
4878
|
+
if (usedSudo) {
|
|
4879
|
+
console.log(ansis.yellow(`\u2139 ${i18n.t("installation:usingSudo")}`));
|
|
4880
|
+
}
|
|
4881
|
+
await exec(command, args);
|
|
4793
4882
|
console.log(`\u2714 ${i18n.t("installation:installSuccess")}`);
|
|
4794
4883
|
await setInstallMethod("npm");
|
|
4795
4884
|
if (isTermux()) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"installingCli": "🚀 Installing Codex CLI...",
|
|
3
3
|
"installSuccess": "✔ Codex CLI installed",
|
|
4
|
+
"usingSudo": "⚠️ Detected non-root Linux user. Using sudo for Codex CLI installation (password prompt may appear).",
|
|
4
5
|
"alreadyInstalled": "⚠️ Codex CLI already installed, skipping installation",
|
|
5
6
|
"updatingCli": "🔄 Updating Codex CLI...",
|
|
6
7
|
"updateSuccess": "✔ Codex CLI updated",
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"installPrompt": "Claude Code not found. Install automatically?",
|
|
5
5
|
"installSuccess": "Claude Code installed successfully",
|
|
6
6
|
"installing": "Installing Claude Code...",
|
|
7
|
+
"usingSudo": "Detected non-root Linux user. Elevating with sudo for global installation (password prompt may appear).",
|
|
7
8
|
"termuxDetected": "Termux environment detected",
|
|
8
9
|
"termuxEnvironmentInfo": "Termux environment provides Node.js and npm through pkg manager",
|
|
9
10
|
"termuxInstallHint": "In Termux, please run first: pkg install nodejs or pkg install nodejs-lts",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"installingCli": "🚀 正在安装 Codex CLI...",
|
|
3
3
|
"installSuccess": "✔ Codex CLI 安装完成",
|
|
4
|
+
"usingSudo": "⚠️ 检测到 Linux 非 root 用户,正在使用 sudo 安装 Codex CLI(可能需要输入密码)。",
|
|
4
5
|
"alreadyInstalled": "⚠️ Codex CLI 已安装,跳过安装步骤",
|
|
5
6
|
"updatingCli": "🔄 正在更新 Codex CLI...",
|
|
6
7
|
"updateSuccess": "✔ Codex CLI 更新完成",
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"installPrompt": "检测到 Claude Code 未安装,是否自动安装?",
|
|
5
5
|
"installSuccess": "Claude Code 安装成功",
|
|
6
6
|
"installing": "正在安装 Claude Code...",
|
|
7
|
+
"usingSudo": "检测到 Linux 非 root 用户,正在使用 sudo 提升权限进行全局安装(可能需要输入密码)。",
|
|
7
8
|
"termuxDetected": "检测到 Termux 环境",
|
|
8
9
|
"termuxEnvironmentInfo": "Termux 环境通过 pkg 管理器提供 Node.js 和 npm",
|
|
9
10
|
"termuxInstallHint": "在 Termux 中,请先运行: pkg install nodejs 或 pkg install nodejs-lts",
|