xiaozhi-client 1.1.0 → 1.2.0-beta.0
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 +57 -3
- package/dist/autoCompletion.js +1 -1
- package/dist/autoCompletion.js.map +1 -1
- package/dist/cli.d.ts +28 -0
- package/dist/cli.js +7 -6
- package/dist/cli.js.map +1 -1
- package/dist/configManager.d.ts +66 -2
- package/dist/configManager.js +1 -1
- package/dist/configManager.js.map +1 -1
- package/dist/logger.d.ts +45 -0
- package/dist/logger.js +3 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcpCommands.js +1 -1
- package/dist/mcpCommands.js.map +1 -1
- package/dist/mcpPipe.d.ts +39 -0
- package/dist/mcpPipe.js +8 -5
- package/dist/mcpPipe.js.map +1 -1
- package/dist/mcpServerProxy.d.ts +73 -5
- package/dist/mcpServerProxy.js +7 -6
- package/dist/mcpServerProxy.js.map +1 -1
- package/dist/package.json +6 -1
- package/dist/templates/hello-world/xiaozhi.config.json +5 -0
- package/dist/xiaozhi.config.default.json +8 -0
- package/package.json +23 -18
- package/templates/hello-world/xiaozhi.config.json +5 -0
package/README.md
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
- 支持 动态控制 MCP Server 提供的工具
|
|
19
19
|
- 支持 通过模板创建
|
|
20
20
|
- 支持 后台运行
|
|
21
|
+
- 支持 通过 SSE 类型接入 ModelScope MCP 服务
|
|
21
22
|
|
|
22
23
|
## 快速上手
|
|
23
24
|
|
|
@@ -90,11 +91,64 @@ xiaozhi restart
|
|
|
90
91
|
xiaozhi mcp list
|
|
91
92
|
|
|
92
93
|
# 列出所有mcp所提供的tools
|
|
93
|
-
xiaozhi mcp --tools
|
|
94
|
+
xiaozhi mcp list --tools
|
|
94
95
|
```
|
|
95
96
|
|
|
97
|
+
## ModelScope MCP 服务集成
|
|
98
|
+
|
|
99
|
+
xiaozhi-client 现已支持接入 [ModelScope](https://www.modelscope.cn/mcp) 托管的 MCP 服务。
|
|
100
|
+
|
|
101
|
+
### 配置方式
|
|
102
|
+
|
|
103
|
+
在 `xiaozhi.config.json` 的 `mcpServers` 中添加 SSE 类型的配置:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"mcpServers": {
|
|
108
|
+
"amap-maps": {
|
|
109
|
+
"type": "sse",
|
|
110
|
+
"url": "https://mcp.api-inference.modelscope.net/caa0bd914d9b44/sse"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 使用前准备
|
|
117
|
+
|
|
118
|
+
1. 获取 ModelScope API Token:
|
|
119
|
+
- 访问 [ModelScope](https://www.modelscope.cn) 并登录
|
|
120
|
+
- 在个人中心获取 API Token
|
|
121
|
+
|
|
122
|
+
2. 配置 API Token(两种方式任选其一):
|
|
123
|
+
|
|
124
|
+
**方式一:在配置文件中设置(推荐)**
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"modelscope": {
|
|
128
|
+
"apiKey": "你的API Token"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**方式二:设置环境变量**
|
|
134
|
+
```bash
|
|
135
|
+
export MODELSCOPE_API_TOKEN="你的API Token"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
3. 启动服务:
|
|
139
|
+
```bash
|
|
140
|
+
xiaozhi start
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### 注意事项
|
|
144
|
+
|
|
145
|
+
- ModelScope MCP 服务需要有效的 API Token 才能使用
|
|
146
|
+
- 配置文件中的 API Token 优先级高于环境变量
|
|
147
|
+
- 确保网络能够访问 ModelScope 的服务端点
|
|
148
|
+
- SSE 类型的服务会自动识别并使用相应的连接方式
|
|
149
|
+
|
|
96
150
|
## 路线图
|
|
97
151
|
|
|
98
|
-
- 支持 通过 SSE 类型的 MCP Server
|
|
99
|
-
- 支持 直接使用 [modelscope](https://www.modelscope.cn/mcp) 中托管的 MCP 服务
|
|
152
|
+
- ✅ 支持 通过 SSE 类型的 MCP Server
|
|
153
|
+
- ✅ 支持 直接使用 [modelscope](https://www.modelscope.cn/mcp) 中托管的 MCP 服务
|
|
100
154
|
- 支持 通过使用网页进行 MCP 配置
|
package/dist/autoCompletion.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var S=Object.defineProperty;var l=(r,o)=>S(r,"name",{value:o,configurable:!0});import z from"omelette";import{copyFileSync as b,existsSync as C,readFileSync as w,writeFileSync as x}from"fs";import{dirname as E,resolve as v}from"path";import{fileURLToPath as P}from"url";var M=E(P(import.meta.url)),u=class r{static{l(this,"ConfigManager")}static instance;defaultConfigPath;config=null;constructor(){this.defaultConfigPath=v(M,"xiaozhi.config.default.json")}getConfigFilePath(){let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return v(o,"xiaozhi.config.json")}static getInstance(){return r.instance||(r.instance=new r),r.instance}configExists(){let o=this.getConfigFilePath();return C(o)}initConfig(){if(!C(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();b(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(),t=w(o,"utf8"),e=JSON.parse(t);return this.validateConfig(e),e}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 t=o;if(!t.mcpEndpoint||typeof t.mcpEndpoint!="string")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5B57\u6BB5\u65E0\u6548");if(!t.mcpServers||typeof t.mcpServers!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers \u5B57\u6BB5\u65E0\u6548");for(let[e,n]of Object.entries(t.mcpServers)){if(!n||typeof n!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${e} \u65E0\u6548`);let f=n;if(!f.command||typeof f.command!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${e}.command \u65E0\u6548`);if(!Array.isArray(f.args))throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${e}.args \u5FC5\u987B\u662F\u6570\u7EC4`);if(f.env&&typeof f.env!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${e}.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,t){return this.getServerToolsConfig(o)[t]?.enable!==!1}updateMcpEndpoint(o){if(!o||typeof o!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let e={...this.getConfig(),mcpEndpoint:o};this.saveConfig(e)}updateMcpServer(o,t){if(!o||typeof o!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!t.command||typeof t.command!="string")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 command \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!Array.isArray(t.args))throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 args \u5B57\u6BB5\u5FC5\u987B\u662F\u6570\u7EC4");if(t.env&&typeof t.env!="object")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 env \u5B57\u6BB5\u5FC5\u987B\u662F\u5BF9\u8C61");let e=this.getConfig(),n={...e,mcpServers:{...e.mcpServers,[o]:t}};this.saveConfig(n)}removeMcpServer(o){if(!o||typeof o!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t=this.getConfig();if(!t.mcpServers[o])throw new Error(`\u670D\u52A1 ${o} \u4E0D\u5B58\u5728`);let e={...t.mcpServers};delete e[o];let n={...t,mcpServers:e};this.saveConfig(n)}updateServerToolsConfig(o,t){let n={...this.getConfig()};n.mcpServerConfig||(n.mcpServerConfig={}),n.mcpServerConfig[o]={tools:t},this.saveConfig(n)}setToolEnabled(o,t,e,n){let i={...this.getConfig()};i.mcpServerConfig||(i.mcpServerConfig={}),i.mcpServerConfig[o]||(i.mcpServerConfig[o]={tools:{}}),i.mcpServerConfig[o].tools[t]={enable:e,...n&&{description:n}},this.saveConfig(i)}saveConfig(o){try{this.validateConfig(o);let t=this.getConfigFilePath(),e=JSON.stringify(o,null,2);x(t,e,"utf8"),this.config=o}catch(t){throw new Error(`\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}reloadConfig(){this.config=null}getConfigPath(){return this.getConfigFilePath()}getDefaultConfigPath(){return this.defaultConfigPath}},m=u.getInstance();function y(){try{if(!m.configExists())return[];let r=m.getMcpServers();return Object.keys(r)}catch{return[]}}l(y,"getMcpServerNames");function T(r){try{if(!m.configExists())return[];let o=m.getServerToolsConfig(r);return Object.keys(o)}catch{return[]}}l(T,"getServerToolNames");function J(){let r=z("xiaozhi");r.on("complete",(o,{line:t,before:e,reply:n})=>{let f=t.trim(),i=f.split(/\s+/),h=t!==f?i.length:i.length-1;if(h===1){let p=["create","init","config","start","stop","status","attach","restart","mcp","completion"],s=i[1]||"",c=p.filter(g=>g.startsWith(s));n(c);return}if(h===2){switch(i[1]){case"create":n(["--template","-t"]);break;case"start":case"restart":n(["--daemon","-d"]);break;case"completion":n(["install","uninstall"]);break;case"mcp":{let s=["list","server","tool"],c=i[2]||"",g=s.filter(a=>a.startsWith(c));n(g);break}default:n([])}return}if(i[1]==="mcp"){let p=i[2];if(h===3){switch(p){case"list":{let s=["--tools"],c=i[3]||"",g=s.filter(a=>a.startsWith(c));n(g);break}case"server":case"tool":{let s=y(),c=i[3]||"",g=s.filter(a=>a.startsWith(c));n(g);break}default:n([])}return}if(h===4&&p==="tool"){let s=i[3],c=T(s),g=i[4]||"",a=c.filter(d=>d.startsWith(g));n(a);return}if(h===5&&p==="tool"){let s=["enable","disable"],c=i[5]||"",g=s.filter(a=>a.startsWith(c));n(g);return}}n([])}),process.argv.includes("--completion")&&(console.log(r.setupShellInitFile()),process.exit(0)),process.argv.includes("--completion-fish")&&(console.log(r.setupShellInitFile("fish")),process.exit(0)),process.argv.includes("--compzsh")||process.argv.includes("--compbash"),r.init()}l(J,"setupAutoCompletion");function D(){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(D,"showCompletionHelp");export{J as setupAutoCompletion,D as showCompletionHelp};
|
|
1
|
+
var S=Object.defineProperty;var l=(r,o)=>S(r,"name",{value:o,configurable:!0});import I from"omelette";import{copyFileSync as w,existsSync as d,readFileSync as E,writeFileSync as M}from"fs";import{dirname as x,resolve as v}from"path";import{fileURLToPath as P}from"url";var y=x(P(import.meta.url)),u={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},m=class r{static{l(this,"ConfigManager")}static instance;defaultConfigPath;config=null;constructor(){this.defaultConfigPath=v(y,"xiaozhi.config.default.json")}getConfigFilePath(){let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return v(o,"xiaozhi.config.json")}static getInstance(){return r.instance||(r.instance=new r),r.instance}configExists(){let o=this.getConfigFilePath();return d(o)}initConfig(){if(!d(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();w(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=E(o,"utf8"),i=JSON.parse(e);return this.validateConfig(i),i}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[i,n]of Object.entries(e.mcpServers)){if(!n||typeof n!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${i} \u65E0\u6548`);let t=n;if(t.type==="sse"){if(!t.url||typeof t.url!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${i}.url \u65E0\u6548`)}else{if(!t.command||typeof t.command!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${i}.command \u65E0\u6548`);if(!Array.isArray(t.args))throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${i}.args \u5FC5\u987B\u662F\u6570\u7EC4`);if(t.env&&typeof t.env!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${i}.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 i={...this.getConfig(),mcpEndpoint:o};this.saveConfig(i)}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 t=e;if(!t.command||typeof t.command!="string")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 command \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!Array.isArray(t.args))throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 args \u5B57\u6BB5\u5FC5\u987B\u662F\u6570\u7EC4");if(t.env&&typeof t.env!="object")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 env \u5B57\u6BB5\u5FC5\u987B\u662F\u5BF9\u8C61")}let i=this.getConfig(),n={...i,mcpServers:{...i.mcpServers,[o]:e}};this.saveConfig(n)}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 i={...e.mcpServers};delete i[o];let n={...e,mcpServers:i};this.saveConfig(n)}updateServerToolsConfig(o,e){let n={...this.getConfig()};n.mcpServerConfig||(n.mcpServerConfig={}),n.mcpServerConfig[o]={tools:e},this.saveConfig(n)}setToolEnabled(o,e,i,n){let f={...this.getConfig()};f.mcpServerConfig||(f.mcpServerConfig={}),f.mcpServerConfig[o]||(f.mcpServerConfig[o]={tools:{}}),f.mcpServerConfig[o].tools[e]={enable:i,...n&&{description:n}},this.saveConfig(f)}saveConfig(o){try{this.validateConfig(o);let e=this.getConfigFilePath(),i=JSON.stringify(o,null,2);M(e,i,"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??u.heartbeatInterval,heartbeatTimeout:e.heartbeatTimeout??u.heartbeatTimeout,reconnectInterval:e.reconnectInterval??u.reconnectInterval}}getHeartbeatInterval(){return this.getConnectionConfig().heartbeatInterval}getHeartbeatTimeout(){return this.getConnectionConfig().heartbeatTimeout}getReconnectInterval(){return this.getConnectionConfig().reconnectInterval}updateConnectionConfig(o){let e=this.getConfig(),n={...e.connection||{},...o},t={...e,connection:n};this.saveConfig(t)}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(),n={...e.modelscope||{},...o},t={...e,modelscope:n};this.saveConfig(t)}setModelScopeApiKey(o){if(!o||typeof o!="string")throw new Error("API Key \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");this.updateModelScopeConfig({apiKey:o})}},h=m.getInstance();function T(){try{if(!h.configExists())return[];let r=h.getMcpServers();return Object.keys(r)}catch{return[]}}l(T,"getMcpServerNames");function z(r){try{if(!h.configExists())return[];let o=h.getServerToolsConfig(r);return Object.keys(o)}catch{return[]}}l(z,"getServerToolNames");function D(){let r=I("xiaozhi <command>");if(r.on("command",({reply:o})=>{o(["create","init","config","start","stop","status","attach","restart","mcp","completion"])}),r.on("complete",(o,{line:e,before:i,reply:n})=>{process.env.XIAOZHI_DEBUG_COMPLETION&&console.error(`Debug completion - line: "${e}", before: "${i}", fragment: "${o}"`);let t=e.trim().split(/\s+/),p=e!==e.trim()?t.length:t.length-1;if(t[1]==="mcp"){let C=t[2];if(p===2){let c=["list","server","tool"],s=t[2]||"",g=c.filter(a=>a.startsWith(s));n(g);return}if(p===3){switch(C){case"list":{let c=["--tools"],s=t[3]||"",g=c.filter(a=>a.startsWith(s));n(g);break}case"server":case"tool":{let c=T(),s=t[3]||"",g=c.filter(a=>a.startsWith(s));n(g);break}default:n([])}return}if(p===4&&C==="tool"){let c=t[3],s=z(c),g=t[4]||"",a=s.filter(b=>b.startsWith(g));n(a);return}if(p===5&&C==="tool"){let c=["enable","disable"],s=t[5]||"",g=c.filter(a=>a.startsWith(s));n(g);return}}if(p===2){switch(t[1]){case"create":n(["--template","-t"]);break;case"start":case"restart":n(["--daemon","-d"]);break;case"completion":n(["install","uninstall"]);break;default:n([])}return}n([])}),process.argv.includes("--completion")){try{console.log(r.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(r.setupShellInitFile("fish")),process.exit(0)),process.argv.includes("--compzsh")||process.argv.includes("--compbash"),r.init()}l(D,"setupAutoCompletion");function _(){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(_,"showCompletionHelp");export{D as setupAutoCompletion,_ as showCompletionHelp};
|
|
2
2
|
//# sourceMappingURL=autoCompletion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/autoCompletion.ts","../src/configManager.ts"],"sourcesContent":["import omelette from \"omelette\";\nimport { configManager } from \"./configManager\";\n\n/**\n * 自动补全功能模块\n */\n\n/**\n * 获取所有可用的MCP服务器名称\n */\nfunction getMcpServerNames(): string[] {\n try {\n if (!configManager.configExists()) {\n return [];\n }\n const mcpServers = configManager.getMcpServers();\n return Object.keys(mcpServers);\n } catch (error) {\n return [];\n }\n}\n\n/**\n * 获取指定服务器的工具名称\n */\nfunction getServerToolNames(serverName: string): string[] {\n try {\n if (!configManager.configExists()) {\n return [];\n }\n const toolsConfig = configManager.getServerToolsConfig(serverName);\n return Object.keys(toolsConfig);\n } catch (error) {\n return [];\n }\n}\n\n/**\n * 设置自动补全功能\n */\nexport function setupAutoCompletion(): void {\n // 创建 omelette 实例,使用简单的模板\n const completion = omelette(\"xiaozhi\");\n\n // 使用全局事件处理所有补全\n completion.on(\"complete\", (fragment, { line, before, reply }) => {\n // 处理行尾空格的情况\n const trimmedLine = line.trim();\n const parts = trimmedLine.split(/\\s+/);\n\n // 如果原始行以空格结尾,说明用户想要补全下一个参数\n const endsWithSpace = line !== trimmedLine;\n const currentIndex = endsWithSpace ? parts.length : parts.length - 1;\n\n // 主命令补全\n if (currentIndex === 1) {\n const commands = [\n \"create\",\n \"init\",\n \"config\",\n \"start\",\n \"stop\",\n \"status\",\n \"attach\",\n \"restart\",\n \"mcp\",\n \"completion\",\n ];\n\n const current = parts[1] || \"\";\n const matches = commands.filter((cmd) => cmd.startsWith(current));\n reply(matches);\n return;\n }\n\n // 子命令补全\n if (currentIndex === 2) {\n const command = parts[1];\n\n switch (command) {\n case \"create\":\n reply([\"--template\", \"-t\"]);\n break;\n case \"start\":\n case \"restart\":\n reply([\"--daemon\", \"-d\"]);\n break;\n case \"completion\":\n reply([\"install\", \"uninstall\"]);\n break;\n case \"mcp\": {\n const subcommands = [\"list\", \"server\", \"tool\"];\n const current = parts[2] || \"\";\n const matches = subcommands.filter((cmd) => cmd.startsWith(current));\n reply(matches);\n break;\n }\n default:\n reply([]);\n }\n return;\n }\n\n // MCP 相关的进一步补全\n if (parts[1] === \"mcp\") {\n const subcommand = parts[2];\n\n if (currentIndex === 3) {\n switch (subcommand) {\n case \"list\": {\n const options = [\"--tools\"];\n const current = parts[3] || \"\";\n const matches = options.filter((opt) => opt.startsWith(current));\n reply(matches);\n break;\n }\n case \"server\":\n case \"tool\": {\n const serverNames = getMcpServerNames();\n const current = parts[3] || \"\";\n const matches = serverNames.filter((name) =>\n name.startsWith(current)\n );\n reply(matches);\n break;\n }\n default:\n reply([]);\n }\n return;\n }\n\n if (currentIndex === 4 && subcommand === \"tool\") {\n const serverName = parts[3];\n const toolNames = getServerToolNames(serverName);\n const current = parts[4] || \"\";\n const matches = toolNames.filter((name) => name.startsWith(current));\n reply(matches);\n return;\n }\n\n if (currentIndex === 5 && subcommand === \"tool\") {\n const actions = [\"enable\", \"disable\"];\n const current = parts[5] || \"\";\n const matches = actions.filter((action) => action.startsWith(current));\n reply(matches);\n return;\n }\n }\n\n // 默认情况\n reply([]);\n });\n\n // 处理补全相关的命令行参数\n if (process.argv.includes(\"--completion\")) {\n // 输出补全脚本供shell使用\n console.log(completion.setupShellInitFile());\n process.exit(0);\n }\n\n if (process.argv.includes(\"--completion-fish\")) {\n // Fish shell 补全\n console.log(completion.setupShellInitFile(\"fish\"));\n process.exit(0);\n }\n\n if (\n process.argv.includes(\"--compzsh\") ||\n process.argv.includes(\"--compbash\")\n ) {\n // 处理实际的补全请求 - 这些是omelette内部使用的参数\n // 不需要手动处理,让omelette自己处理\n }\n\n // 初始化补全\n completion.init();\n}\n\n/**\n * 显示自动补全安装说明\n */\nexport function showCompletionHelp(): void {\n console.log(\"🚀 xiaozhi 自动补全设置\");\n console.log();\n console.log(\"要启用自动补全,请根据你的shell执行以下命令:\");\n console.log();\n console.log(\"📝 Zsh (推荐):\");\n console.log(\" xiaozhi --completion >> ~/.xiaozhi-completion.zsh\");\n console.log(\" echo 'source ~/.xiaozhi-completion.zsh' >> ~/.zshrc\");\n console.log(\" source ~/.zshrc\");\n console.log();\n console.log(\"📝 Bash:\");\n console.log(\" xiaozhi --completion >> ~/.xiaozhi-completion.bash\");\n console.log(\" echo 'source ~/.xiaozhi-completion.bash' >> ~/.bash_profile\");\n console.log(\" source ~/.bash_profile\");\n console.log();\n console.log(\"📝 Fish:\");\n console.log(\n \" xiaozhi --completion-fish >> ~/.config/fish/completions/xiaozhi.fish\"\n );\n console.log();\n console.log(\"✨ 设置完成后,你就可以使用 Tab 键进行自动补全了!\");\n console.log();\n console.log(\"💡 示例:\");\n console.log(\" xiaozhi m<Tab> # → mcp\");\n console.log(\" xiaozhi mcp l<Tab> # → list\");\n console.log(\" xiaozhi mcp tool <Tab> # → 显示所有服务器名称\");\n}\n","import { copyFileSync, existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n// 在 ESM 中,需要从 import.meta.url 获取当前文件目录\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n// 配置文件接口定义\nexport interface MCPServerConfig {\n command: string;\n args: string[];\n env?: Record<string, string>;\n}\n\nexport interface MCPToolConfig {\n description?: string;\n enable: boolean;\n}\n\nexport interface MCPServerToolsConfig {\n tools: Record<string, MCPToolConfig>;\n}\n\nexport interface AppConfig {\n mcpEndpoint: string;\n mcpServers: Record<string, MCPServerConfig>;\n mcpServerConfig?: Record<string, MCPServerToolsConfig>;\n}\n\n/**\n * 配置管理类\n * 负责管理应用配置,提供只读访问和安全的配置更新功能\n */\nexport class ConfigManager {\n private static instance: ConfigManager;\n private defaultConfigPath: string;\n private config: AppConfig | null = null;\n\n private constructor() {\n this.defaultConfigPath = resolve(__dirname, \"xiaozhi.config.default.json\");\n }\n\n /**\n * 获取配置文件路径(动态计算)\n */\n private getConfigFilePath(): string {\n // 配置文件路径 - 优先使用环境变量指定的目录,否则使用当前工作目录\n const configDir = process.env.XIAOZHI_CONFIG_DIR || process.cwd();\n return resolve(configDir, \"xiaozhi.config.json\");\n }\n\n /**\n * 获取配置管理器单例实例\n */\n public static getInstance(): ConfigManager {\n if (!ConfigManager.instance) {\n ConfigManager.instance = new ConfigManager();\n }\n return ConfigManager.instance;\n }\n\n /**\n * 检查配置文件是否存在\n */\n public configExists(): boolean {\n const configPath = this.getConfigFilePath();\n return existsSync(configPath);\n }\n\n /**\n * 初始化配置文件\n * 从 config.default.json 复制到 config.json\n */\n public initConfig(): void {\n if (!existsSync(this.defaultConfigPath)) {\n throw new Error(\"默认配置文件 xiaozhi.config.default.json 不存在\");\n }\n\n if (this.configExists()) {\n throw new Error(\"配置文件 xiaozhi.config.json 已存在,无需重复初始化\");\n }\n\n const configPath = this.getConfigFilePath();\n copyFileSync(this.defaultConfigPath, configPath);\n this.config = null; // 重置缓存\n }\n\n /**\n * 加载配置文件\n */\n private loadConfig(): AppConfig {\n if (!this.configExists()) {\n throw new Error(\n \"配置文件 xiaozhi.config.json 不存在,请先运行 xiaozhi init 初始化配置\"\n );\n }\n\n try {\n const configPath = this.getConfigFilePath();\n const configData = readFileSync(configPath, \"utf8\");\n const config = JSON.parse(configData) as AppConfig;\n\n // 验证配置结构\n this.validateConfig(config);\n\n return config;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`配置文件格式错误: ${error.message}`);\n }\n throw error;\n }\n }\n\n /**\n * 验证配置文件结构\n */\n private validateConfig(config: unknown): void {\n if (!config || typeof config !== \"object\") {\n throw new Error(\"配置文件格式错误:根对象无效\");\n }\n\n const configObj = config as Record<string, unknown>;\n\n if (!configObj.mcpEndpoint || typeof configObj.mcpEndpoint !== \"string\") {\n throw new Error(\"配置文件格式错误:mcpEndpoint 字段无效\");\n }\n\n if (!configObj.mcpServers || typeof configObj.mcpServers !== \"object\") {\n throw new Error(\"配置文件格式错误:mcpServers 字段无效\");\n }\n\n // 验证每个 MCP 服务配置\n for (const [serverName, serverConfig] of Object.entries(\n configObj.mcpServers as Record<string, unknown>\n )) {\n if (!serverConfig || typeof serverConfig !== \"object\") {\n throw new Error(`配置文件格式错误:mcpServers.${serverName} 无效`);\n }\n\n const sc = serverConfig as Record<string, unknown>;\n if (!sc.command || typeof sc.command !== \"string\") {\n throw new Error(\n `配置文件格式错误:mcpServers.${serverName}.command 无效`\n );\n }\n\n if (!Array.isArray(sc.args)) {\n throw new Error(\n `配置文件格式错误:mcpServers.${serverName}.args 必须是数组`\n );\n }\n\n if (sc.env && typeof sc.env !== \"object\") {\n throw new Error(\n `配置文件格式错误:mcpServers.${serverName}.env 必须是对象`\n );\n }\n }\n }\n\n /**\n * 获取配置(只读)\n */\n public getConfig(): Readonly<AppConfig> {\n if (!this.config) {\n this.config = this.loadConfig();\n }\n\n // 返回深度只读副本\n return JSON.parse(JSON.stringify(this.config));\n }\n\n /**\n * 获取 MCP 端点\n */\n public getMcpEndpoint(): string {\n const config = this.getConfig();\n return config.mcpEndpoint;\n }\n\n /**\n * 获取 MCP 服务配置\n */\n public getMcpServers(): Readonly<Record<string, MCPServerConfig>> {\n const config = this.getConfig();\n return config.mcpServers;\n }\n\n /**\n * 获取 MCP 服务工具配置\n */\n public getMcpServerConfig(): Readonly<Record<string, MCPServerToolsConfig>> {\n const config = this.getConfig();\n return config.mcpServerConfig || {};\n }\n\n /**\n * 获取指定服务的工具配置\n */\n public getServerToolsConfig(\n serverName: string\n ): Readonly<Record<string, MCPToolConfig>> {\n const serverConfig = this.getMcpServerConfig();\n return serverConfig[serverName]?.tools || {};\n }\n\n /**\n * 检查工具是否启用\n */\n public isToolEnabled(serverName: string, toolName: string): boolean {\n const toolsConfig = this.getServerToolsConfig(serverName);\n const toolConfig = toolsConfig[toolName];\n return toolConfig?.enable !== false; // 默认启用\n }\n\n /**\n * 更新 MCP 端点\n */\n public updateMcpEndpoint(endpoint: string): void {\n if (!endpoint || typeof endpoint !== \"string\") {\n throw new Error(\"MCP 端点必须是非空字符串\");\n }\n\n const config = this.getConfig();\n const newConfig = { ...config, mcpEndpoint: endpoint };\n this.saveConfig(newConfig);\n }\n\n /**\n * 更新 MCP 服务配置\n */\n public updateMcpServer(\n serverName: string,\n serverConfig: MCPServerConfig\n ): void {\n if (!serverName || typeof serverName !== \"string\") {\n throw new Error(\"服务名称必须是非空字符串\");\n }\n\n // 验证服务配置\n if (!serverConfig.command || typeof serverConfig.command !== \"string\") {\n throw new Error(\"服务配置的 command 字段必须是非空字符串\");\n }\n\n if (!Array.isArray(serverConfig.args)) {\n throw new Error(\"服务配置的 args 字段必须是数组\");\n }\n\n if (serverConfig.env && typeof serverConfig.env !== \"object\") {\n throw new Error(\"服务配置的 env 字段必须是对象\");\n }\n\n const config = this.getConfig();\n const newConfig = {\n ...config,\n mcpServers: {\n ...config.mcpServers,\n [serverName]: serverConfig,\n },\n };\n this.saveConfig(newConfig);\n }\n\n /**\n * 删除 MCP 服务配置\n */\n public removeMcpServer(serverName: string): void {\n if (!serverName || typeof serverName !== \"string\") {\n throw new Error(\"服务名称必须是非空字符串\");\n }\n\n const config = this.getConfig();\n if (!config.mcpServers[serverName]) {\n throw new Error(`服务 ${serverName} 不存在`);\n }\n\n const newMcpServers = { ...config.mcpServers };\n delete newMcpServers[serverName];\n\n const newConfig = {\n ...config,\n mcpServers: newMcpServers,\n };\n this.saveConfig(newConfig);\n }\n\n /**\n * 更新服务工具配置\n */\n public updateServerToolsConfig(\n serverName: string,\n toolsConfig: Record<string, MCPToolConfig>\n ): void {\n const config = this.getConfig();\n const newConfig = { ...config };\n\n // 确保 mcpServerConfig 存在\n if (!newConfig.mcpServerConfig) {\n newConfig.mcpServerConfig = {};\n }\n\n // 更新指定服务的工具配置\n newConfig.mcpServerConfig[serverName] = {\n tools: toolsConfig,\n };\n\n this.saveConfig(newConfig);\n }\n\n /**\n * 设置工具启用状态\n */\n public setToolEnabled(\n serverName: string,\n toolName: string,\n enabled: boolean,\n description?: string\n ): void {\n const config = this.getConfig();\n const newConfig = { ...config };\n\n // 确保 mcpServerConfig 存在\n if (!newConfig.mcpServerConfig) {\n newConfig.mcpServerConfig = {};\n }\n\n // 确保服务配置存在\n if (!newConfig.mcpServerConfig[serverName]) {\n newConfig.mcpServerConfig[serverName] = { tools: {} };\n }\n\n // 更新工具配置\n newConfig.mcpServerConfig[serverName].tools[toolName] = {\n enable: enabled,\n ...(description && { description }),\n };\n\n this.saveConfig(newConfig);\n }\n\n /**\n * 保存配置到文件\n */\n private saveConfig(config: AppConfig): void {\n try {\n // 验证配置\n this.validateConfig(config);\n\n // 格式化 JSON 并保存\n const configPath = this.getConfigFilePath();\n const configJson = JSON.stringify(config, null, 2);\n writeFileSync(configPath, configJson, \"utf8\");\n\n // 更新缓存\n this.config = config;\n } catch (error) {\n throw new Error(\n `保存配置失败: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * 重新加载配置(清除缓存)\n */\n public reloadConfig(): void {\n this.config = null;\n }\n\n /**\n * 获取配置文件路径\n */\n public getConfigPath(): string {\n return this.getConfigFilePath();\n }\n\n /**\n * 获取默认配置文件路径\n */\n public getDefaultConfigPath(): string {\n return this.defaultConfigPath;\n }\n}\n\n// 导出单例实例\nexport const configManager = ConfigManager.getInstance();\n"],"mappings":"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","names":["omelette","copyFileSync","existsSync","readFileSync","writeFileSync","dirname","resolve","fileURLToPath","__dirname","dirname","fileURLToPath","ConfigManager","_ConfigManager","__name","resolve","configDir","configPath","existsSync","copyFileSync","configData","readFileSync","config","error","configObj","serverName","serverConfig","sc","toolName","endpoint","newConfig","newMcpServers","toolsConfig","enabled","description","configJson","writeFileSync","configManager","getMcpServerNames","configManager","mcpServers","__name","getServerToolNames","serverName","toolsConfig","setupAutoCompletion","completion","omelette","fragment","line","before","reply","trimmedLine","parts","currentIndex","commands","current","matches","cmd","subcommands","subcommand","options","opt","serverNames","name","toolNames","actions","action","showCompletionHelp"]}
|
|
1
|
+
{"version":3,"sources":["../src/autoCompletion.ts","../src/configManager.ts"],"sourcesContent":["import omelette from \"omelette\";\nimport { configManager } from \"./configManager\";\n\n/**\n * 自动补全功能模块\n */\n\n/**\n * 获取所有可用的MCP服务器名称\n */\nfunction getMcpServerNames(): string[] {\n try {\n if (!configManager.configExists()) {\n return [];\n }\n const mcpServers = configManager.getMcpServers();\n return Object.keys(mcpServers);\n } catch (error) {\n return [];\n }\n}\n\n/**\n * 获取指定服务器的工具名称\n */\nfunction getServerToolNames(serverName: string): string[] {\n try {\n if (!configManager.configExists()) {\n return [];\n }\n const toolsConfig = configManager.getServerToolsConfig(serverName);\n return Object.keys(toolsConfig);\n } catch (error) {\n return [];\n }\n}\n\n/**\n * 设置自动补全功能\n */\nexport function setupAutoCompletion(): void {\n // 创建 omelette 实例,使用简单的模板\n const completion = omelette(\"xiaozhi <command>\");\n\n // 处理主命令补全\n completion.on(\"command\", ({ reply }) => {\n reply([\n \"create\",\n \"init\",\n \"config\",\n \"start\",\n \"stop\",\n \"status\",\n \"attach\",\n \"restart\",\n \"mcp\",\n \"completion\",\n ]);\n });\n\n // 处理复杂的多级命令补全\n completion.on(\"complete\", (fragment, { line, before, reply }) => {\n // 调试信息\n if (process.env.XIAOZHI_DEBUG_COMPLETION) {\n console.error(\n `Debug completion - line: \"${line}\", before: \"${before}\", fragment: \"${fragment}\"`\n );\n }\n\n const parts = line.trim().split(/\\s+/);\n const endsWithSpace = line !== line.trim();\n const currentIndex = endsWithSpace ? parts.length : parts.length - 1;\n\n // MCP 相关的补全\n if (parts[1] === \"mcp\") {\n const subcommand = parts[2];\n\n if (currentIndex === 2) {\n // mcp 子命令\n const subcommands = [\"list\", \"server\", \"tool\"];\n const current = parts[2] || \"\";\n const matches = subcommands.filter((cmd) => cmd.startsWith(current));\n reply(matches);\n return;\n }\n\n if (currentIndex === 3) {\n switch (subcommand) {\n case \"list\": {\n const options = [\"--tools\"];\n const current = parts[3] || \"\";\n const matches = options.filter((opt) => opt.startsWith(current));\n reply(matches);\n break;\n }\n case \"server\":\n case \"tool\": {\n const serverNames = getMcpServerNames();\n const current = parts[3] || \"\";\n const matches = serverNames.filter((name) =>\n name.startsWith(current)\n );\n reply(matches);\n break;\n }\n default:\n reply([]);\n }\n return;\n }\n\n if (currentIndex === 4 && subcommand === \"tool\") {\n const serverName = parts[3];\n const toolNames = getServerToolNames(serverName);\n const current = parts[4] || \"\";\n const matches = toolNames.filter((name) => name.startsWith(current));\n reply(matches);\n return;\n }\n\n if (currentIndex === 5 && subcommand === \"tool\") {\n const actions = [\"enable\", \"disable\"];\n const current = parts[5] || \"\";\n const matches = actions.filter((action) => action.startsWith(current));\n reply(matches);\n return;\n }\n }\n\n // 其他命令的子参数补全\n if (currentIndex === 2) {\n const command = parts[1];\n switch (command) {\n case \"create\":\n reply([\"--template\", \"-t\"]);\n break;\n case \"start\":\n case \"restart\":\n reply([\"--daemon\", \"-d\"]);\n break;\n case \"completion\":\n reply([\"install\", \"uninstall\"]);\n break;\n default:\n reply([]);\n }\n return;\n }\n\n // 默认情况\n reply([]);\n });\n\n // 处理补全相关的命令行参数\n if (process.argv.includes(\"--completion\")) {\n // 输出补全脚本供shell使用\n try {\n console.log(completion.setupShellInitFile());\n } catch (error) {\n console.error(\"生成自动补全脚本时出错:\", error);\n }\n process.exit(0);\n }\n\n if (process.argv.includes(\"--completion-fish\")) {\n // Fish shell 补全\n console.log(completion.setupShellInitFile(\"fish\"));\n process.exit(0);\n }\n\n if (\n process.argv.includes(\"--compzsh\") ||\n process.argv.includes(\"--compbash\")\n ) {\n // 处理实际的补全请求 - 这些是omelette内部使用的参数\n // 不需要手动处理,让omelette自己处理\n }\n\n // 初始化补全\n completion.init();\n}\n\n/**\n * 显示自动补全安装说明\n */\nexport function showCompletionHelp(): void {\n console.log(\"🚀 xiaozhi 自动补全设置\");\n console.log();\n console.log(\"要启用自动补全,请根据你的shell执行以下命令:\");\n console.log();\n console.log(\"📝 Zsh (推荐):\");\n console.log(\" xiaozhi --completion >> ~/.xiaozhi-completion.zsh\");\n console.log(\" echo 'source ~/.xiaozhi-completion.zsh' >> ~/.zshrc\");\n console.log(\" source ~/.zshrc\");\n console.log();\n console.log(\"📝 Bash:\");\n console.log(\" xiaozhi --completion >> ~/.xiaozhi-completion.bash\");\n console.log(\" echo 'source ~/.xiaozhi-completion.bash' >> ~/.bash_profile\");\n console.log(\" source ~/.bash_profile\");\n console.log();\n console.log(\"📝 Fish:\");\n console.log(\n \" xiaozhi --completion-fish >> ~/.config/fish/completions/xiaozhi.fish\"\n );\n console.log();\n console.log(\"✨ 设置完成后,你就可以使用 Tab 键进行自动补全了!\");\n console.log();\n console.log(\"💡 示例:\");\n console.log(\" xiaozhi m<Tab> # → mcp\");\n console.log(\" xiaozhi mcp l<Tab> # → list\");\n console.log(\" xiaozhi mcp tool <Tab> # → 显示所有服务器名称\");\n}\n","import { copyFileSync, existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n// 在 ESM 中,需要从 import.meta.url 获取当前文件目录\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n// 默认连接配置\nconst DEFAULT_CONNECTION_CONFIG: Required<ConnectionConfig> = {\n heartbeatInterval: 30000, // 30秒心跳间隔\n heartbeatTimeout: 10000, // 10秒心跳超时\n reconnectInterval: 5000, // 5秒重连间隔\n};\n\n// 配置文件接口定义\n// 本地 MCP 服务配置\nexport interface LocalMCPServerConfig {\n command: string;\n args: string[];\n env?: Record<string, string>;\n}\n\n// ModelScope SSE MCP 服务配置\nexport interface SSEMCPServerConfig {\n type: \"sse\";\n url: string;\n}\n\n// 统一的 MCP 服务配置\nexport type MCPServerConfig = LocalMCPServerConfig | SSEMCPServerConfig;\n\nexport interface MCPToolConfig {\n description?: string;\n enable: boolean;\n}\n\nexport interface MCPServerToolsConfig {\n tools: Record<string, MCPToolConfig>;\n}\n\nexport interface ConnectionConfig {\n heartbeatInterval?: number; // 心跳检测间隔(毫秒),默认30000\n heartbeatTimeout?: number; // 心跳超时时间(毫秒),默认10000\n reconnectInterval?: number; // 重连间隔(毫秒),默认5000\n}\n\nexport interface ModelScopeConfig {\n apiKey?: string; // ModelScope API 密钥\n}\n\nexport interface AppConfig {\n mcpEndpoint: string;\n mcpServers: Record<string, MCPServerConfig>;\n mcpServerConfig?: Record<string, MCPServerToolsConfig>;\n connection?: ConnectionConfig; // 连接配置(可选,用于向后兼容)\n modelscope?: ModelScopeConfig; // ModelScope 配置(可选)\n}\n\n/**\n * 配置管理类\n * 负责管理应用配置,提供只读访问和安全的配置更新功能\n */\nexport class ConfigManager {\n private static instance: ConfigManager;\n private defaultConfigPath: string;\n private config: AppConfig | null = null;\n\n private constructor() {\n this.defaultConfigPath = resolve(__dirname, \"xiaozhi.config.default.json\");\n }\n\n /**\n * 获取配置文件路径(动态计算)\n */\n private getConfigFilePath(): string {\n // 配置文件路径 - 优先使用环境变量指定的目录,否则使用当前工作目录\n const configDir = process.env.XIAOZHI_CONFIG_DIR || process.cwd();\n return resolve(configDir, \"xiaozhi.config.json\");\n }\n\n /**\n * 获取配置管理器单例实例\n */\n public static getInstance(): ConfigManager {\n if (!ConfigManager.instance) {\n ConfigManager.instance = new ConfigManager();\n }\n return ConfigManager.instance;\n }\n\n /**\n * 检查配置文件是否存在\n */\n public configExists(): boolean {\n const configPath = this.getConfigFilePath();\n return existsSync(configPath);\n }\n\n /**\n * 初始化配置文件\n * 从 config.default.json 复制到 config.json\n */\n public initConfig(): void {\n if (!existsSync(this.defaultConfigPath)) {\n throw new Error(\"默认配置文件 xiaozhi.config.default.json 不存在\");\n }\n\n if (this.configExists()) {\n throw new Error(\"配置文件 xiaozhi.config.json 已存在,无需重复初始化\");\n }\n\n const configPath = this.getConfigFilePath();\n copyFileSync(this.defaultConfigPath, configPath);\n this.config = null; // 重置缓存\n }\n\n /**\n * 加载配置文件\n */\n private loadConfig(): AppConfig {\n if (!this.configExists()) {\n throw new Error(\n \"配置文件 xiaozhi.config.json 不存在,请先运行 xiaozhi init 初始化配置\"\n );\n }\n\n try {\n const configPath = this.getConfigFilePath();\n const configData = readFileSync(configPath, \"utf8\");\n const config = JSON.parse(configData) as AppConfig;\n\n // 验证配置结构\n this.validateConfig(config);\n\n return config;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`配置文件格式错误: ${error.message}`);\n }\n throw error;\n }\n }\n\n /**\n * 验证配置文件结构\n */\n private validateConfig(config: unknown): void {\n if (!config || typeof config !== \"object\") {\n throw new Error(\"配置文件格式错误:根对象无效\");\n }\n\n const configObj = config as Record<string, unknown>;\n\n if (!configObj.mcpEndpoint || typeof configObj.mcpEndpoint !== \"string\") {\n throw new Error(\"配置文件格式错误:mcpEndpoint 字段无效\");\n }\n\n if (!configObj.mcpServers || typeof configObj.mcpServers !== \"object\") {\n throw new Error(\"配置文件格式错误:mcpServers 字段无效\");\n }\n\n // 验证每个 MCP 服务配置\n for (const [serverName, serverConfig] of Object.entries(\n configObj.mcpServers as Record<string, unknown>\n )) {\n if (!serverConfig || typeof serverConfig !== \"object\") {\n throw new Error(`配置文件格式错误:mcpServers.${serverName} 无效`);\n }\n\n const sc = serverConfig as Record<string, unknown>;\n\n // 检查是否是 SSE 类型\n if (sc.type === \"sse\") {\n // SSE 类型的验证\n if (!sc.url || typeof sc.url !== \"string\") {\n throw new Error(\n `配置文件格式错误:mcpServers.${serverName}.url 无效`\n );\n }\n } else {\n // 本地类型的验证\n if (!sc.command || typeof sc.command !== \"string\") {\n throw new Error(\n `配置文件格式错误:mcpServers.${serverName}.command 无效`\n );\n }\n\n if (!Array.isArray(sc.args)) {\n throw new Error(\n `配置文件格式错误:mcpServers.${serverName}.args 必须是数组`\n );\n }\n\n if (sc.env && typeof sc.env !== \"object\") {\n throw new Error(\n `配置文件格式错误:mcpServers.${serverName}.env 必须是对象`\n );\n }\n }\n }\n }\n\n /**\n * 获取配置(只读)\n */\n public getConfig(): Readonly<AppConfig> {\n if (!this.config) {\n this.config = this.loadConfig();\n }\n\n // 返回深度只读副本\n return JSON.parse(JSON.stringify(this.config));\n }\n\n /**\n * 获取 MCP 端点\n */\n public getMcpEndpoint(): string {\n const config = this.getConfig();\n return config.mcpEndpoint;\n }\n\n /**\n * 获取 MCP 服务配置\n */\n public getMcpServers(): Readonly<Record<string, MCPServerConfig>> {\n const config = this.getConfig();\n return config.mcpServers;\n }\n\n /**\n * 获取 MCP 服务工具配置\n */\n public getMcpServerConfig(): Readonly<Record<string, MCPServerToolsConfig>> {\n const config = this.getConfig();\n return config.mcpServerConfig || {};\n }\n\n /**\n * 获取指定服务的工具配置\n */\n public getServerToolsConfig(\n serverName: string\n ): Readonly<Record<string, MCPToolConfig>> {\n const serverConfig = this.getMcpServerConfig();\n return serverConfig[serverName]?.tools || {};\n }\n\n /**\n * 检查工具是否启用\n */\n public isToolEnabled(serverName: string, toolName: string): boolean {\n const toolsConfig = this.getServerToolsConfig(serverName);\n const toolConfig = toolsConfig[toolName];\n return toolConfig?.enable !== false; // 默认启用\n }\n\n /**\n * 更新 MCP 端点\n */\n public updateMcpEndpoint(endpoint: string): void {\n if (!endpoint || typeof endpoint !== \"string\") {\n throw new Error(\"MCP 端点必须是非空字符串\");\n }\n\n const config = this.getConfig();\n const newConfig = { ...config, mcpEndpoint: endpoint };\n this.saveConfig(newConfig);\n }\n\n /**\n * 更新 MCP 服务配置\n */\n public updateMcpServer(\n serverName: string,\n serverConfig: MCPServerConfig\n ): void {\n if (!serverName || typeof serverName !== \"string\") {\n throw new Error(\"服务名称必须是非空字符串\");\n }\n\n // 验证服务配置\n if (\"type\" in serverConfig && serverConfig.type === \"sse\") {\n // SSE 类型的验证\n if (!serverConfig.url || typeof serverConfig.url !== \"string\") {\n throw new Error(\"SSE 服务配置的 url 字段必须是非空字符串\");\n }\n } else {\n // 本地类型的验证\n const localConfig = serverConfig as LocalMCPServerConfig;\n if (!localConfig.command || typeof localConfig.command !== \"string\") {\n throw new Error(\"服务配置的 command 字段必须是非空字符串\");\n }\n\n if (!Array.isArray(localConfig.args)) {\n throw new Error(\"服务配置的 args 字段必须是数组\");\n }\n\n if (localConfig.env && typeof localConfig.env !== \"object\") {\n throw new Error(\"服务配置的 env 字段必须是对象\");\n }\n }\n\n const config = this.getConfig();\n const newConfig = {\n ...config,\n mcpServers: {\n ...config.mcpServers,\n [serverName]: serverConfig,\n },\n };\n this.saveConfig(newConfig);\n }\n\n /**\n * 删除 MCP 服务配置\n */\n public removeMcpServer(serverName: string): void {\n if (!serverName || typeof serverName !== \"string\") {\n throw new Error(\"服务名称必须是非空字符串\");\n }\n\n const config = this.getConfig();\n if (!config.mcpServers[serverName]) {\n throw new Error(`服务 ${serverName} 不存在`);\n }\n\n const newMcpServers = { ...config.mcpServers };\n delete newMcpServers[serverName];\n\n const newConfig = {\n ...config,\n mcpServers: newMcpServers,\n };\n this.saveConfig(newConfig);\n }\n\n /**\n * 更新服务工具配置\n */\n public updateServerToolsConfig(\n serverName: string,\n toolsConfig: Record<string, MCPToolConfig>\n ): void {\n const config = this.getConfig();\n const newConfig = { ...config };\n\n // 确保 mcpServerConfig 存在\n if (!newConfig.mcpServerConfig) {\n newConfig.mcpServerConfig = {};\n }\n\n // 更新指定服务的工具配置\n newConfig.mcpServerConfig[serverName] = {\n tools: toolsConfig,\n };\n\n this.saveConfig(newConfig);\n }\n\n /**\n * 设置工具启用状态\n */\n public setToolEnabled(\n serverName: string,\n toolName: string,\n enabled: boolean,\n description?: string\n ): void {\n const config = this.getConfig();\n const newConfig = { ...config };\n\n // 确保 mcpServerConfig 存在\n if (!newConfig.mcpServerConfig) {\n newConfig.mcpServerConfig = {};\n }\n\n // 确保服务配置存在\n if (!newConfig.mcpServerConfig[serverName]) {\n newConfig.mcpServerConfig[serverName] = { tools: {} };\n }\n\n // 更新工具配置\n newConfig.mcpServerConfig[serverName].tools[toolName] = {\n enable: enabled,\n ...(description && { description }),\n };\n\n this.saveConfig(newConfig);\n }\n\n /**\n * 保存配置到文件\n */\n private saveConfig(config: AppConfig): void {\n try {\n // 验证配置\n this.validateConfig(config);\n\n // 格式化 JSON 并保存\n const configPath = this.getConfigFilePath();\n const configJson = JSON.stringify(config, null, 2);\n writeFileSync(configPath, configJson, \"utf8\");\n\n // 更新缓存\n this.config = config;\n } catch (error) {\n throw new Error(\n `保存配置失败: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * 重新加载配置(清除缓存)\n */\n public reloadConfig(): void {\n this.config = null;\n }\n\n /**\n * 获取配置文件路径\n */\n public getConfigPath(): string {\n return this.getConfigFilePath();\n }\n\n /**\n * 获取默认配置文件路径\n */\n public getDefaultConfigPath(): string {\n return this.defaultConfigPath;\n }\n\n /**\n * 获取连接配置(包含默认值)\n */\n public getConnectionConfig(): Required<ConnectionConfig> {\n const config = this.getConfig();\n const connectionConfig = config.connection || {};\n\n return {\n heartbeatInterval:\n connectionConfig.heartbeatInterval ??\n DEFAULT_CONNECTION_CONFIG.heartbeatInterval,\n heartbeatTimeout:\n connectionConfig.heartbeatTimeout ??\n DEFAULT_CONNECTION_CONFIG.heartbeatTimeout,\n reconnectInterval:\n connectionConfig.reconnectInterval ??\n DEFAULT_CONNECTION_CONFIG.reconnectInterval,\n };\n }\n\n /**\n * 获取心跳检测间隔(毫秒)\n */\n public getHeartbeatInterval(): number {\n return this.getConnectionConfig().heartbeatInterval;\n }\n\n /**\n * 获取心跳超时时间(毫秒)\n */\n public getHeartbeatTimeout(): number {\n return this.getConnectionConfig().heartbeatTimeout;\n }\n\n /**\n * 获取重连间隔(毫秒)\n */\n public getReconnectInterval(): number {\n return this.getConnectionConfig().reconnectInterval;\n }\n\n /**\n * 更新连接配置\n */\n public updateConnectionConfig(\n connectionConfig: Partial<ConnectionConfig>\n ): void {\n const config = this.getConfig();\n const currentConnectionConfig = config.connection || {};\n\n const newConnectionConfig = {\n ...currentConnectionConfig,\n ...connectionConfig,\n };\n\n const newConfig = {\n ...config,\n connection: newConnectionConfig,\n };\n\n this.saveConfig(newConfig);\n }\n\n /**\n * 设置心跳检测间隔\n */\n public setHeartbeatInterval(interval: number): void {\n if (interval <= 0) {\n throw new Error(\"心跳检测间隔必须大于0\");\n }\n this.updateConnectionConfig({ heartbeatInterval: interval });\n }\n\n /**\n * 设置心跳超时时间\n */\n public setHeartbeatTimeout(timeout: number): void {\n if (timeout <= 0) {\n throw new Error(\"心跳超时时间必须大于0\");\n }\n this.updateConnectionConfig({ heartbeatTimeout: timeout });\n }\n\n /**\n * 设置重连间隔\n */\n public setReconnectInterval(interval: number): void {\n if (interval <= 0) {\n throw new Error(\"重连间隔必须大于0\");\n }\n this.updateConnectionConfig({ reconnectInterval: interval });\n }\n\n /**\n * 获取 ModelScope 配置\n */\n public getModelScopeConfig(): Readonly<ModelScopeConfig> {\n const config = this.getConfig();\n return config.modelscope || {};\n }\n\n /**\n * 获取 ModelScope API Key\n * 优先从配置文件读取,其次从环境变量读取\n */\n public getModelScopeApiKey(): string | undefined {\n const modelScopeConfig = this.getModelScopeConfig();\n return modelScopeConfig.apiKey || process.env.MODELSCOPE_API_TOKEN;\n }\n\n /**\n * 更新 ModelScope 配置\n */\n public updateModelScopeConfig(\n modelScopeConfig: Partial<ModelScopeConfig>\n ): void {\n const config = this.getConfig();\n const currentModelScopeConfig = config.modelscope || {};\n\n const newModelScopeConfig = {\n ...currentModelScopeConfig,\n ...modelScopeConfig,\n };\n\n const newConfig = {\n ...config,\n modelscope: newModelScopeConfig,\n };\n\n this.saveConfig(newConfig);\n }\n\n /**\n * 设置 ModelScope API Key\n */\n public setModelScopeApiKey(apiKey: string): void {\n if (!apiKey || typeof apiKey !== \"string\") {\n throw new Error(\"API Key 必须是非空字符串\");\n }\n this.updateModelScopeConfig({ apiKey });\n }\n}\n\n// 导出单例实例\nexport const configManager = ConfigManager.getInstance();\n"],"mappings":"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","names":["omelette","copyFileSync","existsSync","readFileSync","writeFileSync","dirname","resolve","fileURLToPath","__dirname","dirname","fileURLToPath","DEFAULT_CONNECTION_CONFIG","ConfigManager","_ConfigManager","__name","resolve","configDir","configPath","existsSync","copyFileSync","configData","readFileSync","config","error","configObj","serverName","serverConfig","sc","toolName","endpoint","newConfig","localConfig","newMcpServers","toolsConfig","enabled","description","configJson","writeFileSync","connectionConfig","newConnectionConfig","interval","timeout","modelScopeConfig","newModelScopeConfig","apiKey","configManager","getMcpServerNames","configManager","mcpServers","__name","getServerToolNames","serverName","toolsConfig","setupAutoCompletion","completion","omelette","reply","fragment","line","before","parts","currentIndex","subcommand","subcommands","current","matches","cmd","options","opt","serverNames","name","toolNames","actions","action","error","showCompletionHelp"]}
|
package/dist/cli.d.ts
CHANGED
|
@@ -1 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 获取版本号
|
|
4
|
+
*/
|
|
5
|
+
declare function getVersion(): string;
|
|
6
|
+
interface ServiceStatus {
|
|
7
|
+
running: boolean;
|
|
8
|
+
pid?: number;
|
|
9
|
+
uptime?: string;
|
|
10
|
+
mode?: "foreground" | "daemon";
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 获取服务状态
|
|
14
|
+
*/
|
|
15
|
+
declare function getServiceStatus(): ServiceStatus;
|
|
16
|
+
/**
|
|
17
|
+
* 格式化运行时间
|
|
18
|
+
*/
|
|
19
|
+
declare function formatUptime(ms: number): string;
|
|
20
|
+
/**
|
|
21
|
+
* 检查配置文件和环境
|
|
22
|
+
*/
|
|
23
|
+
declare function checkEnvironment(): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* 计算字符串相似度(简单的编辑距离算法)
|
|
26
|
+
*/
|
|
27
|
+
declare function calculateSimilarity(str1: string, str2: string): number;
|
|
28
|
+
|
|
29
|
+
export { calculateSimilarity, checkEnvironment, formatUptime, getServiceStatus, getVersion };
|
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var K=Object.defineProperty;var a=(e,o)=>K(e,"name",{value:o,configurable:!0});import{spawn as G}from"child_process";import p from"fs";import J from"os";import f from"path";import{fileURLToPath as P}from"url";import r from"chalk";import{Command as ro}from"commander";import b from"ora";import to from"omelette";import{copyFileSync as Y,existsSync as T,readFileSync as q,writeFileSync as Q}from"fs";import{dirname as oo,resolve as k}from"path";import{fileURLToPath as eo}from"url";var no=oo(eo(import.meta.url)),E=class e{static{a(this,"ConfigManager")}static instance;defaultConfigPath;config=null;constructor(){this.defaultConfigPath=k(no,"xiaozhi.config.default.json")}getConfigFilePath(){let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return k(o,"xiaozhi.config.json")}static getInstance(){return e.instance||(e.instance=new e),e.instance}configExists(){let o=this.getConfigFilePath();return T(o)}initConfig(){if(!T(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(),n=q(o,"utf8"),t=JSON.parse(n);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 n=o;if(!n.mcpEndpoint||typeof n.mcpEndpoint!="string")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5B57\u6BB5\u65E0\u6548");if(!n.mcpServers||typeof n.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(n.mcpServers)){if(!i||typeof i!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t} \u65E0\u6548`);let c=i;if(!c.command||typeof c.command!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.command \u65E0\u6548`);if(!Array.isArray(c.args))throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.args \u5FC5\u987B\u662F\u6570\u7EC4`);if(c.env&&typeof c.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,n){return this.getServerToolsConfig(o)[n]?.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,n){if(!o||typeof o!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!n.command||typeof n.command!="string")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 command \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!Array.isArray(n.args))throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 args \u5B57\u6BB5\u5FC5\u987B\u662F\u6570\u7EC4");if(n.env&&typeof n.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]:n}};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 n=this.getConfig();if(!n.mcpServers[o])throw new Error(`\u670D\u52A1 ${o} \u4E0D\u5B58\u5728`);let t={...n.mcpServers};delete t[o];let i={...n,mcpServers:t};this.saveConfig(i)}updateServerToolsConfig(o,n){let i={...this.getConfig()};i.mcpServerConfig||(i.mcpServerConfig={}),i.mcpServerConfig[o]={tools:n},this.saveConfig(i)}setToolEnabled(o,n,t,i){let s={...this.getConfig()};s.mcpServerConfig||(s.mcpServerConfig={}),s.mcpServerConfig[o]||(s.mcpServerConfig[o]={tools:{}}),s.mcpServerConfig[o].tools[n]={enable:t,...i&&{description:i}},this.saveConfig(s)}saveConfig(o){try{this.validateConfig(o);let n=this.getConfigFilePath(),t=JSON.stringify(o,null,2);Q(n,t,"utf8"),this.config=o}catch(n){throw new Error(`\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`)}}reloadConfig(){this.config=null}getConfigPath(){return this.getConfigFilePath()}getDefaultConfigPath(){return this.defaultConfigPath}},m=E.getInstance();function io(){try{if(!m.configExists())return[];let e=m.getMcpServers();return Object.keys(e)}catch{return[]}}a(io,"getMcpServerNames");function so(e){try{if(!m.configExists())return[];let o=m.getServerToolsConfig(e);return Object.keys(o)}catch{return[]}}a(so,"getServerToolNames");function I(){let e=to("xiaozhi");e.on("complete",(o,{line:n,before:t,reply:i})=>{let c=n.trim(),s=c.split(/\s+/),d=n!==c?s.length:s.length-1;if(d===1){let u=["create","init","config","start","stop","status","attach","restart","mcp","completion"],h=s[1]||"",y=u.filter(C=>C.startsWith(h));i(y);return}if(d===2){switch(s[1]){case"create":i(["--template","-t"]);break;case"start":case"restart":i(["--daemon","-d"]);break;case"completion":i(["install","uninstall"]);break;case"mcp":{let h=["list","server","tool"],y=s[2]||"",C=h.filter(S=>S.startsWith(y));i(C);break}default:i([])}return}if(s[1]==="mcp"){let u=s[2];if(d===3){switch(u){case"list":{let h=["--tools"],y=s[3]||"",C=h.filter(S=>S.startsWith(y));i(C);break}case"server":case"tool":{let h=io(),y=s[3]||"",C=h.filter(S=>S.startsWith(y));i(C);break}default:i([])}return}if(d===4&&u==="tool"){let h=s[3],y=so(h),C=s[4]||"",S=y.filter(X=>X.startsWith(C));i(S);return}if(d===5&&u==="tool"){let h=["enable","disable"],y=s[5]||"",C=h.filter(S=>S.startsWith(y));i(C);return}}i([])}),process.argv.includes("--completion")&&(console.log(e.setupShellInitFile()),process.exit(0)),process.argv.includes("--completion-fish")&&(console.log(e.setupShellInitFile("fish")),process.exit(0)),process.argv.includes("--compzsh")||process.argv.includes("--compbash"),e.init()}a(I,"setupAutoCompletion");function D(){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")}a(D,"showCompletionHelp");import l from"chalk";import O from"cli-table3";import M from"ora";function R(e){let o=0;for(let n of e)/[\u4e00-\u9fff\u3400-\u4dbf\uff00-\uffef]/.test(n)?o+=2:o+=1;return o}a(R,"getDisplayWidth");function F(e,o){if(R(e)<=o)return e;if(o<=3)return"";let n="",t=0,i=!1;for(let c of e){let s=/[\u4e00-\u9fff\u3400-\u4dbf\uff00-\uffef]/.test(c)?2:1;if(t+s>o-3){if(!i)return"";n+="...";break}n+=c,t+=s,i=!0}return n}a(F,"truncateToWidth");async function A(e={}){let o=M("\u83B7\u53D6 MCP \u670D\u52A1\u5217\u8868...").start();try{let n=m.getMcpServers(),t=Object.keys(n);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`),e.tools){console.log(),console.log(l.bold("MCP \u670D\u52A1\u5DE5\u5177\u5217\u8868:")),console.log();let i=8,c=[];for(let g of t){let d=m.getServerToolsConfig(g),u=Object.keys(d);c.push(...u)}for(let g of c){let d=R(g);d>i&&(i=d)}i=Math.max(10,Math.min(i+2,30));let s=new O({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 g of t){let d=m.getServerToolsConfig(g),u=Object.keys(d);if(u.length===0)s.push([l.gray(g),l.gray("(\u65E0\u5DE5\u5177)"),l.gray("-"),l.gray("\u8BF7\u5148\u542F\u52A8\u670D\u52A1\u626B\u63CF\u5DE5\u5177")]);else{s.length>0&&s.push([{colSpan:4,content:""}]);for(let h of u){let y=d[h],C=y.enable?l.green("\u542F\u7528"):l.red("\u7981\u7528"),S=F(y.description||"",32);s.push([g,h,C,S])}}}console.log(s.toString())}else{console.log(),console.log(l.bold("MCP \u670D\u52A1\u5217\u8868:")),console.log();for(let i of t){let c=n[i],s=m.getServerToolsConfig(i),g=Object.keys(s).length,d=Object.values(s).filter(u=>u.enable!==!1).length;console.log(`${l.cyan("\u2022")} ${l.bold(i)}`),console.log(` \u547D\u4EE4: ${l.gray(c.command)} ${l.gray(c.args.join(" "))}`),g>0?console.log(` \u5DE5\u5177: ${l.green(d)} \u542F\u7528 / ${l.yellow(g)} \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(n){o.fail("\u83B7\u53D6 MCP \u670D\u52A1\u5217\u8868\u5931\u8D25"),console.error(l.red(`\u9519\u8BEF: ${n instanceof Error?n.message:String(n)}`)),process.exit(1)}}a(A,"listMcpServers");async function W(e){let o=M(`\u83B7\u53D6 ${e} \u670D\u52A1\u7684\u5DE5\u5177\u5217\u8868...`).start();try{if(!m.getMcpServers()[e]){o.fail(`\u670D\u52A1 '${e}' \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=m.getServerToolsConfig(e),i=Object.keys(t);if(i.length===0){o.warn(`\u670D\u52A1 '${e}' \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 '${e}' \u5171\u6709 ${i.length} \u4E2A\u5DE5\u5177`),console.log(),console.log(l.bold(`${e} \u670D\u52A1\u5DE5\u5177\u5217\u8868:`)),console.log();let c=new O({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 s of i){let g=t[s],d=g.enable?l.green("\u542F\u7528"):l.red("\u7981\u7528"),u=F(g.description||"",40);c.push([s,d,u])}console.log(c.toString()),console.log(),console.log(l.gray("\u{1F4A1} \u63D0\u793A:")),console.log(l.gray(` - \u4F7F\u7528 'xiaozhi mcp ${e} <\u5DE5\u5177\u540D> enable' \u542F\u7528\u5DE5\u5177`)),console.log(l.gray(` - \u4F7F\u7528 'xiaozhi mcp ${e} <\u5DE5\u5177\u540D> disable' \u7981\u7528\u5DE5\u5177`))}catch(n){o.fail("\u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25"),console.error(l.red(`\u9519\u8BEF: ${n instanceof Error?n.message:String(n)}`)),process.exit(1)}}a(W,"listServerTools");async function L(e,o,n){let t=n?"\u542F\u7528":"\u7981\u7528",i=M(`${t}\u5DE5\u5177 ${e}/${o}...`).start();try{if(!m.getMcpServers()[e]){i.fail(`\u670D\u52A1 '${e}' \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 s=m.getServerToolsConfig(e);if(!s[o]){i.fail(`\u5DE5\u5177 '${o}' \u5728\u670D\u52A1 '${e}' \u4E2D\u4E0D\u5B58\u5728`),console.log(l.yellow(`\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp ${e} list' \u67E5\u770B\u8BE5\u670D\u52A1\u7684\u6240\u6709\u5DE5\u5177`));return}m.setToolEnabled(e,o,n,s[o].description),i.succeed(`\u6210\u529F${t}\u5DE5\u5177 ${l.cyan(e)}/${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(c){i.fail(`${t}\u5DE5\u5177\u5931\u8D25`),console.error(l.red(`\u9519\u8BEF: ${c instanceof Error?c.message:String(c)}`)),process.exit(1)}}a(L,"setToolEnabled");var w=new ro,H="xiaozhi-mcp-service";function V(){try{let e=P(import.meta.url),o=f.dirname(e),n=[f.join(o,"..","package.json"),f.join(o,"..","package.json"),f.join(o,"..","..","package.json"),f.join(o,"package.json")];for(let t of n)if(p.existsSync(t)){let i=JSON.parse(p.readFileSync(t,"utf8"));if(i.version)return i.version}return"unknown"}catch(e){return console.warn("Warning: Could not read version from package.json:",e),"unknown"}}a(V,"getVersion");var v=f.join(J.tmpdir(),`${H}.pid`),x=f.join(J.tmpdir(),`${H}.log`);function $(){try{if(!p.existsSync(v))return{running:!1};let e=p.readFileSync(v,"utf8").trim(),[o,n,t]=e.split("|"),i=Number.parseInt(o);if(Number.isNaN(i))return p.unlinkSync(v),{running:!1};try{process.kill(i,0);let c=Number.parseInt(n),s=co(Date.now()-c);return{running:!0,pid:i,uptime:s,mode:t||"foreground"}}catch{return p.unlinkSync(v),{running:!1}}}catch{return{running:!1}}}a($,"getServiceStatus");function co(e){let o=Math.floor(e/1e3),n=Math.floor(o/60),t=Math.floor(n/60),i=Math.floor(t/24);return i>0?`${i}\u5929 ${t%24}\u5C0F\u65F6 ${n%60}\u5206\u949F`:t>0?`${t}\u5C0F\u65F6 ${n%60}\u5206\u949F`:n>0?`${n}\u5206\u949F ${o%60}\u79D2`:`${o}\u79D2`}a(co,"formatUptime");function _(e,o){let n=`${e}|${Date.now()}|${o}`;p.writeFileSync(v,n)}a(_,"savePidInfo");function z(){try{p.existsSync(v)&&p.unlinkSync(v)}catch{}}a(z,"cleanupPidFile");function lo(){if(!m.configExists())return console.error(r.red("\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728")),console.log(r.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E')),!1;try{let e=m.getMcpEndpoint();return!e||e.includes("<\u8BF7\u586B\u5199")?(console.error(r.red("\u274C \u9519\u8BEF: MCP \u7AEF\u70B9\u672A\u914D\u7F6E")),console.log(r.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi config mcpEndpoint <your-endpoint-url>" \u8BBE\u7F6E\u7AEF\u70B9')),!1):!0}catch(e){return console.error(r.red(`\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u65E0\u6548 - ${e instanceof Error?e.message:String(e)}`)),console.log(r.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u91CD\u65B0\u521D\u59CB\u5316\u914D\u7F6E')),!1}}a(lo,"checkEnvironment");function ao(){let e=f.dirname(P(import.meta.url)),o;return e.includes("js-demo/dist")?o=e:o=[f.join(e,"..","js-demo","dist"),f.join(e,"..","..","js-demo","dist"),f.join(e,"..","..","..","js-demo","dist"),f.join(process.cwd(),"js-demo","dist"),f.join(process.cwd(),"dist")].find(t=>p.existsSync(f.join(t,"mcpPipe.js"))&&p.existsSync(f.join(t,"mcpServerProxy.js")))||e,{command:"node",args:["mcpPipe.js","mcpServerProxy.js"],cwd:o}}a(ao,"getServiceCommand");async function U(e=!1){let o=b("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let n=$();if(n.running){o.fail(`\u670D\u52A1\u5DF2\u7ECF\u5728\u8FD0\u884C (PID: ${n.pid})`);return}if(o.text="\u68C0\u67E5\u73AF\u5883\u914D\u7F6E...",!lo()){o.fail("\u73AF\u5883\u914D\u7F6E\u68C0\u67E5\u5931\u8D25");return}let{command:t,args:i,cwd:c}=ao();if(o.text=`\u542F\u52A8\u670D\u52A1 (${e?"\u540E\u53F0\u6A21\u5F0F":"\u524D\u53F0\u6A21\u5F0F"})...`,e){let s=G(t,i,{cwd:c,detached:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd()}});_(s.pid,"daemon");let g=p.createWriteStream(x,{flags:"a"});s.stdout?.pipe(g),s.stderr?.pipe(g),s.unref(),o.succeed(`\u670D\u52A1\u5DF2\u5728\u540E\u53F0\u542F\u52A8 (PID: ${s.pid})`),console.log(r.gray(`\u65E5\u5FD7\u6587\u4EF6: ${x}`)),console.log(r.gray("\u4F7F\u7528 'xiaozhi attach' \u53EF\u4EE5\u67E5\u770B\u5B9E\u65F6\u65E5\u5FD7"))}else{o.succeed("\u670D\u52A1\u542F\u52A8\u4E2D...");let s=G(t,i,{cwd:c,stdio:"inherit",env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd()}});_(s.pid,"foreground"),s.on("exit",(g,d)=>{z(),console.log(g!==0?r.red(`
|
|
3
|
-
\u670D\u52A1\u5F02\u5E38\u9000\u51FA (\u4EE3\u7801: ${g}, \u4FE1\u53F7: ${d})`):r.green(`
|
|
4
|
-
\u670D\u52A1\
|
|
5
|
-
\
|
|
6
|
-
\
|
|
7
|
-
\u65AD\u5F00\u8FDE\u63A5\uFF0C\u670D\u52A1\u7EE7\u7EED\u5728\u540E\u53F0\u8FD0\u884C`)),t.kill(),process.exit(0)}),t.on("exit",()=>{process.exit(0)})}else console.log(r.yellow("\u65E5\u5FD7\u6587\u4EF6\u4E0D\u5B58\u5728"))}catch(o){e.fail(`\u8FDE\u63A5\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}a(fo,"attachService");async function po(e=!1){console.log(r.blue("\u{1F504} \u91CD\u542F\u670D\u52A1...")),await Z(),await new Promise(o=>setTimeout(o,1e3)),await U(e)}a(po,"restartService");function mo(){let e=V();console.log(r.blue(`xiaozhi v${e}`)),console.log(r.gray("MCP Calculator Service CLI Tool")),console.log(r.gray("Built with Node.js and TypeScript")),console.log(r.gray(`Node.js: ${process.version}`)),console.log(r.gray(`Platform: ${process.platform} ${process.arch}`))}a(mo,"showDetailedInfo");async function uo(){let e=b("\u521D\u59CB\u5316\u914D\u7F6E...").start();try{if(m.configExists()){e.warn("\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728"),console.log(r.yellow("\u5982\u9700\u91CD\u65B0\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u5220\u9664\u73B0\u6709\u7684 xiaozhi.config.json \u6587\u4EF6"));return}m.initConfig(),e.succeed("\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u6210\u529F"),console.log(r.green("\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u521B\u5EFA: xiaozhi.config.json")),console.log(r.yellow("\u{1F4DD} \u8BF7\u7F16\u8F91\u914D\u7F6E\u6587\u4EF6\u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9:")),console.log(r.gray(` \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84: ${m.getConfigPath()}`)),console.log(r.yellow("\u{1F4A1} \u6216\u8005\u4F7F\u7528\u547D\u4EE4\u8BBE\u7F6E:")),console.log(r.gray(" xiaozhi config mcpEndpoint <your-endpoint-url>"))}catch(o){e.fail(`\u521D\u59CB\u5316\u914D\u7F6E\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}a(uo,"initConfig");function ho(){let e=f.dirname(P(import.meta.url)),n=[f.join(e,"..","templates"),f.join(e,"templates"),f.join(e,"..","..","templates")].find(t=>p.existsSync(t));return n?p.readdirSync(n).filter(t=>{let i=f.join(n,t);return p.statSync(i).isDirectory()}):[]}a(ho,"getAvailableTemplates");function N(e,o){let n=e.length,t=o.length,i=Array(n+1).fill(null).map(()=>Array(t+1).fill(0));for(let s=0;s<=n;s++)i[s][0]=s;for(let s=0;s<=t;s++)i[0][s]=s;for(let s=1;s<=n;s++)for(let g=1;g<=t;g++)e[s-1]===o[g-1]?i[s][g]=i[s-1][g-1]:i[s][g]=Math.min(i[s-1][g]+1,i[s][g-1]+1,i[s-1][g-1]+1);let c=Math.max(n,t);return c===0?1:(c-i[n][t])/c}a(N,"calculateSimilarity");function yo(e,o){if(o.length===0)return null;let n=o[0],t=N(e.toLowerCase(),n.toLowerCase());for(let i of o.slice(1)){let c=N(e.toLowerCase(),i.toLowerCase());c>t&&(t=c,n=i)}return t>.5?n:null}a(yo,"findSimilarTemplate");async function Co(e){if(!process.stdin.isTTY)return console.log("n (\u975E\u4EA4\u4E92\u5F0F\u73AF\u5883)"),!1;let o=await import("readline");return new Promise(n=>{process.stdout.write(e);let t=o.createInterface({input:process.stdin,output:process.stdout}),i=a(c=>{let s=c.trim().toLowerCase();s==="y"||s==="yes"?(t.close(),n(!0)):s==="n"||s==="no"||s===""?(t.close(),n(!1)):process.stdout.write("\u8BF7\u8F93\u5165 y \u6216 n: ")},"handleInput");t.on("line",i),t.on("SIGINT",()=>{t.close(),n(!1)})})}a(Co,"askUserConfirmation");function wo(e){let o={mcpEndpoint:"<\u8BF7\u586B\u5199\u4F60\u7684\u63A5\u5165\u70B9\u5730\u5740\uFF08\u83B7\u53D6\u5730\u5740\u5728 xiaozhi.me\uFF09>",mcpServers:{}},n=f.join(e,"xiaozhi.config.json");p.writeFileSync(n,JSON.stringify(o,null,2),"utf8")}a(wo,"createBasicConfig");async function So(e,o){let n=b("\u521D\u59CB\u5316\u9879\u76EE...").start();try{let t=f.join(process.cwd(),e);if(p.existsSync(t)){n.fail(`\u76EE\u5F55 "${e}" \u5DF2\u5B58\u5728`),console.log(r.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){n.text="\u68C0\u67E5\u6A21\u677F...";let i=ho();if(i.length===0){n.fail("\u627E\u4E0D\u5230 templates \u76EE\u5F55"),console.log(r.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u786E\u4FDD xiaozhi-client \u6B63\u786E\u5B89\u88C5"));return}if(!i.includes(o.template)){n.fail(`\u6A21\u677F "${o.template}" \u4E0D\u5B58\u5728`);let u=yo(o.template,i);if(u)if(console.log(r.yellow(`\u{1F4A1} \u4F60\u662F\u60F3\u4F7F\u7528\u6A21\u677F "${u}" \u5417\uFF1F`)),await Co(r.cyan("\u786E\u8BA4\u4F7F\u7528\u6B64\u6A21\u677F\uFF1F(y/n): ")))o.template=u;else{console.log(r.yellow("\u53EF\u7528\u7684\u6A21\u677F:"));for(let y of i)console.log(r.gray(` - ${y}`));return}else{console.log(r.yellow("\u53EF\u7528\u7684\u6A21\u677F:"));for(let h of i)console.log(r.gray(` - ${h}`));return}}let c=f.dirname(P(import.meta.url)),g=[f.join(c,"..","templates"),f.join(c,"templates"),f.join(c,"..","..","templates")].find(u=>p.existsSync(u)),d=f.join(g,o.template);n.text=`\u4ECE\u6A21\u677F "${o.template}" \u521B\u5EFA\u9879\u76EE "${e}"...`,B(d,t,["node_modules",".pnpm-debug.log","pnpm-lock.yaml"]),n.succeed(`\u9879\u76EE "${e}" \u521B\u5EFA\u6210\u529F`),console.log(r.green("\u2705 \u9879\u76EE\u521B\u5EFA\u5B8C\u6210!")),console.log(r.yellow("\u{1F4DD} \u63A5\u4E0B\u6765\u7684\u6B65\u9AA4:")),console.log(r.gray(` cd ${e}`)),console.log(r.gray(" pnpm install # \u5B89\u88C5\u4F9D\u8D56")),console.log(r.gray(" # \u7F16\u8F91 xiaozhi.config.json \u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9")),console.log(r.gray(" xiaozhi start # \u542F\u52A8\u670D\u52A1"))}else n.text=`\u521B\u5EFA\u57FA\u672C\u9879\u76EE "${e}"...`,p.mkdirSync(t,{recursive:!0}),wo(t),n.succeed(`\u9879\u76EE "${e}" \u521B\u5EFA\u6210\u529F`),console.log(r.green("\u2705 \u57FA\u672C\u9879\u76EE\u521B\u5EFA\u5B8C\u6210!")),console.log(r.yellow("\u{1F4DD} \u63A5\u4E0B\u6765\u7684\u6B65\u9AA4:")),console.log(r.gray(` cd ${e}`)),console.log(r.gray(" # \u7F16\u8F91 xiaozhi.config.json \u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9\u548C\u670D\u52A1")),console.log(r.gray(" xiaozhi start # \u542F\u52A8\u670D\u52A1")),console.log(r.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 --template \u9009\u9879\u53EF\u4EE5\u4ECE\u6A21\u677F\u521B\u5EFA\u9879\u76EE"))}catch(t){n.fail(`\u521B\u5EFA\u9879\u76EE\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}a(So,"createProject");function B(e,o,n=[]){p.existsSync(o)||p.mkdirSync(o,{recursive:!0});let t=p.readdirSync(e);for(let i of t){if(n.some(d=>i.includes(d)))continue;let c=f.join(e,i),s=f.join(o,i);p.statSync(c).isDirectory()?B(c,s,n):p.copyFileSync(c,s)}}a(B,"copyDirectory");async function vo(e,o){let n=b("\u66F4\u65B0\u914D\u7F6E...").start();try{if(!m.configExists()){n.fail("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728"),console.log(r.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E'));return}if(o)switch(e){case"mcpEndpoint":m.updateMcpEndpoint(o),n.succeed(`MCP \u7AEF\u70B9\u5DF2\u66F4\u65B0\u4E3A: ${o}`);break;default:n.fail(`\u914D\u7F6E\u9879 ${e} \u4E0D\u652F\u6301\u901A\u8FC7\u547D\u4EE4\u884C\u8BBE\u7F6E`),console.log(r.yellow("\u652F\u6301\u8BBE\u7F6E\u7684\u914D\u7F6E\u9879: mcpEndpoint"));return}else{n.text="\u8BFB\u53D6\u914D\u7F6E...";let t=m.getConfig();switch(e){case"mcpEndpoint":n.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(r.green(`MCP \u7AEF\u70B9: ${t.mcpEndpoint}`));break;case"mcpServers":n.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(r.green("MCP \u670D\u52A1:"));for(let[i,c]of Object.entries(t.mcpServers))console.log(r.gray(` ${i}: ${c.command} ${c.args.join(" ")}`));break;default:n.fail(`\u672A\u77E5\u7684\u914D\u7F6E\u9879: ${e}`),console.log(r.yellow("\u652F\u6301\u7684\u914D\u7F6E\u9879: mcpEndpoint, mcpServers"));return}}}catch(t){n.fail(`\u914D\u7F6E\u64CD\u4F5C\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}a(vo,"configCommand");function bo(){console.log(r.blue.bold("xiaozhi - MCP Calculator Service CLI")),console.log(),console.log(r.yellow("\u4F7F\u7528\u65B9\u6CD5:")),console.log(" xiaozhi <command> [options]"),console.log(),console.log(r.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(r.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(r.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(r.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(r.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(r.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(r.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")}a(bo,"showHelp");w.name("xiaozhi").description("MCP Calculator Service CLI Tool").version(V(),"-v, --version","\u663E\u793A\u7248\u672C\u4FE1\u606F").helpOption("-h, --help","\u663E\u793A\u5E2E\u52A9\u4FE1\u606F");w.command("create <projectName>").description("\u521B\u5EFA\u9879\u76EE").option("-t, --template <templateName>","\u4F7F\u7528\u6307\u5B9A\u6A21\u677F\u521B\u5EFA\u9879\u76EE").action(async(e,o)=>{await So(e,o)});w.command("init").description("\u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6").action(async()=>{await uo()});w.command("config <key> [value]").description("\u67E5\u770B\u6216\u8BBE\u7F6E\u914D\u7F6E").action(async(e,o)=>{await vo(e,o)});w.command("start").description("\u542F\u52A8\u670D\u52A1").option("-d, --daemon","\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").action(async e=>{await U(e.daemon)});w.command("stop").description("\u505C\u6B62\u670D\u52A1").action(async()=>{await Z()});w.command("status").description("\u68C0\u67E5\u670D\u52A1\u72B6\u6001").action(async()=>{await go()});w.command("attach").description("\u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1\u67E5\u770B\u65E5\u5FD7").action(async()=>{await fo()});w.command("restart").description("\u91CD\u542F\u670D\u52A1").option("-d, --daemon","\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").action(async e=>{await po(e.daemon)});var j=w.command("mcp").description("MCP \u670D\u52A1\u548C\u5DE5\u5177\u7BA1\u7406");j.command("list").description("\u5217\u51FA MCP \u670D\u52A1").option("--tools","\u663E\u793A\u6240\u6709\u670D\u52A1\u7684\u5DE5\u5177\u5217\u8868").action(async e=>{await A(e)});j.command("server <serverName>").description("\u7BA1\u7406\u6307\u5B9A\u7684 MCP \u670D\u52A1").action(async e=>{await W(e)});j.command("tool <serverName> <toolName> <action>").description("\u542F\u7528\u6216\u7981\u7528\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177").action(async(e,o,n)=>{n!=="enable"&&n!=="disable"&&(console.error(r.red("\u9519\u8BEF: \u64CD\u4F5C\u5FC5\u987B\u662F 'enable' \u6216 'disable'")),process.exit(1)),await L(e,o,n==="enable")});w.command("completion").description("\u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E").action(async()=>{D()});w.option("-V","\u663E\u793A\u8BE6\u7EC6\u4FE1\u606F").action(e=>{e.V&&(mo(),process.exit(0))});I();process.argv.length<=2&&(bo(),process.exit(0));w.parse(process.argv);
|
|
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
|
+
\u670D\u52A1\u5F02\u5E38\u9000\u51FA (\u4EE3\u7801: ${a}, \u4FE1\u53F7: ${d})`):s.green(`
|
|
5
|
+
\u670D\u52A1\u5DF2\u505C\u6B62`))}),process.on("SIGINT",()=>{console.log(s.yellow(`
|
|
6
|
+
\u6B63\u5728\u505C\u6B62\u670D\u52A1...`)),c.kill("SIGTERM")}),process.on("SIGTERM",()=>{c.kill("SIGTERM")})}}catch(e){o.fail(`\u542F\u52A8\u670D\u52A1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}g(K,"startService");async function V(){let n=b("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let o=M();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)}`)}}g(V,"stopService");async function yo(){let n=b("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let o=M();if(o.running){if(n.succeed("\u670D\u52A1\u72B6\u6001"),console.log(s.green("\u2705 \u670D\u52A1\u6B63\u5728\u8FD0\u884C")),console.log(s.gray(` PID: ${o.pid}`)),console.log(s.gray(` \u8FD0\u884C\u65F6\u95F4: ${o.uptime}`)),console.log(s.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(s.gray(` \u65E5\u5FD7\u6587\u4EF6: ${e}`))}}else n.succeed("\u670D\u52A1\u72B6\u6001"),console.log(s.red("\u274C \u670D\u52A1\u672A\u8FD0\u884C"))}catch(o){n.fail(`\u68C0\u67E5\u72B6\u6001\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}g(yo,"checkStatus");async function Co(){let n=b("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let o=M();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(s.green(`\u5DF2\u8FDE\u63A5\u5230\u670D\u52A1 (PID: ${o.pid})`)),console.log(s.gray("\u6309 Ctrl+C \u53EF\u4EE5\u65AD\u5F00\u8FDE\u63A5\uFF08\u4E0D\u4F1A\u505C\u6B62\u670D\u52A1\uFF09")),console.log(s.gray("=".repeat(50)));let e=f.join(process.cwd(),"xiaozhi.log");if(u.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(s.yellow(`
|
|
7
|
+
\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(s.yellow(`
|
|
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};
|
|
8
9
|
//# sourceMappingURL=cli.js.map
|