ccjk 1.3.1
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/LICENSE +21 -0
- package/README.ja.md +455 -0
- package/README.ko.md +455 -0
- package/README.md +550 -0
- package/README.zh-CN.md +488 -0
- package/bin/ccjk.mjs +2 -0
- package/dist/chunks/api-providers.mjs +89 -0
- package/dist/chunks/claude-code-config-manager.mjs +733 -0
- package/dist/chunks/claude-code-incremental-manager.mjs +603 -0
- package/dist/chunks/codex-config-switch.mjs +427 -0
- package/dist/chunks/codex-provider-manager.mjs +232 -0
- package/dist/chunks/codex-uninstaller.mjs +404 -0
- package/dist/chunks/commands.mjs +120 -0
- package/dist/chunks/features.mjs +642 -0
- package/dist/chunks/simple-config.mjs +10445 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.mjs +5972 -0
- package/dist/i18n/locales/en/api.json +63 -0
- package/dist/i18n/locales/en/ccjk.json +276 -0
- package/dist/i18n/locales/en/ccr.json +65 -0
- package/dist/i18n/locales/en/cli.json +57 -0
- package/dist/i18n/locales/en/codex.json +124 -0
- package/dist/i18n/locales/en/cometix.json +29 -0
- package/dist/i18n/locales/en/common.json +20 -0
- package/dist/i18n/locales/en/configuration.json +77 -0
- package/dist/i18n/locales/en/errors.json +26 -0
- package/dist/i18n/locales/en/installation.json +80 -0
- package/dist/i18n/locales/en/interview.json +104 -0
- package/dist/i18n/locales/en/language.json +19 -0
- package/dist/i18n/locales/en/mcp.json +38 -0
- package/dist/i18n/locales/en/menu.json +51 -0
- package/dist/i18n/locales/en/multi-config.json +79 -0
- package/dist/i18n/locales/en/shencha.json +14 -0
- package/dist/i18n/locales/en/team.json +7 -0
- package/dist/i18n/locales/en/tools.json +42 -0
- package/dist/i18n/locales/en/uninstall.json +56 -0
- package/dist/i18n/locales/en/updater.json +25 -0
- package/dist/i18n/locales/en/workflow.json +25 -0
- package/dist/i18n/locales/zh-CN/api.json +63 -0
- package/dist/i18n/locales/zh-CN/ccjk.json +276 -0
- package/dist/i18n/locales/zh-CN/ccr.json +65 -0
- package/dist/i18n/locales/zh-CN/cli.json +57 -0
- package/dist/i18n/locales/zh-CN/codex.json +124 -0
- package/dist/i18n/locales/zh-CN/cometix.json +29 -0
- package/dist/i18n/locales/zh-CN/common.json +20 -0
- package/dist/i18n/locales/zh-CN/configuration.json +77 -0
- package/dist/i18n/locales/zh-CN/errors.json +26 -0
- package/dist/i18n/locales/zh-CN/installation.json +80 -0
- package/dist/i18n/locales/zh-CN/interview.json +104 -0
- package/dist/i18n/locales/zh-CN/language.json +19 -0
- package/dist/i18n/locales/zh-CN/mcp.json +38 -0
- package/dist/i18n/locales/zh-CN/menu.json +51 -0
- package/dist/i18n/locales/zh-CN/multi-config.json +79 -0
- package/dist/i18n/locales/zh-CN/shencha.json +14 -0
- package/dist/i18n/locales/zh-CN/team.json +7 -0
- package/dist/i18n/locales/zh-CN/tools.json +42 -0
- package/dist/i18n/locales/zh-CN/uninstall.json +56 -0
- package/dist/i18n/locales/zh-CN/updater.json +25 -0
- package/dist/i18n/locales/zh-CN/workflow.json +25 -0
- package/dist/index.d.mts +2644 -0
- package/dist/index.d.ts +2644 -0
- package/dist/index.mjs +1706 -0
- package/package.json +157 -0
- package/templates/CLAUDE.md +219 -0
- package/templates/claude-code/CLAUDE.md +250 -0
- package/templates/claude-code/common/settings.json +38 -0
- package/templates/claude-code/en/workflow/bmad/commands/bmad-init.md +165 -0
- package/templates/claude-code/en/workflow/common/agents/get-current-datetime.md +29 -0
- package/templates/claude-code/en/workflow/common/agents/init-architect.md +114 -0
- package/templates/claude-code/en/workflow/common/commands/init-project.md +53 -0
- package/templates/claude-code/en/workflow/plan/agents/planner.md +116 -0
- package/templates/claude-code/en/workflow/plan/agents/ui-ux-designer.md +91 -0
- package/templates/claude-code/en/workflow/plan/commands/feat.md +105 -0
- package/templates/claude-code/zh-CN/workflow/bmad/commands/bmad-init.md +172 -0
- package/templates/claude-code/zh-CN/workflow/common/agents/get-current-datetime.md +29 -0
- package/templates/claude-code/zh-CN/workflow/common/agents/init-architect.md +114 -0
- package/templates/claude-code/zh-CN/workflow/common/commands/init-project.md +53 -0
- package/templates/claude-code/zh-CN/workflow/plan/agents/planner.md +116 -0
- package/templates/claude-code/zh-CN/workflow/plan/agents/ui-ux-designer.md +91 -0
- package/templates/claude-code/zh-CN/workflow/plan/commands/feat.md +105 -0
- package/templates/codex/common/config.toml +0 -0
- package/templates/common/output-styles/en/casual-friendly.md +97 -0
- package/templates/common/output-styles/en/engineer-professional.md +88 -0
- package/templates/common/output-styles/en/expert-concise.md +93 -0
- package/templates/common/output-styles/en/laowang-engineer.md +127 -0
- package/templates/common/output-styles/en/nekomata-engineer.md +120 -0
- package/templates/common/output-styles/en/ojousama-engineer.md +121 -0
- package/templates/common/output-styles/en/teaching-mode.md +102 -0
- package/templates/common/output-styles/en/technical-precise.md +101 -0
- package/templates/common/output-styles/zh-CN/engineer-professional.md +89 -0
- package/templates/common/output-styles/zh-CN/laowang-engineer.md +127 -0
- package/templates/common/output-styles/zh-CN/nekomata-engineer.md +120 -0
- package/templates/common/output-styles/zh-CN/ojousama-engineer.md +121 -0
- package/templates/common/workflow/git/en/git-cleanBranches.md +102 -0
- package/templates/common/workflow/git/en/git-commit.md +205 -0
- package/templates/common/workflow/git/en/git-rollback.md +90 -0
- package/templates/common/workflow/git/en/git-worktree.md +276 -0
- package/templates/common/workflow/git/zh-CN/git-cleanBranches.md +102 -0
- package/templates/common/workflow/git/zh-CN/git-commit.md +205 -0
- package/templates/common/workflow/git/zh-CN/git-rollback.md +90 -0
- package/templates/common/workflow/git/zh-CN/git-worktree.md +276 -0
- package/templates/common/workflow/interview/en/interview.md +212 -0
- package/templates/common/workflow/interview/zh-CN/interview.md +212 -0
- package/templates/common/workflow/sixStep/en/workflow.md +251 -0
- package/templates/common/workflow/sixStep/zh-CN/workflow.md +215 -0
- package/templates/industry/devops/en/ci-cd-pipeline.md +410 -0
- package/templates/industry/web-dev/en/api-design.md +299 -0
- package/templates/industry/web-dev/en/react-nextjs-setup.md +236 -0
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import { pathExists } from 'fs-extra';
|
|
2
|
+
import { join } from 'pathe';
|
|
3
|
+
import { x as CODEX_DIR, y as CODEX_CONFIG_FILE, cE as moveToTrash, cj as i18n, z as CODEX_AUTH_FILE, B as CODEX_AGENTS_FILE, D as CODEX_PROMPTS_DIR } from './simple-config.mjs';
|
|
4
|
+
import 'node:fs';
|
|
5
|
+
import 'node:process';
|
|
6
|
+
import 'ansis';
|
|
7
|
+
import 'inquirer';
|
|
8
|
+
import 'smol-toml';
|
|
9
|
+
import 'dayjs';
|
|
10
|
+
import 'node:child_process';
|
|
11
|
+
import 'node:os';
|
|
12
|
+
import 'node:util';
|
|
13
|
+
import 'node:url';
|
|
14
|
+
import 'inquirer-toggle';
|
|
15
|
+
import 'ora';
|
|
16
|
+
import 'tinyexec';
|
|
17
|
+
import 'semver';
|
|
18
|
+
import 'node:fs/promises';
|
|
19
|
+
import 'trash';
|
|
20
|
+
import 'i18next';
|
|
21
|
+
import 'i18next-fs-backend';
|
|
22
|
+
|
|
23
|
+
class CodexUninstaller {
|
|
24
|
+
_lang;
|
|
25
|
+
conflictResolution = /* @__PURE__ */ new Map();
|
|
26
|
+
CODEX_BACKUP_DIR = join(CODEX_DIR, "backup");
|
|
27
|
+
constructor(lang = "en") {
|
|
28
|
+
this._lang = lang;
|
|
29
|
+
this.conflictResolution.set("cli-package", ["config", "auth"]);
|
|
30
|
+
this.conflictResolution.set("config", ["api-config", "mcp-config"]);
|
|
31
|
+
void this._lang;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Remove config file (config.toml)
|
|
35
|
+
*/
|
|
36
|
+
async removeConfig() {
|
|
37
|
+
const result = {
|
|
38
|
+
success: false,
|
|
39
|
+
removed: [],
|
|
40
|
+
removedConfigs: [],
|
|
41
|
+
errors: [],
|
|
42
|
+
warnings: []
|
|
43
|
+
};
|
|
44
|
+
try {
|
|
45
|
+
if (await pathExists(CODEX_CONFIG_FILE)) {
|
|
46
|
+
const trashResult = await moveToTrash(CODEX_CONFIG_FILE);
|
|
47
|
+
if (!trashResult[0]?.success) {
|
|
48
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
49
|
+
}
|
|
50
|
+
result.removed.push("config.toml");
|
|
51
|
+
result.success = true;
|
|
52
|
+
} else {
|
|
53
|
+
result.warnings.push(i18n.t("codex:configNotFound"));
|
|
54
|
+
result.success = true;
|
|
55
|
+
}
|
|
56
|
+
} catch (error) {
|
|
57
|
+
result.errors.push(`Failed to remove config: ${error.message}`);
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Remove auth file (auth.json)
|
|
63
|
+
*/
|
|
64
|
+
async removeAuth() {
|
|
65
|
+
const result = {
|
|
66
|
+
success: false,
|
|
67
|
+
removed: [],
|
|
68
|
+
removedConfigs: [],
|
|
69
|
+
errors: [],
|
|
70
|
+
warnings: []
|
|
71
|
+
};
|
|
72
|
+
try {
|
|
73
|
+
if (await pathExists(CODEX_AUTH_FILE)) {
|
|
74
|
+
const trashResult = await moveToTrash(CODEX_AUTH_FILE);
|
|
75
|
+
if (!trashResult[0]?.success) {
|
|
76
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
77
|
+
}
|
|
78
|
+
result.removed.push("auth.json");
|
|
79
|
+
result.success = true;
|
|
80
|
+
} else {
|
|
81
|
+
result.warnings.push(i18n.t("codex:authNotFound"));
|
|
82
|
+
result.success = true;
|
|
83
|
+
}
|
|
84
|
+
} catch (error) {
|
|
85
|
+
result.errors.push(`Failed to remove auth: ${error.message}`);
|
|
86
|
+
}
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Remove system prompt file (AGENTS.md)
|
|
91
|
+
*/
|
|
92
|
+
async removeSystemPrompt() {
|
|
93
|
+
const result = {
|
|
94
|
+
success: false,
|
|
95
|
+
removed: [],
|
|
96
|
+
removedConfigs: [],
|
|
97
|
+
errors: [],
|
|
98
|
+
warnings: []
|
|
99
|
+
};
|
|
100
|
+
try {
|
|
101
|
+
if (await pathExists(CODEX_AGENTS_FILE)) {
|
|
102
|
+
const trashResult = await moveToTrash(CODEX_AGENTS_FILE);
|
|
103
|
+
if (!trashResult[0]?.success) {
|
|
104
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
105
|
+
}
|
|
106
|
+
result.removed.push("AGENTS.md");
|
|
107
|
+
result.success = true;
|
|
108
|
+
} else {
|
|
109
|
+
result.warnings.push(i18n.t("codex:systemPromptNotFound"));
|
|
110
|
+
result.success = true;
|
|
111
|
+
}
|
|
112
|
+
} catch (error) {
|
|
113
|
+
result.errors.push(`Failed to remove system prompt: ${error.message}`);
|
|
114
|
+
}
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Remove workflow directory (prompts/)
|
|
119
|
+
*/
|
|
120
|
+
async removeWorkflow() {
|
|
121
|
+
const result = {
|
|
122
|
+
success: false,
|
|
123
|
+
removed: [],
|
|
124
|
+
removedConfigs: [],
|
|
125
|
+
errors: [],
|
|
126
|
+
warnings: []
|
|
127
|
+
};
|
|
128
|
+
try {
|
|
129
|
+
if (await pathExists(CODEX_PROMPTS_DIR)) {
|
|
130
|
+
const trashResult = await moveToTrash(CODEX_PROMPTS_DIR);
|
|
131
|
+
if (!trashResult[0]?.success) {
|
|
132
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
133
|
+
}
|
|
134
|
+
result.removed.push("prompts/");
|
|
135
|
+
result.success = true;
|
|
136
|
+
} else {
|
|
137
|
+
result.warnings.push(i18n.t("codex:workflowNotFound"));
|
|
138
|
+
result.success = true;
|
|
139
|
+
}
|
|
140
|
+
} catch (error) {
|
|
141
|
+
result.errors.push(`Failed to remove workflow: ${error.message}`);
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Uninstall Codex CLI package
|
|
147
|
+
*/
|
|
148
|
+
async uninstallCliPackage() {
|
|
149
|
+
const result = {
|
|
150
|
+
success: false,
|
|
151
|
+
removed: [],
|
|
152
|
+
removedConfigs: [],
|
|
153
|
+
errors: [],
|
|
154
|
+
warnings: []
|
|
155
|
+
};
|
|
156
|
+
try {
|
|
157
|
+
const { uninstallCodeTool } = await import('./simple-config.mjs').then(function (n) { return n.db; });
|
|
158
|
+
const success = await uninstallCodeTool("codex");
|
|
159
|
+
if (success) {
|
|
160
|
+
result.removed.push("@openai/codex");
|
|
161
|
+
result.success = true;
|
|
162
|
+
} else {
|
|
163
|
+
result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:codex"), message: "" }));
|
|
164
|
+
}
|
|
165
|
+
} catch (error) {
|
|
166
|
+
if (error.message.includes("not found") || error.message.includes("not installed")) {
|
|
167
|
+
result.warnings.push(i18n.t("codex:packageNotFound"));
|
|
168
|
+
result.success = true;
|
|
169
|
+
} else {
|
|
170
|
+
result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:codex"), message: `: ${error.message}` }));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Remove API configuration from config.toml
|
|
177
|
+
*/
|
|
178
|
+
async removeApiConfig() {
|
|
179
|
+
const result = {
|
|
180
|
+
success: false,
|
|
181
|
+
removed: [],
|
|
182
|
+
removedConfigs: [],
|
|
183
|
+
errors: [],
|
|
184
|
+
warnings: []
|
|
185
|
+
};
|
|
186
|
+
try {
|
|
187
|
+
if (await pathExists(CODEX_CONFIG_FILE)) {
|
|
188
|
+
const { readFileSync, writeFileSync } = await import('node:fs');
|
|
189
|
+
const content = readFileSync(CODEX_CONFIG_FILE, "utf-8");
|
|
190
|
+
const lines = content.split("\n");
|
|
191
|
+
const newLines = [];
|
|
192
|
+
let inProviderSection = false;
|
|
193
|
+
let configModified = false;
|
|
194
|
+
for (const line of lines) {
|
|
195
|
+
if (line.trim().match(/^\[model_providers\./)) {
|
|
196
|
+
inProviderSection = true;
|
|
197
|
+
configModified = true;
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (inProviderSection && line.trim().startsWith("[") && !line.trim().match(/^\[model_providers\./)) {
|
|
201
|
+
inProviderSection = false;
|
|
202
|
+
}
|
|
203
|
+
if (inProviderSection) {
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (line.trim().startsWith("model_provider")) {
|
|
207
|
+
configModified = true;
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
newLines.push(line);
|
|
211
|
+
}
|
|
212
|
+
if (configModified) {
|
|
213
|
+
writeFileSync(CODEX_CONFIG_FILE, newLines.join("\n"));
|
|
214
|
+
result.removedConfigs.push(i18n.t("codex:apiConfigRemoved"));
|
|
215
|
+
}
|
|
216
|
+
result.success = true;
|
|
217
|
+
} else {
|
|
218
|
+
result.warnings.push(i18n.t("codex:configNotFound"));
|
|
219
|
+
result.success = true;
|
|
220
|
+
}
|
|
221
|
+
} catch (error) {
|
|
222
|
+
result.errors.push(`Failed to remove API config: ${error.message}`);
|
|
223
|
+
}
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Remove backup directory (~/.codex/backup/)
|
|
228
|
+
*/
|
|
229
|
+
async removeBackups() {
|
|
230
|
+
const result = {
|
|
231
|
+
success: false,
|
|
232
|
+
removed: [],
|
|
233
|
+
removedConfigs: [],
|
|
234
|
+
errors: [],
|
|
235
|
+
warnings: []
|
|
236
|
+
};
|
|
237
|
+
try {
|
|
238
|
+
if (await pathExists(this.CODEX_BACKUP_DIR)) {
|
|
239
|
+
const trashResult = await moveToTrash(this.CODEX_BACKUP_DIR);
|
|
240
|
+
if (!trashResult[0]?.success) {
|
|
241
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move backup directory to trash");
|
|
242
|
+
}
|
|
243
|
+
result.removed.push("backup/");
|
|
244
|
+
result.success = true;
|
|
245
|
+
} else {
|
|
246
|
+
result.warnings.push(i18n.t("codex:backupNotFound"));
|
|
247
|
+
result.success = true;
|
|
248
|
+
}
|
|
249
|
+
} catch (error) {
|
|
250
|
+
result.errors.push(`Failed to remove backups: ${error.message}`);
|
|
251
|
+
}
|
|
252
|
+
return result;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Remove MCP configuration from config.toml
|
|
256
|
+
*/
|
|
257
|
+
async removeMcpConfig() {
|
|
258
|
+
const result = {
|
|
259
|
+
success: false,
|
|
260
|
+
removed: [],
|
|
261
|
+
removedConfigs: [],
|
|
262
|
+
errors: [],
|
|
263
|
+
warnings: []
|
|
264
|
+
};
|
|
265
|
+
try {
|
|
266
|
+
if (await pathExists(CODEX_CONFIG_FILE)) {
|
|
267
|
+
const { readFileSync, writeFileSync } = await import('node:fs');
|
|
268
|
+
const content = readFileSync(CODEX_CONFIG_FILE, "utf-8");
|
|
269
|
+
const lines = content.split("\n");
|
|
270
|
+
const newLines = [];
|
|
271
|
+
let inMcpSection = false;
|
|
272
|
+
let configModified = false;
|
|
273
|
+
for (const line of lines) {
|
|
274
|
+
if (line.trim().match(/^\[mcp_servers\./)) {
|
|
275
|
+
inMcpSection = true;
|
|
276
|
+
configModified = true;
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
if (inMcpSection && line.trim().startsWith("[") && !line.trim().match(/^\[mcp_servers\./)) {
|
|
280
|
+
inMcpSection = false;
|
|
281
|
+
}
|
|
282
|
+
if (inMcpSection) {
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
newLines.push(line);
|
|
286
|
+
}
|
|
287
|
+
if (configModified) {
|
|
288
|
+
writeFileSync(CODEX_CONFIG_FILE, newLines.join("\n"));
|
|
289
|
+
result.removedConfigs.push(i18n.t("codex:mcpConfigRemoved"));
|
|
290
|
+
}
|
|
291
|
+
result.success = true;
|
|
292
|
+
} else {
|
|
293
|
+
result.warnings.push(i18n.t("codex:configNotFound"));
|
|
294
|
+
result.success = true;
|
|
295
|
+
}
|
|
296
|
+
} catch (error) {
|
|
297
|
+
result.errors.push(`Failed to remove MCP config: ${error.message}`);
|
|
298
|
+
}
|
|
299
|
+
return result;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Complete uninstall - remove all directories and packages
|
|
303
|
+
*/
|
|
304
|
+
async completeUninstall() {
|
|
305
|
+
const result = {
|
|
306
|
+
success: true,
|
|
307
|
+
removed: [],
|
|
308
|
+
removedConfigs: [],
|
|
309
|
+
errors: [],
|
|
310
|
+
warnings: []
|
|
311
|
+
};
|
|
312
|
+
try {
|
|
313
|
+
if (await pathExists(CODEX_DIR)) {
|
|
314
|
+
const trashResult = await moveToTrash(CODEX_DIR);
|
|
315
|
+
if (!trashResult[0]?.success) {
|
|
316
|
+
result.warnings.push(`Failed to move ~/.codex/ to trash: ${trashResult[0]?.error || "Unknown error"}`);
|
|
317
|
+
}
|
|
318
|
+
result.removed.push("~/.codex/");
|
|
319
|
+
}
|
|
320
|
+
const cliUninstallResult = await this.uninstallCliPackage();
|
|
321
|
+
result.removed.push(...cliUninstallResult.removed);
|
|
322
|
+
result.removedConfigs.push(...cliUninstallResult.removedConfigs);
|
|
323
|
+
result.errors.push(...cliUninstallResult.errors);
|
|
324
|
+
result.warnings.push(...cliUninstallResult.warnings);
|
|
325
|
+
result.success = result.success && cliUninstallResult.success;
|
|
326
|
+
} catch (error) {
|
|
327
|
+
result.errors.push(`Complete uninstall failed: ${error.message}`);
|
|
328
|
+
result.success = false;
|
|
329
|
+
}
|
|
330
|
+
return result;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Custom uninstall with conflict resolution
|
|
334
|
+
*/
|
|
335
|
+
async customUninstall(selectedItems) {
|
|
336
|
+
const resolvedItems = this.resolveConflicts(selectedItems);
|
|
337
|
+
const results = [];
|
|
338
|
+
for (const item of resolvedItems) {
|
|
339
|
+
try {
|
|
340
|
+
const result = await this.executeUninstallItem(item);
|
|
341
|
+
results.push(result);
|
|
342
|
+
} catch (error) {
|
|
343
|
+
results.push({
|
|
344
|
+
success: false,
|
|
345
|
+
removed: [],
|
|
346
|
+
removedConfigs: [],
|
|
347
|
+
errors: [`Failed to execute ${item}: ${error.message}`],
|
|
348
|
+
warnings: []
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return results;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Resolve conflicts between uninstall items
|
|
356
|
+
*/
|
|
357
|
+
resolveConflicts(items) {
|
|
358
|
+
const resolved = [...items];
|
|
359
|
+
for (const [primary, conflicts] of this.conflictResolution) {
|
|
360
|
+
if (resolved.includes(primary)) {
|
|
361
|
+
conflicts.forEach((conflict) => {
|
|
362
|
+
const index = resolved.indexOf(conflict);
|
|
363
|
+
if (index > -1) {
|
|
364
|
+
resolved.splice(index, 1);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return resolved;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Execute uninstall for a specific item
|
|
373
|
+
*/
|
|
374
|
+
async executeUninstallItem(item) {
|
|
375
|
+
switch (item) {
|
|
376
|
+
case "config":
|
|
377
|
+
return await this.removeConfig();
|
|
378
|
+
case "auth":
|
|
379
|
+
return await this.removeAuth();
|
|
380
|
+
case "system-prompt":
|
|
381
|
+
return await this.removeSystemPrompt();
|
|
382
|
+
case "workflow":
|
|
383
|
+
return await this.removeWorkflow();
|
|
384
|
+
case "cli-package":
|
|
385
|
+
return await this.uninstallCliPackage();
|
|
386
|
+
case "api-config":
|
|
387
|
+
return await this.removeApiConfig();
|
|
388
|
+
case "mcp-config":
|
|
389
|
+
return await this.removeMcpConfig();
|
|
390
|
+
case "backups":
|
|
391
|
+
return await this.removeBackups();
|
|
392
|
+
default:
|
|
393
|
+
return {
|
|
394
|
+
success: false,
|
|
395
|
+
removed: [],
|
|
396
|
+
removedConfigs: [],
|
|
397
|
+
errors: [`Unknown uninstall item: ${item}`],
|
|
398
|
+
warnings: []
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
export { CodexUninstaller };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { exec } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import ansis from 'ansis';
|
|
4
|
+
import { co as ensureI18nInitialized, cj as i18n } from './simple-config.mjs';
|
|
5
|
+
import 'node:fs';
|
|
6
|
+
import 'node:process';
|
|
7
|
+
import 'inquirer';
|
|
8
|
+
import 'pathe';
|
|
9
|
+
import 'smol-toml';
|
|
10
|
+
import 'dayjs';
|
|
11
|
+
import 'node:os';
|
|
12
|
+
import 'node:url';
|
|
13
|
+
import 'inquirer-toggle';
|
|
14
|
+
import 'ora';
|
|
15
|
+
import 'tinyexec';
|
|
16
|
+
import 'semver';
|
|
17
|
+
import 'node:fs/promises';
|
|
18
|
+
import 'fs-extra';
|
|
19
|
+
import 'trash';
|
|
20
|
+
import 'i18next';
|
|
21
|
+
import 'i18next-fs-backend';
|
|
22
|
+
|
|
23
|
+
const execAsync = promisify(exec);
|
|
24
|
+
async function runCcrUi(apiKey) {
|
|
25
|
+
ensureI18nInitialized();
|
|
26
|
+
console.log(ansis.cyan(`
|
|
27
|
+
\u{1F5A5}\uFE0F ${i18n.t("ccr:startingCcrUi")}`));
|
|
28
|
+
if (apiKey) {
|
|
29
|
+
console.log(ansis.bold.green(`
|
|
30
|
+
\u{1F511} ${i18n.t("ccr:ccrUiApiKey") || "CCR UI API Key"}: ${apiKey}`));
|
|
31
|
+
console.log(ansis.gray(` ${i18n.t("ccr:ccrUiApiKeyHint") || "Use this API key to login to CCR UI"}
|
|
32
|
+
`));
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const { stdout, stderr } = await execAsync("ccr ui");
|
|
36
|
+
if (stdout)
|
|
37
|
+
console.log(stdout);
|
|
38
|
+
if (stderr)
|
|
39
|
+
console.error(ansis.yellow(stderr));
|
|
40
|
+
console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrUiStarted")}`));
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error(ansis.red(`\u2716 ${i18n.t("ccr:ccrCommandFailed")}: ${error instanceof Error ? error.message : String(error)}`));
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async function runCcrStatus() {
|
|
47
|
+
ensureI18nInitialized();
|
|
48
|
+
console.log(ansis.cyan(`
|
|
49
|
+
\u{1F4CA} ${i18n.t("ccr:checkingCcrStatus")}`));
|
|
50
|
+
try {
|
|
51
|
+
const { stdout, stderr } = await execAsync("ccr status");
|
|
52
|
+
if (stdout) {
|
|
53
|
+
console.log(`
|
|
54
|
+
${ansis.bold(i18n.t("ccr:ccrStatusTitle"))}`);
|
|
55
|
+
console.log(stdout);
|
|
56
|
+
}
|
|
57
|
+
if (stderr)
|
|
58
|
+
console.error(ansis.yellow(stderr));
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error(ansis.red(`\u2716 ${i18n.t("ccr:ccrCommandFailed")}: ${error instanceof Error ? error.message : String(error)}`));
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function runCcrRestart() {
|
|
65
|
+
ensureI18nInitialized();
|
|
66
|
+
console.log(ansis.cyan(`
|
|
67
|
+
\u{1F504} ${i18n.t("ccr:restartingCcr")}`));
|
|
68
|
+
try {
|
|
69
|
+
const { stdout, stderr } = await execAsync("ccr restart");
|
|
70
|
+
if (stdout)
|
|
71
|
+
console.log(stdout);
|
|
72
|
+
if (stderr)
|
|
73
|
+
console.error(ansis.yellow(stderr));
|
|
74
|
+
console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrRestarted")}`));
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error(ansis.red(`\u2716 ${i18n.t("ccr:ccrCommandFailed")}: ${error instanceof Error ? error.message : String(error)}`));
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function runCcrStart() {
|
|
81
|
+
ensureI18nInitialized();
|
|
82
|
+
console.log(ansis.cyan(`
|
|
83
|
+
\u25B6\uFE0F ${i18n.t("ccr:startingCcr")}`));
|
|
84
|
+
try {
|
|
85
|
+
const { stdout, stderr } = await execAsync("ccr start");
|
|
86
|
+
if (stdout)
|
|
87
|
+
console.log(stdout);
|
|
88
|
+
if (stderr)
|
|
89
|
+
console.error(ansis.yellow(stderr));
|
|
90
|
+
console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrStarted")}`));
|
|
91
|
+
} catch (error) {
|
|
92
|
+
if (error.stdout && error.stdout.includes("Loaded JSON config from:")) {
|
|
93
|
+
console.log(error.stdout);
|
|
94
|
+
if (error.stderr)
|
|
95
|
+
console.error(ansis.yellow(error.stderr));
|
|
96
|
+
console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrStarted")}`));
|
|
97
|
+
} else {
|
|
98
|
+
console.error(ansis.red(`\u2716 ${i18n.t("ccr:ccrCommandFailed")}: ${error instanceof Error ? error.message : String(error)}`));
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async function runCcrStop() {
|
|
104
|
+
ensureI18nInitialized();
|
|
105
|
+
console.log(ansis.cyan(`
|
|
106
|
+
\u23F9\uFE0F ${i18n.t("ccr:stoppingCcr")}`));
|
|
107
|
+
try {
|
|
108
|
+
const { stdout, stderr } = await execAsync("ccr stop");
|
|
109
|
+
if (stdout)
|
|
110
|
+
console.log(stdout);
|
|
111
|
+
if (stderr)
|
|
112
|
+
console.error(ansis.yellow(stderr));
|
|
113
|
+
console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrStopped")}`));
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error(ansis.red(`\u2716 ${i18n.t("ccr:ccrCommandFailed")}: ${error instanceof Error ? error.message : String(error)}`));
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export { runCcrRestart, runCcrStart, runCcrStatus, runCcrStop, runCcrUi };
|