xiaozhi-client 1.6.0-beta.2 → 1.6.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +9 -9
- package/dist/cli.js.map +1 -1
- package/dist/services/mcpServer.js +4 -4
- package/dist/services/mcpServer.js.map +1 -1
- package/dist/webServer.js +9 -9
- package/dist/webServer.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var te=Object.defineProperty;var g=(r,e)=>te(r,"name",{value:e,configurable:!0});var D=(r,e)=>()=>(r&&(e=r(r=0)),e);var xe=(r,e)=>{for(var o in e)te(r,o,{get:e[o],enumerable:!0})};import{copyFileSync as Ee,existsSync as U,readFileSync as Te,writeFileSync as $e}from"fs";import{dirname as Me,resolve as T}from"path";import{fileURLToPath as je}from"url";import Re from"json5";import*as ne from"jsonc-parser";var Oe,X,B,l,E=D(()=>{"use strict";Oe=Me(je(import.meta.url)),X={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},B=class r{static{g(this,"ConfigManager")}static instance;defaultConfigPath;config=null;constructor(){this.defaultConfigPath=T(Oe,"xiaozhi.config.default.json")}getConfigFilePath(){let e=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),o=["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"];for(let t of o){let n=T(e,t);if(U(n))return n}return T(e,"xiaozhi.config.json")}getConfigFileFormat(e){return e.endsWith(".json5")?"json5":e.endsWith(".jsonc")?"jsonc":"json"}static getInstance(){return r.instance||(r.instance=new r),r.instance}configExists(){let e=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),o=["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"];for(let t of o){let n=T(e,t);if(U(n))return!0}return!1}initConfig(e="json"){if(!U(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\u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u521D\u59CB\u5316");let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),t=`xiaozhi.config.${e}`,n=T(o,t);Ee(this.defaultConfigPath,n),this.config=null}loadConfig(){if(!this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u8FD0\u884C xiaozhi init \u521D\u59CB\u5316\u914D\u7F6E");try{let e=this.getConfigFilePath(),o=this.getConfigFileFormat(e),t=Te(e,"utf8"),n;switch(o){case"json5":n=Re.parse(t);break;case"jsonc":n=ne.parse(t);break;default:n=JSON.parse(t);break}return this.validateConfig(n),n}catch(e){throw e instanceof SyntaxError?new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF: ${e.message}`):e}}validateConfig(e){if(!e||typeof e!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A\u6839\u5BF9\u8C61\u65E0\u6548");let o=e;if(o.mcpEndpoint===void 0||o.mcpEndpoint===null)throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5B57\u6BB5\u65E0\u6548");if(typeof o.mcpEndpoint!="string")if(Array.isArray(o.mcpEndpoint)){if(o.mcpEndpoint.length===0)throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u6570\u7EC4\u4E0D\u80FD\u4E3A\u7A7A");for(let t of o.mcpEndpoint)if(typeof t!="string"||t.trim()==="")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u6570\u7EC4\u4E2D\u7684\u6BCF\u4E2A\u5143\u7D20\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6216\u5B57\u7B26\u4E32\u6570\u7EC4");if(!o.mcpServers||typeof o.mcpServers!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers \u5B57\u6BB5\u65E0\u6548");for(let[t,n]of Object.entries(o.mcpServers)){if(!n||typeof n!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t} \u65E0\u6548`);let s=n;if(s.url&&typeof s.url=="string"){if(s.type&&s.type!=="sse"&&s.type!=="streamable-http")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.type \u5FC5\u987B\u662F "sse" \u6216 "streamable-http"`)}else{if(!s.command||typeof s.command!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.command \u65E0\u6548`);if(!Array.isArray(s.args))throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.args \u5FC5\u987B\u662F\u6570\u7EC4`);if(s.env&&typeof s.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(){let e=this.getConfig();return Array.isArray(e.mcpEndpoint)?e.mcpEndpoint[0]||"":e.mcpEndpoint}getMcpEndpoints(){let e=this.getConfig();return Array.isArray(e.mcpEndpoint)?[...e.mcpEndpoint]:e.mcpEndpoint?[e.mcpEndpoint]:[]}getMcpServers(){return this.getConfig().mcpServers}getMcpServerConfig(){return this.getConfig().mcpServerConfig||{}}getServerToolsConfig(e){return this.getMcpServerConfig()[e]?.tools||{}}isToolEnabled(e,o){return this.getServerToolsConfig(e)[o]?.enable!==!1}updateMcpEndpoint(e){if(Array.isArray(e)){if(e.length===0)throw new Error("MCP \u7AEF\u70B9\u6570\u7EC4\u4E0D\u80FD\u4E3A\u7A7A");for(let n of e)if(!n||typeof n!="string")throw new Error("MCP \u7AEF\u70B9\u6570\u7EC4\u4E2D\u7684\u6BCF\u4E2A\u5143\u7D20\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t={...this.getConfig(),mcpEndpoint:e};this.saveConfig(t)}addMcpEndpoint(e){if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let o=this.getConfig(),t=this.getMcpEndpoints();if(t.includes(e))throw new Error(`MCP \u7AEF\u70B9 ${e} \u5DF2\u5B58\u5728`);let n=[...t,e],s={...o,mcpEndpoint:n};this.saveConfig(s)}removeMcpEndpoint(e){if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let o=this.getConfig(),t=this.getMcpEndpoints();if(t.indexOf(e)===-1)throw new Error(`MCP \u7AEF\u70B9 ${e} \u4E0D\u5B58\u5728`);if(t.length===1)throw new Error("\u4E0D\u80FD\u5220\u9664\u6700\u540E\u4E00\u4E2A MCP \u7AEF\u70B9");let s=t.filter(a=>a!==e),c={...o,mcpEndpoint:s};this.saveConfig(c)}updateMcpServer(e,o){if(!e||typeof e!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if("type"in o&&o.type==="sse"){if(!o.url||typeof o.url!="string")throw new Error("SSE \u670D\u52A1\u914D\u7F6E\u7684 url \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else{let s=o;if(!s.command||typeof s.command!="string")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 command \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!Array.isArray(s.args))throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 args \u5B57\u6BB5\u5FC5\u987B\u662F\u6570\u7EC4");if(s.env&&typeof s.env!="object")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 env \u5B57\u6BB5\u5FC5\u987B\u662F\u5BF9\u8C61")}let t=this.getConfig(),n={...t,mcpServers:{...t.mcpServers,[e]:o}};this.saveConfig(n)}removeMcpServer(e){if(!e||typeof e!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let o=this.getConfig();if(!o.mcpServers[e])throw new Error(`\u670D\u52A1 ${e} \u4E0D\u5B58\u5728`);let t={...o.mcpServers};delete t[e];let n={...o,mcpServers:t};this.saveConfig(n)}updateServerToolsConfig(e,o){let n={...this.getConfig()};n.mcpServerConfig||(n.mcpServerConfig={}),Object.keys(o).length===0?delete n.mcpServerConfig[e]:n.mcpServerConfig[e]={tools:o},this.saveConfig(n)}removeServerToolsConfig(e){let t={...this.getConfig()};t.mcpServerConfig&&(delete t.mcpServerConfig[e],this.saveConfig(t))}setToolEnabled(e,o,t,n){let c={...this.getConfig()};c.mcpServerConfig||(c.mcpServerConfig={}),c.mcpServerConfig[e]||(c.mcpServerConfig[e]={tools:{}}),c.mcpServerConfig[e].tools[o]={enable:t,...n&&{description:n}},this.saveConfig(c)}saveConfig(e){try{this.validateConfig(e);let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),t=T(o,"xiaozhi.config.json"),n=JSON.stringify(e,null,2);$e(t,n,"utf8"),this.config=e}catch(o){throw new Error(`\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}reloadConfig(){this.config=null}getConfigPath(){return this.getConfigFilePath()}getDefaultConfigPath(){return this.defaultConfigPath}getConnectionConfig(){let o=this.getConfig().connection||{};return{heartbeatInterval:o.heartbeatInterval??X.heartbeatInterval,heartbeatTimeout:o.heartbeatTimeout??X.heartbeatTimeout,reconnectInterval:o.reconnectInterval??X.reconnectInterval}}getHeartbeatInterval(){return this.getConnectionConfig().heartbeatInterval}getHeartbeatTimeout(){return this.getConnectionConfig().heartbeatTimeout}getReconnectInterval(){return this.getConnectionConfig().reconnectInterval}updateConnectionConfig(e){let o=this.getConfig(),n={...o.connection||{},...e},s={...o,connection:n};this.saveConfig(s)}setHeartbeatInterval(e){if(e<=0)throw new Error("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatInterval:e})}setHeartbeatTimeout(e){if(e<=0)throw new Error("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatTimeout:e})}setReconnectInterval(e){if(e<=0)throw new Error("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({reconnectInterval:e})}getModelScopeConfig(){return this.getConfig().modelscope||{}}getModelScopeApiKey(){return this.getModelScopeConfig().apiKey||process.env.MODELSCOPE_API_TOKEN}updateModelScopeConfig(e){let o=this.getConfig(),n={...o.modelscope||{},...e},s={...o,modelscope:n};this.saveConfig(s)}setModelScopeApiKey(e){if(!e||typeof e!="string")throw new Error("API Key \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");this.updateModelScopeConfig({apiKey:e})}getWebUIConfig(){return this.getConfig().webUI||{}}getWebUIPort(){return this.getWebUIConfig().port??9999}updateWebUIConfig(e){let o=this.getConfig(),n={...o.webUI||{},...e},s={...o,webUI:n};this.saveConfig(s)}setWebUIPort(e){if(!Number.isInteger(e)||e<=0||e>65535)throw new Error("\u7AEF\u53E3\u53F7\u5FC5\u987B\u662F 1-65535 \u4E4B\u95F4\u7684\u6574\u6570");this.updateWebUIConfig({port:e})}},l=B.getInstance()});import W from"fs";import ze from"path";import O from"chalk";import{createConsola as _e}from"consola";function He(r){let e=r.getFullYear(),o=String(r.getMonth()+1).padStart(2,"0"),t=String(r.getDate()).padStart(2,"0"),n=String(r.getHours()).padStart(2,"0"),s=String(r.getMinutes()).padStart(2,"0"),c=String(r.getSeconds()).padStart(2,"0");return`${e}-${o}-${t} ${n}:${s}:${c}`}var k,I,A=D(()=>{"use strict";g(He,"formatDateTime");k=class{static{g(this,"Logger")}logFilePath=null;writeStream=null;consolaInstance;isDaemonMode;constructor(){this.isDaemonMode=process.env.XIAOZHI_DAEMON==="true",this.consolaInstance=_e({formatOptions:{date:!1,colors:!0,compact:!0},fancy:!1});let e=this.isDaemonMode;this.consolaInstance.setReporters([{log:g(o=>{let t={info:"INFO",success:"SUCCESS",warn:"WARN",error:"ERROR",debug:"DEBUG",log:"LOG"},n={info:O.blue,success:O.green,warn:O.yellow,error:O.red,debug:O.gray,log:g(y=>y,"log")},s=t[o.type]||o.type.toUpperCase(),c=n[o.type]||(y=>y),a=He(new Date),m=c(`[${s}]`),u=`[${a}] ${m} ${o.args.join(" ")}`;if(!e)try{console.error(u)}catch(y){if(y instanceof Error&&y.message?.includes("EPIPE"))return;throw y}},"log")}])}initLogFile(e){this.logFilePath=ze.join(e,"xiaozhi.log"),W.existsSync(this.logFilePath)||W.writeFileSync(this.logFilePath,""),this.writeStream=W.createWriteStream(this.logFilePath,{flags:"a",encoding:"utf8"})}logToFile(e,o,...t){if(this.writeStream){let s=`[${new Date().toISOString()}] [${e.toUpperCase()}] ${o}`,c=t.length>0?`${s} ${t.map(a=>typeof a=="object"?JSON.stringify(a):String(a)).join(" ")}`:s;this.writeStream.write(`${c}
|
|
3
|
-
`)}}enableFileLogging(e){e&&!this.writeStream&&this.logFilePath?this.writeStream=W.createWriteStream(this.logFilePath,{flags:"a",encoding:"utf8"}):!e&&this.writeStream&&(this.writeStream.end(),this.writeStream=null)}info(e,...o){this.consolaInstance.info(e,...o),this.logToFile("info",e,...o)}success(e,...o){this.consolaInstance.success(e,...o),this.logToFile("success",e,...o)}warn(e,...o){this.consolaInstance.warn(e,...o),this.logToFile("warn",e,...o)}error(e,...o){this.consolaInstance.error(e,...o),this.logToFile("error",e,...o)}debug(e,...o){this.consolaInstance.debug(e,...o),this.logToFile("debug",e,...o)}log(e,...o){this.consolaInstance.log(e,...o),this.logToFile("log",e,...o)}withTag(e){return this}close(){this.writeStream&&(this.writeStream.end(),this.writeStream=null)}},I=new k});import{spawn as Je}from"child_process";import x from"process";import z from"ws";var me,d,G,he=D(()=>{"use strict"
|
|
2
|
+
var te=Object.defineProperty;var g=(r,e)=>te(r,"name",{value:e,configurable:!0});var D=(r,e)=>()=>(r&&(e=r(r=0)),e);var xe=(r,e)=>{for(var o in e)te(r,o,{get:e[o],enumerable:!0})};import{copyFileSync as $e,existsSync as U,readFileSync as Ee,writeFileSync as Te}from"fs";import{dirname as Me,resolve as E}from"path";import{fileURLToPath as je}from"url";import Re from"json5";import*as ne from"jsonc-parser";var Oe,X,B,l,$=D(()=>{"use strict";Oe=Me(je(import.meta.url)),X={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},B=class r{static{g(this,"ConfigManager")}static instance;defaultConfigPath;config=null;constructor(){this.defaultConfigPath=E(Oe,"xiaozhi.config.default.json")}getConfigFilePath(){let e=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),o=["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"];for(let t of o){let n=E(e,t);if(U(n))return n}return E(e,"xiaozhi.config.json")}getConfigFileFormat(e){return e.endsWith(".json5")?"json5":e.endsWith(".jsonc")?"jsonc":"json"}static getInstance(){return r.instance||(r.instance=new r),r.instance}configExists(){let e=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),o=["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"];for(let t of o){let n=E(e,t);if(U(n))return!0}return!1}initConfig(e="json"){if(!U(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\u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u521D\u59CB\u5316");let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),t=`xiaozhi.config.${e}`,n=E(o,t);$e(this.defaultConfigPath,n),this.config=null}loadConfig(){if(!this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u8FD0\u884C xiaozhi init \u521D\u59CB\u5316\u914D\u7F6E");try{let e=this.getConfigFilePath(),o=this.getConfigFileFormat(e),t=Ee(e,"utf8"),n;switch(o){case"json5":n=Re.parse(t);break;case"jsonc":n=ne.parse(t);break;default:n=JSON.parse(t);break}return this.validateConfig(n),n}catch(e){throw e instanceof SyntaxError?new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF: ${e.message}`):e}}validateConfig(e){if(!e||typeof e!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A\u6839\u5BF9\u8C61\u65E0\u6548");let o=e;if(o.mcpEndpoint===void 0||o.mcpEndpoint===null)throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5B57\u6BB5\u65E0\u6548");if(typeof o.mcpEndpoint!="string")if(Array.isArray(o.mcpEndpoint)){if(o.mcpEndpoint.length===0)throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u6570\u7EC4\u4E0D\u80FD\u4E3A\u7A7A");for(let t of o.mcpEndpoint)if(typeof t!="string"||t.trim()==="")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u6570\u7EC4\u4E2D\u7684\u6BCF\u4E2A\u5143\u7D20\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6216\u5B57\u7B26\u4E32\u6570\u7EC4");if(!o.mcpServers||typeof o.mcpServers!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers \u5B57\u6BB5\u65E0\u6548");for(let[t,n]of Object.entries(o.mcpServers)){if(!n||typeof n!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t} \u65E0\u6548`);let s=n;if(s.url&&typeof s.url=="string"){if(s.type&&s.type!=="sse"&&s.type!=="streamable-http")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.type \u5FC5\u987B\u662F "sse" \u6216 "streamable-http"`)}else{if(!s.command||typeof s.command!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.command \u65E0\u6548`);if(!Array.isArray(s.args))throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.args \u5FC5\u987B\u662F\u6570\u7EC4`);if(s.env&&typeof s.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(){let e=this.getConfig();return Array.isArray(e.mcpEndpoint)?e.mcpEndpoint[0]||"":e.mcpEndpoint}getMcpEndpoints(){let e=this.getConfig();return Array.isArray(e.mcpEndpoint)?[...e.mcpEndpoint]:e.mcpEndpoint?[e.mcpEndpoint]:[]}getMcpServers(){return this.getConfig().mcpServers}getMcpServerConfig(){return this.getConfig().mcpServerConfig||{}}getServerToolsConfig(e){return this.getMcpServerConfig()[e]?.tools||{}}isToolEnabled(e,o){return this.getServerToolsConfig(e)[o]?.enable!==!1}updateMcpEndpoint(e){if(Array.isArray(e)){if(e.length===0)throw new Error("MCP \u7AEF\u70B9\u6570\u7EC4\u4E0D\u80FD\u4E3A\u7A7A");for(let n of e)if(!n||typeof n!="string")throw new Error("MCP \u7AEF\u70B9\u6570\u7EC4\u4E2D\u7684\u6BCF\u4E2A\u5143\u7D20\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t={...this.getConfig(),mcpEndpoint:e};this.saveConfig(t)}addMcpEndpoint(e){if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let o=this.getConfig(),t=this.getMcpEndpoints();if(t.includes(e))throw new Error(`MCP \u7AEF\u70B9 ${e} \u5DF2\u5B58\u5728`);let n=[...t,e],s={...o,mcpEndpoint:n};this.saveConfig(s)}removeMcpEndpoint(e){if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let o=this.getConfig(),t=this.getMcpEndpoints();if(t.indexOf(e)===-1)throw new Error(`MCP \u7AEF\u70B9 ${e} \u4E0D\u5B58\u5728`);if(t.length===1)throw new Error("\u4E0D\u80FD\u5220\u9664\u6700\u540E\u4E00\u4E2A MCP \u7AEF\u70B9");let s=t.filter(a=>a!==e),c={...o,mcpEndpoint:s};this.saveConfig(c)}updateMcpServer(e,o){if(!e||typeof e!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if("type"in o&&o.type==="sse"){if(!o.url||typeof o.url!="string")throw new Error("SSE \u670D\u52A1\u914D\u7F6E\u7684 url \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else{let s=o;if(!s.command||typeof s.command!="string")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 command \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!Array.isArray(s.args))throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 args \u5B57\u6BB5\u5FC5\u987B\u662F\u6570\u7EC4");if(s.env&&typeof s.env!="object")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 env \u5B57\u6BB5\u5FC5\u987B\u662F\u5BF9\u8C61")}let t=this.getConfig(),n={...t,mcpServers:{...t.mcpServers,[e]:o}};this.saveConfig(n)}removeMcpServer(e){if(!e||typeof e!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let o=this.getConfig();if(!o.mcpServers[e])throw new Error(`\u670D\u52A1 ${e} \u4E0D\u5B58\u5728`);let t={...o.mcpServers};delete t[e];let n={...o,mcpServers:t};this.saveConfig(n)}updateServerToolsConfig(e,o){let n={...this.getConfig()};n.mcpServerConfig||(n.mcpServerConfig={}),Object.keys(o).length===0?delete n.mcpServerConfig[e]:n.mcpServerConfig[e]={tools:o},this.saveConfig(n)}removeServerToolsConfig(e){let t={...this.getConfig()};t.mcpServerConfig&&(delete t.mcpServerConfig[e],this.saveConfig(t))}setToolEnabled(e,o,t,n){let c={...this.getConfig()};c.mcpServerConfig||(c.mcpServerConfig={}),c.mcpServerConfig[e]||(c.mcpServerConfig[e]={tools:{}}),c.mcpServerConfig[e].tools[o]={enable:t,...n&&{description:n}},this.saveConfig(c)}saveConfig(e){try{this.validateConfig(e);let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),t=E(o,"xiaozhi.config.json"),n=JSON.stringify(e,null,2);Te(t,n,"utf8"),this.config=e}catch(o){throw new Error(`\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}reloadConfig(){this.config=null}getConfigPath(){return this.getConfigFilePath()}getDefaultConfigPath(){return this.defaultConfigPath}getConnectionConfig(){let o=this.getConfig().connection||{};return{heartbeatInterval:o.heartbeatInterval??X.heartbeatInterval,heartbeatTimeout:o.heartbeatTimeout??X.heartbeatTimeout,reconnectInterval:o.reconnectInterval??X.reconnectInterval}}getHeartbeatInterval(){return this.getConnectionConfig().heartbeatInterval}getHeartbeatTimeout(){return this.getConnectionConfig().heartbeatTimeout}getReconnectInterval(){return this.getConnectionConfig().reconnectInterval}updateConnectionConfig(e){let o=this.getConfig(),n={...o.connection||{},...e},s={...o,connection:n};this.saveConfig(s)}setHeartbeatInterval(e){if(e<=0)throw new Error("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatInterval:e})}setHeartbeatTimeout(e){if(e<=0)throw new Error("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatTimeout:e})}setReconnectInterval(e){if(e<=0)throw new Error("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({reconnectInterval:e})}getModelScopeConfig(){return this.getConfig().modelscope||{}}getModelScopeApiKey(){return this.getModelScopeConfig().apiKey||process.env.MODELSCOPE_API_TOKEN}updateModelScopeConfig(e){let o=this.getConfig(),n={...o.modelscope||{},...e},s={...o,modelscope:n};this.saveConfig(s)}setModelScopeApiKey(e){if(!e||typeof e!="string")throw new Error("API Key \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");this.updateModelScopeConfig({apiKey:e})}getWebUIConfig(){return this.getConfig().webUI||{}}getWebUIPort(){return this.getWebUIConfig().port??9999}updateWebUIConfig(e){let o=this.getConfig(),n={...o.webUI||{},...e},s={...o,webUI:n};this.saveConfig(s)}setWebUIPort(e){if(!Number.isInteger(e)||e<=0||e>65535)throw new Error("\u7AEF\u53E3\u53F7\u5FC5\u987B\u662F 1-65535 \u4E4B\u95F4\u7684\u6574\u6570");this.updateWebUIConfig({port:e})}},l=B.getInstance()});import W from"fs";import ze from"path";import O from"chalk";import{createConsola as _e}from"consola";function He(r){let e=r.getFullYear(),o=String(r.getMonth()+1).padStart(2,"0"),t=String(r.getDate()).padStart(2,"0"),n=String(r.getHours()).padStart(2,"0"),s=String(r.getMinutes()).padStart(2,"0"),c=String(r.getSeconds()).padStart(2,"0");return`${e}-${o}-${t} ${n}:${s}:${c}`}var k,I,A=D(()=>{"use strict";g(He,"formatDateTime");k=class{static{g(this,"Logger")}logFilePath=null;writeStream=null;consolaInstance;isDaemonMode;constructor(){this.isDaemonMode=process.env.XIAOZHI_DAEMON==="true",this.consolaInstance=_e({formatOptions:{date:!1,colors:!0,compact:!0},fancy:!1});let e=this.isDaemonMode;this.consolaInstance.setReporters([{log:g(o=>{let t={info:"INFO",success:"SUCCESS",warn:"WARN",error:"ERROR",debug:"DEBUG",log:"LOG"},n={info:O.blue,success:O.green,warn:O.yellow,error:O.red,debug:O.gray,log:g(y=>y,"log")},s=t[o.type]||o.type.toUpperCase(),c=n[o.type]||(y=>y),a=He(new Date),m=c(`[${s}]`),u=`[${a}] ${m} ${o.args.join(" ")}`;if(!e)try{console.error(u)}catch(y){if(y instanceof Error&&y.message?.includes("EPIPE"))return;throw y}},"log")}])}initLogFile(e){this.logFilePath=ze.join(e,"xiaozhi.log"),W.existsSync(this.logFilePath)||W.writeFileSync(this.logFilePath,""),this.writeStream=W.createWriteStream(this.logFilePath,{flags:"a",encoding:"utf8"})}logToFile(e,o,...t){if(this.writeStream){let s=`[${new Date().toISOString()}] [${e.toUpperCase()}] ${o}`,c=t.length>0?`${s} ${t.map(a=>typeof a=="object"?JSON.stringify(a):String(a)).join(" ")}`:s;this.writeStream.write(`${c}
|
|
3
|
+
`)}}enableFileLogging(e){e&&!this.writeStream&&this.logFilePath?this.writeStream=W.createWriteStream(this.logFilePath,{flags:"a",encoding:"utf8"}):!e&&this.writeStream&&(this.writeStream.end(),this.writeStream=null)}info(e,...o){this.consolaInstance.info(e,...o),this.logToFile("info",e,...o)}success(e,...o){this.consolaInstance.success(e,...o),this.logToFile("success",e,...o)}warn(e,...o){this.consolaInstance.warn(e,...o),this.logToFile("warn",e,...o)}error(e,...o){this.consolaInstance.error(e,...o),this.logToFile("error",e,...o)}debug(e,...o){this.consolaInstance.debug(e,...o),this.logToFile("debug",e,...o)}log(e,...o){this.consolaInstance.log(e,...o),this.logToFile("log",e,...o)}withTag(e){return this}close(){this.writeStream&&(this.writeStream.end(),this.writeStream=null)}},I=new k});import{spawn as Je}from"child_process";import x from"process";import z from"ws";var me,d,G,he=D(()=>{"use strict";$();A();me=g(()=>x.env.NODE_ENV==="test"||x.env.VITEST==="true","isTestEnvironment"),d=I.withTag("MULTI_MCP_PIPE");x.env.XIAOZHI_DAEMON==="true"&&x.env.XIAOZHI_CONFIG_DIR&&(I.initLogFile(x.env.XIAOZHI_CONFIG_DIR),I.enableFileLogging(!0));G=class{static{g(this,"MultiEndpointMCPPipe")}mcpScript;endpoints;shouldReconnect;shutdownResolve;connectionConfig;constructor(e,o){this.mcpScript=e,this.endpoints=new Map,this.shouldReconnect=!0,d.info(o.length===1?`\u521D\u59CB\u5316\u5355\u7AEF\u70B9\u8FDE\u63A5: ${o[0]}`:`\u521D\u59CB\u5316\u591A\u7AEF\u70B9\u8FDE\u63A5\uFF08${o.length} \u4E2A\u7AEF\u70B9\uFF09`);for(let t of o)this.endpoints.set(t,{url:t,websocket:null,isConnected:!1,reconnectAttempt:0,maxReconnectAttempts:5,process:null,stdoutBuffer:""});try{this.connectionConfig=l.getConnectionConfig(),d.info(`\u8FDE\u63A5\u914D\u7F6E: \u5FC3\u8DF3\u95F4\u9694=${this.connectionConfig.heartbeatInterval}ms, \u5FC3\u8DF3\u8D85\u65F6=${this.connectionConfig.heartbeatTimeout}ms, \u91CD\u8FDE\u95F4\u9694=${this.connectionConfig.reconnectInterval}ms`)}catch(t){this.connectionConfig={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},d.warn(`\u65E0\u6CD5\u83B7\u53D6\u8FDE\u63A5\u914D\u7F6E\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u503C: ${t instanceof Error?t.message:String(t)}`)}}async start(){return await this.connectToAllEndpoints(),this.reportStatusToWebUI(),new Promise(e=>{this.shutdownResolve=e})}async connectToAllEndpoints(){let e=[];for(let[o,t]of this.endpoints)e.push(this.connectToEndpoint(o));await Promise.allSettled(e)}async connectToEndpoint(e){let o=this.endpoints.get(e);if(!o||o.isConnected)return;this.startMCPProcessForEndpoint(e),d.info(`\u6B63\u5728\u8FDE\u63A5\u5230 WebSocket \u670D\u52A1\u5668: ${e}`);let t=new z(e);o.websocket=t,t.on("open",()=>{d.info(`\u6210\u529F\u8FDE\u63A5\u5230 WebSocket \u670D\u52A1\u5668: ${e}`),o.isConnected=!0,o.reconnectAttempt=0,o.reconnectTimer&&(clearTimeout(o.reconnectTimer),o.reconnectTimer=void 0),this.reportStatusToWebUI(),this.startHeartbeat(e)}),t.on("message",n=>{let s=n.toString();d.info(`<< [${e}] WebSocket\u6536\u5230\u6D88\u606F: ${s}`);try{let c=JSON.parse(s);(c.method==="notifications/initialized"||c.method==="tools/list"&&c.id||c?.result?.tools)&&setTimeout(()=>{this.reportStatusToWebUI()},1e3)}catch{}o.process?.stdin&&!o.process.stdin.destroyed&&o.process.stdin.write(`${s}
|
|
4
4
|
`)}),t.on("close",(n,s)=>{d.error(`[${e}] WebSocket \u8FDE\u63A5\u5DF2\u5173\u95ED: ${n} ${s}`),o.isConnected=!1,o.websocket=null,this.stopHeartbeat(e),this.reportStatusToWebUI(),this.shouldReconnect&&(n===4004?o.reconnectAttempt<o.maxReconnectAttempts?(d.warn(`[${e}] \u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF(4004)\uFF0C\u5C06\u8FDB\u884C\u7B2C ${o.reconnectAttempt+1} \u6B21\u91CD\u8FDE\u5C1D\u8BD5\uFF08\u6700\u591A ${o.maxReconnectAttempts} \u6B21\uFF09`),this.scheduleReconnect(e)):d.error(`[${e}] \u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF(4004)\uFF0C\u5DF2\u8FBE\u5230\u6700\u5927\u91CD\u8FDE\u6B21\u6570(${o.maxReconnectAttempts})\uFF0C\u505C\u6B62\u91CD\u8FDE`):this.scheduleReconnect(e))}),t.on("error",n=>{d.error(`[${e}] WebSocket \u9519\u8BEF: ${n.message}`),o.isConnected=!1,this.stopHeartbeat(e)}),t.on("pong",()=>{o.heartbeatTimeoutTimer&&(clearTimeout(o.heartbeatTimeoutTimer),o.heartbeatTimeoutTimer=void 0)})}scheduleReconnect(e){let o=this.endpoints.get(e);if(!o||!this.shouldReconnect)return;o.reconnectTimer&&clearTimeout(o.reconnectTimer),o.reconnectAttempt++;let t=this.connectionConfig.reconnectInterval,s=Math.min(t*2**(o.reconnectAttempt-1),6e4);d.info(`[${e}] \u8BA1\u5212\u5728 ${(s/1e3).toFixed(2)} \u79D2\u540E\u8FDB\u884C\u7B2C ${o.reconnectAttempt} \u6B21\u91CD\u8FDE\u5C1D\u8BD5...`),o.reconnectTimer=setTimeout(async()=>{this.shouldReconnect&&(await this.cleanupEndpointResources(e),(!o.process||o.process.killed)&&d.info(`[${e}] MCP \u8FDB\u7A0B\u672A\u8FD0\u884C\uFF0C\u5C06\u5728\u91CD\u8FDE\u65F6\u542F\u52A8...`),this.connectToEndpoint(e))},s)}startMCPProcessForEndpoint(e){let o=this.endpoints.get(e);if(!o){d.error(`\u7AEF\u70B9\u4E0D\u5B58\u5728: ${e}`);return}if(o.process){d.info(`[${e}] MCP \u8FDB\u7A0B\u5DF2\u5728\u8FD0\u884C`);return}d.info(`[${e}] \u6B63\u5728\u542F\u52A8 MCP \u8FDB\u7A0B`),o.process=Je("node",[this.mcpScript],{stdio:["pipe","pipe","pipe"]}),o.process.stdout?.on("data",t=>{o.stdoutBuffer+=t.toString();let n=o.stdoutBuffer.split(`
|
|
5
5
|
`);o.stdoutBuffer=n.pop()||"";for(let s of n)s.trim()&&this.handleMCPMessage(e,s)}),o.process.stderr?.on("data",t=>{if(x.env.XIAOZHI_DAEMON!=="true")try{x.stderr.write(t)}catch{}}),o.process.on("exit",(t,n)=>{d.warn(`[${e}] MCP \u8FDB\u7A0B\u5DF2\u9000\u51FA\uFF0C\u9000\u51FA\u7801: ${t}, \u4FE1\u53F7: ${n}`),o.process=null,this.shouldReconnect&&n!=="SIGTERM"&&n!=="SIGKILL"&&d.info(`[${e}] MCP \u8FDB\u7A0B\u610F\u5916\u9000\u51FA\uFF0C\u5C06\u5728\u4E0B\u6B21\u91CD\u8FDE\u65F6\u5C1D\u8BD5\u91CD\u542F`)}),o.process.on("error",t=>{d.error(`[${e}] \u8FDB\u7A0B\u9519\u8BEF: ${t.message}`),o.process=null,this.shouldReconnect&&d.info(`[${e}] MCP \u8FDB\u7A0B\u53D1\u751F\u9519\u8BEF\uFF0C\u5C06\u5728\u4E0B\u6B21\u91CD\u8FDE\u65F6\u5C1D\u8BD5\u91CD\u542F`)})}handleMCPMessage(e,o){d.info(`>> [${e}] mcpServerProxy\u53D1\u9001\u6D88\u606F\u957F\u5EA6: ${o.length} \u5B57\u8282`),d.info(`>> [${e}] mcpServerProxy\u53D1\u9001\u6D88\u606F: ${o.substring(0,500)}...`),this.sendToEndpoint(e,o)}sendToEndpoint(e,o){let t=this.endpoints.get(e);if(!t||!t.websocket||t.websocket.readyState!==z.OPEN){d.warn(`[${e}] \u7AEF\u70B9\u4E0D\u53EF\u7528\uFF0C\u6D88\u606F\u65E0\u6CD5\u53D1\u9001`);return}try{t.websocket.send(`${o}
|
|
6
|
-
`),d.info(`>> [${e}] \u6210\u529F\u53D1\u9001\u6D88\u606F\u5230 WebSocket`)}catch(n){d.error(`>> [${e}] \u53D1\u9001\u6D88\u606F\u5230 WebSocket \u5931\u8D25: ${n}`)}}startHeartbeat(e){let o=this.endpoints.get(e);o&&(this.stopHeartbeat(e),o.heartbeatTimer=setInterval(()=>{o.websocket&&o.websocket.readyState===z.OPEN&&(o.websocket.ping(),o.heartbeatTimeoutTimer=setTimeout(()=>{d.warn(`[${e}] \u5FC3\u8DF3\u8D85\u65F6\uFF0C\u65AD\u5F00\u8FDE\u63A5`),o.websocket?.close()},this.connectionConfig.heartbeatTimeout),this.reportStatusToWebUI())},this.connectionConfig.heartbeatInterval))}stopHeartbeat(e){let o=this.endpoints.get(e);o&&(o.heartbeatTimer&&(clearInterval(o.heartbeatTimer),o.heartbeatTimer=void 0),o.heartbeatTimeoutTimer&&(clearTimeout(o.heartbeatTimeoutTimer),o.heartbeatTimeoutTimer=void 0))}async cleanupEndpointResources(e){let o=this.endpoints.get(e);if(o){if(d.debug(`[${e}] \u6E05\u7406\u7AEF\u70B9\u8D44\u6E90...`),this.stopHeartbeat(e),o.reconnectTimer&&(clearTimeout(o.reconnectTimer),o.reconnectTimer=void 0),o.websocket){try{o.websocket.readyState===z.OPEN&&o.websocket.close()}catch(t){d.debug(`[${e}] \u5173\u95ED WebSocket \u65F6\u51FA\u9519: ${t}`)}o.websocket=null}if(o.process&&!o.process.killed){try{d.debug(`[${e}] \u7EC8\u6B62 MCP \u8FDB\u7A0B...`),o.process.kill("SIGTERM"),await new Promise(t=>{let n=setTimeout(()=>{o.process&&!o.process.killed&&(d.warn(`[${e}] MCP \u8FDB\u7A0B\u672A\u80FD\u6B63\u5E38\u9000\u51FA\uFF0C\u5F3A\u5236\u7EC8\u6B62`),o.process.kill("SIGKILL")),t()},2e3);o.process?.on("exit",()=>{clearTimeout(n),t()})})}catch(t){d.warn(`[${e}] \u7EC8\u6B62 MCP \u8FDB\u7A0B\u65F6\u51FA\u9519: ${t}`)}o.process=null}o.stdoutBuffer="",o.isConnected=!1,d.debug(`[${e}] \u7AEF\u70B9\u8D44\u6E90\u6E05\u7406\u5B8C\u6210`)}}cleanup(){for(let e of this.endpoints.keys())this.stopHeartbeat(e);for(let[e,o]of this.endpoints){if(o.reconnectTimer&&(clearTimeout(o.reconnectTimer),o.reconnectTimer=void 0),o.stdoutBuffer="",o.process){d.info(`[${e}] \u6B63\u5728\u7EC8\u6B62 MCP \u8FDB\u7A0B`);try{o.process.kill("SIGTERM"),setTimeout(()=>{o.process&&!o.process.killed&&o.process.kill("SIGKILL")},5e3)}catch(t){d.error(`[${e}] \u7EC8\u6B62\u8FDB\u7A0B\u65F6\u51FA\u9519: ${t instanceof Error?t.message:String(t)}`)}o.process=null}if(o.websocket){try{o.websocket.close()}catch(t){d.warn(`[${e}] \u5173\u95ED WebSocket \u65F6\u51FA\u9519: ${t}`)}o.websocket=null}}}shutdown(){d.info("\u6B63\u5728\u5173\u95ED Multi-Endpoint MCP Pipe..."),this.shouldReconnect=!1;for(let e of this.endpoints.values())e.isConnected=!1;this.reportStatusToWebUI(),this.cleanup(),this.shutdownResolve&&this.shutdownResolve(),me()||setTimeout(()=>{x.exit(0)},100)}async reportStatusToWebUI(){if(!me())try{let e=l.getWebUIPort(),o=new z(`ws://localhost:${e}`);o.on("open",()=>{let t=[];for(let[s,c]of this.endpoints)t.push({url:s,connected:c.isConnected});let n={type:"clientStatus",data:{status:this.hasAnyConnection()?"connected":"disconnected",mcpEndpoints:t,activeMCPServers:[],lastHeartbeat:Date.now()}};o.send(JSON.stringify(n)),d.debug("\u5DF2\u5411 Web UI \u62A5\u544A\u72B6\u6001"),setTimeout(()=>{o.close()},1e3)}),o.on("error",t=>{d.debug(`Web UI \u8FDE\u63A5\u5931\u8D25\uFF08\u53EF\u80FD\u672A\u8FD0\u884C\uFF09: ${t.message}`)})}catch(e){d.debug(`\u5411 Web UI \u62A5\u544A\u72B6\u6001\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}hasAnyConnection(){for(let e of this.endpoints.values())if(e.isConnected)return!0;return!1}}});var ye={};xe(ye,{MCPServer:()=>Y});import{spawn as Ue}from"child_process";import{randomUUID as Xe}from"crypto";import{EventEmitter as Be}from"events";import L from"fs";import Ze from"os";import w from"path";import{fileURLToPath as ue}from"url";import K from"express";var Ve,_,h,H,Y,Ce=D(()=>{"use strict"
|
|
6
|
+
`),d.info(`>> [${e}] \u6210\u529F\u53D1\u9001\u6D88\u606F\u5230 WebSocket`)}catch(n){d.error(`>> [${e}] \u53D1\u9001\u6D88\u606F\u5230 WebSocket \u5931\u8D25: ${n}`)}}startHeartbeat(e){let o=this.endpoints.get(e);o&&(this.stopHeartbeat(e),o.heartbeatTimer=setInterval(()=>{o.websocket&&o.websocket.readyState===z.OPEN&&(o.websocket.ping(),o.heartbeatTimeoutTimer=setTimeout(()=>{d.warn(`[${e}] \u5FC3\u8DF3\u8D85\u65F6\uFF0C\u65AD\u5F00\u8FDE\u63A5`),o.websocket?.close()},this.connectionConfig.heartbeatTimeout),this.reportStatusToWebUI())},this.connectionConfig.heartbeatInterval))}stopHeartbeat(e){let o=this.endpoints.get(e);o&&(o.heartbeatTimer&&(clearInterval(o.heartbeatTimer),o.heartbeatTimer=void 0),o.heartbeatTimeoutTimer&&(clearTimeout(o.heartbeatTimeoutTimer),o.heartbeatTimeoutTimer=void 0))}async cleanupEndpointResources(e){let o=this.endpoints.get(e);if(o){if(d.debug(`[${e}] \u6E05\u7406\u7AEF\u70B9\u8D44\u6E90...`),this.stopHeartbeat(e),o.reconnectTimer&&(clearTimeout(o.reconnectTimer),o.reconnectTimer=void 0),o.websocket){try{o.websocket.readyState===z.OPEN&&o.websocket.close()}catch(t){d.debug(`[${e}] \u5173\u95ED WebSocket \u65F6\u51FA\u9519: ${t}`)}o.websocket=null}if(o.process&&!o.process.killed){try{d.debug(`[${e}] \u7EC8\u6B62 MCP \u8FDB\u7A0B...`),o.process.kill("SIGTERM"),await new Promise(t=>{let n=setTimeout(()=>{o.process&&!o.process.killed&&(d.warn(`[${e}] MCP \u8FDB\u7A0B\u672A\u80FD\u6B63\u5E38\u9000\u51FA\uFF0C\u5F3A\u5236\u7EC8\u6B62`),o.process.kill("SIGKILL")),t()},2e3);o.process?.on("exit",()=>{clearTimeout(n),t()})})}catch(t){d.warn(`[${e}] \u7EC8\u6B62 MCP \u8FDB\u7A0B\u65F6\u51FA\u9519: ${t}`)}o.process=null}o.stdoutBuffer="",o.isConnected=!1,d.debug(`[${e}] \u7AEF\u70B9\u8D44\u6E90\u6E05\u7406\u5B8C\u6210`)}}cleanup(){for(let e of this.endpoints.keys())this.stopHeartbeat(e);for(let[e,o]of this.endpoints){if(o.reconnectTimer&&(clearTimeout(o.reconnectTimer),o.reconnectTimer=void 0),o.stdoutBuffer="",o.process){d.info(`[${e}] \u6B63\u5728\u7EC8\u6B62 MCP \u8FDB\u7A0B`);try{o.process.kill("SIGTERM"),setTimeout(()=>{o.process&&!o.process.killed&&o.process.kill("SIGKILL")},5e3)}catch(t){d.error(`[${e}] \u7EC8\u6B62\u8FDB\u7A0B\u65F6\u51FA\u9519: ${t instanceof Error?t.message:String(t)}`)}o.process=null}if(o.websocket){try{o.websocket.close()}catch(t){d.warn(`[${e}] \u5173\u95ED WebSocket \u65F6\u51FA\u9519: ${t}`)}o.websocket=null}}}shutdown(){d.info("\u6B63\u5728\u5173\u95ED Multi-Endpoint MCP Pipe..."),this.shouldReconnect=!1;for(let e of this.endpoints.values())e.isConnected=!1;this.reportStatusToWebUI(),this.cleanup(),this.shutdownResolve&&this.shutdownResolve(),me()||setTimeout(()=>{x.exit(0)},100)}async reportStatusToWebUI(){if(!me())try{let e=l.getWebUIPort(),o=new z(`ws://localhost:${e}`);o.on("open",()=>{let t=[];for(let[s,c]of this.endpoints)t.push({url:s,connected:c.isConnected});let n={type:"clientStatus",data:{status:this.hasAnyConnection()?"connected":"disconnected",mcpEndpoints:t,activeMCPServers:[],lastHeartbeat:Date.now()}};o.send(JSON.stringify(n)),d.debug("\u5DF2\u5411 Web UI \u62A5\u544A\u72B6\u6001"),setTimeout(()=>{o.close()},1e3)}),o.on("error",t=>{d.debug(`Web UI \u8FDE\u63A5\u5931\u8D25\uFF08\u53EF\u80FD\u672A\u8FD0\u884C\uFF09: ${t.message}`)})}catch(e){d.debug(`\u5411 Web UI \u62A5\u544A\u72B6\u6001\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}hasAnyConnection(){for(let e of this.endpoints.values())if(e.isConnected)return!0;return!1}}});var ye={};xe(ye,{MCPServer:()=>Y});import{spawn as Ue}from"child_process";import{randomUUID as Xe}from"crypto";import{EventEmitter as Be}from"events";import L from"fs";import Ze from"os";import w from"path";import{fileURLToPath as ue}from"url";import K from"express";var Ve,_,h,H,Ke,Y,Ce=D(()=>{"use strict";$();A();he();Ve=ue(import.meta.url),_=w.dirname(Ve),h=I.withTag("mcp-server"),H="mcpServerProxy.js",Ke=5,Y=class extends Be{static{g(this,"MCPServer")}app;server=null;clients=new Map;mcpProxy=null;mcpClient=null;mcpProxyPath=null;port;constructor(e=3e3){super(),this.port=e,this.app=K(),this.setupMiddleware(),this.setupRoutes()}setupMiddleware(){this.app.use(K.json()),this.app.use(K.urlencoded({extended:!0})),this.app.use((e,o,t)=>{o.header("Access-Control-Allow-Origin","*"),o.header("Access-Control-Allow-Methods","GET, POST, OPTIONS"),o.header("Access-Control-Allow-Headers","Content-Type, Accept"),o.header("Cache-Control","no-cache"),t()})}setupRoutes(){this.app.get("/sse",(e,o)=>{let t=Date.now().toString(),n=Xe();o.setHeader("Content-Type","text/event-stream"),o.setHeader("Cache-Control","no-cache, no-transform"),o.setHeader("Connection","keep-alive"),o.setHeader("X-Accel-Buffering","no"),this.clients.set(n,{id:t,sessionId:n,response:o}),h.info(`MCP\u5BA2\u6237\u7AEF\u5DF2\u8FDE\u63A5: ${t} (\u4F1A\u8BDD: ${n})`),o.write(`event: endpoint
|
|
7
7
|
data: /messages?sessionId=${n}
|
|
8
8
|
|
|
9
9
|
`),e.on("close",()=>{this.clients.delete(n),h.info(`MCP\u5BA2\u6237\u7AEF\u5DF2\u65AD\u5F00\u8FDE\u63A5: ${t} (\u4F1A\u8BDD: ${n})`)})}),this.app.post("/messages",async(e,o)=>{try{let t=e.query.sessionId,n=e.body;if(h.info(`\u901A\u8FC7SSE\u4F20\u8F93\u6536\u5230\u6D88\u606F (\u4F1A\u8BDD: ${t}):`,JSON.stringify(n)),!t||!this.clients.has(t)){o.status(400).json({jsonrpc:"2.0",error:{code:-32600,message:"\u65E0\u6548\u6216\u7F3A\u5C11sessionId"},id:n.id});return}if(!this.mcpProxy){o.status(503).json({jsonrpc:"2.0",error:{code:-32603,message:"MCP\u4EE3\u7406\u672A\u8FD0\u884C"},id:n.id});return}if(n.id===void 0)h.info(`\u8F6C\u53D1\u901A\u77E5: ${n.method}`),this.mcpProxy.stdin.write(`${JSON.stringify(n)}
|
|
@@ -12,7 +12,7 @@ data: /messages?sessionId=${n}
|
|
|
12
12
|
`);this.responseBuffer=o.pop()||"";for(let t of o)if(t.trim())try{let n=JSON.parse(t);if(h.debug(`\u6536\u5230\u4EE3\u7406\u54CD\u5E94: ${t.substring(0,200)}...`),n.id!==void 0&&this.pendingRequests.has(n.id)){let s=this.pendingRequests.get(n.id);clearTimeout(s.timeoutId),this.pendingRequests.delete(n.id),s.resolve(n)}}catch{h.debug(`\u6765\u81EA\u4EE3\u7406\u7684\u975EJSON\u884C: ${t}`)}}catch(o){h.error("\u5904\u7406\u4EE3\u7406\u54CD\u5E94\u65F6\u51FA\u9519:",o)}}sendToClient(e,o){try{let t=`event: message
|
|
13
13
|
data: ${JSON.stringify(o)}
|
|
14
14
|
|
|
15
|
-
`;e.response.write(t)}catch(t){h.error(`\u53D1\u9001\u5230\u5BA2\u6237\u7AEF ${e.id} \u5931\u8D25:`,t),this.clients.delete(e.sessionId)}}broadcastToClients(e){for(let o of this.clients.values())this.sendToClient(o,e)}async start(){try{let e=await Promise.allSettled([this.startMCPProxy(),new Promise(n=>{this.server=this.app.listen(this.port,()=>{h.info(`MCP\u670D\u52A1\u5668\u76D1\u542C\u7AEF\u53E3 ${this.port}`),h.info(`SSE\u7AEF\u70B9: http://localhost:${this.port}/sse`),h.info(`\u6D88\u606F\u7AEF\u70B9: http://localhost:${this.port}/messages`),h.info(`RPC\u7AEF\u70B9: http://localhost:${this.port}/rpc`),n()})})]),[o,t]=e;if(o.status==="rejected"&&h.error("MCP\u4EE3\u7406\u542F\u52A8\u5931\u8D25:",o.reason),t.status==="rejected")throw h.error("HTTP\u670D\u52A1\u5668\u542F\u52A8\u5931\u8D25:",t.reason),t.reason;this.startMCPClient().catch(n=>{h.error("\u542F\u52A8\u8FDE\u63A5\u5230xiaozhi.me\u7684MCP\u5BA2\u6237\u7AEF\u5931\u8D25:",n)}),this.emit("started")}catch(e){throw h.error("\u542F\u52A8MCP\u670D\u52A1\u5668\u5931\u8D25:",e),e}}findMCPProxyPath(){if(this.mcpProxyPath)return this.mcpProxyPath;if(process.env.MCP_SERVER_PROXY_PATH){let n=w.normalize(process.env.MCP_SERVER_PROXY_PATH),s=w.resolve(n),c=[_,w.join(_,".."),w.join(_,"..",".."),w.join(_,"..","..","dist"),Ze.tmpdir()];if(L.existsSync(s)&&w.basename(s)===H&&c.some(a=>s.startsWith(a)))return this.mcpProxyPath=s,this.mcpProxyPath;throw h.warn(`MCP_SERVER_PROXY_PATH \u8DEF\u5F84\u4E0D\u5B89\u5168: ${n}`),new Error(`\u6307\u5B9A\u7684 MCP \u4EE3\u7406\u8DEF\u5F84\u4E0D\u5B58\u5728\u6216\u4E0D\u5B89\u5168: ${process.env.MCP_SERVER_PROXY_PATH}`)}let e=ue(import.meta.url),o=w.dirname(e),t=null;for(let n=0;n<5;n++){let s=w.join(o,H);if(L.existsSync(s)){t=s;break}let c=w.join(o,"dist",H);if(L.existsSync(c)){t=c;break}o=w.dirname(o)}if(!t){let n=w.resolve(_,"..",".."),s=w.join(n,"dist",H);L.existsSync(s)&&(t=s)}if(!t)throw new Error(`\u5728\u9879\u76EE\u7ED3\u6784\u4E2D\u627E\u4E0D\u5230 ${H}`);return this.mcpProxyPath=t,this.mcpProxyPath}async startMCPProxy(){let e=this.findMCPProxyPath();h.info(`\u6B63\u5728\u542F\u52A8MCP\u4EE3\u7406: ${e}`),this.mcpProxy=Ue("node",[e],{stdio:["pipe","pipe","pipe"],env:{...process.env,MCP_SERVER_MODE:"true",XIAOZHI_CONFIG_DIR:process.env.XIAOZHI_CONFIG_DIR||process.cwd()}}),this.mcpProxy.on("error",o=>{h.error("MCP\u4EE3\u7406\u9519\u8BEF:",o)}),this.mcpProxy.on("exit",(o,t)=>{h.warn(`MCP\u4EE3\u7406\u9000\u51FA\uFF0C\u4EE3\u7801 ${o}\uFF0C\u4FE1\u53F7 ${t}`),this.mcpProxy=null}),this.mcpProxy.stderr&&this.mcpProxy.stderr.on("data",o=>{let t=o.toString().trim();t.includes("[ERROR]")||t.includes("Error:")||t.includes("Failed")?h.error("MCP\u4EE3\u7406stderr:",t):h.info("MCP\u4EE3\u7406\u8F93\u51FA:",t)}),this.mcpProxy.stdout&&this.mcpProxy.stdout.on("data",o=>{this.handleProxyResponse(o)}),await new Promise((o,t)=>{let n=setTimeout(()=>{t(new Error("MCP\u4EE3\u7406\u542F\u52A8\u8D85\u65F6"))},1e4),s=g(c=>{let a=c.toString();(a.includes("MCP proxy ready")||a.includes("started"))&&(clearTimeout(n),this.mcpProxy?.stdout?.removeListener("data",s),o())},"dataHandler");this.mcpProxy?.stdout?.on("data",s)}),h.info("MCP\u4EE3\u7406\u542F\u52A8\u6210\u529F")}async startMCPClient(){let e=[];try{l.configExists()&&(e=l.getMcpEndpoints())}catch(o){h.warn("\u4ECE\u914D\u7F6E\u4E2D\u8BFB\u53D6MCP\u7AEF\u70B9\u5931\u8D25:",o)}if(e.length>0){let o=this.findMCPProxyPath();this.mcpClient=new G(o,e),await this.mcpClient.start(),h.info("MCP\u5BA2\u6237\u7AEF\u5DF2\u542F\u52A8\uFF0C\u6B63\u5728\u8FDE\u63A5\u5230 xiaozhi.me")}else h.info("\u672A\u914D\u7F6EMCP\u7AEF\u70B9\uFF0C\u8DF3\u8FC7\u5BA2\u6237\u7AEF\u8FDE\u63A5")}async stop(){h.info("\u6B63\u5728\u505C\u6B62MCP\u670D\u52A1\u5668...");for(let e of this.clients.values())try{e.response.end()}catch{}this.clients.clear(),this.server&&(await new Promise(e=>{this.server.close(()=>e())}),this.server=null),this.mcpProxy&&(this.mcpProxy.kill("SIGTERM"),await new Promise(e=>{this.mcpProxy.on("exit",()=>e()),setTimeout(()=>{this.mcpProxy?.kill("SIGKILL"),e()},5e3)}),this.mcpProxy=null),this.mcpClient&&(this.mcpClient.shutdown(),this.mcpClient=null),this.mcpProxyPath=null,this.emit("stopped"),h.info("MCP\u670D\u52A1\u5668\u5DF2\u505C\u6B62")}}});import{spawn as q}from"child_process";import C from"fs";import f from"path";import{fileURLToPath as j}from"url";import i from"chalk";import{Command as Ke}from"commander";import P from"ora";E();import ke from"omelette";function Ae(){try{if(!l.configExists())return[];let r=l.getMcpServers();return Object.keys(r)}catch{return[]}}g(Ae,"getMcpServerNames");function Ne(r){try{if(!l.configExists())return[];let e=l.getServerToolsConfig(r);return Object.keys(e)}catch{return[]}}g(Ne,"getServerToolNames");function re(){let r=ke("xiaozhi <command>");if(r.on("command",({reply:e})=>{e(["create","init","config","start","stop","status","attach","restart","mcp","completion"])}),r.on("complete",(e,{line:o,before:t,reply:n})=>{process.env.XIAOZHI_DEBUG_COMPLETION&&console.error(`Debug completion - line: "${o}", before: "${t}", fragment: "${e}"`);let s=o.trim().split(/\s+/),a=o!==o.trim()?s.length:s.length-1;if(s[1]==="mcp"){let m=s[2];if(a===2){let u=["list","server","tool"],y=s[2]||"",b=u.filter(S=>S.startsWith(y));n(b);return}if(a===3){switch(m){case"list":{let u=["--tools"],y=s[3]||"",b=u.filter(S=>S.startsWith(y));n(b);break}case"server":case"tool":{let u=Ae(),y=s[3]||"",b=u.filter(S=>S.startsWith(y));n(b);break}default:n([])}return}if(a===4&&m==="tool"){let u=s[3],y=Ne(u),b=s[4]||"",S=y.filter(R=>R.startsWith(b));n(S);return}if(a===5&&m==="tool"){let u=["enable","disable"],y=s[5]||"",b=u.filter(S=>S.startsWith(y));n(b);return}}if(a===2){switch(s[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(e){console.error("\u751F\u6210\u81EA\u52A8\u8865\u5168\u811A\u672C\u65F6\u51FA\u9519:",e)}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()}g(re,"setupAutoCompletion");function se(){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(se,"showCompletionHelp");E();A();E();import p from"chalk";import ie from"cli-table3";import Z from"ora";function ce(r){let e=0;for(let o of r)/[\u4e00-\u9fff\u3400-\u4dbf\uff00-\uffef]/.test(o)?e+=2:e+=1;return e}g(ce,"getDisplayWidth");function ae(r,e){if(ce(r)<=e)return r;if(e<=3)return"";let o="",t=0,n=!1;for(let s of r){let c=/[\u4e00-\u9fff\u3400-\u4dbf\uff00-\uffef]/.test(s)?2:1;if(t+c>e-3){if(!n)return"";o+="...";break}o+=s,t+=c,n=!0}return o}g(ae,"truncateToWidth");async function le(r={}){let e=Z("\u83B7\u53D6 MCP \u670D\u52A1\u5217\u8868...").start();try{let o=l.getMcpServers(),t=Object.keys(o);if(t.length===0){e.warn("\u672A\u914D\u7F6E\u4EFB\u4F55 MCP \u670D\u52A1"),console.log(p.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi config' \u547D\u4EE4\u914D\u7F6E MCP \u670D\u52A1"));return}if(e.succeed(`\u627E\u5230 ${t.length} \u4E2A MCP \u670D\u52A1`),r.tools){console.log(),console.log(p.bold("MCP \u670D\u52A1\u5DE5\u5177\u5217\u8868:")),console.log();let n=8,s=[];for(let a of t){let m=l.getServerToolsConfig(a),u=Object.keys(m);s.push(...u)}for(let a of s){let m=ce(a);m>n&&(n=m)}n=Math.max(10,Math.min(n+2,30));let c=new ie({head:[p.bold("MCP"),p.bold("\u5DE5\u5177\u540D\u79F0"),p.bold("\u72B6\u6001"),p.bold("\u63CF\u8FF0")],colWidths:[15,n,8,40],wordWrap:!0,style:{head:[],border:[]}});for(let a of t){let m=l.getServerToolsConfig(a),u=Object.keys(m);if(u.length===0)c.push([p.gray(a),p.gray("-"),p.gray("-"),p.gray("\u6682\u672A\u8BC6\u522B\u5230\u76F8\u5173\u5DE5\u5177")]);else{c.length>0&&c.push([{colSpan:4,content:""}]);for(let y of u){let b=m[y],S=b.enable?p.green("\u542F\u7528"):p.red("\u7981\u7528"),R=ae(b.description||"",32);c.push([a,y,S,R])}}}console.log(c.toString())}else{console.log(),console.log(p.bold("MCP \u670D\u52A1\u5217\u8868:")),console.log();for(let n of t){let s=o[n],c=l.getServerToolsConfig(n),a=Object.keys(c).length,m=Object.values(c).filter(u=>u.enable!==!1).length;console.log(`${p.cyan("\u2022")} ${p.bold(n)}`),"url"in s?("type"in s&&s.type==="sse"?console.log(` \u7C7B\u578B: ${p.gray("SSE")}`):console.log(` \u7C7B\u578B: ${p.gray("Streamable HTTP")}`),console.log(` URL: ${p.gray(s.url)}`)):console.log(` \u547D\u4EE4: ${p.gray(s.command)} ${p.gray(s.args.join(" "))}`),a>0?console.log(` \u5DE5\u5177: ${p.green(m)} \u542F\u7528 / ${p.yellow(a)} \u603B\u8BA1`):console.log(` \u5DE5\u5177: ${p.gray("\u672A\u626B\u63CF (\u8BF7\u5148\u542F\u52A8\u670D\u52A1)")}`),console.log()}}console.log(p.gray("\u{1F4A1} \u63D0\u793A:")),console.log(p.gray(" - \u4F7F\u7528 'xiaozhi mcp list --tools' \u67E5\u770B\u6240\u6709\u5DE5\u5177")),console.log(p.gray(" - \u4F7F\u7528 'xiaozhi mcp <\u670D\u52A1\u540D> list' \u67E5\u770B\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177")),console.log(p.gray(" - \u4F7F\u7528 'xiaozhi mcp <\u670D\u52A1\u540D> <\u5DE5\u5177\u540D> enable/disable' \u542F\u7528/\u7981\u7528\u5DE5\u5177"))}catch(o){e.fail("\u83B7\u53D6 MCP \u670D\u52A1\u5217\u8868\u5931\u8D25"),console.error(p.red(`\u9519\u8BEF: ${o instanceof Error?o.message:String(o)}`)),process.exit(1)}}g(le,"listMcpServers");async function ge(r){let e=Z(`\u83B7\u53D6 ${r} \u670D\u52A1\u7684\u5DE5\u5177\u5217\u8868...`).start();try{if(!l.getMcpServers()[r]){e.fail(`\u670D\u52A1 '${r}' \u4E0D\u5B58\u5728`),console.log(p.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp list' \u67E5\u770B\u6240\u6709\u53EF\u7528\u670D\u52A1"));return}let t=l.getServerToolsConfig(r),n=Object.keys(t);if(n.length===0){e.warn(`\u670D\u52A1 '${r}' \u6682\u65E0\u5DE5\u5177\u4FE1\u606F`),console.log(p.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u542F\u52A8\u670D\u52A1\u4EE5\u626B\u63CF\u5DE5\u5177\u5217\u8868"));return}e.succeed(`\u670D\u52A1 '${r}' \u5171\u6709 ${n.length} \u4E2A\u5DE5\u5177`),console.log(),console.log(p.bold(`${r} \u670D\u52A1\u5DE5\u5177\u5217\u8868:`)),console.log();let s=new ie({head:[p.bold("\u5DE5\u5177\u540D\u79F0"),p.bold("\u72B6\u6001"),p.bold("\u63CF\u8FF0")],colWidths:[30,8,50],wordWrap:!0,style:{head:[],border:[]}});for(let c of n){let a=t[c],m=a.enable?p.green("\u542F\u7528"):p.red("\u7981\u7528"),u=ae(a.description||"",40);s.push([c,m,u])}console.log(s.toString()),console.log(),console.log(p.gray("\u{1F4A1} \u63D0\u793A:")),console.log(p.gray(` - \u4F7F\u7528 'xiaozhi mcp ${r} <\u5DE5\u5177\u540D> enable' \u542F\u7528\u5DE5\u5177`)),console.log(p.gray(` - \u4F7F\u7528 'xiaozhi mcp ${r} <\u5DE5\u5177\u540D> disable' \u7981\u7528\u5DE5\u5177`))}catch(o){e.fail("\u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25"),console.error(p.red(`\u9519\u8BEF: ${o instanceof Error?o.message:String(o)}`)),process.exit(1)}}g(ge,"listServerTools");async function pe(r,e,o){let t=o?"\u542F\u7528":"\u7981\u7528",n=Z(`${t}\u5DE5\u5177 ${r}/${e}...`).start();try{if(!l.getMcpServers()[r]){n.fail(`\u670D\u52A1 '${r}' \u4E0D\u5B58\u5728`),console.log(p.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp list' \u67E5\u770B\u6240\u6709\u53EF\u7528\u670D\u52A1"));return}let c=l.getServerToolsConfig(r);if(!c[e]){n.fail(`\u5DE5\u5177 '${e}' \u5728\u670D\u52A1 '${r}' \u4E2D\u4E0D\u5B58\u5728`),console.log(p.yellow(`\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp ${r} list' \u67E5\u770B\u8BE5\u670D\u52A1\u7684\u6240\u6709\u5DE5\u5177`));return}l.setToolEnabled(r,e,o,c[e].description),n.succeed(`\u6210\u529F${t}\u5DE5\u5177 ${p.cyan(r)}/${p.cyan(e)}`),console.log(),console.log(p.gray("\u{1F4A1} \u63D0\u793A: \u5DE5\u5177\u72B6\u6001\u66F4\u6539\u5C06\u5728\u4E0B\u6B21\u542F\u52A8\u670D\u52A1\u65F6\u751F\u6548"))}catch(s){n.fail(`${t}\u5DE5\u5177\u5931\u8D25`),console.error(p.red(`\u9519\u8BEF: ${s instanceof Error?s.message:String(s)}`)),process.exit(1)}}g(pe,"setToolEnabled");import{spawn as fe}from"child_process";import{existsSync as V}from"fs";import{readFile as de}from"fs/promises";import{createServer as Fe}from"http";import{dirname as De,join as $}from"path";import{parse as We}from"url";import{fileURLToPath as Ge}from"url";import{WebSocketServer as Le}from"ws";E();A();var N=class{static{g(this,"WebServer")}httpServer;wss;logger;port;clientInfo={status:"disconnected",mcpEndpoint:"",activeMCPServers:[]};heartbeatTimeout;HEARTBEAT_TIMEOUT=35e3;constructor(e){if(e===void 0)try{this.port=l.getWebUIPort()}catch{this.port=9999}else this.port=e;this.logger=new k,this.httpServer=Fe((o,t)=>{this.handleHttpRequest(o,t)}),this.wss=new Le({server:this.httpServer}),this.setupWebSocket()}async handleHttpRequest(e,o){let{pathname:t}=We(e.url||"",!0);if(o.setHeader("Access-Control-Allow-Origin","*"),o.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, OPTIONS"),o.setHeader("Access-Control-Allow-Headers","Content-Type"),e.method==="OPTIONS"){o.writeHead(200),o.end();return}try{if(e.method==="GET"&&!t?.startsWith("/api/")){await this.serveStaticFile(t||"/",o);return}if(t==="/api/config"&&e.method==="GET"){let n=l.getConfig();o.writeHead(200,{"Content-Type":"application/json"}),o.end(JSON.stringify(n))}else if(t==="/api/config"&&e.method==="PUT"){let n="";e.on("data",s=>{n+=s.toString()}),e.on("end",async()=>{try{let s=JSON.parse(n);this.updateConfig(s),this.broadcastConfigUpdate(s),o.writeHead(200,{"Content-Type":"application/json"}),o.end(JSON.stringify({success:!0})),this.logger.info("\u914D\u7F6E\u5DF2\u66F4\u65B0")}catch(s){o.writeHead(400,{"Content-Type":"application/json"}),o.end(JSON.stringify({error:s instanceof Error?s.message:String(s)}))}})}else t==="/api/status"&&e.method==="GET"?(o.writeHead(200,{"Content-Type":"application/json"}),o.end(JSON.stringify(this.clientInfo))):(o.writeHead(404),o.end("Not Found"))}catch(n){this.logger.error("HTTP request error:",n),o.writeHead(500,{"Content-Type":"application/json"}),o.end(JSON.stringify({error:"Internal Server Error"}))}}async serveStaticFile(e,o){try{let t=De(Ge(import.meta.url)),s=[$(t,"..","web","dist"),$(t,"..","web"),$(process.cwd(),"web","dist"),$(process.cwd(),"web")].find(S=>V(S));if(!s){o.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),o.end(`
|
|
15
|
+
`;e.response.write(t)}catch(t){h.error(`\u53D1\u9001\u5230\u5BA2\u6237\u7AEF ${e.id} \u5931\u8D25:`,t),this.clients.delete(e.sessionId)}}broadcastToClients(e){for(let o of this.clients.values())this.sendToClient(o,e)}async start(){try{let e=await Promise.allSettled([this.startMCPProxy(),new Promise(n=>{this.server=this.app.listen(this.port,"0.0.0.0",()=>{h.info(`MCP\u670D\u52A1\u5668\u76D1\u542C\u7AEF\u53E3 ${this.port} (\u6240\u6709\u7F51\u7EDC\u63A5\u53E3)`),h.info(`SSE\u7AEF\u70B9: http://0.0.0.0:${this.port}/sse`),h.info(`\u6D88\u606F\u7AEF\u70B9: http://0.0.0.0:${this.port}/messages`),h.info(`RPC\u7AEF\u70B9: http://0.0.0.0:${this.port}/rpc`),h.info(`\u672C\u5730\u8BBF\u95EE: http://localhost:${this.port}`),n()})})]),[o,t]=e;if(o.status==="rejected"&&h.error("MCP\u4EE3\u7406\u542F\u52A8\u5931\u8D25:",o.reason),t.status==="rejected")throw h.error("HTTP\u670D\u52A1\u5668\u542F\u52A8\u5931\u8D25:",t.reason),t.reason;this.startMCPClient().catch(n=>{h.error("\u542F\u52A8\u8FDE\u63A5\u5230xiaozhi.me\u7684MCP\u5BA2\u6237\u7AEF\u5931\u8D25:",n)}),this.emit("started")}catch(e){throw h.error("\u542F\u52A8MCP\u670D\u52A1\u5668\u5931\u8D25:",e),e}}findMCPProxyPath(){if(this.mcpProxyPath)return this.mcpProxyPath;if(process.env.MCP_SERVER_PROXY_PATH){let n=w.normalize(process.env.MCP_SERVER_PROXY_PATH),s=w.resolve(n),c=[_,w.join(_,".."),w.join(_,"..",".."),w.join(_,"..","..","dist"),Ze.tmpdir()];if(L.existsSync(s)&&w.basename(s)===H&&c.some(a=>s.startsWith(a)))return this.mcpProxyPath=s,this.mcpProxyPath;throw h.warn(`MCP_SERVER_PROXY_PATH \u8DEF\u5F84\u4E0D\u5B89\u5168: ${n}`),new Error(`\u6307\u5B9A\u7684 MCP \u4EE3\u7406\u8DEF\u5F84\u4E0D\u5B58\u5728\u6216\u4E0D\u5B89\u5168: ${process.env.MCP_SERVER_PROXY_PATH}`)}let e=ue(import.meta.url),o=w.dirname(e),t=null;for(let n=0;n<Ke;n++){let s=w.join(o,H);if(L.existsSync(s)){t=s;break}let c=w.join(o,"dist",H);if(L.existsSync(c)){t=c;break}o=w.dirname(o)}if(!t){let n=w.resolve(_,"..",".."),s=w.join(n,"dist",H);L.existsSync(s)&&(t=s)}if(!t)throw new Error(`\u5728\u9879\u76EE\u7ED3\u6784\u4E2D\u627E\u4E0D\u5230 ${H}`);return this.mcpProxyPath=t,this.mcpProxyPath}async startMCPProxy(){let e=this.findMCPProxyPath();h.info(`\u6B63\u5728\u542F\u52A8MCP\u4EE3\u7406: ${e}`),this.mcpProxy=Ue("node",[e],{stdio:["pipe","pipe","pipe"],env:{...process.env,MCP_SERVER_MODE:"true",XIAOZHI_CONFIG_DIR:process.env.XIAOZHI_CONFIG_DIR||process.cwd()}}),this.mcpProxy.on("error",o=>{h.error("MCP\u4EE3\u7406\u9519\u8BEF:",o)}),this.mcpProxy.on("exit",(o,t)=>{h.warn(`MCP\u4EE3\u7406\u9000\u51FA\uFF0C\u4EE3\u7801 ${o}\uFF0C\u4FE1\u53F7 ${t}`),this.mcpProxy=null}),this.mcpProxy.stderr&&this.mcpProxy.stderr.on("data",o=>{let t=o.toString().trim();t.includes("[ERROR]")||t.includes("Error:")||t.includes("Failed")?h.error("MCP\u4EE3\u7406stderr:",t):h.info("MCP\u4EE3\u7406\u8F93\u51FA:",t)}),this.mcpProxy.stdout&&this.mcpProxy.stdout.on("data",o=>{this.handleProxyResponse(o)}),await new Promise((o,t)=>{let n=setTimeout(()=>{t(new Error("MCP\u4EE3\u7406\u542F\u52A8\u8D85\u65F6"))},1e4),s=g(c=>{let a=c.toString();(a.includes("MCP proxy ready")||a.includes("started"))&&(clearTimeout(n),this.mcpProxy?.stdout?.removeListener("data",s),o())},"dataHandler");this.mcpProxy?.stdout?.on("data",s)}),h.info("MCP\u4EE3\u7406\u542F\u52A8\u6210\u529F")}async startMCPClient(){let e=[];try{l.configExists()&&(e=l.getMcpEndpoints())}catch(o){h.warn("\u4ECE\u914D\u7F6E\u4E2D\u8BFB\u53D6MCP\u7AEF\u70B9\u5931\u8D25:",o)}if(e.length>0){let o=this.findMCPProxyPath();this.mcpClient=new G(o,e),await this.mcpClient.start(),h.info("MCP\u5BA2\u6237\u7AEF\u5DF2\u542F\u52A8\uFF0C\u6B63\u5728\u8FDE\u63A5\u5230 xiaozhi.me")}else h.info("\u672A\u914D\u7F6EMCP\u7AEF\u70B9\uFF0C\u8DF3\u8FC7\u5BA2\u6237\u7AEF\u8FDE\u63A5")}async stop(){h.info("\u6B63\u5728\u505C\u6B62MCP\u670D\u52A1\u5668...");for(let e of this.clients.values())try{e.response.end()}catch{}this.clients.clear(),this.server&&(await new Promise(e=>{this.server.close(()=>e())}),this.server=null),this.mcpProxy&&(this.mcpProxy.kill("SIGTERM"),await new Promise(e=>{this.mcpProxy.on("exit",()=>e()),setTimeout(()=>{this.mcpProxy?.kill("SIGKILL"),e()},5e3)}),this.mcpProxy=null),this.mcpClient&&(this.mcpClient.shutdown(),this.mcpClient=null),this.mcpProxyPath=null,this.emit("stopped"),h.info("MCP\u670D\u52A1\u5668\u5DF2\u505C\u6B62")}}});import{spawn as q}from"child_process";import C from"fs";import f from"path";import{fileURLToPath as j}from"url";import i from"chalk";import{Command as Ye}from"commander";import P from"ora";$();import ke from"omelette";function Ae(){try{if(!l.configExists())return[];let r=l.getMcpServers();return Object.keys(r)}catch{return[]}}g(Ae,"getMcpServerNames");function Ne(r){try{if(!l.configExists())return[];let e=l.getServerToolsConfig(r);return Object.keys(e)}catch{return[]}}g(Ne,"getServerToolNames");function re(){let r=ke("xiaozhi <command>");if(r.on("command",({reply:e})=>{e(["create","init","config","start","stop","status","attach","restart","mcp","completion"])}),r.on("complete",(e,{line:o,before:t,reply:n})=>{process.env.XIAOZHI_DEBUG_COMPLETION&&console.error(`Debug completion - line: "${o}", before: "${t}", fragment: "${e}"`);let s=o.trim().split(/\s+/),a=o!==o.trim()?s.length:s.length-1;if(s[1]==="mcp"){let m=s[2];if(a===2){let u=["list","server","tool"],y=s[2]||"",b=u.filter(S=>S.startsWith(y));n(b);return}if(a===3){switch(m){case"list":{let u=["--tools"],y=s[3]||"",b=u.filter(S=>S.startsWith(y));n(b);break}case"server":case"tool":{let u=Ae(),y=s[3]||"",b=u.filter(S=>S.startsWith(y));n(b);break}default:n([])}return}if(a===4&&m==="tool"){let u=s[3],y=Ne(u),b=s[4]||"",S=y.filter(R=>R.startsWith(b));n(S);return}if(a===5&&m==="tool"){let u=["enable","disable"],y=s[5]||"",b=u.filter(S=>S.startsWith(y));n(b);return}}if(a===2){switch(s[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(e){console.error("\u751F\u6210\u81EA\u52A8\u8865\u5168\u811A\u672C\u65F6\u51FA\u9519:",e)}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()}g(re,"setupAutoCompletion");function se(){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(se,"showCompletionHelp");$();A();$();import p from"chalk";import ie from"cli-table3";import Z from"ora";function ce(r){let e=0;for(let o of r)/[\u4e00-\u9fff\u3400-\u4dbf\uff00-\uffef]/.test(o)?e+=2:e+=1;return e}g(ce,"getDisplayWidth");function ae(r,e){if(ce(r)<=e)return r;if(e<=3)return"";let o="",t=0,n=!1;for(let s of r){let c=/[\u4e00-\u9fff\u3400-\u4dbf\uff00-\uffef]/.test(s)?2:1;if(t+c>e-3){if(!n)return"";o+="...";break}o+=s,t+=c,n=!0}return o}g(ae,"truncateToWidth");async function le(r={}){let e=Z("\u83B7\u53D6 MCP \u670D\u52A1\u5217\u8868...").start();try{let o=l.getMcpServers(),t=Object.keys(o);if(t.length===0){e.warn("\u672A\u914D\u7F6E\u4EFB\u4F55 MCP \u670D\u52A1"),console.log(p.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi config' \u547D\u4EE4\u914D\u7F6E MCP \u670D\u52A1"));return}if(e.succeed(`\u627E\u5230 ${t.length} \u4E2A MCP \u670D\u52A1`),r.tools){console.log(),console.log(p.bold("MCP \u670D\u52A1\u5DE5\u5177\u5217\u8868:")),console.log();let n=8,s=[];for(let a of t){let m=l.getServerToolsConfig(a),u=Object.keys(m);s.push(...u)}for(let a of s){let m=ce(a);m>n&&(n=m)}n=Math.max(10,Math.min(n+2,30));let c=new ie({head:[p.bold("MCP"),p.bold("\u5DE5\u5177\u540D\u79F0"),p.bold("\u72B6\u6001"),p.bold("\u63CF\u8FF0")],colWidths:[15,n,8,40],wordWrap:!0,style:{head:[],border:[]}});for(let a of t){let m=l.getServerToolsConfig(a),u=Object.keys(m);if(u.length===0)c.push([p.gray(a),p.gray("-"),p.gray("-"),p.gray("\u6682\u672A\u8BC6\u522B\u5230\u76F8\u5173\u5DE5\u5177")]);else{c.length>0&&c.push([{colSpan:4,content:""}]);for(let y of u){let b=m[y],S=b.enable?p.green("\u542F\u7528"):p.red("\u7981\u7528"),R=ae(b.description||"",32);c.push([a,y,S,R])}}}console.log(c.toString())}else{console.log(),console.log(p.bold("MCP \u670D\u52A1\u5217\u8868:")),console.log();for(let n of t){let s=o[n],c=l.getServerToolsConfig(n),a=Object.keys(c).length,m=Object.values(c).filter(u=>u.enable!==!1).length;console.log(`${p.cyan("\u2022")} ${p.bold(n)}`),"url"in s?("type"in s&&s.type==="sse"?console.log(` \u7C7B\u578B: ${p.gray("SSE")}`):console.log(` \u7C7B\u578B: ${p.gray("Streamable HTTP")}`),console.log(` URL: ${p.gray(s.url)}`)):console.log(` \u547D\u4EE4: ${p.gray(s.command)} ${p.gray(s.args.join(" "))}`),a>0?console.log(` \u5DE5\u5177: ${p.green(m)} \u542F\u7528 / ${p.yellow(a)} \u603B\u8BA1`):console.log(` \u5DE5\u5177: ${p.gray("\u672A\u626B\u63CF (\u8BF7\u5148\u542F\u52A8\u670D\u52A1)")}`),console.log()}}console.log(p.gray("\u{1F4A1} \u63D0\u793A:")),console.log(p.gray(" - \u4F7F\u7528 'xiaozhi mcp list --tools' \u67E5\u770B\u6240\u6709\u5DE5\u5177")),console.log(p.gray(" - \u4F7F\u7528 'xiaozhi mcp <\u670D\u52A1\u540D> list' \u67E5\u770B\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177")),console.log(p.gray(" - \u4F7F\u7528 'xiaozhi mcp <\u670D\u52A1\u540D> <\u5DE5\u5177\u540D> enable/disable' \u542F\u7528/\u7981\u7528\u5DE5\u5177"))}catch(o){e.fail("\u83B7\u53D6 MCP \u670D\u52A1\u5217\u8868\u5931\u8D25"),console.error(p.red(`\u9519\u8BEF: ${o instanceof Error?o.message:String(o)}`)),process.exit(1)}}g(le,"listMcpServers");async function ge(r){let e=Z(`\u83B7\u53D6 ${r} \u670D\u52A1\u7684\u5DE5\u5177\u5217\u8868...`).start();try{if(!l.getMcpServers()[r]){e.fail(`\u670D\u52A1 '${r}' \u4E0D\u5B58\u5728`),console.log(p.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp list' \u67E5\u770B\u6240\u6709\u53EF\u7528\u670D\u52A1"));return}let t=l.getServerToolsConfig(r),n=Object.keys(t);if(n.length===0){e.warn(`\u670D\u52A1 '${r}' \u6682\u65E0\u5DE5\u5177\u4FE1\u606F`),console.log(p.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u542F\u52A8\u670D\u52A1\u4EE5\u626B\u63CF\u5DE5\u5177\u5217\u8868"));return}e.succeed(`\u670D\u52A1 '${r}' \u5171\u6709 ${n.length} \u4E2A\u5DE5\u5177`),console.log(),console.log(p.bold(`${r} \u670D\u52A1\u5DE5\u5177\u5217\u8868:`)),console.log();let s=new ie({head:[p.bold("\u5DE5\u5177\u540D\u79F0"),p.bold("\u72B6\u6001"),p.bold("\u63CF\u8FF0")],colWidths:[30,8,50],wordWrap:!0,style:{head:[],border:[]}});for(let c of n){let a=t[c],m=a.enable?p.green("\u542F\u7528"):p.red("\u7981\u7528"),u=ae(a.description||"",40);s.push([c,m,u])}console.log(s.toString()),console.log(),console.log(p.gray("\u{1F4A1} \u63D0\u793A:")),console.log(p.gray(` - \u4F7F\u7528 'xiaozhi mcp ${r} <\u5DE5\u5177\u540D> enable' \u542F\u7528\u5DE5\u5177`)),console.log(p.gray(` - \u4F7F\u7528 'xiaozhi mcp ${r} <\u5DE5\u5177\u540D> disable' \u7981\u7528\u5DE5\u5177`))}catch(o){e.fail("\u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25"),console.error(p.red(`\u9519\u8BEF: ${o instanceof Error?o.message:String(o)}`)),process.exit(1)}}g(ge,"listServerTools");async function pe(r,e,o){let t=o?"\u542F\u7528":"\u7981\u7528",n=Z(`${t}\u5DE5\u5177 ${r}/${e}...`).start();try{if(!l.getMcpServers()[r]){n.fail(`\u670D\u52A1 '${r}' \u4E0D\u5B58\u5728`),console.log(p.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp list' \u67E5\u770B\u6240\u6709\u53EF\u7528\u670D\u52A1"));return}let c=l.getServerToolsConfig(r);if(!c[e]){n.fail(`\u5DE5\u5177 '${e}' \u5728\u670D\u52A1 '${r}' \u4E2D\u4E0D\u5B58\u5728`),console.log(p.yellow(`\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp ${r} list' \u67E5\u770B\u8BE5\u670D\u52A1\u7684\u6240\u6709\u5DE5\u5177`));return}l.setToolEnabled(r,e,o,c[e].description),n.succeed(`\u6210\u529F${t}\u5DE5\u5177 ${p.cyan(r)}/${p.cyan(e)}`),console.log(),console.log(p.gray("\u{1F4A1} \u63D0\u793A: \u5DE5\u5177\u72B6\u6001\u66F4\u6539\u5C06\u5728\u4E0B\u6B21\u542F\u52A8\u670D\u52A1\u65F6\u751F\u6548"))}catch(s){n.fail(`${t}\u5DE5\u5177\u5931\u8D25`),console.error(p.red(`\u9519\u8BEF: ${s instanceof Error?s.message:String(s)}`)),process.exit(1)}}g(pe,"setToolEnabled");import{spawn as fe}from"child_process";import{existsSync as V}from"fs";import{readFile as de}from"fs/promises";import{createServer as Fe}from"http";import{dirname as De,join as T}from"path";import{parse as We}from"url";import{fileURLToPath as Ge}from"url";import{WebSocketServer as Le}from"ws";$();A();var N=class{static{g(this,"WebServer")}httpServer;wss;logger;port;clientInfo={status:"disconnected",mcpEndpoint:"",activeMCPServers:[]};heartbeatTimeout;HEARTBEAT_TIMEOUT=35e3;constructor(e){if(e===void 0)try{this.port=l.getWebUIPort()}catch{this.port=9999}else this.port=e;this.logger=new k,this.httpServer=Fe((o,t)=>{this.handleHttpRequest(o,t)}),this.wss=new Le({server:this.httpServer}),this.setupWebSocket()}async handleHttpRequest(e,o){let{pathname:t}=We(e.url||"",!0);if(o.setHeader("Access-Control-Allow-Origin","*"),o.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, OPTIONS"),o.setHeader("Access-Control-Allow-Headers","Content-Type"),e.method==="OPTIONS"){o.writeHead(200),o.end();return}try{if(e.method==="GET"&&!t?.startsWith("/api/")){await this.serveStaticFile(t||"/",o);return}if(t==="/api/config"&&e.method==="GET"){let n=l.getConfig();o.writeHead(200,{"Content-Type":"application/json"}),o.end(JSON.stringify(n))}else if(t==="/api/config"&&e.method==="PUT"){let n="";e.on("data",s=>{n+=s.toString()}),e.on("end",async()=>{try{let s=JSON.parse(n);this.updateConfig(s),this.broadcastConfigUpdate(s),o.writeHead(200,{"Content-Type":"application/json"}),o.end(JSON.stringify({success:!0})),this.logger.info("\u914D\u7F6E\u5DF2\u66F4\u65B0")}catch(s){o.writeHead(400,{"Content-Type":"application/json"}),o.end(JSON.stringify({error:s instanceof Error?s.message:String(s)}))}})}else t==="/api/status"&&e.method==="GET"?(o.writeHead(200,{"Content-Type":"application/json"}),o.end(JSON.stringify(this.clientInfo))):(o.writeHead(404),o.end("Not Found"))}catch(n){this.logger.error("HTTP request error:",n),o.writeHead(500,{"Content-Type":"application/json"}),o.end(JSON.stringify({error:"Internal Server Error"}))}}async serveStaticFile(e,o){try{let t=De(Ge(import.meta.url)),s=[T(t,"..","web","dist"),T(t,"..","web"),T(process.cwd(),"web","dist"),T(process.cwd(),"web")].find(S=>V(S));if(!s){o.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),o.end(`
|
|
16
16
|
<!DOCTYPE html>
|
|
17
17
|
<html>
|
|
18
18
|
<head>
|
|
@@ -32,13 +32,13 @@ data: ${JSON.stringify(o)}
|
|
|
32
32
|
</div>
|
|
33
33
|
</body>
|
|
34
34
|
</html>
|
|
35
|
-
`);return}let c=e;if(c==="/"&&(c="/index.html"),c.includes("..")){o.writeHead(403),o.end("Forbidden");return}let a=$(s,c);if(!V(a)){let S=$(s,"index.html");if(V(S)){let R=await de(S);o.writeHead(200,{"Content-Type":"text/html"}),o.end(R)}else o.writeHead(404),o.end("Not Found");return}let m=await de(a),u=a.split(".").pop()?.toLowerCase(),b={html:"text/html",js:"application/javascript",css:"text/css",json:"application/json",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",svg:"image/svg+xml",ico:"image/x-icon"}[u||""]||"application/octet-stream";o.writeHead(200,{"Content-Type":b}),o.end(m)}catch(t){this.logger.error("Serve static file error:",t),o.writeHead(500),o.end("Internal Server Error")}}setupWebSocket(){this.wss.on("connection",e=>{this.logger.debug("WebSocket client connected"),e.on("message",async o=>{try{let t=JSON.parse(o.toString());await this.handleWebSocketMessage(e,t)}catch(t){this.logger.error("WebSocket message error:",t),e.send(JSON.stringify({type:"error",error:t instanceof Error?t.message:String(t)}))}}),e.on("close",()=>{this.logger.debug("WebSocket client disconnected")}),this.sendInitialData(e)})}async handleWebSocketMessage(e,o){switch(o.type){case"getConfig":{let t=l.getConfig();e.send(JSON.stringify({type:"config",data:t}));break}case"updateConfig":this.updateConfig(o.config),this.broadcastConfigUpdate(o.config);break;case"getStatus":e.send(JSON.stringify({type:"status",data:this.clientInfo}));break;case"clientStatus":this.updateClientInfo(o.data),this.broadcastStatusUpdate();break;case"restartService":this.logger.info("\u6536\u5230\u624B\u52A8\u91CD\u542F\u670D\u52A1\u8BF7\u6C42"),this.broadcastRestartStatus("restarting"),setTimeout(async()=>{try{await this.restartService(),setTimeout(()=>{this.broadcastRestartStatus("completed")},5e3)}catch(t){this.logger.error(`\u624B\u52A8\u91CD\u542F\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`),this.broadcastRestartStatus("failed",t instanceof Error?t.message:"\u672A\u77E5\u9519\u8BEF")}},500);break}}async sendInitialData(e){let o=l.getConfig();e.send(JSON.stringify({type:"config",data:o})),e.send(JSON.stringify({type:"status",data:this.clientInfo}))}broadcastConfigUpdate(e){let o=JSON.stringify({type:"configUpdate",data:e});for(let t of this.wss.clients)t.readyState===1&&t.send(o)}broadcastRestartStatus(e,o){let t=JSON.stringify({type:"restartStatus",data:{status:e,error:o,timestamp:Date.now()}});for(let n of this.wss.clients)n.readyState===1&&n.send(t)}broadcastStatusUpdate(){let e=JSON.stringify({type:"statusUpdate",data:this.clientInfo});for(let o of this.wss.clients)o.readyState===1&&o.send(e)}updateClientInfo(e){this.clientInfo={...this.clientInfo,...e},e.lastHeartbeat&&(this.clientInfo.lastHeartbeat=Date.now()),e.status==="connected"&&this.resetHeartbeatTimeout()}resetHeartbeatTimeout(){this.heartbeatTimeout&&clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=setTimeout(()=>{this.logger.warn("\u5BA2\u6237\u7AEF\u5FC3\u8DF3\u8D85\u65F6\uFF0C\u6807\u8BB0\u4E3A\u65AD\u5F00\u8FDE\u63A5"),this.updateClientInfo({status:"disconnected"}),this.broadcastStatusUpdate()},this.HEARTBEAT_TIMEOUT)}updateConfig(e){e.mcpEndpoint!==l.getMcpEndpoint()&&l.updateMcpEndpoint(e.mcpEndpoint);let o=l.getMcpServers();for(let[t,n]of Object.entries(e.mcpServers))JSON.stringify(o[t])!==JSON.stringify(n)&&l.updateMcpServer(t,n);for(let t of Object.keys(o))t in e.mcpServers||(l.removeMcpServer(t),l.removeServerToolsConfig(t));if(e.connection&&l.updateConnectionConfig(e.connection),e.modelscope&&l.updateModelScopeConfig(e.modelscope),e.webUI&&l.updateWebUIConfig(e.webUI),e.mcpServerConfig)for(let[t,n]of Object.entries(e.mcpServerConfig))for(let[s,c]of Object.entries(n.tools))l.setToolEnabled(t,s,c.enable)}async restartService(){this.logger.info("\u6B63\u5728\u91CD\u542F MCP \u670D\u52A1..."),this.heartbeatTimeout&&(clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=void 0);try{let e=M();if(!e.running){this.logger.warn("MCP \u670D\u52A1\u672A\u8FD0\u884C\uFF0C\u5C1D\u8BD5\u542F\u52A8\u670D\u52A1"),fe("xiaozhi",["start","--daemon"],{detached:!0,stdio:"ignore",env:{...process.env,XIAOZHI_CONFIG_DIR:process.env.XIAOZHI_CONFIG_DIR||process.cwd()}}).unref(),this.logger.info("MCP \u670D\u52A1\u542F\u52A8\u547D\u4EE4\u5DF2\u53D1\u9001");return}let o=e.mode==="daemon",t=["restart"];o&&t.push("--daemon"),fe("xiaozhi",t,{detached:!0,stdio:"ignore",env:{...process.env,XIAOZHI_CONFIG_DIR:process.env.XIAOZHI_CONFIG_DIR||process.cwd()}}).unref(),this.logger.info("MCP \u670D\u52A1\u91CD\u542F\u547D\u4EE4\u5DF2\u53D1\u9001"),this.resetHeartbeatTimeout()}catch(e){throw this.logger.error(`\u91CD\u542F\u670D\u52A1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`),this.resetHeartbeatTimeout(),e}}updateStatus(e){this.updateClientInfo(e),this.broadcastStatusUpdate()}start(){return new Promise((e,o)=>{this.httpServer.listen(this.port,()=>{this.logger.info(`Web server listening on http://localhost:${this.port}`),e()}).on("error",o)})}stop(){return new Promise(e=>{this.heartbeatTimeout&&(clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=void 0);for(let o of this.wss.clients)o.terminate();this.wss.close(()=>{this.httpServer.close(()=>{this.logger.info("Web server stopped"),e()}),setTimeout(()=>{this.logger.info("Web server force stopped"),e()},2e3)})})}};var v=new Ke,Ye="xiaozhi-mcp-service";function ve(){try{let r=j(import.meta.url),e=f.dirname(r),o=[f.join(e,"..","package.json"),f.join(e,"..","package.json"),f.join(e,"..","..","package.json"),f.join(e,"package.json")];for(let t of o)if(C.existsSync(t)){let n=JSON.parse(C.readFileSync(t,"utf8"));if(n.version)return n.version}return"unknown"}catch(r){return console.warn("\u65E0\u6CD5\u4ECE package.json \u8BFB\u53D6\u7248\u672C\u4FE1\u606F:",r),"unknown"}}g(ve,"getVersion");var ee=g(()=>{let r=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return f.join(r,`.${Ye}.pid`)},"getPidFile");function M(){try{let r=ee();if(!C.existsSync(r))return{running:!1};let e=C.readFileSync(r,"utf8").trim(),[o,t,n]=e.split("|"),s=Number.parseInt(o);if(Number.isNaN(s))return C.unlinkSync(r),{running:!1};try{process.kill(s,0);let c=Number.parseInt(t),a=qe(Date.now()-c);return{running:!0,pid:s,uptime:a,mode:n||"foreground"}}catch{return C.unlinkSync(r),{running:!1}}}catch{return{running:!1}}}g(M,"getServiceStatus");function qe(r){let e=Math.floor(r/1e3),o=Math.floor(e/60),t=Math.floor(o/60),n=Math.floor(t/24);return n>0?`${n}\u5929 ${t%24}\u5C0F\u65F6 ${o%60}\u5206\u949F`:t>0?`${t}\u5C0F\u65F6 ${o%60}\u5206\u949F`:o>0?`${o}\u5206\u949F ${e%60}\u79D2`:`${e}\u79D2`}g(qe,"formatUptime");function Q(r,e){let o=`${r}|${Date.now()}|${e}`;C.writeFileSync(ee(),o)}g(Q,"savePidInfo");function F(){try{let r=ee();C.existsSync(r)&&C.unlinkSync(r)}catch{}}g(F,"cleanupPidFile");function Qe(){if(!l.configExists())return console.error(i.red("\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728")),console.log(i.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E')),!1;try{let r=l.getMcpEndpoint();return!r||r.includes("<\u8BF7\u586B\u5199")?(console.error(i.red("\u274C \u9519\u8BEF: MCP \u7AEF\u70B9\u672A\u914D\u7F6E")),console.log(i.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi config mcpEndpoint <your-endpoint-url>" \u8BBE\u7F6E\u7AEF\u70B9')),!1):!0}catch(r){return console.error(i.red(`\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u65E0\u6548 - ${r instanceof Error?r.message:String(r)}`)),console.log(i.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u91CD\u65B0\u521D\u59CB\u5316\u914D\u7F6E')),!1}}g(Qe,"checkEnvironment");function eo(){let r=f.dirname(j(import.meta.url)),e;return r.includes("js-demo/dist")?e=r:e=[f.join(r,"..","js-demo","dist"),f.join(r,"..","..","js-demo","dist"),f.join(r,"..","..","..","js-demo","dist"),f.join(process.cwd(),"js-demo","dist"),f.join(process.cwd(),"dist")].find(t=>C.existsSync(f.join(t,"adaptiveMCPPipe.js"))&&C.existsSync(f.join(t,"mcpServerProxy.js")))||r,{command:"node",args:["adaptiveMCPPipe.js","mcpServerProxy.js"],cwd:e}}g(eo,"getServiceCommand");async function be(){try{if(!l.configExists()){console.log(i.yellow("\u{1F4A1} \u63D0\u793A: \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7 Web UI \u542F\u52A8"));return}let r=new N;await r.start();let e=l.getWebUIPort();console.log(i.green(`\u2705 Web UI \u5DF2\u542F\u52A8: http://localhost:${e}`));let{spawn:o}=await import("child_process"),t=`http://localhost:${e}`;try{process.platform==="darwin"?o("open",[t],{detached:!0,stdio:"ignore"}).unref():process.platform==="win32"?o("cmd",["/c","start",t],{detached:!0,stdio:"ignore"}).unref():o("xdg-open",[t],{detached:!0,stdio:"ignore"}).unref()}catch{}global.__webServer=r}catch(r){console.log(i.yellow(`\u26A0\uFE0F Web UI \u542F\u52A8\u5931\u8D25: ${r instanceof Error?r.message:String(r)}`))}}g(be,"startWebUIInBackground");async function we(r=!1,e=!1){let o=P("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let t=M();if(t.running){o.fail(`\u670D\u52A1\u5DF2\u7ECF\u5728\u8FD0\u884C (PID: ${t.pid})`);return}if(o.text="\u68C0\u67E5\u73AF\u5883\u914D\u7F6E...",!Qe()){o.fail("\u73AF\u5883\u914D\u7F6E\u68C0\u67E5\u5931\u8D25");return}let{command:n,args:s,cwd:c}=eo();if(o.text=`\u542F\u52A8\u670D\u52A1 (${r?"\u540E\u53F0\u6A21\u5F0F":"\u524D\u53F0\u6A21\u5F0F"})...`,r){let a=q(n,s,{cwd:c,detached:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd(),XIAOZHI_DAEMON:"true"}});Q(a.pid,"daemon");let m=process.cwd();I.initLogFile(m),I.enableFileLogging(!0);let u=f.join(m,"xiaozhi.log"),y=C.createWriteStream(u,{flags:"a"});a.stdout?.pipe(y),a.stderr?.pipe(y),a.on("exit",(b,S)=>{b!==0&&b!==null&&I.error(`\u540E\u53F0\u670D\u52A1\u5F02\u5E38\u9000\u51FA (\u4EE3\u7801: ${b}, \u4FE1\u53F7: ${S})`),F()}),a.on("error",b=>{I.error(`\u540E\u53F0\u670D\u52A1\u542F\u52A8\u9519\u8BEF: ${b.message}`),F(),o.fail(`\u540E\u53F0\u670D\u52A1\u542F\u52A8\u5931\u8D25: ${b.message}`)}),a.unref(),o.succeed(`\u670D\u52A1\u5DF2\u5728\u540E\u53F0\u542F\u52A8 (PID: ${a.pid})`),console.log(i.gray(`\u65E5\u5FD7\u6587\u4EF6: ${u}`)),console.log(i.gray("\u4F7F\u7528 'xiaozhi attach' \u53EF\u4EE5\u67E5\u770B\u5B9E\u65F6\u65E5\u5FD7")),e&&await be()}else{o.succeed("\u670D\u52A1\u542F\u52A8\u4E2D...");let a=q(n,s,{cwd:c,stdio:"inherit",env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd()}});Q(a.pid,"foreground"),a.on("exit",(m,u)=>{F(),console.log(m!==0?i.red(`
|
|
35
|
+
`);return}let c=e;if(c==="/"&&(c="/index.html"),c.includes("..")){o.writeHead(403),o.end("Forbidden");return}let a=T(s,c);if(!V(a)){let S=T(s,"index.html");if(V(S)){let R=await de(S);o.writeHead(200,{"Content-Type":"text/html"}),o.end(R)}else o.writeHead(404),o.end("Not Found");return}let m=await de(a),u=a.split(".").pop()?.toLowerCase(),b={html:"text/html",js:"application/javascript",css:"text/css",json:"application/json",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",svg:"image/svg+xml",ico:"image/x-icon"}[u||""]||"application/octet-stream";o.writeHead(200,{"Content-Type":b}),o.end(m)}catch(t){this.logger.error("Serve static file error:",t),o.writeHead(500),o.end("Internal Server Error")}}setupWebSocket(){this.wss.on("connection",e=>{this.logger.debug("WebSocket client connected"),e.on("message",async o=>{try{let t=JSON.parse(o.toString());await this.handleWebSocketMessage(e,t)}catch(t){this.logger.error("WebSocket message error:",t),e.send(JSON.stringify({type:"error",error:t instanceof Error?t.message:String(t)}))}}),e.on("close",()=>{this.logger.debug("WebSocket client disconnected")}),this.sendInitialData(e)})}async handleWebSocketMessage(e,o){switch(o.type){case"getConfig":{let t=l.getConfig();e.send(JSON.stringify({type:"config",data:t}));break}case"updateConfig":this.updateConfig(o.config),this.broadcastConfigUpdate(o.config);break;case"getStatus":e.send(JSON.stringify({type:"status",data:this.clientInfo}));break;case"clientStatus":this.updateClientInfo(o.data),this.broadcastStatusUpdate();break;case"restartService":this.logger.info("\u6536\u5230\u624B\u52A8\u91CD\u542F\u670D\u52A1\u8BF7\u6C42"),this.broadcastRestartStatus("restarting"),setTimeout(async()=>{try{await this.restartService(),setTimeout(()=>{this.broadcastRestartStatus("completed")},5e3)}catch(t){this.logger.error(`\u624B\u52A8\u91CD\u542F\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`),this.broadcastRestartStatus("failed",t instanceof Error?t.message:"\u672A\u77E5\u9519\u8BEF")}},500);break}}async sendInitialData(e){let o=l.getConfig();e.send(JSON.stringify({type:"config",data:o})),e.send(JSON.stringify({type:"status",data:this.clientInfo}))}broadcastConfigUpdate(e){let o=JSON.stringify({type:"configUpdate",data:e});for(let t of this.wss.clients)t.readyState===1&&t.send(o)}broadcastRestartStatus(e,o){let t=JSON.stringify({type:"restartStatus",data:{status:e,error:o,timestamp:Date.now()}});for(let n of this.wss.clients)n.readyState===1&&n.send(t)}broadcastStatusUpdate(){let e=JSON.stringify({type:"statusUpdate",data:this.clientInfo});for(let o of this.wss.clients)o.readyState===1&&o.send(e)}updateClientInfo(e){this.clientInfo={...this.clientInfo,...e},e.lastHeartbeat&&(this.clientInfo.lastHeartbeat=Date.now()),e.status==="connected"&&this.resetHeartbeatTimeout()}resetHeartbeatTimeout(){this.heartbeatTimeout&&clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=setTimeout(()=>{this.logger.warn("\u5BA2\u6237\u7AEF\u5FC3\u8DF3\u8D85\u65F6\uFF0C\u6807\u8BB0\u4E3A\u65AD\u5F00\u8FDE\u63A5"),this.updateClientInfo({status:"disconnected"}),this.broadcastStatusUpdate()},this.HEARTBEAT_TIMEOUT)}updateConfig(e){e.mcpEndpoint!==l.getMcpEndpoint()&&l.updateMcpEndpoint(e.mcpEndpoint);let o=l.getMcpServers();for(let[t,n]of Object.entries(e.mcpServers))JSON.stringify(o[t])!==JSON.stringify(n)&&l.updateMcpServer(t,n);for(let t of Object.keys(o))t in e.mcpServers||(l.removeMcpServer(t),l.removeServerToolsConfig(t));if(e.connection&&l.updateConnectionConfig(e.connection),e.modelscope&&l.updateModelScopeConfig(e.modelscope),e.webUI&&l.updateWebUIConfig(e.webUI),e.mcpServerConfig)for(let[t,n]of Object.entries(e.mcpServerConfig))for(let[s,c]of Object.entries(n.tools))l.setToolEnabled(t,s,c.enable)}async restartService(){this.logger.info("\u6B63\u5728\u91CD\u542F MCP \u670D\u52A1..."),this.heartbeatTimeout&&(clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=void 0);try{let e=M();if(!e.running){this.logger.warn("MCP \u670D\u52A1\u672A\u8FD0\u884C\uFF0C\u5C1D\u8BD5\u542F\u52A8\u670D\u52A1"),fe("xiaozhi",["start","--daemon"],{detached:!0,stdio:"ignore",env:{...process.env,XIAOZHI_CONFIG_DIR:process.env.XIAOZHI_CONFIG_DIR||process.cwd()}}).unref(),this.logger.info("MCP \u670D\u52A1\u542F\u52A8\u547D\u4EE4\u5DF2\u53D1\u9001");return}let o=e.mode==="daemon",t=["restart"];o&&t.push("--daemon"),fe("xiaozhi",t,{detached:!0,stdio:"ignore",env:{...process.env,XIAOZHI_CONFIG_DIR:process.env.XIAOZHI_CONFIG_DIR||process.cwd()}}).unref(),this.logger.info("MCP \u670D\u52A1\u91CD\u542F\u547D\u4EE4\u5DF2\u53D1\u9001"),this.resetHeartbeatTimeout()}catch(e){throw this.logger.error(`\u91CD\u542F\u670D\u52A1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`),this.resetHeartbeatTimeout(),e}}updateStatus(e){this.updateClientInfo(e),this.broadcastStatusUpdate()}start(){return new Promise((e,o)=>{this.httpServer.listen(this.port,"0.0.0.0",()=>{this.logger.info(`Web server listening on http://0.0.0.0:${this.port}`),this.logger.info(`Local access: http://localhost:${this.port}`),e()}).on("error",o)})}stop(){return new Promise(e=>{let o=!1,t=g(()=>{o||(o=!0,e())},"doResolve");this.heartbeatTimeout&&(clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=void 0);for(let n of this.wss.clients)n.terminate();this.wss.close(()=>{this.httpServer.close(()=>{this.logger.info("Web server stopped"),t()}),setTimeout(()=>{this.logger.info("Web server force stopped"),t()},2e3)})})}};var v=new Ye,qe="xiaozhi-mcp-service";function ve(){try{let r=j(import.meta.url),e=f.dirname(r),o=[f.join(e,"..","package.json"),f.join(e,"..","package.json"),f.join(e,"..","..","package.json"),f.join(e,"package.json")];for(let t of o)if(C.existsSync(t)){let n=JSON.parse(C.readFileSync(t,"utf8"));if(n.version)return n.version}return"unknown"}catch(r){return console.warn("\u65E0\u6CD5\u4ECE package.json \u8BFB\u53D6\u7248\u672C\u4FE1\u606F:",r),"unknown"}}g(ve,"getVersion");var ee=g(()=>{let r=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return f.join(r,`.${qe}.pid`)},"getPidFile");function M(){try{let r=ee();if(!C.existsSync(r))return{running:!1};let e=C.readFileSync(r,"utf8").trim(),[o,t,n]=e.split("|"),s=Number.parseInt(o);if(Number.isNaN(s))return C.unlinkSync(r),{running:!1};try{process.kill(s,0);let c=Number.parseInt(t),a=Qe(Date.now()-c);return{running:!0,pid:s,uptime:a,mode:n||"foreground"}}catch{return C.unlinkSync(r),{running:!1}}}catch{return{running:!1}}}g(M,"getServiceStatus");function Qe(r){let e=Math.floor(r/1e3),o=Math.floor(e/60),t=Math.floor(o/60),n=Math.floor(t/24);return n>0?`${n}\u5929 ${t%24}\u5C0F\u65F6 ${o%60}\u5206\u949F`:t>0?`${t}\u5C0F\u65F6 ${o%60}\u5206\u949F`:o>0?`${o}\u5206\u949F ${e%60}\u79D2`:`${e}\u79D2`}g(Qe,"formatUptime");function Q(r,e){let o=`${r}|${Date.now()}|${e}`;C.writeFileSync(ee(),o)}g(Q,"savePidInfo");function F(){try{let r=ee();C.existsSync(r)&&C.unlinkSync(r)}catch{}}g(F,"cleanupPidFile");function eo(){if(!l.configExists())return console.error(i.red("\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728")),console.log(i.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E')),!1;try{let r=l.getMcpEndpoint();return!r||r.includes("<\u8BF7\u586B\u5199")?(console.error(i.red("\u274C \u9519\u8BEF: MCP \u7AEF\u70B9\u672A\u914D\u7F6E")),console.log(i.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi config mcpEndpoint <your-endpoint-url>" \u8BBE\u7F6E\u7AEF\u70B9')),!1):!0}catch(r){return console.error(i.red(`\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u65E0\u6548 - ${r instanceof Error?r.message:String(r)}`)),console.log(i.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u91CD\u65B0\u521D\u59CB\u5316\u914D\u7F6E')),!1}}g(eo,"checkEnvironment");function oo(){let r=f.dirname(j(import.meta.url)),e;return r.includes("js-demo/dist")?e=r:e=[f.join(r,"..","js-demo","dist"),f.join(r,"..","..","js-demo","dist"),f.join(r,"..","..","..","js-demo","dist"),f.join(process.cwd(),"js-demo","dist"),f.join(process.cwd(),"dist")].find(t=>C.existsSync(f.join(t,"adaptiveMCPPipe.js"))&&C.existsSync(f.join(t,"mcpServerProxy.js")))||r,{command:"node",args:["adaptiveMCPPipe.js","mcpServerProxy.js"],cwd:e}}g(oo,"getServiceCommand");async function be(){try{if(!l.configExists()){console.log(i.yellow("\u{1F4A1} \u63D0\u793A: \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7 Web UI \u542F\u52A8"));return}let r=new N;await r.start();let e=l.getWebUIPort();console.log(i.green("\u2705 Web UI \u5DF2\u542F\u52A8\uFF0C\u53EF\u901A\u8FC7\u4EE5\u4E0B\u5730\u5740\u8BBF\u95EE:")),console.log(i.green(` \u672C\u5730\u8BBF\u95EE: http://localhost:${e}`)),console.log(i.green(` \u7F51\u7EDC\u8BBF\u95EE: http://<\u4F60\u7684IP\u5730\u5740>:${e}`));let{spawn:o}=await import("child_process"),t=`http://localhost:${e}`;try{let n;process.platform==="darwin"?n=o("open",[t],{detached:!0,stdio:"ignore"}):process.platform==="win32"?n=o("cmd",["/c","start",t],{detached:!0,stdio:"ignore"}):n=o("xdg-open",[t],{detached:!0,stdio:"ignore"}),n.on("error",()=>{console.log(i.gray(`\u{1F4A1} \u63D0\u793A: \u65E0\u6CD5\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u624B\u52A8\u8BBF\u95EE: ${t}`))}),n.unref()}catch{console.log(i.gray(`\u{1F4A1} \u63D0\u793A: \u65E0\u6CD5\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u624B\u52A8\u8BBF\u95EE: ${t}`))}global.__webServer=r}catch(r){console.log(i.yellow(`\u26A0\uFE0F Web UI \u542F\u52A8\u5931\u8D25: ${r instanceof Error?r.message:String(r)}`))}}g(be,"startWebUIInBackground");async function we(r=!1,e=!1){let o=P("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let t=M();if(t.running){o.fail(`\u670D\u52A1\u5DF2\u7ECF\u5728\u8FD0\u884C (PID: ${t.pid})`);return}if(o.text="\u68C0\u67E5\u73AF\u5883\u914D\u7F6E...",!eo()){o.fail("\u73AF\u5883\u914D\u7F6E\u68C0\u67E5\u5931\u8D25");return}let{command:n,args:s,cwd:c}=oo();if(o.text=`\u542F\u52A8\u670D\u52A1 (${r?"\u540E\u53F0\u6A21\u5F0F":"\u524D\u53F0\u6A21\u5F0F"})...`,r){let a=q(n,s,{cwd:c,detached:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd(),XIAOZHI_DAEMON:"true"}});Q(a.pid,"daemon");let m=process.cwd();I.initLogFile(m),I.enableFileLogging(!0);let u=f.join(m,"xiaozhi.log"),y=C.createWriteStream(u,{flags:"a"});a.stdout?.pipe(y),a.stderr?.pipe(y),a.on("exit",(b,S)=>{b!==0&&b!==null&&I.error(`\u540E\u53F0\u670D\u52A1\u5F02\u5E38\u9000\u51FA (\u4EE3\u7801: ${b}, \u4FE1\u53F7: ${S})`),F()}),a.on("error",b=>{I.error(`\u540E\u53F0\u670D\u52A1\u542F\u52A8\u9519\u8BEF: ${b.message}`),F(),o.fail(`\u540E\u53F0\u670D\u52A1\u542F\u52A8\u5931\u8D25: ${b.message}`)}),a.unref(),o.succeed(`\u670D\u52A1\u5DF2\u5728\u540E\u53F0\u542F\u52A8 (PID: ${a.pid})`),console.log(i.gray(`\u65E5\u5FD7\u6587\u4EF6: ${u}`)),console.log(i.gray("\u4F7F\u7528 'xiaozhi attach' \u53EF\u4EE5\u67E5\u770B\u5B9E\u65F6\u65E5\u5FD7")),e&&await be()}else{o.succeed("\u670D\u52A1\u542F\u52A8\u4E2D...");let a=q(n,s,{cwd:c,stdio:"inherit",env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd()}});Q(a.pid,"foreground"),a.on("exit",(m,u)=>{F(),console.log(m!==0?i.red(`
|
|
36
36
|
\u670D\u52A1\u5F02\u5E38\u9000\u51FA (\u4EE3\u7801: ${m}, \u4FE1\u53F7: ${u})`):i.green(`
|
|
37
37
|
\u670D\u52A1\u5DF2\u505C\u6B62`))}),e&&setTimeout(()=>{be()},1e3),process.on("SIGINT",async()=>{if(console.log(i.yellow(`
|
|
38
|
-
\u6B63\u5728\u505C\u6B62\u670D\u52A1...`)),a.kill("SIGTERM"),global.__webServer)try{await global.__webServer.stop(),console.log(i.green("Web UI \u5DF2\u505C\u6B62"))}catch{}}),process.on("SIGTERM",async()=>{if(a.kill("SIGTERM"),global.__webServer)try{await global.__webServer.stop()}catch{}})}}catch(t){o.fail(`\u542F\u52A8\u670D\u52A1\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}g(we,"startService");async function Pe(){let r=P("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let e=M();if(!e.running){r.warn("\u670D\u52A1\u672A\u5728\u8FD0\u884C");return}r.text=`\u505C\u6B62\u670D\u52A1 (PID: ${e.pid})...`;try{process.kill(e.pid,"SIGTERM");let o=0,t=30;for(;o<t;){await new Promise(n=>setTimeout(n,100));try{process.kill(e.pid,0),o++}catch{break}}try{process.kill(e.pid,0),r.text="\u5F3A\u5236\u505C\u6B62\u670D\u52A1...",process.kill(e.pid,"SIGKILL"),await new Promise(n=>setTimeout(n,500))}catch{}F(),r.succeed("\u670D\u52A1\u5DF2\u505C\u6B62")}catch(o){F(),r.fail(`\u505C\u6B62\u670D\u52A1\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}catch(e){r.fail(`\u505C\u6B62\u670D\u52A1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}g(Pe,"stopService");async function
|
|
38
|
+
\u6B63\u5728\u505C\u6B62\u670D\u52A1...`)),a.kill("SIGTERM"),global.__webServer)try{await global.__webServer.stop(),console.log(i.green("Web UI \u5DF2\u505C\u6B62"))}catch{}}),process.on("SIGTERM",async()=>{if(a.kill("SIGTERM"),global.__webServer)try{await global.__webServer.stop()}catch{}})}}catch(t){o.fail(`\u542F\u52A8\u670D\u52A1\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}g(we,"startService");async function Pe(){let r=P("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let e=M();if(!e.running){r.warn("\u670D\u52A1\u672A\u5728\u8FD0\u884C");return}r.text=`\u505C\u6B62\u670D\u52A1 (PID: ${e.pid})...`;try{process.kill(e.pid,"SIGTERM");let o=0,t=30;for(;o<t;){await new Promise(n=>setTimeout(n,100));try{process.kill(e.pid,0),o++}catch{break}}try{process.kill(e.pid,0),r.text="\u5F3A\u5236\u505C\u6B62\u670D\u52A1...",process.kill(e.pid,"SIGKILL"),await new Promise(n=>setTimeout(n,500))}catch{}F(),r.succeed("\u670D\u52A1\u5DF2\u505C\u6B62")}catch(o){F(),r.fail(`\u505C\u6B62\u670D\u52A1\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}catch(e){r.fail(`\u505C\u6B62\u670D\u52A1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}g(Pe,"stopService");async function to(){let r=P("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let e=M();if(e.running){if(r.succeed("\u670D\u52A1\u72B6\u6001"),console.log(i.green("\u2705 \u670D\u52A1\u6B63\u5728\u8FD0\u884C")),console.log(i.gray(` PID: ${e.pid}`)),console.log(i.gray(` \u8FD0\u884C\u65F6\u95F4: ${e.uptime}`)),console.log(i.gray(` \u8FD0\u884C\u6A21\u5F0F: ${e.mode==="daemon"?"\u540E\u53F0\u6A21\u5F0F":"\u524D\u53F0\u6A21\u5F0F"}`)),e.mode==="daemon"){let o=f.join(process.cwd(),"xiaozhi.log");console.log(i.gray(` \u65E5\u5FD7\u6587\u4EF6: ${o}`))}}else r.succeed("\u670D\u52A1\u72B6\u6001"),console.log(i.red("\u274C \u670D\u52A1\u672A\u8FD0\u884C"))}catch(e){r.fail(`\u68C0\u67E5\u72B6\u6001\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}g(to,"checkStatus");async function no(){let r=P("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let e=M();if(!e.running){r.fail("\u670D\u52A1\u672A\u5728\u8FD0\u884C");return}if(e.mode!=="daemon"){r.fail("\u670D\u52A1\u4E0D\u662F\u5728\u540E\u53F0\u6A21\u5F0F\u8FD0\u884C");return}r.succeed("\u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1..."),console.log(i.green(`\u5DF2\u8FDE\u63A5\u5230\u670D\u52A1 (PID: ${e.pid})`)),console.log(i.gray("\u6309 Ctrl+C \u53EF\u4EE5\u65AD\u5F00\u8FDE\u63A5\uFF08\u4E0D\u4F1A\u505C\u6B62\u670D\u52A1\uFF09")),console.log(i.gray("=".repeat(50)));let o=f.join(process.cwd(),"xiaozhi.log");if(C.existsSync(o))if(process.platform==="win32"){let{spawn:t}=await import("child_process"),n=t("powershell",["-Command",`Get-Content -Path "${o}" -Wait`],{stdio:"inherit"});process.on("SIGINT",()=>{console.log(i.yellow(`
|
|
39
39
|
\u65AD\u5F00\u8FDE\u63A5\uFF0C\u670D\u52A1\u7EE7\u7EED\u5728\u540E\u53F0\u8FD0\u884C`)),n.kill(),process.exit(0)}),n.on("exit",()=>{process.exit(0)})}else{let{spawn:t}=await import("child_process"),n=t("tail",["-f",o],{stdio:"inherit"});process.on("SIGINT",()=>{console.log(i.yellow(`
|
|
40
|
-
\u65AD\u5F00\u8FDE\u63A5\uFF0C\u670D\u52A1\u7EE7\u7EED\u5728\u540E\u53F0\u8FD0\u884C`)),n.kill(),process.exit(0)}),n.on("exit",()=>{process.exit(0)})}else console.log(i.yellow("\u65E5\u5FD7\u6587\u4EF6\u4E0D\u5B58\u5728"))}catch(e){r.fail(`\u8FDE\u63A5\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}g(
|
|
41
|
-
\u6B63\u5728\u505C\u6B62 MCP Server...`)),await n.stop(),process.exit(0)},"cleanup");process.on("SIGINT",s),process.on("SIGTERM",s),await n.start(),o.succeed("MCP Server \u5DF2\u542F\u52A8"),console.log(i.green(
|
|
40
|
+
\u65AD\u5F00\u8FDE\u63A5\uFF0C\u670D\u52A1\u7EE7\u7EED\u5728\u540E\u53F0\u8FD0\u884C`)),n.kill(),process.exit(0)}),n.on("exit",()=>{process.exit(0)})}else console.log(i.yellow("\u65E5\u5FD7\u6587\u4EF6\u4E0D\u5B58\u5728"))}catch(e){r.fail(`\u8FDE\u63A5\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}g(no,"attachService");async function ro(r=!1,e=!1){console.log(i.blue("\u{1F504} \u91CD\u542F\u670D\u52A1...")),await Pe(),await new Promise(o=>setTimeout(o,1e3)),await we(r,e)}g(ro,"restartService");async function so(r,e=!1){let o=P("\u542F\u52A8 MCP Server \u6A21\u5F0F...").start();try{if(!l.configExists()){o.fail("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728"),console.log(i.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E'));return}let{MCPServer:t}=await Promise.resolve().then(()=>(Ce(),ye));if(e){let n=j(import.meta.url),s=f.dirname(n),c=q("node",[f.join(s,"cli.js"),"start","--server",r.toString()],{detached:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd(),XIAOZHI_DAEMON:"true",MCP_SERVER_MODE:"true"}});Q(c.pid,"daemon");let a=f.join(process.cwd(),"xiaozhi-mcp-server.log"),m=C.createWriteStream(a,{flags:"a"});c.stdout?.pipe(m),c.stderr?.pipe(m),c.unref(),o.succeed(`MCP Server \u5DF2\u5728\u540E\u53F0\u542F\u52A8 (PID: ${c.pid}, Port: ${r})`),console.log(i.gray(`\u65E5\u5FD7\u6587\u4EF6: ${a}`))}else{let n=new t(r),s=g(async()=>{console.log(i.yellow(`
|
|
41
|
+
\u6B63\u5728\u505C\u6B62 MCP Server...`)),await n.stop(),process.exit(0)},"cleanup");process.on("SIGINT",s),process.on("SIGTERM",s),await n.start(),o.succeed("MCP Server \u5DF2\u542F\u52A8"),console.log(i.green("\u2705 MCP Server \u7AEF\u70B9\u5DF2\u542F\u52A8\uFF0C\u53EF\u901A\u8FC7\u4EE5\u4E0B\u5730\u5740\u8BBF\u95EE:")),console.log(i.green(` SSE endpoint: http://localhost:${r}/sse`)),console.log(i.green(` Messages endpoint: http://localhost:${r}/messages`)),console.log(i.green(` RPC endpoint: http://localhost:${r}/rpc`)),console.log(i.green(" \u7F51\u7EDC\u8BBF\u95EE: \u5C06 localhost \u66FF\u6362\u4E3A\u4F60\u7684IP\u5730\u5740")),console.log(i.yellow("\u{1F4A1} \u63D0\u793A: \u6309 Ctrl+C \u505C\u6B62\u670D\u52A1"))}}catch(t){o.fail(`\u542F\u52A8 MCP Server \u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}g(so,"startMCPServerMode");function io(){let r=ve();console.log(i.blue(`xiaozhi v${r}`)),console.log(i.gray("MCP Calculator Service CLI Tool")),console.log(i.gray("Built with Node.js and TypeScript")),console.log(i.gray(`Node.js: ${process.version}`)),console.log(i.gray(`Platform: ${process.platform} ${process.arch}`))}g(io,"showDetailedInfo");async function co(r="json"){let e=P("\u521D\u59CB\u5316\u914D\u7F6E...").start();try{if(l.configExists()){e.warn("\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728"),console.log(i.yellow("\u5982\u9700\u91CD\u65B0\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u5220\u9664\u73B0\u6709\u7684\u914D\u7F6E\u6587\u4EF6"));return}l.initConfig(r),e.succeed("\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u6210\u529F");let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),t=`xiaozhi.config.${r}`,n=f.join(o,t);console.log(i.green(`\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u521B\u5EFA: ${t}`)),console.log(i.yellow("\u{1F4DD} \u8BF7\u7F16\u8F91\u914D\u7F6E\u6587\u4EF6\u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9:")),console.log(i.gray(` \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84: ${n}`)),console.log(i.yellow("\u{1F4A1} \u6216\u8005\u4F7F\u7528\u547D\u4EE4\u8BBE\u7F6E:")),console.log(i.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)}`)}}g(co,"initConfig");function ao(){let r=f.dirname(j(import.meta.url)),o=[f.join(r,"..","templates"),f.join(r,"templates"),f.join(r,"..","..","templates")].find(t=>C.existsSync(t));return o?C.readdirSync(o).filter(t=>{let n=f.join(o,t);return C.statSync(n).isDirectory()}):[]}g(ao,"getAvailableTemplates");function Se(r,e){let o=r.length,t=e.length,n=Array(o+1).fill(null).map(()=>Array(t+1).fill(0));for(let c=0;c<=o;c++)n[c][0]=c;for(let c=0;c<=t;c++)n[0][c]=c;for(let c=1;c<=o;c++)for(let a=1;a<=t;a++)r[c-1]===e[a-1]?n[c][a]=n[c-1][a-1]:n[c][a]=Math.min(n[c-1][a]+1,n[c][a-1]+1,n[c-1][a-1]+1);let s=Math.max(o,t);return s===0?1:(s-n[o][t])/s}g(Se,"calculateSimilarity");function lo(r,e){if(e.length===0)return null;let o=e[0],t=Se(r.toLowerCase(),o.toLowerCase());for(let n of e.slice(1)){let s=Se(r.toLowerCase(),n.toLowerCase());s>t&&(t=s,o=n)}return t>.5?o:null}g(lo,"findSimilarTemplate");async function go(r){if(!process.stdin.isTTY)return console.log("n (\u975E\u4EA4\u4E92\u5F0F\u73AF\u5883)"),!1;let e=await import("readline");return new Promise(o=>{process.stdout.write(r);let t=e.createInterface({input:process.stdin,output:process.stdout}),n=g(s=>{let c=s.trim().toLowerCase();c==="y"||c==="yes"?(t.close(),o(!0)):c==="n"||c==="no"||c===""?(t.close(),o(!1)):process.stdout.write("\u8BF7\u8F93\u5165 y \u6216 n: ")},"handleInput");t.on("line",n),t.on("SIGINT",()=>{t.close(),o(!1)})})}g(go,"askUserConfirmation");function po(r){let e={mcpEndpoint:"<\u8BF7\u586B\u5199\u4F60\u7684\u63A5\u5165\u70B9\u5730\u5740\uFF08\u83B7\u53D6\u5730\u5740\u5728 xiaozhi.me\uFF09>",mcpServers:{}},o=f.join(r,"xiaozhi.config.json");C.writeFileSync(o,JSON.stringify(e,null,2),"utf8")}g(po,"createBasicConfig");async function fo(r,e){let o=P("\u521D\u59CB\u5316\u9879\u76EE...").start();try{let t=f.join(process.cwd(),r);if(C.existsSync(t)){o.fail(`\u76EE\u5F55 "${r}" \u5DF2\u5B58\u5728`),console.log(i.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u9009\u62E9\u4E0D\u540C\u7684\u9879\u76EE\u540D\u79F0\u6216\u5220\u9664\u73B0\u6709\u76EE\u5F55"));return}if(e.template){o.text="\u68C0\u67E5\u6A21\u677F...";let n=ao();if(n.length===0){o.fail("\u627E\u4E0D\u5230 templates \u76EE\u5F55"),console.log(i.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u786E\u4FDD xiaozhi-client \u6B63\u786E\u5B89\u88C5"));return}if(!n.includes(e.template)){o.fail(`\u6A21\u677F "${e.template}" \u4E0D\u5B58\u5728`);let y=lo(e.template,n);if(y)if(console.log(i.yellow(`\u{1F4A1} \u4F60\u662F\u60F3\u4F7F\u7528\u6A21\u677F "${y}" \u5417\uFF1F`)),await go(i.cyan("\u786E\u8BA4\u4F7F\u7528\u6B64\u6A21\u677F\uFF1F(y/n): ")))e.template=y;else{console.log(i.yellow("\u53EF\u7528\u7684\u6A21\u677F:"));for(let S of n)console.log(i.gray(` - ${S}`));return}else{console.log(i.yellow("\u53EF\u7528\u7684\u6A21\u677F:"));for(let b of n)console.log(i.gray(` - ${b}`));return}}let s=f.dirname(j(import.meta.url)),a=[f.join(s,"..","templates"),f.join(s,"templates"),f.join(s,"..","..","templates")].find(y=>C.existsSync(y)),m=f.join(a,e.template);o.text=`\u4ECE\u6A21\u677F "${e.template}" \u521B\u5EFA\u9879\u76EE "${r}"...`,Ie(m,t,["node_modules",".pnpm-debug.log","pnpm-lock.yaml"]);let u=f.join(t,"xiaozhi.log");C.existsSync(u)||C.writeFileSync(u,"","utf8"),o.succeed(`\u9879\u76EE "${r}" \u521B\u5EFA\u6210\u529F`),console.log(i.green("\u2705 \u9879\u76EE\u521B\u5EFA\u5B8C\u6210!")),console.log(i.yellow("\u{1F4DD} \u63A5\u4E0B\u6765\u7684\u6B65\u9AA4:")),console.log(i.gray(` cd ${r}`)),console.log(i.gray(" pnpm install # \u5B89\u88C5\u4F9D\u8D56")),console.log(i.gray(" # \u7F16\u8F91 xiaozhi.config.json \u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9")),console.log(i.gray(" xiaozhi start # \u542F\u52A8\u670D\u52A1"))}else{o.text=`\u521B\u5EFA\u57FA\u672C\u9879\u76EE "${r}"...`,C.mkdirSync(t,{recursive:!0}),po(t);let n=f.join(t,"xiaozhi.log");C.writeFileSync(n,"","utf8"),o.succeed(`\u9879\u76EE "${r}" \u521B\u5EFA\u6210\u529F`),console.log(i.green("\u2705 \u57FA\u672C\u9879\u76EE\u521B\u5EFA\u5B8C\u6210!")),console.log(i.yellow("\u{1F4DD} \u63A5\u4E0B\u6765\u7684\u6B65\u9AA4:")),console.log(i.gray(` cd ${r}`)),console.log(i.gray(" # \u7F16\u8F91 xiaozhi.config.json \u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9\u548C\u670D\u52A1")),console.log(i.gray(" xiaozhi start # \u542F\u52A8\u670D\u52A1")),console.log(i.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 --template \u9009\u9879\u53EF\u4EE5\u4ECE\u6A21\u677F\u521B\u5EFA\u9879\u76EE"))}}catch(t){o.fail(`\u521B\u5EFA\u9879\u76EE\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}g(fo,"createProject");function Ie(r,e,o=[]){C.existsSync(e)||C.mkdirSync(e,{recursive:!0});let t=C.readdirSync(r);for(let n of t){if(o.some(m=>n.includes(m)))continue;let s=f.join(r,n),c=f.join(e,n);C.statSync(s).isDirectory()?Ie(s,c,o):C.copyFileSync(s,c)}}g(Ie,"copyDirectory");async function mo(){let r=P("\u542F\u52A8 UI \u670D\u52A1...").start();try{if(!l.configExists()){r.fail("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728"),console.log(i.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E'));return}let e=new N;await e.start(),r.succeed("UI \u670D\u52A1\u5DF2\u542F\u52A8");let o=l.getWebUIPort();console.log(i.green("\u2705 \u914D\u7F6E\u7BA1\u7406\u7F51\u9875\u5DF2\u542F\u52A8\uFF0C\u53EF\u901A\u8FC7\u4EE5\u4E0B\u5730\u5740\u8BBF\u95EE:")),console.log(i.green(` \u672C\u5730\u8BBF\u95EE: http://localhost:${o}`)),console.log(i.green(` \u7F51\u7EDC\u8BBF\u95EE: http://<\u4F60\u7684IP\u5730\u5740>:${o}`)),console.log(i.yellow("\u{1F4A1} \u63D0\u793A: \u6309 Ctrl+C \u505C\u6B62\u670D\u52A1"));let{spawn:t}=await import("child_process"),n=`http://localhost:${o}`;try{let c;process.platform==="darwin"?c=t("open",[n],{detached:!0,stdio:"ignore"}):process.platform==="win32"?c=t("cmd",["/c","start",n],{detached:!0,stdio:"ignore"}):c=t("xdg-open",[n],{detached:!0,stdio:"ignore"}),c.on("error",()=>{console.log(i.gray(`\u{1F4A1} \u63D0\u793A: \u65E0\u6CD5\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u624B\u52A8\u8BBF\u95EE: ${n}`))}),c.unref()}catch{console.log(i.gray(`\u{1F4A1} \u63D0\u793A: \u65E0\u6CD5\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u624B\u52A8\u8BBF\u95EE: ${n}`))}let s=!1;process.on("SIGINT",async()=>{s&&(console.log(i.red(`
|
|
42
42
|
\u5F3A\u5236\u9000\u51FA...`)),process.exit(1)),s=!0,console.log(i.yellow(`
|
|
43
|
-
\u6B63\u5728\u505C\u6B62 UI \u670D\u52A1...`));try{await e.stop(),console.log(i.green("UI \u670D\u52A1\u5DF2\u505C\u6B62"))}catch{console.log(i.red("\u505C\u6B62\u670D\u52A1\u65F6\u51FA\u9519\uFF0C\u5F3A\u5236\u9000\u51FA"))}process.exit(0)}),process.on("SIGTERM",async()=>{s=!0,await e.stop(),process.exit(0)})}catch(e){r.fail(`\u542F\u52A8 UI \u670D\u52A1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}g(fo,"startUIService");async function mo(r,e){let o=P("\u66F4\u65B0\u914D\u7F6E...").start();try{if(!l.configExists()){o.fail("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728"),console.log(i.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E'));return}if(e)switch(r){case"mcpEndpoint":l.updateMcpEndpoint(e),o.succeed(`MCP \u7AEF\u70B9\u5DF2\u66F4\u65B0\u4E3A: ${e}`);break;case"heartbeatInterval":{let t=Number.parseInt(e,10);if(Number.isNaN(t)||t<=0){o.fail("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}l.setHeartbeatInterval(t),o.succeed(`\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}case"heartbeatTimeout":{let t=Number.parseInt(e,10);if(Number.isNaN(t)||t<=0){o.fail("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}l.setHeartbeatTimeout(t),o.succeed(`\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}case"reconnectInterval":{let t=Number.parseInt(e,10);if(Number.isNaN(t)||t<=0){o.fail("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}l.setReconnectInterval(t),o.succeed(`\u91CD\u8FDE\u95F4\u9694\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}default:o.fail(`\u914D\u7F6E\u9879 ${r} \u4E0D\u652F\u6301\u901A\u8FC7\u547D\u4EE4\u884C\u8BBE\u7F6E`),console.log(i.yellow("\u652F\u6301\u8BBE\u7F6E\u7684\u914D\u7F6E\u9879: mcpEndpoint, heartbeatInterval, heartbeatTimeout, reconnectInterval"));return}else{o.text="\u8BFB\u53D6\u914D\u7F6E...";let t=l.getConfig();switch(r){case"mcpEndpoint":{o.succeed("\u914D\u7F6E\u4FE1\u606F");let n=l.getMcpEndpoints();n.length===0?console.log(i.yellow("\u672A\u914D\u7F6E\u4EFB\u4F55 MCP \u7AEF\u70B9")):n.length===1?console.log(i.green(`MCP \u7AEF\u70B9: ${n[0]}`)):(console.log(i.green(`MCP \u7AEF\u70B9 (${n.length} \u4E2A):`)),n.forEach((s,c)=>{console.log(i.gray(` ${c+1}. ${s}`))}));break}case"mcpServers":o.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(i.green("MCP \u670D\u52A1:"));for(let[n,s]of Object.entries(t.mcpServers))"type"in s&&s.type==="sse"?console.log(i.gray(` ${n}: [SSE] ${s.url}`)):console.log(i.gray(` ${n}: ${s.command} ${s.args.join(" ")}`));break;case"connection":{o.succeed("\u914D\u7F6E\u4FE1\u606F");let n=l.getConnectionConfig();console.log(i.green("\u8FDE\u63A5\u914D\u7F6E:")),console.log(i.gray(` \u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694: ${n.heartbeatInterval}ms`)),console.log(i.gray(` \u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4: ${n.heartbeatTimeout}ms`)),console.log(i.gray(` \u91CD\u8FDE\u95F4\u9694: ${n.reconnectInterval}ms`));break}case"heartbeatInterval":o.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(i.green(`\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694: ${l.getHeartbeatInterval()}ms`));break;case"heartbeatTimeout":o.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(i.green(`\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4: ${l.getHeartbeatTimeout()}ms`));break;case"reconnectInterval":o.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(i.green(`\u91CD\u8FDE\u95F4\u9694: ${l.getReconnectInterval()}ms`));break;default:o.fail(`\u672A\u77E5\u7684\u914D\u7F6E\u9879: ${r}`),console.log(i.yellow("\u652F\u6301\u7684\u914D\u7F6E\u9879: mcpEndpoint, mcpServers, connection, heartbeatInterval, heartbeatTimeout, reconnectInterval"));return}}}catch(t){o.fail(`\u914D\u7F6E\u64CD\u4F5C\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}g(mo,"configCommand");function ho(){console.log(i.blue.bold("xiaozhi - MCP Calculator Service CLI")),console.log(),console.log(i.yellow("\u4F7F\u7528\u65B9\u6CD5:")),console.log(" xiaozhi <command> [options]"),console.log(),console.log(i.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] [--ui] [--server] \u542F\u52A8\u670D\u52A1 (--daemon \u540E\u53F0\u8FD0\u884C, --ui \u540C\u65F6\u542F\u52A8 Web UI, --server MCP Server \u6A21\u5F0F)"),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] [--ui] \u91CD\u542F\u670D\u52A1 (--daemon \u540E\u53F0\u8FD0\u884C, --ui \u540C\u65F6\u542F\u52A8 Web UI)"),console.log(" ui \u542F\u52A8\u914D\u7F6E\u7BA1\u7406\u7F51\u9875"),console.log(" completion \u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E"),console.log(),console.log(i.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(i.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(i.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(i.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 start --ui # \u542F\u52A8\u670D\u52A1\u5E76\u540C\u65F6\u542F\u52A8 Web UI"),console.log(" xiaozhi start -d -u # \u540E\u53F0\u542F\u52A8\u670D\u52A1\u5E76\u540C\u65F6\u542F\u52A8 Web UI"),console.log(" xiaozhi start --server # \u4EE5 MCP Server \u6A21\u5F0F\u542F\u52A8 (\u7AEF\u53E3 3000)"),console.log(" xiaozhi start -s 8080 # \u4EE5 MCP Server \u6A21\u5F0F\u542F\u52A8 (\u7AEF\u53E3 8080)"),console.log(" xiaozhi start -s -d # \u540E\u53F0\u8FD0\u884C MCP Server"),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(i.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(i.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(ho,"showHelp");v.name("xiaozhi").description("MCP Calculator Service CLI Tool").version(ve(),"-v, --version","\u663E\u793A\u7248\u672C\u4FE1\u606F").helpOption("-h, --help","\u663E\u793A\u5E2E\u52A9\u4FE1\u606F");v.command("create <projectName>").description("\u521B\u5EFA\u9879\u76EE").option("-t, --template <templateName>","\u4F7F\u7528\u6307\u5B9A\u6A21\u677F\u521B\u5EFA\u9879\u76EE").action(async(r,e)=>{await po(r,e)});v.command("init").description("\u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6").option("-f, --format <format>","\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F (json, json5, jsonc)","json").action(async r=>{let e=r.format;e!=="json"&&e!=="json5"&&e!=="jsonc"&&(console.error(i.red("\u9519\u8BEF: \u683C\u5F0F\u5FC5\u987B\u662F json, json5 \u6216 jsonc")),process.exit(1)),await io(e)});v.command("config <key> [value]").description("\u67E5\u770B\u6216\u8BBE\u7F6E\u914D\u7F6E").action(async(r,e)=>{await mo(r,e)});v.command("start").description("\u542F\u52A8\u670D\u52A1").option("-d, --daemon","\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").option("-u, --ui","\u540C\u65F6\u542F\u52A8 Web UI \u670D\u52A1").option("-s, --server [port]","\u4EE5 MCP Server \u6A21\u5F0F\u542F\u52A8 (\u53EF\u9009\u6307\u5B9A\u7AEF\u53E3\uFF0C\u9ED8\u8BA4 3000)").option("--stdio","\u4EE5 stdio \u6A21\u5F0F\u8FD0\u884C MCP Server (\u7528\u4E8E Cursor \u7B49\u5BA2\u6237\u7AEF)").action(async r=>{if(r.stdio){let{spawn:e}=await import("child_process"),o=j(import.meta.url),t=f.dirname(o),n=f.join(t,"mcpServerProxy.js");e("node",[n],{stdio:"inherit",env:{...process.env,XIAOZHI_CONFIG_DIR:process.env.XIAOZHI_CONFIG_DIR||process.cwd()}})}else if(r.server){let e=typeof r.server=="string"?Number.parseInt(r.server):3e3;await ro(e,r.daemon)}else await we(r.daemon,r.ui)});v.command("stop").description("\u505C\u6B62\u670D\u52A1").action(async()=>{await Pe()});v.command("status").description("\u68C0\u67E5\u670D\u52A1\u72B6\u6001").action(async()=>{await oo()});v.command("attach").description("\u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1\u67E5\u770B\u65E5\u5FD7").action(async()=>{await to()});v.command("restart").description("\u91CD\u542F\u670D\u52A1").option("-d, --daemon","\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").option("-u, --ui","\u540C\u65F6\u542F\u52A8 Web UI \u670D\u52A1").action(async r=>{await no(r.daemon,r.ui)});var oe=v.command("mcp").description("MCP \u670D\u52A1\u548C\u5DE5\u5177\u7BA1\u7406");oe.command("list").description("\u5217\u51FA MCP \u670D\u52A1").option("--tools","\u663E\u793A\u6240\u6709\u670D\u52A1\u7684\u5DE5\u5177\u5217\u8868").action(async r=>{await le(r)});oe.command("server <serverName>").description("\u7BA1\u7406\u6307\u5B9A\u7684 MCP \u670D\u52A1").action(async r=>{await ge(r)});oe.command("tool <serverName> <toolName> <action>").description("\u542F\u7528\u6216\u7981\u7528\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177").action(async(r,e,o)=>{o!=="enable"&&o!=="disable"&&(console.error(i.red("\u9519\u8BEF: \u64CD\u4F5C\u5FC5\u987B\u662F 'enable' \u6216 'disable'")),process.exit(1)),await pe(r,e,o==="enable")});var J=v.command("endpoint").description("\u7BA1\u7406 MCP \u7AEF\u70B9");J.command("list").description("\u5217\u51FA\u6240\u6709 MCP \u7AEF\u70B9").action(async()=>{let r=P("\u8BFB\u53D6\u7AEF\u70B9\u914D\u7F6E...").start();try{let e=l.getMcpEndpoints();r.succeed("\u7AEF\u70B9\u5217\u8868"),e.length===0?console.log(i.yellow("\u672A\u914D\u7F6E\u4EFB\u4F55 MCP \u7AEF\u70B9")):(console.log(i.green(`\u5171 ${e.length} \u4E2A\u7AEF\u70B9:`)),e.forEach((o,t)=>{console.log(i.gray(` ${t+1}. ${o}`))}))}catch(e){r.fail(`\u8BFB\u53D6\u7AEF\u70B9\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}});J.command("add <url>").description("\u6DFB\u52A0\u65B0\u7684 MCP \u7AEF\u70B9").action(async r=>{let e=P("\u6DFB\u52A0\u7AEF\u70B9...").start();try{l.addMcpEndpoint(r),e.succeed(`\u6210\u529F\u6DFB\u52A0\u7AEF\u70B9: ${r}`);let o=l.getMcpEndpoints();console.log(i.gray(`\u5F53\u524D\u5171 ${o.length} \u4E2A\u7AEF\u70B9`))}catch(o){e.fail(`\u6DFB\u52A0\u7AEF\u70B9\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}});J.command("remove <url>").description("\u79FB\u9664\u6307\u5B9A\u7684 MCP \u7AEF\u70B9").action(async r=>{let e=P("\u79FB\u9664\u7AEF\u70B9...").start();try{l.removeMcpEndpoint(r),e.succeed(`\u6210\u529F\u79FB\u9664\u7AEF\u70B9: ${r}`);let o=l.getMcpEndpoints();console.log(i.gray(`\u5F53\u524D\u5269\u4F59 ${o.length} \u4E2A\u7AEF\u70B9`))}catch(o){e.fail(`\u79FB\u9664\u7AEF\u70B9\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}});J.command("set <urls...>").description("\u8BBE\u7F6E MCP \u7AEF\u70B9\uFF08\u53EF\u4EE5\u662F\u5355\u4E2A\u6216\u591A\u4E2A\uFF09").action(async r=>{let e=P("\u8BBE\u7F6E\u7AEF\u70B9...").start();try{if(r.length===1)l.updateMcpEndpoint(r[0]),e.succeed(`\u6210\u529F\u8BBE\u7F6E\u7AEF\u70B9: ${r[0]}`);else{l.updateMcpEndpoint(r),e.succeed(`\u6210\u529F\u8BBE\u7F6E ${r.length} \u4E2A\u7AEF\u70B9`);for(let[o,t]of r.entries())console.log(i.gray(` ${o+1}. ${t}`))}}catch(o){e.fail(`\u8BBE\u7F6E\u7AEF\u70B9\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}});v.command("ui").description("\u542F\u52A8\u914D\u7F6E\u7BA1\u7406\u7F51\u9875").action(async()=>{await fo()});v.command("completion").description("\u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E").action(async()=>{se()});v.option("-V","\u663E\u793A\u8BE6\u7EC6\u4FE1\u606F").action(r=>{r.V&&(so(),process.exit(0))});re();process.argv.length<=2&&(ho(),process.exit(0));v.parse(process.argv);export{Se as calculateSimilarity,Qe as checkEnvironment,qe as formatUptime,M as getServiceStatus,ve as getVersion};
|
|
43
|
+
\u6B63\u5728\u505C\u6B62 UI \u670D\u52A1...`));try{await e.stop(),console.log(i.green("UI \u670D\u52A1\u5DF2\u505C\u6B62"))}catch{console.log(i.red("\u505C\u6B62\u670D\u52A1\u65F6\u51FA\u9519\uFF0C\u5F3A\u5236\u9000\u51FA"))}process.exit(0)}),process.on("SIGTERM",async()=>{s=!0,await e.stop(),process.exit(0)})}catch(e){r.fail(`\u542F\u52A8 UI \u670D\u52A1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}g(mo,"startUIService");async function ho(r,e){let o=P("\u66F4\u65B0\u914D\u7F6E...").start();try{if(!l.configExists()){o.fail("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728"),console.log(i.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E'));return}if(e)switch(r){case"mcpEndpoint":l.updateMcpEndpoint(e),o.succeed(`MCP \u7AEF\u70B9\u5DF2\u66F4\u65B0\u4E3A: ${e}`);break;case"heartbeatInterval":{let t=Number.parseInt(e,10);if(Number.isNaN(t)||t<=0){o.fail("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}l.setHeartbeatInterval(t),o.succeed(`\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}case"heartbeatTimeout":{let t=Number.parseInt(e,10);if(Number.isNaN(t)||t<=0){o.fail("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}l.setHeartbeatTimeout(t),o.succeed(`\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}case"reconnectInterval":{let t=Number.parseInt(e,10);if(Number.isNaN(t)||t<=0){o.fail("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}l.setReconnectInterval(t),o.succeed(`\u91CD\u8FDE\u95F4\u9694\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}default:o.fail(`\u914D\u7F6E\u9879 ${r} \u4E0D\u652F\u6301\u901A\u8FC7\u547D\u4EE4\u884C\u8BBE\u7F6E`),console.log(i.yellow("\u652F\u6301\u8BBE\u7F6E\u7684\u914D\u7F6E\u9879: mcpEndpoint, heartbeatInterval, heartbeatTimeout, reconnectInterval"));return}else{o.text="\u8BFB\u53D6\u914D\u7F6E...";let t=l.getConfig();switch(r){case"mcpEndpoint":{o.succeed("\u914D\u7F6E\u4FE1\u606F");let n=l.getMcpEndpoints();n.length===0?console.log(i.yellow("\u672A\u914D\u7F6E\u4EFB\u4F55 MCP \u7AEF\u70B9")):n.length===1?console.log(i.green(`MCP \u7AEF\u70B9: ${n[0]}`)):(console.log(i.green(`MCP \u7AEF\u70B9 (${n.length} \u4E2A):`)),n.forEach((s,c)=>{console.log(i.gray(` ${c+1}. ${s}`))}));break}case"mcpServers":o.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(i.green("MCP \u670D\u52A1:"));for(let[n,s]of Object.entries(t.mcpServers))"type"in s&&s.type==="sse"?console.log(i.gray(` ${n}: [SSE] ${s.url}`)):console.log(i.gray(` ${n}: ${s.command} ${s.args.join(" ")}`));break;case"connection":{o.succeed("\u914D\u7F6E\u4FE1\u606F");let n=l.getConnectionConfig();console.log(i.green("\u8FDE\u63A5\u914D\u7F6E:")),console.log(i.gray(` \u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694: ${n.heartbeatInterval}ms`)),console.log(i.gray(` \u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4: ${n.heartbeatTimeout}ms`)),console.log(i.gray(` \u91CD\u8FDE\u95F4\u9694: ${n.reconnectInterval}ms`));break}case"heartbeatInterval":o.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(i.green(`\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694: ${l.getHeartbeatInterval()}ms`));break;case"heartbeatTimeout":o.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(i.green(`\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4: ${l.getHeartbeatTimeout()}ms`));break;case"reconnectInterval":o.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(i.green(`\u91CD\u8FDE\u95F4\u9694: ${l.getReconnectInterval()}ms`));break;default:o.fail(`\u672A\u77E5\u7684\u914D\u7F6E\u9879: ${r}`),console.log(i.yellow("\u652F\u6301\u7684\u914D\u7F6E\u9879: mcpEndpoint, mcpServers, connection, heartbeatInterval, heartbeatTimeout, reconnectInterval"));return}}}catch(t){o.fail(`\u914D\u7F6E\u64CD\u4F5C\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}g(ho,"configCommand");function uo(){console.log(i.blue.bold("xiaozhi - MCP Calculator Service CLI")),console.log(),console.log(i.yellow("\u4F7F\u7528\u65B9\u6CD5:")),console.log(" xiaozhi <command> [options]"),console.log(),console.log(i.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] [--ui] [--server] \u542F\u52A8\u670D\u52A1 (--daemon \u540E\u53F0\u8FD0\u884C, --ui \u540C\u65F6\u542F\u52A8 Web UI, --server MCP Server \u6A21\u5F0F)"),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] [--ui] \u91CD\u542F\u670D\u52A1 (--daemon \u540E\u53F0\u8FD0\u884C, --ui \u540C\u65F6\u542F\u52A8 Web UI)"),console.log(" ui \u542F\u52A8\u914D\u7F6E\u7BA1\u7406\u7F51\u9875"),console.log(" completion \u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E"),console.log(),console.log(i.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(i.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(i.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(i.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 start --ui # \u542F\u52A8\u670D\u52A1\u5E76\u540C\u65F6\u542F\u52A8 Web UI"),console.log(" xiaozhi start -d -u # \u540E\u53F0\u542F\u52A8\u670D\u52A1\u5E76\u540C\u65F6\u542F\u52A8 Web UI"),console.log(" xiaozhi start --server # \u4EE5 MCP Server \u6A21\u5F0F\u542F\u52A8 (\u7AEF\u53E3 3000)"),console.log(" xiaozhi start -s 8080 # \u4EE5 MCP Server \u6A21\u5F0F\u542F\u52A8 (\u7AEF\u53E3 8080)"),console.log(" xiaozhi start -s -d # \u540E\u53F0\u8FD0\u884C MCP Server"),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(i.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(i.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(uo,"showHelp");v.name("xiaozhi").description("MCP Calculator Service CLI Tool").version(ve(),"-v, --version","\u663E\u793A\u7248\u672C\u4FE1\u606F").helpOption("-h, --help","\u663E\u793A\u5E2E\u52A9\u4FE1\u606F");v.command("create <projectName>").description("\u521B\u5EFA\u9879\u76EE").option("-t, --template <templateName>","\u4F7F\u7528\u6307\u5B9A\u6A21\u677F\u521B\u5EFA\u9879\u76EE").action(async(r,e)=>{await fo(r,e)});v.command("init").description("\u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6").option("-f, --format <format>","\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F (json, json5, jsonc)","json").action(async r=>{let e=r.format;e!=="json"&&e!=="json5"&&e!=="jsonc"&&(console.error(i.red("\u9519\u8BEF: \u683C\u5F0F\u5FC5\u987B\u662F json, json5 \u6216 jsonc")),process.exit(1)),await co(e)});v.command("config <key> [value]").description("\u67E5\u770B\u6216\u8BBE\u7F6E\u914D\u7F6E").action(async(r,e)=>{await ho(r,e)});v.command("start").description("\u542F\u52A8\u670D\u52A1").option("-d, --daemon","\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").option("-u, --ui","\u540C\u65F6\u542F\u52A8 Web UI \u670D\u52A1").option("-s, --server [port]","\u4EE5 MCP Server \u6A21\u5F0F\u542F\u52A8 (\u53EF\u9009\u6307\u5B9A\u7AEF\u53E3\uFF0C\u9ED8\u8BA4 3000)").option("--stdio","\u4EE5 stdio \u6A21\u5F0F\u8FD0\u884C MCP Server (\u7528\u4E8E Cursor \u7B49\u5BA2\u6237\u7AEF)").action(async r=>{if(r.stdio){let{spawn:e}=await import("child_process"),o=j(import.meta.url),t=f.dirname(o),n=f.join(t,"mcpServerProxy.js");e("node",[n],{stdio:"inherit",env:{...process.env,XIAOZHI_CONFIG_DIR:process.env.XIAOZHI_CONFIG_DIR||process.cwd()}})}else if(r.server){let e=typeof r.server=="string"?Number.parseInt(r.server):3e3;await so(e,r.daemon)}else await we(r.daemon,r.ui)});v.command("stop").description("\u505C\u6B62\u670D\u52A1").action(async()=>{await Pe()});v.command("status").description("\u68C0\u67E5\u670D\u52A1\u72B6\u6001").action(async()=>{await to()});v.command("attach").description("\u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1\u67E5\u770B\u65E5\u5FD7").action(async()=>{await no()});v.command("restart").description("\u91CD\u542F\u670D\u52A1").option("-d, --daemon","\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").option("-u, --ui","\u540C\u65F6\u542F\u52A8 Web UI \u670D\u52A1").action(async r=>{await ro(r.daemon,r.ui)});var oe=v.command("mcp").description("MCP \u670D\u52A1\u548C\u5DE5\u5177\u7BA1\u7406");oe.command("list").description("\u5217\u51FA MCP \u670D\u52A1").option("--tools","\u663E\u793A\u6240\u6709\u670D\u52A1\u7684\u5DE5\u5177\u5217\u8868").action(async r=>{await le(r)});oe.command("server <serverName>").description("\u7BA1\u7406\u6307\u5B9A\u7684 MCP \u670D\u52A1").action(async r=>{await ge(r)});oe.command("tool <serverName> <toolName> <action>").description("\u542F\u7528\u6216\u7981\u7528\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177").action(async(r,e,o)=>{o!=="enable"&&o!=="disable"&&(console.error(i.red("\u9519\u8BEF: \u64CD\u4F5C\u5FC5\u987B\u662F 'enable' \u6216 'disable'")),process.exit(1)),await pe(r,e,o==="enable")});var J=v.command("endpoint").description("\u7BA1\u7406 MCP \u7AEF\u70B9");J.command("list").description("\u5217\u51FA\u6240\u6709 MCP \u7AEF\u70B9").action(async()=>{let r=P("\u8BFB\u53D6\u7AEF\u70B9\u914D\u7F6E...").start();try{let e=l.getMcpEndpoints();r.succeed("\u7AEF\u70B9\u5217\u8868"),e.length===0?console.log(i.yellow("\u672A\u914D\u7F6E\u4EFB\u4F55 MCP \u7AEF\u70B9")):(console.log(i.green(`\u5171 ${e.length} \u4E2A\u7AEF\u70B9:`)),e.forEach((o,t)=>{console.log(i.gray(` ${t+1}. ${o}`))}))}catch(e){r.fail(`\u8BFB\u53D6\u7AEF\u70B9\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}});J.command("add <url>").description("\u6DFB\u52A0\u65B0\u7684 MCP \u7AEF\u70B9").action(async r=>{let e=P("\u6DFB\u52A0\u7AEF\u70B9...").start();try{l.addMcpEndpoint(r),e.succeed(`\u6210\u529F\u6DFB\u52A0\u7AEF\u70B9: ${r}`);let o=l.getMcpEndpoints();console.log(i.gray(`\u5F53\u524D\u5171 ${o.length} \u4E2A\u7AEF\u70B9`))}catch(o){e.fail(`\u6DFB\u52A0\u7AEF\u70B9\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}});J.command("remove <url>").description("\u79FB\u9664\u6307\u5B9A\u7684 MCP \u7AEF\u70B9").action(async r=>{let e=P("\u79FB\u9664\u7AEF\u70B9...").start();try{l.removeMcpEndpoint(r),e.succeed(`\u6210\u529F\u79FB\u9664\u7AEF\u70B9: ${r}`);let o=l.getMcpEndpoints();console.log(i.gray(`\u5F53\u524D\u5269\u4F59 ${o.length} \u4E2A\u7AEF\u70B9`))}catch(o){e.fail(`\u79FB\u9664\u7AEF\u70B9\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}});J.command("set <urls...>").description("\u8BBE\u7F6E MCP \u7AEF\u70B9\uFF08\u53EF\u4EE5\u662F\u5355\u4E2A\u6216\u591A\u4E2A\uFF09").action(async r=>{let e=P("\u8BBE\u7F6E\u7AEF\u70B9...").start();try{if(r.length===1)l.updateMcpEndpoint(r[0]),e.succeed(`\u6210\u529F\u8BBE\u7F6E\u7AEF\u70B9: ${r[0]}`);else{l.updateMcpEndpoint(r),e.succeed(`\u6210\u529F\u8BBE\u7F6E ${r.length} \u4E2A\u7AEF\u70B9`);for(let[o,t]of r.entries())console.log(i.gray(` ${o+1}. ${t}`))}}catch(o){e.fail(`\u8BBE\u7F6E\u7AEF\u70B9\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}});v.command("ui").description("\u542F\u52A8\u914D\u7F6E\u7BA1\u7406\u7F51\u9875").action(async()=>{await mo()});v.command("completion").description("\u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E").action(async()=>{se()});v.option("-V","\u663E\u793A\u8BE6\u7EC6\u4FE1\u606F").action(r=>{r.V&&(io(),process.exit(0))});re();process.argv.length<=2&&(uo(),process.exit(0));v.parse(process.argv);export{Se as calculateSimilarity,eo as checkEnvironment,Qe as formatUptime,M as getServiceStatus,ve as getVersion};
|
|
44
44
|
//# sourceMappingURL=cli.js.map
|