zcf 3.2.2 → 3.3.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 +131 -24
- package/dist/chunks/api-providers.mjs +76 -0
- package/dist/chunks/claude-code-config-manager.mjs +21 -7
- package/dist/chunks/claude-code-incremental-manager.mjs +59 -17
- package/dist/chunks/codex-config-switch.mjs +72 -13
- package/dist/chunks/codex-provider-manager.mjs +18 -8
- package/dist/chunks/codex-uninstaller.mjs +1 -1
- package/dist/chunks/commands.mjs +1 -1
- package/dist/chunks/features.mjs +637 -0
- package/dist/chunks/simple-config.mjs +192 -40
- package/dist/cli.mjs +28 -615
- package/dist/i18n/locales/en/api.json +6 -1
- package/dist/i18n/locales/en/common.json +0 -1
- package/dist/i18n/locales/en/errors.json +2 -1
- package/dist/i18n/locales/en/multi-config.json +2 -1
- package/dist/i18n/locales/zh-CN/api.json +6 -1
- package/dist/i18n/locales/zh-CN/common.json +0 -1
- package/dist/i18n/locales/zh-CN/errors.json +2 -1
- package/dist/i18n/locales/zh-CN/multi-config.json +2 -1
- package/dist/index.d.mts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/templates/CLAUDE.md +190 -0
- package/templates/claude-code/en/output-styles/engineer-professional.md +2 -1
- package/templates/claude-code/en/output-styles/laowang-engineer.md +1 -0
- package/templates/claude-code/en/output-styles/nekomata-engineer.md +1 -0
- package/templates/claude-code/en/output-styles/ojousama-engineer.md +1 -0
- package/templates/claude-code/zh-CN/output-styles/engineer-professional.md +2 -1
- package/templates/claude-code/zh-CN/output-styles/laowang-engineer.md +1 -0
- package/templates/claude-code/zh-CN/output-styles/nekomata-engineer.md +1 -0
- package/templates/claude-code/zh-CN/output-styles/ojousama-engineer.md +1 -0
- package/templates/codex/en/system-prompt/engineer-professional.md +2 -1
- package/templates/codex/en/system-prompt/laowang-engineer.md +1 -0
- package/templates/codex/en/system-prompt/nekomata-engineer.md +1 -0
- package/templates/codex/en/system-prompt/ojousama-engineer.md +1 -0
- package/templates/codex/zh-CN/system-prompt/engineer-professional.md +2 -1
- package/templates/codex/zh-CN/system-prompt/laowang-engineer.md +1 -0
- package/templates/codex/zh-CN/system-prompt/nekomata-engineer.md +1 -0
- package/templates/codex/zh-CN/system-prompt/ojousama-engineer.md +1 -0
|
@@ -16,7 +16,7 @@ import { rm, mkdir, copyFile as copyFile$1 } from 'node:fs/promises';
|
|
|
16
16
|
import i18next from 'i18next';
|
|
17
17
|
import Backend from 'i18next-fs-backend';
|
|
18
18
|
|
|
19
|
-
const version = "3.
|
|
19
|
+
const version = "3.3.0";
|
|
20
20
|
const homepage = "https://github.com/UfoMiao/zcf";
|
|
21
21
|
|
|
22
22
|
const i18n = i18next.createInstance();
|
|
@@ -1666,9 +1666,9 @@ async function configureCcrWithPreset(preset) {
|
|
|
1666
1666
|
if (preset.requiresApiKey) {
|
|
1667
1667
|
try {
|
|
1668
1668
|
const { apiKey } = await inquirer.prompt({
|
|
1669
|
-
type: "
|
|
1669
|
+
type: "input",
|
|
1670
1670
|
name: "apiKey",
|
|
1671
|
-
message: i18n.t("ccr:enterApiKeyForProvider").replace("{provider}", preset.name)
|
|
1671
|
+
message: i18n.t("ccr:enterApiKeyForProvider").replace("{provider}", preset.name),
|
|
1672
1672
|
validate: async (value) => !!value || i18n.t("api:keyRequired")
|
|
1673
1673
|
});
|
|
1674
1674
|
provider.api_key = apiKey;
|
|
@@ -2867,9 +2867,9 @@ async function configureCodexMcp(options) {
|
|
|
2867
2867
|
if (configInfo.requiresApiKey && configInfo.apiKeyEnvVar) {
|
|
2868
2868
|
const promptMessage = serviceMeta?.apiKeyPrompt || i18n.t("mcp:apiKeyPrompt");
|
|
2869
2869
|
const { apiKey } = await inquirer.prompt([{
|
|
2870
|
-
type: "
|
|
2870
|
+
type: "input",
|
|
2871
2871
|
name: "apiKey",
|
|
2872
|
-
message: promptMessage
|
|
2872
|
+
message: promptMessage,
|
|
2873
2873
|
validate: (input) => !!input || i18n.t("api:keyRequired")
|
|
2874
2874
|
}]);
|
|
2875
2875
|
if (!apiKey)
|
|
@@ -3032,7 +3032,7 @@ function sanitizeProviderName(input) {
|
|
|
3032
3032
|
const cleaned = input.trim();
|
|
3033
3033
|
if (!cleaned)
|
|
3034
3034
|
return "";
|
|
3035
|
-
return cleaned.replace(/[
|
|
3035
|
+
return cleaned.toLowerCase().replace(/\./g, "-").replace(/\s+/g, "-").replace(/[^a-z0-9\-]/g, "");
|
|
3036
3036
|
}
|
|
3037
3037
|
function parseCodexConfig(content) {
|
|
3038
3038
|
if (!content.trim()) {
|
|
@@ -3061,7 +3061,9 @@ function parseCodexConfig(content) {
|
|
|
3061
3061
|
baseUrl: provider.base_url || "",
|
|
3062
3062
|
wireApi: provider.wire_api || "responses",
|
|
3063
3063
|
envKey: provider.env_key || "OPENAI_API_KEY",
|
|
3064
|
-
requiresOpenaiAuth: provider.requires_openai_auth !== false
|
|
3064
|
+
requiresOpenaiAuth: provider.requires_openai_auth !== false,
|
|
3065
|
+
model: provider.model || void 0
|
|
3066
|
+
// Parse model field from provider
|
|
3065
3067
|
});
|
|
3066
3068
|
}
|
|
3067
3069
|
}
|
|
@@ -3211,7 +3213,7 @@ function renderCodexConfig(data) {
|
|
|
3211
3213
|
return false;
|
|
3212
3214
|
if (/^#?\s*model_provider\s*=/.test(l))
|
|
3213
3215
|
return false;
|
|
3214
|
-
if (/^\s*model\s*=/.test(l))
|
|
3216
|
+
if (/^\s*model\s*=/.test(l) && !l.includes("["))
|
|
3215
3217
|
return false;
|
|
3216
3218
|
return true;
|
|
3217
3219
|
});
|
|
@@ -3231,6 +3233,9 @@ function renderCodexConfig(data) {
|
|
|
3231
3233
|
lines.push(`wire_api = "${provider.wireApi}"`);
|
|
3232
3234
|
lines.push(`env_key = "${provider.envKey}"`);
|
|
3233
3235
|
lines.push(`requires_openai_auth = ${provider.requiresOpenaiAuth}`);
|
|
3236
|
+
if (provider.model) {
|
|
3237
|
+
lines.push(`model = "${provider.model}"`);
|
|
3238
|
+
}
|
|
3234
3239
|
}
|
|
3235
3240
|
}
|
|
3236
3241
|
if (data.mcpServices.length > 0) {
|
|
@@ -3710,12 +3715,36 @@ async function configureCodexApi(options) {
|
|
|
3710
3715
|
const existingValues = existingMap.size ? Array.from(existingMap.values()) : [];
|
|
3711
3716
|
const firstExisting = existingValues.length === 1 ? existingValues[0] : void 0;
|
|
3712
3717
|
while (addMore) {
|
|
3718
|
+
const { getApiProviders } = await import('./api-providers.mjs');
|
|
3719
|
+
const apiProviders = getApiProviders("codex");
|
|
3720
|
+
const providerChoices = [
|
|
3721
|
+
{ name: i18n.t("api:customProvider"), value: "custom" },
|
|
3722
|
+
...apiProviders.map((p) => ({ name: p.name, value: p.id }))
|
|
3723
|
+
];
|
|
3724
|
+
const { selectedProvider: selectedProvider2 } = await inquirer.prompt([{
|
|
3725
|
+
type: "list",
|
|
3726
|
+
name: "selectedProvider",
|
|
3727
|
+
message: i18n.t("api:selectApiProvider"),
|
|
3728
|
+
choices: addNumbersToChoices(providerChoices)
|
|
3729
|
+
}]);
|
|
3730
|
+
let prefilledBaseUrl;
|
|
3731
|
+
let prefilledWireApi;
|
|
3732
|
+
let prefilledModel;
|
|
3733
|
+
if (selectedProvider2 !== "custom") {
|
|
3734
|
+
const provider = apiProviders.find((p) => p.id === selectedProvider2);
|
|
3735
|
+
if (provider?.codex) {
|
|
3736
|
+
prefilledBaseUrl = provider.codex.baseUrl;
|
|
3737
|
+
prefilledWireApi = provider.codex.wireApi;
|
|
3738
|
+
prefilledModel = provider.codex.defaultModel;
|
|
3739
|
+
console.log(ansis.gray(i18n.t("api:providerSelected", { name: provider.name })));
|
|
3740
|
+
}
|
|
3741
|
+
}
|
|
3713
3742
|
const answers = await inquirer.prompt([
|
|
3714
3743
|
{
|
|
3715
3744
|
type: "input",
|
|
3716
3745
|
name: "providerName",
|
|
3717
3746
|
message: i18n.t("codex:providerNamePrompt"),
|
|
3718
|
-
default: firstExisting?.name,
|
|
3747
|
+
default: selectedProvider2 !== "custom" ? apiProviders.find((p) => p.id === selectedProvider2)?.name : firstExisting?.name,
|
|
3719
3748
|
validate: (input) => {
|
|
3720
3749
|
const sanitized = sanitizeProviderName(input);
|
|
3721
3750
|
if (!sanitized)
|
|
@@ -3729,7 +3758,8 @@ async function configureCodexApi(options) {
|
|
|
3729
3758
|
type: "input",
|
|
3730
3759
|
name: "baseUrl",
|
|
3731
3760
|
message: i18n.t("codex:providerBaseUrlPrompt"),
|
|
3732
|
-
default: (answers2) => existingMap.get(answers2.providerId)?.baseUrl || "https://api.openai.com/v1",
|
|
3761
|
+
default: prefilledBaseUrl || ((answers2) => existingMap.get(answers2.providerId)?.baseUrl || "https://api.openai.com/v1"),
|
|
3762
|
+
when: () => selectedProvider2 === "custom",
|
|
3733
3763
|
validate: (input) => !!input || i18n.t("codex:providerBaseUrlRequired")
|
|
3734
3764
|
},
|
|
3735
3765
|
{
|
|
@@ -3740,15 +3770,29 @@ async function configureCodexApi(options) {
|
|
|
3740
3770
|
{ name: i18n.t("codex:protocolResponses"), value: "responses" },
|
|
3741
3771
|
{ name: i18n.t("codex:protocolChat"), value: "chat" }
|
|
3742
3772
|
],
|
|
3743
|
-
default: (answers2) => existingMap.get(sanitizeProviderName(answers2.providerName))?.wireApi || "responses"
|
|
3773
|
+
default: prefilledWireApi || ((answers2) => existingMap.get(sanitizeProviderName(answers2.providerName))?.wireApi || "responses"),
|
|
3774
|
+
when: () => selectedProvider2 === "custom"
|
|
3775
|
+
// Only ask if custom
|
|
3744
3776
|
},
|
|
3745
3777
|
{
|
|
3746
|
-
type: "
|
|
3778
|
+
type: "input",
|
|
3747
3779
|
name: "apiKey",
|
|
3748
|
-
message: i18n.t("
|
|
3780
|
+
message: selectedProvider2 !== "custom" ? i18n.t("api:enterProviderApiKey", { provider: apiProviders.find((p) => p.id === selectedProvider2)?.name || selectedProvider2 }) : i18n.t("codex:providerApiKeyPrompt"),
|
|
3749
3781
|
validate: (input) => !!input || i18n.t("codex:providerApiKeyRequired")
|
|
3750
3782
|
}
|
|
3751
3783
|
]);
|
|
3784
|
+
let customModel;
|
|
3785
|
+
if (selectedProvider2 === "custom") {
|
|
3786
|
+
const { model } = await inquirer.prompt([{
|
|
3787
|
+
type: "input",
|
|
3788
|
+
name: "model",
|
|
3789
|
+
message: `${i18n.t("configuration:enterCustomModel")}${i18n.t("common:emptyToSkip")}`,
|
|
3790
|
+
default: "gpt-5-codex"
|
|
3791
|
+
}]);
|
|
3792
|
+
if (model.trim()) {
|
|
3793
|
+
customModel = model.trim();
|
|
3794
|
+
}
|
|
3795
|
+
}
|
|
3752
3796
|
const providerId = sanitizeProviderName(answers.providerName);
|
|
3753
3797
|
const envKey = `${providerId.toUpperCase().replace(/-/g, "_")}_API_KEY`;
|
|
3754
3798
|
const existingProvider = existingMap.get(providerId);
|
|
@@ -3780,10 +3824,12 @@ async function configureCodexApi(options) {
|
|
|
3780
3824
|
const newProvider = {
|
|
3781
3825
|
id: providerId,
|
|
3782
3826
|
name: answers.providerName,
|
|
3783
|
-
baseUrl: answers.baseUrl,
|
|
3784
|
-
wireApi: answers.wireApi || "responses",
|
|
3827
|
+
baseUrl: selectedProvider2 === "custom" ? answers.baseUrl : prefilledBaseUrl,
|
|
3828
|
+
wireApi: selectedProvider2 === "custom" ? answers.wireApi || "responses" : prefilledWireApi,
|
|
3785
3829
|
envKey,
|
|
3786
|
-
requiresOpenaiAuth: true
|
|
3830
|
+
requiresOpenaiAuth: true,
|
|
3831
|
+
model: customModel || prefilledModel || "gpt-5-codex"
|
|
3832
|
+
// Use custom model, provider's default model, or fallback
|
|
3787
3833
|
};
|
|
3788
3834
|
providers.push(newProvider);
|
|
3789
3835
|
currentSessionProviders.set(providerId, newProvider);
|
|
@@ -4078,8 +4124,18 @@ async function switchToProvider(providerId) {
|
|
|
4078
4124
|
console.log(ansis.gray(getBackupMessage(backupPath)));
|
|
4079
4125
|
}
|
|
4080
4126
|
try {
|
|
4127
|
+
let targetModel = existingConfig.model;
|
|
4128
|
+
if (provider.model) {
|
|
4129
|
+
targetModel = provider.model;
|
|
4130
|
+
} else {
|
|
4131
|
+
const currentModel = existingConfig.model;
|
|
4132
|
+
if (currentModel !== "gpt-5" && currentModel !== "gpt-5-codex") {
|
|
4133
|
+
targetModel = "gpt-5-codex";
|
|
4134
|
+
}
|
|
4135
|
+
}
|
|
4081
4136
|
const updatedConfig = {
|
|
4082
4137
|
...existingConfig,
|
|
4138
|
+
model: targetModel,
|
|
4083
4139
|
modelProvider: providerId,
|
|
4084
4140
|
modelProviderCommented: false
|
|
4085
4141
|
// Ensure it's not commented
|
|
@@ -4147,12 +4203,16 @@ async function resolveCodeType(codeTypeParam) {
|
|
|
4147
4203
|
const validAbbreviations = Object.keys(CODE_TYPE_ABBREVIATIONS);
|
|
4148
4204
|
const validFullTypes = Object.values(CODE_TYPE_ABBREVIATIONS);
|
|
4149
4205
|
const validOptions = [...validAbbreviations, ...validFullTypes].join(", ");
|
|
4206
|
+
let defaultValue = DEFAULT_CODE_TOOL_TYPE;
|
|
4207
|
+
try {
|
|
4208
|
+
const config = await readZcfConfigAsync();
|
|
4209
|
+
if (config?.codeToolType && isValidCodeType(config.codeToolType)) {
|
|
4210
|
+
defaultValue = config.codeToolType;
|
|
4211
|
+
}
|
|
4212
|
+
} catch {
|
|
4213
|
+
}
|
|
4150
4214
|
throw new Error(
|
|
4151
|
-
i18n.t(
|
|
4152
|
-
"errors:invalidCodeType",
|
|
4153
|
-
`Invalid code type: "${codeTypeParam}". Valid options are: ${validOptions}.`,
|
|
4154
|
-
{ value: codeTypeParam, validOptions }
|
|
4155
|
-
)
|
|
4215
|
+
i18n.t("errors:invalidCodeType", { value: codeTypeParam, validOptions, defaultValue })
|
|
4156
4216
|
);
|
|
4157
4217
|
}
|
|
4158
4218
|
try {
|
|
@@ -4544,9 +4604,9 @@ async function configureApiCompletely(preselectedAuthType) {
|
|
|
4544
4604
|
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
4545
4605
|
return null;
|
|
4546
4606
|
}
|
|
4547
|
-
const keyMessage = authType === "auth_token" ? i18n.t("api:enterAuthToken")
|
|
4607
|
+
const keyMessage = authType === "auth_token" ? i18n.t("api:enterAuthToken") : i18n.t("api:enterApiKey");
|
|
4548
4608
|
const { key } = await inquirer.prompt({
|
|
4549
|
-
type: "
|
|
4609
|
+
type: "input",
|
|
4550
4610
|
name: "key",
|
|
4551
4611
|
message: keyMessage,
|
|
4552
4612
|
validate: async (value) => {
|
|
@@ -4617,9 +4677,9 @@ async function modifyApiConfigPartially(existingConfig) {
|
|
|
4617
4677
|
}
|
|
4618
4678
|
} else if (item === "key") {
|
|
4619
4679
|
const authType = currentConfig.authType || "auth_token";
|
|
4620
|
-
const keyMessage = authType === "auth_token" ? i18n.t("api:enterNewApiKey").replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.t("common:none"))
|
|
4680
|
+
const keyMessage = authType === "auth_token" ? i18n.t("api:enterNewApiKey").replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.t("common:none")) : i18n.t("api:enterNewApiKey").replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.t("common:none"));
|
|
4621
4681
|
const { key } = await inquirer.prompt({
|
|
4622
|
-
type: "
|
|
4682
|
+
type: "input",
|
|
4623
4683
|
name: "key",
|
|
4624
4684
|
message: keyMessage,
|
|
4625
4685
|
validate: async (value) => {
|
|
@@ -4708,6 +4768,7 @@ async function installClaudeCode() {
|
|
|
4708
4768
|
if (installed) {
|
|
4709
4769
|
console.log(ansis.green(`\u2714 ${i18n.t("installation:alreadyInstalled")}`));
|
|
4710
4770
|
await updateClaudeCode();
|
|
4771
|
+
await setInstallMethod("npm");
|
|
4711
4772
|
return;
|
|
4712
4773
|
}
|
|
4713
4774
|
if (isTermux()) {
|
|
@@ -4730,6 +4791,7 @@ async function installClaudeCode() {
|
|
|
4730
4791
|
try {
|
|
4731
4792
|
await exec("npm", ["install", "-g", "@anthropic-ai/claude-code"]);
|
|
4732
4793
|
console.log(`\u2714 ${i18n.t("installation:installSuccess")}`);
|
|
4794
|
+
await setInstallMethod("npm");
|
|
4733
4795
|
if (isTermux()) {
|
|
4734
4796
|
console.log(ansis.gray(`
|
|
4735
4797
|
Claude Code installed to: ${getTermuxPrefix()}/bin/claude`));
|
|
@@ -4779,6 +4841,19 @@ async function removeLocalClaudeCode() {
|
|
|
4779
4841
|
throw new Error(`${i18n.t("installation:failedToRemoveLocalInstallation")}: ${error}`);
|
|
4780
4842
|
}
|
|
4781
4843
|
}
|
|
4844
|
+
async function setInstallMethod(method = "npm") {
|
|
4845
|
+
try {
|
|
4846
|
+
const { readMcpConfig, writeMcpConfig } = await Promise.resolve().then(function () { return claudeConfig; });
|
|
4847
|
+
let config = readMcpConfig();
|
|
4848
|
+
if (!config) {
|
|
4849
|
+
config = { mcpServers: {} };
|
|
4850
|
+
}
|
|
4851
|
+
config.installMethod = method;
|
|
4852
|
+
writeMcpConfig(config);
|
|
4853
|
+
} catch (error) {
|
|
4854
|
+
console.error("Failed to set installMethod in ~/.claude.json:", error);
|
|
4855
|
+
}
|
|
4856
|
+
}
|
|
4782
4857
|
|
|
4783
4858
|
const installer = {
|
|
4784
4859
|
__proto__: null,
|
|
@@ -4786,7 +4861,8 @@ const installer = {
|
|
|
4786
4861
|
installClaudeCode: installClaudeCode,
|
|
4787
4862
|
isClaudeCodeInstalled: isClaudeCodeInstalled,
|
|
4788
4863
|
isLocalClaudeCodeInstalled: isLocalClaudeCodeInstalled,
|
|
4789
|
-
removeLocalClaudeCode: removeLocalClaudeCode
|
|
4864
|
+
removeLocalClaudeCode: removeLocalClaudeCode,
|
|
4865
|
+
setInstallMethod: setInstallMethod
|
|
4790
4866
|
};
|
|
4791
4867
|
|
|
4792
4868
|
async function chooseInstallationMethod() {
|
|
@@ -5051,7 +5127,7 @@ async function cleanupOldVersionFiles() {
|
|
|
5051
5127
|
}
|
|
5052
5128
|
}
|
|
5053
5129
|
|
|
5054
|
-
function validateSkipPromptOptions(options) {
|
|
5130
|
+
async function validateSkipPromptOptions(options) {
|
|
5055
5131
|
if (options.allLang) {
|
|
5056
5132
|
if (options.allLang === "zh-CN" || options.allLang === "en") {
|
|
5057
5133
|
options.configLang = options.allLang;
|
|
@@ -5061,6 +5137,22 @@ function validateSkipPromptOptions(options) {
|
|
|
5061
5137
|
options.aiOutputLang = options.allLang;
|
|
5062
5138
|
}
|
|
5063
5139
|
}
|
|
5140
|
+
if (options.provider) {
|
|
5141
|
+
const { getValidProviderIds, getProviderPreset } = await import('./api-providers.mjs');
|
|
5142
|
+
const validProviders = [...getValidProviderIds(), "custom"];
|
|
5143
|
+
if (!validProviders.includes(options.provider)) {
|
|
5144
|
+
throw new Error(
|
|
5145
|
+
i18n.t("errors:invalidProvider", {
|
|
5146
|
+
provider: options.provider,
|
|
5147
|
+
validProviders: validProviders.join(", ")
|
|
5148
|
+
})
|
|
5149
|
+
);
|
|
5150
|
+
}
|
|
5151
|
+
if (!options.apiType) {
|
|
5152
|
+
const preset = options.provider !== "custom" ? getProviderPreset(options.provider) : null;
|
|
5153
|
+
options.apiType = preset?.claudeCode?.authType || "api_key";
|
|
5154
|
+
}
|
|
5155
|
+
}
|
|
5064
5156
|
if (!options.configAction) {
|
|
5065
5157
|
options.configAction = "backup";
|
|
5066
5158
|
}
|
|
@@ -5173,7 +5265,7 @@ function validateSkipPromptOptions(options) {
|
|
|
5173
5265
|
}
|
|
5174
5266
|
async function init(options = {}) {
|
|
5175
5267
|
if (options.skipPrompt) {
|
|
5176
|
-
validateSkipPromptOptions(options);
|
|
5268
|
+
await validateSkipPromptOptions(options);
|
|
5177
5269
|
}
|
|
5178
5270
|
try {
|
|
5179
5271
|
const zcfConfig = readZcfConfig();
|
|
@@ -5417,6 +5509,18 @@ async function init(options = {}) {
|
|
|
5417
5509
|
if (options.apiConfigs || options.apiConfigsFile) {
|
|
5418
5510
|
await handleMultiConfigurations(options, codeToolType);
|
|
5419
5511
|
apiConfig = null;
|
|
5512
|
+
} else if (options.provider && options.apiKey) {
|
|
5513
|
+
const { getProviderPreset } = await import('./api-providers.mjs');
|
|
5514
|
+
const preset = options.provider !== "custom" ? getProviderPreset(options.provider) : null;
|
|
5515
|
+
apiConfig = {
|
|
5516
|
+
authType: preset?.claudeCode?.authType || "api_key",
|
|
5517
|
+
key: options.apiKey,
|
|
5518
|
+
url: preset?.claudeCode?.baseUrl || options.apiUrl || API_DEFAULT_URL
|
|
5519
|
+
};
|
|
5520
|
+
if (preset?.claudeCode?.defaultModels && preset.claudeCode.defaultModels.length >= 2) {
|
|
5521
|
+
options.apiModel = options.apiModel || preset.claudeCode.defaultModels[0];
|
|
5522
|
+
options.apiFastModel = options.apiFastModel || preset.claudeCode.defaultModels[1];
|
|
5523
|
+
}
|
|
5420
5524
|
} else if (options.apiType === "auth_token" && options.apiKey) {
|
|
5421
5525
|
apiConfig = {
|
|
5422
5526
|
authType: "auth_token",
|
|
@@ -5613,9 +5717,9 @@ async function init(options = {}) {
|
|
|
5613
5717
|
continue;
|
|
5614
5718
|
} else {
|
|
5615
5719
|
const response = await inquirer.prompt({
|
|
5616
|
-
type: "
|
|
5720
|
+
type: "input",
|
|
5617
5721
|
name: "apiKey",
|
|
5618
|
-
message: service.apiKeyPrompt
|
|
5722
|
+
message: service.apiKeyPrompt,
|
|
5619
5723
|
validate: (value) => !!value || i18n.t("api:keyRequired")
|
|
5620
5724
|
});
|
|
5621
5725
|
if (!response.apiKey) {
|
|
@@ -5704,7 +5808,7 @@ async function handleMultiConfigurations(options, codeToolType) {
|
|
|
5704
5808
|
throw new Error(i18n.t("multi-config:fileReadFailed", { error: error instanceof Error ? error.message : String(error) }));
|
|
5705
5809
|
}
|
|
5706
5810
|
}
|
|
5707
|
-
validateApiConfigs(configs);
|
|
5811
|
+
await validateApiConfigs(configs);
|
|
5708
5812
|
if (codeToolType === "claude-code") {
|
|
5709
5813
|
await handleClaudeCodeConfigs(configs);
|
|
5710
5814
|
} else if (codeToolType === "codex") {
|
|
@@ -5716,12 +5820,29 @@ async function handleMultiConfigurations(options, codeToolType) {
|
|
|
5716
5820
|
throw error;
|
|
5717
5821
|
}
|
|
5718
5822
|
}
|
|
5719
|
-
function validateApiConfigs(configs) {
|
|
5823
|
+
async function validateApiConfigs(configs) {
|
|
5720
5824
|
if (!Array.isArray(configs)) {
|
|
5721
5825
|
throw new TypeError(i18n.t("multi-config:mustBeArray"));
|
|
5722
5826
|
}
|
|
5827
|
+
const { getValidProviderIds } = await import('./api-providers.mjs');
|
|
5828
|
+
const validProviders = [...getValidProviderIds(), "custom"];
|
|
5723
5829
|
const names = /* @__PURE__ */ new Set();
|
|
5724
5830
|
for (const config of configs) {
|
|
5831
|
+
if (config.provider && !config.type) {
|
|
5832
|
+
config.type = "api_key";
|
|
5833
|
+
}
|
|
5834
|
+
if (config.provider && !config.name) {
|
|
5835
|
+
config.name = config.provider.toUpperCase();
|
|
5836
|
+
}
|
|
5837
|
+
if (!config.provider && !config.type) {
|
|
5838
|
+
throw new Error(i18n.t("multi-config:providerOrTypeRequired"));
|
|
5839
|
+
}
|
|
5840
|
+
if (config.provider && !validProviders.includes(config.provider)) {
|
|
5841
|
+
throw new Error(i18n.t("errors:invalidProvider", {
|
|
5842
|
+
provider: config.provider,
|
|
5843
|
+
validProviders: validProviders.join(", ")
|
|
5844
|
+
}));
|
|
5845
|
+
}
|
|
5725
5846
|
if (!config.name || typeof config.name !== "string" || config.name.trim() === "") {
|
|
5726
5847
|
throw new Error(i18n.t("multi-config:mustHaveValidName"));
|
|
5727
5848
|
}
|
|
@@ -5772,7 +5893,7 @@ async function handleCodexConfigs(configs) {
|
|
|
5772
5893
|
const { addProviderToExisting } = await import('./codex-provider-manager.mjs');
|
|
5773
5894
|
for (const config of configs) {
|
|
5774
5895
|
try {
|
|
5775
|
-
const provider = convertToCodexProvider(config);
|
|
5896
|
+
const provider = await convertToCodexProvider(config);
|
|
5776
5897
|
const result = await addProviderToExisting(provider, config.key || "");
|
|
5777
5898
|
if (!result.success) {
|
|
5778
5899
|
throw new Error(i18n.t("multi-config:providerAddFailed", { name: config.name, error: result.error }));
|
|
@@ -5795,23 +5916,54 @@ async function handleCodexConfigs(configs) {
|
|
|
5795
5916
|
}
|
|
5796
5917
|
async function convertToClaudeCodeProfile(config) {
|
|
5797
5918
|
const { ClaudeCodeConfigManager } = await import('./claude-code-config-manager.mjs');
|
|
5919
|
+
let baseUrl = config.url;
|
|
5920
|
+
let primaryModel = config.primaryModel;
|
|
5921
|
+
let fastModel = config.fastModel;
|
|
5922
|
+
let authType = config.type || "api_key";
|
|
5923
|
+
if (config.provider && config.provider !== "custom") {
|
|
5924
|
+
const { getProviderPreset } = await import('./api-providers.mjs');
|
|
5925
|
+
const preset = getProviderPreset(config.provider);
|
|
5926
|
+
if (preset?.claudeCode) {
|
|
5927
|
+
baseUrl = baseUrl || preset.claudeCode.baseUrl;
|
|
5928
|
+
authType = preset.claudeCode.authType;
|
|
5929
|
+
if (preset.claudeCode.defaultModels && preset.claudeCode.defaultModels.length >= 2) {
|
|
5930
|
+
primaryModel = primaryModel || preset.claudeCode.defaultModels[0];
|
|
5931
|
+
fastModel = fastModel || preset.claudeCode.defaultModels[1];
|
|
5932
|
+
}
|
|
5933
|
+
}
|
|
5934
|
+
}
|
|
5798
5935
|
const profile = {
|
|
5799
5936
|
name: config.name,
|
|
5800
|
-
authType
|
|
5937
|
+
authType,
|
|
5801
5938
|
apiKey: config.key,
|
|
5802
|
-
baseUrl
|
|
5939
|
+
baseUrl,
|
|
5940
|
+
primaryModel,
|
|
5941
|
+
fastModel,
|
|
5803
5942
|
id: ClaudeCodeConfigManager.generateProfileId(config.name)
|
|
5804
5943
|
};
|
|
5805
5944
|
return profile;
|
|
5806
5945
|
}
|
|
5807
|
-
function convertToCodexProvider(config) {
|
|
5946
|
+
async function convertToCodexProvider(config) {
|
|
5947
|
+
let baseUrl = config.url || API_DEFAULT_URL;
|
|
5948
|
+
let model = config.primaryModel || "gpt-5-codex";
|
|
5949
|
+
let wireApi = "chat";
|
|
5950
|
+
if (config.provider && config.provider !== "custom") {
|
|
5951
|
+
const { getProviderPreset } = await import('./api-providers.mjs');
|
|
5952
|
+
const preset = getProviderPreset(config.provider);
|
|
5953
|
+
if (preset?.codex) {
|
|
5954
|
+
baseUrl = config.url || preset.codex.baseUrl;
|
|
5955
|
+
model = config.primaryModel || preset.codex.defaultModel || model;
|
|
5956
|
+
wireApi = preset.codex.wireApi;
|
|
5957
|
+
}
|
|
5958
|
+
}
|
|
5808
5959
|
return {
|
|
5809
5960
|
id: config.name.toLowerCase().replace(/[^a-z0-9]/g, "-"),
|
|
5810
5961
|
name: config.name,
|
|
5811
|
-
baseUrl
|
|
5812
|
-
wireApi
|
|
5962
|
+
baseUrl,
|
|
5963
|
+
wireApi,
|
|
5813
5964
|
envKey: API_ENV_KEY,
|
|
5814
|
-
requiresOpenaiAuth: false
|
|
5965
|
+
requiresOpenaiAuth: false,
|
|
5966
|
+
model
|
|
5815
5967
|
};
|
|
5816
5968
|
}
|
|
5817
5969
|
|
|
@@ -5893,4 +6045,4 @@ async function openSettingsJson() {
|
|
|
5893
6045
|
}
|
|
5894
6046
|
}
|
|
5895
6047
|
|
|
5896
|
-
export { isClaudeCodeInstalled as $, API_DEFAULT_URL as A, mergeMcpServers as B, CLAUDE_DIR as C, DEFAULT_CODE_TOOL_TYPE as D, buildMcpServerConfig as E, fixWindowsMcpConfig as F, addCompletedOnboarding as G, ensureApiKeyApproved as H, removeApiKeyFromRejected as I, manageApiKeyApproval as J, setPrimaryApiKey as K, LEGACY_ZCF_CONFIG_FILES as L, ensureClaudeDir as M, backupExistingConfig as N, copyConfigFiles as O, configureApi as P, mergeConfigs as Q, updateCustomModel as R, SETTINGS_FILE as S, updateDefaultModel as T, mergeSettingsFile as U, getExistingModelConfig as V, getExistingApiConfig as W, applyAiLanguageDirective as X, switchToOfficialLogin$1 as Y, ZCF_CONFIG_DIR as Z, promptApiConfigurationAction as _, commandExists as a,
|
|
6048
|
+
export { isClaudeCodeInstalled as $, API_DEFAULT_URL as A, mergeMcpServers as B, CLAUDE_DIR as C, DEFAULT_CODE_TOOL_TYPE as D, buildMcpServerConfig as E, fixWindowsMcpConfig as F, addCompletedOnboarding as G, ensureApiKeyApproved as H, removeApiKeyFromRejected as I, manageApiKeyApproval as J, setPrimaryApiKey as K, LEGACY_ZCF_CONFIG_FILES as L, ensureClaudeDir as M, backupExistingConfig as N, copyConfigFiles as O, configureApi as P, mergeConfigs as Q, updateCustomModel as R, SETTINGS_FILE as S, updateDefaultModel as T, mergeSettingsFile as U, getExistingModelConfig as V, getExistingApiConfig as W, applyAiLanguageDirective as X, switchToOfficialLogin$1 as Y, ZCF_CONFIG_DIR as Z, promptApiConfigurationAction as _, commandExists as a, index as a$, installClaudeCode as a0, isLocalClaudeCodeInstalled as a1, getInstallationStatus as a2, removeLocalClaudeCode as a3, setInstallMethod as a4, ensureI18nInitialized as a5, i18n as a6, addNumbersToChoices as a7, validateApiKey as a8, ensureDir as a9, handleGeneralError as aA, COMETIX_COMMAND_NAME as aB, COMETIX_COMMANDS as aC, installCometixLine as aD, checkAndUpdateTools as aE, runCodexUpdate as aF, resolveCodeType as aG, writeJsonConfig as aH, displayBanner as aI, version as aJ, resolveAiOutputLanguage as aK, updatePromptOnly as aL, selectAndInstallWorkflows as aM, checkClaudeCodeVersionAndPrompt as aN, displayBannerWithInfo as aO, runCodexUninstall as aP, configureCodexMcp as aQ, configureCodexApi as aR, runCodexWorkflowImportWithLanguageSelection as aS, runCodexFullInit as aT, switchCodexProvider as aU, listCodexProviders as aV, switchToOfficialLogin as aW, switchToProvider as aX, readZcfConfigAsync as aY, initI18n as aZ, selectScriptLanguage as a_, readDefaultTomlConfig as aa, createDefaultTomlConfig as ab, exists as ac, readJsonConfig as ad, writeTomlConfig as ae, copyFile as af, detectConfigManagementMode as ag, readCodexConfig as ah, backupCodexComplete as ai, writeCodexConfig as aj, writeAuthFile as ak, updateZcfConfig as al, changeLanguage as am, readZcfConfig as an, configureOutputStyle as ao, isWindows as ap, selectMcpServices as aq, getMcpServices as ar, isCcrInstalled as as, installCcr as at, setupCcrConfiguration as au, modifyApiConfigPartially as av, formatApiKeyDisplay as aw, readCcrConfig as ax, configureCcrFeature as ay, handleExitPromptError as az, importRecommendedEnv as b, fsOperations as b0, jsonConfig as b1, claudeConfig as b2, config$1 as b3, config as b4, prompts as b5, codex as b6, 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, ZCF_CONFIG_FILE as j, CODE_TOOL_TYPES as k, CODE_TOOL_BANNERS as l, mergeAndCleanPermissions as m, CODE_TOOL_ALIASES as n, openSettingsJson as o, isCodeToolType as p, API_ENV_KEY as q, resolveCodeToolType as r, SUPPORTED_LANGS as s, LANG_LABELS as t, AI_OUTPUT_LANGUAGES as u, getAiOutputLanguageLabel as v, getMcpConfigPath as w, readMcpConfig as x, writeMcpConfig as y, backupMcpConfig as z };
|