ccg-workflow 3.1.0 → 3.1.2
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 +4 -2
- package/README.zh-CN.md +3 -1
- package/dist/cli.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/shared/{ccg-workflow.B4hxlK6F.mjs → ccg-workflow.CTnUpMWE.mjs} +100 -78
- package/package.json +1 -1
- package/templates/codex/AGENTS.md +12 -12
- package/templates/codex/hooks/ccg-workflow.py +4 -4
- package/templates/codex/hooks.json +1 -1
package/README.md
CHANGED
|
@@ -26,7 +26,9 @@
|
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
[
|
|
29
|
+
[](https://notebooklmremover.org)
|
|
30
|
+
|
|
31
|
+
[NotebookLM Remover](https://notebooklmremover.org) — Free browser-local AI watermark remover. Remove NotebookLM watermarks across every format — video, PDF, PPTX, infographic, podcast, and more. 100% private, works offline.
|
|
30
32
|
|
|
31
33
|
---
|
|
32
34
|
|
|
@@ -251,4 +253,4 @@ MIT
|
|
|
251
253
|
|
|
252
254
|
---
|
|
253
255
|
|
|
254
|
-
v3.
|
|
256
|
+
v3.1.2 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [Contributing](./CONTRIBUTING.md)
|
package/README.zh-CN.md
CHANGED
|
@@ -27,7 +27,9 @@
|
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
30
|
-
[
|
|
30
|
+
[](https://notebooklmremover.org)
|
|
31
|
+
|
|
32
|
+
[NotebookLM Remover](https://notebooklmremover.org) — 免费浏览器本地 AI 水印去除工具。支持视频、PDF、PPTX、信息图、播客等全格式,100% 隐私,离线可用。
|
|
31
33
|
|
|
32
34
|
---
|
|
33
35
|
|
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import cac from 'cac';
|
|
3
3
|
import ansis from 'ansis';
|
|
4
|
-
import { B as diagnoseMcpConfig, C as isWindows, D as readClaudeCodeConfig, E as fixWindowsMcpConfig, F as writeClaudeCodeConfig, r as readCcgConfig, b as initI18n, a as i18n, s as showMainMenu, i as init, G as configMcp, H as version } from './shared/ccg-workflow.
|
|
4
|
+
import { B as diagnoseMcpConfig, C as isWindows, D as readClaudeCodeConfig, E as fixWindowsMcpConfig, F as writeClaudeCodeConfig, r as readCcgConfig, b as initI18n, a as i18n, s as showMainMenu, i as init, G as configMcp, H as version } from './shared/ccg-workflow.CTnUpMWE.mjs';
|
|
5
5
|
import 'inquirer';
|
|
6
6
|
import 'ora';
|
|
7
7
|
import 'node:child_process';
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { c as changeLanguage, z as checkForUpdates, A as compareVersions, d as createDefaultConfig, e as createDefaultRouting, g as getCcgDir, f as getConfigPath, x as getCurrentVersion, y as getLatestVersion, j as getWorkflowById, h as getWorkflowConfigs, a as i18n, i as init, b as initI18n, l as installAceTool, m as installAceToolRs, n as installCodexMode, k as installWorkflows, t as migrateToV1_4_0, v as needsMigration, r as readCcgConfig, s as showMainMenu, q as uninstallAceTool, o as uninstallCodexMode, p as uninstallWorkflows, u as update, w as writeCcgConfig } from './shared/ccg-workflow.
|
|
1
|
+
export { c as changeLanguage, z as checkForUpdates, A as compareVersions, d as createDefaultConfig, e as createDefaultRouting, g as getCcgDir, f as getConfigPath, x as getCurrentVersion, y as getLatestVersion, j as getWorkflowById, h as getWorkflowConfigs, a as i18n, i as init, b as initI18n, l as installAceTool, m as installAceToolRs, n as installCodexMode, k as installWorkflows, t as migrateToV1_4_0, v as needsMigration, r as readCcgConfig, s as showMainMenu, q as uninstallAceTool, o as uninstallCodexMode, p as uninstallWorkflows, u as update, w as writeCcgConfig } from './shared/ccg-workflow.CTnUpMWE.mjs';
|
|
2
2
|
import 'ansis';
|
|
3
3
|
import 'inquirer';
|
|
4
4
|
import 'ora';
|
|
@@ -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 = "3.1.
|
|
13
|
+
const version = "3.1.2";
|
|
14
14
|
|
|
15
15
|
function cmd(id, order, category, name, nameEn, description, descriptionEn, cmdOverride) {
|
|
16
16
|
return {
|
|
@@ -197,6 +197,79 @@ function replaceHomePathsInTemplate(content, installDir) {
|
|
|
197
197
|
return processed;
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
+
const CCG_DIR = join(homedir(), ".claude", ".ccg");
|
|
201
|
+
const CONFIG_FILE = join(CCG_DIR, "config.toml");
|
|
202
|
+
function getCcgDir() {
|
|
203
|
+
return CCG_DIR;
|
|
204
|
+
}
|
|
205
|
+
function getConfigPath() {
|
|
206
|
+
return CONFIG_FILE;
|
|
207
|
+
}
|
|
208
|
+
async function ensureCcgDir() {
|
|
209
|
+
await fs.ensureDir(CCG_DIR);
|
|
210
|
+
}
|
|
211
|
+
async function readCcgConfig() {
|
|
212
|
+
try {
|
|
213
|
+
if (await fs.pathExists(CONFIG_FILE)) {
|
|
214
|
+
const content = await fs.readFile(CONFIG_FILE, "utf-8");
|
|
215
|
+
return parse(content);
|
|
216
|
+
}
|
|
217
|
+
} catch {
|
|
218
|
+
}
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
async function writeCcgConfig(config) {
|
|
222
|
+
await ensureCcgDir();
|
|
223
|
+
const content = stringify(config);
|
|
224
|
+
await fs.writeFile(CONFIG_FILE, content, "utf-8");
|
|
225
|
+
}
|
|
226
|
+
function createDefaultConfig(options) {
|
|
227
|
+
return {
|
|
228
|
+
general: {
|
|
229
|
+
version: version,
|
|
230
|
+
language: options.language,
|
|
231
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
232
|
+
},
|
|
233
|
+
routing: options.routing,
|
|
234
|
+
workflows: {
|
|
235
|
+
installed: options.installedWorkflows
|
|
236
|
+
},
|
|
237
|
+
paths: {
|
|
238
|
+
commands: join(homedir(), ".claude", "commands", "ccg"),
|
|
239
|
+
prompts: join(CCG_DIR, "prompts"),
|
|
240
|
+
// v1.4.0: 移到配置目录
|
|
241
|
+
backup: join(CCG_DIR, "backup")
|
|
242
|
+
},
|
|
243
|
+
mcp: {
|
|
244
|
+
provider: options.mcpProvider || "fast-context",
|
|
245
|
+
setup_url: "https://augmentcode.com/"
|
|
246
|
+
},
|
|
247
|
+
performance: {
|
|
248
|
+
liteMode: options.liteMode || false,
|
|
249
|
+
skipImpeccable: options.skipImpeccable || false
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function createDefaultRouting() {
|
|
254
|
+
return {
|
|
255
|
+
frontend: {
|
|
256
|
+
models: ["antigravity"],
|
|
257
|
+
primary: "antigravity",
|
|
258
|
+
strategy: "parallel"
|
|
259
|
+
},
|
|
260
|
+
backend: {
|
|
261
|
+
models: ["codex"],
|
|
262
|
+
primary: "codex",
|
|
263
|
+
strategy: "parallel"
|
|
264
|
+
},
|
|
265
|
+
review: {
|
|
266
|
+
models: ["codex", "antigravity"],
|
|
267
|
+
strategy: "parallel"
|
|
268
|
+
},
|
|
269
|
+
mode: "smart"
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
200
273
|
const DEFAULT_ALLOWED_TOOLS = ["Read"];
|
|
201
274
|
const NAME_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
202
275
|
const TOOL_NAME_RE = /^[A-Z][A-Za-z0-9]*$/;
|
|
@@ -1100,6 +1173,12 @@ async function installCodexMode() {
|
|
|
1100
1173
|
try {
|
|
1101
1174
|
const codexHome = join(homedir(), ".codex");
|
|
1102
1175
|
await fs.ensureDir(join(codexHome, "agents"));
|
|
1176
|
+
const config = await readCcgConfig();
|
|
1177
|
+
const injectOpts = {
|
|
1178
|
+
routing: config?.routing,
|
|
1179
|
+
liteMode: config?.performance?.liteMode || false,
|
|
1180
|
+
mcpProvider: config?.mcp?.provider || "skip"
|
|
1181
|
+
};
|
|
1103
1182
|
const configSrc = join(codexTemplateDir, "config.toml");
|
|
1104
1183
|
const configDest = join(codexHome, "config.toml");
|
|
1105
1184
|
if (await fs.pathExists(configSrc) && !await fs.pathExists(configDest)) {
|
|
@@ -1111,16 +1190,32 @@ async function installCodexMode() {
|
|
|
1111
1190
|
}
|
|
1112
1191
|
const agentsMdSrc = join(codexTemplateDir, "AGENTS.md");
|
|
1113
1192
|
if (await fs.pathExists(agentsMdSrc)) {
|
|
1114
|
-
await fs.
|
|
1193
|
+
let content = await fs.readFile(agentsMdSrc, "utf-8");
|
|
1194
|
+
content = injectConfigVariables(content, injectOpts);
|
|
1195
|
+
await fs.writeFile(join(codexHome, "AGENTS.md"), content, "utf-8");
|
|
1115
1196
|
}
|
|
1116
1197
|
const hooksSrc = join(codexTemplateDir, "hooks");
|
|
1117
1198
|
if (await fs.pathExists(hooksSrc)) {
|
|
1118
|
-
|
|
1119
|
-
await fs.
|
|
1199
|
+
const hooksDest = join(codexHome, "hooks");
|
|
1200
|
+
await fs.ensureDir(hooksDest);
|
|
1201
|
+
for (const file of await fs.readdir(hooksSrc)) {
|
|
1202
|
+
const srcFile = join(hooksSrc, file);
|
|
1203
|
+
const destFile = join(hooksDest, file);
|
|
1204
|
+
if (file.endsWith(".py")) {
|
|
1205
|
+
let content = await fs.readFile(srcFile, "utf-8");
|
|
1206
|
+
content = injectConfigVariables(content, injectOpts);
|
|
1207
|
+
await fs.writeFile(destFile, content, "utf-8");
|
|
1208
|
+
} else {
|
|
1209
|
+
await fs.copy(srcFile, destFile, { overwrite: true });
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1120
1212
|
}
|
|
1121
1213
|
const hooksJsonSrc = join(codexTemplateDir, "hooks.json");
|
|
1122
1214
|
if (await fs.pathExists(hooksJsonSrc)) {
|
|
1123
|
-
await fs.
|
|
1215
|
+
let content = await fs.readFile(hooksJsonSrc, "utf-8");
|
|
1216
|
+
const absHome = homedir().replace(/\\/g, "/");
|
|
1217
|
+
content = content.replace(/~\//g, `${absHome}/`);
|
|
1218
|
+
await fs.writeFile(join(codexHome, "hooks.json"), content, "utf-8");
|
|
1124
1219
|
}
|
|
1125
1220
|
return {
|
|
1126
1221
|
success: true,
|
|
@@ -2888,79 +2983,6 @@ async function changeLanguage(lang) {
|
|
|
2888
2983
|
await i18n.changeLanguage(lang);
|
|
2889
2984
|
}
|
|
2890
2985
|
|
|
2891
|
-
const CCG_DIR = join(homedir(), ".claude", ".ccg");
|
|
2892
|
-
const CONFIG_FILE = join(CCG_DIR, "config.toml");
|
|
2893
|
-
function getCcgDir() {
|
|
2894
|
-
return CCG_DIR;
|
|
2895
|
-
}
|
|
2896
|
-
function getConfigPath() {
|
|
2897
|
-
return CONFIG_FILE;
|
|
2898
|
-
}
|
|
2899
|
-
async function ensureCcgDir() {
|
|
2900
|
-
await fs.ensureDir(CCG_DIR);
|
|
2901
|
-
}
|
|
2902
|
-
async function readCcgConfig() {
|
|
2903
|
-
try {
|
|
2904
|
-
if (await fs.pathExists(CONFIG_FILE)) {
|
|
2905
|
-
const content = await fs.readFile(CONFIG_FILE, "utf-8");
|
|
2906
|
-
return parse(content);
|
|
2907
|
-
}
|
|
2908
|
-
} catch {
|
|
2909
|
-
}
|
|
2910
|
-
return null;
|
|
2911
|
-
}
|
|
2912
|
-
async function writeCcgConfig(config) {
|
|
2913
|
-
await ensureCcgDir();
|
|
2914
|
-
const content = stringify(config);
|
|
2915
|
-
await fs.writeFile(CONFIG_FILE, content, "utf-8");
|
|
2916
|
-
}
|
|
2917
|
-
function createDefaultConfig(options) {
|
|
2918
|
-
return {
|
|
2919
|
-
general: {
|
|
2920
|
-
version: version,
|
|
2921
|
-
language: options.language,
|
|
2922
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2923
|
-
},
|
|
2924
|
-
routing: options.routing,
|
|
2925
|
-
workflows: {
|
|
2926
|
-
installed: options.installedWorkflows
|
|
2927
|
-
},
|
|
2928
|
-
paths: {
|
|
2929
|
-
commands: join(homedir(), ".claude", "commands", "ccg"),
|
|
2930
|
-
prompts: join(CCG_DIR, "prompts"),
|
|
2931
|
-
// v1.4.0: 移到配置目录
|
|
2932
|
-
backup: join(CCG_DIR, "backup")
|
|
2933
|
-
},
|
|
2934
|
-
mcp: {
|
|
2935
|
-
provider: options.mcpProvider || "fast-context",
|
|
2936
|
-
setup_url: "https://augmentcode.com/"
|
|
2937
|
-
},
|
|
2938
|
-
performance: {
|
|
2939
|
-
liteMode: options.liteMode || false,
|
|
2940
|
-
skipImpeccable: options.skipImpeccable || false
|
|
2941
|
-
}
|
|
2942
|
-
};
|
|
2943
|
-
}
|
|
2944
|
-
function createDefaultRouting() {
|
|
2945
|
-
return {
|
|
2946
|
-
frontend: {
|
|
2947
|
-
models: ["antigravity"],
|
|
2948
|
-
primary: "antigravity",
|
|
2949
|
-
strategy: "parallel"
|
|
2950
|
-
},
|
|
2951
|
-
backend: {
|
|
2952
|
-
models: ["codex"],
|
|
2953
|
-
primary: "codex",
|
|
2954
|
-
strategy: "parallel"
|
|
2955
|
-
},
|
|
2956
|
-
review: {
|
|
2957
|
-
models: ["codex", "antigravity"],
|
|
2958
|
-
strategy: "parallel"
|
|
2959
|
-
},
|
|
2960
|
-
mode: "smart"
|
|
2961
|
-
};
|
|
2962
|
-
}
|
|
2963
|
-
|
|
2964
2986
|
async function migrateToV1_4_0() {
|
|
2965
2987
|
const result = {
|
|
2966
2988
|
success: true,
|
package/package.json
CHANGED
|
@@ -23,12 +23,12 @@ You are the **lead orchestrator** of a multi-model development team. You think,
|
|
|
23
23
|
|
|
24
24
|
```
|
|
25
25
|
S + 低风险 → 直接写,跑测试,完事
|
|
26
|
-
S + 高风险 → 直接写,但必须调双模型审查(
|
|
27
|
-
M + 任意 → 双模型并行分析(
|
|
26
|
+
S + 高风险 → 直接写,但必须调双模型审查({{FRONTEND_PRIMARY}} + Claude)
|
|
27
|
+
M + 任意 → 双模型并行分析({{FRONTEND_PRIMARY}} + Claude 都调),再写,完成后双模型审查
|
|
28
28
|
L+ + 任意 → 双模型并行分析,制定 plan.md,spawn 子 Agent 并行写,双模型审查
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
**⛔ M 以上复杂度,分析和审查都必须是双模型(
|
|
31
|
+
**⛔ M 以上复杂度,分析和审查都必须是双模型({{FRONTEND_PRIMARY}} + Claude 都调)。**
|
|
32
32
|
这是 CCG 的核心价值——两个模型从不同角度分析同一个问题,交叉验证,弥补单模型盲区。只调一个模型 = 浪费了多模型协作的意义。
|
|
33
33
|
|
|
34
34
|
**不确定时,选高一级。** 宁可多做一步分析,不可写完才发现方向错了。
|
|
@@ -127,13 +127,13 @@ ls .ccg/spec/ 2>/dev/null
|
|
|
127
127
|
### ⛔ 默认调用方式:双模型并行(M+ 复杂度必须用这个)
|
|
128
128
|
|
|
129
129
|
```bash
|
|
130
|
-
~/.claude/bin/codeagent-wrapper --progress --backend
|
|
131
|
-
ROLE_FILE: ~/.claude/.ccg/prompts/
|
|
130
|
+
~/.claude/bin/codeagent-wrapper --progress --backend {{FRONTEND_PRIMARY}} - "$(pwd)" <<'FRONTEND_EOF'
|
|
131
|
+
ROLE_FILE: ~/.claude/.ccg/prompts/{{FRONTEND_PRIMARY}}/$ROLE.md
|
|
132
132
|
<TASK>
|
|
133
133
|
{任务描述 + 上下文}
|
|
134
134
|
</TASK>
|
|
135
135
|
OUTPUT: {期望输出格式}
|
|
136
|
-
|
|
136
|
+
FRONTEND_EOF
|
|
137
137
|
&
|
|
138
138
|
~/.claude/bin/codeagent-wrapper --progress --backend claude - "$(pwd)" <<'CLAUDE_EOF'
|
|
139
139
|
ROLE_FILE: ~/.claude/.ccg/prompts/claude/$ROLE.md
|
|
@@ -150,10 +150,10 @@ wait
|
|
|
150
150
|
|
|
151
151
|
### 单模型调用(仅 S 复杂度可用)
|
|
152
152
|
|
|
153
|
-
####
|
|
153
|
+
#### {{FRONTEND_PRIMARY}}(前端/UI 分析)
|
|
154
154
|
```bash
|
|
155
|
-
~/.claude/bin/codeagent-wrapper --progress --backend
|
|
156
|
-
ROLE_FILE: ~/.claude/.ccg/prompts/
|
|
155
|
+
~/.claude/bin/codeagent-wrapper --progress --backend {{FRONTEND_PRIMARY}} - "$(pwd)" <<'EOF'
|
|
156
|
+
ROLE_FILE: ~/.claude/.ccg/prompts/{{FRONTEND_PRIMARY}}/$ROLE.md
|
|
157
157
|
<TASK>
|
|
158
158
|
{任务描述 + 上下文}
|
|
159
159
|
</TASK>
|
|
@@ -279,7 +279,7 @@ Critical 问题 → spawn 修复代理。Warning → 视情况修复。
|
|
|
279
279
|
- [ ] git diff 只有预期变更
|
|
280
280
|
|
|
281
281
|
### 何时调外部模型审查
|
|
282
|
-
- 变更 >30 行 → **必须**调双模型审查(
|
|
282
|
+
- 变更 >30 行 → **必须**调双模型审查({{FRONTEND_PRIMARY}} + Claude 都调)
|
|
283
283
|
- 变更 ≤30 行但涉及 auth/数据库/加密 → **必须**调双模型审查
|
|
284
284
|
- 变更 ≤30 行且低风险 → 可以只调一个
|
|
285
285
|
|
|
@@ -287,8 +287,8 @@ Critical 问题 → spawn 修复代理。Warning → 视情况修复。
|
|
|
287
287
|
|
|
288
288
|
```bash
|
|
289
289
|
# 必须并行调用两个模型审查 git diff
|
|
290
|
-
~/.claude/bin/codeagent-wrapper --progress --backend
|
|
291
|
-
ROLE_FILE: ~/.claude/.ccg/prompts/
|
|
290
|
+
~/.claude/bin/codeagent-wrapper --progress --backend {{FRONTEND_PRIMARY}} - "$(pwd)" <<'EOF'
|
|
291
|
+
ROLE_FILE: ~/.claude/.ccg/prompts/{{FRONTEND_PRIMARY}}/reviewer.md
|
|
292
292
|
<TASK>审查以下代码变更:$(git diff)</TASK>
|
|
293
293
|
OUTPUT: Critical/Warning/Info 分级审查报告
|
|
294
294
|
EOF
|
|
@@ -127,8 +127,8 @@ def build_guidance(task, progress, root):
|
|
|
127
127
|
if phase == "analysis":
|
|
128
128
|
if complexity in ("M", "L", "XL"):
|
|
129
129
|
parts.append("")
|
|
130
|
-
parts.append(f"⛔ {complexity} complexity: you MUST call BOTH
|
|
131
|
-
parts.append("Use the dual-model parallel template in AGENTS.md: --backend
|
|
130
|
+
parts.append(f"⛔ {complexity} complexity: you MUST call BOTH the frontend model AND Claude for parallel analysis before coding.")
|
|
131
|
+
parts.append("Use the dual-model parallel template in AGENTS.md: --backend {{FRONTEND_PRIMARY}} & --backend claude with & + wait.")
|
|
132
132
|
|
|
133
133
|
# Phase: implementation — coding in progress
|
|
134
134
|
elif phase == "implementation":
|
|
@@ -146,12 +146,12 @@ def build_guidance(task, progress, root):
|
|
|
146
146
|
# Big changes without review
|
|
147
147
|
if progress["changed_lines"] > 30 and phase != "review":
|
|
148
148
|
parts.append("")
|
|
149
|
-
parts.append(f"⚠️ {progress['changed_lines']} lines changed. When done coding, you MUST call BOTH
|
|
149
|
+
parts.append(f"⚠️ {progress['changed_lines']} lines changed. When done coding, you MUST call BOTH the frontend model AND Claude for dual-model review. Not just one — both.")
|
|
150
150
|
|
|
151
151
|
# Review phase: enforce dual model
|
|
152
152
|
if phase == "review":
|
|
153
153
|
parts.append("")
|
|
154
|
-
parts.append("⛔ Review phase: call BOTH
|
|
154
|
+
parts.append("⛔ Review phase: call BOTH the frontend model (--backend {{FRONTEND_PRIMARY}}) AND Claude (--backend claude) with reviewer role. Two models, not one.")
|
|
155
155
|
|
|
156
156
|
# High-risk files detected
|
|
157
157
|
if progress["high_risk_files"] and phase not in ("review", "completed"):
|