xiaozhi-client 0.0.1 → 1.0.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/README.md +54 -55
- package/dist/cli.cjs +5 -450
- package/dist/cli.cjs.map +1 -1
- package/dist/configManager.cjs +1 -233
- package/dist/configManager.cjs.map +1 -1
- package/dist/configManager.d.ts +33 -2
- package/dist/mcpCommands.cjs +2 -0
- package/dist/mcpCommands.cjs.map +1 -0
- package/dist/mcpCommands.d.ts +19 -0
- package/dist/mcpPipe.cjs +6 -262
- package/dist/mcpPipe.cjs.map +1 -1
- package/dist/mcpServerProxy.cjs +6 -491
- package/dist/mcpServerProxy.cjs.map +1 -1
- package/docs/CLI.md +189 -0
- package/docs/SettingManager.md +122 -0
- package/docs/images/preview.png +0 -0
- package/package.json +44 -22
- package/templates/hello-world/mcpServers/calculator.js +100 -0
- package/templates/hello-world/mcpServers/datetime.js +384 -0
- package/templates/hello-world/package.json +12 -0
- package/dist/mcpServers/calculator.js +0 -96
- package/dist/mcpServers/datetime.js +0 -354
- /package/dist/{config.default.json → xiaozhi.config.default.json} +0 -0
- /package/{dist/config.json → templates/hello-world/xiaozhi.config.json} +0 -0
package/README.md
CHANGED
|
@@ -1,68 +1,82 @@
|
|
|
1
1
|
# Xiaozhi Client
|
|
2
2
|
|
|
3
|
+
[](https://badge.fury.io/js/xiaozhi-client)
|
|
4
|
+
[](https://codecov.io/gh/shenjingnan/xiaozhi-client)
|
|
5
|
+
[](https://github.com/shenjingnan/xiaozhi-client/actions)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
3
8
|
小智 AI 客户端,目前主要用于 MCP 的对接
|
|
4
9
|
|
|
5
|
-

|
|
11
|
+
|
|
12
|
+
## 功能特性
|
|
6
13
|
|
|
7
|
-
|
|
14
|
+
- 支持 小智(xiaozhi.me) 官方服务器接入点
|
|
15
|
+
- 支持 自定义 MCP 服务
|
|
16
|
+
- 支持 使用标准 MCP 配置方式多个 MCP Server
|
|
17
|
+
- 支持 聚合多个 MCP Server
|
|
18
|
+
- 支持 动态控制 MCP Server 提供的工具
|
|
19
|
+
- 支持 通过模板创建
|
|
20
|
+
- 支持 后台运行
|
|
8
21
|
|
|
9
|
-
|
|
22
|
+
## 快速上手
|
|
10
23
|
|
|
11
|
-
|
|
24
|
+
### 全局安装 xiaozhi-client 命令行工具
|
|
12
25
|
|
|
13
26
|
```bash
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
```
|
|
27
|
+
## 安装
|
|
28
|
+
npm i -g xiaozhi-client
|
|
17
29
|
|
|
18
|
-
|
|
30
|
+
## 创建项目
|
|
31
|
+
xiaozhi create my-app --template hello-world
|
|
19
32
|
|
|
20
|
-
|
|
33
|
+
## 进入项目
|
|
34
|
+
cd my-app
|
|
35
|
+
|
|
36
|
+
## 安装依赖(主要是示例代码中mcp服务所使用的依赖)
|
|
21
37
|
pnpm install
|
|
22
|
-
```
|
|
23
38
|
|
|
24
|
-
|
|
39
|
+
# 修改 xiaozhi.config.json 中的 mcpEndpoint 为你的接入点地址(需要自行前往xiaozhi.me获取)
|
|
40
|
+
# 小智AI配置MCP接入点使用说明:https://ccnphfhqs21z.feishu.cn/wiki/HiPEwZ37XiitnwktX13cEM5KnSb
|
|
25
41
|
|
|
26
|
-
|
|
27
|
-
|
|
42
|
+
## 运行
|
|
43
|
+
xiaozhi start
|
|
28
44
|
```
|
|
29
45
|
|
|
30
|
-
|
|
46
|
+
### 通过 npx 直接运行
|
|
31
47
|
|
|
32
48
|
```bash
|
|
33
|
-
|
|
34
|
-
|
|
49
|
+
# 创建项目
|
|
50
|
+
npx -y xiaozhi-client create --template hello-world
|
|
35
51
|
|
|
36
|
-
|
|
52
|
+
# 进入项目目录
|
|
53
|
+
cd hello-world
|
|
37
54
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
项目使用 tsup 打包成单个可执行的 JavaScript 文件,所有依赖都被正确处理。
|
|
55
|
+
# 安装依赖
|
|
56
|
+
pnpm install
|
|
41
57
|
|
|
42
|
-
|
|
58
|
+
# 修改 xiaozhi.config.json 中的 mcpEndpoint 为你的接入点地址(需要自行前往xiaozhi.me获取)
|
|
59
|
+
# 小智AI配置MCP接入点使用说明:https://ccnphfhqs21z.feishu.cn/wiki/HiPEwZ37XiitnwktX13cEM5KnSb
|
|
43
60
|
|
|
44
|
-
|
|
45
|
-
-
|
|
46
|
-
|
|
61
|
+
# 启动服务
|
|
62
|
+
npx -y xiaozhi-client start
|
|
63
|
+
```
|
|
47
64
|
|
|
48
|
-
|
|
65
|
+
## 可用命令
|
|
49
66
|
|
|
50
67
|
```bash
|
|
51
68
|
# 查看帮助
|
|
52
69
|
xiaozhi --help
|
|
53
70
|
|
|
54
|
-
# 配置端点
|
|
55
|
-
xiaozhi set-config xiaozhi.endpoint=wss://your-endpoint
|
|
56
|
-
|
|
57
|
-
# 查看配置
|
|
58
|
-
xiaozhi get-config
|
|
59
|
-
|
|
60
71
|
# 启动服务
|
|
61
72
|
xiaozhi start
|
|
62
73
|
|
|
63
74
|
# 后台启动服务
|
|
64
75
|
xiaozhi start --daemon
|
|
65
76
|
|
|
77
|
+
# 将后台服务转到前台运行
|
|
78
|
+
xiaozhi attach
|
|
79
|
+
|
|
66
80
|
# 查看服务状态
|
|
67
81
|
xiaozhi status
|
|
68
82
|
|
|
@@ -71,31 +85,16 @@ xiaozhi stop
|
|
|
71
85
|
|
|
72
86
|
# 重启服务
|
|
73
87
|
xiaozhi restart
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## 开发
|
|
77
|
-
|
|
78
|
-
### 构建脚本
|
|
79
88
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
- `pnpm run clean` - 清理构建文件
|
|
83
|
-
- `pnpm run dev` - 开发模式(监听文件变化)
|
|
84
|
-
- `pnpm run type-check` - 仅进行类型检查
|
|
85
|
-
- `pnpm run start` - 编译并启动服务
|
|
89
|
+
# 列出所有使用的mcp服务
|
|
90
|
+
xiaozhi mcp list
|
|
86
91
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
- tsup (打包工具)
|
|
91
|
-
- Commander.js (CLI 框架)
|
|
92
|
-
- Chalk (终端颜色)
|
|
93
|
-
- Ora (加载动画)
|
|
92
|
+
# 列出所有mcp所提供的tools
|
|
93
|
+
xiaozhi mcp --tools
|
|
94
|
+
```
|
|
94
95
|
|
|
95
|
-
|
|
96
|
+
## 路线图
|
|
96
97
|
|
|
97
|
-
-
|
|
98
|
-
-
|
|
99
|
-
-
|
|
100
|
-
- 支持 ES 模块
|
|
101
|
-
- 生成 source maps 和类型定义文件
|
|
98
|
+
- 支持 通过 SSE 类型的 MCP Server
|
|
99
|
+
- 支持 直接使用 [modelscope](https://www.modelscope.cn/mcp) 中托管的 MCP 服务
|
|
100
|
+
- 支持 通过使用网页进行 MCP 配置
|
package/dist/cli.cjs
CHANGED
|
@@ -1,452 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
19
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
20
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
21
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
22
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
23
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
24
|
-
mod
|
|
25
|
-
));
|
|
26
|
-
var import_commander = require("commander");
|
|
27
|
-
var import_chalk = __toESM(require("chalk"));
|
|
28
|
-
var import_ora = __toESM(require("ora"));
|
|
29
|
-
var import_child_process = require("child_process");
|
|
30
|
-
var import_fs = __toESM(require("fs"));
|
|
31
|
-
var import_path = __toESM(require("path"));
|
|
32
|
-
var import_os = __toESM(require("os"));
|
|
33
|
-
var import_configManager = require("./configManager.cjs");
|
|
34
|
-
const program = new import_commander.Command();
|
|
35
|
-
const VERSION = "0.0.1";
|
|
36
|
-
const SERVICE_NAME = "xiaozhi-mcp-service";
|
|
37
|
-
const PID_FILE = import_path.default.join(import_os.default.tmpdir(), `${SERVICE_NAME}.pid`);
|
|
38
|
-
const LOG_FILE = import_path.default.join(import_os.default.tmpdir(), `${SERVICE_NAME}.log`);
|
|
39
|
-
function getServiceStatus() {
|
|
40
|
-
try {
|
|
41
|
-
if (!import_fs.default.existsSync(PID_FILE)) {
|
|
42
|
-
return { running: false };
|
|
43
|
-
}
|
|
44
|
-
const pidContent = import_fs.default.readFileSync(PID_FILE, "utf8").trim();
|
|
45
|
-
const [pidStr, startTime, mode] = pidContent.split("|");
|
|
46
|
-
const pid = parseInt(pidStr);
|
|
47
|
-
if (isNaN(pid)) {
|
|
48
|
-
import_fs.default.unlinkSync(PID_FILE);
|
|
49
|
-
return { running: false };
|
|
50
|
-
}
|
|
51
|
-
try {
|
|
52
|
-
process.kill(pid, 0);
|
|
53
|
-
const start = parseInt(startTime);
|
|
54
|
-
const uptime = formatUptime(Date.now() - start);
|
|
55
|
-
return {
|
|
56
|
-
running: true,
|
|
57
|
-
pid,
|
|
58
|
-
uptime,
|
|
59
|
-
mode: mode || "foreground"
|
|
60
|
-
};
|
|
61
|
-
} catch (error) {
|
|
62
|
-
import_fs.default.unlinkSync(PID_FILE);
|
|
63
|
-
return { running: false };
|
|
64
|
-
}
|
|
65
|
-
} catch (error) {
|
|
66
|
-
return { running: false };
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
__name(getServiceStatus, "getServiceStatus");
|
|
70
|
-
function formatUptime(ms) {
|
|
71
|
-
const seconds = Math.floor(ms / 1e3);
|
|
72
|
-
const minutes = Math.floor(seconds / 60);
|
|
73
|
-
const hours = Math.floor(minutes / 60);
|
|
74
|
-
const days = Math.floor(hours / 24);
|
|
75
|
-
if (days > 0) {
|
|
76
|
-
return `${days}\u5929 ${hours % 24}\u5C0F\u65F6 ${minutes % 60}\u5206\u949F`;
|
|
77
|
-
} else if (hours > 0) {
|
|
78
|
-
return `${hours}\u5C0F\u65F6 ${minutes % 60}\u5206\u949F`;
|
|
79
|
-
} else if (minutes > 0) {
|
|
80
|
-
return `${minutes}\u5206\u949F ${seconds % 60}\u79D2`;
|
|
81
|
-
} else {
|
|
82
|
-
return `${seconds}\u79D2`;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
__name(formatUptime, "formatUptime");
|
|
86
|
-
function savePidInfo(pid, mode) {
|
|
87
|
-
const pidInfo = `${pid}|${Date.now()}|${mode}`;
|
|
88
|
-
import_fs.default.writeFileSync(PID_FILE, pidInfo);
|
|
89
|
-
}
|
|
90
|
-
__name(savePidInfo, "savePidInfo");
|
|
91
|
-
function cleanupPidFile() {
|
|
92
|
-
try {
|
|
93
|
-
if (import_fs.default.existsSync(PID_FILE)) {
|
|
94
|
-
import_fs.default.unlinkSync(PID_FILE);
|
|
95
|
-
}
|
|
96
|
-
} catch (error) {
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
__name(cleanupPidFile, "cleanupPidFile");
|
|
100
|
-
function checkEnvironment() {
|
|
101
|
-
if (!import_configManager.configManager.configExists()) {
|
|
102
|
-
console.error(import_chalk.default.red("\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728"));
|
|
103
|
-
console.log(import_chalk.default.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E'));
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
try {
|
|
107
|
-
const endpoint = import_configManager.configManager.getMcpEndpoint();
|
|
108
|
-
if (!endpoint || endpoint.includes("<\u8BF7\u586B\u5199")) {
|
|
109
|
-
console.error(import_chalk.default.red("\u274C \u9519\u8BEF: MCP \u7AEF\u70B9\u672A\u914D\u7F6E"));
|
|
110
|
-
console.log(import_chalk.default.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi config mcpEndpoint <your-endpoint-url>" \u8BBE\u7F6E\u7AEF\u70B9'));
|
|
111
|
-
return false;
|
|
112
|
-
}
|
|
113
|
-
return true;
|
|
114
|
-
} catch (error) {
|
|
115
|
-
console.error(import_chalk.default.red(`\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u65E0\u6548 - ${error instanceof Error ? error.message : String(error)}`));
|
|
116
|
-
console.log(import_chalk.default.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u91CD\u65B0\u521D\u59CB\u5316\u914D\u7F6E'));
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
__name(checkEnvironment, "checkEnvironment");
|
|
121
|
-
function getServiceCommand() {
|
|
122
|
-
const scriptDir = __dirname;
|
|
123
|
-
let distDir;
|
|
124
|
-
if (scriptDir.includes("js-demo/dist")) {
|
|
125
|
-
distDir = scriptDir;
|
|
126
|
-
} else {
|
|
127
|
-
const possiblePaths = [
|
|
128
|
-
import_path.default.join(scriptDir, "..", "js-demo", "dist"),
|
|
129
|
-
import_path.default.join(scriptDir, "..", "..", "js-demo", "dist"),
|
|
130
|
-
import_path.default.join(scriptDir, "..", "..", "..", "js-demo", "dist"),
|
|
131
|
-
import_path.default.join(process.cwd(), "js-demo", "dist"),
|
|
132
|
-
import_path.default.join(process.cwd(), "dist")
|
|
133
|
-
];
|
|
134
|
-
distDir = possiblePaths.find(
|
|
135
|
-
(p) => import_fs.default.existsSync(import_path.default.join(p, "mcpPipe.cjs")) && import_fs.default.existsSync(import_path.default.join(p, "mcpServerProxy.cjs"))
|
|
136
|
-
) || scriptDir;
|
|
137
|
-
}
|
|
138
|
-
return {
|
|
139
|
-
command: "node",
|
|
140
|
-
args: ["mcpPipe.cjs", "mcpServerProxy.cjs"],
|
|
141
|
-
cwd: distDir
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
__name(getServiceCommand, "getServiceCommand");
|
|
145
|
-
async function startService(daemon = false) {
|
|
146
|
-
const spinner = (0, import_ora.default)("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();
|
|
147
|
-
try {
|
|
148
|
-
const status = getServiceStatus();
|
|
149
|
-
if (status.running) {
|
|
150
|
-
spinner.fail(`\u670D\u52A1\u5DF2\u7ECF\u5728\u8FD0\u884C (PID: ${status.pid})`);
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
spinner.text = "\u68C0\u67E5\u73AF\u5883\u914D\u7F6E...";
|
|
154
|
-
if (!checkEnvironment()) {
|
|
155
|
-
spinner.fail("\u73AF\u5883\u914D\u7F6E\u68C0\u67E5\u5931\u8D25");
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
const { command, args, cwd } = getServiceCommand();
|
|
159
|
-
spinner.text = `\u542F\u52A8\u670D\u52A1 (${daemon ? "\u540E\u53F0\u6A21\u5F0F" : "\u524D\u53F0\u6A21\u5F0F"})...`;
|
|
160
|
-
if (daemon) {
|
|
161
|
-
const child = (0, import_child_process.spawn)(command, args, {
|
|
162
|
-
cwd,
|
|
163
|
-
detached: true,
|
|
164
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
165
|
-
env: { ...process.env }
|
|
166
|
-
});
|
|
167
|
-
savePidInfo(child.pid, "daemon");
|
|
168
|
-
const logStream = import_fs.default.createWriteStream(LOG_FILE, { flags: "a" });
|
|
169
|
-
child.stdout?.pipe(logStream);
|
|
170
|
-
child.stderr?.pipe(logStream);
|
|
171
|
-
child.unref();
|
|
172
|
-
spinner.succeed(`\u670D\u52A1\u5DF2\u5728\u540E\u53F0\u542F\u52A8 (PID: ${child.pid})`);
|
|
173
|
-
console.log(import_chalk.default.gray(`\u65E5\u5FD7\u6587\u4EF6: ${LOG_FILE}`));
|
|
174
|
-
console.log(import_chalk.default.gray(`\u4F7F\u7528 'xiaozhi attach' \u53EF\u4EE5\u67E5\u770B\u5B9E\u65F6\u65E5\u5FD7`));
|
|
175
|
-
} else {
|
|
176
|
-
spinner.succeed("\u670D\u52A1\u542F\u52A8\u4E2D...");
|
|
177
|
-
const child = (0, import_child_process.spawn)(command, args, {
|
|
178
|
-
cwd,
|
|
179
|
-
stdio: "inherit",
|
|
180
|
-
env: { ...process.env }
|
|
181
|
-
});
|
|
182
|
-
savePidInfo(child.pid, "foreground");
|
|
183
|
-
child.on("exit", (code, signal) => {
|
|
184
|
-
cleanupPidFile();
|
|
185
|
-
if (code !== 0) {
|
|
186
|
-
console.log(import_chalk.default.red(`
|
|
187
|
-
\u670D\u52A1\u5F02\u5E38\u9000\u51FA (\u4EE3\u7801: ${code}, \u4FE1\u53F7: ${signal})`));
|
|
188
|
-
} else {
|
|
189
|
-
console.log(import_chalk.default.green("\n\u670D\u52A1\u5DF2\u505C\u6B62"));
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
process.on("SIGINT", () => {
|
|
193
|
-
console.log(import_chalk.default.yellow("\n\u6B63\u5728\u505C\u6B62\u670D\u52A1..."));
|
|
194
|
-
child.kill("SIGTERM");
|
|
195
|
-
});
|
|
196
|
-
process.on("SIGTERM", () => {
|
|
197
|
-
child.kill("SIGTERM");
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
} catch (error) {
|
|
201
|
-
spinner.fail(`\u542F\u52A8\u670D\u52A1\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
__name(startService, "startService");
|
|
205
|
-
async function stopService() {
|
|
206
|
-
const spinner = (0, import_ora.default)("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();
|
|
207
|
-
try {
|
|
208
|
-
const status = getServiceStatus();
|
|
209
|
-
if (!status.running) {
|
|
210
|
-
spinner.warn("\u670D\u52A1\u672A\u5728\u8FD0\u884C");
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
spinner.text = `\u505C\u6B62\u670D\u52A1 (PID: ${status.pid})...`;
|
|
214
|
-
try {
|
|
215
|
-
process.kill(status.pid, "SIGTERM");
|
|
216
|
-
let attempts = 0;
|
|
217
|
-
const maxAttempts = 30;
|
|
218
|
-
while (attempts < maxAttempts) {
|
|
219
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
220
|
-
try {
|
|
221
|
-
process.kill(status.pid, 0);
|
|
222
|
-
attempts++;
|
|
223
|
-
} catch {
|
|
224
|
-
break;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
try {
|
|
228
|
-
process.kill(status.pid, 0);
|
|
229
|
-
spinner.text = "\u5F3A\u5236\u505C\u6B62\u670D\u52A1...";
|
|
230
|
-
process.kill(status.pid, "SIGKILL");
|
|
231
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
232
|
-
} catch {
|
|
233
|
-
}
|
|
234
|
-
cleanupPidFile();
|
|
235
|
-
spinner.succeed("\u670D\u52A1\u5DF2\u505C\u6B62");
|
|
236
|
-
} catch (error) {
|
|
237
|
-
cleanupPidFile();
|
|
238
|
-
spinner.fail(`\u505C\u6B62\u670D\u52A1\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
239
|
-
}
|
|
240
|
-
} catch (error) {
|
|
241
|
-
spinner.fail(`\u505C\u6B62\u670D\u52A1\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
__name(stopService, "stopService");
|
|
245
|
-
async function checkStatus() {
|
|
246
|
-
const spinner = (0, import_ora.default)("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();
|
|
247
|
-
try {
|
|
248
|
-
const status = getServiceStatus();
|
|
249
|
-
if (status.running) {
|
|
250
|
-
spinner.succeed("\u670D\u52A1\u72B6\u6001");
|
|
251
|
-
console.log(import_chalk.default.green("\u2705 \u670D\u52A1\u6B63\u5728\u8FD0\u884C"));
|
|
252
|
-
console.log(import_chalk.default.gray(` PID: ${status.pid}`));
|
|
253
|
-
console.log(import_chalk.default.gray(` \u8FD0\u884C\u65F6\u95F4: ${status.uptime}`));
|
|
254
|
-
console.log(import_chalk.default.gray(` \u8FD0\u884C\u6A21\u5F0F: ${status.mode === "daemon" ? "\u540E\u53F0\u6A21\u5F0F" : "\u524D\u53F0\u6A21\u5F0F"}`));
|
|
255
|
-
if (status.mode === "daemon") {
|
|
256
|
-
console.log(import_chalk.default.gray(` \u65E5\u5FD7\u6587\u4EF6: ${LOG_FILE}`));
|
|
257
|
-
}
|
|
258
|
-
} else {
|
|
259
|
-
spinner.succeed("\u670D\u52A1\u72B6\u6001");
|
|
260
|
-
console.log(import_chalk.default.red("\u274C \u670D\u52A1\u672A\u8FD0\u884C"));
|
|
261
|
-
}
|
|
262
|
-
} catch (error) {
|
|
263
|
-
spinner.fail(`\u68C0\u67E5\u72B6\u6001\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
__name(checkStatus, "checkStatus");
|
|
267
|
-
async function attachService() {
|
|
268
|
-
const spinner = (0, import_ora.default)("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();
|
|
269
|
-
try {
|
|
270
|
-
const status = getServiceStatus();
|
|
271
|
-
if (!status.running) {
|
|
272
|
-
spinner.fail("\u670D\u52A1\u672A\u5728\u8FD0\u884C");
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
if (status.mode !== "daemon") {
|
|
276
|
-
spinner.fail("\u670D\u52A1\u4E0D\u662F\u5728\u540E\u53F0\u6A21\u5F0F\u8FD0\u884C");
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
spinner.succeed("\u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1...");
|
|
280
|
-
console.log(import_chalk.default.green(`\u5DF2\u8FDE\u63A5\u5230\u670D\u52A1 (PID: ${status.pid})`));
|
|
281
|
-
console.log(import_chalk.default.gray("\u6309 Ctrl+C \u53EF\u4EE5\u65AD\u5F00\u8FDE\u63A5\uFF08\u4E0D\u4F1A\u505C\u6B62\u670D\u52A1\uFF09"));
|
|
282
|
-
console.log(import_chalk.default.gray("=".repeat(50)));
|
|
283
|
-
if (import_fs.default.existsSync(LOG_FILE)) {
|
|
284
|
-
const { spawn: spawn2 } = await import("child_process");
|
|
285
|
-
const tail = spawn2("tail", ["-f", LOG_FILE], { stdio: "inherit" });
|
|
286
|
-
process.on("SIGINT", () => {
|
|
287
|
-
console.log(import_chalk.default.yellow("\n\u65AD\u5F00\u8FDE\u63A5\uFF0C\u670D\u52A1\u7EE7\u7EED\u5728\u540E\u53F0\u8FD0\u884C"));
|
|
288
|
-
tail.kill();
|
|
289
|
-
process.exit(0);
|
|
290
|
-
});
|
|
291
|
-
tail.on("exit", () => {
|
|
292
|
-
process.exit(0);
|
|
293
|
-
});
|
|
294
|
-
} else {
|
|
295
|
-
console.log(import_chalk.default.yellow("\u65E5\u5FD7\u6587\u4EF6\u4E0D\u5B58\u5728"));
|
|
296
|
-
}
|
|
297
|
-
} catch (error) {
|
|
298
|
-
spinner.fail(`\u8FDE\u63A5\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
__name(attachService, "attachService");
|
|
302
|
-
async function restartService(daemon = false) {
|
|
303
|
-
console.log(import_chalk.default.blue("\u{1F504} \u91CD\u542F\u670D\u52A1..."));
|
|
304
|
-
await stopService();
|
|
305
|
-
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
306
|
-
await startService(daemon);
|
|
307
|
-
}
|
|
308
|
-
__name(restartService, "restartService");
|
|
309
|
-
function showVersion() {
|
|
310
|
-
console.log(import_chalk.default.blue(`xiaozhi v${VERSION}`));
|
|
311
|
-
}
|
|
312
|
-
__name(showVersion, "showVersion");
|
|
313
|
-
function showDetailedInfo() {
|
|
314
|
-
console.log(import_chalk.default.blue(`xiaozhi v${VERSION}`));
|
|
315
|
-
console.log(import_chalk.default.gray("MCP Calculator Service CLI Tool"));
|
|
316
|
-
console.log(import_chalk.default.gray("Built with Node.js and TypeScript"));
|
|
317
|
-
console.log(import_chalk.default.gray(`Node.js: ${process.version}`));
|
|
318
|
-
console.log(import_chalk.default.gray(`Platform: ${process.platform} ${process.arch}`));
|
|
319
|
-
}
|
|
320
|
-
__name(showDetailedInfo, "showDetailedInfo");
|
|
321
|
-
async function initConfig() {
|
|
322
|
-
const spinner = (0, import_ora.default)("\u521D\u59CB\u5316\u914D\u7F6E...").start();
|
|
323
|
-
try {
|
|
324
|
-
if (import_configManager.configManager.configExists()) {
|
|
325
|
-
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"));
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
import_configManager.configManager.initConfig();
|
|
330
|
-
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"));
|
|
332
|
-
console.log(import_chalk.default.yellow("\u{1F4DD} \u8BF7\u7F16\u8F91\u914D\u7F6E\u6587\u4EF6\u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9:"));
|
|
333
|
-
console.log(import_chalk.default.gray(` \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84: ${import_configManager.configManager.getConfigPath()}`));
|
|
334
|
-
console.log(import_chalk.default.yellow("\u{1F4A1} \u6216\u8005\u4F7F\u7528\u547D\u4EE4\u8BBE\u7F6E:"));
|
|
335
|
-
console.log(import_chalk.default.gray(" xiaozhi config mcpEndpoint <your-endpoint-url>"));
|
|
336
|
-
} catch (error) {
|
|
337
|
-
spinner.fail(`\u521D\u59CB\u5316\u914D\u7F6E\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
__name(initConfig, "initConfig");
|
|
341
|
-
async function configCommand(key, value) {
|
|
342
|
-
const spinner = (0, import_ora.default)("\u66F4\u65B0\u914D\u7F6E...").start();
|
|
343
|
-
try {
|
|
344
|
-
if (!import_configManager.configManager.configExists()) {
|
|
345
|
-
spinner.fail("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728");
|
|
346
|
-
console.log(import_chalk.default.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E'));
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
|
-
if (!value) {
|
|
350
|
-
spinner.text = "\u8BFB\u53D6\u914D\u7F6E...";
|
|
351
|
-
const config = import_configManager.configManager.getConfig();
|
|
352
|
-
switch (key) {
|
|
353
|
-
case "mcpEndpoint":
|
|
354
|
-
spinner.succeed("\u914D\u7F6E\u4FE1\u606F");
|
|
355
|
-
console.log(import_chalk.default.green(`MCP \u7AEF\u70B9: ${config.mcpEndpoint}`));
|
|
356
|
-
break;
|
|
357
|
-
case "mcpServers":
|
|
358
|
-
spinner.succeed("\u914D\u7F6E\u4FE1\u606F");
|
|
359
|
-
console.log(import_chalk.default.green("MCP \u670D\u52A1:"));
|
|
360
|
-
for (const [name, serverConfig] of Object.entries(config.mcpServers)) {
|
|
361
|
-
console.log(import_chalk.default.gray(` ${name}: ${serverConfig.command} ${serverConfig.args.join(" ")}`));
|
|
362
|
-
}
|
|
363
|
-
break;
|
|
364
|
-
default:
|
|
365
|
-
spinner.fail(`\u672A\u77E5\u7684\u914D\u7F6E\u9879: ${key}`);
|
|
366
|
-
console.log(import_chalk.default.yellow("\u652F\u6301\u7684\u914D\u7F6E\u9879: mcpEndpoint, mcpServers"));
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
} else {
|
|
370
|
-
switch (key) {
|
|
371
|
-
case "mcpEndpoint":
|
|
372
|
-
import_configManager.configManager.updateMcpEndpoint(value);
|
|
373
|
-
spinner.succeed(`MCP \u7AEF\u70B9\u5DF2\u66F4\u65B0\u4E3A: ${value}`);
|
|
374
|
-
break;
|
|
375
|
-
default:
|
|
376
|
-
spinner.fail(`\u914D\u7F6E\u9879 ${key} \u4E0D\u652F\u6301\u901A\u8FC7\u547D\u4EE4\u884C\u8BBE\u7F6E`);
|
|
377
|
-
console.log(import_chalk.default.yellow("\u652F\u6301\u8BBE\u7F6E\u7684\u914D\u7F6E\u9879: mcpEndpoint"));
|
|
378
|
-
return;
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
} catch (error) {
|
|
382
|
-
spinner.fail(`\u914D\u7F6E\u64CD\u4F5C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
__name(configCommand, "configCommand");
|
|
386
|
-
function showHelp() {
|
|
387
|
-
console.log(import_chalk.default.blue.bold("xiaozhi - MCP Calculator Service CLI"));
|
|
388
|
-
console.log();
|
|
389
|
-
console.log(import_chalk.default.yellow("\u4F7F\u7528\u65B9\u6CD5:"));
|
|
390
|
-
console.log(" xiaozhi <command> [options]");
|
|
391
|
-
console.log();
|
|
392
|
-
console.log(import_chalk.default.yellow("\u547D\u4EE4:"));
|
|
393
|
-
console.log(" init \u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6");
|
|
394
|
-
console.log(" config <key> [value] \u67E5\u770B\u6216\u8BBE\u7F6E\u914D\u7F6E");
|
|
395
|
-
console.log(" start [--daemon] \u542F\u52A8\u670D\u52A1 (--daemon \u540E\u53F0\u8FD0\u884C)");
|
|
396
|
-
console.log(" stop \u505C\u6B62\u670D\u52A1");
|
|
397
|
-
console.log(" status \u68C0\u67E5\u670D\u52A1\u72B6\u6001");
|
|
398
|
-
console.log(" attach \u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1\u67E5\u770B\u65E5\u5FD7");
|
|
399
|
-
console.log(" restart [--daemon] \u91CD\u542F\u670D\u52A1 (--daemon \u540E\u53F0\u8FD0\u884C)");
|
|
400
|
-
console.log();
|
|
401
|
-
console.log(import_chalk.default.yellow("\u9009\u9879:"));
|
|
402
|
-
console.log(" -v, --version \u663E\u793A\u7248\u672C\u4FE1\u606F");
|
|
403
|
-
console.log(" -V \u663E\u793A\u8BE6\u7EC6\u4FE1\u606F");
|
|
404
|
-
console.log(" -h, --help \u663E\u793A\u5E2E\u52A9\u4FE1\u606F");
|
|
405
|
-
console.log();
|
|
406
|
-
console.log(import_chalk.default.yellow("\u914D\u7F6E\u793A\u4F8B:"));
|
|
407
|
-
console.log(" xiaozhi init # \u521D\u59CB\u5316\u914D\u7F6E");
|
|
408
|
-
console.log(" xiaozhi config mcpEndpoint # \u67E5\u770B MCP \u7AEF\u70B9");
|
|
409
|
-
console.log(" xiaozhi config mcpEndpoint wss://... # \u8BBE\u7F6E MCP \u7AEF\u70B9");
|
|
410
|
-
console.log();
|
|
411
|
-
console.log(import_chalk.default.yellow("\u670D\u52A1\u793A\u4F8B:"));
|
|
412
|
-
console.log(" xiaozhi start # \u524D\u53F0\u542F\u52A8\u670D\u52A1");
|
|
413
|
-
console.log(" xiaozhi start --daemon # \u540E\u53F0\u542F\u52A8\u670D\u52A1");
|
|
414
|
-
console.log(" xiaozhi status # \u68C0\u67E5\u670D\u52A1\u72B6\u6001");
|
|
415
|
-
console.log(" xiaozhi attach # \u67E5\u770B\u540E\u53F0\u670D\u52A1\u65E5\u5FD7");
|
|
416
|
-
console.log(" xiaozhi stop # \u505C\u6B62\u670D\u52A1");
|
|
417
|
-
}
|
|
418
|
-
__name(showHelp, "showHelp");
|
|
419
|
-
program.name("xiaozhi").description("MCP Calculator Service CLI Tool").version(VERSION, "-v, --version", "\u663E\u793A\u7248\u672C\u4FE1\u606F").helpOption("-h, --help", "\u663E\u793A\u5E2E\u52A9\u4FE1\u606F");
|
|
420
|
-
program.command("init").description("\u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6").action(async () => {
|
|
421
|
-
await initConfig();
|
|
422
|
-
});
|
|
423
|
-
program.command("config <key> [value]").description("\u67E5\u770B\u6216\u8BBE\u7F6E\u914D\u7F6E").action(async (key, value) => {
|
|
424
|
-
await configCommand(key, value);
|
|
425
|
-
});
|
|
426
|
-
program.command("start").description("\u542F\u52A8\u670D\u52A1").option("-d, --daemon", "\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").action(async (options) => {
|
|
427
|
-
await startService(options.daemon);
|
|
428
|
-
});
|
|
429
|
-
program.command("stop").description("\u505C\u6B62\u670D\u52A1").action(async () => {
|
|
430
|
-
await stopService();
|
|
431
|
-
});
|
|
432
|
-
program.command("status").description("\u68C0\u67E5\u670D\u52A1\u72B6\u6001").action(async () => {
|
|
433
|
-
await checkStatus();
|
|
434
|
-
});
|
|
435
|
-
program.command("attach").description("\u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1\u67E5\u770B\u65E5\u5FD7").action(async () => {
|
|
436
|
-
await attachService();
|
|
437
|
-
});
|
|
438
|
-
program.command("restart").description("\u91CD\u542F\u670D\u52A1").option("-d, --daemon", "\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").action(async (options) => {
|
|
439
|
-
await restartService(options.daemon);
|
|
440
|
-
});
|
|
441
|
-
program.option("-V", "\u663E\u793A\u8BE6\u7EC6\u4FE1\u606F").action((options) => {
|
|
442
|
-
if (options.V) {
|
|
443
|
-
showDetailedInfo();
|
|
444
|
-
process.exit(0);
|
|
445
|
-
}
|
|
446
|
-
});
|
|
447
|
-
if (process.argv.length <= 2) {
|
|
448
|
-
showHelp();
|
|
449
|
-
process.exit(0);
|
|
450
|
-
}
|
|
451
|
-
program.parse(process.argv);
|
|
2
|
+
"use strict";var G=Object.create;var v=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var R=Object.getPrototypeOf,A=Object.prototype.hasOwnProperty;var l=(o,e)=>v(o,"name",{value:e,configurable:!0});var V=(o,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of O(e))!A.call(o,s)&&s!==n&&v(o,s,{get:()=>e[s],enumerable:!(i=F(e,s))||i.enumerable});return o};var u=(o,e,n)=>(n=o!=null?G(R(o)):{},V(e||!o||!o.__esModule?v(n,"default",{value:o,enumerable:!0}):n,o));var b=require("node:child_process"),a=u(require("node:fs")),I=u(require("node:os")),g=u(require("node:path")),t=u(require("chalk")),N=require("commander"),f=u(require("ora")),d=require("./configManager.cjs"),h=require("./mcpCommands.cjs");const p=new N.Command,z="0.0.1",E="xiaozhi-mcp-service",y=g.default.join(I.default.tmpdir(),`${E}.pid`),x=g.default.join(I.default.tmpdir(),`${E}.log`);function $(){try{if(!a.default.existsSync(y))return{running:!1};const o=a.default.readFileSync(y,"utf8").trim(),[e,n,i]=o.split("|"),s=Number.parseInt(e);if(Number.isNaN(s))return a.default.unlinkSync(y),{running:!1};try{process.kill(s,0);const c=Number.parseInt(n),r=H(Date.now()-c);return{running:!0,pid:s,uptime:r,mode:i||"foreground"}}catch{return a.default.unlinkSync(y),{running:!1}}}catch{return{running:!1}}}l($,"getServiceStatus");function H(o){const e=Math.floor(o/1e3),n=Math.floor(e/60),i=Math.floor(n/60),s=Math.floor(i/24);return s>0?`${s}\u5929 ${i%24}\u5C0F\u65F6 ${n%60}\u5206\u949F`:i>0?`${i}\u5C0F\u65F6 ${n%60}\u5206\u949F`:n>0?`${n}\u5206\u949F ${e%60}\u79D2`:`${e}\u79D2`}l(H,"formatUptime");function M(o,e){const n=`${o}|${Date.now()}|${e}`;a.default.writeFileSync(y,n)}l(M,"savePidInfo");function P(){try{a.default.existsSync(y)&&a.default.unlinkSync(y)}catch{}}l(P,"cleanupPidFile");function B(){if(!d.configManager.configExists())return console.error(t.default.red("\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728")),console.log(t.default.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E')),!1;try{const o=d.configManager.getMcpEndpoint();return!o||o.includes("<\u8BF7\u586B\u5199")?(console.error(t.default.red("\u274C \u9519\u8BEF: MCP \u7AEF\u70B9\u672A\u914D\u7F6E")),console.log(t.default.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi config mcpEndpoint <your-endpoint-url>" \u8BBE\u7F6E\u7AEF\u70B9')),!1):!0}catch(o){return console.error(t.default.red(`\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u65E0\u6548 - ${o instanceof Error?o.message:String(o)}`)),console.log(t.default.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u91CD\u65B0\u521D\u59CB\u5316\u914D\u7F6E')),!1}}l(B,"checkEnvironment");function U(){const o=__dirname;let e;return o.includes("js-demo/dist")?e=o:e=[g.default.join(o,"..","js-demo","dist"),g.default.join(o,"..","..","js-demo","dist"),g.default.join(o,"..","..","..","js-demo","dist"),g.default.join(process.cwd(),"js-demo","dist"),g.default.join(process.cwd(),"dist")].find(i=>a.default.existsSync(g.default.join(i,"mcpPipe.cjs"))&&a.default.existsSync(g.default.join(i,"mcpServerProxy.cjs")))||o,{command:"node",args:["mcpPipe.cjs","mcpServerProxy.cjs"],cwd:e}}l(U,"getServiceCommand");async function T(o=!1){const e=(0,f.default)("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{const n=$();if(n.running){e.fail(`\u670D\u52A1\u5DF2\u7ECF\u5728\u8FD0\u884C (PID: ${n.pid})`);return}if(e.text="\u68C0\u67E5\u73AF\u5883\u914D\u7F6E...",!B()){e.fail("\u73AF\u5883\u914D\u7F6E\u68C0\u67E5\u5931\u8D25");return}const{command:i,args:s,cwd:c}=U();if(e.text=`\u542F\u52A8\u670D\u52A1 (${o?"\u540E\u53F0\u6A21\u5F0F":"\u524D\u53F0\u6A21\u5F0F"})...`,o){const r=(0,b.spawn)(i,s,{cwd:c,detached:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd()}});M(r.pid,"daemon");const m=a.default.createWriteStream(x,{flags:"a"});r.stdout?.pipe(m),r.stderr?.pipe(m),r.unref(),e.succeed(`\u670D\u52A1\u5DF2\u5728\u540E\u53F0\u542F\u52A8 (PID: ${r.pid})`),console.log(t.default.gray(`\u65E5\u5FD7\u6587\u4EF6: ${x}`)),console.log(t.default.gray("\u4F7F\u7528 'xiaozhi attach' \u53EF\u4EE5\u67E5\u770B\u5B9E\u65F6\u65E5\u5FD7"))}else{e.succeed("\u670D\u52A1\u542F\u52A8\u4E2D...");const r=(0,b.spawn)(i,s,{cwd:c,stdio:"inherit",env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd()}});M(r.pid,"foreground"),r.on("exit",(m,w)=>{P(),console.log(m!==0?t.default.red(`
|
|
3
|
+
\u670D\u52A1\u5F02\u5E38\u9000\u51FA (\u4EE3\u7801: ${m}, \u4FE1\u53F7: ${w})`):t.default.green(`
|
|
4
|
+
\u670D\u52A1\u5DF2\u505C\u6B62`))}),process.on("SIGINT",()=>{console.log(t.default.yellow(`
|
|
5
|
+
\u6B63\u5728\u505C\u6B62\u670D\u52A1...`)),r.kill("SIGTERM")}),process.on("SIGTERM",()=>{r.kill("SIGTERM")})}}catch(n){e.fail(`\u542F\u52A8\u670D\u52A1\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`)}}l(T,"startService");async function k(){const o=(0,f.default)("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{const e=$();if(!e.running){o.warn("\u670D\u52A1\u672A\u5728\u8FD0\u884C");return}o.text=`\u505C\u6B62\u670D\u52A1 (PID: ${e.pid})...`;try{process.kill(e.pid,"SIGTERM");let n=0;const i=30;for(;n<i;){await new Promise(s=>setTimeout(s,100));try{process.kill(e.pid,0),n++}catch{break}}try{process.kill(e.pid,0),o.text="\u5F3A\u5236\u505C\u6B62\u670D\u52A1...",process.kill(e.pid,"SIGKILL"),await new Promise(s=>setTimeout(s,500))}catch{}P(),o.succeed("\u670D\u52A1\u5DF2\u505C\u6B62")}catch(n){P(),o.fail(`\u505C\u6B62\u670D\u52A1\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`)}}catch(e){o.fail(`\u505C\u6B62\u670D\u52A1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}l(k,"stopService");async function X(){const o=(0,f.default)("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{const e=$();e.running?(o.succeed("\u670D\u52A1\u72B6\u6001"),console.log(t.default.green("\u2705 \u670D\u52A1\u6B63\u5728\u8FD0\u884C")),console.log(t.default.gray(` PID: ${e.pid}`)),console.log(t.default.gray(` \u8FD0\u884C\u65F6\u95F4: ${e.uptime}`)),console.log(t.default.gray(` \u8FD0\u884C\u6A21\u5F0F: ${e.mode==="daemon"?"\u540E\u53F0\u6A21\u5F0F":"\u524D\u53F0\u6A21\u5F0F"}`)),e.mode==="daemon"&&console.log(t.default.gray(` \u65E5\u5FD7\u6587\u4EF6: ${x}`))):(o.succeed("\u670D\u52A1\u72B6\u6001"),console.log(t.default.red("\u274C \u670D\u52A1\u672A\u8FD0\u884C")))}catch(e){o.fail(`\u68C0\u67E5\u72B6\u6001\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}l(X,"checkStatus");async function Z(){const o=(0,f.default)("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{const e=$();if(!e.running){o.fail("\u670D\u52A1\u672A\u5728\u8FD0\u884C");return}if(e.mode!=="daemon"){o.fail("\u670D\u52A1\u4E0D\u662F\u5728\u540E\u53F0\u6A21\u5F0F\u8FD0\u884C");return}if(o.succeed("\u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1..."),console.log(t.default.green(`\u5DF2\u8FDE\u63A5\u5230\u670D\u52A1 (PID: ${e.pid})`)),console.log(t.default.gray("\u6309 Ctrl+C \u53EF\u4EE5\u65AD\u5F00\u8FDE\u63A5\uFF08\u4E0D\u4F1A\u505C\u6B62\u670D\u52A1\uFF09")),console.log(t.default.gray("=".repeat(50))),a.default.existsSync(x)){const{spawn:n}=await import("node:child_process"),i=n("tail",["-f",x],{stdio:"inherit"});process.on("SIGINT",()=>{console.log(t.default.yellow(`
|
|
6
|
+
\u65AD\u5F00\u8FDE\u63A5\uFF0C\u670D\u52A1\u7EE7\u7EED\u5728\u540E\u53F0\u8FD0\u884C`)),i.kill(),process.exit(0)}),i.on("exit",()=>{process.exit(0)})}else console.log(t.default.yellow("\u65E5\u5FD7\u6587\u4EF6\u4E0D\u5B58\u5728"))}catch(e){o.fail(`\u8FDE\u63A5\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}l(Z,"attachService");async function J(o=!1){console.log(t.default.blue("\u{1F504} \u91CD\u542F\u670D\u52A1...")),await k(),await new Promise(e=>setTimeout(e,1e3)),await T(o)}l(J,"restartService");function K(){console.log(t.default.blue(`xiaozhi v${z}`)),console.log(t.default.gray("MCP Calculator Service CLI Tool")),console.log(t.default.gray("Built with Node.js and TypeScript")),console.log(t.default.gray(`Node.js: ${process.version}`)),console.log(t.default.gray(`Platform: ${process.platform} ${process.arch}`))}l(K,"showDetailedInfo");async function W(){const o=(0,f.default)("\u521D\u59CB\u5316\u914D\u7F6E...").start();try{if(d.configManager.configExists()){o.warn("\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728"),console.log(t.default.yellow("\u5982\u9700\u91CD\u65B0\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u5220\u9664\u73B0\u6709\u7684 xiaozhi.config.json \u6587\u4EF6"));return}d.configManager.initConfig(),o.succeed("\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u6210\u529F"),console.log(t.default.green("\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u521B\u5EFA: xiaozhi.config.json")),console.log(t.default.yellow("\u{1F4DD} \u8BF7\u7F16\u8F91\u914D\u7F6E\u6587\u4EF6\u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9:")),console.log(t.default.gray(` \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84: ${d.configManager.getConfigPath()}`)),console.log(t.default.yellow("\u{1F4A1} \u6216\u8005\u4F7F\u7528\u547D\u4EE4\u8BBE\u7F6E:")),console.log(t.default.gray(" xiaozhi config mcpEndpoint <your-endpoint-url>"))}catch(e){o.fail(`\u521D\u59CB\u5316\u914D\u7F6E\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}l(W,"initConfig");function Y(){const o=__dirname,n=[g.default.join(o,"..","templates"),g.default.join(o,"templates"),g.default.join(o,"..","..","templates")].find(i=>a.default.existsSync(i));return n?a.default.readdirSync(n).filter(i=>{const s=g.default.join(n,i);return a.default.statSync(s).isDirectory()}):[]}l(Y,"getAvailableTemplates");function D(o,e){const n=o.length,i=e.length,s=Array(n+1).fill(null).map(()=>Array(i+1).fill(0));for(let r=0;r<=n;r++)s[r][0]=r;for(let r=0;r<=i;r++)s[0][r]=r;for(let r=1;r<=n;r++)for(let m=1;m<=i;m++)o[r-1]===e[m-1]?s[r][m]=s[r-1][m-1]:s[r][m]=Math.min(s[r-1][m]+1,s[r][m-1]+1,s[r-1][m-1]+1);const c=Math.max(n,i);return c===0?1:(c-s[n][i])/c}l(D,"calculateSimilarity");function q(o,e){if(e.length===0)return null;let n=e[0],i=D(o.toLowerCase(),n.toLowerCase());for(const s of e.slice(1)){const c=D(o.toLowerCase(),s.toLowerCase());c>i&&(i=c,n=s)}return i>.5?n:null}l(q,"findSimilarTemplate");async function Q(o){if(!process.stdin.isTTY)return console.log("n (\u975E\u4EA4\u4E92\u5F0F\u73AF\u5883)"),!1;const e=await import("node:readline");return new Promise(n=>{process.stdout.write(o);const i=e.createInterface({input:process.stdin,output:process.stdout}),s=l(c=>{const r=c.trim().toLowerCase();r==="y"||r==="yes"?(i.close(),n(!0)):r==="n"||r==="no"||r===""?(i.close(),n(!1)):process.stdout.write("\u8BF7\u8F93\u5165 y \u6216 n: ")},"handleInput");i.on("line",s),i.on("SIGINT",()=>{i.close(),n(!1)})})}l(Q,"askUserConfirmation");function oo(o){const e={mcpEndpoint:"<\u8BF7\u586B\u5199\u4F60\u7684\u63A5\u5165\u70B9\u5730\u5740\uFF08\u83B7\u53D6\u5730\u5740\u5728 xiaozhi.me\uFF09>",mcpServers:{}},n=g.default.join(o,"xiaozhi.config.json");a.default.writeFileSync(n,JSON.stringify(e,null,2),"utf8")}l(oo,"createBasicConfig");async function eo(o,e){const n=(0,f.default)("\u521D\u59CB\u5316\u9879\u76EE...").start();try{const i=g.default.join(process.cwd(),o);if(a.default.existsSync(i)){n.fail(`\u76EE\u5F55 "${o}" \u5DF2\u5B58\u5728`),console.log(t.default.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u9009\u62E9\u4E0D\u540C\u7684\u9879\u76EE\u540D\u79F0\u6216\u5220\u9664\u73B0\u6709\u76EE\u5F55"));return}if(e.template){n.text="\u68C0\u67E5\u6A21\u677F...";const s=Y();if(s.length===0){n.fail("\u627E\u4E0D\u5230 templates \u76EE\u5F55"),console.log(t.default.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u786E\u4FDD xiaozhi-client \u6B63\u786E\u5B89\u88C5"));return}if(!s.includes(e.template)){n.fail(`\u6A21\u677F "${e.template}" \u4E0D\u5B58\u5728`);const S=q(e.template,s);if(S)if(console.log(t.default.yellow(`\u{1F4A1} \u4F60\u662F\u60F3\u4F7F\u7528\u6A21\u677F "${S}" \u5417\uFF1F`)),await Q(t.default.cyan("\u786E\u8BA4\u4F7F\u7528\u6B64\u6A21\u677F\uFF1F(y/n): ")))e.template=S;else{console.log(t.default.yellow("\u53EF\u7528\u7684\u6A21\u677F:"));for(const _ of s)console.log(t.default.gray(` - ${_}`));return}else{console.log(t.default.yellow("\u53EF\u7528\u7684\u6A21\u677F:"));for(const j of s)console.log(t.default.gray(` - ${j}`));return}}const c=__dirname,m=[g.default.join(c,"..","templates"),g.default.join(c,"templates"),g.default.join(c,"..","..","templates")].find(S=>a.default.existsSync(S)),w=g.default.join(m,e.template);n.text=`\u4ECE\u6A21\u677F "${e.template}" \u521B\u5EFA\u9879\u76EE "${o}"...`,L(w,i,["node_modules",".pnpm-debug.log","pnpm-lock.yaml"]),n.succeed(`\u9879\u76EE "${o}" \u521B\u5EFA\u6210\u529F`),console.log(t.default.green("\u2705 \u9879\u76EE\u521B\u5EFA\u5B8C\u6210!")),console.log(t.default.yellow("\u{1F4DD} \u63A5\u4E0B\u6765\u7684\u6B65\u9AA4:")),console.log(t.default.gray(` cd ${o}`)),console.log(t.default.gray(" pnpm install # \u5B89\u88C5\u4F9D\u8D56")),console.log(t.default.gray(" # \u7F16\u8F91 xiaozhi.config.json \u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9")),console.log(t.default.gray(" xiaozhi start # \u542F\u52A8\u670D\u52A1"))}else n.text=`\u521B\u5EFA\u57FA\u672C\u9879\u76EE "${o}"...`,a.default.mkdirSync(i,{recursive:!0}),oo(i),n.succeed(`\u9879\u76EE "${o}" \u521B\u5EFA\u6210\u529F`),console.log(t.default.green("\u2705 \u57FA\u672C\u9879\u76EE\u521B\u5EFA\u5B8C\u6210!")),console.log(t.default.yellow("\u{1F4DD} \u63A5\u4E0B\u6765\u7684\u6B65\u9AA4:")),console.log(t.default.gray(` cd ${o}`)),console.log(t.default.gray(" # \u7F16\u8F91 xiaozhi.config.json \u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9\u548C\u670D\u52A1")),console.log(t.default.gray(" xiaozhi start # \u542F\u52A8\u670D\u52A1")),console.log(t.default.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 --template \u9009\u9879\u53EF\u4EE5\u4ECE\u6A21\u677F\u521B\u5EFA\u9879\u76EE"))}catch(i){n.fail(`\u521B\u5EFA\u9879\u76EE\u5931\u8D25: ${i instanceof Error?i.message:String(i)}`)}}l(eo,"createProject");function L(o,e,n=[]){a.default.existsSync(e)||a.default.mkdirSync(e,{recursive:!0});const i=a.default.readdirSync(o);for(const s of i){if(n.some(w=>s.includes(w)))continue;const c=g.default.join(o,s),r=g.default.join(e,s);a.default.statSync(c).isDirectory()?L(c,r,n):a.default.copyFileSync(c,r)}}l(L,"copyDirectory");async function no(o,e){const n=(0,f.default)("\u66F4\u65B0\u914D\u7F6E...").start();try{if(!d.configManager.configExists()){n.fail("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728"),console.log(t.default.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E'));return}if(e)switch(o){case"mcpEndpoint":d.configManager.updateMcpEndpoint(e),n.succeed(`MCP \u7AEF\u70B9\u5DF2\u66F4\u65B0\u4E3A: ${e}`);break;default:n.fail(`\u914D\u7F6E\u9879 ${o} \u4E0D\u652F\u6301\u901A\u8FC7\u547D\u4EE4\u884C\u8BBE\u7F6E`),console.log(t.default.yellow("\u652F\u6301\u8BBE\u7F6E\u7684\u914D\u7F6E\u9879: mcpEndpoint"));return}else{n.text="\u8BFB\u53D6\u914D\u7F6E...";const i=d.configManager.getConfig();switch(o){case"mcpEndpoint":n.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(t.default.green(`MCP \u7AEF\u70B9: ${i.mcpEndpoint}`));break;case"mcpServers":n.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(t.default.green("MCP \u670D\u52A1:"));for(const[s,c]of Object.entries(i.mcpServers))console.log(t.default.gray(` ${s}: ${c.command} ${c.args.join(" ")}`));break;default:n.fail(`\u672A\u77E5\u7684\u914D\u7F6E\u9879: ${o}`),console.log(t.default.yellow("\u652F\u6301\u7684\u914D\u7F6E\u9879: mcpEndpoint, mcpServers"));return}}}catch(i){n.fail(`\u914D\u7F6E\u64CD\u4F5C\u5931\u8D25: ${i instanceof Error?i.message:String(i)}`)}}l(no,"configCommand");function to(){console.log(t.default.blue.bold("xiaozhi - MCP Calculator Service CLI")),console.log(),console.log(t.default.yellow("\u4F7F\u7528\u65B9\u6CD5:")),console.log(" xiaozhi <command> [options]"),console.log(),console.log(t.default.yellow("\u547D\u4EE4:")),console.log(" create <projectName> \u521B\u5EFA\u9879\u76EE"),console.log(" init \u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6"),console.log(" config <key> [value] \u67E5\u770B\u6216\u8BBE\u7F6E\u914D\u7F6E"),console.log(" start [--daemon] \u542F\u52A8\u670D\u52A1 (--daemon \u540E\u53F0\u8FD0\u884C)"),console.log(" stop \u505C\u6B62\u670D\u52A1"),console.log(" status \u68C0\u67E5\u670D\u52A1\u72B6\u6001"),console.log(" attach \u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1\u67E5\u770B\u65E5\u5FD7"),console.log(" restart [--daemon] \u91CD\u542F\u670D\u52A1 (--daemon \u540E\u53F0\u8FD0\u884C)"),console.log(),console.log(t.default.yellow("\u9009\u9879:")),console.log(" -v, --version \u663E\u793A\u7248\u672C\u4FE1\u606F"),console.log(" -V \u663E\u793A\u8BE6\u7EC6\u4FE1\u606F"),console.log(" -h, --help \u663E\u793A\u5E2E\u52A9\u4FE1\u606F"),console.log(" -t, --template <name> \u6307\u5B9A\u6A21\u677F\u540D\u79F0\uFF08\u7528\u4E8E create \u547D\u4EE4\uFF09"),console.log(),console.log(t.default.yellow("\u9879\u76EE\u793A\u4F8B:")),console.log(" xiaozhi create my-app # \u521B\u5EFA\u57FA\u672C\u9879\u76EE"),console.log(" xiaozhi create my-app -t hello-world # \u4F7F\u7528 hello-world \u6A21\u677F"),console.log(" xiaozhi create my-app --template hello-world # \u540C\u4E0A\uFF0C\u5B8C\u6574\u9009\u9879\u540D"),console.log(),console.log(t.default.yellow("\u914D\u7F6E\u793A\u4F8B:")),console.log(" xiaozhi init # \u521D\u59CB\u5316\u914D\u7F6E"),console.log(" xiaozhi config mcpEndpoint # \u67E5\u770B MCP \u7AEF\u70B9"),console.log(" xiaozhi config mcpEndpoint wss://... # \u8BBE\u7F6E MCP \u7AEF\u70B9"),console.log(),console.log(t.default.yellow("\u670D\u52A1\u793A\u4F8B:")),console.log(" xiaozhi start # \u524D\u53F0\u542F\u52A8\u670D\u52A1"),console.log(" xiaozhi start --daemon # \u540E\u53F0\u542F\u52A8\u670D\u52A1"),console.log(" xiaozhi status # \u68C0\u67E5\u670D\u52A1\u72B6\u6001"),console.log(" xiaozhi attach # \u67E5\u770B\u540E\u53F0\u670D\u52A1\u65E5\u5FD7"),console.log(" xiaozhi stop # \u505C\u6B62\u670D\u52A1"),console.log(),console.log(t.default.yellow("MCP \u7BA1\u7406\u793A\u4F8B:")),console.log(" xiaozhi mcp list # \u5217\u51FA\u6240\u6709 MCP \u670D\u52A1"),console.log(" xiaozhi mcp list --tools # \u5217\u51FA\u6240\u6709\u670D\u52A1\u7684\u5DE5\u5177"),console.log(" xiaozhi mcp server <name> # \u5217\u51FA\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177"),console.log(" xiaozhi mcp tool <server> <tool> enable # \u542F\u7528\u5DE5\u5177"),console.log(" xiaozhi mcp tool <server> <tool> disable # \u7981\u7528\u5DE5\u5177")}l(to,"showHelp"),p.name("xiaozhi").description("MCP Calculator Service CLI Tool").version(z,"-v, --version","\u663E\u793A\u7248\u672C\u4FE1\u606F").helpOption("-h, --help","\u663E\u793A\u5E2E\u52A9\u4FE1\u606F"),p.command("create <projectName>").description("\u521B\u5EFA\u9879\u76EE").option("-t, --template <templateName>","\u4F7F\u7528\u6307\u5B9A\u6A21\u677F\u521B\u5EFA\u9879\u76EE").action(async(o,e)=>{await eo(o,e)}),p.command("init").description("\u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6").action(async()=>{await W()}),p.command("config <key> [value]").description("\u67E5\u770B\u6216\u8BBE\u7F6E\u914D\u7F6E").action(async(o,e)=>{await no(o,e)}),p.command("start").description("\u542F\u52A8\u670D\u52A1").option("-d, --daemon","\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").action(async o=>{await T(o.daemon)}),p.command("stop").description("\u505C\u6B62\u670D\u52A1").action(async()=>{await k()}),p.command("status").description("\u68C0\u67E5\u670D\u52A1\u72B6\u6001").action(async()=>{await X()}),p.command("attach").description("\u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1\u67E5\u770B\u65E5\u5FD7").action(async()=>{await Z()}),p.command("restart").description("\u91CD\u542F\u670D\u52A1").option("-d, --daemon","\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").action(async o=>{await J(o.daemon)});const C=p.command("mcp").description("MCP \u670D\u52A1\u548C\u5DE5\u5177\u7BA1\u7406");C.command("list").description("\u5217\u51FA MCP \u670D\u52A1").option("--tools","\u663E\u793A\u6240\u6709\u670D\u52A1\u7684\u5DE5\u5177\u5217\u8868").action(async o=>{await(0,h.listMcpServers)(o)}),C.command("server <serverName>").description("\u7BA1\u7406\u6307\u5B9A\u7684 MCP \u670D\u52A1").action(async o=>{await(0,h.listServerTools)(o)}),C.command("tool <serverName> <toolName> <action>").description("\u542F\u7528\u6216\u7981\u7528\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177").action(async(o,e,n)=>{n!=="enable"&&n!=="disable"&&(console.error(t.default.red("\u9519\u8BEF: \u64CD\u4F5C\u5FC5\u987B\u662F 'enable' \u6216 'disable'")),process.exit(1)),await(0,h.setToolEnabled)(o,e,n==="enable")}),p.option("-V","\u663E\u793A\u8BE6\u7EC6\u4FE1\u606F").action(o=>{o.V&&(K(),process.exit(0))}),process.argv.length<=2&&(to(),process.exit(0)),p.parse(process.argv);
|
|
452
7
|
//# sourceMappingURL=cli.cjs.map
|