ccjk 2.0.20 → 2.2.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.
Files changed (71) hide show
  1. package/README.md +601 -35
  2. package/README.zh-CN.md +651 -0
  3. package/dist/chunks/api.mjs +100 -0
  4. package/dist/chunks/auto-updater.mjs +252 -0
  5. package/dist/chunks/ccjk-config.mjs +261 -0
  6. package/dist/chunks/ccr.mjs +77 -0
  7. package/dist/chunks/ccu.mjs +36 -0
  8. package/dist/chunks/check-updates.mjs +93 -0
  9. package/dist/chunks/claude-code-config-manager.mjs +28 -21
  10. package/dist/chunks/claude-code-incremental-manager.mjs +26 -18
  11. package/dist/chunks/claude-config.mjs +228 -0
  12. package/dist/chunks/codex.mjs +2134 -0
  13. package/dist/chunks/commands.mjs +2 -15
  14. package/dist/chunks/commit.mjs +119 -0
  15. package/dist/chunks/config-consolidator.mjs +281 -0
  16. package/dist/chunks/config-switch.mjs +302 -0
  17. package/dist/chunks/constants.mjs +156 -0
  18. package/dist/chunks/doctor.mjs +708 -0
  19. package/dist/chunks/features.mjs +35 -640
  20. package/dist/chunks/features2.mjs +661 -0
  21. package/dist/chunks/fs-operations.mjs +180 -0
  22. package/dist/chunks/index.mjs +3082 -0
  23. package/dist/chunks/index2.mjs +145 -0
  24. package/dist/chunks/init.mjs +2468 -0
  25. package/dist/chunks/interview.mjs +2916 -0
  26. package/dist/chunks/json-config.mjs +59 -0
  27. package/dist/chunks/marketplace.mjs +258 -0
  28. package/dist/chunks/mcp-doctor.mjs +160 -0
  29. package/dist/chunks/mcp-market.mjs +475 -0
  30. package/dist/chunks/mcp-performance.mjs +110 -0
  31. package/dist/chunks/mcp-profile.mjs +220 -0
  32. package/dist/chunks/mcp-release.mjs +138 -0
  33. package/dist/chunks/menu.mjs +3599 -0
  34. package/dist/chunks/notification.mjs +2336 -0
  35. package/dist/chunks/onboarding.mjs +711 -0
  36. package/dist/chunks/package.mjs +4 -0
  37. package/dist/chunks/permission-manager.mjs +210 -0
  38. package/dist/chunks/platform.mjs +321 -0
  39. package/dist/chunks/prompts.mjs +228 -0
  40. package/dist/chunks/session.mjs +355 -0
  41. package/dist/chunks/shencha.mjs +320 -0
  42. package/dist/chunks/skills-sync.mjs +4 -13
  43. package/dist/chunks/team.mjs +51 -0
  44. package/dist/chunks/tools.mjs +169 -0
  45. package/dist/chunks/uninstall.mjs +784 -0
  46. package/dist/chunks/update.mjs +104 -0
  47. package/dist/chunks/upgrade-manager.mjs +197 -0
  48. package/dist/chunks/workflows.mjs +100 -0
  49. package/dist/cli.mjs +581 -15348
  50. package/dist/i18n/locales/zh-CN/cli.json +1 -1
  51. package/dist/i18n/locales/zh-CN/common.json +1 -1
  52. package/dist/index.mjs +43 -2062
  53. package/dist/shared/ccjk.-FoZ3zat.mjs +761 -0
  54. package/dist/shared/ccjk.B7169qud.mjs +25 -0
  55. package/dist/shared/ccjk.BhKlRJ0h.mjs +114 -0
  56. package/dist/shared/ccjk.Bi-m3LKY.mjs +357 -0
  57. package/dist/shared/ccjk.COdsoe-Y.mjs +64 -0
  58. package/dist/shared/ccjk.CUdzQluX.mjs +46 -0
  59. package/dist/shared/ccjk.Cy-RH2qV.mjs +506 -0
  60. package/dist/shared/ccjk.DGjQxTq_.mjs +34 -0
  61. package/dist/shared/ccjk.DJM5aVQJ.mjs +586 -0
  62. package/dist/shared/ccjk.DhBeLRzf.mjs +28 -0
  63. package/dist/shared/ccjk.DwDtZ5cK.mjs +266 -0
  64. package/dist/shared/ccjk.n_AtlHzB.mjs +186 -0
  65. package/dist/shared/ccjk.qYAnUMuy.mjs +749 -0
  66. package/package.json +29 -25
  67. package/dist/chunks/codex-config-switch.mjs +0 -429
  68. package/dist/chunks/codex-provider-manager.mjs +0 -234
  69. package/dist/chunks/codex-uninstaller.mjs +0 -406
  70. package/dist/chunks/plugin-recommendation.mjs +0 -575
  71. package/dist/chunks/simple-config.mjs +0 -10950
@@ -0,0 +1,25 @@
1
+ import process from 'node:process';
2
+ import ansis from 'ansis';
3
+ import { ensureI18nInitialized, i18n } from '../chunks/index2.mjs';
4
+
5
+ function handleExitPromptError(error) {
6
+ const isExitError = error instanceof Error && (error.name === "ExitPromptError" || error.message?.includes("ExitPromptError") || error.message?.includes("User force closed the prompt"));
7
+ if (isExitError) {
8
+ ensureI18nInitialized();
9
+ console.log(ansis.cyan(`
10
+ ${i18n.t("common:goodbye")}
11
+ `));
12
+ process.exit(0);
13
+ }
14
+ return false;
15
+ }
16
+ function handleGeneralError(error) {
17
+ ensureI18nInitialized();
18
+ console.error(ansis.red(`${i18n.t("errors:generalError")}:`), error);
19
+ if (error instanceof Error) {
20
+ console.error(ansis.gray(`${i18n.t("errors:stackTrace")}: ${error.stack}`));
21
+ }
22
+ process.exit(1);
23
+ }
24
+
25
+ export { handleGeneralError as a, handleExitPromptError as h };
@@ -0,0 +1,114 @@
1
+ import ansis from 'ansis';
2
+ import { homepage, version } from '../chunks/package.mjs';
3
+ import { ensureI18nInitialized, i18n } from '../chunks/index2.mjs';
4
+
5
+ const COLORS = {
6
+ primary: ansis.hex("#00D4FF"),
7
+ // Cyan blue
8
+ secondary: ansis.hex("#00FF88"),
9
+ // Spring green
10
+ accent: ansis.hex("#FFD700"),
11
+ // Gold
12
+ warning: ansis.hex("#FFA500"),
13
+ // Orange
14
+ error: ansis.hex("#FF4444"),
15
+ // Red
16
+ success: ansis.hex("#00FF7F"),
17
+ // Green
18
+ muted: ansis.gray,
19
+ bold: ansis.bold
20
+ };
21
+ function getDisplayWidth(str) {
22
+ let width = 0;
23
+ for (const char of str) {
24
+ if (char.match(/[\u4E00-\u9FFF\uFF01-\uFF60\u3000-\u303F]/)) {
25
+ width += 2;
26
+ } else {
27
+ width += 1;
28
+ }
29
+ }
30
+ return width;
31
+ }
32
+ function padToDisplayWidth(str, targetWidth) {
33
+ const currentWidth = getDisplayWidth(str);
34
+ const paddingNeeded = Math.max(0, targetWidth - currentWidth);
35
+ return str + " ".repeat(paddingNeeded);
36
+ }
37
+ function displayBanner(subtitle) {
38
+ ensureI18nInitialized();
39
+ const defaultSubtitle = i18n.t("cli:banner.subtitle");
40
+ const subtitleText = subtitle || defaultSubtitle;
41
+ const paddedSubtitle = padToDisplayWidth(subtitleText, 28);
42
+ console.log(
43
+ ansis.cyan.bold(`
44
+ \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
45
+ \u2551 \u2551
46
+ \u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2551
47
+ \u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2554\u255D \u2551
48
+ \u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2554\u255D ${ansis.white.bold("JinKu")} \u2551
49
+ \u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2588\u2588\u2557 ${ansis.gray(`v${version}`)}${" ".repeat(Math.max(0, 17 - version.length))}\u2551
50
+ \u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2557 \u2551
51
+ \u2551 \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D ${ansis.gray(paddedSubtitle)} \u2551
52
+ \u2551 \u2551
53
+ \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
54
+ `)
55
+ );
56
+ }
57
+ function displayBannerWithInfo(subtitle) {
58
+ displayBanner(subtitle);
59
+ console.log(ansis.gray(` ${ansis.cyan("ccjk")} - Advanced AI Development Assistant`));
60
+ console.log(ansis.gray(` ${ansis.cyan(homepage)}
61
+ `));
62
+ }
63
+ function renderProgressBar(progress, width = 30) {
64
+ const filled = Math.round(progress / 100 * width);
65
+ const empty = width - filled;
66
+ const bar = COLORS.primary("\u2588".repeat(filled)) + ansis.gray("\u2591".repeat(empty));
67
+ const percentage = `${Math.round(progress)}%`.padStart(4);
68
+ return `[${bar}] ${ansis.cyan(percentage)}`;
69
+ }
70
+ const BOX_CHARS = {
71
+ single: { tl: "\u250C", tr: "\u2510", bl: "\u2514", br: "\u2518", h: "\u2500", v: "\u2502" },
72
+ double: { tl: "\u2554", tr: "\u2557", bl: "\u255A", br: "\u255D", h: "\u2550", v: "\u2551" },
73
+ rounded: { tl: "\u256D", tr: "\u256E", bl: "\u2570", br: "\u256F", h: "\u2500", v: "\u2502" },
74
+ heavy: { tl: "\u250F", tr: "\u2513", bl: "\u2517", br: "\u251B", h: "\u2501", v: "\u2503" }
75
+ };
76
+ function boxify(content, style = "double", title) {
77
+ const chars = BOX_CHARS[style];
78
+ const lines = content.split("\n");
79
+ const maxWidth = Math.max(...lines.map(getDisplayWidth), title ? getDisplayWidth(title) + 4 : 0);
80
+ const paddedLines = lines.map((line) => {
81
+ const padding = maxWidth - getDisplayWidth(line);
82
+ return `${chars.v} ${line}${" ".repeat(padding)} ${chars.v}`;
83
+ });
84
+ let topBorder = `${chars.tl}${chars.h.repeat(maxWidth + 2)}${chars.tr}`;
85
+ if (title) {
86
+ const titlePadding = Math.floor((maxWidth - getDisplayWidth(title)) / 2);
87
+ topBorder = `${chars.tl}${chars.h.repeat(titlePadding)} ${title} ${chars.h.repeat(maxWidth - titlePadding - getDisplayWidth(title))}${chars.tr}`;
88
+ }
89
+ const bottomBorder = `${chars.bl}${chars.h.repeat(maxWidth + 2)}${chars.br}`;
90
+ return [topBorder, ...paddedLines, bottomBorder].join("\n");
91
+ }
92
+ function sectionDivider(title, width = 50) {
93
+ if (!title) {
94
+ return ansis.cyan("\u2550".repeat(width));
95
+ }
96
+ const padding = Math.floor((width - getDisplayWidth(title) - 2) / 2);
97
+ return ansis.cyan(`${"\u2550".repeat(padding)} ${ansis.white.bold(title)} ${"\u2550".repeat(width - padding - getDisplayWidth(title) - 2)}`);
98
+ }
99
+ const STATUS = {
100
+ success: (text) => `${ansis.green("\u2713")} ${text}`,
101
+ error: (text) => `${ansis.red("\u2717")} ${text}`,
102
+ warning: (text) => `${ansis.yellow("\u26A0")} ${text}`,
103
+ info: (text) => `${ansis.blue("\u2139")} ${text}`,
104
+ pending: (text) => `${ansis.gray("\u25CB")} ${text}`,
105
+ inProgress: (text) => `${ansis.cyan("\u25D0")} ${text}`
106
+ };
107
+ function menuItem(key, label, description) {
108
+ const keyPart = ansis.cyan.bold(`[${key}]`);
109
+ const labelPart = ansis.white(label);
110
+ const descPart = description ? ansis.gray(` - ${description}`) : "";
111
+ return ` ${keyPart} ${labelPart}${descPart}`;
112
+ }
113
+
114
+ export { COLORS as C, STATUS as S, displayBannerWithInfo as a, boxify as b, displayBanner as d, getDisplayWidth as g, menuItem as m, padToDisplayWidth as p, renderProgressBar as r, sectionDivider as s };
@@ -0,0 +1,357 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { readFile, mkdir, rm } from 'node:fs/promises';
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'pathe';
5
+ import { i18n } from '../chunks/index2.mjs';
6
+ import { writeFileAtomicAsync } from '../chunks/fs-operations.mjs';
7
+
8
+ const DEFAULT_REGISTRY_URL = "https://registry.ccjk.dev/v1";
9
+ const DEFAULT_CACHE_CONFIG = {
10
+ cacheDir: join(homedir(), ".ccjk", "cache"),
11
+ ttl: 3600,
12
+ // 1 hour
13
+ enabled: true
14
+ };
15
+ const BUILTIN_PACKAGES = [
16
+ // Built-in packages will be added here in future versions
17
+ ];
18
+ function getCacheFilePath(cacheDir) {
19
+ return join(cacheDir, "registry-cache.json");
20
+ }
21
+ async function isCacheValid(cacheDir, ttl) {
22
+ const cachePath = getCacheFilePath(cacheDir);
23
+ if (!existsSync(cachePath)) {
24
+ return false;
25
+ }
26
+ try {
27
+ const content = await readFile(cachePath, "utf-8");
28
+ const cache = JSON.parse(content);
29
+ const cacheTime = new Date(cache.lastUpdated).getTime();
30
+ const now = Date.now();
31
+ return now - cacheTime < ttl * 1e3;
32
+ } catch {
33
+ return false;
34
+ }
35
+ }
36
+ async function readCachedRegistry(cacheDir) {
37
+ const cachePath = getCacheFilePath(cacheDir);
38
+ if (!existsSync(cachePath)) {
39
+ return null;
40
+ }
41
+ try {
42
+ const content = await readFile(cachePath, "utf-8");
43
+ return JSON.parse(content);
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
48
+ async function writeCacheRegistry(cacheDir, registry) {
49
+ await mkdir(cacheDir, { recursive: true });
50
+ const cachePath = getCacheFilePath(cacheDir);
51
+ await writeFileAtomicAsync(cachePath, JSON.stringify(registry, null, 2));
52
+ }
53
+ async function fetchRemoteRegistry(registryUrl = DEFAULT_REGISTRY_URL, timeout = 3e4) {
54
+ const controller = new AbortController();
55
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
56
+ try {
57
+ const response = await fetch(`${registryUrl}/registry.json`, {
58
+ signal: controller.signal,
59
+ headers: {
60
+ "Accept": "application/json",
61
+ "User-Agent": "ccjk-cli"
62
+ }
63
+ });
64
+ if (!response.ok) {
65
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
66
+ }
67
+ return await response.json();
68
+ } finally {
69
+ clearTimeout(timeoutId);
70
+ }
71
+ }
72
+ async function getRegistry(options = {}) {
73
+ const cacheConfig = { ...DEFAULT_CACHE_CONFIG, ...options.cache };
74
+ const registryUrl = options.registryUrl || DEFAULT_REGISTRY_URL;
75
+ if (cacheConfig.enabled && !options.forceRefresh) {
76
+ const cacheValid = await isCacheValid(cacheConfig.cacheDir, cacheConfig.ttl);
77
+ if (cacheValid) {
78
+ const cached = await readCachedRegistry(cacheConfig.cacheDir);
79
+ if (cached) {
80
+ return cached;
81
+ }
82
+ }
83
+ }
84
+ try {
85
+ const registry = await fetchRemoteRegistry(registryUrl);
86
+ if (cacheConfig.enabled) {
87
+ await writeCacheRegistry(cacheConfig.cacheDir, registry);
88
+ }
89
+ return registry;
90
+ } catch {
91
+ const cached = await readCachedRegistry(cacheConfig.cacheDir);
92
+ if (cached) {
93
+ return cached;
94
+ }
95
+ return {
96
+ version: "1.0.0",
97
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
98
+ url: registryUrl,
99
+ packages: BUILTIN_PACKAGES,
100
+ categories: {
101
+ "plugin": 0,
102
+ "skill": 0,
103
+ "workflow": 0,
104
+ "agent": 0,
105
+ "mcp-service": 0,
106
+ "output-style": 0,
107
+ "bundle": 0
108
+ }
109
+ };
110
+ }
111
+ }
112
+ async function searchPackages(options = {}) {
113
+ const registry = await getRegistry();
114
+ let packages = [...registry.packages];
115
+ if (options.query) {
116
+ const query = options.query.toLowerCase();
117
+ packages = packages.filter(
118
+ (pkg) => pkg.name.toLowerCase().includes(query) || pkg.id.toLowerCase().includes(query) || pkg.keywords.some((k) => k.toLowerCase().includes(query)) || Object.values(pkg.description).some((d) => d.toLowerCase().includes(query))
119
+ );
120
+ }
121
+ if (options.category) {
122
+ packages = packages.filter((pkg) => pkg.category === options.category);
123
+ }
124
+ if (options.author) {
125
+ packages = packages.filter(
126
+ (pkg) => pkg.author.toLowerCase().includes(options.author.toLowerCase())
127
+ );
128
+ }
129
+ if (options.verified) {
130
+ packages = packages.filter((pkg) => pkg.verified === options.verified);
131
+ }
132
+ if (options.keywords?.length) {
133
+ packages = packages.filter(
134
+ (pkg) => options.keywords.some((k) => pkg.keywords.includes(k))
135
+ );
136
+ }
137
+ if (options.minRating) {
138
+ packages = packages.filter((pkg) => pkg.rating >= options.minRating);
139
+ }
140
+ if (options.supportedTool) {
141
+ packages = packages.filter(
142
+ (pkg) => pkg.supportedTools?.includes(options.supportedTool)
143
+ );
144
+ }
145
+ const sortBy = options.sortBy || "downloads";
146
+ const sortDir = options.sortDir || "desc";
147
+ packages.sort((a, b) => {
148
+ let comparison = 0;
149
+ switch (sortBy) {
150
+ case "downloads":
151
+ comparison = a.downloads - b.downloads;
152
+ break;
153
+ case "rating":
154
+ comparison = a.rating - b.rating;
155
+ break;
156
+ case "updated":
157
+ comparison = new Date(a.updatedAt).getTime() - new Date(b.updatedAt).getTime();
158
+ break;
159
+ case "created":
160
+ comparison = new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
161
+ break;
162
+ case "name":
163
+ comparison = a.name.localeCompare(b.name);
164
+ break;
165
+ }
166
+ return sortDir === "desc" ? -comparison : comparison;
167
+ });
168
+ const total = packages.length;
169
+ const offset = options.offset || 0;
170
+ const limit = options.limit || 20;
171
+ packages = packages.slice(offset, offset + limit);
172
+ return {
173
+ packages,
174
+ total,
175
+ offset,
176
+ limit,
177
+ query: options.query,
178
+ filters: options
179
+ };
180
+ }
181
+ async function getPackage(packageId) {
182
+ const registry = await getRegistry();
183
+ return registry.packages.find((pkg) => pkg.id === packageId) || null;
184
+ }
185
+
186
+ const DEFAULT_INSTALL_DIR = join(homedir(), ".ccjk", "packages");
187
+ const INSTALLED_MANIFEST = join(homedir(), ".ccjk", "installed-packages.json");
188
+ async function getInstalledPackages() {
189
+ if (!existsSync(INSTALLED_MANIFEST)) {
190
+ return [];
191
+ }
192
+ try {
193
+ const content = await readFile(INSTALLED_MANIFEST, "utf-8");
194
+ return JSON.parse(content);
195
+ } catch {
196
+ return [];
197
+ }
198
+ }
199
+ async function saveInstalledPackages(packages) {
200
+ const dir = join(homedir(), ".ccjk");
201
+ await mkdir(dir, { recursive: true });
202
+ await writeFileAtomicAsync(INSTALLED_MANIFEST, JSON.stringify(packages, null, 2));
203
+ }
204
+ async function isPackageInstalled(packageId) {
205
+ const installed = await getInstalledPackages();
206
+ return installed.some((pkg) => pkg.package.id === packageId);
207
+ }
208
+ async function installPackage(packageId, options = {}) {
209
+ const startTime = Date.now();
210
+ try {
211
+ const alreadyInstalled = await isPackageInstalled(packageId);
212
+ if (alreadyInstalled && !options.force) {
213
+ const pkg2 = await getPackage(packageId);
214
+ if (!pkg2) {
215
+ return {
216
+ success: false,
217
+ package: {},
218
+ error: i18n.t("marketplace:packageNotFound", { name: packageId })
219
+ };
220
+ }
221
+ return {
222
+ success: true,
223
+ package: pkg2,
224
+ alreadyInstalled: true,
225
+ durationMs: Date.now() - startTime
226
+ };
227
+ }
228
+ const pkg = await getPackage(packageId);
229
+ if (!pkg) {
230
+ return {
231
+ success: false,
232
+ package: {},
233
+ error: i18n.t("marketplace:packageNotFound", { name: packageId })
234
+ };
235
+ }
236
+ const warnings = [];
237
+ if (options.codeToolType && pkg.supportedTools) {
238
+ if (!pkg.supportedTools.includes(options.codeToolType)) {
239
+ warnings.push(
240
+ i18n.t("marketplace:incompatibleTool", {
241
+ tool: options.codeToolType,
242
+ supported: pkg.supportedTools.join(", ")
243
+ })
244
+ );
245
+ }
246
+ }
247
+ const targetDir = options.targetDir || DEFAULT_INSTALL_DIR;
248
+ const installPath = join(targetDir, pkg.id);
249
+ await mkdir(installPath, { recursive: true });
250
+ const installed = await getInstalledPackages();
251
+ const installedPackage = {
252
+ package: pkg,
253
+ path: installPath,
254
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
255
+ source: "marketplace",
256
+ enabled: true
257
+ };
258
+ const existingIndex = installed.findIndex((p) => p.package.id === pkg.id);
259
+ if (existingIndex >= 0) {
260
+ installed[existingIndex] = installedPackage;
261
+ } else {
262
+ installed.push(installedPackage);
263
+ }
264
+ await saveInstalledPackages(installed);
265
+ return {
266
+ success: true,
267
+ package: pkg,
268
+ installedPath: installPath,
269
+ warnings: warnings.length > 0 ? warnings : void 0,
270
+ durationMs: Date.now() - startTime
271
+ };
272
+ } catch (error) {
273
+ return {
274
+ success: false,
275
+ package: {},
276
+ error: error instanceof Error ? error.message : String(error),
277
+ durationMs: Date.now() - startTime
278
+ };
279
+ }
280
+ }
281
+ async function uninstallPackage(packageId, options = {}) {
282
+ try {
283
+ const installed = await getInstalledPackages();
284
+ const pkg = installed.find((p) => p.package.id === packageId);
285
+ if (!pkg) {
286
+ return {
287
+ success: false,
288
+ packageId,
289
+ error: i18n.t("marketplace:packageNotInstalled", { name: packageId })
290
+ };
291
+ }
292
+ if (!options.force) {
293
+ const dependents = installed.filter(
294
+ (p) => p.package.dependencies && Object.keys(p.package.dependencies).includes(packageId)
295
+ );
296
+ if (dependents.length > 0) {
297
+ return {
298
+ success: false,
299
+ packageId,
300
+ error: i18n.t("marketplace:packageHasDependents", {
301
+ name: packageId,
302
+ dependents: dependents.map((p) => p.package.name).join(", ")
303
+ })
304
+ };
305
+ }
306
+ }
307
+ if (existsSync(pkg.path)) {
308
+ await rm(pkg.path, { recursive: true, force: true });
309
+ }
310
+ const updated = installed.filter((p) => p.package.id !== packageId);
311
+ await saveInstalledPackages(updated);
312
+ return {
313
+ success: true,
314
+ packageId
315
+ };
316
+ } catch (error) {
317
+ return {
318
+ success: false,
319
+ packageId,
320
+ error: error instanceof Error ? error.message : String(error)
321
+ };
322
+ }
323
+ }
324
+ async function updatePackage(packageId) {
325
+ const uninstallResult = await uninstallPackage(packageId, { keepConfig: true });
326
+ if (!uninstallResult.success) {
327
+ return {
328
+ success: false,
329
+ package: {},
330
+ error: uninstallResult.error
331
+ };
332
+ }
333
+ return await installPackage(packageId, { force: true });
334
+ }
335
+ async function checkForUpdates() {
336
+ const installed = await getInstalledPackages();
337
+ const updates = [];
338
+ for (const installedPkg of installed) {
339
+ const latestPkg = await getPackage(installedPkg.package.id);
340
+ if (!latestPkg)
341
+ continue;
342
+ if (latestPkg.version !== installedPkg.package.version) {
343
+ updates.push({
344
+ id: installedPkg.package.id,
345
+ currentVersion: installedPkg.package.version,
346
+ latestVersion: latestPkg.version,
347
+ breaking: false,
348
+ // TODO: Implement semver comparison
349
+ changelog: latestPkg.changelog,
350
+ releaseDate: latestPkg.updatedAt
351
+ });
352
+ }
353
+ }
354
+ return updates;
355
+ }
356
+
357
+ export { getPackage as a, uninstallPackage as b, checkForUpdates as c, installPackage as d, getInstalledPackages as g, isPackageInstalled as i, searchPackages as s, updatePackage as u };
@@ -0,0 +1,64 @@
1
+ const MCP_TIER_DEFAULTS = {
2
+ core: {
3
+ tier: "core",
4
+ autoStart: true,
5
+ idleTimeout: void 0,
6
+ // Never timeout
7
+ description: "Essential services, always available"
8
+ },
9
+ ondemand: {
10
+ tier: "ondemand",
11
+ autoStart: false,
12
+ idleTimeout: 300,
13
+ // 5 minutes
14
+ description: "Loaded when needed, auto-released after idle"
15
+ },
16
+ scenario: {
17
+ tier: "scenario",
18
+ autoStart: false,
19
+ idleTimeout: 600,
20
+ // 10 minutes
21
+ description: "Loaded for specific scenarios"
22
+ }
23
+ };
24
+ const MCP_SERVICE_TIERS = {
25
+ // Core services - high frequency, essential
26
+ "context7": "core",
27
+ "open-websearch": "core",
28
+ // On-demand services - medium frequency
29
+ "mcp-deepwiki": "ondemand",
30
+ "Playwright": "ondemand",
31
+ "puppeteer": "ondemand",
32
+ "filesystem": "ondemand",
33
+ "memory": "ondemand",
34
+ "sequential-thinking": "ondemand",
35
+ "fetch": "ondemand",
36
+ // Scenario services - low frequency, specific use cases
37
+ "sqlite": "scenario",
38
+ "spec-workflow": "scenario",
39
+ "serena": "scenario"
40
+ };
41
+ function getMcpTierConfig(serviceId) {
42
+ const tier = MCP_SERVICE_TIERS[serviceId] || "ondemand";
43
+ return MCP_TIER_DEFAULTS[tier];
44
+ }
45
+ function getServicesByTier(tier) {
46
+ return Object.entries(MCP_SERVICE_TIERS).filter(([_, t]) => t === tier).map(([id]) => id);
47
+ }
48
+ function isCoreService(serviceId) {
49
+ return MCP_SERVICE_TIERS[serviceId] === "core";
50
+ }
51
+ const MCP_PERFORMANCE_THRESHOLDS = {
52
+ /** Warning threshold for number of services */
53
+ warningCount: 5,
54
+ /** Critical threshold for number of services */
55
+ criticalCount: 8,
56
+ /** Maximum recommended services */
57
+ maxRecommended: 6,
58
+ /** Estimated memory per service (MB) */
59
+ estimatedMemoryPerService: 50,
60
+ /** Estimated CPU overhead per service (%) */
61
+ estimatedCpuPerService: 5
62
+ };
63
+
64
+ export { MCP_SERVICE_TIERS as M, getMcpTierConfig as a, MCP_PERFORMANCE_THRESHOLDS as b, getServicesByTier as g, isCoreService as i };
@@ -0,0 +1,46 @@
1
+ import { DEFAULT_CODE_TOOL_TYPE } from '../chunks/constants.mjs';
2
+ import { i18n } from '../chunks/index2.mjs';
3
+ import { readZcfConfigAsync } from '../chunks/ccjk-config.mjs';
4
+
5
+ const CODE_TYPE_ABBREVIATIONS = {
6
+ cc: "claude-code",
7
+ cx: "codex"
8
+ };
9
+ async function resolveCodeType(codeTypeParam) {
10
+ if (codeTypeParam) {
11
+ const normalizedParam = codeTypeParam.toLowerCase().trim();
12
+ if (normalizedParam in CODE_TYPE_ABBREVIATIONS) {
13
+ return CODE_TYPE_ABBREVIATIONS[normalizedParam];
14
+ }
15
+ if (isValidCodeType(normalizedParam)) {
16
+ return normalizedParam;
17
+ }
18
+ const validAbbreviations = Object.keys(CODE_TYPE_ABBREVIATIONS);
19
+ const validFullTypes = Object.values(CODE_TYPE_ABBREVIATIONS);
20
+ const validOptions = [...validAbbreviations, ...validFullTypes].join(", ");
21
+ let defaultValue = DEFAULT_CODE_TOOL_TYPE;
22
+ try {
23
+ const config = await readZcfConfigAsync();
24
+ if (config?.codeToolType && isValidCodeType(config.codeToolType)) {
25
+ defaultValue = config.codeToolType;
26
+ }
27
+ } catch {
28
+ }
29
+ throw new Error(
30
+ i18n.t("errors:invalidCodeType", { value: codeTypeParam, validOptions, defaultValue })
31
+ );
32
+ }
33
+ try {
34
+ const config = await readZcfConfigAsync();
35
+ if (config?.codeToolType && isValidCodeType(config.codeToolType)) {
36
+ return config.codeToolType;
37
+ }
38
+ } catch {
39
+ }
40
+ return DEFAULT_CODE_TOOL_TYPE;
41
+ }
42
+ function isValidCodeType(value) {
43
+ return ["claude-code", "codex"].includes(value);
44
+ }
45
+
46
+ export { resolveCodeType as r };