zcf 3.4.3 → 3.5.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 (56) hide show
  1. package/README.md +8 -1
  2. package/dist/chunks/api-providers.mjs +1 -1
  3. package/dist/chunks/claude-code-config-manager.mjs +7 -7
  4. package/dist/chunks/claude-code-incremental-manager.mjs +1 -1
  5. package/dist/chunks/codex-config-switch.mjs +4 -4
  6. package/dist/chunks/codex-provider-manager.mjs +28 -41
  7. package/dist/chunks/codex-uninstaller.mjs +1 -1
  8. package/dist/chunks/commands.mjs +1 -1
  9. package/dist/chunks/features.mjs +20 -28
  10. package/dist/chunks/simple-config.mjs +351 -263
  11. package/dist/cli.mjs +3 -3
  12. package/dist/i18n/locales/en/codex.json +1 -1
  13. package/dist/i18n/locales/en/configuration.json +3 -2
  14. package/dist/i18n/locales/en/menu.json +1 -1
  15. package/dist/i18n/locales/zh-CN/codex.json +1 -1
  16. package/dist/i18n/locales/zh-CN/configuration.json +3 -2
  17. package/dist/i18n/locales/zh-CN/menu.json +1 -1
  18. package/dist/index.mjs +1 -1
  19. package/package.json +2 -2
  20. package/templates/CLAUDE.md +39 -11
  21. package/templates/{codex/en/workflow/sixStep/prompts → common/workflow/sixStep/en}/workflow.md +25 -4
  22. package/templates/{codex/zh-CN/workflow/sixStep/prompts → common/workflow/sixStep/zh-CN}/workflow.md +25 -4
  23. package/templates/claude-code/en/workflow/sixStep/commands/workflow.md +0 -230
  24. package/templates/claude-code/zh-CN/workflow/sixStep/commands/workflow.md +0 -194
  25. package/templates/codex/en/system-prompt/engineer-professional.md +0 -88
  26. package/templates/codex/en/system-prompt/laowang-engineer.md +0 -127
  27. package/templates/codex/en/system-prompt/nekomata-engineer.md +0 -120
  28. package/templates/codex/en/system-prompt/ojousama-engineer.md +0 -121
  29. package/templates/codex/en/workflow/git/prompts/git-cleanBranches.md +0 -102
  30. package/templates/codex/en/workflow/git/prompts/git-commit.md +0 -205
  31. package/templates/codex/en/workflow/git/prompts/git-rollback.md +0 -90
  32. package/templates/codex/en/workflow/git/prompts/git-worktree.md +0 -276
  33. package/templates/codex/zh-CN/system-prompt/engineer-professional.md +0 -89
  34. package/templates/codex/zh-CN/system-prompt/laowang-engineer.md +0 -127
  35. package/templates/codex/zh-CN/system-prompt/nekomata-engineer.md +0 -120
  36. package/templates/codex/zh-CN/system-prompt/ojousama-engineer.md +0 -121
  37. package/templates/codex/zh-CN/workflow/git/prompts/git-cleanBranches.md +0 -102
  38. package/templates/codex/zh-CN/workflow/git/prompts/git-commit.md +0 -205
  39. package/templates/codex/zh-CN/workflow/git/prompts/git-rollback.md +0 -90
  40. package/templates/codex/zh-CN/workflow/git/prompts/git-worktree.md +0 -276
  41. /package/templates/{claude-code/en/output-styles → common/output-styles/en}/engineer-professional.md +0 -0
  42. /package/templates/{claude-code/en/output-styles → common/output-styles/en}/laowang-engineer.md +0 -0
  43. /package/templates/{claude-code/en/output-styles → common/output-styles/en}/nekomata-engineer.md +0 -0
  44. /package/templates/{claude-code/en/output-styles → common/output-styles/en}/ojousama-engineer.md +0 -0
  45. /package/templates/{claude-code/zh-CN/output-styles → common/output-styles/zh-CN}/engineer-professional.md +0 -0
  46. /package/templates/{claude-code/zh-CN/output-styles → common/output-styles/zh-CN}/laowang-engineer.md +0 -0
  47. /package/templates/{claude-code/zh-CN/output-styles → common/output-styles/zh-CN}/nekomata-engineer.md +0 -0
  48. /package/templates/{claude-code/zh-CN/output-styles → common/output-styles/zh-CN}/ojousama-engineer.md +0 -0
  49. /package/templates/{claude-code/en/workflow/git/commands → common/workflow/git/en}/git-cleanBranches.md +0 -0
  50. /package/templates/{claude-code/en/workflow/git/commands → common/workflow/git/en}/git-commit.md +0 -0
  51. /package/templates/{claude-code/en/workflow/git/commands → common/workflow/git/en}/git-rollback.md +0 -0
  52. /package/templates/{claude-code/en/workflow/git/commands → common/workflow/git/en}/git-worktree.md +0 -0
  53. /package/templates/{claude-code/zh-CN/workflow/git/commands → common/workflow/git/zh-CN}/git-cleanBranches.md +0 -0
  54. /package/templates/{claude-code/zh-CN/workflow/git/commands → common/workflow/git/zh-CN}/git-commit.md +0 -0
  55. /package/templates/{claude-code/zh-CN/workflow/git/commands → common/workflow/git/zh-CN}/git-rollback.md +0 -0
  56. /package/templates/{claude-code/zh-CN/workflow/git/commands → common/workflow/git/zh-CN}/git-worktree.md +0 -0
@@ -13,12 +13,12 @@ import toggleModule from 'inquirer-toggle';
13
13
  import ora from 'ora';
14
14
  import { exec, x } from 'tinyexec';
15
15
  import semver from 'semver';
16
- import { stringify, parse } from 'smol-toml';
16
+ import { edit, stringify, parse, initSync } from '@rainbowatcher/toml-edit-js';
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.4.3";
21
+ const version = "3.5.1";
22
22
  const homepage = "https://github.com/UfoMiao/zcf";
23
23
 
24
24
  const i18n = i18next.createInstance();
@@ -1852,6 +1852,7 @@ async function configureCcrProxy(ccrConfig) {
1852
1852
  if (!settings.env) {
1853
1853
  settings.env = {};
1854
1854
  }
1855
+ delete settings.env.ANTHROPIC_AUTH_TOKEN;
1855
1856
  settings.env.ANTHROPIC_BASE_URL = `http://${host}:${port}`;
1856
1857
  settings.env.ANTHROPIC_API_KEY = apiKey;
1857
1858
  writeJsonConfig(SETTINGS_FILE, settings);
@@ -2849,6 +2850,34 @@ function addNumbersToChoices(choices, startFrom = 1, format = (n) => `${n}. `) {
2849
2850
  });
2850
2851
  }
2851
2852
 
2853
+ let initialized = false;
2854
+ function ensureTomlInitSync() {
2855
+ if (!initialized) {
2856
+ initSync();
2857
+ initialized = true;
2858
+ }
2859
+ }
2860
+ function parseToml(content) {
2861
+ ensureTomlInitSync();
2862
+ return parse(content);
2863
+ }
2864
+ function stringifyToml(data) {
2865
+ ensureTomlInitSync();
2866
+ return stringify(data);
2867
+ }
2868
+ function editToml(content, path, value) {
2869
+ ensureTomlInitSync();
2870
+ return edit(content, path, value);
2871
+ }
2872
+ function batchEditToml(content, edits) {
2873
+ ensureTomlInitSync();
2874
+ let result = content;
2875
+ for (const [path, value] of edits) {
2876
+ result = edit(result, path, value);
2877
+ }
2878
+ return result;
2879
+ }
2880
+
2852
2881
  function isSupportedLang(value) {
2853
2882
  return SUPPORTED_LANGS.includes(value);
2854
2883
  }
@@ -2864,18 +2893,117 @@ function readTomlConfig(configPath) {
2864
2893
  return null;
2865
2894
  }
2866
2895
  const content = readFile(configPath);
2867
- const parsed = parse(content);
2896
+ const parsed = parseToml(content);
2868
2897
  return parsed;
2869
2898
  } catch {
2870
2899
  return null;
2871
2900
  }
2872
2901
  }
2902
+ function insertAtTopLevelStart(topLevel, content) {
2903
+ const lines = topLevel.split("\n");
2904
+ let insertLineIndex = 0;
2905
+ for (let i = 0; i < lines.length; i++) {
2906
+ const trimmed = lines[i].trim();
2907
+ if (trimmed === "" || trimmed.startsWith("#")) {
2908
+ insertLineIndex = i + 1;
2909
+ } else {
2910
+ insertLineIndex = i;
2911
+ break;
2912
+ }
2913
+ }
2914
+ lines.splice(insertLineIndex, 0, content.replace(/\n$/, ""));
2915
+ return lines.join("\n");
2916
+ }
2917
+ function insertAfterVersionField(topLevel, content) {
2918
+ const versionRegex = /^version\s*=\s*["'][^"']*["'][ \t]*(?:#.*)?$/m;
2919
+ const match = topLevel.match(versionRegex);
2920
+ if (match && match.index !== void 0) {
2921
+ const versionEnd = match.index + match[0].length;
2922
+ const before = topLevel.slice(0, versionEnd);
2923
+ const after = topLevel.slice(versionEnd);
2924
+ return `${before}
2925
+ ${content.replace(/\n$/, "")}${after}`;
2926
+ }
2927
+ return insertAtTopLevelStart(topLevel, content);
2928
+ }
2929
+ function updateTopLevelTomlFields(content, version, lastUpdated) {
2930
+ const firstSectionMatch = content.match(/^\[/m);
2931
+ const topLevelEnd = firstSectionMatch?.index ?? content.length;
2932
+ let topLevel = content.slice(0, topLevelEnd);
2933
+ const rest = content.slice(topLevelEnd);
2934
+ const versionRegex = /^version\s*=\s*["'][^"']*["'][ \t]*(?:#.*)?$/m;
2935
+ const versionMatch = topLevel.match(versionRegex);
2936
+ if (versionMatch) {
2937
+ topLevel = topLevel.replace(versionRegex, `version = "${version}"`);
2938
+ } else {
2939
+ topLevel = insertAtTopLevelStart(topLevel, `version = "${version}"`);
2940
+ }
2941
+ const lastUpdatedRegex = /^lastUpdated\s*=\s*["'][^"']*["'][ \t]*(?:#.*)?$/m;
2942
+ const lastUpdatedMatch = topLevel.match(lastUpdatedRegex);
2943
+ if (lastUpdatedMatch) {
2944
+ topLevel = topLevel.replace(lastUpdatedRegex, `lastUpdated = "${lastUpdated}"`);
2945
+ } else {
2946
+ topLevel = insertAfterVersionField(topLevel, `lastUpdated = "${lastUpdated}"`);
2947
+ }
2948
+ if (rest.length > 0 && !topLevel.endsWith("\n\n") && !topLevel.endsWith("\n")) {
2949
+ topLevel += "\n";
2950
+ }
2951
+ return topLevel + rest;
2952
+ }
2873
2953
  function writeTomlConfig(configPath, config) {
2874
2954
  try {
2875
2955
  const configDir = dirname(configPath);
2876
2956
  ensureDir(configDir);
2877
- const tomlContent = stringify(config);
2878
- writeFile(configPath, tomlContent);
2957
+ if (exists(configPath)) {
2958
+ const existingContent = readFile(configPath);
2959
+ const edits = [
2960
+ // General section
2961
+ ["general.preferredLang", config.general.preferredLang],
2962
+ ["general.currentTool", config.general.currentTool]
2963
+ ];
2964
+ if (config.general.templateLang !== void 0) {
2965
+ edits.push(["general.templateLang", config.general.templateLang]);
2966
+ }
2967
+ if (config.general.aiOutputLang !== void 0) {
2968
+ edits.push(["general.aiOutputLang", config.general.aiOutputLang]);
2969
+ }
2970
+ edits.push(
2971
+ ["claudeCode.enabled", config.claudeCode.enabled],
2972
+ ["claudeCode.outputStyles", config.claudeCode.outputStyles],
2973
+ ["claudeCode.installType", config.claudeCode.installType]
2974
+ );
2975
+ if (config.claudeCode.defaultOutputStyle !== void 0) {
2976
+ edits.push(["claudeCode.defaultOutputStyle", config.claudeCode.defaultOutputStyle]);
2977
+ }
2978
+ if (config.claudeCode.currentProfile !== void 0) {
2979
+ edits.push(["claudeCode.currentProfile", config.claudeCode.currentProfile]);
2980
+ }
2981
+ if (config.claudeCode.profiles !== void 0) {
2982
+ edits.push(["claudeCode.profiles", config.claudeCode.profiles]);
2983
+ }
2984
+ if (config.claudeCode.version !== void 0) {
2985
+ edits.push(["claudeCode.version", config.claudeCode.version]);
2986
+ }
2987
+ edits.push(
2988
+ ["codex.enabled", config.codex.enabled],
2989
+ ["codex.systemPromptStyle", config.codex.systemPromptStyle]
2990
+ );
2991
+ try {
2992
+ let updatedContent = batchEditToml(existingContent, edits);
2993
+ updatedContent = updateTopLevelTomlFields(
2994
+ updatedContent,
2995
+ config.version,
2996
+ config.lastUpdated
2997
+ );
2998
+ writeFile(configPath, updatedContent);
2999
+ } catch {
3000
+ const tomlContent = stringifyToml(config);
3001
+ writeFile(configPath, tomlContent);
3002
+ }
3003
+ } else {
3004
+ const tomlContent = stringifyToml(config);
3005
+ writeFile(configPath, tomlContent);
3006
+ }
2879
3007
  } catch {
2880
3008
  }
2881
3009
  }
@@ -3379,6 +3507,147 @@ function applyCodexPlatformCommand(config) {
3379
3507
  }
3380
3508
  }
3381
3509
 
3510
+ function updateTopLevelTomlField(content, field, value, options = {}) {
3511
+ if (!content) {
3512
+ if (value === null) {
3513
+ return "";
3514
+ }
3515
+ const commentPrefix = options.commented ? "# " : "";
3516
+ return `${commentPrefix}${field} = "${value}"
3517
+ `;
3518
+ }
3519
+ const firstSectionMatch = content.match(/^\[/m);
3520
+ const topLevelEnd = firstSectionMatch?.index ?? content.length;
3521
+ let topLevel = content.slice(0, topLevelEnd);
3522
+ const rest = content.slice(topLevelEnd);
3523
+ const fieldRegex = new RegExp(`^(#\\s*)?${field}\\s*=\\s*["'][^"']*["'][ \\t]*(?:#.*)?$`, "m");
3524
+ const existingMatch = topLevel.match(fieldRegex);
3525
+ if (value === null) {
3526
+ if (existingMatch) {
3527
+ topLevel = topLevel.replace(fieldRegex, "").replace(/\n{2,}/g, "\n\n");
3528
+ }
3529
+ } else {
3530
+ const commentPrefix = options.commented ? "# " : "";
3531
+ const newLine = `${commentPrefix}${field} = "${value}"`;
3532
+ if (existingMatch) {
3533
+ topLevel = topLevel.replace(fieldRegex, newLine);
3534
+ } else {
3535
+ topLevel = `${topLevel.trimEnd()}
3536
+ ${newLine}
3537
+ `;
3538
+ }
3539
+ }
3540
+ if (rest.length > 0 && !topLevel.endsWith("\n\n")) {
3541
+ topLevel = `${topLevel.trimEnd()}
3542
+
3543
+ `;
3544
+ }
3545
+ return topLevel + rest;
3546
+ }
3547
+ function updateCodexApiFields(fields) {
3548
+ if (!exists(CODEX_CONFIG_FILE)) {
3549
+ ensureDir(CODEX_DIR);
3550
+ writeFile(CODEX_CONFIG_FILE, "");
3551
+ }
3552
+ let content = readFile(CODEX_CONFIG_FILE) || "";
3553
+ if (fields.model !== void 0) {
3554
+ content = updateTopLevelTomlField(content, "model", fields.model);
3555
+ }
3556
+ if (fields.modelProvider !== void 0) {
3557
+ content = updateTopLevelTomlField(
3558
+ content,
3559
+ "model_provider",
3560
+ fields.modelProvider,
3561
+ { commented: fields.modelProviderCommented }
3562
+ );
3563
+ }
3564
+ writeFile(CODEX_CONFIG_FILE, content);
3565
+ }
3566
+ function upsertCodexProvider(providerId, provider) {
3567
+ if (!exists(CODEX_CONFIG_FILE)) {
3568
+ ensureDir(CODEX_DIR);
3569
+ writeFile(CODEX_CONFIG_FILE, "");
3570
+ }
3571
+ let content = readFile(CODEX_CONFIG_FILE) || "";
3572
+ const basePath = `model_providers.${providerId}`;
3573
+ content = editToml(content, `${basePath}.name`, provider.name);
3574
+ content = editToml(content, `${basePath}.base_url`, provider.baseUrl);
3575
+ content = editToml(content, `${basePath}.wire_api`, provider.wireApi);
3576
+ content = editToml(content, `${basePath}.temp_env_key`, provider.tempEnvKey);
3577
+ content = editToml(content, `${basePath}.requires_openai_auth`, provider.requiresOpenaiAuth);
3578
+ if (provider.model) {
3579
+ content = editToml(content, `${basePath}.model`, provider.model);
3580
+ }
3581
+ writeFile(CODEX_CONFIG_FILE, content);
3582
+ }
3583
+ function deleteCodexProvider(providerId) {
3584
+ if (!exists(CODEX_CONFIG_FILE)) {
3585
+ return;
3586
+ }
3587
+ const content = readFile(CODEX_CONFIG_FILE) || "";
3588
+ const sectionRegex = new RegExp(
3589
+ `\\n?\\[model_providers\\.${escapeRegex(providerId)}\\][\\s\\S]*?(?=\\n\\[|$)`,
3590
+ "g"
3591
+ );
3592
+ const updatedContent = content.replace(sectionRegex, "");
3593
+ writeFile(CODEX_CONFIG_FILE, updatedContent);
3594
+ }
3595
+ function upsertCodexMcpService(serviceId, service) {
3596
+ if (!exists(CODEX_CONFIG_FILE)) {
3597
+ ensureDir(CODEX_DIR);
3598
+ writeFile(CODEX_CONFIG_FILE, "");
3599
+ }
3600
+ let content = readFile(CODEX_CONFIG_FILE) || "";
3601
+ const basePath = `mcp_servers.${serviceId}`;
3602
+ const parsed = content ? parseToml(content) : {};
3603
+ const existingService = parsed.mcp_servers?.[serviceId];
3604
+ if (existingService?.url && !existingService?.command) {
3605
+ if (service.env && Object.keys(service.env).length > 0) {
3606
+ content = editToml(content, `${basePath}.env`, service.env);
3607
+ }
3608
+ if (service.startup_timeout_sec) {
3609
+ content = editToml(content, `${basePath}.startup_timeout_sec`, service.startup_timeout_sec);
3610
+ }
3611
+ } else {
3612
+ const normalizedCommand = normalizeTomlPath(service.command);
3613
+ content = editToml(content, `${basePath}.command`, normalizedCommand);
3614
+ content = editToml(content, `${basePath}.args`, service.args || []);
3615
+ if (service.env && Object.keys(service.env).length > 0) {
3616
+ content = editToml(content, `${basePath}.env`, service.env);
3617
+ }
3618
+ if (service.startup_timeout_sec) {
3619
+ content = editToml(content, `${basePath}.startup_timeout_sec`, service.startup_timeout_sec);
3620
+ }
3621
+ }
3622
+ writeFile(CODEX_CONFIG_FILE, content);
3623
+ }
3624
+ function batchUpdateCodexMcpServices(services, options = {}) {
3625
+ if (options.replaceAll) {
3626
+ if (exists(CODEX_CONFIG_FILE)) {
3627
+ let content = readFile(CODEX_CONFIG_FILE) || "";
3628
+ content = content.replace(/\n?\[mcp_servers\.[^\]]+\][\s\S]*?(?=\n\[|$)/g, "");
3629
+ content = content.replace(/\n?#\s*---\s*MCP servers added by ZCF\s*---\s*/gi, "");
3630
+ writeFile(CODEX_CONFIG_FILE, content);
3631
+ }
3632
+ }
3633
+ for (const service of services) {
3634
+ upsertCodexMcpService(service.id, service);
3635
+ }
3636
+ }
3637
+ function escapeRegex(str) {
3638
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3639
+ }
3640
+
3641
+ const codexTomlUpdater = {
3642
+ __proto__: null,
3643
+ batchUpdateCodexMcpServices: batchUpdateCodexMcpServices,
3644
+ deleteCodexProvider: deleteCodexProvider,
3645
+ updateCodexApiFields: updateCodexApiFields,
3646
+ updateTopLevelTomlField: updateTopLevelTomlField,
3647
+ upsertCodexMcpService: upsertCodexMcpService,
3648
+ upsertCodexProvider: upsertCodexProvider
3649
+ };
3650
+
3382
3651
  async function configureCodexMcp(options) {
3383
3652
  ensureI18nInitialized();
3384
3653
  const { skipPrompt = false } = options ?? {};
@@ -3395,7 +3664,6 @@ async function configureCodexMcp(options) {
3395
3664
  return;
3396
3665
  }
3397
3666
  const defaultServiceIds = Array.isArray(options?.mcpServices) ? options.mcpServices : MCP_SERVICE_CONFIGS.filter((service) => !service.requiresApiKey).map((service) => service.id);
3398
- const baseProviders2 = existingConfig?.providers || [];
3399
3667
  const existingServices2 = existingConfig?.mcpServices || [];
3400
3668
  const selection2 = [];
3401
3669
  for (const id of defaultServiceIds) {
@@ -3449,13 +3717,7 @@ async function configureCodexMcp(options) {
3449
3717
  }
3450
3718
  return svc;
3451
3719
  });
3452
- writeCodexConfig({
3453
- model: existingConfig?.model || null,
3454
- modelProvider: existingConfig?.modelProvider || null,
3455
- providers: baseProviders2,
3456
- mcpServices: finalServices2,
3457
- otherConfig: existingConfig?.otherConfig || []
3458
- });
3720
+ batchUpdateCodexMcpServices(finalServices2);
3459
3721
  updateZcfConfig({ codeToolType: "codex" });
3460
3722
  console.log(ansis.green(i18n.t("codex:mcpConfigured")));
3461
3723
  return;
@@ -3464,7 +3726,6 @@ async function configureCodexMcp(options) {
3464
3726
  if (!selectedIds)
3465
3727
  return;
3466
3728
  const servicesMeta = await getMcpServices();
3467
- const baseProviders = existingConfig?.providers || [];
3468
3729
  const selection = [];
3469
3730
  const existingServices = existingConfig?.mcpServices || [];
3470
3731
  if (selectedIds.length === 0) {
@@ -3484,13 +3745,7 @@ async function configureCodexMcp(options) {
3484
3745
  }
3485
3746
  return svc;
3486
3747
  });
3487
- writeCodexConfig({
3488
- model: existingConfig?.model || null,
3489
- modelProvider: existingConfig?.modelProvider || null,
3490
- providers: baseProviders,
3491
- mcpServices: preserved,
3492
- otherConfig: existingConfig?.otherConfig || []
3493
- });
3748
+ batchUpdateCodexMcpServices(preserved);
3494
3749
  updateZcfConfig({ codeToolType: "codex" });
3495
3750
  return;
3496
3751
  }
@@ -3559,13 +3814,7 @@ async function configureCodexMcp(options) {
3559
3814
  }
3560
3815
  return svc;
3561
3816
  });
3562
- writeCodexConfig({
3563
- model: existingConfig?.model || null,
3564
- modelProvider: existingConfig?.modelProvider || null,
3565
- providers: baseProviders,
3566
- mcpServices: finalServices,
3567
- otherConfig: existingConfig?.otherConfig || []
3568
- });
3817
+ batchUpdateCodexMcpServices(finalServices);
3569
3818
  updateZcfConfig({ codeToolType: "codex" });
3570
3819
  console.log(ansis.green(i18n.t("codex:mcpConfigured")));
3571
3820
  }
@@ -3827,7 +4076,7 @@ function parseCodexConfig(content) {
3827
4076
  const normalizedContent = content.replace(/(SYSTEMROOT\s*=\s*")[^"\n]+("?)/g, (match) => {
3828
4077
  return match.replace(/\\\\/g, "/").replace(/\\/g, "/").replace('C:/Windows"?', 'C:/Windows"');
3829
4078
  });
3830
- const tomlData = parse(normalizedContent);
4079
+ const tomlData = parseToml(normalizedContent);
3831
4080
  const providers = [];
3832
4081
  if (tomlData.model_providers) {
3833
4082
  for (const [id, providerData] of Object.entries(tomlData.model_providers)) {
@@ -3961,70 +4210,6 @@ function parseCodexConfig(content) {
3961
4210
  };
3962
4211
  }
3963
4212
  }
3964
- function formatInlineTableValue(value) {
3965
- if (value === null || value === void 0) {
3966
- return "";
3967
- }
3968
- if (typeof value === "string") {
3969
- const normalized = normalizeTomlPath(value);
3970
- return `'${normalized}'`;
3971
- }
3972
- if (typeof value === "number" || typeof value === "boolean") {
3973
- return String(value);
3974
- }
3975
- if (Array.isArray(value)) {
3976
- const items = value.map((item) => {
3977
- if (typeof item === "string") {
3978
- const normalized = normalizeTomlPath(item);
3979
- return `'${normalized}'`;
3980
- }
3981
- if (typeof item === "object" && item !== null && !Array.isArray(item)) {
3982
- return formatInlineTable(item);
3983
- }
3984
- return String(item);
3985
- }).join(", ");
3986
- return `[${items}]`;
3987
- }
3988
- if (typeof value === "object") {
3989
- return formatInlineTable(value);
3990
- }
3991
- return String(value);
3992
- }
3993
- function formatInlineTable(obj) {
3994
- const entries = Object.entries(obj).filter(([_, v]) => v !== null && v !== void 0).map(([k, v]) => `${k} = ${formatInlineTableValue(v)}`).join(", ");
3995
- return `{${entries}}`;
3996
- }
3997
- function formatTomlField(key, value) {
3998
- if (value === null || value === void 0) {
3999
- return "";
4000
- }
4001
- if (typeof value === "string") {
4002
- const normalized = normalizeTomlPath(value);
4003
- const escaped = normalized.replace(/"/g, '\\"');
4004
- return `${key} = "${escaped}"`;
4005
- }
4006
- if (typeof value === "number" || typeof value === "boolean") {
4007
- return `${key} = ${value}`;
4008
- }
4009
- if (Array.isArray(value)) {
4010
- const items = value.map((item) => {
4011
- if (typeof item === "string") {
4012
- const normalized = normalizeTomlPath(item);
4013
- const escaped = normalized.replace(/"/g, '\\"');
4014
- return `"${escaped}"`;
4015
- }
4016
- if (typeof item === "object" && item !== null && !Array.isArray(item)) {
4017
- return formatInlineTable(item);
4018
- }
4019
- return String(item);
4020
- }).join(", ");
4021
- return `${key} = [${items}]`;
4022
- }
4023
- if (typeof value === "object") {
4024
- return `${key} = ${formatInlineTable(value)}`;
4025
- }
4026
- return "";
4027
- }
4028
4213
  function readCodexConfig() {
4029
4214
  if (!exists(CODEX_CONFIG_FILE))
4030
4215
  return null;
@@ -4036,100 +4221,6 @@ function readCodexConfig() {
4036
4221
  return null;
4037
4222
  }
4038
4223
  }
4039
- function renderCodexConfig(data) {
4040
- const lines = [];
4041
- if (data.model || data.modelProvider || data.providers.length > 0 || data.modelProviderCommented) {
4042
- lines.push("# --- model provider added by ZCF ---");
4043
- if (data.model) {
4044
- lines.push(`model = "${data.model}"`);
4045
- }
4046
- if (data.modelProvider) {
4047
- const commentPrefix = data.modelProviderCommented ? "# " : "";
4048
- lines.push(`${commentPrefix}model_provider = "${data.modelProvider}"`);
4049
- }
4050
- lines.push("");
4051
- }
4052
- if (data.otherConfig && data.otherConfig.length > 0) {
4053
- const preserved = data.otherConfig.filter((raw) => {
4054
- const l = String(raw).trim();
4055
- if (!l)
4056
- return false;
4057
- if (/^#\s*---\s*model provider added by ZCF\s*---\s*$/i.test(l))
4058
- return false;
4059
- if (/^#\s*---\s*MCP servers added by ZCF\s*---\s*$/i.test(l))
4060
- return false;
4061
- if (/^\[\s*mcp_servers\./i.test(l))
4062
- return false;
4063
- if (/^\[\s*model_providers\./i.test(l))
4064
- return false;
4065
- if (/^#?\s*model_provider\s*=/.test(l))
4066
- return false;
4067
- if (/^\s*model\s*=/.test(l) && !l.includes("["))
4068
- return false;
4069
- return true;
4070
- });
4071
- if (preserved.length > 0) {
4072
- lines.push(...preserved);
4073
- if (data.providers.length > 0 || data.mcpServices.length > 0) {
4074
- lines.push("");
4075
- }
4076
- }
4077
- }
4078
- if (data.providers.length > 0) {
4079
- for (const provider of data.providers) {
4080
- lines.push("");
4081
- lines.push(`[model_providers.${provider.id}]`);
4082
- lines.push(`name = "${provider.name}"`);
4083
- lines.push(`base_url = "${provider.baseUrl}"`);
4084
- lines.push(`wire_api = "${provider.wireApi}"`);
4085
- lines.push(`temp_env_key = "${provider.tempEnvKey}"`);
4086
- lines.push(`requires_openai_auth = ${provider.requiresOpenaiAuth}`);
4087
- if (provider.model) {
4088
- lines.push(`model = "${provider.model}"`);
4089
- }
4090
- }
4091
- }
4092
- if (data.mcpServices.length > 0) {
4093
- lines.push("");
4094
- lines.push("# --- MCP servers added by ZCF ---");
4095
- for (const service of data.mcpServices) {
4096
- lines.push(`[mcp_servers.${service.id}]`);
4097
- const normalizedCommand = normalizeTomlPath(service.command);
4098
- lines.push(`command = "${normalizedCommand}"`);
4099
- const argsString = service.args.length > 0 ? service.args.map((arg) => `"${arg}"`).join(", ") : "";
4100
- lines.push(`args = [${argsString}]`);
4101
- if (service.env && Object.keys(service.env).length > 0) {
4102
- const envEntries = Object.entries(service.env).map(([key, value]) => `${key} = '${value}'`).join(", ");
4103
- lines.push(`env = {${envEntries}}`);
4104
- }
4105
- if (service.startup_timeout_sec) {
4106
- lines.push(`startup_timeout_sec = ${service.startup_timeout_sec}`);
4107
- }
4108
- if (service.extraFields) {
4109
- for (const [key, value] of Object.entries(service.extraFields)) {
4110
- const formatted = formatTomlField(key, value);
4111
- if (formatted) {
4112
- lines.push(formatted);
4113
- }
4114
- }
4115
- }
4116
- lines.push("");
4117
- }
4118
- if (lines[lines.length - 1] === "") {
4119
- lines.pop();
4120
- }
4121
- }
4122
- let result = lines.join("\n");
4123
- if (result && !result.endsWith("\n")) {
4124
- result += "\n";
4125
- }
4126
- return result;
4127
- }
4128
- function writeCodexConfig(data) {
4129
- ensureEnvKeyMigration();
4130
- ensureDir(CODEX_DIR);
4131
- writeFile(CODEX_CONFIG_FILE, renderCodexConfig(data));
4132
- }
4133
4224
  function writeAuthFile(newEntries) {
4134
4225
  ensureDir(CODEX_DIR);
4135
4226
  const existing = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
@@ -4260,7 +4351,6 @@ async function runCodexWorkflowImportWithLanguageSelection(options) {
4260
4351
  async function runCodexSystemPromptSelection(skipPrompt = false) {
4261
4352
  ensureI18nInitialized();
4262
4353
  const rootDir = getRootDir$1();
4263
- const templateRoot = join(rootDir, "templates", "codex");
4264
4354
  const zcfConfig$1 = readZcfConfig();
4265
4355
  const { readDefaultTomlConfig: readDefaultTomlConfig2 } = await Promise.resolve().then(function () { return zcfConfig; });
4266
4356
  const tomlConfig = readDefaultTomlConfig2();
@@ -4273,10 +4363,9 @@ async function runCodexSystemPromptSelection(skipPrompt = false) {
4273
4363
  // Pass skipPrompt flag
4274
4364
  );
4275
4365
  updateZcfConfig({ templateLang: preferredLang });
4276
- let langDir = join(templateRoot, preferredLang);
4277
- if (!exists(langDir))
4278
- langDir = join(templateRoot, "zh-CN");
4279
- const systemPromptSrc = join(langDir, "system-prompt");
4366
+ let systemPromptSrc = join(rootDir, "templates", "common", "output-styles", preferredLang);
4367
+ if (!exists(systemPromptSrc))
4368
+ systemPromptSrc = join(rootDir, "templates", "common", "output-styles", "zh-CN");
4280
4369
  if (!exists(systemPromptSrc))
4281
4370
  return;
4282
4371
  const availablePrompts = [
@@ -4338,17 +4427,17 @@ async function runCodexWorkflowSelection(options) {
4338
4427
  ensureI18nInitialized();
4339
4428
  const { skipPrompt = false, workflows: presetWorkflows = [] } = options ?? {};
4340
4429
  const rootDir = getRootDir$1();
4341
- const templateRoot = join(rootDir, "templates", "codex");
4342
4430
  const zcfConfig = readZcfConfig();
4343
4431
  const templateLang = zcfConfig?.templateLang || zcfConfig?.preferredLang || "en";
4344
- const preferredLang = templateLang === "en" ? "en" : "zh-CN";
4345
- let langDir = join(templateRoot, preferredLang);
4346
- if (!exists(langDir))
4347
- langDir = join(templateRoot, "zh-CN");
4348
- const workflowSrc = join(langDir, "workflow");
4432
+ let preferredLang = templateLang === "en" ? "en" : "zh-CN";
4433
+ const workflowSrc = join(rootDir, "templates", "common", "workflow");
4349
4434
  if (!exists(workflowSrc))
4350
4435
  return;
4351
- const allWorkflows = getAllWorkflowFiles(workflowSrc);
4436
+ let allWorkflows = getAllWorkflowFiles(workflowSrc, preferredLang);
4437
+ if (allWorkflows.length === 0 && preferredLang === "en") {
4438
+ preferredLang = "zh-CN";
4439
+ allWorkflows = getAllWorkflowFiles(workflowSrc, preferredLang);
4440
+ }
4352
4441
  if (allWorkflows.length === 0)
4353
4442
  return;
4354
4443
  if (skipPrompt) {
@@ -4362,9 +4451,9 @@ async function runCodexWorkflowSelection(options) {
4362
4451
  const selectedWorkflows = allWorkflows.filter(
4363
4452
  (workflow) => presetWorkflows.includes(workflow.name)
4364
4453
  );
4365
- workflowsToInstall = expandSelectedWorkflowPaths(selectedWorkflows.map((w) => w.path), workflowSrc);
4454
+ workflowsToInstall = expandSelectedWorkflowPaths(selectedWorkflows.map((w) => w.path), workflowSrc, preferredLang);
4366
4455
  } else {
4367
- workflowsToInstall = expandSelectedWorkflowPaths(allWorkflows.map((w) => w.path), workflowSrc);
4456
+ workflowsToInstall = expandSelectedWorkflowPaths(allWorkflows.map((w) => w.path), workflowSrc, preferredLang);
4368
4457
  }
4369
4458
  for (const workflowPath of workflowsToInstall) {
4370
4459
  const content = readFile(workflowPath);
@@ -4392,7 +4481,7 @@ async function runCodexWorkflowSelection(options) {
4392
4481
  if (backupPath) {
4393
4482
  console.log(ansis.gray(getBackupMessage(backupPath)));
4394
4483
  }
4395
- const finalWorkflowPaths = expandSelectedWorkflowPaths(workflows, workflowSrc);
4484
+ const finalWorkflowPaths = expandSelectedWorkflowPaths(workflows, workflowSrc, preferredLang);
4396
4485
  for (const workflowPath of finalWorkflowPaths) {
4397
4486
  const content = readFile(workflowPath);
4398
4487
  const filename = workflowPath.split("/").pop() || "workflow.md";
@@ -4401,19 +4490,16 @@ async function runCodexWorkflowSelection(options) {
4401
4490
  }
4402
4491
  }
4403
4492
  const GIT_GROUP_SENTINEL = "::gitGroup";
4404
- function getAllWorkflowFiles(dirPath) {
4493
+ function getAllWorkflowFiles(workflowSrc, preferredLang) {
4405
4494
  const workflows = [];
4406
- const sixStepDir = join(dirPath, "sixStep", "prompts");
4407
- if (exists(sixStepDir)) {
4408
- const workflowFile = join(sixStepDir, "workflow.md");
4409
- if (exists(workflowFile)) {
4410
- workflows.push({
4411
- name: i18n.t("workflow:workflowOption.sixStepsWorkflow"),
4412
- path: workflowFile
4413
- });
4414
- }
4495
+ const sixStepFile = join(workflowSrc, "sixStep", preferredLang, "workflow.md");
4496
+ if (exists(sixStepFile)) {
4497
+ workflows.push({
4498
+ name: i18n.t("workflow:workflowOption.sixStepsWorkflow"),
4499
+ path: sixStepFile
4500
+ });
4415
4501
  }
4416
- const gitPromptsDir = join(dirPath, "git", "prompts");
4502
+ const gitPromptsDir = join(workflowSrc, "git", preferredLang);
4417
4503
  if (exists(gitPromptsDir)) {
4418
4504
  workflows.push({
4419
4505
  name: i18n.t("workflow:workflowOption.gitWorkflow"),
@@ -4423,19 +4509,19 @@ function getAllWorkflowFiles(dirPath) {
4423
4509
  }
4424
4510
  return workflows;
4425
4511
  }
4426
- function expandSelectedWorkflowPaths(paths, workflowSrc) {
4512
+ function expandSelectedWorkflowPaths(paths, workflowSrc, preferredLang) {
4427
4513
  const expanded = [];
4428
4514
  for (const p of paths) {
4429
4515
  if (p === GIT_GROUP_SENTINEL) {
4430
- expanded.push(...getGitPromptFiles(workflowSrc));
4516
+ expanded.push(...getGitPromptFiles(workflowSrc, preferredLang));
4431
4517
  } else {
4432
4518
  expanded.push(p);
4433
4519
  }
4434
4520
  }
4435
4521
  return expanded;
4436
4522
  }
4437
- function getGitPromptFiles(workflowSrc) {
4438
- const gitDir = join(workflowSrc, "git", "prompts");
4523
+ function getGitPromptFiles(workflowSrc, preferredLang) {
4524
+ const gitPromptsDir = join(workflowSrc, "git", preferredLang);
4439
4525
  const files = [
4440
4526
  "git-commit.md",
4441
4527
  "git-rollback.md",
@@ -4444,7 +4530,7 @@ function getGitPromptFiles(workflowSrc) {
4444
4530
  ];
4445
4531
  const resolved = [];
4446
4532
  for (const f of files) {
4447
- const full = join(gitDir, f);
4533
+ const full = join(gitPromptsDir, f);
4448
4534
  if (exists(full))
4449
4535
  resolved.push(full);
4450
4536
  }
@@ -4477,12 +4563,11 @@ async function applyCustomApiConfig(customApiConfig) {
4477
4563
  }
4478
4564
  const existingConfig = readCodexConfig();
4479
4565
  const existingAuth = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
4480
- const providers = [];
4481
4566
  const authEntries = { ...existingAuth };
4482
4567
  const providerId = type === "auth_token" ? "official-auth-token" : "custom-api-key";
4483
4568
  const providerName = type === "auth_token" ? "Official Auth Token" : "Custom API Key";
4484
4569
  const existingProvider = existingConfig?.providers.find((p) => p.id === providerId);
4485
- providers.push({
4570
+ const newProvider = {
4486
4571
  id: providerId,
4487
4572
  name: providerName,
4488
4573
  baseUrl: baseUrl || existingProvider?.baseUrl || "https://api.anthropic.com",
@@ -4490,24 +4575,18 @@ async function applyCustomApiConfig(customApiConfig) {
4490
4575
  tempEnvKey: existingProvider?.tempEnvKey || `${providerId.toUpperCase()}_API_KEY`,
4491
4576
  requiresOpenaiAuth: existingProvider?.requiresOpenaiAuth ?? false,
4492
4577
  model: model || existingProvider?.model
4493
- });
4494
- if (existingConfig?.providers) {
4495
- providers.push(...existingConfig.providers.filter((p) => p.id !== providerId));
4496
- }
4578
+ };
4497
4579
  if (token) {
4498
4580
  authEntries[providerId] = token;
4499
4581
  authEntries.OPENAI_API_KEY = token;
4500
4582
  }
4501
- const configData = {
4583
+ const { updateCodexApiFields, upsertCodexProvider } = await Promise.resolve().then(function () { return codexTomlUpdater; });
4584
+ updateCodexApiFields({
4502
4585
  model: model || existingConfig?.model || "claude-3-5-sonnet-20241022",
4503
- // Prefer provided model, then existing, fallback default
4504
4586
  modelProvider: providerId,
4505
- modelProviderCommented: false,
4506
- providers,
4507
- mcpServices: existingConfig?.mcpServices || [],
4508
- otherConfig: existingConfig?.otherConfig || []
4509
- };
4510
- writeCodexConfig(configData);
4587
+ modelProviderCommented: false
4588
+ });
4589
+ upsertCodexProvider(providerId, newProvider);
4511
4590
  writeJsonConfig(CODEX_AUTH_FILE, authEntries);
4512
4591
  updateZcfConfig({ codeToolType: "codex" });
4513
4592
  console.log(ansis.green(`\u2714 ${i18n.t("codex:apiConfigured")}`));
@@ -4678,7 +4757,7 @@ async function configureCodexApi(options) {
4678
4757
  type: "input",
4679
4758
  name: "model",
4680
4759
  message: `${i18n.t("configuration:enterCustomModel")}${i18n.t("common:emptyToSkip")}`,
4681
- default: "gpt-5-codex"
4760
+ default: "gpt-5.2"
4682
4761
  }]);
4683
4762
  if (model.trim()) {
4684
4763
  customModel = model.trim();
@@ -4717,7 +4796,7 @@ async function configureCodexApi(options) {
4717
4796
  wireApi: selectedProvider2 === "custom" ? answers.wireApi || "responses" : prefilledWireApi,
4718
4797
  tempEnvKey,
4719
4798
  requiresOpenaiAuth: true,
4720
- model: customModel || prefilledModel || "gpt-5-codex"
4799
+ model: customModel || prefilledModel || "gpt-5.2"
4721
4800
  // Use custom model, provider's default model, or fallback
4722
4801
  };
4723
4802
  providers.push(newProvider);
@@ -4747,13 +4826,15 @@ async function configureCodexApi(options) {
4747
4826
  if (defaultApiKey)
4748
4827
  authEntries.OPENAI_API_KEY = defaultApiKey;
4749
4828
  }
4750
- writeCodexConfig({
4751
- model: existingConfig?.model || null,
4829
+ const { updateCodexApiFields, upsertCodexProvider } = await Promise.resolve().then(function () { return codexTomlUpdater; });
4830
+ updateCodexApiFields({
4831
+ model: existingConfig?.model,
4752
4832
  modelProvider: defaultProvider,
4753
- providers,
4754
- mcpServices: existingConfig?.mcpServices || [],
4755
- otherConfig: existingConfig?.otherConfig || []
4833
+ modelProviderCommented: false
4756
4834
  });
4835
+ for (const provider of providers) {
4836
+ upsertCodexProvider(provider.id, provider);
4837
+ }
4757
4838
  writeAuthFile(authEntries);
4758
4839
  updateZcfConfig({ codeToolType: "codex" });
4759
4840
  console.log(ansis.green(i18n.t("codex:apiConfigured")));
@@ -4941,12 +5022,12 @@ async function switchCodexProvider(providerId) {
4941
5022
  if (backupPath) {
4942
5023
  console.log(ansis.gray(getBackupMessage(backupPath)));
4943
5024
  }
4944
- const updatedConfig = {
4945
- ...existingConfig,
4946
- modelProvider: providerId
4947
- };
4948
5025
  try {
4949
- writeCodexConfig(updatedConfig);
5026
+ const { updateCodexApiFields } = await Promise.resolve().then(function () { return codexTomlUpdater; });
5027
+ updateCodexApiFields({
5028
+ modelProvider: providerId,
5029
+ modelProviderCommented: false
5030
+ });
4950
5031
  console.log(ansis.green(i18n.t("codex:providerSwitchSuccess", { provider: providerId })));
4951
5032
  return true;
4952
5033
  } catch (error) {
@@ -4970,19 +5051,18 @@ async function switchToOfficialLogin() {
4970
5051
  if (!preservedModelProvider) {
4971
5052
  try {
4972
5053
  const rawContent = readFile(CODEX_CONFIG_FILE);
4973
- const parsedToml = parse(rawContent);
5054
+ const parsedToml = parseToml(rawContent);
4974
5055
  if (typeof parsedToml.model_provider === "string" && parsedToml.model_provider.trim().length > 0)
4975
5056
  preservedModelProvider = parsedToml.model_provider.trim();
4976
5057
  } catch {
4977
5058
  }
4978
5059
  }
4979
5060
  const shouldCommentModelProvider = typeof preservedModelProvider === "string" && preservedModelProvider.length > 0;
4980
- const updatedConfig = {
4981
- ...existingConfig,
5061
+ const { updateCodexApiFields } = await Promise.resolve().then(function () { return codexTomlUpdater; });
5062
+ updateCodexApiFields({
4982
5063
  modelProvider: shouldCommentModelProvider ? preservedModelProvider : existingConfig.modelProvider,
4983
- modelProviderCommented: shouldCommentModelProvider ? true : existingConfig.modelProviderCommented
4984
- };
4985
- writeCodexConfig(updatedConfig);
5064
+ modelProviderCommented: shouldCommentModelProvider || existingConfig.modelProviderCommented
5065
+ });
4986
5066
  const auth = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
4987
5067
  auth.OPENAI_API_KEY = null;
4988
5068
  writeJsonConfig(CODEX_AUTH_FILE, auth, { pretty: true });
@@ -5015,18 +5095,18 @@ async function switchToProvider(providerId) {
5015
5095
  targetModel = provider.model;
5016
5096
  } else {
5017
5097
  const currentModel = existingConfig.model;
5018
- if (currentModel !== "gpt-5" && currentModel !== "gpt-5-codex") {
5019
- targetModel = "gpt-5-codex";
5098
+ const knownModels = ["gpt-5.1-codex-max", "gpt-5.1-codex-mini", "gpt-5.2"];
5099
+ if (!currentModel || !knownModels.includes(currentModel)) {
5100
+ targetModel = "gpt-5.2";
5020
5101
  }
5021
5102
  }
5022
- const updatedConfig = {
5023
- ...existingConfig,
5103
+ const { updateCodexApiFields } = await Promise.resolve().then(function () { return codexTomlUpdater; });
5104
+ updateCodexApiFields({
5024
5105
  model: targetModel,
5025
5106
  modelProvider: providerId,
5026
5107
  modelProviderCommented: false
5027
5108
  // Ensure it's not commented
5028
- };
5029
- writeCodexConfig(updatedConfig);
5109
+ });
5030
5110
  const auth = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
5031
5111
  const envValue = auth[provider.tempEnvKey] || null;
5032
5112
  auth.OPENAI_API_KEY = envValue;
@@ -5063,7 +5143,6 @@ const codex = {
5063
5143
  needsEnvKeyMigration: needsEnvKeyMigration,
5064
5144
  parseCodexConfig: parseCodexConfig,
5065
5145
  readCodexConfig: readCodexConfig,
5066
- renderCodexConfig: renderCodexConfig,
5067
5146
  runCodexFullInit: runCodexFullInit,
5068
5147
  runCodexSystemPromptSelection: runCodexSystemPromptSelection,
5069
5148
  runCodexUninstall: runCodexUninstall,
@@ -5073,8 +5152,7 @@ const codex = {
5073
5152
  switchCodexProvider: switchCodexProvider,
5074
5153
  switchToOfficialLogin: switchToOfficialLogin,
5075
5154
  switchToProvider: switchToProvider,
5076
- writeAuthFile: writeAuthFile,
5077
- writeCodexConfig: writeCodexConfig
5155
+ writeAuthFile: writeAuthFile
5078
5156
  };
5079
5157
 
5080
5158
  const CODE_TYPE_ABBREVIATIONS = {
@@ -5267,7 +5345,7 @@ async function copyOutputStyles(selectedStyles, lang) {
5267
5345
  const currentFilePath = fileURLToPath(import.meta.url);
5268
5346
  const distDir = dirname(dirname(currentFilePath));
5269
5347
  const rootDir = dirname(distDir);
5270
- const templateDir = join(rootDir, "templates", "claude-code", lang, "output-styles");
5348
+ const templateDir = join(rootDir, "templates", "common", "output-styles", lang);
5271
5349
  for (const styleId of selectedStyles) {
5272
5350
  const style = OUTPUT_STYLES.find((s) => s.id === styleId);
5273
5351
  if (!style || !style.isCustom || !style.filePath) {
@@ -6415,6 +6493,7 @@ function getRootDir() {
6415
6493
  return dirname(distDir);
6416
6494
  }
6417
6495
  const DEFAULT_CODE_TOOL_TEMPLATE = "claude-code";
6496
+ const COMMON_TEMPLATE_CATEGORIES = ["git", "sixStep"];
6418
6497
  async function selectAndInstallWorkflows(configLang, preselectedWorkflows) {
6419
6498
  ensureI18nInitialized();
6420
6499
  const workflows = getOrderedWorkflows();
@@ -6474,7 +6553,16 @@ async function installWorkflowWithDependencies(config, configLang) {
6474
6553
  await mkdir(commandsDir, { recursive: true });
6475
6554
  }
6476
6555
  for (const commandFile of config.commands) {
6477
- const commandSource = join(
6556
+ const isCommonTemplate = COMMON_TEMPLATE_CATEGORIES.includes(config.category);
6557
+ const commandSource = isCommonTemplate ? join(
6558
+ rootDir,
6559
+ "templates",
6560
+ "common",
6561
+ "workflow",
6562
+ config.category,
6563
+ configLang,
6564
+ commandFile
6565
+ ) : join(
6478
6566
  rootDir,
6479
6567
  "templates",
6480
6568
  DEFAULT_CODE_TOOL_TEMPLATE,
@@ -7482,7 +7570,7 @@ async function convertToCodexProvider(config) {
7482
7570
  const displayName = config.name || config.provider || "custom";
7483
7571
  const providerId = displayName.toLowerCase().replace(/[^a-z0-9]/g, "-");
7484
7572
  let baseUrl = config.url || API_DEFAULT_URL;
7485
- let model = config.primaryModel || "gpt-5-codex";
7573
+ let model = config.primaryModel || "gpt-5.2";
7486
7574
  let wireApi = "responses";
7487
7575
  if (config.provider && config.provider !== "custom") {
7488
7576
  const { getProviderPreset } = await import('./api-providers.mjs');
@@ -7582,4 +7670,4 @@ async function openSettingsJson() {
7582
7670
  }
7583
7671
  }
7584
7672
 
7585
- 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 };
7673
+ 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, updatePromptOnly 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, writeAuthFile as aA, updateZcfConfig as aB, changeLanguage as aC, readZcfConfig as aD, configureOutputStyle as aE, isWindows as aF, selectMcpServices as aG, getMcpServices as aH, isCcrInstalled as aI, installCcr as aJ, setupCcrConfiguration as aK, modifyApiConfigPartially as aL, formatApiKeyDisplay as aM, readCcrConfig as aN, configureCcrFeature as aO, handleExitPromptError as aP, handleGeneralError as aQ, COMETIX_COMMAND_NAME as aR, COMETIX_COMMANDS as aS, installCometixLine as aT, checkAndUpdateTools as aU, runCodexUpdate as aV, resolveCodeType as aW, writeJsonConfig as aX, displayBanner as aY, version as aZ, resolveAiOutputLanguage 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, selectAndInstallWorkflows as b0, checkClaudeCodeVersionAndPrompt as b1, displayBannerWithInfo as b2, runCodexUninstall as b3, configureCodexMcp as b4, configureCodexApi as b5, runCodexWorkflowImportWithLanguageSelection as b6, runCodexFullInit as b7, switchCodexProvider as b8, listCodexProviders as b9, switchToOfficialLogin as ba, switchToProvider as bb, readZcfConfigAsync as bc, initI18n as bd, selectScriptLanguage as be, index as bf, fsOperations as bg, jsonConfig as bh, claudeConfig as bi, config$1 as bj, config as bk, prompts as bl, codexTomlUpdater 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 };