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.
Files changed (109) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja.md +455 -0
  3. package/README.ko.md +455 -0
  4. package/README.md +550 -0
  5. package/README.zh-CN.md +488 -0
  6. package/bin/ccjk.mjs +2 -0
  7. package/dist/chunks/api-providers.mjs +89 -0
  8. package/dist/chunks/claude-code-config-manager.mjs +733 -0
  9. package/dist/chunks/claude-code-incremental-manager.mjs +603 -0
  10. package/dist/chunks/codex-config-switch.mjs +427 -0
  11. package/dist/chunks/codex-provider-manager.mjs +232 -0
  12. package/dist/chunks/codex-uninstaller.mjs +404 -0
  13. package/dist/chunks/commands.mjs +120 -0
  14. package/dist/chunks/features.mjs +642 -0
  15. package/dist/chunks/simple-config.mjs +10445 -0
  16. package/dist/cli.d.mts +1 -0
  17. package/dist/cli.d.ts +1 -0
  18. package/dist/cli.mjs +5972 -0
  19. package/dist/i18n/locales/en/api.json +63 -0
  20. package/dist/i18n/locales/en/ccjk.json +276 -0
  21. package/dist/i18n/locales/en/ccr.json +65 -0
  22. package/dist/i18n/locales/en/cli.json +57 -0
  23. package/dist/i18n/locales/en/codex.json +124 -0
  24. package/dist/i18n/locales/en/cometix.json +29 -0
  25. package/dist/i18n/locales/en/common.json +20 -0
  26. package/dist/i18n/locales/en/configuration.json +77 -0
  27. package/dist/i18n/locales/en/errors.json +26 -0
  28. package/dist/i18n/locales/en/installation.json +80 -0
  29. package/dist/i18n/locales/en/interview.json +104 -0
  30. package/dist/i18n/locales/en/language.json +19 -0
  31. package/dist/i18n/locales/en/mcp.json +38 -0
  32. package/dist/i18n/locales/en/menu.json +51 -0
  33. package/dist/i18n/locales/en/multi-config.json +79 -0
  34. package/dist/i18n/locales/en/shencha.json +14 -0
  35. package/dist/i18n/locales/en/team.json +7 -0
  36. package/dist/i18n/locales/en/tools.json +42 -0
  37. package/dist/i18n/locales/en/uninstall.json +56 -0
  38. package/dist/i18n/locales/en/updater.json +25 -0
  39. package/dist/i18n/locales/en/workflow.json +25 -0
  40. package/dist/i18n/locales/zh-CN/api.json +63 -0
  41. package/dist/i18n/locales/zh-CN/ccjk.json +276 -0
  42. package/dist/i18n/locales/zh-CN/ccr.json +65 -0
  43. package/dist/i18n/locales/zh-CN/cli.json +57 -0
  44. package/dist/i18n/locales/zh-CN/codex.json +124 -0
  45. package/dist/i18n/locales/zh-CN/cometix.json +29 -0
  46. package/dist/i18n/locales/zh-CN/common.json +20 -0
  47. package/dist/i18n/locales/zh-CN/configuration.json +77 -0
  48. package/dist/i18n/locales/zh-CN/errors.json +26 -0
  49. package/dist/i18n/locales/zh-CN/installation.json +80 -0
  50. package/dist/i18n/locales/zh-CN/interview.json +104 -0
  51. package/dist/i18n/locales/zh-CN/language.json +19 -0
  52. package/dist/i18n/locales/zh-CN/mcp.json +38 -0
  53. package/dist/i18n/locales/zh-CN/menu.json +51 -0
  54. package/dist/i18n/locales/zh-CN/multi-config.json +79 -0
  55. package/dist/i18n/locales/zh-CN/shencha.json +14 -0
  56. package/dist/i18n/locales/zh-CN/team.json +7 -0
  57. package/dist/i18n/locales/zh-CN/tools.json +42 -0
  58. package/dist/i18n/locales/zh-CN/uninstall.json +56 -0
  59. package/dist/i18n/locales/zh-CN/updater.json +25 -0
  60. package/dist/i18n/locales/zh-CN/workflow.json +25 -0
  61. package/dist/index.d.mts +2644 -0
  62. package/dist/index.d.ts +2644 -0
  63. package/dist/index.mjs +1706 -0
  64. package/package.json +157 -0
  65. package/templates/CLAUDE.md +219 -0
  66. package/templates/claude-code/CLAUDE.md +250 -0
  67. package/templates/claude-code/common/settings.json +38 -0
  68. package/templates/claude-code/en/workflow/bmad/commands/bmad-init.md +165 -0
  69. package/templates/claude-code/en/workflow/common/agents/get-current-datetime.md +29 -0
  70. package/templates/claude-code/en/workflow/common/agents/init-architect.md +114 -0
  71. package/templates/claude-code/en/workflow/common/commands/init-project.md +53 -0
  72. package/templates/claude-code/en/workflow/plan/agents/planner.md +116 -0
  73. package/templates/claude-code/en/workflow/plan/agents/ui-ux-designer.md +91 -0
  74. package/templates/claude-code/en/workflow/plan/commands/feat.md +105 -0
  75. package/templates/claude-code/zh-CN/workflow/bmad/commands/bmad-init.md +172 -0
  76. package/templates/claude-code/zh-CN/workflow/common/agents/get-current-datetime.md +29 -0
  77. package/templates/claude-code/zh-CN/workflow/common/agents/init-architect.md +114 -0
  78. package/templates/claude-code/zh-CN/workflow/common/commands/init-project.md +53 -0
  79. package/templates/claude-code/zh-CN/workflow/plan/agents/planner.md +116 -0
  80. package/templates/claude-code/zh-CN/workflow/plan/agents/ui-ux-designer.md +91 -0
  81. package/templates/claude-code/zh-CN/workflow/plan/commands/feat.md +105 -0
  82. package/templates/codex/common/config.toml +0 -0
  83. package/templates/common/output-styles/en/casual-friendly.md +97 -0
  84. package/templates/common/output-styles/en/engineer-professional.md +88 -0
  85. package/templates/common/output-styles/en/expert-concise.md +93 -0
  86. package/templates/common/output-styles/en/laowang-engineer.md +127 -0
  87. package/templates/common/output-styles/en/nekomata-engineer.md +120 -0
  88. package/templates/common/output-styles/en/ojousama-engineer.md +121 -0
  89. package/templates/common/output-styles/en/teaching-mode.md +102 -0
  90. package/templates/common/output-styles/en/technical-precise.md +101 -0
  91. package/templates/common/output-styles/zh-CN/engineer-professional.md +89 -0
  92. package/templates/common/output-styles/zh-CN/laowang-engineer.md +127 -0
  93. package/templates/common/output-styles/zh-CN/nekomata-engineer.md +120 -0
  94. package/templates/common/output-styles/zh-CN/ojousama-engineer.md +121 -0
  95. package/templates/common/workflow/git/en/git-cleanBranches.md +102 -0
  96. package/templates/common/workflow/git/en/git-commit.md +205 -0
  97. package/templates/common/workflow/git/en/git-rollback.md +90 -0
  98. package/templates/common/workflow/git/en/git-worktree.md +276 -0
  99. package/templates/common/workflow/git/zh-CN/git-cleanBranches.md +102 -0
  100. package/templates/common/workflow/git/zh-CN/git-commit.md +205 -0
  101. package/templates/common/workflow/git/zh-CN/git-rollback.md +90 -0
  102. package/templates/common/workflow/git/zh-CN/git-worktree.md +276 -0
  103. package/templates/common/workflow/interview/en/interview.md +212 -0
  104. package/templates/common/workflow/interview/zh-CN/interview.md +212 -0
  105. package/templates/common/workflow/sixStep/en/workflow.md +251 -0
  106. package/templates/common/workflow/sixStep/zh-CN/workflow.md +215 -0
  107. package/templates/industry/devops/en/ci-cd-pipeline.md +410 -0
  108. package/templates/industry/web-dev/en/api-design.md +299 -0
  109. package/templates/industry/web-dev/en/react-nextjs-setup.md +236 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,1706 @@
1
+ import { C as CCJK_PLUGINS_DIR, a as CCJK_SKILLS_DIR, b as CCJK_GROUPS_DIR, A as AIDER_DIR, c as AIDER_CONFIG_FILE, d as AIDER_ENV_FILE, e as CONTINUE_DIR, f as CONTINUE_CONFIG_FILE, s as sectionDivider, g as COLORS, S as STATUS } from './chunks/simple-config.mjs';
2
+ export { $ as AI_OUTPUT_LANGUAGES, V as API_DEFAULT_URL, W as API_ENV_KEY, I as CCJK_CONFIG_DIR, J as CCJK_CONFIG_FILE, q as CLAUDE_DIR, u as CLAUDE_MD_FILE, w as CLAUDE_VSC_CONFIG_FILE, F as CLINE_CONFIG_FILE, E as CLINE_DIR, B as CODEX_AGENTS_FILE, z as CODEX_AUTH_FILE, y as CODEX_CONFIG_FILE, x as CODEX_DIR, D as CODEX_PROMPTS_DIR, R as CODE_TOOL_ALIASES, Q as CODE_TOOL_BANNERS, T as CODE_TOOL_INFO, O as CODE_TOOL_TYPES, H as CURSOR_CONFIG_FILE, G as CURSOR_DIR, v as ClAUDE_CONFIG_FILE, P as DEFAULT_CODE_TOOL_TYPE, _ as LANG_LABELS, L as LEGACY_ZCF_CONFIG_DIR, K as LEGACY_ZCF_CONFIG_FILE, M as LEGACY_ZCF_CONFIG_FILES, bX as PERMISSION_TEMPLATES, t as SETTINGS_FILE, Y as SUPPORTED_LANGS, Z as ZCF_CONFIG_DIR, N as ZCF_CONFIG_FILE, c3 as addAutoApprovePattern, an as addCompletedOnboarding, bp as applyAiLanguageDirective, b1 as applyCodexPlatformCommand, b_ as applyTemplate, as as backupCodexAgents, at as backupCodexComplete, au as backupCodexConfig, av as backupCodexFiles, aw as backupCodexPrompts, bg as backupExistingConfig, aj as backupMcpConfig, ae as boxify, al as buildMcpServerConfig, ch as checkAllVersions, cb as checkCcjkVersion, ca as checkClaudeCodeVersion, ax as checkCodexUpdate, cc as checkPluginVersions, j as cleanupPermissions, ay as codexSwitchToOfficialLogin, k as commandExists, bt as compareConfigs, bi as configureApi, az as configureCodexApi, b0 as configureCodexMcp, bu as consolidateConfigs, bh as copyConfigFiles, aA as createBackupDirectory, bP as createHomebrewSymlink, bs as detectAllConfigs, a3 as detectBuildTools, a5 as detectCICDSystems, aZ as detectConfigManagementMode, a2 as detectFrameworks, bK as detectInstalledVersion, a6 as detectLanguages, a1 as detectPackageManager, a8 as detectProject, a4 as detectTestFrameworks, a7 as determineProjectType, ab as displayBanner, ac as displayBannerWithInfo, bx as displayConfigScan, h as displayCurrentStatus, bz as displayHealthReport, c9 as displayPermissions, bQ as displayVerificationResult, ao as ensureApiKeyApproved, bf as ensureClaudeDir, aB as ensureEnvKeyMigration, bM as executeInstallMethod, c6 as exportPermissions, bW as exportProjectKnowledge, am as fixWindowsMcpConfig, bd as formatToolStatus, a9 as generateSuggestions, a0 as getAiOutputLanguageLabel, bb as getAllToolsInfo, b7 as getAllToolsStatus, a$ as getAvailableManagementActions, aC as getBackupMessage, aD as getCodexVersion, aE as getCurrentCodexProvider, c8 as getCurrentTemplateId, bo as getExistingApiConfig, bn as getExistingModelConfig, bG as getInstallationStatus, b8 as getInstalledTools, ag as getMcpConfigPath, l as getPlatform, bV as getProjectKnowledge, aa as getProjectSummary, be as getRecommendedTools, b2 as getToolConfigPath, b3 as getToolDir, ba as getToolInfo, b6 as getToolStatus, b5 as getToolVersion, bc as getToolsByCategory, bN as handleInstallFailure, c7 as importPermissions, n as importRecommendedEnv, o as importRecommendedPermissions, i as init, bC as installClaudeCode, bE as installCodex, aF as installCodexCli, b9 as installTool, bB as isClaudeCodeInstalled, U as isCodeToolType, aG as isCodexCliInstalled, bD as isCodexInstalled, c2 as isDirectoryTrusted, bF as isLocalClaudeCodeInstalled, c1 as isPermissionAllowed, b4 as isToolInstalled, aH as listCodexProviders, bR as loadKnowledgeBase, aq as manageApiKeyApproval, af as menuItem, m as mergeAndCleanPermissions, bj as mergeConfigs, ak as mergeMcpServers, bm as mergeSettingsFile, aI as migrateEnvKeyInContent, aJ as migrateEnvKeyToTempEnvKey, aK as needsEnvKeyMigration, p as openSettingsJson, aL as parseCodexConfig, br as promptApiConfigurationAction, bU as quickSync, aM as readCodexConfig, ah as readMcpConfig, bY as readPermissions, ap as removeApiKeyFromRejected, c4 as removeAutoApprovePattern, bH as removeLocalClaudeCode, bw as removeRedundantConfigs, aN as renderCodexConfig, ad as renderProgressBar, c5 as resetPermissions, X as resolveCodeToolType, aO as runCodexFullInit, aP as runCodexSystemPromptSelection, aQ as runCodexUninstall, aR as runCodexUpdate, aS as runCodexWorkflowImport, aT as runCodexWorkflowImportWithLanguageSelection, aU as runCodexWorkflowSelection, r as runConfigWizard, bA as runDoctor, by as runHealthCheck, bT as runOnboarding, bS as saveKnowledgeBase, bL as selectInstallMethod, bJ as setInstallMethod, ar as setPrimaryApiKey, a_ as shouldShowManagementMode, aV as switchCodexProvider, bq as switchToOfficialLogin, aW as switchToProvider, b$ as trustDirectory, bI as uninstallCodeTool, c0 as untrustDirectory, bk as updateCustomModel, bl as updateDefaultModel, ci as upgradeAll, cg as upgradeAllPlugins, ce as upgradeCcjk, cd as upgradeClaudeCode, cf as upgradePlugin, bO as verifyInstallation, aX as writeAuthFile, aY as writeCodexConfig, bv as writeConsolidatedConfig, ai as writeMcpConfig, bZ as writePermissions } from './chunks/simple-config.mjs';
3
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync } from 'node:fs';
4
+ import { join } from 'pathe';
5
+ import { exec } from 'tinyexec';
6
+ export { configureIncrementalManagement } from './chunks/codex-config-switch.mjs';
7
+ export { addProviderToExisting, deleteProviders, editExistingProvider, validateProviderData } from './chunks/codex-provider-manager.mjs';
8
+ export { CodexUninstaller } from './chunks/codex-uninstaller.mjs';
9
+ import ansis from 'ansis';
10
+ import inquirer from 'inquirer';
11
+ import 'node:process';
12
+ import 'smol-toml';
13
+ import 'dayjs';
14
+ import 'node:child_process';
15
+ import 'node:os';
16
+ import 'node:util';
17
+ import 'node:url';
18
+ import 'inquirer-toggle';
19
+ import 'ora';
20
+ import 'semver';
21
+ import 'node:fs/promises';
22
+ import 'fs-extra';
23
+ import 'trash';
24
+ import 'i18next';
25
+ import 'i18next-fs-backend';
26
+
27
+ const loadedPlugins = /* @__PURE__ */ new Map();
28
+ const PLUGIN_CONFIG_FILE = join(CCJK_PLUGINS_DIR, "plugins.json");
29
+ function ensurePluginsDir() {
30
+ if (!existsSync(CCJK_PLUGINS_DIR)) {
31
+ mkdirSync(CCJK_PLUGINS_DIR, { recursive: true });
32
+ }
33
+ }
34
+ function createLogger(pluginName) {
35
+ const prefix = `[${pluginName}]`;
36
+ return {
37
+ info: (msg) => console.log(`${prefix} ${msg}`),
38
+ warn: (msg) => console.warn(`${prefix} ${msg}`),
39
+ error: (msg) => console.error(`${prefix} ${msg}`),
40
+ debug: (msg) => {
41
+ if (process.env.DEBUG)
42
+ console.log(`${prefix} [DEBUG] ${msg}`);
43
+ }
44
+ };
45
+ }
46
+ function createStorage(pluginName) {
47
+ const storageFile = join(CCJK_PLUGINS_DIR, pluginName, "storage.json");
48
+ let data = {};
49
+ if (existsSync(storageFile)) {
50
+ try {
51
+ data = JSON.parse(readFileSync(storageFile, "utf-8"));
52
+ } catch {
53
+ data = {};
54
+ }
55
+ }
56
+ const save = () => {
57
+ const dir = join(CCJK_PLUGINS_DIR, pluginName);
58
+ if (!existsSync(dir)) {
59
+ mkdirSync(dir, { recursive: true });
60
+ }
61
+ writeFileSync(storageFile, JSON.stringify(data, null, 2));
62
+ };
63
+ return {
64
+ get: (key) => data[key],
65
+ set: (key, value) => {
66
+ data[key] = value;
67
+ save();
68
+ },
69
+ delete: (key) => {
70
+ delete data[key];
71
+ save();
72
+ },
73
+ clear: () => {
74
+ data = {};
75
+ save();
76
+ }
77
+ };
78
+ }
79
+ function createContext(pluginName) {
80
+ const { version } = require("../../package.json");
81
+ return {
82
+ ccjkVersion: version,
83
+ configDir: join(CCJK_PLUGINS_DIR, pluginName),
84
+ i18n: require("../i18n").i18n,
85
+ logger: createLogger(pluginName),
86
+ storage: createStorage(pluginName)
87
+ };
88
+ }
89
+ function readPluginConfig() {
90
+ ensurePluginsDir();
91
+ if (existsSync(PLUGIN_CONFIG_FILE)) {
92
+ try {
93
+ return JSON.parse(readFileSync(PLUGIN_CONFIG_FILE, "utf-8"));
94
+ } catch {
95
+ }
96
+ }
97
+ return {
98
+ enabled: [],
99
+ disabled: [],
100
+ settings: {}
101
+ };
102
+ }
103
+ function writePluginConfig(config) {
104
+ ensurePluginsDir();
105
+ writeFileSync(PLUGIN_CONFIG_FILE, JSON.stringify(config, null, 2));
106
+ }
107
+ async function discoverPlugins() {
108
+ ensurePluginsDir();
109
+ const results = [];
110
+ const dirs = readdirSync(CCJK_PLUGINS_DIR, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
111
+ for (const dir of dirs) {
112
+ const pluginPath = join(CCJK_PLUGINS_DIR, dir);
113
+ const packagePath = join(pluginPath, "package.json");
114
+ if (!existsSync(packagePath)) {
115
+ results.push({
116
+ name: dir,
117
+ path: pluginPath,
118
+ metadata: { name: dir, version: "0.0.0", description: "" },
119
+ valid: false,
120
+ error: "Missing package.json"
121
+ });
122
+ continue;
123
+ }
124
+ try {
125
+ const pkg = JSON.parse(readFileSync(packagePath, "utf-8"));
126
+ results.push({
127
+ name: pkg.name || dir,
128
+ path: pluginPath,
129
+ metadata: {
130
+ name: pkg.name || dir,
131
+ version: pkg.version || "0.0.0",
132
+ description: pkg.description || "",
133
+ author: pkg.author,
134
+ license: pkg.license,
135
+ keywords: pkg.keywords
136
+ },
137
+ valid: true
138
+ });
139
+ } catch (error) {
140
+ results.push({
141
+ name: dir,
142
+ path: pluginPath,
143
+ metadata: { name: dir, version: "0.0.0", description: "" },
144
+ valid: false,
145
+ error: error instanceof Error ? error.message : "Invalid package.json"
146
+ });
147
+ }
148
+ }
149
+ return results;
150
+ }
151
+ async function loadPlugin(pathOrName) {
152
+ const isPath = pathOrName.includes("/") || pathOrName.includes("\\");
153
+ const pluginPath = isPath ? pathOrName : join(CCJK_PLUGINS_DIR, pathOrName);
154
+ if (!existsSync(pluginPath)) {
155
+ console.error(`Plugin not found: ${pluginPath}`);
156
+ return null;
157
+ }
158
+ try {
159
+ const indexPath = join(pluginPath, "index.js");
160
+ const tsIndexPath = join(pluginPath, "index.ts");
161
+ let plugin;
162
+ if (existsSync(indexPath)) {
163
+ plugin = require(indexPath).default || require(indexPath);
164
+ } else if (existsSync(tsIndexPath)) {
165
+ plugin = require(tsIndexPath).default || require(tsIndexPath);
166
+ } else {
167
+ const pkg = JSON.parse(readFileSync(join(pluginPath, "package.json"), "utf-8"));
168
+ if (pkg.main) {
169
+ const mainPath = join(pluginPath, pkg.main);
170
+ plugin = require(mainPath).default || require(mainPath);
171
+ } else {
172
+ throw new Error("No entry point found");
173
+ }
174
+ }
175
+ const context = createContext(plugin.metadata.name);
176
+ if (plugin.onLoad) {
177
+ await plugin.onLoad(context);
178
+ }
179
+ const loaded = {
180
+ plugin,
181
+ path: pluginPath,
182
+ enabled: true,
183
+ loadedAt: /* @__PURE__ */ new Date()
184
+ };
185
+ loadedPlugins.set(plugin.metadata.name, loaded);
186
+ return loaded;
187
+ } catch (error) {
188
+ console.error(`Failed to load plugin: ${pathOrName}`, error);
189
+ return null;
190
+ }
191
+ }
192
+ async function unloadPlugin(name) {
193
+ const loaded = loadedPlugins.get(name);
194
+ if (!loaded)
195
+ return false;
196
+ try {
197
+ if (loaded.plugin.onUnload) {
198
+ await loaded.plugin.onUnload();
199
+ }
200
+ loadedPlugins.delete(name);
201
+ return true;
202
+ } catch (error) {
203
+ console.error(`Failed to unload plugin: ${name}`, error);
204
+ return false;
205
+ }
206
+ }
207
+ function getLoadedPlugins() {
208
+ return Array.from(loadedPlugins.values());
209
+ }
210
+ function getPluginInfo(name) {
211
+ const loaded = loadedPlugins.get(name);
212
+ if (!loaded)
213
+ return null;
214
+ return {
215
+ name: loaded.plugin.metadata.name,
216
+ version: loaded.plugin.metadata.version,
217
+ description: loaded.plugin.metadata.description,
218
+ enabled: loaded.enabled,
219
+ path: loaded.path,
220
+ author: loaded.plugin.metadata.author
221
+ };
222
+ }
223
+ async function listPlugins() {
224
+ const discovered = await discoverPlugins();
225
+ const config = readPluginConfig();
226
+ return discovered.map((d) => {
227
+ const loaded = loadedPlugins.get(d.name);
228
+ return {
229
+ name: d.name,
230
+ version: d.metadata.version,
231
+ description: d.metadata.description,
232
+ enabled: loaded?.enabled ?? !config.disabled.includes(d.name),
233
+ path: d.path,
234
+ author: d.metadata.author
235
+ };
236
+ });
237
+ }
238
+ async function enablePlugin(name) {
239
+ const config = readPluginConfig();
240
+ config.disabled = config.disabled.filter((n) => n !== name);
241
+ if (!config.enabled.includes(name)) {
242
+ config.enabled.push(name);
243
+ }
244
+ writePluginConfig(config);
245
+ if (!loadedPlugins.has(name)) {
246
+ await loadPlugin(name);
247
+ } else {
248
+ const loaded = loadedPlugins.get(name);
249
+ loaded.enabled = true;
250
+ }
251
+ return true;
252
+ }
253
+ async function disablePlugin(name) {
254
+ const config = readPluginConfig();
255
+ config.enabled = config.enabled.filter((n) => n !== name);
256
+ if (!config.disabled.includes(name)) {
257
+ config.disabled.push(name);
258
+ }
259
+ writePluginConfig(config);
260
+ if (loadedPlugins.has(name)) {
261
+ await unloadPlugin(name);
262
+ }
263
+ return true;
264
+ }
265
+ function getPluginWorkflows() {
266
+ const workflows = [];
267
+ for (const loaded of loadedPlugins.values()) {
268
+ if (loaded.enabled && loaded.plugin.workflows) {
269
+ workflows.push(...loaded.plugin.workflows);
270
+ }
271
+ }
272
+ return workflows;
273
+ }
274
+ function getPluginAgents() {
275
+ const agents = [];
276
+ for (const loaded of loadedPlugins.values()) {
277
+ if (loaded.enabled && loaded.plugin.agents) {
278
+ agents.push(...loaded.plugin.agents);
279
+ }
280
+ }
281
+ return agents;
282
+ }
283
+ function getPluginMcpServices() {
284
+ const services = [];
285
+ for (const loaded of loadedPlugins.values()) {
286
+ if (loaded.enabled && loaded.plugin.mcpServices) {
287
+ services.push(...loaded.plugin.mcpServices);
288
+ }
289
+ }
290
+ return services;
291
+ }
292
+ function getPluginOutputStyles() {
293
+ const styles = [];
294
+ for (const loaded of loadedPlugins.values()) {
295
+ if (loaded.enabled && loaded.plugin.outputStyles) {
296
+ styles.push(...loaded.plugin.outputStyles);
297
+ }
298
+ }
299
+ return styles;
300
+ }
301
+ function getPluginSkills() {
302
+ const skills = [];
303
+ for (const loaded of loadedPlugins.values()) {
304
+ if (loaded.enabled && loaded.plugin.skills) {
305
+ skills.push(...loaded.plugin.skills);
306
+ }
307
+ }
308
+ return skills;
309
+ }
310
+ async function initializePlugins() {
311
+ const config = readPluginConfig();
312
+ const discovered = await discoverPlugins();
313
+ for (const plugin of discovered) {
314
+ if (plugin.valid && !config.disabled.includes(plugin.name)) {
315
+ await loadPlugin(plugin.path);
316
+ }
317
+ }
318
+ }
319
+
320
+ let registry$1 = null;
321
+ function ensureSkillsDir() {
322
+ if (!existsSync(CCJK_SKILLS_DIR)) {
323
+ mkdirSync(CCJK_SKILLS_DIR, { recursive: true });
324
+ }
325
+ }
326
+ function getRegistry$1() {
327
+ if (!registry$1) {
328
+ registry$1 = loadRegistry$1();
329
+ }
330
+ return registry$1;
331
+ }
332
+ function loadRegistry$1() {
333
+ ensureSkillsDir();
334
+ const skills = /* @__PURE__ */ new Map();
335
+ const categories = /* @__PURE__ */ new Map();
336
+ const files = readdirSync(CCJK_SKILLS_DIR).filter((f) => f.endsWith(".json"));
337
+ for (const file of files) {
338
+ try {
339
+ const content = readFileSync(join(CCJK_SKILLS_DIR, file), "utf-8");
340
+ const skill = JSON.parse(content);
341
+ skills.set(skill.id, skill);
342
+ const categorySkills = categories.get(skill.category) || [];
343
+ categorySkills.push(skill.id);
344
+ categories.set(skill.category, categorySkills);
345
+ } catch {
346
+ }
347
+ }
348
+ return {
349
+ skills,
350
+ categories,
351
+ lastUpdated: /* @__PURE__ */ new Date()
352
+ };
353
+ }
354
+ function refreshRegistry$1() {
355
+ registry$1 = loadRegistry$1();
356
+ }
357
+ function getAllSkills() {
358
+ return Array.from(getRegistry$1().skills.values());
359
+ }
360
+ function getSkill(id) {
361
+ return getRegistry$1().skills.get(id);
362
+ }
363
+ function searchSkills(options) {
364
+ let skills = getAllSkills();
365
+ if (options.category) {
366
+ skills = skills.filter((s) => s.category === options.category);
367
+ }
368
+ if (options.enabled !== void 0) {
369
+ skills = skills.filter((s) => s.enabled === options.enabled);
370
+ }
371
+ if (options.tags && options.tags.length > 0) {
372
+ skills = skills.filter(
373
+ (s) => s.tags && options.tags.some((tag) => s.tags.includes(tag))
374
+ );
375
+ }
376
+ if (options.query) {
377
+ const query = options.query.toLowerCase();
378
+ skills = skills.filter(
379
+ (s) => s.id.toLowerCase().includes(query) || s.name.en.toLowerCase().includes(query) || s.name["zh-CN"].toLowerCase().includes(query) || s.triggers.some((t) => t.toLowerCase().includes(query))
380
+ );
381
+ }
382
+ if (options.limit) {
383
+ skills = skills.slice(0, options.limit);
384
+ }
385
+ return skills;
386
+ }
387
+ function addSkill(skill) {
388
+ ensureSkillsDir();
389
+ try {
390
+ const filePath = join(CCJK_SKILLS_DIR, `${skill.id}.json`);
391
+ writeFileSync(filePath, JSON.stringify(skill, null, 2));
392
+ refreshRegistry$1();
393
+ return {
394
+ skillId: skill.id,
395
+ success: true,
396
+ path: filePath
397
+ };
398
+ } catch (error) {
399
+ return {
400
+ skillId: skill.id,
401
+ success: false,
402
+ error: error instanceof Error ? error.message : "Unknown error"
403
+ };
404
+ }
405
+ }
406
+ function removeSkill(id) {
407
+ const filePath = join(CCJK_SKILLS_DIR, `${id}.json`);
408
+ if (existsSync(filePath)) {
409
+ const fs = require("node:fs");
410
+ fs.unlinkSync(filePath);
411
+ refreshRegistry$1();
412
+ return true;
413
+ }
414
+ return false;
415
+ }
416
+ function setSkillEnabled(id, enabled) {
417
+ const skill = getSkill(id);
418
+ if (!skill)
419
+ return false;
420
+ skill.enabled = enabled;
421
+ addSkill(skill);
422
+ return true;
423
+ }
424
+ function exportSkills(skillIds) {
425
+ const skills = skillIds ? skillIds.map((id) => getSkill(id)).filter(Boolean) : getAllSkills();
426
+ return {
427
+ version: "1.0.0",
428
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
429
+ skills
430
+ };
431
+ }
432
+ function importSkills(data) {
433
+ return data.skills.map((skill) => addSkill(skill));
434
+ }
435
+ const BATCH_TEMPLATES = {
436
+ typescript: {
437
+ category: "dev",
438
+ skills: [
439
+ {
440
+ id: "ts-debug",
441
+ name: { "en": "TypeScript Debug", "zh-CN": "TypeScript \u8C03\u8BD5" },
442
+ description: { "en": "Debug TypeScript code", "zh-CN": "\u8C03\u8BD5 TypeScript \u4EE3\u7801" },
443
+ triggers: ["/ts-debug", "/tsd"],
444
+ templateFile: "ts-debug.md",
445
+ tags: ["typescript", "debug"]
446
+ },
447
+ {
448
+ id: "ts-refactor",
449
+ name: { "en": "TypeScript Refactor", "zh-CN": "TypeScript \u91CD\u6784" },
450
+ description: { "en": "Refactor TypeScript code", "zh-CN": "\u91CD\u6784 TypeScript \u4EE3\u7801" },
451
+ triggers: ["/ts-refactor", "/tsr"],
452
+ templateFile: "ts-refactor.md",
453
+ tags: ["typescript", "refactor"]
454
+ },
455
+ {
456
+ id: "ts-test",
457
+ name: { "en": "TypeScript Test", "zh-CN": "TypeScript \u6D4B\u8BD5" },
458
+ description: { "en": "Generate TypeScript tests", "zh-CN": "\u751F\u6210 TypeScript \u6D4B\u8BD5" },
459
+ triggers: ["/ts-test", "/tst"],
460
+ templateFile: "ts-test.md",
461
+ tags: ["typescript", "testing"]
462
+ },
463
+ {
464
+ id: "ts-type-check",
465
+ name: { "en": "TypeScript Type Check", "zh-CN": "TypeScript \u7C7B\u578B\u68C0\u67E5" },
466
+ description: { "en": "Fix TypeScript type errors", "zh-CN": "\u4FEE\u590D TypeScript \u7C7B\u578B\u9519\u8BEF" },
467
+ triggers: ["/ts-type", "/tstc"],
468
+ templateFile: "ts-type-check.md",
469
+ tags: ["typescript", "types"]
470
+ },
471
+ {
472
+ id: "ts-migrate",
473
+ name: { "en": "TypeScript Migration", "zh-CN": "TypeScript \u8FC1\u79FB" },
474
+ description: { "en": "Migrate JS to TypeScript", "zh-CN": "\u4ECE JS \u8FC1\u79FB\u5230 TypeScript" },
475
+ triggers: ["/ts-migrate", "/tsm"],
476
+ templateFile: "ts-migrate.md",
477
+ tags: ["typescript", "migration"]
478
+ }
479
+ ]
480
+ },
481
+ python: {
482
+ category: "dev",
483
+ skills: [
484
+ {
485
+ id: "py-debug",
486
+ name: { "en": "Python Debug", "zh-CN": "Python \u8C03\u8BD5" },
487
+ description: { "en": "Debug Python code", "zh-CN": "\u8C03\u8BD5 Python \u4EE3\u7801" },
488
+ triggers: ["/py-debug", "/pyd"],
489
+ templateFile: "py-debug.md",
490
+ tags: ["python", "debug"]
491
+ },
492
+ {
493
+ id: "py-refactor",
494
+ name: { "en": "Python Refactor", "zh-CN": "Python \u91CD\u6784" },
495
+ description: { "en": "Refactor Python code", "zh-CN": "\u91CD\u6784 Python \u4EE3\u7801" },
496
+ triggers: ["/py-refactor", "/pyr"],
497
+ templateFile: "py-refactor.md",
498
+ tags: ["python", "refactor"]
499
+ },
500
+ {
501
+ id: "py-test",
502
+ name: { "en": "Python Test", "zh-CN": "Python \u6D4B\u8BD5" },
503
+ description: { "en": "Generate Python tests", "zh-CN": "\u751F\u6210 Python \u6D4B\u8BD5" },
504
+ triggers: ["/py-test", "/pyt"],
505
+ templateFile: "py-test.md",
506
+ tags: ["python", "testing"]
507
+ }
508
+ ]
509
+ },
510
+ seo: {
511
+ category: "seo",
512
+ skills: [
513
+ {
514
+ id: "seo-meta",
515
+ name: { "en": "SEO Meta Optimization", "zh-CN": "SEO \u5143\u6570\u636E\u4F18\u5316" },
516
+ description: { "en": "Optimize meta tags for SEO", "zh-CN": "\u4F18\u5316 SEO \u5143\u6807\u7B7E" },
517
+ triggers: ["/seo-meta", "/meta"],
518
+ templateFile: "seo-meta.md",
519
+ tags: ["seo", "meta"]
520
+ },
521
+ {
522
+ id: "seo-sitemap",
523
+ name: { "en": "Sitemap Generator", "zh-CN": "\u7AD9\u70B9\u5730\u56FE\u751F\u6210" },
524
+ description: { "en": "Generate XML sitemap", "zh-CN": "\u751F\u6210 XML \u7AD9\u70B9\u5730\u56FE" },
525
+ triggers: ["/sitemap", "/seo-sitemap"],
526
+ templateFile: "seo-sitemap.md",
527
+ tags: ["seo", "sitemap"]
528
+ },
529
+ {
530
+ id: "seo-schema",
531
+ name: { "en": "Schema Markup", "zh-CN": "\u7ED3\u6784\u5316\u6570\u636E\u6807\u8BB0" },
532
+ description: { "en": "Add structured data markup", "zh-CN": "\u6DFB\u52A0\u7ED3\u6784\u5316\u6570\u636E\u6807\u8BB0" },
533
+ triggers: ["/schema", "/seo-schema"],
534
+ templateFile: "seo-schema.md",
535
+ tags: ["seo", "schema"]
536
+ },
537
+ {
538
+ id: "seo-cwv",
539
+ name: { "en": "Core Web Vitals", "zh-CN": "\u6838\u5FC3\u7F51\u9875\u6307\u6807" },
540
+ description: { "en": "Optimize Core Web Vitals", "zh-CN": "\u4F18\u5316\u6838\u5FC3\u7F51\u9875\u6307\u6807" },
541
+ triggers: ["/cwv", "/seo-cwv"],
542
+ templateFile: "seo-cwv.md",
543
+ tags: ["seo", "performance"]
544
+ }
545
+ ]
546
+ },
547
+ devops: {
548
+ category: "devops",
549
+ skills: [
550
+ {
551
+ id: "devops-docker",
552
+ name: { "en": "Docker Setup", "zh-CN": "Docker \u914D\u7F6E" },
553
+ description: { "en": "Set up Docker configuration", "zh-CN": "\u914D\u7F6E Docker" },
554
+ triggers: ["/docker", "/devops-docker"],
555
+ templateFile: "devops-docker.md",
556
+ tags: ["devops", "docker"]
557
+ },
558
+ {
559
+ id: "devops-ci",
560
+ name: { "en": "CI Pipeline", "zh-CN": "CI \u6D41\u6C34\u7EBF" },
561
+ description: { "en": "Set up CI pipeline", "zh-CN": "\u914D\u7F6E CI \u6D41\u6C34\u7EBF" },
562
+ triggers: ["/ci", "/devops-ci"],
563
+ templateFile: "devops-ci.md",
564
+ tags: ["devops", "ci"]
565
+ },
566
+ {
567
+ id: "devops-deploy",
568
+ name: { "en": "Deploy Script", "zh-CN": "\u90E8\u7F72\u811A\u672C" },
569
+ description: { "en": "Create deployment script", "zh-CN": "\u521B\u5EFA\u90E8\u7F72\u811A\u672C" },
570
+ triggers: ["/deploy", "/devops-deploy"],
571
+ templateFile: "devops-deploy.md",
572
+ tags: ["devops", "deploy"]
573
+ },
574
+ {
575
+ id: "devops-monitor",
576
+ name: { "en": "Monitoring Setup", "zh-CN": "\u76D1\u63A7\u914D\u7F6E" },
577
+ description: { "en": "Set up monitoring", "zh-CN": "\u914D\u7F6E\u76D1\u63A7" },
578
+ triggers: ["/monitor", "/devops-monitor"],
579
+ templateFile: "devops-monitor.md",
580
+ tags: ["devops", "monitoring"]
581
+ }
582
+ ]
583
+ }
584
+ };
585
+ function createBatchSkills(options) {
586
+ const results = [];
587
+ if (options.lang) {
588
+ const template = BATCH_TEMPLATES[options.lang];
589
+ if (template) {
590
+ for (const skillDef of template.skills) {
591
+ const skill = {
592
+ ...skillDef,
593
+ category: template.category,
594
+ enabled: true,
595
+ version: "1.0.0",
596
+ template: `# ${skillDef.name.en}
597
+
598
+ ${skillDef.description.en}
599
+
600
+ This is a placeholder template.`
601
+ };
602
+ results.push(addSkill(skill));
603
+ }
604
+ }
605
+ }
606
+ if (options.seo) {
607
+ const template = BATCH_TEMPLATES.seo;
608
+ for (const skillDef of template.skills) {
609
+ const skill = {
610
+ ...skillDef,
611
+ category: template.category,
612
+ enabled: true,
613
+ version: "1.0.0",
614
+ template: `# ${skillDef.name.en}
615
+
616
+ ${skillDef.description.en}
617
+
618
+ This is a placeholder template.`
619
+ };
620
+ results.push(addSkill(skill));
621
+ }
622
+ }
623
+ if (options.devops) {
624
+ const template = BATCH_TEMPLATES.devops;
625
+ for (const skillDef of template.skills) {
626
+ const skill = {
627
+ ...skillDef,
628
+ category: template.category,
629
+ enabled: true,
630
+ version: "1.0.0",
631
+ template: `# ${skillDef.name.en}
632
+
633
+ ${skillDef.description.en}
634
+
635
+ This is a placeholder template.`
636
+ };
637
+ results.push(addSkill(skill));
638
+ }
639
+ }
640
+ return results;
641
+ }
642
+ function getBatchCategories() {
643
+ return Object.keys(BATCH_TEMPLATES);
644
+ }
645
+
646
+ let registry = null;
647
+ function ensureGroupsDir() {
648
+ if (!existsSync(CCJK_GROUPS_DIR)) {
649
+ mkdirSync(CCJK_GROUPS_DIR, { recursive: true });
650
+ }
651
+ }
652
+ function getRegistry() {
653
+ if (!registry) {
654
+ registry = loadRegistry();
655
+ }
656
+ return registry;
657
+ }
658
+ function loadRegistry() {
659
+ ensureGroupsDir();
660
+ const groups = /* @__PURE__ */ new Map();
661
+ const enabledGroups = /* @__PURE__ */ new Set();
662
+ const registryFile = join(CCJK_GROUPS_DIR, "registry.json");
663
+ if (existsSync(registryFile)) {
664
+ try {
665
+ const data = JSON.parse(readFileSync(registryFile, "utf-8"));
666
+ for (const group of data.groups || []) {
667
+ groups.set(group.id, group);
668
+ }
669
+ for (const id of data.enabled || []) {
670
+ enabledGroups.add(id);
671
+ }
672
+ } catch {
673
+ }
674
+ }
675
+ if (groups.size === 0) {
676
+ for (const group of PREDEFINED_GROUPS) {
677
+ groups.set(group.id, group);
678
+ if (group.defaultEnabled) {
679
+ enabledGroups.add(group.id);
680
+ }
681
+ }
682
+ saveRegistry({ groups, enabledGroups, lastUpdated: /* @__PURE__ */ new Date() });
683
+ }
684
+ return {
685
+ groups,
686
+ enabledGroups,
687
+ lastUpdated: /* @__PURE__ */ new Date()
688
+ };
689
+ }
690
+ function saveRegistry(reg) {
691
+ ensureGroupsDir();
692
+ const registryFile = join(CCJK_GROUPS_DIR, "registry.json");
693
+ const data = {
694
+ groups: Array.from(reg.groups.values()),
695
+ enabled: Array.from(reg.enabledGroups),
696
+ lastUpdated: reg.lastUpdated.toISOString()
697
+ };
698
+ writeFileSync(registryFile, JSON.stringify(data, null, 2));
699
+ }
700
+ function refreshRegistry() {
701
+ registry = loadRegistry();
702
+ }
703
+ function getAllGroups() {
704
+ return Array.from(getRegistry().groups.values());
705
+ }
706
+ function getGroup(id) {
707
+ return getRegistry().groups.get(id);
708
+ }
709
+ function isGroupEnabled(id) {
710
+ return getRegistry().enabledGroups.has(id);
711
+ }
712
+ function searchGroups(options) {
713
+ let groups = getAllGroups();
714
+ if (options.category) {
715
+ groups = groups.filter((g) => g.category === options.category);
716
+ }
717
+ if (options.enabled !== void 0) {
718
+ const enabledSet = getRegistry().enabledGroups;
719
+ groups = groups.filter(
720
+ (g) => options.enabled ? enabledSet.has(g.id) : !enabledSet.has(g.id)
721
+ );
722
+ }
723
+ if (options.query) {
724
+ const query = options.query.toLowerCase();
725
+ groups = groups.filter(
726
+ (g) => g.id.toLowerCase().includes(query) || g.name.en.toLowerCase().includes(query) || g.name["zh-CN"].toLowerCase().includes(query)
727
+ );
728
+ }
729
+ if (options.limit) {
730
+ groups = groups.slice(0, options.limit);
731
+ }
732
+ return groups;
733
+ }
734
+ function enableGroup(id) {
735
+ const reg = getRegistry();
736
+ if (!reg.groups.has(id))
737
+ return false;
738
+ reg.enabledGroups.add(id);
739
+ reg.lastUpdated = /* @__PURE__ */ new Date();
740
+ saveRegistry(reg);
741
+ return true;
742
+ }
743
+ function disableGroup(id) {
744
+ const reg = getRegistry();
745
+ if (!reg.groups.has(id))
746
+ return false;
747
+ reg.enabledGroups.delete(id);
748
+ reg.lastUpdated = /* @__PURE__ */ new Date();
749
+ saveRegistry(reg);
750
+ return true;
751
+ }
752
+ function addGroup(group) {
753
+ const reg = getRegistry();
754
+ try {
755
+ reg.groups.set(group.id, group);
756
+ if (group.defaultEnabled) {
757
+ reg.enabledGroups.add(group.id);
758
+ }
759
+ reg.lastUpdated = /* @__PURE__ */ new Date();
760
+ saveRegistry(reg);
761
+ return {
762
+ groupId: group.id,
763
+ success: true,
764
+ installedAgents: group.agents.map((a) => a.id),
765
+ installedSkills: group.skills
766
+ };
767
+ } catch (error) {
768
+ return {
769
+ groupId: group.id,
770
+ success: false,
771
+ installedAgents: [],
772
+ installedSkills: [],
773
+ errors: [error instanceof Error ? error.message : "Unknown error"]
774
+ };
775
+ }
776
+ }
777
+ function removeGroup(id) {
778
+ const reg = getRegistry();
779
+ if (!reg.groups.has(id))
780
+ return false;
781
+ reg.groups.delete(id);
782
+ reg.enabledGroups.delete(id);
783
+ reg.lastUpdated = /* @__PURE__ */ new Date();
784
+ saveRegistry(reg);
785
+ return true;
786
+ }
787
+ function exportGroups(groupIds) {
788
+ const groups = groupIds ? groupIds.map((id) => getGroup(id)).filter(Boolean) : getAllGroups();
789
+ return {
790
+ version: "1.0.0",
791
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
792
+ groups
793
+ };
794
+ }
795
+ function importGroups(data) {
796
+ return data.groups.map((group) => addGroup(group));
797
+ }
798
+ function getEnabledAgents() {
799
+ const reg = getRegistry();
800
+ const agents = [];
801
+ for (const groupId of reg.enabledGroups) {
802
+ const group = reg.groups.get(groupId);
803
+ if (group) {
804
+ agents.push(...group.agents);
805
+ }
806
+ }
807
+ return agents;
808
+ }
809
+ function getEnabledSkillIds() {
810
+ const reg = getRegistry();
811
+ const skills = [];
812
+ for (const groupId of reg.enabledGroups) {
813
+ const group = reg.groups.get(groupId);
814
+ if (group) {
815
+ skills.push(...group.skills);
816
+ }
817
+ }
818
+ return [...new Set(skills)];
819
+ }
820
+ const PREDEFINED_GROUPS = [
821
+ // TypeScript Development Group
822
+ {
823
+ id: "typescript-dev",
824
+ name: { "en": "TypeScript Development", "zh-CN": "TypeScript \u5F00\u53D1" },
825
+ description: { "en": "Specialized agents for TypeScript development", "zh-CN": "TypeScript \u5F00\u53D1\u4E13\u7528\u4EE3\u7406" },
826
+ category: "language",
827
+ version: "1.0.0",
828
+ icon: "\u{1F537}",
829
+ defaultEnabled: false,
830
+ skills: ["ts-debug", "ts-refactor", "ts-test", "ts-type-check", "ts-migrate"],
831
+ agents: [
832
+ {
833
+ id: "ts-architect",
834
+ name: "TypeScript Architect",
835
+ description: "Designs TypeScript architecture, module structure, and type systems",
836
+ model: "sonnet",
837
+ required: true,
838
+ tags: ["typescript", "architecture"],
839
+ definition: `---
840
+ name: ts-architect
841
+ description: TypeScript architecture and type system expert
842
+ model: sonnet
843
+ ---
844
+
845
+ # TypeScript Architect Agent
846
+
847
+ ## CORE MISSION
848
+ Design robust TypeScript architectures with proper type safety, module organization, and scalable patterns.
849
+
850
+ ## RESPONSIBILITIES
851
+ - Design type-safe API interfaces
852
+ - Create module structure and barrel exports
853
+ - Implement generic utility types
854
+ - Review type definitions for completeness
855
+ - Suggest TypeScript best practices
856
+
857
+ ## ALLOWED ACTIONS
858
+ - Create/modify .ts and .tsx files
859
+ - Design type definitions
860
+ - Implement design patterns
861
+ - Review code architecture
862
+
863
+ ## FORBIDDEN ACTIONS
864
+ - Do not modify test files (delegate to ts-tester)
865
+ - Do not handle runtime debugging (delegate to ts-debugger)
866
+ `
867
+ },
868
+ {
869
+ id: "ts-debugger",
870
+ name: "TypeScript Debugger",
871
+ description: "Debugs TypeScript runtime issues and type errors",
872
+ model: "sonnet",
873
+ required: true,
874
+ tags: ["typescript", "debug"],
875
+ definition: `---
876
+ name: ts-debugger
877
+ description: TypeScript debugging and error resolution expert
878
+ model: sonnet
879
+ ---
880
+
881
+ # TypeScript Debugger Agent
882
+
883
+ ## CORE MISSION
884
+ Identify and resolve TypeScript compilation errors, runtime issues, and type mismatches.
885
+
886
+ ## RESPONSIBILITIES
887
+ - Diagnose type errors
888
+ - Fix runtime exceptions
889
+ - Resolve module resolution issues
890
+ - Debug async/await problems
891
+ - Trace type inference failures
892
+
893
+ ## ALLOWED ACTIONS
894
+ - Debug TypeScript code
895
+ - Fix type errors
896
+ - Add type assertions when needed
897
+ - Improve error handling
898
+ `
899
+ },
900
+ {
901
+ id: "ts-tester",
902
+ name: "TypeScript Tester",
903
+ description: "Creates comprehensive TypeScript tests",
904
+ model: "haiku",
905
+ required: false,
906
+ tags: ["typescript", "testing"],
907
+ definition: `---
908
+ name: ts-tester
909
+ description: TypeScript testing specialist
910
+ model: haiku
911
+ ---
912
+
913
+ # TypeScript Tester Agent
914
+
915
+ ## CORE MISSION
916
+ Create comprehensive, type-safe tests for TypeScript codebases.
917
+
918
+ ## RESPONSIBILITIES
919
+ - Write unit tests with proper typing
920
+ - Create integration tests
921
+ - Mock typed dependencies
922
+ - Test type guards and assertions
923
+ - Achieve high code coverage
924
+ `
925
+ }
926
+ ]
927
+ },
928
+ // Python Development Group
929
+ {
930
+ id: "python-dev",
931
+ name: { "en": "Python Development", "zh-CN": "Python \u5F00\u53D1" },
932
+ description: { "en": "Specialized agents for Python development", "zh-CN": "Python \u5F00\u53D1\u4E13\u7528\u4EE3\u7406" },
933
+ category: "language",
934
+ version: "1.0.0",
935
+ icon: "\u{1F40D}",
936
+ defaultEnabled: false,
937
+ skills: ["py-debug", "py-refactor", "py-test"],
938
+ agents: [
939
+ {
940
+ id: "py-architect",
941
+ name: "Python Architect",
942
+ description: "Designs Python architecture and package structure",
943
+ model: "sonnet",
944
+ required: true,
945
+ tags: ["python", "architecture"],
946
+ definition: `---
947
+ name: py-architect
948
+ description: Python architecture and design patterns expert
949
+ model: sonnet
950
+ ---
951
+
952
+ # Python Architect Agent
953
+
954
+ ## CORE MISSION
955
+ Design clean, Pythonic architectures with proper package structure and design patterns.
956
+
957
+ ## RESPONSIBILITIES
958
+ - Design package/module structure
959
+ - Implement design patterns (Factory, Strategy, etc.)
960
+ - Create abstract base classes
961
+ - Design API interfaces
962
+ - Review architecture decisions
963
+ `
964
+ }
965
+ ]
966
+ },
967
+ // SEO Team Group
968
+ {
969
+ id: "seo-team",
970
+ name: { "en": "SEO Team", "zh-CN": "SEO \u56E2\u961F" },
971
+ description: { "en": "Complete SEO optimization team", "zh-CN": "\u5B8C\u6574\u7684 SEO \u4F18\u5316\u56E2\u961F" },
972
+ category: "seo",
973
+ version: "1.0.0",
974
+ icon: "\u{1F50D}",
975
+ defaultEnabled: false,
976
+ skills: ["seo-meta", "seo-sitemap", "seo-schema", "seo-cwv"],
977
+ agents: [
978
+ {
979
+ id: "seo-meta-optimizer",
980
+ name: "Meta Tag Optimizer",
981
+ description: "Optimizes meta tags, titles, and descriptions for SEO",
982
+ model: "haiku",
983
+ required: true,
984
+ tags: ["seo", "meta"],
985
+ definition: `---
986
+ name: seo-meta-optimizer
987
+ description: SEO meta tag optimization specialist
988
+ model: haiku
989
+ ---
990
+
991
+ # SEO Meta Optimizer Agent
992
+
993
+ ## CORE MISSION
994
+ Optimize meta tags, titles, and descriptions for maximum search visibility.
995
+
996
+ ## RESPONSIBILITIES
997
+ - Audit existing meta tags
998
+ - Write compelling title tags (50-60 chars)
999
+ - Create engaging meta descriptions (150-160 chars)
1000
+ - Implement Open Graph tags
1001
+ - Add Twitter Card meta tags
1002
+ `
1003
+ },
1004
+ {
1005
+ id: "seo-content-analyst",
1006
+ name: "Content Analyst",
1007
+ description: "Analyzes content for SEO optimization opportunities",
1008
+ model: "sonnet",
1009
+ required: true,
1010
+ tags: ["seo", "content"],
1011
+ definition: `---
1012
+ name: seo-content-analyst
1013
+ description: SEO content analysis specialist
1014
+ model: sonnet
1015
+ ---
1016
+
1017
+ # SEO Content Analyst Agent
1018
+
1019
+ ## CORE MISSION
1020
+ Analyze and optimize content for search engine visibility and user engagement.
1021
+
1022
+ ## RESPONSIBILITIES
1023
+ - Analyze keyword density
1024
+ - Check heading hierarchy (H1-H6)
1025
+ - Evaluate content structure
1026
+ - Suggest internal linking
1027
+ - Review image alt texts
1028
+ `
1029
+ },
1030
+ {
1031
+ id: "seo-schema-expert",
1032
+ name: "Schema Markup Expert",
1033
+ description: "Implements structured data and schema markup",
1034
+ model: "haiku",
1035
+ required: false,
1036
+ tags: ["seo", "schema"],
1037
+ definition: `---
1038
+ name: seo-schema-expert
1039
+ description: Schema.org structured data specialist
1040
+ model: haiku
1041
+ ---
1042
+
1043
+ # SEO Schema Expert Agent
1044
+
1045
+ ## CORE MISSION
1046
+ Implement proper Schema.org structured data for enhanced search results.
1047
+
1048
+ ## RESPONSIBILITIES
1049
+ - Add JSON-LD structured data
1050
+ - Implement product schema
1051
+ - Create article/blog schema
1052
+ - Add organization schema
1053
+ - Validate with Google Rich Results Test
1054
+ `
1055
+ }
1056
+ ]
1057
+ },
1058
+ // DevOps Team Group
1059
+ {
1060
+ id: "devops-team",
1061
+ name: { "en": "DevOps Team", "zh-CN": "DevOps \u56E2\u961F" },
1062
+ description: { "en": "Complete DevOps and infrastructure team", "zh-CN": "\u5B8C\u6574\u7684 DevOps \u548C\u57FA\u7840\u8BBE\u65BD\u56E2\u961F" },
1063
+ category: "devops",
1064
+ version: "1.0.0",
1065
+ icon: "\u{1F680}",
1066
+ defaultEnabled: false,
1067
+ skills: ["devops-docker", "devops-ci", "devops-deploy", "devops-monitor"],
1068
+ agents: [
1069
+ {
1070
+ id: "devops-docker-expert",
1071
+ name: "Docker Expert",
1072
+ description: "Containerization and Docker configuration specialist",
1073
+ model: "sonnet",
1074
+ required: true,
1075
+ tags: ["devops", "docker"],
1076
+ definition: `---
1077
+ name: devops-docker-expert
1078
+ description: Docker and containerization specialist
1079
+ model: sonnet
1080
+ ---
1081
+
1082
+ # Docker Expert Agent
1083
+
1084
+ ## CORE MISSION
1085
+ Create efficient, secure Docker configurations for applications.
1086
+
1087
+ ## RESPONSIBILITIES
1088
+ - Write optimized Dockerfiles
1089
+ - Create docker-compose configurations
1090
+ - Implement multi-stage builds
1091
+ - Optimize image sizes
1092
+ - Configure container networking
1093
+ `
1094
+ },
1095
+ {
1096
+ id: "devops-ci-expert",
1097
+ name: "CI/CD Expert",
1098
+ description: "Continuous integration and deployment specialist",
1099
+ model: "sonnet",
1100
+ required: true,
1101
+ tags: ["devops", "ci", "cd"],
1102
+ definition: `---
1103
+ name: devops-ci-expert
1104
+ description: CI/CD pipeline specialist
1105
+ model: sonnet
1106
+ ---
1107
+
1108
+ # CI/CD Expert Agent
1109
+
1110
+ ## CORE MISSION
1111
+ Design and implement robust CI/CD pipelines for automated testing and deployment.
1112
+
1113
+ ## RESPONSIBILITIES
1114
+ - Create GitHub Actions workflows
1115
+ - Set up GitLab CI pipelines
1116
+ - Configure automated testing
1117
+ - Implement deployment strategies
1118
+ - Set up artifact management
1119
+ `
1120
+ }
1121
+ ]
1122
+ },
1123
+ // Security Team Group
1124
+ {
1125
+ id: "security-team",
1126
+ name: { "en": "Security Team", "zh-CN": "\u5B89\u5168\u56E2\u961F" },
1127
+ description: { "en": "Security audit and vulnerability assessment team", "zh-CN": "\u5B89\u5168\u5BA1\u8BA1\u548C\u6F0F\u6D1E\u8BC4\u4F30\u56E2\u961F" },
1128
+ category: "devops",
1129
+ version: "1.0.0",
1130
+ icon: "\u{1F512}",
1131
+ defaultEnabled: false,
1132
+ skills: [],
1133
+ agents: [
1134
+ {
1135
+ id: "security-auditor",
1136
+ name: "Security Auditor",
1137
+ description: "Performs security audits and vulnerability assessments",
1138
+ model: "opus",
1139
+ required: true,
1140
+ tags: ["security", "audit"],
1141
+ definition: `---
1142
+ name: security-auditor
1143
+ description: Security audit and vulnerability assessment specialist
1144
+ model: opus
1145
+ ---
1146
+
1147
+ # Security Auditor Agent
1148
+
1149
+ ## CORE MISSION
1150
+ Identify and report security vulnerabilities, ensuring code follows security best practices.
1151
+
1152
+ ## RESPONSIBILITIES
1153
+ - Audit code for OWASP Top 10 vulnerabilities
1154
+ - Check for SQL injection risks
1155
+ - Identify XSS vulnerabilities
1156
+ - Review authentication implementations
1157
+ - Check authorization logic
1158
+ - Audit dependency security
1159
+ - Review secrets management
1160
+ `
1161
+ }
1162
+ ]
1163
+ }
1164
+ ];
1165
+
1166
+ const DEFAULT_AIDER_CONFIG = {
1167
+ model: "claude-3-5-sonnet-20241022",
1168
+ editFormat: "diff",
1169
+ autoCommits: true,
1170
+ dirtyCommits: false,
1171
+ darkMode: true,
1172
+ prettyOutput: true,
1173
+ showDiffs: true,
1174
+ mapTokens: 1024,
1175
+ maxChatHistory: 20,
1176
+ cachePrompts: true
1177
+ };
1178
+ async function isAiderInstalled() {
1179
+ try {
1180
+ const result = await exec("aider", ["--version"]);
1181
+ return result.exitCode === 0;
1182
+ } catch {
1183
+ return false;
1184
+ }
1185
+ }
1186
+ async function getAiderVersion() {
1187
+ try {
1188
+ const result = await exec("aider", ["--version"]);
1189
+ return result.stdout.trim();
1190
+ } catch {
1191
+ return null;
1192
+ }
1193
+ }
1194
+ async function installAider() {
1195
+ try {
1196
+ const result = await exec("pip", ["install", "aider-chat"]);
1197
+ if (result.exitCode === 0) {
1198
+ return { success: true, message: "Aider installed successfully via pip" };
1199
+ }
1200
+ const pipxResult = await exec("pipx", ["install", "aider-chat"]);
1201
+ if (pipxResult.exitCode === 0) {
1202
+ return { success: true, message: "Aider installed successfully via pipx" };
1203
+ }
1204
+ return { success: false, message: "Failed to install Aider" };
1205
+ } catch (error) {
1206
+ return {
1207
+ success: false,
1208
+ message: `Failed to install Aider: ${error instanceof Error ? error.message : "Unknown error"}`
1209
+ };
1210
+ }
1211
+ }
1212
+ function ensureAiderDir() {
1213
+ if (!existsSync(AIDER_DIR)) {
1214
+ mkdirSync(AIDER_DIR, { recursive: true });
1215
+ }
1216
+ }
1217
+ function readAiderConfig() {
1218
+ if (!existsSync(AIDER_CONFIG_FILE)) {
1219
+ return DEFAULT_AIDER_CONFIG;
1220
+ }
1221
+ try {
1222
+ const content = readFileSync(AIDER_CONFIG_FILE, "utf-8");
1223
+ return parseYamlConfig(content);
1224
+ } catch {
1225
+ return DEFAULT_AIDER_CONFIG;
1226
+ }
1227
+ }
1228
+ function writeAiderConfig(config) {
1229
+ ensureAiderDir();
1230
+ const yamlContent = generateYamlConfig(config);
1231
+ writeFileSync(AIDER_CONFIG_FILE, yamlContent);
1232
+ }
1233
+ function parseYamlConfig(content) {
1234
+ const config = {};
1235
+ const lines = content.split("\n");
1236
+ for (const line of lines) {
1237
+ const trimmed = line.trim();
1238
+ if (!trimmed || trimmed.startsWith("#"))
1239
+ continue;
1240
+ const match = trimmed.match(/^(\w+):\s*(.+)$/);
1241
+ if (match) {
1242
+ const [, key, value] = match;
1243
+ const normalizedKey = kebabToCamel(key);
1244
+ if (value === "true")
1245
+ config[normalizedKey] = true;
1246
+ else if (value === "false")
1247
+ config[normalizedKey] = false;
1248
+ else if (/^\d+$/.test(value))
1249
+ config[normalizedKey] = Number.parseInt(value);
1250
+ else
1251
+ config[normalizedKey] = value;
1252
+ }
1253
+ }
1254
+ return config;
1255
+ }
1256
+ function generateYamlConfig(config) {
1257
+ const lines = [
1258
+ "# Aider Configuration",
1259
+ "# Generated by CCJK",
1260
+ ""
1261
+ ];
1262
+ for (const [key, value] of Object.entries(config)) {
1263
+ if (value !== void 0) {
1264
+ const yamlKey = camelToKebab(key);
1265
+ lines.push(`${yamlKey}: ${value}`);
1266
+ }
1267
+ }
1268
+ return lines.join("\n");
1269
+ }
1270
+ function kebabToCamel(str) {
1271
+ return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
1272
+ }
1273
+ function camelToKebab(str) {
1274
+ return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
1275
+ }
1276
+ function configureAiderApi(apiKey, apiBase) {
1277
+ ensureAiderDir();
1278
+ const envLines = [];
1279
+ if (apiKey.startsWith("sk-ant")) {
1280
+ envLines.push(`ANTHROPIC_API_KEY=${apiKey}`);
1281
+ } else if (apiKey.startsWith("sk-")) {
1282
+ envLines.push(`OPENAI_API_KEY=${apiKey}`);
1283
+ } else {
1284
+ envLines.push(`ANTHROPIC_API_KEY=${apiKey}`);
1285
+ }
1286
+ if (apiBase) {
1287
+ envLines.push(`OPENAI_API_BASE=${apiBase}`);
1288
+ }
1289
+ writeFileSync(AIDER_ENV_FILE, envLines.join("\n"));
1290
+ }
1291
+ function getAiderModelPresets() {
1292
+ return {
1293
+ "claude-sonnet": {
1294
+ model: "claude-3-5-sonnet-20241022",
1295
+ description: "Claude 3.5 Sonnet - Best for coding"
1296
+ },
1297
+ "claude-opus": {
1298
+ model: "claude-3-opus-20240229",
1299
+ description: "Claude 3 Opus - Most capable"
1300
+ },
1301
+ "gpt-4o": {
1302
+ model: "gpt-4o",
1303
+ description: "GPT-4o - OpenAI flagship"
1304
+ },
1305
+ "deepseek": {
1306
+ model: "deepseek-chat",
1307
+ description: "DeepSeek - Cost effective"
1308
+ },
1309
+ "gemini": {
1310
+ model: "gemini-1.5-pro",
1311
+ description: "Gemini 1.5 Pro - Google AI"
1312
+ }
1313
+ };
1314
+ }
1315
+ async function runAider(options) {
1316
+ const args = [];
1317
+ if (options.model) {
1318
+ args.push("--model", options.model);
1319
+ }
1320
+ if (options.autoCommit === false) {
1321
+ args.push("--no-auto-commits");
1322
+ }
1323
+ if (options.message) {
1324
+ args.push("--message", options.message);
1325
+ }
1326
+ if (options.files && options.files.length > 0) {
1327
+ args.push(...options.files);
1328
+ }
1329
+ try {
1330
+ const result = await exec("aider", args);
1331
+ return {
1332
+ success: result.exitCode === 0,
1333
+ output: result.stdout + result.stderr
1334
+ };
1335
+ } catch (error) {
1336
+ return {
1337
+ success: false,
1338
+ output: error instanceof Error ? error.message : "Unknown error"
1339
+ };
1340
+ }
1341
+ }
1342
+
1343
+ const DEFAULT_CONTINUE_CONFIG = {
1344
+ models: [
1345
+ {
1346
+ title: "Claude 3.5 Sonnet",
1347
+ provider: "anthropic",
1348
+ model: "claude-3-5-sonnet-20241022"
1349
+ }
1350
+ ],
1351
+ tabAutocompleteModel: {
1352
+ title: "Starcoder2 3B",
1353
+ provider: "ollama",
1354
+ model: "starcoder2:3b"
1355
+ },
1356
+ contextProviders: [
1357
+ { name: "code", params: {} },
1358
+ { name: "docs", params: {} },
1359
+ { name: "diff", params: {} },
1360
+ { name: "terminal", params: {} },
1361
+ { name: "problems", params: {} },
1362
+ { name: "folder", params: {} },
1363
+ { name: "codebase", params: {} }
1364
+ ],
1365
+ slashCommands: [
1366
+ { name: "edit", description: "Edit selected code" },
1367
+ { name: "comment", description: "Add comments to code" },
1368
+ { name: "share", description: "Share conversation" },
1369
+ { name: "cmd", description: "Run terminal command" },
1370
+ { name: "commit", description: "Generate commit message" }
1371
+ ],
1372
+ allowAnonymousTelemetry: false
1373
+ };
1374
+ function ensureContinueDir() {
1375
+ if (!existsSync(CONTINUE_DIR)) {
1376
+ mkdirSync(CONTINUE_DIR, { recursive: true });
1377
+ }
1378
+ }
1379
+ function isContinueConfigured() {
1380
+ return existsSync(CONTINUE_CONFIG_FILE);
1381
+ }
1382
+ function readContinueConfig() {
1383
+ if (!existsSync(CONTINUE_CONFIG_FILE)) {
1384
+ return DEFAULT_CONTINUE_CONFIG;
1385
+ }
1386
+ try {
1387
+ const content = readFileSync(CONTINUE_CONFIG_FILE, "utf-8");
1388
+ return JSON.parse(content);
1389
+ } catch {
1390
+ return DEFAULT_CONTINUE_CONFIG;
1391
+ }
1392
+ }
1393
+ function writeContinueConfig(config) {
1394
+ ensureContinueDir();
1395
+ writeFileSync(CONTINUE_CONFIG_FILE, JSON.stringify(config, null, 2));
1396
+ }
1397
+ function addContinueModel(model) {
1398
+ const config = readContinueConfig();
1399
+ if (!config.models) {
1400
+ config.models = [];
1401
+ }
1402
+ config.models = config.models.filter((m) => m.title !== model.title);
1403
+ config.models.push(model);
1404
+ writeContinueConfig(config);
1405
+ }
1406
+ function removeContinueModel(title) {
1407
+ const config = readContinueConfig();
1408
+ if (!config.models)
1409
+ return false;
1410
+ const initialLength = config.models.length;
1411
+ config.models = config.models.filter((m) => m.title !== title);
1412
+ if (config.models.length < initialLength) {
1413
+ writeContinueConfig(config);
1414
+ return true;
1415
+ }
1416
+ return false;
1417
+ }
1418
+ function getContinueProviderPresets() {
1419
+ return {
1420
+ "anthropic-sonnet": {
1421
+ title: "Claude 3.5 Sonnet",
1422
+ provider: "anthropic",
1423
+ model: "claude-3-5-sonnet-20241022"
1424
+ },
1425
+ "anthropic-opus": {
1426
+ title: "Claude 3 Opus",
1427
+ provider: "anthropic",
1428
+ model: "claude-3-opus-20240229"
1429
+ },
1430
+ "openai-gpt4o": {
1431
+ title: "GPT-4o",
1432
+ provider: "openai",
1433
+ model: "gpt-4o"
1434
+ },
1435
+ "openai-gpt4": {
1436
+ title: "GPT-4 Turbo",
1437
+ provider: "openai",
1438
+ model: "gpt-4-turbo"
1439
+ },
1440
+ "ollama-llama": {
1441
+ title: "Llama 3.1 (Local)",
1442
+ provider: "ollama",
1443
+ model: "llama3.1:8b"
1444
+ },
1445
+ "ollama-codellama": {
1446
+ title: "Code Llama (Local)",
1447
+ provider: "ollama",
1448
+ model: "codellama:7b"
1449
+ },
1450
+ "gemini-pro": {
1451
+ title: "Gemini Pro",
1452
+ provider: "gemini",
1453
+ model: "gemini-1.5-pro"
1454
+ },
1455
+ "deepseek-chat": {
1456
+ title: "DeepSeek Chat",
1457
+ provider: "deepseek",
1458
+ model: "deepseek-chat"
1459
+ }
1460
+ };
1461
+ }
1462
+ function configureContinueApi(provider, apiKey, apiBase) {
1463
+ const config = readContinueConfig();
1464
+ if (config.models) {
1465
+ config.models = config.models.map((model) => {
1466
+ if (model.provider === provider) {
1467
+ return {
1468
+ ...model,
1469
+ apiKey,
1470
+ ...apiBase ? { apiBase } : {}
1471
+ };
1472
+ }
1473
+ return model;
1474
+ });
1475
+ }
1476
+ writeContinueConfig(config);
1477
+ }
1478
+ function addContinueMcpServer(_name, server) {
1479
+ const config = readContinueConfig();
1480
+ if (!config.experimental) {
1481
+ config.experimental = {};
1482
+ }
1483
+ if (!config.experimental.modelContextProtocolServers) {
1484
+ config.experimental.modelContextProtocolServers = [];
1485
+ }
1486
+ config.experimental.modelContextProtocolServers.push(server);
1487
+ writeContinueConfig(config);
1488
+ }
1489
+ function addContinueCustomCommand(name, description, prompt) {
1490
+ const config = readContinueConfig();
1491
+ if (!config.customCommands) {
1492
+ config.customCommands = [];
1493
+ }
1494
+ config.customCommands = config.customCommands.filter((c) => c.name !== name);
1495
+ config.customCommands.push({ name, description, prompt });
1496
+ writeContinueConfig(config);
1497
+ }
1498
+ function enableContinueContextProvider(name, params) {
1499
+ const config = readContinueConfig();
1500
+ if (!config.contextProviders) {
1501
+ config.contextProviders = [];
1502
+ }
1503
+ if (!config.contextProviders.find((p) => p.name === name)) {
1504
+ config.contextProviders.push({ name, params });
1505
+ writeContinueConfig(config);
1506
+ }
1507
+ }
1508
+ function syncSkillsToContinue(skills) {
1509
+ const config = readContinueConfig();
1510
+ if (!config.customCommands) {
1511
+ config.customCommands = [];
1512
+ }
1513
+ for (const skill of skills) {
1514
+ const existingIndex = config.customCommands.findIndex((c) => c.name === skill.id);
1515
+ if (existingIndex >= 0) {
1516
+ config.customCommands[existingIndex] = {
1517
+ name: skill.id,
1518
+ description: skill.description,
1519
+ prompt: skill.template
1520
+ };
1521
+ } else {
1522
+ config.customCommands.push({
1523
+ name: skill.id,
1524
+ description: skill.description,
1525
+ prompt: skill.template
1526
+ });
1527
+ }
1528
+ }
1529
+ writeContinueConfig(config);
1530
+ }
1531
+
1532
+ class MenuBuilder {
1533
+ sections = [];
1534
+ options;
1535
+ constructor(options) {
1536
+ this.options = {
1537
+ showBack: true,
1538
+ showExit: true,
1539
+ boxStyle: "double",
1540
+ ...options
1541
+ };
1542
+ }
1543
+ /**
1544
+ * Add a section to the menu
1545
+ */
1546
+ addSection(title, icon) {
1547
+ this.sections.push({ title, items: [], icon });
1548
+ return this;
1549
+ }
1550
+ /**
1551
+ * Add an item to the current section
1552
+ */
1553
+ addItem(item) {
1554
+ if (this.sections.length === 0) {
1555
+ this.addSection("");
1556
+ }
1557
+ this.sections[this.sections.length - 1].items.push(item);
1558
+ return this;
1559
+ }
1560
+ /**
1561
+ * Add a separator
1562
+ */
1563
+ addSeparator() {
1564
+ return this;
1565
+ }
1566
+ /**
1567
+ * Render the menu to string
1568
+ */
1569
+ render() {
1570
+ const lines = [];
1571
+ if (this.options.breadcrumb && this.options.breadcrumb.length > 0) {
1572
+ const breadcrumb = this.options.breadcrumb.join(" > ");
1573
+ lines.push(ansis.gray(` ${breadcrumb}`));
1574
+ lines.push("");
1575
+ }
1576
+ lines.push(sectionDivider(this.options.title, 50));
1577
+ if (this.options.subtitle) {
1578
+ lines.push(ansis.gray(` ${this.options.subtitle}`));
1579
+ }
1580
+ lines.push("");
1581
+ for (const section of this.sections) {
1582
+ const visibleItems = section.items.filter(
1583
+ (item) => item.visible ? item.visible() : true
1584
+ );
1585
+ if (visibleItems.length === 0)
1586
+ continue;
1587
+ if (section.title) {
1588
+ const icon = section.icon ? `${section.icon} ` : "";
1589
+ lines.push(ansis.white.bold(` ${icon}${section.title}`));
1590
+ }
1591
+ for (const item of visibleItems) {
1592
+ const keyPart = item.disabled ? ansis.gray(`[${item.key}]`) : item.highlight ? ansis.yellow.bold(`[${item.key}]`) : ansis.cyan.bold(`[${item.key}]`);
1593
+ const iconPart = item.icon ? `${item.icon} ` : "";
1594
+ const labelPart = item.disabled ? ansis.gray(item.label) : item.highlight ? ansis.yellow(item.label) : ansis.white(item.label);
1595
+ const descPart = item.description ? ansis.gray(` - ${item.description}`) : "";
1596
+ lines.push(` ${keyPart} ${iconPart}${labelPart}${descPart}`);
1597
+ }
1598
+ lines.push("");
1599
+ }
1600
+ const systemItems = [];
1601
+ if (this.options.showBack) {
1602
+ systemItems.push(`${ansis.gray("[B]")} ${ansis.gray("Back")}`);
1603
+ }
1604
+ if (this.options.showExit) {
1605
+ systemItems.push(`${ansis.gray("[Q]")} ${ansis.gray("Quit")}`);
1606
+ }
1607
+ if (systemItems.length > 0) {
1608
+ lines.push(` ${systemItems.join(" ")}`);
1609
+ }
1610
+ lines.push(ansis.cyan("\u2550".repeat(50)));
1611
+ return lines.join("\n");
1612
+ }
1613
+ /**
1614
+ * Display menu and handle input
1615
+ */
1616
+ async show() {
1617
+ console.log(this.render());
1618
+ const validKeys = /* @__PURE__ */ new Set();
1619
+ const keyMap = /* @__PURE__ */ new Map();
1620
+ for (const section of this.sections) {
1621
+ for (const item2 of section.items) {
1622
+ if (item2.visible ? item2.visible() : true) {
1623
+ if (!item2.disabled) {
1624
+ validKeys.add(item2.key.toLowerCase());
1625
+ validKeys.add(item2.key.toUpperCase());
1626
+ keyMap.set(item2.key.toLowerCase(), item2);
1627
+ }
1628
+ }
1629
+ }
1630
+ }
1631
+ if (this.options.showBack) {
1632
+ validKeys.add("b");
1633
+ validKeys.add("B");
1634
+ }
1635
+ if (this.options.showExit) {
1636
+ validKeys.add("q");
1637
+ validKeys.add("Q");
1638
+ }
1639
+ const { choice } = await inquirer.prompt([
1640
+ {
1641
+ type: "input",
1642
+ name: "choice",
1643
+ message: COLORS.primary("Select option:"),
1644
+ validate: (value) => {
1645
+ if (validKeys.has(value)) {
1646
+ return true;
1647
+ }
1648
+ return "Invalid option. Please try again.";
1649
+ }
1650
+ }
1651
+ ]);
1652
+ const key = choice.toLowerCase();
1653
+ if (key === "b" && this.options.showBack) {
1654
+ return { action: "back" };
1655
+ }
1656
+ if (key === "q" && this.options.showExit) {
1657
+ return { action: "exit" };
1658
+ }
1659
+ const item = keyMap.get(key);
1660
+ if (item) {
1661
+ return item.action();
1662
+ }
1663
+ return { action: "continue" };
1664
+ }
1665
+ /**
1666
+ * Run menu loop until exit or back
1667
+ */
1668
+ async loop() {
1669
+ while (true) {
1670
+ const result = await this.show();
1671
+ if (result.action === "exit" || result.action === "back") {
1672
+ return result;
1673
+ }
1674
+ }
1675
+ }
1676
+ }
1677
+ async function showQuickMenu(title, items) {
1678
+ const builder = new MenuBuilder({ title, showBack: false });
1679
+ for (const item of items) {
1680
+ builder.addItem({
1681
+ key: item.key,
1682
+ label: item.label,
1683
+ action: async () => {
1684
+ await item.action();
1685
+ return { action: "continue" };
1686
+ }
1687
+ });
1688
+ }
1689
+ await builder.show();
1690
+ }
1691
+ async function confirm(message, defaultValue = false) {
1692
+ const { result } = await inquirer.prompt([
1693
+ {
1694
+ type: "confirm",
1695
+ name: "result",
1696
+ message,
1697
+ default: defaultValue
1698
+ }
1699
+ ]);
1700
+ return result;
1701
+ }
1702
+ function showStatus(type, message) {
1703
+ console.log(STATUS[type](message));
1704
+ }
1705
+
1706
+ export { AIDER_CONFIG_FILE, AIDER_DIR, AIDER_ENV_FILE, CCJK_GROUPS_DIR, CCJK_PLUGINS_DIR, CCJK_SKILLS_DIR, COLORS, CONTINUE_CONFIG_FILE, CONTINUE_DIR, MenuBuilder, STATUS, addContinueCustomCommand, addContinueMcpServer, addContinueModel, addGroup, addSkill, configureAiderApi, configureContinueApi, confirm, createBatchSkills, disableGroup, disablePlugin, discoverPlugins, enableContinueContextProvider, enableGroup, enablePlugin, ensureAiderDir, ensureContinueDir, ensureGroupsDir, ensurePluginsDir, ensureSkillsDir, exportGroups, exportSkills, getAiderModelPresets, getAiderVersion, getAllGroups, getAllSkills, getBatchCategories, getContinueProviderPresets, getEnabledAgents, getEnabledSkillIds, getGroup, getRegistry as getGroupRegistry, getLoadedPlugins, getPluginAgents, getPluginInfo, getPluginMcpServices, getPluginOutputStyles, getPluginSkills, getPluginWorkflows, getSkill, getRegistry$1 as getSkillRegistry, importGroups, importSkills, initializePlugins, installAider, isAiderInstalled, isContinueConfigured, isGroupEnabled, listPlugins, loadPlugin, readAiderConfig, readContinueConfig, readPluginConfig, refreshRegistry as refreshGroupRegistry, refreshRegistry$1 as refreshSkillRegistry, removeContinueModel, removeGroup, removeSkill, runAider, searchGroups, searchSkills, sectionDivider, setSkillEnabled, showQuickMenu, showStatus, syncSkillsToContinue, unloadPlugin, writeAiderConfig, writeContinueConfig, writePluginConfig };