xiaozhi-client 0.0.1-beta.0 → 0.0.1-beta.2
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/cli.cjs +12 -4
- package/dist/cli.cjs.map +1 -1
- package/dist/configManager.cjs +20 -11
- package/dist/configManager.cjs.map +1 -1
- package/dist/configManager.d.ts +4 -1
- package/dist/mcpPipe.cjs +8 -0
- package/dist/mcpPipe.cjs.map +1 -1
- package/dist/xiaozhi.config.json +13 -0
- package/package.json +1 -1
- package/dist/config.json +0 -13
- /package/dist/{config.default.json → xiaozhi.config.default.json} +0 -0
package/dist/cli.cjs
CHANGED
|
@@ -162,7 +162,11 @@ async function startService(daemon = false) {
|
|
|
162
162
|
cwd,
|
|
163
163
|
detached: true,
|
|
164
164
|
stdio: ["ignore", "pipe", "pipe"],
|
|
165
|
-
env: {
|
|
165
|
+
env: {
|
|
166
|
+
...process.env,
|
|
167
|
+
XIAOZHI_CONFIG_DIR: process.cwd()
|
|
168
|
+
// 传递用户的当前工作目录
|
|
169
|
+
}
|
|
166
170
|
});
|
|
167
171
|
savePidInfo(child.pid, "daemon");
|
|
168
172
|
const logStream = import_fs.default.createWriteStream(LOG_FILE, { flags: "a" });
|
|
@@ -177,7 +181,11 @@ async function startService(daemon = false) {
|
|
|
177
181
|
const child = (0, import_child_process.spawn)(command, args, {
|
|
178
182
|
cwd,
|
|
179
183
|
stdio: "inherit",
|
|
180
|
-
env: {
|
|
184
|
+
env: {
|
|
185
|
+
...process.env,
|
|
186
|
+
XIAOZHI_CONFIG_DIR: process.cwd()
|
|
187
|
+
// 传递用户的当前工作目录
|
|
188
|
+
}
|
|
181
189
|
});
|
|
182
190
|
savePidInfo(child.pid, "foreground");
|
|
183
191
|
child.on("exit", (code, signal) => {
|
|
@@ -323,12 +331,12 @@ async function initConfig() {
|
|
|
323
331
|
try {
|
|
324
332
|
if (import_configManager.configManager.configExists()) {
|
|
325
333
|
spinner.warn("\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728");
|
|
326
|
-
console.log(import_chalk.default.yellow("\u5982\u9700\u91CD\u65B0\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u5220\u9664\u73B0\u6709\u7684 config.json \u6587\u4EF6"));
|
|
334
|
+
console.log(import_chalk.default.yellow("\u5982\u9700\u91CD\u65B0\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u5220\u9664\u73B0\u6709\u7684 xiaozhi.config.json \u6587\u4EF6"));
|
|
327
335
|
return;
|
|
328
336
|
}
|
|
329
337
|
import_configManager.configManager.initConfig();
|
|
330
338
|
spinner.succeed("\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u6210\u529F");
|
|
331
|
-
console.log(import_chalk.default.green("\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u521B\u5EFA: config.json"));
|
|
339
|
+
console.log(import_chalk.default.green("\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u521B\u5EFA: xiaozhi.config.json"));
|
|
332
340
|
console.log(import_chalk.default.yellow("\u{1F4DD} \u8BF7\u7F16\u8F91\u914D\u7F6E\u6587\u4EF6\u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9:"));
|
|
333
341
|
console.log(import_chalk.default.gray(` \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84: ${import_configManager.configManager.getConfigPath()}`));
|
|
334
342
|
console.log(import_chalk.default.yellow("\u{1F4A1} \u6216\u8005\u4F7F\u7528\u547D\u4EE4\u8BBE\u7F6E:"));
|
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { spawn, ChildProcess } from 'child_process';\nimport fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { configManager } from './configManager.js';\n\nconst program = new Command();\nconst VERSION = '0.0.1';\nconst SERVICE_NAME = 'xiaozhi-mcp-service';\n\n// PID 文件路径\nconst PID_FILE = path.join(os.tmpdir(), `${SERVICE_NAME}.pid`);\nconst LOG_FILE = path.join(os.tmpdir(), `${SERVICE_NAME}.log`);\n\ninterface ServiceStatus {\n running: boolean;\n pid?: number;\n uptime?: string;\n mode?: 'foreground' | 'daemon';\n}\n\n/**\n * 获取服务状态\n */\nfunction getServiceStatus(): ServiceStatus {\n try {\n if (!fs.existsSync(PID_FILE)) {\n return { running: false };\n }\n\n const pidContent = fs.readFileSync(PID_FILE, 'utf8').trim();\n const [pidStr, startTime, mode] = pidContent.split('|');\n const pid = parseInt(pidStr);\n\n if (isNaN(pid)) {\n // PID 文件损坏,删除它\n fs.unlinkSync(PID_FILE);\n return { running: false };\n }\n\n // 检查进程是否还在运行\n try {\n process.kill(pid, 0); // 发送信号 0 来检查进程是否存在\n\n // 计算运行时间\n const start = parseInt(startTime);\n const uptime = formatUptime(Date.now() - start);\n\n return {\n running: true,\n pid,\n uptime,\n mode: (mode as 'foreground' | 'daemon') || 'foreground'\n };\n } catch (error) {\n // 进程不存在,删除 PID 文件\n fs.unlinkSync(PID_FILE);\n return { running: false };\n }\n } catch (error) {\n return { running: false };\n }\n}\n\n/**\n * 格式化运行时间\n */\nfunction formatUptime(ms: number): string {\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) {\n return `${days}天 ${hours % 24}小时 ${minutes % 60}分钟`;\n } else if (hours > 0) {\n return `${hours}小时 ${minutes % 60}分钟`;\n } else if (minutes > 0) {\n return `${minutes}分钟 ${seconds % 60}秒`;\n } else {\n return `${seconds}秒`;\n }\n}\n\n/**\n * 保存 PID 信息\n */\nfunction savePidInfo(pid: number, mode: 'foreground' | 'daemon') {\n const pidInfo = `${pid}|${Date.now()}|${mode}`;\n fs.writeFileSync(PID_FILE, pidInfo);\n}\n\n/**\n * 清理 PID 文件\n */\nfunction cleanupPidFile() {\n try {\n if (fs.existsSync(PID_FILE)) {\n fs.unlinkSync(PID_FILE);\n }\n } catch (error) {\n // 忽略清理错误\n }\n}\n\n/**\n * 检查配置文件和环境\n */\nfunction checkEnvironment(): boolean {\n // 首先检查配置文件是否存在\n if (!configManager.configExists()) {\n console.error(chalk.red('❌ 错误: 配置文件不存在'));\n console.log(chalk.yellow('💡 提示: 请运行 \"xiaozhi init\" 初始化配置'));\n return false;\n }\n\n try {\n // 检查配置是否有效\n const endpoint = configManager.getMcpEndpoint();\n if (!endpoint || endpoint.includes('<请填写')) {\n console.error(chalk.red('❌ 错误: MCP 端点未配置'));\n console.log(chalk.yellow('💡 提示: 请运行 \"xiaozhi config mcpEndpoint <your-endpoint-url>\" 设置端点'));\n return false;\n }\n return true;\n } catch (error) {\n console.error(chalk.red(`❌ 错误: 配置文件无效 - ${error instanceof Error ? error.message : String(error)}`));\n console.log(chalk.yellow('💡 提示: 请运行 \"xiaozhi init\" 重新初始化配置'));\n return false;\n }\n}\n\n/**\n * 获取服务启动命令和参数\n */\nfunction getServiceCommand(): { command: string; args: string[]; cwd: string } {\n // 获取当前脚本所在目录\n const scriptDir = __dirname;\n\n // 检查是否在开发环境(js-demo/dist)还是全局安装环境\n let distDir: string;\n if (scriptDir.includes('js-demo/dist')) {\n // 开发环境\n distDir = scriptDir;\n } else {\n // 全局安装环境,需要找到实际的项目目录\n // 通常全局安装后,脚本在 node_modules/.bin 或类似位置\n // 我们需要找到实际的 dist 目录\n const possiblePaths = [\n path.join(scriptDir, '..', 'js-demo', 'dist'),\n path.join(scriptDir, '..', '..', 'js-demo', 'dist'),\n path.join(scriptDir, '..', '..', '..', 'js-demo', 'dist'),\n path.join(process.cwd(), 'js-demo', 'dist'),\n path.join(process.cwd(), 'dist')\n ];\n\n distDir = possiblePaths.find(p =>\n fs.existsSync(path.join(p, 'mcpPipe.cjs')) &&\n fs.existsSync(path.join(p, 'mcpServerProxy.cjs'))\n ) || scriptDir;\n }\n\n return {\n command: 'node',\n args: ['mcpPipe.cjs', 'mcpServerProxy.cjs'],\n cwd: distDir\n };\n}\n\n/**\n * 启动服务\n */\nasync function startService(daemon: boolean = false): Promise<void> {\n const spinner = ora('检查服务状态...').start();\n\n try {\n // 检查服务是否已经在运行\n const status = getServiceStatus();\n if (status.running) {\n spinner.fail(`服务已经在运行 (PID: ${status.pid})`);\n return;\n }\n\n // 检查环境变量\n spinner.text = '检查环境配置...';\n if (!checkEnvironment()) {\n spinner.fail('环境配置检查失败');\n return;\n }\n\n // 获取启动命令\n const { command, args, cwd } = getServiceCommand();\n\n spinner.text = `启动服务 (${daemon ? '后台模式' : '前台模式'})...`;\n\n if (daemon) {\n // 后台模式\n const child = spawn(command, args, {\n cwd,\n detached: true,\n stdio: ['ignore', 'pipe', 'pipe'],\n env: { ...process.env }\n });\n\n // 保存 PID 信息\n savePidInfo(child.pid!, 'daemon');\n\n // 设置日志输出\n const logStream = fs.createWriteStream(LOG_FILE, { flags: 'a' });\n child.stdout?.pipe(logStream);\n child.stderr?.pipe(logStream);\n\n // 分离进程\n child.unref();\n\n spinner.succeed(`服务已在后台启动 (PID: ${child.pid})`);\n console.log(chalk.gray(`日志文件: ${LOG_FILE}`));\n console.log(chalk.gray(`使用 'xiaozhi attach' 可以查看实时日志`));\n } else {\n // 前台模式\n spinner.succeed('服务启动中...');\n\n const child = spawn(command, args, {\n cwd,\n stdio: 'inherit',\n env: { ...process.env }\n });\n\n // 保存 PID 信息\n savePidInfo(child.pid!, 'foreground');\n\n // 处理进程退出\n child.on('exit', (code, signal) => {\n cleanupPidFile();\n if (code !== 0) {\n console.log(chalk.red(`\\n服务异常退出 (代码: ${code}, 信号: ${signal})`));\n } else {\n console.log(chalk.green('\\n服务已停止'));\n }\n });\n\n // 处理中断信号\n process.on('SIGINT', () => {\n console.log(chalk.yellow('\\n正在停止服务...'));\n child.kill('SIGTERM');\n });\n\n process.on('SIGTERM', () => {\n child.kill('SIGTERM');\n });\n }\n } catch (error) {\n spinner.fail(`启动服务失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 停止服务\n */\nasync function stopService(): Promise<void> {\n const spinner = ora('检查服务状态...').start();\n\n try {\n const status = getServiceStatus();\n\n if (!status.running) {\n spinner.warn('服务未在运行');\n return;\n }\n\n spinner.text = `停止服务 (PID: ${status.pid})...`;\n\n try {\n // 尝试优雅停止\n process.kill(status.pid!, 'SIGTERM');\n\n // 等待进程停止\n let attempts = 0;\n const maxAttempts = 30; // 3秒超时\n\n while (attempts < maxAttempts) {\n await new Promise(resolve => setTimeout(resolve, 100));\n\n try {\n process.kill(status.pid!, 0);\n attempts++;\n } catch {\n // 进程已停止\n break;\n }\n }\n\n // 检查是否还在运行\n try {\n process.kill(status.pid!, 0);\n // 如果还在运行,强制停止\n spinner.text = '强制停止服务...';\n process.kill(status.pid!, 'SIGKILL');\n await new Promise(resolve => setTimeout(resolve, 500));\n } catch {\n // 进程已停止\n }\n\n cleanupPidFile();\n spinner.succeed('服务已停止');\n\n } catch (error) {\n cleanupPidFile();\n spinner.fail(`停止服务失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n } catch (error) {\n spinner.fail(`停止服务失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 检查服务状态\n */\nasync function checkStatus(): Promise<void> {\n const spinner = ora('检查服务状态...').start();\n\n try {\n const status = getServiceStatus();\n\n if (status.running) {\n spinner.succeed('服务状态');\n console.log(chalk.green('✅ 服务正在运行'));\n console.log(chalk.gray(` PID: ${status.pid}`));\n console.log(chalk.gray(` 运行时间: ${status.uptime}`));\n console.log(chalk.gray(` 运行模式: ${status.mode === 'daemon' ? '后台模式' : '前台模式'}`));\n\n if (status.mode === 'daemon') {\n console.log(chalk.gray(` 日志文件: ${LOG_FILE}`));\n }\n } else {\n spinner.succeed('服务状态');\n console.log(chalk.red('❌ 服务未运行'));\n }\n } catch (error) {\n spinner.fail(`检查状态失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 附加到后台服务\n */\nasync function attachService(): Promise<void> {\n const spinner = ora('检查服务状态...').start();\n\n try {\n const status = getServiceStatus();\n\n if (!status.running) {\n spinner.fail('服务未在运行');\n return;\n }\n\n if (status.mode !== 'daemon') {\n spinner.fail('服务不是在后台模式运行');\n return;\n }\n\n spinner.succeed('连接到后台服务...');\n console.log(chalk.green(`已连接到服务 (PID: ${status.pid})`));\n console.log(chalk.gray('按 Ctrl+C 可以断开连接(不会停止服务)'));\n console.log(chalk.gray('=' .repeat(50)));\n\n // 显示日志文件内容\n if (fs.existsSync(LOG_FILE)) {\n // 显示最后100行日志\n const { spawn } = await import('child_process');\n const tail = spawn('tail', ['-f', LOG_FILE], { stdio: 'inherit' });\n\n // 处理中断信号\n process.on('SIGINT', () => {\n console.log(chalk.yellow('\\n断开连接,服务继续在后台运行'));\n tail.kill();\n process.exit(0);\n });\n\n tail.on('exit', () => {\n process.exit(0);\n });\n } else {\n console.log(chalk.yellow('日志文件不存在'));\n }\n\n } catch (error) {\n spinner.fail(`连接失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 重启服务\n */\nasync function restartService(daemon: boolean = false): Promise<void> {\n console.log(chalk.blue('🔄 重启服务...'));\n\n // 先停止服务\n await stopService();\n\n // 等待一下确保完全停止\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n // 重新启动服务\n await startService(daemon);\n}\n\n/**\n * 显示版本信息\n */\nfunction showVersion(): void {\n console.log(chalk.blue(`xiaozhi v${VERSION}`));\n}\n\n/**\n * 显示详细信息\n */\nfunction showDetailedInfo(): void {\n console.log(chalk.blue(`xiaozhi v${VERSION}`));\n console.log(chalk.gray('MCP Calculator Service CLI Tool'));\n console.log(chalk.gray('Built with Node.js and TypeScript'));\n console.log(chalk.gray(`Node.js: ${process.version}`));\n console.log(chalk.gray(`Platform: ${process.platform} ${process.arch}`));\n}\n\n/**\n * 初始化配置\n */\nasync function initConfig(): Promise<void> {\n const spinner = ora('初始化配置...').start();\n\n try {\n if (configManager.configExists()) {\n spinner.warn('配置文件已存在');\n console.log(chalk.yellow('如需重新初始化,请先删除现有的 config.json 文件'));\n return;\n }\n\n configManager.initConfig();\n spinner.succeed('配置文件初始化成功');\n\n console.log(chalk.green('✅ 配置文件已创建: config.json'));\n console.log(chalk.yellow('📝 请编辑配置文件设置你的 MCP 端点:'));\n console.log(chalk.gray(` 配置文件路径: ${configManager.getConfigPath()}`));\n console.log(chalk.yellow('💡 或者使用命令设置:'));\n console.log(chalk.gray(' xiaozhi config mcpEndpoint <your-endpoint-url>'));\n } catch (error) {\n spinner.fail(`初始化配置失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 配置管理命令\n */\nasync function configCommand(key: string, value?: string): Promise<void> {\n const spinner = ora('更新配置...').start();\n\n try {\n if (!configManager.configExists()) {\n spinner.fail('配置文件不存在');\n console.log(chalk.yellow('💡 提示: 请先运行 \"xiaozhi init\" 初始化配置'));\n return;\n }\n\n if (!value) {\n // 显示配置值\n spinner.text = '读取配置...';\n const config = configManager.getConfig();\n\n switch (key) {\n case 'mcpEndpoint':\n spinner.succeed('配置信息');\n console.log(chalk.green(`MCP 端点: ${config.mcpEndpoint}`));\n break;\n case 'mcpServers':\n spinner.succeed('配置信息');\n console.log(chalk.green('MCP 服务:'));\n for (const [name, serverConfig] of Object.entries(config.mcpServers)) {\n console.log(chalk.gray(` ${name}: ${serverConfig.command} ${serverConfig.args.join(' ')}`));\n }\n break;\n default:\n spinner.fail(`未知的配置项: ${key}`);\n console.log(chalk.yellow('支持的配置项: mcpEndpoint, mcpServers'));\n return;\n }\n } else {\n // 设置配置值\n switch (key) {\n case 'mcpEndpoint':\n configManager.updateMcpEndpoint(value);\n spinner.succeed(`MCP 端点已更新为: ${value}`);\n break;\n default:\n spinner.fail(`配置项 ${key} 不支持通过命令行设置`);\n console.log(chalk.yellow('支持设置的配置项: mcpEndpoint'));\n return;\n }\n }\n } catch (error) {\n spinner.fail(`配置操作失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 显示帮助信息\n */\nfunction showHelp(): void {\n console.log(chalk.blue.bold('xiaozhi - MCP Calculator Service CLI'));\n console.log();\n console.log(chalk.yellow('使用方法:'));\n console.log(' xiaozhi <command> [options]');\n console.log();\n console.log(chalk.yellow('命令:'));\n console.log(' init 初始化配置文件');\n console.log(' config <key> [value] 查看或设置配置');\n console.log(' start [--daemon] 启动服务 (--daemon 后台运行)');\n console.log(' stop 停止服务');\n console.log(' status 检查服务状态');\n console.log(' attach 连接到后台服务查看日志');\n console.log(' restart [--daemon] 重启服务 (--daemon 后台运行)');\n console.log();\n console.log(chalk.yellow('选项:'));\n console.log(' -v, --version 显示版本信息');\n console.log(' -V 显示详细信息');\n console.log(' -h, --help 显示帮助信息');\n console.log();\n console.log(chalk.yellow('配置示例:'));\n console.log(' xiaozhi init # 初始化配置');\n console.log(' xiaozhi config mcpEndpoint # 查看 MCP 端点');\n console.log(' xiaozhi config mcpEndpoint wss://... # 设置 MCP 端点');\n console.log();\n console.log(chalk.yellow('服务示例:'));\n console.log(' xiaozhi start # 前台启动服务');\n console.log(' xiaozhi start --daemon # 后台启动服务');\n console.log(' xiaozhi status # 检查服务状态');\n console.log(' xiaozhi attach # 查看后台服务日志');\n console.log(' xiaozhi stop # 停止服务');\n}\n\n// 配置 Commander 程序\nprogram\n .name('xiaozhi')\n .description('MCP Calculator Service CLI Tool')\n .version(VERSION, '-v, --version', '显示版本信息')\n .helpOption('-h, --help', '显示帮助信息');\n\n// init 命令\nprogram\n .command('init')\n .description('初始化配置文件')\n .action(async () => {\n await initConfig();\n });\n\n// config 命令\nprogram\n .command('config <key> [value]')\n .description('查看或设置配置')\n .action(async (key, value) => {\n await configCommand(key, value);\n });\n\n// start 命令\nprogram\n .command('start')\n .description('启动服务')\n .option('-d, --daemon', '在后台运行服务')\n .action(async (options) => {\n await startService(options.daemon);\n });\n\n// stop 命令\nprogram\n .command('stop')\n .description('停止服务')\n .action(async () => {\n await stopService();\n });\n\n// status 命令\nprogram\n .command('status')\n .description('检查服务状态')\n .action(async () => {\n await checkStatus();\n });\n\n// attach 命令\nprogram\n .command('attach')\n .description('连接到后台服务查看日志')\n .action(async () => {\n await attachService();\n });\n\n// restart 命令\nprogram\n .command('restart')\n .description('重启服务')\n .option('-d, --daemon', '在后台运行服务')\n .action(async (options) => {\n await restartService(options.daemon);\n });\n\n// -V 选项 (详细信息)\nprogram\n .option('-V', '显示详细信息')\n .action((options) => {\n if (options.V) {\n showDetailedInfo();\n process.exit(0);\n }\n });\n\n// 处理无参数情况,显示帮助\nif (process.argv.length <= 2) {\n showHelp();\n process.exit(0);\n}\n\n// 解析命令行参数\nprogram.parse(process.argv);"],"mappings":"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","names":["path","os","fs","chalk","ora","spawn"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { spawn, ChildProcess } from 'child_process';\nimport fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { configManager } from './configManager.js';\n\nconst program = new Command();\nconst VERSION = '0.0.1';\nconst SERVICE_NAME = 'xiaozhi-mcp-service';\n\n// PID 文件路径\nconst PID_FILE = path.join(os.tmpdir(), `${SERVICE_NAME}.pid`);\nconst LOG_FILE = path.join(os.tmpdir(), `${SERVICE_NAME}.log`);\n\ninterface ServiceStatus {\n running: boolean;\n pid?: number;\n uptime?: string;\n mode?: 'foreground' | 'daemon';\n}\n\n/**\n * 获取服务状态\n */\nfunction getServiceStatus(): ServiceStatus {\n try {\n if (!fs.existsSync(PID_FILE)) {\n return { running: false };\n }\n\n const pidContent = fs.readFileSync(PID_FILE, 'utf8').trim();\n const [pidStr, startTime, mode] = pidContent.split('|');\n const pid = parseInt(pidStr);\n\n if (isNaN(pid)) {\n // PID 文件损坏,删除它\n fs.unlinkSync(PID_FILE);\n return { running: false };\n }\n\n // 检查进程是否还在运行\n try {\n process.kill(pid, 0); // 发送信号 0 来检查进程是否存在\n\n // 计算运行时间\n const start = parseInt(startTime);\n const uptime = formatUptime(Date.now() - start);\n\n return {\n running: true,\n pid,\n uptime,\n mode: (mode as 'foreground' | 'daemon') || 'foreground'\n };\n } catch (error) {\n // 进程不存在,删除 PID 文件\n fs.unlinkSync(PID_FILE);\n return { running: false };\n }\n } catch (error) {\n return { running: false };\n }\n}\n\n/**\n * 格式化运行时间\n */\nfunction formatUptime(ms: number): string {\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) {\n return `${days}天 ${hours % 24}小时 ${minutes % 60}分钟`;\n } else if (hours > 0) {\n return `${hours}小时 ${minutes % 60}分钟`;\n } else if (minutes > 0) {\n return `${minutes}分钟 ${seconds % 60}秒`;\n } else {\n return `${seconds}秒`;\n }\n}\n\n/**\n * 保存 PID 信息\n */\nfunction savePidInfo(pid: number, mode: 'foreground' | 'daemon') {\n const pidInfo = `${pid}|${Date.now()}|${mode}`;\n fs.writeFileSync(PID_FILE, pidInfo);\n}\n\n/**\n * 清理 PID 文件\n */\nfunction cleanupPidFile() {\n try {\n if (fs.existsSync(PID_FILE)) {\n fs.unlinkSync(PID_FILE);\n }\n } catch (error) {\n // 忽略清理错误\n }\n}\n\n/**\n * 检查配置文件和环境\n */\nfunction checkEnvironment(): boolean {\n // 首先检查配置文件是否存在\n if (!configManager.configExists()) {\n console.error(chalk.red('❌ 错误: 配置文件不存在'));\n console.log(chalk.yellow('💡 提示: 请运行 \"xiaozhi init\" 初始化配置'));\n return false;\n }\n\n try {\n // 检查配置是否有效\n const endpoint = configManager.getMcpEndpoint();\n if (!endpoint || endpoint.includes('<请填写')) {\n console.error(chalk.red('❌ 错误: MCP 端点未配置'));\n console.log(chalk.yellow('💡 提示: 请运行 \"xiaozhi config mcpEndpoint <your-endpoint-url>\" 设置端点'));\n return false;\n }\n return true;\n } catch (error) {\n console.error(chalk.red(`❌ 错误: 配置文件无效 - ${error instanceof Error ? error.message : String(error)}`));\n console.log(chalk.yellow('💡 提示: 请运行 \"xiaozhi init\" 重新初始化配置'));\n return false;\n }\n}\n\n/**\n * 获取服务启动命令和参数\n */\nfunction getServiceCommand(): { command: string; args: string[]; cwd: string } {\n // 获取当前脚本所在目录\n const scriptDir = __dirname;\n\n // 检查是否在开发环境(js-demo/dist)还是全局安装环境\n let distDir: string;\n if (scriptDir.includes('js-demo/dist')) {\n // 开发环境\n distDir = scriptDir;\n } else {\n // 全局安装环境,需要找到实际的项目目录\n // 通常全局安装后,脚本在 node_modules/.bin 或类似位置\n // 我们需要找到实际的 dist 目录\n const possiblePaths = [\n path.join(scriptDir, '..', 'js-demo', 'dist'),\n path.join(scriptDir, '..', '..', 'js-demo', 'dist'),\n path.join(scriptDir, '..', '..', '..', 'js-demo', 'dist'),\n path.join(process.cwd(), 'js-demo', 'dist'),\n path.join(process.cwd(), 'dist')\n ];\n\n distDir = possiblePaths.find(p =>\n fs.existsSync(path.join(p, 'mcpPipe.cjs')) &&\n fs.existsSync(path.join(p, 'mcpServerProxy.cjs'))\n ) || scriptDir;\n }\n\n return {\n command: 'node',\n args: ['mcpPipe.cjs', 'mcpServerProxy.cjs'],\n cwd: distDir\n };\n}\n\n/**\n * 启动服务\n */\nasync function startService(daemon: boolean = false): Promise<void> {\n const spinner = ora('检查服务状态...').start();\n\n try {\n // 检查服务是否已经在运行\n const status = getServiceStatus();\n if (status.running) {\n spinner.fail(`服务已经在运行 (PID: ${status.pid})`);\n return;\n }\n\n // 检查环境变量\n spinner.text = '检查环境配置...';\n if (!checkEnvironment()) {\n spinner.fail('环境配置检查失败');\n return;\n }\n\n // 获取启动命令\n const { command, args, cwd } = getServiceCommand();\n\n spinner.text = `启动服务 (${daemon ? '后台模式' : '前台模式'})...`;\n\n if (daemon) {\n // 后台模式\n const child = spawn(command, args, {\n cwd,\n detached: true,\n stdio: ['ignore', 'pipe', 'pipe'],\n env: {\n ...process.env,\n XIAOZHI_CONFIG_DIR: process.cwd() // 传递用户的当前工作目录\n }\n });\n\n // 保存 PID 信息\n savePidInfo(child.pid!, 'daemon');\n\n // 设置日志输出\n const logStream = fs.createWriteStream(LOG_FILE, { flags: 'a' });\n child.stdout?.pipe(logStream);\n child.stderr?.pipe(logStream);\n\n // 分离进程\n child.unref();\n\n spinner.succeed(`服务已在后台启动 (PID: ${child.pid})`);\n console.log(chalk.gray(`日志文件: ${LOG_FILE}`));\n console.log(chalk.gray(`使用 'xiaozhi attach' 可以查看实时日志`));\n } else {\n // 前台模式\n spinner.succeed('服务启动中...');\n\n const child = spawn(command, args, {\n cwd,\n stdio: 'inherit',\n env: {\n ...process.env,\n XIAOZHI_CONFIG_DIR: process.cwd() // 传递用户的当前工作目录\n }\n });\n\n // 保存 PID 信息\n savePidInfo(child.pid!, 'foreground');\n\n // 处理进程退出\n child.on('exit', (code, signal) => {\n cleanupPidFile();\n if (code !== 0) {\n console.log(chalk.red(`\\n服务异常退出 (代码: ${code}, 信号: ${signal})`));\n } else {\n console.log(chalk.green('\\n服务已停止'));\n }\n });\n\n // 处理中断信号\n process.on('SIGINT', () => {\n console.log(chalk.yellow('\\n正在停止服务...'));\n child.kill('SIGTERM');\n });\n\n process.on('SIGTERM', () => {\n child.kill('SIGTERM');\n });\n }\n } catch (error) {\n spinner.fail(`启动服务失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 停止服务\n */\nasync function stopService(): Promise<void> {\n const spinner = ora('检查服务状态...').start();\n\n try {\n const status = getServiceStatus();\n\n if (!status.running) {\n spinner.warn('服务未在运行');\n return;\n }\n\n spinner.text = `停止服务 (PID: ${status.pid})...`;\n\n try {\n // 尝试优雅停止\n process.kill(status.pid!, 'SIGTERM');\n\n // 等待进程停止\n let attempts = 0;\n const maxAttempts = 30; // 3秒超时\n\n while (attempts < maxAttempts) {\n await new Promise(resolve => setTimeout(resolve, 100));\n\n try {\n process.kill(status.pid!, 0);\n attempts++;\n } catch {\n // 进程已停止\n break;\n }\n }\n\n // 检查是否还在运行\n try {\n process.kill(status.pid!, 0);\n // 如果还在运行,强制停止\n spinner.text = '强制停止服务...';\n process.kill(status.pid!, 'SIGKILL');\n await new Promise(resolve => setTimeout(resolve, 500));\n } catch {\n // 进程已停止\n }\n\n cleanupPidFile();\n spinner.succeed('服务已停止');\n\n } catch (error) {\n cleanupPidFile();\n spinner.fail(`停止服务失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n } catch (error) {\n spinner.fail(`停止服务失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 检查服务状态\n */\nasync function checkStatus(): Promise<void> {\n const spinner = ora('检查服务状态...').start();\n\n try {\n const status = getServiceStatus();\n\n if (status.running) {\n spinner.succeed('服务状态');\n console.log(chalk.green('✅ 服务正在运行'));\n console.log(chalk.gray(` PID: ${status.pid}`));\n console.log(chalk.gray(` 运行时间: ${status.uptime}`));\n console.log(chalk.gray(` 运行模式: ${status.mode === 'daemon' ? '后台模式' : '前台模式'}`));\n\n if (status.mode === 'daemon') {\n console.log(chalk.gray(` 日志文件: ${LOG_FILE}`));\n }\n } else {\n spinner.succeed('服务状态');\n console.log(chalk.red('❌ 服务未运行'));\n }\n } catch (error) {\n spinner.fail(`检查状态失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 附加到后台服务\n */\nasync function attachService(): Promise<void> {\n const spinner = ora('检查服务状态...').start();\n\n try {\n const status = getServiceStatus();\n\n if (!status.running) {\n spinner.fail('服务未在运行');\n return;\n }\n\n if (status.mode !== 'daemon') {\n spinner.fail('服务不是在后台模式运行');\n return;\n }\n\n spinner.succeed('连接到后台服务...');\n console.log(chalk.green(`已连接到服务 (PID: ${status.pid})`));\n console.log(chalk.gray('按 Ctrl+C 可以断开连接(不会停止服务)'));\n console.log(chalk.gray('=' .repeat(50)));\n\n // 显示日志文件内容\n if (fs.existsSync(LOG_FILE)) {\n // 显示最后100行日志\n const { spawn } = await import('child_process');\n const tail = spawn('tail', ['-f', LOG_FILE], { stdio: 'inherit' });\n\n // 处理中断信号\n process.on('SIGINT', () => {\n console.log(chalk.yellow('\\n断开连接,服务继续在后台运行'));\n tail.kill();\n process.exit(0);\n });\n\n tail.on('exit', () => {\n process.exit(0);\n });\n } else {\n console.log(chalk.yellow('日志文件不存在'));\n }\n\n } catch (error) {\n spinner.fail(`连接失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 重启服务\n */\nasync function restartService(daemon: boolean = false): Promise<void> {\n console.log(chalk.blue('🔄 重启服务...'));\n\n // 先停止服务\n await stopService();\n\n // 等待一下确保完全停止\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n // 重新启动服务\n await startService(daemon);\n}\n\n/**\n * 显示版本信息\n */\nfunction showVersion(): void {\n console.log(chalk.blue(`xiaozhi v${VERSION}`));\n}\n\n/**\n * 显示详细信息\n */\nfunction showDetailedInfo(): void {\n console.log(chalk.blue(`xiaozhi v${VERSION}`));\n console.log(chalk.gray('MCP Calculator Service CLI Tool'));\n console.log(chalk.gray('Built with Node.js and TypeScript'));\n console.log(chalk.gray(`Node.js: ${process.version}`));\n console.log(chalk.gray(`Platform: ${process.platform} ${process.arch}`));\n}\n\n/**\n * 初始化配置\n */\nasync function initConfig(): Promise<void> {\n const spinner = ora('初始化配置...').start();\n\n try {\n if (configManager.configExists()) {\n spinner.warn('配置文件已存在');\n console.log(chalk.yellow('如需重新初始化,请先删除现有的 xiaozhi.config.json 文件'));\n return;\n }\n\n configManager.initConfig();\n spinner.succeed('配置文件初始化成功');\n\n console.log(chalk.green('✅ 配置文件已创建: xiaozhi.config.json'));\n console.log(chalk.yellow('📝 请编辑配置文件设置你的 MCP 端点:'));\n console.log(chalk.gray(` 配置文件路径: ${configManager.getConfigPath()}`));\n console.log(chalk.yellow('💡 或者使用命令设置:'));\n console.log(chalk.gray(' xiaozhi config mcpEndpoint <your-endpoint-url>'));\n } catch (error) {\n spinner.fail(`初始化配置失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 配置管理命令\n */\nasync function configCommand(key: string, value?: string): Promise<void> {\n const spinner = ora('更新配置...').start();\n\n try {\n if (!configManager.configExists()) {\n spinner.fail('配置文件不存在');\n console.log(chalk.yellow('💡 提示: 请先运行 \"xiaozhi init\" 初始化配置'));\n return;\n }\n\n if (!value) {\n // 显示配置值\n spinner.text = '读取配置...';\n const config = configManager.getConfig();\n\n switch (key) {\n case 'mcpEndpoint':\n spinner.succeed('配置信息');\n console.log(chalk.green(`MCP 端点: ${config.mcpEndpoint}`));\n break;\n case 'mcpServers':\n spinner.succeed('配置信息');\n console.log(chalk.green('MCP 服务:'));\n for (const [name, serverConfig] of Object.entries(config.mcpServers)) {\n console.log(chalk.gray(` ${name}: ${serverConfig.command} ${serverConfig.args.join(' ')}`));\n }\n break;\n default:\n spinner.fail(`未知的配置项: ${key}`);\n console.log(chalk.yellow('支持的配置项: mcpEndpoint, mcpServers'));\n return;\n }\n } else {\n // 设置配置值\n switch (key) {\n case 'mcpEndpoint':\n configManager.updateMcpEndpoint(value);\n spinner.succeed(`MCP 端点已更新为: ${value}`);\n break;\n default:\n spinner.fail(`配置项 ${key} 不支持通过命令行设置`);\n console.log(chalk.yellow('支持设置的配置项: mcpEndpoint'));\n return;\n }\n }\n } catch (error) {\n spinner.fail(`配置操作失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 显示帮助信息\n */\nfunction showHelp(): void {\n console.log(chalk.blue.bold('xiaozhi - MCP Calculator Service CLI'));\n console.log();\n console.log(chalk.yellow('使用方法:'));\n console.log(' xiaozhi <command> [options]');\n console.log();\n console.log(chalk.yellow('命令:'));\n console.log(' init 初始化配置文件');\n console.log(' config <key> [value] 查看或设置配置');\n console.log(' start [--daemon] 启动服务 (--daemon 后台运行)');\n console.log(' stop 停止服务');\n console.log(' status 检查服务状态');\n console.log(' attach 连接到后台服务查看日志');\n console.log(' restart [--daemon] 重启服务 (--daemon 后台运行)');\n console.log();\n console.log(chalk.yellow('选项:'));\n console.log(' -v, --version 显示版本信息');\n console.log(' -V 显示详细信息');\n console.log(' -h, --help 显示帮助信息');\n console.log();\n console.log(chalk.yellow('配置示例:'));\n console.log(' xiaozhi init # 初始化配置');\n console.log(' xiaozhi config mcpEndpoint # 查看 MCP 端点');\n console.log(' xiaozhi config mcpEndpoint wss://... # 设置 MCP 端点');\n console.log();\n console.log(chalk.yellow('服务示例:'));\n console.log(' xiaozhi start # 前台启动服务');\n console.log(' xiaozhi start --daemon # 后台启动服务');\n console.log(' xiaozhi status # 检查服务状态');\n console.log(' xiaozhi attach # 查看后台服务日志');\n console.log(' xiaozhi stop # 停止服务');\n}\n\n// 配置 Commander 程序\nprogram\n .name('xiaozhi')\n .description('MCP Calculator Service CLI Tool')\n .version(VERSION, '-v, --version', '显示版本信息')\n .helpOption('-h, --help', '显示帮助信息');\n\n// init 命令\nprogram\n .command('init')\n .description('初始化配置文件')\n .action(async () => {\n await initConfig();\n });\n\n// config 命令\nprogram\n .command('config <key> [value]')\n .description('查看或设置配置')\n .action(async (key, value) => {\n await configCommand(key, value);\n });\n\n// start 命令\nprogram\n .command('start')\n .description('启动服务')\n .option('-d, --daemon', '在后台运行服务')\n .action(async (options) => {\n await startService(options.daemon);\n });\n\n// stop 命令\nprogram\n .command('stop')\n .description('停止服务')\n .action(async () => {\n await stopService();\n });\n\n// status 命令\nprogram\n .command('status')\n .description('检查服务状态')\n .action(async () => {\n await checkStatus();\n });\n\n// attach 命令\nprogram\n .command('attach')\n .description('连接到后台服务查看日志')\n .action(async () => {\n await attachService();\n });\n\n// restart 命令\nprogram\n .command('restart')\n .description('重启服务')\n .option('-d, --daemon', '在后台运行服务')\n .action(async (options) => {\n await restartService(options.daemon);\n });\n\n// -V 选项 (详细信息)\nprogram\n .option('-V', '显示详细信息')\n .action((options) => {\n if (options.V) {\n showDetailedInfo();\n process.exit(0);\n }\n });\n\n// 处理无参数情况,显示帮助\nif (process.argv.length <= 2) {\n showHelp();\n process.exit(0);\n}\n\n// 解析命令行参数\nprogram.parse(process.argv);"],"mappings":"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","names":["path","os","fs","chalk","ora","spawn"]}
|
package/dist/configManager.cjs
CHANGED
|
@@ -30,12 +30,17 @@ class ConfigManager {
|
|
|
30
30
|
__name(this, "ConfigManager");
|
|
31
31
|
}
|
|
32
32
|
static instance;
|
|
33
|
-
configPath;
|
|
34
33
|
defaultConfigPath;
|
|
35
34
|
config = null;
|
|
36
35
|
constructor() {
|
|
37
|
-
this.
|
|
38
|
-
|
|
36
|
+
this.defaultConfigPath = (0, import_path.resolve)(__dirname, "xiaozhi.config.default.json");
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 获取配置文件路径(动态计算)
|
|
40
|
+
*/
|
|
41
|
+
getConfigFilePath() {
|
|
42
|
+
const configDir = process.env.XIAOZHI_CONFIG_DIR || process.cwd();
|
|
43
|
+
return (0, import_path.resolve)(configDir, "xiaozhi.config.json");
|
|
39
44
|
}
|
|
40
45
|
/**
|
|
41
46
|
* 获取配置管理器单例实例
|
|
@@ -50,7 +55,8 @@ class ConfigManager {
|
|
|
50
55
|
* 检查配置文件是否存在
|
|
51
56
|
*/
|
|
52
57
|
configExists() {
|
|
53
|
-
|
|
58
|
+
const configPath = this.getConfigFilePath();
|
|
59
|
+
return (0, import_fs.existsSync)(configPath);
|
|
54
60
|
}
|
|
55
61
|
/**
|
|
56
62
|
* 初始化配置文件
|
|
@@ -58,12 +64,13 @@ class ConfigManager {
|
|
|
58
64
|
*/
|
|
59
65
|
initConfig() {
|
|
60
66
|
if (!(0, import_fs.existsSync)(this.defaultConfigPath)) {
|
|
61
|
-
throw new Error("\u9ED8\u8BA4\u914D\u7F6E\u6587\u4EF6 config.default.json \u4E0D\u5B58\u5728");
|
|
67
|
+
throw new Error("\u9ED8\u8BA4\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.default.json \u4E0D\u5B58\u5728");
|
|
62
68
|
}
|
|
63
69
|
if (this.configExists()) {
|
|
64
|
-
throw new Error("\u914D\u7F6E\u6587\u4EF6 config.json \u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u521D\u59CB\u5316");
|
|
70
|
+
throw new Error("\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.json \u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u521D\u59CB\u5316");
|
|
65
71
|
}
|
|
66
|
-
|
|
72
|
+
const configPath = this.getConfigFilePath();
|
|
73
|
+
(0, import_fs.copyFileSync)(this.defaultConfigPath, configPath);
|
|
67
74
|
this.config = null;
|
|
68
75
|
}
|
|
69
76
|
/**
|
|
@@ -71,10 +78,11 @@ class ConfigManager {
|
|
|
71
78
|
*/
|
|
72
79
|
loadConfig() {
|
|
73
80
|
if (!this.configExists()) {
|
|
74
|
-
throw new Error("\u914D\u7F6E\u6587\u4EF6 config.json \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u8FD0\u884C xiaozhi init \u521D\u59CB\u5316\u914D\u7F6E");
|
|
81
|
+
throw new Error("\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.json \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u8FD0\u884C xiaozhi init \u521D\u59CB\u5316\u914D\u7F6E");
|
|
75
82
|
}
|
|
76
83
|
try {
|
|
77
|
-
const
|
|
84
|
+
const configPath = this.getConfigFilePath();
|
|
85
|
+
const configData = (0, import_fs.readFileSync)(configPath, "utf8");
|
|
78
86
|
const config = JSON.parse(configData);
|
|
79
87
|
this.validateConfig(config);
|
|
80
88
|
return config;
|
|
@@ -199,8 +207,9 @@ class ConfigManager {
|
|
|
199
207
|
saveConfig(config) {
|
|
200
208
|
try {
|
|
201
209
|
this.validateConfig(config);
|
|
210
|
+
const configPath = this.getConfigFilePath();
|
|
202
211
|
const configJson = JSON.stringify(config, null, 2);
|
|
203
|
-
(0, import_fs.writeFileSync)(
|
|
212
|
+
(0, import_fs.writeFileSync)(configPath, configJson, "utf8");
|
|
204
213
|
this.config = config;
|
|
205
214
|
} catch (error) {
|
|
206
215
|
throw new Error(`\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -216,7 +225,7 @@ class ConfigManager {
|
|
|
216
225
|
* 获取配置文件路径
|
|
217
226
|
*/
|
|
218
227
|
getConfigPath() {
|
|
219
|
-
return this.
|
|
228
|
+
return this.getConfigFilePath();
|
|
220
229
|
}
|
|
221
230
|
/**
|
|
222
231
|
* 获取默认配置文件路径
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/configManager.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, copyFileSync } from 'fs';\nimport { resolve } from 'path';\n\n// 在 CommonJS 中,__dirname 是内置的,不需要定义\n// 在 ESM 中,需要从 import.meta.url 获取\n// 这里我们假设编译后是 CommonJS,所以直接使用内置的 __dirname\n\n// 配置文件接口定义\nexport interface MCPServerConfig {\n command: string;\n args: string[];\n env?: Record<string, string>;\n}\n\nexport interface AppConfig {\n mcpEndpoint: string;\n mcpServers: Record<string, MCPServerConfig>;\n}\n\n/**\n * 配置管理类\n * 负责管理应用配置,提供只读访问和安全的配置更新功能\n */\nexport class ConfigManager {\n private static instance: ConfigManager;\n private configPath: string;\n private defaultConfigPath: string;\n private config: AppConfig | null = null;\n\n private constructor() {\n // 配置文件路径\n this.configPath = resolve(__dirname, 'config.json');\n this.defaultConfigPath = resolve(__dirname, 'config.default.json');\n }\n\n /**\n * 获取配置管理器单例实例\n */\n public static getInstance(): ConfigManager {\n if (!ConfigManager.instance) {\n ConfigManager.instance = new ConfigManager();\n }\n return ConfigManager.instance;\n }\n\n /**\n * 检查配置文件是否存在\n */\n public configExists(): boolean {\n return existsSync(this.configPath);\n }\n\n /**\n * 初始化配置文件\n * 从 config.default.json 复制到 config.json\n */\n public initConfig(): void {\n if (!existsSync(this.defaultConfigPath)) {\n throw new Error('默认配置文件 config.default.json 不存在');\n }\n\n if (this.configExists()) {\n throw new Error('配置文件 config.json 已存在,无需重复初始化');\n }\n\n copyFileSync(this.defaultConfigPath, this.configPath);\n this.config = null; // 重置缓存\n }\n\n /**\n * 加载配置文件\n */\n private loadConfig(): AppConfig {\n if (!this.configExists()) {\n throw new Error('配置文件 config.json 不存在,请先运行 xiaozhi init 初始化配置');\n }\n\n try {\n const configData = readFileSync(this.configPath, 'utf8');\n const config = JSON.parse(configData) as AppConfig;\n \n // 验证配置结构\n this.validateConfig(config);\n \n return config;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`配置文件格式错误: ${error.message}`);\n }\n throw error;\n }\n }\n\n /**\n * 验证配置文件结构\n */\n private validateConfig(config: any): void {\n if (!config || typeof config !== 'object') {\n throw new Error('配置文件格式错误:根对象无效');\n }\n\n if (!config.mcpEndpoint || typeof config.mcpEndpoint !== 'string') {\n throw new Error('配置文件格式错误:mcpEndpoint 字段无效');\n }\n\n if (!config.mcpServers || typeof config.mcpServers !== 'object') {\n throw new Error('配置文件格式错误:mcpServers 字段无效');\n }\n\n // 验证每个 MCP 服务配置\n for (const [serverName, serverConfig] of Object.entries(config.mcpServers)) {\n if (!serverConfig || typeof serverConfig !== 'object') {\n throw new Error(`配置文件格式错误:mcpServers.${serverName} 无效`);\n }\n\n const sc = serverConfig as any;\n if (!sc.command || typeof sc.command !== 'string') {\n throw new Error(`配置文件格式错误:mcpServers.${serverName}.command 无效`);\n }\n\n if (!Array.isArray(sc.args)) {\n throw new Error(`配置文件格式错误:mcpServers.${serverName}.args 必须是数组`);\n }\n\n if (sc.env && typeof sc.env !== 'object') {\n throw new Error(`配置文件格式错误:mcpServers.${serverName}.env 必须是对象`);\n }\n }\n }\n\n /**\n * 获取配置(只读)\n */\n public getConfig(): Readonly<AppConfig> {\n if (!this.config) {\n this.config = this.loadConfig();\n }\n \n // 返回深度只读副本\n return JSON.parse(JSON.stringify(this.config));\n }\n\n /**\n * 获取 MCP 端点\n */\n public getMcpEndpoint(): string {\n const config = this.getConfig();\n return config.mcpEndpoint;\n }\n\n /**\n * 获取 MCP 服务配置\n */\n public getMcpServers(): Readonly<Record<string, MCPServerConfig>> {\n const config = this.getConfig();\n return config.mcpServers;\n }\n\n /**\n * 更新 MCP 端点\n */\n public updateMcpEndpoint(endpoint: string): void {\n if (!endpoint || typeof endpoint !== 'string') {\n throw new Error('MCP 端点必须是非空字符串');\n }\n\n const config = this.getConfig();\n const newConfig = { ...config, mcpEndpoint: endpoint };\n this.saveConfig(newConfig);\n }\n\n /**\n * 更新 MCP 服务配置\n */\n public updateMcpServer(serverName: string, serverConfig: MCPServerConfig): void {\n if (!serverName || typeof serverName !== 'string') {\n throw new Error('服务名称必须是非空字符串');\n }\n\n // 验证服务配置\n if (!serverConfig.command || typeof serverConfig.command !== 'string') {\n throw new Error('服务配置的 command 字段必须是非空字符串');\n }\n\n if (!Array.isArray(serverConfig.args)) {\n throw new Error('服务配置的 args 字段必须是数组');\n }\n\n if (serverConfig.env && typeof serverConfig.env !== 'object') {\n throw new Error('服务配置的 env 字段必须是对象');\n }\n\n const config = this.getConfig();\n const newConfig = {\n ...config,\n mcpServers: {\n ...config.mcpServers,\n [serverName]: serverConfig\n }\n };\n this.saveConfig(newConfig);\n }\n\n /**\n * 删除 MCP 服务配置\n */\n public removeMcpServer(serverName: string): void {\n if (!serverName || typeof serverName !== 'string') {\n throw new Error('服务名称必须是非空字符串');\n }\n\n const config = this.getConfig();\n if (!config.mcpServers[serverName]) {\n throw new Error(`服务 ${serverName} 不存在`);\n }\n\n const newMcpServers = { ...config.mcpServers };\n delete newMcpServers[serverName];\n\n const newConfig = {\n ...config,\n mcpServers: newMcpServers\n };\n this.saveConfig(newConfig);\n }\n\n /**\n * 保存配置到文件\n */\n private saveConfig(config: AppConfig): void {\n try {\n // 验证配置\n this.validateConfig(config);\n \n // 格式化 JSON 并保存\n const configJson = JSON.stringify(config, null, 2);\n writeFileSync(this.configPath, configJson, 'utf8');\n \n // 更新缓存\n this.config = config;\n } catch (error) {\n throw new Error(`保存配置失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n /**\n * 重新加载配置(清除缓存)\n */\n public reloadConfig(): void {\n this.config = null;\n }\n\n /**\n * 获取配置文件路径\n */\n public getConfigPath(): string {\n return this.configPath;\n }\n\n /**\n * 获取默认配置文件路径\n */\n public getDefaultConfigPath(): string {\n return this.defaultConfigPath;\n }\n}\n\n// 导出单例实例\nexport const configManager = ConfigManager.getInstance();\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/configManager.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, copyFileSync } from 'fs';\nimport { resolve } from 'path';\n\n// 在 CommonJS 中,__dirname 是内置的,不需要定义\n// 在 ESM 中,需要从 import.meta.url 获取\n// 这里我们假设编译后是 CommonJS,所以直接使用内置的 __dirname\n\n// 配置文件接口定义\nexport interface MCPServerConfig {\n command: string;\n args: string[];\n env?: Record<string, string>;\n}\n\nexport interface AppConfig {\n mcpEndpoint: string;\n mcpServers: Record<string, MCPServerConfig>;\n}\n\n/**\n * 配置管理类\n * 负责管理应用配置,提供只读访问和安全的配置更新功能\n */\nexport class ConfigManager {\n private static instance: ConfigManager;\n private defaultConfigPath: string;\n private config: AppConfig | null = null;\n\n private constructor() {\n this.defaultConfigPath = resolve(__dirname, 'xiaozhi.config.default.json');\n }\n\n /**\n * 获取配置文件路径(动态计算)\n */\n private getConfigFilePath(): string {\n // 配置文件路径 - 优先使用环境变量指定的目录,否则使用当前工作目录\n const configDir = process.env.XIAOZHI_CONFIG_DIR || process.cwd();\n return resolve(configDir, 'xiaozhi.config.json');\n }\n\n /**\n * 获取配置管理器单例实例\n */\n public static getInstance(): ConfigManager {\n if (!ConfigManager.instance) {\n ConfigManager.instance = new ConfigManager();\n }\n return ConfigManager.instance;\n }\n\n /**\n * 检查配置文件是否存在\n */\n public configExists(): boolean {\n const configPath = this.getConfigFilePath();\n return existsSync(configPath);\n }\n\n /**\n * 初始化配置文件\n * 从 config.default.json 复制到 config.json\n */\n public initConfig(): void {\n if (!existsSync(this.defaultConfigPath)) {\n throw new Error('默认配置文件 xiaozhi.config.default.json 不存在');\n }\n\n if (this.configExists()) {\n throw new Error('配置文件 xiaozhi.config.json 已存在,无需重复初始化');\n }\n\n const configPath = this.getConfigFilePath();\n copyFileSync(this.defaultConfigPath, configPath);\n this.config = null; // 重置缓存\n }\n\n /**\n * 加载配置文件\n */\n private loadConfig(): AppConfig {\n if (!this.configExists()) {\n throw new Error('配置文件 xiaozhi.config.json 不存在,请先运行 xiaozhi init 初始化配置');\n }\n\n try {\n const configPath = this.getConfigFilePath();\n const configData = readFileSync(configPath, 'utf8');\n const config = JSON.parse(configData) as AppConfig;\n\n // 验证配置结构\n this.validateConfig(config);\n\n return config;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`配置文件格式错误: ${error.message}`);\n }\n throw error;\n }\n }\n\n /**\n * 验证配置文件结构\n */\n private validateConfig(config: any): void {\n if (!config || typeof config !== 'object') {\n throw new Error('配置文件格式错误:根对象无效');\n }\n\n if (!config.mcpEndpoint || typeof config.mcpEndpoint !== 'string') {\n throw new Error('配置文件格式错误:mcpEndpoint 字段无效');\n }\n\n if (!config.mcpServers || typeof config.mcpServers !== 'object') {\n throw new Error('配置文件格式错误:mcpServers 字段无效');\n }\n\n // 验证每个 MCP 服务配置\n for (const [serverName, serverConfig] of Object.entries(config.mcpServers)) {\n if (!serverConfig || typeof serverConfig !== 'object') {\n throw new Error(`配置文件格式错误:mcpServers.${serverName} 无效`);\n }\n\n const sc = serverConfig as any;\n if (!sc.command || typeof sc.command !== 'string') {\n throw new Error(`配置文件格式错误:mcpServers.${serverName}.command 无效`);\n }\n\n if (!Array.isArray(sc.args)) {\n throw new Error(`配置文件格式错误:mcpServers.${serverName}.args 必须是数组`);\n }\n\n if (sc.env && typeof sc.env !== 'object') {\n throw new Error(`配置文件格式错误:mcpServers.${serverName}.env 必须是对象`);\n }\n }\n }\n\n /**\n * 获取配置(只读)\n */\n public getConfig(): Readonly<AppConfig> {\n if (!this.config) {\n this.config = this.loadConfig();\n }\n \n // 返回深度只读副本\n return JSON.parse(JSON.stringify(this.config));\n }\n\n /**\n * 获取 MCP 端点\n */\n public getMcpEndpoint(): string {\n const config = this.getConfig();\n return config.mcpEndpoint;\n }\n\n /**\n * 获取 MCP 服务配置\n */\n public getMcpServers(): Readonly<Record<string, MCPServerConfig>> {\n const config = this.getConfig();\n return config.mcpServers;\n }\n\n /**\n * 更新 MCP 端点\n */\n public updateMcpEndpoint(endpoint: string): void {\n if (!endpoint || typeof endpoint !== 'string') {\n throw new Error('MCP 端点必须是非空字符串');\n }\n\n const config = this.getConfig();\n const newConfig = { ...config, mcpEndpoint: endpoint };\n this.saveConfig(newConfig);\n }\n\n /**\n * 更新 MCP 服务配置\n */\n public updateMcpServer(serverName: string, serverConfig: MCPServerConfig): void {\n if (!serverName || typeof serverName !== 'string') {\n throw new Error('服务名称必须是非空字符串');\n }\n\n // 验证服务配置\n if (!serverConfig.command || typeof serverConfig.command !== 'string') {\n throw new Error('服务配置的 command 字段必须是非空字符串');\n }\n\n if (!Array.isArray(serverConfig.args)) {\n throw new Error('服务配置的 args 字段必须是数组');\n }\n\n if (serverConfig.env && typeof serverConfig.env !== 'object') {\n throw new Error('服务配置的 env 字段必须是对象');\n }\n\n const config = this.getConfig();\n const newConfig = {\n ...config,\n mcpServers: {\n ...config.mcpServers,\n [serverName]: serverConfig\n }\n };\n this.saveConfig(newConfig);\n }\n\n /**\n * 删除 MCP 服务配置\n */\n public removeMcpServer(serverName: string): void {\n if (!serverName || typeof serverName !== 'string') {\n throw new Error('服务名称必须是非空字符串');\n }\n\n const config = this.getConfig();\n if (!config.mcpServers[serverName]) {\n throw new Error(`服务 ${serverName} 不存在`);\n }\n\n const newMcpServers = { ...config.mcpServers };\n delete newMcpServers[serverName];\n\n const newConfig = {\n ...config,\n mcpServers: newMcpServers\n };\n this.saveConfig(newConfig);\n }\n\n /**\n * 保存配置到文件\n */\n private saveConfig(config: AppConfig): void {\n try {\n // 验证配置\n this.validateConfig(config);\n\n // 格式化 JSON 并保存\n const configPath = this.getConfigFilePath();\n const configJson = JSON.stringify(config, null, 2);\n writeFileSync(configPath, configJson, 'utf8');\n\n // 更新缓存\n this.config = config;\n } catch (error) {\n throw new Error(`保存配置失败: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n /**\n * 重新加载配置(清除缓存)\n */\n public reloadConfig(): void {\n this.config = null;\n }\n\n /**\n * 获取配置文件路径\n */\n public getConfigPath(): string {\n return this.getConfigFilePath();\n }\n\n /**\n * 获取默认配置文件路径\n */\n public getDefaultConfigPath(): string {\n return this.defaultConfigPath;\n }\n}\n\n// 导出单例实例\nexport const configManager = ConfigManager.getInstance();\n"],"mappings":"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","names":[]}
|
package/dist/configManager.d.ts
CHANGED
|
@@ -13,10 +13,13 @@ interface AppConfig {
|
|
|
13
13
|
*/
|
|
14
14
|
declare class ConfigManager {
|
|
15
15
|
private static instance;
|
|
16
|
-
private configPath;
|
|
17
16
|
private defaultConfigPath;
|
|
18
17
|
private config;
|
|
19
18
|
private constructor();
|
|
19
|
+
/**
|
|
20
|
+
* 获取配置文件路径(动态计算)
|
|
21
|
+
*/
|
|
22
|
+
private getConfigFilePath;
|
|
20
23
|
/**
|
|
21
24
|
* 获取配置管理器单例实例
|
|
22
25
|
*/
|
package/dist/mcpPipe.cjs
CHANGED
|
@@ -219,6 +219,14 @@ async function main() {
|
|
|
219
219
|
const mcpScript = import_process.default.argv[2];
|
|
220
220
|
let endpointUrl;
|
|
221
221
|
try {
|
|
222
|
+
import_process.default.stderr.write(`[DEBUG] XIAOZHI_CONFIG_DIR: ${import_process.default.env.XIAOZHI_CONFIG_DIR}
|
|
223
|
+
`);
|
|
224
|
+
import_process.default.stderr.write(`[DEBUG] process.cwd(): ${import_process.default.cwd()}
|
|
225
|
+
`);
|
|
226
|
+
import_process.default.stderr.write(`[DEBUG] configManager.getConfigPath(): ${import_configManager.configManager.getConfigPath()}
|
|
227
|
+
`);
|
|
228
|
+
import_process.default.stderr.write(`[DEBUG] configManager.configExists(): ${import_configManager.configManager.configExists()}
|
|
229
|
+
`);
|
|
222
230
|
if (import_configManager.configManager.configExists()) {
|
|
223
231
|
endpointUrl = import_configManager.configManager.getMcpEndpoint();
|
|
224
232
|
logger.info("\u4F7F\u7528\u914D\u7F6E\u6587\u4EF6\u4E2D\u7684 MCP \u7AEF\u70B9");
|
package/dist/mcpPipe.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcpPipe.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * MCP Pipe - JavaScript Implementation\n * Connects to MCP server and pipes input/output to WebSocket endpoint\n * d\n * Version: 0.2.0\n *\n * Usage:\n * export MCP_ENDPOINT=<mcp_endpoint>\n * node mcp_pipe.js <mcp_script>\n */\n\nimport WebSocket from 'ws';\nimport { spawn, ChildProcess } from 'child_process';\nimport { config } from 'dotenv';\nimport process from 'process';\nimport { configManager } from './configManager.js';\n\n// Load environment variables\nconfig();\n\n// Logger utility\nclass Logger {\n private name: string;\n\n constructor(name: string) {\n this.name = name;\n }\n\n info(message: string): void {\n const timestamp = new Date().toISOString();\n console.error(`${timestamp} - ${this.name} - INFO - ${message}`);\n }\n\n error(message: string): void {\n const timestamp = new Date().toISOString();\n console.error(`${timestamp} - ${this.name} - ERROR - ${message}`);\n }\n\n warning(message: string): void {\n const timestamp = new Date().toISOString();\n console.error(`${timestamp} - ${this.name} - WARNING - ${message}`);\n }\n\n debug(message: string): void {\n const timestamp = new Date().toISOString();\n console.error(`${timestamp} - ${this.name} - DEBUG - ${message}`);\n }\n}\n\nconst logger = new Logger('MCP_PIPE');\n\n// Reconnection settings\nconst INITIAL_BACKOFF = 1000; // Initial wait time in milliseconds\nconst MAX_BACKOFF = 30000; // Maximum wait time in milliseconds (reduced)\nlet reconnectAttempt = 0;\nlet backoff = INITIAL_BACKOFF;\n\nclass MCPPipe {\n private mcpScript: string;\n private endpointUrl: string;\n private process: ChildProcess | null;\n private websocket: WebSocket | null;\n private shouldReconnect: boolean;\n private isConnected: boolean;\n private shutdownResolve?: () => void;\n\n constructor(mcpScript: string, endpointUrl: string) {\n this.mcpScript = mcpScript;\n this.endpointUrl = endpointUrl;\n this.process = null;\n this.websocket = null;\n this.shouldReconnect = true;\n this.isConnected = false;\n }\n\n async start() {\n // Start MCP script process\n this.startMCPProcess();\n\n // Start WebSocket connection\n await this.connectToServer();\n\n // Keep the process running\n return new Promise<void>((resolve) => {\n // This promise will only resolve when shutdown is called\n this.shutdownResolve = resolve;\n });\n }\n\n async connectToServer() {\n if (this.isConnected) {\n return;\n }\n\n logger.info('Connecting to WebSocket server...');\n\n this.websocket = new WebSocket(this.endpointUrl);\n\n this.websocket.on('open', () => {\n logger.info('Successfully connected to WebSocket server');\n this.isConnected = true;\n\n // Reset reconnection counter\n reconnectAttempt = 0;\n backoff = INITIAL_BACKOFF;\n });\n\n this.websocket.on('message', (data: WebSocket.Data) => {\n const message = data.toString();\n logger.debug(`<< ${message.substring(0, 120)}...`);\n\n // Write to process stdin\n if (this.process && this.process.stdin && !this.process.stdin.destroyed) {\n this.process.stdin.write(message + '\\n');\n }\n });\n\n this.websocket.on('close', (code: number, reason: Buffer) => {\n logger.error(`WebSocket connection closed: ${code} ${reason}`);\n this.isConnected = false;\n this.websocket = null;\n\n // Only reconnect if we should and it's not a permanent error\n if (this.shouldReconnect && code !== 4004) {\n this.scheduleReconnect();\n }\n });\n\n this.websocket.on('error', (error: Error) => {\n logger.error(`WebSocket error: ${error.message}`);\n this.isConnected = false;\n });\n }\n\n scheduleReconnect() {\n if (!this.shouldReconnect) return;\n\n reconnectAttempt++;\n const waitTime = Math.min(backoff * Math.pow(2, reconnectAttempt - 1), MAX_BACKOFF);\n\n logger.info(`Scheduling reconnection attempt ${reconnectAttempt} in ${(waitTime / 1000).toFixed(2)} seconds...`);\n\n setTimeout(() => {\n if (this.shouldReconnect) {\n this.connectToServer();\n }\n }, waitTime);\n }\n\n startMCPProcess() {\n if (this.process) {\n logger.info(`${this.mcpScript} process already running`);\n return;\n }\n\n logger.info(`Starting ${this.mcpScript} process`);\n\n this.process = spawn('node', [this.mcpScript], {\n stdio: ['pipe', 'pipe', 'pipe']\n });\n\n // Handle process stdout - send to WebSocket\n this.process.stdout?.on('data', (data: Buffer) => {\n const message = data.toString();\n logger.debug(`>> ${message.substring(0, 120)}...`);\n\n if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {\n this.websocket.send(message);\n }\n });\n\n // Handle process stderr - print to terminal\n this.process.stderr?.on('data', (data: Buffer) => {\n process.stderr.write(data);\n });\n\n // Handle process exit\n this.process.on('exit', (code: number | null, signal: NodeJS.Signals | null) => {\n logger.info(`${this.mcpScript} process exited with code ${code}, signal ${signal}`);\n this.process = null;\n this.shouldReconnect = false;\n if (this.websocket) {\n this.websocket.close();\n }\n });\n\n // Handle process error\n this.process.on('error', (error: Error) => {\n logger.error(`Process error: ${error.message}`);\n this.process = null;\n this.shouldReconnect = false;\n if (this.websocket) {\n this.websocket.close();\n }\n });\n }\n\n cleanup() {\n if (this.process) {\n logger.info(`Terminating ${this.mcpScript} process`);\n try {\n this.process.kill('SIGTERM');\n\n // Force kill after timeout\n setTimeout(() => {\n if (this.process && !this.process.killed) {\n this.process.kill('SIGKILL');\n }\n }, 5000);\n } catch (error) {\n logger.error(`Error terminating process: ${error instanceof Error ? error.message : String(error)}`);\n }\n this.process = null;\n }\n\n if (this.websocket) {\n this.websocket = null;\n }\n\n this.isConnected = false;\n }\n\n sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n\n shutdown() {\n logger.info('Shutting down MCP Pipe...');\n this.shouldReconnect = false;\n this.cleanup();\n if (this.websocket) {\n this.websocket.close();\n }\n if (this.shutdownResolve) {\n this.shutdownResolve();\n }\n process.exit(0);\n }\n}\n\n// Signal handlers\nfunction setupSignalHandlers(mcpPipe: MCPPipe): void {\n process.on('SIGINT', () => {\n logger.info('Received interrupt signal, shutting down...');\n mcpPipe.shutdown();\n });\n\n process.on('SIGTERM', () => {\n logger.info('Received terminate signal, shutting down...');\n mcpPipe.shutdown();\n });\n}\n\n// Main execution\nasync function main() {\n // Check command line arguments\n if (process.argv.length < 3) {\n logger.error('Usage: node mcp_pipe.js <mcp_script>');\n process.exit(1);\n }\n\n const mcpScript = process.argv[2];\n\n // Get endpoint URL from config file or environment variable (fallback)\n let endpointUrl: string;\n\n try {\n // 首先尝试从配置文件读取\n if (configManager.configExists()) {\n endpointUrl = configManager.getMcpEndpoint();\n logger.info('使用配置文件中的 MCP 端点');\n } else {\n // 如果配置文件不存在,尝试从环境变量读取(向后兼容)\n endpointUrl = process.env.MCP_ENDPOINT || '';\n if (!endpointUrl) {\n logger.error('配置文件不存在且未设置 MCP_ENDPOINT 环境变量');\n logger.error('请运行 \"xiaozhi init\" 初始化配置,或设置 MCP_ENDPOINT 环境变量');\n process.exit(1);\n }\n logger.info('使用环境变量中的 MCP 端点(建议使用配置文件)');\n }\n } catch (error) {\n logger.error(`读取配置失败: ${error instanceof Error ? error.message : String(error)}`);\n\n // 尝试从环境变量读取作为备用方案\n endpointUrl = process.env.MCP_ENDPOINT || '';\n if (!endpointUrl) {\n logger.error('请运行 \"xiaozhi init\" 初始化配置,或设置 MCP_ENDPOINT 环境变量');\n process.exit(1);\n }\n logger.info('使用环境变量中的 MCP 端点作为备用方案');\n }\n\n // 验证端点 URL\n if (!endpointUrl || endpointUrl.includes('<请填写')) {\n logger.error('MCP 端点未配置或配置无效');\n logger.error('请运行 \"xiaozhi config mcpEndpoint <your-endpoint-url>\" 设置端点');\n process.exit(1);\n }\n\n // Create MCP Pipe instance\n const mcpPipe = new MCPPipe(mcpScript, endpointUrl);\n\n // Setup signal handlers\n setupSignalHandlers(mcpPipe);\n\n // Start the MCP pipe\n try {\n await mcpPipe.start();\n } catch (error) {\n logger.error(`Program execution error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n}\n\n// Run if this file is executed directly\nif (require.main === module) {\n main().catch(error => {\n logger.error(`Unhandled error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n });\n}\n"],"mappings":"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","names":["WebSocket","process"]}
|
|
1
|
+
{"version":3,"sources":["../src/mcpPipe.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * MCP Pipe - JavaScript Implementation\n * Connects to MCP server and pipes input/output to WebSocket endpoint\n * d\n * Version: 0.2.0\n *\n * Usage:\n * export MCP_ENDPOINT=<mcp_endpoint>\n * node mcp_pipe.js <mcp_script>\n */\n\nimport WebSocket from 'ws';\nimport { spawn, ChildProcess } from 'child_process';\nimport { config } from 'dotenv';\nimport process from 'process';\nimport { configManager } from './configManager.js';\n\n// Load environment variables\nconfig();\n\n// Logger utility\nclass Logger {\n private name: string;\n\n constructor(name: string) {\n this.name = name;\n }\n\n info(message: string): void {\n const timestamp = new Date().toISOString();\n console.error(`${timestamp} - ${this.name} - INFO - ${message}`);\n }\n\n error(message: string): void {\n const timestamp = new Date().toISOString();\n console.error(`${timestamp} - ${this.name} - ERROR - ${message}`);\n }\n\n warning(message: string): void {\n const timestamp = new Date().toISOString();\n console.error(`${timestamp} - ${this.name} - WARNING - ${message}`);\n }\n\n debug(message: string): void {\n const timestamp = new Date().toISOString();\n console.error(`${timestamp} - ${this.name} - DEBUG - ${message}`);\n }\n}\n\nconst logger = new Logger('MCP_PIPE');\n\n// Reconnection settings\nconst INITIAL_BACKOFF = 1000; // Initial wait time in milliseconds\nconst MAX_BACKOFF = 30000; // Maximum wait time in milliseconds (reduced)\nlet reconnectAttempt = 0;\nlet backoff = INITIAL_BACKOFF;\n\nclass MCPPipe {\n private mcpScript: string;\n private endpointUrl: string;\n private process: ChildProcess | null;\n private websocket: WebSocket | null;\n private shouldReconnect: boolean;\n private isConnected: boolean;\n private shutdownResolve?: () => void;\n\n constructor(mcpScript: string, endpointUrl: string) {\n this.mcpScript = mcpScript;\n this.endpointUrl = endpointUrl;\n this.process = null;\n this.websocket = null;\n this.shouldReconnect = true;\n this.isConnected = false;\n }\n\n async start() {\n // Start MCP script process\n this.startMCPProcess();\n\n // Start WebSocket connection\n await this.connectToServer();\n\n // Keep the process running\n return new Promise<void>((resolve) => {\n // This promise will only resolve when shutdown is called\n this.shutdownResolve = resolve;\n });\n }\n\n async connectToServer() {\n if (this.isConnected) {\n return;\n }\n\n logger.info('Connecting to WebSocket server...');\n\n this.websocket = new WebSocket(this.endpointUrl);\n\n this.websocket.on('open', () => {\n logger.info('Successfully connected to WebSocket server');\n this.isConnected = true;\n\n // Reset reconnection counter\n reconnectAttempt = 0;\n backoff = INITIAL_BACKOFF;\n });\n\n this.websocket.on('message', (data: WebSocket.Data) => {\n const message = data.toString();\n logger.debug(`<< ${message.substring(0, 120)}...`);\n\n // Write to process stdin\n if (this.process && this.process.stdin && !this.process.stdin.destroyed) {\n this.process.stdin.write(message + '\\n');\n }\n });\n\n this.websocket.on('close', (code: number, reason: Buffer) => {\n logger.error(`WebSocket connection closed: ${code} ${reason}`);\n this.isConnected = false;\n this.websocket = null;\n\n // Only reconnect if we should and it's not a permanent error\n if (this.shouldReconnect && code !== 4004) {\n this.scheduleReconnect();\n }\n });\n\n this.websocket.on('error', (error: Error) => {\n logger.error(`WebSocket error: ${error.message}`);\n this.isConnected = false;\n });\n }\n\n scheduleReconnect() {\n if (!this.shouldReconnect) return;\n\n reconnectAttempt++;\n const waitTime = Math.min(backoff * Math.pow(2, reconnectAttempt - 1), MAX_BACKOFF);\n\n logger.info(`Scheduling reconnection attempt ${reconnectAttempt} in ${(waitTime / 1000).toFixed(2)} seconds...`);\n\n setTimeout(() => {\n if (this.shouldReconnect) {\n this.connectToServer();\n }\n }, waitTime);\n }\n\n startMCPProcess() {\n if (this.process) {\n logger.info(`${this.mcpScript} process already running`);\n return;\n }\n\n logger.info(`Starting ${this.mcpScript} process`);\n\n this.process = spawn('node', [this.mcpScript], {\n stdio: ['pipe', 'pipe', 'pipe']\n });\n\n // Handle process stdout - send to WebSocket\n this.process.stdout?.on('data', (data: Buffer) => {\n const message = data.toString();\n logger.debug(`>> ${message.substring(0, 120)}...`);\n\n if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {\n this.websocket.send(message);\n }\n });\n\n // Handle process stderr - print to terminal\n this.process.stderr?.on('data', (data: Buffer) => {\n process.stderr.write(data);\n });\n\n // Handle process exit\n this.process.on('exit', (code: number | null, signal: NodeJS.Signals | null) => {\n logger.info(`${this.mcpScript} process exited with code ${code}, signal ${signal}`);\n this.process = null;\n this.shouldReconnect = false;\n if (this.websocket) {\n this.websocket.close();\n }\n });\n\n // Handle process error\n this.process.on('error', (error: Error) => {\n logger.error(`Process error: ${error.message}`);\n this.process = null;\n this.shouldReconnect = false;\n if (this.websocket) {\n this.websocket.close();\n }\n });\n }\n\n cleanup() {\n if (this.process) {\n logger.info(`Terminating ${this.mcpScript} process`);\n try {\n this.process.kill('SIGTERM');\n\n // Force kill after timeout\n setTimeout(() => {\n if (this.process && !this.process.killed) {\n this.process.kill('SIGKILL');\n }\n }, 5000);\n } catch (error) {\n logger.error(`Error terminating process: ${error instanceof Error ? error.message : String(error)}`);\n }\n this.process = null;\n }\n\n if (this.websocket) {\n this.websocket = null;\n }\n\n this.isConnected = false;\n }\n\n sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n\n shutdown() {\n logger.info('Shutting down MCP Pipe...');\n this.shouldReconnect = false;\n this.cleanup();\n if (this.websocket) {\n this.websocket.close();\n }\n if (this.shutdownResolve) {\n this.shutdownResolve();\n }\n process.exit(0);\n }\n}\n\n// Signal handlers\nfunction setupSignalHandlers(mcpPipe: MCPPipe): void {\n process.on('SIGINT', () => {\n logger.info('Received interrupt signal, shutting down...');\n mcpPipe.shutdown();\n });\n\n process.on('SIGTERM', () => {\n logger.info('Received terminate signal, shutting down...');\n mcpPipe.shutdown();\n });\n}\n\n// Main execution\nasync function main() {\n // Check command line arguments\n if (process.argv.length < 3) {\n logger.error('Usage: node mcp_pipe.js <mcp_script>');\n process.exit(1);\n }\n\n const mcpScript = process.argv[2];\n\n // Get endpoint URL from config file or environment variable (fallback)\n let endpointUrl: string;\n\n try {\n // 调试信息 - 使用 process.stderr.write 确保能看到\n process.stderr.write(`[DEBUG] XIAOZHI_CONFIG_DIR: ${process.env.XIAOZHI_CONFIG_DIR}\\n`);\n process.stderr.write(`[DEBUG] process.cwd(): ${process.cwd()}\\n`);\n process.stderr.write(`[DEBUG] configManager.getConfigPath(): ${configManager.getConfigPath()}\\n`);\n process.stderr.write(`[DEBUG] configManager.configExists(): ${configManager.configExists()}\\n`);\n\n // 首先尝试从配置文件读取\n if (configManager.configExists()) {\n endpointUrl = configManager.getMcpEndpoint();\n logger.info('使用配置文件中的 MCP 端点');\n } else {\n // 如果配置文件不存在,尝试从环境变量读取(向后兼容)\n endpointUrl = process.env.MCP_ENDPOINT || '';\n if (!endpointUrl) {\n logger.error('配置文件不存在且未设置 MCP_ENDPOINT 环境变量');\n logger.error('请运行 \"xiaozhi init\" 初始化配置,或设置 MCP_ENDPOINT 环境变量');\n process.exit(1);\n }\n logger.info('使用环境变量中的 MCP 端点(建议使用配置文件)');\n }\n } catch (error) {\n logger.error(`读取配置失败: ${error instanceof Error ? error.message : String(error)}`);\n\n // 尝试从环境变量读取作为备用方案\n endpointUrl = process.env.MCP_ENDPOINT || '';\n if (!endpointUrl) {\n logger.error('请运行 \"xiaozhi init\" 初始化配置,或设置 MCP_ENDPOINT 环境变量');\n process.exit(1);\n }\n logger.info('使用环境变量中的 MCP 端点作为备用方案');\n }\n\n // 验证端点 URL\n if (!endpointUrl || endpointUrl.includes('<请填写')) {\n logger.error('MCP 端点未配置或配置无效');\n logger.error('请运行 \"xiaozhi config mcpEndpoint <your-endpoint-url>\" 设置端点');\n process.exit(1);\n }\n\n // Create MCP Pipe instance\n const mcpPipe = new MCPPipe(mcpScript, endpointUrl);\n\n // Setup signal handlers\n setupSignalHandlers(mcpPipe);\n\n // Start the MCP pipe\n try {\n await mcpPipe.start();\n } catch (error) {\n logger.error(`Program execution error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n}\n\n// Run if this file is executed directly\nif (require.main === module) {\n main().catch(error => {\n logger.error(`Unhandled error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n });\n}\n"],"mappings":"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","names":["WebSocket","process"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpEndpoint": "wss://api.xiaozhi.me/mcp/?token=eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjMwMjcyMCwiYWdlbnRJZCI6MzAwNzQ1LCJlbmRwb2ludElkIjoiYWdlbnRfMzAwNzQ1IiwicHVycG9zZSI6Im1jcC1lbmRwb2ludCIsImlhdCI6MTc0OTY5ODk5OX0.b-bwXaBG2ozprDruAFbTzZfm4rloGj75I9qHzmyodWTPgz0OHKXguCwIS62ukYLv0VqqhvsD85YZJqDV7r3Fug",
|
|
3
|
+
"mcpServers": {
|
|
4
|
+
"calculator": {
|
|
5
|
+
"command": "node",
|
|
6
|
+
"args": ["./mcpServers/calculator.js"]
|
|
7
|
+
},
|
|
8
|
+
"datetime": {
|
|
9
|
+
"command": "node",
|
|
10
|
+
"args": ["./mcpServers/datetime.js"]
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
package/package.json
CHANGED
package/dist/config.json
DELETED
|
File without changes
|