ccg-workflow 1.7.69 → 1.7.70
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 -4
- package/README.zh-CN.md +4 -4
- package/dist/cli.mjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/shared/{ccg-workflow.3chn8_4c.mjs → ccg-workflow.BPzva2Np.mjs} +220 -110
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -178,8 +178,8 @@ scoop install jq
|
|
|
178
178
|
### MCP Configuration
|
|
179
179
|
|
|
180
180
|
Code retrieval MCP (choose one):
|
|
181
|
-
- **
|
|
182
|
-
- **
|
|
181
|
+
- **ace-tool** (recommended) - Code search via `search_context` (note: `enhance_prompt` is no longer available). [Official](https://augmentcode.com/) | [Third-party proxy (recommended)](https://acemcp.heroman.wtf/)
|
|
182
|
+
- **ContextWeaver** (alternative) - Local hybrid search, requires SiliconFlow API Key (free)
|
|
183
183
|
|
|
184
184
|
Optional MCP tools:
|
|
185
185
|
- **Context7** - Latest library documentation
|
|
@@ -225,7 +225,7 @@ npm uninstall -g ccg-workflow # npm global users need this extra step
|
|
|
225
225
|
|
|
226
226
|
### 1. How to auto-authorize codeagent-wrapper without manual approval?
|
|
227
227
|
|
|
228
|
-
CCG automatically installs the Hook during setup (v1.7.
|
|
228
|
+
CCG automatically installs the Hook during setup (v1.7.70+). If you installed an older version, add this to `~/.claude/settings.json`:
|
|
229
229
|
|
|
230
230
|
```json
|
|
231
231
|
{
|
|
@@ -288,4 +288,4 @@ MIT
|
|
|
288
288
|
|
|
289
289
|
---
|
|
290
290
|
|
|
291
|
-
v1.7.
|
|
291
|
+
v1.7.70 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues)
|
package/README.zh-CN.md
CHANGED
|
@@ -180,8 +180,8 @@ scoop install jq
|
|
|
180
180
|
### MCP 配置
|
|
181
181
|
|
|
182
182
|
代码检索 MCP(二选一):
|
|
183
|
-
- **
|
|
184
|
-
- **
|
|
183
|
+
- **ace-tool**(推荐)- 代码检索 `search_context` 可用(注:`enhance_prompt` 已不可用)。[官方](https://augmentcode.com/) | [第三方中转(推荐)](https://acemcp.heroman.wtf/)
|
|
184
|
+
- **ContextWeaver**(备选)- 本地混合搜索,需要硅基流动 API Key(免费)
|
|
185
185
|
|
|
186
186
|
辅助工具 MCP(可选):
|
|
187
187
|
- **Context7** - 获取最新库文档
|
|
@@ -227,7 +227,7 @@ npm uninstall -g ccg-workflow # npm 全局用户需额外执行
|
|
|
227
227
|
|
|
228
228
|
### 1. 如何让 codeagent-wrapper 无需手动同意即可运行?
|
|
229
229
|
|
|
230
|
-
v1.7.
|
|
230
|
+
v1.7.70+ 安装时会自动写入 Hook。如果你是旧版本用户,可手动在 `~/.claude/settings.json` 中添加:
|
|
231
231
|
|
|
232
232
|
```json
|
|
233
233
|
{
|
|
@@ -290,4 +290,4 @@ MIT
|
|
|
290
290
|
|
|
291
291
|
---
|
|
292
292
|
|
|
293
|
-
v1.7.
|
|
293
|
+
v1.7.70 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues)
|
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.BPzva2Np.mjs';
|
|
5
5
|
import 'inquirer';
|
|
6
6
|
import 'node:child_process';
|
|
7
7
|
import 'node:util';
|
|
@@ -9,9 +9,9 @@ import 'node:os';
|
|
|
9
9
|
import 'node:url';
|
|
10
10
|
import 'pathe';
|
|
11
11
|
import 'fs-extra';
|
|
12
|
+
import 'smol-toml';
|
|
12
13
|
import 'i18next';
|
|
13
14
|
import 'ora';
|
|
14
|
-
import 'smol-toml';
|
|
15
15
|
|
|
16
16
|
async function diagnoseMcp() {
|
|
17
17
|
console.log();
|
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.BPzva2Np.mjs';
|
|
2
2
|
import 'ansis';
|
|
3
3
|
import 'inquirer';
|
|
4
4
|
import 'node:child_process';
|
|
@@ -7,6 +7,6 @@ import 'node:os';
|
|
|
7
7
|
import 'node:url';
|
|
8
8
|
import 'pathe';
|
|
9
9
|
import 'fs-extra';
|
|
10
|
+
import 'smol-toml';
|
|
10
11
|
import 'i18next';
|
|
11
12
|
import 'ora';
|
|
12
|
-
import 'smol-toml';
|
|
@@ -6,11 +6,11 @@ import { homedir } from 'node:os';
|
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
7
|
import { join, dirname } from 'pathe';
|
|
8
8
|
import fs from 'fs-extra';
|
|
9
|
+
import { parse, stringify } from 'smol-toml';
|
|
9
10
|
import i18next from 'i18next';
|
|
10
11
|
import ora from 'ora';
|
|
11
|
-
import { parse, stringify } from 'smol-toml';
|
|
12
12
|
|
|
13
|
-
const version = "1.7.
|
|
13
|
+
const version = "1.7.70";
|
|
14
14
|
|
|
15
15
|
function isWindows() {
|
|
16
16
|
return process.platform === "win32";
|
|
@@ -1064,9 +1064,9 @@ async function handleCodeRetrieval() {
|
|
|
1064
1064
|
name: "tool",
|
|
1065
1065
|
message: "\u9009\u62E9\u4EE3\u7801\u68C0\u7D22\u5DE5\u5177",
|
|
1066
1066
|
choices: [
|
|
1067
|
-
{ name: `
|
|
1068
|
-
{ name: `ace-tool ${ansis.
|
|
1069
|
-
{ name: `
|
|
1067
|
+
{ name: `ace-tool ${ansis.green("(\u63A8\u8350)")} ${ansis.gray("- \u4EE3\u7801\u68C0\u7D22\uFF08enhance_prompt \u5DF2\u4E0D\u53EF\u7528\uFF09")}`, value: "ace-tool" },
|
|
1068
|
+
{ name: `ace-tool-rs ${ansis.green("(\u63A8\u8350)")} ${ansis.gray("- Rust \u7248\u672C")}`, value: "ace-tool-rs" },
|
|
1069
|
+
{ name: `ContextWeaver ${ansis.gray("- \u672C\u5730\u6DF7\u5408\u641C\u7D22\uFF08\u9700\u7845\u57FA\u6D41\u52A8 API Key\uFF09")}`, value: "contextweaver" },
|
|
1070
1070
|
new inquirer.Separator(),
|
|
1071
1071
|
{ name: `${ansis.gray("\u8FD4\u56DE")}`, value: "cancel" }
|
|
1072
1072
|
]
|
|
@@ -1084,7 +1084,8 @@ async function handleInstallAceTool(isRs) {
|
|
|
1084
1084
|
console.log();
|
|
1085
1085
|
console.log(ansis.cyan(`\u{1F4D6} \u83B7\u53D6 ${toolName} \u8BBF\u95EE\u65B9\u5F0F\uFF1A`));
|
|
1086
1086
|
console.log(` ${ansis.gray("\u2022")} ${ansis.cyan("\u5B98\u65B9\u670D\u52A1")}: ${ansis.underline("https://augmentcode.com/")}`);
|
|
1087
|
-
console.log(` ${ansis.gray("\u2022")} ${ansis.cyan("\u4E2D\u8F6C
|
|
1087
|
+
console.log(` ${ansis.gray("\u2022")} ${ansis.cyan("\u7B2C\u4E09\u65B9\u4E2D\u8F6C")} ${ansis.green("(\u63A8\u8350)")}: ${ansis.underline("https://acemcp.heroman.wtf/")}`);
|
|
1088
|
+
console.log(` ${ansis.gray("\u26A0")} ${ansis.yellow("\u6CE8\u610F")}: enhance_prompt \u5DF2\u4E0D\u53EF\u7528\uFF0Csearch_context \u4EE3\u7801\u68C0\u7D22\u6B63\u5E38`);
|
|
1088
1089
|
console.log();
|
|
1089
1090
|
const answers = await inquirer.prompt([
|
|
1090
1091
|
{ type: "input", name: "baseUrl", message: `Base URL ${ansis.gray("(\u4E2D\u8F6C\u670D\u52A1\u5FC5\u586B\uFF0C\u5B98\u65B9\u7559\u7A7A)")}` },
|
|
@@ -2985,60 +2986,147 @@ async function performUpdate(fromVersion, toVersion, isNewVersion) {
|
|
|
2985
2986
|
}
|
|
2986
2987
|
|
|
2987
2988
|
const execAsync = promisify(exec);
|
|
2989
|
+
function visWidth(s) {
|
|
2990
|
+
const stripped = s.replace(/\x1B\[[0-9;]*m/g, "");
|
|
2991
|
+
let w = 0;
|
|
2992
|
+
for (const ch of stripped) {
|
|
2993
|
+
const code = ch.codePointAt(0) || 0;
|
|
2994
|
+
if (code >= 11904 && code <= 40959 || code >= 63744 && code <= 64255 || code >= 65072 && code <= 65103 || code >= 65280 && code <= 65376 || code >= 65504 && code <= 65510 || code >= 127744 && code <= 129535 || code >= 131072 && code <= 195103) {
|
|
2995
|
+
w += 2;
|
|
2996
|
+
} else {
|
|
2997
|
+
w += 1;
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
3000
|
+
return w;
|
|
3001
|
+
}
|
|
3002
|
+
function pad(s, w) {
|
|
3003
|
+
const diff = w - visWidth(s);
|
|
3004
|
+
return diff > 0 ? s + " ".repeat(diff) : s;
|
|
3005
|
+
}
|
|
3006
|
+
const INNER_W = 60;
|
|
3007
|
+
function centerLine(s, w) {
|
|
3008
|
+
const vis = visWidth(s);
|
|
3009
|
+
const left = Math.max(0, Math.floor((w - vis) / 2));
|
|
3010
|
+
const right = Math.max(0, w - vis - left);
|
|
3011
|
+
return " ".repeat(left) + s + " ".repeat(right);
|
|
3012
|
+
}
|
|
3013
|
+
function boxRow(content) {
|
|
3014
|
+
const vis = visWidth(content);
|
|
3015
|
+
const gap = Math.max(0, INNER_W - vis);
|
|
3016
|
+
return ansis.cyan("\u2551") + content + " ".repeat(gap) + ansis.cyan("\u2551");
|
|
3017
|
+
}
|
|
3018
|
+
function drawHeader(statusParts) {
|
|
3019
|
+
const top = ansis.cyan("\u2554" + "\u2550".repeat(INNER_W) + "\u2557");
|
|
3020
|
+
const bot = ansis.cyan("\u255A" + "\u2550".repeat(INNER_W) + "\u255D");
|
|
3021
|
+
const empty = boxRow(" ".repeat(INNER_W));
|
|
3022
|
+
const logo = [
|
|
3023
|
+
" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ",
|
|
3024
|
+
" \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ",
|
|
3025
|
+
" \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2557",
|
|
3026
|
+
" \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551",
|
|
3027
|
+
" \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D",
|
|
3028
|
+
" \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "
|
|
3029
|
+
];
|
|
3030
|
+
console.log();
|
|
3031
|
+
console.log(top);
|
|
3032
|
+
console.log(empty);
|
|
3033
|
+
for (const line of logo) {
|
|
3034
|
+
console.log(boxRow(centerLine(ansis.bold.white(line), INNER_W)));
|
|
3035
|
+
}
|
|
3036
|
+
console.log(empty);
|
|
3037
|
+
console.log(boxRow(centerLine(ansis.gray("Claude + Codex + Gemini"), INNER_W)));
|
|
3038
|
+
console.log(boxRow(centerLine(ansis.gray("Multi-Model Collaboration"), INNER_W)));
|
|
3039
|
+
console.log(empty);
|
|
3040
|
+
if (statusParts.length > 0) {
|
|
3041
|
+
const statusLine = statusParts.join(ansis.gray(" | "));
|
|
3042
|
+
console.log(boxRow(centerLine(statusLine, INNER_W)));
|
|
3043
|
+
console.log(empty);
|
|
3044
|
+
}
|
|
3045
|
+
console.log(bot);
|
|
3046
|
+
console.log();
|
|
3047
|
+
}
|
|
3048
|
+
function groupSep(label) {
|
|
3049
|
+
const w = 42;
|
|
3050
|
+
const labelW = visWidth(label);
|
|
3051
|
+
const remaining = Math.max(0, w - labelW - 2);
|
|
3052
|
+
const left = Math.floor(remaining / 2);
|
|
3053
|
+
const right = remaining - left;
|
|
3054
|
+
return new inquirer.Separator(ansis.gray(`${"\u2500".repeat(left)} ${label} ${"\u2500".repeat(right)}`));
|
|
3055
|
+
}
|
|
2988
3056
|
async function showMainMenu() {
|
|
2989
3057
|
while (true) {
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
3058
|
+
const config = await readCcgConfig();
|
|
3059
|
+
const cmdCount = config?.workflows?.installed?.length || 0;
|
|
3060
|
+
const lang = config?.general?.language || "zh-CN";
|
|
3061
|
+
const mcpProvider = config?.mcp?.provider || "\u2014";
|
|
3062
|
+
const statusParts = [
|
|
3063
|
+
ansis.green(`v${version}`),
|
|
3064
|
+
ansis.white(`${cmdCount} commands`),
|
|
3065
|
+
ansis.yellow(lang)
|
|
3066
|
+
];
|
|
3067
|
+
if (mcpProvider !== "\u2014" && mcpProvider !== "skip") {
|
|
3068
|
+
statusParts.push(ansis.magenta(mcpProvider));
|
|
3069
|
+
}
|
|
3070
|
+
drawHeader(statusParts);
|
|
3071
|
+
const isZh = lang === "zh-CN";
|
|
3072
|
+
const item = (key, label, desc) => ({
|
|
3073
|
+
name: ` ${ansis.green(key + ".")} ${pad(label, 20)} ${ansis.gray("- " + desc)}`,
|
|
3074
|
+
value: key
|
|
3075
|
+
});
|
|
2994
3076
|
const { action } = await inquirer.prompt([{
|
|
2995
3077
|
type: "list",
|
|
2996
3078
|
name: "action",
|
|
2997
3079
|
message: i18n.t("menu:title"),
|
|
3080
|
+
pageSize: 20,
|
|
2998
3081
|
choices: [
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3082
|
+
groupSep(isZh ? "Claude Code" : "Claude Code"),
|
|
3083
|
+
item("1", i18n.t("menu:options.init"), isZh ? "\u5B89\u88C5 CCG \u5DE5\u4F5C\u6D41" : "Install CCG workflows"),
|
|
3084
|
+
item("2", i18n.t("menu:options.update"), isZh ? "\u66F4\u65B0\u5230\u6700\u65B0\u7248\u672C" : "Update to latest version"),
|
|
3085
|
+
item("3", i18n.t("menu:options.configMcp"), isZh ? "\u4EE3\u7801\u68C0\u7D22 MCP \u5DE5\u5177" : "Code retrieval MCP tool"),
|
|
3086
|
+
item("4", i18n.t("menu:options.configApi"), isZh ? "\u81EA\u5B9A\u4E49 API \u7AEF\u70B9" : "Custom API endpoint"),
|
|
3087
|
+
item("5", i18n.t("menu:options.configStyle"), isZh ? "\u9009\u62E9\u8F93\u51FA\u4EBA\u683C" : "Choose output personality"),
|
|
3088
|
+
groupSep(isZh ? "\u5176\u4ED6\u5DE5\u5177" : "Tools"),
|
|
3089
|
+
item("T", i18n.t("menu:options.tools"), "ccusage, CCometixLine"),
|
|
3090
|
+
item("C", i18n.t("menu:options.installClaude"), isZh ? "\u5B89\u88C5/\u91CD\u88C5 CLI" : "Install/reinstall CLI"),
|
|
3091
|
+
groupSep("CCG"),
|
|
3092
|
+
item("H", i18n.t("menu:options.help"), isZh ? "\u67E5\u770B\u5168\u90E8\u659C\u6760\u547D\u4EE4" : "View all slash commands"),
|
|
3093
|
+
item("-", i18n.t("menu:options.uninstall"), isZh ? "\u79FB\u9664 CCG \u914D\u7F6E" : "Remove CCG config"),
|
|
3094
|
+
new inquirer.Separator(ansis.gray("\u2500".repeat(42))),
|
|
3095
|
+
{ name: ` ${ansis.red("Q.")} ${i18n.t("menu:options.exit")}`, value: "Q" }
|
|
3010
3096
|
]
|
|
3011
3097
|
}]);
|
|
3012
3098
|
switch (action) {
|
|
3013
|
-
case "
|
|
3099
|
+
case "1":
|
|
3014
3100
|
await init();
|
|
3015
3101
|
break;
|
|
3016
|
-
case "
|
|
3102
|
+
case "2":
|
|
3017
3103
|
await update();
|
|
3018
3104
|
break;
|
|
3019
|
-
case "
|
|
3105
|
+
case "3":
|
|
3020
3106
|
await configMcp();
|
|
3021
3107
|
break;
|
|
3022
|
-
case "
|
|
3108
|
+
case "4":
|
|
3023
3109
|
await configApi();
|
|
3024
3110
|
break;
|
|
3025
|
-
case "
|
|
3111
|
+
case "5":
|
|
3026
3112
|
await configOutputStyle();
|
|
3027
3113
|
break;
|
|
3028
|
-
case "
|
|
3114
|
+
case "T":
|
|
3029
3115
|
await handleTools();
|
|
3030
3116
|
break;
|
|
3031
|
-
case "
|
|
3117
|
+
case "C":
|
|
3032
3118
|
await handleInstallClaude();
|
|
3033
3119
|
break;
|
|
3034
|
-
case "
|
|
3120
|
+
case "-":
|
|
3035
3121
|
await uninstall();
|
|
3036
3122
|
break;
|
|
3037
|
-
case "
|
|
3123
|
+
case "H":
|
|
3038
3124
|
showHelp();
|
|
3039
3125
|
break;
|
|
3040
|
-
case "
|
|
3041
|
-
console.log(
|
|
3126
|
+
case "Q":
|
|
3127
|
+
console.log();
|
|
3128
|
+
console.log(ansis.gray(` ${i18n.t("common:goodbye")}`));
|
|
3129
|
+
console.log();
|
|
3042
3130
|
return;
|
|
3043
3131
|
}
|
|
3044
3132
|
console.log();
|
|
@@ -3050,41 +3138,63 @@ async function showMainMenu() {
|
|
|
3050
3138
|
}
|
|
3051
3139
|
}
|
|
3052
3140
|
function showHelp() {
|
|
3141
|
+
const config = readCcgConfigSync();
|
|
3142
|
+
const isZh = (config?.general?.language || "zh-CN") === "zh-CN";
|
|
3053
3143
|
console.log();
|
|
3054
|
-
console.log(ansis.cyan.bold(i18n.t("menu:help.title")));
|
|
3144
|
+
console.log(ansis.cyan.bold(` ${i18n.t("menu:help.title")}`));
|
|
3055
3145
|
console.log();
|
|
3056
|
-
|
|
3057
|
-
console.log(
|
|
3058
|
-
console.log(` ${ansis.green(
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3146
|
+
const col1 = 22;
|
|
3147
|
+
const section = (title) => console.log(ansis.yellow.bold(` ${title}`));
|
|
3148
|
+
const cmd = (name, desc) => console.log(` ${ansis.green(name.padEnd(col1))} ${ansis.gray(desc)}`);
|
|
3149
|
+
section(i18n.t("menu:help.sections.devWorkflow"));
|
|
3150
|
+
cmd("/ccg:workflow", i18n.t("menu:help.descriptions.workflow"));
|
|
3151
|
+
cmd("/ccg:plan", i18n.t("menu:help.descriptions.plan"));
|
|
3152
|
+
cmd("/ccg:execute", i18n.t("menu:help.descriptions.execute"));
|
|
3153
|
+
cmd("/ccg:frontend", i18n.t("menu:help.descriptions.frontend"));
|
|
3154
|
+
cmd("/ccg:backend", i18n.t("menu:help.descriptions.backend"));
|
|
3155
|
+
cmd("/ccg:feat", i18n.t("menu:help.descriptions.feat"));
|
|
3156
|
+
cmd("/ccg:analyze", i18n.t("menu:help.descriptions.analyze"));
|
|
3157
|
+
cmd("/ccg:debug", i18n.t("menu:help.descriptions.debug"));
|
|
3158
|
+
cmd("/ccg:optimize", i18n.t("menu:help.descriptions.optimize"));
|
|
3159
|
+
cmd("/ccg:test", i18n.t("menu:help.descriptions.test"));
|
|
3160
|
+
cmd("/ccg:review", i18n.t("menu:help.descriptions.review"));
|
|
3068
3161
|
console.log();
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
console.log(` ${ansis.green("/ccg:spec-review")} ${i18n.t("menu:help.descriptions.specReview")}`);
|
|
3162
|
+
section(isZh ? "Agent Teams \u5E76\u884C\u5B9E\u65BD:" : "Agent Teams Parallel:");
|
|
3163
|
+
cmd("/ccg:team-research", isZh ? "\u9700\u6C42 \u2192 \u7EA6\u675F\u96C6" : "Requirements \u2192 Constraints");
|
|
3164
|
+
cmd("/ccg:team-plan", isZh ? "\u7EA6\u675F \u2192 \u5E76\u884C\u8BA1\u5212" : "Constraints \u2192 Parallel plan");
|
|
3165
|
+
cmd("/ccg:team-exec", isZh ? "\u5E76\u884C\u5B9E\u65BD" : "Parallel execution");
|
|
3166
|
+
cmd("/ccg:team-review", isZh ? "\u53CC\u6A21\u578B\u5BA1\u67E5" : "Dual-model review");
|
|
3075
3167
|
console.log();
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3168
|
+
section(i18n.t("menu:help.sections.opsx"));
|
|
3169
|
+
cmd("/ccg:spec-init", i18n.t("menu:help.descriptions.specInit"));
|
|
3170
|
+
cmd("/ccg:spec-research", i18n.t("menu:help.descriptions.specResearch"));
|
|
3171
|
+
cmd("/ccg:spec-plan", i18n.t("menu:help.descriptions.specPlan"));
|
|
3172
|
+
cmd("/ccg:spec-impl", i18n.t("menu:help.descriptions.specImpl"));
|
|
3173
|
+
cmd("/ccg:spec-review", i18n.t("menu:help.descriptions.specReview"));
|
|
3081
3174
|
console.log();
|
|
3082
|
-
|
|
3083
|
-
|
|
3175
|
+
section(i18n.t("menu:help.sections.gitTools"));
|
|
3176
|
+
cmd("/ccg:commit", i18n.t("menu:help.descriptions.commit"));
|
|
3177
|
+
cmd("/ccg:rollback", i18n.t("menu:help.descriptions.rollback"));
|
|
3178
|
+
cmd("/ccg:clean-branches", i18n.t("menu:help.descriptions.cleanBranches"));
|
|
3179
|
+
cmd("/ccg:worktree", i18n.t("menu:help.descriptions.worktree"));
|
|
3084
3180
|
console.log();
|
|
3085
|
-
|
|
3181
|
+
section(i18n.t("menu:help.sections.projectMgmt"));
|
|
3182
|
+
cmd("/ccg:init", i18n.t("menu:help.descriptions.init"));
|
|
3183
|
+
cmd("/ccg:enhance", isZh ? "Prompt \u589E\u5F3A" : "Prompt enhancement");
|
|
3184
|
+
console.log();
|
|
3185
|
+
console.log(ansis.gray(` ${i18n.t("menu:help.hint")}`));
|
|
3086
3186
|
console.log();
|
|
3087
3187
|
}
|
|
3188
|
+
function readCcgConfigSync() {
|
|
3189
|
+
try {
|
|
3190
|
+
const configPath = join(homedir(), ".claude", ".ccg", "config.toml");
|
|
3191
|
+
if (fs.pathExistsSync(configPath)) {
|
|
3192
|
+
return parse(fs.readFileSync(configPath, "utf-8"));
|
|
3193
|
+
}
|
|
3194
|
+
} catch {
|
|
3195
|
+
}
|
|
3196
|
+
return null;
|
|
3197
|
+
}
|
|
3088
3198
|
async function configApi() {
|
|
3089
3199
|
console.log();
|
|
3090
3200
|
console.log(ansis.cyan.bold(` ${i18n.t("menu:api.title")}`));
|
|
@@ -3151,8 +3261,8 @@ async function configApi() {
|
|
|
3151
3261
|
await fs.ensureDir(join(homedir(), ".claude"));
|
|
3152
3262
|
await fs.writeJson(settingsPath, settings, { spaces: 2 });
|
|
3153
3263
|
console.log();
|
|
3154
|
-
console.log(ansis.green(
|
|
3155
|
-
console.log(ansis.gray(`
|
|
3264
|
+
console.log(ansis.green(` \u2713 ${i18n.t("menu:api.saved")}`));
|
|
3265
|
+
console.log(ansis.gray(` ${i18n.t("common:configFile")}: ${settingsPath}`));
|
|
3156
3266
|
}
|
|
3157
3267
|
const OUTPUT_STYLES = [
|
|
3158
3268
|
{ id: "default", nameKey: "menu:style.default", descKey: "menu:style.defaultDesc" },
|
|
@@ -3201,7 +3311,7 @@ async function configOutputStyle() {
|
|
|
3201
3311
|
const destPath = join(outputStylesDir, `${style}.md`);
|
|
3202
3312
|
if (await fs.pathExists(templatePath)) {
|
|
3203
3313
|
await fs.copy(templatePath, destPath);
|
|
3204
|
-
console.log(ansis.green(
|
|
3314
|
+
console.log(ansis.green(` \u2713 ${i18n.t("menu:style.installed", { style })}`));
|
|
3205
3315
|
}
|
|
3206
3316
|
}
|
|
3207
3317
|
if (style === "default") {
|
|
@@ -3211,8 +3321,8 @@ async function configOutputStyle() {
|
|
|
3211
3321
|
}
|
|
3212
3322
|
await fs.writeJson(settingsPath, settings, { spaces: 2 });
|
|
3213
3323
|
console.log();
|
|
3214
|
-
console.log(ansis.green(
|
|
3215
|
-
console.log(ansis.gray(`
|
|
3324
|
+
console.log(ansis.green(` \u2713 ${i18n.t("menu:style.set", { style })}`));
|
|
3325
|
+
console.log(ansis.gray(` ${i18n.t("common:restartToApply")}`));
|
|
3216
3326
|
}
|
|
3217
3327
|
async function handleInstallClaude() {
|
|
3218
3328
|
console.log();
|
|
@@ -3226,7 +3336,7 @@ async function handleInstallClaude() {
|
|
|
3226
3336
|
isInstalled = false;
|
|
3227
3337
|
}
|
|
3228
3338
|
if (isInstalled) {
|
|
3229
|
-
console.log(ansis.yellow(
|
|
3339
|
+
console.log(ansis.yellow(` \u26A0 ${i18n.t("menu:claude.alreadyInstalled")}`));
|
|
3230
3340
|
const { confirm } = await inquirer.prompt([{
|
|
3231
3341
|
type: "confirm",
|
|
3232
3342
|
name: "confirm",
|
|
@@ -3234,17 +3344,17 @@ async function handleInstallClaude() {
|
|
|
3234
3344
|
default: false
|
|
3235
3345
|
}]);
|
|
3236
3346
|
if (!confirm) {
|
|
3237
|
-
console.log(ansis.gray(i18n.t("common:cancelled")));
|
|
3347
|
+
console.log(ansis.gray(` ${i18n.t("common:cancelled")}`));
|
|
3238
3348
|
return;
|
|
3239
3349
|
}
|
|
3240
3350
|
console.log();
|
|
3241
|
-
console.log(ansis.yellow(
|
|
3351
|
+
console.log(ansis.yellow(` \u23F3 ${i18n.t("menu:claude.uninstalling")}`));
|
|
3242
3352
|
try {
|
|
3243
3353
|
const uninstallCmd = isWindows() ? "npm uninstall -g @anthropic-ai/claude-code" : "sudo npm uninstall -g @anthropic-ai/claude-code";
|
|
3244
3354
|
await execAsync(uninstallCmd, { timeout: 6e4 });
|
|
3245
|
-
console.log(ansis.green(
|
|
3355
|
+
console.log(ansis.green(` \u2713 ${i18n.t("menu:claude.uninstallSuccess")}`));
|
|
3246
3356
|
} catch (e) {
|
|
3247
|
-
console.log(ansis.red(
|
|
3357
|
+
console.log(ansis.red(` \u2717 ${i18n.t("menu:claude.uninstallFailed", { error: String(e) })}`));
|
|
3248
3358
|
return;
|
|
3249
3359
|
}
|
|
3250
3360
|
}
|
|
@@ -3255,7 +3365,7 @@ async function handleInstallClaude() {
|
|
|
3255
3365
|
name: "method",
|
|
3256
3366
|
message: i18n.t("menu:claude.selectMethod"),
|
|
3257
3367
|
choices: [
|
|
3258
|
-
{ name: `npm ${ansis.green(
|
|
3368
|
+
{ name: `npm ${ansis.green("(\u2B50)")} ${ansis.gray("- npm install -g")}`, value: "npm" },
|
|
3259
3369
|
...isMac || isLinux ? [{ name: `homebrew ${ansis.gray("- brew install")}`, value: "homebrew" }] : [],
|
|
3260
3370
|
...isMac || isLinux ? [{ name: `curl ${ansis.gray("- official script")}`, value: "curl" }] : [],
|
|
3261
3371
|
...isWindows() ? [
|
|
@@ -3269,7 +3379,7 @@ async function handleInstallClaude() {
|
|
|
3269
3379
|
if (method === "cancel")
|
|
3270
3380
|
return;
|
|
3271
3381
|
console.log();
|
|
3272
|
-
console.log(ansis.yellow(
|
|
3382
|
+
console.log(ansis.yellow(` \u23F3 ${i18n.t("menu:claude.installing")}`));
|
|
3273
3383
|
try {
|
|
3274
3384
|
if (method === "npm") {
|
|
3275
3385
|
const installCmd = isWindows() ? "npm install -g @anthropic-ai/claude-code" : "sudo npm install -g @anthropic-ai/claude-code";
|
|
@@ -3283,11 +3393,11 @@ async function handleInstallClaude() {
|
|
|
3283
3393
|
} else if (method === "cmd") {
|
|
3284
3394
|
await execAsync('cmd /c "curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd"', { timeout: 3e5 });
|
|
3285
3395
|
}
|
|
3286
|
-
console.log(ansis.green(
|
|
3396
|
+
console.log(ansis.green(` \u2713 ${i18n.t("menu:claude.installSuccess")}`));
|
|
3287
3397
|
console.log();
|
|
3288
|
-
console.log(ansis.cyan(
|
|
3398
|
+
console.log(ansis.cyan(` \u{1F4A1} ${i18n.t("menu:claude.runHint")}`));
|
|
3289
3399
|
} catch (e) {
|
|
3290
|
-
console.log(ansis.red(
|
|
3400
|
+
console.log(ansis.red(` \u2717 ${i18n.t("menu:claude.installFailed", { error: String(e) })}`));
|
|
3291
3401
|
}
|
|
3292
3402
|
}
|
|
3293
3403
|
async function checkIfGlobalInstall() {
|
|
@@ -3302,11 +3412,11 @@ async function uninstall() {
|
|
|
3302
3412
|
console.log();
|
|
3303
3413
|
const isGlobalInstall = await checkIfGlobalInstall();
|
|
3304
3414
|
if (isGlobalInstall) {
|
|
3305
|
-
console.log(ansis.yellow(
|
|
3415
|
+
console.log(ansis.yellow(` \u26A0\uFE0F ${i18n.t("menu:uninstall.globalDetected")}`));
|
|
3306
3416
|
console.log();
|
|
3307
|
-
console.log(i18n.t("menu:uninstall.twoSteps"));
|
|
3308
|
-
console.log(`
|
|
3309
|
-
console.log(`
|
|
3417
|
+
console.log(` ${i18n.t("menu:uninstall.twoSteps")}`);
|
|
3418
|
+
console.log(` ${ansis.cyan(`1. ${i18n.t("menu:uninstall.step1")}`)} ${ansis.gray(`(${i18n.t("menu:uninstall.step1Hint")})`)}`);
|
|
3419
|
+
console.log(` ${ansis.cyan(`2. ${i18n.t("menu:uninstall.step2")}`)} ${ansis.gray(`(${i18n.t("menu:uninstall.step2Hint")})`)}`);
|
|
3310
3420
|
console.log();
|
|
3311
3421
|
}
|
|
3312
3422
|
const { confirm } = await inquirer.prompt([{
|
|
@@ -3316,53 +3426,53 @@ async function uninstall() {
|
|
|
3316
3426
|
default: false
|
|
3317
3427
|
}]);
|
|
3318
3428
|
if (!confirm) {
|
|
3319
|
-
console.log(ansis.gray(i18n.t("menu:uninstall.cancelled")));
|
|
3429
|
+
console.log(ansis.gray(` ${i18n.t("menu:uninstall.cancelled")}`));
|
|
3320
3430
|
return;
|
|
3321
3431
|
}
|
|
3322
3432
|
console.log();
|
|
3323
|
-
console.log(ansis.yellow(i18n.t("menu:uninstall.uninstalling")));
|
|
3433
|
+
console.log(ansis.yellow(` ${i18n.t("menu:uninstall.uninstalling")}`));
|
|
3324
3434
|
const installDir = join(homedir(), ".claude");
|
|
3325
3435
|
const result = await uninstallWorkflows(installDir);
|
|
3326
3436
|
if (result.success) {
|
|
3327
|
-
console.log(ansis.green(
|
|
3437
|
+
console.log(ansis.green(` \u2705 ${i18n.t("menu:uninstall.success")}`));
|
|
3328
3438
|
if (result.removedCommands.length > 0) {
|
|
3329
3439
|
console.log();
|
|
3330
|
-
console.log(ansis.cyan(i18n.t("menu:uninstall.removedCommands")));
|
|
3440
|
+
console.log(ansis.cyan(` ${i18n.t("menu:uninstall.removedCommands")}`));
|
|
3331
3441
|
for (const cmd of result.removedCommands) {
|
|
3332
|
-
console.log(`
|
|
3442
|
+
console.log(` ${ansis.gray("\u2022")} /ccg:${cmd}`);
|
|
3333
3443
|
}
|
|
3334
3444
|
}
|
|
3335
3445
|
if (result.removedAgents.length > 0) {
|
|
3336
3446
|
console.log();
|
|
3337
|
-
console.log(ansis.cyan(i18n.t("menu:uninstall.removedAgents")));
|
|
3447
|
+
console.log(ansis.cyan(` ${i18n.t("menu:uninstall.removedAgents")}`));
|
|
3338
3448
|
for (const agent of result.removedAgents) {
|
|
3339
|
-
console.log(`
|
|
3449
|
+
console.log(` ${ansis.gray("\u2022")} ${agent}`);
|
|
3340
3450
|
}
|
|
3341
3451
|
}
|
|
3342
3452
|
if (result.removedSkills.length > 0) {
|
|
3343
3453
|
console.log();
|
|
3344
|
-
console.log(ansis.cyan(i18n.t("menu:uninstall.removedSkills")));
|
|
3345
|
-
console.log(`
|
|
3454
|
+
console.log(ansis.cyan(` ${i18n.t("menu:uninstall.removedSkills")}`));
|
|
3455
|
+
console.log(` ${ansis.gray("\u2022")} multi-model-collaboration`);
|
|
3346
3456
|
}
|
|
3347
3457
|
if (result.removedBin) {
|
|
3348
3458
|
console.log();
|
|
3349
|
-
console.log(ansis.cyan(i18n.t("menu:uninstall.removedBin")));
|
|
3350
|
-
console.log(`
|
|
3459
|
+
console.log(ansis.cyan(` ${i18n.t("menu:uninstall.removedBin")}`));
|
|
3460
|
+
console.log(` ${ansis.gray("\u2022")} codeagent-wrapper`);
|
|
3351
3461
|
}
|
|
3352
3462
|
if (isGlobalInstall) {
|
|
3353
3463
|
console.log();
|
|
3354
|
-
console.log(ansis.yellow.bold(
|
|
3464
|
+
console.log(ansis.yellow.bold(` \u{1F538} ${i18n.t("menu:uninstall.lastStep")}`));
|
|
3355
3465
|
console.log();
|
|
3356
|
-
console.log(i18n.t("menu:uninstall.runInNewTerminal"));
|
|
3466
|
+
console.log(` ${i18n.t("menu:uninstall.runInNewTerminal")}`);
|
|
3357
3467
|
console.log();
|
|
3358
|
-
console.log(ansis.cyan.bold("
|
|
3468
|
+
console.log(ansis.cyan.bold(" npm uninstall -g ccg-workflow"));
|
|
3359
3469
|
console.log();
|
|
3360
|
-
console.log(ansis.gray(`(${i18n.t("menu:uninstall.afterDone")})`));
|
|
3470
|
+
console.log(ansis.gray(` (${i18n.t("menu:uninstall.afterDone")})`));
|
|
3361
3471
|
}
|
|
3362
3472
|
} else {
|
|
3363
|
-
console.log(ansis.red(i18n.t("menu:uninstall.failed")));
|
|
3473
|
+
console.log(ansis.red(` ${i18n.t("menu:uninstall.failed")}`));
|
|
3364
3474
|
for (const error of result.errors) {
|
|
3365
|
-
console.log(ansis.red(`
|
|
3475
|
+
console.log(ansis.red(` ${error}`));
|
|
3366
3476
|
}
|
|
3367
3477
|
}
|
|
3368
3478
|
console.log();
|
|
@@ -3374,10 +3484,10 @@ async function handleTools() {
|
|
|
3374
3484
|
name: "tool",
|
|
3375
3485
|
message: i18n.t("menu:tools.title"),
|
|
3376
3486
|
choices: [
|
|
3377
|
-
{ name: `${ansis.green("\u{1F4CA}")} ccusage
|
|
3378
|
-
{ name: `${ansis.blue("\u{1F4DF}")} CCometixLine
|
|
3487
|
+
{ name: `${ansis.green("\u{1F4CA}")} ccusage ${ansis.gray(`${i18n.t("menu:tools.ccusage")}`)}`, value: "ccusage" },
|
|
3488
|
+
{ name: `${ansis.blue("\u{1F4DF}")} CCometixLine ${ansis.gray(`${i18n.t("menu:tools.ccline")}`)}`, value: "ccline" },
|
|
3379
3489
|
new inquirer.Separator(),
|
|
3380
|
-
{ name: `${ansis.gray(i18n.t("common:back"))}`, value: "cancel" }
|
|
3490
|
+
{ name: `${ansis.gray(`\u2190 ${i18n.t("common:back")}`)}`, value: "cancel" }
|
|
3381
3491
|
]
|
|
3382
3492
|
}]);
|
|
3383
3493
|
if (tool === "cancel")
|
|
@@ -3390,8 +3500,8 @@ async function handleTools() {
|
|
|
3390
3500
|
}
|
|
3391
3501
|
async function runCcusage() {
|
|
3392
3502
|
console.log();
|
|
3393
|
-
console.log(ansis.cyan(
|
|
3394
|
-
console.log(ansis.gray("$ npx ccusage@latest"));
|
|
3503
|
+
console.log(ansis.cyan(` \u{1F4CA} ${i18n.t("menu:tools.runningCcusage")}`));
|
|
3504
|
+
console.log(ansis.gray(" $ npx ccusage@latest"));
|
|
3395
3505
|
console.log();
|
|
3396
3506
|
return new Promise((resolve) => {
|
|
3397
3507
|
const child = spawn("npx", ["ccusage@latest"], {
|
|
@@ -3412,7 +3522,7 @@ async function handleCCometixLine() {
|
|
|
3412
3522
|
{ name: `${ansis.green("\u279C")} ${i18n.t("menu:tools.cclineInstall")}`, value: "install" },
|
|
3413
3523
|
{ name: `${ansis.red("\u2715")} ${i18n.t("menu:tools.cclineUninstall")}`, value: "uninstall" },
|
|
3414
3524
|
new inquirer.Separator(),
|
|
3415
|
-
{ name: `${ansis.gray(i18n.t("common:back"))}`, value: "cancel" }
|
|
3525
|
+
{ name: `${ansis.gray(`\u2190 ${i18n.t("common:back")}`)}`, value: "cancel" }
|
|
3416
3526
|
]
|
|
3417
3527
|
}]);
|
|
3418
3528
|
if (action === "cancel")
|
|
@@ -3425,11 +3535,11 @@ async function handleCCometixLine() {
|
|
|
3425
3535
|
}
|
|
3426
3536
|
async function installCCometixLine() {
|
|
3427
3537
|
console.log();
|
|
3428
|
-
console.log(ansis.yellow(
|
|
3538
|
+
console.log(ansis.yellow(` \u23F3 ${i18n.t("menu:tools.cclineInstalling")}`));
|
|
3429
3539
|
try {
|
|
3430
3540
|
const installCmd = isWindows() ? "npm install -g @cometix/ccline" : "sudo npm install -g @cometix/ccline";
|
|
3431
3541
|
await execAsync(installCmd, { timeout: 12e4 });
|
|
3432
|
-
console.log(ansis.green(
|
|
3542
|
+
console.log(ansis.green(` \u2713 ${i18n.t("menu:tools.cclineInstallSuccess")}`));
|
|
3433
3543
|
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
3434
3544
|
let settings = {};
|
|
3435
3545
|
if (await fs.pathExists(settingsPath)) {
|
|
@@ -3442,29 +3552,29 @@ async function installCCometixLine() {
|
|
|
3442
3552
|
};
|
|
3443
3553
|
await fs.ensureDir(join(homedir(), ".claude"));
|
|
3444
3554
|
await fs.writeJson(settingsPath, settings, { spaces: 2 });
|
|
3445
|
-
console.log(ansis.green(
|
|
3555
|
+
console.log(ansis.green(` \u2713 ${i18n.t("menu:tools.cclineConfigured")}`));
|
|
3446
3556
|
console.log();
|
|
3447
|
-
console.log(ansis.cyan(
|
|
3557
|
+
console.log(ansis.cyan(` \u{1F4A1} ${i18n.t("common:restartToApply")}`));
|
|
3448
3558
|
} catch (error) {
|
|
3449
|
-
console.log(ansis.red(
|
|
3559
|
+
console.log(ansis.red(` \u2717 ${i18n.t("menu:tools.cclineInstallFailed", { error: String(error) })}`));
|
|
3450
3560
|
}
|
|
3451
3561
|
}
|
|
3452
3562
|
async function uninstallCCometixLine() {
|
|
3453
3563
|
console.log();
|
|
3454
|
-
console.log(ansis.yellow(
|
|
3564
|
+
console.log(ansis.yellow(` \u23F3 ${i18n.t("menu:tools.cclineUninstalling")}`));
|
|
3455
3565
|
try {
|
|
3456
3566
|
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
3457
3567
|
if (await fs.pathExists(settingsPath)) {
|
|
3458
3568
|
const settings = await fs.readJson(settingsPath);
|
|
3459
3569
|
delete settings.statusLine;
|
|
3460
3570
|
await fs.writeJson(settingsPath, settings, { spaces: 2 });
|
|
3461
|
-
console.log(ansis.green(
|
|
3571
|
+
console.log(ansis.green(` \u2713 ${i18n.t("menu:tools.cclineConfigRemoved")}`));
|
|
3462
3572
|
}
|
|
3463
3573
|
const uninstallCmd = isWindows() ? "npm uninstall -g @cometix/ccline" : "sudo npm uninstall -g @cometix/ccline";
|
|
3464
3574
|
await execAsync(uninstallCmd, { timeout: 6e4 });
|
|
3465
|
-
console.log(ansis.green(
|
|
3575
|
+
console.log(ansis.green(` \u2713 ${i18n.t("menu:tools.cclineUninstalled")}`));
|
|
3466
3576
|
} catch (error) {
|
|
3467
|
-
console.log(ansis.red(
|
|
3577
|
+
console.log(ansis.red(` \u2717 ${i18n.t("menu:tools.cclineUninstallFailed", { error: String(error) })}`));
|
|
3468
3578
|
}
|
|
3469
3579
|
}
|
|
3470
3580
|
|
package/package.json
CHANGED