ccg-workflow 2.1.15 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -270
- package/README.zh-CN.md +119 -269
- package/dist/cli.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/shared/{ccg-workflow.C2MaYeHU.mjs → ccg-workflow.81OoN8XX.mjs} +629 -297
- package/package.json +6 -30
- package/templates/commands/go.md +199 -0
- package/templates/commands-legacy/team.md +475 -0
- package/templates/engine/model-router.md +117 -0
- package/templates/engine/phase-guide.md +95 -0
- package/templates/engine/strategies/debug-investigate.md +156 -0
- package/templates/engine/strategies/deep-research.md +141 -0
- package/templates/engine/strategies/direct-fix.md +108 -0
- package/templates/engine/strategies/full-collaborate.md +291 -0
- package/templates/engine/strategies/git-action.md +43 -0
- package/templates/engine/strategies/guided-develop.md +208 -0
- package/templates/engine/strategies/optimize-measure.md +103 -0
- package/templates/engine/strategies/quick-implement.md +96 -0
- package/templates/engine/strategies/refactor-safely.md +157 -0
- package/templates/engine/strategies/review-audit.md +116 -0
- package/templates/hooks/session-start.js +100 -0
- package/templates/hooks/skill-router.js +144 -0
- package/templates/hooks/subagent-context.js +118 -0
- package/templates/hooks/task-utils.js +113 -0
- package/templates/hooks/workflow-state.js +39 -0
- package/templates/spec/backend/index.md +31 -0
- package/templates/spec/frontend/index.md +31 -0
- package/templates/spec/guides/index.md +30 -0
- /package/templates/{commands → commands-legacy}/analyze.md +0 -0
- /package/templates/{commands → commands-legacy}/backend.md +0 -0
- /package/templates/{commands → commands-legacy}/codex-exec.md +0 -0
- /package/templates/{commands → commands-legacy}/debug.md +0 -0
- /package/templates/{commands → commands-legacy}/enhance.md +0 -0
- /package/templates/{commands → commands-legacy}/execute.md +0 -0
- /package/templates/{commands → commands-legacy}/feat.md +0 -0
- /package/templates/{commands → commands-legacy}/frontend.md +0 -0
- /package/templates/{commands → commands-legacy}/optimize.md +0 -0
- /package/templates/{commands → commands-legacy}/plan.md +0 -0
- /package/templates/{commands → commands-legacy}/review.md +0 -0
- /package/templates/{commands → commands-legacy}/team-exec.md +0 -0
- /package/templates/{commands → commands-legacy}/team-plan.md +0 -0
- /package/templates/{commands → commands-legacy}/team-research.md +0 -0
- /package/templates/{commands → commands-legacy}/team-review.md +0 -0
- /package/templates/{commands → commands-legacy}/test.md +0 -0
- /package/templates/{commands → commands-legacy}/workflow.md +0 -0
|
@@ -10,7 +10,7 @@ import fs from 'fs-extra';
|
|
|
10
10
|
import { parse, stringify } from 'smol-toml';
|
|
11
11
|
import i18next from 'i18next';
|
|
12
12
|
|
|
13
|
-
const version = "
|
|
13
|
+
const version = "3.0.0";
|
|
14
14
|
|
|
15
15
|
function cmd(id, order, category, name, nameEn, description, descriptionEn, cmdOverride) {
|
|
16
16
|
return {
|
|
@@ -25,8 +25,25 @@ function cmd(id, order, category, name, nameEn, description, descriptionEn, cmdO
|
|
|
25
25
|
descriptionEn
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
const
|
|
29
|
-
// ──
|
|
28
|
+
const CORE_CONFIGS = [
|
|
29
|
+
// ── Smart Entry ──────────────────────────────────────
|
|
30
|
+
cmd("go", 0, "development", "CCG \u667A\u80FD\u5165\u53E3", "CCG Smart Entry", "\u63CF\u8FF0\u4F60\u8981\u505A\u4EC0\u4E48\uFF0CAI \u81EA\u52A8\u9009\u62E9\u6700\u4F73\u7B56\u7565\u6267\u884C", "Describe what you want, AI picks the best strategy"),
|
|
31
|
+
// ── Independent Tools ────────────────────────────────
|
|
32
|
+
cmd("init-project", 10, "init", "\u9879\u76EE\u521D\u59CB\u5316", "Project Init", "\u521D\u59CB\u5316\u9879\u76EE AI \u4E0A\u4E0B\u6587\uFF0C\u751F\u6210 CLAUDE.md", "Initialize project AI context, generate CLAUDE.md", "init"),
|
|
33
|
+
cmd("context", 11, "development", "\u9879\u76EE\u4E0A\u4E0B\u6587\u7BA1\u7406", "Project Context Manager", "\u521D\u59CB\u5316 .context \u76EE\u5F55\u3001\u8BB0\u5F55\u51B3\u7B56\u65E5\u5FD7\u3001\u538B\u7F29\u5F52\u6863\u3001\u67E5\u770B\u5386\u53F2", "Init .context dir, log decisions, compress, view history"),
|
|
34
|
+
// ── Git ──────────────────────────────────────────────
|
|
35
|
+
cmd("commit", 20, "git", "Git \u63D0\u4EA4", "Git Commit", "\u667A\u80FD\u751F\u6210 conventional commit \u4FE1\u606F", "Smart conventional commit message generation"),
|
|
36
|
+
cmd("rollback", 21, "git", "Git \u56DE\u6EDA", "Git Rollback", "\u4EA4\u4E92\u5F0F\u56DE\u6EDA\u5206\u652F\u5230\u5386\u53F2\u7248\u672C", "Interactive rollback to historical version"),
|
|
37
|
+
cmd("clean-branches", 22, "git", "Git \u6E05\u7406\u5206\u652F", "Git Clean Branches", "\u5B89\u5168\u6E05\u7406\u5DF2\u5408\u5E76\u6216\u8FC7\u671F\u5206\u652F", "Safely clean merged or stale branches"),
|
|
38
|
+
cmd("worktree", 23, "git", "Git Worktree", "Git Worktree", "\u7BA1\u7406 Git worktree", "Manage Git worktree"),
|
|
39
|
+
// ── Spec (OpenSpec / OPSX) ───────────────────────────
|
|
40
|
+
cmd("spec-init", 30, "spec", "OpenSpec \u521D\u59CB\u5316", "OpenSpec Init", "\u521D\u59CB\u5316 OpenSpec \u73AF\u5883 + \u9A8C\u8BC1\u591A\u6A21\u578B MCP \u5DE5\u5177", "Initialize OpenSpec environment with multi-model MCP validation"),
|
|
41
|
+
cmd("spec-research", 31, "spec", "\u9700\u6C42\u7814\u7A76", "Spec Research", "\u9700\u6C42 \u2192 \u7EA6\u675F\u96C6\uFF08\u5E76\u884C\u63A2\u7D22 + OpenSpec \u63D0\u6848\uFF09", "Transform requirements into constraint sets via parallel exploration"),
|
|
42
|
+
cmd("spec-plan", 32, "spec", "\u96F6\u51B3\u7B56\u89C4\u5212", "Spec Plan", "\u591A\u6A21\u578B\u5206\u6790 \u2192 \u6D88\u9664\u6B67\u4E49 \u2192 \u96F6\u51B3\u7B56\u53EF\u6267\u884C\u8BA1\u5212", "Refine proposals into zero-decision executable plans"),
|
|
43
|
+
cmd("spec-impl", 33, "spec", "\u89C4\u8303\u9A71\u52A8\u5B9E\u73B0", "Spec Implementation", "\u6309\u89C4\u8303\u6267\u884C + \u591A\u6A21\u578B\u534F\u4F5C + \u5F52\u6863", "Execute changes via multi-model collaboration with spec compliance"),
|
|
44
|
+
cmd("spec-review", 34, "spec", "\u5F52\u6863\u524D\u5BA1\u67E5", "Spec Review", "\u53CC\u6A21\u578B\u4EA4\u53C9\u5BA1\u67E5 \u2192 Critical \u5FC5\u987B\u4FEE\u590D \u2192 \u5141\u8BB8\u5F52\u6863", "Multi-model compliance review before archiving")
|
|
45
|
+
];
|
|
46
|
+
const LEGACY_CONFIGS = [
|
|
30
47
|
cmd("workflow", 1, "development", "\u5B8C\u6574\u5F00\u53D1\u5DE5\u4F5C\u6D41", "Full Development Workflow", "\u5B8C\u65746\u9636\u6BB5\u5F00\u53D1\u5DE5\u4F5C\u6D41\uFF08\u7814\u7A76\u2192\u6784\u601D\u2192\u8BA1\u5212\u2192\u6267\u884C\u2192\u4F18\u5316\u2192\u8BC4\u5BA1\uFF09", "Full 6-phase development workflow"),
|
|
31
48
|
cmd("plan", 1.5, "development", "\u591A\u6A21\u578B\u534F\u4F5C\u89C4\u5212", "Multi-Model Planning", "\u4E0A\u4E0B\u6587\u68C0\u7D22 + \u53CC\u6A21\u578B\u5206\u6790 \u2192 \u751F\u6210 Step-by-step \u5B9E\u65BD\u8BA1\u5212", "Context retrieval + dual-model analysis \u2192 Step-by-step plan"),
|
|
32
49
|
cmd("execute", 1.6, "development", "\u591A\u6A21\u578B\u534F\u4F5C\u6267\u884C", "Multi-Model Execution", "\u6839\u636E\u8BA1\u5212\u83B7\u53D6\u539F\u578B \u2192 Claude \u91CD\u6784\u5B9E\u65BD \u2192 \u591A\u6A21\u578B\u5BA1\u8BA1\u4EA4\u4ED8", "Get prototype from plan \u2192 Claude refactor \u2192 Multi-model audit"),
|
|
@@ -37,7 +54,6 @@ const WORKFLOW_CONFIGS = [
|
|
|
37
54
|
cmd("team-review", 1.95, "development", "Agent Teams \u5BA1\u67E5", "Agent Teams Review", "\u53CC\u6A21\u578B\u4EA4\u53C9\u5BA1\u67E5\u5E76\u884C\u5B9E\u65BD\u4EA7\u51FA\uFF0C\u5206\u7EA7\u5904\u7406 Critical/Warning/Info", "Dual-model cross-review with severity classification"),
|
|
38
55
|
cmd("frontend", 2, "development", "\u524D\u7AEF\u4E13\u9879", "Frontend Tasks", "\u524D\u7AEF\u4E13\u9879\u4EFB\u52A1\uFF08Gemini\u4E3B\u5BFC\uFF0C\u66F4\u5FEB\u66F4\u7CBE\u51C6\uFF09", "Frontend tasks (Gemini-led, faster)"),
|
|
39
56
|
cmd("codex-exec", 2.5, "development", "Codex \u6267\u884C\u8BA1\u5212", "Codex Plan Executor", "\u8BFB\u53D6 /ccg:plan \u8BA1\u5212\u6587\u4EF6\uFF0CCodex \u5168\u6743\u6267\u884C + \u591A\u6A21\u578B\u5BA1\u6838", "Read plan file from /ccg:plan, Codex executes + multi-model review"),
|
|
40
|
-
cmd("context", 2.6, "development", "\u9879\u76EE\u4E0A\u4E0B\u6587\u7BA1\u7406", "Project Context Manager", "\u521D\u59CB\u5316 .context \u76EE\u5F55\u3001\u8BB0\u5F55\u51B3\u7B56\u65E5\u5FD7\u3001\u538B\u7F29\u5F52\u6863\u3001\u67E5\u770B\u5386\u53F2", "Init .context dir, log decisions, compress, view history"),
|
|
41
57
|
cmd("backend", 3, "development", "\u540E\u7AEF\u4E13\u9879", "Backend Tasks", "\u540E\u7AEF\u4E13\u9879\u4EFB\u52A1\uFF08Codex\u4E3B\u5BFC\uFF0C\u66F4\u5FEB\u66F4\u7CBE\u51C6\uFF09", "Backend tasks (Codex-led, faster)"),
|
|
42
58
|
cmd("feat", 4, "development", "\u667A\u80FD\u529F\u80FD\u5F00\u53D1", "Smart Feature Development", "\u667A\u80FD\u529F\u80FD\u5F00\u53D1 - \u81EA\u52A8\u89C4\u5212\u3001\u8BBE\u8BA1\u3001\u5B9E\u65BD", "Smart feature development - auto plan, design, implement"),
|
|
43
59
|
cmd("analyze", 5, "development", "\u6280\u672F\u5206\u6790", "Technical Analysis", "\u53CC\u6A21\u578B\u6280\u672F\u5206\u6790\uFF0C\u4EC5\u5206\u6790\u4E0D\u4FEE\u6539\u4EE3\u7801", "Dual-model technical analysis, analysis only"),
|
|
@@ -45,27 +61,21 @@ const WORKFLOW_CONFIGS = [
|
|
|
45
61
|
cmd("optimize", 7, "development", "\u6027\u80FD\u4F18\u5316", "Performance Optimization", "\u591A\u6A21\u578B\u6027\u80FD\u4F18\u5316", "Multi-model performance optimization"),
|
|
46
62
|
cmd("test", 8, "development", "\u6D4B\u8BD5\u751F\u6210", "Test Generation", "\u667A\u80FD\u8DEF\u7531\u6D4B\u8BD5\u751F\u6210", "Smart routing test generation"),
|
|
47
63
|
cmd("review", 9, "development", "\u4EE3\u7801\u5BA1\u67E5", "Code Review", "\u53CC\u6A21\u578B\u4EE3\u7801\u5BA1\u67E5\uFF0C\u65E0\u53C2\u6570\u65F6\u81EA\u52A8\u5BA1\u67E5 git diff", "Dual-model code review, auto-review git diff when no args"),
|
|
48
|
-
cmd("enhance", 9.5, "development", "Prompt \u589E\u5F3A", "Prompt Enhancement", "ace-tool Prompt \u589E\u5F3A\u5DE5\u5177", "ace-tool prompt enhancement")
|
|
49
|
-
// ── Init ─────────────────────────────────────────────
|
|
50
|
-
cmd("init-project", 10, "init", "\u9879\u76EE\u521D\u59CB\u5316", "Project Init", "\u521D\u59CB\u5316\u9879\u76EE AI \u4E0A\u4E0B\u6587\uFF0C\u751F\u6210 CLAUDE.md", "Initialize project AI context, generate CLAUDE.md", "init"),
|
|
51
|
-
// ── Git ──────────────────────────────────────────────
|
|
52
|
-
cmd("commit", 20, "git", "Git \u63D0\u4EA4", "Git Commit", "\u667A\u80FD\u751F\u6210 conventional commit \u4FE1\u606F", "Smart conventional commit message generation"),
|
|
53
|
-
cmd("rollback", 21, "git", "Git \u56DE\u6EDA", "Git Rollback", "\u4EA4\u4E92\u5F0F\u56DE\u6EDA\u5206\u652F\u5230\u5386\u53F2\u7248\u672C", "Interactive rollback to historical version"),
|
|
54
|
-
cmd("clean-branches", 22, "git", "Git \u6E05\u7406\u5206\u652F", "Git Clean Branches", "\u5B89\u5168\u6E05\u7406\u5DF2\u5408\u5E76\u6216\u8FC7\u671F\u5206\u652F", "Safely clean merged or stale branches"),
|
|
55
|
-
cmd("worktree", 23, "git", "Git Worktree", "Git Worktree", "\u7BA1\u7406 Git worktree", "Manage Git worktree"),
|
|
56
|
-
// ── Spec (OpenSpec / OPSX) ───────────────────────────
|
|
57
|
-
cmd("spec-init", 30, "spec", "OpenSpec \u521D\u59CB\u5316", "OpenSpec Init", "\u521D\u59CB\u5316 OpenSpec \u73AF\u5883 + \u9A8C\u8BC1\u591A\u6A21\u578B MCP \u5DE5\u5177", "Initialize OpenSpec environment with multi-model MCP validation"),
|
|
58
|
-
cmd("spec-research", 31, "spec", "\u9700\u6C42\u7814\u7A76", "Spec Research", "\u9700\u6C42 \u2192 \u7EA6\u675F\u96C6\uFF08\u5E76\u884C\u63A2\u7D22 + OpenSpec \u63D0\u6848\uFF09", "Transform requirements into constraint sets via parallel exploration"),
|
|
59
|
-
cmd("spec-plan", 32, "spec", "\u96F6\u51B3\u7B56\u89C4\u5212", "Spec Plan", "\u591A\u6A21\u578B\u5206\u6790 \u2192 \u6D88\u9664\u6B67\u4E49 \u2192 \u96F6\u51B3\u7B56\u53EF\u6267\u884C\u8BA1\u5212", "Refine proposals into zero-decision executable plans"),
|
|
60
|
-
cmd("spec-impl", 33, "spec", "\u89C4\u8303\u9A71\u52A8\u5B9E\u73B0", "Spec Implementation", "\u6309\u89C4\u8303\u6267\u884C + \u591A\u6A21\u578B\u534F\u4F5C + \u5F52\u6863", "Execute changes via multi-model collaboration with spec compliance"),
|
|
61
|
-
cmd("spec-review", 34, "spec", "\u5F52\u6863\u524D\u5BA1\u67E5", "Spec Review", "\u53CC\u6A21\u578B\u4EA4\u53C9\u5BA1\u67E5 \u2192 Critical \u5FC5\u987B\u4FEE\u590D \u2192 \u5141\u8BB8\u5F52\u6863", "Multi-model compliance review before archiving")
|
|
64
|
+
cmd("enhance", 9.5, "development", "Prompt \u589E\u5F3A", "Prompt Enhancement", "ace-tool Prompt \u589E\u5F3A\u5DE5\u5177", "ace-tool prompt enhancement")
|
|
62
65
|
];
|
|
66
|
+
const WORKFLOW_CONFIGS = [...CORE_CONFIGS, ...LEGACY_CONFIGS];
|
|
63
67
|
function getWorkflowConfigs() {
|
|
64
68
|
return WORKFLOW_CONFIGS.sort((a, b) => a.order - b.order);
|
|
65
69
|
}
|
|
66
70
|
function getWorkflowById(id) {
|
|
67
71
|
return WORKFLOW_CONFIGS.find((w) => w.id === id);
|
|
68
72
|
}
|
|
73
|
+
function getCoreCommandIds() {
|
|
74
|
+
return CORE_CONFIGS.map((w) => w.id);
|
|
75
|
+
}
|
|
76
|
+
function getLegacyCommandIds() {
|
|
77
|
+
return LEGACY_CONFIGS.map((w) => w.id);
|
|
78
|
+
}
|
|
69
79
|
function getAllCommandIds() {
|
|
70
80
|
return WORKFLOW_CONFIGS.map((w) => w.id);
|
|
71
81
|
}
|
|
@@ -886,6 +896,7 @@ async function copyMdTemplates(ctx, srcDir, destDir, options = {}) {
|
|
|
886
896
|
}
|
|
887
897
|
async function installCommandFiles(ctx, workflowIds) {
|
|
888
898
|
const commandsDir = join(ctx.installDir, "commands", "ccg");
|
|
899
|
+
const legacyIds = new Set(getLegacyCommandIds());
|
|
889
900
|
for (const workflowId of workflowIds) {
|
|
890
901
|
const workflow = getWorkflowById(workflowId);
|
|
891
902
|
if (!workflow) {
|
|
@@ -893,7 +904,8 @@ async function installCommandFiles(ctx, workflowIds) {
|
|
|
893
904
|
continue;
|
|
894
905
|
}
|
|
895
906
|
for (const cmd of workflow.commands) {
|
|
896
|
-
const
|
|
907
|
+
const srcSubdir = legacyIds.has(workflowId) ? "commands-legacy" : "commands";
|
|
908
|
+
const srcFile = join(ctx.templateDir, srcSubdir, `${cmd}.md`);
|
|
897
909
|
const destFile = join(commandsDir, `${cmd}.md`);
|
|
898
910
|
try {
|
|
899
911
|
if (await fs.pathExists(srcFile)) {
|
|
@@ -1198,6 +1210,88 @@ async function installBinaryFile(ctx) {
|
|
|
1198
1210
|
ctx.result.errors.push(`Failed to install codeagent-wrapper (non-blocking): ${error}`);
|
|
1199
1211
|
}
|
|
1200
1212
|
}
|
|
1213
|
+
async function installEngineFiles(ctx) {
|
|
1214
|
+
const engineSrcDir = join(ctx.templateDir, "engine");
|
|
1215
|
+
if (!await fs.pathExists(engineSrcDir)) return;
|
|
1216
|
+
const engineDestDir = join(ctx.installDir, ".ccg", "engine");
|
|
1217
|
+
try {
|
|
1218
|
+
await copyMdTemplates(ctx, engineSrcDir, engineDestDir, { inject: true });
|
|
1219
|
+
const strategiesSrc = join(engineSrcDir, "strategies");
|
|
1220
|
+
const strategiesDest = join(engineDestDir, "strategies");
|
|
1221
|
+
if (await fs.pathExists(strategiesSrc)) {
|
|
1222
|
+
await copyMdTemplates(ctx, strategiesSrc, strategiesDest, { inject: true });
|
|
1223
|
+
}
|
|
1224
|
+
} catch (error) {
|
|
1225
|
+
ctx.result.errors.push(`Failed to install engine files: ${error}`);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
const HOOK_FILES = ["task-utils.js", "workflow-state.js", "session-start.js", "subagent-context.js", "skill-router.js"];
|
|
1229
|
+
async function installHookScripts(ctx) {
|
|
1230
|
+
const hooksSrcDir = join(ctx.templateDir, "hooks");
|
|
1231
|
+
if (!await fs.pathExists(hooksSrcDir)) return;
|
|
1232
|
+
const hooksDestDir = join(ctx.installDir, "hooks", "ccg");
|
|
1233
|
+
await fs.ensureDir(hooksDestDir);
|
|
1234
|
+
try {
|
|
1235
|
+
for (const file of HOOK_FILES) {
|
|
1236
|
+
const src = join(hooksSrcDir, file);
|
|
1237
|
+
const dest = join(hooksDestDir, file);
|
|
1238
|
+
if (await fs.pathExists(src)) {
|
|
1239
|
+
await fs.copy(src, dest, { overwrite: true });
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
} catch (error) {
|
|
1243
|
+
ctx.result.errors.push(`Failed to install hook scripts: ${error}`);
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
async function registerHooksInSettings(ctx) {
|
|
1247
|
+
const settingsPath = join(ctx.installDir, "settings.json");
|
|
1248
|
+
const hooksDir = join(ctx.installDir, "hooks", "ccg");
|
|
1249
|
+
try {
|
|
1250
|
+
let settings = {};
|
|
1251
|
+
if (await fs.pathExists(settingsPath)) {
|
|
1252
|
+
try {
|
|
1253
|
+
settings = JSON.parse(await fs.readFile(settingsPath, "utf-8"));
|
|
1254
|
+
} catch {
|
|
1255
|
+
settings = {};
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
const hooks = settings.hooks || {};
|
|
1259
|
+
const ccgHookDefs = {
|
|
1260
|
+
UserPromptSubmit: {
|
|
1261
|
+
hooks: [
|
|
1262
|
+
{ type: "command", command: `node ${join(hooksDir, "workflow-state.js")}`, timeout: 1e4 },
|
|
1263
|
+
{ type: "command", command: `node ${join(hooksDir, "skill-router.js")}`, timeout: 5e3 }
|
|
1264
|
+
]
|
|
1265
|
+
},
|
|
1266
|
+
SessionStart: {
|
|
1267
|
+
matcher: "startup|clear|compact",
|
|
1268
|
+
hooks: [{ type: "command", command: `node ${join(hooksDir, "session-start.js")}`, timeout: 15e3 }]
|
|
1269
|
+
},
|
|
1270
|
+
PreToolUse: {
|
|
1271
|
+
matcher: "Bash|Agent",
|
|
1272
|
+
hooks: [{ type: "command", command: `node ${join(hooksDir, "subagent-context.js")}`, timeout: 15e3 }]
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
1275
|
+
for (const [event, def] of Object.entries(ccgHookDefs)) {
|
|
1276
|
+
const eventHooks = hooks[event] || [];
|
|
1277
|
+
const ccgCommand = def.hooks[0].command;
|
|
1278
|
+
const existingIdx = eventHooks.findIndex((h) => {
|
|
1279
|
+
const hHooks = h.hooks || [];
|
|
1280
|
+
return hHooks.some((hh) => typeof hh.command === "string" && hh.command.includes("hooks/ccg/"));
|
|
1281
|
+
});
|
|
1282
|
+
if (existingIdx >= 0) {
|
|
1283
|
+
eventHooks[existingIdx] = def;
|
|
1284
|
+
} else {
|
|
1285
|
+
eventHooks.push(def);
|
|
1286
|
+
}
|
|
1287
|
+
hooks[event] = eventHooks;
|
|
1288
|
+
}
|
|
1289
|
+
settings.hooks = hooks;
|
|
1290
|
+
await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
1291
|
+
} catch (error) {
|
|
1292
|
+
ctx.result.errors.push(`Failed to register hooks in settings.json: ${error}`);
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1201
1295
|
async function installWorkflows(workflowIds, installDir, force = false, config) {
|
|
1202
1296
|
const ctx = {
|
|
1203
1297
|
installDir,
|
|
@@ -1210,7 +1304,7 @@ async function installWorkflows(workflowIds, installDir, force = false, config)
|
|
|
1210
1304
|
review: { models: ["codex", "gemini"] }
|
|
1211
1305
|
},
|
|
1212
1306
|
liteMode: config?.liteMode || false,
|
|
1213
|
-
mcpProvider: config?.mcpProvider || "
|
|
1307
|
+
mcpProvider: config?.mcpProvider || "fast-context",
|
|
1214
1308
|
skipImpeccable: config?.skipImpeccable || false
|
|
1215
1309
|
},
|
|
1216
1310
|
templateDir: join(PACKAGE_ROOT$1, "templates"),
|
|
@@ -1231,7 +1325,11 @@ async function installWorkflows(workflowIds, installDir, force = false, config)
|
|
|
1231
1325
|
await fs.ensureDir(join(installDir, "commands", "ccg"));
|
|
1232
1326
|
await fs.ensureDir(join(installDir, ".ccg"));
|
|
1233
1327
|
await fs.ensureDir(join(installDir, ".ccg", "prompts"));
|
|
1328
|
+
await fs.ensureDir(join(installDir, ".ccg", "engine", "strategies"));
|
|
1234
1329
|
await installCommandFiles(ctx, workflowIds);
|
|
1330
|
+
await installEngineFiles(ctx);
|
|
1331
|
+
await installHookScripts(ctx);
|
|
1332
|
+
await registerHooksInSettings(ctx);
|
|
1235
1333
|
await installAgentFiles(ctx);
|
|
1236
1334
|
await installPromptFiles(ctx);
|
|
1237
1335
|
await installSkillFiles(ctx);
|
|
@@ -1327,6 +1425,8 @@ const installer = {
|
|
|
1327
1425
|
collectInvocableSkills: collectInvocableSkills,
|
|
1328
1426
|
collectSkills: collectSkills,
|
|
1329
1427
|
getAllCommandIds: getAllCommandIds,
|
|
1428
|
+
getCoreCommandIds: getCoreCommandIds,
|
|
1429
|
+
getLegacyCommandIds: getLegacyCommandIds,
|
|
1330
1430
|
getWorkflowById: getWorkflowById,
|
|
1331
1431
|
getWorkflowConfigs: getWorkflowConfigs,
|
|
1332
1432
|
injectConfigVariables: injectConfigVariables,
|
|
@@ -1795,15 +1895,31 @@ const zhCN = {
|
|
|
1795
1895
|
collaboration: "\u534F\u4F5C\u6A21\u5F0F:",
|
|
1796
1896
|
workflows: "\u5DE5\u4F5C\u6D41:",
|
|
1797
1897
|
selected: "\u4E2A\u5DF2\u9009\u62E9",
|
|
1898
|
+
apiProvider: "API \u63D0\u4F9B\u65B9",
|
|
1798
1899
|
modelRouting: "\u6A21\u578B\u8DEF\u7531",
|
|
1900
|
+
geminiModel: "Gemini \u578B\u53F7",
|
|
1799
1901
|
commandCount: "\u547D\u4EE4\u6570\u91CF",
|
|
1800
1902
|
mcpTool: "MCP \u5DE5\u5177",
|
|
1801
1903
|
webUI: "Web UI",
|
|
1904
|
+
apiSelfManaged: "\u81EA\u884C\u7BA1\u7406\uFF08CCG \u4E0D\u4ECB\u5165\uFF09",
|
|
1802
1905
|
pendingConfig: "\u5F85\u914D\u7F6E",
|
|
1803
1906
|
skipped: "\u8DF3\u8FC7",
|
|
1804
1907
|
enabled: "\u542F\u7528",
|
|
1805
1908
|
disabled: "\u7981\u7528"
|
|
1806
1909
|
},
|
|
1910
|
+
nav: {
|
|
1911
|
+
back: "\u8FD4\u56DE\u4E0A\u4E00\u6B65",
|
|
1912
|
+
cancel: "\u53D6\u6D88\u5B89\u88C5"
|
|
1913
|
+
},
|
|
1914
|
+
summaryMenu: {
|
|
1915
|
+
prompt: "\u786E\u8BA4\u914D\u7F6E\uFF1F",
|
|
1916
|
+
confirm: "\u786E\u8BA4\u5B89\u88C5",
|
|
1917
|
+
editApi: "\u6539 API \u914D\u7F6E",
|
|
1918
|
+
editModel: "\u6539\u6A21\u578B\u8DEF\u7531",
|
|
1919
|
+
editMcp: "\u6539 MCP \u5DE5\u5177",
|
|
1920
|
+
editPerf: "\u6539\u6027\u80FD\u6A21\u5F0F",
|
|
1921
|
+
cancel: "\u53D6\u6D88\u5B89\u88C5"
|
|
1922
|
+
},
|
|
1807
1923
|
mcp: {
|
|
1808
1924
|
title: "MCP \u4EE3\u7801\u68C0\u7D22\u5DE5\u5177\u914D\u7F6E",
|
|
1809
1925
|
selectProvider: "\u9009\u62E9\u4EE3\u7801\u68C0\u7D22 MCP \u5DE5\u5177",
|
|
@@ -1851,7 +1967,9 @@ const zhCN = {
|
|
|
1851
1967
|
cwConfiguring: "\u6B63\u5728\u914D\u7F6E ContextWeaver MCP...",
|
|
1852
1968
|
cwFailed: "ContextWeaver MCP \u914D\u7F6E\u5931\u8D25",
|
|
1853
1969
|
cwConfigFile: "\u914D\u7F6E\u6587\u4EF6",
|
|
1854
|
-
cwIndexHint: "\u9996\u6B21\u4F7F\u7528\u9700\u8981\u7D22\u5F15\u4EE3\u7801\u5E93\uFF1A"
|
|
1970
|
+
cwIndexHint: "\u9996\u6B21\u4F7F\u7528\u9700\u8981\u7D22\u5F15\u4EE3\u7801\u5E93\uFF1A",
|
|
1971
|
+
gatePrompt: "\u914D\u7F6E MCP \u5DE5\u5177\uFF1F",
|
|
1972
|
+
gateContinue: "\u5F00\u59CB\u914D\u7F6E"
|
|
1855
1973
|
},
|
|
1856
1974
|
api: {
|
|
1857
1975
|
title: "Claude Code API \u914D\u7F6E",
|
|
@@ -1861,6 +1979,8 @@ const zhCN = {
|
|
|
1861
1979
|
thirdPartyOption: "\u7B2C\u4E09\u65B9 API \u4EE3\u7406\uFF08\u81EA\u5B9A\u4E49 URL + Key\uFF09",
|
|
1862
1980
|
sponsor302AI: "302.AI\uFF08\u6309\u7528\u91CF\u4ED8\u8D39\u7684\u4F01\u4E1A\u7EA7 AI \u8D44\u6E90\u5E73\u53F0\uFF09",
|
|
1863
1981
|
sponsor302AIGetKey: "\u83B7\u53D6 API Key",
|
|
1982
|
+
skipOption: "\u8DF3\u8FC7 \u2014 \u6211\u5DF2\u901A\u8FC7 cc-switch / \u5176\u4ED6\u5DE5\u5177\u81EA\u884C\u914D\u7F6E",
|
|
1983
|
+
skipNoticeTitle: "API \u914D\u7F6E\u5DF2\u8DF3\u8FC7\uFF0CCCG \u4E0D\u4F1A\u4FEE\u6539 settings.json \u4E2D\u7684 ANTHROPIC_*",
|
|
1864
1984
|
urlPrompt: "API URL",
|
|
1865
1985
|
urlRequired: "\u5FC5\u586B",
|
|
1866
1986
|
keyPrompt: "API Key",
|
|
@@ -2271,15 +2391,31 @@ const en = {
|
|
|
2271
2391
|
collaboration: "Collaboration:",
|
|
2272
2392
|
workflows: "Workflows:",
|
|
2273
2393
|
selected: "selected",
|
|
2394
|
+
apiProvider: "API Provider",
|
|
2274
2395
|
modelRouting: "Model Routing",
|
|
2396
|
+
geminiModel: "Gemini Model",
|
|
2275
2397
|
commandCount: "Commands",
|
|
2276
2398
|
mcpTool: "MCP Tool",
|
|
2277
2399
|
webUI: "Web UI",
|
|
2400
|
+
apiSelfManaged: "self-managed (CCG does not touch)",
|
|
2278
2401
|
pendingConfig: "pending",
|
|
2279
2402
|
skipped: "skipped",
|
|
2280
2403
|
enabled: "Enabled",
|
|
2281
2404
|
disabled: "Disabled"
|
|
2282
2405
|
},
|
|
2406
|
+
nav: {
|
|
2407
|
+
back: "Back to previous step",
|
|
2408
|
+
cancel: "Cancel installation"
|
|
2409
|
+
},
|
|
2410
|
+
summaryMenu: {
|
|
2411
|
+
prompt: "Confirm configuration?",
|
|
2412
|
+
confirm: "Confirm and install",
|
|
2413
|
+
editApi: "Edit API configuration",
|
|
2414
|
+
editModel: "Edit model routing",
|
|
2415
|
+
editMcp: "Edit MCP tools",
|
|
2416
|
+
editPerf: "Edit performance mode",
|
|
2417
|
+
cancel: "Cancel installation"
|
|
2418
|
+
},
|
|
2283
2419
|
mcp: {
|
|
2284
2420
|
title: "MCP Code Retrieval Tool",
|
|
2285
2421
|
selectProvider: "Select code retrieval MCP tool",
|
|
@@ -2327,7 +2463,9 @@ const en = {
|
|
|
2327
2463
|
cwConfiguring: "Configuring ContextWeaver MCP...",
|
|
2328
2464
|
cwFailed: "ContextWeaver MCP configuration failed",
|
|
2329
2465
|
cwConfigFile: "Config file",
|
|
2330
|
-
cwIndexHint: "First use requires indexing your codebase:"
|
|
2466
|
+
cwIndexHint: "First use requires indexing your codebase:",
|
|
2467
|
+
gatePrompt: "Configure MCP tools?",
|
|
2468
|
+
gateContinue: "Start configuration"
|
|
2331
2469
|
},
|
|
2332
2470
|
api: {
|
|
2333
2471
|
title: "Claude Code API Configuration",
|
|
@@ -2337,6 +2475,8 @@ const en = {
|
|
|
2337
2475
|
thirdPartyOption: "Third-party API proxy (custom URL + Key)",
|
|
2338
2476
|
sponsor302AI: "302.AI (Pay-as-you-go Enterprise AI Resource Hub)",
|
|
2339
2477
|
sponsor302AIGetKey: "Get API Key",
|
|
2478
|
+
skipOption: "Skip \u2014 I've already configured API via cc-switch / other tools",
|
|
2479
|
+
skipNoticeTitle: "API configuration skipped \u2014 CCG will not touch ANTHROPIC_* in settings.json",
|
|
2340
2480
|
urlPrompt: "API URL",
|
|
2341
2481
|
urlRequired: "Required",
|
|
2342
2482
|
keyPrompt: "API Key",
|
|
@@ -2707,7 +2847,7 @@ function createDefaultConfig(options) {
|
|
|
2707
2847
|
backup: join(CCG_DIR, "backup")
|
|
2708
2848
|
},
|
|
2709
2849
|
mcp: {
|
|
2710
|
-
provider: options.mcpProvider || "
|
|
2850
|
+
provider: options.mcpProvider || "fast-context",
|
|
2711
2851
|
setup_url: "https://augmentcode.com/"
|
|
2712
2852
|
},
|
|
2713
2853
|
performance: {
|
|
@@ -2903,6 +3043,22 @@ For example, when using the \`fastapi\` library to encapsulate an API endpoint,
|
|
|
2903
3043
|
await fs.ensureDir(rulesDir);
|
|
2904
3044
|
await fs.writeFile(rulePath, prompt, "utf-8");
|
|
2905
3045
|
}
|
|
3046
|
+
const BACK_SENTINEL = "__ccg_back__";
|
|
3047
|
+
const CANCEL_SENTINEL = "__ccg_cancel__";
|
|
3048
|
+
function navSentinels(canGoBack) {
|
|
3049
|
+
const items = [new inquirer.Separator()];
|
|
3050
|
+
if (canGoBack) {
|
|
3051
|
+
items.push({
|
|
3052
|
+
name: `${ansis.cyan("\u2190")} ${i18n.t("init:nav.back")}`,
|
|
3053
|
+
value: BACK_SENTINEL
|
|
3054
|
+
});
|
|
3055
|
+
}
|
|
3056
|
+
items.push({
|
|
3057
|
+
name: `${ansis.red("\xD7")} ${i18n.t("init:nav.cancel")}`,
|
|
3058
|
+
value: CANCEL_SENTINEL
|
|
3059
|
+
});
|
|
3060
|
+
return items;
|
|
3061
|
+
}
|
|
2906
3062
|
async function installGrokSearchMcp(keys) {
|
|
2907
3063
|
const env = {};
|
|
2908
3064
|
if (keys.tavilyKey)
|
|
@@ -2954,7 +3110,7 @@ async function init(options = {}) {
|
|
|
2954
3110
|
let backendModels = ["codex"];
|
|
2955
3111
|
let geminiModel = "gemini-3.1-pro-preview";
|
|
2956
3112
|
const mode = "smart";
|
|
2957
|
-
|
|
3113
|
+
let selectedWorkflows = getCoreCommandIds();
|
|
2958
3114
|
if (options.skipPrompt) {
|
|
2959
3115
|
const existingConfig = await readCcgConfig();
|
|
2960
3116
|
if (existingConfig?.routing) {
|
|
@@ -2962,10 +3118,18 @@ async function init(options = {}) {
|
|
|
2962
3118
|
backendModels = existingConfig.routing.backend?.models || ["codex"];
|
|
2963
3119
|
geminiModel = existingConfig.routing.geminiModel || "gemini-3.1-pro-preview";
|
|
2964
3120
|
}
|
|
3121
|
+
if (existingConfig?.workflows?.installed) {
|
|
3122
|
+
const hadLegacy = existingConfig.workflows.installed.some(
|
|
3123
|
+
(w) => ["workflow", "plan", "execute", "frontend", "backend", "feat", "debug", "team"].includes(w)
|
|
3124
|
+
);
|
|
3125
|
+
if (hadLegacy) {
|
|
3126
|
+
selectedWorkflows = getAllCommandIds();
|
|
3127
|
+
}
|
|
3128
|
+
}
|
|
2965
3129
|
}
|
|
2966
3130
|
let liteMode = false;
|
|
2967
3131
|
let skipImpeccable = false;
|
|
2968
|
-
let mcpProvider = "
|
|
3132
|
+
let mcpProvider = "fast-context";
|
|
2969
3133
|
let aceToolBaseUrl = "";
|
|
2970
3134
|
let aceToolToken = "";
|
|
2971
3135
|
let contextWeaverApiKey = "";
|
|
@@ -2979,273 +3143,460 @@ async function init(options = {}) {
|
|
|
2979
3143
|
let grokApiKey = "";
|
|
2980
3144
|
let apiUrl = "";
|
|
2981
3145
|
let apiKey = "";
|
|
3146
|
+
if (options.skipPrompt) {
|
|
3147
|
+
const existingConfig = await readCcgConfig();
|
|
3148
|
+
if (existingConfig?.performance?.liteMode !== void 0) {
|
|
3149
|
+
liteMode = existingConfig.performance.liteMode;
|
|
3150
|
+
}
|
|
3151
|
+
if (existingConfig?.performance?.skipImpeccable !== void 0) {
|
|
3152
|
+
skipImpeccable = existingConfig.performance.skipImpeccable;
|
|
3153
|
+
}
|
|
3154
|
+
if (options.skipMcp) {
|
|
3155
|
+
mcpProvider = existingConfig?.mcp?.provider || "skip";
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
2982
3158
|
if (!options.skipPrompt) {
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
3159
|
+
const existingConfig = await readCcgConfig();
|
|
3160
|
+
if (existingConfig?.routing) {
|
|
3161
|
+
const ef = existingConfig.routing.frontend?.primary;
|
|
3162
|
+
const eb = existingConfig.routing.backend?.primary;
|
|
3163
|
+
if (ef)
|
|
3164
|
+
frontendModels = [ef];
|
|
3165
|
+
if (eb)
|
|
3166
|
+
backendModels = [eb];
|
|
3167
|
+
if (existingConfig.routing.geminiModel)
|
|
3168
|
+
geminiModel = existingConfig.routing.geminiModel;
|
|
3169
|
+
}
|
|
3170
|
+
if (existingConfig?.performance?.liteMode !== void 0) {
|
|
3171
|
+
liteMode = existingConfig.performance.liteMode;
|
|
3172
|
+
}
|
|
3173
|
+
async function runApiStep(canGoBack) {
|
|
2998
3174
|
console.log();
|
|
2999
|
-
console.log(
|
|
3175
|
+
console.log(ansis.cyan.bold(` \u{1F511} Step 1/4 \u2014 ${i18n.t("init:api.title")}`));
|
|
3000
3176
|
console.log();
|
|
3001
|
-
const {
|
|
3002
|
-
type: "
|
|
3003
|
-
name: "
|
|
3004
|
-
message:
|
|
3005
|
-
|
|
3006
|
-
|
|
3177
|
+
const { apiProvider } = await inquirer.prompt([{
|
|
3178
|
+
type: "list",
|
|
3179
|
+
name: "apiProvider",
|
|
3180
|
+
message: i18n.t("init:api.providerPrompt"),
|
|
3181
|
+
choices: [
|
|
3182
|
+
{ name: `${ansis.green("\u25CF")} ${i18n.t("init:api.officialOption")}`, value: "official" },
|
|
3183
|
+
{ name: `${ansis.cyan("\u25CF")} ${i18n.t("init:api.thirdPartyOption")}`, value: "thirdparty" },
|
|
3184
|
+
{ name: `${ansis.yellow("\u2605")} ${i18n.t("init:api.sponsor302AI")} ${ansis.gray("\u2014 https://share.302.ai/oUDqQ6")}`, value: "302ai" },
|
|
3185
|
+
{ name: `${ansis.gray("\u25CB")} ${i18n.t("init:api.skipOption")}`, value: "skip" },
|
|
3186
|
+
...navSentinels(canGoBack)
|
|
3187
|
+
]
|
|
3007
3188
|
}]);
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
{
|
|
3189
|
+
if (apiProvider === BACK_SENTINEL)
|
|
3190
|
+
return "back";
|
|
3191
|
+
if (apiProvider === CANCEL_SENTINEL)
|
|
3192
|
+
return "cancel";
|
|
3193
|
+
apiUrl = "";
|
|
3194
|
+
apiKey = "";
|
|
3195
|
+
if (apiProvider === "302ai") {
|
|
3196
|
+
apiUrl = "https://api.302.ai/cc";
|
|
3197
|
+
console.log();
|
|
3198
|
+
console.log(` ${ansis.yellow("\u2605")} ${i18n.t("init:api.sponsor302AIGetKey")}: ${ansis.cyan.underline("https://share.302.ai/oUDqQ6")}`);
|
|
3199
|
+
console.log();
|
|
3200
|
+
const { key } = await inquirer.prompt([{
|
|
3018
3201
|
type: "password",
|
|
3019
3202
|
name: "key",
|
|
3020
|
-
message: `API Key ${ansis.gray(`(${i18n.t("init:api.keyRequired")})`)}`,
|
|
3203
|
+
message: `302.AI API Key ${ansis.gray(`(${i18n.t("init:api.keyRequired")})`)}`,
|
|
3021
3204
|
mask: "*",
|
|
3022
3205
|
validate: (v) => v.trim() !== "" || i18n.t("init:api.enterKey")
|
|
3023
|
-
}
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3206
|
+
}]);
|
|
3207
|
+
apiKey = key?.trim() || "";
|
|
3208
|
+
} else if (apiProvider === "thirdparty") {
|
|
3209
|
+
const apiAnswers = await inquirer.prompt([
|
|
3210
|
+
{
|
|
3211
|
+
type: "input",
|
|
3212
|
+
name: "url",
|
|
3213
|
+
message: `API URL ${ansis.gray(`(${i18n.t("init:api.urlRequired")})`)}`,
|
|
3214
|
+
validate: (v) => v.trim() !== "" || i18n.t("init:api.enterUrl")
|
|
3215
|
+
},
|
|
3216
|
+
{
|
|
3217
|
+
type: "password",
|
|
3218
|
+
name: "key",
|
|
3219
|
+
message: `API Key ${ansis.gray(`(${i18n.t("init:api.keyRequired")})`)}`,
|
|
3220
|
+
mask: "*",
|
|
3221
|
+
validate: (v) => v.trim() !== "" || i18n.t("init:api.enterKey")
|
|
3222
|
+
}
|
|
3223
|
+
]);
|
|
3224
|
+
apiUrl = apiAnswers.url?.trim() || "";
|
|
3225
|
+
apiKey = apiAnswers.key?.trim() || "";
|
|
3226
|
+
} else if (apiProvider === "skip") {
|
|
3227
|
+
console.log();
|
|
3228
|
+
console.log(` ${ansis.gray("\u25CB")} ${i18n.t("init:api.skipNoticeTitle")}`);
|
|
3229
|
+
}
|
|
3230
|
+
return "next";
|
|
3027
3231
|
}
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
choices: [
|
|
3049
|
-
{ name: "Gemini", value: "gemini" },
|
|
3050
|
-
{ name: `Codex ${ansis.green(`(${i18n.t("init:model.recommended")})`)}`, value: "codex" }
|
|
3051
|
-
],
|
|
3052
|
-
default: existingConfig?.routing?.backend?.primary || "codex"
|
|
3053
|
-
}]);
|
|
3054
|
-
frontendModels = [selectedFrontend];
|
|
3055
|
-
backendModels = [selectedBackend];
|
|
3056
|
-
if (selectedFrontend === "gemini" || selectedBackend === "gemini") {
|
|
3057
|
-
const { selectedGeminiModel } = await inquirer.prompt([{
|
|
3232
|
+
async function runModelStep(canGoBack) {
|
|
3233
|
+
console.log();
|
|
3234
|
+
console.log(ansis.cyan.bold(` \u{1F9E0} Step 2/4 \u2014 ${i18n.t("init:model.title")}`));
|
|
3235
|
+
console.log();
|
|
3236
|
+
const { selectedFrontend } = await inquirer.prompt([{
|
|
3237
|
+
type: "list",
|
|
3238
|
+
name: "selectedFrontend",
|
|
3239
|
+
message: i18n.t("init:model.selectFrontend"),
|
|
3240
|
+
choices: [
|
|
3241
|
+
{ name: `Gemini ${ansis.green(`(${i18n.t("init:model.recommended")})`)}`, value: "gemini" },
|
|
3242
|
+
{ name: "Codex", value: "codex" },
|
|
3243
|
+
...navSentinels(canGoBack)
|
|
3244
|
+
],
|
|
3245
|
+
default: frontendModels[0] || "gemini"
|
|
3246
|
+
}]);
|
|
3247
|
+
if (selectedFrontend === BACK_SENTINEL)
|
|
3248
|
+
return "back";
|
|
3249
|
+
if (selectedFrontend === CANCEL_SENTINEL)
|
|
3250
|
+
return "cancel";
|
|
3251
|
+
const { selectedBackend } = await inquirer.prompt([{
|
|
3058
3252
|
type: "list",
|
|
3059
|
-
name: "
|
|
3060
|
-
message: i18n.t("init:model.
|
|
3253
|
+
name: "selectedBackend",
|
|
3254
|
+
message: i18n.t("init:model.selectBackend"),
|
|
3061
3255
|
choices: [
|
|
3062
|
-
{ name:
|
|
3063
|
-
{ name: "
|
|
3064
|
-
{ name: `${i18n.t("init:model.custom")}`, value: "custom" }
|
|
3256
|
+
{ name: "Gemini", value: "gemini" },
|
|
3257
|
+
{ name: `Codex ${ansis.green(`(${i18n.t("init:model.recommended")})`)}`, value: "codex" }
|
|
3065
3258
|
],
|
|
3066
|
-
default:
|
|
3259
|
+
default: backendModels[0] || "codex"
|
|
3067
3260
|
}]);
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3261
|
+
frontendModels = [selectedFrontend];
|
|
3262
|
+
backendModels = [selectedBackend];
|
|
3263
|
+
if (selectedFrontend === "gemini" || selectedBackend === "gemini") {
|
|
3264
|
+
const { selectedGeminiModel } = await inquirer.prompt([{
|
|
3265
|
+
type: "list",
|
|
3266
|
+
name: "selectedGeminiModel",
|
|
3267
|
+
message: i18n.t("init:model.selectGeminiModel"),
|
|
3268
|
+
choices: [
|
|
3269
|
+
{ name: `gemini-3.1-pro-preview ${ansis.green(`(${i18n.t("init:model.recommended")})`)}`, value: "gemini-3.1-pro-preview" },
|
|
3270
|
+
{ name: "gemini-2.5-flash", value: "gemini-2.5-flash" },
|
|
3271
|
+
{ name: `${i18n.t("init:model.custom")}`, value: "custom" }
|
|
3272
|
+
],
|
|
3273
|
+
default: geminiModel || "gemini-3.1-pro-preview"
|
|
3074
3274
|
}]);
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
console.log(ansis.cyan.bold(` \u{1F527} Step 3/4 \u2014 ${i18n.t("init:mcp.title")}`));
|
|
3087
|
-
console.log();
|
|
3088
|
-
const { selectedTools } = await inquirer.prompt([{
|
|
3089
|
-
type: "checkbox",
|
|
3090
|
-
name: "selectedTools",
|
|
3091
|
-
message: i18n.t("init:mcp.selectTools"),
|
|
3092
|
-
choices: [
|
|
3093
|
-
{
|
|
3094
|
-
name: `ace-tool ${ansis.green(`(${i18n.t("common:info")})`)} ${ansis.gray("\u2014 search_context \u4EE3\u7801\u68C0\u7D22")}`,
|
|
3095
|
-
value: "ace-tool",
|
|
3096
|
-
checked: true
|
|
3097
|
-
},
|
|
3098
|
-
{
|
|
3099
|
-
name: `fast-context ${ansis.gray("\u2014 AI \u9A71\u52A8\u8BED\u4E49\u641C\u7D22")}`,
|
|
3100
|
-
value: "fast-context"
|
|
3101
|
-
},
|
|
3102
|
-
{
|
|
3103
|
-
name: `context7 ${ansis.green("(free)")} ${ansis.gray("\u2014 \u5E93\u6587\u6863\u67E5\u8BE2")}`,
|
|
3104
|
-
value: "context7",
|
|
3105
|
-
checked: true
|
|
3106
|
-
},
|
|
3107
|
-
{
|
|
3108
|
-
name: `grok-search ${ansis.gray("\u2014 \u8054\u7F51\u641C\u7D22 (\u9700 API Key)")}`,
|
|
3109
|
-
value: "grok-search"
|
|
3110
|
-
},
|
|
3111
|
-
{
|
|
3112
|
-
name: `contextweaver ${ansis.gray("\u2014 \u7845\u57FA\u6D41\u52A8\u5D4C\u5165\u68C0\u7D22 (\u9700 API Key)")}`,
|
|
3113
|
-
value: "contextweaver"
|
|
3275
|
+
if (selectedGeminiModel === "custom") {
|
|
3276
|
+
const { customModel } = await inquirer.prompt([{
|
|
3277
|
+
type: "input",
|
|
3278
|
+
name: "customModel",
|
|
3279
|
+
message: i18n.t("init:model.enterCustomModel"),
|
|
3280
|
+
default: geminiModel || "",
|
|
3281
|
+
validate: (v) => v.trim() !== "" || i18n.t("init:model.enterCustomModel")
|
|
3282
|
+
}]);
|
|
3283
|
+
geminiModel = customModel.trim();
|
|
3284
|
+
} else {
|
|
3285
|
+
geminiModel = selectedGeminiModel;
|
|
3114
3286
|
}
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
const hasAceTool = selectedTools.includes("ace-tool");
|
|
3118
|
-
const hasFastContext = selectedTools.includes("fast-context");
|
|
3119
|
-
const hasContextWeaver = selectedTools.includes("contextweaver");
|
|
3120
|
-
wantFastContext = hasFastContext;
|
|
3121
|
-
wantGrokSearch = selectedTools.includes("grok-search");
|
|
3122
|
-
if (hasAceTool) {
|
|
3123
|
-
mcpProvider = "ace-tool";
|
|
3124
|
-
} else if (hasFastContext) {
|
|
3125
|
-
mcpProvider = "fast-context";
|
|
3126
|
-
} else if (hasContextWeaver) {
|
|
3127
|
-
mcpProvider = "contextweaver";
|
|
3128
|
-
} else {
|
|
3129
|
-
mcpProvider = "skip";
|
|
3287
|
+
}
|
|
3288
|
+
return "next";
|
|
3130
3289
|
}
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3290
|
+
async function runMcpStep(canGoBack) {
|
|
3291
|
+
if (options.skipMcp) {
|
|
3292
|
+
mcpProvider = existingConfig?.mcp?.provider || "skip";
|
|
3293
|
+
return "next";
|
|
3294
|
+
}
|
|
3134
3295
|
console.log();
|
|
3135
|
-
console.log(
|
|
3136
|
-
console.log(` ${ansis.gray("\u2022")} ${ansis.cyan(i18n.t("init:mcp.proxyService"))} ${ansis.yellow(`(${i18n.t("init:mcp.noSignup")})`)}: ${ansis.underline("https://acemcp.heroman.wtf/")}`);
|
|
3296
|
+
console.log(ansis.cyan.bold(` \u{1F527} Step 3/4 \u2014 ${i18n.t("init:mcp.title")}`));
|
|
3137
3297
|
console.log();
|
|
3138
|
-
const
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3298
|
+
const { gate } = await inquirer.prompt([{
|
|
3299
|
+
type: "list",
|
|
3300
|
+
name: "gate",
|
|
3301
|
+
message: i18n.t("init:mcp.gatePrompt"),
|
|
3302
|
+
choices: [
|
|
3303
|
+
{ name: `${ansis.green("\u25CF")} ${i18n.t("init:mcp.gateContinue")}`, value: "continue" },
|
|
3304
|
+
...navSentinels(canGoBack)
|
|
3305
|
+
]
|
|
3306
|
+
}]);
|
|
3307
|
+
if (gate === BACK_SENTINEL)
|
|
3308
|
+
return "back";
|
|
3309
|
+
if (gate === CANCEL_SENTINEL)
|
|
3310
|
+
return "cancel";
|
|
3311
|
+
aceToolBaseUrl = "";
|
|
3312
|
+
aceToolToken = "";
|
|
3313
|
+
fastContextApiKey = "";
|
|
3314
|
+
fastContextIncludeSnippets = false;
|
|
3315
|
+
contextWeaverApiKey = "";
|
|
3316
|
+
wantFastContext = false;
|
|
3317
|
+
wantGrokSearch = false;
|
|
3318
|
+
tavilyKey = "";
|
|
3319
|
+
firecrawlKey = "";
|
|
3320
|
+
grokApiUrl = "";
|
|
3321
|
+
grokApiKey = "";
|
|
3322
|
+
const { selectedTools } = await inquirer.prompt([{
|
|
3323
|
+
type: "checkbox",
|
|
3324
|
+
name: "selectedTools",
|
|
3325
|
+
message: i18n.t("init:mcp.selectTools"),
|
|
3326
|
+
choices: [
|
|
3327
|
+
{
|
|
3328
|
+
name: `fast-context ${ansis.green(`(${i18n.t("common:recommended")})`)} ${ansis.gray("\u2014 AI \u9A71\u52A8\u8BED\u4E49\u641C\u7D22")}`,
|
|
3329
|
+
value: "fast-context",
|
|
3330
|
+
checked: true
|
|
3331
|
+
},
|
|
3332
|
+
{
|
|
3333
|
+
name: `ace-tool ${ansis.gray("\u2014 search_context \u4EE3\u7801\u68C0\u7D22")}`,
|
|
3334
|
+
value: "ace-tool"
|
|
3335
|
+
},
|
|
3336
|
+
{
|
|
3337
|
+
name: `context7 ${ansis.green("(free)")} ${ansis.gray("\u2014 \u5E93\u6587\u6863\u67E5\u8BE2")}`,
|
|
3338
|
+
value: "context7",
|
|
3339
|
+
checked: true
|
|
3340
|
+
},
|
|
3341
|
+
{
|
|
3342
|
+
name: `grok-search ${ansis.gray("\u2014 \u8054\u7F51\u641C\u7D22 (\u9700 API Key)")}`,
|
|
3343
|
+
value: "grok-search"
|
|
3344
|
+
},
|
|
3345
|
+
{
|
|
3346
|
+
name: `contextweaver ${ansis.gray("\u2014 \u7845\u57FA\u6D41\u52A8\u5D4C\u5165\u68C0\u7D22 (\u9700 API Key)")}`,
|
|
3347
|
+
value: "contextweaver"
|
|
3348
|
+
}
|
|
3349
|
+
]
|
|
3350
|
+
}]);
|
|
3351
|
+
const hasAceTool = selectedTools.includes("ace-tool");
|
|
3352
|
+
const hasFastContext = selectedTools.includes("fast-context");
|
|
3353
|
+
const hasContextWeaver = selectedTools.includes("contextweaver");
|
|
3354
|
+
wantFastContext = hasFastContext;
|
|
3355
|
+
wantGrokSearch = selectedTools.includes("grok-search");
|
|
3356
|
+
if (hasAceTool) {
|
|
3357
|
+
mcpProvider = "ace-tool";
|
|
3358
|
+
} else if (hasFastContext) {
|
|
3359
|
+
mcpProvider = "fast-context";
|
|
3360
|
+
} else if (hasContextWeaver) {
|
|
3361
|
+
mcpProvider = "contextweaver";
|
|
3362
|
+
} else {
|
|
3363
|
+
mcpProvider = "skip";
|
|
3364
|
+
}
|
|
3365
|
+
if (hasAceTool) {
|
|
3366
|
+
console.log();
|
|
3367
|
+
console.log(ansis.cyan.bold(` \u{1F527} ace-tool MCP`));
|
|
3368
|
+
console.log();
|
|
3369
|
+
console.log(` ${ansis.gray("\u2022")} ${ansis.cyan(i18n.t("init:mcp.officialService"))}: ${ansis.underline("https://augmentcode.com/")}`);
|
|
3370
|
+
console.log(` ${ansis.gray("\u2022")} ${ansis.cyan(i18n.t("init:mcp.proxyService"))} ${ansis.yellow(`(${i18n.t("init:mcp.noSignup")})`)}: ${ansis.underline("https://acemcp.heroman.wtf/")}`);
|
|
3371
|
+
console.log();
|
|
3372
|
+
const aceAnswers = await inquirer.prompt([
|
|
3373
|
+
{
|
|
3374
|
+
type: "input",
|
|
3375
|
+
name: "baseUrl",
|
|
3376
|
+
message: `Base URL ${ansis.gray(`(${i18n.t("init:mcp.baseUrlHint")})`)}`,
|
|
3377
|
+
default: ""
|
|
3378
|
+
},
|
|
3379
|
+
{
|
|
3380
|
+
type: "password",
|
|
3381
|
+
name: "token",
|
|
3382
|
+
message: `Token ${ansis.gray(`(${i18n.t("init:mcp.tokenRequired")})`)}`,
|
|
3383
|
+
mask: "*",
|
|
3384
|
+
validate: (input) => input.trim() !== "" || i18n.t("init:mcp.enterToken")
|
|
3385
|
+
}
|
|
3386
|
+
]);
|
|
3387
|
+
aceToolBaseUrl = aceAnswers.baseUrl || "";
|
|
3388
|
+
aceToolToken = aceAnswers.token || "";
|
|
3389
|
+
}
|
|
3390
|
+
if (hasFastContext) {
|
|
3391
|
+
console.log();
|
|
3392
|
+
console.log(ansis.cyan.bold(` \u{1F527} fast-context MCP`));
|
|
3393
|
+
console.log(ansis.gray(` Windsurf Fast Context \u2014 ${i18n.t("init:mcp.fcAutoExtract")}`));
|
|
3394
|
+
console.log();
|
|
3395
|
+
const fcAnswers = await inquirer.prompt([
|
|
3396
|
+
{
|
|
3397
|
+
type: "input",
|
|
3398
|
+
name: "apiKey",
|
|
3399
|
+
message: `WINDSURF_API_KEY ${ansis.gray(`(${i18n.t("init:mcp.fcLeaveEmpty")})`)}`,
|
|
3400
|
+
default: ""
|
|
3401
|
+
},
|
|
3402
|
+
{
|
|
3403
|
+
type: "list",
|
|
3404
|
+
name: "includeSnippets",
|
|
3405
|
+
message: i18n.t("init:mcp.fcSnippetMode"),
|
|
3406
|
+
choices: [
|
|
3407
|
+
{ name: `${i18n.t("init:mcp.fcPathOnly")} ${ansis.gray(`(${i18n.t("init:mcp.fcSaveToken")})`)}`, value: false },
|
|
3408
|
+
{ name: i18n.t("init:mcp.fcFullSnippet"), value: true }
|
|
3409
|
+
]
|
|
3410
|
+
}
|
|
3411
|
+
]);
|
|
3412
|
+
fastContextApiKey = fcAnswers.apiKey?.trim() || "";
|
|
3413
|
+
fastContextIncludeSnippets = fcAnswers.includeSnippets;
|
|
3414
|
+
}
|
|
3415
|
+
if (hasContextWeaver) {
|
|
3416
|
+
console.log();
|
|
3417
|
+
console.log(ansis.cyan.bold(` \u{1F527} ContextWeaver MCP`));
|
|
3418
|
+
console.log();
|
|
3419
|
+
console.log(` ${ansis.gray("1.")} ${i18n.t("init:mcp.siliconflowStep1", { url: ansis.underline("https://siliconflow.cn/") })}`);
|
|
3420
|
+
console.log(` ${ansis.gray("2.")} ${i18n.t("init:mcp.siliconflowStep2")}`);
|
|
3421
|
+
console.log(` ${ansis.gray("3.")} ${i18n.t("init:mcp.siliconflowStep3")}`);
|
|
3422
|
+
console.log();
|
|
3423
|
+
const cwAnswers = await inquirer.prompt([{
|
|
3146
3424
|
type: "password",
|
|
3147
|
-
name: "token",
|
|
3148
|
-
message: `Token ${ansis.gray(`(${i18n.t("init:mcp.tokenRequired")})`)}`,
|
|
3149
|
-
mask: "*",
|
|
3150
|
-
validate: (input) => input.trim() !== "" || i18n.t("init:mcp.enterToken")
|
|
3151
|
-
}
|
|
3152
|
-
]);
|
|
3153
|
-
aceToolBaseUrl = aceAnswers.baseUrl || "";
|
|
3154
|
-
aceToolToken = aceAnswers.token || "";
|
|
3155
|
-
}
|
|
3156
|
-
if (hasFastContext) {
|
|
3157
|
-
console.log();
|
|
3158
|
-
console.log(ansis.cyan.bold(` \u{1F527} fast-context MCP`));
|
|
3159
|
-
console.log(ansis.gray(` Windsurf Fast Context \u2014 ${i18n.t("init:mcp.fcAutoExtract")}`));
|
|
3160
|
-
console.log();
|
|
3161
|
-
const fcAnswers = await inquirer.prompt([
|
|
3162
|
-
{
|
|
3163
|
-
type: "input",
|
|
3164
3425
|
name: "apiKey",
|
|
3165
|
-
message: `
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
}
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3426
|
+
message: `SiliconFlow API Key ${ansis.gray("(sk-xxx)")}`,
|
|
3427
|
+
mask: "*",
|
|
3428
|
+
validate: (input) => input.trim() !== "" || i18n.t("init:mcp.enterApiKey")
|
|
3429
|
+
}]);
|
|
3430
|
+
contextWeaverApiKey = cwAnswers.apiKey || "";
|
|
3431
|
+
}
|
|
3432
|
+
if (wantGrokSearch) {
|
|
3433
|
+
console.log();
|
|
3434
|
+
console.log(ansis.cyan.bold(` \u{1F50D} grok-search MCP`));
|
|
3435
|
+
console.log();
|
|
3436
|
+
console.log(` Tavily: ${ansis.underline("https://www.tavily.com/")} ${ansis.gray(`(${i18n.t("init:grok.tavilyHint")})`)}`);
|
|
3437
|
+
console.log(` Firecrawl: ${ansis.underline("https://www.firecrawl.dev/")} ${ansis.gray(`(${i18n.t("init:grok.firecrawlHint")})`)}`);
|
|
3438
|
+
console.log(` Grok API: ${ansis.gray(i18n.t("init:grok.grokHint"))}`);
|
|
3439
|
+
console.log();
|
|
3440
|
+
const grokAnswers = await inquirer.prompt([
|
|
3441
|
+
{ type: "input", name: "grokApiUrl", message: `GROK_API_URL ${ansis.gray(`(${i18n.t("init:grok.optional")})`)}`, default: "" },
|
|
3442
|
+
{ type: "password", name: "grokApiKey", message: `GROK_API_KEY ${ansis.gray(`(${i18n.t("init:grok.optional")})`)}`, mask: "*" },
|
|
3443
|
+
{ type: "password", name: "tavilyKey", message: `TAVILY_API_KEY ${ansis.gray(`(${i18n.t("init:grok.optional")})`)}`, mask: "*" },
|
|
3444
|
+
{ type: "password", name: "firecrawlKey", message: `FIRECRAWL_API_KEY ${ansis.gray(`(${i18n.t("init:grok.optional")})`)}`, mask: "*" }
|
|
3445
|
+
]);
|
|
3446
|
+
tavilyKey = grokAnswers.tavilyKey?.trim() || "";
|
|
3447
|
+
firecrawlKey = grokAnswers.firecrawlKey?.trim() || "";
|
|
3448
|
+
grokApiUrl = grokAnswers.grokApiUrl?.trim() || "";
|
|
3449
|
+
grokApiKey = grokAnswers.grokApiKey?.trim() || "";
|
|
3450
|
+
}
|
|
3451
|
+
return "next";
|
|
3180
3452
|
}
|
|
3181
|
-
|
|
3453
|
+
async function runPerfStep(canGoBack) {
|
|
3182
3454
|
console.log();
|
|
3183
|
-
console.log(ansis.cyan.bold(` \
|
|
3455
|
+
console.log(ansis.cyan.bold(` \u26A1 Step 4/4 \u2014 ${i18n.t("init:perf.title")}`));
|
|
3184
3456
|
console.log();
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3457
|
+
const { perfMode } = await inquirer.prompt([{
|
|
3458
|
+
type: "list",
|
|
3459
|
+
name: "perfMode",
|
|
3460
|
+
message: i18n.t("init:perf.selectMode"),
|
|
3461
|
+
choices: [
|
|
3462
|
+
{ name: `${ansis.green("\u25CF")} ${i18n.t("init:perf.standardOption")}`, value: "standard" },
|
|
3463
|
+
{ name: `${ansis.cyan("\u25CF")} ${i18n.t("init:perf.liteOption")}`, value: "lite" },
|
|
3464
|
+
...navSentinels(canGoBack)
|
|
3465
|
+
],
|
|
3466
|
+
default: liteMode ? "lite" : "standard"
|
|
3467
|
+
}]);
|
|
3468
|
+
if (perfMode === BACK_SENTINEL)
|
|
3469
|
+
return "back";
|
|
3470
|
+
if (perfMode === CANCEL_SENTINEL)
|
|
3471
|
+
return "cancel";
|
|
3472
|
+
liteMode = perfMode === "lite";
|
|
3473
|
+
const { versionMode } = await inquirer.prompt([{
|
|
3474
|
+
type: "list",
|
|
3475
|
+
name: "versionMode",
|
|
3476
|
+
message: "\u5B89\u88C5\u6A21\u5F0F",
|
|
3477
|
+
choices: [
|
|
3478
|
+
{ name: `${ansis.green("v3 \u65B0\u7248")} \u2014 /ccg:go \u667A\u80FD\u5165\u53E3 + Hook \u5F15\u64CE + 12 \u6838\u5FC3\u547D\u4EE4\uFF08\u63A8\u8350\uFF09`, value: "v3" },
|
|
3479
|
+
{ name: `${ansis.gray("\u65E7\u7248\u517C\u5BB9")} \u2014 \u65B0\u7248\u5168\u90E8 + 18 \u4E2A\u65E7\u7248\u547D\u4EE4\uFF08workflow/debug/team \u7B49\uFF09`, value: "legacy" }
|
|
3480
|
+
],
|
|
3481
|
+
default: "v3"
|
|
3195
3482
|
}]);
|
|
3196
|
-
|
|
3483
|
+
if (versionMode === "legacy") {
|
|
3484
|
+
selectedWorkflows = getAllCommandIds();
|
|
3485
|
+
const { includeImpeccable } = await inquirer.prompt([{
|
|
3486
|
+
type: "confirm",
|
|
3487
|
+
name: "includeImpeccable",
|
|
3488
|
+
message: i18n.t("init:commands.includeImpeccable"),
|
|
3489
|
+
default: !skipImpeccable
|
|
3490
|
+
}]);
|
|
3491
|
+
skipImpeccable = !includeImpeccable;
|
|
3492
|
+
} else {
|
|
3493
|
+
selectedWorkflows = getCoreCommandIds();
|
|
3494
|
+
skipImpeccable = true;
|
|
3495
|
+
}
|
|
3496
|
+
return "next";
|
|
3197
3497
|
}
|
|
3198
|
-
|
|
3498
|
+
const runSummaryStep = async (workflowsCount) => {
|
|
3199
3499
|
console.log();
|
|
3200
|
-
console.log(ansis.
|
|
3500
|
+
console.log(ansis.yellow("\u2501".repeat(50)));
|
|
3501
|
+
console.log(ansis.bold(` ${i18n.t("init:summary.title")}`));
|
|
3201
3502
|
console.log();
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3503
|
+
const fmName = frontendModels[0].charAt(0).toUpperCase() + frontendModels[0].slice(1);
|
|
3504
|
+
const bmName = backendModels[0].charAt(0).toUpperCase() + backendModels[0].slice(1);
|
|
3505
|
+
const apiLabel = (() => {
|
|
3506
|
+
if (apiUrl && apiKey)
|
|
3507
|
+
return `${ansis.green("\u25CF")} ${apiUrl} ${ansis.gray("+ ***")}`;
|
|
3508
|
+
if (apiUrl)
|
|
3509
|
+
return `${ansis.green("\u25CF")} ${apiUrl}`;
|
|
3510
|
+
return `${ansis.gray("\u25CB")} ${i18n.t("init:summary.apiSelfManaged")}`;
|
|
3511
|
+
})();
|
|
3512
|
+
console.log(` ${ansis.cyan(i18n.t("init:summary.apiProvider"))} ${apiLabel}`);
|
|
3513
|
+
console.log(` ${ansis.cyan(i18n.t("init:summary.modelRouting"))} ${ansis.green(fmName)} (Frontend) + ${ansis.blue(bmName)} (Backend)`);
|
|
3514
|
+
if (frontendModels[0] === "gemini" || backendModels[0] === "gemini") {
|
|
3515
|
+
console.log(` ${ansis.cyan(i18n.t("init:summary.geminiModel"))} ${ansis.gray(geminiModel)}`);
|
|
3516
|
+
}
|
|
3517
|
+
console.log(` ${ansis.cyan(i18n.t("init:summary.commandCount"))} ${ansis.yellow(workflowsCount.toString())}`);
|
|
3518
|
+
const mcpSummary = (() => {
|
|
3519
|
+
if (mcpProvider === "fast-context")
|
|
3520
|
+
return ansis.green("fast-context");
|
|
3521
|
+
if (mcpProvider === "ace-tool" || mcpProvider === "ace-tool-rs")
|
|
3522
|
+
return aceToolToken ? ansis.green(mcpProvider) : ansis.yellow(`${mcpProvider} (${i18n.t("init:summary.pendingConfig")})`);
|
|
3523
|
+
if (mcpProvider === "contextweaver")
|
|
3524
|
+
return contextWeaverApiKey ? ansis.green("contextweaver") : ansis.yellow(`contextweaver (${i18n.t("init:summary.pendingConfig")})`);
|
|
3525
|
+
return ansis.gray(i18n.t("init:summary.skipped"));
|
|
3526
|
+
})();
|
|
3527
|
+
console.log(` ${ansis.cyan(i18n.t("init:summary.mcpTool"))} ${mcpSummary}`);
|
|
3528
|
+
console.log(` ${ansis.cyan(i18n.t("init:summary.webUI"))} ${liteMode ? ansis.gray(i18n.t("init:summary.disabled")) : ansis.green(i18n.t("init:summary.enabled"))}`);
|
|
3529
|
+
if (wantGrokSearch) {
|
|
3530
|
+
console.log(` ${ansis.cyan("grok-search")} ${tavilyKey ? ansis.green("\u2713") : ansis.yellow(`(${i18n.t("init:summary.pendingConfig")})`)}`);
|
|
3531
|
+
}
|
|
3532
|
+
console.log(ansis.yellow("\u2501".repeat(50)));
|
|
3205
3533
|
console.log();
|
|
3206
|
-
const
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
const
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3534
|
+
const { action } = await inquirer.prompt([{
|
|
3535
|
+
type: "list",
|
|
3536
|
+
name: "action",
|
|
3537
|
+
message: i18n.t("init:summaryMenu.prompt"),
|
|
3538
|
+
choices: [
|
|
3539
|
+
{ name: `${ansis.green("\u2713")} ${i18n.t("init:summaryMenu.confirm")}`, value: "confirm" },
|
|
3540
|
+
new inquirer.Separator(),
|
|
3541
|
+
{ name: `${ansis.cyan("\u270E")} ${i18n.t("init:summaryMenu.editApi")}`, value: "api" },
|
|
3542
|
+
{ name: `${ansis.cyan("\u270E")} ${i18n.t("init:summaryMenu.editModel")}`, value: "model" },
|
|
3543
|
+
{ name: `${ansis.cyan("\u270E")} ${i18n.t("init:summaryMenu.editMcp")}`, value: "mcp" },
|
|
3544
|
+
{ name: `${ansis.cyan("\u270E")} ${i18n.t("init:summaryMenu.editPerf")}`, value: "perf" },
|
|
3545
|
+
new inquirer.Separator(),
|
|
3546
|
+
{ name: `${ansis.red("\xD7")} ${i18n.t("init:summaryMenu.cancel")}`, value: "cancel" }
|
|
3547
|
+
],
|
|
3548
|
+
default: "confirm"
|
|
3549
|
+
}]);
|
|
3550
|
+
return action;
|
|
3551
|
+
};
|
|
3552
|
+
const stepOrder = ["api", "model", "mcp", "perf"];
|
|
3553
|
+
let stepIdx = 0;
|
|
3554
|
+
let jumpingToSummary = false;
|
|
3555
|
+
while (true) {
|
|
3556
|
+
if (stepIdx < stepOrder.length) {
|
|
3557
|
+
const stepId = stepOrder[stepIdx];
|
|
3558
|
+
const canGoBack = stepIdx > 0;
|
|
3559
|
+
let result;
|
|
3560
|
+
switch (stepId) {
|
|
3561
|
+
case "api":
|
|
3562
|
+
result = await runApiStep(canGoBack);
|
|
3563
|
+
break;
|
|
3564
|
+
case "model":
|
|
3565
|
+
result = await runModelStep(canGoBack);
|
|
3566
|
+
break;
|
|
3567
|
+
case "mcp":
|
|
3568
|
+
result = await runMcpStep(canGoBack);
|
|
3569
|
+
break;
|
|
3570
|
+
case "perf":
|
|
3571
|
+
result = await runPerfStep(canGoBack);
|
|
3572
|
+
break;
|
|
3573
|
+
}
|
|
3574
|
+
if (result === "cancel") {
|
|
3575
|
+
console.log(ansis.yellow(i18n.t("init:installCancelled")));
|
|
3576
|
+
return;
|
|
3577
|
+
}
|
|
3578
|
+
if (result === "back") {
|
|
3579
|
+
stepIdx = Math.max(0, stepIdx - 1);
|
|
3580
|
+
continue;
|
|
3581
|
+
}
|
|
3582
|
+
if (jumpingToSummary) {
|
|
3583
|
+
jumpingToSummary = false;
|
|
3584
|
+
stepIdx = stepOrder.length;
|
|
3585
|
+
} else {
|
|
3586
|
+
stepIdx++;
|
|
3587
|
+
}
|
|
3588
|
+
} else {
|
|
3589
|
+
const summaryAction = await runSummaryStep(selectedWorkflows.length);
|
|
3590
|
+
if (summaryAction === "confirm") {
|
|
3591
|
+
break;
|
|
3592
|
+
}
|
|
3593
|
+
if (summaryAction === "cancel") {
|
|
3594
|
+
console.log(ansis.yellow(i18n.t("init:installCancelled")));
|
|
3595
|
+
return;
|
|
3596
|
+
}
|
|
3597
|
+
jumpingToSummary = true;
|
|
3598
|
+
stepIdx = stepOrder.indexOf(summaryAction);
|
|
3599
|
+
}
|
|
3249
3600
|
}
|
|
3250
3601
|
}
|
|
3251
3602
|
const routing = {
|
|
@@ -3266,38 +3617,17 @@ async function init(options = {}) {
|
|
|
3266
3617
|
mode,
|
|
3267
3618
|
geminiModel
|
|
3268
3619
|
};
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
if (mcpProvider === "contextweaver") return contextWeaverApiKey ? ansis.green("contextweaver") : ansis.yellow(`contextweaver (${i18n.t("init:summary.pendingConfig")})`);
|
|
3281
|
-
return ansis.gray(i18n.t("init:summary.skipped"));
|
|
3282
|
-
})();
|
|
3283
|
-
console.log(` ${ansis.cyan(i18n.t("init:summary.mcpTool"))} ${mcpSummary}`);
|
|
3284
|
-
console.log(` ${ansis.cyan(i18n.t("init:summary.webUI"))} ${liteMode ? ansis.gray(i18n.t("init:summary.disabled")) : ansis.green(i18n.t("init:summary.enabled"))}`);
|
|
3285
|
-
if (wantGrokSearch) {
|
|
3286
|
-
console.log(` ${ansis.cyan("grok-search")} ${tavilyKey ? ansis.green("\u2713") : ansis.yellow(`(${i18n.t("init:summary.pendingConfig")})`)}`);
|
|
3287
|
-
}
|
|
3288
|
-
console.log(ansis.yellow("\u2501".repeat(50)));
|
|
3289
|
-
console.log();
|
|
3290
|
-
if (!options.skipPrompt && !options.force) {
|
|
3291
|
-
const { confirmed } = await inquirer.prompt([{
|
|
3292
|
-
type: "confirm",
|
|
3293
|
-
name: "confirmed",
|
|
3294
|
-
message: i18n.t("init:confirmInstall"),
|
|
3295
|
-
default: true
|
|
3296
|
-
}]);
|
|
3297
|
-
if (!confirmed) {
|
|
3298
|
-
console.log(ansis.yellow(i18n.t("init:installCancelled")));
|
|
3299
|
-
return;
|
|
3300
|
-
}
|
|
3620
|
+
if (options.skipPrompt || options.force) {
|
|
3621
|
+
console.log();
|
|
3622
|
+
console.log(ansis.yellow("\u2501".repeat(50)));
|
|
3623
|
+
console.log(ansis.bold(` ${i18n.t("init:summary.title")}`));
|
|
3624
|
+
console.log();
|
|
3625
|
+
const fmName = frontendModels[0].charAt(0).toUpperCase() + frontendModels[0].slice(1);
|
|
3626
|
+
const bmName = backendModels[0].charAt(0).toUpperCase() + backendModels[0].slice(1);
|
|
3627
|
+
console.log(` ${ansis.cyan(i18n.t("init:summary.modelRouting"))} ${ansis.green(fmName)} (Frontend) + ${ansis.blue(bmName)} (Backend)`);
|
|
3628
|
+
console.log(` ${ansis.cyan(i18n.t("init:summary.commandCount"))} ${ansis.yellow(selectedWorkflows.length.toString())}`);
|
|
3629
|
+
console.log(ansis.yellow("\u2501".repeat(50)));
|
|
3630
|
+
console.log();
|
|
3301
3631
|
}
|
|
3302
3632
|
const spinner = ora(i18n.t("init:installing")).start();
|
|
3303
3633
|
try {
|
|
@@ -3831,7 +4161,9 @@ async function performUpdate(fromVersion, toVersion, isNewVersion) {
|
|
|
3831
4161
|
const backupTargets = [
|
|
3832
4162
|
join(installDir, "commands", "ccg"),
|
|
3833
4163
|
join(installDir, "agents", "ccg"),
|
|
3834
|
-
join(installDir, "skills", "ccg")
|
|
4164
|
+
join(installDir, "skills", "ccg"),
|
|
4165
|
+
join(installDir, "hooks", "ccg"),
|
|
4166
|
+
join(installDir, ".ccg", "engine")
|
|
3835
4167
|
];
|
|
3836
4168
|
spinner = ora(i18n.t("update:removingOld")).start();
|
|
3837
4169
|
const backedUp = [];
|