zcf 3.2.3 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +102 -14
  2. package/dist/chunks/api-providers.mjs +76 -0
  3. package/dist/chunks/claude-code-config-manager.mjs +21 -7
  4. package/dist/chunks/claude-code-incremental-manager.mjs +210 -14
  5. package/dist/chunks/codex-config-switch.mjs +197 -12
  6. package/dist/chunks/codex-provider-manager.mjs +20 -9
  7. package/dist/chunks/codex-uninstaller.mjs +19 -24
  8. package/dist/chunks/commands.mjs +1 -1
  9. package/dist/chunks/features.mjs +637 -0
  10. package/dist/chunks/simple-config.mjs +182 -29
  11. package/dist/cli.mjs +13 -613
  12. package/dist/i18n/locales/en/api.json +6 -1
  13. package/dist/i18n/locales/en/codex.json +7 -0
  14. package/dist/i18n/locales/en/errors.json +1 -0
  15. package/dist/i18n/locales/en/multi-config.json +8 -1
  16. package/dist/i18n/locales/zh-CN/api.json +6 -1
  17. package/dist/i18n/locales/zh-CN/codex.json +7 -0
  18. package/dist/i18n/locales/zh-CN/errors.json +1 -0
  19. package/dist/i18n/locales/zh-CN/multi-config.json +8 -1
  20. package/dist/index.d.mts +13 -1
  21. package/dist/index.d.ts +13 -1
  22. package/dist/index.mjs +1 -1
  23. package/package.json +1 -1
  24. package/templates/CLAUDE.md +191 -0
  25. package/templates/claude-code/CLAUDE.md +1 -0
  26. package/templates/claude-code/en/output-styles/engineer-professional.md +2 -1
  27. package/templates/claude-code/en/output-styles/laowang-engineer.md +1 -0
  28. package/templates/claude-code/en/output-styles/nekomata-engineer.md +1 -0
  29. package/templates/claude-code/en/output-styles/ojousama-engineer.md +1 -0
  30. package/templates/claude-code/zh-CN/output-styles/engineer-professional.md +2 -1
  31. package/templates/claude-code/zh-CN/output-styles/laowang-engineer.md +1 -0
  32. package/templates/claude-code/zh-CN/output-styles/nekomata-engineer.md +1 -0
  33. package/templates/claude-code/zh-CN/output-styles/ojousama-engineer.md +1 -0
  34. package/templates/codex/en/system-prompt/engineer-professional.md +2 -1
  35. package/templates/codex/en/system-prompt/laowang-engineer.md +1 -0
  36. package/templates/codex/en/system-prompt/nekomata-engineer.md +1 -0
  37. package/templates/codex/en/system-prompt/ojousama-engineer.md +1 -0
  38. package/templates/codex/zh-CN/system-prompt/engineer-professional.md +2 -1
  39. package/templates/codex/zh-CN/system-prompt/laowang-engineer.md +1 -0
  40. package/templates/codex/zh-CN/system-prompt/nekomata-engineer.md +1 -0
  41. 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.2.3";
19
+ const version = "3.3.1";
20
20
  const homepage = "https://github.com/UfoMiao/zcf";
21
21
 
22
22
  const i18n = i18next.createInstance();
@@ -381,6 +381,11 @@ const SETTINGS_FILE = join(CLAUDE_DIR, "settings.json");
381
381
  const CLAUDE_MD_FILE = join(CLAUDE_DIR, "CLAUDE.md");
382
382
  const ClAUDE_CONFIG_FILE = join(homedir(), ".claude.json");
383
383
  const CLAUDE_VSC_CONFIG_FILE = join(CLAUDE_DIR, "config.json");
384
+ const CODEX_DIR = join(homedir(), ".codex");
385
+ const CODEX_CONFIG_FILE = join(CODEX_DIR, "config.toml");
386
+ const CODEX_AUTH_FILE = join(CODEX_DIR, "auth.json");
387
+ const CODEX_AGENTS_FILE = join(CODEX_DIR, "AGENTS.md");
388
+ const CODEX_PROMPTS_DIR = join(CODEX_DIR, "prompts");
384
389
  const ZCF_CONFIG_DIR = join(homedir(), ".ufomiao", "zcf");
385
390
  const ZCF_CONFIG_FILE = join(ZCF_CONFIG_DIR, "config.toml");
386
391
  const LEGACY_ZCF_CONFIG_FILES = [
@@ -442,6 +447,11 @@ const constants = {
442
447
  CLAUDE_DIR: CLAUDE_DIR,
443
448
  CLAUDE_MD_FILE: CLAUDE_MD_FILE,
444
449
  CLAUDE_VSC_CONFIG_FILE: CLAUDE_VSC_CONFIG_FILE,
450
+ CODEX_AGENTS_FILE: CODEX_AGENTS_FILE,
451
+ CODEX_AUTH_FILE: CODEX_AUTH_FILE,
452
+ CODEX_CONFIG_FILE: CODEX_CONFIG_FILE,
453
+ CODEX_DIR: CODEX_DIR,
454
+ CODEX_PROMPTS_DIR: CODEX_PROMPTS_DIR,
445
455
  CODE_TOOL_ALIASES: CODE_TOOL_ALIASES,
446
456
  CODE_TOOL_BANNERS: CODE_TOOL_BANNERS,
447
457
  CODE_TOOL_TYPES: CODE_TOOL_TYPES,
@@ -2915,11 +2925,6 @@ async function configureCodexMcp(options) {
2915
2925
  console.log(ansis.green(i18n.t("codex:mcpConfigured")));
2916
2926
  }
2917
2927
 
2918
- const CODEX_DIR = join(homedir(), ".codex");
2919
- const CODEX_CONFIG_FILE = join(CODEX_DIR, "config.toml");
2920
- const CODEX_AUTH_FILE = join(CODEX_DIR, "auth.json");
2921
- const CODEX_AGENTS_FILE = join(CODEX_DIR, "AGENTS.md");
2922
- const CODEX_PROMPTS_DIR = join(CODEX_DIR, "prompts");
2923
2928
  function getRootDir$1() {
2924
2929
  const currentFilePath = fileURLToPath(import.meta.url);
2925
2930
  let dir = dirname(currentFilePath);
@@ -3032,7 +3037,7 @@ function sanitizeProviderName(input) {
3032
3037
  const cleaned = input.trim();
3033
3038
  if (!cleaned)
3034
3039
  return "";
3035
- return cleaned.replace(/[^\w.-]/g, "");
3040
+ return cleaned.toLowerCase().replace(/\./g, "-").replace(/\s+/g, "-").replace(/[^a-z0-9\-]/g, "");
3036
3041
  }
3037
3042
  function parseCodexConfig(content) {
3038
3043
  if (!content.trim()) {
@@ -3061,7 +3066,9 @@ function parseCodexConfig(content) {
3061
3066
  baseUrl: provider.base_url || "",
3062
3067
  wireApi: provider.wire_api || "responses",
3063
3068
  envKey: provider.env_key || "OPENAI_API_KEY",
3064
- requiresOpenaiAuth: provider.requires_openai_auth !== false
3069
+ requiresOpenaiAuth: provider.requires_openai_auth !== false,
3070
+ model: provider.model || void 0
3071
+ // Parse model field from provider
3065
3072
  });
3066
3073
  }
3067
3074
  }
@@ -3211,7 +3218,7 @@ function renderCodexConfig(data) {
3211
3218
  return false;
3212
3219
  if (/^#?\s*model_provider\s*=/.test(l))
3213
3220
  return false;
3214
- if (/^\s*model\s*=/.test(l))
3221
+ if (/^\s*model\s*=/.test(l) && !l.includes("["))
3215
3222
  return false;
3216
3223
  return true;
3217
3224
  });
@@ -3231,6 +3238,9 @@ function renderCodexConfig(data) {
3231
3238
  lines.push(`wire_api = "${provider.wireApi}"`);
3232
3239
  lines.push(`env_key = "${provider.envKey}"`);
3233
3240
  lines.push(`requires_openai_auth = ${provider.requiresOpenaiAuth}`);
3241
+ if (provider.model) {
3242
+ lines.push(`model = "${provider.model}"`);
3243
+ }
3234
3244
  }
3235
3245
  }
3236
3246
  if (data.mcpServices.length > 0) {
@@ -3710,12 +3720,36 @@ async function configureCodexApi(options) {
3710
3720
  const existingValues = existingMap.size ? Array.from(existingMap.values()) : [];
3711
3721
  const firstExisting = existingValues.length === 1 ? existingValues[0] : void 0;
3712
3722
  while (addMore) {
3723
+ const { getApiProviders } = await import('./api-providers.mjs');
3724
+ const apiProviders = getApiProviders("codex");
3725
+ const providerChoices = [
3726
+ { name: i18n.t("api:customProvider"), value: "custom" },
3727
+ ...apiProviders.map((p) => ({ name: p.name, value: p.id }))
3728
+ ];
3729
+ const { selectedProvider: selectedProvider2 } = await inquirer.prompt([{
3730
+ type: "list",
3731
+ name: "selectedProvider",
3732
+ message: i18n.t("api:selectApiProvider"),
3733
+ choices: addNumbersToChoices(providerChoices)
3734
+ }]);
3735
+ let prefilledBaseUrl;
3736
+ let prefilledWireApi;
3737
+ let prefilledModel;
3738
+ if (selectedProvider2 !== "custom") {
3739
+ const provider = apiProviders.find((p) => p.id === selectedProvider2);
3740
+ if (provider?.codex) {
3741
+ prefilledBaseUrl = provider.codex.baseUrl;
3742
+ prefilledWireApi = provider.codex.wireApi;
3743
+ prefilledModel = provider.codex.defaultModel;
3744
+ console.log(ansis.gray(i18n.t("api:providerSelected", { name: provider.name })));
3745
+ }
3746
+ }
3713
3747
  const answers = await inquirer.prompt([
3714
3748
  {
3715
3749
  type: "input",
3716
3750
  name: "providerName",
3717
3751
  message: i18n.t("codex:providerNamePrompt"),
3718
- default: firstExisting?.name,
3752
+ default: selectedProvider2 !== "custom" ? apiProviders.find((p) => p.id === selectedProvider2)?.name : firstExisting?.name,
3719
3753
  validate: (input) => {
3720
3754
  const sanitized = sanitizeProviderName(input);
3721
3755
  if (!sanitized)
@@ -3729,7 +3763,8 @@ async function configureCodexApi(options) {
3729
3763
  type: "input",
3730
3764
  name: "baseUrl",
3731
3765
  message: i18n.t("codex:providerBaseUrlPrompt"),
3732
- default: (answers2) => existingMap.get(answers2.providerId)?.baseUrl || "https://api.openai.com/v1",
3766
+ default: prefilledBaseUrl || ((answers2) => existingMap.get(answers2.providerId)?.baseUrl || "https://api.openai.com/v1"),
3767
+ when: () => selectedProvider2 === "custom",
3733
3768
  validate: (input) => !!input || i18n.t("codex:providerBaseUrlRequired")
3734
3769
  },
3735
3770
  {
@@ -3740,15 +3775,29 @@ async function configureCodexApi(options) {
3740
3775
  { name: i18n.t("codex:protocolResponses"), value: "responses" },
3741
3776
  { name: i18n.t("codex:protocolChat"), value: "chat" }
3742
3777
  ],
3743
- default: (answers2) => existingMap.get(sanitizeProviderName(answers2.providerName))?.wireApi || "responses"
3778
+ default: prefilledWireApi || ((answers2) => existingMap.get(sanitizeProviderName(answers2.providerName))?.wireApi || "responses"),
3779
+ when: () => selectedProvider2 === "custom"
3780
+ // Only ask if custom
3744
3781
  },
3745
3782
  {
3746
3783
  type: "input",
3747
3784
  name: "apiKey",
3748
- message: i18n.t("codex:providerApiKeyPrompt"),
3785
+ message: selectedProvider2 !== "custom" ? i18n.t("api:enterProviderApiKey", { provider: apiProviders.find((p) => p.id === selectedProvider2)?.name || selectedProvider2 }) : i18n.t("codex:providerApiKeyPrompt"),
3749
3786
  validate: (input) => !!input || i18n.t("codex:providerApiKeyRequired")
3750
3787
  }
3751
3788
  ]);
3789
+ let customModel;
3790
+ if (selectedProvider2 === "custom") {
3791
+ const { model } = await inquirer.prompt([{
3792
+ type: "input",
3793
+ name: "model",
3794
+ message: `${i18n.t("configuration:enterCustomModel")}${i18n.t("common:emptyToSkip")}`,
3795
+ default: "gpt-5-codex"
3796
+ }]);
3797
+ if (model.trim()) {
3798
+ customModel = model.trim();
3799
+ }
3800
+ }
3752
3801
  const providerId = sanitizeProviderName(answers.providerName);
3753
3802
  const envKey = `${providerId.toUpperCase().replace(/-/g, "_")}_API_KEY`;
3754
3803
  const existingProvider = existingMap.get(providerId);
@@ -3780,10 +3829,12 @@ async function configureCodexApi(options) {
3780
3829
  const newProvider = {
3781
3830
  id: providerId,
3782
3831
  name: answers.providerName,
3783
- baseUrl: answers.baseUrl,
3784
- wireApi: answers.wireApi || "responses",
3832
+ baseUrl: selectedProvider2 === "custom" ? answers.baseUrl : prefilledBaseUrl,
3833
+ wireApi: selectedProvider2 === "custom" ? answers.wireApi || "responses" : prefilledWireApi,
3785
3834
  envKey,
3786
- requiresOpenaiAuth: true
3835
+ requiresOpenaiAuth: true,
3836
+ model: customModel || prefilledModel || "gpt-5-codex"
3837
+ // Use custom model, provider's default model, or fallback
3787
3838
  };
3788
3839
  providers.push(newProvider);
3789
3840
  currentSessionProviders.set(providerId, newProvider);
@@ -4078,8 +4129,18 @@ async function switchToProvider(providerId) {
4078
4129
  console.log(ansis.gray(getBackupMessage(backupPath)));
4079
4130
  }
4080
4131
  try {
4132
+ let targetModel = existingConfig.model;
4133
+ if (provider.model) {
4134
+ targetModel = provider.model;
4135
+ } else {
4136
+ const currentModel = existingConfig.model;
4137
+ if (currentModel !== "gpt-5" && currentModel !== "gpt-5-codex") {
4138
+ targetModel = "gpt-5-codex";
4139
+ }
4140
+ }
4081
4141
  const updatedConfig = {
4082
4142
  ...existingConfig,
4143
+ model: targetModel,
4083
4144
  modelProvider: providerId,
4084
4145
  modelProviderCommented: false
4085
4146
  // Ensure it's not commented
@@ -4712,6 +4773,7 @@ async function installClaudeCode() {
4712
4773
  if (installed) {
4713
4774
  console.log(ansis.green(`\u2714 ${i18n.t("installation:alreadyInstalled")}`));
4714
4775
  await updateClaudeCode();
4776
+ await setInstallMethod("npm");
4715
4777
  return;
4716
4778
  }
4717
4779
  if (isTermux()) {
@@ -4734,6 +4796,7 @@ async function installClaudeCode() {
4734
4796
  try {
4735
4797
  await exec("npm", ["install", "-g", "@anthropic-ai/claude-code"]);
4736
4798
  console.log(`\u2714 ${i18n.t("installation:installSuccess")}`);
4799
+ await setInstallMethod("npm");
4737
4800
  if (isTermux()) {
4738
4801
  console.log(ansis.gray(`
4739
4802
  Claude Code installed to: ${getTermuxPrefix()}/bin/claude`));
@@ -4783,6 +4846,19 @@ async function removeLocalClaudeCode() {
4783
4846
  throw new Error(`${i18n.t("installation:failedToRemoveLocalInstallation")}: ${error}`);
4784
4847
  }
4785
4848
  }
4849
+ async function setInstallMethod(method = "npm") {
4850
+ try {
4851
+ const { readMcpConfig, writeMcpConfig } = await Promise.resolve().then(function () { return claudeConfig; });
4852
+ let config = readMcpConfig();
4853
+ if (!config) {
4854
+ config = { mcpServers: {} };
4855
+ }
4856
+ config.installMethod = method;
4857
+ writeMcpConfig(config);
4858
+ } catch (error) {
4859
+ console.error("Failed to set installMethod in ~/.claude.json:", error);
4860
+ }
4861
+ }
4786
4862
 
4787
4863
  const installer = {
4788
4864
  __proto__: null,
@@ -4790,7 +4866,8 @@ const installer = {
4790
4866
  installClaudeCode: installClaudeCode,
4791
4867
  isClaudeCodeInstalled: isClaudeCodeInstalled,
4792
4868
  isLocalClaudeCodeInstalled: isLocalClaudeCodeInstalled,
4793
- removeLocalClaudeCode: removeLocalClaudeCode
4869
+ removeLocalClaudeCode: removeLocalClaudeCode,
4870
+ setInstallMethod: setInstallMethod
4794
4871
  };
4795
4872
 
4796
4873
  async function chooseInstallationMethod() {
@@ -5055,7 +5132,7 @@ async function cleanupOldVersionFiles() {
5055
5132
  }
5056
5133
  }
5057
5134
 
5058
- function validateSkipPromptOptions(options) {
5135
+ async function validateSkipPromptOptions(options) {
5059
5136
  if (options.allLang) {
5060
5137
  if (options.allLang === "zh-CN" || options.allLang === "en") {
5061
5138
  options.configLang = options.allLang;
@@ -5065,6 +5142,22 @@ function validateSkipPromptOptions(options) {
5065
5142
  options.aiOutputLang = options.allLang;
5066
5143
  }
5067
5144
  }
5145
+ if (options.provider) {
5146
+ const { getValidProviderIds, getProviderPreset } = await import('./api-providers.mjs');
5147
+ const validProviders = [...getValidProviderIds(), "custom"];
5148
+ if (!validProviders.includes(options.provider)) {
5149
+ throw new Error(
5150
+ i18n.t("errors:invalidProvider", {
5151
+ provider: options.provider,
5152
+ validProviders: validProviders.join(", ")
5153
+ })
5154
+ );
5155
+ }
5156
+ if (!options.apiType) {
5157
+ const preset = options.provider !== "custom" ? getProviderPreset(options.provider) : null;
5158
+ options.apiType = preset?.claudeCode?.authType || "api_key";
5159
+ }
5160
+ }
5068
5161
  if (!options.configAction) {
5069
5162
  options.configAction = "backup";
5070
5163
  }
@@ -5177,7 +5270,7 @@ function validateSkipPromptOptions(options) {
5177
5270
  }
5178
5271
  async function init(options = {}) {
5179
5272
  if (options.skipPrompt) {
5180
- validateSkipPromptOptions(options);
5273
+ await validateSkipPromptOptions(options);
5181
5274
  }
5182
5275
  try {
5183
5276
  const zcfConfig = readZcfConfig();
@@ -5421,6 +5514,18 @@ async function init(options = {}) {
5421
5514
  if (options.apiConfigs || options.apiConfigsFile) {
5422
5515
  await handleMultiConfigurations(options, codeToolType);
5423
5516
  apiConfig = null;
5517
+ } else if (options.provider && options.apiKey) {
5518
+ const { getProviderPreset } = await import('./api-providers.mjs');
5519
+ const preset = options.provider !== "custom" ? getProviderPreset(options.provider) : null;
5520
+ apiConfig = {
5521
+ authType: preset?.claudeCode?.authType || "api_key",
5522
+ key: options.apiKey,
5523
+ url: preset?.claudeCode?.baseUrl || options.apiUrl || API_DEFAULT_URL
5524
+ };
5525
+ if (preset?.claudeCode?.defaultModels && preset.claudeCode.defaultModels.length >= 2) {
5526
+ options.apiModel = options.apiModel || preset.claudeCode.defaultModels[0];
5527
+ options.apiFastModel = options.apiFastModel || preset.claudeCode.defaultModels[1];
5528
+ }
5424
5529
  } else if (options.apiType === "auth_token" && options.apiKey) {
5425
5530
  apiConfig = {
5426
5531
  authType: "auth_token",
@@ -5708,7 +5813,7 @@ async function handleMultiConfigurations(options, codeToolType) {
5708
5813
  throw new Error(i18n.t("multi-config:fileReadFailed", { error: error instanceof Error ? error.message : String(error) }));
5709
5814
  }
5710
5815
  }
5711
- validateApiConfigs(configs);
5816
+ await validateApiConfigs(configs);
5712
5817
  if (codeToolType === "claude-code") {
5713
5818
  await handleClaudeCodeConfigs(configs);
5714
5819
  } else if (codeToolType === "codex") {
@@ -5720,12 +5825,29 @@ async function handleMultiConfigurations(options, codeToolType) {
5720
5825
  throw error;
5721
5826
  }
5722
5827
  }
5723
- function validateApiConfigs(configs) {
5828
+ async function validateApiConfigs(configs) {
5724
5829
  if (!Array.isArray(configs)) {
5725
5830
  throw new TypeError(i18n.t("multi-config:mustBeArray"));
5726
5831
  }
5832
+ const { getValidProviderIds } = await import('./api-providers.mjs');
5833
+ const validProviders = [...getValidProviderIds(), "custom"];
5727
5834
  const names = /* @__PURE__ */ new Set();
5728
5835
  for (const config of configs) {
5836
+ if (config.provider && !config.type) {
5837
+ config.type = "api_key";
5838
+ }
5839
+ if (config.provider && !config.name) {
5840
+ config.name = config.provider.toUpperCase();
5841
+ }
5842
+ if (!config.provider && !config.type) {
5843
+ throw new Error(i18n.t("multi-config:providerOrTypeRequired"));
5844
+ }
5845
+ if (config.provider && !validProviders.includes(config.provider)) {
5846
+ throw new Error(i18n.t("errors:invalidProvider", {
5847
+ provider: config.provider,
5848
+ validProviders: validProviders.join(", ")
5849
+ }));
5850
+ }
5729
5851
  if (!config.name || typeof config.name !== "string" || config.name.trim() === "") {
5730
5852
  throw new Error(i18n.t("multi-config:mustHaveValidName"));
5731
5853
  }
@@ -5776,7 +5898,7 @@ async function handleCodexConfigs(configs) {
5776
5898
  const { addProviderToExisting } = await import('./codex-provider-manager.mjs');
5777
5899
  for (const config of configs) {
5778
5900
  try {
5779
- const provider = convertToCodexProvider(config);
5901
+ const provider = await convertToCodexProvider(config);
5780
5902
  const result = await addProviderToExisting(provider, config.key || "");
5781
5903
  if (!result.success) {
5782
5904
  throw new Error(i18n.t("multi-config:providerAddFailed", { name: config.name, error: result.error }));
@@ -5799,23 +5921,54 @@ async function handleCodexConfigs(configs) {
5799
5921
  }
5800
5922
  async function convertToClaudeCodeProfile(config) {
5801
5923
  const { ClaudeCodeConfigManager } = await import('./claude-code-config-manager.mjs');
5924
+ let baseUrl = config.url;
5925
+ let primaryModel = config.primaryModel;
5926
+ let fastModel = config.fastModel;
5927
+ let authType = config.type || "api_key";
5928
+ if (config.provider && config.provider !== "custom") {
5929
+ const { getProviderPreset } = await import('./api-providers.mjs');
5930
+ const preset = getProviderPreset(config.provider);
5931
+ if (preset?.claudeCode) {
5932
+ baseUrl = baseUrl || preset.claudeCode.baseUrl;
5933
+ authType = preset.claudeCode.authType;
5934
+ if (preset.claudeCode.defaultModels && preset.claudeCode.defaultModels.length >= 2) {
5935
+ primaryModel = primaryModel || preset.claudeCode.defaultModels[0];
5936
+ fastModel = fastModel || preset.claudeCode.defaultModels[1];
5937
+ }
5938
+ }
5939
+ }
5802
5940
  const profile = {
5803
5941
  name: config.name,
5804
- authType: config.type,
5942
+ authType,
5805
5943
  apiKey: config.key,
5806
- baseUrl: config.url,
5944
+ baseUrl,
5945
+ primaryModel,
5946
+ fastModel,
5807
5947
  id: ClaudeCodeConfigManager.generateProfileId(config.name)
5808
5948
  };
5809
5949
  return profile;
5810
5950
  }
5811
- function convertToCodexProvider(config) {
5951
+ async function convertToCodexProvider(config) {
5952
+ let baseUrl = config.url || API_DEFAULT_URL;
5953
+ let model = config.primaryModel || "gpt-5-codex";
5954
+ let wireApi = "chat";
5955
+ if (config.provider && config.provider !== "custom") {
5956
+ const { getProviderPreset } = await import('./api-providers.mjs');
5957
+ const preset = getProviderPreset(config.provider);
5958
+ if (preset?.codex) {
5959
+ baseUrl = config.url || preset.codex.baseUrl;
5960
+ model = config.primaryModel || preset.codex.defaultModel || model;
5961
+ wireApi = preset.codex.wireApi;
5962
+ }
5963
+ }
5812
5964
  return {
5813
5965
  id: config.name.toLowerCase().replace(/[^a-z0-9]/g, "-"),
5814
5966
  name: config.name,
5815
- baseUrl: config.url || API_DEFAULT_URL,
5816
- wireApi: "chat",
5967
+ baseUrl,
5968
+ wireApi,
5817
5969
  envKey: API_ENV_KEY,
5818
- requiresOpenaiAuth: false
5970
+ requiresOpenaiAuth: false,
5971
+ model
5819
5972
  };
5820
5973
  }
5821
5974
 
@@ -5897,4 +6050,4 @@ async function openSettingsJson() {
5897
6050
  }
5898
6051
  }
5899
6052
 
5900
- 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, fsOperations as a$, installClaudeCode as a0, isLocalClaudeCodeInstalled as a1, getInstallationStatus as a2, removeLocalClaudeCode as a3, ensureI18nInitialized as a4, i18n as a5, addNumbersToChoices as a6, validateApiKey as a7, ensureDir as a8, readDefaultTomlConfig as a9, COMETIX_COMMAND_NAME as aA, COMETIX_COMMANDS as aB, installCometixLine as aC, checkAndUpdateTools as aD, runCodexUpdate as aE, resolveCodeType as aF, writeJsonConfig as aG, displayBanner as aH, version as aI, resolveAiOutputLanguage as aJ, updatePromptOnly as aK, selectAndInstallWorkflows as aL, checkClaudeCodeVersionAndPrompt as aM, displayBannerWithInfo as aN, runCodexUninstall as aO, configureCodexMcp as aP, configureCodexApi as aQ, runCodexWorkflowImportWithLanguageSelection as aR, runCodexFullInit as aS, switchCodexProvider as aT, listCodexProviders as aU, switchToOfficialLogin as aV, switchToProvider as aW, readZcfConfigAsync as aX, initI18n as aY, selectScriptLanguage as aZ, index as a_, createDefaultTomlConfig as aa, exists as ab, readJsonConfig as ac, writeTomlConfig as ad, copyFile as ae, detectConfigManagementMode as af, readCodexConfig as ag, backupCodexComplete as ah, writeCodexConfig as ai, writeAuthFile as aj, readCcrConfig as ak, isCcrInstalled as al, installCcr as am, configureCcrFeature as an, handleExitPromptError as ao, handleGeneralError as ap, updateZcfConfig as aq, changeLanguage as ar, readZcfConfig as as, configureOutputStyle as at, isWindows as au, selectMcpServices as av, getMcpServices as aw, setupCcrConfiguration as ax, modifyApiConfigPartially as ay, formatApiKeyDisplay as az, importRecommendedEnv as b, jsonConfig as b0, claudeConfig as b1, config$1 as b2, config as b3, prompts as b4, codex as b5, 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 };
6053
+ 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, switchToOfficialLogin as a$, getExistingApiConfig as a0, applyAiLanguageDirective as a1, switchToOfficialLogin$1 as a2, promptApiConfigurationAction as a3, isClaudeCodeInstalled as a4, installClaudeCode as a5, isLocalClaudeCodeInstalled as a6, getInstallationStatus as a7, removeLocalClaudeCode as a8, setInstallMethod as a9, modifyApiConfigPartially as aA, formatApiKeyDisplay as aB, readCcrConfig as aC, configureCcrFeature as aD, handleExitPromptError as aE, handleGeneralError as aF, COMETIX_COMMAND_NAME as aG, COMETIX_COMMANDS as aH, installCometixLine as aI, checkAndUpdateTools as aJ, runCodexUpdate as aK, resolveCodeType as aL, writeJsonConfig as aM, displayBanner as aN, version as aO, resolveAiOutputLanguage as aP, updatePromptOnly as aQ, selectAndInstallWorkflows as aR, checkClaudeCodeVersionAndPrompt as aS, displayBannerWithInfo as aT, runCodexUninstall as aU, configureCodexMcp as aV, configureCodexApi as aW, runCodexWorkflowImportWithLanguageSelection as aX, runCodexFullInit as aY, switchCodexProvider as aZ, listCodexProviders as a_, ensureI18nInitialized as aa, i18n as ab, addNumbersToChoices as ac, validateApiKey as ad, ensureDir as ae, readDefaultTomlConfig as af, createDefaultTomlConfig as ag, exists as ah, readJsonConfig as ai, writeTomlConfig as aj, copyFile as ak, detectConfigManagementMode as al, readCodexConfig as am, backupCodexComplete as an, writeCodexConfig as ao, writeAuthFile as ap, updateZcfConfig as aq, changeLanguage as ar, readZcfConfig as as, configureOutputStyle as at, isWindows as au, selectMcpServices as av, getMcpServices as aw, isCcrInstalled as ax, installCcr as ay, setupCcrConfiguration as az, importRecommendedEnv as b, switchToProvider as b0, readZcfConfigAsync as b1, initI18n as b2, selectScriptLanguage as b3, index as b4, fsOperations as b5, jsonConfig as b6, claudeConfig as b7, config$1 as b8, config as b9, prompts as ba, codex as bb, 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 };