ccg-workflow 2.0.0 → 2.1.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.
package/dist/cli.mjs CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import cac from 'cac';
3
3
  import ansis from 'ansis';
4
- import { z as diagnoseMcpConfig, A as isWindows, B as readClaudeCodeConfig, C as fixWindowsMcpConfig, D as writeClaudeCodeConfig, r as readCcgConfig, b as initI18n, a as i18n, s as showMainMenu, i as init, E as configMcp, F as version } from './shared/ccg-workflow.iK6lgCG3.mjs';
4
+ import { z as diagnoseMcpConfig, A as isWindows, B as readClaudeCodeConfig, C as fixWindowsMcpConfig, D as writeClaudeCodeConfig, r as readCcgConfig, b as initI18n, a as i18n, s as showMainMenu, i as init, E as configMcp, F as version } from './shared/ccg-workflow.pMx0aHNz.mjs';
5
5
  import 'inquirer';
6
+ import 'ora';
6
7
  import 'node:child_process';
7
8
  import 'node:util';
8
9
  import 'node:os';
@@ -11,7 +12,6 @@ import 'pathe';
11
12
  import 'fs-extra';
12
13
  import 'smol-toml';
13
14
  import 'i18next';
14
- import 'ora';
15
15
 
16
16
  async function diagnoseMcp() {
17
17
  console.log();
package/dist/index.d.mts CHANGED
@@ -32,6 +32,7 @@ interface ModelRouting {
32
32
  strategy: 'parallel';
33
33
  };
34
34
  mode: CollaborationMode;
35
+ geminiModel?: string;
35
36
  }
36
37
  interface CcgConfig {
37
38
  general: {
package/dist/index.d.ts CHANGED
@@ -32,6 +32,7 @@ interface ModelRouting {
32
32
  strategy: 'parallel';
33
33
  };
34
34
  mode: CollaborationMode;
35
+ geminiModel?: string;
35
36
  }
36
37
  interface CcgConfig {
37
38
  general: {
package/dist/index.mjs CHANGED
@@ -1,6 +1,7 @@
1
- export { c as changeLanguage, x as checkForUpdates, y as compareVersions, d as createDefaultConfig, e as createDefaultRouting, g as getCcgDir, f as getConfigPath, t as getCurrentVersion, v as getLatestVersion, j as getWorkflowById, h as getWorkflowConfigs, a as i18n, i as init, b as initI18n, l as installAceTool, m as installAceToolRs, k as installWorkflows, p as migrateToV1_4_0, q as needsMigration, r as readCcgConfig, s as showMainMenu, o as uninstallAceTool, n as uninstallWorkflows, u as update, w as writeCcgConfig } from './shared/ccg-workflow.iK6lgCG3.mjs';
1
+ export { c as changeLanguage, x as checkForUpdates, y as compareVersions, d as createDefaultConfig, e as createDefaultRouting, g as getCcgDir, f as getConfigPath, t as getCurrentVersion, v as getLatestVersion, j as getWorkflowById, h as getWorkflowConfigs, a as i18n, i as init, b as initI18n, l as installAceTool, m as installAceToolRs, k as installWorkflows, p as migrateToV1_4_0, q as needsMigration, r as readCcgConfig, s as showMainMenu, o as uninstallAceTool, n as uninstallWorkflows, u as update, w as writeCcgConfig } from './shared/ccg-workflow.pMx0aHNz.mjs';
2
2
  import 'ansis';
3
3
  import 'inquirer';
4
+ import 'ora';
4
5
  import 'node:child_process';
5
6
  import 'node:util';
6
7
  import 'node:os';
@@ -9,4 +10,3 @@ import 'pathe';
9
10
  import 'fs-extra';
10
11
  import 'smol-toml';
11
12
  import 'i18next';
12
- import 'ora';
@@ -1,5 +1,6 @@
1
1
  import ansis from 'ansis';
2
2
  import inquirer from 'inquirer';
3
+ import ora from 'ora';
3
4
  import { exec, spawn } from 'node:child_process';
4
5
  import { promisify } from 'node:util';
5
6
  import { homedir } from 'node:os';
@@ -8,9 +9,8 @@ import { dirname, join, relative, sep, basename } from 'pathe';
8
9
  import fs from 'fs-extra';
9
10
  import { parse, stringify } from 'smol-toml';
10
11
  import i18next from 'i18next';
11
- import ora from 'ora';
12
12
 
13
- const version = "2.0.0";
13
+ const version = "2.1.1";
14
14
 
15
15
  function cmd(id, order, category, name, nameEn, description, descriptionEn, cmdOverride) {
16
16
  return {
@@ -133,6 +133,10 @@ function injectConfigVariables(content, config) {
133
133
  processed = processed.replace(/\{\{REVIEW_MODELS\}\}/g, JSON.stringify(reviewModels));
134
134
  const routingMode = routing.mode || "smart";
135
135
  processed = processed.replace(/\{\{ROUTING_MODE\}\}/g, routingMode);
136
+ const geminiModel = routing.geminiModel || "gemini-3.1-pro-preview";
137
+ const usesGemini = frontendPrimary === "gemini" || backendPrimary === "gemini";
138
+ const geminiModelFlag = usesGemini ? `--gemini-model ${geminiModel} ` : "";
139
+ processed = processed.replace(/\{\{GEMINI_MODEL_FLAG\}\}/g, geminiModelFlag);
136
140
  const liteModeFlag = config.liteMode ? "--lite " : "";
137
141
  processed = processed.replace(/\{\{LITE_MODE_FLAG\}\}/g, liteModeFlag);
138
142
  const mcpProvider = config.mcpProvider || "ace-tool";
@@ -275,8 +279,15 @@ function collectInvocableSkills(skillsDir) {
275
279
  function generateCommandContent(skill, skillsInstallDir) {
276
280
  const skillMdPath = join(skillsInstallDir, skill.relPath, "SKILL.md");
277
281
  const runSkillPath = join(skillsInstallDir, "run_skill.js");
282
+ const frontmatter = [
283
+ "---",
284
+ `description: '${skill.description.replace(/'/g, "''")}'`,
285
+ "---"
286
+ ].join("\n");
278
287
  if (skill.runtimeType === "scripted") {
279
288
  return [
289
+ frontmatter,
290
+ "",
280
291
  `# ${skill.name}`,
281
292
  "",
282
293
  skill.description,
@@ -293,6 +304,8 @@ function generateCommandContent(skill, skillsInstallDir) {
293
304
  ].join("\n");
294
305
  }
295
306
  return [
307
+ frontmatter,
308
+ "",
296
309
  `# ${skill.name}`,
297
310
  "",
298
311
  skill.description,
@@ -1842,6 +1855,20 @@ const zhCN = {
1842
1855
  prompt: "\u542F\u7528 Web UI \u5B9E\u65F6\u8F93\u51FA\uFF1F",
1843
1856
  disableHint: "\u7981\u7528\u53EF\u52A0\u901F\u54CD\u5E94"
1844
1857
  },
1858
+ model: {
1859
+ title: "\u6A21\u578B\u8DEF\u7531\u914D\u7F6E",
1860
+ selectFrontend: "\u9009\u62E9\u524D\u7AEF\u6A21\u578B",
1861
+ selectBackend: "\u9009\u62E9\u540E\u7AEF\u6A21\u578B",
1862
+ selectGeminiModel: "Gemini \u6A21\u578B\u578B\u53F7",
1863
+ recommended: "\u63A8\u8350",
1864
+ custom: "\u81EA\u5B9A\u4E49...",
1865
+ enterCustomModel: "\u8F93\u5165\u81EA\u5B9A\u4E49 Gemini \u6A21\u578B\u540D\u79F0",
1866
+ currentRouting: "\u5F53\u524D\u6A21\u578B\u8DEF\u7531",
1867
+ routingUpdated: "\u6A21\u578B\u8DEF\u7531\u5DF2\u66F4\u65B0",
1868
+ reinstalling: "\u6B63\u5728\u91CD\u88C5\u6A21\u677F\u4EE5\u5E94\u7528\u65B0\u914D\u7F6E...",
1869
+ reinstallDone: "\u6A21\u677F\u5DF2\u66F4\u65B0",
1870
+ reinstallFailed: "\u6A21\u677F\u66F4\u65B0\u5931\u8D25"
1871
+ },
1845
1872
  perf: {
1846
1873
  title: "\u6027\u80FD\u6A21\u5F0F",
1847
1874
  selectMode: "\u9009\u62E9\u6027\u80FD\u6A21\u5F0F",
@@ -1974,6 +2001,7 @@ const zhCN = {
1974
2001
  configMcp: "\u914D\u7F6E MCP",
1975
2002
  configApi: "\u914D\u7F6E API",
1976
2003
  configStyle: "\u914D\u7F6E\u8F93\u51FA\u98CE\u683C",
2004
+ configModel: "\u914D\u7F6E\u6A21\u578B\u8DEF\u7531",
1977
2005
  tools: "\u5B9E\u7528\u5DE5\u5177",
1978
2006
  installClaude: "\u5B89\u88C5 Claude Code",
1979
2007
  uninstall: "\u5378\u8F7D CCG",
@@ -2300,6 +2328,20 @@ const en = {
2300
2328
  prompt: "Enable Web UI real-time output?",
2301
2329
  disableHint: "Disabling can speed up response"
2302
2330
  },
2331
+ model: {
2332
+ title: "Model Routing",
2333
+ selectFrontend: "Select frontend model",
2334
+ selectBackend: "Select backend model",
2335
+ selectGeminiModel: "Gemini model name",
2336
+ recommended: "Recommended",
2337
+ custom: "Custom...",
2338
+ enterCustomModel: "Enter custom Gemini model name",
2339
+ currentRouting: "Current model routing",
2340
+ routingUpdated: "Model routing updated",
2341
+ reinstalling: "Reinstalling templates with new config...",
2342
+ reinstallDone: "Templates updated",
2343
+ reinstallFailed: "Template update failed"
2344
+ },
2303
2345
  perf: {
2304
2346
  title: "Performance Mode",
2305
2347
  selectMode: "Select performance mode",
@@ -2432,6 +2474,7 @@ const en = {
2432
2474
  configMcp: "Configure MCP",
2433
2475
  configApi: "Configure API",
2434
2476
  configStyle: "Configure output style",
2477
+ configModel: "Configure model routing",
2435
2478
  tools: "Tools",
2436
2479
  installClaude: "Install Claude Code",
2437
2480
  uninstall: "Uninstall CCG",
@@ -2880,10 +2923,19 @@ async function init(options = {}) {
2880
2923
  language = options.lang;
2881
2924
  await initI18n(language);
2882
2925
  }
2883
- const frontendModels = ["gemini"];
2884
- const backendModels = ["codex"];
2926
+ let frontendModels = ["gemini"];
2927
+ let backendModels = ["codex"];
2928
+ let geminiModel = "gemini-3.1-pro-preview";
2885
2929
  const mode = "smart";
2886
2930
  const selectedWorkflows = getAllCommandIds();
2931
+ if (options.skipPrompt) {
2932
+ const existingConfig = await readCcgConfig();
2933
+ if (existingConfig?.routing) {
2934
+ frontendModels = existingConfig.routing.frontend?.models || ["gemini"];
2935
+ backendModels = existingConfig.routing.backend?.models || ["codex"];
2936
+ geminiModel = existingConfig.routing.geminiModel || "gemini-3.1-pro-preview";
2937
+ }
2938
+ }
2887
2939
  let liteMode = false;
2888
2940
  let mcpProvider = "ace-tool";
2889
2941
  let aceToolBaseUrl = "";
@@ -2901,7 +2953,7 @@ async function init(options = {}) {
2901
2953
  let apiKey = "";
2902
2954
  if (!options.skipPrompt) {
2903
2955
  console.log();
2904
- console.log(ansis.cyan.bold(` \u{1F511} Step 1/3 \u2014 ${i18n.t("init:api.title")}`));
2956
+ console.log(ansis.cyan.bold(` \u{1F511} Step 1/4 \u2014 ${i18n.t("init:api.title")}`));
2905
2957
  console.log();
2906
2958
  const { apiProvider } = await inquirer.prompt([{
2907
2959
  type: "list",
@@ -2933,11 +2985,63 @@ async function init(options = {}) {
2933
2985
  apiKey = apiAnswers.key?.trim() || "";
2934
2986
  }
2935
2987
  }
2988
+ if (!options.skipPrompt) {
2989
+ const existingConfig = await readCcgConfig();
2990
+ console.log();
2991
+ console.log(ansis.cyan.bold(` \u{1F9E0} Step 2/4 \u2014 ${i18n.t("init:model.title")}`));
2992
+ console.log();
2993
+ const { selectedFrontend } = await inquirer.prompt([{
2994
+ type: "list",
2995
+ name: "selectedFrontend",
2996
+ message: i18n.t("init:model.selectFrontend"),
2997
+ choices: [
2998
+ { name: `Gemini ${ansis.green(`(${i18n.t("init:model.recommended")})`)}`, value: "gemini" },
2999
+ { name: "Codex", value: "codex" }
3000
+ ],
3001
+ default: existingConfig?.routing?.frontend?.primary || "gemini"
3002
+ }]);
3003
+ const { selectedBackend } = await inquirer.prompt([{
3004
+ type: "list",
3005
+ name: "selectedBackend",
3006
+ message: i18n.t("init:model.selectBackend"),
3007
+ choices: [
3008
+ { name: "Gemini", value: "gemini" },
3009
+ { name: `Codex ${ansis.green(`(${i18n.t("init:model.recommended")})`)}`, value: "codex" }
3010
+ ],
3011
+ default: existingConfig?.routing?.backend?.primary || "codex"
3012
+ }]);
3013
+ frontendModels = [selectedFrontend];
3014
+ backendModels = [selectedBackend];
3015
+ if (selectedFrontend === "gemini" || selectedBackend === "gemini") {
3016
+ const { selectedGeminiModel } = await inquirer.prompt([{
3017
+ type: "list",
3018
+ name: "selectedGeminiModel",
3019
+ message: i18n.t("init:model.selectGeminiModel"),
3020
+ choices: [
3021
+ { name: `gemini-3.1-pro-preview ${ansis.green(`(${i18n.t("init:model.recommended")})`)}`, value: "gemini-3.1-pro-preview" },
3022
+ { name: "gemini-2.5-flash", value: "gemini-2.5-flash" },
3023
+ { name: `${i18n.t("init:model.custom")}`, value: "custom" }
3024
+ ],
3025
+ default: existingConfig?.routing?.geminiModel || "gemini-3.1-pro-preview"
3026
+ }]);
3027
+ if (selectedGeminiModel === "custom") {
3028
+ const { customModel } = await inquirer.prompt([{
3029
+ type: "input",
3030
+ name: "customModel",
3031
+ message: i18n.t("init:model.enterCustomModel"),
3032
+ validate: (v) => v.trim() !== "" || i18n.t("init:model.enterCustomModel")
3033
+ }]);
3034
+ geminiModel = customModel.trim();
3035
+ } else {
3036
+ geminiModel = selectedGeminiModel;
3037
+ }
3038
+ }
3039
+ }
2936
3040
  if (options.skipMcp) {
2937
3041
  mcpProvider = "skip";
2938
3042
  } else if (!options.skipPrompt) {
2939
3043
  console.log();
2940
- console.log(ansis.cyan.bold(` \u{1F527} Step 2/3 \u2014 ${i18n.t("init:mcp.title")}`));
3044
+ console.log(ansis.cyan.bold(` \u{1F527} Step 3/4 \u2014 ${i18n.t("init:mcp.title")}`));
2941
3045
  console.log();
2942
3046
  const { selectedTools } = await inquirer.prompt([{
2943
3047
  type: "checkbox",
@@ -3073,7 +3177,7 @@ async function init(options = {}) {
3073
3177
  const existingConfig = await readCcgConfig();
3074
3178
  const currentLiteMode = existingConfig?.performance?.liteMode || false;
3075
3179
  console.log();
3076
- console.log(ansis.cyan.bold(` \u26A1 Step 3/3 \u2014 ${i18n.t("init:perf.title")}`));
3180
+ console.log(ansis.cyan.bold(` \u26A1 Step 4/4 \u2014 ${i18n.t("init:perf.title")}`));
3077
3181
  console.log();
3078
3182
  const { perfMode } = await inquirer.prompt([{
3079
3183
  type: "list",
@@ -3095,25 +3199,28 @@ async function init(options = {}) {
3095
3199
  const routing = {
3096
3200
  frontend: {
3097
3201
  models: frontendModels,
3098
- primary: "gemini",
3202
+ primary: frontendModels[0],
3099
3203
  strategy: "fallback"
3100
3204
  },
3101
3205
  backend: {
3102
3206
  models: backendModels,
3103
- primary: "codex",
3207
+ primary: backendModels[0],
3104
3208
  strategy: "fallback"
3105
3209
  },
3106
3210
  review: {
3107
- models: ["codex", "gemini"],
3211
+ models: [.../* @__PURE__ */ new Set([...frontendModels, ...backendModels])],
3108
3212
  strategy: "parallel"
3109
3213
  },
3110
- mode
3214
+ mode,
3215
+ geminiModel
3111
3216
  };
3112
3217
  console.log();
3113
3218
  console.log(ansis.yellow("\u2501".repeat(50)));
3114
3219
  console.log(ansis.bold(` ${i18n.t("init:summary.title")}`));
3115
3220
  console.log();
3116
- console.log(` ${ansis.cyan(i18n.t("init:summary.modelRouting"))} ${ansis.green("Gemini")} (Frontend) + ${ansis.blue("Codex")} (Backend)`);
3221
+ const fmName = frontendModels[0].charAt(0).toUpperCase() + frontendModels[0].slice(1);
3222
+ const bmName = backendModels[0].charAt(0).toUpperCase() + backendModels[0].slice(1);
3223
+ console.log(` ${ansis.cyan(i18n.t("init:summary.modelRouting"))} ${ansis.green(fmName)} (Frontend) + ${ansis.blue(bmName)} (Backend)`);
3117
3224
  console.log(` ${ansis.cyan(i18n.t("init:summary.commandCount"))} ${ansis.yellow(selectedWorkflows.length.toString())}`);
3118
3225
  const mcpSummary = (() => {
3119
3226
  if (mcpProvider === "fast-context") return ansis.green("fast-context");
@@ -3886,6 +3993,7 @@ async function showMainMenu() {
3886
3993
  item("3", i18n.t("menu:options.configMcp"), isZh ? "\u4EE3\u7801\u68C0\u7D22 MCP \u5DE5\u5177" : "Code retrieval MCP tool"),
3887
3994
  item("4", i18n.t("menu:options.configApi"), isZh ? "\u81EA\u5B9A\u4E49 API \u7AEF\u70B9" : "Custom API endpoint"),
3888
3995
  item("5", i18n.t("menu:options.configStyle"), isZh ? "\u9009\u62E9\u8F93\u51FA\u4EBA\u683C" : "Choose output personality"),
3996
+ item("6", i18n.t("menu:options.configModel"), isZh ? "\u524D\u7AEF/\u540E\u7AEF\u6A21\u578B\u5207\u6362" : "Switch frontend/backend models"),
3889
3997
  groupSep(isZh ? "\u5176\u4ED6\u5DE5\u5177" : "Tools"),
3890
3998
  item("T", i18n.t("menu:options.tools"), "ccusage, CCometixLine"),
3891
3999
  item("C", i18n.t("menu:options.installClaude"), isZh ? "\u5B89\u88C5/\u91CD\u88C5 CLI" : "Install/reinstall CLI"),
@@ -3912,6 +4020,9 @@ async function showMainMenu() {
3912
4020
  case "5":
3913
4021
  await configOutputStyle();
3914
4022
  break;
4023
+ case "6":
4024
+ await configModelRouting();
4025
+ break;
3915
4026
  case "T":
3916
4027
  await handleTools();
3917
4028
  break;
@@ -4088,6 +4199,105 @@ const OUTPUT_STYLES = [
4088
4199
  { id: "abyss-command", nameKey: "menu:style.abyssCommand", descKey: "menu:style.abyssCommandDesc" },
4089
4200
  { id: "abyss-ritual", nameKey: "menu:style.abyssRitual", descKey: "menu:style.abyssRitualDesc" }
4090
4201
  ];
4202
+ async function configModelRouting() {
4203
+ const config = await readCcgConfig();
4204
+ (config?.general?.language || "zh-CN") === "zh-CN";
4205
+ console.log();
4206
+ console.log(ansis.cyan.bold(` ${i18n.t("init:model.title")}`));
4207
+ console.log();
4208
+ const currentFrontend = config?.routing?.frontend?.primary || "gemini";
4209
+ const currentBackend = config?.routing?.backend?.primary || "codex";
4210
+ const currentGeminiModel = config?.routing?.geminiModel || "gemini-3.1-pro-preview";
4211
+ console.log(ansis.gray(` ${i18n.t("init:model.currentRouting")}:`));
4212
+ console.log(` ${ansis.cyan("Frontend:")} ${ansis.green(currentFrontend)}`);
4213
+ console.log(` ${ansis.cyan("Backend:")} ${ansis.blue(currentBackend)}`);
4214
+ if (currentFrontend === "gemini" || currentBackend === "gemini") {
4215
+ console.log(` ${ansis.cyan("Gemini:")} ${ansis.gray(currentGeminiModel)}`);
4216
+ }
4217
+ console.log();
4218
+ const { selectedFrontend } = await inquirer.prompt([{
4219
+ type: "list",
4220
+ name: "selectedFrontend",
4221
+ message: i18n.t("init:model.selectFrontend"),
4222
+ choices: [
4223
+ { name: `Gemini ${ansis.green(`(${i18n.t("init:model.recommended")})`)}`, value: "gemini" },
4224
+ { name: "Codex", value: "codex" }
4225
+ ],
4226
+ default: currentFrontend
4227
+ }]);
4228
+ const { selectedBackend } = await inquirer.prompt([{
4229
+ type: "list",
4230
+ name: "selectedBackend",
4231
+ message: i18n.t("init:model.selectBackend"),
4232
+ choices: [
4233
+ { name: "Gemini", value: "gemini" },
4234
+ { name: `Codex ${ansis.green(`(${i18n.t("init:model.recommended")})`)}`, value: "codex" }
4235
+ ],
4236
+ default: currentBackend
4237
+ }]);
4238
+ let geminiModel = currentGeminiModel;
4239
+ if (selectedFrontend === "gemini" || selectedBackend === "gemini") {
4240
+ const { selectedGeminiModel } = await inquirer.prompt([{
4241
+ type: "list",
4242
+ name: "selectedGeminiModel",
4243
+ message: i18n.t("init:model.selectGeminiModel"),
4244
+ choices: [
4245
+ { name: `gemini-3.1-pro-preview ${ansis.green(`(${i18n.t("init:model.recommended")})`)}`, value: "gemini-3.1-pro-preview" },
4246
+ { name: "gemini-2.5-flash", value: "gemini-2.5-flash" },
4247
+ { name: `${i18n.t("init:model.custom")}`, value: "custom" }
4248
+ ],
4249
+ default: currentGeminiModel
4250
+ }]);
4251
+ if (selectedGeminiModel === "custom") {
4252
+ const { customModel } = await inquirer.prompt([{
4253
+ type: "input",
4254
+ name: "customModel",
4255
+ message: i18n.t("init:model.enterCustomModel"),
4256
+ validate: (v) => v.trim() !== "" || i18n.t("init:model.enterCustomModel")
4257
+ }]);
4258
+ geminiModel = customModel.trim();
4259
+ } else {
4260
+ geminiModel = selectedGeminiModel;
4261
+ }
4262
+ }
4263
+ if (selectedFrontend === currentFrontend && selectedBackend === currentBackend && geminiModel === currentGeminiModel) {
4264
+ console.log(ansis.gray(` ${i18n.t("common:configNotModified")}`));
4265
+ return;
4266
+ }
4267
+ if (config) {
4268
+ config.routing.frontend = {
4269
+ models: [selectedFrontend],
4270
+ primary: selectedFrontend,
4271
+ strategy: "fallback"
4272
+ };
4273
+ config.routing.backend = {
4274
+ models: [selectedBackend],
4275
+ primary: selectedBackend,
4276
+ strategy: "fallback"
4277
+ };
4278
+ config.routing.review = {
4279
+ models: [.../* @__PURE__ */ new Set([selectedFrontend, selectedBackend])],
4280
+ strategy: "parallel"
4281
+ };
4282
+ config.routing.geminiModel = geminiModel;
4283
+ await writeCcgConfig(config);
4284
+ }
4285
+ console.log();
4286
+ console.log(ansis.green(` \u2713 ${i18n.t("init:model.routingUpdated")}`));
4287
+ const spinner = ora(i18n.t("init:model.reinstalling")).start();
4288
+ try {
4289
+ const { execSync } = await import('node:child_process');
4290
+ execSync("npx --yes ccg-workflow init --force --skip-prompt --skip-mcp", {
4291
+ timeout: 3e5,
4292
+ stdio: "pipe",
4293
+ env: { ...process.env, CCG_UPDATE_MODE: "true" }
4294
+ });
4295
+ spinner.succeed(i18n.t("init:model.reinstallDone"));
4296
+ } catch {
4297
+ spinner.fail(i18n.t("init:model.reinstallFailed"));
4298
+ }
4299
+ console.log(ansis.gray(` ${i18n.t("common:restartToApply")}`));
4300
+ }
4091
4301
  async function configOutputStyle() {
4092
4302
  console.log();
4093
4303
  console.log(ansis.cyan.bold(` ${i18n.t("menu:style.title")}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccg-workflow",
3
- "version": "2.0.0",
3
+ "version": "2.1.1",
4
4
  "description": "Claude + Codex + Gemini multi-model collaboration system - smart routing development workflow",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.17.1",
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: '多模型技术分析(并行执行):Codex 后端视角 + Gemini 前端视角,交叉验证后综合见解'
2
+ description: '多模型技术分析(并行执行):{{BACKEND_PRIMARY}} 后端视角 + {{FRONTEND_PRIMARY}} 前端视角,交叉验证后综合见解'
3
3
  ---
4
4
 
5
5
  # Analyze - 多模型技术分析
@@ -16,8 +16,8 @@ description: '多模型技术分析(并行执行):Codex 后端视角 + Gem
16
16
 
17
17
  你是**分析协调者**,编排多模型分析流程:
18
18
  - **ace-tool** – 代码上下文检索
19
- - **Codex** – 后端/系统视角(**后端权威**)
20
- - **Gemini** – 前端/用户视角(**前端权威**)
19
+ - **{{BACKEND_PRIMARY}}** – 后端/系统视角(**后端权威**)
20
+ - **{{FRONTEND_PRIMARY}}** – 前端/用户视角(**前端权威**)
21
21
  - **Claude (自己)** – 综合见解
22
22
 
23
23
  ---
@@ -33,7 +33,7 @@ description: '多模型技术分析(并行执行):Codex 后端视角 + Gem
33
33
 
34
34
  ```
35
35
  Bash({
36
- command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend <codex|gemini> {{GEMINI_MODEL_FLAG}}- \"{{WORKDIR}}\" <<'EOF'
36
+ command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend <{{BACKEND_PRIMARY}}|{{FRONTEND_PRIMARY}}> {{GEMINI_MODEL_FLAG}}- \"{{WORKDIR}}\" <<'EOF'
37
37
  ROLE_FILE: <角色提示词路径>
38
38
  <TASK>
39
39
  需求:<增强后的需求(如未增强则用 $ARGUMENTS)>
@@ -47,9 +47,6 @@ EOF",
47
47
  })
48
48
  ```
49
49
 
50
- **模型参数说明**:
51
- - `{{GEMINI_MODEL_FLAG}}`:当使用 `--backend gemini` 时,替换为 `--gemini-model gemini-3.1-pro-preview `(注意末尾空格);使用 codex 时替换为空字符串
52
-
53
50
  **角色提示词**:
54
51
 
55
52
  | 模型 | 提示词 |
@@ -96,11 +93,11 @@ TaskOutput({ task_id: "<task_id>", block: true, timeout: 600000 })
96
93
 
97
94
  **⚠️ 必须发起两个并行 Bash 调用**(参照上方调用规范):
98
95
 
99
- 1. **Codex 后端分析**:`Bash({ command: "...--backend codex...", run_in_background: true })`
96
+ 1. **{{BACKEND_PRIMARY}} 后端分析**:`Bash({ command: "...--backend {{BACKEND_PRIMARY}}...", run_in_background: true })`
100
97
  - ROLE_FILE: `~/.claude/.ccg/prompts/codex/analyzer.md`
101
98
  - OUTPUT:技术可行性、架构影响、性能考量
102
99
 
103
- 2. **Gemini 前端分析**:`Bash({ command: "...--backend gemini...", run_in_background: true })`
100
+ 2. **{{FRONTEND_PRIMARY}} 前端分析**:`Bash({ command: "...--backend {{FRONTEND_PRIMARY}}...", run_in_background: true })`
104
101
  - ROLE_FILE: `~/.claude/.ccg/prompts/gemini/analyzer.md`
105
102
  - OUTPUT:UI/UX 影响、用户体验、视觉设计考量
106
103
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: '后端专项工作流(研究→构思→计划→执行→优化→评审),Codex 主导'
2
+ description: '后端专项工作流(研究→构思→计划→执行→优化→评审),{{BACKEND_PRIMARY}} 主导'
3
3
  ---
4
4
 
5
5
  # Backend - 后端专项开发
@@ -13,7 +13,7 @@ description: '后端专项工作流(研究→构思→计划→执行→优化
13
13
  ## 上下文
14
14
 
15
15
  - 后端任务:$ARGUMENTS
16
- - Codex 主导,Gemini 辅助参考
16
+ - {{BACKEND_PRIMARY}} 主导,{{FRONTEND_PRIMARY}} 辅助参考
17
17
  - 适用:API 设计、算法实现、数据库优化、业务逻辑
18
18
 
19
19
  ## 你的角色
@@ -21,8 +21,8 @@ description: '后端专项工作流(研究→构思→计划→执行→优化
21
21
  你是**后端编排者**,协调多模型完成服务端任务(研究 → 构思 → 计划 → 执行 → 优化 → 评审),用中文协助用户。
22
22
 
23
23
  **协作模型**:
24
- - **Codex** – 后端逻辑、算法(**后端权威,可信赖**)
25
- - **Gemini** – 前端视角(**后端意见仅供参考**)
24
+ - **{{BACKEND_PRIMARY}}** – 后端逻辑、算法(**后端权威,可信赖**)
25
+ - **{{FRONTEND_PRIMARY}}** – 前端视角(**后端意见仅供参考**)
26
26
  - **Claude (自己)** – 编排、计划、执行、交付
27
27
 
28
28
  ---
@@ -39,7 +39,7 @@ description: '后端专项工作流(研究→构思→计划→执行→优化
39
39
  ```
40
40
  # 新会话调用
41
41
  Bash({
42
- command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend codex - \"{{WORKDIR}}\" <<'EOF'
42
+ command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend {{BACKEND_PRIMARY}} {{GEMINI_MODEL_FLAG}}- \"{{WORKDIR}}\" <<'EOF'
43
43
  ROLE_FILE: <角色提示词路径>
44
44
  <TASK>
45
45
  需求:<增强后的需求(如未增强则用 $ARGUMENTS)>
@@ -54,7 +54,7 @@ EOF",
54
54
 
55
55
  # 复用会话调用
56
56
  Bash({
57
- command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend codex resume <SESSION_ID> - \"{{WORKDIR}}\" <<'EOF'
57
+ command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend {{BACKEND_PRIMARY}} {{GEMINI_MODEL_FLAG}}resume <SESSION_ID> - \"{{WORKDIR}}\" <<'EOF'
58
58
  ROLE_FILE: <角色提示词路径>
59
59
  <TASK>
60
60
  需求:<增强后的需求(如未增强则用 $ARGUMENTS)>
@@ -105,7 +105,7 @@ EOF",
105
105
 
106
106
  ### 💡 阶段 2:构思
107
107
 
108
- `[模式:构思]` - Codex 主导分析
108
+ `[模式:构思]` - {{BACKEND_PRIMARY}} 主导分析
109
109
 
110
110
  **⚠️ 必须调用 Codex**(参照上方调用规范):
111
111
  - ROLE_FILE: `~/.claude/.ccg/prompts/codex/analyzer.md`
@@ -119,7 +119,7 @@ EOF",
119
119
 
120
120
  ### 📋 阶段 3:计划
121
121
 
122
- `[模式:计划]` - Codex 主导规划
122
+ `[模式:计划]` - {{BACKEND_PRIMARY}} 主导规划
123
123
 
124
124
  **⚠️ 必须调用 Codex**(使用 `resume <CODEX_SESSION>` 复用会话):
125
125
  - ROLE_FILE: `~/.claude/.ccg/prompts/codex/architect.md`
@@ -139,7 +139,7 @@ Claude 综合规划,请求用户批准后存入 `.claude/plan/任务名.md`
139
139
 
140
140
  ### 🚀 阶段 5:优化
141
141
 
142
- `[模式:优化]` - Codex 主导审查
142
+ `[模式:优化]` - {{BACKEND_PRIMARY}} 主导审查
143
143
 
144
144
  **⚠️ 必须调用 Codex**(参照上方调用规范):
145
145
  - ROLE_FILE: `~/.claude/.ccg/prompts/codex/reviewer.md`
@@ -161,7 +161,7 @@ Claude 综合规划,请求用户批准后存入 `.claude/plan/任务名.md`
161
161
 
162
162
  ## 关键规则
163
163
 
164
- 1. **Codex 后端意见可信赖**
165
- 2. **Gemini 后端意见仅供参考**
164
+ 1. **{{BACKEND_PRIMARY}} 后端意见可信赖**
165
+ 2. **{{FRONTEND_PRIMARY}} 后端意见仅供参考**
166
166
  3. 外部模型对文件系统**零写入权限**
167
167
  4. Claude 负责所有代码写入和文件操作
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: 'Codex 全权执行计划 - 读取 /ccg:plan 产出的计划文件,Codex 承担 MCP 搜索 + 代码实现 + 测试,多模型审核'
2
+ description: '{{BACKEND_PRIMARY}} 全权执行计划 - 读取 /ccg:plan 产出的计划文件,{{BACKEND_PRIMARY}} 承担 MCP 搜索 + 代码实现 + 测试,多模型审核'
3
3
  ---
4
4
 
5
5
  # Codex-Exec - Codex 全权执行计划
@@ -24,8 +24,8 @@ $ARGUMENTS
24
24
 
25
25
  | 维度 | `/ccg:execute` | `/ccg:codex-exec` |
26
26
  |------|---------------|-------------------|
27
- | 代码实现 | Claude 重构 Codex/Gemini 的 Diff | **Codex 直接实现** |
28
- | MCP 搜索 | Claude 调用 MCP | **Codex 调用 MCP** |
27
+ | 代码实现 | Claude 重构 {{BACKEND_PRIMARY}}/{{FRONTEND_PRIMARY}} 的 Diff | **{{BACKEND_PRIMARY}} 直接实现** |
28
+ | MCP 搜索 | Claude 调用 MCP | **{{BACKEND_PRIMARY}} 调用 MCP** |
29
29
  | Claude 上下文 | 高(搜索结果 + 代码全进来) | **极低(只看摘要 + diff)** |
30
30
  | Claude token | 大量消耗 | **极少消耗** |
31
31
  | 审核 | 多模型审查 | **多模型审查(不变)** |
@@ -46,11 +46,11 @@ $ARGUMENTS
46
46
  - 如果用户通过 `/add-dir` 添加了多个工作区,先用 Glob/Grep 确定任务相关的工作区
47
47
  - 如果无法确定,用 `AskUserQuestion` 询问用户选择目标工作区
48
48
 
49
- **Codex 执行调用语法**:
49
+ **{{BACKEND_PRIMARY}} 执行调用语法**:
50
50
 
51
51
  ```
52
52
  Bash({
53
- command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend codex - \"{{WORKDIR}}\" <<'EXEC_EOF'
53
+ command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend {{BACKEND_PRIMARY}} {{GEMINI_MODEL_FLAG}}- \"{{WORKDIR}}\" <<'EXEC_EOF'
54
54
  <TASK>
55
55
  <指令内容>
56
56
  </TASK>
@@ -61,11 +61,11 @@ EXEC_EOF",
61
61
  })
62
62
  ```
63
63
 
64
- **Codex 复用会话调用**:
64
+ **{{BACKEND_PRIMARY}} 复用会话调用**:
65
65
 
66
66
  ```
67
67
  Bash({
68
- command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend codex resume <SESSION_ID> - \"{{WORKDIR}}\" <<'EXEC_EOF'
68
+ command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend {{BACKEND_PRIMARY}} {{GEMINI_MODEL_FLAG}}resume <SESSION_ID> - \"{{WORKDIR}}\" <<'EXEC_EOF'
69
69
  <TASK>
70
70
  <指令内容>
71
71
  </TASK>
@@ -76,14 +76,11 @@ EXEC_EOF",
76
76
  })
77
77
  ```
78
78
 
79
- **模型参数说明**:
80
- - `{{GEMINI_MODEL_FLAG}}`:当使用 `--backend gemini` 时,替换为 `--gemini-model gemini-3.1-pro-preview `(注意末尾空格);使用 codex 时替换为空字符串
81
-
82
79
  **审核调用语法**(Codex ∥ Gemini 并行审查):
83
80
 
84
81
  ```
85
82
  Bash({
86
- command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend <codex|gemini> {{GEMINI_MODEL_FLAG}}- \"{{WORKDIR}}\" <<'REVIEW_EOF'
83
+ command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend <{{BACKEND_PRIMARY}}|{{FRONTEND_PRIMARY}}> {{GEMINI_MODEL_FLAG}}- \"{{WORKDIR}}\" <<'REVIEW_EOF'
87
84
  ROLE_FILE: <角色提示词路径>
88
85
  <TASK>
89
86
  Scope: Audit the code changes made by Codex.
@@ -170,7 +167,7 @@ TaskOutput({ task_id: "<task_id>", block: true, timeout: 600000 })
170
167
 
171
168
  ```
172
169
  Bash({
173
- command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend codex resume <CODEX_SESSION> - \"{{WORKDIR}}\" <<'EXEC_EOF'
170
+ command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend {{BACKEND_PRIMARY}} {{GEMINI_MODEL_FLAG}}resume <CODEX_SESSION> - \"{{WORKDIR}}\" <<'EXEC_EOF'
174
171
  <TASK>
175
172
  You are a full-stack execution agent. Implement the following plan end-to-end.
176
173
 
@@ -270,7 +267,7 @@ EXEC_EOF",
270
267
 
271
268
  ```
272
269
  Bash({
273
- command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend codex resume <CODEX_EXEC_SESSION> - \"{{WORKDIR}}\" <<'FIXEOF'
270
+ command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend {{BACKEND_PRIMARY}} {{GEMINI_MODEL_FLAG}}resume <CODEX_EXEC_SESSION> - \"{{WORKDIR}}\" <<'FIXEOF'
274
271
  <TASK>
275
272
  The implementation needs corrections:
276
273
 
@@ -309,12 +306,12 @@ FIXEOF",
309
306
 
310
307
  2. **并行调用**(`run_in_background: true`):
311
308
 
312
- - **Codex 审查**:
309
+ - **{{BACKEND_PRIMARY}} 审查**:
313
310
  - ROLE_FILE: `~/.claude/.ccg/prompts/codex/reviewer.md`
314
311
  - 输入:变更 Diff + 计划文件内容
315
312
  - 关注:安全性、性能、错误处理、逻辑正确性
316
313
 
317
- - **Gemini 审查**:
314
+ - **{{FRONTEND_PRIMARY}} 审查**:
318
315
  - ROLE_FILE: `~/.claude/.ccg/prompts/gemini/reviewer.md`
319
316
  - 输入:变更 Diff + 计划文件内容
320
317
  - 关注:代码可读性、设计一致性、可维护性
@@ -373,7 +370,7 @@ FIXEOF",
373
370
  ## 关键规则
374
371
 
375
372
  1. **Claude 极简原则** — Claude 不调用 MCP、不做代码检索。只读计划、指挥 Codex、审核结果。
376
- 2. **Codex 全权执行** — MCP 搜索、文档查询、代码检索、实现、测试全由 Codex 完成。
373
+ 2. **{{BACKEND_PRIMARY}} 全权执行** — MCP 搜索、文档查询、代码检索、实现、测试全由 {{BACKEND_PRIMARY}} 完成。
377
374
  3. **多模型审核不变** — 审核阶段仍然 Codex ∥ Gemini 交叉审查,保证质量。
378
375
  4. **信任规则** — 后端以 Codex 为准,前端以 Gemini 为准。
379
376
  5. **一次性下发** — 尽量一次给 Codex 完整指令 + 完整计划,减少来回通信。