ccg-workflow 1.7.81 → 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 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.81 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [Contributing](./CONTRIBUTING.md)
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.81 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [参与贡献](./CONTRIBUTING.md)
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.DLkUGirT.mjs';
4
+ import { z as diagnoseMcpConfig, A as isWindows, B as readClaudeCodeConfig, C as fixWindowsMcpConfig, D as writeClaudeCodeConfig, r as readCcgConfig, b as initI18n, a as i18n, s as showMainMenu, i as init, E as configMcp, F as version } from './shared/ccg-workflow.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.DLkUGirT.mjs';
1
+ export { c as changeLanguage, x as checkForUpdates, y as compareVersions, d as createDefaultConfig, e as createDefaultRouting, g as getCcgDir, f as getConfigPath, t as getCurrentVersion, v as getLatestVersion, j as getWorkflowById, h as getWorkflowConfigs, a as i18n, i as init, b as initI18n, l as installAceTool, m as installAceToolRs, k as installWorkflows, p as migrateToV1_4_0, q as needsMigration, r as readCcgConfig, s as showMainMenu, o as uninstallAceTool, n as uninstallWorkflows, u as update, w as writeCcgConfig } from './shared/ccg-workflow.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.81";
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: `ace-tool ${ansis.green(`(${i18n.t("common:info")})`)} ${ansis.gray("- search_context (enhance_prompt N/A)")}`,
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.green(`(${i18n.t("common:info")})`)} ${ansis.gray("(Rust) - search_context")}`,
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: "ace-tool"
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
- console.log(` ${ansis.cyan(i18n.t("init:summary.mcpTool"))} ${mcpProvider === "ace-tool" || mcpProvider === "ace-tool-rs" ? aceToolToken ? ansis.green(mcpProvider) : ansis.yellow(`${mcpProvider} (${i18n.t("init:summary.pendingConfig")})`) : mcpProvider === "contextweaver" ? contextWeaverApiKey ? ansis.green("contextweaver") : ansis.yellow(`contextweaver (${i18n.t("init:summary.pendingConfig")})`) : ansis.gray(i18n.t("init:summary.skipped"))}`);
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("ace-tool / ace-tool-rs")}: ${ansis.underline("https://augmentcode.com/")}`);
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("2.")} ${ansis.cyan("ace-tool " + i18n.t("init:mcp.proxyService"))} ${ansis.yellow(`(${i18n.t("init:mcp.noSignup")})`)}: ${ansis.underline("https://acemcp.heroman.wtf/")}`);
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("3.")} ${ansis.cyan("ContextWeaver")} ${ansis.yellow(`(${i18n.t("init:mcp.freeQuota")})`)}: ${ansis.underline("https://siliconflow.cn/")}`);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccg-workflow",
3
- "version": "1.7.81",
3
+ "version": "1.7.82",
4
4
  "description": "Claude + Codex + Gemini multi-model collaboration system - smart routing development workflow",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.17.1",