ccjk 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.ja.md +455 -0
- package/README.ko.md +455 -0
- package/README.md +550 -0
- package/README.zh-CN.md +488 -0
- package/bin/ccjk.mjs +2 -0
- package/dist/chunks/api-providers.mjs +89 -0
- package/dist/chunks/claude-code-config-manager.mjs +733 -0
- package/dist/chunks/claude-code-incremental-manager.mjs +603 -0
- package/dist/chunks/codex-config-switch.mjs +427 -0
- package/dist/chunks/codex-provider-manager.mjs +232 -0
- package/dist/chunks/codex-uninstaller.mjs +404 -0
- package/dist/chunks/commands.mjs +120 -0
- package/dist/chunks/features.mjs +642 -0
- package/dist/chunks/simple-config.mjs +10445 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.mjs +5972 -0
- package/dist/i18n/locales/en/api.json +63 -0
- package/dist/i18n/locales/en/ccjk.json +276 -0
- package/dist/i18n/locales/en/ccr.json +65 -0
- package/dist/i18n/locales/en/cli.json +57 -0
- package/dist/i18n/locales/en/codex.json +124 -0
- package/dist/i18n/locales/en/cometix.json +29 -0
- package/dist/i18n/locales/en/common.json +20 -0
- package/dist/i18n/locales/en/configuration.json +77 -0
- package/dist/i18n/locales/en/errors.json +26 -0
- package/dist/i18n/locales/en/installation.json +80 -0
- package/dist/i18n/locales/en/interview.json +104 -0
- package/dist/i18n/locales/en/language.json +19 -0
- package/dist/i18n/locales/en/mcp.json +38 -0
- package/dist/i18n/locales/en/menu.json +51 -0
- package/dist/i18n/locales/en/multi-config.json +79 -0
- package/dist/i18n/locales/en/shencha.json +14 -0
- package/dist/i18n/locales/en/team.json +7 -0
- package/dist/i18n/locales/en/tools.json +42 -0
- package/dist/i18n/locales/en/uninstall.json +56 -0
- package/dist/i18n/locales/en/updater.json +25 -0
- package/dist/i18n/locales/en/workflow.json +25 -0
- package/dist/i18n/locales/zh-CN/api.json +63 -0
- package/dist/i18n/locales/zh-CN/ccjk.json +276 -0
- package/dist/i18n/locales/zh-CN/ccr.json +65 -0
- package/dist/i18n/locales/zh-CN/cli.json +57 -0
- package/dist/i18n/locales/zh-CN/codex.json +124 -0
- package/dist/i18n/locales/zh-CN/cometix.json +29 -0
- package/dist/i18n/locales/zh-CN/common.json +20 -0
- package/dist/i18n/locales/zh-CN/configuration.json +77 -0
- package/dist/i18n/locales/zh-CN/errors.json +26 -0
- package/dist/i18n/locales/zh-CN/installation.json +80 -0
- package/dist/i18n/locales/zh-CN/interview.json +104 -0
- package/dist/i18n/locales/zh-CN/language.json +19 -0
- package/dist/i18n/locales/zh-CN/mcp.json +38 -0
- package/dist/i18n/locales/zh-CN/menu.json +51 -0
- package/dist/i18n/locales/zh-CN/multi-config.json +79 -0
- package/dist/i18n/locales/zh-CN/shencha.json +14 -0
- package/dist/i18n/locales/zh-CN/team.json +7 -0
- package/dist/i18n/locales/zh-CN/tools.json +42 -0
- package/dist/i18n/locales/zh-CN/uninstall.json +56 -0
- package/dist/i18n/locales/zh-CN/updater.json +25 -0
- package/dist/i18n/locales/zh-CN/workflow.json +25 -0
- package/dist/index.d.mts +2644 -0
- package/dist/index.d.ts +2644 -0
- package/dist/index.mjs +1706 -0
- package/package.json +157 -0
- package/templates/CLAUDE.md +219 -0
- package/templates/claude-code/CLAUDE.md +250 -0
- package/templates/claude-code/common/settings.json +38 -0
- package/templates/claude-code/en/workflow/bmad/commands/bmad-init.md +165 -0
- package/templates/claude-code/en/workflow/common/agents/get-current-datetime.md +29 -0
- package/templates/claude-code/en/workflow/common/agents/init-architect.md +114 -0
- package/templates/claude-code/en/workflow/common/commands/init-project.md +53 -0
- package/templates/claude-code/en/workflow/plan/agents/planner.md +116 -0
- package/templates/claude-code/en/workflow/plan/agents/ui-ux-designer.md +91 -0
- package/templates/claude-code/en/workflow/plan/commands/feat.md +105 -0
- package/templates/claude-code/zh-CN/workflow/bmad/commands/bmad-init.md +172 -0
- package/templates/claude-code/zh-CN/workflow/common/agents/get-current-datetime.md +29 -0
- package/templates/claude-code/zh-CN/workflow/common/agents/init-architect.md +114 -0
- package/templates/claude-code/zh-CN/workflow/common/commands/init-project.md +53 -0
- package/templates/claude-code/zh-CN/workflow/plan/agents/planner.md +116 -0
- package/templates/claude-code/zh-CN/workflow/plan/agents/ui-ux-designer.md +91 -0
- package/templates/claude-code/zh-CN/workflow/plan/commands/feat.md +105 -0
- package/templates/codex/common/config.toml +0 -0
- package/templates/common/output-styles/en/casual-friendly.md +97 -0
- package/templates/common/output-styles/en/engineer-professional.md +88 -0
- package/templates/common/output-styles/en/expert-concise.md +93 -0
- package/templates/common/output-styles/en/laowang-engineer.md +127 -0
- package/templates/common/output-styles/en/nekomata-engineer.md +120 -0
- package/templates/common/output-styles/en/ojousama-engineer.md +121 -0
- package/templates/common/output-styles/en/teaching-mode.md +102 -0
- package/templates/common/output-styles/en/technical-precise.md +101 -0
- package/templates/common/output-styles/zh-CN/engineer-professional.md +89 -0
- package/templates/common/output-styles/zh-CN/laowang-engineer.md +127 -0
- package/templates/common/output-styles/zh-CN/nekomata-engineer.md +120 -0
- package/templates/common/output-styles/zh-CN/ojousama-engineer.md +121 -0
- package/templates/common/workflow/git/en/git-cleanBranches.md +102 -0
- package/templates/common/workflow/git/en/git-commit.md +205 -0
- package/templates/common/workflow/git/en/git-rollback.md +90 -0
- package/templates/common/workflow/git/en/git-worktree.md +276 -0
- package/templates/common/workflow/git/zh-CN/git-cleanBranches.md +102 -0
- package/templates/common/workflow/git/zh-CN/git-commit.md +205 -0
- package/templates/common/workflow/git/zh-CN/git-rollback.md +90 -0
- package/templates/common/workflow/git/zh-CN/git-worktree.md +276 -0
- package/templates/common/workflow/interview/en/interview.md +212 -0
- package/templates/common/workflow/interview/zh-CN/interview.md +212 -0
- package/templates/common/workflow/sixStep/en/workflow.md +251 -0
- package/templates/common/workflow/sixStep/zh-CN/workflow.md +215 -0
- package/templates/industry/devops/en/ci-cd-pipeline.md +410 -0
- package/templates/industry/web-dev/en/api-design.md +299 -0
- package/templates/industry/web-dev/en/react-nextjs-setup.md +236 -0
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 };
|