zcf 2.12.13 → 3.0.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 (67) hide show
  1. package/README.md +94 -4
  2. package/dist/chunks/codex-config-switch.mjs +419 -0
  3. package/dist/chunks/codex-uninstaller.mjs +404 -0
  4. package/dist/chunks/simple-config.mjs +1869 -374
  5. package/dist/cli.mjs +672 -206
  6. package/dist/i18n/locales/en/cli.json +1 -0
  7. package/dist/i18n/locales/en/codex.json +102 -0
  8. package/dist/i18n/locales/en/common.json +4 -1
  9. package/dist/i18n/locales/en/configuration.json +10 -4
  10. package/dist/i18n/locales/en/language.json +8 -2
  11. package/dist/i18n/locales/en/mcp.json +4 -3
  12. package/dist/i18n/locales/en/menu.json +20 -0
  13. package/dist/i18n/locales/en/uninstall.json +0 -4
  14. package/dist/i18n/locales/zh-CN/cli.json +1 -0
  15. package/dist/i18n/locales/zh-CN/codex.json +102 -0
  16. package/dist/i18n/locales/zh-CN/common.json +4 -1
  17. package/dist/i18n/locales/zh-CN/configuration.json +10 -4
  18. package/dist/i18n/locales/zh-CN/language.json +8 -2
  19. package/dist/i18n/locales/zh-CN/mcp.json +4 -3
  20. package/dist/i18n/locales/zh-CN/menu.json +20 -0
  21. package/dist/i18n/locales/zh-CN/uninstall.json +0 -4
  22. package/dist/index.d.mts +11 -3
  23. package/dist/index.d.ts +11 -3
  24. package/dist/index.mjs +2 -1
  25. package/dist/shared/zcf.DGjQxTq_.mjs +34 -0
  26. package/package.json +11 -10
  27. package/templates/{common → claude-code/common}/settings.json +2 -1
  28. package/templates/codex/common/config.toml +0 -0
  29. package/templates/codex/en/system-prompt/engineer-professional.md +87 -0
  30. package/templates/codex/en/system-prompt/laowang-engineer.md +126 -0
  31. package/templates/codex/en/system-prompt/nekomata-engineer.md +119 -0
  32. package/templates/codex/en/workflow/sixStep/prompts/workflow.md +211 -0
  33. package/templates/codex/zh-CN/system-prompt/engineer-professional.md +88 -0
  34. package/templates/codex/zh-CN/system-prompt/laowang-engineer.md +126 -0
  35. package/templates/codex/zh-CN/system-prompt/nekomata-engineer.md +119 -0
  36. package/templates/codex/zh-CN/workflow/sixStep/prompts/workflow.md +211 -0
  37. /package/templates/{CLAUDE.md → claude-code/CLAUDE.md} +0 -0
  38. /package/templates/{en → claude-code/en}/output-styles/engineer-professional.md +0 -0
  39. /package/templates/{en → claude-code/en}/output-styles/laowang-engineer.md +0 -0
  40. /package/templates/{en → claude-code/en}/output-styles/nekomata-engineer.md +0 -0
  41. /package/templates/{en → claude-code/en}/workflow/bmad/commands/bmad-init.md +0 -0
  42. /package/templates/{en → claude-code/en}/workflow/common/agents/get-current-datetime.md +0 -0
  43. /package/templates/{en → claude-code/en}/workflow/common/agents/init-architect.md +0 -0
  44. /package/templates/{en → claude-code/en}/workflow/common/commands/init-project.md +0 -0
  45. /package/templates/{en → claude-code/en}/workflow/git/commands/git-cleanBranches.md +0 -0
  46. /package/templates/{en → claude-code/en}/workflow/git/commands/git-commit.md +0 -0
  47. /package/templates/{en → claude-code/en}/workflow/git/commands/git-rollback.md +0 -0
  48. /package/templates/{en → claude-code/en}/workflow/git/commands/git-worktree.md +0 -0
  49. /package/templates/{en → claude-code/en}/workflow/plan/agents/planner.md +0 -0
  50. /package/templates/{en → claude-code/en}/workflow/plan/agents/ui-ux-designer.md +0 -0
  51. /package/templates/{en → claude-code/en}/workflow/plan/commands/feat.md +0 -0
  52. /package/templates/{en → claude-code/en}/workflow/sixStep/commands/workflow.md +0 -0
  53. /package/templates/{zh-CN → claude-code/zh-CN}/output-styles/engineer-professional.md +0 -0
  54. /package/templates/{zh-CN → claude-code/zh-CN}/output-styles/laowang-engineer.md +0 -0
  55. /package/templates/{zh-CN → claude-code/zh-CN}/output-styles/nekomata-engineer.md +0 -0
  56. /package/templates/{zh-CN → claude-code/zh-CN}/workflow/bmad/commands/bmad-init.md +0 -0
  57. /package/templates/{zh-CN → claude-code/zh-CN}/workflow/common/agents/get-current-datetime.md +0 -0
  58. /package/templates/{zh-CN → claude-code/zh-CN}/workflow/common/agents/init-architect.md +0 -0
  59. /package/templates/{zh-CN → claude-code/zh-CN}/workflow/common/commands/init-project.md +0 -0
  60. /package/templates/{zh-CN → claude-code/zh-CN}/workflow/git/commands/git-cleanBranches.md +0 -0
  61. /package/templates/{zh-CN → claude-code/zh-CN}/workflow/git/commands/git-commit.md +0 -0
  62. /package/templates/{zh-CN → claude-code/zh-CN}/workflow/git/commands/git-rollback.md +0 -0
  63. /package/templates/{zh-CN → claude-code/zh-CN}/workflow/git/commands/git-worktree.md +0 -0
  64. /package/templates/{zh-CN → claude-code/zh-CN}/workflow/plan/agents/planner.md +0 -0
  65. /package/templates/{zh-CN → claude-code/zh-CN}/workflow/plan/agents/ui-ux-designer.md +0 -0
  66. /package/templates/{zh-CN → claude-code/zh-CN}/workflow/plan/commands/feat.md +0 -0
  67. /package/templates/{zh-CN → claude-code/zh-CN}/workflow/sixStep/commands/workflow.md +0 -0
@@ -1,4 +1,4 @@
1
- import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync, rmSync, rmdirSync, readdirSync, statSync, unlinkSync } from 'node:fs';
1
+ import { existsSync, readFileSync, mkdirSync, writeFileSync, copyFileSync, rmSync, rmdirSync, readdirSync, statSync, unlinkSync, renameSync } from 'node:fs';
2
2
  import process from 'node:process';
3
3
  import ansis from 'ansis';
4
4
  import inquirer from 'inquirer';
@@ -10,12 +10,13 @@ import { dirname, join } from 'pathe';
10
10
  import { fileURLToPath } from 'node:url';
11
11
  import ora from 'ora';
12
12
  import semver from 'semver';
13
- import { exec } from 'tinyexec';
13
+ import { parse, stringify } from 'smol-toml';
14
+ import { exec, x } from 'tinyexec';
14
15
  import { rm, mkdir, copyFile as copyFile$1 } from 'node:fs/promises';
15
16
  import i18next from 'i18next';
16
17
  import Backend from 'i18next-fs-backend';
17
18
 
18
- const version = "2.12.13";
19
+ const version = "3.0.1";
19
20
  const homepage = "https://github.com/UfoMiao/zcf";
20
21
 
21
22
  const i18n = i18next.createInstance();
@@ -34,7 +35,8 @@ const NAMESPACES = [
34
35
  "tools",
35
36
  "uninstall",
36
37
  "updater",
37
- "workflow"
38
+ "workflow",
39
+ "codex"
38
40
  ];
39
41
  function ensureI18nInitialized() {
40
42
  if (!i18n.isInitialized) {
@@ -128,7 +130,7 @@ const MCP_SERVICE_CONFIGS = [
128
130
  config: {
129
131
  type: "stdio",
130
132
  command: "npx",
131
- args: ["-y", "@upstash/context7-mcp"],
133
+ args: ["-y", "@upstash/context7-mcp@latest"],
132
134
  env: {}
133
135
  }
134
136
  },
@@ -183,7 +185,7 @@ const MCP_SERVICE_CONFIGS = [
183
185
  config: {
184
186
  type: "stdio",
185
187
  command: "npx",
186
- args: ["-y", "exa-mcp-server"],
188
+ args: ["-y", "exa-mcp-server@latest"],
187
189
  env: {
188
190
  EXA_API_KEY: "YOUR_EXA_API_KEY"
189
191
  }
@@ -215,8 +217,8 @@ async function getMcpServices() {
215
217
  },
216
218
  {
217
219
  id: "Playwright",
218
- name: i18n.t("mcp:services.Playwright.name"),
219
- description: i18n.t("mcp:services.Playwright.description")
220
+ name: i18n.t("mcp:services.playwright.name"),
221
+ description: i18n.t("mcp:services.playwright.description")
220
222
  },
221
223
  {
222
224
  id: "exa",
@@ -353,8 +355,17 @@ const CLAUDE_DIR = join(homedir(), ".claude");
353
355
  const SETTINGS_FILE = join(CLAUDE_DIR, "settings.json");
354
356
  const CLAUDE_MD_FILE = join(CLAUDE_DIR, "CLAUDE.md");
355
357
  const ClAUDE_CONFIG_FILE = join(homedir(), ".claude.json");
356
- const LEGACY_ZCF_CONFIG_FILE = join(homedir(), ".zcf.json");
357
- const ZCF_CONFIG_FILE = join(CLAUDE_DIR, ".zcf-config.json");
358
+ const ZCF_CONFIG_DIR = join(homedir(), ".ufomiao", "zcf");
359
+ const ZCF_CONFIG_FILE = join(ZCF_CONFIG_DIR, "config.toml");
360
+ const LEGACY_ZCF_CONFIG_FILES = [
361
+ join(CLAUDE_DIR, ".zcf-config.json"),
362
+ join(homedir(), ".zcf.json")
363
+ ];
364
+ const CODE_TOOL_TYPES = ["claude-code", "codex"];
365
+ const DEFAULT_CODE_TOOL_TYPE = "claude-code";
366
+ function isCodeToolType(value) {
367
+ return CODE_TOOL_TYPES.includes(value);
368
+ }
358
369
  const SUPPORTED_LANGS = ["zh-CN", "en"];
359
370
  const LANG_LABELS = {
360
371
  "zh-CN": "\u7B80\u4F53\u4E2D\u6587",
@@ -378,6 +389,24 @@ function getAiOutputLanguageLabel(lang) {
378
389
  return lang;
379
390
  }
380
391
 
392
+ const constants = {
393
+ __proto__: null,
394
+ AI_OUTPUT_LANGUAGES: AI_OUTPUT_LANGUAGES,
395
+ CLAUDE_DIR: CLAUDE_DIR,
396
+ CLAUDE_MD_FILE: CLAUDE_MD_FILE,
397
+ CODE_TOOL_TYPES: CODE_TOOL_TYPES,
398
+ ClAUDE_CONFIG_FILE: ClAUDE_CONFIG_FILE,
399
+ DEFAULT_CODE_TOOL_TYPE: DEFAULT_CODE_TOOL_TYPE,
400
+ LANG_LABELS: LANG_LABELS,
401
+ LEGACY_ZCF_CONFIG_FILES: LEGACY_ZCF_CONFIG_FILES,
402
+ SETTINGS_FILE: SETTINGS_FILE,
403
+ SUPPORTED_LANGS: SUPPORTED_LANGS,
404
+ ZCF_CONFIG_DIR: ZCF_CONFIG_DIR,
405
+ ZCF_CONFIG_FILE: ZCF_CONFIG_FILE,
406
+ getAiOutputLanguageLabel: getAiOutputLanguageLabel,
407
+ isCodeToolType: isCodeToolType
408
+ };
409
+
381
410
  function getDisplayWidth(str) {
382
411
  let width = 0;
383
412
  for (const char of str) {
@@ -398,7 +427,8 @@ function displayBanner(subtitle) {
398
427
  ensureI18nInitialized();
399
428
  const defaultSubtitle = i18n.t("cli:banner.subtitle");
400
429
  const subtitleText = subtitle || defaultSubtitle;
401
- const paddedSubtitle = padToDisplayWidth(subtitleText, 60);
430
+ const paddedSubtitle = padToDisplayWidth(subtitleText, 30);
431
+ const paddedTitle = padToDisplayWidth("Zero-Config Code Flow", 60);
402
432
  console.log(
403
433
  ansis.cyan.bold(`
404
434
  \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
@@ -408,10 +438,9 @@ function displayBanner(subtitle) {
408
438
  \u2551 \u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2557 \u2551
409
439
  \u2551 \u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D \u2551
410
440
  \u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2551
411
- \u2551 \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u2551
441
+ \u2551 \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D ${ansis.gray(paddedSubtitle)} \u2551
412
442
  \u2551 \u2551
413
- \u2551 ${ansis.white.bold("Zero-Config Claude-Code Flow")} \u2551
414
- \u2551 ${ansis.gray(paddedSubtitle)} \u2551
443
+ \u2551 ${ansis.white.bold(paddedTitle)} \u2551
415
444
  \u2551 \u2551
416
445
  \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
417
446
  `)
@@ -423,6 +452,118 @@ function displayBannerWithInfo(subtitle) {
423
452
  `));
424
453
  }
425
454
 
455
+ function getPlatform() {
456
+ const p = platform();
457
+ if (p === "win32")
458
+ return "windows";
459
+ if (p === "darwin")
460
+ return "macos";
461
+ return "linux";
462
+ }
463
+ function isTermux() {
464
+ return !!(process.env.PREFIX && process.env.PREFIX.includes("com.termux")) || !!process.env.TERMUX_VERSION || existsSync("/data/data/com.termux/files/usr");
465
+ }
466
+ function getTermuxPrefix() {
467
+ return process.env.PREFIX || "/data/data/com.termux/files/usr";
468
+ }
469
+ function isWindows() {
470
+ return getPlatform() === "windows";
471
+ }
472
+ function isWSL() {
473
+ if (process.env.WSL_DISTRO_NAME) {
474
+ return true;
475
+ }
476
+ if (existsSync("/proc/version")) {
477
+ try {
478
+ const version = readFileSync("/proc/version", "utf8");
479
+ if (version.includes("Microsoft") || version.includes("WSL")) {
480
+ return true;
481
+ }
482
+ } catch {
483
+ }
484
+ }
485
+ if (existsSync("/mnt/c")) {
486
+ return true;
487
+ }
488
+ return false;
489
+ }
490
+ function getWSLDistro() {
491
+ if (process.env.WSL_DISTRO_NAME) {
492
+ return process.env.WSL_DISTRO_NAME;
493
+ }
494
+ if (existsSync("/etc/os-release")) {
495
+ try {
496
+ const osRelease = readFileSync("/etc/os-release", "utf8");
497
+ const nameMatch = osRelease.match(/^PRETTY_NAME="(.+)"$/m);
498
+ if (nameMatch) {
499
+ return nameMatch[1];
500
+ }
501
+ } catch {
502
+ }
503
+ }
504
+ return null;
505
+ }
506
+ function getWSLInfo() {
507
+ if (!isWSL()) {
508
+ return null;
509
+ }
510
+ let version = null;
511
+ if (existsSync("/proc/version")) {
512
+ try {
513
+ version = readFileSync("/proc/version", "utf8").trim();
514
+ } catch {
515
+ }
516
+ }
517
+ return {
518
+ isWSL: true,
519
+ distro: getWSLDistro(),
520
+ version
521
+ };
522
+ }
523
+ function getMcpCommand() {
524
+ if (isWindows()) {
525
+ return ["cmd", "/c", "npx"];
526
+ }
527
+ return ["npx"];
528
+ }
529
+ async function commandExists(command) {
530
+ try {
531
+ const cmd = getPlatform() === "windows" ? "where" : "which";
532
+ const res = await exec(cmd, [command]);
533
+ if (res.exitCode === 0) {
534
+ return true;
535
+ }
536
+ } catch {
537
+ }
538
+ if (isTermux()) {
539
+ const termuxPrefix = getTermuxPrefix();
540
+ const possiblePaths = [
541
+ `${termuxPrefix}/bin/${command}`,
542
+ `${termuxPrefix}/usr/bin/${command}`,
543
+ `/data/data/com.termux/files/usr/bin/${command}`
544
+ ];
545
+ for (const path of possiblePaths) {
546
+ if (existsSync(path)) {
547
+ return true;
548
+ }
549
+ }
550
+ }
551
+ if (getPlatform() !== "windows") {
552
+ const commonPaths = [
553
+ `/usr/local/bin/${command}`,
554
+ `/usr/bin/${command}`,
555
+ `/bin/${command}`,
556
+ `${process.env.HOME}/.local/bin/${command}`
557
+ ];
558
+ for (const path of commonPaths) {
559
+ if (existsSync(path)) {
560
+ return true;
561
+ }
562
+ }
563
+ }
564
+ return false;
565
+ }
566
+
426
567
  class FileSystemError extends Error {
427
568
  constructor(message, path, cause) {
428
569
  super(message);
@@ -546,7 +687,7 @@ async function isExecutable(path) {
546
687
  if (!stats.isFile()) {
547
688
  return false;
548
689
  }
549
- if (process.platform !== "win32") {
690
+ if (!isWindows()) {
550
691
  const mode = stats.mode;
551
692
  const executePermission = 73;
552
693
  return (mode & executePermission) !== 0;
@@ -593,6 +734,23 @@ async function remove(path) {
593
734
  }
594
735
  }
595
736
 
737
+ const fsOperations = {
738
+ __proto__: null,
739
+ FileSystemError: FileSystemError,
740
+ copyDir: copyDir,
741
+ copyFile: copyFile,
742
+ ensureDir: ensureDir,
743
+ ensureFileDir: ensureFileDir,
744
+ exists: exists,
745
+ getStats: getStats,
746
+ isExecutable: isExecutable,
747
+ readDir: readDir,
748
+ readFile: readFile,
749
+ remove: remove,
750
+ removeFile: removeFile,
751
+ writeFile: writeFile
752
+ };
753
+
596
754
  function readJsonConfig(path, options = {}) {
597
755
  const { defaultValue = null, validate, sanitize } = options;
598
756
  if (!exists(path)) {
@@ -701,118 +859,6 @@ function deepClone(obj) {
701
859
  return obj;
702
860
  }
703
861
 
704
- function getPlatform() {
705
- const p = platform();
706
- if (p === "win32")
707
- return "windows";
708
- if (p === "darwin")
709
- return "macos";
710
- return "linux";
711
- }
712
- function isTermux() {
713
- return !!(process.env.PREFIX && process.env.PREFIX.includes("com.termux")) || !!process.env.TERMUX_VERSION || existsSync("/data/data/com.termux/files/usr");
714
- }
715
- function getTermuxPrefix() {
716
- return process.env.PREFIX || "/data/data/com.termux/files/usr";
717
- }
718
- function isWindows() {
719
- return getPlatform() === "windows";
720
- }
721
- function isWSL() {
722
- if (process.env.WSL_DISTRO_NAME) {
723
- return true;
724
- }
725
- if (existsSync("/proc/version")) {
726
- try {
727
- const version = readFileSync("/proc/version", "utf8");
728
- if (version.includes("Microsoft") || version.includes("WSL")) {
729
- return true;
730
- }
731
- } catch {
732
- }
733
- }
734
- if (existsSync("/mnt/c")) {
735
- return true;
736
- }
737
- return false;
738
- }
739
- function getWSLDistro() {
740
- if (process.env.WSL_DISTRO_NAME) {
741
- return process.env.WSL_DISTRO_NAME;
742
- }
743
- if (existsSync("/etc/os-release")) {
744
- try {
745
- const osRelease = readFileSync("/etc/os-release", "utf8");
746
- const nameMatch = osRelease.match(/^PRETTY_NAME="(.+)"$/m);
747
- if (nameMatch) {
748
- return nameMatch[1];
749
- }
750
- } catch {
751
- }
752
- }
753
- return null;
754
- }
755
- function getWSLInfo() {
756
- if (!isWSL()) {
757
- return null;
758
- }
759
- let version = null;
760
- if (existsSync("/proc/version")) {
761
- try {
762
- version = readFileSync("/proc/version", "utf8").trim();
763
- } catch {
764
- }
765
- }
766
- return {
767
- isWSL: true,
768
- distro: getWSLDistro(),
769
- version
770
- };
771
- }
772
- function getMcpCommand() {
773
- if (isWindows()) {
774
- return ["cmd", "/c", "npx"];
775
- }
776
- return ["npx"];
777
- }
778
- async function commandExists(command) {
779
- try {
780
- const cmd = getPlatform() === "windows" ? "where" : "which";
781
- const res = await exec(cmd, [command]);
782
- if (res.exitCode === 0) {
783
- return true;
784
- }
785
- } catch {
786
- }
787
- if (isTermux()) {
788
- const termuxPrefix = getTermuxPrefix();
789
- const possiblePaths = [
790
- `${termuxPrefix}/bin/${command}`,
791
- `${termuxPrefix}/usr/bin/${command}`,
792
- `/data/data/com.termux/files/usr/bin/${command}`
793
- ];
794
- for (const path of possiblePaths) {
795
- if (existsSync(path)) {
796
- return true;
797
- }
798
- }
799
- }
800
- if (getPlatform() !== "windows") {
801
- const commonPaths = [
802
- `/usr/local/bin/${command}`,
803
- `/usr/bin/${command}`,
804
- `/bin/${command}`,
805
- `${process.env.HOME}/.local/bin/${command}`
806
- ];
807
- for (const path of commonPaths) {
808
- if (existsSync(path)) {
809
- return true;
810
- }
811
- }
812
- }
813
- return false;
814
- }
815
-
816
862
  function getMcpConfigPath() {
817
863
  return ClAUDE_CONFIG_FILE;
818
864
  }
@@ -1008,7 +1054,7 @@ function copyConfigFiles(onlyMd = false) {
1008
1054
  const currentFilePath = fileURLToPath(import.meta.url);
1009
1055
  const distDir = dirname(dirname(currentFilePath));
1010
1056
  const rootDir = dirname(distDir);
1011
- const baseTemplateDir = join(rootDir, "templates");
1057
+ const baseTemplateDir = join(rootDir, "templates", "claude-code");
1012
1058
  if (!onlyMd) {
1013
1059
  const baseSettingsPath = join(baseTemplateDir, "common", "settings.json");
1014
1060
  const destSettingsPath = join(CLAUDE_DIR, "settings.json");
@@ -1022,7 +1068,7 @@ function getDefaultSettings() {
1022
1068
  const currentFilePath = fileURLToPath(import.meta.url);
1023
1069
  const distDir = dirname(dirname(currentFilePath));
1024
1070
  const rootDir = dirname(distDir);
1025
- const templateSettingsPath = join(rootDir, "templates", "common", "settings.json");
1071
+ const templateSettingsPath = join(rootDir, "templates", "claude-code", "common", "settings.json");
1026
1072
  return readJsonConfig(templateSettingsPath) || {};
1027
1073
  } catch (error) {
1028
1074
  console.error("Failed to read template settings", error);
@@ -1442,9 +1488,9 @@ async function configureCcrWithPreset(preset) {
1442
1488
  if (preset.requiresApiKey) {
1443
1489
  try {
1444
1490
  const { apiKey } = await inquirer.prompt({
1445
- type: "input",
1491
+ type: "password",
1446
1492
  name: "apiKey",
1447
- message: i18n.t("ccr:enterApiKeyForProvider").replace("{provider}", preset.name),
1493
+ message: i18n.t("ccr:enterApiKeyForProvider").replace("{provider}", preset.name) + i18n.t("common:inputHidden"),
1448
1494
  validate: async (value) => !!value || i18n.t("api:keyRequired")
1449
1495
  });
1450
1496
  provider.api_key = apiKey;
@@ -1987,29 +2033,1613 @@ async function installCcr() {
1987
2033
  }
1988
2034
  }
1989
2035
 
1990
- function getPlatformStatusLineConfig() {
1991
- return {
1992
- type: "command",
1993
- command: isWindows() ? "%USERPROFILE%\\.claude\\ccline\\ccline.exe" : "~/.claude/ccline/ccline",
1994
- padding: 0
1995
- };
1996
- }
1997
-
1998
- function addCCometixLineConfig() {
1999
- try {
2000
- const statusLineConfig = getPlatformStatusLineConfig();
2001
- let settings = {};
2002
- if (exists(SETTINGS_FILE)) {
2003
- settings = readJsonConfig(SETTINGS_FILE) || {};
2004
- }
2005
- settings.statusLine = statusLineConfig;
2006
- writeJsonConfig(SETTINGS_FILE, settings);
2007
- return true;
2008
- } catch (error) {
2009
- console.error("Failed to add CCometixLine configuration:", error);
2010
- return false;
2011
- }
2012
- }
2036
+ async function selectMcpServices() {
2037
+ ensureI18nInitialized();
2038
+ const mcpServices = await getMcpServices();
2039
+ const choices = mcpServices.map((service) => ({
2040
+ name: `${service.name} - ${ansis.gray(service.description)}`,
2041
+ value: service.id,
2042
+ selected: false
2043
+ }));
2044
+ const { services } = await inquirer.prompt({
2045
+ type: "checkbox",
2046
+ name: "services",
2047
+ message: `${i18n.t("mcp:selectMcpServices")}${i18n.t("common:multiSelectHint")}`,
2048
+ choices
2049
+ });
2050
+ if (services === void 0) {
2051
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2052
+ return void 0;
2053
+ }
2054
+ return services;
2055
+ }
2056
+
2057
+ function addNumbersToChoices(choices, startFrom = 1, format = (n) => `${n}. `) {
2058
+ let currentNumber = startFrom;
2059
+ return choices.map((choice) => {
2060
+ if (choice.disabled) {
2061
+ return choice;
2062
+ }
2063
+ const numbered = {
2064
+ ...choice,
2065
+ name: `${format(currentNumber)}${choice.name}`
2066
+ };
2067
+ currentNumber++;
2068
+ return numbered;
2069
+ });
2070
+ }
2071
+
2072
+ function isSupportedLang(value) {
2073
+ return SUPPORTED_LANGS.includes(value);
2074
+ }
2075
+ function sanitizePreferredLang(lang) {
2076
+ return isSupportedLang(lang) ? lang : "en";
2077
+ }
2078
+ function sanitizeCodeToolType(codeTool) {
2079
+ return isCodeToolType(codeTool) ? codeTool : DEFAULT_CODE_TOOL_TYPE;
2080
+ }
2081
+ function readTomlConfig(configPath) {
2082
+ try {
2083
+ if (!exists(configPath)) {
2084
+ return null;
2085
+ }
2086
+ const content = readFile(configPath);
2087
+ const parsed = parse(content);
2088
+ return parsed;
2089
+ } catch {
2090
+ return null;
2091
+ }
2092
+ }
2093
+ function writeTomlConfig(configPath, config) {
2094
+ try {
2095
+ const configDir = dirname(configPath);
2096
+ ensureDir(configDir);
2097
+ const tomlContent = stringify(config);
2098
+ writeFile(configPath, tomlContent);
2099
+ } catch {
2100
+ }
2101
+ }
2102
+ function createDefaultTomlConfig(preferredLang = "en", claudeCodeInstallType = "global") {
2103
+ return {
2104
+ version: "1.0.0",
2105
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
2106
+ general: {
2107
+ preferredLang,
2108
+ templateLang: preferredLang,
2109
+ // Default templateLang to preferredLang for new installations
2110
+ aiOutputLang: preferredLang === "zh-CN" ? "zh-CN" : void 0,
2111
+ currentTool: DEFAULT_CODE_TOOL_TYPE
2112
+ },
2113
+ claudeCode: {
2114
+ enabled: true,
2115
+ outputStyles: ["engineer-professional"],
2116
+ defaultOutputStyle: "engineer-professional",
2117
+ installType: claudeCodeInstallType
2118
+ },
2119
+ codex: {
2120
+ enabled: false,
2121
+ systemPromptStyle: "engineer-professional"
2122
+ }
2123
+ };
2124
+ }
2125
+ function migrateFromJsonConfig(jsonConfig) {
2126
+ const claudeCodeInstallType = jsonConfig.claudeCodeInstallation?.type || "global";
2127
+ const defaultConfig = createDefaultTomlConfig("en", claudeCodeInstallType);
2128
+ const tomlConfig = {
2129
+ version: jsonConfig.version || defaultConfig.version,
2130
+ lastUpdated: jsonConfig.lastUpdated || (/* @__PURE__ */ new Date()).toISOString(),
2131
+ general: {
2132
+ preferredLang: jsonConfig.preferredLang || defaultConfig.general.preferredLang,
2133
+ templateLang: jsonConfig.templateLang || jsonConfig.preferredLang || defaultConfig.general.preferredLang,
2134
+ // Backward compatibility: use preferredLang as default
2135
+ aiOutputLang: jsonConfig.aiOutputLang || defaultConfig.general.aiOutputLang,
2136
+ currentTool: jsonConfig.codeToolType || defaultConfig.general.currentTool
2137
+ },
2138
+ claudeCode: {
2139
+ enabled: jsonConfig.codeToolType === "claude-code",
2140
+ outputStyles: jsonConfig.outputStyles || defaultConfig.claudeCode.outputStyles,
2141
+ defaultOutputStyle: jsonConfig.defaultOutputStyle || defaultConfig.claudeCode.defaultOutputStyle,
2142
+ installType: claudeCodeInstallType
2143
+ },
2144
+ codex: {
2145
+ enabled: jsonConfig.codeToolType === "codex",
2146
+ systemPromptStyle: jsonConfig.systemPromptStyle || defaultConfig.codex.systemPromptStyle
2147
+ }
2148
+ };
2149
+ return tomlConfig;
2150
+ }
2151
+ function updateTomlConfig(configPath, updates) {
2152
+ const existingConfig = readTomlConfig(configPath) || createDefaultTomlConfig();
2153
+ const updatedConfig = {
2154
+ version: updates.version || existingConfig.version,
2155
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
2156
+ general: {
2157
+ ...existingConfig.general,
2158
+ ...updates.general
2159
+ },
2160
+ claudeCode: {
2161
+ ...existingConfig.claudeCode,
2162
+ ...updates.claudeCode
2163
+ },
2164
+ codex: {
2165
+ ...existingConfig.codex,
2166
+ ...updates.codex
2167
+ }
2168
+ };
2169
+ writeTomlConfig(configPath, updatedConfig);
2170
+ return updatedConfig;
2171
+ }
2172
+ function convertTomlToLegacyConfig(tomlConfig) {
2173
+ return {
2174
+ version: tomlConfig.version,
2175
+ preferredLang: tomlConfig.general.preferredLang,
2176
+ templateLang: tomlConfig.general.templateLang,
2177
+ aiOutputLang: tomlConfig.general.aiOutputLang,
2178
+ outputStyles: tomlConfig.claudeCode.outputStyles,
2179
+ defaultOutputStyle: tomlConfig.claudeCode.defaultOutputStyle,
2180
+ codeToolType: tomlConfig.general.currentTool,
2181
+ lastUpdated: tomlConfig.lastUpdated
2182
+ };
2183
+ }
2184
+ function convertLegacyToTomlConfig(legacyConfig) {
2185
+ return migrateFromJsonConfig(legacyConfig);
2186
+ }
2187
+ function normalizeZcfConfig(config) {
2188
+ if (!config) {
2189
+ return null;
2190
+ }
2191
+ return {
2192
+ version: typeof config.version === "string" ? config.version : "1.0.0",
2193
+ preferredLang: sanitizePreferredLang(config.preferredLang),
2194
+ templateLang: config.templateLang ? sanitizePreferredLang(config.templateLang) : void 0,
2195
+ aiOutputLang: config.aiOutputLang,
2196
+ outputStyles: Array.isArray(config.outputStyles) ? config.outputStyles : void 0,
2197
+ defaultOutputStyle: typeof config.defaultOutputStyle === "string" ? config.defaultOutputStyle : void 0,
2198
+ codeToolType: sanitizeCodeToolType(config.codeToolType),
2199
+ lastUpdated: typeof config.lastUpdated === "string" ? config.lastUpdated : (/* @__PURE__ */ new Date()).toISOString()
2200
+ };
2201
+ }
2202
+ function migrateZcfConfigIfNeeded() {
2203
+ const target = ZCF_CONFIG_FILE;
2204
+ const removed = [];
2205
+ const targetExists = existsSync(target);
2206
+ const legacySources = LEGACY_ZCF_CONFIG_FILES.filter((path) => existsSync(path));
2207
+ if (!targetExists && legacySources.length > 0) {
2208
+ const source = legacySources[0];
2209
+ if (!existsSync(ZCF_CONFIG_DIR)) {
2210
+ mkdirSync(ZCF_CONFIG_DIR, { recursive: true });
2211
+ }
2212
+ renameSync(source, target);
2213
+ for (const leftover of legacySources.slice(1)) {
2214
+ try {
2215
+ rmSync(leftover, { force: true });
2216
+ removed.push(leftover);
2217
+ } catch {
2218
+ }
2219
+ }
2220
+ return { migrated: true, source, target, removed };
2221
+ }
2222
+ if (targetExists && legacySources.length > 0) {
2223
+ for (const source of legacySources) {
2224
+ try {
2225
+ rmSync(source, { force: true });
2226
+ removed.push(source);
2227
+ } catch {
2228
+ }
2229
+ }
2230
+ return { migrated: false, target, removed };
2231
+ }
2232
+ return { migrated: false, target, removed };
2233
+ }
2234
+ function readZcfConfig() {
2235
+ migrateZcfConfigIfNeeded();
2236
+ const tomlConfig = readTomlConfig(ZCF_CONFIG_FILE);
2237
+ if (tomlConfig) {
2238
+ return convertTomlToLegacyConfig(tomlConfig);
2239
+ }
2240
+ const raw = readJsonConfig(ZCF_CONFIG_FILE.replace(".toml", ".json"));
2241
+ const normalized = normalizeZcfConfig(raw || null);
2242
+ if (normalized) {
2243
+ return normalized;
2244
+ }
2245
+ for (const legacyPath of LEGACY_ZCF_CONFIG_FILES) {
2246
+ if (existsSync(legacyPath)) {
2247
+ const legacyRaw = readJsonConfig(legacyPath);
2248
+ const legacyNormalized = normalizeZcfConfig(legacyRaw || null);
2249
+ if (legacyNormalized) {
2250
+ return legacyNormalized;
2251
+ }
2252
+ }
2253
+ }
2254
+ return null;
2255
+ }
2256
+ async function readZcfConfigAsync() {
2257
+ return readZcfConfig();
2258
+ }
2259
+ function writeZcfConfig(config) {
2260
+ try {
2261
+ const sanitizedConfig = {
2262
+ ...config,
2263
+ codeToolType: sanitizeCodeToolType(config.codeToolType)
2264
+ };
2265
+ const tomlConfig = convertLegacyToTomlConfig(sanitizedConfig);
2266
+ writeTomlConfig(ZCF_CONFIG_FILE, tomlConfig);
2267
+ } catch {
2268
+ }
2269
+ }
2270
+ function updateZcfConfig(updates) {
2271
+ const existingConfig = readZcfConfig();
2272
+ const newConfig = {
2273
+ version: updates.version || existingConfig?.version || "1.0.0",
2274
+ preferredLang: updates.preferredLang || existingConfig?.preferredLang || "en",
2275
+ templateLang: updates.templateLang !== void 0 ? updates.templateLang : existingConfig?.templateLang,
2276
+ aiOutputLang: updates.aiOutputLang || existingConfig?.aiOutputLang,
2277
+ outputStyles: updates.outputStyles !== void 0 ? updates.outputStyles : existingConfig?.outputStyles,
2278
+ defaultOutputStyle: updates.defaultOutputStyle !== void 0 ? updates.defaultOutputStyle : existingConfig?.defaultOutputStyle,
2279
+ codeToolType: updates.codeToolType || existingConfig?.codeToolType || DEFAULT_CODE_TOOL_TYPE,
2280
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
2281
+ };
2282
+ writeZcfConfig(newConfig);
2283
+ }
2284
+ function readDefaultTomlConfig() {
2285
+ return readTomlConfig(ZCF_CONFIG_FILE);
2286
+ }
2287
+
2288
+ const zcfConfig = {
2289
+ __proto__: null,
2290
+ createDefaultTomlConfig: createDefaultTomlConfig,
2291
+ migrateFromJsonConfig: migrateFromJsonConfig,
2292
+ migrateZcfConfigIfNeeded: migrateZcfConfigIfNeeded,
2293
+ readDefaultTomlConfig: readDefaultTomlConfig,
2294
+ readTomlConfig: readTomlConfig,
2295
+ readZcfConfig: readZcfConfig,
2296
+ readZcfConfigAsync: readZcfConfigAsync,
2297
+ updateTomlConfig: updateTomlConfig,
2298
+ updateZcfConfig: updateZcfConfig,
2299
+ writeTomlConfig: writeTomlConfig,
2300
+ writeZcfConfig: writeZcfConfig
2301
+ };
2302
+
2303
+ async function selectAiOutputLanguage(defaultLang) {
2304
+ ensureI18nInitialized();
2305
+ console.log(ansis.dim(`
2306
+ ${i18n.t("language:aiOutputLangHint")}
2307
+ `));
2308
+ const aiLangChoices = Object.entries(AI_OUTPUT_LANGUAGES).map(([key]) => ({
2309
+ title: getAiOutputLanguageLabel(key),
2310
+ value: key
2311
+ }));
2312
+ const defaultChoice = defaultLang || "en";
2313
+ const { lang } = await inquirer.prompt({
2314
+ type: "list",
2315
+ name: "lang",
2316
+ message: i18n.t("language:selectAiOutputLang"),
2317
+ choices: addNumbersToChoices(aiLangChoices.map((choice) => ({
2318
+ name: choice.title,
2319
+ value: choice.value
2320
+ }))),
2321
+ default: defaultChoice
2322
+ });
2323
+ if (!lang) {
2324
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2325
+ process.exit(0);
2326
+ }
2327
+ const aiOutputLang = lang;
2328
+ if (aiOutputLang === "custom") {
2329
+ const { customLang } = await inquirer.prompt({
2330
+ type: "input",
2331
+ name: "customLang",
2332
+ message: i18n.t("language:enterCustomLanguage"),
2333
+ validate: async (value) => !!value || i18n.t("language:languageRequired") || "Language is required"
2334
+ });
2335
+ if (!customLang) {
2336
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2337
+ process.exit(0);
2338
+ }
2339
+ return customLang;
2340
+ }
2341
+ return aiOutputLang;
2342
+ }
2343
+ const LANGUAGE_SELECTION_MESSAGES = {
2344
+ selectLanguage: "Select ZCF display language / \u9009\u62E9ZCF\u663E\u793A\u8BED\u8A00",
2345
+ operationCancelled: "Operation cancelled / \u64CD\u4F5C\u5DF2\u53D6\u6D88"
2346
+ };
2347
+ async function selectScriptLanguage(currentLang) {
2348
+ const zcfConfig = readZcfConfig();
2349
+ if (zcfConfig?.preferredLang) {
2350
+ return zcfConfig.preferredLang;
2351
+ }
2352
+ const { lang } = await inquirer.prompt({
2353
+ type: "list",
2354
+ name: "lang",
2355
+ message: LANGUAGE_SELECTION_MESSAGES.selectLanguage,
2356
+ choices: addNumbersToChoices(SUPPORTED_LANGS.map((l) => ({
2357
+ name: LANG_LABELS[l],
2358
+ value: l
2359
+ })))
2360
+ });
2361
+ if (!lang) {
2362
+ console.log(ansis.yellow(LANGUAGE_SELECTION_MESSAGES.operationCancelled));
2363
+ process.exit(0);
2364
+ }
2365
+ const scriptLang = lang;
2366
+ updateZcfConfig({
2367
+ version,
2368
+ preferredLang: scriptLang
2369
+ });
2370
+ return scriptLang;
2371
+ }
2372
+ async function resolveAiOutputLanguage(scriptLang, commandLineOption, savedConfig) {
2373
+ ensureI18nInitialized();
2374
+ if (commandLineOption) {
2375
+ return commandLineOption;
2376
+ }
2377
+ if (savedConfig?.aiOutputLang) {
2378
+ const currentLanguageLabel = getAiOutputLanguageLabel(savedConfig.aiOutputLang) || savedConfig.aiOutputLang;
2379
+ console.log(ansis.blue(`${i18n.t("language:currentConfigFound")}: ${currentLanguageLabel}`));
2380
+ const { shouldModify } = await inquirer.prompt({
2381
+ type: "confirm",
2382
+ name: "shouldModify",
2383
+ message: i18n.t("language:modifyConfigPrompt"),
2384
+ default: false
2385
+ });
2386
+ if (shouldModify === void 0) {
2387
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2388
+ process.exit(0);
2389
+ }
2390
+ if (!shouldModify) {
2391
+ console.log(ansis.gray(`\u2714 ${i18n.t("language:aiOutputLangHint")}: ${currentLanguageLabel}`));
2392
+ return savedConfig.aiOutputLang;
2393
+ }
2394
+ return await selectAiOutputLanguage(scriptLang);
2395
+ }
2396
+ return await selectAiOutputLanguage(scriptLang);
2397
+ }
2398
+ async function selectTemplateLanguage() {
2399
+ ensureI18nInitialized();
2400
+ const LANG_HINT_KEYS = {
2401
+ "zh-CN": i18n.t("language:configLangHint.zh-CN"),
2402
+ "en": i18n.t("language:configLangHint.en")
2403
+ };
2404
+ const { lang } = await inquirer.prompt({
2405
+ type: "list",
2406
+ name: "lang",
2407
+ message: i18n.t("language:selectConfigLang"),
2408
+ choices: addNumbersToChoices(
2409
+ SUPPORTED_LANGS.map((l) => ({
2410
+ name: `${LANG_LABELS[l]} - ${LANG_HINT_KEYS[l]}`,
2411
+ value: l
2412
+ }))
2413
+ )
2414
+ });
2415
+ if (!lang) {
2416
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2417
+ process.exit(0);
2418
+ }
2419
+ return lang;
2420
+ }
2421
+ async function resolveTemplateLanguage(commandLineOption, savedConfig) {
2422
+ ensureI18nInitialized();
2423
+ if (commandLineOption) {
2424
+ return commandLineOption;
2425
+ }
2426
+ if (savedConfig?.templateLang) {
2427
+ const currentLanguageLabel = LANG_LABELS[savedConfig.templateLang];
2428
+ console.log(ansis.blue(`${i18n.t("language:currentTemplateLanguageFound")}: ${currentLanguageLabel}`));
2429
+ const { shouldModify } = await inquirer.prompt({
2430
+ type: "confirm",
2431
+ name: "shouldModify",
2432
+ message: i18n.t("language:modifyTemplateLanguagePrompt"),
2433
+ default: false
2434
+ });
2435
+ if (shouldModify === void 0) {
2436
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2437
+ process.exit(0);
2438
+ }
2439
+ if (!shouldModify) {
2440
+ console.log(ansis.gray(`\u2714 ${i18n.t("language:selectConfigLang")}: ${currentLanguageLabel}`));
2441
+ return savedConfig.templateLang;
2442
+ }
2443
+ return await selectTemplateLanguage();
2444
+ }
2445
+ if (savedConfig?.preferredLang && !savedConfig?.templateLang) {
2446
+ console.log(ansis.yellow(`${i18n.t("language:usingFallbackTemplate")}: ${LANG_LABELS[savedConfig.preferredLang]}`));
2447
+ const { shouldModify } = await inquirer.prompt({
2448
+ type: "confirm",
2449
+ name: "shouldModify",
2450
+ message: i18n.t("language:modifyTemplateLanguagePrompt"),
2451
+ default: false
2452
+ });
2453
+ if (shouldModify === void 0) {
2454
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2455
+ process.exit(0);
2456
+ }
2457
+ if (!shouldModify) {
2458
+ return savedConfig.preferredLang;
2459
+ }
2460
+ return await selectTemplateLanguage();
2461
+ }
2462
+ return await selectTemplateLanguage();
2463
+ }
2464
+ async function resolveSystemPromptStyle(availablePrompts, commandLineOption, savedConfig) {
2465
+ ensureI18nInitialized();
2466
+ if (commandLineOption && availablePrompts.some((p) => p.id === commandLineOption)) {
2467
+ return commandLineOption;
2468
+ }
2469
+ if (savedConfig?.codex?.systemPromptStyle) {
2470
+ const currentStyleId = savedConfig.codex.systemPromptStyle;
2471
+ const currentStyle = availablePrompts.find((p) => p.id === currentStyleId);
2472
+ if (currentStyle) {
2473
+ console.log(ansis.blue(`${i18n.t("language:currentSystemPromptFound")}: ${currentStyle.name}`));
2474
+ const { shouldModify } = await inquirer.prompt({
2475
+ type: "confirm",
2476
+ name: "shouldModify",
2477
+ message: i18n.t("language:modifySystemPromptPrompt"),
2478
+ default: false
2479
+ });
2480
+ if (shouldModify === void 0) {
2481
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2482
+ process.exit(0);
2483
+ }
2484
+ if (!shouldModify) {
2485
+ console.log(ansis.gray(`\u2714 ${i18n.t("language:currentSystemPromptFound")}: ${currentStyle.name}`));
2486
+ return currentStyleId;
2487
+ }
2488
+ }
2489
+ }
2490
+ const { systemPrompt } = await inquirer.prompt([{
2491
+ type: "list",
2492
+ name: "systemPrompt",
2493
+ message: i18n.t("codex:systemPromptPrompt"),
2494
+ choices: addNumbersToChoices(availablePrompts.map((style) => ({
2495
+ name: `${style.name} - ${ansis.gray(style.description)}`,
2496
+ value: style.id
2497
+ }))),
2498
+ default: "engineer-professional"
2499
+ // Default to engineer-professional
2500
+ }]);
2501
+ if (!systemPrompt) {
2502
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2503
+ process.exit(0);
2504
+ }
2505
+ return systemPrompt;
2506
+ }
2507
+
2508
+ const prompts = {
2509
+ __proto__: null,
2510
+ resolveAiOutputLanguage: resolveAiOutputLanguage,
2511
+ resolveSystemPromptStyle: resolveSystemPromptStyle,
2512
+ resolveTemplateLanguage: resolveTemplateLanguage,
2513
+ selectAiOutputLanguage: selectAiOutputLanguage,
2514
+ selectScriptLanguage: selectScriptLanguage,
2515
+ selectTemplateLanguage: selectTemplateLanguage
2516
+ };
2517
+
2518
+ function detectConfigManagementMode() {
2519
+ try {
2520
+ const config = readCodexConfig();
2521
+ if (!config || !config.providers || config.providers.length === 0) {
2522
+ return {
2523
+ mode: "initial",
2524
+ hasProviders: false,
2525
+ providerCount: 0
2526
+ };
2527
+ }
2528
+ return {
2529
+ mode: "management",
2530
+ hasProviders: true,
2531
+ providerCount: config.providers.length,
2532
+ currentProvider: config.modelProvider,
2533
+ providers: config.providers,
2534
+ isUnmanaged: config.managed === false ? true : void 0
2535
+ };
2536
+ } catch (error) {
2537
+ return {
2538
+ mode: "initial",
2539
+ hasProviders: false,
2540
+ providerCount: 0,
2541
+ error: error instanceof Error ? error.message : "Unknown error"
2542
+ };
2543
+ }
2544
+ }
2545
+
2546
+ const CODEX_DIR = join(homedir(), ".codex");
2547
+ const CODEX_CONFIG_FILE = join(CODEX_DIR, "config.toml");
2548
+ const CODEX_AUTH_FILE = join(CODEX_DIR, "auth.json");
2549
+ const CODEX_AGENTS_FILE = join(CODEX_DIR, "AGENTS.md");
2550
+ const CODEX_PROMPTS_DIR = join(CODEX_DIR, "prompts");
2551
+ function getRootDir$1() {
2552
+ const currentFilePath = fileURLToPath(import.meta.url);
2553
+ let dir = dirname(currentFilePath);
2554
+ while (dir !== dirname(dir)) {
2555
+ if (exists(join(dir, "templates"))) {
2556
+ return dir;
2557
+ }
2558
+ dir = dirname(dir);
2559
+ }
2560
+ return dirname(currentFilePath);
2561
+ }
2562
+ async function executeCodexInstallation(isUpdate) {
2563
+ const action = isUpdate ? "update" : "install";
2564
+ if (isUpdate) {
2565
+ console.log(ansis.cyan(i18n.t("codex:updatingCli")));
2566
+ } else {
2567
+ console.log(ansis.cyan(i18n.t("codex:installingCli")));
2568
+ }
2569
+ const result = await x("npm", ["install", "-g", "@openai/codex"]);
2570
+ if (result.exitCode !== 0) {
2571
+ throw new Error(`Failed to ${action} codex CLI: exit code ${result.exitCode}`);
2572
+ }
2573
+ if (isUpdate) {
2574
+ console.log(ansis.green(i18n.t("codex:updateSuccess")));
2575
+ } else {
2576
+ console.log(ansis.green(i18n.t("codex:installSuccess")));
2577
+ }
2578
+ }
2579
+ function getUninstallOptions() {
2580
+ return [
2581
+ { name: i18n.t("codex:uninstallItemConfig"), value: "config" },
2582
+ { name: i18n.t("codex:uninstallItemAuth"), value: "auth" },
2583
+ { name: i18n.t("codex:uninstallItemApiConfig"), value: "api-config" },
2584
+ { name: i18n.t("codex:uninstallItemMcpConfig"), value: "mcp-config" },
2585
+ { name: i18n.t("codex:uninstallItemSystemPrompt"), value: "system-prompt" },
2586
+ { name: i18n.t("codex:uninstallItemWorkflow"), value: "workflow" },
2587
+ { name: i18n.t("codex:uninstallItemCliPackage"), value: "cli-package" },
2588
+ { name: i18n.t("codex:uninstallItemBackups"), value: "backups" }
2589
+ ];
2590
+ }
2591
+ function handleUninstallCancellation() {
2592
+ console.log(ansis.yellow(i18n.t("codex:uninstallCancelled")));
2593
+ }
2594
+ function createBackupDirectory(timestamp) {
2595
+ const backupBaseDir = join(CODEX_DIR, "backup");
2596
+ const backupDir = join(backupBaseDir, `backup_${timestamp}`);
2597
+ ensureDir(backupDir);
2598
+ return backupDir;
2599
+ }
2600
+ function backupCodexFiles() {
2601
+ if (!exists(CODEX_DIR))
2602
+ return null;
2603
+ const timestamp = dayjs().format("YYYY-MM-DD_HH-mm-ss");
2604
+ const backupDir = createBackupDirectory(timestamp);
2605
+ const filter = (path) => {
2606
+ return !path.includes("/backup");
2607
+ };
2608
+ copyDir(CODEX_DIR, backupDir, { filter });
2609
+ return backupDir;
2610
+ }
2611
+ function backupCodexComplete() {
2612
+ return backupCodexFiles();
2613
+ }
2614
+ function backupCodexConfig() {
2615
+ if (!exists(CODEX_CONFIG_FILE))
2616
+ return null;
2617
+ try {
2618
+ const timestamp = dayjs().format("YYYY-MM-DD_HH-mm-ss");
2619
+ const backupDir = createBackupDirectory(timestamp);
2620
+ const backupPath = join(backupDir, "config.toml");
2621
+ copyFile(CODEX_CONFIG_FILE, backupPath);
2622
+ return backupPath;
2623
+ } catch {
2624
+ return null;
2625
+ }
2626
+ }
2627
+ function backupCodexAgents() {
2628
+ if (!exists(CODEX_AGENTS_FILE))
2629
+ return null;
2630
+ try {
2631
+ const timestamp = dayjs().format("YYYY-MM-DD_HH-mm-ss");
2632
+ const backupDir = createBackupDirectory(timestamp);
2633
+ const backupPath = join(backupDir, "AGENTS.md");
2634
+ copyFile(CODEX_AGENTS_FILE, backupPath);
2635
+ return backupPath;
2636
+ } catch {
2637
+ return null;
2638
+ }
2639
+ }
2640
+ function backupCodexPrompts() {
2641
+ if (!exists(CODEX_PROMPTS_DIR))
2642
+ return null;
2643
+ try {
2644
+ const timestamp = dayjs().format("YYYY-MM-DD_HH-mm-ss");
2645
+ const backupDir = createBackupDirectory(timestamp);
2646
+ const backupPath = join(backupDir, "prompts");
2647
+ copyDir(CODEX_PROMPTS_DIR, backupPath);
2648
+ return backupPath;
2649
+ } catch {
2650
+ return null;
2651
+ }
2652
+ }
2653
+ function getBackupMessage(path) {
2654
+ if (!path)
2655
+ return "";
2656
+ ensureI18nInitialized();
2657
+ return i18n.t("codex:backupSuccess", { path });
2658
+ }
2659
+ function sanitizeProviderName(input) {
2660
+ const cleaned = input.trim();
2661
+ if (!cleaned)
2662
+ return "";
2663
+ return cleaned.replace(/[^\w.-]/g, "");
2664
+ }
2665
+ function parseCodexConfig(content) {
2666
+ if (!content.trim()) {
2667
+ return {
2668
+ model: null,
2669
+ modelProvider: null,
2670
+ providers: [],
2671
+ mcpServices: [],
2672
+ managed: false,
2673
+ otherConfig: [],
2674
+ modelProviderCommented: void 0
2675
+ };
2676
+ }
2677
+ try {
2678
+ const tomlData = parse(content);
2679
+ const providers = [];
2680
+ if (tomlData.model_providers) {
2681
+ for (const [id, providerData] of Object.entries(tomlData.model_providers)) {
2682
+ const provider = providerData;
2683
+ providers.push({
2684
+ id,
2685
+ name: provider.name || id,
2686
+ baseUrl: provider.base_url || "",
2687
+ wireApi: provider.wire_api || "responses",
2688
+ envKey: provider.env_key || "OPENAI_API_KEY",
2689
+ requiresOpenaiAuth: provider.requires_openai_auth !== false
2690
+ });
2691
+ }
2692
+ }
2693
+ const mcpServices = [];
2694
+ if (tomlData.mcp_servers) {
2695
+ for (const [id, mcpData] of Object.entries(tomlData.mcp_servers)) {
2696
+ const mcp = mcpData;
2697
+ mcpServices.push({
2698
+ id,
2699
+ command: mcp.command || id,
2700
+ args: mcp.args || [],
2701
+ env: Object.keys(mcp.env || {}).length > 0 ? mcp.env : void 0,
2702
+ startup_timeout_ms: mcp.startup_timeout_ms
2703
+ });
2704
+ }
2705
+ }
2706
+ const model = tomlData.model || null;
2707
+ let modelProvider = null;
2708
+ let modelProviderCommented;
2709
+ const commentedMatch = content.match(/^(\s*)#\s*model_provider\s*=\s*"([^"]+)"/m);
2710
+ if (commentedMatch) {
2711
+ modelProvider = commentedMatch[2];
2712
+ modelProviderCommented = true;
2713
+ } else {
2714
+ const lines2 = content.split("\n");
2715
+ let inSection = false;
2716
+ for (const line of lines2) {
2717
+ const trimmedLine = line.trim();
2718
+ if (!trimmedLine)
2719
+ continue;
2720
+ if (trimmedLine.startsWith("[")) {
2721
+ inSection = true;
2722
+ continue;
2723
+ }
2724
+ if (trimmedLine.startsWith("#")) {
2725
+ if (trimmedLine.includes("--- model provider added by ZCF ---")) {
2726
+ inSection = false;
2727
+ }
2728
+ continue;
2729
+ }
2730
+ if (!inSection && trimmedLine.startsWith("model_provider")) {
2731
+ const match = trimmedLine.match(/model_provider\s*=\s*"([^"]+)"/);
2732
+ if (match) {
2733
+ modelProvider = match[1];
2734
+ modelProviderCommented = false;
2735
+ break;
2736
+ }
2737
+ }
2738
+ }
2739
+ if (!modelProvider) {
2740
+ modelProvider = tomlData.model_provider || null;
2741
+ modelProviderCommented = false;
2742
+ }
2743
+ }
2744
+ const otherConfig = [];
2745
+ const lines = content.split("\n");
2746
+ let skipCurrentSection = false;
2747
+ let currentSection = "";
2748
+ for (const line of lines) {
2749
+ const trimmedLine = line.trim();
2750
+ if (trimmedLine.includes("--- model provider added by ZCF ---") || trimmedLine.includes("--- MCP servers added by ZCF ---") || trimmedLine.includes("Managed by ZCF")) {
2751
+ continue;
2752
+ }
2753
+ const sectionMatch = trimmedLine.match(/^\[([^\]]+)\]/);
2754
+ if (sectionMatch) {
2755
+ currentSection = sectionMatch[1];
2756
+ skipCurrentSection = currentSection.startsWith("model_providers.") || currentSection.startsWith("mcp_servers.");
2757
+ }
2758
+ if (!skipCurrentSection && (trimmedLine.startsWith("model_provider") || trimmedLine.startsWith("# model_provider") || /^model\s*=/.test(trimmedLine))) {
2759
+ continue;
2760
+ }
2761
+ if (!skipCurrentSection && trimmedLine) {
2762
+ otherConfig.push(line);
2763
+ }
2764
+ }
2765
+ const managed = providers.length > 0 || mcpServices.length > 0 || modelProvider !== null || model !== null;
2766
+ return {
2767
+ model,
2768
+ modelProvider,
2769
+ providers,
2770
+ mcpServices,
2771
+ managed,
2772
+ otherConfig,
2773
+ modelProviderCommented
2774
+ };
2775
+ } catch (error) {
2776
+ console.warn("TOML parsing failed, falling back to basic parsing:", error);
2777
+ return {
2778
+ model: null,
2779
+ modelProvider: null,
2780
+ providers: [],
2781
+ mcpServices: [],
2782
+ managed: false,
2783
+ otherConfig: content.split("\n"),
2784
+ modelProviderCommented: void 0
2785
+ };
2786
+ }
2787
+ }
2788
+ function readCodexConfig() {
2789
+ if (!exists(CODEX_CONFIG_FILE))
2790
+ return null;
2791
+ try {
2792
+ const content = readFile(CODEX_CONFIG_FILE);
2793
+ return parseCodexConfig(content);
2794
+ } catch {
2795
+ return null;
2796
+ }
2797
+ }
2798
+ function renderCodexConfig(data) {
2799
+ const lines = [];
2800
+ if (data.model || data.modelProvider || data.providers.length > 0 || data.modelProviderCommented) {
2801
+ lines.push("# --- model provider added by ZCF ---");
2802
+ if (data.model) {
2803
+ lines.push(`model = "${data.model}"`);
2804
+ }
2805
+ if (data.modelProvider) {
2806
+ const commentPrefix = data.modelProviderCommented ? "# " : "";
2807
+ lines.push(`${commentPrefix}model_provider = "${data.modelProvider}"`);
2808
+ }
2809
+ lines.push("");
2810
+ }
2811
+ if (data.otherConfig && data.otherConfig.length > 0) {
2812
+ lines.push(...data.otherConfig);
2813
+ if (data.providers.length > 0 || data.mcpServices.length > 0) {
2814
+ lines.push("");
2815
+ }
2816
+ }
2817
+ if (data.providers.length > 0) {
2818
+ for (const provider of data.providers) {
2819
+ lines.push("");
2820
+ lines.push(`[model_providers.${provider.id}]`);
2821
+ lines.push(`name = "${provider.name}"`);
2822
+ lines.push(`base_url = "${provider.baseUrl}"`);
2823
+ lines.push(`wire_api = "${provider.wireApi}"`);
2824
+ lines.push(`env_key = "${provider.envKey}"`);
2825
+ lines.push(`requires_openai_auth = ${provider.requiresOpenaiAuth}`);
2826
+ }
2827
+ }
2828
+ if (data.mcpServices.length > 0) {
2829
+ lines.push("");
2830
+ lines.push("# --- MCP servers added by ZCF ---");
2831
+ for (const service of data.mcpServices) {
2832
+ lines.push(`[mcp_servers.${service.id}]`);
2833
+ lines.push(`command = "${service.command}"`);
2834
+ const argsString = service.args.length > 0 ? service.args.map((arg) => `"${arg}"`).join(", ") : "";
2835
+ lines.push(`args = [${argsString}]`);
2836
+ if (service.env && Object.keys(service.env).length > 0) {
2837
+ const envEntries = Object.entries(service.env).map(([key, value]) => `${key} = "${value}"`).join(", ");
2838
+ lines.push(`env = {${envEntries}}`);
2839
+ }
2840
+ if (service.startup_timeout_ms) {
2841
+ lines.push(`startup_timeout_ms = ${service.startup_timeout_ms}`);
2842
+ }
2843
+ lines.push("");
2844
+ }
2845
+ if (lines[lines.length - 1] === "") {
2846
+ lines.pop();
2847
+ }
2848
+ }
2849
+ let result = lines.join("\n");
2850
+ if (result && !result.endsWith("\n")) {
2851
+ result += "\n";
2852
+ }
2853
+ return result;
2854
+ }
2855
+ function writeCodexConfig(data) {
2856
+ ensureDir(CODEX_DIR);
2857
+ writeFile(CODEX_CONFIG_FILE, renderCodexConfig(data));
2858
+ }
2859
+ function writeAuthFile(newEntries) {
2860
+ ensureDir(CODEX_DIR);
2861
+ const existing = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
2862
+ const merged = { ...existing, ...newEntries };
2863
+ writeJsonConfig(CODEX_AUTH_FILE, merged, { pretty: true });
2864
+ }
2865
+ async function isCodexInstalled() {
2866
+ try {
2867
+ const result = await x("npm", ["list", "-g", "--depth=0"]);
2868
+ if (result.exitCode !== 0) {
2869
+ return false;
2870
+ }
2871
+ return result.stdout.includes("@openai/codex@");
2872
+ } catch {
2873
+ return false;
2874
+ }
2875
+ }
2876
+ async function getCodexVersion() {
2877
+ try {
2878
+ const result = await x("npm", ["list", "-g", "--depth=0"]);
2879
+ if (result.exitCode !== 0) {
2880
+ return null;
2881
+ }
2882
+ const match = result.stdout.match(/@openai\/codex@(\S+)/);
2883
+ return match ? match[1] : null;
2884
+ } catch {
2885
+ return null;
2886
+ }
2887
+ }
2888
+ async function checkCodexUpdate() {
2889
+ try {
2890
+ const currentVersion = await getCodexVersion();
2891
+ if (!currentVersion) {
2892
+ return {
2893
+ installed: false,
2894
+ currentVersion: null,
2895
+ latestVersion: null,
2896
+ needsUpdate: false
2897
+ };
2898
+ }
2899
+ const result = await x("npm", ["view", "@openai/codex", "--json"]);
2900
+ if (result.exitCode !== 0) {
2901
+ return {
2902
+ installed: true,
2903
+ currentVersion,
2904
+ latestVersion: null,
2905
+ needsUpdate: false
2906
+ };
2907
+ }
2908
+ const packageInfo = JSON.parse(result.stdout);
2909
+ const latestVersion = packageInfo["dist-tags"]?.latest;
2910
+ if (!latestVersion) {
2911
+ return {
2912
+ installed: true,
2913
+ currentVersion,
2914
+ latestVersion: null,
2915
+ needsUpdate: false
2916
+ };
2917
+ }
2918
+ const needsUpdate = semver.gt(latestVersion, currentVersion);
2919
+ return {
2920
+ installed: true,
2921
+ currentVersion,
2922
+ latestVersion,
2923
+ needsUpdate
2924
+ };
2925
+ } catch {
2926
+ return {
2927
+ installed: false,
2928
+ currentVersion: null,
2929
+ latestVersion: null,
2930
+ needsUpdate: false
2931
+ };
2932
+ }
2933
+ }
2934
+ async function installCodexCli() {
2935
+ ensureI18nInitialized();
2936
+ if (await isCodexInstalled()) {
2937
+ const { needsUpdate } = await checkCodexUpdate();
2938
+ if (needsUpdate) {
2939
+ await executeCodexInstallation(true);
2940
+ return;
2941
+ } else {
2942
+ console.log(ansis.yellow(i18n.t("codex:alreadyInstalled")));
2943
+ return;
2944
+ }
2945
+ }
2946
+ await executeCodexInstallation(false);
2947
+ }
2948
+ async function runCodexWorkflowImport() {
2949
+ ensureI18nInitialized();
2950
+ await runCodexSystemPromptSelection();
2951
+ await runCodexWorkflowSelection();
2952
+ console.log(ansis.green(i18n.t("codex:workflowInstall")));
2953
+ }
2954
+ async function runCodexSystemPromptSelection() {
2955
+ ensureI18nInitialized();
2956
+ const rootDir = getRootDir$1();
2957
+ const templateRoot = join(rootDir, "templates", "codex");
2958
+ const zcfConfig$1 = readZcfConfig();
2959
+ const { readDefaultTomlConfig } = await Promise.resolve().then(function () { return zcfConfig; });
2960
+ const tomlConfig = readDefaultTomlConfig();
2961
+ const { resolveTemplateLanguage } = await Promise.resolve().then(function () { return prompts; });
2962
+ const preferredLang = await resolveTemplateLanguage(
2963
+ void 0,
2964
+ // No command line option for this function
2965
+ zcfConfig$1
2966
+ );
2967
+ let langDir = join(templateRoot, preferredLang);
2968
+ if (!exists(langDir))
2969
+ langDir = join(templateRoot, "zh-CN");
2970
+ const systemPromptSrc = join(langDir, "system-prompt");
2971
+ if (!exists(systemPromptSrc))
2972
+ return;
2973
+ const availablePrompts = [
2974
+ {
2975
+ id: "engineer-professional",
2976
+ name: i18n.t("configuration:outputStyles.engineer-professional.name"),
2977
+ description: i18n.t("configuration:outputStyles.engineer-professional.description")
2978
+ },
2979
+ {
2980
+ id: "laowang-engineer",
2981
+ name: i18n.t("configuration:outputStyles.laowang-engineer.name"),
2982
+ description: i18n.t("configuration:outputStyles.laowang-engineer.description")
2983
+ },
2984
+ {
2985
+ id: "nekomata-engineer",
2986
+ name: i18n.t("configuration:outputStyles.nekomata-engineer.name"),
2987
+ description: i18n.t("configuration:outputStyles.nekomata-engineer.description")
2988
+ }
2989
+ ].filter((style) => exists(join(systemPromptSrc, `${style.id}.md`)));
2990
+ if (availablePrompts.length === 0)
2991
+ return;
2992
+ const { resolveSystemPromptStyle } = await Promise.resolve().then(function () { return prompts; });
2993
+ const systemPrompt = await resolveSystemPromptStyle(
2994
+ availablePrompts,
2995
+ void 0,
2996
+ // No command line option for this function
2997
+ tomlConfig
2998
+ );
2999
+ if (!systemPrompt)
3000
+ return;
3001
+ const promptFile = join(systemPromptSrc, `${systemPrompt}.md`);
3002
+ const content = readFile(promptFile);
3003
+ ensureDir(CODEX_DIR);
3004
+ const backupPath = backupCodexAgents();
3005
+ if (backupPath) {
3006
+ console.log(ansis.gray(getBackupMessage(backupPath)));
3007
+ }
3008
+ writeFile(CODEX_AGENTS_FILE, content);
3009
+ try {
3010
+ const { updateTomlConfig } = await Promise.resolve().then(function () { return zcfConfig; });
3011
+ const { ZCF_CONFIG_FILE } = await Promise.resolve().then(function () { return constants; });
3012
+ updateTomlConfig(ZCF_CONFIG_FILE, {
3013
+ codex: {
3014
+ systemPromptStyle: systemPrompt
3015
+ }
3016
+ });
3017
+ } catch (error) {
3018
+ console.error("Failed to update ZCF config:", error);
3019
+ }
3020
+ }
3021
+ async function runCodexWorkflowSelection() {
3022
+ ensureI18nInitialized();
3023
+ const rootDir = getRootDir$1();
3024
+ const templateRoot = join(rootDir, "templates", "codex");
3025
+ const zcfConfig = readZcfConfig();
3026
+ const templateLang = zcfConfig?.templateLang || zcfConfig?.preferredLang || "en";
3027
+ const preferredLang = templateLang === "en" ? "en" : "zh-CN";
3028
+ let langDir = join(templateRoot, preferredLang);
3029
+ if (!exists(langDir))
3030
+ langDir = join(templateRoot, "zh-CN");
3031
+ const workflowSrc = join(langDir, "workflow");
3032
+ if (!exists(workflowSrc))
3033
+ return;
3034
+ const allWorkflows = getAllWorkflowFiles(workflowSrc);
3035
+ if (allWorkflows.length === 0)
3036
+ return;
3037
+ const { workflows } = await inquirer.prompt([{
3038
+ type: "checkbox",
3039
+ name: "workflows",
3040
+ message: i18n.t("codex:workflowSelectionPrompt"),
3041
+ choices: addNumbersToChoices(allWorkflows.map((workflow) => ({
3042
+ name: workflow.name,
3043
+ value: workflow.path,
3044
+ checked: true
3045
+ // Default all selected
3046
+ })))
3047
+ }]);
3048
+ if (!workflows || workflows.length === 0)
3049
+ return;
3050
+ ensureDir(CODEX_PROMPTS_DIR);
3051
+ const backupPath = backupCodexPrompts();
3052
+ if (backupPath) {
3053
+ console.log(ansis.gray(getBackupMessage(backupPath)));
3054
+ }
3055
+ for (const workflowPath of workflows) {
3056
+ const content = readFile(workflowPath);
3057
+ const filename = workflowPath.split("/").pop() || "workflow.md";
3058
+ const targetPath = join(CODEX_PROMPTS_DIR, filename);
3059
+ writeFile(targetPath, content);
3060
+ }
3061
+ }
3062
+ function getAllWorkflowFiles(dirPath) {
3063
+ const workflows = [];
3064
+ const sixStepDir = join(dirPath, "sixStep", "prompts");
3065
+ if (exists(sixStepDir)) {
3066
+ const workflowFile = join(sixStepDir, "workflow.md");
3067
+ if (exists(workflowFile)) {
3068
+ workflows.push({
3069
+ name: i18n.t("workflow:workflowOption.sixStepsWorkflow"),
3070
+ path: workflowFile
3071
+ });
3072
+ }
3073
+ }
3074
+ return workflows;
3075
+ }
3076
+ function toProvidersList(providers) {
3077
+ return providers.map((provider) => ({ name: provider.name || provider.id, value: provider.id }));
3078
+ }
3079
+ function createApiConfigChoices(providers, currentProvider, isCommented) {
3080
+ const choices = [];
3081
+ const isOfficialMode = !currentProvider || isCommented;
3082
+ choices.push({
3083
+ name: isOfficialMode ? `${ansis.green("\u25CF ")}${i18n.t("codex:useOfficialLogin")} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${i18n.t("codex:useOfficialLogin")}`,
3084
+ value: "official"
3085
+ });
3086
+ providers.forEach((provider) => {
3087
+ const isCurrent = currentProvider === provider.id && !isCommented;
3088
+ choices.push({
3089
+ name: isCurrent ? `${ansis.green("\u25CF ")}${provider.name} - ${ansis.gray(provider.id)} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${provider.name} - ${ansis.gray(provider.id)}`,
3090
+ value: provider.id
3091
+ });
3092
+ });
3093
+ return choices;
3094
+ }
3095
+ async function configureCodexApi() {
3096
+ ensureI18nInitialized();
3097
+ const existingConfig = readCodexConfig();
3098
+ const existingAuth = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
3099
+ const hasProviders = existingConfig?.providers && existingConfig.providers.length > 0;
3100
+ const modeChoices = [
3101
+ { name: i18n.t("codex:apiModeOfficial"), value: "official" },
3102
+ { name: i18n.t("codex:apiModeCustom"), value: "custom" }
3103
+ ];
3104
+ if (hasProviders) {
3105
+ modeChoices.push({ name: i18n.t("codex:configSwitchMode"), value: "switch" });
3106
+ }
3107
+ const { mode } = await inquirer.prompt([{
3108
+ type: "list",
3109
+ name: "mode",
3110
+ message: i18n.t("codex:apiModePrompt"),
3111
+ choices: addNumbersToChoices(modeChoices),
3112
+ default: "custom"
3113
+ }]);
3114
+ if (!mode) {
3115
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
3116
+ return;
3117
+ }
3118
+ if (mode === "official") {
3119
+ const success = await switchToOfficialLogin();
3120
+ if (success) {
3121
+ updateZcfConfig({ codeToolType: "codex" });
3122
+ }
3123
+ return;
3124
+ }
3125
+ if (mode === "switch") {
3126
+ if (!hasProviders) {
3127
+ console.log(ansis.yellow(i18n.t("codex:noProvidersAvailable")));
3128
+ return;
3129
+ }
3130
+ const currentProvider = existingConfig?.modelProvider;
3131
+ const isCommented = existingConfig?.modelProviderCommented;
3132
+ const choices = createApiConfigChoices(existingConfig.providers, currentProvider, isCommented);
3133
+ const { selectedConfig } = await inquirer.prompt([{
3134
+ type: "list",
3135
+ name: "selectedConfig",
3136
+ message: i18n.t("codex:apiConfigSwitchPrompt"),
3137
+ choices: addNumbersToChoices(choices)
3138
+ }]);
3139
+ if (!selectedConfig) {
3140
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
3141
+ return;
3142
+ }
3143
+ let success = false;
3144
+ if (selectedConfig === "official") {
3145
+ success = await switchToOfficialLogin();
3146
+ } else {
3147
+ success = await switchToProvider(selectedConfig);
3148
+ }
3149
+ if (success) {
3150
+ updateZcfConfig({ codeToolType: "codex" });
3151
+ }
3152
+ return;
3153
+ }
3154
+ const managementMode = detectConfigManagementMode();
3155
+ if (managementMode.mode === "management" && managementMode.hasProviders) {
3156
+ const { default: { configureIncrementalManagement } } = await import('./codex-config-switch.mjs');
3157
+ await configureIncrementalManagement();
3158
+ return;
3159
+ }
3160
+ const backupPath = backupCodexComplete();
3161
+ if (backupPath) {
3162
+ console.log(ansis.gray(getBackupMessage(backupPath)));
3163
+ }
3164
+ const providers = [];
3165
+ const authEntries = {};
3166
+ const existingMap = new Map(existingConfig?.providers.map((provider) => [provider.id, provider]));
3167
+ const currentSessionProviders = /* @__PURE__ */ new Map();
3168
+ let addMore = true;
3169
+ const existingValues = existingMap.size ? Array.from(existingMap.values()) : [];
3170
+ const firstExisting = existingValues.length === 1 ? existingValues[0] : void 0;
3171
+ while (addMore) {
3172
+ const answers = await inquirer.prompt([
3173
+ {
3174
+ type: "input",
3175
+ name: "providerName",
3176
+ message: i18n.t("codex:providerNamePrompt"),
3177
+ default: firstExisting?.name,
3178
+ validate: (input) => {
3179
+ const sanitized = sanitizeProviderName(input);
3180
+ if (!sanitized)
3181
+ return i18n.t("codex:providerNameRequired");
3182
+ if (sanitized !== input.trim())
3183
+ return i18n.t("codex:providerNameInvalid");
3184
+ return true;
3185
+ }
3186
+ },
3187
+ {
3188
+ type: "input",
3189
+ name: "baseUrl",
3190
+ message: i18n.t("codex:providerBaseUrlPrompt"),
3191
+ default: (answers2) => existingMap.get(answers2.providerId)?.baseUrl || "https://api.openai.com/v1",
3192
+ validate: (input) => !!input || i18n.t("codex:providerBaseUrlRequired")
3193
+ },
3194
+ {
3195
+ type: "list",
3196
+ name: "wireApi",
3197
+ message: i18n.t("codex:providerProtocolPrompt"),
3198
+ choices: [
3199
+ { name: i18n.t("codex:protocolResponses"), value: "responses" },
3200
+ { name: i18n.t("codex:protocolChat"), value: "chat" }
3201
+ ],
3202
+ default: (answers2) => existingMap.get(sanitizeProviderName(answers2.providerName))?.wireApi || "responses"
3203
+ },
3204
+ {
3205
+ type: "password",
3206
+ name: "apiKey",
3207
+ message: i18n.t("codex:providerApiKeyPrompt") + i18n.t("common:inputHidden"),
3208
+ validate: (input) => !!input || i18n.t("codex:providerApiKeyRequired")
3209
+ }
3210
+ ]);
3211
+ const providerId = sanitizeProviderName(answers.providerName);
3212
+ const envKey = `${providerId.toUpperCase().replace(/-/g, "_")}_API_KEY`;
3213
+ const existingProvider = existingMap.get(providerId);
3214
+ const sessionProvider = currentSessionProviders.get(providerId);
3215
+ if (existingProvider || sessionProvider) {
3216
+ const sourceType = existingProvider ? "existing" : "session";
3217
+ const sourceProvider = existingProvider || sessionProvider;
3218
+ const { shouldOverwrite } = await inquirer.prompt([{
3219
+ type: "confirm",
3220
+ name: "shouldOverwrite",
3221
+ message: i18n.t("codex:providerDuplicatePrompt", {
3222
+ name: sourceProvider.name,
3223
+ source: sourceType === "existing" ? i18n.t("codex:existingConfig") : i18n.t("codex:currentSession")
3224
+ }),
3225
+ default: false
3226
+ }]);
3227
+ if (!shouldOverwrite) {
3228
+ console.log(ansis.yellow(i18n.t("codex:providerDuplicateSkipped")));
3229
+ continue;
3230
+ }
3231
+ if (sessionProvider) {
3232
+ currentSessionProviders.delete(providerId);
3233
+ const sessionIndex = providers.findIndex((p) => p.id === providerId);
3234
+ if (sessionIndex !== -1) {
3235
+ providers.splice(sessionIndex, 1);
3236
+ }
3237
+ }
3238
+ }
3239
+ const newProvider = {
3240
+ id: providerId,
3241
+ name: answers.providerName,
3242
+ baseUrl: answers.baseUrl,
3243
+ wireApi: answers.wireApi || "responses",
3244
+ envKey,
3245
+ requiresOpenaiAuth: true
3246
+ };
3247
+ providers.push(newProvider);
3248
+ currentSessionProviders.set(providerId, newProvider);
3249
+ authEntries[envKey] = answers.apiKey;
3250
+ const { addAnother } = await inquirer.prompt([{
3251
+ type: "confirm",
3252
+ name: "addAnother",
3253
+ message: i18n.t("codex:addProviderPrompt"),
3254
+ default: false
3255
+ }]);
3256
+ addMore = addAnother;
3257
+ }
3258
+ if (providers.length === 0) {
3259
+ console.log(ansis.yellow(i18n.t("codex:noProvidersConfigured")));
3260
+ return;
3261
+ }
3262
+ const { defaultProvider } = await inquirer.prompt([{
3263
+ type: "list",
3264
+ name: "defaultProvider",
3265
+ message: i18n.t("codex:selectDefaultProviderPrompt"),
3266
+ choices: addNumbersToChoices(toProvidersList(providers)),
3267
+ default: existingConfig?.modelProvider || providers[0].id
3268
+ }]);
3269
+ const selectedProvider = providers.find((provider) => provider.id === defaultProvider);
3270
+ if (selectedProvider) {
3271
+ const envKey = selectedProvider.envKey;
3272
+ const defaultApiKey = authEntries[envKey] ?? existingAuth[envKey] ?? null;
3273
+ if (defaultApiKey)
3274
+ authEntries.OPENAI_API_KEY = defaultApiKey;
3275
+ }
3276
+ writeCodexConfig({
3277
+ model: existingConfig?.model || null,
3278
+ modelProvider: defaultProvider,
3279
+ providers,
3280
+ mcpServices: existingConfig?.mcpServices || [],
3281
+ otherConfig: existingConfig?.otherConfig || []
3282
+ });
3283
+ writeAuthFile(authEntries);
3284
+ updateZcfConfig({ codeToolType: "codex" });
3285
+ console.log(ansis.green(i18n.t("codex:apiConfigured")));
3286
+ }
3287
+ async function configureCodexMcp() {
3288
+ ensureI18nInitialized();
3289
+ const existingConfig = readCodexConfig();
3290
+ const backupPath = backupCodexComplete();
3291
+ if (backupPath) {
3292
+ console.log(ansis.gray(getBackupMessage(backupPath)));
3293
+ }
3294
+ const selectedIds = await selectMcpServices();
3295
+ if (!selectedIds)
3296
+ return;
3297
+ const servicesMeta = await getMcpServices();
3298
+ const baseProviders = existingConfig?.providers || [];
3299
+ const selection = [];
3300
+ const existingMap = new Map((existingConfig?.mcpServices || []).map((service) => [service.id, service]));
3301
+ if (selectedIds.length === 0) {
3302
+ console.log(ansis.yellow(i18n.t("codex:noMcpConfigured")));
3303
+ writeCodexConfig({
3304
+ model: existingConfig?.model || null,
3305
+ modelProvider: existingConfig?.modelProvider || null,
3306
+ providers: baseProviders,
3307
+ mcpServices: Array.from(existingMap.values()),
3308
+ otherConfig: existingConfig?.otherConfig || []
3309
+ });
3310
+ updateZcfConfig({ codeToolType: "codex" });
3311
+ return;
3312
+ }
3313
+ for (const id of selectedIds) {
3314
+ const configInfo = MCP_SERVICE_CONFIGS.find((service) => service.id === id);
3315
+ if (!configInfo)
3316
+ continue;
3317
+ const serviceMeta = servicesMeta.find((service) => service.id === id);
3318
+ let command = configInfo.config.command || id;
3319
+ const args = (configInfo.config.args || []).map((arg) => String(arg));
3320
+ if (isWindows() && command === "npx")
3321
+ command = "npx.cmd";
3322
+ const env = { ...configInfo.config.env || {} };
3323
+ if (configInfo.requiresApiKey && configInfo.apiKeyEnvVar) {
3324
+ const promptMessage = serviceMeta?.apiKeyPrompt || i18n.t("mcp:apiKeyPrompt");
3325
+ const { apiKey } = await inquirer.prompt([{
3326
+ type: "password",
3327
+ name: "apiKey",
3328
+ message: promptMessage + i18n.t("common:inputHidden"),
3329
+ validate: (input) => !!input || i18n.t("api:keyRequired")
3330
+ }]);
3331
+ if (!apiKey)
3332
+ continue;
3333
+ env[configInfo.apiKeyEnvVar] = apiKey;
3334
+ }
3335
+ selection.push({
3336
+ id: id.toLowerCase(),
3337
+ // Convert to lowercase for Codex compatibility
3338
+ command,
3339
+ args,
3340
+ env: Object.keys(env).length > 0 ? env : void 0,
3341
+ startup_timeout_ms: configInfo.config.startup_timeout_ms
3342
+ });
3343
+ }
3344
+ const selectionMap = new Map(selection.map((service) => [service.id, service]));
3345
+ const mergedMap = new Map(existingMap);
3346
+ for (const service of selectionMap.values())
3347
+ mergedMap.set(service.id, service);
3348
+ writeCodexConfig({
3349
+ model: existingConfig?.model || null,
3350
+ modelProvider: existingConfig?.modelProvider || null,
3351
+ providers: baseProviders,
3352
+ mcpServices: Array.from(mergedMap.values()),
3353
+ otherConfig: existingConfig?.otherConfig || []
3354
+ });
3355
+ updateZcfConfig({ codeToolType: "codex" });
3356
+ console.log(ansis.green(i18n.t("codex:mcpConfigured")));
3357
+ }
3358
+ async function runCodexFullInit() {
3359
+ ensureI18nInitialized();
3360
+ await installCodexCli();
3361
+ await runCodexWorkflowImport();
3362
+ await configureCodexApi();
3363
+ await configureCodexMcp();
3364
+ }
3365
+ async function runCodexUpdate(force = false, skipPrompt = false) {
3366
+ ensureI18nInitialized();
3367
+ const spinner = ora(i18n.t("codex:checkingVersion")).start();
3368
+ try {
3369
+ const { installed, currentVersion, latestVersion, needsUpdate } = await checkCodexUpdate();
3370
+ spinner.stop();
3371
+ if (!installed) {
3372
+ console.log(ansis.yellow(i18n.t("codex:notInstalled")));
3373
+ return false;
3374
+ }
3375
+ if (!needsUpdate && !force) {
3376
+ console.log(ansis.green(format(i18n.t("codex:upToDate"), { version: currentVersion || "" })));
3377
+ return true;
3378
+ }
3379
+ if (!latestVersion) {
3380
+ console.log(ansis.yellow(i18n.t("codex:cannotCheckVersion")));
3381
+ return false;
3382
+ }
3383
+ console.log(ansis.cyan(format(i18n.t("codex:currentVersion"), { version: currentVersion || "" })));
3384
+ console.log(ansis.cyan(format(i18n.t("codex:latestVersion"), { version: latestVersion })));
3385
+ if (!skipPrompt) {
3386
+ const { confirm } = await inquirer.prompt({
3387
+ type: "confirm",
3388
+ name: "confirm",
3389
+ message: i18n.t("codex:confirmUpdate"),
3390
+ default: true
3391
+ });
3392
+ if (!confirm) {
3393
+ console.log(ansis.gray(i18n.t("codex:updateSkipped")));
3394
+ return true;
3395
+ }
3396
+ } else {
3397
+ console.log(ansis.cyan(i18n.t("codex:autoUpdating")));
3398
+ }
3399
+ const updateSpinner = ora(i18n.t("codex:updating")).start();
3400
+ try {
3401
+ await executeCodexInstallation(true);
3402
+ updateSpinner.succeed(i18n.t("codex:updateSuccess"));
3403
+ return true;
3404
+ } catch (error) {
3405
+ updateSpinner.fail(i18n.t("codex:updateFailed"));
3406
+ console.error(ansis.red(error instanceof Error ? error.message : String(error)));
3407
+ return false;
3408
+ }
3409
+ } catch (error) {
3410
+ spinner.fail(i18n.t("codex:checkFailed"));
3411
+ console.error(ansis.red(error instanceof Error ? error.message : String(error)));
3412
+ return false;
3413
+ }
3414
+ }
3415
+ async function runCodexUninstall() {
3416
+ ensureI18nInitialized();
3417
+ const { CodexUninstaller } = await import('./codex-uninstaller.mjs');
3418
+ const uninstaller = new CodexUninstaller("en");
3419
+ const { mode } = await inquirer.prompt([{
3420
+ type: "list",
3421
+ name: "mode",
3422
+ message: i18n.t("codex:uninstallModePrompt"),
3423
+ choices: addNumbersToChoices([
3424
+ { name: i18n.t("codex:uninstallModeComplete"), value: "complete" },
3425
+ { name: i18n.t("codex:uninstallModeCustom"), value: "custom" }
3426
+ ]),
3427
+ default: "complete"
3428
+ }]);
3429
+ if (!mode) {
3430
+ handleUninstallCancellation();
3431
+ return;
3432
+ }
3433
+ try {
3434
+ if (mode === "complete") {
3435
+ const { confirm } = await inquirer.prompt([{
3436
+ type: "confirm",
3437
+ name: "confirm",
3438
+ message: i18n.t("codex:uninstallPrompt"),
3439
+ default: false
3440
+ }]);
3441
+ if (!confirm) {
3442
+ handleUninstallCancellation();
3443
+ return;
3444
+ }
3445
+ const result = await uninstaller.completeUninstall();
3446
+ displayUninstallResults([result]);
3447
+ } else if (mode === "custom") {
3448
+ const { items } = await inquirer.prompt([{
3449
+ type: "checkbox",
3450
+ name: "items",
3451
+ message: i18n.t("codex:customUninstallPrompt"),
3452
+ choices: addNumbersToChoices(getUninstallOptions())
3453
+ }]);
3454
+ if (!items || items.length === 0) {
3455
+ handleUninstallCancellation();
3456
+ return;
3457
+ }
3458
+ const results = await uninstaller.customUninstall(items);
3459
+ displayUninstallResults(results);
3460
+ }
3461
+ console.log(ansis.green(i18n.t("codex:uninstallSuccess")));
3462
+ } catch (error) {
3463
+ console.error(ansis.red(`Error during uninstall: ${error.message}`));
3464
+ throw error;
3465
+ }
3466
+ }
3467
+ function displayUninstallResults(results) {
3468
+ for (const result of results) {
3469
+ for (const item of result.removed) {
3470
+ console.log(ansis.green(`\u2714 ${i18n.t("codex:removedItem", { item })}`));
3471
+ }
3472
+ for (const config of result.removedConfigs) {
3473
+ console.log(ansis.green(`\u2714 ${i18n.t("codex:removedConfig", { config })}`));
3474
+ }
3475
+ for (const warning of result.warnings) {
3476
+ console.log(ansis.yellow(`\u26A0\uFE0F ${warning}`));
3477
+ }
3478
+ for (const error of result.errors) {
3479
+ console.log(ansis.red(`\u274C ${error}`));
3480
+ }
3481
+ }
3482
+ }
3483
+ async function getCurrentCodexProvider() {
3484
+ const config = readCodexConfig();
3485
+ return config?.modelProvider || null;
3486
+ }
3487
+ async function listCodexProviders() {
3488
+ const config = readCodexConfig();
3489
+ return config?.providers || [];
3490
+ }
3491
+ async function switchCodexProvider(providerId) {
3492
+ ensureI18nInitialized();
3493
+ const existingConfig = readCodexConfig();
3494
+ if (!existingConfig) {
3495
+ console.log(ansis.red(i18n.t("codex:configNotFound")));
3496
+ return false;
3497
+ }
3498
+ const providerExists = existingConfig.providers.some((provider) => provider.id === providerId);
3499
+ if (!providerExists) {
3500
+ console.log(ansis.red(i18n.t("codex:providerNotFound", { provider: providerId })));
3501
+ return false;
3502
+ }
3503
+ const backupPath = backupCodexComplete();
3504
+ if (backupPath) {
3505
+ console.log(ansis.gray(getBackupMessage(backupPath)));
3506
+ }
3507
+ const updatedConfig = {
3508
+ ...existingConfig,
3509
+ modelProvider: providerId
3510
+ };
3511
+ try {
3512
+ writeCodexConfig(updatedConfig);
3513
+ console.log(ansis.green(i18n.t("codex:providerSwitchSuccess", { provider: providerId })));
3514
+ return true;
3515
+ } catch (error) {
3516
+ console.error(ansis.red(`Error switching provider: ${error.message}`));
3517
+ return false;
3518
+ }
3519
+ }
3520
+ async function switchToOfficialLogin() {
3521
+ ensureI18nInitialized();
3522
+ const existingConfig = readCodexConfig();
3523
+ if (!existingConfig) {
3524
+ console.log(ansis.red(i18n.t("codex:configNotFound")));
3525
+ return false;
3526
+ }
3527
+ const backupPath = backupCodexComplete();
3528
+ if (backupPath) {
3529
+ console.log(ansis.gray(getBackupMessage(backupPath)));
3530
+ }
3531
+ try {
3532
+ const updatedConfig = {
3533
+ ...existingConfig,
3534
+ modelProvider: existingConfig.modelProvider,
3535
+ // Keep the current provider value
3536
+ modelProviderCommented: true
3537
+ // Mark as commented
3538
+ };
3539
+ writeCodexConfig(updatedConfig);
3540
+ const auth = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
3541
+ auth.OPENAI_API_KEY = null;
3542
+ writeJsonConfig(CODEX_AUTH_FILE, auth, { pretty: true });
3543
+ console.log(ansis.green(i18n.t("codex:officialConfigured")));
3544
+ return true;
3545
+ } catch (error) {
3546
+ console.error(ansis.red(`Error switching to official login: ${error.message}`));
3547
+ return false;
3548
+ }
3549
+ }
3550
+ async function switchToProvider(providerId) {
3551
+ ensureI18nInitialized();
3552
+ const existingConfig = readCodexConfig();
3553
+ if (!existingConfig) {
3554
+ console.log(ansis.red(i18n.t("codex:configNotFound")));
3555
+ return false;
3556
+ }
3557
+ const provider = existingConfig.providers.find((p) => p.id === providerId);
3558
+ if (!provider) {
3559
+ console.log(ansis.red(i18n.t("codex:providerNotFound", { provider: providerId })));
3560
+ return false;
3561
+ }
3562
+ const backupPath = backupCodexComplete();
3563
+ if (backupPath) {
3564
+ console.log(ansis.gray(getBackupMessage(backupPath)));
3565
+ }
3566
+ try {
3567
+ const updatedConfig = {
3568
+ ...existingConfig,
3569
+ modelProvider: providerId,
3570
+ modelProviderCommented: false
3571
+ // Ensure it's not commented
3572
+ };
3573
+ writeCodexConfig(updatedConfig);
3574
+ const auth = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
3575
+ const envValue = auth[provider.envKey] || null;
3576
+ auth.OPENAI_API_KEY = envValue;
3577
+ writeJsonConfig(CODEX_AUTH_FILE, auth, { pretty: true });
3578
+ console.log(ansis.green(i18n.t("codex:providerSwitchSuccess", { provider: providerId })));
3579
+ return true;
3580
+ } catch (error) {
3581
+ console.error(ansis.red(`Error switching to provider: ${error.message}`));
3582
+ return false;
3583
+ }
3584
+ }
3585
+
3586
+ const codex = {
3587
+ __proto__: null,
3588
+ CODEX_DIR: CODEX_DIR,
3589
+ backupCodexAgents: backupCodexAgents,
3590
+ backupCodexComplete: backupCodexComplete,
3591
+ backupCodexConfig: backupCodexConfig,
3592
+ backupCodexFiles: backupCodexFiles,
3593
+ backupCodexPrompts: backupCodexPrompts,
3594
+ checkCodexUpdate: checkCodexUpdate,
3595
+ configureCodexApi: configureCodexApi,
3596
+ configureCodexMcp: configureCodexMcp,
3597
+ createBackupDirectory: createBackupDirectory,
3598
+ getBackupMessage: getBackupMessage,
3599
+ getCodexVersion: getCodexVersion,
3600
+ getCurrentCodexProvider: getCurrentCodexProvider,
3601
+ installCodexCli: installCodexCli,
3602
+ isCodexInstalled: isCodexInstalled,
3603
+ listCodexProviders: listCodexProviders,
3604
+ parseCodexConfig: parseCodexConfig,
3605
+ readCodexConfig: readCodexConfig,
3606
+ renderCodexConfig: renderCodexConfig,
3607
+ runCodexFullInit: runCodexFullInit,
3608
+ runCodexSystemPromptSelection: runCodexSystemPromptSelection,
3609
+ runCodexUninstall: runCodexUninstall,
3610
+ runCodexUpdate: runCodexUpdate,
3611
+ runCodexWorkflowImport: runCodexWorkflowImport,
3612
+ runCodexWorkflowSelection: runCodexWorkflowSelection,
3613
+ switchCodexProvider: switchCodexProvider,
3614
+ switchToOfficialLogin: switchToOfficialLogin,
3615
+ switchToProvider: switchToProvider,
3616
+ writeAuthFile: writeAuthFile,
3617
+ writeCodexConfig: writeCodexConfig
3618
+ };
3619
+
3620
+ function getPlatformStatusLineConfig() {
3621
+ return {
3622
+ type: "command",
3623
+ command: isWindows() ? "%USERPROFILE%\\.claude\\ccline\\ccline.exe" : "~/.claude/ccline/ccline",
3624
+ padding: 0
3625
+ };
3626
+ }
3627
+
3628
+ function addCCometixLineConfig() {
3629
+ try {
3630
+ const statusLineConfig = getPlatformStatusLineConfig();
3631
+ let settings = {};
3632
+ if (exists(SETTINGS_FILE)) {
3633
+ settings = readJsonConfig(SETTINGS_FILE) || {};
3634
+ }
3635
+ settings.statusLine = statusLineConfig;
3636
+ writeJsonConfig(SETTINGS_FILE, settings);
3637
+ return true;
3638
+ } catch (error) {
3639
+ console.error("Failed to add CCometixLine configuration:", error);
3640
+ return false;
3641
+ }
3642
+ }
2013
3643
  function hasCCometixLineConfig() {
2014
3644
  try {
2015
3645
  if (!exists(SETTINGS_FILE)) {
@@ -2082,59 +3712,6 @@ async function installCometixLine() {
2082
3712
  }
2083
3713
  }
2084
3714
 
2085
- function addNumbersToChoices(choices, startFrom = 1, format = (n) => `${n}. `) {
2086
- let currentNumber = startFrom;
2087
- return choices.map((choice) => {
2088
- if (choice.disabled) {
2089
- return choice;
2090
- }
2091
- const numbered = {
2092
- ...choice,
2093
- name: `${format(currentNumber)}${choice.name}`
2094
- };
2095
- currentNumber++;
2096
- return numbered;
2097
- });
2098
- }
2099
-
2100
- function readZcfConfig() {
2101
- let config = readJsonConfig(ZCF_CONFIG_FILE);
2102
- if (!config && existsSync(LEGACY_ZCF_CONFIG_FILE)) {
2103
- config = readJsonConfig(LEGACY_ZCF_CONFIG_FILE);
2104
- }
2105
- return config;
2106
- }
2107
- async function readZcfConfigAsync() {
2108
- return readZcfConfig();
2109
- }
2110
- function writeZcfConfig(config) {
2111
- try {
2112
- writeJsonConfig(ZCF_CONFIG_FILE, config);
2113
- } catch {
2114
- }
2115
- }
2116
- function updateZcfConfig(updates) {
2117
- const existingConfig = readZcfConfig();
2118
- const newConfig = {
2119
- version: updates.version || existingConfig?.version || "1.0.0",
2120
- preferredLang: updates.preferredLang || existingConfig?.preferredLang || "en",
2121
- aiOutputLang: updates.aiOutputLang || existingConfig?.aiOutputLang,
2122
- outputStyles: updates.outputStyles !== void 0 ? updates.outputStyles : existingConfig?.outputStyles,
2123
- defaultOutputStyle: updates.defaultOutputStyle !== void 0 ? updates.defaultOutputStyle : existingConfig?.defaultOutputStyle,
2124
- claudeCodeInstallation: updates.claudeCodeInstallation !== void 0 ? updates.claudeCodeInstallation : existingConfig?.claudeCodeInstallation,
2125
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
2126
- };
2127
- writeZcfConfig(newConfig);
2128
- }
2129
- function getZcfConfig() {
2130
- const config = readZcfConfig();
2131
- return config || {
2132
- version: "1.0.0",
2133
- preferredLang: "en",
2134
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
2135
- };
2136
- }
2137
-
2138
3715
  const OUTPUT_STYLES = [
2139
3716
  // Custom styles (have template files)
2140
3717
  {
@@ -2176,7 +3753,7 @@ async function copyOutputStyles(selectedStyles, lang) {
2176
3753
  const currentFilePath = fileURLToPath(import.meta.url);
2177
3754
  const distDir = dirname(dirname(currentFilePath));
2178
3755
  const rootDir = dirname(distDir);
2179
- const templateDir = join(rootDir, "templates", lang, "output-styles");
3756
+ const templateDir = join(rootDir, "templates", "claude-code", lang, "output-styles");
2180
3757
  for (const styleId of selectedStyles) {
2181
3758
  const style = OUTPUT_STYLES.find((s) => s.id === styleId);
2182
3759
  if (!style || !style.isCustom || !style.filePath) {
@@ -2392,9 +3969,9 @@ async function configureApiCompletely(preselectedAuthType) {
2392
3969
  console.log(ansis.yellow(i18n.t("common:cancelled")));
2393
3970
  return null;
2394
3971
  }
2395
- const keyMessage = authType === "auth_token" ? i18n.t("api:enterAuthToken") : i18n.t("api:enterApiKey");
3972
+ const keyMessage = authType === "auth_token" ? i18n.t("api:enterAuthToken") + i18n.t("common:inputHidden") : i18n.t("api:enterApiKey") + i18n.t("common:inputHidden");
2396
3973
  const { key } = await inquirer.prompt({
2397
- type: "input",
3974
+ type: "password",
2398
3975
  name: "key",
2399
3976
  message: keyMessage,
2400
3977
  validate: async (value) => {
@@ -2465,9 +4042,9 @@ async function modifyApiConfigPartially(existingConfig) {
2465
4042
  }
2466
4043
  } else if (item === "key") {
2467
4044
  const authType = currentConfig.authType || "auth_token";
2468
- 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"));
4045
+ const keyMessage = authType === "auth_token" ? i18n.t("api:enterNewApiKey").replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.t("common:none")) + i18n.t("common:inputHidden") : i18n.t("api:enterNewApiKey").replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.t("common:none")) + i18n.t("common:inputHidden");
2469
4046
  const { key } = await inquirer.prompt({
2470
- type: "input",
4047
+ type: "password",
2471
4048
  name: "key",
2472
4049
  message: keyMessage,
2473
4050
  validate: async (value) => {
@@ -2661,14 +4238,16 @@ async function chooseInstallationMethod() {
2661
4238
  }
2662
4239
  async function handleMultipleInstallations(status) {
2663
4240
  ensureI18nInitialized();
2664
- const existingConfig = getZcfConfig();
2665
- const previousChoice = existingConfig.claudeCodeInstallation;
2666
- if (previousChoice) {
2667
- if (previousChoice.type === "global" && status.hasGlobal) {
2668
- return "global";
2669
- }
2670
- if (previousChoice.type === "local" && status.hasLocal) {
2671
- return "local";
4241
+ const tomlConfig = readTomlConfig(ZCF_CONFIG_FILE);
4242
+ if (tomlConfig && tomlConfig.general?.currentTool === "claude-code") {
4243
+ const previousChoice = tomlConfig.claudeCode?.installType;
4244
+ if (previousChoice) {
4245
+ if (previousChoice === "global" && status.hasGlobal) {
4246
+ return "global";
4247
+ }
4248
+ if (previousChoice === "local" && status.hasLocal) {
4249
+ return "local";
4250
+ }
2672
4251
  }
2673
4252
  }
2674
4253
  if (!status.hasGlobal && !status.hasLocal) {
@@ -2704,17 +4283,17 @@ async function handleMultipleInstallations(status) {
2704
4283
  await removeLocalClaudeCode();
2705
4284
  console.log(ansis.green(`\u2714 ${i18n.t("installation:localInstallationRemoved")}`));
2706
4285
  }
2707
- await saveInstallationConfig({
2708
- type: "global",
2709
- path: "claude",
2710
- configDir: CLAUDE_DIR
4286
+ updateTomlConfig(ZCF_CONFIG_FILE, {
4287
+ claudeCode: {
4288
+ installType: "global"
4289
+ }
2711
4290
  });
2712
4291
  } else {
2713
4292
  console.log(ansis.green(`\u2714 ${i18n.t("installation:usingLocalInstallation")}`));
2714
- await saveInstallationConfig({
2715
- type: "local",
2716
- path: status.localPath,
2717
- configDir: join(homedir(), ".claude")
4293
+ updateTomlConfig(ZCF_CONFIG_FILE, {
4294
+ claudeCode: {
4295
+ installType: "local"
4296
+ }
2718
4297
  });
2719
4298
  }
2720
4299
  return choice;
@@ -2728,130 +4307,13 @@ async function handleMultipleInstallations(status) {
2728
4307
  }
2729
4308
  }
2730
4309
  }
2731
- async function saveInstallationConfig(installation) {
2732
- try {
2733
- updateZcfConfig({
2734
- claudeCodeInstallation: installation
2735
- });
2736
- } catch (error) {
2737
- console.error(ansis.red(`\u2716 ${i18n.t("installation:failedToSaveInstallationConfig")}: ${error}`));
2738
- }
2739
- }
2740
-
2741
- async function selectMcpServices() {
2742
- ensureI18nInitialized();
2743
- const mcpServices = await getMcpServices();
2744
- const choices = mcpServices.map((service) => ({
2745
- name: `${service.name} - ${ansis.gray(service.description)}`,
2746
- value: service.id,
2747
- selected: false
2748
- }));
2749
- const { services } = await inquirer.prompt({
2750
- type: "checkbox",
2751
- name: "services",
2752
- message: `${i18n.t("mcp:selectMcpServices")}${i18n.t("common:multiSelectHint")}`,
2753
- choices
2754
- });
2755
- if (services === void 0) {
2756
- console.log(ansis.yellow(i18n.t("common:cancelled")));
2757
- return void 0;
2758
- }
2759
- return services;
2760
- }
2761
-
2762
- async function selectAiOutputLanguage(defaultLang) {
2763
- ensureI18nInitialized();
2764
- console.log(ansis.dim(`
2765
- ${i18n.t("language:aiOutputLangHint")}
2766
- `));
2767
- const aiLangChoices = Object.entries(AI_OUTPUT_LANGUAGES).map(([key]) => ({
2768
- title: getAiOutputLanguageLabel(key),
2769
- value: key
2770
- }));
2771
- const defaultChoice = defaultLang || "en";
2772
- const { lang } = await inquirer.prompt({
2773
- type: "list",
2774
- name: "lang",
2775
- message: i18n.t("language:selectAiOutputLang"),
2776
- choices: addNumbersToChoices(aiLangChoices.map((choice) => ({
2777
- name: choice.title,
2778
- value: choice.value
2779
- }))),
2780
- default: defaultChoice
2781
- });
2782
- if (!lang) {
2783
- console.log(ansis.yellow(i18n.t("common:cancelled")));
2784
- process.exit(0);
2785
- }
2786
- const aiOutputLang = lang;
2787
- if (aiOutputLang === "custom") {
2788
- const { customLang } = await inquirer.prompt({
2789
- type: "input",
2790
- name: "customLang",
2791
- message: i18n.t("language:enterCustomLanguage"),
2792
- validate: async (value) => !!value || i18n.t("language:languageRequired") || "Language is required"
2793
- });
2794
- if (!customLang) {
2795
- console.log(ansis.yellow(i18n.t("common:cancelled")));
2796
- process.exit(0);
2797
- }
2798
- return customLang;
2799
- }
2800
- return aiOutputLang;
2801
- }
2802
- const LANGUAGE_SELECTION_MESSAGES = {
2803
- selectLanguage: "Select ZCF display language / \u9009\u62E9ZCF\u663E\u793A\u8BED\u8A00",
2804
- operationCancelled: "Operation cancelled / \u64CD\u4F5C\u5DF2\u53D6\u6D88"
2805
- };
2806
- async function selectScriptLanguage(currentLang) {
2807
- const zcfConfig = readZcfConfig();
2808
- if (zcfConfig?.preferredLang) {
2809
- return zcfConfig.preferredLang;
2810
- }
2811
- const { lang } = await inquirer.prompt({
2812
- type: "list",
2813
- name: "lang",
2814
- message: LANGUAGE_SELECTION_MESSAGES.selectLanguage,
2815
- choices: addNumbersToChoices(SUPPORTED_LANGS.map((l) => ({
2816
- name: LANG_LABELS[l],
2817
- value: l
2818
- })))
2819
- });
2820
- if (!lang) {
2821
- console.log(ansis.yellow(LANGUAGE_SELECTION_MESSAGES.operationCancelled));
2822
- process.exit(0);
2823
- }
2824
- const scriptLang = lang;
2825
- updateZcfConfig({
2826
- version,
2827
- preferredLang: scriptLang
2828
- });
2829
- return scriptLang;
2830
- }
2831
- async function resolveAiOutputLanguage(scriptLang, commandLineOption, savedConfig) {
2832
- ensureI18nInitialized();
2833
- if (commandLineOption) {
2834
- return commandLineOption;
2835
- }
2836
- if (savedConfig?.aiOutputLang) {
2837
- console.log(ansis.gray(`\u2714 ${i18n.t("language:aiOutputLangHint")}: ${savedConfig.aiOutputLang}`));
2838
- return savedConfig.aiOutputLang;
2839
- }
2840
- return await selectAiOutputLanguage(scriptLang);
2841
- }
2842
-
2843
- const prompts = {
2844
- __proto__: null,
2845
- resolveAiOutputLanguage: resolveAiOutputLanguage,
2846
- selectAiOutputLanguage: selectAiOutputLanguage,
2847
- selectScriptLanguage: selectScriptLanguage
2848
- };
2849
4310
 
2850
4311
  function getRootDir() {
2851
4312
  const currentFilePath = fileURLToPath(import.meta.url);
2852
4313
  const distDir = dirname(dirname(currentFilePath));
2853
4314
  return dirname(distDir);
2854
4315
  }
4316
+ const DEFAULT_CODE_TOOL_TEMPLATE = "claude-code";
2855
4317
  async function selectAndInstallWorkflows(configLang, preselectedWorkflows) {
2856
4318
  ensureI18nInitialized();
2857
4319
  const workflows = getOrderedWorkflows();
@@ -2911,7 +4373,16 @@ async function installWorkflowWithDependencies(config, configLang) {
2911
4373
  await mkdir(commandsDir, { recursive: true });
2912
4374
  }
2913
4375
  for (const commandFile of config.commands) {
2914
- const commandSource = join(rootDir, "templates", configLang, "workflow", config.category, "commands", commandFile);
4376
+ const commandSource = join(
4377
+ rootDir,
4378
+ "templates",
4379
+ DEFAULT_CODE_TOOL_TEMPLATE,
4380
+ configLang,
4381
+ "workflow",
4382
+ config.category,
4383
+ "commands",
4384
+ commandFile
4385
+ );
2915
4386
  const destFileName = commandFile;
2916
4387
  const commandDest = join(commandsDir, destFileName);
2917
4388
  if (existsSync(commandSource)) {
@@ -2933,7 +4404,16 @@ async function installWorkflowWithDependencies(config, configLang) {
2933
4404
  await mkdir(agentsCategoryDir, { recursive: true });
2934
4405
  }
2935
4406
  for (const agent of config.agents) {
2936
- const agentSource = join(rootDir, "templates", configLang, "workflow", config.category, "agents", agent.filename);
4407
+ const agentSource = join(
4408
+ rootDir,
4409
+ "templates",
4410
+ DEFAULT_CODE_TOOL_TEMPLATE,
4411
+ configLang,
4412
+ "workflow",
4413
+ config.category,
4414
+ "agents",
4415
+ agent.filename
4416
+ );
2937
4417
  const agentDest = join(agentsCategoryDir, agent.filename);
2938
4418
  if (existsSync(agentSource)) {
2939
4419
  try {
@@ -3109,6 +4589,15 @@ function validateSkipPromptOptions(options) {
3109
4589
  options.workflows = WORKFLOW_CONFIG_BASE.map((w) => w.id);
3110
4590
  }
3111
4591
  }
4592
+ function resolveCodeToolType(optionValue, savedValue) {
4593
+ if (isCodeToolType(optionValue)) {
4594
+ return optionValue;
4595
+ }
4596
+ if (savedValue && isCodeToolType(savedValue)) {
4597
+ return savedValue;
4598
+ }
4599
+ return DEFAULT_CODE_TOOL_TYPE;
4600
+ }
3112
4601
  async function init(options = {}) {
3113
4602
  if (options.skipPrompt) {
3114
4603
  validateSkipPromptOptions(options);
@@ -3122,32 +4611,34 @@ async function init(options = {}) {
3122
4611
  \u2139 ${i18n.t("installation:termuxDetected")}`));
3123
4612
  console.log(ansis.gray(i18n.t("installation:termuxEnvironmentInfo")));
3124
4613
  }
4614
+ const zcfConfig = readZcfConfig();
3125
4615
  let configLang = options.configLang;
3126
4616
  if (!configLang && !options.skipPrompt) {
3127
- const LANG_HINT_KEYS = {
3128
- "zh-CN": i18n.t("language:configLangHint.zh-CN"),
3129
- "en": i18n.t("language:configLangHint.en")
3130
- };
3131
- const { lang } = await inquirer.prompt({
3132
- type: "list",
3133
- name: "lang",
3134
- message: i18n.t("language:selectConfigLang"),
3135
- choices: addNumbersToChoices(
3136
- SUPPORTED_LANGS.map((l) => ({
3137
- name: `${LANG_LABELS[l]} - ${LANG_HINT_KEYS[l]}`,
3138
- value: l
3139
- }))
3140
- )
3141
- });
3142
- if (!lang) {
3143
- console.log(ansis.yellow(i18n.t("common:cancelled")));
3144
- process.exit(0);
3145
- }
3146
- configLang = lang;
4617
+ const { resolveTemplateLanguage } = await Promise.resolve().then(function () { return prompts; });
4618
+ configLang = await resolveTemplateLanguage(
4619
+ options.configLang,
4620
+ // Command line option
4621
+ zcfConfig
4622
+ );
3147
4623
  } else if (!configLang && options.skipPrompt) {
3148
4624
  configLang = "en";
3149
4625
  }
3150
- const zcfConfig = readZcfConfig();
4626
+ const codeToolType = resolveCodeToolType(options.codeType, zcfConfig?.codeToolType);
4627
+ options.codeType = codeToolType;
4628
+ if (codeToolType === "codex") {
4629
+ await runCodexFullInit();
4630
+ updateZcfConfig({
4631
+ version,
4632
+ preferredLang: i18n.language,
4633
+ // ZCF界面语言
4634
+ templateLang: configLang,
4635
+ // 模板语言
4636
+ aiOutputLang: options.aiOutputLang || "en",
4637
+ codeToolType
4638
+ });
4639
+ console.log(ansis.green(i18n.t("codex:setupComplete")));
4640
+ return;
4641
+ }
3151
4642
  const aiOutputLang = options.skipPrompt ? options.aiOutputLang || "en" : await resolveAiOutputLanguage(i18n.language, options.aiOutputLang, zcfConfig);
3152
4643
  const installationStatus = await getInstallationStatus();
3153
4644
  if (installationStatus.hasGlobal || installationStatus.hasLocal) {
@@ -3468,9 +4959,9 @@ ${ansis.blue(`\u2139 ${i18n.t("api:existingApiConfig")}`)}`);
3468
4959
  continue;
3469
4960
  } else {
3470
4961
  const response = await inquirer.prompt({
3471
- type: "input",
4962
+ type: "password",
3472
4963
  name: "apiKey",
3473
- message: service.apiKeyPrompt,
4964
+ message: service.apiKeyPrompt + i18n.t("common:inputHidden"),
3474
4965
  validate: (value) => !!value || i18n.t("api:keyRequired")
3475
4966
  });
3476
4967
  if (!response.apiKey) {
@@ -3523,7 +5014,11 @@ ${ansis.blue(`\u2139 ${i18n.t("api:existingApiConfig")}`)}`);
3523
5014
  updateZcfConfig({
3524
5015
  version,
3525
5016
  preferredLang: i18n.language,
3526
- aiOutputLang
5017
+ // ZCF界面语言
5018
+ templateLang: configLang,
5019
+ // 模板语言
5020
+ aiOutputLang,
5021
+ codeToolType
3527
5022
  });
3528
5023
  console.log(ansis.green(`\u2714 ${i18n.t("configuration:configSuccess")} ${CLAUDE_DIR}`));
3529
5024
  console.log(`
@@ -3537,7 +5032,7 @@ ${ansis.cyan(i18n.t("common:complete"))}`);
3537
5032
 
3538
5033
  const __dirname = dirname(fileURLToPath(import.meta.url));
3539
5034
  function getTemplateSettings() {
3540
- const templatePath = join(__dirname, "../../templates/common/settings.json");
5035
+ const templatePath = join(__dirname, "../../templates/claude-code/common/settings.json");
3541
5036
  const content = readFileSync(templatePath, "utf-8");
3542
5037
  return JSON.parse(content);
3543
5038
  }
@@ -3613,4 +5108,4 @@ async function openSettingsJson() {
3613
5108
  }
3614
5109
  }
3615
5110
 
3616
- export { addNumbersToChoices as $, AI_OUTPUT_LANGUAGES as A, copyConfigFiles as B, CLAUDE_DIR as C, configureApi as D, mergeConfigs as E, updateCustomModel as F, updateDefaultModel as G, mergeSettingsFile as H, getExistingModelConfig as I, getExistingApiConfig as J, applyAiLanguageDirective as K, LEGACY_ZCF_CONFIG_FILE as L, isClaudeCodeInstalled as M, installClaudeCode as N, isLocalClaudeCodeInstalled as O, getInstallationStatus as P, removeLocalClaudeCode as Q, ensureI18nInitialized as R, SETTINGS_FILE as S, i18n as T, readCcrConfig as U, isCcrInstalled as V, installCcr as W, configureCcrFeature as X, handleExitPromptError as Y, ZCF_CONFIG_FILE as Z, handleGeneralError as _, commandExists as a, updateZcfConfig as a0, changeLanguage as a1, readZcfConfig as a2, configureOutputStyle as a3, isWindows as a4, selectMcpServices as a5, getMcpServices as a6, formatApiKeyDisplay as a7, modifyApiConfigPartially as a8, setupCcrConfiguration as a9, validateApiKey as aa, COMETIX_COMMAND_NAME as ab, COMETIX_COMMANDS as ac, installCometixLine as ad, checkAndUpdateTools as ae, readJsonConfig as af, writeJsonConfig as ag, displayBanner as ah, resolveAiOutputLanguage as ai, updatePromptOnly as aj, selectAndInstallWorkflows as ak, checkClaudeCodeVersionAndPrompt as al, version as am, displayBannerWithInfo as an, readZcfConfigAsync as ao, initI18n as ap, selectScriptLanguage as aq, prompts as ar, importRecommendedEnv as b, cleanupPermissions as c, importRecommendedPermissions as d, CLAUDE_MD_FILE as e, ClAUDE_CONFIG_FILE as f, getPlatform as g, SUPPORTED_LANGS as h, init as i, LANG_LABELS as j, getAiOutputLanguageLabel as k, getMcpConfigPath as l, mergeAndCleanPermissions as m, backupMcpConfig as n, openSettingsJson as o, mergeMcpServers as p, buildMcpServerConfig as q, readMcpConfig as r, fixWindowsMcpConfig as s, addCompletedOnboarding as t, ensureApiKeyApproved as u, removeApiKeyFromRejected as v, writeMcpConfig as w, manageApiKeyApproval as x, ensureClaudeDir as y, backupExistingConfig as z };
5111
+ export { writeAuthFile as $, AI_OUTPUT_LANGUAGES as A, manageApiKeyApproval as B, CLAUDE_DIR as C, DEFAULT_CODE_TOOL_TYPE as D, ensureClaudeDir as E, backupExistingConfig as F, copyConfigFiles as G, configureApi as H, mergeConfigs as I, updateCustomModel as J, updateDefaultModel as K, LEGACY_ZCF_CONFIG_FILES as L, mergeSettingsFile as M, getExistingModelConfig as N, getExistingApiConfig as O, applyAiLanguageDirective as P, isClaudeCodeInstalled as Q, installClaudeCode as R, SETTINGS_FILE as S, isLocalClaudeCodeInstalled as T, getInstallationStatus as U, removeLocalClaudeCode as V, i18n as W, readCodexConfig as X, backupCodexComplete as Y, ZCF_CONFIG_DIR as Z, writeCodexConfig as _, commandExists as a, ensureI18nInitialized as a0, detectConfigManagementMode as a1, addNumbersToChoices as a2, readCcrConfig as a3, isCcrInstalled as a4, installCcr as a5, configureCcrFeature as a6, handleExitPromptError as a7, handleGeneralError as a8, updateZcfConfig as a9, configureCodexApi as aA, runCodexWorkflowImport as aB, runCodexFullInit as aC, listCodexProviders as aD, getCurrentCodexProvider as aE, switchCodexProvider as aF, switchToOfficialLogin as aG, switchToProvider as aH, readZcfConfigAsync as aI, initI18n as aJ, selectScriptLanguage as aK, fsOperations as aL, prompts as aM, codex as aN, changeLanguage as aa, readZcfConfig as ab, configureOutputStyle as ac, isWindows as ad, selectMcpServices as ae, getMcpServices as af, formatApiKeyDisplay as ag, modifyApiConfigPartially as ah, setupCcrConfiguration as ai, validateApiKey as aj, COMETIX_COMMAND_NAME as ak, COMETIX_COMMANDS as al, installCometixLine as am, checkAndUpdateTools as an, readJsonConfig as ao, writeJsonConfig as ap, displayBanner as aq, runCodexUpdate as ar, version as as, resolveAiOutputLanguage as at, updatePromptOnly as au, selectAndInstallWorkflows as av, checkClaudeCodeVersionAndPrompt as aw, displayBannerWithInfo as ax, runCodexUninstall as ay, configureCodexMcp as az, importRecommendedEnv as b, cleanupPermissions as c, importRecommendedPermissions as d, CLAUDE_MD_FILE as e, ClAUDE_CONFIG_FILE as f, getPlatform as g, ZCF_CONFIG_FILE as h, init as i, CODE_TOOL_TYPES as j, isCodeToolType as k, SUPPORTED_LANGS as l, mergeAndCleanPermissions as m, LANG_LABELS as n, openSettingsJson as o, getAiOutputLanguageLabel as p, getMcpConfigPath as q, readMcpConfig as r, backupMcpConfig as s, mergeMcpServers as t, buildMcpServerConfig as u, fixWindowsMcpConfig as v, writeMcpConfig as w, addCompletedOnboarding as x, ensureApiKeyApproved as y, removeApiKeyFromRejected as z };