ccg-workflow 1.7.80 → 1.7.82
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 +2 -1
- package/README.zh-CN.md +3 -2
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.mjs +1 -1
- package/dist/shared/{ccg-workflow.DKLTZQCk.mjs → ccg-workflow.C7wxgYrc.mjs} +333 -10
- package/package.json +1 -1
- package/templates/commands/commit.md +20 -13
- package/templates/commands/context.md +4 -2
package/README.md
CHANGED
|
@@ -243,6 +243,7 @@ npx ccg-workflow menu # Select "Configure MCP"
|
|
|
243
243
|
|
|
244
244
|
**Code retrieval** (choose one):
|
|
245
245
|
- **ace-tool** (recommended) — Code search via `search_context`. [Official](https://augmentcode.com/) | [Third-party proxy](https://acemcp.heroman.wtf/)
|
|
246
|
+
- **fast-context** (recommended) — Windsurf Fast Context, AI-powered search without full-repo indexing. Requires Windsurf account
|
|
246
247
|
- **ContextWeaver** (alternative) — Local hybrid search, requires SiliconFlow API Key (free)
|
|
247
248
|
|
|
248
249
|
**Optional tools**:
|
|
@@ -353,4 +354,4 @@ MIT
|
|
|
353
354
|
|
|
354
355
|
---
|
|
355
356
|
|
|
356
|
-
v1.7.
|
|
357
|
+
v1.7.82 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [Contributing](./CONTRIBUTING.md)
|
package/README.zh-CN.md
CHANGED
|
@@ -241,8 +241,9 @@ npx ccg-workflow menu # 选择「安装 Claude Code」
|
|
|
241
241
|
npx ccg-workflow menu # 选择「配置 MCP」
|
|
242
242
|
```
|
|
243
243
|
|
|
244
|
-
|
|
244
|
+
**代码检索**(多选一):
|
|
245
245
|
- **ace-tool**(推荐)— 代码检索 `search_context` 可用。[官方](https://augmentcode.com/) | [第三方中转](https://acemcp.heroman.wtf/)
|
|
246
|
+
- **fast-context**(推荐)— Windsurf Fast Context,AI 驱动搜索,无需全量索引。需 Windsurf 账号
|
|
246
247
|
- **ContextWeaver**(备选)— 本地混合搜索,需要硅基流动 API Key(免费)
|
|
247
248
|
|
|
248
249
|
**辅助工具**(可选):
|
|
@@ -353,4 +354,4 @@ MIT
|
|
|
353
354
|
|
|
354
355
|
---
|
|
355
356
|
|
|
356
|
-
v1.7.
|
|
357
|
+
v1.7.82 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [参与贡献](./CONTRIBUTING.md)
|
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 { 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.
|
|
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.C7wxgYrc.mjs';
|
|
5
5
|
import 'inquirer';
|
|
6
6
|
import 'node:child_process';
|
|
7
7
|
import 'node:util';
|
package/dist/index.d.mts
CHANGED
|
@@ -93,6 +93,10 @@ interface AceToolConfig {
|
|
|
93
93
|
baseUrl: string;
|
|
94
94
|
token: string;
|
|
95
95
|
}
|
|
96
|
+
interface FastContextConfig {
|
|
97
|
+
apiKey?: string;
|
|
98
|
+
includeSnippets?: boolean;
|
|
99
|
+
}
|
|
96
100
|
|
|
97
101
|
declare function init(options?: InitOptions): Promise<void>;
|
|
98
102
|
|
|
@@ -226,4 +230,4 @@ declare function checkForUpdates(): Promise<{
|
|
|
226
230
|
}>;
|
|
227
231
|
|
|
228
232
|
export { changeLanguage, checkForUpdates, compareVersions, createDefaultConfig, createDefaultRouting, getCcgDir, getConfigPath, getCurrentVersion, getLatestVersion, getWorkflowById, getWorkflowConfigs, i18n, init, initI18n, installAceTool, installAceToolRs, installWorkflows, migrateToV1_4_0, needsMigration, readCcgConfig, showMainMenu, uninstallAceTool, uninstallWorkflows, update, writeCcgConfig };
|
|
229
|
-
export type { AceToolConfig, CcgConfig, CliOptions, CollaborationMode, InitOptions, InstallResult, ModelRouting, ModelType, RoutingStrategy, SupportedLang, WorkflowConfig };
|
|
233
|
+
export type { AceToolConfig, CcgConfig, CliOptions, CollaborationMode, FastContextConfig, InitOptions, InstallResult, ModelRouting, ModelType, RoutingStrategy, SupportedLang, WorkflowConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -93,6 +93,10 @@ interface AceToolConfig {
|
|
|
93
93
|
baseUrl: string;
|
|
94
94
|
token: string;
|
|
95
95
|
}
|
|
96
|
+
interface FastContextConfig {
|
|
97
|
+
apiKey?: string;
|
|
98
|
+
includeSnippets?: boolean;
|
|
99
|
+
}
|
|
96
100
|
|
|
97
101
|
declare function init(options?: InitOptions): Promise<void>;
|
|
98
102
|
|
|
@@ -226,4 +230,4 @@ declare function checkForUpdates(): Promise<{
|
|
|
226
230
|
}>;
|
|
227
231
|
|
|
228
232
|
export { changeLanguage, checkForUpdates, compareVersions, createDefaultConfig, createDefaultRouting, getCcgDir, getConfigPath, getCurrentVersion, getLatestVersion, getWorkflowById, getWorkflowConfigs, i18n, init, initI18n, installAceTool, installAceToolRs, installWorkflows, migrateToV1_4_0, needsMigration, readCcgConfig, showMainMenu, uninstallAceTool, uninstallWorkflows, update, writeCcgConfig };
|
|
229
|
-
export type { AceToolConfig, CcgConfig, CliOptions, CollaborationMode, InitOptions, InstallResult, ModelRouting, ModelType, RoutingStrategy, SupportedLang, WorkflowConfig };
|
|
233
|
+
export type { AceToolConfig, CcgConfig, CliOptions, CollaborationMode, FastContextConfig, InitOptions, InstallResult, ModelRouting, ModelType, RoutingStrategy, SupportedLang, WorkflowConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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.
|
|
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.C7wxgYrc.mjs';
|
|
2
2
|
import 'ansis';
|
|
3
3
|
import 'inquirer';
|
|
4
4
|
import 'node:child_process';
|
|
@@ -10,7 +10,7 @@ import { parse, stringify } from 'smol-toml';
|
|
|
10
10
|
import i18next from 'i18next';
|
|
11
11
|
import ora from 'ora';
|
|
12
12
|
|
|
13
|
-
const version = "1.7.
|
|
13
|
+
const version = "1.7.82";
|
|
14
14
|
|
|
15
15
|
function isWindows() {
|
|
16
16
|
return process.platform === "win32";
|
|
@@ -563,6 +563,9 @@ function injectConfigVariables(content, config) {
|
|
|
563
563
|
} else if (mcpProvider === "contextweaver") {
|
|
564
564
|
processed = processed.replace(/\{\{MCP_SEARCH_TOOL\}\}/g, "mcp__contextweaver__codebase-retrieval");
|
|
565
565
|
processed = processed.replace(/\{\{MCP_SEARCH_PARAM\}\}/g, "information_request");
|
|
566
|
+
} else if (mcpProvider === "fast-context") {
|
|
567
|
+
processed = processed.replace(/\{\{MCP_SEARCH_TOOL\}\}/g, "mcp__fast-context__fast_context_search");
|
|
568
|
+
processed = processed.replace(/\{\{MCP_SEARCH_PARAM\}\}/g, "query");
|
|
566
569
|
} else {
|
|
567
570
|
processed = processed.replace(/\{\{MCP_SEARCH_TOOL\}\}/g, "mcp__ace-tool__search_context");
|
|
568
571
|
processed = processed.replace(/\{\{MCP_SEARCH_PARAM\}\}/g, "query");
|
|
@@ -1134,6 +1137,161 @@ async function uninstallContextWeaver() {
|
|
|
1134
1137
|
};
|
|
1135
1138
|
}
|
|
1136
1139
|
}
|
|
1140
|
+
async function installFastContext(config) {
|
|
1141
|
+
const { apiKey, includeSnippets } = config;
|
|
1142
|
+
try {
|
|
1143
|
+
let existingConfig = await readClaudeCodeConfig();
|
|
1144
|
+
if (!existingConfig) {
|
|
1145
|
+
existingConfig = { mcpServers: {} };
|
|
1146
|
+
}
|
|
1147
|
+
if (existingConfig.mcpServers && Object.keys(existingConfig.mcpServers).length > 0) {
|
|
1148
|
+
const backupPath = await backupClaudeCodeConfig();
|
|
1149
|
+
if (backupPath) {
|
|
1150
|
+
console.log(` \u2713 Backup created: ${backupPath}`);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
const env = {};
|
|
1154
|
+
if (apiKey) {
|
|
1155
|
+
env.WINDSURF_API_KEY = apiKey;
|
|
1156
|
+
}
|
|
1157
|
+
if (includeSnippets) {
|
|
1158
|
+
env.FC_INCLUDE_SNIPPETS = "true";
|
|
1159
|
+
}
|
|
1160
|
+
const fastContextConfig = buildMcpServerConfig({
|
|
1161
|
+
type: "stdio",
|
|
1162
|
+
command: "npx",
|
|
1163
|
+
args: ["-y", "--prefer-online", "fast-context-mcp@latest"],
|
|
1164
|
+
...Object.keys(env).length > 0 ? { env } : {}
|
|
1165
|
+
});
|
|
1166
|
+
let mergedConfig = mergeMcpServers(existingConfig, {
|
|
1167
|
+
"fast-context": fastContextConfig
|
|
1168
|
+
});
|
|
1169
|
+
if (isWindows()) {
|
|
1170
|
+
mergedConfig = fixWindowsMcpConfig(mergedConfig);
|
|
1171
|
+
console.log(" \u2713 Applied Windows MCP configuration fixes");
|
|
1172
|
+
}
|
|
1173
|
+
await writeClaudeCodeConfig(mergedConfig);
|
|
1174
|
+
return {
|
|
1175
|
+
success: true,
|
|
1176
|
+
message: isWindows() ? "fast-context MCP configured successfully with Windows compatibility" : "fast-context MCP configured successfully",
|
|
1177
|
+
configPath: join(homedir(), ".claude.json")
|
|
1178
|
+
};
|
|
1179
|
+
} catch (error) {
|
|
1180
|
+
return {
|
|
1181
|
+
success: false,
|
|
1182
|
+
message: `Failed to configure fast-context: ${error}`
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
async function uninstallFastContext() {
|
|
1187
|
+
try {
|
|
1188
|
+
const existingConfig = await readClaudeCodeConfig();
|
|
1189
|
+
if (existingConfig?.mcpServers?.["fast-context"]) {
|
|
1190
|
+
delete existingConfig.mcpServers["fast-context"];
|
|
1191
|
+
await writeClaudeCodeConfig(existingConfig);
|
|
1192
|
+
}
|
|
1193
|
+
return {
|
|
1194
|
+
success: true,
|
|
1195
|
+
message: "fast-context MCP uninstalled successfully"
|
|
1196
|
+
};
|
|
1197
|
+
} catch (error) {
|
|
1198
|
+
return {
|
|
1199
|
+
success: false,
|
|
1200
|
+
message: `Failed to uninstall fast-context: ${error}`
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
const FAST_CONTEXT_PROMPT = `# fast-context MCP \u5DE5\u5177\u4F7F\u7528\u6307\u5357
|
|
1205
|
+
|
|
1206
|
+
## \u6838\u5FC3\u539F\u5219
|
|
1207
|
+
|
|
1208
|
+
**\u4EFB\u4F55\u9700\u8981\u7406\u89E3\u4EE3\u7801\u4E0A\u4E0B\u6587\u3001\u63A2\u7D22\u6027\u641C\u7D22\u3001\u6216\u81EA\u7136\u8BED\u8A00\u5B9A\u4F4D\u4EE3\u7801\u7684\u573A\u666F\uFF0C\u4F18\u5148\u4F7F\u7528 \`mcp__fast-context__fast_context_search\`**
|
|
1209
|
+
|
|
1210
|
+
## \u4F7F\u7528\u573A\u666F
|
|
1211
|
+
|
|
1212
|
+
### \u5FC5\u987B\u7528 fast_context_search
|
|
1213
|
+
- \u63A2\u7D22\u6027\u641C\u7D22\uFF08\u4E0D\u786E\u5B9A\u4EE3\u7801\u5728\u54EA\u4E2A\u6587\u4EF6/\u76EE\u5F55\uFF09
|
|
1214
|
+
- \u7528\u81EA\u7136\u8BED\u8A00\u63CF\u8FF0\u8981\u627E\u7684\u903B\u8F91\uFF08\u5982"\u90E8\u7F72\u6D41\u7A0B"\u3001"\u4E8B\u4EF6\u5904\u7406"\uFF09
|
|
1215
|
+
- \u7406\u89E3\u4E1A\u52A1\u903B\u8F91\u548C\u8C03\u7528\u94FE\u8DEF
|
|
1216
|
+
- \u8DE8\u6A21\u5757\u3001\u8DE8\u5C42\u7EA7\u67E5\u8BE2\uFF08\u5982\u4ECE router \u8FFD\u5230 service \u5230 model\uFF09
|
|
1217
|
+
- \u65B0\u4EFB\u52A1\u5F00\u59CB\u524D\u7684\u4EE3\u7801\u8C03\u7814\u548C\u67B6\u6784\u7406\u89E3
|
|
1218
|
+
- \u4E2D\u6587\u8BED\u4E49\u641C\u7D22\uFF08\u5DE5\u5177\u652F\u6301\u4E2D\u82F1\u6587\u53CC\u8BED\u67E5\u8BE2\uFF09
|
|
1219
|
+
|
|
1220
|
+
### \u6839\u636E\u9700\u6C42\u9009\u62E9\u5DE5\u5177
|
|
1221
|
+
- **\u8BED\u4E49\u641C\u7D22 / \u4E0D\u786E\u5B9A\u4F4D\u7F6E** \u2192 \`mcp__fast-context__fast_context_search\`\uFF08\u8FD4\u56DE\u6587\u4EF6+\u884C\u53F7\u8303\u56F4+grep\u5173\u952E\u8BCD\u5EFA\u8BAE\uFF09
|
|
1222
|
+
- **\u7CBE\u786E\u5173\u952E\u8BCD\u641C\u7D22** \u2192 Grep
|
|
1223
|
+
- **\u5DF2\u77E5\u6587\u4EF6\u8DEF\u5F84\uFF0C\u67E5\u770B\u5185\u5BB9** \u2192 Read
|
|
1224
|
+
- **\u6309\u6587\u4EF6\u540D\u6A21\u5F0F\u67E5\u627E** \u2192 Glob
|
|
1225
|
+
- **\u7F16\u8F91\u5DF2\u6709\u6587\u4EF6** \u2192 Edit
|
|
1226
|
+
|
|
1227
|
+
### fast_context_search \u53C2\u6570\u8C03\u4F18
|
|
1228
|
+
- \`tree_depth=1, max_turns=1\` \u2014 \u5FEB\u901F\u7C97\u67E5\uFF0C\u9002\u5408\u5C0F\u9879\u76EE\u6216\u521D\u6B65\u5B9A\u4F4D
|
|
1229
|
+
- \`tree_depth=3, max_turns=3\`\uFF08\u9ED8\u8BA4\uFF09\u2014 \u5E73\u8861\u7CBE\u5EA6\u4E0E\u901F\u5EA6\uFF0C\u9002\u5408\u5927\u591A\u6570\u573A\u666F
|
|
1230
|
+
- \`max_turns=5\` \u2014 \u6DF1\u5EA6\u641C\u7D22\uFF0C\u9002\u5408\u590D\u6742\u8C03\u7528\u94FE\u8FFD\u8E2A
|
|
1231
|
+
- \`project_path\` \u2014 \u6307\u5B9A\u641C\u7D22\u7684\u9879\u76EE\u6839\u76EE\u5F55\uFF0C\u9ED8\u8BA4\u4E3A\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55
|
|
1232
|
+
|
|
1233
|
+
### \u7981\u6B62\u884C\u4E3A
|
|
1234
|
+
- \u274C \u731C\u6D4B\u4EE3\u7801\u4F4D\u7F6E\uFF08"\u5E94\u8BE5\u5728 service/firmware \u91CC"\uFF09
|
|
1235
|
+
- \u274C \u8DF3\u8FC7\u641C\u7D22\u76F4\u63A5\u56DE\u7B54\uFF08"\u6839\u636E\u6846\u67B6\u60EF\u4F8B\uFF0C\u5E94\u8BE5\u662F..."\uFF09
|
|
1236
|
+
- \u274C \u9047\u5230\u641C\u7D22\u5C31\u542F\u52A8\u5B50\u4EE3\u7406\uFF08fast-context + Grep \u7EC4\u5408\u4F18\u5148\uFF09
|
|
1237
|
+
|
|
1238
|
+
### \u5B50\u4EE3\u7406\u4F7F\u7528\u6761\u4EF6
|
|
1239
|
+
\u4EC5\u5F53\u9700\u8981\u8BFB\u53D6 10+ \u6587\u4EF6\u4EA4\u53C9\u6BD4\u5BF9\u3001\u6216\u591A\u8F6E\u641C\u7D22\u4F1A\u6491\u7206\u4E0A\u4E0B\u6587\u65F6\uFF0C\u624D\u542F\u52A8\u5B50\u4EE3\u7406\u3002
|
|
1240
|
+
`;
|
|
1241
|
+
const FC_MARKER_START = "<!-- CCG-FAST-CONTEXT-START -->";
|
|
1242
|
+
const FC_MARKER_END = "<!-- CCG-FAST-CONTEXT-END -->";
|
|
1243
|
+
async function writeFastContextPrompt() {
|
|
1244
|
+
const markerStart = FC_MARKER_START;
|
|
1245
|
+
const markerEnd = FC_MARKER_END;
|
|
1246
|
+
const markedBlock = `
|
|
1247
|
+
${markerStart}
|
|
1248
|
+
${FAST_CONTEXT_PROMPT}
|
|
1249
|
+
${markerEnd}
|
|
1250
|
+
`;
|
|
1251
|
+
const markerRegex = new RegExp(
|
|
1252
|
+
`\\n?${markerStart.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\s\\S]*?${markerEnd.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\n?`
|
|
1253
|
+
);
|
|
1254
|
+
async function injectIntoFile(filePath) {
|
|
1255
|
+
const dir = dirname(filePath);
|
|
1256
|
+
await fs.ensureDir(dir);
|
|
1257
|
+
if (await fs.pathExists(filePath)) {
|
|
1258
|
+
let content = await fs.readFile(filePath, "utf-8");
|
|
1259
|
+
if (content.includes(markerStart)) {
|
|
1260
|
+
content = content.replace(markerRegex, markedBlock);
|
|
1261
|
+
} else {
|
|
1262
|
+
content += markedBlock;
|
|
1263
|
+
}
|
|
1264
|
+
await fs.writeFile(filePath, content, "utf-8");
|
|
1265
|
+
} else {
|
|
1266
|
+
await fs.writeFile(filePath, markedBlock.trim() + "\n", "utf-8");
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
const rulesDir = join(homedir(), ".claude", "rules");
|
|
1270
|
+
await fs.ensureDir(rulesDir);
|
|
1271
|
+
await fs.writeFile(join(rulesDir, "ccg-fast-context.md"), FAST_CONTEXT_PROMPT, "utf-8");
|
|
1272
|
+
await injectIntoFile(join(homedir(), ".codex", "AGENTS.md"));
|
|
1273
|
+
await injectIntoFile(join(homedir(), ".gemini", "GEMINI.md"));
|
|
1274
|
+
}
|
|
1275
|
+
async function removeFastContextPrompt() {
|
|
1276
|
+
const markerRegex = new RegExp(
|
|
1277
|
+
`\\n?${FC_MARKER_START.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\s\\S]*?${FC_MARKER_END.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\n?`
|
|
1278
|
+
);
|
|
1279
|
+
async function removeFromFile(filePath) {
|
|
1280
|
+
if (await fs.pathExists(filePath)) {
|
|
1281
|
+
let content = await fs.readFile(filePath, "utf-8");
|
|
1282
|
+
if (content.includes(FC_MARKER_START)) {
|
|
1283
|
+
content = content.replace(markerRegex, "");
|
|
1284
|
+
await fs.writeFile(filePath, content, "utf-8");
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
const rulePath = join(homedir(), ".claude", "rules", "ccg-fast-context.md");
|
|
1289
|
+
if (await fs.pathExists(rulePath)) {
|
|
1290
|
+
await fs.remove(rulePath);
|
|
1291
|
+
}
|
|
1292
|
+
await removeFromFile(join(homedir(), ".codex", "AGENTS.md"));
|
|
1293
|
+
await removeFromFile(join(homedir(), ".gemini", "GEMINI.md"));
|
|
1294
|
+
}
|
|
1137
1295
|
async function installMcpServer(id, command, args, env = {}) {
|
|
1138
1296
|
try {
|
|
1139
1297
|
await backupClaudeCodeConfig();
|
|
@@ -1166,7 +1324,8 @@ const CCG_MCP_IDS = /* @__PURE__ */ new Set([
|
|
|
1166
1324
|
"context7",
|
|
1167
1325
|
"ace-tool",
|
|
1168
1326
|
"ace-tool-rs",
|
|
1169
|
-
"contextweaver"
|
|
1327
|
+
"contextweaver",
|
|
1328
|
+
"fast-context"
|
|
1170
1329
|
]);
|
|
1171
1330
|
async function syncMcpToCodex() {
|
|
1172
1331
|
const synced = [];
|
|
@@ -1237,6 +1396,50 @@ async function syncMcpToCodex() {
|
|
|
1237
1396
|
};
|
|
1238
1397
|
}
|
|
1239
1398
|
}
|
|
1399
|
+
async function syncMcpToGemini() {
|
|
1400
|
+
const synced = [];
|
|
1401
|
+
const removed = [];
|
|
1402
|
+
try {
|
|
1403
|
+
const claudeConfig = await readClaudeCodeConfig();
|
|
1404
|
+
const claudeMcpServers = claudeConfig?.mcpServers || {};
|
|
1405
|
+
const serversToSync = {};
|
|
1406
|
+
for (const [id, config] of Object.entries(claudeMcpServers)) {
|
|
1407
|
+
if (CCG_MCP_IDS.has(id) && config) {
|
|
1408
|
+
serversToSync[id] = config;
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
const geminiDir = join(homedir(), ".gemini");
|
|
1412
|
+
const geminiSettingsPath = join(geminiDir, "settings.json");
|
|
1413
|
+
await fs.ensureDir(geminiDir);
|
|
1414
|
+
let geminiSettings = {};
|
|
1415
|
+
if (await fs.pathExists(geminiSettingsPath)) {
|
|
1416
|
+
geminiSettings = await fs.readJSON(geminiSettingsPath);
|
|
1417
|
+
}
|
|
1418
|
+
if (!geminiSettings.mcpServers) {
|
|
1419
|
+
geminiSettings.mcpServers = {};
|
|
1420
|
+
}
|
|
1421
|
+
for (const [id, claudeServer] of Object.entries(serversToSync)) {
|
|
1422
|
+
geminiSettings.mcpServers[id] = claudeServer;
|
|
1423
|
+
synced.push(id);
|
|
1424
|
+
}
|
|
1425
|
+
for (const id of CCG_MCP_IDS) {
|
|
1426
|
+
if (!serversToSync[id] && geminiSettings.mcpServers[id]) {
|
|
1427
|
+
delete geminiSettings.mcpServers[id];
|
|
1428
|
+
removed.push(id);
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
if (synced.length === 0 && removed.length === 0) {
|
|
1432
|
+
return { success: true, message: "No CCG MCP servers to sync to Gemini", synced: [], removed: [] };
|
|
1433
|
+
}
|
|
1434
|
+
await fs.writeJSON(geminiSettingsPath, geminiSettings, { spaces: 2 });
|
|
1435
|
+
const parts = [];
|
|
1436
|
+
if (synced.length > 0) parts.push(`synced: ${synced.join(", ")}`);
|
|
1437
|
+
if (removed.length > 0) parts.push(`removed: ${removed.join(", ")}`);
|
|
1438
|
+
return { success: true, message: `Gemini MCP mirror complete (${parts.join("; ")})`, synced, removed };
|
|
1439
|
+
} catch (error) {
|
|
1440
|
+
return { success: false, message: `Failed to sync MCP to Gemini: ${error}`, synced, removed };
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1240
1443
|
|
|
1241
1444
|
async function configMcp() {
|
|
1242
1445
|
console.log();
|
|
@@ -1247,7 +1450,7 @@ async function configMcp() {
|
|
|
1247
1450
|
name: "action",
|
|
1248
1451
|
message: "\u9009\u62E9\u64CD\u4F5C",
|
|
1249
1452
|
choices: [
|
|
1250
|
-
{ name: `${ansis.green("\u279C")} \u4EE3\u7801\u68C0\u7D22 MCP ${ansis.gray("(ace-tool / ContextWeaver)")}`, value: "code-retrieval" },
|
|
1453
|
+
{ name: `${ansis.green("\u279C")} \u4EE3\u7801\u68C0\u7D22 MCP ${ansis.gray("(ace-tool / fast-context / ContextWeaver)")}`, value: "code-retrieval" },
|
|
1251
1454
|
{ name: `${ansis.green("\u279C")} \u8054\u7F51\u641C\u7D22 MCP ${ansis.gray("(grok-search\uFF0C\u6BD4\u5185\u7F6E\u8054\u7F51\u66F4\u597D\u7528)")}`, value: "grok-search" },
|
|
1252
1455
|
{ name: `${ansis.blue("\u279C")} \u8F85\u52A9\u5DE5\u5177 MCP ${ansis.gray("(context7 / Playwright / exa...)")}`, value: "auxiliary" },
|
|
1253
1456
|
{ name: `${ansis.red("\u2715")} \u5378\u8F7D MCP`, value: "uninstall" },
|
|
@@ -1276,6 +1479,7 @@ async function handleCodeRetrieval() {
|
|
|
1276
1479
|
choices: [
|
|
1277
1480
|
{ name: `ace-tool ${ansis.green("(\u63A8\u8350)")} ${ansis.gray("- \u4EE3\u7801\u68C0\u7D22\uFF08enhance_prompt \u5DF2\u4E0D\u53EF\u7528\uFF09")}`, value: "ace-tool" },
|
|
1278
1481
|
{ name: `ace-tool-rs ${ansis.green("(\u63A8\u8350)")} ${ansis.gray("- Rust \u7248\u672C")}`, value: "ace-tool-rs" },
|
|
1482
|
+
{ name: `fast-context ${ansis.green("(\u63A8\u8350)")} ${ansis.gray("- Windsurf Fast Context\uFF08\u514D\u8D39/\u4F4E\u6210\u672C\uFF09")}`, value: "fast-context" },
|
|
1279
1483
|
{ name: `ContextWeaver ${ansis.gray("- \u672C\u5730\u6DF7\u5408\u641C\u7D22\uFF08\u9700\u7845\u57FA\u6D41\u52A8 API Key\uFF09")}`, value: "contextweaver" },
|
|
1280
1484
|
new inquirer.Separator(),
|
|
1281
1485
|
{ name: `${ansis.gray("\u8FD4\u56DE")}`, value: "cancel" }
|
|
@@ -1285,6 +1489,8 @@ async function handleCodeRetrieval() {
|
|
|
1285
1489
|
return;
|
|
1286
1490
|
if (tool === "contextweaver") {
|
|
1287
1491
|
await handleInstallContextWeaver();
|
|
1492
|
+
} else if (tool === "fast-context") {
|
|
1493
|
+
await handleInstallFastContext();
|
|
1288
1494
|
} else {
|
|
1289
1495
|
await handleInstallAceTool(tool === "ace-tool-rs");
|
|
1290
1496
|
}
|
|
@@ -1340,6 +1546,39 @@ async function handleInstallContextWeaver() {
|
|
|
1340
1546
|
console.log(ansis.red(`\u2717 ContextWeaver MCP \u914D\u7F6E\u5931\u8D25: ${result.message}`));
|
|
1341
1547
|
}
|
|
1342
1548
|
}
|
|
1549
|
+
async function handleInstallFastContext() {
|
|
1550
|
+
console.log();
|
|
1551
|
+
console.log(ansis.cyan("\u{1F4D6} Fast Context (Windsurf Fast Context)\uFF1A"));
|
|
1552
|
+
console.log(` ${ansis.gray("\u2022")} \u9700\u8981 Windsurf \u8D26\u53F7\u7684 API Key`);
|
|
1553
|
+
console.log(` ${ansis.gray("\u2022")} \u672C\u5730\u88C5\u8FC7 Windsurf \u5E76\u767B\u5F55 \u2192 Key \u53EF\u81EA\u52A8\u63D0\u53D6\uFF0C\u4E5F\u53EF\u624B\u52A8\u586B\u5165`);
|
|
1554
|
+
console.log(` ${ansis.gray("\u2022")} Key \u83B7\u53D6\uFF1A\u5B89\u88C5 Windsurf \u2192 \u767B\u5F55 \u2192 \u4ECE\u672C\u5730 SQLite \u63D0\u53D6 apiKey`);
|
|
1555
|
+
console.log(` ${ansis.gray("\u2022")} \u8F7B\u91CF\u6A21\u5F0F\u8FD4\u56DE\u6587\u4EF6\u8DEF\u5F84+\u884C\u8303\u56F4\uFF0C\u5B8C\u6574\u6A21\u5F0F\u989D\u5916\u8FD4\u56DE\u4EE3\u7801\u7247\u6BB5`);
|
|
1556
|
+
console.log();
|
|
1557
|
+
const answers = await inquirer.prompt([
|
|
1558
|
+
{ type: "input", name: "apiKey", message: `WINDSURF_API_KEY ${ansis.gray("(\u672C\u5730\u88C5\u4E86 Windsurf \u53EF\u7559\u7A7A\u81EA\u52A8\u63D0\u53D6)")}` },
|
|
1559
|
+
{
|
|
1560
|
+
type: "confirm",
|
|
1561
|
+
name: "includeSnippets",
|
|
1562
|
+
message: `\u8FD4\u56DE\u5B8C\u6574\u4EE3\u7801\u7247\u6BB5\uFF1F${ansis.gray("(FC_INCLUDE_SNIPPETS\uFF0C\u8F93\u51FA ~40KB\uFF0C\u5426\u5219\u4EC5\u8DEF\u5F84+\u884C\u53F7 ~2KB)")}`,
|
|
1563
|
+
default: false
|
|
1564
|
+
}
|
|
1565
|
+
]);
|
|
1566
|
+
console.log();
|
|
1567
|
+
console.log(ansis.yellow("\u23F3 \u6B63\u5728\u914D\u7F6E fast-context MCP..."));
|
|
1568
|
+
const result = await installFastContext({
|
|
1569
|
+
apiKey: answers.apiKey?.trim() || void 0,
|
|
1570
|
+
includeSnippets: answers.includeSnippets
|
|
1571
|
+
});
|
|
1572
|
+
console.log();
|
|
1573
|
+
if (result.success) {
|
|
1574
|
+
await writeFastContextPrompt();
|
|
1575
|
+
console.log(ansis.green("\u2713 fast-context MCP \u914D\u7F6E\u6210\u529F\uFF01"));
|
|
1576
|
+
console.log(ansis.green("\u2713 \u641C\u7D22\u63D0\u793A\u8BCD\u5DF2\u5199\u5165 ~/.claude/rules/ + ~/.codex/AGENTS.md + ~/.gemini/GEMINI.md"));
|
|
1577
|
+
console.log(ansis.gray(" \u91CD\u542F Claude Code CLI \u4F7F\u914D\u7F6E\u751F\u6548"));
|
|
1578
|
+
} else {
|
|
1579
|
+
console.log(ansis.red(`\u2717 fast-context MCP \u914D\u7F6E\u5931\u8D25: ${result.message}`));
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1343
1582
|
const GROK_SEARCH_PROMPT = `## 0. Language and Format Standards
|
|
1344
1583
|
|
|
1345
1584
|
- **Interaction Language**: Tools and models must interact exclusively in **English**; user outputs must be in **Chinese**.
|
|
@@ -1485,6 +1724,7 @@ async function handleUninstall() {
|
|
|
1485
1724
|
console.log();
|
|
1486
1725
|
const allMcps = [
|
|
1487
1726
|
{ name: "ace-tool", value: "ace-tool" },
|
|
1727
|
+
{ name: "fast-context", value: "fast-context" },
|
|
1488
1728
|
{ name: "ContextWeaver", value: "contextweaver" },
|
|
1489
1729
|
{ name: "grok-search", value: "grok-search" },
|
|
1490
1730
|
...AUXILIARY_MCPS.map((m) => ({ name: m.name, value: m.id }))
|
|
@@ -1505,6 +1745,9 @@ async function handleUninstall() {
|
|
|
1505
1745
|
let result;
|
|
1506
1746
|
if (target === "ace-tool") {
|
|
1507
1747
|
result = await uninstallAceTool();
|
|
1748
|
+
} else if (target === "fast-context") {
|
|
1749
|
+
result = await uninstallFastContext();
|
|
1750
|
+
await removeFastContextPrompt();
|
|
1508
1751
|
} else if (target === "contextweaver") {
|
|
1509
1752
|
result = await uninstallContextWeaver();
|
|
1510
1753
|
} else {
|
|
@@ -2714,6 +2957,8 @@ async function init(options = {}) {
|
|
|
2714
2957
|
let aceToolBaseUrl = "";
|
|
2715
2958
|
let aceToolToken = "";
|
|
2716
2959
|
let contextWeaverApiKey = "";
|
|
2960
|
+
let fastContextApiKey = "";
|
|
2961
|
+
let fastContextIncludeSnippets = false;
|
|
2717
2962
|
if (options.skipMcp) {
|
|
2718
2963
|
mcpProvider = "skip";
|
|
2719
2964
|
} else if (!options.skipPrompt) {
|
|
@@ -2726,11 +2971,15 @@ async function init(options = {}) {
|
|
|
2726
2971
|
message: i18n.t("init:mcp.selectProvider"),
|
|
2727
2972
|
choices: [
|
|
2728
2973
|
{
|
|
2729
|
-
name: `
|
|
2974
|
+
name: `fast-context ${ansis.green(`(${i18n.t("common:info")})`)} ${ansis.gray("- Windsurf Fast Context, AI \u9A71\u52A8\u641C\u7D22")}`,
|
|
2975
|
+
value: "fast-context"
|
|
2976
|
+
},
|
|
2977
|
+
{
|
|
2978
|
+
name: `ace-tool ${ansis.gray("- search_context (enhance_prompt N/A)")}`,
|
|
2730
2979
|
value: "ace-tool"
|
|
2731
2980
|
},
|
|
2732
2981
|
{
|
|
2733
|
-
name: `ace-tool-rs ${ansis.
|
|
2982
|
+
name: `ace-tool-rs ${ansis.gray("(Rust) - search_context")}`,
|
|
2734
2983
|
value: "ace-tool-rs"
|
|
2735
2984
|
},
|
|
2736
2985
|
{
|
|
@@ -2742,7 +2991,7 @@ async function init(options = {}) {
|
|
|
2742
2991
|
value: "skip"
|
|
2743
2992
|
}
|
|
2744
2993
|
],
|
|
2745
|
-
default: "
|
|
2994
|
+
default: "fast-context"
|
|
2746
2995
|
}]);
|
|
2747
2996
|
mcpProvider = selectedMcp;
|
|
2748
2997
|
if (selectedMcp === "ace-tool" || selectedMcp === "ace-tool-rs") {
|
|
@@ -2792,6 +3041,46 @@ async function init(options = {}) {
|
|
|
2792
3041
|
console.log(ansis.gray(` \u2022 ${i18n.t("init:mcp.configLater", { cmd: ansis.cyan("npx ccg config mcp") })}`));
|
|
2793
3042
|
console.log();
|
|
2794
3043
|
}
|
|
3044
|
+
} else if (selectedMcp === "fast-context") {
|
|
3045
|
+
console.log();
|
|
3046
|
+
console.log(ansis.cyan.bold(` \u{1F527} Fast Context MCP`));
|
|
3047
|
+
console.log(ansis.gray(` Windsurf Fast Context \u2014 AI \u9A71\u52A8\u4EE3\u7801\u641C\u7D22\uFF0C\u65E0\u9700\u5168\u91CF\u7D22\u5F15`));
|
|
3048
|
+
console.log();
|
|
3049
|
+
const { skipKey } = await inquirer.prompt([{
|
|
3050
|
+
type: "confirm",
|
|
3051
|
+
name: "skipKey",
|
|
3052
|
+
message: "\u8DF3\u8FC7 API Key \u914D\u7F6E\uFF1F\uFF08\u672C\u5730\u88C5\u4E86 Windsurf \u5E76\u767B\u5F55\u53EF\u81EA\u52A8\u63D0\u53D6\uFF09",
|
|
3053
|
+
default: false
|
|
3054
|
+
}]);
|
|
3055
|
+
if (!skipKey) {
|
|
3056
|
+
console.log();
|
|
3057
|
+
console.log(ansis.cyan(` \u{1F4D6} \u83B7\u53D6 WINDSURF_API_KEY\uFF1A`));
|
|
3058
|
+
console.log();
|
|
3059
|
+
console.log(` ${ansis.gray("\u2022")} \u5B89\u88C5 Windsurf \u7F16\u8F91\u5668 \u2192 \u767B\u5F55 \u2192 Key \u81EA\u52A8\u5B58\u5165\u672C\u5730 SQLite`);
|
|
3060
|
+
console.log(` ${ansis.gray("\u2022")} \u4E5F\u53EF\u624B\u52A8\u4ECE SQLite \u63D0\u53D6\uFF08AI \u53EF\u8C03\u7528 extract_windsurf_key \u5DE5\u5177\uFF09`);
|
|
3061
|
+
console.log();
|
|
3062
|
+
const fcAnswers = await inquirer.prompt([
|
|
3063
|
+
{
|
|
3064
|
+
type: "input",
|
|
3065
|
+
name: "apiKey",
|
|
3066
|
+
message: `WINDSURF_API_KEY ${ansis.gray("(\u7559\u7A7A\u5219\u542F\u52A8\u65F6\u81EA\u52A8\u63D0\u53D6)")}`,
|
|
3067
|
+
default: ""
|
|
3068
|
+
},
|
|
3069
|
+
{
|
|
3070
|
+
type: "confirm",
|
|
3071
|
+
name: "includeSnippets",
|
|
3072
|
+
message: `\u8FD4\u56DE\u5B8C\u6574\u4EE3\u7801\u7247\u6BB5\uFF1F${ansis.gray("(\u5426\u5219\u4EC5\u8DEF\u5F84+\u884C\u53F7\uFF0C\u66F4\u7701 token)")}`,
|
|
3073
|
+
default: false
|
|
3074
|
+
}
|
|
3075
|
+
]);
|
|
3076
|
+
fastContextApiKey = fcAnswers.apiKey?.trim() || "";
|
|
3077
|
+
fastContextIncludeSnippets = fcAnswers.includeSnippets;
|
|
3078
|
+
} else {
|
|
3079
|
+
console.log();
|
|
3080
|
+
console.log(ansis.yellow(` \u2139\uFE0F API Key \u5DF2\u8DF3\u8FC7`));
|
|
3081
|
+
console.log(ansis.gray(` \u2022 fast-context MCP \u5C06\u4E0D\u5E26 Key \u5B89\u88C5\uFF08\u542F\u52A8\u65F6\u81EA\u52A8\u4ECE\u672C\u5730 Windsurf \u63D0\u53D6\uFF09`));
|
|
3082
|
+
console.log();
|
|
3083
|
+
}
|
|
2795
3084
|
} else if (selectedMcp === "contextweaver") {
|
|
2796
3085
|
console.log();
|
|
2797
3086
|
console.log(ansis.cyan.bold(` \u{1F527} ContextWeaver MCP`));
|
|
@@ -2941,7 +3230,13 @@ async function init(options = {}) {
|
|
|
2941
3230
|
console.log();
|
|
2942
3231
|
console.log(` ${ansis.cyan(i18n.t("init:summary.modelRouting"))} ${ansis.green("Gemini")} (Frontend) + ${ansis.blue("Codex")} (Backend)`);
|
|
2943
3232
|
console.log(` ${ansis.cyan(i18n.t("init:summary.commandCount"))} ${ansis.yellow(selectedWorkflows.length.toString())}`);
|
|
2944
|
-
|
|
3233
|
+
const mcpSummary = (() => {
|
|
3234
|
+
if (mcpProvider === "fast-context") return ansis.green("fast-context");
|
|
3235
|
+
if (mcpProvider === "ace-tool" || mcpProvider === "ace-tool-rs") return aceToolToken ? ansis.green(mcpProvider) : ansis.yellow(`${mcpProvider} (${i18n.t("init:summary.pendingConfig")})`);
|
|
3236
|
+
if (mcpProvider === "contextweaver") return contextWeaverApiKey ? ansis.green("contextweaver") : ansis.yellow(`contextweaver (${i18n.t("init:summary.pendingConfig")})`);
|
|
3237
|
+
return ansis.gray(i18n.t("init:summary.skipped"));
|
|
3238
|
+
})();
|
|
3239
|
+
console.log(` ${ansis.cyan(i18n.t("init:summary.mcpTool"))} ${mcpSummary}`);
|
|
2945
3240
|
console.log(` ${ansis.cyan(i18n.t("init:summary.webUI"))} ${liteMode ? ansis.gray(i18n.t("init:summary.disabled")) : ansis.green(i18n.t("init:summary.enabled"))}`);
|
|
2946
3241
|
if (wantGrokSearch) {
|
|
2947
3242
|
console.log(` ${ansis.cyan("grok-search")} ${tavilyKey ? ansis.green("\u2713") : ansis.yellow(`(${i18n.t("init:summary.pendingConfig")})`)}`);
|
|
@@ -3021,6 +3316,22 @@ async function init(options = {}) {
|
|
|
3021
3316
|
spinner.warn(ansis.yellow(mcpProvider === "ace-tool-rs" ? i18n.t("init:aceToolRs.failed") : i18n.t("init:aceTool.failed")));
|
|
3022
3317
|
console.log(ansis.gray(` ${aceResult.message}`));
|
|
3023
3318
|
}
|
|
3319
|
+
} else if (mcpProvider === "fast-context") {
|
|
3320
|
+
spinner.text = "Configuring fast-context MCP...";
|
|
3321
|
+
const fcResult = await installFastContext({
|
|
3322
|
+
apiKey: fastContextApiKey || void 0,
|
|
3323
|
+
includeSnippets: fastContextIncludeSnippets
|
|
3324
|
+
});
|
|
3325
|
+
if (fcResult.success) {
|
|
3326
|
+
spinner.succeed(ansis.green(i18n.t("init:installSuccess")));
|
|
3327
|
+
console.log();
|
|
3328
|
+
console.log(` ${ansis.green("\u2713")} fast-context MCP ${ansis.gray(`\u2192 ${fcResult.configPath}`)}`);
|
|
3329
|
+
await writeFastContextPrompt();
|
|
3330
|
+
console.log(` ${ansis.green("\u2713")} \u641C\u7D22\u63D0\u793A\u8BCD ${ansis.gray("\u2192 ~/.claude/rules/ + ~/.codex/AGENTS.md + ~/.gemini/GEMINI.md")}`);
|
|
3331
|
+
} else {
|
|
3332
|
+
spinner.warn(ansis.yellow("fast-context MCP \u914D\u7F6E\u5931\u8D25"));
|
|
3333
|
+
console.log(ansis.gray(` ${fcResult.message}`));
|
|
3334
|
+
}
|
|
3024
3335
|
} else if (mcpProvider === "contextweaver" && contextWeaverApiKey) {
|
|
3025
3336
|
spinner.text = i18n.t("init:mcp.cwConfiguring");
|
|
3026
3337
|
const cwResult = await installContextWeaver({
|
|
@@ -3133,6 +3444,15 @@ async function init(options = {}) {
|
|
|
3133
3444
|
console.log(` ${ansis.yellow("\u26A0")} Codex MCP sync failed`);
|
|
3134
3445
|
console.log(ansis.gray(` ${codexSyncResult.message}`));
|
|
3135
3446
|
}
|
|
3447
|
+
const geminiSyncResult = await syncMcpToGemini();
|
|
3448
|
+
if (geminiSyncResult.success && geminiSyncResult.synced.length > 0) {
|
|
3449
|
+
console.log();
|
|
3450
|
+
console.log(` ${ansis.green("\u2713")} Gemini MCP sync: ${geminiSyncResult.synced.join(", ")} ${ansis.gray("\u2192 ~/.gemini/settings.json")}`);
|
|
3451
|
+
} else if (!geminiSyncResult.success) {
|
|
3452
|
+
console.log();
|
|
3453
|
+
console.log(` ${ansis.yellow("\u26A0")} Gemini MCP sync failed`);
|
|
3454
|
+
console.log(ansis.gray(` ${geminiSyncResult.message}`));
|
|
3455
|
+
}
|
|
3136
3456
|
}
|
|
3137
3457
|
if (hookMethod === "hook") {
|
|
3138
3458
|
const hasJq = await checkJqAvailable();
|
|
@@ -3275,13 +3595,16 @@ ${exportCommand}
|
|
|
3275
3595
|
console.log();
|
|
3276
3596
|
console.log(ansis.gray(` ${i18n.t("init:mcp.mcpOptionsHint")}`));
|
|
3277
3597
|
console.log();
|
|
3278
|
-
console.log(` ${ansis.green("1.")} ${ansis.cyan("
|
|
3598
|
+
console.log(` ${ansis.green("1.")} ${ansis.cyan("fast-context")} ${ansis.yellow("(\u63A8\u8350)")}: Windsurf Fast Context`);
|
|
3599
|
+
console.log(` ${ansis.gray("AI \u9A71\u52A8\u4EE3\u7801\u641C\u7D22\uFF0C\u9700 Windsurf \u8D26\u53F7\uFF0C\u514D\u8D39/\u4F4E\u6210\u672C")}`);
|
|
3600
|
+
console.log();
|
|
3601
|
+
console.log(` ${ansis.green("2.")} ${ansis.cyan("ace-tool / ace-tool-rs")}: ${ansis.underline("https://augmentcode.com/")}`);
|
|
3279
3602
|
console.log(` ${ansis.gray(i18n.t("init:mcp.promptEnhancement"))}`);
|
|
3280
3603
|
console.log();
|
|
3281
|
-
console.log(` ${ansis.green("
|
|
3604
|
+
console.log(` ${ansis.green("3.")} ${ansis.cyan("ace-tool " + i18n.t("init:mcp.proxyService"))} ${ansis.yellow(`(${i18n.t("init:mcp.noSignup")})`)}: ${ansis.underline("https://acemcp.heroman.wtf/")}`);
|
|
3282
3605
|
console.log(` ${ansis.gray(i18n.t("init:mcp.communityProxy"))}`);
|
|
3283
3606
|
console.log();
|
|
3284
|
-
console.log(` ${ansis.green("
|
|
3607
|
+
console.log(` ${ansis.green("4.")} ${ansis.cyan("ContextWeaver")} ${ansis.yellow(`(${i18n.t("init:mcp.freeQuota")})`)}: ${ansis.underline("https://siliconflow.cn/")}`);
|
|
3285
3608
|
console.log(` ${ansis.gray(i18n.t("init:mcp.localEngine"))}`);
|
|
3286
3609
|
console.log();
|
|
3287
3610
|
}
|
package/package.json
CHANGED
|
@@ -68,27 +68,34 @@ description: '智能 Git 提交:分析改动生成 Conventional Commit 信息
|
|
|
68
68
|
|
|
69
69
|
**语言**:根据最近 50 次提交判断中文/英文
|
|
70
70
|
|
|
71
|
-
### 📦 阶段 5:Context
|
|
71
|
+
### 📦 阶段 5:Context 自动归档(若 .context/ 存在)
|
|
72
72
|
|
|
73
73
|
`[模式:上下文归档]`
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
**前置判断**:
|
|
76
|
+
- 若 `.context/` 目录不存在 → 在提交成功后输出提示:`💡 建议执行 /ccg:context init 启用决策追踪`,不阻断
|
|
77
|
+
- 若 `.context/` 存在 → 执行以下步骤
|
|
78
|
+
|
|
79
|
+
**从 git diff 自动生成 ContextEntry**:
|
|
76
80
|
|
|
77
81
|
1. 获取当前分支名:`git branch --show-current`
|
|
78
|
-
2.
|
|
79
|
-
3.
|
|
80
|
-
-
|
|
81
|
-
-
|
|
82
|
-
-
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
2. 获取暂存区变更:`git diff --cached --stat` + `git diff --cached`(完整 diff)
|
|
83
|
+
3. **分析 diff 生成 ContextEntry**:
|
|
84
|
+
- `summary`:从阶段 4 生成的 commit message 中取首行
|
|
85
|
+
- `decisions`:分析 diff 中的关键变更(新增依赖、架构调整、接口变更、配置修改),推断决策理由
|
|
86
|
+
- `bugs`:若 commit type 为 `fix`,从 diff 中提取 bug 症状、根因、修复方式
|
|
87
|
+
- `changes.files`:从 `git diff --cached --name-only` 提取
|
|
88
|
+
- `tests`:若变更包含测试文件,记录测试相关信息
|
|
89
|
+
4. **合并 session.log**(可选):若 `.context/current/branches/<branch>/session.log` 存在且非空,将其中的手动记录合并到 decisions/bugs 中,然后清空 session.log
|
|
90
|
+
5. **脱敏**:扫描 token/key/password/secret 模式 → 替换为 `[REDACTED]`
|
|
91
|
+
6. **追加**:将 ContextEntry 作为一行追加到 `.context/history/commits.jsonl`
|
|
92
|
+
7. **重生成**:更新 `.context/history/commits.md` 人类视图
|
|
93
|
+
8. **暂存**:`git add .context/history/`
|
|
94
|
+
9. **Trailer**:在 commit message 中添加 `Context-Id: <uuid>` trailer
|
|
88
95
|
|
|
89
96
|
**ContextEntry 格式**参见 `/ccg:context` 命令中的 Schema 定义。
|
|
90
97
|
|
|
91
|
-
|
|
98
|
+
**失败降级**:若归档过程出错,不阻断提交。写入 minimal ContextEntry(仅 summary + files),继续正常提交。
|
|
92
99
|
|
|
93
100
|
### ✅ 阶段 6:执行提交
|
|
94
101
|
|
|
@@ -17,12 +17,14 @@ description: '项目上下文管理:初始化 .context 目录、记录决策
|
|
|
17
17
|
| 子命令 | 说明 |
|
|
18
18
|
|--------|------|
|
|
19
19
|
| `init` | 初始化 `.context/` 目录结构 |
|
|
20
|
-
| `log <message>` |
|
|
20
|
+
| `log <message>` | (可选)手动追加备注到 session.log,commit 时会合并 |
|
|
21
21
|
| `show` | 查看当前分支的 session.log |
|
|
22
|
-
| `compress` | 压缩 session.log → uncommit.md |
|
|
22
|
+
| `compress` | 压缩 session.log → uncommit.md(手动预览用) |
|
|
23
23
|
| `history` | 查看 history/commits.md |
|
|
24
24
|
| `squash <ids...>` | 合并多条 history 记录(配合 git squash) |
|
|
25
25
|
|
|
26
|
+
> **核心用法**:`init` 一次,之后只管开发。`/ccg:commit` 提交时自动从 git diff 分析决策并归档到 history/。`log` 仅在你想手动补充备注时使用。
|
|
27
|
+
|
|
26
28
|
---
|
|
27
29
|
|
|
28
30
|
## 执行工作流
|