ccjk 13.6.4 → 13.6.7
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/dist/chunks/agents.mjs +1 -1
- package/dist/chunks/api-config-selector.mjs +6 -4
- package/dist/chunks/auto-updater.mjs +100 -2
- package/dist/chunks/banner.mjs +0 -16
- package/dist/chunks/ccjk-mcp.mjs +2 -2
- package/dist/chunks/ccr.mjs +6 -4
- package/dist/chunks/check-updates.mjs +28 -17
- package/dist/chunks/claude-code-config-manager.mjs +3 -1
- package/dist/chunks/claude-code-incremental-manager.mjs +46 -20
- package/dist/chunks/claude-config.mjs +52 -2
- package/dist/chunks/claude-wrapper.mjs +1 -1
- package/dist/chunks/cli-hook.mjs +25 -83
- package/dist/chunks/codex-config-switch.mjs +3 -2
- package/dist/chunks/codex-provider-manager.mjs +1 -0
- package/dist/chunks/codex.mjs +3 -359
- package/dist/chunks/config-switch.mjs +23 -10
- package/dist/chunks/config.mjs +1 -1
- package/dist/chunks/config2.mjs +3 -3
- package/dist/chunks/constants.mjs +179 -3
- package/dist/chunks/doctor.mjs +1 -1
- package/dist/chunks/features.mjs +76 -11
- package/dist/chunks/index10.mjs +55 -36
- package/dist/chunks/init.mjs +120 -61
- package/dist/chunks/installer.mjs +80 -19
- package/dist/chunks/mcp-cli.mjs +17 -16
- package/dist/chunks/mcp.mjs +8 -7
- package/dist/chunks/memory-check.mjs +1 -1
- package/dist/chunks/package.mjs +1 -1
- package/dist/chunks/platform.mjs +5 -1
- package/dist/chunks/quick-setup.mjs +13 -11
- package/dist/chunks/research.mjs +1177 -0
- package/dist/chunks/sessions.mjs +1 -1
- package/dist/chunks/smart-defaults.mjs +42 -14
- package/dist/chunks/uninstall.mjs +2 -2
- package/dist/chunks/update.mjs +14 -13
- package/dist/chunks/version-checker.mjs +11 -1
- package/dist/cli.mjs +32 -0
- package/dist/i18n/locales/en/cli.json +0 -4
- package/dist/i18n/locales/en/menu.json +3 -3
- package/dist/i18n/locales/en/notification.json +2 -2
- package/dist/i18n/locales/zh-CN/cli.json +0 -4
- package/dist/i18n/locales/zh-CN/menu.json +3 -3
- package/dist/i18n/locales/zh-CN/notification.json +2 -2
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +8 -174
- package/dist/shared/{ccjk.DvAP4XfP.mjs → ccjk.B4aXNclK.mjs} +2 -2
- package/dist/shared/ccjk.BI-hdI7P.mjs +30 -0
- package/dist/shared/{ccjk.DwSebGy0.mjs → ccjk.BOO14f66.mjs} +1 -1
- package/dist/shared/ccjk.BnsY5WxD.mjs +171 -0
- package/dist/shared/{ccjk.C4m4ypdk.mjs → ccjk.DHaUdzX3.mjs} +4 -3
- package/dist/shared/ccjk.DKXs7Fbm.mjs +361 -0
- package/dist/shared/{ccjk.BP5hsTZQ.mjs → ccjk.Dz0ssUQx.mjs} +1 -1
- package/dist/shared/ccjk.yYQMbHH3.mjs +115 -0
- package/package.json +70 -65
- package/templates/common/workflow/essential/en/feat.md +68 -291
- package/templates/common/workflow/sixStep/en/workflow.md +56 -330
- package/dist/shared/ccjk.CiKtBUW_.mjs +0 -54
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import a from '../chunks/index5.mjs';
|
|
2
|
+
import { i as inquirer } from '../chunks/index6.mjs';
|
|
3
|
+
import { g as getMcpServices, M as MCP_SERVICE_CONFIGS } from './ccjk.DKXs7Fbm.mjs';
|
|
4
|
+
import { ensureI18nInitialized, i18n } from '../chunks/index2.mjs';
|
|
5
|
+
|
|
6
|
+
async function selectMcpServices() {
|
|
7
|
+
ensureI18nInitialized();
|
|
8
|
+
const mcpServices = await getMcpServices();
|
|
9
|
+
const defaultSelectedIds = new Set(
|
|
10
|
+
MCP_SERVICE_CONFIGS.filter((c) => c.defaultSelected).map((c) => c.id)
|
|
11
|
+
);
|
|
12
|
+
const choices = mcpServices.map((service) => ({
|
|
13
|
+
name: `${service.name} - ${a.gray(service.description)}`,
|
|
14
|
+
value: service.id,
|
|
15
|
+
checked: defaultSelectedIds.has(service.id)
|
|
16
|
+
}));
|
|
17
|
+
const { services } = await inquirer.prompt({
|
|
18
|
+
type: "checkbox",
|
|
19
|
+
name: "services",
|
|
20
|
+
message: `${i18n.t("mcp:selectMcpServices")}${i18n.t("common:multiSelectHint")}`,
|
|
21
|
+
choices
|
|
22
|
+
});
|
|
23
|
+
if (services === void 0) {
|
|
24
|
+
console.log(a.yellow(i18n.t("common:cancelled")));
|
|
25
|
+
return void 0;
|
|
26
|
+
}
|
|
27
|
+
return services;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { selectMcpServices as s };
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { exec, spawn } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
|
|
4
|
+
const execAsync = promisify(exec);
|
|
5
|
+
async function executeCommand(command, args = [], options = {}) {
|
|
6
|
+
try {
|
|
7
|
+
const fullCommand = buildCommand(command, args);
|
|
8
|
+
const execOptions = {
|
|
9
|
+
cwd: options.cwd,
|
|
10
|
+
env: { ...process.env, ...options.env },
|
|
11
|
+
timeout: options.timeout,
|
|
12
|
+
shell: typeof options.shell === "string" ? options.shell : options.shell ? "/bin/sh" : void 0,
|
|
13
|
+
encoding: options.encoding || "utf8",
|
|
14
|
+
maxBuffer: options.maxBuffer || 1024 * 1024 * 10
|
|
15
|
+
// 10MB default
|
|
16
|
+
};
|
|
17
|
+
const { stdout, stderr } = await execAsync(fullCommand, execOptions);
|
|
18
|
+
return {
|
|
19
|
+
success: true,
|
|
20
|
+
stdout: stdout.toString().trim(),
|
|
21
|
+
stderr: stderr.toString().trim(),
|
|
22
|
+
exitCode: 0
|
|
23
|
+
};
|
|
24
|
+
} catch (error) {
|
|
25
|
+
return {
|
|
26
|
+
success: false,
|
|
27
|
+
stdout: error.stdout?.toString().trim() || "",
|
|
28
|
+
stderr: error.stderr?.toString().trim() || "",
|
|
29
|
+
exitCode: error.code || 1,
|
|
30
|
+
error: error.message
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function executeCommandStream(command, args = [], options = {}) {
|
|
35
|
+
return new Promise((resolve) => {
|
|
36
|
+
const spawnOptions = {
|
|
37
|
+
cwd: options.cwd,
|
|
38
|
+
env: { ...process.env, ...options.env },
|
|
39
|
+
shell: options.shell !== false
|
|
40
|
+
};
|
|
41
|
+
const child = spawn(command, args, spawnOptions);
|
|
42
|
+
let stdout = "";
|
|
43
|
+
let stderr = "";
|
|
44
|
+
child.stdout?.on("data", (data) => {
|
|
45
|
+
const text = data.toString();
|
|
46
|
+
stdout += text;
|
|
47
|
+
if (options.onStdout) {
|
|
48
|
+
options.onStdout(text);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
child.stderr?.on("data", (data) => {
|
|
52
|
+
const text = data.toString();
|
|
53
|
+
stderr += text;
|
|
54
|
+
if (options.onStderr) {
|
|
55
|
+
options.onStderr(text);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
child.on("close", (code) => {
|
|
59
|
+
resolve({
|
|
60
|
+
success: code === 0,
|
|
61
|
+
stdout: stdout.trim(),
|
|
62
|
+
stderr: stderr.trim(),
|
|
63
|
+
exitCode: code || 0,
|
|
64
|
+
error: code !== 0 ? `Command exited with code ${code}` : void 0
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
child.on("error", (error) => {
|
|
68
|
+
resolve({
|
|
69
|
+
success: false,
|
|
70
|
+
stdout: stdout.trim(),
|
|
71
|
+
stderr: stderr.trim(),
|
|
72
|
+
exitCode: 1,
|
|
73
|
+
error: error.message
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
if (options.timeout) {
|
|
77
|
+
setTimeout(() => {
|
|
78
|
+
child.kill();
|
|
79
|
+
resolve({
|
|
80
|
+
success: false,
|
|
81
|
+
stdout: stdout.trim(),
|
|
82
|
+
stderr: stderr.trim(),
|
|
83
|
+
exitCode: 1,
|
|
84
|
+
error: `Command timed out after ${options.timeout}ms`
|
|
85
|
+
});
|
|
86
|
+
}, options.timeout);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function buildCommand(command, args) {
|
|
91
|
+
const escapedArgs = args.map(escapeArgument);
|
|
92
|
+
return [command, ...escapedArgs].join(" ");
|
|
93
|
+
}
|
|
94
|
+
function escapeArgument(arg) {
|
|
95
|
+
if (/[\s"'`$&|;<>(){}[\]\\]/.test(arg)) {
|
|
96
|
+
const escaped = arg.replace(/"/g, '\\"');
|
|
97
|
+
return `"${escaped}"`;
|
|
98
|
+
}
|
|
99
|
+
return arg;
|
|
100
|
+
}
|
|
101
|
+
async function commandExists(command) {
|
|
102
|
+
const isWindows = process.platform === "win32";
|
|
103
|
+
const checkCommand = isWindows ? "where" : "which";
|
|
104
|
+
try {
|
|
105
|
+
const result = await executeCommand(checkCommand, [command]);
|
|
106
|
+
return result.success;
|
|
107
|
+
} catch {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async function getCommandPath(command) {
|
|
112
|
+
const isWindows = process.platform === "win32";
|
|
113
|
+
const checkCommand = isWindows ? "where" : "which";
|
|
114
|
+
try {
|
|
115
|
+
const result = await executeCommand(checkCommand, [command]);
|
|
116
|
+
if (result.success) {
|
|
117
|
+
return result.stdout.split("\n")[0].trim();
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
} catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function parseVersion(output) {
|
|
125
|
+
const patterns = [
|
|
126
|
+
/version\s+v?(\d+\.\d+\.\d+)/i,
|
|
127
|
+
/v?(\d+\.\d+\.\d+)/,
|
|
128
|
+
/(\d+\.\d+\.\d+)/
|
|
129
|
+
];
|
|
130
|
+
for (const pattern of patterns) {
|
|
131
|
+
const match = output.match(pattern);
|
|
132
|
+
if (match) {
|
|
133
|
+
return match[1];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
async function getCommandVersion(command, versionFlag = "--version") {
|
|
139
|
+
try {
|
|
140
|
+
const result = await executeCommand(command, [versionFlag]);
|
|
141
|
+
if (result.success) {
|
|
142
|
+
return parseVersion(result.stdout || result.stderr);
|
|
143
|
+
}
|
|
144
|
+
return null;
|
|
145
|
+
} catch {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async function executeCommandSequence(commands) {
|
|
150
|
+
const results = [];
|
|
151
|
+
for (const cmd of commands) {
|
|
152
|
+
const result = await executeCommand(
|
|
153
|
+
cmd.command,
|
|
154
|
+
cmd.args || [],
|
|
155
|
+
cmd.options || {}
|
|
156
|
+
);
|
|
157
|
+
results.push(result);
|
|
158
|
+
if (!result.success) {
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return results;
|
|
163
|
+
}
|
|
164
|
+
async function executeCommandParallel(commands) {
|
|
165
|
+
const promises = commands.map(
|
|
166
|
+
(cmd) => executeCommand(cmd.command, cmd.args || [], cmd.options || {})
|
|
167
|
+
);
|
|
168
|
+
return Promise.all(promises);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export { escapeArgument as a, buildCommand as b, commandExists as c, executeCommandParallel as d, executeCommand as e, executeCommandSequence as f, executeCommandStream as g, getCommandPath as h, getCommandVersion as i, parseVersion as p };
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import a from '../chunks/index5.mjs';
|
|
2
2
|
import { i as inquirer } from '../chunks/index6.mjs';
|
|
3
|
-
import {
|
|
3
|
+
import { a as getMcpService, d as dynamicMcpRegistry, M as MCP_SERVICE_CONFIGS } from './ccjk.DKXs7Fbm.mjs';
|
|
4
4
|
import { SETTINGS_FILE, CLAUDE_DIR, ClAUDE_CONFIG_FILE, CODEX_CONFIG_FILE } from '../chunks/constants.mjs';
|
|
5
5
|
import { exists, ensureDir } from '../chunks/fs-operations.mjs';
|
|
6
6
|
import { readJsonConfig, writeJsonConfig } from '../chunks/json-config.mjs';
|
|
7
|
-
import {
|
|
7
|
+
import { g as deepMerge, r as readMcpConfig, a as buildMcpServerConfig, w as writeMcpConfig } from '../chunks/claude-config.mjs';
|
|
8
8
|
import { ensureI18nInitialized, i18n } from '../chunks/index2.mjs';
|
|
9
|
-
import {
|
|
9
|
+
import { r as readCodexConfig, g as applyCodexPlatformCommand, w as writeCodexConfig } from '../chunks/codex.mjs';
|
|
10
|
+
import { i as isWindows, m as getSystemRoot } from '../chunks/platform.mjs';
|
|
10
11
|
|
|
11
12
|
function readClaudeConfig(configPath = SETTINGS_FILE) {
|
|
12
13
|
try {
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import process__default from 'node:process';
|
|
3
|
+
import { ensureI18nInitialized, i18n } from '../chunks/index2.mjs';
|
|
4
|
+
|
|
5
|
+
const MCP_SERVICE_CONFIGS = [
|
|
6
|
+
// Documentation and research services
|
|
7
|
+
{
|
|
8
|
+
id: "context7",
|
|
9
|
+
requiresApiKey: false,
|
|
10
|
+
defaultSelected: true,
|
|
11
|
+
config: {
|
|
12
|
+
type: "stdio",
|
|
13
|
+
command: "npx",
|
|
14
|
+
args: ["-y", "@upstash/context7-mcp@latest"],
|
|
15
|
+
env: {}
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: "open-websearch",
|
|
20
|
+
requiresApiKey: false,
|
|
21
|
+
config: {
|
|
22
|
+
type: "stdio",
|
|
23
|
+
command: "npx",
|
|
24
|
+
args: ["-y", "open-websearch@latest"],
|
|
25
|
+
env: {
|
|
26
|
+
MODE: "stdio",
|
|
27
|
+
DEFAULT_SEARCH_ENGINE: "duckduckgo",
|
|
28
|
+
ALLOWED_SEARCH_ENGINES: "duckduckgo,bing,brave"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: "mcp-deepwiki",
|
|
34
|
+
requiresApiKey: false,
|
|
35
|
+
config: {
|
|
36
|
+
type: "stdio",
|
|
37
|
+
command: "npx",
|
|
38
|
+
args: ["-y", "mcp-deepwiki@latest"],
|
|
39
|
+
env: {}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: "spec-workflow",
|
|
44
|
+
requiresApiKey: false,
|
|
45
|
+
config: {
|
|
46
|
+
type: "stdio",
|
|
47
|
+
command: "npx",
|
|
48
|
+
args: ["-y", "@pimzino/spec-workflow-mcp@latest"],
|
|
49
|
+
env: {}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: "serena",
|
|
54
|
+
requiresApiKey: false,
|
|
55
|
+
config: {
|
|
56
|
+
type: "stdio",
|
|
57
|
+
command: "uvx",
|
|
58
|
+
args: ["--from", "git+https://github.com/oraios/serena", "serena", "start-mcp-server", "--context", "ide-assistant", "--enable-web-dashboard", "false"],
|
|
59
|
+
env: {}
|
|
60
|
+
},
|
|
61
|
+
platformRequirements: {
|
|
62
|
+
requiredCommands: ["uvx"]
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: "Playwright",
|
|
67
|
+
requiresApiKey: false,
|
|
68
|
+
config: {
|
|
69
|
+
type: "stdio",
|
|
70
|
+
command: "npx",
|
|
71
|
+
args: ["-y", "@playwright/mcp@latest", "--browser", "chromium"],
|
|
72
|
+
env: {}
|
|
73
|
+
},
|
|
74
|
+
platformRequirements: {
|
|
75
|
+
platforms: ["macos", "windows"],
|
|
76
|
+
requiresGui: true
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: "intent-engine",
|
|
81
|
+
requiresApiKey: false,
|
|
82
|
+
config: {
|
|
83
|
+
type: "stdio",
|
|
84
|
+
command: "npx",
|
|
85
|
+
args: ["-y", "@origintask/intent-engine@latest", "mcp"],
|
|
86
|
+
env: {}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: "sqlite",
|
|
91
|
+
requiresApiKey: false,
|
|
92
|
+
config: {
|
|
93
|
+
type: "stdio",
|
|
94
|
+
command: "npx",
|
|
95
|
+
args: ["-y", "@anthropic-ai/mcp-server-sqlite@latest"],
|
|
96
|
+
env: {}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
];
|
|
100
|
+
async function getMcpServices() {
|
|
101
|
+
ensureI18nInitialized();
|
|
102
|
+
const mcpServiceList = [
|
|
103
|
+
{
|
|
104
|
+
id: "context7",
|
|
105
|
+
name: i18n.t("mcp:services.context7.name"),
|
|
106
|
+
description: i18n.t("mcp:services.context7.description")
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
id: "open-websearch",
|
|
110
|
+
name: i18n.t("mcp:services.open-websearch.name"),
|
|
111
|
+
description: i18n.t("mcp:services.open-websearch.description")
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: "mcp-deepwiki",
|
|
115
|
+
name: i18n.t("mcp:services.mcp-deepwiki.name"),
|
|
116
|
+
description: i18n.t("mcp:services.mcp-deepwiki.description")
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: "spec-workflow",
|
|
120
|
+
name: i18n.t("mcp:services.spec-workflow.name"),
|
|
121
|
+
description: i18n.t("mcp:services.spec-workflow.description")
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
id: "serena",
|
|
125
|
+
name: i18n.t("mcp:services.serena.name"),
|
|
126
|
+
description: i18n.t("mcp:services.serena.description")
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: "Playwright",
|
|
130
|
+
name: i18n.t("mcp:services.Playwright.name"),
|
|
131
|
+
description: i18n.t("mcp:services.Playwright.description")
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
id: "intent-engine",
|
|
135
|
+
name: i18n.t("mcp:services.intent-engine.name"),
|
|
136
|
+
description: i18n.t("mcp:services.intent-engine.description")
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
id: "sqlite",
|
|
140
|
+
name: i18n.t("mcp:services.sqlite.name"),
|
|
141
|
+
description: i18n.t("mcp:services.sqlite.description")
|
|
142
|
+
}
|
|
143
|
+
];
|
|
144
|
+
return MCP_SERVICE_CONFIGS.map((config) => {
|
|
145
|
+
const serviceInfo = mcpServiceList.find((s) => s.id === config.id);
|
|
146
|
+
const service = {
|
|
147
|
+
id: config.id,
|
|
148
|
+
name: serviceInfo?.name || config.id,
|
|
149
|
+
description: serviceInfo?.description || "",
|
|
150
|
+
requiresApiKey: config.requiresApiKey,
|
|
151
|
+
config: config.config
|
|
152
|
+
};
|
|
153
|
+
if (config.apiKeyEnvVar) {
|
|
154
|
+
service.apiKeyEnvVar = config.apiKeyEnvVar;
|
|
155
|
+
}
|
|
156
|
+
return service;
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
async function getMcpService(id) {
|
|
160
|
+
const services = await getMcpServices();
|
|
161
|
+
return services.find((service) => service.id === id);
|
|
162
|
+
}
|
|
163
|
+
function detectPlatform() {
|
|
164
|
+
const platform = process__default.platform;
|
|
165
|
+
const env = process__default.env;
|
|
166
|
+
const isWsl = !!(env.WSL_DISTRO_NAME || env.WSLENV || env.PATH && env.PATH.includes("/mnt/c/"));
|
|
167
|
+
const isTermux = !!(env.TERMUX_VERSION || env.PREFIX?.includes("com.termux"));
|
|
168
|
+
const isHeadless = !!(env.SSH_CLIENT || env.SSH_TTY || env.SSH_CONNECTION || !env.DISPLAY && platform === "linux");
|
|
169
|
+
const hasGui = (() => {
|
|
170
|
+
if (platform === "darwin")
|
|
171
|
+
return true;
|
|
172
|
+
if (platform === "win32")
|
|
173
|
+
return !isHeadless;
|
|
174
|
+
if (isWsl || isTermux)
|
|
175
|
+
return false;
|
|
176
|
+
if (platform === "linux")
|
|
177
|
+
return !!env.DISPLAY || !!env.WAYLAND_DISPLAY;
|
|
178
|
+
return false;
|
|
179
|
+
})();
|
|
180
|
+
let detectedPlatform;
|
|
181
|
+
if (platform === "darwin") {
|
|
182
|
+
detectedPlatform = "macos";
|
|
183
|
+
} else if (platform === "win32") {
|
|
184
|
+
detectedPlatform = "windows";
|
|
185
|
+
} else if (isWsl) {
|
|
186
|
+
detectedPlatform = "wsl";
|
|
187
|
+
} else if (isTermux) {
|
|
188
|
+
detectedPlatform = "termux";
|
|
189
|
+
} else if (platform === "linux") {
|
|
190
|
+
detectedPlatform = "linux";
|
|
191
|
+
} else {
|
|
192
|
+
detectedPlatform = "unknown";
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
platform: detectedPlatform,
|
|
196
|
+
hasGui,
|
|
197
|
+
isHeadless
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function isCommandAvailable(command) {
|
|
201
|
+
try {
|
|
202
|
+
execSync(`which ${command}`, { stdio: "ignore" });
|
|
203
|
+
return true;
|
|
204
|
+
} catch {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
function isMcpServiceCompatible(serviceId) {
|
|
209
|
+
const config = MCP_SERVICE_CONFIGS.find((c) => c.id === serviceId);
|
|
210
|
+
if (!config) {
|
|
211
|
+
return { compatible: false, reason: "Service not found" };
|
|
212
|
+
}
|
|
213
|
+
const requirements = config.platformRequirements;
|
|
214
|
+
if (!requirements) {
|
|
215
|
+
return { compatible: true };
|
|
216
|
+
}
|
|
217
|
+
const { platform, hasGui } = detectPlatform();
|
|
218
|
+
if (requirements.platforms && requirements.platforms.length > 0) {
|
|
219
|
+
if (platform !== "unknown" && !requirements.platforms.includes(platform)) {
|
|
220
|
+
return {
|
|
221
|
+
compatible: false,
|
|
222
|
+
reason: `Not supported on ${platform}. Requires: ${requirements.platforms.join(", ")}`
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (requirements.requiresGui && !hasGui) {
|
|
227
|
+
return {
|
|
228
|
+
compatible: false,
|
|
229
|
+
reason: "Requires GUI environment (X11/Wayland/Desktop)"
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
if (requirements.requiredCommands) {
|
|
233
|
+
for (const cmd of requirements.requiredCommands) {
|
|
234
|
+
if (!isCommandAvailable(cmd)) {
|
|
235
|
+
return {
|
|
236
|
+
compatible: false,
|
|
237
|
+
reason: `Required command not found: ${cmd}`
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return { compatible: true };
|
|
243
|
+
}
|
|
244
|
+
async function getMcpServicesWithCompatibility() {
|
|
245
|
+
const allServices = await getMcpServices();
|
|
246
|
+
return allServices.map((service) => {
|
|
247
|
+
const { compatible, reason } = isMcpServiceCompatible(service.id);
|
|
248
|
+
return {
|
|
249
|
+
...service,
|
|
250
|
+
compatible,
|
|
251
|
+
incompatibleReason: reason
|
|
252
|
+
};
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
const DEFAULT_MCP_TOOL_SEARCH_CONFIG = {
|
|
256
|
+
mcpAutoEnableThreshold: 10,
|
|
257
|
+
excludedServices: ["mcp-search", "context7"]
|
|
258
|
+
};
|
|
259
|
+
function getMcpToolSearchConfig() {
|
|
260
|
+
const env = process__default.env;
|
|
261
|
+
return {
|
|
262
|
+
mcpAutoEnableThreshold: env.MCP_AUTO_THRESHOLD || DEFAULT_MCP_TOOL_SEARCH_CONFIG.mcpAutoEnableThreshold,
|
|
263
|
+
dynamicServiceDiscovery: env.MCP_DYNAMIC_DISCOVERY !== "false",
|
|
264
|
+
listChangedNotifications: env.MCP_LIST_CHANGED !== "false",
|
|
265
|
+
excludedServices: env.MCP_EXCLUDED_SERVICES?.split(",").map((s) => s.trim()).filter(Boolean) || DEFAULT_MCP_TOOL_SEARCH_CONFIG.excludedServices
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
class DynamicMcpServiceRegistry {
|
|
269
|
+
_services = /* @__PURE__ */ new Map();
|
|
270
|
+
_listeners = /* @__PURE__ */ new Set();
|
|
271
|
+
_enabled = false;
|
|
272
|
+
/**
|
|
273
|
+
* Enable dynamic service discovery
|
|
274
|
+
*/
|
|
275
|
+
enable() {
|
|
276
|
+
this._enabled = true;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Disable dynamic service discovery
|
|
280
|
+
*/
|
|
281
|
+
disable() {
|
|
282
|
+
this._enabled = false;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Check if dynamic discovery is enabled
|
|
286
|
+
*/
|
|
287
|
+
isEnabled() {
|
|
288
|
+
return this._enabled;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Add a service dynamically
|
|
292
|
+
*/
|
|
293
|
+
addService(serviceId, config) {
|
|
294
|
+
if (!this._enabled) {
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
const isUpdate = this._services.has(serviceId);
|
|
298
|
+
this._services.set(serviceId, config);
|
|
299
|
+
this._notify({
|
|
300
|
+
type: isUpdate ? "updated" : "added",
|
|
301
|
+
serviceId,
|
|
302
|
+
timestamp: Date.now(),
|
|
303
|
+
config
|
|
304
|
+
});
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Remove a service dynamically
|
|
309
|
+
*/
|
|
310
|
+
removeService(serviceId) {
|
|
311
|
+
if (!this._enabled || !this._services.has(serviceId)) {
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
const config = this._services.get(serviceId);
|
|
315
|
+
this._services.delete(serviceId);
|
|
316
|
+
this._notify({
|
|
317
|
+
type: "removed",
|
|
318
|
+
serviceId,
|
|
319
|
+
timestamp: Date.now(),
|
|
320
|
+
config
|
|
321
|
+
});
|
|
322
|
+
return true;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Get a service configuration
|
|
326
|
+
*/
|
|
327
|
+
getService(serviceId) {
|
|
328
|
+
return this._services.get(serviceId);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* List all dynamically registered services
|
|
332
|
+
*/
|
|
333
|
+
listServices() {
|
|
334
|
+
return new Map(this._services);
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Subscribe to list change notifications
|
|
338
|
+
*/
|
|
339
|
+
subscribe(listener) {
|
|
340
|
+
this._listeners.add(listener);
|
|
341
|
+
return () => this._listeners.delete(listener);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Notify all listeners of a change
|
|
345
|
+
*/
|
|
346
|
+
_notify(notification) {
|
|
347
|
+
const toolSearchConfig = getMcpToolSearchConfig();
|
|
348
|
+
if (toolSearchConfig.listChangedNotifications) {
|
|
349
|
+
for (const listener of Array.from(this._listeners)) {
|
|
350
|
+
try {
|
|
351
|
+
listener(notification);
|
|
352
|
+
} catch (error) {
|
|
353
|
+
console.error("Error notifying MCP list change listener:", error);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
const dynamicMcpRegistry = new DynamicMcpServiceRegistry();
|
|
360
|
+
|
|
361
|
+
export { MCP_SERVICE_CONFIGS as M, getMcpService as a, getMcpServicesWithCompatibility as b, dynamicMcpRegistry as d, getMcpServices as g, isMcpServiceCompatible as i };
|
|
@@ -490,4 +490,4 @@ async function updatePromptOnly(aiOutputLang) {
|
|
|
490
490
|
${a.green(i18n.t("common:complete"))}`);
|
|
491
491
|
}
|
|
492
492
|
|
|
493
|
-
export {
|
|
493
|
+
export { configureApiCompletely as a, configureOutputStyle as c, formatApiKeyDisplay as f, modifyApiConfigPartially as m, updatePromptOnly as u, validateApiKey as v };
|