zcf 3.4.2 → 3.5.0
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 +1 -1
- package/dist/chunks/api-providers.mjs +1 -1
- package/dist/chunks/claude-code-config-manager.mjs +28 -18
- package/dist/chunks/claude-code-incremental-manager.mjs +36 -19
- package/dist/chunks/codex-config-switch.mjs +4 -4
- package/dist/chunks/codex-provider-manager.mjs +28 -19
- package/dist/chunks/codex-uninstaller.mjs +2 -2
- package/dist/chunks/commands.mjs +1 -1
- package/dist/chunks/features.mjs +32 -20
- package/dist/chunks/simple-config.mjs +294 -114
- package/dist/cli.mjs +8 -6
- package/dist/i18n/locales/en/cli.json +3 -1
- package/dist/i18n/locales/en/configuration.json +3 -1
- package/dist/i18n/locales/en/errors.json +1 -1
- package/dist/i18n/locales/en/updater.json +1 -0
- package/dist/i18n/locales/zh-CN/cli.json +3 -1
- package/dist/i18n/locales/zh-CN/configuration.json +3 -1
- package/dist/i18n/locales/zh-CN/errors.json +1 -1
- package/dist/i18n/locales/zh-CN/updater.json +1 -0
- package/dist/index.d.mts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/templates/CLAUDE.md +39 -11
- package/templates/{codex/en/workflow/git/prompts → common/workflow/git/en}/git-commit.md +50 -3
- package/templates/{claude-code/zh-CN/workflow/git/commands → common/workflow/git/zh-CN}/git-commit.md +50 -3
- package/templates/{codex/en/workflow/sixStep/prompts → common/workflow/sixStep/en}/workflow.md +25 -4
- package/templates/{codex/zh-CN/workflow/sixStep/prompts → common/workflow/sixStep/zh-CN}/workflow.md +25 -4
- package/templates/claude-code/en/workflow/git/commands/git-commit.md +0 -158
- package/templates/claude-code/en/workflow/sixStep/commands/workflow.md +0 -230
- package/templates/claude-code/zh-CN/workflow/sixStep/commands/workflow.md +0 -194
- package/templates/codex/en/system-prompt/engineer-professional.md +0 -88
- package/templates/codex/en/system-prompt/laowang-engineer.md +0 -127
- package/templates/codex/en/system-prompt/nekomata-engineer.md +0 -120
- package/templates/codex/en/system-prompt/ojousama-engineer.md +0 -121
- package/templates/codex/en/workflow/git/prompts/git-cleanBranches.md +0 -102
- package/templates/codex/en/workflow/git/prompts/git-rollback.md +0 -90
- package/templates/codex/en/workflow/git/prompts/git-worktree.md +0 -276
- package/templates/codex/zh-CN/system-prompt/engineer-professional.md +0 -89
- package/templates/codex/zh-CN/system-prompt/laowang-engineer.md +0 -127
- package/templates/codex/zh-CN/system-prompt/nekomata-engineer.md +0 -120
- package/templates/codex/zh-CN/system-prompt/ojousama-engineer.md +0 -121
- package/templates/codex/zh-CN/workflow/git/prompts/git-cleanBranches.md +0 -102
- package/templates/codex/zh-CN/workflow/git/prompts/git-commit.md +0 -158
- package/templates/codex/zh-CN/workflow/git/prompts/git-rollback.md +0 -90
- package/templates/codex/zh-CN/workflow/git/prompts/git-worktree.md +0 -276
- /package/templates/{claude-code/en/output-styles → common/output-styles/en}/engineer-professional.md +0 -0
- /package/templates/{claude-code/en/output-styles → common/output-styles/en}/laowang-engineer.md +0 -0
- /package/templates/{claude-code/en/output-styles → common/output-styles/en}/nekomata-engineer.md +0 -0
- /package/templates/{claude-code/en/output-styles → common/output-styles/en}/ojousama-engineer.md +0 -0
- /package/templates/{claude-code/zh-CN/output-styles → common/output-styles/zh-CN}/engineer-professional.md +0 -0
- /package/templates/{claude-code/zh-CN/output-styles → common/output-styles/zh-CN}/laowang-engineer.md +0 -0
- /package/templates/{claude-code/zh-CN/output-styles → common/output-styles/zh-CN}/nekomata-engineer.md +0 -0
- /package/templates/{claude-code/zh-CN/output-styles → common/output-styles/zh-CN}/ojousama-engineer.md +0 -0
- /package/templates/{claude-code/en/workflow/git/commands → common/workflow/git/en}/git-cleanBranches.md +0 -0
- /package/templates/{claude-code/en/workflow/git/commands → common/workflow/git/en}/git-rollback.md +0 -0
- /package/templates/{claude-code/en/workflow/git/commands → common/workflow/git/en}/git-worktree.md +0 -0
- /package/templates/{claude-code/zh-CN/workflow/git/commands → common/workflow/git/zh-CN}/git-cleanBranches.md +0 -0
- /package/templates/{claude-code/zh-CN/workflow/git/commands → common/workflow/git/zh-CN}/git-rollback.md +0 -0
- /package/templates/{claude-code/zh-CN/workflow/git/commands → common/workflow/git/zh-CN}/git-worktree.md +0 -0
|
@@ -11,14 +11,14 @@ import { dirname, join } from 'pathe';
|
|
|
11
11
|
import { fileURLToPath } from 'node:url';
|
|
12
12
|
import toggleModule from 'inquirer-toggle';
|
|
13
13
|
import ora from 'ora';
|
|
14
|
+
import { exec, x } from 'tinyexec';
|
|
14
15
|
import semver from 'semver';
|
|
15
16
|
import { stringify, parse } from 'smol-toml';
|
|
16
|
-
import { exec, x } from 'tinyexec';
|
|
17
17
|
import { rm, mkdir, copyFile as copyFile$1 } from 'node:fs/promises';
|
|
18
18
|
import i18next from 'i18next';
|
|
19
19
|
import Backend from 'i18next-fs-backend';
|
|
20
20
|
|
|
21
|
-
const version = "3.
|
|
21
|
+
const version = "3.5.0";
|
|
22
22
|
const homepage = "https://github.com/UfoMiao/zcf";
|
|
23
23
|
|
|
24
24
|
const i18n = i18next.createInstance();
|
|
@@ -1309,6 +1309,20 @@ const claudeConfig = {
|
|
|
1309
1309
|
writeMcpConfig: writeMcpConfig
|
|
1310
1310
|
};
|
|
1311
1311
|
|
|
1312
|
+
const MODEL_ENV_KEYS = [
|
|
1313
|
+
"ANTHROPIC_MODEL",
|
|
1314
|
+
"ANTHROPIC_DEFAULT_HAIKU_MODEL",
|
|
1315
|
+
"ANTHROPIC_DEFAULT_SONNET_MODEL",
|
|
1316
|
+
"ANTHROPIC_DEFAULT_OPUS_MODEL",
|
|
1317
|
+
// Deprecated but still cleaned to avoid stale values
|
|
1318
|
+
"ANTHROPIC_SMALL_FAST_MODEL"
|
|
1319
|
+
];
|
|
1320
|
+
function clearModelEnv(env) {
|
|
1321
|
+
for (const key of MODEL_ENV_KEYS) {
|
|
1322
|
+
delete env[key];
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1312
1326
|
function cleanupPermissions(templatePermissions, userPermissions) {
|
|
1313
1327
|
const templateSet = new Set(templatePermissions);
|
|
1314
1328
|
const cleanedPermissions = userPermissions.filter((permission) => {
|
|
@@ -1426,8 +1440,8 @@ function mergeConfigs(sourceFile, targetFile) {
|
|
|
1426
1440
|
const merged = deepMerge(target, source);
|
|
1427
1441
|
writeJsonConfig(targetFile, merged);
|
|
1428
1442
|
}
|
|
1429
|
-
function updateCustomModel(primaryModel,
|
|
1430
|
-
if (!primaryModel?.trim() && !
|
|
1443
|
+
function updateCustomModel(primaryModel, haikuModel, sonnetModel, opusModel) {
|
|
1444
|
+
if (!primaryModel?.trim() && !haikuModel?.trim() && !sonnetModel?.trim() && !opusModel?.trim()) {
|
|
1431
1445
|
return;
|
|
1432
1446
|
}
|
|
1433
1447
|
let settings = getDefaultSettings();
|
|
@@ -1437,12 +1451,16 @@ function updateCustomModel(primaryModel, fastModel) {
|
|
|
1437
1451
|
}
|
|
1438
1452
|
delete settings.model;
|
|
1439
1453
|
settings.env = settings.env || {};
|
|
1454
|
+
clearModelEnv(settings.env);
|
|
1440
1455
|
if (primaryModel?.trim()) {
|
|
1441
1456
|
settings.env.ANTHROPIC_MODEL = primaryModel.trim();
|
|
1442
1457
|
}
|
|
1443
|
-
if (
|
|
1444
|
-
settings.env.
|
|
1445
|
-
|
|
1458
|
+
if (haikuModel?.trim())
|
|
1459
|
+
settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL = haikuModel.trim();
|
|
1460
|
+
if (sonnetModel?.trim())
|
|
1461
|
+
settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL = sonnetModel.trim();
|
|
1462
|
+
if (opusModel?.trim())
|
|
1463
|
+
settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL = opusModel.trim();
|
|
1446
1464
|
writeJsonConfig(SETTINGS_FILE, settings);
|
|
1447
1465
|
}
|
|
1448
1466
|
function updateDefaultModel(model) {
|
|
@@ -1454,13 +1472,10 @@ function updateDefaultModel(model) {
|
|
|
1454
1472
|
if (!settings.env) {
|
|
1455
1473
|
settings.env = {};
|
|
1456
1474
|
}
|
|
1457
|
-
if (model !== "custom"
|
|
1458
|
-
|
|
1459
|
-
delete settings.env.ANTHROPIC_SMALL_FAST_MODEL;
|
|
1475
|
+
if (model !== "custom") {
|
|
1476
|
+
clearModelEnv(settings.env);
|
|
1460
1477
|
}
|
|
1461
|
-
if (model === "default") {
|
|
1462
|
-
delete settings.model;
|
|
1463
|
-
} else if (model === "custom") {
|
|
1478
|
+
if (model === "default" || model === "custom") {
|
|
1464
1479
|
delete settings.model;
|
|
1465
1480
|
} else {
|
|
1466
1481
|
settings.model = model;
|
|
@@ -1511,13 +1526,18 @@ function getExistingModelConfig() {
|
|
|
1511
1526
|
if (!settings) {
|
|
1512
1527
|
return null;
|
|
1513
1528
|
}
|
|
1514
|
-
|
|
1529
|
+
const hasModelEnv = MODEL_ENV_KEYS.some((key) => settings.env?.[key]);
|
|
1530
|
+
if (hasModelEnv) {
|
|
1515
1531
|
return "custom";
|
|
1516
1532
|
}
|
|
1517
1533
|
if (!settings.model) {
|
|
1518
1534
|
return "default";
|
|
1519
1535
|
}
|
|
1520
|
-
|
|
1536
|
+
const validModels = ["opus", "sonnet", "sonnet[1m]"];
|
|
1537
|
+
if (validModels.includes(settings.model)) {
|
|
1538
|
+
return settings.model;
|
|
1539
|
+
}
|
|
1540
|
+
return "default";
|
|
1521
1541
|
}
|
|
1522
1542
|
function getExistingApiConfig() {
|
|
1523
1543
|
const settings = readJsonConfig(SETTINGS_FILE);
|
|
@@ -1787,7 +1807,7 @@ function getFallbackPresets() {
|
|
|
1787
1807
|
];
|
|
1788
1808
|
}
|
|
1789
1809
|
|
|
1790
|
-
const execAsync$
|
|
1810
|
+
const execAsync$3 = promisify(exec$1);
|
|
1791
1811
|
const CCR_CONFIG_DIR = join(homedir(), ".claude-code-router");
|
|
1792
1812
|
const CCR_CONFIG_FILE = join(CCR_CONFIG_DIR, "config.json");
|
|
1793
1813
|
const CCR_BACKUP_DIR = CCR_CONFIG_DIR;
|
|
@@ -1832,6 +1852,7 @@ async function configureCcrProxy(ccrConfig) {
|
|
|
1832
1852
|
if (!settings.env) {
|
|
1833
1853
|
settings.env = {};
|
|
1834
1854
|
}
|
|
1855
|
+
delete settings.env.ANTHROPIC_AUTH_TOKEN;
|
|
1835
1856
|
settings.env.ANTHROPIC_BASE_URL = `http://${host}:${port}`;
|
|
1836
1857
|
settings.env.ANTHROPIC_API_KEY = apiKey;
|
|
1837
1858
|
writeJsonConfig(SETTINGS_FILE, settings);
|
|
@@ -1953,10 +1974,10 @@ async function restartAndCheckCcrStatus() {
|
|
|
1953
1974
|
ensureI18nInitialized();
|
|
1954
1975
|
try {
|
|
1955
1976
|
console.log(ansis.cyan(`${i18n.t("ccr:restartingCcr")}`));
|
|
1956
|
-
await execAsync$
|
|
1977
|
+
await execAsync$3("ccr restart");
|
|
1957
1978
|
console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrRestartSuccess")}`));
|
|
1958
1979
|
console.log(ansis.cyan(`${i18n.t("ccr:checkingCcrStatus")}`));
|
|
1959
|
-
const { stdout } = await execAsync$
|
|
1980
|
+
const { stdout } = await execAsync$3("ccr status");
|
|
1960
1981
|
console.log(ansis.gray(stdout));
|
|
1961
1982
|
} catch (error) {
|
|
1962
1983
|
console.error(ansis.red(`${i18n.t("ccr:ccrRestartFailed")}:`), error.message || error);
|
|
@@ -2093,16 +2114,16 @@ const config = {
|
|
|
2093
2114
|
writeCcrConfig: writeCcrConfig
|
|
2094
2115
|
};
|
|
2095
2116
|
|
|
2096
|
-
const execAsync$
|
|
2117
|
+
const execAsync$2 = promisify(exec$1);
|
|
2097
2118
|
async function getInstalledVersion(command, maxRetries = 3) {
|
|
2098
2119
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
2099
2120
|
try {
|
|
2100
2121
|
let stdout;
|
|
2101
2122
|
try {
|
|
2102
|
-
const result = await execAsync$
|
|
2123
|
+
const result = await execAsync$2(`${command} -v`);
|
|
2103
2124
|
stdout = result.stdout;
|
|
2104
2125
|
} catch {
|
|
2105
|
-
const result = await execAsync$
|
|
2126
|
+
const result = await execAsync$2(`${command} --version`);
|
|
2106
2127
|
stdout = result.stdout;
|
|
2107
2128
|
}
|
|
2108
2129
|
const versionMatch = stdout.match(/(\d+\.\d+\.\d+(?:-[\w.]+)?)/);
|
|
@@ -2119,7 +2140,7 @@ async function getInstalledVersion(command, maxRetries = 3) {
|
|
|
2119
2140
|
async function getLatestVersion(packageName, maxRetries = 3) {
|
|
2120
2141
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
2121
2142
|
try {
|
|
2122
|
-
const { stdout } = await execAsync$
|
|
2143
|
+
const { stdout } = await execAsync$2(`npm view ${packageName} version`);
|
|
2123
2144
|
return stdout.trim();
|
|
2124
2145
|
} catch {
|
|
2125
2146
|
if (attempt === maxRetries) {
|
|
@@ -2148,7 +2169,7 @@ async function getClaudeCodeInstallationSource() {
|
|
|
2148
2169
|
return { isHomebrew: true, commandPath, source: "homebrew-cask" };
|
|
2149
2170
|
}
|
|
2150
2171
|
try {
|
|
2151
|
-
const { stdout: realPath } = await execAsync$
|
|
2172
|
+
const { stdout: realPath } = await execAsync$2(`readlink -f "${commandPath}" 2>/dev/null || realpath "${commandPath}" 2>/dev/null || echo "${commandPath}"`);
|
|
2152
2173
|
const resolvedPath = realPath.trim();
|
|
2153
2174
|
if (resolvedPath.includes("/Caskroom/claude-code/")) {
|
|
2154
2175
|
return { isHomebrew: true, commandPath, source: "homebrew-cask" };
|
|
@@ -2167,7 +2188,7 @@ async function detectAllClaudeCodeInstallations() {
|
|
|
2167
2188
|
let activeResolvedPath = null;
|
|
2168
2189
|
if (activeCommandPath) {
|
|
2169
2190
|
try {
|
|
2170
|
-
const { stdout } = await execAsync$
|
|
2191
|
+
const { stdout } = await execAsync$2(`readlink -f "${activeCommandPath}" 2>/dev/null || realpath "${activeCommandPath}" 2>/dev/null || echo "${activeCommandPath}"`);
|
|
2171
2192
|
activeResolvedPath = stdout.trim();
|
|
2172
2193
|
} catch {
|
|
2173
2194
|
activeResolvedPath = activeCommandPath;
|
|
@@ -2175,7 +2196,7 @@ async function detectAllClaudeCodeInstallations() {
|
|
|
2175
2196
|
}
|
|
2176
2197
|
async function getVersionFromPath(path) {
|
|
2177
2198
|
try {
|
|
2178
|
-
const { stdout } = await execAsync$
|
|
2199
|
+
const { stdout } = await execAsync$2(`"${path}" -v 2>/dev/null || "${path}" --version 2>/dev/null`);
|
|
2179
2200
|
const versionMatch = stdout.match(/(\d+\.\d+\.\d+(?:-[\w.]+)?)/);
|
|
2180
2201
|
return versionMatch ? versionMatch[1] : null;
|
|
2181
2202
|
} catch {
|
|
@@ -2190,7 +2211,7 @@ async function detectAllClaudeCodeInstallations() {
|
|
|
2190
2211
|
async function addInstallation(path, source) {
|
|
2191
2212
|
let resolvedPath = path;
|
|
2192
2213
|
try {
|
|
2193
|
-
const { stdout } = await execAsync$
|
|
2214
|
+
const { stdout } = await execAsync$2(`readlink -f "${path}" 2>/dev/null || realpath "${path}" 2>/dev/null || echo "${path}"`);
|
|
2194
2215
|
resolvedPath = stdout.trim();
|
|
2195
2216
|
} catch {
|
|
2196
2217
|
}
|
|
@@ -2226,7 +2247,7 @@ async function detectAllClaudeCodeInstallations() {
|
|
|
2226
2247
|
}
|
|
2227
2248
|
}
|
|
2228
2249
|
try {
|
|
2229
|
-
await execAsync$
|
|
2250
|
+
await execAsync$2("brew list --cask claude-code");
|
|
2230
2251
|
const homebrewPrefixes = ["/opt/homebrew", "/usr/local"];
|
|
2231
2252
|
for (const prefix of homebrewPrefixes) {
|
|
2232
2253
|
const caskroomPath = `${prefix}/Caskroom/claude-code`;
|
|
@@ -2251,7 +2272,7 @@ async function detectAllClaudeCodeInstallations() {
|
|
|
2251
2272
|
if (nodeFs.existsSync(path)) {
|
|
2252
2273
|
let resolvedPath = path;
|
|
2253
2274
|
try {
|
|
2254
|
-
const { stdout } = await execAsync$
|
|
2275
|
+
const { stdout } = await execAsync$2(`readlink -f "${path}" 2>/dev/null || realpath "${path}" 2>/dev/null || echo "${path}"`);
|
|
2255
2276
|
resolvedPath = stdout.trim();
|
|
2256
2277
|
} catch {
|
|
2257
2278
|
}
|
|
@@ -2441,7 +2462,7 @@ async function handleDuplicateInstallations(skipPrompt = false) {
|
|
|
2441
2462
|
}
|
|
2442
2463
|
async function getHomebrewClaudeCodeVersion() {
|
|
2443
2464
|
try {
|
|
2444
|
-
const { stdout } = await execAsync$
|
|
2465
|
+
const { stdout } = await execAsync$2("brew info --cask claude-code --json=v2");
|
|
2445
2466
|
const info = JSON.parse(stdout);
|
|
2446
2467
|
if (info.casks && info.casks.length > 0) {
|
|
2447
2468
|
return info.casks[0].version;
|
|
@@ -2514,7 +2535,24 @@ async function checkClaudeCodeVersionAndPrompt(skipPrompt = false) {
|
|
|
2514
2535
|
}
|
|
2515
2536
|
}
|
|
2516
2537
|
|
|
2517
|
-
|
|
2538
|
+
async function execWithSudoIfNeeded(command, args) {
|
|
2539
|
+
const needsSudo = shouldUseSudoForGlobalInstall();
|
|
2540
|
+
if (needsSudo) {
|
|
2541
|
+
console.log(ansis.yellow(`
|
|
2542
|
+
${i18n.t("updater:usingSudo")}`));
|
|
2543
|
+
const result = await exec("sudo", [command, ...args]);
|
|
2544
|
+
if (result.exitCode !== 0) {
|
|
2545
|
+
throw new Error(result.stderr || `Command failed with exit code ${result.exitCode}`);
|
|
2546
|
+
}
|
|
2547
|
+
return { usedSudo: true };
|
|
2548
|
+
} else {
|
|
2549
|
+
const result = await exec(command, args);
|
|
2550
|
+
if (result.exitCode !== 0) {
|
|
2551
|
+
throw new Error(result.stderr || `Command failed with exit code ${result.exitCode}`);
|
|
2552
|
+
}
|
|
2553
|
+
return { usedSudo: false };
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2518
2556
|
async function updateCcr(force = false, skipPrompt = false) {
|
|
2519
2557
|
ensureI18nInitialized();
|
|
2520
2558
|
const spinner = ora(i18n.t("updater:checkingVersion")).start();
|
|
@@ -2549,7 +2587,7 @@ async function updateCcr(force = false, skipPrompt = false) {
|
|
|
2549
2587
|
}
|
|
2550
2588
|
const updateSpinner = ora(format(i18n.t("updater:updating"), { tool: "CCR" })).start();
|
|
2551
2589
|
try {
|
|
2552
|
-
await
|
|
2590
|
+
await execWithSudoIfNeeded("npm", ["update", "-g", "@musistudio/claude-code-router"]);
|
|
2553
2591
|
updateSpinner.succeed(format(i18n.t("updater:updateSuccess"), { tool: "CCR" }));
|
|
2554
2592
|
return true;
|
|
2555
2593
|
} catch (error) {
|
|
@@ -2599,9 +2637,12 @@ async function updateClaudeCode(force = false, skipPrompt = false) {
|
|
|
2599
2637
|
const updateSpinner = ora(format(i18n.t("updater:updating"), { tool: toolName })).start();
|
|
2600
2638
|
try {
|
|
2601
2639
|
if (isHomebrew) {
|
|
2602
|
-
await
|
|
2640
|
+
const result = await exec("brew", ["upgrade", "--cask", "claude-code"]);
|
|
2641
|
+
if (result.exitCode !== 0) {
|
|
2642
|
+
throw new Error(result.stderr || `Command failed with exit code ${result.exitCode}`);
|
|
2643
|
+
}
|
|
2603
2644
|
} else {
|
|
2604
|
-
await
|
|
2645
|
+
await execWithSudoIfNeeded("claude", ["update"]);
|
|
2605
2646
|
}
|
|
2606
2647
|
updateSpinner.succeed(format(i18n.t("updater:updateSuccess"), { tool: "Claude Code" }));
|
|
2607
2648
|
return true;
|
|
@@ -2650,7 +2691,7 @@ async function updateCometixLine(force = false, skipPrompt = false) {
|
|
|
2650
2691
|
}
|
|
2651
2692
|
const updateSpinner = ora(format(i18n.t("updater:updating"), { tool: "CCometixLine" })).start();
|
|
2652
2693
|
try {
|
|
2653
|
-
await
|
|
2694
|
+
await execWithSudoIfNeeded("npm", ["update", "-g", "@cometix/ccline"]);
|
|
2654
2695
|
updateSpinner.succeed(format(i18n.t("updater:updateSuccess"), { tool: "CCometixLine" }));
|
|
2655
2696
|
return true;
|
|
2656
2697
|
} catch (error) {
|
|
@@ -2721,6 +2762,7 @@ async function checkAndUpdateTools(skipPrompt = false) {
|
|
|
2721
2762
|
const autoUpdater = {
|
|
2722
2763
|
__proto__: null,
|
|
2723
2764
|
checkAndUpdateTools: checkAndUpdateTools,
|
|
2765
|
+
execWithSudoIfNeeded: execWithSudoIfNeeded,
|
|
2724
2766
|
updateCcr: updateCcr,
|
|
2725
2767
|
updateClaudeCode: updateClaudeCode,
|
|
2726
2768
|
updateCometixLine: updateCometixLine
|
|
@@ -3342,11 +3384,83 @@ async function configureCodexMcp(options) {
|
|
|
3342
3384
|
ensureI18nInitialized();
|
|
3343
3385
|
const { skipPrompt = false } = options ?? {};
|
|
3344
3386
|
const existingConfig = readCodexConfig();
|
|
3345
|
-
if (skipPrompt)
|
|
3346
|
-
return;
|
|
3347
3387
|
const backupPath = backupCodexComplete();
|
|
3348
3388
|
if (backupPath)
|
|
3349
3389
|
console.log(ansis.gray(getBackupMessage(backupPath)));
|
|
3390
|
+
if (skipPrompt) {
|
|
3391
|
+
const { runCodexWorkflowSelection } = await Promise.resolve().then(function () { return codex; });
|
|
3392
|
+
await runCodexWorkflowSelection({ skipPrompt: true, workflows: options?.workflows ?? [] });
|
|
3393
|
+
if (options?.mcpServices === false) {
|
|
3394
|
+
updateZcfConfig({ codeToolType: "codex" });
|
|
3395
|
+
console.log(ansis.green(i18n.t("codex:mcpConfigured")));
|
|
3396
|
+
return;
|
|
3397
|
+
}
|
|
3398
|
+
const defaultServiceIds = Array.isArray(options?.mcpServices) ? options.mcpServices : MCP_SERVICE_CONFIGS.filter((service) => !service.requiresApiKey).map((service) => service.id);
|
|
3399
|
+
const baseProviders2 = existingConfig?.providers || [];
|
|
3400
|
+
const existingServices2 = existingConfig?.mcpServices || [];
|
|
3401
|
+
const selection2 = [];
|
|
3402
|
+
for (const id of defaultServiceIds) {
|
|
3403
|
+
const configInfo = MCP_SERVICE_CONFIGS.find((service) => service.id === id);
|
|
3404
|
+
if (!configInfo)
|
|
3405
|
+
continue;
|
|
3406
|
+
let command = configInfo.config.command || id;
|
|
3407
|
+
let args = (configInfo.config.args || []).map((arg) => String(arg));
|
|
3408
|
+
if (id === "serena") {
|
|
3409
|
+
const idx = args.indexOf("--context");
|
|
3410
|
+
if (idx >= 0 && idx + 1 < args.length)
|
|
3411
|
+
args[idx + 1] = "codex";
|
|
3412
|
+
else
|
|
3413
|
+
args.push("--context", "codex");
|
|
3414
|
+
}
|
|
3415
|
+
const serviceConfig = { id: id.toLowerCase(), command, args };
|
|
3416
|
+
applyCodexPlatformCommand(serviceConfig);
|
|
3417
|
+
command = serviceConfig.command;
|
|
3418
|
+
args = serviceConfig.args || [];
|
|
3419
|
+
const env = { ...configInfo.config.env || {} };
|
|
3420
|
+
if (isWindows()) {
|
|
3421
|
+
const systemRoot = getSystemRoot();
|
|
3422
|
+
if (systemRoot)
|
|
3423
|
+
env.SYSTEMROOT = systemRoot;
|
|
3424
|
+
}
|
|
3425
|
+
selection2.push({
|
|
3426
|
+
id: id.toLowerCase(),
|
|
3427
|
+
command,
|
|
3428
|
+
args,
|
|
3429
|
+
env: Object.keys(env).length > 0 ? env : void 0,
|
|
3430
|
+
startup_timeout_sec: 30
|
|
3431
|
+
});
|
|
3432
|
+
}
|
|
3433
|
+
const mergedMap2 = /* @__PURE__ */ new Map();
|
|
3434
|
+
for (const svc of existingServices2)
|
|
3435
|
+
mergedMap2.set(svc.id.toLowerCase(), { ...svc });
|
|
3436
|
+
for (const svc of selection2)
|
|
3437
|
+
mergedMap2.set(svc.id.toLowerCase(), { ...svc });
|
|
3438
|
+
const finalServices2 = Array.from(mergedMap2.values()).map((svc) => {
|
|
3439
|
+
if (isWindows()) {
|
|
3440
|
+
const systemRoot = getSystemRoot();
|
|
3441
|
+
if (systemRoot) {
|
|
3442
|
+
return {
|
|
3443
|
+
...svc,
|
|
3444
|
+
env: {
|
|
3445
|
+
...svc.env || {},
|
|
3446
|
+
SYSTEMROOT: systemRoot
|
|
3447
|
+
}
|
|
3448
|
+
};
|
|
3449
|
+
}
|
|
3450
|
+
}
|
|
3451
|
+
return svc;
|
|
3452
|
+
});
|
|
3453
|
+
writeCodexConfig({
|
|
3454
|
+
model: existingConfig?.model || null,
|
|
3455
|
+
modelProvider: existingConfig?.modelProvider || null,
|
|
3456
|
+
providers: baseProviders2,
|
|
3457
|
+
mcpServices: finalServices2,
|
|
3458
|
+
otherConfig: existingConfig?.otherConfig || []
|
|
3459
|
+
});
|
|
3460
|
+
updateZcfConfig({ codeToolType: "codex" });
|
|
3461
|
+
console.log(ansis.green(i18n.t("codex:mcpConfigured")));
|
|
3462
|
+
return;
|
|
3463
|
+
}
|
|
3350
3464
|
const selectedIds = await selectMcpServices();
|
|
3351
3465
|
if (!selectedIds)
|
|
3352
3466
|
return;
|
|
@@ -3457,6 +3571,7 @@ async function configureCodexMcp(options) {
|
|
|
3457
3571
|
console.log(ansis.green(i18n.t("codex:mcpConfigured")));
|
|
3458
3572
|
}
|
|
3459
3573
|
|
|
3574
|
+
let cachedSkipPromptBackup = null;
|
|
3460
3575
|
function getRootDir$1() {
|
|
3461
3576
|
const currentFilePath = fileURLToPath(import.meta.url);
|
|
3462
3577
|
let dir = dirname(currentFilePath);
|
|
@@ -3545,12 +3660,16 @@ function createBackupDirectory(timestamp) {
|
|
|
3545
3660
|
function backupCodexFiles() {
|
|
3546
3661
|
if (!exists(CODEX_DIR))
|
|
3547
3662
|
return null;
|
|
3663
|
+
if (process.env.ZCF_CODEX_SKIP_PROMPT_SINGLE_BACKUP === "true" && cachedSkipPromptBackup)
|
|
3664
|
+
return cachedSkipPromptBackup;
|
|
3548
3665
|
const timestamp = dayjs().format("YYYY-MM-DD_HH-mm-ss");
|
|
3549
3666
|
const backupDir = createBackupDirectory(timestamp);
|
|
3550
3667
|
const filter = (path) => {
|
|
3551
3668
|
return !path.includes("/backup");
|
|
3552
3669
|
};
|
|
3553
3670
|
copyDir(CODEX_DIR, backupDir, { filter });
|
|
3671
|
+
if (process.env.ZCF_CODEX_SKIP_PROMPT_SINGLE_BACKUP === "true")
|
|
3672
|
+
cachedSkipPromptBackup = backupDir;
|
|
3554
3673
|
return backupDir;
|
|
3555
3674
|
}
|
|
3556
3675
|
function backupCodexComplete() {
|
|
@@ -3570,6 +3689,8 @@ function backupCodexConfig() {
|
|
|
3570
3689
|
}
|
|
3571
3690
|
}
|
|
3572
3691
|
function backupCodexAgents() {
|
|
3692
|
+
if (process.env.ZCF_CODEX_SKIP_PROMPT_SINGLE_BACKUP === "true" && cachedSkipPromptBackup)
|
|
3693
|
+
return cachedSkipPromptBackup;
|
|
3573
3694
|
if (!exists(CODEX_AGENTS_FILE))
|
|
3574
3695
|
return null;
|
|
3575
3696
|
try {
|
|
@@ -3583,6 +3704,8 @@ function backupCodexAgents() {
|
|
|
3583
3704
|
}
|
|
3584
3705
|
}
|
|
3585
3706
|
function backupCodexPrompts() {
|
|
3707
|
+
if (process.env.ZCF_CODEX_SKIP_PROMPT_SINGLE_BACKUP === "true" && cachedSkipPromptBackup)
|
|
3708
|
+
return cachedSkipPromptBackup;
|
|
3586
3709
|
if (!exists(CODEX_PROMPTS_DIR))
|
|
3587
3710
|
return null;
|
|
3588
3711
|
try {
|
|
@@ -4138,7 +4261,6 @@ async function runCodexWorkflowImportWithLanguageSelection(options) {
|
|
|
4138
4261
|
async function runCodexSystemPromptSelection(skipPrompt = false) {
|
|
4139
4262
|
ensureI18nInitialized();
|
|
4140
4263
|
const rootDir = getRootDir$1();
|
|
4141
|
-
const templateRoot = join(rootDir, "templates", "codex");
|
|
4142
4264
|
const zcfConfig$1 = readZcfConfig();
|
|
4143
4265
|
const { readDefaultTomlConfig: readDefaultTomlConfig2 } = await Promise.resolve().then(function () { return zcfConfig; });
|
|
4144
4266
|
const tomlConfig = readDefaultTomlConfig2();
|
|
@@ -4151,10 +4273,9 @@ async function runCodexSystemPromptSelection(skipPrompt = false) {
|
|
|
4151
4273
|
// Pass skipPrompt flag
|
|
4152
4274
|
);
|
|
4153
4275
|
updateZcfConfig({ templateLang: preferredLang });
|
|
4154
|
-
let
|
|
4155
|
-
if (!exists(
|
|
4156
|
-
|
|
4157
|
-
const systemPromptSrc = join(langDir, "system-prompt");
|
|
4276
|
+
let systemPromptSrc = join(rootDir, "templates", "common", "output-styles", preferredLang);
|
|
4277
|
+
if (!exists(systemPromptSrc))
|
|
4278
|
+
systemPromptSrc = join(rootDir, "templates", "common", "output-styles", "zh-CN");
|
|
4158
4279
|
if (!exists(systemPromptSrc))
|
|
4159
4280
|
return;
|
|
4160
4281
|
const availablePrompts = [
|
|
@@ -4216,17 +4337,17 @@ async function runCodexWorkflowSelection(options) {
|
|
|
4216
4337
|
ensureI18nInitialized();
|
|
4217
4338
|
const { skipPrompt = false, workflows: presetWorkflows = [] } = options ?? {};
|
|
4218
4339
|
const rootDir = getRootDir$1();
|
|
4219
|
-
const templateRoot = join(rootDir, "templates", "codex");
|
|
4220
4340
|
const zcfConfig = readZcfConfig();
|
|
4221
4341
|
const templateLang = zcfConfig?.templateLang || zcfConfig?.preferredLang || "en";
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
if (!exists(langDir))
|
|
4225
|
-
langDir = join(templateRoot, "zh-CN");
|
|
4226
|
-
const workflowSrc = join(langDir, "workflow");
|
|
4342
|
+
let preferredLang = templateLang === "en" ? "en" : "zh-CN";
|
|
4343
|
+
const workflowSrc = join(rootDir, "templates", "common", "workflow");
|
|
4227
4344
|
if (!exists(workflowSrc))
|
|
4228
4345
|
return;
|
|
4229
|
-
|
|
4346
|
+
let allWorkflows = getAllWorkflowFiles(workflowSrc, preferredLang);
|
|
4347
|
+
if (allWorkflows.length === 0 && preferredLang === "en") {
|
|
4348
|
+
preferredLang = "zh-CN";
|
|
4349
|
+
allWorkflows = getAllWorkflowFiles(workflowSrc, preferredLang);
|
|
4350
|
+
}
|
|
4230
4351
|
if (allWorkflows.length === 0)
|
|
4231
4352
|
return;
|
|
4232
4353
|
if (skipPrompt) {
|
|
@@ -4240,9 +4361,9 @@ async function runCodexWorkflowSelection(options) {
|
|
|
4240
4361
|
const selectedWorkflows = allWorkflows.filter(
|
|
4241
4362
|
(workflow) => presetWorkflows.includes(workflow.name)
|
|
4242
4363
|
);
|
|
4243
|
-
workflowsToInstall = expandSelectedWorkflowPaths(selectedWorkflows.map((w) => w.path), workflowSrc);
|
|
4364
|
+
workflowsToInstall = expandSelectedWorkflowPaths(selectedWorkflows.map((w) => w.path), workflowSrc, preferredLang);
|
|
4244
4365
|
} else {
|
|
4245
|
-
workflowsToInstall = expandSelectedWorkflowPaths(allWorkflows.map((w) => w.path), workflowSrc);
|
|
4366
|
+
workflowsToInstall = expandSelectedWorkflowPaths(allWorkflows.map((w) => w.path), workflowSrc, preferredLang);
|
|
4246
4367
|
}
|
|
4247
4368
|
for (const workflowPath of workflowsToInstall) {
|
|
4248
4369
|
const content = readFile(workflowPath);
|
|
@@ -4270,7 +4391,7 @@ async function runCodexWorkflowSelection(options) {
|
|
|
4270
4391
|
if (backupPath) {
|
|
4271
4392
|
console.log(ansis.gray(getBackupMessage(backupPath)));
|
|
4272
4393
|
}
|
|
4273
|
-
const finalWorkflowPaths = expandSelectedWorkflowPaths(workflows, workflowSrc);
|
|
4394
|
+
const finalWorkflowPaths = expandSelectedWorkflowPaths(workflows, workflowSrc, preferredLang);
|
|
4274
4395
|
for (const workflowPath of finalWorkflowPaths) {
|
|
4275
4396
|
const content = readFile(workflowPath);
|
|
4276
4397
|
const filename = workflowPath.split("/").pop() || "workflow.md";
|
|
@@ -4279,19 +4400,16 @@ async function runCodexWorkflowSelection(options) {
|
|
|
4279
4400
|
}
|
|
4280
4401
|
}
|
|
4281
4402
|
const GIT_GROUP_SENTINEL = "::gitGroup";
|
|
4282
|
-
function getAllWorkflowFiles(
|
|
4403
|
+
function getAllWorkflowFiles(workflowSrc, preferredLang) {
|
|
4283
4404
|
const workflows = [];
|
|
4284
|
-
const
|
|
4285
|
-
if (exists(
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
path: workflowFile
|
|
4291
|
-
});
|
|
4292
|
-
}
|
|
4405
|
+
const sixStepFile = join(workflowSrc, "sixStep", preferredLang, "workflow.md");
|
|
4406
|
+
if (exists(sixStepFile)) {
|
|
4407
|
+
workflows.push({
|
|
4408
|
+
name: i18n.t("workflow:workflowOption.sixStepsWorkflow"),
|
|
4409
|
+
path: sixStepFile
|
|
4410
|
+
});
|
|
4293
4411
|
}
|
|
4294
|
-
const gitPromptsDir = join(
|
|
4412
|
+
const gitPromptsDir = join(workflowSrc, "git", preferredLang);
|
|
4295
4413
|
if (exists(gitPromptsDir)) {
|
|
4296
4414
|
workflows.push({
|
|
4297
4415
|
name: i18n.t("workflow:workflowOption.gitWorkflow"),
|
|
@@ -4301,19 +4419,19 @@ function getAllWorkflowFiles(dirPath) {
|
|
|
4301
4419
|
}
|
|
4302
4420
|
return workflows;
|
|
4303
4421
|
}
|
|
4304
|
-
function expandSelectedWorkflowPaths(paths, workflowSrc) {
|
|
4422
|
+
function expandSelectedWorkflowPaths(paths, workflowSrc, preferredLang) {
|
|
4305
4423
|
const expanded = [];
|
|
4306
4424
|
for (const p of paths) {
|
|
4307
4425
|
if (p === GIT_GROUP_SENTINEL) {
|
|
4308
|
-
expanded.push(...getGitPromptFiles(workflowSrc));
|
|
4426
|
+
expanded.push(...getGitPromptFiles(workflowSrc, preferredLang));
|
|
4309
4427
|
} else {
|
|
4310
4428
|
expanded.push(p);
|
|
4311
4429
|
}
|
|
4312
4430
|
}
|
|
4313
4431
|
return expanded;
|
|
4314
4432
|
}
|
|
4315
|
-
function getGitPromptFiles(workflowSrc) {
|
|
4316
|
-
const
|
|
4433
|
+
function getGitPromptFiles(workflowSrc, preferredLang) {
|
|
4434
|
+
const gitPromptsDir = join(workflowSrc, "git", preferredLang);
|
|
4317
4435
|
const files = [
|
|
4318
4436
|
"git-commit.md",
|
|
4319
4437
|
"git-rollback.md",
|
|
@@ -4322,7 +4440,7 @@ function getGitPromptFiles(workflowSrc) {
|
|
|
4322
4440
|
];
|
|
4323
4441
|
const resolved = [];
|
|
4324
4442
|
for (const f of files) {
|
|
4325
|
-
const full = join(
|
|
4443
|
+
const full = join(gitPromptsDir, f);
|
|
4326
4444
|
if (exists(full))
|
|
4327
4445
|
resolved.push(full);
|
|
4328
4446
|
}
|
|
@@ -4353,29 +4471,39 @@ async function applyCustomApiConfig(customApiConfig) {
|
|
|
4353
4471
|
if (backupPath) {
|
|
4354
4472
|
console.log(ansis.gray(getBackupMessage(backupPath)));
|
|
4355
4473
|
}
|
|
4474
|
+
const existingConfig = readCodexConfig();
|
|
4475
|
+
const existingAuth = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
|
|
4356
4476
|
const providers = [];
|
|
4357
|
-
const authEntries = {};
|
|
4477
|
+
const authEntries = { ...existingAuth };
|
|
4358
4478
|
const providerId = type === "auth_token" ? "official-auth-token" : "custom-api-key";
|
|
4359
4479
|
const providerName = type === "auth_token" ? "Official Auth Token" : "Custom API Key";
|
|
4480
|
+
const existingProvider = existingConfig?.providers.find((p) => p.id === providerId);
|
|
4360
4481
|
providers.push({
|
|
4361
4482
|
id: providerId,
|
|
4362
4483
|
name: providerName,
|
|
4363
|
-
baseUrl: baseUrl || "https://api.anthropic.com",
|
|
4364
|
-
wireApi: "
|
|
4365
|
-
tempEnvKey: `${providerId.toUpperCase()}_API_KEY`,
|
|
4366
|
-
requiresOpenaiAuth: false
|
|
4484
|
+
baseUrl: baseUrl || existingProvider?.baseUrl || "https://api.anthropic.com",
|
|
4485
|
+
wireApi: existingProvider?.wireApi || "responses",
|
|
4486
|
+
tempEnvKey: existingProvider?.tempEnvKey || `${providerId.toUpperCase()}_API_KEY`,
|
|
4487
|
+
requiresOpenaiAuth: existingProvider?.requiresOpenaiAuth ?? false,
|
|
4488
|
+
model: model || existingProvider?.model
|
|
4367
4489
|
});
|
|
4490
|
+
if (existingConfig?.providers) {
|
|
4491
|
+
providers.push(...existingConfig.providers.filter((p) => p.id !== providerId));
|
|
4492
|
+
}
|
|
4368
4493
|
if (token) {
|
|
4369
4494
|
authEntries[providerId] = token;
|
|
4495
|
+
authEntries.OPENAI_API_KEY = token;
|
|
4370
4496
|
}
|
|
4371
4497
|
const configData = {
|
|
4372
|
-
model: model || "claude-3-5-sonnet-20241022",
|
|
4373
|
-
//
|
|
4498
|
+
model: model || existingConfig?.model || "claude-3-5-sonnet-20241022",
|
|
4499
|
+
// Prefer provided model, then existing, fallback default
|
|
4374
4500
|
modelProvider: providerId,
|
|
4375
4501
|
modelProviderCommented: false,
|
|
4376
4502
|
providers,
|
|
4377
|
-
mcpServices: []
|
|
4378
|
-
|
|
4503
|
+
mcpServices: existingConfig?.mcpServices || [],
|
|
4504
|
+
otherConfig: existingConfig?.otherConfig || []
|
|
4505
|
+
};
|
|
4506
|
+
writeCodexConfig(configData);
|
|
4379
4507
|
writeJsonConfig(CODEX_AUTH_FILE, authEntries);
|
|
4380
4508
|
updateZcfConfig({ codeToolType: "codex" });
|
|
4381
4509
|
console.log(ansis.green(`\u2714 ${i18n.t("codex:apiConfigured")}`));
|
|
@@ -5135,7 +5263,7 @@ async function copyOutputStyles(selectedStyles, lang) {
|
|
|
5135
5263
|
const currentFilePath = fileURLToPath(import.meta.url);
|
|
5136
5264
|
const distDir = dirname(dirname(currentFilePath));
|
|
5137
5265
|
const rootDir = dirname(distDir);
|
|
5138
|
-
const templateDir = join(rootDir, "templates", "
|
|
5266
|
+
const templateDir = join(rootDir, "templates", "common", "output-styles", lang);
|
|
5139
5267
|
for (const styleId of selectedStyles) {
|
|
5140
5268
|
const style = OUTPUT_STYLES.find((s) => s.id === styleId);
|
|
5141
5269
|
if (!style || !style.isCustom || !style.filePath) {
|
|
@@ -6283,6 +6411,7 @@ function getRootDir() {
|
|
|
6283
6411
|
return dirname(distDir);
|
|
6284
6412
|
}
|
|
6285
6413
|
const DEFAULT_CODE_TOOL_TEMPLATE = "claude-code";
|
|
6414
|
+
const COMMON_TEMPLATE_CATEGORIES = ["git", "sixStep"];
|
|
6286
6415
|
async function selectAndInstallWorkflows(configLang, preselectedWorkflows) {
|
|
6287
6416
|
ensureI18nInitialized();
|
|
6288
6417
|
const workflows = getOrderedWorkflows();
|
|
@@ -6342,7 +6471,16 @@ async function installWorkflowWithDependencies(config, configLang) {
|
|
|
6342
6471
|
await mkdir(commandsDir, { recursive: true });
|
|
6343
6472
|
}
|
|
6344
6473
|
for (const commandFile of config.commands) {
|
|
6345
|
-
const
|
|
6474
|
+
const isCommonTemplate = COMMON_TEMPLATE_CATEGORIES.includes(config.category);
|
|
6475
|
+
const commandSource = isCommonTemplate ? join(
|
|
6476
|
+
rootDir,
|
|
6477
|
+
"templates",
|
|
6478
|
+
"common",
|
|
6479
|
+
"workflow",
|
|
6480
|
+
config.category,
|
|
6481
|
+
configLang,
|
|
6482
|
+
commandFile
|
|
6483
|
+
) : join(
|
|
6346
6484
|
rootDir,
|
|
6347
6485
|
"templates",
|
|
6348
6486
|
DEFAULT_CODE_TOOL_TEMPLATE,
|
|
@@ -6508,15 +6646,18 @@ async function validateSkipPromptOptions(options) {
|
|
|
6508
6646
|
if (options.apiConfigs && options.apiConfigsFile) {
|
|
6509
6647
|
throw new Error(i18n.t("multi-config:conflictingParams"));
|
|
6510
6648
|
}
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
6649
|
+
const modelParams = [
|
|
6650
|
+
["apiModel", options.apiModel],
|
|
6651
|
+
["apiHaikuModel", options.apiHaikuModel],
|
|
6652
|
+
["apiSonnetModel", options.apiSonnetModel],
|
|
6653
|
+
["apiOpusModel", options.apiOpusModel]
|
|
6654
|
+
];
|
|
6655
|
+
for (const [key, value] of modelParams) {
|
|
6656
|
+
if (value !== void 0 && typeof value !== "string") {
|
|
6657
|
+
if (key === "apiModel")
|
|
6658
|
+
throw new Error(i18n.t("errors:invalidApiModel", { value }));
|
|
6659
|
+
throw new Error(i18n.t("errors:invalidModelParam", { key, value }));
|
|
6660
|
+
}
|
|
6520
6661
|
}
|
|
6521
6662
|
if (options.apiType === "api_key" && !options.apiKey) {
|
|
6522
6663
|
throw new Error(i18n.t("errors:apiKeyRequiredForApiKey"));
|
|
@@ -6706,8 +6847,11 @@ async function init(options = {}) {
|
|
|
6706
6847
|
configLang = "en";
|
|
6707
6848
|
}
|
|
6708
6849
|
if (codeToolType === "codex") {
|
|
6709
|
-
|
|
6710
|
-
|
|
6850
|
+
if (options.skipPrompt)
|
|
6851
|
+
process.env.ZCF_CODEX_SKIP_PROMPT_SINGLE_BACKUP = "true";
|
|
6852
|
+
const hasApiConfigs = Boolean(options.apiConfigs || options.apiConfigsFile);
|
|
6853
|
+
const apiMode = hasApiConfigs ? "skip" : options.apiType === "auth_token" ? "official" : options.apiType === "api_key" ? "custom" : options.apiType === "skip" ? "skip" : options.skipPrompt ? "skip" : void 0;
|
|
6854
|
+
const customApiConfig = !hasApiConfigs && options.apiType === "api_key" && options.apiKey ? {
|
|
6711
6855
|
type: "api_key",
|
|
6712
6856
|
token: options.apiKey,
|
|
6713
6857
|
baseUrl: options.apiUrl,
|
|
@@ -6722,6 +6866,9 @@ async function init(options = {}) {
|
|
|
6722
6866
|
} else if (options.workflows === true) {
|
|
6723
6867
|
selectedWorkflows = [];
|
|
6724
6868
|
}
|
|
6869
|
+
if (hasApiConfigs) {
|
|
6870
|
+
await handleMultiConfigurations(options, "codex");
|
|
6871
|
+
}
|
|
6725
6872
|
const resolvedAiOutputLang = await runCodexFullInit({
|
|
6726
6873
|
aiOutputLang: options.aiOutputLang,
|
|
6727
6874
|
skipPrompt: options.skipPrompt,
|
|
@@ -6840,9 +6987,12 @@ async function init(options = {}) {
|
|
|
6840
6987
|
key: options.apiKey,
|
|
6841
6988
|
url: preset?.claudeCode?.baseUrl || options.apiUrl || API_DEFAULT_URL
|
|
6842
6989
|
};
|
|
6843
|
-
if (preset?.claudeCode?.defaultModels && preset.claudeCode.defaultModels.length
|
|
6844
|
-
|
|
6845
|
-
options.
|
|
6990
|
+
if (preset?.claudeCode?.defaultModels && preset.claudeCode.defaultModels.length > 0) {
|
|
6991
|
+
const [primary, haiku, sonnet, opus] = preset.claudeCode.defaultModels;
|
|
6992
|
+
options.apiModel = options.apiModel || primary;
|
|
6993
|
+
options.apiHaikuModel = options.apiHaikuModel || haiku;
|
|
6994
|
+
options.apiSonnetModel = options.apiSonnetModel || sonnet;
|
|
6995
|
+
options.apiOpusModel = options.apiOpusModel || opus;
|
|
6846
6996
|
}
|
|
6847
6997
|
await saveSingleConfigToToml(apiConfig, options.provider, options);
|
|
6848
6998
|
} else if (options.apiType === "auth_token" && options.apiKey) {
|
|
@@ -6969,20 +7119,26 @@ async function init(options = {}) {
|
|
|
6969
7119
|
console.log(ansis.gray(` Key: ${formatApiKeyDisplay(configuredApi.key)}`));
|
|
6970
7120
|
}
|
|
6971
7121
|
}
|
|
6972
|
-
|
|
7122
|
+
const hasModelParams = options.apiModel || options.apiHaikuModel || options.apiSonnetModel || options.apiOpusModel;
|
|
7123
|
+
if (hasModelParams && action !== "docs-only" && codeToolType === "claude-code") {
|
|
6973
7124
|
if (options.skipPrompt) {
|
|
6974
7125
|
const { updateCustomModel } = await Promise.resolve().then(function () { return config$1; });
|
|
6975
7126
|
updateCustomModel(
|
|
6976
7127
|
options.apiModel || void 0,
|
|
6977
|
-
options.
|
|
7128
|
+
options.apiHaikuModel || void 0,
|
|
7129
|
+
options.apiSonnetModel || void 0,
|
|
7130
|
+
options.apiOpusModel || void 0
|
|
6978
7131
|
);
|
|
6979
7132
|
console.log(ansis.green(`\u2714 ${i18n.t("api:modelConfigSuccess")}`));
|
|
6980
7133
|
if (options.apiModel) {
|
|
6981
7134
|
console.log(ansis.gray(` ${i18n.t("api:primaryModel")}: ${options.apiModel}`));
|
|
6982
7135
|
}
|
|
6983
|
-
if (options.
|
|
6984
|
-
console.log(ansis.gray(`
|
|
6985
|
-
|
|
7136
|
+
if (options.apiHaikuModel)
|
|
7137
|
+
console.log(ansis.gray(` Haiku: ${options.apiHaikuModel}`));
|
|
7138
|
+
if (options.apiSonnetModel)
|
|
7139
|
+
console.log(ansis.gray(` Sonnet: ${options.apiSonnetModel}`));
|
|
7140
|
+
if (options.apiOpusModel)
|
|
7141
|
+
console.log(ansis.gray(` Opus: ${options.apiOpusModel}`));
|
|
6986
7142
|
}
|
|
6987
7143
|
}
|
|
6988
7144
|
if (action !== "docs-only") {
|
|
@@ -7205,6 +7361,7 @@ async function handleClaudeCodeConfigs(configs) {
|
|
|
7205
7361
|
}
|
|
7206
7362
|
async function handleCodexConfigs(configs) {
|
|
7207
7363
|
const { addProviderToExisting } = await import('./codex-provider-manager.mjs');
|
|
7364
|
+
const addedProviderIds = [];
|
|
7208
7365
|
for (const config of configs) {
|
|
7209
7366
|
try {
|
|
7210
7367
|
const provider = await convertToCodexProvider(config);
|
|
@@ -7212,6 +7369,7 @@ async function handleCodexConfigs(configs) {
|
|
|
7212
7369
|
if (!result.success) {
|
|
7213
7370
|
throw new Error(i18n.t("multi-config:providerAddFailed", { name: config.name, error: result.error }));
|
|
7214
7371
|
}
|
|
7372
|
+
addedProviderIds.push(provider.id);
|
|
7215
7373
|
console.log(ansis.green(`\u2714 ${i18n.t("multi-config:providerAdded", { name: config.name })}`));
|
|
7216
7374
|
} catch (error) {
|
|
7217
7375
|
console.error(ansis.red(i18n.t("multi-config:providerAddFailed", {
|
|
@@ -7224,8 +7382,14 @@ async function handleCodexConfigs(configs) {
|
|
|
7224
7382
|
const defaultConfig = configs.find((c) => c.default);
|
|
7225
7383
|
if (defaultConfig) {
|
|
7226
7384
|
const { switchCodexProvider } = await Promise.resolve().then(function () { return codex; });
|
|
7227
|
-
|
|
7228
|
-
|
|
7385
|
+
const displayName = defaultConfig.name || defaultConfig.provider || "custom";
|
|
7386
|
+
const providerId = displayName.toLowerCase().replace(/[^a-z0-9]/g, "-");
|
|
7387
|
+
if (addedProviderIds.includes(providerId)) {
|
|
7388
|
+
await switchCodexProvider(providerId);
|
|
7389
|
+
console.log(ansis.green(`\u2714 ${i18n.t("multi-config:defaultProviderSet", { name: displayName })}`));
|
|
7390
|
+
} else {
|
|
7391
|
+
console.log(ansis.red(i18n.t("multi-config:providerAddFailed", { name: displayName, error: "provider not added" })));
|
|
7392
|
+
}
|
|
7229
7393
|
}
|
|
7230
7394
|
}
|
|
7231
7395
|
async function saveSingleConfigToToml(apiConfig, provider, options) {
|
|
@@ -7252,7 +7416,9 @@ async function convertSingleConfigToProfile(apiConfig, provider, options) {
|
|
|
7252
7416
|
const configName = provider && provider !== "custom" ? provider : "custom-config";
|
|
7253
7417
|
let baseUrl = apiConfig.url || API_DEFAULT_URL;
|
|
7254
7418
|
let primaryModel = options?.apiModel;
|
|
7255
|
-
let
|
|
7419
|
+
let defaultHaikuModel = options?.apiHaikuModel;
|
|
7420
|
+
let defaultSonnetModel = options?.apiSonnetModel;
|
|
7421
|
+
let defaultOpusModel = options?.apiOpusModel;
|
|
7256
7422
|
let authType = apiConfig.authType;
|
|
7257
7423
|
if (provider && provider !== "custom") {
|
|
7258
7424
|
const { getProviderPreset } = await import('./api-providers.mjs');
|
|
@@ -7260,9 +7426,12 @@ async function convertSingleConfigToProfile(apiConfig, provider, options) {
|
|
|
7260
7426
|
if (preset?.claudeCode) {
|
|
7261
7427
|
baseUrl = apiConfig.url || preset.claudeCode.baseUrl;
|
|
7262
7428
|
authType = preset.claudeCode.authType;
|
|
7263
|
-
if (preset.claudeCode.defaultModels && preset.claudeCode.defaultModels.length
|
|
7264
|
-
|
|
7265
|
-
|
|
7429
|
+
if (preset.claudeCode.defaultModels && preset.claudeCode.defaultModels.length > 0) {
|
|
7430
|
+
const [p, h, s, o] = preset.claudeCode.defaultModels;
|
|
7431
|
+
primaryModel = primaryModel || p;
|
|
7432
|
+
defaultHaikuModel = defaultHaikuModel || h;
|
|
7433
|
+
defaultSonnetModel = defaultSonnetModel || s;
|
|
7434
|
+
defaultOpusModel = defaultOpusModel || o;
|
|
7266
7435
|
}
|
|
7267
7436
|
}
|
|
7268
7437
|
}
|
|
@@ -7272,7 +7441,9 @@ async function convertSingleConfigToProfile(apiConfig, provider, options) {
|
|
|
7272
7441
|
apiKey: apiConfig.key,
|
|
7273
7442
|
baseUrl,
|
|
7274
7443
|
primaryModel,
|
|
7275
|
-
|
|
7444
|
+
defaultHaikuModel,
|
|
7445
|
+
defaultSonnetModel,
|
|
7446
|
+
defaultOpusModel,
|
|
7276
7447
|
id: ClaudeCodeConfigManager.generateProfileId(configName)
|
|
7277
7448
|
};
|
|
7278
7449
|
return profile;
|
|
@@ -7281,7 +7452,9 @@ async function convertToClaudeCodeProfile(config) {
|
|
|
7281
7452
|
const { ClaudeCodeConfigManager } = await import('./claude-code-config-manager.mjs');
|
|
7282
7453
|
let baseUrl = config.url;
|
|
7283
7454
|
let primaryModel = config.primaryModel;
|
|
7284
|
-
let
|
|
7455
|
+
let defaultHaikuModel = config.defaultHaikuModel;
|
|
7456
|
+
let defaultSonnetModel = config.defaultSonnetModel;
|
|
7457
|
+
let defaultOpusModel = config.defaultOpusModel;
|
|
7285
7458
|
let authType = config.type || "api_key";
|
|
7286
7459
|
if (config.provider && config.provider !== "custom") {
|
|
7287
7460
|
const { getProviderPreset } = await import('./api-providers.mjs');
|
|
@@ -7289,9 +7462,12 @@ async function convertToClaudeCodeProfile(config) {
|
|
|
7289
7462
|
if (preset?.claudeCode) {
|
|
7290
7463
|
baseUrl = baseUrl || preset.claudeCode.baseUrl;
|
|
7291
7464
|
authType = preset.claudeCode.authType;
|
|
7292
|
-
if (preset.claudeCode.defaultModels && preset.claudeCode.defaultModels.length
|
|
7293
|
-
|
|
7294
|
-
|
|
7465
|
+
if (preset.claudeCode.defaultModels && preset.claudeCode.defaultModels.length > 0) {
|
|
7466
|
+
const [p, h, s, o] = preset.claudeCode.defaultModels;
|
|
7467
|
+
primaryModel = primaryModel || p;
|
|
7468
|
+
defaultHaikuModel = defaultHaikuModel || h;
|
|
7469
|
+
defaultSonnetModel = defaultSonnetModel || s;
|
|
7470
|
+
defaultOpusModel = defaultOpusModel || o;
|
|
7295
7471
|
}
|
|
7296
7472
|
}
|
|
7297
7473
|
}
|
|
@@ -7301,15 +7477,19 @@ async function convertToClaudeCodeProfile(config) {
|
|
|
7301
7477
|
apiKey: config.key,
|
|
7302
7478
|
baseUrl,
|
|
7303
7479
|
primaryModel,
|
|
7304
|
-
|
|
7480
|
+
defaultHaikuModel,
|
|
7481
|
+
defaultSonnetModel,
|
|
7482
|
+
defaultOpusModel,
|
|
7305
7483
|
id: ClaudeCodeConfigManager.generateProfileId(config.name)
|
|
7306
7484
|
};
|
|
7307
7485
|
return profile;
|
|
7308
7486
|
}
|
|
7309
7487
|
async function convertToCodexProvider(config) {
|
|
7488
|
+
const displayName = config.name || config.provider || "custom";
|
|
7489
|
+
const providerId = displayName.toLowerCase().replace(/[^a-z0-9]/g, "-");
|
|
7310
7490
|
let baseUrl = config.url || API_DEFAULT_URL;
|
|
7311
7491
|
let model = config.primaryModel || "gpt-5-codex";
|
|
7312
|
-
let wireApi = "
|
|
7492
|
+
let wireApi = "responses";
|
|
7313
7493
|
if (config.provider && config.provider !== "custom") {
|
|
7314
7494
|
const { getProviderPreset } = await import('./api-providers.mjs');
|
|
7315
7495
|
const preset = getProviderPreset(config.provider);
|
|
@@ -7320,11 +7500,11 @@ async function convertToCodexProvider(config) {
|
|
|
7320
7500
|
}
|
|
7321
7501
|
}
|
|
7322
7502
|
return {
|
|
7323
|
-
id:
|
|
7324
|
-
name:
|
|
7503
|
+
id: providerId,
|
|
7504
|
+
name: displayName,
|
|
7325
7505
|
baseUrl,
|
|
7326
7506
|
wireApi,
|
|
7327
|
-
tempEnvKey:
|
|
7507
|
+
tempEnvKey: `${displayName}_API_KEY`.replace(/\W/g, "_").toUpperCase(),
|
|
7328
7508
|
requiresOpenaiAuth: false,
|
|
7329
7509
|
model
|
|
7330
7510
|
};
|
|
@@ -7408,4 +7588,4 @@ async function openSettingsJson() {
|
|
|
7408
7588
|
}
|
|
7409
7589
|
}
|
|
7410
7590
|
|
|
7411
|
-
export { getExistingModelConfig as $, API_DEFAULT_URL as A, getAiOutputLanguageLabel as B, CLAUDE_DIR as C, DEFAULT_CODE_TOOL_TYPE as D, getMcpConfigPath as E, readMcpConfig as F, writeMcpConfig as G, backupMcpConfig as H, mergeMcpServers as I, buildMcpServerConfig as J, fixWindowsMcpConfig as K, LEGACY_ZCF_CONFIG_FILES as L, addCompletedOnboarding as M, ensureApiKeyApproved as N, removeApiKeyFromRejected as O, manageApiKeyApproval as P, setPrimaryApiKey as Q, ensureClaudeDir as R, SETTINGS_FILE as S, backupExistingConfig as T, copyConfigFiles as U, configureApi as V, mergeConfigs as W, updateCustomModel as X, updateDefaultModel as Y, ZCF_CONFIG_DIR as Z, mergeSettingsFile as _, commandExists as a,
|
|
7591
|
+
export { getExistingModelConfig as $, API_DEFAULT_URL as A, getAiOutputLanguageLabel as B, CLAUDE_DIR as C, DEFAULT_CODE_TOOL_TYPE as D, getMcpConfigPath as E, readMcpConfig as F, writeMcpConfig as G, backupMcpConfig as H, mergeMcpServers as I, buildMcpServerConfig as J, fixWindowsMcpConfig as K, LEGACY_ZCF_CONFIG_FILES as L, addCompletedOnboarding as M, ensureApiKeyApproved as N, removeApiKeyFromRejected as O, manageApiKeyApproval as P, setPrimaryApiKey as Q, ensureClaudeDir as R, SETTINGS_FILE as S, backupExistingConfig as T, copyConfigFiles as U, configureApi as V, mergeConfigs as W, updateCustomModel as X, updateDefaultModel as Y, ZCF_CONFIG_DIR as Z, mergeSettingsFile as _, commandExists as a, resolveAiOutputLanguage as a$, getExistingApiConfig as a0, applyAiLanguageDirective as a1, switchToOfficialLogin$1 as a2, promptApiConfigurationAction as a3, isClaudeCodeInstalled as a4, installClaudeCode as a5, isCodexInstalled as a6, installCodex as a7, isLocalClaudeCodeInstalled as a8, getInstallationStatus as a9, writeCodexConfig as aA, writeAuthFile as aB, updateZcfConfig as aC, changeLanguage as aD, readZcfConfig as aE, configureOutputStyle as aF, isWindows as aG, selectMcpServices as aH, getMcpServices as aI, isCcrInstalled as aJ, installCcr as aK, setupCcrConfiguration as aL, modifyApiConfigPartially as aM, formatApiKeyDisplay as aN, readCcrConfig as aO, configureCcrFeature as aP, handleExitPromptError as aQ, handleGeneralError as aR, COMETIX_COMMAND_NAME as aS, COMETIX_COMMANDS as aT, installCometixLine as aU, checkAndUpdateTools as aV, runCodexUpdate as aW, resolveCodeType as aX, writeJsonConfig as aY, displayBanner as aZ, version as a_, removeLocalClaudeCode as aa, uninstallCodeTool as ab, setInstallMethod as ac, detectInstalledVersion as ad, selectInstallMethod as ae, executeInstallMethod as af, handleInstallFailure as ag, verifyInstallation as ah, createHomebrewSymlink as ai, displayVerificationResult as aj, ensureI18nInitialized as ak, i18n as al, addNumbersToChoices as am, validateApiKey as an, promptBoolean as ao, ensureDir as ap, readDefaultTomlConfig as aq, createDefaultTomlConfig as ar, exists as as, readJsonConfig as at, writeTomlConfig as au, clearModelEnv as av, copyFile as aw, detectConfigManagementMode as ax, readCodexConfig as ay, backupCodexComplete as az, importRecommendedEnv as b, updatePromptOnly as b0, selectAndInstallWorkflows as b1, checkClaudeCodeVersionAndPrompt as b2, displayBannerWithInfo as b3, runCodexUninstall as b4, configureCodexMcp as b5, configureCodexApi as b6, runCodexWorkflowImportWithLanguageSelection as b7, runCodexFullInit as b8, switchCodexProvider as b9, listCodexProviders as ba, switchToOfficialLogin as bb, switchToProvider as bc, readZcfConfigAsync as bd, initI18n as be, selectScriptLanguage as bf, index as bg, fsOperations as bh, jsonConfig as bi, claudeConfig as bj, config$1 as bk, config as bl, prompts as bm, codex as bn, installer as bo, cleanupPermissions as c, importRecommendedPermissions as d, CLAUDE_MD_FILE as e, ClAUDE_CONFIG_FILE as f, getPlatform as g, CLAUDE_VSC_CONFIG_FILE as h, init as i, CODEX_DIR as j, CODEX_CONFIG_FILE as k, CODEX_AUTH_FILE as l, mergeAndCleanPermissions as m, CODEX_AGENTS_FILE as n, openSettingsJson as o, CODEX_PROMPTS_DIR as p, ZCF_CONFIG_FILE as q, CODE_TOOL_TYPES as r, CODE_TOOL_BANNERS as s, CODE_TOOL_ALIASES as t, isCodeToolType as u, API_ENV_KEY as v, resolveCodeToolType as w, SUPPORTED_LANGS as x, LANG_LABELS as y, AI_OUTPUT_LANGUAGES as z };
|