xiaozhi-client 1.4.0-beta.2 → 1.4.0-beta.4

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.
@@ -1,2 +1,2 @@
1
- var S=Object.defineProperty;var l=(r,o)=>S(r,"name",{value:o,configurable:!0});import I from"omelette";import{copyFileSync as w,existsSync as d,readFileSync as E,writeFileSync as M}from"fs";import{dirname as x,resolve as v}from"path";import{fileURLToPath as P}from"url";var y=x(P(import.meta.url)),u={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},m=class r{static{l(this,"ConfigManager")}static instance;defaultConfigPath;config=null;constructor(){this.defaultConfigPath=v(y,"xiaozhi.config.default.json")}getConfigFilePath(){let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return v(o,"xiaozhi.config.json")}static getInstance(){return r.instance||(r.instance=new r),r.instance}configExists(){let o=this.getConfigFilePath();return d(o)}initConfig(){if(!d(this.defaultConfigPath))throw new Error("\u9ED8\u8BA4\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.default.json \u4E0D\u5B58\u5728");if(this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.json \u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u521D\u59CB\u5316");let o=this.getConfigFilePath();w(this.defaultConfigPath,o),this.config=null}loadConfig(){if(!this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.json \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u8FD0\u884C xiaozhi init \u521D\u59CB\u5316\u914D\u7F6E");try{let o=this.getConfigFilePath(),e=E(o,"utf8"),i=JSON.parse(e);return this.validateConfig(i),i}catch(o){throw o instanceof SyntaxError?new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF: ${o.message}`):o}}validateConfig(o){if(!o||typeof o!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A\u6839\u5BF9\u8C61\u65E0\u6548");let e=o;if(!e.mcpEndpoint||typeof e.mcpEndpoint!="string")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5B57\u6BB5\u65E0\u6548");if(!e.mcpServers||typeof e.mcpServers!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers \u5B57\u6BB5\u65E0\u6548");for(let[i,n]of Object.entries(e.mcpServers)){if(!n||typeof n!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${i} \u65E0\u6548`);let t=n;if(t.type==="sse"){if(!t.url||typeof t.url!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${i}.url \u65E0\u6548`)}else{if(!t.command||typeof t.command!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${i}.command \u65E0\u6548`);if(!Array.isArray(t.args))throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${i}.args \u5FC5\u987B\u662F\u6570\u7EC4`);if(t.env&&typeof t.env!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${i}.env \u5FC5\u987B\u662F\u5BF9\u8C61`)}}}getConfig(){return this.config||(this.config=this.loadConfig()),JSON.parse(JSON.stringify(this.config))}getMcpEndpoint(){return this.getConfig().mcpEndpoint}getMcpServers(){return this.getConfig().mcpServers}getMcpServerConfig(){return this.getConfig().mcpServerConfig||{}}getServerToolsConfig(o){return this.getMcpServerConfig()[o]?.tools||{}}isToolEnabled(o,e){return this.getServerToolsConfig(o)[e]?.enable!==!1}updateMcpEndpoint(o){if(!o||typeof o!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let i={...this.getConfig(),mcpEndpoint:o};this.saveConfig(i)}updateMcpServer(o,e){if(!o||typeof o!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if("type"in e&&e.type==="sse"){if(!e.url||typeof e.url!="string")throw new Error("SSE \u670D\u52A1\u914D\u7F6E\u7684 url \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else{let t=e;if(!t.command||typeof t.command!="string")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 command \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!Array.isArray(t.args))throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 args \u5B57\u6BB5\u5FC5\u987B\u662F\u6570\u7EC4");if(t.env&&typeof t.env!="object")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 env \u5B57\u6BB5\u5FC5\u987B\u662F\u5BF9\u8C61")}let i=this.getConfig(),n={...i,mcpServers:{...i.mcpServers,[o]:e}};this.saveConfig(n)}removeMcpServer(o){if(!o||typeof o!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let e=this.getConfig();if(!e.mcpServers[o])throw new Error(`\u670D\u52A1 ${o} \u4E0D\u5B58\u5728`);let i={...e.mcpServers};delete i[o];let n={...e,mcpServers:i};this.saveConfig(n)}updateServerToolsConfig(o,e){let n={...this.getConfig()};n.mcpServerConfig||(n.mcpServerConfig={}),n.mcpServerConfig[o]={tools:e},this.saveConfig(n)}setToolEnabled(o,e,i,n){let f={...this.getConfig()};f.mcpServerConfig||(f.mcpServerConfig={}),f.mcpServerConfig[o]||(f.mcpServerConfig[o]={tools:{}}),f.mcpServerConfig[o].tools[e]={enable:i,...n&&{description:n}},this.saveConfig(f)}saveConfig(o){try{this.validateConfig(o);let e=this.getConfigFilePath(),i=JSON.stringify(o,null,2);M(e,i,"utf8"),this.config=o}catch(e){throw new Error(`\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}reloadConfig(){this.config=null}getConfigPath(){return this.getConfigFilePath()}getDefaultConfigPath(){return this.defaultConfigPath}getConnectionConfig(){let e=this.getConfig().connection||{};return{heartbeatInterval:e.heartbeatInterval??u.heartbeatInterval,heartbeatTimeout:e.heartbeatTimeout??u.heartbeatTimeout,reconnectInterval:e.reconnectInterval??u.reconnectInterval}}getHeartbeatInterval(){return this.getConnectionConfig().heartbeatInterval}getHeartbeatTimeout(){return this.getConnectionConfig().heartbeatTimeout}getReconnectInterval(){return this.getConnectionConfig().reconnectInterval}updateConnectionConfig(o){let e=this.getConfig(),n={...e.connection||{},...o},t={...e,connection:n};this.saveConfig(t)}setHeartbeatInterval(o){if(o<=0)throw new Error("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatInterval:o})}setHeartbeatTimeout(o){if(o<=0)throw new Error("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatTimeout:o})}setReconnectInterval(o){if(o<=0)throw new Error("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({reconnectInterval:o})}getModelScopeConfig(){return this.getConfig().modelscope||{}}getModelScopeApiKey(){return this.getModelScopeConfig().apiKey||process.env.MODELSCOPE_API_TOKEN}updateModelScopeConfig(o){let e=this.getConfig(),n={...e.modelscope||{},...o},t={...e,modelscope:n};this.saveConfig(t)}setModelScopeApiKey(o){if(!o||typeof o!="string")throw new Error("API Key \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");this.updateModelScopeConfig({apiKey:o})}},h=m.getInstance();function T(){try{if(!h.configExists())return[];let r=h.getMcpServers();return Object.keys(r)}catch{return[]}}l(T,"getMcpServerNames");function z(r){try{if(!h.configExists())return[];let o=h.getServerToolsConfig(r);return Object.keys(o)}catch{return[]}}l(z,"getServerToolNames");function D(){let r=I("xiaozhi <command>");if(r.on("command",({reply:o})=>{o(["create","init","config","start","stop","status","attach","restart","mcp","completion"])}),r.on("complete",(o,{line:e,before:i,reply:n})=>{process.env.XIAOZHI_DEBUG_COMPLETION&&console.error(`Debug completion - line: "${e}", before: "${i}", fragment: "${o}"`);let t=e.trim().split(/\s+/),p=e!==e.trim()?t.length:t.length-1;if(t[1]==="mcp"){let C=t[2];if(p===2){let c=["list","server","tool"],s=t[2]||"",g=c.filter(a=>a.startsWith(s));n(g);return}if(p===3){switch(C){case"list":{let c=["--tools"],s=t[3]||"",g=c.filter(a=>a.startsWith(s));n(g);break}case"server":case"tool":{let c=T(),s=t[3]||"",g=c.filter(a=>a.startsWith(s));n(g);break}default:n([])}return}if(p===4&&C==="tool"){let c=t[3],s=z(c),g=t[4]||"",a=s.filter(b=>b.startsWith(g));n(a);return}if(p===5&&C==="tool"){let c=["enable","disable"],s=t[5]||"",g=c.filter(a=>a.startsWith(s));n(g);return}}if(p===2){switch(t[1]){case"create":n(["--template","-t"]);break;case"start":case"restart":n(["--daemon","-d"]);break;case"completion":n(["install","uninstall"]);break;default:n([])}return}n([])}),process.argv.includes("--completion")){try{console.log(r.setupShellInitFile())}catch(o){console.error("\u751F\u6210\u81EA\u52A8\u8865\u5168\u811A\u672C\u65F6\u51FA\u9519:",o)}process.exit(0)}process.argv.includes("--completion-fish")&&(console.log(r.setupShellInitFile("fish")),process.exit(0)),process.argv.includes("--compzsh")||process.argv.includes("--compbash"),r.init()}l(D,"setupAutoCompletion");function _(){console.log("\u{1F680} xiaozhi \u81EA\u52A8\u8865\u5168\u8BBE\u7F6E"),console.log(),console.log("\u8981\u542F\u7528\u81EA\u52A8\u8865\u5168\uFF0C\u8BF7\u6839\u636E\u4F60\u7684shell\u6267\u884C\u4EE5\u4E0B\u547D\u4EE4\uFF1A"),console.log(),console.log("\u{1F4DD} Zsh (\u63A8\u8350):"),console.log(" xiaozhi --completion >> ~/.xiaozhi-completion.zsh"),console.log(" echo 'source ~/.xiaozhi-completion.zsh' >> ~/.zshrc"),console.log(" source ~/.zshrc"),console.log(),console.log("\u{1F4DD} Bash:"),console.log(" xiaozhi --completion >> ~/.xiaozhi-completion.bash"),console.log(" echo 'source ~/.xiaozhi-completion.bash' >> ~/.bash_profile"),console.log(" source ~/.bash_profile"),console.log(),console.log("\u{1F4DD} Fish:"),console.log(" xiaozhi --completion-fish >> ~/.config/fish/completions/xiaozhi.fish"),console.log(),console.log("\u2728 \u8BBE\u7F6E\u5B8C\u6210\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u4F7F\u7528 Tab \u952E\u8FDB\u884C\u81EA\u52A8\u8865\u5168\u4E86\uFF01"),console.log(),console.log("\u{1F4A1} \u793A\u4F8B:"),console.log(" xiaozhi m<Tab> # \u2192 mcp"),console.log(" xiaozhi mcp l<Tab> # \u2192 list"),console.log(" xiaozhi mcp tool <Tab> # \u2192 \u663E\u793A\u6240\u6709\u670D\u52A1\u5668\u540D\u79F0")}l(_,"showCompletionHelp");export{D as setupAutoCompletion,_ as showCompletionHelp};
1
+ var S=Object.defineProperty;var l=(r,o)=>S(r,"name",{value:o,configurable:!0});import y from"omelette";import{copyFileSync as w,existsSync as b,readFileSync as I,writeFileSync as E}from"fs";import{dirname as M,resolve as d}from"path";import{fileURLToPath as P}from"url";var x=M(P(import.meta.url)),u={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},m=class r{static{l(this,"ConfigManager")}static instance;defaultConfigPath;config=null;constructor(){this.defaultConfigPath=d(x,"xiaozhi.config.default.json")}getConfigFilePath(){let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return d(o,"xiaozhi.config.json")}static getInstance(){return r.instance||(r.instance=new r),r.instance}configExists(){let o=this.getConfigFilePath();return b(o)}initConfig(){if(!b(this.defaultConfigPath))throw new Error("\u9ED8\u8BA4\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.default.json \u4E0D\u5B58\u5728");if(this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.json \u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u521D\u59CB\u5316");let o=this.getConfigFilePath();w(this.defaultConfigPath,o),this.config=null}loadConfig(){if(!this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.json \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u8FD0\u884C xiaozhi init \u521D\u59CB\u5316\u914D\u7F6E");try{let o=this.getConfigFilePath(),e=I(o,"utf8"),i=JSON.parse(e);return this.validateConfig(i),i}catch(o){throw o instanceof SyntaxError?new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF: ${o.message}`):o}}validateConfig(o){if(!o||typeof o!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A\u6839\u5BF9\u8C61\u65E0\u6548");let e=o;if(!e.mcpEndpoint||typeof e.mcpEndpoint!="string")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5B57\u6BB5\u65E0\u6548");if(!e.mcpServers||typeof e.mcpServers!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers \u5B57\u6BB5\u65E0\u6548");for(let[i,n]of Object.entries(e.mcpServers)){if(!n||typeof n!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${i} \u65E0\u6548`);let t=n;if(t.type==="sse"){if(!t.url||typeof t.url!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${i}.url \u65E0\u6548`)}else{if(!t.command||typeof t.command!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${i}.command \u65E0\u6548`);if(!Array.isArray(t.args))throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${i}.args \u5FC5\u987B\u662F\u6570\u7EC4`);if(t.env&&typeof t.env!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${i}.env \u5FC5\u987B\u662F\u5BF9\u8C61`)}}}getConfig(){return this.config||(this.config=this.loadConfig()),JSON.parse(JSON.stringify(this.config))}getMcpEndpoint(){return this.getConfig().mcpEndpoint}getMcpServers(){return this.getConfig().mcpServers}getMcpServerConfig(){return this.getConfig().mcpServerConfig||{}}getServerToolsConfig(o){return this.getMcpServerConfig()[o]?.tools||{}}isToolEnabled(o,e){return this.getServerToolsConfig(o)[e]?.enable!==!1}updateMcpEndpoint(o){if(!o||typeof o!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let i={...this.getConfig(),mcpEndpoint:o};this.saveConfig(i)}updateMcpServer(o,e){if(!o||typeof o!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if("type"in e&&e.type==="sse"){if(!e.url||typeof e.url!="string")throw new Error("SSE \u670D\u52A1\u914D\u7F6E\u7684 url \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else{let t=e;if(!t.command||typeof t.command!="string")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 command \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!Array.isArray(t.args))throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 args \u5B57\u6BB5\u5FC5\u987B\u662F\u6570\u7EC4");if(t.env&&typeof t.env!="object")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 env \u5B57\u6BB5\u5FC5\u987B\u662F\u5BF9\u8C61")}let i=this.getConfig(),n={...i,mcpServers:{...i.mcpServers,[o]:e}};this.saveConfig(n)}removeMcpServer(o){if(!o||typeof o!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let e=this.getConfig();if(!e.mcpServers[o])throw new Error(`\u670D\u52A1 ${o} \u4E0D\u5B58\u5728`);let i={...e.mcpServers};delete i[o];let n={...e,mcpServers:i};this.saveConfig(n)}updateServerToolsConfig(o,e){let n={...this.getConfig()};n.mcpServerConfig||(n.mcpServerConfig={}),n.mcpServerConfig[o]={tools:e},this.saveConfig(n)}setToolEnabled(o,e,i,n){let a={...this.getConfig()};a.mcpServerConfig||(a.mcpServerConfig={}),a.mcpServerConfig[o]||(a.mcpServerConfig[o]={tools:{}}),a.mcpServerConfig[o].tools[e]={enable:i,...n&&{description:n}},this.saveConfig(a)}saveConfig(o){try{this.validateConfig(o);let e=this.getConfigFilePath(),i=JSON.stringify(o,null,2);E(e,i,"utf8"),this.config=o}catch(e){throw new Error(`\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}reloadConfig(){this.config=null}getConfigPath(){return this.getConfigFilePath()}getDefaultConfigPath(){return this.defaultConfigPath}getConnectionConfig(){let e=this.getConfig().connection||{};return{heartbeatInterval:e.heartbeatInterval??u.heartbeatInterval,heartbeatTimeout:e.heartbeatTimeout??u.heartbeatTimeout,reconnectInterval:e.reconnectInterval??u.reconnectInterval}}getHeartbeatInterval(){return this.getConnectionConfig().heartbeatInterval}getHeartbeatTimeout(){return this.getConnectionConfig().heartbeatTimeout}getReconnectInterval(){return this.getConnectionConfig().reconnectInterval}updateConnectionConfig(o){let e=this.getConfig(),n={...e.connection||{},...o},t={...e,connection:n};this.saveConfig(t)}setHeartbeatInterval(o){if(o<=0)throw new Error("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatInterval:o})}setHeartbeatTimeout(o){if(o<=0)throw new Error("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatTimeout:o})}setReconnectInterval(o){if(o<=0)throw new Error("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({reconnectInterval:o})}getModelScopeConfig(){return this.getConfig().modelscope||{}}getModelScopeApiKey(){return this.getModelScopeConfig().apiKey||process.env.MODELSCOPE_API_TOKEN}updateModelScopeConfig(o){let e=this.getConfig(),n={...e.modelscope||{},...o},t={...e,modelscope:n};this.saveConfig(t)}setModelScopeApiKey(o){if(!o||typeof o!="string")throw new Error("API Key \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");this.updateModelScopeConfig({apiKey:o})}getWebUIConfig(){return this.getConfig().webUI||{}}getWebUIPort(){return this.getWebUIConfig().port??9999}updateWebUIConfig(o){let e=this.getConfig(),n={...e.webUI||{},...o},t={...e,webUI:n};this.saveConfig(t)}setWebUIPort(o){if(!Number.isInteger(o)||o<=0||o>65535)throw new Error("\u7AEF\u53E3\u53F7\u5FC5\u987B\u662F 1-65535 \u4E4B\u95F4\u7684\u6574\u6570");this.updateWebUIConfig({port:o})}},C=m.getInstance();function T(){try{if(!C.configExists())return[];let r=C.getMcpServers();return Object.keys(r)}catch{return[]}}l(T,"getMcpServerNames");function z(r){try{if(!C.configExists())return[];let o=C.getServerToolsConfig(r);return Object.keys(o)}catch{return[]}}l(z,"getServerToolNames");function $(){let r=y("xiaozhi <command>");if(r.on("command",({reply:o})=>{o(["create","init","config","start","stop","status","attach","restart","mcp","completion"])}),r.on("complete",(o,{line:e,before:i,reply:n})=>{process.env.XIAOZHI_DEBUG_COMPLETION&&console.error(`Debug completion - line: "${e}", before: "${i}", fragment: "${o}"`);let t=e.trim().split(/\s+/),p=e!==e.trim()?t.length:t.length-1;if(t[1]==="mcp"){let h=t[2];if(p===2){let c=["list","server","tool"],s=t[2]||"",g=c.filter(f=>f.startsWith(s));n(g);return}if(p===3){switch(h){case"list":{let c=["--tools"],s=t[3]||"",g=c.filter(f=>f.startsWith(s));n(g);break}case"server":case"tool":{let c=T(),s=t[3]||"",g=c.filter(f=>f.startsWith(s));n(g);break}default:n([])}return}if(p===4&&h==="tool"){let c=t[3],s=z(c),g=t[4]||"",f=s.filter(v=>v.startsWith(g));n(f);return}if(p===5&&h==="tool"){let c=["enable","disable"],s=t[5]||"",g=c.filter(f=>f.startsWith(s));n(g);return}}if(p===2){switch(t[1]){case"create":n(["--template","-t"]);break;case"start":case"restart":n(["--daemon","-d"]);break;case"completion":n(["install","uninstall"]);break;default:n([])}return}n([])}),process.argv.includes("--completion")){try{console.log(r.setupShellInitFile())}catch(o){console.error("\u751F\u6210\u81EA\u52A8\u8865\u5168\u811A\u672C\u65F6\u51FA\u9519:",o)}process.exit(0)}process.argv.includes("--completion-fish")&&(console.log(r.setupShellInitFile("fish")),process.exit(0)),process.argv.includes("--compzsh")||process.argv.includes("--compbash"),r.init()}l($,"setupAutoCompletion");function N(){console.log("\u{1F680} xiaozhi \u81EA\u52A8\u8865\u5168\u8BBE\u7F6E"),console.log(),console.log("\u8981\u542F\u7528\u81EA\u52A8\u8865\u5168\uFF0C\u8BF7\u6839\u636E\u4F60\u7684shell\u6267\u884C\u4EE5\u4E0B\u547D\u4EE4\uFF1A"),console.log(),console.log("\u{1F4DD} Zsh (\u63A8\u8350):"),console.log(" xiaozhi --completion >> ~/.xiaozhi-completion.zsh"),console.log(" echo 'source ~/.xiaozhi-completion.zsh' >> ~/.zshrc"),console.log(" source ~/.zshrc"),console.log(),console.log("\u{1F4DD} Bash:"),console.log(" xiaozhi --completion >> ~/.xiaozhi-completion.bash"),console.log(" echo 'source ~/.xiaozhi-completion.bash' >> ~/.bash_profile"),console.log(" source ~/.bash_profile"),console.log(),console.log("\u{1F4DD} Fish:"),console.log(" xiaozhi --completion-fish >> ~/.config/fish/completions/xiaozhi.fish"),console.log(),console.log("\u2728 \u8BBE\u7F6E\u5B8C\u6210\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u4F7F\u7528 Tab \u952E\u8FDB\u884C\u81EA\u52A8\u8865\u5168\u4E86\uFF01"),console.log(),console.log("\u{1F4A1} \u793A\u4F8B:"),console.log(" xiaozhi m<Tab> # \u2192 mcp"),console.log(" xiaozhi mcp l<Tab> # \u2192 list"),console.log(" xiaozhi mcp tool <Tab> # \u2192 \u663E\u793A\u6240\u6709\u670D\u52A1\u5668\u540D\u79F0")}l(N,"showCompletionHelp");export{$ as setupAutoCompletion,N as showCompletionHelp};
2
2
  //# sourceMappingURL=autoCompletion.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/autoCompletion.ts","../src/configManager.ts"],"sourcesContent":["import omelette from \"omelette\";\nimport { configManager } from \"./configManager\";\n\n/**\n * 自动补全功能模块\n */\n\n/**\n * 获取所有可用的MCP服务器名称\n */\nfunction getMcpServerNames(): string[] {\n try {\n if (!configManager.configExists()) {\n return [];\n }\n const mcpServers = configManager.getMcpServers();\n return Object.keys(mcpServers);\n } catch (error) {\n return [];\n }\n}\n\n/**\n * 获取指定服务器的工具名称\n */\nfunction getServerToolNames(serverName: string): string[] {\n try {\n if (!configManager.configExists()) {\n return [];\n }\n const toolsConfig = configManager.getServerToolsConfig(serverName);\n return Object.keys(toolsConfig);\n } catch (error) {\n return [];\n }\n}\n\n/**\n * 设置自动补全功能\n */\nexport function setupAutoCompletion(): void {\n // 创建 omelette 实例,使用简单的模板\n const completion = omelette(\"xiaozhi <command>\");\n\n // 处理主命令补全\n completion.on(\"command\", ({ reply }) => {\n reply([\n \"create\",\n \"init\",\n \"config\",\n \"start\",\n \"stop\",\n \"status\",\n \"attach\",\n \"restart\",\n \"mcp\",\n \"completion\",\n ]);\n });\n\n // 处理复杂的多级命令补全\n completion.on(\"complete\", (fragment, { line, before, reply }) => {\n // 调试信息\n if (process.env.XIAOZHI_DEBUG_COMPLETION) {\n console.error(\n `Debug completion - line: \"${line}\", before: \"${before}\", fragment: \"${fragment}\"`\n );\n }\n\n const parts = line.trim().split(/\\s+/);\n const endsWithSpace = line !== line.trim();\n const currentIndex = endsWithSpace ? parts.length : parts.length - 1;\n\n // MCP 相关的补全\n if (parts[1] === \"mcp\") {\n const subcommand = parts[2];\n\n if (currentIndex === 2) {\n // mcp 子命令\n const subcommands = [\"list\", \"server\", \"tool\"];\n const current = parts[2] || \"\";\n const matches = subcommands.filter((cmd) => cmd.startsWith(current));\n reply(matches);\n return;\n }\n\n if (currentIndex === 3) {\n switch (subcommand) {\n case \"list\": {\n const options = [\"--tools\"];\n const current = parts[3] || \"\";\n const matches = options.filter((opt) => opt.startsWith(current));\n reply(matches);\n break;\n }\n case \"server\":\n case \"tool\": {\n const serverNames = getMcpServerNames();\n const current = parts[3] || \"\";\n const matches = serverNames.filter((name) =>\n name.startsWith(current)\n );\n reply(matches);\n break;\n }\n default:\n reply([]);\n }\n return;\n }\n\n if (currentIndex === 4 && subcommand === \"tool\") {\n const serverName = parts[3];\n const toolNames = getServerToolNames(serverName);\n const current = parts[4] || \"\";\n const matches = toolNames.filter((name) => name.startsWith(current));\n reply(matches);\n return;\n }\n\n if (currentIndex === 5 && subcommand === \"tool\") {\n const actions = [\"enable\", \"disable\"];\n const current = parts[5] || \"\";\n const matches = actions.filter((action) => action.startsWith(current));\n reply(matches);\n return;\n }\n }\n\n // 其他命令的子参数补全\n if (currentIndex === 2) {\n const command = parts[1];\n switch (command) {\n case \"create\":\n reply([\"--template\", \"-t\"]);\n break;\n case \"start\":\n case \"restart\":\n reply([\"--daemon\", \"-d\"]);\n break;\n case \"completion\":\n reply([\"install\", \"uninstall\"]);\n break;\n default:\n reply([]);\n }\n return;\n }\n\n // 默认情况\n reply([]);\n });\n\n // 处理补全相关的命令行参数\n if (process.argv.includes(\"--completion\")) {\n // 输出补全脚本供shell使用\n try {\n console.log(completion.setupShellInitFile());\n } catch (error) {\n console.error(\"生成自动补全脚本时出错:\", error);\n }\n process.exit(0);\n }\n\n if (process.argv.includes(\"--completion-fish\")) {\n // Fish shell 补全\n console.log(completion.setupShellInitFile(\"fish\"));\n process.exit(0);\n }\n\n if (\n process.argv.includes(\"--compzsh\") ||\n process.argv.includes(\"--compbash\")\n ) {\n // 处理实际的补全请求 - 这些是omelette内部使用的参数\n // 不需要手动处理,让omelette自己处理\n }\n\n // 初始化补全\n completion.init();\n}\n\n/**\n * 显示自动补全安装说明\n */\nexport function showCompletionHelp(): void {\n console.log(\"🚀 xiaozhi 自动补全设置\");\n console.log();\n console.log(\"要启用自动补全,请根据你的shell执行以下命令:\");\n console.log();\n console.log(\"📝 Zsh (推荐):\");\n console.log(\" xiaozhi --completion >> ~/.xiaozhi-completion.zsh\");\n console.log(\" echo 'source ~/.xiaozhi-completion.zsh' >> ~/.zshrc\");\n console.log(\" source ~/.zshrc\");\n console.log();\n console.log(\"📝 Bash:\");\n console.log(\" xiaozhi --completion >> ~/.xiaozhi-completion.bash\");\n console.log(\" echo 'source ~/.xiaozhi-completion.bash' >> ~/.bash_profile\");\n console.log(\" source ~/.bash_profile\");\n console.log();\n console.log(\"📝 Fish:\");\n console.log(\n \" xiaozhi --completion-fish >> ~/.config/fish/completions/xiaozhi.fish\"\n );\n console.log();\n console.log(\"✨ 设置完成后,你就可以使用 Tab 键进行自动补全了!\");\n console.log();\n console.log(\"💡 示例:\");\n console.log(\" xiaozhi m<Tab> # → mcp\");\n console.log(\" xiaozhi mcp l<Tab> # → list\");\n console.log(\" xiaozhi mcp tool <Tab> # → 显示所有服务器名称\");\n}\n","import { copyFileSync, existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n// 在 ESM 中,需要从 import.meta.url 获取当前文件目录\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n// 默认连接配置\nconst DEFAULT_CONNECTION_CONFIG: Required<ConnectionConfig> = {\n heartbeatInterval: 30000, // 30秒心跳间隔\n heartbeatTimeout: 10000, // 10秒心跳超时\n reconnectInterval: 5000, // 5秒重连间隔\n};\n\n// 配置文件接口定义\n// 本地 MCP 服务配置\nexport interface LocalMCPServerConfig {\n command: string;\n args: string[];\n env?: Record<string, string>;\n}\n\n// ModelScope SSE MCP 服务配置\nexport interface SSEMCPServerConfig {\n type: \"sse\";\n url: string;\n}\n\n// 统一的 MCP 服务配置\nexport type MCPServerConfig = LocalMCPServerConfig | SSEMCPServerConfig;\n\nexport interface MCPToolConfig {\n description?: string;\n enable: boolean;\n}\n\nexport interface MCPServerToolsConfig {\n tools: Record<string, MCPToolConfig>;\n}\n\nexport interface ConnectionConfig {\n heartbeatInterval?: number; // 心跳检测间隔(毫秒),默认30000\n heartbeatTimeout?: number; // 心跳超时时间(毫秒),默认10000\n reconnectInterval?: number; // 重连间隔(毫秒),默认5000\n}\n\nexport interface ModelScopeConfig {\n apiKey?: string; // ModelScope API 密钥\n}\n\nexport interface AppConfig {\n mcpEndpoint: string;\n mcpServers: Record<string, MCPServerConfig>;\n mcpServerConfig?: Record<string, MCPServerToolsConfig>;\n connection?: ConnectionConfig; // 连接配置(可选,用于向后兼容)\n modelscope?: ModelScopeConfig; // ModelScope 配置(可选)\n}\n\n/**\n * 配置管理类\n * 负责管理应用配置,提供只读访问和安全的配置更新功能\n */\nexport class ConfigManager {\n private static instance: ConfigManager;\n private defaultConfigPath: string;\n private config: AppConfig | null = null;\n\n private constructor() {\n this.defaultConfigPath = resolve(__dirname, \"xiaozhi.config.default.json\");\n }\n\n /**\n * 获取配置文件路径(动态计算)\n */\n private getConfigFilePath(): string {\n // 配置文件路径 - 优先使用环境变量指定的目录,否则使用当前工作目录\n const configDir = process.env.XIAOZHI_CONFIG_DIR || process.cwd();\n return resolve(configDir, \"xiaozhi.config.json\");\n }\n\n /**\n * 获取配置管理器单例实例\n */\n public static getInstance(): ConfigManager {\n if (!ConfigManager.instance) {\n ConfigManager.instance = new ConfigManager();\n }\n return ConfigManager.instance;\n }\n\n /**\n * 检查配置文件是否存在\n */\n public configExists(): boolean {\n const configPath = this.getConfigFilePath();\n return existsSync(configPath);\n }\n\n /**\n * 初始化配置文件\n * 从 config.default.json 复制到 config.json\n */\n public initConfig(): void {\n if (!existsSync(this.defaultConfigPath)) {\n throw new Error(\"默认配置文件 xiaozhi.config.default.json 不存在\");\n }\n\n if (this.configExists()) {\n throw new Error(\"配置文件 xiaozhi.config.json 已存在,无需重复初始化\");\n }\n\n const configPath = this.getConfigFilePath();\n copyFileSync(this.defaultConfigPath, configPath);\n this.config = null; // 重置缓存\n }\n\n /**\n * 加载配置文件\n */\n private loadConfig(): AppConfig {\n if (!this.configExists()) {\n throw new Error(\n \"配置文件 xiaozhi.config.json 不存在,请先运行 xiaozhi init 初始化配置\"\n );\n }\n\n try {\n const configPath = this.getConfigFilePath();\n const configData = readFileSync(configPath, \"utf8\");\n const config = JSON.parse(configData) as AppConfig;\n\n // 验证配置结构\n this.validateConfig(config);\n\n return config;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`配置文件格式错误: ${error.message}`);\n }\n throw error;\n }\n }\n\n /**\n * 验证配置文件结构\n */\n private validateConfig(config: unknown): void {\n if (!config || typeof config !== \"object\") {\n throw new Error(\"配置文件格式错误:根对象无效\");\n }\n\n const configObj = config as Record<string, unknown>;\n\n if (!configObj.mcpEndpoint || typeof configObj.mcpEndpoint !== \"string\") {\n throw new Error(\"配置文件格式错误:mcpEndpoint 字段无效\");\n }\n\n if (!configObj.mcpServers || typeof configObj.mcpServers !== \"object\") {\n throw new Error(\"配置文件格式错误:mcpServers 字段无效\");\n }\n\n // 验证每个 MCP 服务配置\n for (const [serverName, serverConfig] of Object.entries(\n configObj.mcpServers as Record<string, unknown>\n )) {\n if (!serverConfig || typeof serverConfig !== \"object\") {\n throw new Error(`配置文件格式错误:mcpServers.${serverName} 无效`);\n }\n\n const sc = serverConfig as Record<string, unknown>;\n\n // 检查是否是 SSE 类型\n if (sc.type === \"sse\") {\n // SSE 类型的验证\n if (!sc.url || typeof sc.url !== \"string\") {\n throw new Error(\n `配置文件格式错误:mcpServers.${serverName}.url 无效`\n );\n }\n } else {\n // 本地类型的验证\n if (!sc.command || typeof sc.command !== \"string\") {\n throw new Error(\n `配置文件格式错误:mcpServers.${serverName}.command 无效`\n );\n }\n\n if (!Array.isArray(sc.args)) {\n throw new Error(\n `配置文件格式错误:mcpServers.${serverName}.args 必须是数组`\n );\n }\n\n if (sc.env && typeof sc.env !== \"object\") {\n throw new Error(\n `配置文件格式错误:mcpServers.${serverName}.env 必须是对象`\n );\n }\n }\n }\n }\n\n /**\n * 获取配置(只读)\n */\n public getConfig(): Readonly<AppConfig> {\n if (!this.config) {\n this.config = this.loadConfig();\n }\n\n // 返回深度只读副本\n return JSON.parse(JSON.stringify(this.config));\n }\n\n /**\n * 获取 MCP 端点\n */\n public getMcpEndpoint(): string {\n const config = this.getConfig();\n return config.mcpEndpoint;\n }\n\n /**\n * 获取 MCP 服务配置\n */\n public getMcpServers(): Readonly<Record<string, MCPServerConfig>> {\n const config = this.getConfig();\n return config.mcpServers;\n }\n\n /**\n * 获取 MCP 服务工具配置\n */\n public getMcpServerConfig(): Readonly<Record<string, MCPServerToolsConfig>> {\n const config = this.getConfig();\n return config.mcpServerConfig || {};\n }\n\n /**\n * 获取指定服务的工具配置\n */\n public getServerToolsConfig(\n serverName: string\n ): Readonly<Record<string, MCPToolConfig>> {\n const serverConfig = this.getMcpServerConfig();\n return serverConfig[serverName]?.tools || {};\n }\n\n /**\n * 检查工具是否启用\n */\n public isToolEnabled(serverName: string, toolName: string): boolean {\n const toolsConfig = this.getServerToolsConfig(serverName);\n const toolConfig = toolsConfig[toolName];\n return toolConfig?.enable !== false; // 默认启用\n }\n\n /**\n * 更新 MCP 端点\n */\n public updateMcpEndpoint(endpoint: string): void {\n if (!endpoint || typeof endpoint !== \"string\") {\n throw new Error(\"MCP 端点必须是非空字符串\");\n }\n\n const config = this.getConfig();\n const newConfig = { ...config, mcpEndpoint: endpoint };\n this.saveConfig(newConfig);\n }\n\n /**\n * 更新 MCP 服务配置\n */\n public updateMcpServer(\n serverName: string,\n serverConfig: MCPServerConfig\n ): void {\n if (!serverName || typeof serverName !== \"string\") {\n throw new Error(\"服务名称必须是非空字符串\");\n }\n\n // 验证服务配置\n if (\"type\" in serverConfig && serverConfig.type === \"sse\") {\n // SSE 类型的验证\n if (!serverConfig.url || typeof serverConfig.url !== \"string\") {\n throw new Error(\"SSE 服务配置的 url 字段必须是非空字符串\");\n }\n } else {\n // 本地类型的验证\n const localConfig = serverConfig as LocalMCPServerConfig;\n if (!localConfig.command || typeof localConfig.command !== \"string\") {\n throw new Error(\"服务配置的 command 字段必须是非空字符串\");\n }\n\n if (!Array.isArray(localConfig.args)) {\n throw new Error(\"服务配置的 args 字段必须是数组\");\n }\n\n if (localConfig.env && typeof localConfig.env !== \"object\") {\n throw new Error(\"服务配置的 env 字段必须是对象\");\n }\n }\n\n const config = this.getConfig();\n const newConfig = {\n ...config,\n mcpServers: {\n ...config.mcpServers,\n [serverName]: serverConfig,\n },\n };\n this.saveConfig(newConfig);\n }\n\n /**\n * 删除 MCP 服务配置\n */\n public removeMcpServer(serverName: string): void {\n if (!serverName || typeof serverName !== \"string\") {\n throw new Error(\"服务名称必须是非空字符串\");\n }\n\n const config = this.getConfig();\n if (!config.mcpServers[serverName]) {\n throw new Error(`服务 ${serverName} 不存在`);\n }\n\n const newMcpServers = { ...config.mcpServers };\n delete newMcpServers[serverName];\n\n const newConfig = {\n ...config,\n mcpServers: newMcpServers,\n };\n this.saveConfig(newConfig);\n }\n\n /**\n * 更新服务工具配置\n */\n public updateServerToolsConfig(\n serverName: string,\n toolsConfig: Record<string, MCPToolConfig>\n ): void {\n const config = this.getConfig();\n const newConfig = { ...config };\n\n // 确保 mcpServerConfig 存在\n if (!newConfig.mcpServerConfig) {\n newConfig.mcpServerConfig = {};\n }\n\n // 更新指定服务的工具配置\n newConfig.mcpServerConfig[serverName] = {\n tools: toolsConfig,\n };\n\n this.saveConfig(newConfig);\n }\n\n /**\n * 设置工具启用状态\n */\n public setToolEnabled(\n serverName: string,\n toolName: string,\n enabled: boolean,\n description?: string\n ): void {\n const config = this.getConfig();\n const newConfig = { ...config };\n\n // 确保 mcpServerConfig 存在\n if (!newConfig.mcpServerConfig) {\n newConfig.mcpServerConfig = {};\n }\n\n // 确保服务配置存在\n if (!newConfig.mcpServerConfig[serverName]) {\n newConfig.mcpServerConfig[serverName] = { tools: {} };\n }\n\n // 更新工具配置\n newConfig.mcpServerConfig[serverName].tools[toolName] = {\n enable: enabled,\n ...(description && { description }),\n };\n\n this.saveConfig(newConfig);\n }\n\n /**\n * 保存配置到文件\n */\n private saveConfig(config: AppConfig): void {\n try {\n // 验证配置\n this.validateConfig(config);\n\n // 格式化 JSON 并保存\n const configPath = this.getConfigFilePath();\n const configJson = JSON.stringify(config, null, 2);\n writeFileSync(configPath, configJson, \"utf8\");\n\n // 更新缓存\n this.config = config;\n } catch (error) {\n throw new Error(\n `保存配置失败: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * 重新加载配置(清除缓存)\n */\n public reloadConfig(): void {\n this.config = null;\n }\n\n /**\n * 获取配置文件路径\n */\n public getConfigPath(): string {\n return this.getConfigFilePath();\n }\n\n /**\n * 获取默认配置文件路径\n */\n public getDefaultConfigPath(): string {\n return this.defaultConfigPath;\n }\n\n /**\n * 获取连接配置(包含默认值)\n */\n public getConnectionConfig(): Required<ConnectionConfig> {\n const config = this.getConfig();\n const connectionConfig = config.connection || {};\n\n return {\n heartbeatInterval:\n connectionConfig.heartbeatInterval ??\n DEFAULT_CONNECTION_CONFIG.heartbeatInterval,\n heartbeatTimeout:\n connectionConfig.heartbeatTimeout ??\n DEFAULT_CONNECTION_CONFIG.heartbeatTimeout,\n reconnectInterval:\n connectionConfig.reconnectInterval ??\n DEFAULT_CONNECTION_CONFIG.reconnectInterval,\n };\n }\n\n /**\n * 获取心跳检测间隔(毫秒)\n */\n public getHeartbeatInterval(): number {\n return this.getConnectionConfig().heartbeatInterval;\n }\n\n /**\n * 获取心跳超时时间(毫秒)\n */\n public getHeartbeatTimeout(): number {\n return this.getConnectionConfig().heartbeatTimeout;\n }\n\n /**\n * 获取重连间隔(毫秒)\n */\n public getReconnectInterval(): number {\n return this.getConnectionConfig().reconnectInterval;\n }\n\n /**\n * 更新连接配置\n */\n public updateConnectionConfig(\n connectionConfig: Partial<ConnectionConfig>\n ): void {\n const config = this.getConfig();\n const currentConnectionConfig = config.connection || {};\n\n const newConnectionConfig = {\n ...currentConnectionConfig,\n ...connectionConfig,\n };\n\n const newConfig = {\n ...config,\n connection: newConnectionConfig,\n };\n\n this.saveConfig(newConfig);\n }\n\n /**\n * 设置心跳检测间隔\n */\n public setHeartbeatInterval(interval: number): void {\n if (interval <= 0) {\n throw new Error(\"心跳检测间隔必须大于0\");\n }\n this.updateConnectionConfig({ heartbeatInterval: interval });\n }\n\n /**\n * 设置心跳超时时间\n */\n public setHeartbeatTimeout(timeout: number): void {\n if (timeout <= 0) {\n throw new Error(\"心跳超时时间必须大于0\");\n }\n this.updateConnectionConfig({ heartbeatTimeout: timeout });\n }\n\n /**\n * 设置重连间隔\n */\n public setReconnectInterval(interval: number): void {\n if (interval <= 0) {\n throw new Error(\"重连间隔必须大于0\");\n }\n this.updateConnectionConfig({ reconnectInterval: interval });\n }\n\n /**\n * 获取 ModelScope 配置\n */\n public getModelScopeConfig(): Readonly<ModelScopeConfig> {\n const config = this.getConfig();\n return config.modelscope || {};\n }\n\n /**\n * 获取 ModelScope API Key\n * 优先从配置文件读取,其次从环境变量读取\n */\n public getModelScopeApiKey(): string | undefined {\n const modelScopeConfig = this.getModelScopeConfig();\n return modelScopeConfig.apiKey || process.env.MODELSCOPE_API_TOKEN;\n }\n\n /**\n * 更新 ModelScope 配置\n */\n public updateModelScopeConfig(\n modelScopeConfig: Partial<ModelScopeConfig>\n ): void {\n const config = this.getConfig();\n const currentModelScopeConfig = config.modelscope || {};\n\n const newModelScopeConfig = {\n ...currentModelScopeConfig,\n ...modelScopeConfig,\n };\n\n const newConfig = {\n ...config,\n modelscope: newModelScopeConfig,\n };\n\n this.saveConfig(newConfig);\n }\n\n /**\n * 设置 ModelScope API Key\n */\n public setModelScopeApiKey(apiKey: string): void {\n if (!apiKey || typeof apiKey !== \"string\") {\n throw new Error(\"API Key 必须是非空字符串\");\n }\n this.updateModelScopeConfig({ apiKey });\n }\n}\n\n// 导出单例实例\nexport const configManager = ConfigManager.getInstance();\n"],"mappings":"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","names":["omelette","copyFileSync","existsSync","readFileSync","writeFileSync","dirname","resolve","fileURLToPath","__dirname","dirname","fileURLToPath","DEFAULT_CONNECTION_CONFIG","ConfigManager","_ConfigManager","__name","resolve","configDir","configPath","existsSync","copyFileSync","configData","readFileSync","config","error","configObj","serverName","serverConfig","sc","toolName","endpoint","newConfig","localConfig","newMcpServers","toolsConfig","enabled","description","configJson","writeFileSync","connectionConfig","newConnectionConfig","interval","timeout","modelScopeConfig","newModelScopeConfig","apiKey","configManager","getMcpServerNames","configManager","mcpServers","__name","getServerToolNames","serverName","toolsConfig","setupAutoCompletion","completion","omelette","reply","fragment","line","before","parts","currentIndex","subcommand","subcommands","current","matches","cmd","options","opt","serverNames","name","toolNames","actions","action","error","showCompletionHelp"]}
1
+ {"version":3,"sources":["../src/autoCompletion.ts","../src/configManager.ts"],"sourcesContent":["import omelette from \"omelette\";\nimport { configManager } from \"./configManager\";\n\n/**\n * 自动补全功能模块\n */\n\n/**\n * 获取所有可用的MCP服务器名称\n */\nfunction getMcpServerNames(): string[] {\n try {\n if (!configManager.configExists()) {\n return [];\n }\n const mcpServers = configManager.getMcpServers();\n return Object.keys(mcpServers);\n } catch (error) {\n return [];\n }\n}\n\n/**\n * 获取指定服务器的工具名称\n */\nfunction getServerToolNames(serverName: string): string[] {\n try {\n if (!configManager.configExists()) {\n return [];\n }\n const toolsConfig = configManager.getServerToolsConfig(serverName);\n return Object.keys(toolsConfig);\n } catch (error) {\n return [];\n }\n}\n\n/**\n * 设置自动补全功能\n */\nexport function setupAutoCompletion(): void {\n // 创建 omelette 实例,使用简单的模板\n const completion = omelette(\"xiaozhi <command>\");\n\n // 处理主命令补全\n completion.on(\"command\", ({ reply }) => {\n reply([\n \"create\",\n \"init\",\n \"config\",\n \"start\",\n \"stop\",\n \"status\",\n \"attach\",\n \"restart\",\n \"mcp\",\n \"completion\",\n ]);\n });\n\n // 处理复杂的多级命令补全\n completion.on(\"complete\", (fragment, { line, before, reply }) => {\n // 调试信息\n if (process.env.XIAOZHI_DEBUG_COMPLETION) {\n console.error(\n `Debug completion - line: \"${line}\", before: \"${before}\", fragment: \"${fragment}\"`\n );\n }\n\n const parts = line.trim().split(/\\s+/);\n const endsWithSpace = line !== line.trim();\n const currentIndex = endsWithSpace ? parts.length : parts.length - 1;\n\n // MCP 相关的补全\n if (parts[1] === \"mcp\") {\n const subcommand = parts[2];\n\n if (currentIndex === 2) {\n // mcp 子命令\n const subcommands = [\"list\", \"server\", \"tool\"];\n const current = parts[2] || \"\";\n const matches = subcommands.filter((cmd) => cmd.startsWith(current));\n reply(matches);\n return;\n }\n\n if (currentIndex === 3) {\n switch (subcommand) {\n case \"list\": {\n const options = [\"--tools\"];\n const current = parts[3] || \"\";\n const matches = options.filter((opt) => opt.startsWith(current));\n reply(matches);\n break;\n }\n case \"server\":\n case \"tool\": {\n const serverNames = getMcpServerNames();\n const current = parts[3] || \"\";\n const matches = serverNames.filter((name) =>\n name.startsWith(current)\n );\n reply(matches);\n break;\n }\n default:\n reply([]);\n }\n return;\n }\n\n if (currentIndex === 4 && subcommand === \"tool\") {\n const serverName = parts[3];\n const toolNames = getServerToolNames(serverName);\n const current = parts[4] || \"\";\n const matches = toolNames.filter((name) => name.startsWith(current));\n reply(matches);\n return;\n }\n\n if (currentIndex === 5 && subcommand === \"tool\") {\n const actions = [\"enable\", \"disable\"];\n const current = parts[5] || \"\";\n const matches = actions.filter((action) => action.startsWith(current));\n reply(matches);\n return;\n }\n }\n\n // 其他命令的子参数补全\n if (currentIndex === 2) {\n const command = parts[1];\n switch (command) {\n case \"create\":\n reply([\"--template\", \"-t\"]);\n break;\n case \"start\":\n case \"restart\":\n reply([\"--daemon\", \"-d\"]);\n break;\n case \"completion\":\n reply([\"install\", \"uninstall\"]);\n break;\n default:\n reply([]);\n }\n return;\n }\n\n // 默认情况\n reply([]);\n });\n\n // 处理补全相关的命令行参数\n if (process.argv.includes(\"--completion\")) {\n // 输出补全脚本供shell使用\n try {\n console.log(completion.setupShellInitFile());\n } catch (error) {\n console.error(\"生成自动补全脚本时出错:\", error);\n }\n process.exit(0);\n }\n\n if (process.argv.includes(\"--completion-fish\")) {\n // Fish shell 补全\n console.log(completion.setupShellInitFile(\"fish\"));\n process.exit(0);\n }\n\n if (\n process.argv.includes(\"--compzsh\") ||\n process.argv.includes(\"--compbash\")\n ) {\n // 处理实际的补全请求 - 这些是omelette内部使用的参数\n // 不需要手动处理,让omelette自己处理\n }\n\n // 初始化补全\n completion.init();\n}\n\n/**\n * 显示自动补全安装说明\n */\nexport function showCompletionHelp(): void {\n console.log(\"🚀 xiaozhi 自动补全设置\");\n console.log();\n console.log(\"要启用自动补全,请根据你的shell执行以下命令:\");\n console.log();\n console.log(\"📝 Zsh (推荐):\");\n console.log(\" xiaozhi --completion >> ~/.xiaozhi-completion.zsh\");\n console.log(\" echo 'source ~/.xiaozhi-completion.zsh' >> ~/.zshrc\");\n console.log(\" source ~/.zshrc\");\n console.log();\n console.log(\"📝 Bash:\");\n console.log(\" xiaozhi --completion >> ~/.xiaozhi-completion.bash\");\n console.log(\" echo 'source ~/.xiaozhi-completion.bash' >> ~/.bash_profile\");\n console.log(\" source ~/.bash_profile\");\n console.log();\n console.log(\"📝 Fish:\");\n console.log(\n \" xiaozhi --completion-fish >> ~/.config/fish/completions/xiaozhi.fish\"\n );\n console.log();\n console.log(\"✨ 设置完成后,你就可以使用 Tab 键进行自动补全了!\");\n console.log();\n console.log(\"💡 示例:\");\n console.log(\" xiaozhi m<Tab> # → mcp\");\n console.log(\" xiaozhi mcp l<Tab> # → list\");\n console.log(\" xiaozhi mcp tool <Tab> # → 显示所有服务器名称\");\n}\n","import { copyFileSync, existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n// 在 ESM 中,需要从 import.meta.url 获取当前文件目录\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n// 默认连接配置\nconst DEFAULT_CONNECTION_CONFIG: Required<ConnectionConfig> = {\n heartbeatInterval: 30000, // 30秒心跳间隔\n heartbeatTimeout: 10000, // 10秒心跳超时\n reconnectInterval: 5000, // 5秒重连间隔\n};\n\n// 配置文件接口定义\n// 本地 MCP 服务配置\nexport interface LocalMCPServerConfig {\n command: string;\n args: string[];\n env?: Record<string, string>;\n}\n\n// ModelScope SSE MCP 服务配置\nexport interface SSEMCPServerConfig {\n type: \"sse\";\n url: string;\n}\n\n// 统一的 MCP 服务配置\nexport type MCPServerConfig = LocalMCPServerConfig | SSEMCPServerConfig;\n\nexport interface MCPToolConfig {\n description?: string;\n enable: boolean;\n}\n\nexport interface MCPServerToolsConfig {\n tools: Record<string, MCPToolConfig>;\n}\n\nexport interface ConnectionConfig {\n heartbeatInterval?: number; // 心跳检测间隔(毫秒),默认30000\n heartbeatTimeout?: number; // 心跳超时时间(毫秒),默认10000\n reconnectInterval?: number; // 重连间隔(毫秒),默认5000\n}\n\nexport interface ModelScopeConfig {\n apiKey?: string; // ModelScope API 密钥\n}\n\nexport interface WebUIConfig {\n port?: number; // Web UI 端口号,默认 9999\n}\n\nexport interface AppConfig {\n mcpEndpoint: string;\n mcpServers: Record<string, MCPServerConfig>;\n mcpServerConfig?: Record<string, MCPServerToolsConfig>;\n connection?: ConnectionConfig; // 连接配置(可选,用于向后兼容)\n modelscope?: ModelScopeConfig; // ModelScope 配置(可选)\n webUI?: WebUIConfig; // Web UI 配置(可选)\n}\n\n/**\n * 配置管理类\n * 负责管理应用配置,提供只读访问和安全的配置更新功能\n */\nexport class ConfigManager {\n private static instance: ConfigManager;\n private defaultConfigPath: string;\n private config: AppConfig | null = null;\n\n private constructor() {\n this.defaultConfigPath = resolve(__dirname, \"xiaozhi.config.default.json\");\n }\n\n /**\n * 获取配置文件路径(动态计算)\n */\n private getConfigFilePath(): string {\n // 配置文件路径 - 优先使用环境变量指定的目录,否则使用当前工作目录\n const configDir = process.env.XIAOZHI_CONFIG_DIR || process.cwd();\n return resolve(configDir, \"xiaozhi.config.json\");\n }\n\n /**\n * 获取配置管理器单例实例\n */\n public static getInstance(): ConfigManager {\n if (!ConfigManager.instance) {\n ConfigManager.instance = new ConfigManager();\n }\n return ConfigManager.instance;\n }\n\n /**\n * 检查配置文件是否存在\n */\n public configExists(): boolean {\n const configPath = this.getConfigFilePath();\n return existsSync(configPath);\n }\n\n /**\n * 初始化配置文件\n * 从 config.default.json 复制到 config.json\n */\n public initConfig(): void {\n if (!existsSync(this.defaultConfigPath)) {\n throw new Error(\"默认配置文件 xiaozhi.config.default.json 不存在\");\n }\n\n if (this.configExists()) {\n throw new Error(\"配置文件 xiaozhi.config.json 已存在,无需重复初始化\");\n }\n\n const configPath = this.getConfigFilePath();\n copyFileSync(this.defaultConfigPath, configPath);\n this.config = null; // 重置缓存\n }\n\n /**\n * 加载配置文件\n */\n private loadConfig(): AppConfig {\n if (!this.configExists()) {\n throw new Error(\n \"配置文件 xiaozhi.config.json 不存在,请先运行 xiaozhi init 初始化配置\"\n );\n }\n\n try {\n const configPath = this.getConfigFilePath();\n const configData = readFileSync(configPath, \"utf8\");\n const config = JSON.parse(configData) as AppConfig;\n\n // 验证配置结构\n this.validateConfig(config);\n\n return config;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`配置文件格式错误: ${error.message}`);\n }\n throw error;\n }\n }\n\n /**\n * 验证配置文件结构\n */\n private validateConfig(config: unknown): void {\n if (!config || typeof config !== \"object\") {\n throw new Error(\"配置文件格式错误:根对象无效\");\n }\n\n const configObj = config as Record<string, unknown>;\n\n if (!configObj.mcpEndpoint || typeof configObj.mcpEndpoint !== \"string\") {\n throw new Error(\"配置文件格式错误:mcpEndpoint 字段无效\");\n }\n\n if (!configObj.mcpServers || typeof configObj.mcpServers !== \"object\") {\n throw new Error(\"配置文件格式错误:mcpServers 字段无效\");\n }\n\n // 验证每个 MCP 服务配置\n for (const [serverName, serverConfig] of Object.entries(\n configObj.mcpServers as Record<string, unknown>\n )) {\n if (!serverConfig || typeof serverConfig !== \"object\") {\n throw new Error(`配置文件格式错误:mcpServers.${serverName} 无效`);\n }\n\n const sc = serverConfig as Record<string, unknown>;\n\n // 检查是否是 SSE 类型\n if (sc.type === \"sse\") {\n // SSE 类型的验证\n if (!sc.url || typeof sc.url !== \"string\") {\n throw new Error(\n `配置文件格式错误:mcpServers.${serverName}.url 无效`\n );\n }\n } else {\n // 本地类型的验证\n if (!sc.command || typeof sc.command !== \"string\") {\n throw new Error(\n `配置文件格式错误:mcpServers.${serverName}.command 无效`\n );\n }\n\n if (!Array.isArray(sc.args)) {\n throw new Error(\n `配置文件格式错误:mcpServers.${serverName}.args 必须是数组`\n );\n }\n\n if (sc.env && typeof sc.env !== \"object\") {\n throw new Error(\n `配置文件格式错误:mcpServers.${serverName}.env 必须是对象`\n );\n }\n }\n }\n }\n\n /**\n * 获取配置(只读)\n */\n public getConfig(): Readonly<AppConfig> {\n if (!this.config) {\n this.config = this.loadConfig();\n }\n\n // 返回深度只读副本\n return JSON.parse(JSON.stringify(this.config));\n }\n\n /**\n * 获取 MCP 端点\n */\n public getMcpEndpoint(): string {\n const config = this.getConfig();\n return config.mcpEndpoint;\n }\n\n /**\n * 获取 MCP 服务配置\n */\n public getMcpServers(): Readonly<Record<string, MCPServerConfig>> {\n const config = this.getConfig();\n return config.mcpServers;\n }\n\n /**\n * 获取 MCP 服务工具配置\n */\n public getMcpServerConfig(): Readonly<Record<string, MCPServerToolsConfig>> {\n const config = this.getConfig();\n return config.mcpServerConfig || {};\n }\n\n /**\n * 获取指定服务的工具配置\n */\n public getServerToolsConfig(\n serverName: string\n ): Readonly<Record<string, MCPToolConfig>> {\n const serverConfig = this.getMcpServerConfig();\n return serverConfig[serverName]?.tools || {};\n }\n\n /**\n * 检查工具是否启用\n */\n public isToolEnabled(serverName: string, toolName: string): boolean {\n const toolsConfig = this.getServerToolsConfig(serverName);\n const toolConfig = toolsConfig[toolName];\n return toolConfig?.enable !== false; // 默认启用\n }\n\n /**\n * 更新 MCP 端点\n */\n public updateMcpEndpoint(endpoint: string): void {\n if (!endpoint || typeof endpoint !== \"string\") {\n throw new Error(\"MCP 端点必须是非空字符串\");\n }\n\n const config = this.getConfig();\n const newConfig = { ...config, mcpEndpoint: endpoint };\n this.saveConfig(newConfig);\n }\n\n /**\n * 更新 MCP 服务配置\n */\n public updateMcpServer(\n serverName: string,\n serverConfig: MCPServerConfig\n ): void {\n if (!serverName || typeof serverName !== \"string\") {\n throw new Error(\"服务名称必须是非空字符串\");\n }\n\n // 验证服务配置\n if (\"type\" in serverConfig && serverConfig.type === \"sse\") {\n // SSE 类型的验证\n if (!serverConfig.url || typeof serverConfig.url !== \"string\") {\n throw new Error(\"SSE 服务配置的 url 字段必须是非空字符串\");\n }\n } else {\n // 本地类型的验证\n const localConfig = serverConfig as LocalMCPServerConfig;\n if (!localConfig.command || typeof localConfig.command !== \"string\") {\n throw new Error(\"服务配置的 command 字段必须是非空字符串\");\n }\n\n if (!Array.isArray(localConfig.args)) {\n throw new Error(\"服务配置的 args 字段必须是数组\");\n }\n\n if (localConfig.env && typeof localConfig.env !== \"object\") {\n throw new Error(\"服务配置的 env 字段必须是对象\");\n }\n }\n\n const config = this.getConfig();\n const newConfig = {\n ...config,\n mcpServers: {\n ...config.mcpServers,\n [serverName]: serverConfig,\n },\n };\n this.saveConfig(newConfig);\n }\n\n /**\n * 删除 MCP 服务配置\n */\n public removeMcpServer(serverName: string): void {\n if (!serverName || typeof serverName !== \"string\") {\n throw new Error(\"服务名称必须是非空字符串\");\n }\n\n const config = this.getConfig();\n if (!config.mcpServers[serverName]) {\n throw new Error(`服务 ${serverName} 不存在`);\n }\n\n const newMcpServers = { ...config.mcpServers };\n delete newMcpServers[serverName];\n\n const newConfig = {\n ...config,\n mcpServers: newMcpServers,\n };\n this.saveConfig(newConfig);\n }\n\n /**\n * 更新服务工具配置\n */\n public updateServerToolsConfig(\n serverName: string,\n toolsConfig: Record<string, MCPToolConfig>\n ): void {\n const config = this.getConfig();\n const newConfig = { ...config };\n\n // 确保 mcpServerConfig 存在\n if (!newConfig.mcpServerConfig) {\n newConfig.mcpServerConfig = {};\n }\n\n // 更新指定服务的工具配置\n newConfig.mcpServerConfig[serverName] = {\n tools: toolsConfig,\n };\n\n this.saveConfig(newConfig);\n }\n\n /**\n * 设置工具启用状态\n */\n public setToolEnabled(\n serverName: string,\n toolName: string,\n enabled: boolean,\n description?: string\n ): void {\n const config = this.getConfig();\n const newConfig = { ...config };\n\n // 确保 mcpServerConfig 存在\n if (!newConfig.mcpServerConfig) {\n newConfig.mcpServerConfig = {};\n }\n\n // 确保服务配置存在\n if (!newConfig.mcpServerConfig[serverName]) {\n newConfig.mcpServerConfig[serverName] = { tools: {} };\n }\n\n // 更新工具配置\n newConfig.mcpServerConfig[serverName].tools[toolName] = {\n enable: enabled,\n ...(description && { description }),\n };\n\n this.saveConfig(newConfig);\n }\n\n /**\n * 保存配置到文件\n */\n private saveConfig(config: AppConfig): void {\n try {\n // 验证配置\n this.validateConfig(config);\n\n // 格式化 JSON 并保存\n const configPath = this.getConfigFilePath();\n const configJson = JSON.stringify(config, null, 2);\n writeFileSync(configPath, configJson, \"utf8\");\n\n // 更新缓存\n this.config = config;\n } catch (error) {\n throw new Error(\n `保存配置失败: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * 重新加载配置(清除缓存)\n */\n public reloadConfig(): void {\n this.config = null;\n }\n\n /**\n * 获取配置文件路径\n */\n public getConfigPath(): string {\n return this.getConfigFilePath();\n }\n\n /**\n * 获取默认配置文件路径\n */\n public getDefaultConfigPath(): string {\n return this.defaultConfigPath;\n }\n\n /**\n * 获取连接配置(包含默认值)\n */\n public getConnectionConfig(): Required<ConnectionConfig> {\n const config = this.getConfig();\n const connectionConfig = config.connection || {};\n\n return {\n heartbeatInterval:\n connectionConfig.heartbeatInterval ??\n DEFAULT_CONNECTION_CONFIG.heartbeatInterval,\n heartbeatTimeout:\n connectionConfig.heartbeatTimeout ??\n DEFAULT_CONNECTION_CONFIG.heartbeatTimeout,\n reconnectInterval:\n connectionConfig.reconnectInterval ??\n DEFAULT_CONNECTION_CONFIG.reconnectInterval,\n };\n }\n\n /**\n * 获取心跳检测间隔(毫秒)\n */\n public getHeartbeatInterval(): number {\n return this.getConnectionConfig().heartbeatInterval;\n }\n\n /**\n * 获取心跳超时时间(毫秒)\n */\n public getHeartbeatTimeout(): number {\n return this.getConnectionConfig().heartbeatTimeout;\n }\n\n /**\n * 获取重连间隔(毫秒)\n */\n public getReconnectInterval(): number {\n return this.getConnectionConfig().reconnectInterval;\n }\n\n /**\n * 更新连接配置\n */\n public updateConnectionConfig(\n connectionConfig: Partial<ConnectionConfig>\n ): void {\n const config = this.getConfig();\n const currentConnectionConfig = config.connection || {};\n\n const newConnectionConfig = {\n ...currentConnectionConfig,\n ...connectionConfig,\n };\n\n const newConfig = {\n ...config,\n connection: newConnectionConfig,\n };\n\n this.saveConfig(newConfig);\n }\n\n /**\n * 设置心跳检测间隔\n */\n public setHeartbeatInterval(interval: number): void {\n if (interval <= 0) {\n throw new Error(\"心跳检测间隔必须大于0\");\n }\n this.updateConnectionConfig({ heartbeatInterval: interval });\n }\n\n /**\n * 设置心跳超时时间\n */\n public setHeartbeatTimeout(timeout: number): void {\n if (timeout <= 0) {\n throw new Error(\"心跳超时时间必须大于0\");\n }\n this.updateConnectionConfig({ heartbeatTimeout: timeout });\n }\n\n /**\n * 设置重连间隔\n */\n public setReconnectInterval(interval: number): void {\n if (interval <= 0) {\n throw new Error(\"重连间隔必须大于0\");\n }\n this.updateConnectionConfig({ reconnectInterval: interval });\n }\n\n /**\n * 获取 ModelScope 配置\n */\n public getModelScopeConfig(): Readonly<ModelScopeConfig> {\n const config = this.getConfig();\n return config.modelscope || {};\n }\n\n /**\n * 获取 ModelScope API Key\n * 优先从配置文件读取,其次从环境变量读取\n */\n public getModelScopeApiKey(): string | undefined {\n const modelScopeConfig = this.getModelScopeConfig();\n return modelScopeConfig.apiKey || process.env.MODELSCOPE_API_TOKEN;\n }\n\n /**\n * 更新 ModelScope 配置\n */\n public updateModelScopeConfig(\n modelScopeConfig: Partial<ModelScopeConfig>\n ): void {\n const config = this.getConfig();\n const currentModelScopeConfig = config.modelscope || {};\n\n const newModelScopeConfig = {\n ...currentModelScopeConfig,\n ...modelScopeConfig,\n };\n\n const newConfig = {\n ...config,\n modelscope: newModelScopeConfig,\n };\n\n this.saveConfig(newConfig);\n }\n\n /**\n * 设置 ModelScope API Key\n */\n public setModelScopeApiKey(apiKey: string): void {\n if (!apiKey || typeof apiKey !== \"string\") {\n throw new Error(\"API Key 必须是非空字符串\");\n }\n this.updateModelScopeConfig({ apiKey });\n }\n\n /**\n * 获取 Web UI 配置\n */\n public getWebUIConfig(): Readonly<WebUIConfig> {\n const config = this.getConfig();\n return config.webUI || {};\n }\n\n /**\n * 获取 Web UI 端口号\n */\n public getWebUIPort(): number {\n const webUIConfig = this.getWebUIConfig();\n return webUIConfig.port ?? 9999; // 默认端口 9999\n }\n\n /**\n * 更新 Web UI 配置\n */\n public updateWebUIConfig(webUIConfig: Partial<WebUIConfig>): void {\n const config = this.getConfig();\n const currentWebUIConfig = config.webUI || {};\n\n const newWebUIConfig = {\n ...currentWebUIConfig,\n ...webUIConfig,\n };\n\n const newConfig = {\n ...config,\n webUI: newWebUIConfig,\n };\n\n this.saveConfig(newConfig);\n }\n\n /**\n * 设置 Web UI 端口号\n */\n public setWebUIPort(port: number): void {\n if (!Number.isInteger(port) || port <= 0 || port > 65535) {\n throw new Error(\"端口号必须是 1-65535 之间的整数\");\n }\n this.updateWebUIConfig({ port });\n }\n}\n\n// 导出单例实例\nexport const configManager = ConfigManager.getInstance();\n"],"mappings":"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","names":["omelette","copyFileSync","existsSync","readFileSync","writeFileSync","dirname","resolve","fileURLToPath","__dirname","dirname","fileURLToPath","DEFAULT_CONNECTION_CONFIG","ConfigManager","_ConfigManager","__name","resolve","configDir","configPath","existsSync","copyFileSync","configData","readFileSync","config","error","configObj","serverName","serverConfig","sc","toolName","endpoint","newConfig","localConfig","newMcpServers","toolsConfig","enabled","description","configJson","writeFileSync","connectionConfig","newConnectionConfig","interval","timeout","modelScopeConfig","newModelScopeConfig","apiKey","webUIConfig","newWebUIConfig","port","configManager","getMcpServerNames","configManager","mcpServers","__name","getServerToolNames","serverName","toolsConfig","setupAutoCompletion","completion","omelette","reply","fragment","line","before","parts","currentIndex","subcommand","subcommands","current","matches","cmd","options","opt","serverNames","name","toolNames","actions","action","error","showCompletionHelp"]}
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- var eo=Object.defineProperty;var l=(n,o)=>eo(n,"name",{value:o,configurable:!0});import{spawn as K}from"child_process";import h from"fs";import bo from"os";import f from"path";import{fileURLToPath as j}from"url";import c from"chalk";import{Command as vo}from"commander";import b from"ora";import ao from"omelette";import{copyFileSync as to,existsSync as A,readFileSync as no,writeFileSync as io}from"fs";import{dirname as ro,resolve as H}from"path";import{fileURLToPath as so}from"url";var co=ro(so(import.meta.url)),k={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},O=class n{static{l(this,"ConfigManager")}static instance;defaultConfigPath;config=null;constructor(){this.defaultConfigPath=H(co,"xiaozhi.config.default.json")}getConfigFilePath(){let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return H(o,"xiaozhi.config.json")}static getInstance(){return n.instance||(n.instance=new n),n.instance}configExists(){let o=this.getConfigFilePath();return A(o)}initConfig(){if(!A(this.defaultConfigPath))throw new Error("\u9ED8\u8BA4\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.default.json \u4E0D\u5B58\u5728");if(this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.json \u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u521D\u59CB\u5316");let o=this.getConfigFilePath();to(this.defaultConfigPath,o),this.config=null}loadConfig(){if(!this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.json \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u8FD0\u884C xiaozhi init \u521D\u59CB\u5316\u914D\u7F6E");try{let o=this.getConfigFilePath(),e=no(o,"utf8"),t=JSON.parse(e);return this.validateConfig(t),t}catch(o){throw o instanceof SyntaxError?new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF: ${o.message}`):o}}validateConfig(o){if(!o||typeof o!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A\u6839\u5BF9\u8C61\u65E0\u6548");let e=o;if(!e.mcpEndpoint||typeof e.mcpEndpoint!="string")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5B57\u6BB5\u65E0\u6548");if(!e.mcpServers||typeof e.mcpServers!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers \u5B57\u6BB5\u65E0\u6548");for(let[t,i]of Object.entries(e.mcpServers)){if(!i||typeof i!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t} \u65E0\u6548`);let r=i;if(r.type==="sse"){if(!r.url||typeof r.url!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.url \u65E0\u6548`)}else{if(!r.command||typeof r.command!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.command \u65E0\u6548`);if(!Array.isArray(r.args))throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.args \u5FC5\u987B\u662F\u6570\u7EC4`);if(r.env&&typeof r.env!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.env \u5FC5\u987B\u662F\u5BF9\u8C61`)}}}getConfig(){return this.config||(this.config=this.loadConfig()),JSON.parse(JSON.stringify(this.config))}getMcpEndpoint(){return this.getConfig().mcpEndpoint}getMcpServers(){return this.getConfig().mcpServers}getMcpServerConfig(){return this.getConfig().mcpServerConfig||{}}getServerToolsConfig(o){return this.getMcpServerConfig()[o]?.tools||{}}isToolEnabled(o,e){return this.getServerToolsConfig(o)[e]?.enable!==!1}updateMcpEndpoint(o){if(!o||typeof o!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t={...this.getConfig(),mcpEndpoint:o};this.saveConfig(t)}updateMcpServer(o,e){if(!o||typeof o!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if("type"in e&&e.type==="sse"){if(!e.url||typeof e.url!="string")throw new Error("SSE \u670D\u52A1\u914D\u7F6E\u7684 url \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else{let r=e;if(!r.command||typeof r.command!="string")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 command \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!Array.isArray(r.args))throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 args \u5B57\u6BB5\u5FC5\u987B\u662F\u6570\u7EC4");if(r.env&&typeof r.env!="object")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 env \u5B57\u6BB5\u5FC5\u987B\u662F\u5BF9\u8C61")}let t=this.getConfig(),i={...t,mcpServers:{...t.mcpServers,[o]:e}};this.saveConfig(i)}removeMcpServer(o){if(!o||typeof o!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let e=this.getConfig();if(!e.mcpServers[o])throw new Error(`\u670D\u52A1 ${o} \u4E0D\u5B58\u5728`);let t={...e.mcpServers};delete t[o];let i={...e,mcpServers:t};this.saveConfig(i)}updateServerToolsConfig(o,e){let i={...this.getConfig()};i.mcpServerConfig||(i.mcpServerConfig={}),i.mcpServerConfig[o]={tools:e},this.saveConfig(i)}setToolEnabled(o,e,t,i){let s={...this.getConfig()};s.mcpServerConfig||(s.mcpServerConfig={}),s.mcpServerConfig[o]||(s.mcpServerConfig[o]={tools:{}}),s.mcpServerConfig[o].tools[e]={enable:t,...i&&{description:i}},this.saveConfig(s)}saveConfig(o){try{this.validateConfig(o);let e=this.getConfigFilePath(),t=JSON.stringify(o,null,2);io(e,t,"utf8"),this.config=o}catch(e){throw new Error(`\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}reloadConfig(){this.config=null}getConfigPath(){return this.getConfigFilePath()}getDefaultConfigPath(){return this.defaultConfigPath}getConnectionConfig(){let e=this.getConfig().connection||{};return{heartbeatInterval:e.heartbeatInterval??k.heartbeatInterval,heartbeatTimeout:e.heartbeatTimeout??k.heartbeatTimeout,reconnectInterval:e.reconnectInterval??k.reconnectInterval}}getHeartbeatInterval(){return this.getConnectionConfig().heartbeatInterval}getHeartbeatTimeout(){return this.getConnectionConfig().heartbeatTimeout}getReconnectInterval(){return this.getConnectionConfig().reconnectInterval}updateConnectionConfig(o){let e=this.getConfig(),i={...e.connection||{},...o},r={...e,connection:i};this.saveConfig(r)}setHeartbeatInterval(o){if(o<=0)throw new Error("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatInterval:o})}setHeartbeatTimeout(o){if(o<=0)throw new Error("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatTimeout:o})}setReconnectInterval(o){if(o<=0)throw new Error("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({reconnectInterval:o})}getModelScopeConfig(){return this.getConfig().modelscope||{}}getModelScopeApiKey(){return this.getModelScopeConfig().apiKey||process.env.MODELSCOPE_API_TOKEN}updateModelScopeConfig(o){let e=this.getConfig(),i={...e.modelscope||{},...o},r={...e,modelscope:i};this.saveConfig(r)}setModelScopeApiKey(o){if(!o||typeof o!="string")throw new Error("API Key \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");this.updateModelScopeConfig({apiKey:o})}},p=O.getInstance();function lo(){try{if(!p.configExists())return[];let n=p.getMcpServers();return Object.keys(n)}catch{return[]}}l(lo,"getMcpServerNames");function go(n){try{if(!p.configExists())return[];let o=p.getServerToolsConfig(n);return Object.keys(o)}catch{return[]}}l(go,"getServerToolNames");function D(){let n=ao("xiaozhi <command>");if(n.on("command",({reply:o})=>{o(["create","init","config","start","stop","status","attach","restart","mcp","completion"])}),n.on("complete",(o,{line:e,before:t,reply:i})=>{process.env.XIAOZHI_DEBUG_COMPLETION&&console.error(`Debug completion - line: "${e}", before: "${t}", fragment: "${o}"`);let r=e.trim().split(/\s+/),a=e!==e.trim()?r.length:r.length-1;if(r[1]==="mcp"){let m=r[2];if(a===2){let d=["list","server","tool"],u=r[2]||"",y=d.filter(S=>S.startsWith(u));i(y);return}if(a===3){switch(m){case"list":{let d=["--tools"],u=r[3]||"",y=d.filter(S=>S.startsWith(u));i(y);break}case"server":case"tool":{let d=lo(),u=r[3]||"",y=d.filter(S=>S.startsWith(u));i(y);break}default:i([])}return}if(a===4&&m==="tool"){let d=r[3],u=go(d),y=r[4]||"",S=u.filter(x=>x.startsWith(y));i(S);return}if(a===5&&m==="tool"){let d=["enable","disable"],u=r[5]||"",y=d.filter(S=>S.startsWith(u));i(y);return}}if(a===2){switch(r[1]){case"create":i(["--template","-t"]);break;case"start":case"restart":i(["--daemon","-d"]);break;case"completion":i(["install","uninstall"]);break;default:i([])}return}i([])}),process.argv.includes("--completion")){try{console.log(n.setupShellInitFile())}catch(o){console.error("\u751F\u6210\u81EA\u52A8\u8865\u5168\u811A\u672C\u65F6\u51FA\u9519:",o)}process.exit(0)}process.argv.includes("--completion-fish")&&(console.log(n.setupShellInitFile("fish")),process.exit(0)),process.argv.includes("--compzsh")||process.argv.includes("--compbash"),n.init()}l(D,"setupAutoCompletion");function W(){console.log("\u{1F680} xiaozhi \u81EA\u52A8\u8865\u5168\u8BBE\u7F6E"),console.log(),console.log("\u8981\u542F\u7528\u81EA\u52A8\u8865\u5168\uFF0C\u8BF7\u6839\u636E\u4F60\u7684shell\u6267\u884C\u4EE5\u4E0B\u547D\u4EE4\uFF1A"),console.log(),console.log("\u{1F4DD} Zsh (\u63A8\u8350):"),console.log(" xiaozhi --completion >> ~/.xiaozhi-completion.zsh"),console.log(" echo 'source ~/.xiaozhi-completion.zsh' >> ~/.zshrc"),console.log(" source ~/.zshrc"),console.log(),console.log("\u{1F4DD} Bash:"),console.log(" xiaozhi --completion >> ~/.xiaozhi-completion.bash"),console.log(" echo 'source ~/.xiaozhi-completion.bash' >> ~/.bash_profile"),console.log(" source ~/.bash_profile"),console.log(),console.log("\u{1F4DD} Fish:"),console.log(" xiaozhi --completion-fish >> ~/.config/fish/completions/xiaozhi.fish"),console.log(),console.log("\u2728 \u8BBE\u7F6E\u5B8C\u6210\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u4F7F\u7528 Tab \u952E\u8FDB\u884C\u81EA\u52A8\u8865\u5168\u4E86\uFF01"),console.log(),console.log("\u{1F4A1} \u793A\u4F8B:"),console.log(" xiaozhi m<Tab> # \u2192 mcp"),console.log(" xiaozhi mcp l<Tab> # \u2192 list"),console.log(" xiaozhi mcp tool <Tab> # \u2192 \u663E\u793A\u6240\u6709\u670D\u52A1\u5668\u540D\u79F0")}l(W,"showCompletionHelp");import E from"fs";import po from"path";import P from"chalk";import{createConsola as fo}from"consola";function mo(n){let o=n.getFullYear(),e=String(n.getMonth()+1).padStart(2,"0"),t=String(n.getDate()).padStart(2,"0"),i=String(n.getHours()).padStart(2,"0"),r=String(n.getMinutes()).padStart(2,"0"),s=String(n.getSeconds()).padStart(2,"0");return`${o}-${e}-${t} ${i}:${r}:${s}`}l(mo,"formatDateTime");var I=class{static{l(this,"Logger")}logFilePath=null;writeStream=null;consolaInstance;constructor(){this.consolaInstance=fo({formatOptions:{date:!1,colors:!0,compact:!0},fancy:!1}),this.consolaInstance.setReporters([{log:l(o=>{let e={info:"INFO",success:"SUCCESS",warn:"WARN",error:"ERROR",debug:"DEBUG",log:"LOG"},t={info:P.blue,success:P.green,warn:P.yellow,error:P.red,debug:P.gray,log:l(d=>d,"log")},i=e[o.type]||o.type.toUpperCase(),r=t[o.type]||(d=>d),s=mo(new Date),a=r(`[${i}]`),m=`[${s}] ${a} ${o.args.join(" ")}`;console.error(m)},"log")}])}initLogFile(o){this.logFilePath=po.join(o,"xiaozhi.log"),E.existsSync(this.logFilePath)||E.writeFileSync(this.logFilePath,""),this.writeStream=E.createWriteStream(this.logFilePath,{flags:"a",encoding:"utf8"})}logToFile(o,e,...t){if(this.writeStream){let r=`[${new Date().toISOString()}] [${o.toUpperCase()}] ${e}`,s=t.length>0?`${r} ${t.map(a=>typeof a=="object"?JSON.stringify(a):String(a)).join(" ")}`:r;this.writeStream.write(`${s}
3
- `)}}enableFileLogging(o){o&&!this.writeStream&&this.logFilePath?this.writeStream=E.createWriteStream(this.logFilePath,{flags:"a",encoding:"utf8"}):!o&&this.writeStream&&(this.writeStream.end(),this.writeStream=null)}info(o,...e){this.consolaInstance.info(o,...e),this.logToFile("info",o,...e)}success(o,...e){this.consolaInstance.success(o,...e),this.logToFile("success",o,...e)}warn(o,...e){this.consolaInstance.warn(o,...e),this.logToFile("warn",o,...e)}error(o,...e){this.consolaInstance.error(o,...e),this.logToFile("error",o,...e)}debug(o,...e){this.consolaInstance.debug(o,...e),this.logToFile("debug",o,...e)}log(o,...e){this.consolaInstance.log(o,...e),this.logToFile("log",o,...e)}withTag(o){return this}close(){this.writeStream&&(this.writeStream.end(),this.writeStream=null)}},T=new I;import g from"chalk";import L from"cli-table3";import F from"ora";function U(n){let o=0;for(let e of n)/[\u4e00-\u9fff\u3400-\u4dbf\uff00-\uffef]/.test(e)?o+=2:o+=1;return o}l(U,"getDisplayWidth");function J(n,o){if(U(n)<=o)return n;if(o<=3)return"";let e="",t=0,i=!1;for(let r of n){let s=/[\u4e00-\u9fff\u3400-\u4dbf\uff00-\uffef]/.test(r)?2:1;if(t+s>o-3){if(!i)return"";e+="...";break}e+=r,t+=s,i=!0}return e}l(J,"truncateToWidth");async function G(n={}){let o=F("\u83B7\u53D6 MCP \u670D\u52A1\u5217\u8868...").start();try{let e=p.getMcpServers(),t=Object.keys(e);if(t.length===0){o.warn("\u672A\u914D\u7F6E\u4EFB\u4F55 MCP \u670D\u52A1"),console.log(g.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi config' \u547D\u4EE4\u914D\u7F6E MCP \u670D\u52A1"));return}if(o.succeed(`\u627E\u5230 ${t.length} \u4E2A MCP \u670D\u52A1`),n.tools){console.log(),console.log(g.bold("MCP \u670D\u52A1\u5DE5\u5177\u5217\u8868:")),console.log();let i=8,r=[];for(let a of t){let m=p.getServerToolsConfig(a),d=Object.keys(m);r.push(...d)}for(let a of r){let m=U(a);m>i&&(i=m)}i=Math.max(10,Math.min(i+2,30));let s=new L({head:[g.bold("MCP"),g.bold("\u5DE5\u5177\u540D\u79F0"),g.bold("\u72B6\u6001"),g.bold("\u63CF\u8FF0")],colWidths:[15,i,8,40],wordWrap:!0,style:{head:[],border:[]}});for(let a of t){let m=p.getServerToolsConfig(a),d=Object.keys(m);if(d.length===0)s.push([g.gray(a),g.gray("(\u65E0\u5DE5\u5177)"),g.gray("-"),g.gray("\u8BF7\u5148\u542F\u52A8\u670D\u52A1\u626B\u63CF\u5DE5\u5177")]);else{s.length>0&&s.push([{colSpan:4,content:""}]);for(let u of d){let y=m[u],S=y.enable?g.green("\u542F\u7528"):g.red("\u7981\u7528"),x=J(y.description||"",32);s.push([a,u,S,x])}}}console.log(s.toString())}else{console.log(),console.log(g.bold("MCP \u670D\u52A1\u5217\u8868:")),console.log();for(let i of t){let r=e[i],s=p.getServerToolsConfig(i),a=Object.keys(s).length,m=Object.values(s).filter(d=>d.enable!==!1).length;console.log(`${g.cyan("\u2022")} ${g.bold(i)}`),"type"in r&&r.type==="sse"?(console.log(` \u7C7B\u578B: ${g.gray("SSE")}`),console.log(` URL: ${g.gray(r.url)}`)):console.log(` \u547D\u4EE4: ${g.gray(r.command)} ${g.gray(r.args.join(" "))}`),a>0?console.log(` \u5DE5\u5177: ${g.green(m)} \u542F\u7528 / ${g.yellow(a)} \u603B\u8BA1`):console.log(` \u5DE5\u5177: ${g.gray("\u672A\u626B\u63CF (\u8BF7\u5148\u542F\u52A8\u670D\u52A1)")}`),console.log()}}console.log(g.gray("\u{1F4A1} \u63D0\u793A:")),console.log(g.gray(" - \u4F7F\u7528 'xiaozhi mcp list --tools' \u67E5\u770B\u6240\u6709\u5DE5\u5177")),console.log(g.gray(" - \u4F7F\u7528 'xiaozhi mcp <\u670D\u52A1\u540D> list' \u67E5\u770B\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177")),console.log(g.gray(" - \u4F7F\u7528 'xiaozhi mcp <\u670D\u52A1\u540D> <\u5DE5\u5177\u540D> enable/disable' \u542F\u7528/\u7981\u7528\u5DE5\u5177"))}catch(e){o.fail("\u83B7\u53D6 MCP \u670D\u52A1\u5217\u8868\u5931\u8D25"),console.error(g.red(`\u9519\u8BEF: ${e instanceof Error?e.message:String(e)}`)),process.exit(1)}}l(G,"listMcpServers");async function _(n){let o=F(`\u83B7\u53D6 ${n} \u670D\u52A1\u7684\u5DE5\u5177\u5217\u8868...`).start();try{if(!p.getMcpServers()[n]){o.fail(`\u670D\u52A1 '${n}' \u4E0D\u5B58\u5728`),console.log(g.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp list' \u67E5\u770B\u6240\u6709\u53EF\u7528\u670D\u52A1"));return}let t=p.getServerToolsConfig(n),i=Object.keys(t);if(i.length===0){o.warn(`\u670D\u52A1 '${n}' \u6682\u65E0\u5DE5\u5177\u4FE1\u606F`),console.log(g.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u542F\u52A8\u670D\u52A1\u4EE5\u626B\u63CF\u5DE5\u5177\u5217\u8868"));return}o.succeed(`\u670D\u52A1 '${n}' \u5171\u6709 ${i.length} \u4E2A\u5DE5\u5177`),console.log(),console.log(g.bold(`${n} \u670D\u52A1\u5DE5\u5177\u5217\u8868:`)),console.log();let r=new L({head:[g.bold("\u5DE5\u5177\u540D\u79F0"),g.bold("\u72B6\u6001"),g.bold("\u63CF\u8FF0")],colWidths:[30,8,50],wordWrap:!0,style:{head:[],border:[]}});for(let s of i){let a=t[s],m=a.enable?g.green("\u542F\u7528"):g.red("\u7981\u7528"),d=J(a.description||"",40);r.push([s,m,d])}console.log(r.toString()),console.log(),console.log(g.gray("\u{1F4A1} \u63D0\u793A:")),console.log(g.gray(` - \u4F7F\u7528 'xiaozhi mcp ${n} <\u5DE5\u5177\u540D> enable' \u542F\u7528\u5DE5\u5177`)),console.log(g.gray(` - \u4F7F\u7528 'xiaozhi mcp ${n} <\u5DE5\u5177\u540D> disable' \u7981\u7528\u5DE5\u5177`))}catch(e){o.fail("\u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25"),console.error(g.red(`\u9519\u8BEF: ${e instanceof Error?e.message:String(e)}`)),process.exit(1)}}l(_,"listServerTools");async function B(n,o,e){let t=e?"\u542F\u7528":"\u7981\u7528",i=F(`${t}\u5DE5\u5177 ${n}/${o}...`).start();try{if(!p.getMcpServers()[n]){i.fail(`\u670D\u52A1 '${n}' \u4E0D\u5B58\u5728`),console.log(g.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp list' \u67E5\u770B\u6240\u6709\u53EF\u7528\u670D\u52A1"));return}let s=p.getServerToolsConfig(n);if(!s[o]){i.fail(`\u5DE5\u5177 '${o}' \u5728\u670D\u52A1 '${n}' \u4E2D\u4E0D\u5B58\u5728`),console.log(g.yellow(`\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp ${n} list' \u67E5\u770B\u8BE5\u670D\u52A1\u7684\u6240\u6709\u5DE5\u5177`));return}p.setToolEnabled(n,o,e,s[o].description),i.succeed(`\u6210\u529F${t}\u5DE5\u5177 ${g.cyan(n)}/${g.cyan(o)}`),console.log(),console.log(g.gray("\u{1F4A1} \u63D0\u793A: \u5DE5\u5177\u72B6\u6001\u66F4\u6539\u5C06\u5728\u4E0B\u6B21\u542F\u52A8\u670D\u52A1\u65F6\u751F\u6548"))}catch(r){i.fail(`${t}\u5DE5\u5177\u5931\u8D25`),console.error(g.red(`\u9519\u8BEF: ${r instanceof Error?r.message:String(r)}`)),process.exit(1)}}l(B,"setToolEnabled");import{existsSync as N}from"fs";import{readFile as Z}from"fs/promises";import{createServer as ho}from"http";import{dirname as uo,join as w}from"path";import{parse as yo}from"url";import{fileURLToPath as So}from"url";import{WebSocketServer as Co}from"ws";var M=class{static{l(this,"WebServer")}httpServer;wss;logger;port;clientInfo={status:"disconnected",mcpEndpoint:"",activeMCPServers:[]};heartbeatTimeout;HEARTBEAT_TIMEOUT=35e3;constructor(o=9999){this.port=o,this.logger=new I,this.httpServer=ho((e,t)=>{this.handleHttpRequest(e,t)}),this.wss=new Co({server:this.httpServer}),this.setupWebSocket()}async handleHttpRequest(o,e){let{pathname:t}=yo(o.url||"",!0);if(e.setHeader("Access-Control-Allow-Origin","*"),e.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type"),o.method==="OPTIONS"){e.writeHead(200),e.end();return}try{if(o.method==="GET"&&!t?.startsWith("/api/")){await this.serveStaticFile(t||"/",e);return}if(t==="/api/config"&&o.method==="GET"){let i=p.getConfig();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(i))}else if(t==="/api/config"&&o.method==="PUT"){let i="";o.on("data",r=>{i+=r.toString()}),o.on("end",async()=>{try{let r=JSON.parse(i);this.updateConfig(r),e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({success:!0})),this.broadcastConfigUpdate(r)}catch(r){e.writeHead(400,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:r instanceof Error?r.message:String(r)}))}})}else t==="/api/status"&&o.method==="GET"?(e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(this.clientInfo))):(e.writeHead(404),e.end("Not Found"))}catch(i){this.logger.error("HTTP request error:",i),e.writeHead(500,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"Internal Server Error"}))}}async serveStaticFile(o,e){try{let t=uo(So(import.meta.url)),r=[w(t,"..","web","dist"),w(t,"..","web"),w(process.cwd(),"web","dist"),w(process.cwd(),"web")].find(S=>N(S));if(!r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(`
2
+ var to=Object.defineProperty;var g=(n,o)=>to(n,"name",{value:o,configurable:!0});import{spawn as X}from"child_process";import h from"fs";import vo from"os";import p from"path";import{fileURLToPath as j}from"url";import s from"chalk";import{Command as wo}from"commander";import C from"ora";import lo from"omelette";import{copyFileSync as no,existsSync as N,readFileSync as io,writeFileSync as ro}from"fs";import{dirname as so,resolve as R}from"path";import{fileURLToPath as co}from"url";var ao=so(co(import.meta.url)),k={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},O=class n{static{g(this,"ConfigManager")}static instance;defaultConfigPath;config=null;constructor(){this.defaultConfigPath=R(ao,"xiaozhi.config.default.json")}getConfigFilePath(){let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return R(o,"xiaozhi.config.json")}static getInstance(){return n.instance||(n.instance=new n),n.instance}configExists(){let o=this.getConfigFilePath();return N(o)}initConfig(){if(!N(this.defaultConfigPath))throw new Error("\u9ED8\u8BA4\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.default.json \u4E0D\u5B58\u5728");if(this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.json \u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u521D\u59CB\u5316");let o=this.getConfigFilePath();no(this.defaultConfigPath,o),this.config=null}loadConfig(){if(!this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6 xiaozhi.config.json \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u8FD0\u884C xiaozhi init \u521D\u59CB\u5316\u914D\u7F6E");try{let o=this.getConfigFilePath(),e=io(o,"utf8"),t=JSON.parse(e);return this.validateConfig(t),t}catch(o){throw o instanceof SyntaxError?new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF: ${o.message}`):o}}validateConfig(o){if(!o||typeof o!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A\u6839\u5BF9\u8C61\u65E0\u6548");let e=o;if(!e.mcpEndpoint||typeof e.mcpEndpoint!="string")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5B57\u6BB5\u65E0\u6548");if(!e.mcpServers||typeof e.mcpServers!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers \u5B57\u6BB5\u65E0\u6548");for(let[t,i]of Object.entries(e.mcpServers)){if(!i||typeof i!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t} \u65E0\u6548`);let r=i;if(r.type==="sse"){if(!r.url||typeof r.url!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.url \u65E0\u6548`)}else{if(!r.command||typeof r.command!="string")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.command \u65E0\u6548`);if(!Array.isArray(r.args))throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.args \u5FC5\u987B\u662F\u6570\u7EC4`);if(r.env&&typeof r.env!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${t}.env \u5FC5\u987B\u662F\u5BF9\u8C61`)}}}getConfig(){return this.config||(this.config=this.loadConfig()),JSON.parse(JSON.stringify(this.config))}getMcpEndpoint(){return this.getConfig().mcpEndpoint}getMcpServers(){return this.getConfig().mcpServers}getMcpServerConfig(){return this.getConfig().mcpServerConfig||{}}getServerToolsConfig(o){return this.getMcpServerConfig()[o]?.tools||{}}isToolEnabled(o,e){return this.getServerToolsConfig(o)[e]?.enable!==!1}updateMcpEndpoint(o){if(!o||typeof o!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t={...this.getConfig(),mcpEndpoint:o};this.saveConfig(t)}updateMcpServer(o,e){if(!o||typeof o!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if("type"in e&&e.type==="sse"){if(!e.url||typeof e.url!="string")throw new Error("SSE \u670D\u52A1\u914D\u7F6E\u7684 url \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else{let r=e;if(!r.command||typeof r.command!="string")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 command \u5B57\u6BB5\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!Array.isArray(r.args))throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 args \u5B57\u6BB5\u5FC5\u987B\u662F\u6570\u7EC4");if(r.env&&typeof r.env!="object")throw new Error("\u670D\u52A1\u914D\u7F6E\u7684 env \u5B57\u6BB5\u5FC5\u987B\u662F\u5BF9\u8C61")}let t=this.getConfig(),i={...t,mcpServers:{...t.mcpServers,[o]:e}};this.saveConfig(i)}removeMcpServer(o){if(!o||typeof o!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let e=this.getConfig();if(!e.mcpServers[o])throw new Error(`\u670D\u52A1 ${o} \u4E0D\u5B58\u5728`);let t={...e.mcpServers};delete t[o];let i={...e,mcpServers:t};this.saveConfig(i)}updateServerToolsConfig(o,e){let i={...this.getConfig()};i.mcpServerConfig||(i.mcpServerConfig={}),i.mcpServerConfig[o]={tools:e},this.saveConfig(i)}setToolEnabled(o,e,t,i){let c={...this.getConfig()};c.mcpServerConfig||(c.mcpServerConfig={}),c.mcpServerConfig[o]||(c.mcpServerConfig[o]={tools:{}}),c.mcpServerConfig[o].tools[e]={enable:t,...i&&{description:i}},this.saveConfig(c)}saveConfig(o){try{this.validateConfig(o);let e=this.getConfigFilePath(),t=JSON.stringify(o,null,2);ro(e,t,"utf8"),this.config=o}catch(e){throw new Error(`\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}reloadConfig(){this.config=null}getConfigPath(){return this.getConfigFilePath()}getDefaultConfigPath(){return this.defaultConfigPath}getConnectionConfig(){let e=this.getConfig().connection||{};return{heartbeatInterval:e.heartbeatInterval??k.heartbeatInterval,heartbeatTimeout:e.heartbeatTimeout??k.heartbeatTimeout,reconnectInterval:e.reconnectInterval??k.reconnectInterval}}getHeartbeatInterval(){return this.getConnectionConfig().heartbeatInterval}getHeartbeatTimeout(){return this.getConnectionConfig().heartbeatTimeout}getReconnectInterval(){return this.getConnectionConfig().reconnectInterval}updateConnectionConfig(o){let e=this.getConfig(),i={...e.connection||{},...o},r={...e,connection:i};this.saveConfig(r)}setHeartbeatInterval(o){if(o<=0)throw new Error("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatInterval:o})}setHeartbeatTimeout(o){if(o<=0)throw new Error("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatTimeout:o})}setReconnectInterval(o){if(o<=0)throw new Error("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({reconnectInterval:o})}getModelScopeConfig(){return this.getConfig().modelscope||{}}getModelScopeApiKey(){return this.getModelScopeConfig().apiKey||process.env.MODELSCOPE_API_TOKEN}updateModelScopeConfig(o){let e=this.getConfig(),i={...e.modelscope||{},...o},r={...e,modelscope:i};this.saveConfig(r)}setModelScopeApiKey(o){if(!o||typeof o!="string")throw new Error("API Key \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");this.updateModelScopeConfig({apiKey:o})}getWebUIConfig(){return this.getConfig().webUI||{}}getWebUIPort(){return this.getWebUIConfig().port??9999}updateWebUIConfig(o){let e=this.getConfig(),i={...e.webUI||{},...o},r={...e,webUI:i};this.saveConfig(r)}setWebUIPort(o){if(!Number.isInteger(o)||o<=0||o>65535)throw new Error("\u7AEF\u53E3\u53F7\u5FC5\u987B\u662F 1-65535 \u4E4B\u95F4\u7684\u6574\u6570");this.updateWebUIConfig({port:o})}},l=O.getInstance();function go(){try{if(!l.configExists())return[];let n=l.getMcpServers();return Object.keys(n)}catch{return[]}}g(go,"getMcpServerNames");function fo(n){try{if(!l.configExists())return[];let o=l.getServerToolsConfig(n);return Object.keys(o)}catch{return[]}}g(fo,"getServerToolNames");function D(){let n=lo("xiaozhi <command>");if(n.on("command",({reply:o})=>{o(["create","init","config","start","stop","status","attach","restart","mcp","completion"])}),n.on("complete",(o,{line:e,before:t,reply:i})=>{process.env.XIAOZHI_DEBUG_COMPLETION&&console.error(`Debug completion - line: "${e}", before: "${t}", fragment: "${o}"`);let r=e.trim().split(/\s+/),a=e!==e.trim()?r.length:r.length-1;if(r[1]==="mcp"){let d=r[2];if(a===2){let m=["list","server","tool"],u=r[2]||"",y=m.filter(b=>b.startsWith(u));i(y);return}if(a===3){switch(d){case"list":{let m=["--tools"],u=r[3]||"",y=m.filter(b=>b.startsWith(u));i(y);break}case"server":case"tool":{let m=go(),u=r[3]||"",y=m.filter(b=>b.startsWith(u));i(y);break}default:i([])}return}if(a===4&&d==="tool"){let m=r[3],u=fo(m),y=r[4]||"",b=u.filter(I=>I.startsWith(y));i(b);return}if(a===5&&d==="tool"){let m=["enable","disable"],u=r[5]||"",y=m.filter(b=>b.startsWith(u));i(y);return}}if(a===2){switch(r[1]){case"create":i(["--template","-t"]);break;case"start":case"restart":i(["--daemon","-d"]);break;case"completion":i(["install","uninstall"]);break;default:i([])}return}i([])}),process.argv.includes("--completion")){try{console.log(n.setupShellInitFile())}catch(o){console.error("\u751F\u6210\u81EA\u52A8\u8865\u5168\u811A\u672C\u65F6\u51FA\u9519:",o)}process.exit(0)}process.argv.includes("--completion-fish")&&(console.log(n.setupShellInitFile("fish")),process.exit(0)),process.argv.includes("--compzsh")||process.argv.includes("--compbash"),n.init()}g(D,"setupAutoCompletion");function A(){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(A,"showCompletionHelp");import M from"fs";import po from"path";import x from"chalk";import{createConsola as mo}from"consola";function uo(n){let o=n.getFullYear(),e=String(n.getMonth()+1).padStart(2,"0"),t=String(n.getDate()).padStart(2,"0"),i=String(n.getHours()).padStart(2,"0"),r=String(n.getMinutes()).padStart(2,"0"),c=String(n.getSeconds()).padStart(2,"0");return`${o}-${e}-${t} ${i}:${r}:${c}`}g(uo,"formatDateTime");var P=class{static{g(this,"Logger")}logFilePath=null;writeStream=null;consolaInstance;isDaemonMode;constructor(){this.isDaemonMode=process.env.XIAOZHI_DAEMON==="true",this.consolaInstance=mo({formatOptions:{date:!1,colors:!0,compact:!0},fancy:!1});let o=this.isDaemonMode;this.consolaInstance.setReporters([{log:g(e=>{let t={info:"INFO",success:"SUCCESS",warn:"WARN",error:"ERROR",debug:"DEBUG",log:"LOG"},i={info:x.blue,success:x.green,warn:x.yellow,error:x.red,debug:x.gray,log:g(u=>u,"log")},r=t[e.type]||e.type.toUpperCase(),c=i[e.type]||(u=>u),a=uo(new Date),d=c(`[${r}]`),m=`[${a}] ${d} ${e.args.join(" ")}`;if(!o)try{console.error(m)}catch(u){if(u instanceof Error&&u.message?.includes("EPIPE"))return;throw u}},"log")}])}initLogFile(o){this.logFilePath=po.join(o,"xiaozhi.log"),M.existsSync(this.logFilePath)||M.writeFileSync(this.logFilePath,""),this.writeStream=M.createWriteStream(this.logFilePath,{flags:"a",encoding:"utf8"})}logToFile(o,e,...t){if(this.writeStream){let r=`[${new Date().toISOString()}] [${o.toUpperCase()}] ${e}`,c=t.length>0?`${r} ${t.map(a=>typeof a=="object"?JSON.stringify(a):String(a)).join(" ")}`:r;this.writeStream.write(`${c}
3
+ `)}}enableFileLogging(o){o&&!this.writeStream&&this.logFilePath?this.writeStream=M.createWriteStream(this.logFilePath,{flags:"a",encoding:"utf8"}):!o&&this.writeStream&&(this.writeStream.end(),this.writeStream=null)}info(o,...e){this.consolaInstance.info(o,...e),this.logToFile("info",o,...e)}success(o,...e){this.consolaInstance.success(o,...e),this.logToFile("success",o,...e)}warn(o,...e){this.consolaInstance.warn(o,...e),this.logToFile("warn",o,...e)}error(o,...e){this.consolaInstance.error(o,...e),this.logToFile("error",o,...e)}debug(o,...e){this.consolaInstance.debug(o,...e),this.logToFile("debug",o,...e)}log(o,...e){this.consolaInstance.log(o,...e),this.logToFile("log",o,...e)}withTag(o){return this}close(){this.writeStream&&(this.writeStream.end(),this.writeStream=null)}},$=new P;import f from"chalk";import H from"cli-table3";import U from"ora";function _(n){let o=0;for(let e of n)/[\u4e00-\u9fff\u3400-\u4dbf\uff00-\uffef]/.test(e)?o+=2:o+=1;return o}g(_,"getDisplayWidth");function L(n,o){if(_(n)<=o)return n;if(o<=3)return"";let e="",t=0,i=!1;for(let r of n){let c=/[\u4e00-\u9fff\u3400-\u4dbf\uff00-\uffef]/.test(r)?2:1;if(t+c>o-3){if(!i)return"";e+="...";break}e+=r,t+=c,i=!0}return e}g(L,"truncateToWidth");async function J(n={}){let o=U("\u83B7\u53D6 MCP \u670D\u52A1\u5217\u8868...").start();try{let e=l.getMcpServers(),t=Object.keys(e);if(t.length===0){o.warn("\u672A\u914D\u7F6E\u4EFB\u4F55 MCP \u670D\u52A1"),console.log(f.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi config' \u547D\u4EE4\u914D\u7F6E MCP \u670D\u52A1"));return}if(o.succeed(`\u627E\u5230 ${t.length} \u4E2A MCP \u670D\u52A1`),n.tools){console.log(),console.log(f.bold("MCP \u670D\u52A1\u5DE5\u5177\u5217\u8868:")),console.log();let i=8,r=[];for(let a of t){let d=l.getServerToolsConfig(a),m=Object.keys(d);r.push(...m)}for(let a of r){let d=_(a);d>i&&(i=d)}i=Math.max(10,Math.min(i+2,30));let c=new H({head:[f.bold("MCP"),f.bold("\u5DE5\u5177\u540D\u79F0"),f.bold("\u72B6\u6001"),f.bold("\u63CF\u8FF0")],colWidths:[15,i,8,40],wordWrap:!0,style:{head:[],border:[]}});for(let a of t){let d=l.getServerToolsConfig(a),m=Object.keys(d);if(m.length===0)c.push([f.gray(a),f.gray("(\u65E0\u5DE5\u5177)"),f.gray("-"),f.gray("\u8BF7\u5148\u542F\u52A8\u670D\u52A1\u626B\u63CF\u5DE5\u5177")]);else{c.length>0&&c.push([{colSpan:4,content:""}]);for(let u of m){let y=d[u],b=y.enable?f.green("\u542F\u7528"):f.red("\u7981\u7528"),I=L(y.description||"",32);c.push([a,u,b,I])}}}console.log(c.toString())}else{console.log(),console.log(f.bold("MCP \u670D\u52A1\u5217\u8868:")),console.log();for(let i of t){let r=e[i],c=l.getServerToolsConfig(i),a=Object.keys(c).length,d=Object.values(c).filter(m=>m.enable!==!1).length;console.log(`${f.cyan("\u2022")} ${f.bold(i)}`),"type"in r&&r.type==="sse"?(console.log(` \u7C7B\u578B: ${f.gray("SSE")}`),console.log(` URL: ${f.gray(r.url)}`)):console.log(` \u547D\u4EE4: ${f.gray(r.command)} ${f.gray(r.args.join(" "))}`),a>0?console.log(` \u5DE5\u5177: ${f.green(d)} \u542F\u7528 / ${f.yellow(a)} \u603B\u8BA1`):console.log(` \u5DE5\u5177: ${f.gray("\u672A\u626B\u63CF (\u8BF7\u5148\u542F\u52A8\u670D\u52A1)")}`),console.log()}}console.log(f.gray("\u{1F4A1} \u63D0\u793A:")),console.log(f.gray(" - \u4F7F\u7528 'xiaozhi mcp list --tools' \u67E5\u770B\u6240\u6709\u5DE5\u5177")),console.log(f.gray(" - \u4F7F\u7528 'xiaozhi mcp <\u670D\u52A1\u540D> list' \u67E5\u770B\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177")),console.log(f.gray(" - \u4F7F\u7528 'xiaozhi mcp <\u670D\u52A1\u540D> <\u5DE5\u5177\u540D> enable/disable' \u542F\u7528/\u7981\u7528\u5DE5\u5177"))}catch(e){o.fail("\u83B7\u53D6 MCP \u670D\u52A1\u5217\u8868\u5931\u8D25"),console.error(f.red(`\u9519\u8BEF: ${e instanceof Error?e.message:String(e)}`)),process.exit(1)}}g(J,"listMcpServers");async function G(n){let o=U(`\u83B7\u53D6 ${n} \u670D\u52A1\u7684\u5DE5\u5177\u5217\u8868...`).start();try{if(!l.getMcpServers()[n]){o.fail(`\u670D\u52A1 '${n}' \u4E0D\u5B58\u5728`),console.log(f.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp list' \u67E5\u770B\u6240\u6709\u53EF\u7528\u670D\u52A1"));return}let t=l.getServerToolsConfig(n),i=Object.keys(t);if(i.length===0){o.warn(`\u670D\u52A1 '${n}' \u6682\u65E0\u5DE5\u5177\u4FE1\u606F`),console.log(f.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u542F\u52A8\u670D\u52A1\u4EE5\u626B\u63CF\u5DE5\u5177\u5217\u8868"));return}o.succeed(`\u670D\u52A1 '${n}' \u5171\u6709 ${i.length} \u4E2A\u5DE5\u5177`),console.log(),console.log(f.bold(`${n} \u670D\u52A1\u5DE5\u5177\u5217\u8868:`)),console.log();let r=new H({head:[f.bold("\u5DE5\u5177\u540D\u79F0"),f.bold("\u72B6\u6001"),f.bold("\u63CF\u8FF0")],colWidths:[30,8,50],wordWrap:!0,style:{head:[],border:[]}});for(let c of i){let a=t[c],d=a.enable?f.green("\u542F\u7528"):f.red("\u7981\u7528"),m=L(a.description||"",40);r.push([c,d,m])}console.log(r.toString()),console.log(),console.log(f.gray("\u{1F4A1} \u63D0\u793A:")),console.log(f.gray(` - \u4F7F\u7528 'xiaozhi mcp ${n} <\u5DE5\u5177\u540D> enable' \u542F\u7528\u5DE5\u5177`)),console.log(f.gray(` - \u4F7F\u7528 'xiaozhi mcp ${n} <\u5DE5\u5177\u540D> disable' \u7981\u7528\u5DE5\u5177`))}catch(e){o.fail("\u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25"),console.error(f.red(`\u9519\u8BEF: ${e instanceof Error?e.message:String(e)}`)),process.exit(1)}}g(G,"listServerTools");async function B(n,o,e){let t=e?"\u542F\u7528":"\u7981\u7528",i=U(`${t}\u5DE5\u5177 ${n}/${o}...`).start();try{if(!l.getMcpServers()[n]){i.fail(`\u670D\u52A1 '${n}' \u4E0D\u5B58\u5728`),console.log(f.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp list' \u67E5\u770B\u6240\u6709\u53EF\u7528\u670D\u52A1"));return}let c=l.getServerToolsConfig(n);if(!c[o]){i.fail(`\u5DE5\u5177 '${o}' \u5728\u670D\u52A1 '${n}' \u4E2D\u4E0D\u5B58\u5728`),console.log(f.yellow(`\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 'xiaozhi mcp ${n} list' \u67E5\u770B\u8BE5\u670D\u52A1\u7684\u6240\u6709\u5DE5\u5177`));return}l.setToolEnabled(n,o,e,c[o].description),i.succeed(`\u6210\u529F${t}\u5DE5\u5177 ${f.cyan(n)}/${f.cyan(o)}`),console.log(),console.log(f.gray("\u{1F4A1} \u63D0\u793A: \u5DE5\u5177\u72B6\u6001\u66F4\u6539\u5C06\u5728\u4E0B\u6B21\u542F\u52A8\u670D\u52A1\u65F6\u751F\u6548"))}catch(r){i.fail(`${t}\u5DE5\u5177\u5931\u8D25`),console.error(f.red(`\u9519\u8BEF: ${r instanceof Error?r.message:String(r)}`)),process.exit(1)}}g(B,"setToolEnabled");import{existsSync as W}from"fs";import{readFile as Z}from"fs/promises";import{createServer as ho}from"http";import{dirname as yo,join as w}from"path";import{parse as bo}from"url";import{fileURLToPath as So}from"url";import{WebSocketServer as Co}from"ws";var T=class{static{g(this,"WebServer")}httpServer;wss;logger;port;clientInfo={status:"disconnected",mcpEndpoint:"",activeMCPServers:[]};heartbeatTimeout;HEARTBEAT_TIMEOUT=35e3;constructor(o){if(o===void 0)try{this.port=l.getWebUIPort()}catch{this.port=9999}else this.port=o;this.logger=new P,this.httpServer=ho((e,t)=>{this.handleHttpRequest(e,t)}),this.wss=new Co({server:this.httpServer}),this.setupWebSocket()}async handleHttpRequest(o,e){let{pathname:t}=bo(o.url||"",!0);if(e.setHeader("Access-Control-Allow-Origin","*"),e.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type"),o.method==="OPTIONS"){e.writeHead(200),e.end();return}try{if(o.method==="GET"&&!t?.startsWith("/api/")){await this.serveStaticFile(t||"/",e);return}if(t==="/api/config"&&o.method==="GET"){let i=l.getConfig();e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(i))}else if(t==="/api/config"&&o.method==="PUT"){let i="";o.on("data",r=>{i+=r.toString()}),o.on("end",async()=>{try{let r=JSON.parse(i);this.updateConfig(r),e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({success:!0})),this.broadcastConfigUpdate(r)}catch(r){e.writeHead(400,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:r instanceof Error?r.message:String(r)}))}})}else t==="/api/status"&&o.method==="GET"?(e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(this.clientInfo))):(e.writeHead(404),e.end("Not Found"))}catch(i){this.logger.error("HTTP request error:",i),e.writeHead(500,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"Internal Server Error"}))}}async serveStaticFile(o,e){try{let t=yo(So(import.meta.url)),r=[w(t,"..","web","dist"),w(t,"..","web"),w(process.cwd(),"web","dist"),w(process.cwd(),"web")].find(b=>W(b));if(!r){e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(`
4
4
  <!DOCTYPE html>
5
5
  <html>
6
6
  <head>
@@ -20,11 +20,12 @@ var eo=Object.defineProperty;var l=(n,o)=>eo(n,"name",{value:o,configurable:!0})
20
20
  </div>
21
21
  </body>
22
22
  </html>
23
- `);return}let s=o;if(s==="/"&&(s="/index.html"),s.includes("..")){e.writeHead(403),e.end("Forbidden");return}let a=w(r,s);if(!N(a)){let S=w(r,"index.html");if(N(S)){let x=await Z(S);e.writeHead(200,{"Content-Type":"text/html"}),e.end(x)}else e.writeHead(404),e.end("Not Found");return}let m=await Z(a),d=a.split(".").pop()?.toLowerCase(),y={html:"text/html",js:"application/javascript",css:"text/css",json:"application/json",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",svg:"image/svg+xml",ico:"image/x-icon"}[d||""]||"application/octet-stream";e.writeHead(200,{"Content-Type":y}),e.end(m)}catch(t){this.logger.error("Serve static file error:",t),e.writeHead(500),e.end("Internal Server Error")}}setupWebSocket(){this.wss.on("connection",o=>{this.logger.info("WebSocket client connected"),o.on("message",async e=>{try{let t=JSON.parse(e.toString());await this.handleWebSocketMessage(o,t)}catch(t){this.logger.error("WebSocket message error:",t),o.send(JSON.stringify({type:"error",error:t instanceof Error?t.message:String(t)}))}}),o.on("close",()=>{this.logger.info("WebSocket client disconnected")}),this.sendInitialData(o)})}async handleWebSocketMessage(o,e){switch(e.type){case"getConfig":{let t=p.getConfig();o.send(JSON.stringify({type:"config",data:t}));break}case"updateConfig":this.updateConfig(e.config),this.broadcastConfigUpdate(e.config);break;case"getStatus":o.send(JSON.stringify({type:"status",data:this.clientInfo}));break;case"clientStatus":this.updateClientInfo(e.data),this.broadcastStatusUpdate();break}}async sendInitialData(o){let e=p.getConfig();o.send(JSON.stringify({type:"config",data:e})),o.send(JSON.stringify({type:"status",data:this.clientInfo}))}broadcastConfigUpdate(o){let e=JSON.stringify({type:"configUpdate",data:o});for(let t of this.wss.clients)t.readyState===1&&t.send(e)}broadcastStatusUpdate(){let o=JSON.stringify({type:"statusUpdate",data:this.clientInfo});for(let e of this.wss.clients)e.readyState===1&&e.send(o)}updateClientInfo(o){this.clientInfo={...this.clientInfo,...o},o.lastHeartbeat&&(this.clientInfo.lastHeartbeat=Date.now()),o.status==="connected"&&this.resetHeartbeatTimeout()}resetHeartbeatTimeout(){this.heartbeatTimeout&&clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=setTimeout(()=>{this.logger.warn("\u5BA2\u6237\u7AEF\u5FC3\u8DF3\u8D85\u65F6\uFF0C\u6807\u8BB0\u4E3A\u65AD\u5F00\u8FDE\u63A5"),this.updateClientInfo({status:"disconnected"}),this.broadcastStatusUpdate()},this.HEARTBEAT_TIMEOUT)}updateConfig(o){o.mcpEndpoint!==p.getMcpEndpoint()&&p.updateMcpEndpoint(o.mcpEndpoint);let e=p.getMcpServers();for(let[t,i]of Object.entries(o.mcpServers))JSON.stringify(e[t])!==JSON.stringify(i)&&p.updateMcpServer(t,i);for(let t of Object.keys(e))t in o.mcpServers||p.removeMcpServer(t);if(o.connection&&p.updateConnectionConfig(o.connection),o.modelscope&&p.updateModelScopeConfig(o.modelscope),o.mcpServerConfig)for(let[t,i]of Object.entries(o.mcpServerConfig))for(let[r,s]of Object.entries(i.tools))p.setToolEnabled(t,r,s.enable)}updateStatus(o){this.updateClientInfo(o),this.broadcastStatusUpdate()}start(){return new Promise((o,e)=>{this.httpServer.listen(this.port,()=>{this.logger.info(`Web server listening on http://localhost:${this.port}`),o()}).on("error",e)})}stop(){return new Promise(o=>{this.heartbeatTimeout&&(clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=void 0),this.wss.close(()=>{this.httpServer.close(()=>{this.logger.info("Web server stopped"),o()})})})}};var C=new vo,wo="xiaozhi-mcp-service";function Y(){try{let n=j(import.meta.url),o=f.dirname(n),e=[f.join(o,"..","package.json"),f.join(o,"..","package.json"),f.join(o,"..","..","package.json"),f.join(o,"package.json")];for(let t of e)if(h.existsSync(t)){let i=JSON.parse(h.readFileSync(t,"utf8"));if(i.version)return i.version}return"unknown"}catch(n){return console.warn("\u65E0\u6CD5\u4ECE package.json \u8BFB\u53D6\u7248\u672C\u4FE1\u606F:",n),"unknown"}}l(Y,"getVersion");var v=f.join(bo.tmpdir(),`${wo}.pid`);function z(){try{if(!h.existsSync(v))return{running:!1};let n=h.readFileSync(v,"utf8").trim(),[o,e,t]=n.split("|"),i=Number.parseInt(o);if(Number.isNaN(i))return h.unlinkSync(v),{running:!1};try{process.kill(i,0);let r=Number.parseInt(e),s=xo(Date.now()-r);return{running:!0,pid:i,uptime:s,mode:t||"foreground"}}catch{return h.unlinkSync(v),{running:!1}}}catch{return{running:!1}}}l(z,"getServiceStatus");function xo(n){let o=Math.floor(n/1e3),e=Math.floor(o/60),t=Math.floor(e/60),i=Math.floor(t/24);return i>0?`${i}\u5929 ${t%24}\u5C0F\u65F6 ${e%60}\u5206\u949F`:t>0?`${t}\u5C0F\u65F6 ${e%60}\u5206\u949F`:e>0?`${e}\u5206\u949F ${o%60}\u79D2`:`${o}\u79D2`}l(xo,"formatUptime");function V(n,o){let e=`${n}|${Date.now()}|${o}`;h.writeFileSync(v,e)}l(V,"savePidInfo");function $(){try{h.existsSync(v)&&h.unlinkSync(v)}catch{}}l($,"cleanupPidFile");function Po(){if(!p.configExists())return console.error(c.red("\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728")),console.log(c.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E')),!1;try{let n=p.getMcpEndpoint();return!n||n.includes("<\u8BF7\u586B\u5199")?(console.error(c.red("\u274C \u9519\u8BEF: MCP \u7AEF\u70B9\u672A\u914D\u7F6E")),console.log(c.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi config mcpEndpoint <your-endpoint-url>" \u8BBE\u7F6E\u7AEF\u70B9')),!1):!0}catch(n){return console.error(c.red(`\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u65E0\u6548 - ${n instanceof Error?n.message:String(n)}`)),console.log(c.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u91CD\u65B0\u521D\u59CB\u5316\u914D\u7F6E')),!1}}l(Po,"checkEnvironment");function Io(){let n=f.dirname(j(import.meta.url)),o;return n.includes("js-demo/dist")?o=n:o=[f.join(n,"..","js-demo","dist"),f.join(n,"..","..","js-demo","dist"),f.join(n,"..","..","..","js-demo","dist"),f.join(process.cwd(),"js-demo","dist"),f.join(process.cwd(),"dist")].find(t=>h.existsSync(f.join(t,"mcpPipe.js"))&&h.existsSync(f.join(t,"mcpServerProxy.js")))||n,{command:"node",args:["mcpPipe.js","mcpServerProxy.js"],cwd:o}}l(Io,"getServiceCommand");async function Q(n=!1){let o=b("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let e=z();if(e.running){o.fail(`\u670D\u52A1\u5DF2\u7ECF\u5728\u8FD0\u884C (PID: ${e.pid})`);return}if(o.text="\u68C0\u67E5\u73AF\u5883\u914D\u7F6E...",!Po()){o.fail("\u73AF\u5883\u914D\u7F6E\u68C0\u67E5\u5931\u8D25");return}let{command:t,args:i,cwd:r}=Io();if(o.text=`\u542F\u52A8\u670D\u52A1 (${n?"\u540E\u53F0\u6A21\u5F0F":"\u524D\u53F0\u6A21\u5F0F"})...`,n){let s=K(t,i,{cwd:r,detached:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd(),XIAOZHI_DAEMON:"true"}});V(s.pid,"daemon");let a=process.cwd();T.initLogFile(a),T.enableFileLogging(!0);let m=f.join(a,"xiaozhi.log"),d=h.createWriteStream(m,{flags:"a"});s.stdout?.pipe(d),s.stderr?.pipe(d),s.on("exit",(u,y)=>{u!==0&&u!==null&&T.error(`\u540E\u53F0\u670D\u52A1\u5F02\u5E38\u9000\u51FA (\u4EE3\u7801: ${u}, \u4FE1\u53F7: ${y})`),$()}),s.on("error",u=>{T.error(`\u540E\u53F0\u670D\u52A1\u542F\u52A8\u9519\u8BEF: ${u.message}`),$(),o.fail(`\u540E\u53F0\u670D\u52A1\u542F\u52A8\u5931\u8D25: ${u.message}`)}),s.unref(),o.succeed(`\u670D\u52A1\u5DF2\u5728\u540E\u53F0\u542F\u52A8 (PID: ${s.pid})`),console.log(c.gray(`\u65E5\u5FD7\u6587\u4EF6: ${m}`)),console.log(c.gray("\u4F7F\u7528 'xiaozhi attach' \u53EF\u4EE5\u67E5\u770B\u5B9E\u65F6\u65E5\u5FD7"))}else{o.succeed("\u670D\u52A1\u542F\u52A8\u4E2D...");let s=K(t,i,{cwd:r,stdio:"inherit",env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd()}});V(s.pid,"foreground"),s.on("exit",(a,m)=>{$(),console.log(a!==0?c.red(`
24
- \u670D\u52A1\u5F02\u5E38\u9000\u51FA (\u4EE3\u7801: ${a}, \u4FE1\u53F7: ${m})`):c.green(`
25
- \u670D\u52A1\u5DF2\u505C\u6B62`))}),process.on("SIGINT",()=>{console.log(c.yellow(`
26
- \u6B63\u5728\u505C\u6B62\u670D\u52A1...`)),s.kill("SIGTERM")}),process.on("SIGTERM",()=>{s.kill("SIGTERM")})}}catch(e){o.fail(`\u542F\u52A8\u670D\u52A1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}l(Q,"startService");async function q(){let n=b("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let o=z();if(!o.running){n.warn("\u670D\u52A1\u672A\u5728\u8FD0\u884C");return}n.text=`\u505C\u6B62\u670D\u52A1 (PID: ${o.pid})...`;try{process.kill(o.pid,"SIGTERM");let e=0,t=30;for(;e<t;){await new Promise(i=>setTimeout(i,100));try{process.kill(o.pid,0),e++}catch{break}}try{process.kill(o.pid,0),n.text="\u5F3A\u5236\u505C\u6B62\u670D\u52A1...",process.kill(o.pid,"SIGKILL"),await new Promise(i=>setTimeout(i,500))}catch{}$(),n.succeed("\u670D\u52A1\u5DF2\u505C\u6B62")}catch(e){$(),n.fail(`\u505C\u6B62\u670D\u52A1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}catch(o){n.fail(`\u505C\u6B62\u670D\u52A1\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}l(q,"stopService");async function To(){let n=b("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let o=z();if(o.running){if(n.succeed("\u670D\u52A1\u72B6\u6001"),console.log(c.green("\u2705 \u670D\u52A1\u6B63\u5728\u8FD0\u884C")),console.log(c.gray(` PID: ${o.pid}`)),console.log(c.gray(` \u8FD0\u884C\u65F6\u95F4: ${o.uptime}`)),console.log(c.gray(` \u8FD0\u884C\u6A21\u5F0F: ${o.mode==="daemon"?"\u540E\u53F0\u6A21\u5F0F":"\u524D\u53F0\u6A21\u5F0F"}`)),o.mode==="daemon"){let e=f.join(process.cwd(),"xiaozhi.log");console.log(c.gray(` \u65E5\u5FD7\u6587\u4EF6: ${e}`))}}else n.succeed("\u670D\u52A1\u72B6\u6001"),console.log(c.red("\u274C \u670D\u52A1\u672A\u8FD0\u884C"))}catch(o){n.fail(`\u68C0\u67E5\u72B6\u6001\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}l(To,"checkStatus");async function $o(){let n=b("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let o=z();if(!o.running){n.fail("\u670D\u52A1\u672A\u5728\u8FD0\u884C");return}if(o.mode!=="daemon"){n.fail("\u670D\u52A1\u4E0D\u662F\u5728\u540E\u53F0\u6A21\u5F0F\u8FD0\u884C");return}n.succeed("\u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1..."),console.log(c.green(`\u5DF2\u8FDE\u63A5\u5230\u670D\u52A1 (PID: ${o.pid})`)),console.log(c.gray("\u6309 Ctrl+C \u53EF\u4EE5\u65AD\u5F00\u8FDE\u63A5\uFF08\u4E0D\u4F1A\u505C\u6B62\u670D\u52A1\uFF09")),console.log(c.gray("=".repeat(50)));let e=f.join(process.cwd(),"xiaozhi.log");if(h.existsSync(e))if(process.platform==="win32"){let{spawn:t}=await import("child_process"),i=t("powershell",["-Command",`Get-Content -Path "${e}" -Wait`],{stdio:"inherit"});process.on("SIGINT",()=>{console.log(c.yellow(`
27
- \u65AD\u5F00\u8FDE\u63A5\uFF0C\u670D\u52A1\u7EE7\u7EED\u5728\u540E\u53F0\u8FD0\u884C`)),i.kill(),process.exit(0)}),i.on("exit",()=>{process.exit(0)})}else{let{spawn:t}=await import("child_process"),i=t("tail",["-f",e],{stdio:"inherit"});process.on("SIGINT",()=>{console.log(c.yellow(`
28
- \u65AD\u5F00\u8FDE\u63A5\uFF0C\u670D\u52A1\u7EE7\u7EED\u5728\u540E\u53F0\u8FD0\u884C`)),i.kill(),process.exit(0)}),i.on("exit",()=>{process.exit(0)})}else console.log(c.yellow("\u65E5\u5FD7\u6587\u4EF6\u4E0D\u5B58\u5728"))}catch(o){n.fail(`\u8FDE\u63A5\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}l($o,"attachService");async function Eo(n=!1){console.log(c.blue("\u{1F504} \u91CD\u542F\u670D\u52A1...")),await q(),await new Promise(o=>setTimeout(o,1e3)),await Q(n)}l(Eo,"restartService");function Mo(){let n=Y();console.log(c.blue(`xiaozhi v${n}`)),console.log(c.gray("MCP Calculator Service CLI Tool")),console.log(c.gray("Built with Node.js and TypeScript")),console.log(c.gray(`Node.js: ${process.version}`)),console.log(c.gray(`Platform: ${process.platform} ${process.arch}`))}l(Mo,"showDetailedInfo");async function jo(){let n=b("\u521D\u59CB\u5316\u914D\u7F6E...").start();try{if(p.configExists()){n.warn("\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728"),console.log(c.yellow("\u5982\u9700\u91CD\u65B0\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u5220\u9664\u73B0\u6709\u7684 xiaozhi.config.json \u6587\u4EF6"));return}p.initConfig(),n.succeed("\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u6210\u529F"),console.log(c.green("\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u521B\u5EFA: xiaozhi.config.json")),console.log(c.yellow("\u{1F4DD} \u8BF7\u7F16\u8F91\u914D\u7F6E\u6587\u4EF6\u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9:")),console.log(c.gray(` \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84: ${p.getConfigPath()}`)),console.log(c.yellow("\u{1F4A1} \u6216\u8005\u4F7F\u7528\u547D\u4EE4\u8BBE\u7F6E:")),console.log(c.gray(" xiaozhi config mcpEndpoint <your-endpoint-url>"))}catch(o){n.fail(`\u521D\u59CB\u5316\u914D\u7F6E\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}l(jo,"initConfig");function zo(){let n=f.dirname(j(import.meta.url)),e=[f.join(n,"..","templates"),f.join(n,"templates"),f.join(n,"..","..","templates")].find(t=>h.existsSync(t));return e?h.readdirSync(e).filter(t=>{let i=f.join(e,t);return h.statSync(i).isDirectory()}):[]}l(zo,"getAvailableTemplates");function X(n,o){let e=n.length,t=o.length,i=Array(e+1).fill(null).map(()=>Array(t+1).fill(0));for(let s=0;s<=e;s++)i[s][0]=s;for(let s=0;s<=t;s++)i[0][s]=s;for(let s=1;s<=e;s++)for(let a=1;a<=t;a++)n[s-1]===o[a-1]?i[s][a]=i[s-1][a-1]:i[s][a]=Math.min(i[s-1][a]+1,i[s][a-1]+1,i[s-1][a-1]+1);let r=Math.max(e,t);return r===0?1:(r-i[e][t])/r}l(X,"calculateSimilarity");function ko(n,o){if(o.length===0)return null;let e=o[0],t=X(n.toLowerCase(),e.toLowerCase());for(let i of o.slice(1)){let r=X(n.toLowerCase(),i.toLowerCase());r>t&&(t=r,e=i)}return t>.5?e:null}l(ko,"findSimilarTemplate");async function Oo(n){if(!process.stdin.isTTY)return console.log("n (\u975E\u4EA4\u4E92\u5F0F\u73AF\u5883)"),!1;let o=await import("readline");return new Promise(e=>{process.stdout.write(n);let t=o.createInterface({input:process.stdin,output:process.stdout}),i=l(r=>{let s=r.trim().toLowerCase();s==="y"||s==="yes"?(t.close(),e(!0)):s==="n"||s==="no"||s===""?(t.close(),e(!1)):process.stdout.write("\u8BF7\u8F93\u5165 y \u6216 n: ")},"handleInput");t.on("line",i),t.on("SIGINT",()=>{t.close(),e(!1)})})}l(Oo,"askUserConfirmation");function Fo(n){let o={mcpEndpoint:"<\u8BF7\u586B\u5199\u4F60\u7684\u63A5\u5165\u70B9\u5730\u5740\uFF08\u83B7\u53D6\u5730\u5740\u5728 xiaozhi.me\uFF09>",mcpServers:{}},e=f.join(n,"xiaozhi.config.json");h.writeFileSync(e,JSON.stringify(o,null,2),"utf8")}l(Fo,"createBasicConfig");async function No(n,o){let e=b("\u521D\u59CB\u5316\u9879\u76EE...").start();try{let t=f.join(process.cwd(),n);if(h.existsSync(t)){e.fail(`\u76EE\u5F55 "${n}" \u5DF2\u5B58\u5728`),console.log(c.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u9009\u62E9\u4E0D\u540C\u7684\u9879\u76EE\u540D\u79F0\u6216\u5220\u9664\u73B0\u6709\u76EE\u5F55"));return}if(o.template){e.text="\u68C0\u67E5\u6A21\u677F...";let i=zo();if(i.length===0){e.fail("\u627E\u4E0D\u5230 templates \u76EE\u5F55"),console.log(c.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u786E\u4FDD xiaozhi-client \u6B63\u786E\u5B89\u88C5"));return}if(!i.includes(o.template)){e.fail(`\u6A21\u677F "${o.template}" \u4E0D\u5B58\u5728`);let u=ko(o.template,i);if(u)if(console.log(c.yellow(`\u{1F4A1} \u4F60\u662F\u60F3\u4F7F\u7528\u6A21\u677F "${u}" \u5417\uFF1F`)),await Oo(c.cyan("\u786E\u8BA4\u4F7F\u7528\u6B64\u6A21\u677F\uFF1F(y/n): ")))o.template=u;else{console.log(c.yellow("\u53EF\u7528\u7684\u6A21\u677F:"));for(let S of i)console.log(c.gray(` - ${S}`));return}else{console.log(c.yellow("\u53EF\u7528\u7684\u6A21\u677F:"));for(let y of i)console.log(c.gray(` - ${y}`));return}}let r=f.dirname(j(import.meta.url)),a=[f.join(r,"..","templates"),f.join(r,"templates"),f.join(r,"..","..","templates")].find(u=>h.existsSync(u)),m=f.join(a,o.template);e.text=`\u4ECE\u6A21\u677F "${o.template}" \u521B\u5EFA\u9879\u76EE "${n}"...`,oo(m,t,["node_modules",".pnpm-debug.log","pnpm-lock.yaml"]);let d=f.join(t,"xiaozhi.log");h.existsSync(d)||h.writeFileSync(d,"","utf8"),e.succeed(`\u9879\u76EE "${n}" \u521B\u5EFA\u6210\u529F`),console.log(c.green("\u2705 \u9879\u76EE\u521B\u5EFA\u5B8C\u6210!")),console.log(c.yellow("\u{1F4DD} \u63A5\u4E0B\u6765\u7684\u6B65\u9AA4:")),console.log(c.gray(` cd ${n}`)),console.log(c.gray(" pnpm install # \u5B89\u88C5\u4F9D\u8D56")),console.log(c.gray(" # \u7F16\u8F91 xiaozhi.config.json \u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9")),console.log(c.gray(" xiaozhi start # \u542F\u52A8\u670D\u52A1"))}else{e.text=`\u521B\u5EFA\u57FA\u672C\u9879\u76EE "${n}"...`,h.mkdirSync(t,{recursive:!0}),Fo(t);let i=f.join(t,"xiaozhi.log");h.writeFileSync(i,"","utf8"),e.succeed(`\u9879\u76EE "${n}" \u521B\u5EFA\u6210\u529F`),console.log(c.green("\u2705 \u57FA\u672C\u9879\u76EE\u521B\u5EFA\u5B8C\u6210!")),console.log(c.yellow("\u{1F4DD} \u63A5\u4E0B\u6765\u7684\u6B65\u9AA4:")),console.log(c.gray(` cd ${n}`)),console.log(c.gray(" # \u7F16\u8F91 xiaozhi.config.json \u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9\u548C\u670D\u52A1")),console.log(c.gray(" xiaozhi start # \u542F\u52A8\u670D\u52A1")),console.log(c.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 --template \u9009\u9879\u53EF\u4EE5\u4ECE\u6A21\u677F\u521B\u5EFA\u9879\u76EE"))}}catch(t){e.fail(`\u521B\u5EFA\u9879\u76EE\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}l(No,"createProject");function oo(n,o,e=[]){h.existsSync(o)||h.mkdirSync(o,{recursive:!0});let t=h.readdirSync(n);for(let i of t){if(e.some(m=>i.includes(m)))continue;let r=f.join(n,i),s=f.join(o,i);h.statSync(r).isDirectory()?oo(r,s,e):h.copyFileSync(r,s)}}l(oo,"copyDirectory");async function Ro(){let n=b("\u542F\u52A8 UI \u670D\u52A1...").start();try{if(!p.configExists()){n.fail("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728"),console.log(c.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E'));return}let o=new M(9999);await o.start(),n.succeed("UI \u670D\u52A1\u5DF2\u542F\u52A8"),console.log(c.green("\u2705 \u914D\u7F6E\u7BA1\u7406\u7F51\u9875\u5DF2\u542F\u52A8: http://localhost:9999")),console.log(c.yellow("\u{1F4A1} \u63D0\u793A: \u6309 Ctrl+C \u505C\u6B62\u670D\u52A1"));let{spawn:e}=await import("child_process"),t="http://localhost:9999",i=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";try{e(i,[t],{detached:!0,stdio:"ignore"}).unref()}catch{}process.on("SIGINT",async()=>{console.log(c.yellow(`
29
- \u6B63\u5728\u505C\u6B62 UI \u670D\u52A1...`)),await o.stop(),process.exit(0)}),process.on("SIGTERM",async()=>{await o.stop(),process.exit(0)})}catch(o){n.fail(`\u542F\u52A8 UI \u670D\u52A1\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}l(Ro,"startUIService");async function Ao(n,o){let e=b("\u66F4\u65B0\u914D\u7F6E...").start();try{if(!p.configExists()){e.fail("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728"),console.log(c.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E'));return}if(o)switch(n){case"mcpEndpoint":p.updateMcpEndpoint(o),e.succeed(`MCP \u7AEF\u70B9\u5DF2\u66F4\u65B0\u4E3A: ${o}`);break;case"heartbeatInterval":{let t=Number.parseInt(o,10);if(Number.isNaN(t)||t<=0){e.fail("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}p.setHeartbeatInterval(t),e.succeed(`\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}case"heartbeatTimeout":{let t=Number.parseInt(o,10);if(Number.isNaN(t)||t<=0){e.fail("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}p.setHeartbeatTimeout(t),e.succeed(`\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}case"reconnectInterval":{let t=Number.parseInt(o,10);if(Number.isNaN(t)||t<=0){e.fail("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}p.setReconnectInterval(t),e.succeed(`\u91CD\u8FDE\u95F4\u9694\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}default:e.fail(`\u914D\u7F6E\u9879 ${n} \u4E0D\u652F\u6301\u901A\u8FC7\u547D\u4EE4\u884C\u8BBE\u7F6E`),console.log(c.yellow("\u652F\u6301\u8BBE\u7F6E\u7684\u914D\u7F6E\u9879: mcpEndpoint, heartbeatInterval, heartbeatTimeout, reconnectInterval"));return}else{e.text="\u8BFB\u53D6\u914D\u7F6E...";let t=p.getConfig();switch(n){case"mcpEndpoint":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(c.green(`MCP \u7AEF\u70B9: ${t.mcpEndpoint}`));break;case"mcpServers":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(c.green("MCP \u670D\u52A1:"));for(let[i,r]of Object.entries(t.mcpServers))"type"in r&&r.type==="sse"?console.log(c.gray(` ${i}: [SSE] ${r.url}`)):console.log(c.gray(` ${i}: ${r.command} ${r.args.join(" ")}`));break;case"connection":{e.succeed("\u914D\u7F6E\u4FE1\u606F");let i=p.getConnectionConfig();console.log(c.green("\u8FDE\u63A5\u914D\u7F6E:")),console.log(c.gray(` \u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694: ${i.heartbeatInterval}ms`)),console.log(c.gray(` \u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4: ${i.heartbeatTimeout}ms`)),console.log(c.gray(` \u91CD\u8FDE\u95F4\u9694: ${i.reconnectInterval}ms`));break}case"heartbeatInterval":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(c.green(`\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694: ${p.getHeartbeatInterval()}ms`));break;case"heartbeatTimeout":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(c.green(`\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4: ${p.getHeartbeatTimeout()}ms`));break;case"reconnectInterval":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(c.green(`\u91CD\u8FDE\u95F4\u9694: ${p.getReconnectInterval()}ms`));break;default:e.fail(`\u672A\u77E5\u7684\u914D\u7F6E\u9879: ${n}`),console.log(c.yellow("\u652F\u6301\u7684\u914D\u7F6E\u9879: mcpEndpoint, mcpServers, connection, heartbeatInterval, heartbeatTimeout, reconnectInterval"));return}}}catch(t){e.fail(`\u914D\u7F6E\u64CD\u4F5C\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}l(Ao,"configCommand");function Ho(){console.log(c.blue.bold("xiaozhi - MCP Calculator Service CLI")),console.log(),console.log(c.yellow("\u4F7F\u7528\u65B9\u6CD5:")),console.log(" xiaozhi <command> [options]"),console.log(),console.log(c.yellow("\u547D\u4EE4:")),console.log(" create <projectName> \u521B\u5EFA\u9879\u76EE"),console.log(" init \u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6"),console.log(" config <key> [value] \u67E5\u770B\u6216\u8BBE\u7F6E\u914D\u7F6E"),console.log(" start [--daemon] \u542F\u52A8\u670D\u52A1 (--daemon \u540E\u53F0\u8FD0\u884C)"),console.log(" stop \u505C\u6B62\u670D\u52A1"),console.log(" status \u68C0\u67E5\u670D\u52A1\u72B6\u6001"),console.log(" attach \u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1\u67E5\u770B\u65E5\u5FD7"),console.log(" restart [--daemon] \u91CD\u542F\u670D\u52A1 (--daemon \u540E\u53F0\u8FD0\u884C)"),console.log(" ui \u542F\u52A8\u914D\u7F6E\u7BA1\u7406\u7F51\u9875"),console.log(" completion \u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E"),console.log(),console.log(c.yellow("\u9009\u9879:")),console.log(" -v, --version \u663E\u793A\u7248\u672C\u4FE1\u606F"),console.log(" -V \u663E\u793A\u8BE6\u7EC6\u4FE1\u606F"),console.log(" -h, --help \u663E\u793A\u5E2E\u52A9\u4FE1\u606F"),console.log(" -t, --template <name> \u6307\u5B9A\u6A21\u677F\u540D\u79F0\uFF08\u7528\u4E8E create \u547D\u4EE4\uFF09"),console.log(),console.log(c.yellow("\u9879\u76EE\u793A\u4F8B:")),console.log(" xiaozhi create my-app # \u521B\u5EFA\u57FA\u672C\u9879\u76EE"),console.log(" xiaozhi create my-app -t hello-world # \u4F7F\u7528 hello-world \u6A21\u677F"),console.log(" xiaozhi create my-app --template hello-world # \u540C\u4E0A\uFF0C\u5B8C\u6574\u9009\u9879\u540D"),console.log(),console.log(c.yellow("\u914D\u7F6E\u793A\u4F8B:")),console.log(" xiaozhi init # \u521D\u59CB\u5316\u914D\u7F6E"),console.log(" xiaozhi config mcpEndpoint # \u67E5\u770B MCP \u7AEF\u70B9"),console.log(" xiaozhi config mcpEndpoint wss://... # \u8BBE\u7F6E MCP \u7AEF\u70B9"),console.log(),console.log(c.yellow("\u670D\u52A1\u793A\u4F8B:")),console.log(" xiaozhi start # \u524D\u53F0\u542F\u52A8\u670D\u52A1"),console.log(" xiaozhi start --daemon # \u540E\u53F0\u542F\u52A8\u670D\u52A1"),console.log(" xiaozhi status # \u68C0\u67E5\u670D\u52A1\u72B6\u6001"),console.log(" xiaozhi attach # \u67E5\u770B\u540E\u53F0\u670D\u52A1\u65E5\u5FD7"),console.log(" xiaozhi stop # \u505C\u6B62\u670D\u52A1"),console.log(),console.log(c.yellow("MCP \u7BA1\u7406\u793A\u4F8B:")),console.log(" xiaozhi mcp list # \u5217\u51FA\u6240\u6709 MCP \u670D\u52A1"),console.log(" xiaozhi mcp list --tools # \u5217\u51FA\u6240\u6709\u670D\u52A1\u7684\u5DE5\u5177"),console.log(" xiaozhi mcp server <name> # \u5217\u51FA\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177"),console.log(" xiaozhi mcp tool <server> <tool> enable # \u542F\u7528\u5DE5\u5177"),console.log(" xiaozhi mcp tool <server> <tool> disable # \u7981\u7528\u5DE5\u5177"),console.log(),console.log(c.yellow("\u81EA\u52A8\u8865\u5168:")),console.log(" xiaozhi completion # \u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E"),console.log(" # \u8BBE\u7F6E\u540E\u53EF\u4F7F\u7528 Tab \u952E\u8FDB\u884C\u547D\u4EE4\u3001\u53C2\u6570\u81EA\u52A8\u8865\u5168")}l(Ho,"showHelp");C.name("xiaozhi").description("MCP Calculator Service CLI Tool").version(Y(),"-v, --version","\u663E\u793A\u7248\u672C\u4FE1\u606F").helpOption("-h, --help","\u663E\u793A\u5E2E\u52A9\u4FE1\u606F");C.command("create <projectName>").description("\u521B\u5EFA\u9879\u76EE").option("-t, --template <templateName>","\u4F7F\u7528\u6307\u5B9A\u6A21\u677F\u521B\u5EFA\u9879\u76EE").action(async(n,o)=>{await No(n,o)});C.command("init").description("\u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6").action(async()=>{await jo()});C.command("config <key> [value]").description("\u67E5\u770B\u6216\u8BBE\u7F6E\u914D\u7F6E").action(async(n,o)=>{await Ao(n,o)});C.command("start").description("\u542F\u52A8\u670D\u52A1").option("-d, --daemon","\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").action(async n=>{await Q(n.daemon)});C.command("stop").description("\u505C\u6B62\u670D\u52A1").action(async()=>{await q()});C.command("status").description("\u68C0\u67E5\u670D\u52A1\u72B6\u6001").action(async()=>{await To()});C.command("attach").description("\u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1\u67E5\u770B\u65E5\u5FD7").action(async()=>{await $o()});C.command("restart").description("\u91CD\u542F\u670D\u52A1").option("-d, --daemon","\u5728\u540E\u53F0\u8FD0\u884C\u670D\u52A1").action(async n=>{await Eo(n.daemon)});var R=C.command("mcp").description("MCP \u670D\u52A1\u548C\u5DE5\u5177\u7BA1\u7406");R.command("list").description("\u5217\u51FA MCP \u670D\u52A1").option("--tools","\u663E\u793A\u6240\u6709\u670D\u52A1\u7684\u5DE5\u5177\u5217\u8868").action(async n=>{await G(n)});R.command("server <serverName>").description("\u7BA1\u7406\u6307\u5B9A\u7684 MCP \u670D\u52A1").action(async n=>{await _(n)});R.command("tool <serverName> <toolName> <action>").description("\u542F\u7528\u6216\u7981\u7528\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177").action(async(n,o,e)=>{e!=="enable"&&e!=="disable"&&(console.error(c.red("\u9519\u8BEF: \u64CD\u4F5C\u5FC5\u987B\u662F 'enable' \u6216 'disable'")),process.exit(1)),await B(n,o,e==="enable")});C.command("ui").description("\u542F\u52A8\u914D\u7F6E\u7BA1\u7406\u7F51\u9875").action(async()=>{await Ro()});C.command("completion").description("\u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E").action(async()=>{W()});C.option("-V","\u663E\u793A\u8BE6\u7EC6\u4FE1\u606F").action(n=>{n.V&&(Mo(),process.exit(0))});D();process.argv.length<=2&&(Ho(),process.exit(0));C.parse(process.argv);export{X as calculateSimilarity,Po as checkEnvironment,xo as formatUptime,z as getServiceStatus,Y as getVersion};
23
+ `);return}let c=o;if(c==="/"&&(c="/index.html"),c.includes("..")){e.writeHead(403),e.end("Forbidden");return}let a=w(r,c);if(!W(a)){let b=w(r,"index.html");if(W(b)){let I=await Z(b);e.writeHead(200,{"Content-Type":"text/html"}),e.end(I)}else e.writeHead(404),e.end("Not Found");return}let d=await Z(a),m=a.split(".").pop()?.toLowerCase(),y={html:"text/html",js:"application/javascript",css:"text/css",json:"application/json",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",svg:"image/svg+xml",ico:"image/x-icon"}[m||""]||"application/octet-stream";e.writeHead(200,{"Content-Type":y}),e.end(d)}catch(t){this.logger.error("Serve static file error:",t),e.writeHead(500),e.end("Internal Server Error")}}setupWebSocket(){this.wss.on("connection",o=>{this.logger.debug("WebSocket client connected"),o.on("message",async e=>{try{let t=JSON.parse(e.toString());await this.handleWebSocketMessage(o,t)}catch(t){this.logger.error("WebSocket message error:",t),o.send(JSON.stringify({type:"error",error:t instanceof Error?t.message:String(t)}))}}),o.on("close",()=>{this.logger.debug("WebSocket client disconnected")}),this.sendInitialData(o)})}async handleWebSocketMessage(o,e){switch(e.type){case"getConfig":{let t=l.getConfig();o.send(JSON.stringify({type:"config",data:t}));break}case"updateConfig":this.updateConfig(e.config),this.broadcastConfigUpdate(e.config);break;case"getStatus":o.send(JSON.stringify({type:"status",data:this.clientInfo}));break;case"clientStatus":this.updateClientInfo(e.data),this.broadcastStatusUpdate();break}}async sendInitialData(o){let e=l.getConfig();o.send(JSON.stringify({type:"config",data:e})),o.send(JSON.stringify({type:"status",data:this.clientInfo}))}broadcastConfigUpdate(o){let e=JSON.stringify({type:"configUpdate",data:o});for(let t of this.wss.clients)t.readyState===1&&t.send(e)}broadcastStatusUpdate(){let o=JSON.stringify({type:"statusUpdate",data:this.clientInfo});for(let e of this.wss.clients)e.readyState===1&&e.send(o)}updateClientInfo(o){this.clientInfo={...this.clientInfo,...o},o.lastHeartbeat&&(this.clientInfo.lastHeartbeat=Date.now()),o.status==="connected"&&this.resetHeartbeatTimeout()}resetHeartbeatTimeout(){this.heartbeatTimeout&&clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=setTimeout(()=>{this.logger.warn("\u5BA2\u6237\u7AEF\u5FC3\u8DF3\u8D85\u65F6\uFF0C\u6807\u8BB0\u4E3A\u65AD\u5F00\u8FDE\u63A5"),this.updateClientInfo({status:"disconnected"}),this.broadcastStatusUpdate()},this.HEARTBEAT_TIMEOUT)}updateConfig(o){o.mcpEndpoint!==l.getMcpEndpoint()&&l.updateMcpEndpoint(o.mcpEndpoint);let e=l.getMcpServers();for(let[t,i]of Object.entries(o.mcpServers))JSON.stringify(e[t])!==JSON.stringify(i)&&l.updateMcpServer(t,i);for(let t of Object.keys(e))t in o.mcpServers||l.removeMcpServer(t);if(o.connection&&l.updateConnectionConfig(o.connection),o.modelscope&&l.updateModelScopeConfig(o.modelscope),o.webUI&&l.updateWebUIConfig(o.webUI),o.mcpServerConfig)for(let[t,i]of Object.entries(o.mcpServerConfig))for(let[r,c]of Object.entries(i.tools))l.setToolEnabled(t,r,c.enable)}updateStatus(o){this.updateClientInfo(o),this.broadcastStatusUpdate()}start(){return new Promise((o,e)=>{this.httpServer.listen(this.port,()=>{this.logger.info(`Web server listening on http://localhost:${this.port}`),o()}).on("error",e)})}stop(){return new Promise(o=>{this.heartbeatTimeout&&(clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=void 0);for(let e of this.wss.clients)e.terminate();this.wss.close(()=>{this.httpServer.close(()=>{this.logger.info("Web server stopped"),o()}),setTimeout(()=>{this.logger.info("Web server force stopped"),o()},2e3)})})}};var S=new wo,Io="xiaozhi-mcp-service";function Q(){try{let n=j(import.meta.url),o=p.dirname(n),e=[p.join(o,"..","package.json"),p.join(o,"..","package.json"),p.join(o,"..","..","package.json"),p.join(o,"package.json")];for(let t of e)if(h.existsSync(t)){let i=JSON.parse(h.readFileSync(t,"utf8"));if(i.version)return i.version}return"unknown"}catch(n){return console.warn("\u65E0\u6CD5\u4ECE package.json \u8BFB\u53D6\u7248\u672C\u4FE1\u606F:",n),"unknown"}}g(Q,"getVersion");var v=p.join(vo.tmpdir(),`${Io}.pid`);function z(){try{if(!h.existsSync(v))return{running:!1};let n=h.readFileSync(v,"utf8").trim(),[o,e,t]=n.split("|"),i=Number.parseInt(o);if(Number.isNaN(i))return h.unlinkSync(v),{running:!1};try{process.kill(i,0);let r=Number.parseInt(e),c=xo(Date.now()-r);return{running:!0,pid:i,uptime:c,mode:t||"foreground"}}catch{return h.unlinkSync(v),{running:!1}}}catch{return{running:!1}}}g(z,"getServiceStatus");function xo(n){let o=Math.floor(n/1e3),e=Math.floor(o/60),t=Math.floor(e/60),i=Math.floor(t/24);return i>0?`${i}\u5929 ${t%24}\u5C0F\u65F6 ${e%60}\u5206\u949F`:t>0?`${t}\u5C0F\u65F6 ${e%60}\u5206\u949F`:e>0?`${e}\u5206\u949F ${o%60}\u79D2`:`${o}\u79D2`}g(xo,"formatUptime");function K(n,o){let e=`${n}|${Date.now()}|${o}`;h.writeFileSync(v,e)}g(K,"savePidInfo");function E(){try{h.existsSync(v)&&h.unlinkSync(v)}catch{}}g(E,"cleanupPidFile");function Po(){if(!l.configExists())return console.error(s.red("\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728")),console.log(s.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E')),!1;try{let n=l.getMcpEndpoint();return!n||n.includes("<\u8BF7\u586B\u5199")?(console.error(s.red("\u274C \u9519\u8BEF: MCP \u7AEF\u70B9\u672A\u914D\u7F6E")),console.log(s.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi config mcpEndpoint <your-endpoint-url>" \u8BBE\u7F6E\u7AEF\u70B9')),!1):!0}catch(n){return console.error(s.red(`\u274C \u9519\u8BEF: \u914D\u7F6E\u6587\u4EF6\u65E0\u6548 - ${n instanceof Error?n.message:String(n)}`)),console.log(s.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u8FD0\u884C "xiaozhi init" \u91CD\u65B0\u521D\u59CB\u5316\u914D\u7F6E')),!1}}g(Po,"checkEnvironment");function $o(){let n=p.dirname(j(import.meta.url)),o;return n.includes("js-demo/dist")?o=n:o=[p.join(n,"..","js-demo","dist"),p.join(n,"..","..","js-demo","dist"),p.join(n,"..","..","..","js-demo","dist"),p.join(process.cwd(),"js-demo","dist"),p.join(process.cwd(),"dist")].find(t=>h.existsSync(p.join(t,"mcpPipe.js"))&&h.existsSync(p.join(t,"mcpServerProxy.js")))||n,{command:"node",args:["mcpPipe.js","mcpServerProxy.js"],cwd:o}}g($o,"getServiceCommand");async function V(){try{if(!l.configExists()){console.log(s.yellow("\u{1F4A1} \u63D0\u793A: \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7 Web UI \u542F\u52A8"));return}let n=new T;await n.start();let o=l.getWebUIPort();console.log(s.green(`\u2705 Web UI \u5DF2\u542F\u52A8: http://localhost:${o}`));let{spawn:e}=await import("child_process"),t=`http://localhost:${o}`,i=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";try{e(i,[t],{detached:!0,stdio:"ignore"}).unref()}catch{}global.__webServer=n}catch(n){console.log(s.yellow(`\u26A0\uFE0F Web UI \u542F\u52A8\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`))}}g(V,"startWebUIInBackground");async function q(n=!1,o=!1){let e=C("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let t=z();if(t.running){e.fail(`\u670D\u52A1\u5DF2\u7ECF\u5728\u8FD0\u884C (PID: ${t.pid})`);return}if(e.text="\u68C0\u67E5\u73AF\u5883\u914D\u7F6E...",!Po()){e.fail("\u73AF\u5883\u914D\u7F6E\u68C0\u67E5\u5931\u8D25");return}let{command:i,args:r,cwd:c}=$o();if(e.text=`\u542F\u52A8\u670D\u52A1 (${n?"\u540E\u53F0\u6A21\u5F0F":"\u524D\u53F0\u6A21\u5F0F"})...`,n){let a=X(i,r,{cwd:c,detached:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd(),XIAOZHI_DAEMON:"true"}});K(a.pid,"daemon");let d=process.cwd();$.initLogFile(d),$.enableFileLogging(!0);let m=p.join(d,"xiaozhi.log"),u=h.createWriteStream(m,{flags:"a"});a.stdout?.pipe(u),a.stderr?.pipe(u),a.on("exit",(y,b)=>{y!==0&&y!==null&&$.error(`\u540E\u53F0\u670D\u52A1\u5F02\u5E38\u9000\u51FA (\u4EE3\u7801: ${y}, \u4FE1\u53F7: ${b})`),E()}),a.on("error",y=>{$.error(`\u540E\u53F0\u670D\u52A1\u542F\u52A8\u9519\u8BEF: ${y.message}`),E(),e.fail(`\u540E\u53F0\u670D\u52A1\u542F\u52A8\u5931\u8D25: ${y.message}`)}),a.unref(),e.succeed(`\u670D\u52A1\u5DF2\u5728\u540E\u53F0\u542F\u52A8 (PID: ${a.pid})`),console.log(s.gray(`\u65E5\u5FD7\u6587\u4EF6: ${m}`)),console.log(s.gray("\u4F7F\u7528 'xiaozhi attach' \u53EF\u4EE5\u67E5\u770B\u5B9E\u65F6\u65E5\u5FD7")),o&&await V()}else{e.succeed("\u670D\u52A1\u542F\u52A8\u4E2D...");let a=X(i,r,{cwd:c,stdio:"inherit",env:{...process.env,XIAOZHI_CONFIG_DIR:process.cwd()}});K(a.pid,"foreground"),a.on("exit",(d,m)=>{E(),console.log(d!==0?s.red(`
24
+ \u670D\u52A1\u5F02\u5E38\u9000\u51FA (\u4EE3\u7801: ${d}, \u4FE1\u53F7: ${m})`):s.green(`
25
+ \u670D\u52A1\u5DF2\u505C\u6B62`))}),o&&setTimeout(()=>{V()},1e3),process.on("SIGINT",async()=>{if(console.log(s.yellow(`
26
+ \u6B63\u5728\u505C\u6B62\u670D\u52A1...`)),a.kill("SIGTERM"),global.__webServer)try{await global.__webServer.stop(),console.log(s.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){e.fail(`\u542F\u52A8\u670D\u52A1\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}g(q,"startService");async function oo(){let n=C("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let o=z();if(!o.running){n.warn("\u670D\u52A1\u672A\u5728\u8FD0\u884C");return}n.text=`\u505C\u6B62\u670D\u52A1 (PID: ${o.pid})...`;try{process.kill(o.pid,"SIGTERM");let e=0,t=30;for(;e<t;){await new Promise(i=>setTimeout(i,100));try{process.kill(o.pid,0),e++}catch{break}}try{process.kill(o.pid,0),n.text="\u5F3A\u5236\u505C\u6B62\u670D\u52A1...",process.kill(o.pid,"SIGKILL"),await new Promise(i=>setTimeout(i,500))}catch{}E(),n.succeed("\u670D\u52A1\u5DF2\u505C\u6B62")}catch(e){E(),n.fail(`\u505C\u6B62\u670D\u52A1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}catch(o){n.fail(`\u505C\u6B62\u670D\u52A1\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}g(oo,"stopService");async function To(){let n=C("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let o=z();if(o.running){if(n.succeed("\u670D\u52A1\u72B6\u6001"),console.log(s.green("\u2705 \u670D\u52A1\u6B63\u5728\u8FD0\u884C")),console.log(s.gray(` PID: ${o.pid}`)),console.log(s.gray(` \u8FD0\u884C\u65F6\u95F4: ${o.uptime}`)),console.log(s.gray(` \u8FD0\u884C\u6A21\u5F0F: ${o.mode==="daemon"?"\u540E\u53F0\u6A21\u5F0F":"\u524D\u53F0\u6A21\u5F0F"}`)),o.mode==="daemon"){let e=p.join(process.cwd(),"xiaozhi.log");console.log(s.gray(` \u65E5\u5FD7\u6587\u4EF6: ${e}`))}}else n.succeed("\u670D\u52A1\u72B6\u6001"),console.log(s.red("\u274C \u670D\u52A1\u672A\u8FD0\u884C"))}catch(o){n.fail(`\u68C0\u67E5\u72B6\u6001\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}g(To,"checkStatus");async function Eo(){let n=C("\u68C0\u67E5\u670D\u52A1\u72B6\u6001...").start();try{let o=z();if(!o.running){n.fail("\u670D\u52A1\u672A\u5728\u8FD0\u884C");return}if(o.mode!=="daemon"){n.fail("\u670D\u52A1\u4E0D\u662F\u5728\u540E\u53F0\u6A21\u5F0F\u8FD0\u884C");return}n.succeed("\u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1..."),console.log(s.green(`\u5DF2\u8FDE\u63A5\u5230\u670D\u52A1 (PID: ${o.pid})`)),console.log(s.gray("\u6309 Ctrl+C \u53EF\u4EE5\u65AD\u5F00\u8FDE\u63A5\uFF08\u4E0D\u4F1A\u505C\u6B62\u670D\u52A1\uFF09")),console.log(s.gray("=".repeat(50)));let e=p.join(process.cwd(),"xiaozhi.log");if(h.existsSync(e))if(process.platform==="win32"){let{spawn:t}=await import("child_process"),i=t("powershell",["-Command",`Get-Content -Path "${e}" -Wait`],{stdio:"inherit"});process.on("SIGINT",()=>{console.log(s.yellow(`
27
+ \u65AD\u5F00\u8FDE\u63A5\uFF0C\u670D\u52A1\u7EE7\u7EED\u5728\u540E\u53F0\u8FD0\u884C`)),i.kill(),process.exit(0)}),i.on("exit",()=>{process.exit(0)})}else{let{spawn:t}=await import("child_process"),i=t("tail",["-f",e],{stdio:"inherit"});process.on("SIGINT",()=>{console.log(s.yellow(`
28
+ \u65AD\u5F00\u8FDE\u63A5\uFF0C\u670D\u52A1\u7EE7\u7EED\u5728\u540E\u53F0\u8FD0\u884C`)),i.kill(),process.exit(0)}),i.on("exit",()=>{process.exit(0)})}else console.log(s.yellow("\u65E5\u5FD7\u6587\u4EF6\u4E0D\u5B58\u5728"))}catch(o){n.fail(`\u8FDE\u63A5\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}g(Eo,"attachService");async function Mo(n=!1,o=!1){console.log(s.blue("\u{1F504} \u91CD\u542F\u670D\u52A1...")),await oo(),await new Promise(e=>setTimeout(e,1e3)),await q(n,o)}g(Mo,"restartService");function jo(){let n=Q();console.log(s.blue(`xiaozhi v${n}`)),console.log(s.gray("MCP Calculator Service CLI Tool")),console.log(s.gray("Built with Node.js and TypeScript")),console.log(s.gray(`Node.js: ${process.version}`)),console.log(s.gray(`Platform: ${process.platform} ${process.arch}`))}g(jo,"showDetailedInfo");async function zo(){let n=C("\u521D\u59CB\u5316\u914D\u7F6E...").start();try{if(l.configExists()){n.warn("\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728"),console.log(s.yellow("\u5982\u9700\u91CD\u65B0\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u5220\u9664\u73B0\u6709\u7684 xiaozhi.config.json \u6587\u4EF6"));return}l.initConfig(),n.succeed("\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u6210\u529F"),console.log(s.green("\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u521B\u5EFA: xiaozhi.config.json")),console.log(s.yellow("\u{1F4DD} \u8BF7\u7F16\u8F91\u914D\u7F6E\u6587\u4EF6\u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9:")),console.log(s.gray(` \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84: ${l.getConfigPath()}`)),console.log(s.yellow("\u{1F4A1} \u6216\u8005\u4F7F\u7528\u547D\u4EE4\u8BBE\u7F6E:")),console.log(s.gray(" xiaozhi config mcpEndpoint <your-endpoint-url>"))}catch(o){n.fail(`\u521D\u59CB\u5316\u914D\u7F6E\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}g(zo,"initConfig");function ko(){let n=p.dirname(j(import.meta.url)),e=[p.join(n,"..","templates"),p.join(n,"templates"),p.join(n,"..","..","templates")].find(t=>h.existsSync(t));return e?h.readdirSync(e).filter(t=>{let i=p.join(e,t);return h.statSync(i).isDirectory()}):[]}g(ko,"getAvailableTemplates");function Y(n,o){let e=n.length,t=o.length,i=Array(e+1).fill(null).map(()=>Array(t+1).fill(0));for(let c=0;c<=e;c++)i[c][0]=c;for(let c=0;c<=t;c++)i[0][c]=c;for(let c=1;c<=e;c++)for(let a=1;a<=t;a++)n[c-1]===o[a-1]?i[c][a]=i[c-1][a-1]:i[c][a]=Math.min(i[c-1][a]+1,i[c][a-1]+1,i[c-1][a-1]+1);let r=Math.max(e,t);return r===0?1:(r-i[e][t])/r}g(Y,"calculateSimilarity");function Oo(n,o){if(o.length===0)return null;let e=o[0],t=Y(n.toLowerCase(),e.toLowerCase());for(let i of o.slice(1)){let r=Y(n.toLowerCase(),i.toLowerCase());r>t&&(t=r,e=i)}return t>.5?e:null}g(Oo,"findSimilarTemplate");async function Uo(n){if(!process.stdin.isTTY)return console.log("n (\u975E\u4EA4\u4E92\u5F0F\u73AF\u5883)"),!1;let o=await import("readline");return new Promise(e=>{process.stdout.write(n);let t=o.createInterface({input:process.stdin,output:process.stdout}),i=g(r=>{let c=r.trim().toLowerCase();c==="y"||c==="yes"?(t.close(),e(!0)):c==="n"||c==="no"||c===""?(t.close(),e(!1)):process.stdout.write("\u8BF7\u8F93\u5165 y \u6216 n: ")},"handleInput");t.on("line",i),t.on("SIGINT",()=>{t.close(),e(!1)})})}g(Uo,"askUserConfirmation");function Wo(n){let o={mcpEndpoint:"<\u8BF7\u586B\u5199\u4F60\u7684\u63A5\u5165\u70B9\u5730\u5740\uFF08\u83B7\u53D6\u5730\u5740\u5728 xiaozhi.me\uFF09>",mcpServers:{}},e=p.join(n,"xiaozhi.config.json");h.writeFileSync(e,JSON.stringify(o,null,2),"utf8")}g(Wo,"createBasicConfig");async function Fo(n,o){let e=C("\u521D\u59CB\u5316\u9879\u76EE...").start();try{let t=p.join(process.cwd(),n);if(h.existsSync(t)){e.fail(`\u76EE\u5F55 "${n}" \u5DF2\u5B58\u5728`),console.log(s.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u9009\u62E9\u4E0D\u540C\u7684\u9879\u76EE\u540D\u79F0\u6216\u5220\u9664\u73B0\u6709\u76EE\u5F55"));return}if(o.template){e.text="\u68C0\u67E5\u6A21\u677F...";let i=ko();if(i.length===0){e.fail("\u627E\u4E0D\u5230 templates \u76EE\u5F55"),console.log(s.yellow("\u{1F4A1} \u63D0\u793A: \u8BF7\u786E\u4FDD xiaozhi-client \u6B63\u786E\u5B89\u88C5"));return}if(!i.includes(o.template)){e.fail(`\u6A21\u677F "${o.template}" \u4E0D\u5B58\u5728`);let u=Oo(o.template,i);if(u)if(console.log(s.yellow(`\u{1F4A1} \u4F60\u662F\u60F3\u4F7F\u7528\u6A21\u677F "${u}" \u5417\uFF1F`)),await Uo(s.cyan("\u786E\u8BA4\u4F7F\u7528\u6B64\u6A21\u677F\uFF1F(y/n): ")))o.template=u;else{console.log(s.yellow("\u53EF\u7528\u7684\u6A21\u677F:"));for(let b of i)console.log(s.gray(` - ${b}`));return}else{console.log(s.yellow("\u53EF\u7528\u7684\u6A21\u677F:"));for(let y of i)console.log(s.gray(` - ${y}`));return}}let r=p.dirname(j(import.meta.url)),a=[p.join(r,"..","templates"),p.join(r,"templates"),p.join(r,"..","..","templates")].find(u=>h.existsSync(u)),d=p.join(a,o.template);e.text=`\u4ECE\u6A21\u677F "${o.template}" \u521B\u5EFA\u9879\u76EE "${n}"...`,eo(d,t,["node_modules",".pnpm-debug.log","pnpm-lock.yaml"]);let m=p.join(t,"xiaozhi.log");h.existsSync(m)||h.writeFileSync(m,"","utf8"),e.succeed(`\u9879\u76EE "${n}" \u521B\u5EFA\u6210\u529F`),console.log(s.green("\u2705 \u9879\u76EE\u521B\u5EFA\u5B8C\u6210!")),console.log(s.yellow("\u{1F4DD} \u63A5\u4E0B\u6765\u7684\u6B65\u9AA4:")),console.log(s.gray(` cd ${n}`)),console.log(s.gray(" pnpm install # \u5B89\u88C5\u4F9D\u8D56")),console.log(s.gray(" # \u7F16\u8F91 xiaozhi.config.json \u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9")),console.log(s.gray(" xiaozhi start # \u542F\u52A8\u670D\u52A1"))}else{e.text=`\u521B\u5EFA\u57FA\u672C\u9879\u76EE "${n}"...`,h.mkdirSync(t,{recursive:!0}),Wo(t);let i=p.join(t,"xiaozhi.log");h.writeFileSync(i,"","utf8"),e.succeed(`\u9879\u76EE "${n}" \u521B\u5EFA\u6210\u529F`),console.log(s.green("\u2705 \u57FA\u672C\u9879\u76EE\u521B\u5EFA\u5B8C\u6210!")),console.log(s.yellow("\u{1F4DD} \u63A5\u4E0B\u6765\u7684\u6B65\u9AA4:")),console.log(s.gray(` cd ${n}`)),console.log(s.gray(" # \u7F16\u8F91 xiaozhi.config.json \u8BBE\u7F6E\u4F60\u7684 MCP \u7AEF\u70B9\u548C\u670D\u52A1")),console.log(s.gray(" xiaozhi start # \u542F\u52A8\u670D\u52A1")),console.log(s.yellow("\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 --template \u9009\u9879\u53EF\u4EE5\u4ECE\u6A21\u677F\u521B\u5EFA\u9879\u76EE"))}}catch(t){e.fail(`\u521B\u5EFA\u9879\u76EE\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}g(Fo,"createProject");function eo(n,o,e=[]){h.existsSync(o)||h.mkdirSync(o,{recursive:!0});let t=h.readdirSync(n);for(let i of t){if(e.some(d=>i.includes(d)))continue;let r=p.join(n,i),c=p.join(o,i);h.statSync(r).isDirectory()?eo(r,c,e):h.copyFileSync(r,c)}}g(eo,"copyDirectory");async function No(){let n=C("\u542F\u52A8 UI \u670D\u52A1...").start();try{if(!l.configExists()){n.fail("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728"),console.log(s.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E'));return}let o=new T;await o.start(),n.succeed("UI \u670D\u52A1\u5DF2\u542F\u52A8");let e=l.getWebUIPort();console.log(s.green(`\u2705 \u914D\u7F6E\u7BA1\u7406\u7F51\u9875\u5DF2\u542F\u52A8: http://localhost:${e}`)),console.log(s.yellow("\u{1F4A1} \u63D0\u793A: \u6309 Ctrl+C \u505C\u6B62\u670D\u52A1"));let{spawn:t}=await import("child_process"),i=`http://localhost:${e}`,r=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";try{t(r,[i],{detached:!0,stdio:"ignore"}).unref()}catch{}let c=!1;process.on("SIGINT",async()=>{c&&(console.log(s.red(`
29
+ \u5F3A\u5236\u9000\u51FA...`)),process.exit(1)),c=!0,console.log(s.yellow(`
30
+ \u6B63\u5728\u505C\u6B62 UI \u670D\u52A1...`));try{await o.stop(),console.log(s.green("UI \u670D\u52A1\u5DF2\u505C\u6B62"))}catch{console.log(s.red("\u505C\u6B62\u670D\u52A1\u65F6\u51FA\u9519\uFF0C\u5F3A\u5236\u9000\u51FA"))}process.exit(0)}),process.on("SIGTERM",async()=>{c=!0,await o.stop(),process.exit(0)})}catch(o){n.fail(`\u542F\u52A8 UI \u670D\u52A1\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`)}}g(No,"startUIService");async function Ro(n,o){let e=C("\u66F4\u65B0\u914D\u7F6E...").start();try{if(!l.configExists()){e.fail("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728"),console.log(s.yellow('\u{1F4A1} \u63D0\u793A: \u8BF7\u5148\u8FD0\u884C "xiaozhi init" \u521D\u59CB\u5316\u914D\u7F6E'));return}if(o)switch(n){case"mcpEndpoint":l.updateMcpEndpoint(o),e.succeed(`MCP \u7AEF\u70B9\u5DF2\u66F4\u65B0\u4E3A: ${o}`);break;case"heartbeatInterval":{let t=Number.parseInt(o,10);if(Number.isNaN(t)||t<=0){e.fail("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}l.setHeartbeatInterval(t),e.succeed(`\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}case"heartbeatTimeout":{let t=Number.parseInt(o,10);if(Number.isNaN(t)||t<=0){e.fail("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}l.setHeartbeatTimeout(t),e.succeed(`\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}case"reconnectInterval":{let t=Number.parseInt(o,10);if(Number.isNaN(t)||t<=0){e.fail("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u662F\u5927\u4E8E0\u7684\u6570\u5B57\uFF08\u6BEB\u79D2\uFF09");return}l.setReconnectInterval(t),e.succeed(`\u91CD\u8FDE\u95F4\u9694\u5DF2\u66F4\u65B0\u4E3A: ${t}ms`);break}default:e.fail(`\u914D\u7F6E\u9879 ${n} \u4E0D\u652F\u6301\u901A\u8FC7\u547D\u4EE4\u884C\u8BBE\u7F6E`),console.log(s.yellow("\u652F\u6301\u8BBE\u7F6E\u7684\u914D\u7F6E\u9879: mcpEndpoint, heartbeatInterval, heartbeatTimeout, reconnectInterval"));return}else{e.text="\u8BFB\u53D6\u914D\u7F6E...";let t=l.getConfig();switch(n){case"mcpEndpoint":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(s.green(`MCP \u7AEF\u70B9: ${t.mcpEndpoint}`));break;case"mcpServers":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(s.green("MCP \u670D\u52A1:"));for(let[i,r]of Object.entries(t.mcpServers))"type"in r&&r.type==="sse"?console.log(s.gray(` ${i}: [SSE] ${r.url}`)):console.log(s.gray(` ${i}: ${r.command} ${r.args.join(" ")}`));break;case"connection":{e.succeed("\u914D\u7F6E\u4FE1\u606F");let i=l.getConnectionConfig();console.log(s.green("\u8FDE\u63A5\u914D\u7F6E:")),console.log(s.gray(` \u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694: ${i.heartbeatInterval}ms`)),console.log(s.gray(` \u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4: ${i.heartbeatTimeout}ms`)),console.log(s.gray(` \u91CD\u8FDE\u95F4\u9694: ${i.reconnectInterval}ms`));break}case"heartbeatInterval":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(s.green(`\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694: ${l.getHeartbeatInterval()}ms`));break;case"heartbeatTimeout":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(s.green(`\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4: ${l.getHeartbeatTimeout()}ms`));break;case"reconnectInterval":e.succeed("\u914D\u7F6E\u4FE1\u606F"),console.log(s.green(`\u91CD\u8FDE\u95F4\u9694: ${l.getReconnectInterval()}ms`));break;default:e.fail(`\u672A\u77E5\u7684\u914D\u7F6E\u9879: ${n}`),console.log(s.yellow("\u652F\u6301\u7684\u914D\u7F6E\u9879: mcpEndpoint, mcpServers, connection, heartbeatInterval, heartbeatTimeout, reconnectInterval"));return}}}catch(t){e.fail(`\u914D\u7F6E\u64CD\u4F5C\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}g(Ro,"configCommand");function Do(){console.log(s.blue.bold("xiaozhi - MCP Calculator Service CLI")),console.log(),console.log(s.yellow("\u4F7F\u7528\u65B9\u6CD5:")),console.log(" xiaozhi <command> [options]"),console.log(),console.log(s.yellow("\u547D\u4EE4:")),console.log(" create <projectName> \u521B\u5EFA\u9879\u76EE"),console.log(" init \u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6"),console.log(" config <key> [value] \u67E5\u770B\u6216\u8BBE\u7F6E\u914D\u7F6E"),console.log(" start [--daemon] [--ui] \u542F\u52A8\u670D\u52A1 (--daemon \u540E\u53F0\u8FD0\u884C, --ui \u540C\u65F6\u542F\u52A8 Web UI)"),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(s.yellow("\u9009\u9879:")),console.log(" -v, --version \u663E\u793A\u7248\u672C\u4FE1\u606F"),console.log(" -V \u663E\u793A\u8BE6\u7EC6\u4FE1\u606F"),console.log(" -h, --help \u663E\u793A\u5E2E\u52A9\u4FE1\u606F"),console.log(" -t, --template <name> \u6307\u5B9A\u6A21\u677F\u540D\u79F0\uFF08\u7528\u4E8E create \u547D\u4EE4\uFF09"),console.log(),console.log(s.yellow("\u9879\u76EE\u793A\u4F8B:")),console.log(" xiaozhi create my-app # \u521B\u5EFA\u57FA\u672C\u9879\u76EE"),console.log(" xiaozhi create my-app -t hello-world # \u4F7F\u7528 hello-world \u6A21\u677F"),console.log(" xiaozhi create my-app --template hello-world # \u540C\u4E0A\uFF0C\u5B8C\u6574\u9009\u9879\u540D"),console.log(),console.log(s.yellow("\u914D\u7F6E\u793A\u4F8B:")),console.log(" xiaozhi init # \u521D\u59CB\u5316\u914D\u7F6E"),console.log(" xiaozhi config mcpEndpoint # \u67E5\u770B MCP \u7AEF\u70B9"),console.log(" xiaozhi config mcpEndpoint wss://... # \u8BBE\u7F6E MCP \u7AEF\u70B9"),console.log(),console.log(s.yellow("\u670D\u52A1\u793A\u4F8B:")),console.log(" xiaozhi start # \u524D\u53F0\u542F\u52A8\u670D\u52A1"),console.log(" xiaozhi start --daemon # \u540E\u53F0\u542F\u52A8\u670D\u52A1"),console.log(" xiaozhi 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 status # \u68C0\u67E5\u670D\u52A1\u72B6\u6001"),console.log(" xiaozhi attach # \u67E5\u770B\u540E\u53F0\u670D\u52A1\u65E5\u5FD7"),console.log(" xiaozhi stop # \u505C\u6B62\u670D\u52A1"),console.log(),console.log(s.yellow("MCP \u7BA1\u7406\u793A\u4F8B:")),console.log(" xiaozhi mcp list # \u5217\u51FA\u6240\u6709 MCP \u670D\u52A1"),console.log(" xiaozhi mcp list --tools # \u5217\u51FA\u6240\u6709\u670D\u52A1\u7684\u5DE5\u5177"),console.log(" xiaozhi mcp server <name> # \u5217\u51FA\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177"),console.log(" xiaozhi mcp tool <server> <tool> enable # \u542F\u7528\u5DE5\u5177"),console.log(" xiaozhi mcp tool <server> <tool> disable # \u7981\u7528\u5DE5\u5177"),console.log(),console.log(s.yellow("\u81EA\u52A8\u8865\u5168:")),console.log(" xiaozhi completion # \u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E"),console.log(" # \u8BBE\u7F6E\u540E\u53EF\u4F7F\u7528 Tab \u952E\u8FDB\u884C\u547D\u4EE4\u3001\u53C2\u6570\u81EA\u52A8\u8865\u5168")}g(Do,"showHelp");S.name("xiaozhi").description("MCP Calculator Service CLI Tool").version(Q(),"-v, --version","\u663E\u793A\u7248\u672C\u4FE1\u606F").helpOption("-h, --help","\u663E\u793A\u5E2E\u52A9\u4FE1\u606F");S.command("create <projectName>").description("\u521B\u5EFA\u9879\u76EE").option("-t, --template <templateName>","\u4F7F\u7528\u6307\u5B9A\u6A21\u677F\u521B\u5EFA\u9879\u76EE").action(async(n,o)=>{await Fo(n,o)});S.command("init").description("\u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6").action(async()=>{await zo()});S.command("config <key> [value]").description("\u67E5\u770B\u6216\u8BBE\u7F6E\u914D\u7F6E").action(async(n,o)=>{await Ro(n,o)});S.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").action(async n=>{await q(n.daemon,n.ui)});S.command("stop").description("\u505C\u6B62\u670D\u52A1").action(async()=>{await oo()});S.command("status").description("\u68C0\u67E5\u670D\u52A1\u72B6\u6001").action(async()=>{await To()});S.command("attach").description("\u8FDE\u63A5\u5230\u540E\u53F0\u670D\u52A1\u67E5\u770B\u65E5\u5FD7").action(async()=>{await Eo()});S.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 n=>{await Mo(n.daemon,n.ui)});var F=S.command("mcp").description("MCP \u670D\u52A1\u548C\u5DE5\u5177\u7BA1\u7406");F.command("list").description("\u5217\u51FA MCP \u670D\u52A1").option("--tools","\u663E\u793A\u6240\u6709\u670D\u52A1\u7684\u5DE5\u5177\u5217\u8868").action(async n=>{await J(n)});F.command("server <serverName>").description("\u7BA1\u7406\u6307\u5B9A\u7684 MCP \u670D\u52A1").action(async n=>{await G(n)});F.command("tool <serverName> <toolName> <action>").description("\u542F\u7528\u6216\u7981\u7528\u6307\u5B9A\u670D\u52A1\u7684\u5DE5\u5177").action(async(n,o,e)=>{e!=="enable"&&e!=="disable"&&(console.error(s.red("\u9519\u8BEF: \u64CD\u4F5C\u5FC5\u987B\u662F 'enable' \u6216 'disable'")),process.exit(1)),await B(n,o,e==="enable")});S.command("ui").description("\u542F\u52A8\u914D\u7F6E\u7BA1\u7406\u7F51\u9875").action(async()=>{await No()});S.command("completion").description("\u663E\u793A\u81EA\u52A8\u8865\u5168\u8BBE\u7F6E\u8BF4\u660E").action(async()=>{A()});S.option("-V","\u663E\u793A\u8BE6\u7EC6\u4FE1\u606F").action(n=>{n.V&&(jo(),process.exit(0))});D();process.argv.length<=2&&(Do(),process.exit(0));S.parse(process.argv);export{Y as calculateSimilarity,Po as checkEnvironment,xo as formatUptime,z as getServiceStatus,Q as getVersion};
30
31
  //# sourceMappingURL=cli.js.map