xiaozhi-client 1.3.0 → 1.4.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +156 -6
- package/dist/cli.js +28 -7
- package/dist/cli.js.map +1 -1
- package/dist/mcpPipe.d.ts +1 -0
- package/dist/mcpPipe.js +8 -8
- package/dist/mcpPipe.js.map +1 -1
- package/dist/mcpServerProxy.js +0 -0
- package/dist/package.json +4 -2
- package/dist/webServer.d.ts +31 -0
- package/dist/webServer.js +23 -0
- package/dist/webServer.js.map +1 -0
- package/docs/images/web-ui-preview.png +0 -0
- package/package.json +21 -19
- package/web/dist/assets/index-Dds-Fr4c.js +139 -0
- package/web/dist/assets/index-Dds-Fr4c.js.map +1 -0
- package/web/dist/assets/index-Do_WccF3.css +1 -0
- package/web/dist/index.html +14 -0
package/README.md
CHANGED
|
@@ -116,12 +116,14 @@ xiaozhi-client 现已支持接入 [ModelScope](https://www.modelscope.cn/mcp)
|
|
|
116
116
|
### 使用前准备
|
|
117
117
|
|
|
118
118
|
1. 获取 ModelScope API Token:
|
|
119
|
+
|
|
119
120
|
- 访问 [ModelScope](https://www.modelscope.cn) 并登录
|
|
120
121
|
- 在个人中心获取 API Token
|
|
121
122
|
|
|
122
123
|
2. 配置 API Token(两种方式任选其一):
|
|
123
|
-
|
|
124
|
+
|
|
124
125
|
**方式一:在配置文件中设置(推荐)**
|
|
126
|
+
|
|
125
127
|
```json
|
|
126
128
|
{
|
|
127
129
|
"modelscope": {
|
|
@@ -129,8 +131,9 @@ xiaozhi-client 现已支持接入 [ModelScope](https://www.modelscope.cn/mcp)
|
|
|
129
131
|
}
|
|
130
132
|
}
|
|
131
133
|
```
|
|
132
|
-
|
|
134
|
+
|
|
133
135
|
**方式二:设置环境变量**
|
|
136
|
+
|
|
134
137
|
```bash
|
|
135
138
|
export MODELSCOPE_API_TOKEN="你的API Token"
|
|
136
139
|
```
|
|
@@ -147,8 +150,155 @@ xiaozhi-client 现已支持接入 [ModelScope](https://www.modelscope.cn/mcp)
|
|
|
147
150
|
- 确保网络能够访问 ModelScope 的服务端点
|
|
148
151
|
- SSE 类型的服务会自动识别并使用相应的连接方式
|
|
149
152
|
|
|
150
|
-
##
|
|
153
|
+
## 自建服务端 JSON-RPC 消息格式规范
|
|
154
|
+
|
|
155
|
+
如果您使用自建的 MCP 服务端,请确保遵循以下 JSON-RPC 2.0 消息格式规范:
|
|
156
|
+
|
|
157
|
+
### 消息类型
|
|
158
|
+
|
|
159
|
+
#### 1. 请求(Request)- 需要响应
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"jsonrpc": "2.0",
|
|
164
|
+
"method": "方法名",
|
|
165
|
+
"params": {},
|
|
166
|
+
"id": 1 // 必须包含id字段,可以是数字或字符串
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
支持的请求方法:
|
|
171
|
+
|
|
172
|
+
- `initialize` - 初始化连接
|
|
173
|
+
- `tools/list` - 获取工具列表
|
|
174
|
+
- `tools/call` - 调用工具
|
|
175
|
+
- `ping` - 连接测试
|
|
176
|
+
|
|
177
|
+
#### 2. 通知(Notification)- 不需要响应
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"jsonrpc": "2.0",
|
|
182
|
+
"method": "方法名",
|
|
183
|
+
"params": {}
|
|
184
|
+
// 注意:不能包含id字段
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
支持的通知方法:
|
|
151
189
|
|
|
152
|
-
-
|
|
153
|
-
|
|
154
|
-
|
|
190
|
+
- `notifications/initialized` - 初始化完成通知
|
|
191
|
+
|
|
192
|
+
#### 3. 成功响应(Response)
|
|
193
|
+
|
|
194
|
+
```json
|
|
195
|
+
{
|
|
196
|
+
"jsonrpc": "2.0",
|
|
197
|
+
"result": {},
|
|
198
|
+
"id": 1 // 必须与请求的id相同
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
#### 4. 错误响应(Error)
|
|
203
|
+
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"jsonrpc": "2.0",
|
|
207
|
+
"error": {
|
|
208
|
+
"code": -32600,
|
|
209
|
+
"message": "错误描述"
|
|
210
|
+
},
|
|
211
|
+
"id": 1 // 必须与请求的id相同
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### 重要注意事项
|
|
216
|
+
|
|
217
|
+
1. **关键区别**:请求和通知的唯一区别是是否包含 `id` 字段
|
|
218
|
+
|
|
219
|
+
- 有 `id` = 请求,需要响应
|
|
220
|
+
- 无 `id` = 通知,不需要响应
|
|
221
|
+
|
|
222
|
+
2. **"notifications/initialized" 必须作为通知发送**:
|
|
223
|
+
|
|
224
|
+
```json
|
|
225
|
+
// ✅ 正确
|
|
226
|
+
{
|
|
227
|
+
"jsonrpc": "2.0",
|
|
228
|
+
"method": "notifications/initialized"
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ❌ 错误 - 不应包含id
|
|
232
|
+
{
|
|
233
|
+
"jsonrpc": "2.0",
|
|
234
|
+
"method": "notifications/initialized",
|
|
235
|
+
"id": 1
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
3. **消息分隔**:每条 JSON-RPC 消息必须以换行符 `\n` 结束
|
|
240
|
+
|
|
241
|
+
4. **通信流程**:
|
|
242
|
+
1. 客户端发送 `initialize` 请求
|
|
243
|
+
2. 服务端返回 `initialize` 响应
|
|
244
|
+
3. 客户端发送 `notifications/initialized` 通知(无需响应)
|
|
245
|
+
4. 后续可进行工具列表查询和调用
|
|
246
|
+
|
|
247
|
+
### 通信时序图
|
|
248
|
+
|
|
249
|
+
```mermaid
|
|
250
|
+
sequenceDiagram
|
|
251
|
+
participant Client as 小智客户端
|
|
252
|
+
participant Server as 自建MCP服务端
|
|
253
|
+
|
|
254
|
+
Note over Client,Server: 初始化阶段
|
|
255
|
+
Client->>Server: {"jsonrpc":"2.0","method":"initialize","params":{...},"id":1}
|
|
256
|
+
Server->>Client: {"jsonrpc":"2.0","result":{...},"id":1}
|
|
257
|
+
Client->>Server: {"jsonrpc":"2.0","method":"notifications/initialized"}
|
|
258
|
+
Note over Server: 无需响应通知
|
|
259
|
+
|
|
260
|
+
Note over Client,Server: 获取工具列表
|
|
261
|
+
Client->>Server: {"jsonrpc":"2.0","method":"tools/list","params":{},"id":2}
|
|
262
|
+
Server->>Client: {"jsonrpc":"2.0","result":{"tools":[...]},"id":2}
|
|
263
|
+
|
|
264
|
+
Note over Client,Server: 调用工具
|
|
265
|
+
Client->>Server: {"jsonrpc":"2.0","method":"tools/call","params":{...},"id":3}
|
|
266
|
+
Server->>Client: {"jsonrpc":"2.0","result":{...},"id":3}
|
|
267
|
+
|
|
268
|
+
Note over Client,Server: 保持连接
|
|
269
|
+
Client->>Server: {"jsonrpc":"2.0","method":"ping","params":{},"id":4}
|
|
270
|
+
Server->>Client: {"jsonrpc":"2.0","result":{},"id":4}
|
|
271
|
+
|
|
272
|
+
Note over Client,Server: 错误处理示例
|
|
273
|
+
Client->>Server: {"jsonrpc":"2.0","method":"unknown_method","params":{},"id":5}
|
|
274
|
+
Server->>Client: {"jsonrpc":"2.0","error":{"code":-32601,"message":"Method not found"},"id":5}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### 常见错误
|
|
278
|
+
|
|
279
|
+
如果您看到类似 "未知的方法:notifications/initialized" 的错误,通常是因为在通知消息中错误地包含了 `id` 字段,导致客户端将其识别为请求而非通知。
|
|
280
|
+
|
|
281
|
+
## Web UI 配置界面
|
|
282
|
+
|
|
283
|
+
xiaozhi-client 提供了一个现代化的 Web UI 界面,让配置 MCP 服务更加直观和便捷。
|
|
284
|
+
|
|
285
|
+

|
|
286
|
+
|
|
287
|
+
### 功能特性
|
|
288
|
+
|
|
289
|
+
- 🎨 **现代化界面**:基于 React + TypeScript + Tailwind CSS 构建
|
|
290
|
+
- 🔧 **可视化配置**:直观的界面操作,无需手动编辑 JSON 文件
|
|
291
|
+
- 🚀 **实时连接状态**:实时显示与小智服务器的连接状态
|
|
292
|
+
- 📦 **MCP 服务管理**:
|
|
293
|
+
- 添加/编辑/删除 MCP 服务
|
|
294
|
+
- 支持本地服务和 SSE 服务
|
|
295
|
+
- 支持批量导入配置
|
|
296
|
+
- ⚙️ **配置管理**:
|
|
297
|
+
- 编辑连接参数(心跳间隔、超时时间等)
|
|
298
|
+
- 管理 ModelScope API Key
|
|
299
|
+
|
|
300
|
+
### 启动 Web UI
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
xiaozhi ui
|
|
304
|
+
```
|
package/dist/cli.js
CHANGED
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var q=Object.defineProperty;var g=(n,o)=>q(n,"name",{value:o,configurable:!0});import{spawn as U}from"child_process";import u from"fs";import go from"os";import f from"path";import{fileURLToPath as I}from"url";import s from"chalk";import{Command as fo}from"commander";import b from"ora";import io from"omelette";import{copyFileSync as Y,existsSync as R,readFileSync as Q,writeFileSync as oo}from"fs";import{dirname as eo,resolve as D}from"path";import{fileURLToPath as no}from"url";var to=eo(no(import.meta.url)),T={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},z=class n{static{g(this,"ConfigManager")}static instance;defaultConfigPath;config=null;constructor(){this.defaultConfigPath=D(to,"xiaozhi.config.default.json")}getConfigFilePath(){let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return D(o,"xiaozhi.config.json")}static getInstance(){return n.instance||(n.instance=new n),n.instance}configExists(){let o=this.getConfigFilePath();return R(o)}initConfig(){if(!R(this.defaultConfigPath))throw new Error("\u9ED8\u8BA4\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.default.json \u4E0D\u5B58\u5728");if(this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.json \u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u521D\u59CB\u5316");let o=this.getConfigFilePath();Y(this.defaultConfigPath,o),this.config=null}loadConfig(){if(!this.configExists())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");try{let o=this.getConfigFilePath(),e=Q(o,"utf8"),t=JSON.parse(e);return this.validateConfig(t),t}catch(o){throw o instanceof SyntaxError?new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF: ${o.message}`):o}}validateConfig(o){if(!o||typeof o!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A\u6839\u5BF9\u8C61\u65E0\u6548");let e=o;if(!e.mcpEndpoint||typeof e.mcpEndpoint!="string")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5B57\u6BB5\u65E0\u6548");if(!e.mcpServers||typeof e.mcpServers!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers \u5B57\u6BB5\u65E0\u6548");for(let[t,i]of Object.entries(e.mcpServers)){if(!i||typeof i!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t} \u65E0\u6548`);let r=i;if(r.type==="sse"){if(!r.url||typeof r.url!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.url \u65E0\u6548`)}else{if(!r.command||typeof r.command!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.command \u65E0\u6548`);if(!Array.isArray(r.args))throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.args \u5FC5\u987B\u662F\u6570\u7EC4`);if(r.env&&typeof r.env!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.env \u5FC5\u987B\u662F\u5BF9\u8C61`)}}}getConfig(){return this.config||(this.config=this.loadConfig()),JSON.parse(JSON.stringify(this.config))}getMcpEndpoint(){return this.getConfig().mcpEndpoint}getMcpServers(){return this.getConfig().mcpServers}getMcpServerConfig(){return this.getConfig().mcpServerConfig||{}}getServerToolsConfig(o){return this.getMcpServerConfig()[o]?.tools||{}}isToolEnabled(o,e){return this.getServerToolsConfig(o)[e]?.enable!==!1}updateMcpEndpoint(o){if(!o||typeof o!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t={...this.getConfig(),mcpEndpoint:o};this.saveConfig(t)}updateMcpServer(o,e){if(!o||typeof o!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if("type"in e&&e.type==="sse"){if(!e.url||typeof e.url!="string")throw new Error("SSE \u670D\u52A1\u914D\u7F6E\u7684 url \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else{let r=e;if(!r.command||typeof r.command!="string")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 command \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!Array.isArray(r.args))throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 args \u5B57\u6BB5\u5FC5\u987B\u662F\u6570\u7EC4");if(r.env&&typeof r.env!="object")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 env \u5B57\u6BB5\u5FC5\u987B\u662F\u5BF9\u8C61")}let t=this.getConfig(),i={...t,mcpServers:{...t.mcpServers,[o]:e}};this.saveConfig(i)}removeMcpServer(o){if(!o||typeof o!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let e=this.getConfig();if(!e.mcpServers[o])throw new Error(`\u670D\u52A1 ${o} \u4E0D\u5B58\u5728`);let t={...e.mcpServers};delete t[o];let i={...e,mcpServers:t};this.saveConfig(i)}updateServerToolsConfig(o,e){let i={...this.getConfig()};i.mcpServerConfig||(i.mcpServerConfig={}),i.mcpServerConfig[o]={tools:e},this.saveConfig(i)}setToolEnabled(o,e,t,i){let c={...this.getConfig()};c.mcpServerConfig||(c.mcpServerConfig={}),c.mcpServerConfig[o]||(c.mcpServerConfig[o]={tools:{}}),c.mcpServerConfig[o].tools[e]={enable:t,...i&&{description:i}},this.saveConfig(c)}saveConfig(o){try{this.validateConfig(o);let e=this.getConfigFilePath(),t=JSON.stringify(o,null,2);oo(e,t,"utf8"),this.config=o}catch(e){throw new Error(`\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}reloadConfig(){this.config=null}getConfigPath(){return this.getConfigFilePath()}getDefaultConfigPath(){return this.defaultConfigPath}getConnectionConfig(){let e=this.getConfig().connection||{};return{heartbeatInterval:e.heartbeatInterval??T.heartbeatInterval,heartbeatTimeout:e.heartbeatTimeout??T.heartbeatTimeout,reconnectInterval:e.reconnectInterval??T.reconnectInterval}}getHeartbeatInterval(){return this.getConnectionConfig().heartbeatInterval}getHeartbeatTimeout(){return this.getConnectionConfig().heartbeatTimeout}getReconnectInterval(){return this.getConnectionConfig().reconnectInterval}updateConnectionConfig(o){let e=this.getConfig(),i={...e.connection||{},...o},r={...e,connection:i};this.saveConfig(r)}setHeartbeatInterval(o){if(o<=0)throw new Error("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatInterval:o})}setHeartbeatTimeout(o){if(o<=0)throw new Error("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatTimeout:o})}setReconnectInterval(o){if(o<=0)throw new Error("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({reconnectInterval:o})}getModelScopeConfig(){return this.getConfig().modelscope||{}}getModelScopeApiKey(){return this.getModelScopeConfig().apiKey||process.env.MODELSCOPE_API_TOKEN}updateModelScopeConfig(o){let e=this.getConfig(),i={...e.modelscope||{},...o},r={...e,modelscope:i};this.saveConfig(r)}setModelScopeApiKey(o){if(!o||typeof o!="string")throw new Error("API Key \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");this.updateModelScopeConfig({apiKey:o})}},p=z.getInstance();function ro(){try{if(!p.configExists())return[];let n=p.getMcpServers();return Object.keys(n)}catch{return[]}}g(ro,"getMcpServerNames");function so(n){try{if(!p.configExists())return[];let o=p.getServerToolsConfig(n);return Object.keys(o)}catch{return[]}}g(so,"getServerToolNames");function O(){let n=io("xiaozhi <command>");if(n.on("command",({reply:o})=>{o(["create","init","config","start","stop","status","attach","restart","mcp","completion"])}),n.on("complete",(o,{line:e,before:t,reply:i})=>{process.env.XIAOZHI_DEBUG_COMPLETION&&console.error(`Debug completion - line: "${e}", before: "${t}", fragment: "${o}"`);let r=e.trim().split(/\s+/),a=e!==e.trim()?r.length:r.length-1;if(r[1]==="mcp"){let d=r[2];if(a===2){let m=["list","server","tool"],h=r[2]||"",y=m.filter(C=>C.startsWith(h));i(y);return}if(a===3){switch(d){case"list":{let m=["--tools"],h=r[3]||"",y=m.filter(C=>C.startsWith(h));i(y);break}case"server":case"tool":{let m=ro(),h=r[3]||"",y=m.filter(C=>C.startsWith(h));i(y);break}default:i([])}return}if(a===4&&d==="tool"){let m=r[3],h=so(m),y=r[4]||"",C=h.filter(E=>E.startsWith(y));i(C);return}if(a===5&&d==="tool"){let m=["enable","disable"],h=r[5]||"",y=m.filter(C=>C.startsWith(h));i(y);return}}if(a===2){switch(r[1]){case"create":i(["--template","-t"]);break;case"start":case"restart":i(["--daemon","-d"]);break;case"completion":i(["install","uninstall"]);break;default:i([])}return}i([])}),process.argv.includes("--completion")){try{console.log(n.setupShellInitFile())}catch(o){console.error("\u751F\u6210\u81EA\u52A8\u8865\u5168\u811A\u672C\u65F6\u51FA\u9519:",o)}process.exit(0)}process.argv.includes("--completion-fish")&&(console.log(n.setupShellInitFile("fish")),process.exit(0)),process.argv.includes("--compzsh")||process.argv.includes("--compbash"),n.init()}g(O,"setupAutoCompletion");function N(){console.log("\u{1F680} xiaozhi \u81EA\u52A8\u8865\u5168\u8BBE\u7F6E"),console.log(),console.log("\u8981\u542F\u7528\u81EA\u52A8\u8865\u5168\uFF0C\u8BF7\u6839\u636E\u4F60\u7684shell\u6267\u884C\u4EE5\u4E0B\u547D\u4EE4\uFF1A"),console.log(),console.log("\u{1F4DD} Zsh (\u63A8\u8350):"),console.log(" xiaozhi --completion >> ~/.xiaozhi-completion.zsh"),console.log(" echo 'source ~/.xiaozhi-completion.zsh' >> ~/.zshrc"),console.log(" source ~/.zshrc"),console.log(),console.log("\u{1F4DD} Bash:"),console.log(" xiaozhi --completion >> ~/.xiaozhi-completion.bash"),console.log(" echo 'source ~/.xiaozhi-completion.bash' >> ~/.bash_profile"),console.log(" source ~/.bash_profile"),console.log(),console.log("\u{1F4DD} Fish:"),console.log(" xiaozhi --completion-fish >> ~/.config/fish/completions/xiaozhi.fish"),console.log(),console.log("\u2728 \u8BBE\u7F6E\u5B8C\u6210\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u4F7F\u7528 Tab \u952E\u8FDB\u884C\u81EA\u52A8\u8865\u5168\u4E86\uFF01"),console.log(),console.log("\u{1F4A1} \u793A\u4F8B:"),console.log(" xiaozhi m<Tab> # \u2192 mcp"),console.log(" xiaozhi mcp l<Tab> # \u2192 list"),console.log(" xiaozhi mcp tool <Tab> # \u2192 \u663E\u793A\u6240\u6709\u670D\u52A1\u5668\u540D\u79F0")}g(N,"showCompletionHelp");import P from"fs";import co from"path";import w from"chalk";import{createConsola as lo}from"consola";function ao(n){let o=n.getFullYear(),e=String(n.getMonth()+1).padStart(2,"0"),t=String(n.getDate()).padStart(2,"0"),i=String(n.getHours()).padStart(2,"0"),r=String(n.getMinutes()).padStart(2,"0"),c=String(n.getSeconds()).padStart(2,"0");return`${o}-${e}-${t} ${i}:${r}:${c}`}g(ao,"formatDateTime");var j=class{static{g(this,"Logger")}logFilePath=null;writeStream=null;consolaInstance;constructor(){this.consolaInstance=lo({formatOptions:{date:!1,colors:!0,compact:!0},fancy:!1}),this.consolaInstance.setReporters([{log:g(o=>{let e={info:"INFO",success:"SUCCESS",warn:"WARN",error:"ERROR",debug:"DEBUG",log:"LOG"},t={info:w.blue,success:w.green,warn:w.yellow,error:w.red,debug:w.gray,log:g(m=>m,"log")},i=e[o.type]||o.type.toUpperCase(),r=t[o.type]||(m=>m),c=ao(new Date),a=r(`[${i}]`),d=`[${c}] ${a} ${o.args.join(" ")}`;console.error(d)},"log")}])}initLogFile(o){this.logFilePath=co.join(o,"xiaozhi.log"),P.existsSync(this.logFilePath)||P.writeFileSync(this.logFilePath,""),this.writeStream=P.createWriteStream(this.logFilePath,{flags:"a",encoding:"utf8"})}logToFile(o,e,...t){if(this.writeStream){let r=`[${new Date().toISOString()}] [${o.toUpperCase()}] ${e}`,c=t.length>0?`${r} ${t.map(a=>typeof a=="object"?JSON.stringify(a):String(a)).join(" ")}`:r;this.writeStream.write(`${c}
|
|
3
|
-
`)}}enableFileLogging(o){o&&!this.writeStream&&this.logFilePath?this.writeStream=P.createWriteStream(this.logFilePath,{flags:"a",encoding:"utf8"}):!o&&this.writeStream&&(this.writeStream.end(),this.writeStream=null)}info(o,...e){this.consolaInstance.info(o,...e),this.logToFile("info",o,...e)}success(o,...e){this.consolaInstance.success(o,...e),this.logToFile("success",o,...e)}warn(o,...e){this.consolaInstance.warn(o,...e),this.logToFile("warn",o,...e)}error(o,...e){this.consolaInstance.error(o,...e),this.logToFile("error",o,...e)}debug(o,...e){this.consolaInstance.debug(o,...e),this.logToFile("debug",o,...e)}log(o,...e){this.consolaInstance.log(o,...e),this.logToFile("log",o,...e)}withTag(o){return this}close(){this.writeStream&&(this.writeStream.end(),this.writeStream=null)}},x=new j;import l from"chalk";import A from"cli-table3";import k from"ora";function L(n){let o=0;for(let e of n)/[\u4e00-\u9fff\u3400-\u4dbf\uff00-\uffef]/.test(e)?o+=2:o+=1;return o}g(L,"getDisplayWidth");function W(n,o){if(L(n)<=o)return n;if(o<=3)return"";let e="",t=0,i=!1;for(let r of n){let c=/[\u4e00-\u9fff\u3400-\u4dbf\uff00-\uffef]/.test(r)?2:1;if(t+c>o-3){if(!i)return"";e+="...";break}e+=r,t+=c,i=!0}return e}g(W,"truncateToWidth");async function _(n={}){let o=k("\u83B7\u53D6 MCP \u670D\u52A1\u5217\u8868...").start();try{let e=p.getMcpServers(),t=Object.keys(e);if(t.length===0){o.warn("\u672A\u914D\u7F6E\u4EFB\u4F55 MCP \u670D\u52A1"),console.log(l.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi config' \u547D\u4EE4\u914D\u7F6E MCP \u670D\u52A1"));return}if(o.succeed(`\u627E\u5230 ${t.length} \u4E2A MCP \u670D\u52A1`),n.tools){console.log(),console.log(l.bold("MCP \u670D\u52A1\u5DE5\u5177\u5217\u8868:")),console.log();let i=8,r=[];for(let a of t){let d=p.getServerToolsConfig(a),m=Object.keys(d);r.push(...m)}for(let a of r){let d=L(a);d>i&&(i=d)}i=Math.max(10,Math.min(i+2,30));let c=new A({head:[l.bold("MCP"),l.bold("\u5DE5\u5177\u540D\u79F0"),l.bold("\u72B6\u6001"),l.bold("\u63CF\u8FF0")],colWidths:[15,i,8,40],wordWrap:!0,style:{head:[],border:[]}});for(let a of t){let d=p.getServerToolsConfig(a),m=Object.keys(d);if(m.length===0)c.push([l.gray(a),l.gray("(\u65E0\u5DE5\u5177)"),l.gray("-"),l.gray("\u8BF7\u5148\u542F\u52A8\u670D\u52A1\u626B\u63CF\u5DE5\u5177")]);else{c.length>0&&c.push([{colSpan:4,content:""}]);for(let h of m){let y=d[h],C=y.enable?l.green("\u542F\u7528"):l.red("\u7981\u7528"),E=W(y.description||"",32);c.push([a,h,C,E])}}}console.log(c.toString())}else{console.log(),console.log(l.bold("MCP \u670D\u52A1\u5217\u8868:")),console.log();for(let i of t){let r=e[i],c=p.getServerToolsConfig(i),a=Object.keys(c).length,d=Object.values(c).filter(m=>m.enable!==!1).length;console.log(`${l.cyan("\u2022")} ${l.bold(i)}`),"type"in r&&r.type==="sse"?(console.log(` \u7C7B\u578B: ${l.gray("SSE")}`),console.log(` URL: ${l.gray(r.url)}`)):console.log(` \u547D\u4EE4: ${l.gray(r.command)} ${l.gray(r.args.join(" "))}`),a>0?console.log(` \u5DE5\u5177: ${l.green(d)} \u542F\u7528 / ${l.yellow(a)} \u603B\u8BA1`):console.log(` \u5DE5\u5177: ${l.gray("\u672A\u626B\u63CF (\u8BF7\u5148\u542F\u52A8\u670D\u52A1)")}`),console.log()}}console.log(l.gray("\u{1F4A1} \u63D0\u793A:")),console.log(l.gray(" - \u4F7F\u7528 'xiaozhi mcp list --tools' \u67E5\u770B\u6240\u6709\u5DE5\u5177")),console.log(l.gray(" - \u4F7F\u7528 'xiaozhi mcp <\u670D\u52A1\u540D> list' \u67E5\u770B\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177")),console.log(l.gray(" - \u4F7F\u7528 'xiaozhi mcp <\u670D\u52A1\u540D> <\u5DE5\u5177\u540D> enable/disable' \u542F\u7528/\u7981\u7528\u5DE5\u5177"))}catch(e){o.fail("\u83B7\u53D6 MCP \u670D\u52A1\u5217\u8868\u5931\u8D25"),console.error(l.red(`\u9519\u8BEF: ${e instanceof Error?e.message:String(e)}`)),process.exit(1)}}g(_,"listMcpServers");async function G(n){let o=k(`\u83B7\u53D6 ${n} \u670D\u52A1\u7684\u5DE5\u5177\u5217\u8868...`).start();try{if(!p.getMcpServers()[n]){o.fail(`\u670D\u52A1 '${n}' \u4E0D\u5B58\u5728`),console.log(l.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp list' \u67E5\u770B\u6240\u6709\u53EF\u7528\u670D\u52A1"));return}let t=p.getServerToolsConfig(n),i=Object.keys(t);if(i.length===0){o.warn(`\u670D\u52A1 '${n}' \u6682\u65E0\u5DE5\u5177\u4FE1\u606F`),console.log(l.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u542F\u52A8\u670D\u52A1\u4EE5\u626B\u63CF\u5DE5\u5177\u5217\u8868"));return}o.succeed(`\u670D\u52A1 '${n}' \u5171\u6709 ${i.length} \u4E2A\u5DE5\u5177`),console.log(),console.log(l.bold(`${n} \u670D\u52A1\u5DE5\u5177\u5217\u8868:`)),console.log();let r=new A({head:[l.bold("\u5DE5\u5177\u540D\u79F0"),l.bold("\u72B6\u6001"),l.bold("\u63CF\u8FF0")],colWidths:[30,8,50],wordWrap:!0,style:{head:[],border:[]}});for(let c of i){let a=t[c],d=a.enable?l.green("\u542F\u7528"):l.red("\u7981\u7528"),m=W(a.description||"",40);r.push([c,d,m])}console.log(r.toString()),console.log(),console.log(l.gray("\u{1F4A1} \u63D0\u793A:")),console.log(l.gray(` - \u4F7F\u7528 'xiaozhi mcp ${n} <\u5DE5\u5177\u540D> enable' \u542F\u7528\u5DE5\u5177`)),console.log(l.gray(` - \u4F7F\u7528 'xiaozhi mcp ${n} <\u5DE5\u5177\u540D> disable' \u7981\u7528\u5DE5\u5177`))}catch(e){o.fail("\u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25"),console.error(l.red(`\u9519\u8BEF: ${e instanceof Error?e.message:String(e)}`)),process.exit(1)}}g(G,"listServerTools");async function H(n,o,e){let t=e?"\u542F\u7528":"\u7981\u7528",i=k(`${t}\u5DE5\u5177 ${n}/${o}...`).start();try{if(!p.getMcpServers()[n]){i.fail(`\u670D\u52A1 '${n}' \u4E0D\u5B58\u5728`),console.log(l.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp list' \u67E5\u770B\u6240\u6709\u53EF\u7528\u670D\u52A1"));return}let c=p.getServerToolsConfig(n);if(!c[o]){i.fail(`\u5DE5\u5177 '${o}' \u5728\u670D\u52A1 '${n}' \u4E2D\u4E0D\u5B58\u5728`),console.log(l.yellow(`\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp ${n} list' \u67E5\u770B\u8BE5\u670D\u52A1\u7684\u6240\u6709\u5DE5\u5177`));return}p.setToolEnabled(n,o,e,c[o].description),i.succeed(`\u6210\u529F${t}\u5DE5\u5177 ${l.cyan(n)}/${l.cyan(o)}`),console.log(),console.log(l.gray("\u{1F4A1} \u63D0\u793A: \u5DE5\u5177\u72B6\u6001\u66F4\u6539\u5C06\u5728\u4E0B\u6B21\u542F\u52A8\u670D\u52A1\u65F6\u751F\u6548"))}catch(r){i.fail(`${t}\u5DE5\u5177\u5931\u8D25`),console.error(l.red(`\u9519\u8BEF: ${r instanceof Error?r.message:String(r)}`)),process.exit(1)}}g(H,"setToolEnabled");var S=new fo,po="xiaozhi-mcp-service";function B(){try{let n=I(import.meta.url),o=f.dirname(n),e=[f.join(o,"..","package.json"),f.join(o,"..","package.json"),f.join(o,"..","..","package.json"),f.join(o,"package.json")];for(let t of e)if(u.existsSync(t)){let i=JSON.parse(u.readFileSync(t,"utf8"));if(i.version)return i.version}return"unknown"}catch(n){return console.warn("\u65E0\u6CD5\u4ECE package.json \u8BFB\u53D6\u7248\u672C\u4FE1\u606F:",n),"unknown"}}g(B,"getVersion");var v=f.join(go.tmpdir(),`${po}.pid`);function M(){try{if(!u.existsSync(v))return{running:!1};let n=u.readFileSync(v,"utf8").trim(),[o,e,t]=n.split("|"),i=Number.parseInt(o);if(Number.isNaN(i))return u.unlinkSync(v),{running:!1};try{process.kill(i,0);let r=Number.parseInt(e),c=mo(Date.now()-r);return{running:!0,pid:i,uptime:c,mode:t||"foreground"}}catch{return u.unlinkSync(v),{running:!1}}}catch{return{running:!1}}}g(M,"getServiceStatus");function mo(n){let o=Math.floor(n/1e3),e=Math.floor(o/60),t=Math.floor(e/60),i=Math.floor(t/24);return i>0?`${i}\u5929 ${t%24}\u5C0F\u65F6 ${e%60}\u5206\u949F`:t>0?`${t}\u5C0F\u65F6 ${e%60}\u5206\u949F`:e>0?`${e}\u5206\u949F ${o%60}\u79D2`:`${o}\u79D2`}g(mo,"formatUptime");function J(n,o){let e=`${n}|${Date.now()}|${o}`;u.writeFileSync(v,e)}g(J,"savePidInfo");function $(){try{u.existsSync(v)&&u.unlinkSync(v)}catch{}}g($,"cleanupPidFile");function uo(){if(!p.configExists())return console.error(s.red("\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728")),console.log(s.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E')),!1;try{let n=p.getMcpEndpoint();return!n||n.includes("<\u8BF7\u586B\u5199")?(console.error(s.red("\u274C \u9519\u8BEF: MCP \u7AEF\u70B9\u672A\u914D\u7F6E")),console.log(s.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi config mcpEndpoint <your-endpoint-url>" \u8BBE\u7F6E\u7AEF\u70B9')),!1):!0}catch(n){return console.error(s.red(`\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u65E0\u6548 - ${n instanceof Error?n.message:String(n)}`)),console.log(s.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u91CD\u65B0\u521D\u59CB\u5316\u914D\u7F6E')),!1}}g(uo,"checkEnvironment");function ho(){let n=f.dirname(I(import.meta.url)),o;return n.includes("js-demo/dist")?o=n:o=[f.join(n,"..","js-demo","dist"),f.join(n,"..","..","js-demo","dist"),f.join(n,"..","..","..","js-demo","dist"),f.join(process.cwd(),"js-demo","dist"),f.join(process.cwd(),"dist")].find(t=>u.existsSync(f.join(t,"mcpPipe.js"))&&u.existsSync(f.join(t,"mcpServerProxy.js")))||n,{command:"node",args:["mcpPipe.js","mcpServerProxy.js"],cwd:o}}g(ho,"getServiceCommand");async function K(n=!1){let o=b("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let e=M();if(e.running){o.fail(`\u670D\u52A1\u5DF2\u7ECF\u5728\u8FD0\u884C (PID: ${e.pid})`);return}if(o.text="\u68C0\u67E5\u73AF\u5883\u914D\u7F6E...",!uo()){o.fail("\u73AF\u5883\u914D\u7F6E\u68C0\u67E5\u5931\u8D25");return}let{command:t,args:i,cwd:r}=ho();if(o.text=`\u542F\u52A8\u670D\u52A1 (${n?"\u540E\u53F0\u6A21\u5F0F":"\u524D\u53F0\u6A21\u5F0F"})...`,n){let c=U(t,i,{cwd:r,detached:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd(),XIAOZHI_DAEMON:"true"}});J(c.pid,"daemon");let a=process.cwd();x.initLogFile(a),x.enableFileLogging(!0);let d=f.join(a,"xiaozhi.log"),m=u.createWriteStream(d,{flags:"a"});c.stdout?.pipe(m),c.stderr?.pipe(m),c.on("exit",(h,y)=>{h!==0&&h!==null&&x.error(`\u540E\u53F0\u670D\u52A1\u5F02\u5E38\u9000\u51FA (\u4EE3\u7801: ${h}, \u4FE1\u53F7: ${y})`),$()}),c.on("error",h=>{x.error(`\u540E\u53F0\u670D\u52A1\u542F\u52A8\u9519\u8BEF: ${h.message}`),$(),o.fail(`\u540E\u53F0\u670D\u52A1\u542F\u52A8\u5931\u8D25: ${h.message}`)}),c.unref(),o.succeed(`\u670D\u52A1\u5DF2\u5728\u540E\u53F0\u542F\u52A8 (PID: ${c.pid})`),console.log(s.gray(`\u65E5\u5FD7\u6587\u4EF6: ${d}`)),console.log(s.gray("\u4F7F\u7528 'xiaozhi attach' \u53EF\u4EE5\u67E5\u770B\u5B9E\u65F6\u65E5\u5FD7"))}else{o.succeed("\u670D\u52A1\u542F\u52A8\u4E2D...");let c=U(t,i,{cwd:r,stdio:"inherit",env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd()}});J(c.pid,"foreground"),c.on("exit",(a,d)=>{$(),console.log(a!==0?s.red(`
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
\
|
|
8
|
-
\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(s.yellow("\u65E5\u5FD7\u6587\u4EF6\u4E0D\u5B58\u5728"))}catch(o){n.fail(`\u8FDE\u63A5\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}g(Co,"attachService");async function So(n=!1){console.log(s.blue("\u{1F504} \u91CD\u542F\u670D\u52A1...")),await V(),await new Promise(o=>setTimeout(o,1e3)),await K(n)}g(So,"restartService");function vo(){let n=B();console.log(s.blue(`xiaozhi v${n}`)),console.log(s.gray("MCP Calculator Service CLI Tool")),console.log(s.gray("Built with Node.js and TypeScript")),console.log(s.gray(`Node.js: ${process.version}`)),console.log(s.gray(`Platform: ${process.platform} ${process.arch}`))}g(vo,"showDetailedInfo");async function bo(){let n=b("\u521D\u59CB\u5316\u914D\u7F6E...").start();try{if(p.configExists()){n.warn("\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728"),console.log(s.yellow("\u5982\u9700\u91CD\u65B0\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u5220\u9664\u73B0\u6709\u7684 xiaozhi.config.json \u6587\u4EF6"));return}p.initConfig(),n.succeed("\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u6210\u529F"),console.log(s.green("\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u521B\u5EFA: xiaozhi.config.json")),console.log(s.yellow("\u{1F4DD} \u8BF7\u7F16\u8F91\u914D\u7F6E\u6587\u4EF6\u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9:")),console.log(s.gray(` \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84: ${p.getConfigPath()}`)),console.log(s.yellow("\u{1F4A1} \u6216\u8005\u4F7F\u7528\u547D\u4EE4\u8BBE\u7F6E:")),console.log(s.gray(" xiaozhi config mcpEndpoint <your-endpoint-url>"))}catch(o){n.fail(`\u521D\u59CB\u5316\u914D\u7F6E\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}g(bo,"initConfig");function wo(){let n=f.dirname(I(import.meta.url)),e=[f.join(n,"..","templates"),f.join(n,"templates"),f.join(n,"..","..","templates")].find(t=>u.existsSync(t));return e?u.readdirSync(e).filter(t=>{let i=f.join(e,t);return u.statSync(i).isDirectory()}):[]}g(wo,"getAvailableTemplates");function Z(n,o){let e=n.length,t=o.length,i=Array(e+1).fill(null).map(()=>Array(t+1).fill(0));for(let c=0;c<=e;c++)i[c][0]=c;for(let c=0;c<=t;c++)i[0][c]=c;for(let c=1;c<=e;c++)for(let a=1;a<=t;a++)n[c-1]===o[a-1]?i[c][a]=i[c-1][a-1]:i[c][a]=Math.min(i[c-1][a]+1,i[c][a-1]+1,i[c-1][a-1]+1);let r=Math.max(e,t);return r===0?1:(r-i[e][t])/r}g(Z,"calculateSimilarity");function xo(n,o){if(o.length===0)return null;let e=o[0],t=Z(n.toLowerCase(),e.toLowerCase());for(let i of o.slice(1)){let r=Z(n.toLowerCase(),i.toLowerCase());r>t&&(t=r,e=i)}return t>.5?e:null}g(xo,"findSimilarTemplate");async function $o(n){if(!process.stdin.isTTY)return console.log("n (\u975E\u4EA4\u4E92\u5F0F\u73AF\u5883)"),!1;let o=await import("readline");return new Promise(e=>{process.stdout.write(n);let t=o.createInterface({input:process.stdin,output:process.stdout}),i=g(r=>{let c=r.trim().toLowerCase();c==="y"||c==="yes"?(t.close(),e(!0)):c==="n"||c==="no"||c===""?(t.close(),e(!1)):process.stdout.write("\u8BF7\u8F93\u5165 y \u6216 n: ")},"handleInput");t.on("line",i),t.on("SIGINT",()=>{t.close(),e(!1)})})}g($o,"askUserConfirmation");function Po(n){let o={mcpEndpoint:"<\u8BF7\u586B\u5199\u4F60\u7684\u63A5\u5165\u70B9\u5730\u5740\uFF08\u83B7\u53D6\u5730\u5740\u5728 xiaozhi.me\uFF09>",mcpServers:{}},e=f.join(n,"xiaozhi.config.json");u.writeFileSync(e,JSON.stringify(o,null,2),"utf8")}g(Po,"createBasicConfig");async function Io(n,o){let e=b("\u521D\u59CB\u5316\u9879\u76EE...").start();try{let t=f.join(process.cwd(),n);if(u.existsSync(t)){e.fail(`\u76EE\u5F55 "${n}" \u5DF2\u5B58\u5728`),console.log(s.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u9009\u62E9\u4E0D\u540C\u7684\u9879\u76EE\u540D\u79F0\u6216\u5220\u9664\u73B0\u6709\u76EE\u5F55"));return}if(o.template){e.text="\u68C0\u67E5\u6A21\u677F...";let i=wo();if(i.length===0){e.fail("\u627E\u4E0D\u5230 templates \u76EE\u5F55"),console.log(s.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u786E\u4FDD xiaozhi-client \u6B63\u786E\u5B89\u88C5"));return}if(!i.includes(o.template)){e.fail(`\u6A21\u677F "${o.template}" \u4E0D\u5B58\u5728`);let h=xo(o.template,i);if(h)if(console.log(s.yellow(`\u{1F4A1} \u4F60\u662F\u60F3\u4F7F\u7528\u6A21\u677F "${h}" \u5417\uFF1F`)),await $o(s.cyan("\u786E\u8BA4\u4F7F\u7528\u6B64\u6A21\u677F\uFF1F(y/n): ")))o.template=h;else{console.log(s.yellow("\u53EF\u7528\u7684\u6A21\u677F:"));for(let C of i)console.log(s.gray(` - ${C}`));return}else{console.log(s.yellow("\u53EF\u7528\u7684\u6A21\u677F:"));for(let y of i)console.log(s.gray(` - ${y}`));return}}let r=f.dirname(I(import.meta.url)),a=[f.join(r,"..","templates"),f.join(r,"templates"),f.join(r,"..","..","templates")].find(h=>u.existsSync(h)),d=f.join(a,o.template);e.text=`\u4ECE\u6A21\u677F "${o.template}" \u521B\u5EFA\u9879\u76EE "${n}"...`,X(d,t,["node_modules",".pnpm-debug.log","pnpm-lock.yaml"]);let m=f.join(t,"xiaozhi.log");u.existsSync(m)||u.writeFileSync(m,"","utf8"),e.succeed(`\u9879\u76EE "${n}" \u521B\u5EFA\u6210\u529F`),console.log(s.green("\u2705 \u9879\u76EE\u521B\u5EFA\u5B8C\u6210!")),console.log(s.yellow("\u{1F4DD} \u63A5\u4E0B\u6765\u7684\u6B65\u9AA4:")),console.log(s.gray(` cd ${n}`)),console.log(s.gray(" pnpm install # \u5B89\u88C5\u4F9D\u8D56")),console.log(s.gray(" # \u7F16\u8F91 xiaozhi.config.json \u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9")),console.log(s.gray(" xiaozhi start # \u542F\u52A8\u670D\u52A1"))}else{e.text=`\u521B\u5EFA\u57FA\u672C\u9879\u76EE "${n}"...`,u.mkdirSync(t,{recursive:!0}),Po(t);let i=f.join(t,"xiaozhi.log");u.writeFileSync(i,"","utf8"),e.succeed(`\u9879\u76EE "${n}" \u521B\u5EFA\u6210\u529F`),console.log(s.green("\u2705 \u57FA\u672C\u9879\u76EE\u521B\u5EFA\u5B8C\u6210!")),console.log(s.yellow("\u{1F4DD} \u63A5\u4E0B\u6765\u7684\u6B65\u9AA4:")),console.log(s.gray(` cd ${n}`)),console.log(s.gray(" # \u7F16\u8F91 xiaozhi.config.json \u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9\u548C\u670D\u52A1")),console.log(s.gray(" xiaozhi start # \u542F\u52A8\u670D\u52A1")),console.log(s.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 --template \u9009\u9879\u53EF\u4EE5\u4ECE\u6A21\u677F\u521B\u5EFA\u9879\u76EE"))}}catch(t){e.fail(`\u521B\u5EFA\u9879\u76EE\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}g(Io,"createProject");function X(n,o,e=[]){u.existsSync(o)||u.mkdirSync(o,{recursive:!0});let t=u.readdirSync(n);for(let i of t){if(e.some(d=>i.includes(d)))continue;let r=f.join(n,i),c=f.join(o,i);u.statSync(r).isDirectory()?X(r,c,e):u.copyFileSync(r,c)}}g(X,"copyDirectory");async function Mo(n,o){let e=b("\u66F4\u65B0\u914D\u7F6E...").start();try{if(!p.configExists()){e.fail("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728"),console.log(s.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E'));return}if(o)switch(n){case"mcpEndpoint":p.updateMcpEndpoint(o),e.succeed(`MCP \u7AEF\u70B9\u5DF2\u66F4\u65B0\u4E3A: ${o}`);break;case"heartbeatInterval":{let t=Number.parseInt(o,10);if(Number.isNaN(t)||t<=0){e.fail("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}p.setHeartbeatInterval(t),e.succeed(`\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}case"heartbeatTimeout":{let t=Number.parseInt(o,10);if(Number.isNaN(t)||t<=0){e.fail("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}p.setHeartbeatTimeout(t),e.succeed(`\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}case"reconnectInterval":{let t=Number.parseInt(o,10);if(Number.isNaN(t)||t<=0){e.fail("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}p.setReconnectInterval(t),e.succeed(`\u91CD\u8FDE\u95F4\u9694\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}default:e.fail(`\u914D\u7F6E\u9879 ${n} \u4E0D\u652F\u6301\u901A\u8FC7\u547D\u4EE4\u884C\u8BBE\u7F6E`),console.log(s.yellow("\u652F\u6301\u8BBE\u7F6E\u7684\u914D\u7F6E\u9879: mcpEndpoint, heartbeatInterval, heartbeatTimeout, reconnectInterval"));return}else{e.text="\u8BFB\u53D6\u914D\u7F6E...";let t=p.getConfig();switch(n){case"mcpEndpoint":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(s.green(`MCP \u7AEF\u70B9: ${t.mcpEndpoint}`));break;case"mcpServers":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(s.green("MCP \u670D\u52A1:"));for(let[i,r]of Object.entries(t.mcpServers))"type"in r&&r.type==="sse"?console.log(s.gray(` ${i}: [SSE] ${r.url}`)):console.log(s.gray(` ${i}: ${r.command} ${r.args.join(" ")}`));break;case"connection":{e.succeed("\u914D\u7F6E\u4FE1\u606F");let i=p.getConnectionConfig();console.log(s.green("\u8FDE\u63A5\u914D\u7F6E:")),console.log(s.gray(` \u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694: ${i.heartbeatInterval}ms`)),console.log(s.gray(` \u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4: ${i.heartbeatTimeout}ms`)),console.log(s.gray(` \u91CD\u8FDE\u95F4\u9694: ${i.reconnectInterval}ms`));break}case"heartbeatInterval":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(s.green(`\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694: ${p.getHeartbeatInterval()}ms`));break;case"heartbeatTimeout":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(s.green(`\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4: ${p.getHeartbeatTimeout()}ms`));break;case"reconnectInterval":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(s.green(`\u91CD\u8FDE\u95F4\u9694: ${p.getReconnectInterval()}ms`));break;default:e.fail(`\u672A\u77E5\u7684\u914D\u7F6E\u9879: ${n}`),console.log(s.yellow("\u652F\u6301\u7684\u914D\u7F6E\u9879: mcpEndpoint, mcpServers, connection, heartbeatInterval, heartbeatTimeout, reconnectInterval"));return}}}catch(t){e.fail(`\u914D\u7F6E\u64CD\u4F5C\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}g(Mo,"configCommand");function Eo(){console.log(s.blue.bold("xiaozhi - MCP Calculator Service CLI")),console.log(),console.log(s.yellow("\u4F7F\u7528\u65B9\u6CD5:")),console.log(" xiaozhi <command> [options]"),console.log(),console.log(s.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(" completion \u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E"),console.log(),console.log(s.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(s.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(s.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(s.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(s.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"),console.log(),console.log(s.yellow("\u81EA\u52A8\u8865\u5168:")),console.log(" xiaozhi completion # \u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E"),console.log(" # \u8BBE\u7F6E\u540E\u53EF\u4F7F\u7528 Tab \u952E\u8FDB\u884C\u547D\u4EE4\u3001\u53C2\u6570\u81EA\u52A8\u8865\u5168")}g(Eo,"showHelp");S.name("xiaozhi").description("MCP Calculator Service CLI Tool").version(B(),"-v, --version","\u663E\u793A\u7248\u672C\u4FE1\u606F").helpOption("-h, --help","\u663E\u793A\u5E2E\u52A9\u4FE1\u606F");S.command("create <projectName>").description("\u521B\u5EFA\u9879\u76EE").option("-t, --template <templateName>","\u4F7F\u7528\u6307\u5B9A\u6A21\u677F\u521B\u5EFA\u9879\u76EE").action(async(n,o)=>{await Io(n,o)});S.command("init").description("\u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6").action(async()=>{await bo()});S.command("config <key> [value]").description("\u67E5\u770B\u6216\u8BBE\u7F6E\u914D\u7F6E").action(async(n,o)=>{await Mo(n,o)});S.command("start").description("\u542F\u52A8\u670D\u52A1").option("-d, --daemon","\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").action(async n=>{await K(n.daemon)});S.command("stop").description("\u505C\u6B62\u670D\u52A1").action(async()=>{await V()});S.command("status").description("\u68C0\u67E5\u670D\u52A1\u72B6\u6001").action(async()=>{await yo()});S.command("attach").description("\u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1\u67E5\u770B\u65E5\u5FD7").action(async()=>{await Co()});S.command("restart").description("\u91CD\u542F\u670D\u52A1").option("-d, --daemon","\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").action(async n=>{await So(n.daemon)});var F=S.command("mcp").description("MCP \u670D\u52A1\u548C\u5DE5\u5177\u7BA1\u7406");F.command("list").description("\u5217\u51FA MCP \u670D\u52A1").option("--tools","\u663E\u793A\u6240\u6709\u670D\u52A1\u7684\u5DE5\u5177\u5217\u8868").action(async n=>{await _(n)});F.command("server <serverName>").description("\u7BA1\u7406\u6307\u5B9A\u7684 MCP \u670D\u52A1").action(async n=>{await G(n)});F.command("tool <serverName> <toolName> <action>").description("\u542F\u7528\u6216\u7981\u7528\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177").action(async(n,o,e)=>{e!=="enable"&&e!=="disable"&&(console.error(s.red("\u9519\u8BEF: \u64CD\u4F5C\u5FC5\u987B\u662F 'enable' \u6216 'disable'")),process.exit(1)),await H(n,o,e==="enable")});S.command("completion").description("\u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E").action(async()=>{N()});S.option("-V","\u663E\u793A\u8BE6\u7EC6\u4FE1\u606F").action(n=>{n.V&&(vo(),process.exit(0))});O();process.argv.length<=2&&(Eo(),process.exit(0));S.parse(process.argv);export{Z as calculateSimilarity,uo as checkEnvironment,mo as formatUptime,M as getServiceStatus,B as getVersion};
|
|
2
|
+
var eo=Object.defineProperty;var l=(n,o)=>eo(n,"name",{value:o,configurable:!0});import{spawn as K}from"child_process";import h from"fs";import bo from"os";import f from"path";import{fileURLToPath as j}from"url";import c from"chalk";import{Command as vo}from"commander";import b from"ora";import ao from"omelette";import{copyFileSync as to,existsSync as A,readFileSync as no,writeFileSync as io}from"fs";import{dirname as ro,resolve as H}from"path";import{fileURLToPath as so}from"url";var co=ro(so(import.meta.url)),k={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},O=class n{static{l(this,"ConfigManager")}static instance;defaultConfigPath;config=null;constructor(){this.defaultConfigPath=H(co,"xiaozhi.config.default.json")}getConfigFilePath(){let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return H(o,"xiaozhi.config.json")}static getInstance(){return n.instance||(n.instance=new n),n.instance}configExists(){let o=this.getConfigFilePath();return A(o)}initConfig(){if(!A(this.defaultConfigPath))throw new Error("\u9ED8\u8BA4\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.default.json \u4E0D\u5B58\u5728");if(this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.json \u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u521D\u59CB\u5316");let o=this.getConfigFilePath();to(this.defaultConfigPath,o),this.config=null}loadConfig(){if(!this.configExists())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");try{let o=this.getConfigFilePath(),e=no(o,"utf8"),t=JSON.parse(e);return this.validateConfig(t),t}catch(o){throw o instanceof SyntaxError?new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF: ${o.message}`):o}}validateConfig(o){if(!o||typeof o!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A\u6839\u5BF9\u8C61\u65E0\u6548");let e=o;if(!e.mcpEndpoint||typeof e.mcpEndpoint!="string")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5B57\u6BB5\u65E0\u6548");if(!e.mcpServers||typeof e.mcpServers!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers \u5B57\u6BB5\u65E0\u6548");for(let[t,i]of Object.entries(e.mcpServers)){if(!i||typeof i!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t} \u65E0\u6548`);let r=i;if(r.type==="sse"){if(!r.url||typeof r.url!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.url \u65E0\u6548`)}else{if(!r.command||typeof r.command!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.command \u65E0\u6548`);if(!Array.isArray(r.args))throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.args \u5FC5\u987B\u662F\u6570\u7EC4`);if(r.env&&typeof r.env!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.env \u5FC5\u987B\u662F\u5BF9\u8C61`)}}}getConfig(){return this.config||(this.config=this.loadConfig()),JSON.parse(JSON.stringify(this.config))}getMcpEndpoint(){return this.getConfig().mcpEndpoint}getMcpServers(){return this.getConfig().mcpServers}getMcpServerConfig(){return this.getConfig().mcpServerConfig||{}}getServerToolsConfig(o){return this.getMcpServerConfig()[o]?.tools||{}}isToolEnabled(o,e){return this.getServerToolsConfig(o)[e]?.enable!==!1}updateMcpEndpoint(o){if(!o||typeof o!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t={...this.getConfig(),mcpEndpoint:o};this.saveConfig(t)}updateMcpServer(o,e){if(!o||typeof o!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if("type"in e&&e.type==="sse"){if(!e.url||typeof e.url!="string")throw new Error("SSE \u670D\u52A1\u914D\u7F6E\u7684 url \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else{let r=e;if(!r.command||typeof r.command!="string")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 command \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!Array.isArray(r.args))throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 args \u5B57\u6BB5\u5FC5\u987B\u662F\u6570\u7EC4");if(r.env&&typeof r.env!="object")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 env \u5B57\u6BB5\u5FC5\u987B\u662F\u5BF9\u8C61")}let t=this.getConfig(),i={...t,mcpServers:{...t.mcpServers,[o]:e}};this.saveConfig(i)}removeMcpServer(o){if(!o||typeof o!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let e=this.getConfig();if(!e.mcpServers[o])throw new Error(`\u670D\u52A1 ${o} \u4E0D\u5B58\u5728`);let t={...e.mcpServers};delete t[o];let i={...e,mcpServers:t};this.saveConfig(i)}updateServerToolsConfig(o,e){let i={...this.getConfig()};i.mcpServerConfig||(i.mcpServerConfig={}),i.mcpServerConfig[o]={tools:e},this.saveConfig(i)}setToolEnabled(o,e,t,i){let s={...this.getConfig()};s.mcpServerConfig||(s.mcpServerConfig={}),s.mcpServerConfig[o]||(s.mcpServerConfig[o]={tools:{}}),s.mcpServerConfig[o].tools[e]={enable:t,...i&&{description:i}},this.saveConfig(s)}saveConfig(o){try{this.validateConfig(o);let e=this.getConfigFilePath(),t=JSON.stringify(o,null,2);io(e,t,"utf8"),this.config=o}catch(e){throw new Error(`\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}reloadConfig(){this.config=null}getConfigPath(){return this.getConfigFilePath()}getDefaultConfigPath(){return this.defaultConfigPath}getConnectionConfig(){let e=this.getConfig().connection||{};return{heartbeatInterval:e.heartbeatInterval??k.heartbeatInterval,heartbeatTimeout:e.heartbeatTimeout??k.heartbeatTimeout,reconnectInterval:e.reconnectInterval??k.reconnectInterval}}getHeartbeatInterval(){return this.getConnectionConfig().heartbeatInterval}getHeartbeatTimeout(){return this.getConnectionConfig().heartbeatTimeout}getReconnectInterval(){return this.getConnectionConfig().reconnectInterval}updateConnectionConfig(o){let e=this.getConfig(),i={...e.connection||{},...o},r={...e,connection:i};this.saveConfig(r)}setHeartbeatInterval(o){if(o<=0)throw new Error("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatInterval:o})}setHeartbeatTimeout(o){if(o<=0)throw new Error("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatTimeout:o})}setReconnectInterval(o){if(o<=0)throw new Error("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({reconnectInterval:o})}getModelScopeConfig(){return this.getConfig().modelscope||{}}getModelScopeApiKey(){return this.getModelScopeConfig().apiKey||process.env.MODELSCOPE_API_TOKEN}updateModelScopeConfig(o){let e=this.getConfig(),i={...e.modelscope||{},...o},r={...e,modelscope:i};this.saveConfig(r)}setModelScopeApiKey(o){if(!o||typeof o!="string")throw new Error("API Key \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");this.updateModelScopeConfig({apiKey:o})}},p=O.getInstance();function lo(){try{if(!p.configExists())return[];let n=p.getMcpServers();return Object.keys(n)}catch{return[]}}l(lo,"getMcpServerNames");function go(n){try{if(!p.configExists())return[];let o=p.getServerToolsConfig(n);return Object.keys(o)}catch{return[]}}l(go,"getServerToolNames");function D(){let n=ao("xiaozhi <command>");if(n.on("command",({reply:o})=>{o(["create","init","config","start","stop","status","attach","restart","mcp","completion"])}),n.on("complete",(o,{line:e,before:t,reply:i})=>{process.env.XIAOZHI_DEBUG_COMPLETION&&console.error(`Debug completion - line: "${e}", before: "${t}", fragment: "${o}"`);let r=e.trim().split(/\s+/),a=e!==e.trim()?r.length:r.length-1;if(r[1]==="mcp"){let m=r[2];if(a===2){let d=["list","server","tool"],u=r[2]||"",y=d.filter(S=>S.startsWith(u));i(y);return}if(a===3){switch(m){case"list":{let d=["--tools"],u=r[3]||"",y=d.filter(S=>S.startsWith(u));i(y);break}case"server":case"tool":{let d=lo(),u=r[3]||"",y=d.filter(S=>S.startsWith(u));i(y);break}default:i([])}return}if(a===4&&m==="tool"){let d=r[3],u=go(d),y=r[4]||"",S=u.filter(x=>x.startsWith(y));i(S);return}if(a===5&&m==="tool"){let d=["enable","disable"],u=r[5]||"",y=d.filter(S=>S.startsWith(u));i(y);return}}if(a===2){switch(r[1]){case"create":i(["--template","-t"]);break;case"start":case"restart":i(["--daemon","-d"]);break;case"completion":i(["install","uninstall"]);break;default:i([])}return}i([])}),process.argv.includes("--completion")){try{console.log(n.setupShellInitFile())}catch(o){console.error("\u751F\u6210\u81EA\u52A8\u8865\u5168\u811A\u672C\u65F6\u51FA\u9519:",o)}process.exit(0)}process.argv.includes("--completion-fish")&&(console.log(n.setupShellInitFile("fish")),process.exit(0)),process.argv.includes("--compzsh")||process.argv.includes("--compbash"),n.init()}l(D,"setupAutoCompletion");function W(){console.log("\u{1F680} xiaozhi \u81EA\u52A8\u8865\u5168\u8BBE\u7F6E"),console.log(),console.log("\u8981\u542F\u7528\u81EA\u52A8\u8865\u5168\uFF0C\u8BF7\u6839\u636E\u4F60\u7684shell\u6267\u884C\u4EE5\u4E0B\u547D\u4EE4\uFF1A"),console.log(),console.log("\u{1F4DD} Zsh (\u63A8\u8350):"),console.log(" xiaozhi --completion >> ~/.xiaozhi-completion.zsh"),console.log(" echo 'source ~/.xiaozhi-completion.zsh' >> ~/.zshrc"),console.log(" source ~/.zshrc"),console.log(),console.log("\u{1F4DD} Bash:"),console.log(" xiaozhi --completion >> ~/.xiaozhi-completion.bash"),console.log(" echo 'source ~/.xiaozhi-completion.bash' >> ~/.bash_profile"),console.log(" source ~/.bash_profile"),console.log(),console.log("\u{1F4DD} Fish:"),console.log(" xiaozhi --completion-fish >> ~/.config/fish/completions/xiaozhi.fish"),console.log(),console.log("\u2728 \u8BBE\u7F6E\u5B8C\u6210\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u4F7F\u7528 Tab \u952E\u8FDB\u884C\u81EA\u52A8\u8865\u5168\u4E86\uFF01"),console.log(),console.log("\u{1F4A1} \u793A\u4F8B:"),console.log(" xiaozhi m<Tab> # \u2192 mcp"),console.log(" xiaozhi mcp l<Tab> # \u2192 list"),console.log(" xiaozhi mcp tool <Tab> # \u2192 \u663E\u793A\u6240\u6709\u670D\u52A1\u5668\u540D\u79F0")}l(W,"showCompletionHelp");import E from"fs";import po from"path";import P from"chalk";import{createConsola as fo}from"consola";function mo(n){let o=n.getFullYear(),e=String(n.getMonth()+1).padStart(2,"0"),t=String(n.getDate()).padStart(2,"0"),i=String(n.getHours()).padStart(2,"0"),r=String(n.getMinutes()).padStart(2,"0"),s=String(n.getSeconds()).padStart(2,"0");return`${o}-${e}-${t} ${i}:${r}:${s}`}l(mo,"formatDateTime");var I=class{static{l(this,"Logger")}logFilePath=null;writeStream=null;consolaInstance;constructor(){this.consolaInstance=fo({formatOptions:{date:!1,colors:!0,compact:!0},fancy:!1}),this.consolaInstance.setReporters([{log:l(o=>{let e={info:"INFO",success:"SUCCESS",warn:"WARN",error:"ERROR",debug:"DEBUG",log:"LOG"},t={info:P.blue,success:P.green,warn:P.yellow,error:P.red,debug:P.gray,log:l(d=>d,"log")},i=e[o.type]||o.type.toUpperCase(),r=t[o.type]||(d=>d),s=mo(new Date),a=r(`[${i}]`),m=`[${s}] ${a} ${o.args.join(" ")}`;console.error(m)},"log")}])}initLogFile(o){this.logFilePath=po.join(o,"xiaozhi.log"),E.existsSync(this.logFilePath)||E.writeFileSync(this.logFilePath,""),this.writeStream=E.createWriteStream(this.logFilePath,{flags:"a",encoding:"utf8"})}logToFile(o,e,...t){if(this.writeStream){let r=`[${new Date().toISOString()}] [${o.toUpperCase()}] ${e}`,s=t.length>0?`${r} ${t.map(a=>typeof a=="object"?JSON.stringify(a):String(a)).join(" ")}`:r;this.writeStream.write(`${s}
|
|
3
|
+
`)}}enableFileLogging(o){o&&!this.writeStream&&this.logFilePath?this.writeStream=E.createWriteStream(this.logFilePath,{flags:"a",encoding:"utf8"}):!o&&this.writeStream&&(this.writeStream.end(),this.writeStream=null)}info(o,...e){this.consolaInstance.info(o,...e),this.logToFile("info",o,...e)}success(o,...e){this.consolaInstance.success(o,...e),this.logToFile("success",o,...e)}warn(o,...e){this.consolaInstance.warn(o,...e),this.logToFile("warn",o,...e)}error(o,...e){this.consolaInstance.error(o,...e),this.logToFile("error",o,...e)}debug(o,...e){this.consolaInstance.debug(o,...e),this.logToFile("debug",o,...e)}log(o,...e){this.consolaInstance.log(o,...e),this.logToFile("log",o,...e)}withTag(o){return this}close(){this.writeStream&&(this.writeStream.end(),this.writeStream=null)}},T=new I;import g from"chalk";import L from"cli-table3";import F from"ora";function U(n){let o=0;for(let e of n)/[\u4e00-\u9fff\u3400-\u4dbf\uff00-\uffef]/.test(e)?o+=2:o+=1;return o}l(U,"getDisplayWidth");function J(n,o){if(U(n)<=o)return n;if(o<=3)return"";let e="",t=0,i=!1;for(let r of n){let s=/[\u4e00-\u9fff\u3400-\u4dbf\uff00-\uffef]/.test(r)?2:1;if(t+s>o-3){if(!i)return"";e+="...";break}e+=r,t+=s,i=!0}return e}l(J,"truncateToWidth");async function G(n={}){let o=F("\u83B7\u53D6 MCP \u670D\u52A1\u5217\u8868...").start();try{let e=p.getMcpServers(),t=Object.keys(e);if(t.length===0){o.warn("\u672A\u914D\u7F6E\u4EFB\u4F55 MCP \u670D\u52A1"),console.log(g.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi config' \u547D\u4EE4\u914D\u7F6E MCP \u670D\u52A1"));return}if(o.succeed(`\u627E\u5230 ${t.length} \u4E2A MCP \u670D\u52A1`),n.tools){console.log(),console.log(g.bold("MCP \u670D\u52A1\u5DE5\u5177\u5217\u8868:")),console.log();let i=8,r=[];for(let a of t){let m=p.getServerToolsConfig(a),d=Object.keys(m);r.push(...d)}for(let a of r){let m=U(a);m>i&&(i=m)}i=Math.max(10,Math.min(i+2,30));let s=new L({head:[g.bold("MCP"),g.bold("\u5DE5\u5177\u540D\u79F0"),g.bold("\u72B6\u6001"),g.bold("\u63CF\u8FF0")],colWidths:[15,i,8,40],wordWrap:!0,style:{head:[],border:[]}});for(let a of t){let m=p.getServerToolsConfig(a),d=Object.keys(m);if(d.length===0)s.push([g.gray(a),g.gray("(\u65E0\u5DE5\u5177)"),g.gray("-"),g.gray("\u8BF7\u5148\u542F\u52A8\u670D\u52A1\u626B\u63CF\u5DE5\u5177")]);else{s.length>0&&s.push([{colSpan:4,content:""}]);for(let u of d){let y=m[u],S=y.enable?g.green("\u542F\u7528"):g.red("\u7981\u7528"),x=J(y.description||"",32);s.push([a,u,S,x])}}}console.log(s.toString())}else{console.log(),console.log(g.bold("MCP \u670D\u52A1\u5217\u8868:")),console.log();for(let i of t){let r=e[i],s=p.getServerToolsConfig(i),a=Object.keys(s).length,m=Object.values(s).filter(d=>d.enable!==!1).length;console.log(`${g.cyan("\u2022")} ${g.bold(i)}`),"type"in r&&r.type==="sse"?(console.log(` \u7C7B\u578B: ${g.gray("SSE")}`),console.log(` URL: ${g.gray(r.url)}`)):console.log(` \u547D\u4EE4: ${g.gray(r.command)} ${g.gray(r.args.join(" "))}`),a>0?console.log(` \u5DE5\u5177: ${g.green(m)} \u542F\u7528 / ${g.yellow(a)} \u603B\u8BA1`):console.log(` \u5DE5\u5177: ${g.gray("\u672A\u626B\u63CF (\u8BF7\u5148\u542F\u52A8\u670D\u52A1)")}`),console.log()}}console.log(g.gray("\u{1F4A1} \u63D0\u793A:")),console.log(g.gray(" - \u4F7F\u7528 'xiaozhi mcp list --tools' \u67E5\u770B\u6240\u6709\u5DE5\u5177")),console.log(g.gray(" - \u4F7F\u7528 'xiaozhi mcp <\u670D\u52A1\u540D> list' \u67E5\u770B\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177")),console.log(g.gray(" - \u4F7F\u7528 'xiaozhi mcp <\u670D\u52A1\u540D> <\u5DE5\u5177\u540D> enable/disable' \u542F\u7528/\u7981\u7528\u5DE5\u5177"))}catch(e){o.fail("\u83B7\u53D6 MCP \u670D\u52A1\u5217\u8868\u5931\u8D25"),console.error(g.red(`\u9519\u8BEF: ${e instanceof Error?e.message:String(e)}`)),process.exit(1)}}l(G,"listMcpServers");async function _(n){let o=F(`\u83B7\u53D6 ${n} \u670D\u52A1\u7684\u5DE5\u5177\u5217\u8868...`).start();try{if(!p.getMcpServers()[n]){o.fail(`\u670D\u52A1 '${n}' \u4E0D\u5B58\u5728`),console.log(g.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp list' \u67E5\u770B\u6240\u6709\u53EF\u7528\u670D\u52A1"));return}let t=p.getServerToolsConfig(n),i=Object.keys(t);if(i.length===0){o.warn(`\u670D\u52A1 '${n}' \u6682\u65E0\u5DE5\u5177\u4FE1\u606F`),console.log(g.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u542F\u52A8\u670D\u52A1\u4EE5\u626B\u63CF\u5DE5\u5177\u5217\u8868"));return}o.succeed(`\u670D\u52A1 '${n}' \u5171\u6709 ${i.length} \u4E2A\u5DE5\u5177`),console.log(),console.log(g.bold(`${n} \u670D\u52A1\u5DE5\u5177\u5217\u8868:`)),console.log();let r=new L({head:[g.bold("\u5DE5\u5177\u540D\u79F0"),g.bold("\u72B6\u6001"),g.bold("\u63CF\u8FF0")],colWidths:[30,8,50],wordWrap:!0,style:{head:[],border:[]}});for(let s of i){let a=t[s],m=a.enable?g.green("\u542F\u7528"):g.red("\u7981\u7528"),d=J(a.description||"",40);r.push([s,m,d])}console.log(r.toString()),console.log(),console.log(g.gray("\u{1F4A1} \u63D0\u793A:")),console.log(g.gray(` - \u4F7F\u7528 'xiaozhi mcp ${n} <\u5DE5\u5177\u540D> enable' \u542F\u7528\u5DE5\u5177`)),console.log(g.gray(` - \u4F7F\u7528 'xiaozhi mcp ${n} <\u5DE5\u5177\u540D> disable' \u7981\u7528\u5DE5\u5177`))}catch(e){o.fail("\u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25"),console.error(g.red(`\u9519\u8BEF: ${e instanceof Error?e.message:String(e)}`)),process.exit(1)}}l(_,"listServerTools");async function B(n,o,e){let t=e?"\u542F\u7528":"\u7981\u7528",i=F(`${t}\u5DE5\u5177 ${n}/${o}...`).start();try{if(!p.getMcpServers()[n]){i.fail(`\u670D\u52A1 '${n}' \u4E0D\u5B58\u5728`),console.log(g.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp list' \u67E5\u770B\u6240\u6709\u53EF\u7528\u670D\u52A1"));return}let s=p.getServerToolsConfig(n);if(!s[o]){i.fail(`\u5DE5\u5177 '${o}' \u5728\u670D\u52A1 '${n}' \u4E2D\u4E0D\u5B58\u5728`),console.log(g.yellow(`\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp ${n} list' \u67E5\u770B\u8BE5\u670D\u52A1\u7684\u6240\u6709\u5DE5\u5177`));return}p.setToolEnabled(n,o,e,s[o].description),i.succeed(`\u6210\u529F${t}\u5DE5\u5177 ${g.cyan(n)}/${g.cyan(o)}`),console.log(),console.log(g.gray("\u{1F4A1} \u63D0\u793A: \u5DE5\u5177\u72B6\u6001\u66F4\u6539\u5C06\u5728\u4E0B\u6B21\u542F\u52A8\u670D\u52A1\u65F6\u751F\u6548"))}catch(r){i.fail(`${t}\u5DE5\u5177\u5931\u8D25`),console.error(g.red(`\u9519\u8BEF: ${r instanceof Error?r.message:String(r)}`)),process.exit(1)}}l(B,"setToolEnabled");import{existsSync as N}from"fs";import{readFile as Z}from"fs/promises";import{createServer as ho}from"http";import{dirname as uo,join as w}from"path";import{parse as yo}from"url";import{fileURLToPath as So}from"url";import{WebSocketServer as Co}from"ws";var M=class{static{l(this,"WebServer")}httpServer;wss;logger;port;clientInfo={status:"disconnected",mcpEndpoint:"",activeMCPServers:[]};heartbeatTimeout;HEARTBEAT_TIMEOUT=35e3;constructor(o=9999){this.port=o,this.logger=new I,this.httpServer=ho((e,t)=>{this.handleHttpRequest(e,t)}),this.wss=new Co({server:this.httpServer}),this.setupWebSocket()}async handleHttpRequest(o,e){let{pathname:t}=yo(o.url||"",!0);if(e.setHeader("Access-Control-Allow-Origin","*"),e.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type"),o.method==="OPTIONS"){e.writeHead(200),e.end();return}try{if(o.method==="GET"&&!t?.startsWith("/api/")){await this.serveStaticFile(t||"/",e);return}if(t==="/api/config"&&o.method==="GET"){let i=p.getConfig();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(i))}else if(t==="/api/config"&&o.method==="PUT"){let i="";o.on("data",r=>{i+=r.toString()}),o.on("end",async()=>{try{let r=JSON.parse(i);this.updateConfig(r),e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({success:!0})),this.broadcastConfigUpdate(r)}catch(r){e.writeHead(400,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:r instanceof Error?r.message:String(r)}))}})}else t==="/api/status"&&o.method==="GET"?(e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(this.clientInfo))):(e.writeHead(404),e.end("Not Found"))}catch(i){this.logger.error("HTTP request error:",i),e.writeHead(500,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"Internal Server Error"}))}}async serveStaticFile(o,e){try{let t=uo(So(import.meta.url)),r=[w(t,"..","web","dist"),w(t,"..","web"),w(process.cwd(),"web","dist"),w(process.cwd(),"web")].find(S=>N(S));if(!r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(`
|
|
4
|
+
<!DOCTYPE html>
|
|
5
|
+
<html>
|
|
6
|
+
<head>
|
|
7
|
+
<title>\u5C0F\u667A\u914D\u7F6E\u7BA1\u7406</title>
|
|
8
|
+
<meta charset="utf-8">
|
|
9
|
+
<style>
|
|
10
|
+
body { font-family: sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; }
|
|
11
|
+
.error { color: #e53e3e; background: #fed7d7; padding: 20px; border-radius: 8px; }
|
|
12
|
+
</style>
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
<h1>\u5C0F\u667A\u914D\u7F6E\u7BA1\u7406</h1>
|
|
16
|
+
<div class="error">
|
|
17
|
+
<p>\u9519\u8BEF\uFF1A\u627E\u4E0D\u5230\u524D\u7AEF\u8D44\u6E90\u6587\u4EF6\u3002</p>
|
|
18
|
+
<p>\u8BF7\u5148\u6784\u5EFA\u524D\u7AEF\u9879\u76EE\uFF1A</p>
|
|
19
|
+
<pre>cd web && pnpm install && pnpm build</pre>
|
|
20
|
+
</div>
|
|
21
|
+
</body>
|
|
22
|
+
</html>
|
|
23
|
+
`);return}let s=o;if(s==="/"&&(s="/index.html"),s.includes("..")){e.writeHead(403),e.end("Forbidden");return}let a=w(r,s);if(!N(a)){let S=w(r,"index.html");if(N(S)){let x=await Z(S);e.writeHead(200,{"Content-Type":"text/html"}),e.end(x)}else e.writeHead(404),e.end("Not Found");return}let m=await Z(a),d=a.split(".").pop()?.toLowerCase(),y={html:"text/html",js:"application/javascript",css:"text/css",json:"application/json",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",svg:"image/svg+xml",ico:"image/x-icon"}[d||""]||"application/octet-stream";e.writeHead(200,{"Content-Type":y}),e.end(m)}catch(t){this.logger.error("Serve static file error:",t),e.writeHead(500),e.end("Internal Server Error")}}setupWebSocket(){this.wss.on("connection",o=>{this.logger.info("WebSocket client connected"),o.on("message",async e=>{try{let t=JSON.parse(e.toString());await this.handleWebSocketMessage(o,t)}catch(t){this.logger.error("WebSocket message error:",t),o.send(JSON.stringify({type:"error",error:t instanceof Error?t.message:String(t)}))}}),o.on("close",()=>{this.logger.info("WebSocket client disconnected")}),this.sendInitialData(o)})}async handleWebSocketMessage(o,e){switch(e.type){case"getConfig":{let t=p.getConfig();o.send(JSON.stringify({type:"config",data:t}));break}case"updateConfig":this.updateConfig(e.config),this.broadcastConfigUpdate(e.config);break;case"getStatus":o.send(JSON.stringify({type:"status",data:this.clientInfo}));break;case"clientStatus":this.updateClientInfo(e.data),this.broadcastStatusUpdate();break}}async sendInitialData(o){let e=p.getConfig();o.send(JSON.stringify({type:"config",data:e})),o.send(JSON.stringify({type:"status",data:this.clientInfo}))}broadcastConfigUpdate(o){let e=JSON.stringify({type:"configUpdate",data:o});for(let t of this.wss.clients)t.readyState===1&&t.send(e)}broadcastStatusUpdate(){let o=JSON.stringify({type:"statusUpdate",data:this.clientInfo});for(let e of this.wss.clients)e.readyState===1&&e.send(o)}updateClientInfo(o){this.clientInfo={...this.clientInfo,...o},o.lastHeartbeat&&(this.clientInfo.lastHeartbeat=Date.now()),o.status==="connected"&&this.resetHeartbeatTimeout()}resetHeartbeatTimeout(){this.heartbeatTimeout&&clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=setTimeout(()=>{this.logger.warn("\u5BA2\u6237\u7AEF\u5FC3\u8DF3\u8D85\u65F6\uFF0C\u6807\u8BB0\u4E3A\u65AD\u5F00\u8FDE\u63A5"),this.updateClientInfo({status:"disconnected"}),this.broadcastStatusUpdate()},this.HEARTBEAT_TIMEOUT)}updateConfig(o){o.mcpEndpoint!==p.getMcpEndpoint()&&p.updateMcpEndpoint(o.mcpEndpoint);let e=p.getMcpServers();for(let[t,i]of Object.entries(o.mcpServers))JSON.stringify(e[t])!==JSON.stringify(i)&&p.updateMcpServer(t,i);for(let t of Object.keys(e))t in o.mcpServers||p.removeMcpServer(t);if(o.connection&&p.updateConnectionConfig(o.connection),o.modelscope&&p.updateModelScopeConfig(o.modelscope),o.mcpServerConfig)for(let[t,i]of Object.entries(o.mcpServerConfig))for(let[r,s]of Object.entries(i.tools))p.setToolEnabled(t,r,s.enable)}updateStatus(o){this.updateClientInfo(o),this.broadcastStatusUpdate()}start(){return new Promise((o,e)=>{this.httpServer.listen(this.port,()=>{this.logger.info(`Web server listening on http://localhost:${this.port}`),o()}).on("error",e)})}stop(){return new Promise(o=>{this.heartbeatTimeout&&(clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=void 0),this.wss.close(()=>{this.httpServer.close(()=>{this.logger.info("Web server stopped"),o()})})})}};var C=new vo,wo="xiaozhi-mcp-service";function Y(){try{let n=j(import.meta.url),o=f.dirname(n),e=[f.join(o,"..","package.json"),f.join(o,"..","package.json"),f.join(o,"..","..","package.json"),f.join(o,"package.json")];for(let t of e)if(h.existsSync(t)){let i=JSON.parse(h.readFileSync(t,"utf8"));if(i.version)return i.version}return"unknown"}catch(n){return console.warn("\u65E0\u6CD5\u4ECE package.json \u8BFB\u53D6\u7248\u672C\u4FE1\u606F:",n),"unknown"}}l(Y,"getVersion");var v=f.join(bo.tmpdir(),`${wo}.pid`);function z(){try{if(!h.existsSync(v))return{running:!1};let n=h.readFileSync(v,"utf8").trim(),[o,e,t]=n.split("|"),i=Number.parseInt(o);if(Number.isNaN(i))return h.unlinkSync(v),{running:!1};try{process.kill(i,0);let r=Number.parseInt(e),s=xo(Date.now()-r);return{running:!0,pid:i,uptime:s,mode:t||"foreground"}}catch{return h.unlinkSync(v),{running:!1}}}catch{return{running:!1}}}l(z,"getServiceStatus");function xo(n){let o=Math.floor(n/1e3),e=Math.floor(o/60),t=Math.floor(e/60),i=Math.floor(t/24);return i>0?`${i}\u5929 ${t%24}\u5C0F\u65F6 ${e%60}\u5206\u949F`:t>0?`${t}\u5C0F\u65F6 ${e%60}\u5206\u949F`:e>0?`${e}\u5206\u949F ${o%60}\u79D2`:`${o}\u79D2`}l(xo,"formatUptime");function V(n,o){let e=`${n}|${Date.now()}|${o}`;h.writeFileSync(v,e)}l(V,"savePidInfo");function $(){try{h.existsSync(v)&&h.unlinkSync(v)}catch{}}l($,"cleanupPidFile");function Po(){if(!p.configExists())return console.error(c.red("\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728")),console.log(c.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E')),!1;try{let n=p.getMcpEndpoint();return!n||n.includes("<\u8BF7\u586B\u5199")?(console.error(c.red("\u274C \u9519\u8BEF: MCP \u7AEF\u70B9\u672A\u914D\u7F6E")),console.log(c.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi config mcpEndpoint <your-endpoint-url>" \u8BBE\u7F6E\u7AEF\u70B9')),!1):!0}catch(n){return console.error(c.red(`\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u65E0\u6548 - ${n instanceof Error?n.message:String(n)}`)),console.log(c.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u91CD\u65B0\u521D\u59CB\u5316\u914D\u7F6E')),!1}}l(Po,"checkEnvironment");function Io(){let n=f.dirname(j(import.meta.url)),o;return n.includes("js-demo/dist")?o=n:o=[f.join(n,"..","js-demo","dist"),f.join(n,"..","..","js-demo","dist"),f.join(n,"..","..","..","js-demo","dist"),f.join(process.cwd(),"js-demo","dist"),f.join(process.cwd(),"dist")].find(t=>h.existsSync(f.join(t,"mcpPipe.js"))&&h.existsSync(f.join(t,"mcpServerProxy.js")))||n,{command:"node",args:["mcpPipe.js","mcpServerProxy.js"],cwd:o}}l(Io,"getServiceCommand");async function Q(n=!1){let o=b("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let e=z();if(e.running){o.fail(`\u670D\u52A1\u5DF2\u7ECF\u5728\u8FD0\u884C (PID: ${e.pid})`);return}if(o.text="\u68C0\u67E5\u73AF\u5883\u914D\u7F6E...",!Po()){o.fail("\u73AF\u5883\u914D\u7F6E\u68C0\u67E5\u5931\u8D25");return}let{command:t,args:i,cwd:r}=Io();if(o.text=`\u542F\u52A8\u670D\u52A1 (${n?"\u540E\u53F0\u6A21\u5F0F":"\u524D\u53F0\u6A21\u5F0F"})...`,n){let s=K(t,i,{cwd:r,detached:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd(),XIAOZHI_DAEMON:"true"}});V(s.pid,"daemon");let a=process.cwd();T.initLogFile(a),T.enableFileLogging(!0);let m=f.join(a,"xiaozhi.log"),d=h.createWriteStream(m,{flags:"a"});s.stdout?.pipe(d),s.stderr?.pipe(d),s.on("exit",(u,y)=>{u!==0&&u!==null&&T.error(`\u540E\u53F0\u670D\u52A1\u5F02\u5E38\u9000\u51FA (\u4EE3\u7801: ${u}, \u4FE1\u53F7: ${y})`),$()}),s.on("error",u=>{T.error(`\u540E\u53F0\u670D\u52A1\u542F\u52A8\u9519\u8BEF: ${u.message}`),$(),o.fail(`\u540E\u53F0\u670D\u52A1\u542F\u52A8\u5931\u8D25: ${u.message}`)}),s.unref(),o.succeed(`\u670D\u52A1\u5DF2\u5728\u540E\u53F0\u542F\u52A8 (PID: ${s.pid})`),console.log(c.gray(`\u65E5\u5FD7\u6587\u4EF6: ${m}`)),console.log(c.gray("\u4F7F\u7528 'xiaozhi attach' \u53EF\u4EE5\u67E5\u770B\u5B9E\u65F6\u65E5\u5FD7"))}else{o.succeed("\u670D\u52A1\u542F\u52A8\u4E2D...");let s=K(t,i,{cwd:r,stdio:"inherit",env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd()}});V(s.pid,"foreground"),s.on("exit",(a,m)=>{$(),console.log(a!==0?c.red(`
|
|
24
|
+
\u670D\u52A1\u5F02\u5E38\u9000\u51FA (\u4EE3\u7801: ${a}, \u4FE1\u53F7: ${m})`):c.green(`
|
|
25
|
+
\u670D\u52A1\u5DF2\u505C\u6B62`))}),process.on("SIGINT",()=>{console.log(c.yellow(`
|
|
26
|
+
\u6B63\u5728\u505C\u6B62\u670D\u52A1...`)),s.kill("SIGTERM")}),process.on("SIGTERM",()=>{s.kill("SIGTERM")})}}catch(e){o.fail(`\u542F\u52A8\u670D\u52A1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}l(Q,"startService");async function q(){let n=b("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let o=z();if(!o.running){n.warn("\u670D\u52A1\u672A\u5728\u8FD0\u884C");return}n.text=`\u505C\u6B62\u670D\u52A1 (PID: ${o.pid})...`;try{process.kill(o.pid,"SIGTERM");let e=0,t=30;for(;e<t;){await new Promise(i=>setTimeout(i,100));try{process.kill(o.pid,0),e++}catch{break}}try{process.kill(o.pid,0),n.text="\u5F3A\u5236\u505C\u6B62\u670D\u52A1...",process.kill(o.pid,"SIGKILL"),await new Promise(i=>setTimeout(i,500))}catch{}$(),n.succeed("\u670D\u52A1\u5DF2\u505C\u6B62")}catch(e){$(),n.fail(`\u505C\u6B62\u670D\u52A1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}catch(o){n.fail(`\u505C\u6B62\u670D\u52A1\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}l(q,"stopService");async function To(){let n=b("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let o=z();if(o.running){if(n.succeed("\u670D\u52A1\u72B6\u6001"),console.log(c.green("\u2705 \u670D\u52A1\u6B63\u5728\u8FD0\u884C")),console.log(c.gray(` PID: ${o.pid}`)),console.log(c.gray(` \u8FD0\u884C\u65F6\u95F4: ${o.uptime}`)),console.log(c.gray(` \u8FD0\u884C\u6A21\u5F0F: ${o.mode==="daemon"?"\u540E\u53F0\u6A21\u5F0F":"\u524D\u53F0\u6A21\u5F0F"}`)),o.mode==="daemon"){let e=f.join(process.cwd(),"xiaozhi.log");console.log(c.gray(` \u65E5\u5FD7\u6587\u4EF6: ${e}`))}}else n.succeed("\u670D\u52A1\u72B6\u6001"),console.log(c.red("\u274C \u670D\u52A1\u672A\u8FD0\u884C"))}catch(o){n.fail(`\u68C0\u67E5\u72B6\u6001\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}l(To,"checkStatus");async function $o(){let n=b("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let o=z();if(!o.running){n.fail("\u670D\u52A1\u672A\u5728\u8FD0\u884C");return}if(o.mode!=="daemon"){n.fail("\u670D\u52A1\u4E0D\u662F\u5728\u540E\u53F0\u6A21\u5F0F\u8FD0\u884C");return}n.succeed("\u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1..."),console.log(c.green(`\u5DF2\u8FDE\u63A5\u5230\u670D\u52A1 (PID: ${o.pid})`)),console.log(c.gray("\u6309 Ctrl+C \u53EF\u4EE5\u65AD\u5F00\u8FDE\u63A5\uFF08\u4E0D\u4F1A\u505C\u6B62\u670D\u52A1\uFF09")),console.log(c.gray("=".repeat(50)));let e=f.join(process.cwd(),"xiaozhi.log");if(h.existsSync(e))if(process.platform==="win32"){let{spawn:t}=await import("child_process"),i=t("powershell",["-Command",`Get-Content -Path "${e}" -Wait`],{stdio:"inherit"});process.on("SIGINT",()=>{console.log(c.yellow(`
|
|
27
|
+
\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{let{spawn:t}=await import("child_process"),i=t("tail",["-f",e],{stdio:"inherit"});process.on("SIGINT",()=>{console.log(c.yellow(`
|
|
28
|
+
\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(c.yellow("\u65E5\u5FD7\u6587\u4EF6\u4E0D\u5B58\u5728"))}catch(o){n.fail(`\u8FDE\u63A5\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}l($o,"attachService");async function Eo(n=!1){console.log(c.blue("\u{1F504} \u91CD\u542F\u670D\u52A1...")),await q(),await new Promise(o=>setTimeout(o,1e3)),await Q(n)}l(Eo,"restartService");function Mo(){let n=Y();console.log(c.blue(`xiaozhi v${n}`)),console.log(c.gray("MCP Calculator Service CLI Tool")),console.log(c.gray("Built with Node.js and TypeScript")),console.log(c.gray(`Node.js: ${process.version}`)),console.log(c.gray(`Platform: ${process.platform} ${process.arch}`))}l(Mo,"showDetailedInfo");async function jo(){let n=b("\u521D\u59CB\u5316\u914D\u7F6E...").start();try{if(p.configExists()){n.warn("\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728"),console.log(c.yellow("\u5982\u9700\u91CD\u65B0\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u5220\u9664\u73B0\u6709\u7684 xiaozhi.config.json \u6587\u4EF6"));return}p.initConfig(),n.succeed("\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u6210\u529F"),console.log(c.green("\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u521B\u5EFA: xiaozhi.config.json")),console.log(c.yellow("\u{1F4DD} \u8BF7\u7F16\u8F91\u914D\u7F6E\u6587\u4EF6\u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9:")),console.log(c.gray(` \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84: ${p.getConfigPath()}`)),console.log(c.yellow("\u{1F4A1} \u6216\u8005\u4F7F\u7528\u547D\u4EE4\u8BBE\u7F6E:")),console.log(c.gray(" xiaozhi config mcpEndpoint <your-endpoint-url>"))}catch(o){n.fail(`\u521D\u59CB\u5316\u914D\u7F6E\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}l(jo,"initConfig");function zo(){let n=f.dirname(j(import.meta.url)),e=[f.join(n,"..","templates"),f.join(n,"templates"),f.join(n,"..","..","templates")].find(t=>h.existsSync(t));return e?h.readdirSync(e).filter(t=>{let i=f.join(e,t);return h.statSync(i).isDirectory()}):[]}l(zo,"getAvailableTemplates");function X(n,o){let e=n.length,t=o.length,i=Array(e+1).fill(null).map(()=>Array(t+1).fill(0));for(let s=0;s<=e;s++)i[s][0]=s;for(let s=0;s<=t;s++)i[0][s]=s;for(let s=1;s<=e;s++)for(let a=1;a<=t;a++)n[s-1]===o[a-1]?i[s][a]=i[s-1][a-1]:i[s][a]=Math.min(i[s-1][a]+1,i[s][a-1]+1,i[s-1][a-1]+1);let r=Math.max(e,t);return r===0?1:(r-i[e][t])/r}l(X,"calculateSimilarity");function ko(n,o){if(o.length===0)return null;let e=o[0],t=X(n.toLowerCase(),e.toLowerCase());for(let i of o.slice(1)){let r=X(n.toLowerCase(),i.toLowerCase());r>t&&(t=r,e=i)}return t>.5?e:null}l(ko,"findSimilarTemplate");async function Oo(n){if(!process.stdin.isTTY)return console.log("n (\u975E\u4EA4\u4E92\u5F0F\u73AF\u5883)"),!1;let o=await import("readline");return new Promise(e=>{process.stdout.write(n);let t=o.createInterface({input:process.stdin,output:process.stdout}),i=l(r=>{let s=r.trim().toLowerCase();s==="y"||s==="yes"?(t.close(),e(!0)):s==="n"||s==="no"||s===""?(t.close(),e(!1)):process.stdout.write("\u8BF7\u8F93\u5165 y \u6216 n: ")},"handleInput");t.on("line",i),t.on("SIGINT",()=>{t.close(),e(!1)})})}l(Oo,"askUserConfirmation");function Fo(n){let o={mcpEndpoint:"<\u8BF7\u586B\u5199\u4F60\u7684\u63A5\u5165\u70B9\u5730\u5740\uFF08\u83B7\u53D6\u5730\u5740\u5728 xiaozhi.me\uFF09>",mcpServers:{}},e=f.join(n,"xiaozhi.config.json");h.writeFileSync(e,JSON.stringify(o,null,2),"utf8")}l(Fo,"createBasicConfig");async function No(n,o){let e=b("\u521D\u59CB\u5316\u9879\u76EE...").start();try{let t=f.join(process.cwd(),n);if(h.existsSync(t)){e.fail(`\u76EE\u5F55 "${n}" \u5DF2\u5B58\u5728`),console.log(c.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u9009\u62E9\u4E0D\u540C\u7684\u9879\u76EE\u540D\u79F0\u6216\u5220\u9664\u73B0\u6709\u76EE\u5F55"));return}if(o.template){e.text="\u68C0\u67E5\u6A21\u677F...";let i=zo();if(i.length===0){e.fail("\u627E\u4E0D\u5230 templates \u76EE\u5F55"),console.log(c.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u786E\u4FDD xiaozhi-client \u6B63\u786E\u5B89\u88C5"));return}if(!i.includes(o.template)){e.fail(`\u6A21\u677F "${o.template}" \u4E0D\u5B58\u5728`);let u=ko(o.template,i);if(u)if(console.log(c.yellow(`\u{1F4A1} \u4F60\u662F\u60F3\u4F7F\u7528\u6A21\u677F "${u}" \u5417\uFF1F`)),await Oo(c.cyan("\u786E\u8BA4\u4F7F\u7528\u6B64\u6A21\u677F\uFF1F(y/n): ")))o.template=u;else{console.log(c.yellow("\u53EF\u7528\u7684\u6A21\u677F:"));for(let S of i)console.log(c.gray(` - ${S}`));return}else{console.log(c.yellow("\u53EF\u7528\u7684\u6A21\u677F:"));for(let y of i)console.log(c.gray(` - ${y}`));return}}let r=f.dirname(j(import.meta.url)),a=[f.join(r,"..","templates"),f.join(r,"templates"),f.join(r,"..","..","templates")].find(u=>h.existsSync(u)),m=f.join(a,o.template);e.text=`\u4ECE\u6A21\u677F "${o.template}" \u521B\u5EFA\u9879\u76EE "${n}"...`,oo(m,t,["node_modules",".pnpm-debug.log","pnpm-lock.yaml"]);let d=f.join(t,"xiaozhi.log");h.existsSync(d)||h.writeFileSync(d,"","utf8"),e.succeed(`\u9879\u76EE "${n}" \u521B\u5EFA\u6210\u529F`),console.log(c.green("\u2705 \u9879\u76EE\u521B\u5EFA\u5B8C\u6210!")),console.log(c.yellow("\u{1F4DD} \u63A5\u4E0B\u6765\u7684\u6B65\u9AA4:")),console.log(c.gray(` cd ${n}`)),console.log(c.gray(" pnpm install # \u5B89\u88C5\u4F9D\u8D56")),console.log(c.gray(" # \u7F16\u8F91 xiaozhi.config.json \u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9")),console.log(c.gray(" xiaozhi start # \u542F\u52A8\u670D\u52A1"))}else{e.text=`\u521B\u5EFA\u57FA\u672C\u9879\u76EE "${n}"...`,h.mkdirSync(t,{recursive:!0}),Fo(t);let i=f.join(t,"xiaozhi.log");h.writeFileSync(i,"","utf8"),e.succeed(`\u9879\u76EE "${n}" \u521B\u5EFA\u6210\u529F`),console.log(c.green("\u2705 \u57FA\u672C\u9879\u76EE\u521B\u5EFA\u5B8C\u6210!")),console.log(c.yellow("\u{1F4DD} \u63A5\u4E0B\u6765\u7684\u6B65\u9AA4:")),console.log(c.gray(` cd ${n}`)),console.log(c.gray(" # \u7F16\u8F91 xiaozhi.config.json \u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9\u548C\u670D\u52A1")),console.log(c.gray(" xiaozhi start # \u542F\u52A8\u670D\u52A1")),console.log(c.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 --template \u9009\u9879\u53EF\u4EE5\u4ECE\u6A21\u677F\u521B\u5EFA\u9879\u76EE"))}}catch(t){e.fail(`\u521B\u5EFA\u9879\u76EE\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}l(No,"createProject");function oo(n,o,e=[]){h.existsSync(o)||h.mkdirSync(o,{recursive:!0});let t=h.readdirSync(n);for(let i of t){if(e.some(m=>i.includes(m)))continue;let r=f.join(n,i),s=f.join(o,i);h.statSync(r).isDirectory()?oo(r,s,e):h.copyFileSync(r,s)}}l(oo,"copyDirectory");async function Ro(){let n=b("\u542F\u52A8 UI \u670D\u52A1...").start();try{if(!p.configExists()){n.fail("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728"),console.log(c.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E'));return}let o=new M(9999);await o.start(),n.succeed("UI \u670D\u52A1\u5DF2\u542F\u52A8"),console.log(c.green("\u2705 \u914D\u7F6E\u7BA1\u7406\u7F51\u9875\u5DF2\u542F\u52A8: http://localhost:9999")),console.log(c.yellow("\u{1F4A1} \u63D0\u793A: \u6309 Ctrl+C \u505C\u6B62\u670D\u52A1"));let{spawn:e}=await import("child_process"),t="http://localhost:9999",i=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";try{e(i,[t],{detached:!0,stdio:"ignore"}).unref()}catch{}process.on("SIGINT",async()=>{console.log(c.yellow(`
|
|
29
|
+
\u6B63\u5728\u505C\u6B62 UI \u670D\u52A1...`)),await o.stop(),process.exit(0)}),process.on("SIGTERM",async()=>{await o.stop(),process.exit(0)})}catch(o){n.fail(`\u542F\u52A8 UI \u670D\u52A1\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}l(Ro,"startUIService");async function Ao(n,o){let e=b("\u66F4\u65B0\u914D\u7F6E...").start();try{if(!p.configExists()){e.fail("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728"),console.log(c.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E'));return}if(o)switch(n){case"mcpEndpoint":p.updateMcpEndpoint(o),e.succeed(`MCP \u7AEF\u70B9\u5DF2\u66F4\u65B0\u4E3A: ${o}`);break;case"heartbeatInterval":{let t=Number.parseInt(o,10);if(Number.isNaN(t)||t<=0){e.fail("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}p.setHeartbeatInterval(t),e.succeed(`\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}case"heartbeatTimeout":{let t=Number.parseInt(o,10);if(Number.isNaN(t)||t<=0){e.fail("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}p.setHeartbeatTimeout(t),e.succeed(`\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}case"reconnectInterval":{let t=Number.parseInt(o,10);if(Number.isNaN(t)||t<=0){e.fail("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}p.setReconnectInterval(t),e.succeed(`\u91CD\u8FDE\u95F4\u9694\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}default:e.fail(`\u914D\u7F6E\u9879 ${n} \u4E0D\u652F\u6301\u901A\u8FC7\u547D\u4EE4\u884C\u8BBE\u7F6E`),console.log(c.yellow("\u652F\u6301\u8BBE\u7F6E\u7684\u914D\u7F6E\u9879: mcpEndpoint, heartbeatInterval, heartbeatTimeout, reconnectInterval"));return}else{e.text="\u8BFB\u53D6\u914D\u7F6E...";let t=p.getConfig();switch(n){case"mcpEndpoint":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(c.green(`MCP \u7AEF\u70B9: ${t.mcpEndpoint}`));break;case"mcpServers":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(c.green("MCP \u670D\u52A1:"));for(let[i,r]of Object.entries(t.mcpServers))"type"in r&&r.type==="sse"?console.log(c.gray(` ${i}: [SSE] ${r.url}`)):console.log(c.gray(` ${i}: ${r.command} ${r.args.join(" ")}`));break;case"connection":{e.succeed("\u914D\u7F6E\u4FE1\u606F");let i=p.getConnectionConfig();console.log(c.green("\u8FDE\u63A5\u914D\u7F6E:")),console.log(c.gray(` \u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694: ${i.heartbeatInterval}ms`)),console.log(c.gray(` \u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4: ${i.heartbeatTimeout}ms`)),console.log(c.gray(` \u91CD\u8FDE\u95F4\u9694: ${i.reconnectInterval}ms`));break}case"heartbeatInterval":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(c.green(`\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694: ${p.getHeartbeatInterval()}ms`));break;case"heartbeatTimeout":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(c.green(`\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4: ${p.getHeartbeatTimeout()}ms`));break;case"reconnectInterval":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(c.green(`\u91CD\u8FDE\u95F4\u9694: ${p.getReconnectInterval()}ms`));break;default:e.fail(`\u672A\u77E5\u7684\u914D\u7F6E\u9879: ${n}`),console.log(c.yellow("\u652F\u6301\u7684\u914D\u7F6E\u9879: mcpEndpoint, mcpServers, connection, heartbeatInterval, heartbeatTimeout, reconnectInterval"));return}}}catch(t){e.fail(`\u914D\u7F6E\u64CD\u4F5C\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}l(Ao,"configCommand");function Ho(){console.log(c.blue.bold("xiaozhi - MCP Calculator Service CLI")),console.log(),console.log(c.yellow("\u4F7F\u7528\u65B9\u6CD5:")),console.log(" xiaozhi <command> [options]"),console.log(),console.log(c.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(" ui \u542F\u52A8\u914D\u7F6E\u7BA1\u7406\u7F51\u9875"),console.log(" completion \u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E"),console.log(),console.log(c.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(c.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(c.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(c.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(c.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"),console.log(),console.log(c.yellow("\u81EA\u52A8\u8865\u5168:")),console.log(" xiaozhi completion # \u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E"),console.log(" # \u8BBE\u7F6E\u540E\u53EF\u4F7F\u7528 Tab \u952E\u8FDB\u884C\u547D\u4EE4\u3001\u53C2\u6570\u81EA\u52A8\u8865\u5168")}l(Ho,"showHelp");C.name("xiaozhi").description("MCP Calculator Service CLI Tool").version(Y(),"-v, --version","\u663E\u793A\u7248\u672C\u4FE1\u606F").helpOption("-h, --help","\u663E\u793A\u5E2E\u52A9\u4FE1\u606F");C.command("create <projectName>").description("\u521B\u5EFA\u9879\u76EE").option("-t, --template <templateName>","\u4F7F\u7528\u6307\u5B9A\u6A21\u677F\u521B\u5EFA\u9879\u76EE").action(async(n,o)=>{await No(n,o)});C.command("init").description("\u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6").action(async()=>{await jo()});C.command("config <key> [value]").description("\u67E5\u770B\u6216\u8BBE\u7F6E\u914D\u7F6E").action(async(n,o)=>{await Ao(n,o)});C.command("start").description("\u542F\u52A8\u670D\u52A1").option("-d, --daemon","\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").action(async n=>{await Q(n.daemon)});C.command("stop").description("\u505C\u6B62\u670D\u52A1").action(async()=>{await q()});C.command("status").description("\u68C0\u67E5\u670D\u52A1\u72B6\u6001").action(async()=>{await To()});C.command("attach").description("\u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1\u67E5\u770B\u65E5\u5FD7").action(async()=>{await $o()});C.command("restart").description("\u91CD\u542F\u670D\u52A1").option("-d, --daemon","\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").action(async n=>{await Eo(n.daemon)});var R=C.command("mcp").description("MCP \u670D\u52A1\u548C\u5DE5\u5177\u7BA1\u7406");R.command("list").description("\u5217\u51FA MCP \u670D\u52A1").option("--tools","\u663E\u793A\u6240\u6709\u670D\u52A1\u7684\u5DE5\u5177\u5217\u8868").action(async n=>{await G(n)});R.command("server <serverName>").description("\u7BA1\u7406\u6307\u5B9A\u7684 MCP \u670D\u52A1").action(async n=>{await _(n)});R.command("tool <serverName> <toolName> <action>").description("\u542F\u7528\u6216\u7981\u7528\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177").action(async(n,o,e)=>{e!=="enable"&&e!=="disable"&&(console.error(c.red("\u9519\u8BEF: \u64CD\u4F5C\u5FC5\u987B\u662F 'enable' \u6216 'disable'")),process.exit(1)),await B(n,o,e==="enable")});C.command("ui").description("\u542F\u52A8\u914D\u7F6E\u7BA1\u7406\u7F51\u9875").action(async()=>{await Ro()});C.command("completion").description("\u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E").action(async()=>{W()});C.option("-V","\u663E\u793A\u8BE6\u7EC6\u4FE1\u606F").action(n=>{n.V&&(Mo(),process.exit(0))});D();process.argv.length<=2&&(Ho(),process.exit(0));C.parse(process.argv);export{X as calculateSimilarity,Po as checkEnvironment,xo as formatUptime,z as getServiceStatus,Y as getVersion};
|
|
9
30
|
//# sourceMappingURL=cli.js.map
|