xiaozhi-client 1.9.1 → 1.9.2-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,16 +1,6 @@
1
1
  #!/usr/bin/env node
2
- var We=Object.defineProperty;var l=(o,e)=>We(o,"name",{value:e,configurable:!0});import{dirname as It}from"path";import w from"process";import{fileURLToPath as kt}from"url";import*as v from"fs";import*as M from"path";import z from"chalk";import A from"pino";import{z as Be}from"zod";var Ke=Be.enum(["fatal","error","warn","info","debug","trace"]);function Ve(o){let e=o.getFullYear(),t=String(o.getMonth()+1).padStart(2,"0"),r=String(o.getDate()).padStart(2,"0"),n=String(o.getHours()).padStart(2,"0"),s=String(o.getMinutes()).padStart(2,"0"),i=String(o.getSeconds()).padStart(2,"0");return`${e}-${t}-${r} ${n}:${s}:${i}`}l(Ve,"formatDateTime");var le=class{static{l(this,"Logger")}logFilePath=null;pinoInstance;isDaemonMode;logLevel;maxLogFileSize=10*1024*1024;maxLogFiles=5;constructor(e="info"){this.isDaemonMode=process.env.XIAOZHI_DAEMON==="true",this.logLevel=this.validateLogLevel(e),this.pinoInstance=this.createPinoInstance()}validateLogLevel(e){let t=e.toLowerCase(),r=Ke.safeParse(t);return r.success?r.data:"info"}createPinoInstance(){let e=[];if(!this.isDaemonMode){let t=this.createOptimizedConsoleStream();e.push({level:this.logLevel,stream:t})}return this.logFilePath&&e.push({level:this.logLevel,stream:A.destination({dest:this.logFilePath,sync:!1,append:!0,mkdir:!0})}),e.length===0&&e.push({level:this.logLevel,stream:A.destination({dest:"/dev/null"})}),A({level:this.logLevel,timestamp:A.stdTimeFunctions?.isoTime||(()=>`,"time":${Date.now()}`),formatters:{level:l((t,r)=>({level:r}),"level")},base:null,serializers:{err:A.stdSerializers?.err||(t=>t)}},A.multistream(e,{dedupe:!0}))}createOptimizedConsoleStream(){let e=new Map([[20,{name:"DEBUG",color:z.gray}],[30,{name:"INFO",color:z.blue}],[40,{name:"WARN",color:z.yellow}],[50,{name:"ERROR",color:z.red}],[60,{name:"FATAL",color:z.red}]]);return{write:l(t=>{try{let r=JSON.parse(t),n=this.formatConsoleMessageOptimized(r,e);this.safeWrite(`${n}
3
- `)}catch{this.safeWrite(t)}},"write")}}safeWrite(e){try{process.stderr&&typeof process.stderr.write=="function"?process.stderr.write(e):console&&typeof console.error=="function"&&console.error(e.trim())}catch{}}formatConsoleMessageOptimized(e,t){let r=Ve(new Date),n=t.get(e.level)||{name:"UNKNOWN",color:l(a=>a,"color")},s=n.color(`[${n.name}]`),i=e.msg;if(e.args&&Array.isArray(e.args)){let a=e.args.map(g=>typeof g=="object"?JSON.stringify(g):String(g)).join(" ");i=`${i} ${a}`}return`[${r}] ${s} ${i}`}initLogFile(e){this.logFilePath=M.join(e,"xiaozhi.log"),this.rotateLogFileIfNeeded(),v.existsSync(this.logFilePath)||v.writeFileSync(this.logFilePath,""),this.pinoInstance=this.createPinoInstance()}enableFileLogging(e){e&&this.logFilePath&&(this.pinoInstance=this.createPinoInstance())}info(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.info(e):this.pinoInstance.info({args:t},e):this.pinoInstance.info(e,t[0]||"")}success(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.info(e):this.pinoInstance.info({args:t},e):this.pinoInstance.info(e,t[0]||"")}warn(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.warn(e):this.pinoInstance.warn({args:t},e):this.pinoInstance.warn(e,t[0]||"")}error(e,...t){if(typeof e=="string")if(t.length===0)this.pinoInstance.error(e);else{let r=t.map(n=>n instanceof Error?this.pinoInstance.level==="debug"?n.message:{message:n.message,stack:n.stack,name:n.name,cause:n.cause}:n);this.pinoInstance.error({args:r},e)}else{let r=this.enhanceErrorObject(e);this.pinoInstance.error(r,t[0]||"")}}debug(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.debug(e):this.pinoInstance.debug({args:t},e):this.pinoInstance.debug(e,t[0]||"")}log(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.info(e):this.pinoInstance.info({args:t},e):this.pinoInstance.info(e,t[0]||"")}enhanceErrorObject(e){let t={...e};for(let[r,n]of Object.entries(t))n instanceof Error&&(t[r]={message:n.message,stack:n.stack,name:n.name,cause:n.cause});return t}rotateLogFileIfNeeded(){if(!(!this.logFilePath||!v.existsSync(this.logFilePath)))try{v.statSync(this.logFilePath).size>this.maxLogFileSize&&this.rotateLogFile()}catch{}}rotateLogFile(){if(this.logFilePath)try{let e=M.dirname(this.logFilePath),t=M.basename(this.logFilePath,".log");for(let n=this.maxLogFiles-1;n>=1;n--){let s=M.join(e,`${t}.${n}.log`),i=M.join(e,`${t}.${n+1}.log`);v.existsSync(s)&&(n===this.maxLogFiles-1?v.unlinkSync(s):v.renameSync(s,i))}let r=M.join(e,`${t}.1.log`);v.renameSync(this.logFilePath,r)}catch{}}cleanupOldLogs(){if(this.logFilePath)try{let e=M.dirname(this.logFilePath),t=M.basename(this.logFilePath,".log");for(let r=this.maxLogFiles+1;r<=this.maxLogFiles+10;r++){let n=M.join(e,`${t}.${r}.log`);v.existsSync(n)&&v.unlinkSync(n)}}catch{}}setLogFileOptions(e,t){this.maxLogFileSize=e,this.maxLogFiles=t}withTag(e){return this}close(){}setLevel(e){this.logLevel=this.validateLogLevel(e),this.pinoInstance=this.createPinoInstance()}getLevel(){return this.logLevel}},ce=null,Ge="info";function Je(){return ce||(ce=new le(Ge)),ce}l(Je,"getLogger");var c=Je();import{copyFileSync as Qe,existsSync as K,readFileSync as Xe,writeFileSync as Ze}from"fs";import{dirname as et,resolve as O}from"path";import{fileURLToPath as tt}from"url";import*as V from"comment-json";import Ee from"dayjs";import pe from"json5";import*as $e from"json5-writer";import{EventEmitter as qe}from"events";var ue=class extends qe{static{l(this,"EventBus")}logger;eventStats=new Map;maxListeners=50;constructor(){super(),this.logger=c.withTag("EventBus"),this.setMaxListeners(this.maxListeners),this.setupErrorHandling()}setupErrorHandling(){this.on("error",e=>{this.logger.error("EventBus \u5185\u90E8\u9519\u8BEF:",e)}),this.on("newListener",e=>{let t=this.listenerCount(e);t>this.maxListeners*.8&&this.logger.warn(`\u4E8B\u4EF6 ${e} \u7684\u76D1\u542C\u5668\u6570\u91CF\u8FC7\u591A: ${t}`)})}emitEvent(e,t){try{return this.updateEventStats(e),this.logger.debug(`\u53D1\u5C04\u4E8B\u4EF6: ${e}`,t),super.emit(e,t)}catch(r){return this.logger.error(`\u53D1\u5C04\u4E8B\u4EF6\u5931\u8D25: ${e}`,r),r instanceof Error&&this.emit("error",r),!1}}onEvent(e,t){return this.logger.debug(`\u6DFB\u52A0\u4E8B\u4EF6\u76D1\u542C\u5668: ${e}`),this.on(e,t)}onceEvent(e,t){this.logger.debug(`\u6DFB\u52A0\u4E00\u6B21\u6027\u4E8B\u4EF6\u76D1\u542C\u5668: ${e}`);let r=l(n=>{try{t(n)}catch(s){throw this.emit("error",s),s}finally{this.offEvent(e,r)}},"onceListener");return this.on(e,r)}offEvent(e,t){return this.logger.debug(`\u79FB\u9664\u4E8B\u4EF6\u76D1\u542C\u5668: ${e}`),this.off(e,t)}updateEventStats(e){let t=this.eventStats.get(e)||{count:0,lastEmitted:new Date};t.count++,t.lastEmitted=new Date,this.eventStats.set(e,t)}getEventStats(){let e={};for(let[t,r]of this.eventStats)e[t]={...r};return e}getListenerStats(){let e={};for(let t of this.eventNames())e[t]=this.listenerCount(t);return e}clearEventStats(){this.eventStats.clear(),this.logger.info("\u4E8B\u4EF6\u7EDF\u8BA1\u5DF2\u6E05\u7406")}getStatus(){return{totalEvents:this.eventStats.size,totalListeners:Object.values(this.getListenerStats()).reduce((e,t)=>e+t,0),eventStats:this.getEventStats(),listenerStats:this.getListenerStats()}}destroy(){this.removeAllListeners(),this.eventStats.clear(),this.logger.info("EventBus \u5DF2\u9500\u6BC1")}},ge=null;function b(){return ge||(ge=new ue),ge}l(b,"getEventBus");function Ye(o){if(!o||typeof o!="object")throw new Error("\u670D\u52A1\u914D\u7F6E\u5FC5\u987B\u662F\u4E00\u4E2A\u6709\u6548\u7684\u5BF9\u8C61");if("command"in o&&typeof o.command=="string")return"stdio";if("type"in o&&o.type==="sse")return"sse";if("type"in o&&o.type==="streamable-http"||"url"in o&&typeof o.url=="string")return"streamable-http";throw new Error("\u65E0\u6CD5\u8BC6\u522B\u7684 MCP \u670D\u52A1\u914D\u7F6E\u7C7B\u578B\u3002\u914D\u7F6E\u5FC5\u987B\u5305\u542B command \u5B57\u6BB5\uFF08stdio\uFF09\u3001type: 'sse' \u5B57\u6BB5\uFF08sse\uFF09\u6216 url \u5B57\u6BB5\uFF08streamable-http\uFF09")}l(Ye,"getMcpServerCommunicationType");function he(o,e){if(!e||typeof e!="object")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684\u914D\u7F6E\u5FC5\u987B\u662F\u4E00\u4E2A\u5BF9\u8C61`};try{switch(Ye(e)){case"stdio":if(!e.command||typeof e.command!="string")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7F3A\u5C11\u5FC5\u9700\u7684 command \u5B57\u6BB5\u6216\u5B57\u6BB5\u7C7B\u578B\u4E0D\u6B63\u786E`};if(!Array.isArray(e.args))return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684 args \u5B57\u6BB5\u5FC5\u987B\u662F\u6570\u7EC4`};if(e.env&&typeof e.env!="object")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684 env \u5B57\u6BB5\u5FC5\u987B\u662F\u5BF9\u8C61`};break;case"sse":if(e.type!=="sse")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684 type \u5B57\u6BB5\u5FC5\u987B\u662F "sse"`};if(!e.url||typeof e.url!="string")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7F3A\u5C11\u5FC5\u9700\u7684 url \u5B57\u6BB5\u6216\u5B57\u6BB5\u7C7B\u578B\u4E0D\u6B63\u786E`};break;case"streamable-http":if(!e.url||typeof e.url!="string")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7F3A\u5C11\u5FC5\u9700\u7684 url \u5B57\u6BB5\u6216\u5B57\u6BB5\u7C7B\u578B\u4E0D\u6B63\u786E`};if(e.type&&e.type!=="streamable-http")return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684 type \u5B57\u6BB5\u5982\u679C\u5B58\u5728\uFF0C\u5FC5\u987B\u662F "streamable-http"`};break;default:return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684\u914D\u7F6E\u7C7B\u578B\u65E0\u6CD5\u8BC6\u522B`}}return{valid:!0}}catch(t){return{valid:!1,error:`\u670D\u52A1 "${o}" \u7684\u914D\u7F6E\u65E0\u6548: ${t instanceof Error?t.message:"\u672A\u77E5\u9519\u8BEF"}`}}}l(he,"validateMcpServerConfig");var Re=et(tt(import.meta.url)),me={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},de=class o{static{l(this,"ConfigManager")}static instance;defaultConfigPath;config=null;currentConfigPath=null;json5Writer=null;eventBus=b();statsUpdateLocks=new Map;statsUpdateLockTimeouts=new Map;STATS_UPDATE_TIMEOUT=5e3;constructor(){let e=[O(Re,"templates","default","xiaozhi.config.json"),O(Re,"..","templates","default","xiaozhi.config.json"),O(process.cwd(),"templates","default","xiaozhi.config.json")];this.defaultConfigPath=e.find(t=>K(t))||e[0]}getConfigFilePath(){let e=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),t=["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"];for(let r of t){let n=O(e,r);if(K(n))return n}return O(e,"xiaozhi.config.json")}getConfigFileFormat(e){return e.endsWith(".json5")?"json5":e.endsWith(".jsonc")?"jsonc":"json"}static getInstance(){return o.instance||(o.instance=new o),o.instance}configExists(){let e=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),t=["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"];for(let r of t){let n=O(e,r);if(K(n))return!0}return!1}initConfig(e="json"){if(!K(this.defaultConfigPath))throw new Error(`\u9ED8\u8BA4\u914D\u7F6E\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728: ${this.defaultConfigPath}`);if(this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u521D\u59CB\u5316");let t=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),r=`xiaozhi.config.${e}`,n=O(t,r);Qe(this.defaultConfigPath,n),this.config=null,this.json5Writer=null}loadConfig(){if(!this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u8FD0\u884C xiaozhi init \u521D\u59CB\u5316\u914D\u7F6E");try{let e=this.getConfigFilePath();this.currentConfigPath=e;let t=this.getConfigFileFormat(e),n=Xe(e,"utf8").replace(/^\uFEFF/,""),s;switch(t){case"json5":s=pe.parse(n),this.json5Writer=$e.load(n);break;case"jsonc":s=V.parse(n);break;default:s=JSON.parse(n);break}return this.validateConfig(s),s}catch(e){throw e instanceof SyntaxError?new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF: ${e.message}`):e}}validateConfig(e){if(!e||typeof e!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A\u6839\u5BF9\u8C61\u65E0\u6548");let t=e;if(t.mcpEndpoint===void 0||t.mcpEndpoint===null)throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5B57\u6BB5\u65E0\u6548");if(typeof t.mcpEndpoint!="string")if(Array.isArray(t.mcpEndpoint)){for(let r of t.mcpEndpoint)if(typeof r!="string"||r.trim()==="")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u6570\u7EC4\u4E2D\u7684\u6BCF\u4E2A\u5143\u7D20\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6216\u5B57\u7B26\u4E32\u6570\u7EC4");if(!t.mcpServers||typeof t.mcpServers!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers \u5B57\u6BB5\u65E0\u6548");for(let[r,n]of Object.entries(t.mcpServers)){if(!n||typeof n!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${r} \u65E0\u6548`);let s=he(r,n);if(!s.valid)throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A${s.error}`)}}getConfig(){return this.config=this.loadConfig(),JSON.parse(JSON.stringify(this.config))}getMutableConfig(){return this.config||(this.config=this.loadConfig()),this.config}getMcpEndpoint(){let e=this.getConfig();return Array.isArray(e.mcpEndpoint)?e.mcpEndpoint[0]||"":e.mcpEndpoint}getMcpEndpoints(){let e=this.getConfig();return Array.isArray(e.mcpEndpoint)?[...e.mcpEndpoint]:e.mcpEndpoint?[e.mcpEndpoint]:[]}getMcpServers(){return this.getConfig().mcpServers}getMcpServerConfig(){return this.getConfig().mcpServerConfig||{}}getServerToolsConfig(e){return this.getMcpServerConfig()[e]?.tools||{}}isToolEnabled(e,t){return this.getServerToolsConfig(e)[t]?.enable!==!1}updateMcpEndpoint(e){if(Array.isArray(e)){for(let r of e)if(!r||typeof r!="string")throw new Error("MCP \u7AEF\u70B9\u6570\u7EC4\u4E2D\u7684\u6BCF\u4E2A\u5143\u7D20\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}let t=this.getMutableConfig();t.mcpEndpoint=e,this.saveConfig(t)}addMcpEndpoint(e){if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t=this.getMutableConfig(),r=this.getMcpEndpoints();if(r.includes(e))throw new Error(`MCP \u7AEF\u70B9 ${e} \u5DF2\u5B58\u5728`);let n=[...r,e];t.mcpEndpoint=n,this.saveConfig(t)}removeMcpEndpoint(e){if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t=this.getMutableConfig(),r=this.getMcpEndpoints();if(r.indexOf(e)===-1)throw new Error(`MCP \u7AEF\u70B9 ${e} \u4E0D\u5B58\u5728`);let s=r.filter(i=>i!==e);t.mcpEndpoint=s,this.saveConfig(t)}updateMcpServer(e,t){if(!e||typeof e!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let r=he(e,t);if(!r.valid)throw new Error(r.error||"\u670D\u52A1\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25");let n=this.getMutableConfig();n.mcpServers[e]=t,this.saveConfig(n)}removeMcpServer(e){if(!e||typeof e!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t=this.getMutableConfig();if(!t.mcpServers[e])throw new Error(`\u670D\u52A1 ${e} \u4E0D\u5B58\u5728`);if(delete t.mcpServers[e],t.mcpServerConfig?.[e]&&delete t.mcpServerConfig[e],t.customMCP?.tools){let r=t.customMCP.tools.filter(n=>n.handler?.type==="mcp"&&n.handler.config?.serviceName===e);for(let n of r){let s=t.customMCP.tools.findIndex(i=>i.name===n.name);s!==-1&&t.customMCP.tools.splice(s,1)}t.customMCP.tools.length===0&&(t.customMCP=void 0)}this.saveConfig(t),this.eventBus.emitEvent("config:updated",{type:"customMCP",timestamp:new Date}),c.info(`\u6210\u529F\u79FB\u9664 MCP \u670D\u52A1 ${e} \u53CA\u5176\u76F8\u5173\u914D\u7F6E`)}updateServerToolsConfig(e,t){let r=this.getMutableConfig();r.mcpServerConfig||(r.mcpServerConfig={}),Object.keys(t).length===0?delete r.mcpServerConfig[e]:r.mcpServerConfig[e]={tools:t},this.saveConfig(r),this.eventBus.emitEvent("config:updated",{type:"serverTools",serviceName:e,timestamp:new Date})}removeServerToolsConfig(e){let r={...this.getConfig()};r.mcpServerConfig&&(delete r.mcpServerConfig[e],this.saveConfig(r))}cleanupInvalidServerToolsConfig(){let e=this.getMutableConfig();if(!e.mcpServerConfig)return;let t=Object.keys(e.mcpServers),n=Object.keys(e.mcpServerConfig).filter(s=>!t.includes(s));if(n.length>0){for(let s of n)delete e.mcpServerConfig[s];this.saveConfig(e),c.info(`\u5DF2\u6E05\u7406 ${n.length} \u4E2A\u65E0\u6548\u7684\u670D\u52A1\u5DE5\u5177\u914D\u7F6E: ${n.join(", ")}`)}}setToolEnabled(e,t,r,n){let s=this.getMutableConfig();s.mcpServerConfig||(s.mcpServerConfig={}),s.mcpServerConfig[e]||(s.mcpServerConfig[e]={tools:{}}),s.mcpServerConfig[e].tools[t]={...s.mcpServerConfig[e].tools[t],enable:r,...n&&{description:n}},this.saveConfig(s)}saveConfig(e){try{this.validateConfig(e);let t;this.currentConfigPath?t=this.currentConfigPath:(t=this.getConfigFilePath(),this.currentConfigPath=t);let r=this.getConfigFileFormat(t),n;switch(r){case"json5":try{this.json5Writer?(this.json5Writer.write(e),n=this.json5Writer.toSource()):(console.warn("\u6CA1\u6709 json5Writer \u5B9E\u4F8B\uFF0C\u56DE\u9000\u5230\u6807\u51C6 JSON5 \u683C\u5F0F"),n=pe.stringify(e,null,2))}catch(s){console.warn("\u4F7F\u7528 json5-writer \u4FDD\u5B58\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u6807\u51C6 JSON5 \u683C\u5F0F:",s),n=pe.stringify(e,null,2)}break;case"jsonc":try{n=V.stringify(e,null,2)}catch(s){console.warn("\u4F7F\u7528 comment-json \u4FDD\u5B58\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u6807\u51C6 JSON \u683C\u5F0F:",s),n=JSON.stringify(e,null,2)}break;default:n=JSON.stringify(e,null,2);break}Ze(t,n,"utf8"),this.config=e,this.notifyConfigUpdate(e)}catch(t){throw new Error(`\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}reloadConfig(){this.config=null,this.currentConfigPath=null,this.json5Writer=null}getConfigPath(){return this.getConfigFilePath()}getDefaultConfigPath(){return this.defaultConfigPath}getConnectionConfig(){let t=this.getConfig().connection||{};return{heartbeatInterval:t.heartbeatInterval??me.heartbeatInterval,heartbeatTimeout:t.heartbeatTimeout??me.heartbeatTimeout,reconnectInterval:t.reconnectInterval??me.reconnectInterval}}getHeartbeatInterval(){return this.getConnectionConfig().heartbeatInterval}getHeartbeatTimeout(){return this.getConnectionConfig().heartbeatTimeout}getReconnectInterval(){return this.getConnectionConfig().reconnectInterval}updateConnectionConfig(e){let t=this.getMutableConfig();t.connection||(t.connection={}),Object.assign(t.connection,e),this.saveConfig(t)}async updateToolUsageStats(e,t,r){try{if(typeof t=="string"&&r){let n=e,s=t,i=r;await Promise.all([this._updateMCPServerToolStats(n,s,i),this.updateCustomMCPToolStats(n,s,i)]),c.debug(`\u5DE5\u5177\u4F7F\u7528\u7EDF\u8BA1\u5DF2\u66F4\u65B0: ${n}/${s}`)}else{let n=e,s=t,i=new Date().toISOString();await this.updateCustomMCPToolStats(n,i,s),c.debug(`CustomMCP \u5DE5\u5177\u4F7F\u7528\u7EDF\u8BA1\u5DF2\u66F4\u65B0: ${n}`)}}catch(n){if(typeof t=="string"&&r){let s=e,i=t;c.error(`\u66F4\u65B0\u5DE5\u5177\u4F7F\u7528\u7EDF\u8BA1\u5931\u8D25 (${s}/${i}): ${n instanceof Error?n.message:String(n)}`)}else{let s=e;c.error(`\u66F4\u65B0 CustomMCP \u5DE5\u5177\u4F7F\u7528\u7EDF\u8BA1\u5931\u8D25 (${s}): ${n instanceof Error?n.message:String(n)}`)}}}async updateMCPServerToolStats(e,t,r,n=!0){await this._updateMCPServerToolStats(e,t,r,n)}setHeartbeatInterval(e){if(e<=0)throw new Error("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatInterval:e})}setHeartbeatTimeout(e){if(e<=0)throw new Error("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatTimeout:e})}setReconnectInterval(e){if(e<=0)throw new Error("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({reconnectInterval:e})}getModelScopeConfig(){return this.getConfig().modelscope||{}}getModelScopeApiKey(){return this.getModelScopeConfig().apiKey||process.env.MODELSCOPE_API_TOKEN}updateModelScopeConfig(e){let t=this.getMutableConfig();t.modelscope||(t.modelscope={}),Object.assign(t.modelscope,e),this.saveConfig(t)}setModelScopeApiKey(e){if(!e||typeof e!="string")throw new Error("API Key \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");this.updateModelScopeConfig({apiKey:e})}getCustomMCPConfig(){return this.getConfig().customMCP||null}getCustomMCPTools(){let e=this.getCustomMCPConfig();return!e||!e.tools?[]:e.tools}validateCustomMCPTools(e){if(!Array.isArray(e))return!1;for(let t of e){if(!t.name||typeof t.name!="string")return c.warn(`CustomMCP \u5DE5\u5177\u7F3A\u5C11\u6709\u6548\u7684 name \u5B57\u6BB5: ${JSON.stringify(t)}`),!1;if(!t.description||typeof t.description!="string")return c.warn(`CustomMCP \u5DE5\u5177 ${t.name} \u7F3A\u5C11\u6709\u6548\u7684 description \u5B57\u6BB5`),!1;if(!t.inputSchema||typeof t.inputSchema!="object")return c.warn(`CustomMCP \u5DE5\u5177 ${t.name} \u7F3A\u5C11\u6709\u6548\u7684 inputSchema \u5B57\u6BB5`),!1;if(!t.handler||typeof t.handler!="object")return c.warn(`CustomMCP \u5DE5\u5177 ${t.name} \u7F3A\u5C11\u6709\u6548\u7684 handler \u5B57\u6BB5`),!1;if(!["proxy","function","http","script","chain","mcp"].includes(t.handler.type))return c.warn(`CustomMCP \u5DE5\u5177 ${t.name} \u7684 handler.type \u5FC5\u987B\u662F 'proxy', 'function', 'http', 'script', 'chain' \u6216 'mcp'`),!1;if(!this.validateHandlerConfig(t.name,t.handler))return!1}return!0}validateHandlerConfig(e,t){switch(t.type){case"proxy":return this.validateProxyHandler(e,t);case"http":return this.validateHttpHandler(e,t);case"function":return this.validateFunctionHandler(e,t);case"script":return this.validateScriptHandler(e,t);case"chain":return this.validateChainHandler(e,t);case"mcp":return this.validateMCPHandler(e,t);default:return c.warn(`CustomMCP \u5DE5\u5177 ${e} \u4F7F\u7528\u4E86\u672A\u77E5\u7684\u5904\u7406\u5668\u7C7B\u578B`),!1}}validateProxyHandler(e,t){return t.platform?["coze","openai","anthropic","custom"].includes(t.platform)?!t.config||typeof t.config!="object"?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 proxy \u5904\u7406\u5668\u7F3A\u5C11 config \u5B57\u6BB5`),!1):t.platform==="coze"&&!t.config.workflow_id&&!t.config.bot_id?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 Coze \u5904\u7406\u5668\u5FC5\u987B\u63D0\u4F9B workflow_id \u6216 bot_id`),!1):!0:(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 proxy \u5904\u7406\u5668\u4F7F\u7528\u4E86\u4E0D\u652F\u6301\u7684\u5E73\u53F0: ${t.platform}`),!1):(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 proxy \u5904\u7406\u5668\u7F3A\u5C11 platform \u5B57\u6BB5`),!1)}validateHttpHandler(e,t){if(!t.url||typeof t.url!="string")return c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 http \u5904\u7406\u5668\u7F3A\u5C11\u6709\u6548\u7684 url \u5B57\u6BB5`),!1;try{new URL(t.url)}catch{return c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 http \u5904\u7406\u5668 url \u683C\u5F0F\u65E0\u6548: ${t.url}`),!1}return t.method&&!["GET","POST","PUT","DELETE","PATCH"].includes(t.method)?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 http \u5904\u7406\u5668\u4F7F\u7528\u4E86\u4E0D\u652F\u6301\u7684 HTTP \u65B9\u6CD5: ${t.method}`),!1):!0}validateFunctionHandler(e,t){return!t.module||typeof t.module!="string"?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 function \u5904\u7406\u5668\u7F3A\u5C11\u6709\u6548\u7684 module \u5B57\u6BB5`),!1):!t.function||typeof t.function!="string"?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 function \u5904\u7406\u5668\u7F3A\u5C11\u6709\u6548\u7684 function \u5B57\u6BB5`),!1):!0}validateScriptHandler(e,t){return!t.script||typeof t.script!="string"?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 script \u5904\u7406\u5668\u7F3A\u5C11\u6709\u6548\u7684 script \u5B57\u6BB5`),!1):t.interpreter&&!["node","python","bash"].includes(t.interpreter)?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 script \u5904\u7406\u5668\u4F7F\u7528\u4E86\u4E0D\u652F\u6301\u7684\u89E3\u91CA\u5668: ${t.interpreter}`),!1):!0}validateChainHandler(e,t){return!t.tools||!Array.isArray(t.tools)||t.tools.length===0?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 chain \u5904\u7406\u5668\u7F3A\u5C11\u6709\u6548\u7684 tools \u6570\u7EC4`),!1):["sequential","parallel"].includes(t.mode)?["stop","continue","retry"].includes(t.error_handling)?!0:(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 chain \u5904\u7406\u5668\u4F7F\u7528\u4E86\u4E0D\u652F\u6301\u7684\u9519\u8BEF\u5904\u7406\u7B56\u7565: ${t.error_handling}`),!1):(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 chain \u5904\u7406\u5668\u4F7F\u7528\u4E86\u4E0D\u652F\u6301\u7684\u6267\u884C\u6A21\u5F0F: ${t.mode}`),!1)}validateMCPHandler(e,t){return!t.config||typeof t.config!="object"?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 mcp \u5904\u7406\u5668\u7F3A\u5C11 config \u5B57\u6BB5`),!1):!t.config.serviceName||typeof t.config.serviceName!="string"?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 mcp \u5904\u7406\u5668\u7F3A\u5C11\u6709\u6548\u7684 serviceName`),!1):!t.config.toolName||typeof t.config.toolName!="string"?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 mcp \u5904\u7406\u5668\u7F3A\u5C11\u6709\u6548\u7684 toolName`),!1):!0}hasValidCustomMCPTools(){try{let e=this.getCustomMCPTools();return e.length===0?!1:this.validateCustomMCPTools(e)}catch(e){return c.error("\u68C0\u67E5 customMCP \u5DE5\u5177\u914D\u7F6E\u65F6\u51FA\u9519:",e),!1}}addCustomMCPTool(e){if(!e||typeof e!="object")throw new Error("\u5DE5\u5177\u914D\u7F6E\u4E0D\u80FD\u4E3A\u7A7A");let t=this.getMutableConfig();if(t.customMCP||(t.customMCP={tools:[]}),t.customMCP.tools.find(n=>n.name===e.name))throw new Error(`\u5DE5\u5177 "${e.name}" \u5DF2\u5B58\u5728`);if(!this.validateCustomMCPTools([e]))throw new Error("\u5DE5\u5177\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25");t.customMCP.tools.unshift(e),this.saveConfig(t),c.info(`\u6210\u529F\u6DFB\u52A0\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177: ${e.name}`)}async addCustomMCPTools(e){if(!Array.isArray(e))throw new Error("\u5DE5\u5177\u914D\u7F6E\u5FC5\u987B\u662F\u6570\u7EC4");if(e.length===0)return;let t=this.getMutableConfig();t.customMCP||(t.customMCP={tools:[]});let r=new Set(t.customMCP.tools.map(s=>s.name)),n=e.filter(s=>!r.has(s.name));if(n.length>0){if(!this.validateCustomMCPTools(n))throw new Error("\u5DE5\u5177\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25");t.customMCP.tools.push(...n),this.saveConfig(t),this.eventBus.emitEvent("config:updated",{type:"customMCP",timestamp:new Date}),c.debug(`\u6210\u529F\u6279\u91CF\u6DFB\u52A0 ${n.length} \u4E2A\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177: ${n.map(s=>s.name).join(", ")}`)}}removeCustomMCPTool(e){if(!e||typeof e!="string")throw new Error("\u5DE5\u5177\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");let t=this.getMutableConfig();if(!t.customMCP||!t.customMCP.tools)throw new Error("\u672A\u914D\u7F6E\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177");let r=t.customMCP.tools.findIndex(n=>n.name===e);if(r===-1)throw new Error(`\u5DE5\u5177 "${e}" \u4E0D\u5B58\u5728`);t.customMCP.tools.splice(r,1),this.saveConfig(t),c.info(`\u6210\u529F\u5220\u9664\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177: ${e}`)}updateCustomMCPTool(e,t){if(!e||typeof e!="string")throw new Error("\u5DE5\u5177\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");if(!t||typeof t!="object")throw new Error("\u66F4\u65B0\u540E\u7684\u5DE5\u5177\u914D\u7F6E\u4E0D\u80FD\u4E3A\u7A7A");let r=this.getMutableConfig();if(!r.customMCP||!r.customMCP.tools)throw new Error("\u672A\u914D\u7F6E\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177");let n=r.customMCP.tools.findIndex(s=>s.name===e);if(n===-1)throw new Error(`\u5DE5\u5177 "${e}" \u4E0D\u5B58\u5728`);if(!this.validateCustomMCPTools([t]))throw new Error("\u66F4\u65B0\u540E\u7684\u5DE5\u5177\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25");r.customMCP.tools[n]=t,this.saveConfig(r),c.debug(`\u6210\u529F\u66F4\u65B0\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177: ${e}`)}updateCustomMCPTools(e){if(!Array.isArray(e))throw new Error("\u5DE5\u5177\u914D\u7F6E\u5FC5\u987B\u662F\u6570\u7EC4");if(!this.validateCustomMCPTools(e))throw new Error("\u5DE5\u5177\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25");let t=this.getMutableConfig();t.customMCP||(t.customMCP={tools:[]}),t.customMCP.tools=e,this.saveConfig(t),this.eventBus.emitEvent("config:updated",{type:"customMCP",timestamp:new Date}),c.debug(`\u6210\u529F\u66F4\u65B0\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177\u914D\u7F6E\uFF0C\u5171 ${e.length} \u4E2A\u5DE5\u5177`)}getWebUIConfig(){return this.getConfig().webUI||{}}getWebUIPort(){return this.getWebUIConfig().port??9999}notifyConfigUpdate(e){try{let t=global.__webServer;t&&typeof t.broadcastConfigUpdate=="function"&&(t.broadcastConfigUpdate(e),console.log("\u5DF2\u901A\u8FC7 WebSocket \u5E7F\u64AD\u914D\u7F6E\u66F4\u65B0"))}catch(t){console.warn("\u901A\u77E5 Web \u754C\u9762\u914D\u7F6E\u66F4\u65B0\u5931\u8D25:",t instanceof Error?t.message:String(t))}}updateWebUIConfig(e){let t=this.getMutableConfig();t.webUI||(t.webUI={}),Object.assign(t.webUI,e),this.saveConfig(t)}setWebUIPort(e){if(!Number.isInteger(e)||e<=0||e>65535)throw new Error("\u7AEF\u53E3\u53F7\u5FC5\u987B\u662F 1-65535 \u4E4B\u95F4\u7684\u6574\u6570");this.updateWebUIConfig({port:e})}updatePlatformConfig(e,t){let r=this.getMutableConfig();r.platforms||(r.platforms={}),r.platforms[e]=t,this.saveConfig(r)}getCozePlatformConfig(){let t=this.getConfig().platforms?.coze;return!t||!t.token?null:{token:t.token}}getCozeToken(){return this.getCozePlatformConfig()?.token||null}setCozePlatformConfig(e){if(!e.token||typeof e.token!="string"||e.token.trim()==="")throw new Error("\u6263\u5B50 API Token \u4E0D\u80FD\u4E3A\u7A7A");this.updatePlatformConfig("coze",{token:e.token.trim()})}isCozeConfigValid(){let e=this.getCozePlatformConfig();return e!==null&&typeof e.token=="string"&&e.token.trim()!==""}async _updateMCPServerToolStats(e,t,r,n=!0){let s=this.getMutableConfig();s.mcpServerConfig||(s.mcpServerConfig={}),s.mcpServerConfig[e]||(s.mcpServerConfig[e]={tools:{}}),s.mcpServerConfig[e].tools[t]||(s.mcpServerConfig[e].tools[t]={enable:!0});let i=s.mcpServerConfig[e].tools[t],a=i.usageCount||0,g=i.lastUsedTime;n&&(i.usageCount=a+1),(!g||new Date(r)>new Date(g))&&(i.lastUsedTime=Ee(r).format("YYYY-MM-DD HH:mm:ss")),this.saveConfig(s)}async updateCustomMCPToolStats(e,t,r){try{let n,s,i=!0,a;if(typeof r=="string"){let y=e;n=`${y}__${t}`,s=r,a=`${y}/${t}`}else n=e,s=t,i=r||!0,a=n;let g=this.getCustomMCPTools(),u=g.findIndex(y=>y.name===n);if(u===-1)return;let p=[...g],h=p[u];h.stats||(h.stats={});let S=h.stats.usageCount||0,T=h.stats.lastUsedTime;i&&(h.stats.usageCount=S+1),(!T||new Date(s)>new Date(T))&&(h.stats.lastUsedTime=Ee(s).format("YYYY-MM-DD HH:mm:ss")),await this.updateCustomMCPTools(p)}catch(n){if(typeof r=="string"){let s=e,i=t;c.error(`\u66F4\u65B0 customMCP \u5DE5\u5177\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25 (${s}/${i}): ${n instanceof Error?n.message:String(n)}`)}else{let s=e;c.error(`\u66F4\u65B0 customMCP \u5DE5\u5177\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25 (${s}): ${n instanceof Error?n.message:String(n)}`)}}}async acquireStatsUpdateLock(e){if(this.statsUpdateLocks.has(e))return c.debug(`\u5DE5\u5177 ${e} \u7684\u7EDF\u8BA1\u66F4\u65B0\u6B63\u5728\u8FDB\u884C\u4E2D\uFF0C\u8DF3\u8FC7\u672C\u6B21\u66F4\u65B0`),!1;let t=new Promise(n=>{});this.statsUpdateLocks.set(e,t);let r=setTimeout(()=>{this.releaseStatsUpdateLock(e)},this.STATS_UPDATE_TIMEOUT);return this.statsUpdateLockTimeouts.set(e,r),!0}releaseStatsUpdateLock(e){this.statsUpdateLocks.delete(e);let t=this.statsUpdateLockTimeouts.get(e);t&&(clearTimeout(t),this.statsUpdateLockTimeouts.delete(e)),c.debug(`\u5DF2\u91CA\u653E\u5DE5\u5177 ${e} \u7684\u7EDF\u8BA1\u66F4\u65B0\u9501`)}async updateToolUsageStatsWithLock(e,t=!0){let r=`custommcp_${e}`;if(await this.acquireStatsUpdateLock(r))try{await this.updateToolUsageStats(e,t),c.debug(`\u5DE5\u5177 ${e} \u7EDF\u8BA1\u66F4\u65B0\u5B8C\u6210`)}catch(n){throw c.error(`\u5DE5\u5177 ${e} \u7EDF\u8BA1\u66F4\u65B0\u5931\u8D25:`,n),n}finally{this.releaseStatsUpdateLock(r)}}async updateMCPServerToolStatsWithLock(e,t,r,n=!0){let s=`mcpserver_${e}_${t}`;if(await this.acquireStatsUpdateLock(s))try{await this.updateMCPServerToolStats(e,t,r,n),c.debug(`MCP \u670D\u52A1\u5DE5\u5177 ${e}/${t} \u7EDF\u8BA1\u66F4\u65B0\u5B8C\u6210`)}catch(i){throw c.error(`MCP \u670D\u52A1\u5DE5\u5177 ${e}/${t} \u7EDF\u8BA1\u66F4\u65B0\u5931\u8D25:`,i),i}finally{this.releaseStatsUpdateLock(s)}}clearAllStatsUpdateLocks(){let e=this.statsUpdateLocks.size;this.statsUpdateLocks.clear();for(let t of this.statsUpdateLockTimeouts.values())clearTimeout(t);this.statsUpdateLockTimeouts.clear(),e>0&&c.info(`\u5DF2\u6E05\u7406 ${e} \u4E2A\u7EDF\u8BA1\u66F4\u65B0\u9501`)}getStatsUpdateLocks(){return Array.from(this.statsUpdateLocks.keys())}getToolCallLogConfig(){return this.getConfig().toolCallLog||{}}updateToolCallLogConfig(e){let t=this.getMutableConfig();t.toolCallLog||(t.toolCallLog={}),Object.assign(t.toolCallLog,e),this.saveConfig(t)}getConfigDir(){return process.env.XIAOZHI_CONFIG_DIR||process.cwd()}},f=de.getInstance();import{randomUUID as rt}from"crypto";import fe from"express";var R=class{static{l(this,"TransportAdapter")}logger;messageHandler;connectionId;config;state="disconnected";constructor(e,t){this.messageHandler=e,this.config=t,this.connectionId=this.generateConnectionId(),this.logger=c}async handleIncomingMessage(e){try{this.logger.debug(`\u5904\u7406\u63A5\u6536\u5230\u7684\u6D88\u606F: ${e.method}`,e);let t=await this.messageHandler.handleMessage(e);t!==null?(this.logger.debug("\u53D1\u9001\u54CD\u5E94\u6D88\u606F:",t),await this.sendMessage(t)):this.logger.debug("\u6536\u5230\u901A\u77E5\u6D88\u606F\uFF0C\u65E0\u9700\u54CD\u5E94")}catch(t){this.logger.error(`\u5904\u7406\u6D88\u606F\u65F6\u51FA\u9519: ${e.method}`,t);let r=this.createErrorResponse(t,e.id);await this.sendMessage(r)}}createErrorResponse(e,t){let r=-32603;return e.message.includes("\u672A\u627E\u5230\u5DE5\u5177")||e.message.includes("\u672A\u77E5\u7684\u65B9\u6CD5")?r=-32601:(e.message.includes("\u53C2\u6570")||e.message.includes("\u4E0D\u80FD\u4E3A\u7A7A"))&&(r=-32602),{jsonrpc:"2.0",error:{code:r,message:e.message,data:{stack:e.stack}},id:t||null}}generateConnectionId(){let e=Date.now(),t=Math.random().toString(36).substr(2,9);return`${this.config.name}_${e}_${t}`}getConnectionId(){return this.connectionId}getState(){return this.state}setState(e){let t=this.state;this.state=e,t!==e&&(this.logger.info(`\u8FDE\u63A5\u72B6\u6001\u53D8\u66F4: ${t} -> ${e}`),this.onStateChange(t,e))}onStateChange(e,t){}getConfig(){return{...this.config}}getMessageHandler(){return this.messageHandler}parseMessage(e){try{let t=JSON.parse(e.trim());return!t.jsonrpc||t.jsonrpc!=="2.0"?(this.logger.warn("\u6536\u5230\u975E JSON-RPC 2.0 \u683C\u5F0F\u7684\u6D88\u606F",t),null):t.method?t:(this.logger.warn("\u6536\u5230\u6CA1\u6709 method \u5B57\u6BB5\u7684\u6D88\u606F",t),null)}catch(t){return this.logger.error("\u89E3\u6790 JSON \u6D88\u606F\u5931\u8D25",{data:e,error:t}),null}}serializeMessage(e){try{return JSON.stringify(e)}catch(t){this.logger.error("\u5E8F\u5217\u5316\u6D88\u606F\u5931\u8D25",{message:e,error:t});let r=t instanceof Error?t.message:String(t);throw new Error(`\u6D88\u606F\u5E8F\u5217\u5316\u5931\u8D25: ${r}`)}}validateMessage(e){return!(!e||typeof e!="object"||e.jsonrpc!=="2.0"||e.method&&typeof e.method!="string"||!e.method&&!e.result&&!e.error)}createTimeoutPromise(e,t){return Promise.race([e,new Promise((r,n)=>{setTimeout(()=>{n(new Error(`\u64CD\u4F5C\u8D85\u65F6: ${t}ms`))},t)})])}};var G=class extends R{static{l(this,"HTTPAdapter")}app;server=null;clients=new Map;port;host;enableSSE;enableRPC;corsOrigin;maxClients;constructor(e,t={name:"http"}){super(e,t),console.warn("[\u5DF2\u5E9F\u5F03] HTTPAdapter \u5C06\u5728 v2.0.0 \u4E2D\u79FB\u9664\u3002\u8BF7\u4F7F\u7528 WebServer \u7684 /mcp \u7AEF\u70B9\u66FF\u4EE3\u3002"),this.port=t.port||3e3,this.host=t.host||"0.0.0.0",this.enableSSE=t.enableSSE!==!1,this.enableRPC=t.enableRPC!==!1,this.corsOrigin=t.corsOrigin||"*",this.maxClients=t.maxClients!==void 0?t.maxClients:100,this.app=fe(),this.setupMiddleware()}async initialize(){this.logger.info("\u521D\u59CB\u5316 HTTP \u9002\u914D\u5668");try{this.setupRoutes(),this.setState("connecting"),this.logger.info("HTTP \u9002\u914D\u5668\u521D\u59CB\u5316\u5B8C\u6210")}catch(e){throw this.logger.error("HTTP \u9002\u914D\u5668\u521D\u59CB\u5316\u5931\u8D25",e),this.setState("error"),e}}async start(){if(this.server){this.logger.warn("HTTP \u670D\u52A1\u5668\u5DF2\u5728\u8FD0\u884C");return}return this.logger.info(`\u542F\u52A8 HTTP \u670D\u52A1\u5668\u5728 ${this.host}:${this.port}`),new Promise((e,t)=>{this.server=this.app.listen(this.port,this.host,()=>{this.setState("connected"),this.logger.info("HTTP \u9002\u914D\u5668\u542F\u52A8\u6210\u529F"),this.logger.info(`- RPC \u7AEF\u70B9: http://${this.host}:${this.port}/rpc`),this.enableSSE&&(this.logger.info(`- SSE \u7AEF\u70B9: http://${this.host}:${this.port}/sse`),this.logger.info(`- \u6D88\u606F\u7AEF\u70B9: http://${this.host}:${this.port}/messages`)),e()}),this.server?.on("error",r=>{this.logger.error("HTTP \u670D\u52A1\u5668\u9519\u8BEF",r),this.setState("error"),t(r)})})}async stop(){if(this.server)return this.logger.info("\u505C\u6B62 HTTP \u670D\u52A1\u5668"),new Promise(e=>{for(let t of this.clients.values())t.response.end();this.clients.clear(),this.server.close(()=>{this.server=null,this.setState("disconnected"),this.logger.info("HTTP \u670D\u52A1\u5668\u5DF2\u505C\u6B62"),e()})})}async sendMessage(e){this.clients.size>0&&this.broadcastToClients(e)}setupMiddleware(){this.app.use(fe.json({limit:"10mb"})),this.app.use(fe.urlencoded({extended:!0})),this.app.use((e,t,r)=>{t.header("Access-Control-Allow-Origin",this.corsOrigin),t.header("Access-Control-Allow-Methods","GET, POST, OPTIONS"),t.header("Access-Control-Allow-Headers","Content-Type, Accept"),t.header("Cache-Control","no-cache"),r()}),this.app.use((e,t,r)=>{this.logger.debug(`${e.method} ${e.path}`,{query:e.query,headers:e.headers}),r()})}setupRoutes(){this.enableSSE&&(this.app.get("/sse",this.handleSSE.bind(this)),this.app.post("/messages",this.handleMessages.bind(this))),this.enableRPC&&this.app.post("/rpc",this.handleRPC.bind(this)),this.app.get("/status",this.handleStatus.bind(this)),this.app.get("/health",this.handleHealth.bind(this))}handleSSE(e,t){if(this.clients.size>=this.maxClients){t.status(503).json({error:"\u670D\u52A1\u5668\u7E41\u5FD9\uFF0C\u5BA2\u6237\u7AEF\u8FDE\u63A5\u6570\u5DF2\u8FBE\u4E0A\u9650",maxClients:this.maxClients});return}let r=Date.now().toString(),n=rt();t.setHeader("Content-Type","text/event-stream"),t.setHeader("Cache-Control","no-cache, no-transform"),t.setHeader("Connection","keep-alive"),t.setHeader("X-Accel-Buffering","no");let s={id:r,sessionId:n,response:t,connectedAt:new Date};this.clients.set(n,s),this.logger.info(`SSE \u5BA2\u6237\u7AEF\u5DF2\u8FDE\u63A5: ${r} (\u4F1A\u8BDD: ${n})`),t.write(`event: endpoint
4
- data: /messages?sessionId=${n}
5
-
6
- `),e.on("close",()=>{this.clients.delete(n),this.logger.info(`SSE \u5BA2\u6237\u7AEF\u5DF2\u65AD\u5F00\u8FDE\u63A5: ${r} (\u4F1A\u8BDD: ${n})`)}),e.on("error",i=>{this.logger.error(`SSE \u5BA2\u6237\u7AEF\u8FDE\u63A5\u9519\u8BEF: ${r}`,i),this.clients.delete(n)})}async handleMessages(e,t){try{let r=e.query.sessionId,n=e.body;if(this.logger.debug(`\u6536\u5230 SSE \u6D88\u606F (\u4F1A\u8BDD: ${r}):`,n),!r||!this.clients.has(r)){t.status(400).json({jsonrpc:"2.0",error:{code:-32600,message:"\u65E0\u6548\u6216\u7F3A\u5C11 sessionId"},id:n.id});return}let s=await this.messageHandler.handleMessage(n);this.logger.debug("SSE \u6D88\u606F\u5904\u7406\u54CD\u5E94:",s);let i=this.clients.get(r);i&&s!==null&&this.sendToClient(i,s),t.status(202).send()}catch(r){this.logger.error("\u5904\u7406 SSE \u6D88\u606F\u65F6\u51FA\u9519",r),t.status(500).json({jsonrpc:"2.0",error:{code:-32603,message:r.message}})}}async handleRPC(e,t){try{let r=e.body;this.logger.debug("\u6536\u5230 RPC \u6D88\u606F:",r);let n=await this.messageHandler.handleMessage(r);t.json(n)}catch(r){this.logger.error("\u5904\u7406 RPC \u6D88\u606F\u65F6\u51FA\u9519",r),t.status(500).json({jsonrpc:"2.0",error:{code:-32603,message:r.message},id:e.body?.id||null})}}handleStatus(e,t){t.json({status:"ok",mode:"mcp-server",serviceManager:"running",clients:this.clients.size,tools:0,maxClients:this.maxClients,enableSSE:this.enableSSE,enableRPC:this.enableRPC,uptime:process.uptime()})}handleHealth(e,t){t.json({status:"ok",mode:"mcp-server",timestamp:new Date().toISOString()})}sendToClient(e,t){try{let r=this.serializeMessage(t);e.response.write(`data: ${r}
7
-
8
- `),this.logger.debug(`\u6D88\u606F\u5DF2\u53D1\u9001\u5230\u5BA2\u6237\u7AEF ${e.id}`,{sessionId:e.sessionId,messageId:t.id})}catch(r){this.logger.error(`\u5411\u5BA2\u6237\u7AEF ${e.id} \u53D1\u9001\u6D88\u606F\u5931\u8D25`,r),this.clients.delete(e.sessionId)}}broadcastToClients(e){for(let t of this.clients.values())this.sendToClient(t,e)}getStatus(){return{isRunning:this.server!==null,port:this.port,host:this.host,clientCount:this.clients.size,maxClients:this.maxClients,enableSSE:this.enableSSE,enableRPC:this.enableRPC,connectionId:this.connectionId,state:this.state}}getClients(){return Array.from(this.clients.values()).map(e=>({id:e.id,sessionId:e.sessionId,connectedAt:e.connectedAt}))}};var J=class extends R{static{l(this,"StdioAdapter")}messageBuffer="";isRunning=!1;encoding;bufferSize;constructor(e,t={name:"stdio"}){super(e,t),this.encoding=t.encoding||"utf8",this.bufferSize=t.bufferSize||1024*1024}async initialize(){this.logger.info("\u521D\u59CB\u5316 Stdio \u9002\u914D\u5668");try{process.stdin.setEncoding(this.encoding),this.setupProcessHandlers(),this.setState("connecting"),this.logger.info("Stdio \u9002\u914D\u5668\u521D\u59CB\u5316\u5B8C\u6210")}catch(e){throw this.logger.error("Stdio \u9002\u914D\u5668\u521D\u59CB\u5316\u5931\u8D25",e),this.setState("error"),e}}async start(){if(this.isRunning){this.logger.warn("Stdio \u9002\u914D\u5668\u5DF2\u5728\u8FD0\u884C");return}this.logger.info("\u542F\u52A8 Stdio \u9002\u914D\u5668");try{this.isRunning=!0,this.setupStdioHandlers(),this.setState("connected"),this.logger.info("Stdio \u9002\u914D\u5668\u542F\u52A8\u6210\u529F\uFF0C\u7B49\u5F85\u6D88\u606F...")}catch(e){throw this.logger.error("\u542F\u52A8 Stdio \u9002\u914D\u5668\u5931\u8D25",e),this.setState("error"),this.isRunning=!1,e}}async stop(){if(this.isRunning){this.logger.info("\u505C\u6B62 Stdio \u9002\u914D\u5668");try{this.isRunning=!1,this.removeStdioHandlers(),this.setState("disconnected"),this.logger.info("Stdio \u9002\u914D\u5668\u5DF2\u505C\u6B62")}catch(e){throw this.logger.error("\u505C\u6B62 Stdio \u9002\u914D\u5668\u65F6\u51FA\u9519",e),e}}}async sendMessage(e){try{let t=this.serializeMessage(e);process.stdout.write(`${t}
9
- `),this.logger.debug("\u6D88\u606F\u5DF2\u53D1\u9001\u5230 stdout",{messageId:e.id,method:"method"in e?e.method:"response"})}catch(t){throw this.logger.error("\u53D1\u9001\u6D88\u606F\u5931\u8D25",t),t}}setupStdioHandlers(){process.stdin.on("data",this.handleStdinData.bind(this)),process.stdin.on("end",this.handleStdinEnd.bind(this)),process.stdin.on("error",this.handleStdinError.bind(this))}removeStdioHandlers(){process.stdin.removeListener("data",this.handleStdinData.bind(this)),process.stdin.removeListener("end",this.handleStdinEnd.bind(this)),process.stdin.removeListener("error",this.handleStdinError.bind(this))}async handleStdinData(e){try{if(this.messageBuffer+=e.toString(),this.messageBuffer.length>this.bufferSize){this.logger.warn(`\u6D88\u606F\u7F13\u51B2\u533A\u8D85\u8FC7\u9650\u5236 (${this.bufferSize} bytes)\uFF0C\u6E05\u7A7A\u7F13\u51B2\u533A`),this.messageBuffer="";return}let t=this.messageBuffer.split(`
10
- `);this.messageBuffer=t.pop()||"";for(let r of t){let n=r.trim();n&&await this.processMessageLine(n)}}catch(t){this.logger.error("\u5904\u7406 stdin \u6570\u636E\u65F6\u51FA\u9519",t)}}async processMessageLine(e){try{this.logger.debug(`\u5904\u7406\u6D88\u606F\u884C: ${e.substring(0,200)}...`);let t=this.parseMessage(e);t&&await this.handleIncomingMessage(t)}catch(t){this.logger.error(`\u5904\u7406\u6D88\u606F\u884C\u5931\u8D25: ${e.substring(0,100)}...`,t);let r={jsonrpc:"2.0",error:{code:-32700,message:"\u89E3\u6790\u9519\u8BEF",data:{originalLine:e.substring(0,100)}},id:null};await this.sendMessage(r)}}handleStdinEnd(){this.logger.info("\u6807\u51C6\u8F93\u5165\u5DF2\u5173\u95ED\uFF0C\u505C\u6B62\u9002\u914D\u5668"),this.stop().catch(e=>{this.logger.error("\u505C\u6B62\u9002\u914D\u5668\u65F6\u51FA\u9519",e)})}handleStdinError(e){this.logger.error("\u6807\u51C6\u8F93\u5165\u9519\u8BEF",e),this.setState("error")}setupProcessHandlers(){let e=l(()=>{this.logger.info("\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u6E05\u7406\u8D44\u6E90"),this.stop().finally(()=>{process.exit(0)})},"handleExit");process.on("SIGINT",e),process.on("SIGTERM",e),process.on("uncaughtException",t=>{this.logger.error("\u672A\u6355\u83B7\u7684\u5F02\u5E38",t),this.setState("error")}),process.on("unhandledRejection",(t,r)=>{this.logger.error("\u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD",{reason:t,promise:r})})}getStatus(){return{isRunning:this.isRunning,bufferSize:this.messageBuffer.length,encoding:this.encoding,connectionId:this.connectionId,state:this.state}}clearBuffer(){this.messageBuffer="",this.logger.debug("\u6D88\u606F\u7F13\u51B2\u533A\u5DF2\u6E05\u7A7A")}};import xe,{WebSocketServer as nt}from"ws";var q=class extends R{static{l(this,"WebSocketAdapter")}ws=null;wsServer=null;endpointUrl;mode;wsState="disconnected";reconnectOptions;reconnectState;connectionTimeout=null;compression;batchQueue=[];batchTimer=null;batchSize;batchTimeout;connections=new Map;maxConnections;constructor(e,t){super(e,t),this.endpointUrl=t.endpointUrl,this.mode=t.mode||"client",this.compression=t.compression||!1,this.batchSize=t.batchSize||10,this.batchTimeout=t.batchTimeout||100,this.maxConnections=t.maxConnections||100,this.reconnectOptions={enabled:!0,maxAttempts:5,initialInterval:1e3,maxInterval:3e4,backoffStrategy:"exponential",backoffMultiplier:1.5,timeout:1e4,jitter:!0,...t.reconnect},this.reconnectState={attempts:0,nextInterval:this.reconnectOptions.initialInterval,timer:null,lastError:null,isManualDisconnect:!1}}async initialize(){this.logger.info(`\u521D\u59CB\u5316 WebSocket \u9002\u914D\u5668 (${this.mode} \u6A21\u5F0F)`);try{this.setState("connecting"),this.wsState="connecting",this.mode==="client"?await this.initializeClient():await this.initializeServer(),this.logger.info("WebSocket \u9002\u914D\u5668\u521D\u59CB\u5316\u5B8C\u6210")}catch(e){throw this.logger.error("WebSocket \u9002\u914D\u5668\u521D\u59CB\u5316\u5931\u8D25",e),this.setState("error"),this.wsState="failed",e}}async initializeClient(){return new Promise((e,t)=>{this.connectionTimeout=setTimeout(()=>{let r=new Error(`\u8FDE\u63A5\u8D85\u65F6 (${this.reconnectOptions.timeout}ms)`);this.handleConnectionError(r),t(r)},this.reconnectOptions.timeout),this.ws=new xe(this.endpointUrl),this.compression,this.ws.on("open",()=>{this.handleConnectionSuccess(),e()}),this.ws.on("message",r=>{this.handleIncomingData(r)}),this.ws.on("close",(r,n)=>{this.handleConnectionClose(r,n.toString())}),this.ws.on("error",r=>{this.handleConnectionError(r),t(r)})})}async initializeServer(){return new Promise((e,t)=>{try{let r=new URL(this.endpointUrl),n=Number.parseInt(r.port)||8080;this.wsServer=new nt({port:n,perMessageDeflate:this.compression}),this.wsServer.on("connection",(s,i)=>{this.handleNewConnection(s,i)}),this.wsServer.on("error",s=>{this.logger.error("WebSocket \u670D\u52A1\u5668\u9519\u8BEF",s),t(s)}),this.logger.info(`WebSocket \u670D\u52A1\u5668\u76D1\u542C\u7AEF\u53E3 ${n}`),e()}catch(r){t(r)}})}async start(){if(this.wsState==="connected"){this.logger.warn("WebSocket \u9002\u914D\u5668\u5DF2\u542F\u52A8");return}this.logger.info("\u542F\u52A8 WebSocket \u9002\u914D\u5668");try{this.setState("connected"),this.wsState="connected",this.logger.info("WebSocket \u9002\u914D\u5668\u542F\u52A8\u6210\u529F")}catch(e){throw this.logger.error("\u542F\u52A8 WebSocket \u9002\u914D\u5668\u5931\u8D25",e),this.setState("error"),this.wsState="failed",e}}async stop(){this.logger.info("\u505C\u6B62 WebSocket \u9002\u914D\u5668");try{this.reconnectState.isManualDisconnect=!0,this.reconnectState.timer&&(clearTimeout(this.reconnectState.timer),this.reconnectState.timer=null),this.batchTimer&&(clearTimeout(this.batchTimer),this.batchTimer=null),await this.flushBatchQueue(),this.ws&&(this.ws.close(),this.ws=null),this.wsServer&&(this.wsServer.close(),this.wsServer=null);for(let[e,t]of this.connections)t.close();this.connections.clear(),this.setState("disconnected"),this.wsState="disconnected",this.logger.info("WebSocket \u9002\u914D\u5668\u5DF2\u505C\u6B62")}catch(e){throw this.logger.error("\u505C\u6B62 WebSocket \u9002\u914D\u5668\u65F6\u51FA\u9519",e),e}}async sendMessage(e){if(this.wsState!=="connected")throw new Error(`WebSocket \u672A\u8FDE\u63A5 (\u72B6\u6001: ${this.wsState})`);return this.batchSize>1?this.addToBatchQueue(e):this.sendMessageDirect(e)}async sendMessageDirect(e){try{let t=this.serializeMessage(e);if(this.mode==="client"&&this.ws)this.ws.send(t);else if(this.mode==="server")for(let r of this.connections.values())r.readyState===xe.OPEN&&r.send(t);this.logger.debug("\u6D88\u606F\u5DF2\u53D1\u9001",{messageId:e.id,method:"method"in e?e.method:"response"})}catch(t){throw this.logger.error("\u53D1\u9001\u6D88\u606F\u5931\u8D25",t),t}}async addToBatchQueue(e){return new Promise((t,r)=>{this.batchQueue.push({message:e,timestamp:Date.now(),resolve:t,reject:r}),this.batchQueue.length>=this.batchSize?this.flushBatchQueue():this.batchTimer||(this.batchTimer=setTimeout(()=>{this.flushBatchQueue()},this.batchTimeout))})}async flushBatchQueue(){if(this.batchQueue.length===0)return;this.batchTimer&&(clearTimeout(this.batchTimer),this.batchTimer=null);let e=this.batchQueue.splice(0);try{let r={jsonrpc:"2.0",method:"batch",params:{messages:e.map(n=>n.message)},id:`batch_${Date.now()}`};await this.sendMessageDirect(r);for(let n of e)n.resolve();this.logger.debug(`\u6279\u5904\u7406\u53D1\u9001 ${e.length} \u6761\u6D88\u606F`)}catch(t){for(let r of e)r.reject(t);this.logger.error("\u6279\u5904\u7406\u53D1\u9001\u5931\u8D25",t)}}async handleIncomingData(e){try{let t=e.toString(),r=this.parseMessage(t);if(r)if(r.method==="batch"&&r.params?.messages)for(let n of r.params.messages)await this.handleIncomingMessage(n);else await this.handleIncomingMessage(r)}catch(t){this.logger.error("\u5904\u7406\u63A5\u6536\u6570\u636E\u5931\u8D25",t)}}handleConnectionSuccess(){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.setState("connected"),this.wsState="connected",this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.lastError=null,this.logger.info("WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB")}handleConnectionError(e){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.reconnectState.lastError=e,this.logger.error("WebSocket \u8FDE\u63A5\u9519\u8BEF",e),this.setState("error"),this.wsState="failed",this.cleanupConnection()}handleConnectionClose(e,t){this.setState("disconnected"),this.wsState="disconnected",this.logger.info(`WebSocket \u8FDE\u63A5\u5DF2\u5173\u95ED (\u4EE3\u7801: ${e}, \u539F\u56E0: ${t})`),!this.reconnectState.isManualDisconnect&&(this.shouldReconnect()?this.scheduleReconnect():(this.wsState="failed",this.logger.warn(`\u5DF2\u8FBE\u5230\u6700\u5927\u91CD\u8FDE\u6B21\u6570 (${this.reconnectOptions.maxAttempts})\uFF0C\u505C\u6B62\u91CD\u8FDE`)))}handleNewConnection(e,t){if(this.connections.size>=this.maxConnections){this.logger.warn("\u8FBE\u5230\u6700\u5927\u8FDE\u63A5\u6570\u9650\u5236\uFF0C\u62D2\u7EDD\u65B0\u8FDE\u63A5"),e.close(1013,"\u670D\u52A1\u5668\u7E41\u5FD9");return}let r=`${this.getConnectionId()}_${this.connections.size}`;this.connections.set(r,e),this.logger.info(`\u65B0 WebSocket \u8FDE\u63A5: ${r}`),e.on("message",n=>{this.handleIncomingData(n)}),e.on("close",()=>{this.connections.delete(r),this.logger.info(`WebSocket \u8FDE\u63A5\u5DF2\u65AD\u5F00: ${r}`)}),e.on("error",n=>{this.logger.error(`WebSocket \u8FDE\u63A5\u9519\u8BEF ${r}:`,n),this.connections.delete(r)})}cleanupConnection(){this.ws&&(this.ws.removeAllListeners(),this.ws=null)}shouldReconnect(){return this.reconnectOptions.enabled&&this.reconnectState.attempts<this.reconnectOptions.maxAttempts&&!this.reconnectState.isManualDisconnect}scheduleReconnect(){this.wsState="reconnecting",this.reconnectState.attempts++;let e=this.calculateReconnectInterval();this.reconnectOptions.jitter&&(e+=Math.random()*1e3),this.logger.info(`\u5B89\u6392\u91CD\u8FDE (\u7B2C ${this.reconnectState.attempts} \u6B21\uFF0C${e}ms \u540E)`),this.reconnectState.timer=setTimeout(async()=>{try{await this.initializeClient()}catch(t){this.logger.error("\u91CD\u8FDE\u5931\u8D25",t),this.shouldReconnect()?this.scheduleReconnect():this.wsState="failed"}},e)}calculateReconnectInterval(){let{backoffStrategy:e,initialInterval:t,maxInterval:r,backoffMultiplier:n}=this.reconnectOptions,s=this.reconnectState.attempts,i;switch(e){case"linear":i=t+s*1e3;break;case"exponential":i=t*n**s;break;default:i=t;break}return Math.min(i,r)}getStatus(){return{wsState:this.wsState,connectionState:this.state,mode:this.mode,endpointUrl:this.endpointUrl,connectionCount:this.connections.size,reconnectAttempts:this.reconnectState.attempts,batchQueueSize:this.batchQueue.length,compression:this.compression}}async forceReconnect(){if(this.mode!=="client")throw new Error("\u53EA\u6709\u5BA2\u6237\u7AEF\u6A21\u5F0F\u652F\u6301\u91CD\u8FDE");this.logger.info("\u5F3A\u5236\u91CD\u8FDE"),this.reconnectState.attempts=0,this.reconnectState.isManualDisconnect=!1,this.ws&&this.ws.close(),await this.initializeClient()}};import{EventEmitter as Ne}from"events";import*as F from"fs";import*as L from"path";import Q from"pino";import{realpathSync as st}from"fs";import{tmpdir as it}from"os";import d from"path";import{fileURLToPath as ke}from"url";var ve={NAME:"xiaozhi-mcp-service",DEFAULT_PORT:3e3,DEFAULT_WEB_UI_PORT:9999,PID_FILE:"xiaozhi.pid",LOG_FILE:"xiaozhi.log"},H={FILE_NAMES:["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"],DEFAULT_FILE:"xiaozhi.config.default.json",DIR_ENV_VAR:"XIAOZHI_CONFIG_DIR"},_={WORK_DIR:".xiaozhi",TEMPLATES_DIR:"templates",LOGS_DIR:"logs"},Ie={GENERAL_ERROR:"GENERAL_ERROR",CONFIG_ERROR:"CONFIG_ERROR",SERVICE_ERROR:"SERVICE_ERROR",VALIDATION_ERROR:"VALIDATION_ERROR",FILE_ERROR:"FILE_ERROR",PROCESS_ERROR:"PROCESS_ERROR",NETWORK_ERROR:"NETWORK_ERROR",PERMISSION_ERROR:"PERMISSION_ERROR"};import C from"fs";import P from"path";var Se=class o extends Error{constructor(t,r,n=1,s){super(t);this.code=r;this.exitCode=n;this.suggestions=s;this.name="CLIError",Error.captureStackTrace&&Error.captureStackTrace(this,o)}static{l(this,"CLIError")}static withSuggestions(t,r,n){return new o(t,r,1,n)}};var m=class o extends Se{static{l(this,"FileError")}constructor(e,t,r){let n=t?`${e}: ${t}`:e;super(n,Ie.FILE_ERROR,1,r),this.name="FileError"}static notFound(e){return new o("\u6587\u4EF6\u4E0D\u5B58\u5728",e,["\u68C0\u67E5\u6587\u4EF6\u8DEF\u5F84\u662F\u5426\u6B63\u786E"])}static permissionDenied(e){return new o("\u6743\u9650\u4E0D\u8DB3",e,["\u68C0\u67E5\u6587\u4EF6\u6743\u9650\u6216\u4F7F\u7528\u7BA1\u7406\u5458\u6743\u9650\u8FD0\u884C"])}static alreadyExists(e){return new o("\u6587\u4EF6\u5DF2\u5B58\u5728",e,["\u4F7F\u7528\u4E0D\u540C\u7684\u6587\u4EF6\u540D\u6216\u5220\u9664\u73B0\u6709\u6587\u4EF6"])}};var N=class o{static{l(this,"FileUtils")}static exists(e){try{return C.existsSync(e)}catch{return!1}}static ensureDir(e){try{C.existsSync(e)||C.mkdirSync(e,{recursive:!0})}catch{throw new m("\u65E0\u6CD5\u521B\u5EFA\u76EE\u5F55",e)}}static readFile(e,t="utf8"){try{if(!o.exists(e))throw m.notFound(e);return C.readFileSync(e,t)}catch(r){throw r instanceof m?r:new m("\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6",e)}}static writeFile(e,t,r){try{if(!r?.overwrite&&o.exists(e))throw m.alreadyExists(e);let n=P.dirname(e);o.ensureDir(n),C.writeFileSync(e,t,"utf8")}catch(n){throw n instanceof m?n:new m("\u65E0\u6CD5\u5199\u5165\u6587\u4EF6",e)}}static copyFile(e,t,r){try{if(!o.exists(e))throw m.notFound(e);if(!r?.overwrite&&o.exists(t))throw m.alreadyExists(t);let n=P.dirname(t);o.ensureDir(n),C.copyFileSync(e,t)}catch(n){throw n instanceof m?n:new m("\u65E0\u6CD5\u590D\u5236\u6587\u4EF6",e)}}static deleteFile(e){try{o.exists(e)&&C.unlinkSync(e)}catch{throw new m("\u65E0\u6CD5\u5220\u9664\u6587\u4EF6",e)}}static copyDirectory(e,t,r={}){try{if(!o.exists(e))throw m.notFound(e);o.ensureDir(t);let n=C.readdirSync(e);for(let s of n){if(r.exclude?.includes(s))continue;let i=P.join(e,s),a=P.join(t,s);C.statSync(i).isDirectory()?r.recursive!==!1&&o.copyDirectory(i,a,r):o.copyFile(i,a,{overwrite:r.overwrite})}}catch(n){throw n instanceof m?n:new m("\u65E0\u6CD5\u590D\u5236\u76EE\u5F55",e)}}static deleteDirectory(e,t={}){try{o.exists(e)&&C.rmSync(e,{recursive:t.recursive??!0,force:!0})}catch{throw new m("\u65E0\u6CD5\u5220\u9664\u76EE\u5F55",e)}}static getFileInfo(e){try{if(!o.exists(e))throw m.notFound(e);let t=C.statSync(e);return{size:t.size,isFile:t.isFile(),isDirectory:t.isDirectory(),mtime:t.mtime,ctime:t.ctime}}catch(t){throw t instanceof m?t:new m("\u65E0\u6CD5\u83B7\u53D6\u6587\u4EF6\u4FE1\u606F",e)}}static listDirectory(e,t={}){try{if(!o.exists(e))throw m.notFound(e);let r=C.readdirSync(e),n=[];for(let s of r){if(!t.includeHidden&&s.startsWith("."))continue;let i=P.join(e,s);if(n.push(i),t.recursive&&C.statSync(i).isDirectory()){let a=o.listDirectory(i,t);n=n.concat(a)}}return n}catch(r){throw r instanceof m?r:new m("\u65E0\u6CD5\u5217\u51FA\u76EE\u5F55\u5185\u5BB9",e)}}static createTempFile(e="xiaozhi-",t=".tmp"){let r=process.env.TMPDIR||process.env.TEMP||"/tmp",n=Date.now(),s=Math.random().toString(36).substring(2),i=`${e}${n}-${s}${t}`;return P.join(r,i)}static checkPermissions(e,t=C.constants.R_OK|C.constants.W_OK){try{return C.accessSync(e,t),!0}catch{return!1}}static getExtension(e){return P.extname(e).toLowerCase()}static getBaseName(e){return P.basename(e,P.extname(e))}static normalizePath(e){return P.normalize(e)}static resolvePath(e,t){return t?P.resolve(t,e):P.resolve(e)}};var Y=class o{static{l(this,"PathUtils")}static getPidFile(){let e=process.env[H.DIR_ENV_VAR]||process.cwd();return d.join(e,`.${ve.NAME}.pid`)}static getLogFile(e){let t=e||process.cwd();return d.join(t,ve.LOG_FILE)}static getConfigDir(){return process.env[H.DIR_ENV_VAR]||process.cwd()}static getWorkDir(){let e=o.getConfigDir();return d.join(e,_.WORK_DIR)}static getTemplatesDir(){let e=ke(import.meta.url),t=d.dirname(e);return[d.join(t,_.TEMPLATES_DIR),d.join(t,"..","..","..",_.TEMPLATES_DIR),d.join(t,"..","..","..","..",_.TEMPLATES_DIR)]}static findTemplatesDir(){let e=o.getTemplatesDir();for(let t of e)if(N.exists(t))return t;return null}static getTemplatePath(e){let t=o.findTemplatesDir();if(!t)return null;let r=d.join(t,e);return N.exists(r)?r:null}static getScriptDir(){let e=ke(import.meta.url);return d.dirname(e)}static getProjectRoot(){let e=o.getScriptDir();return d.join(e,"..","..","..")}static getDistDir(){let e=o.getProjectRoot();return d.join(e,"dist")}static getRelativePath(e){let t=o.getProjectRoot();return d.relative(t,e)}static resolveConfigPath(e){let t=o.getConfigDir();if(e)return d.join(t,`xiaozhi.config.${e}`);for(let r of H.FILE_NAMES){let n=d.join(t,r);if(N.exists(n))return n}return d.join(t,H.FILE_NAMES[2])}static getDefaultConfigPath(){let e=o.getProjectRoot();return d.join(e,H.DEFAULT_FILE)}static validatePath(e){return!d.normalize(e).includes("..")}static ensurePathWithin(e,t){let r=d.resolve(t,e),n=d.resolve(t);if(!r.startsWith(n))throw new Error(`\u8DEF\u5F84 ${e} \u8D85\u51FA\u4E86\u5141\u8BB8\u7684\u8303\u56F4`);return r}static getExecutablePath(e){let t=process.argv[1];if(!t)return d.join(process.cwd(),`${e}.js`);let r;try{r=st(t)}catch{r=t}let n=d.dirname(r);return d.join(n,`${e}.js`)}static getMcpServerProxyPath(){return o.getExecutablePath("mcpServerProxy")}static getWebServerStandalonePath(){return o.getExecutablePath("WebServerStandalone")}static createSafePath(...e){let t=d.join(...e),r=d.normalize(t);if(r.includes("..")||r.includes("~"))throw new Error(`\u4E0D\u5B89\u5168\u7684\u8DEF\u5F84: ${r}`);return r}static getTempDir(){return process.env.TMPDIR||process.env.TEMP||it()}static getHomeDir(){return process.env.HOME||process.env.USERPROFILE||""}};var X=class{static{l(this,"ToolCallLogger")}pinoLogger;maxRecords;logFilePath;constructor(e,t){if(this.maxRecords=e.maxRecords??100,e.logFilePath)this.logFilePath=L.resolve(L.normalize(e.logFilePath));else{let r=t||Y.getTempDir();this.logFilePath=L.join(L.normalize(r),"tool-calls.jsonl")}this.pinoLogger=this.createPinoLogger(this.logFilePath),c.debug(`ToolCallLogger \u521D\u59CB\u5316: maxRecords=${this.maxRecords}, path=${this.logFilePath}`)}createPinoLogger(e){let t=[];t.push({level:"info",stream:{write:l(r=>{try{let n=JSON.parse(r),s=this.formatConsoleMessage(n);c.info(`[\u5DE5\u5177\u8C03\u7528] ${s}`)}catch{c.info(`[\u5DE5\u5177\u8C03\u7528] ${r.trim()}`)}},"write")}});try{t.push({level:"info",stream:Q.destination({dest:e,sync:!0,append:!0,mkdir:!0})})}catch(r){c.error("\u65E0\u6CD5\u521B\u5EFA\u5DE5\u5177\u8C03\u7528\u65E5\u5FD7\u6587\u4EF6:",r)}return Q({level:"info",timestamp:Q.stdTimeFunctions?.isoTime||(()=>`,"time":${Date.now()}`),formatters:{level:l((r,n)=>({level:n}),"level")},base:null},Q.multistream(t,{dedupe:!0}))}formatConsoleMessage(e){let t=e.toolName||"\u672A\u77E5\u5DE5\u5177",r=e.success!==!1,n=e.duration?` (${e.duration}ms)`:"";return`${r?"\u2705":"\u274C"} ${t}${n}`}async cleanupOldRecords(){try{if(!F.existsSync(this.logFilePath))return;let t=F.readFileSync(this.logFilePath,"utf8").trim().split(`
11
- `).filter(i=>i.trim()!=="");if(t.length<=this.maxRecords)return;let r=t.length-this.maxRecords+1,n=t.slice(r),s=n.join(`
12
- `)+(n.length>0?`
13
- `:"");F.writeFileSync(this.logFilePath,s,"utf8"),c.debug(`\u5DF2\u6E05\u7406 ${r} \u6761\u65E7\u7684\u5DE5\u5177\u8C03\u7528\u8BB0\u5F55\uFF0C\u4FDD\u7559\u6700\u65B0 ${this.maxRecords} \u6761`)}catch(e){c.error("\u6E05\u7406\u65E7\u5DE5\u5177\u8C03\u7528\u8BB0\u5F55\u5931\u8D25:",e)}}async recordToolCall(e){try{await this.cleanupOldRecords(),this.pinoLogger.info(e,e.toolName)}catch(t){c.error("\u8BB0\u5F55\u5DE5\u5177\u8C03\u7528\u5931\u8D25:",t)}}getLogFilePath(){return this.logFilePath}getMaxRecords(){return this.maxRecords}};import{createHash as ot}from"crypto";function $(o,e){let t=ot("md5").update(JSON.stringify(e||{})).digest("hex");return`${o}_${t}`}l($,"generateCacheKey");function j(o,e){let t=new Date(o).getTime();return Date.now()-t>e}l(j,"isCacheExpired");function D(o){let e=Date.now(),t=new Date(o.timestamp).getTime();return!!(o.consumed&&e-t>6e4||e-t>o.ttl||o.status==="failed")}l(D,"shouldCleanupCache");var x={TIMEOUT:8e3,CACHE_TTL:3e5,CLEANUP_INTERVAL:6e4,MAX_CACHE_SIZE:1e3,ENABLE_ONE_TIME_CACHE:!0};var Z=class{static{l(this,"CacheLifecycleManager")}logger;cleanupInterval;statistics;lastCleanupTime;constructor(e){this.logger=e,this.statistics=this.initializeStatistics(),this.lastCleanupTime=new Date().toISOString()}initializeStatistics(){return{totalEntries:0,pendingTasks:0,completedTasks:0,failedTasks:0,consumedEntries:0,cacheHitRate:0,lastCleanupTime:new Date().toISOString(),memoryUsage:0}}startAutoCleanup(){if(this.cleanupInterval){this.logger.warn("[CacheLifecycle] \u81EA\u52A8\u6E05\u7406\u5B9A\u65F6\u5668\u5DF2\u7ECF\u5728\u8FD0\u884C");return}this.cleanupInterval=setInterval(()=>{this.performCleanup().catch(e=>{this.logger.error(`[CacheLifecycle] \u81EA\u52A8\u6E05\u7406\u5931\u8D25: ${e}`)})},x.CLEANUP_INTERVAL),this.logger.debug(`[CacheLifecycle] \u542F\u52A8\u81EA\u52A8\u6E05\u7406\u5B9A\u65F6\u5668\uFF0C\u95F4\u9694: ${x.CLEANUP_INTERVAL}ms`)}stopAutoCleanup(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=void 0,this.logger.info("[CacheLifecycle] \u505C\u6B62\u81EA\u52A8\u6E05\u7406\u5B9A\u65F6\u5668"))}createCacheEntry(e,t,r,n="pending",s){let i={result:r,timestamp:new Date().toISOString(),ttl:x.CACHE_TTL,status:n,consumed:!1,taskId:s,retryCount:0};return this.logger.debug(`[CacheLifecycle] \u521B\u5EFA\u7F13\u5B58\u6761\u76EE: ${e}, \u72B6\u6001: ${n}`),i}updateCacheStatus(e,t,r,n,s){if(!e.customMCPResults||!e.customMCPResults[t])return this.logger.warn(`[CacheLifecycle] \u7F13\u5B58\u6761\u76EE\u4E0D\u5B58\u5728: ${t}`),!1;let i=e.customMCPResults[t],a=i.status;return this.logStateTransition(t,a,r),i.status=r,i.timestamp=new Date().toISOString(),n&&(i.result=n),s&&r==="failed"&&(i.result={content:[{type:"text",text:`\u4EFB\u52A1\u5931\u8D25: ${s}`}]},i.consumed=!0),r==="completed"&&(i.consumed=!1),this.logger.debug(`[CacheLifecycle] \u66F4\u65B0\u7F13\u5B58\u72B6\u6001: ${t} ${a} -> ${r}`),!0}markAsConsumed(e,t){if(!e.customMCPResults||!e.customMCPResults[t])return!1;let r=e.customMCPResults[t];return r.consumed?(this.logger.debug(`[CacheLifecycle] \u7F13\u5B58\u5DF2\u6807\u8BB0\u4E3A\u6D88\u8D39: ${t}`),!0):(r.consumed=!0,r.timestamp=new Date().toISOString(),this.logStateTransition(t,r.status,"consumed"),this.logger.debug(`[CacheLifecycle] \u6807\u8BB0\u7F13\u5B58\u4E3A\u5DF2\u6D88\u8D39: ${t}`),!0)}isCacheAvailable(e,t){if(!e.customMCPResults||!e.customMCPResults[t])return!1;let r=e.customMCPResults[t];return j(r.timestamp,r.ttl)?(this.logger.debug(`[CacheLifecycle] \u7F13\u5B58\u5DF2\u8FC7\u671F: ${t}`),!1):r.consumed?(this.logger.debug(`[CacheLifecycle] \u7F13\u5B58\u5DF2\u6D88\u8D39: ${t}`),!1):r.status!=="completed"?(this.logger.debug(`[CacheLifecycle] \u7F13\u5B58\u72B6\u6001\u672A\u5B8C\u6210: ${t}, \u72B6\u6001: ${r.status}`),!1):!0}async performCleanup(){try{this.logger.debug("[CacheLifecycle] \u6267\u884C\u7F13\u5B58\u6E05\u7406"),this.lastCleanupTime=new Date().toISOString()}catch(e){throw this.logger.error(`[CacheLifecycle] \u6E05\u7406\u5931\u8D25: ${e}`),e}}cleanupCacheEntries(e,t){if(!e.customMCPResults)return{cleaned:0,total:0};let r=Object.entries(e.customMCPResults),n=0,s=t||r.map(([i])=>i);for(let i of s){let a=e.customMCPResults[i];a&&D(a)&&(delete e.customMCPResults[i],n++,this.logger.debug(`[CacheLifecycle] \u6E05\u7406\u7F13\u5B58\u6761\u76EE: ${i}`))}return this.logger.info(`[CacheLifecycle] \u6E05\u7406\u5B8C\u6210: ${n}/${s.length}`),{cleaned:n,total:s.length}}cleanupExpiredCache(e){if(!e.customMCPResults)return{cleaned:0,total:0};let t=Object.entries(e.customMCPResults),r=0;for(let[n,s]of t)j(s.timestamp,s.ttl)&&(delete e.customMCPResults[n],r++,this.logger.debug(`[CacheLifecycle] \u6E05\u7406\u8FC7\u671F\u7F13\u5B58: ${n}`));return r>0&&this.logger.info(`[CacheLifecycle] \u6E05\u7406\u8FC7\u671F\u7F13\u5B58: ${r}/${t.length}`),{cleaned:r,total:t.length}}cleanupConsumedCache(e){if(!e.customMCPResults)return{cleaned:0,total:0};let t=Object.entries(e.customMCPResults),r=0,n=Date.now();for(let[s,i]of t)if(i.consumed){let a=new Date(i.timestamp).getTime();n-a>6e4&&(delete e.customMCPResults[s],r++,this.logger.debug(`[CacheLifecycle] \u6E05\u7406\u5DF2\u6D88\u8D39\u7F13\u5B58: ${s}`))}return r>0&&this.logger.info(`[CacheLifecycle] \u6E05\u7406\u5DF2\u6D88\u8D39\u7F13\u5B58: ${r}/${t.length}`),{cleaned:r,total:t.length}}updateStatistics(e){if(!e.customMCPResults){this.statistics=this.initializeStatistics();return}let t=Object.values(e.customMCPResults);this.statistics.totalEntries=t.length,this.statistics.pendingTasks=t.filter(s=>s.status==="pending").length,this.statistics.completedTasks=t.filter(s=>s.status==="completed").length,this.statistics.failedTasks=t.filter(s=>s.status==="failed").length,this.statistics.consumedEntries=t.filter(s=>s.consumed).length;let r=this.statistics.completedTasks,n=this.statistics.consumedEntries;this.statistics.cacheHitRate=r>0?n/r*100:0,this.statistics.lastCleanupTime=this.lastCleanupTime,this.statistics.memoryUsage=JSON.stringify(e.customMCPResults).length}getStatistics(){return{...this.statistics}}validateCacheIntegrity(e){let t=[];if(!e.customMCPResults)return{isValid:!0,issues:[]};for(let[r,n]of Object.entries(e.customMCPResults))(!n.timestamp||!n.ttl||!n.status)&&t.push(`\u7F13\u5B58\u6761\u76EE\u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: ${r}`),Number.isNaN(new Date(n.timestamp).getTime())&&t.push(`\u65E0\u6548\u7684\u65F6\u95F4\u6233\u683C\u5F0F: ${r}`),["pending","completed","failed"].includes(n.status)||t.push(`\u65E0\u6548\u7684\u72B6\u6001\u503C: ${r}, \u72B6\u6001: ${n.status}`),j(n.timestamp,n.ttl)&&t.push(`\u7F13\u5B58\u6761\u76EE\u5DF2\u8FC7\u671F: ${r}`);return{isValid:t.length===0,issues:t}}logStateTransition(e,t,r){let n={from:t,to:r,reason:this.getTransitionReason(t,r),timestamp:new Date().toISOString()};this.logger.debug(`[CacheLifecycle] \u72B6\u6001\u8F6C\u6362: ${e} ${t} -> ${r} (${n.reason})`)}getTransitionReason(e,t){return{"pending->completed":"\u4EFB\u52A1\u6267\u884C\u6210\u529F","pending->failed":"\u4EFB\u52A1\u6267\u884C\u5931\u8D25","completed->consumed":"\u7ED3\u679C\u88AB\u6D88\u8D39","failed->consumed":"\u5931\u8D25\u7ED3\u679C\u88AB\u5904\u7406","consumed->deleted":"\u7F13\u5B58\u88AB\u6E05\u7406"}[`${e}->${t}`]||"\u72B6\u6001\u66F4\u65B0"}cleanup(){this.stopAutoCleanup(),this.logger.info("[CacheLifecycle] \u6E05\u7406\u8D44\u6E90\u5B8C\u6210")}};var ee=class{static{l(this,"TaskStateManager")}logger;activeTasks;taskHistory;constructor(e){this.logger=e,this.activeTasks=new Map,this.taskHistory=[]}generateTaskId(e,t){let r=Date.now(),n=Math.random().toString(36).substring(2,11),s=`${e}_${r}_${n}`;return this.logger.debug(`[TaskState] \u751F\u6210\u4EFB\u52A1ID: ${s}`),s}validateTaskId(e){let r=/^[a-zA-Z0-9_-]+_\d+_[a-zA-Z0-9]+$/.test(e);return r||this.logger.warn(`[TaskState] \u65E0\u6548\u7684\u4EFB\u52A1ID\u683C\u5F0F: ${e}`),r}extractToolName(e){if(!this.validateTaskId(e))return null;let t=e.split("_");if(t.length<3)return null;let r=t.findIndex(s=>/^\d+$/.test(s));return r<=0?null:t.slice(0,r).join("_")}createTask(e,t,r,n="pending"){if(this.activeTasks.has(e))throw new Error(`\u4EFB\u52A1\u5DF2\u5B58\u5728: ${e}`);let s={taskId:e,toolName:t,arguments:r,status:n,startTime:new Date().toISOString()};return this.activeTasks.set(e,s),this.recordStateTransition(e,"none",n,"\u521B\u5EFA\u65B0\u4EFB\u52A1"),this.logger.info(`[TaskState] \u521B\u5EFA\u4EFB\u52A1: ${e}, \u5DE5\u5177: ${t}, \u72B6\u6001: ${n}`),s}updateTaskStatus(e,t,r,n){let s=this.activeTasks.get(e);if(!s)return this.logger.warn(`[TaskState] \u4EFB\u52A1\u4E0D\u5B58\u5728: ${e}`),!1;let i=s.status;return s.status=t,(t==="completed"||t==="failed")&&(s.endTime=new Date().toISOString()),r&&(s.result=r),n&&(s.error=n),this.recordStateTransition(e,i,t,this.getStatusChangeReason(i,t,n)),this.logger.info(`[TaskState] \u66F4\u65B0\u4EFB\u52A1\u72B6\u6001: ${e} ${i} -> ${t}`),!0}markTaskAsPending(e,t,r){let n=this.activeTasks.get(e);return n?this.updateTaskStatus(e,"pending"):n=this.createTask(e,t,r,"pending"),n}markTaskAsCompleted(e,t){return this.updateTaskStatus(e,"completed",t)}markTaskAsFailed(e,t){return this.updateTaskStatus(e,"failed",void 0,t)}markTaskAsConsumed(e){return this.updateTaskStatus(e,"consumed")}getTask(e){return this.activeTasks.get(e)||null}hasTask(e){return this.activeTasks.has(e)}getTaskStatus(e){let t=this.activeTasks.get(e);return t?t.status:null}getTasksByStatus(e){return Array.from(this.activeTasks.values()).filter(t=>t.status===e)}getTasksByTool(e){return Array.from(this.activeTasks.values()).filter(t=>t.toolName===e)}getTaskExecutionTime(e){let t=this.activeTasks.get(e);if(!t||!t.endTime)return null;let r=new Date(t.startTime).getTime();return new Date(t.endTime).getTime()-r}isTaskTimeout(e,t=8e3){let r=this.activeTasks.get(e);if(!r)return!1;let n=new Date(r.startTime).getTime();return Date.now()-n>t}getTimeoutTasks(e=8e3){let t=Date.now();return Array.from(this.activeTasks.values()).filter(r=>{let n=new Date(r.startTime).getTime();return t-n>e&&r.status==="pending"})}removeTask(e){let t=this.activeTasks.get(e);return t?(this.recordStateTransition(e,t.status,"deleted","\u4EFB\u52A1\u88AB\u79FB\u9664"),this.activeTasks.delete(e),this.logger.info(`[TaskState] \u79FB\u9664\u4EFB\u52A1: ${e}`),!0):!1}cleanupCompletedTasks(e=3e5){let t=Date.now(),r=0;for(let[n,s]of this.activeTasks.entries())if(s.status==="completed"||s.status==="failed"){let i=s.endTime?new Date(s.endTime).getTime():t;t-i>e&&(this.removeTask(n),r++)}return r>0&&this.logger.info(`[TaskState] \u6E05\u7406\u5DF2\u5B8C\u6210\u4EFB\u52A1: ${r}\u4E2A`),r}getTaskStatistics(){let e=Array.from(this.activeTasks.values()),t=e.length,r=e.filter(u=>u.status==="pending").length,n=e.filter(u=>u.status==="completed").length,s=e.filter(u=>u.status==="failed").length,i=e.filter(u=>u.status==="consumed").length,a=e.filter(u=>u.status==="completed"&&u.endTime),g=a.length>0?a.reduce((u,p)=>{let h=this.getTaskExecutionTime(p.taskId)||0;return u+h},0)/a.length:0;return{total:t,pending:r,completed:n,failed:s,consumed:i,averageExecutionTime:g}}getTaskHistory(e){return e?this.taskHistory.filter(t=>t.taskId===e):[...this.taskHistory]}recordStateTransition(e,t,r,n){let s={from:t,to:r,reason:n,timestamp:new Date().toISOString(),taskId:e};this.taskHistory.push(s),this.taskHistory.length>1e3&&(this.taskHistory=this.taskHistory.slice(-500))}getStatusChangeReason(e,t,r){if(r)return`\u6267\u884C\u5931\u8D25: ${r}`;let n={"none->pending":"\u4EFB\u52A1\u5F00\u59CB\u6267\u884C","pending->completed":"\u4EFB\u52A1\u6267\u884C\u6210\u529F","pending->failed":"\u4EFB\u52A1\u6267\u884C\u5931\u8D25","completed->consumed":"\u7ED3\u679C\u88AB\u6D88\u8D39","failed->consumed":"\u5931\u8D25\u7ED3\u679C\u88AB\u5904\u7406","consumed->deleted":"\u4EFB\u52A1\u88AB\u6E05\u7406"},s=`${e}->${t}`;return n[s]||"\u72B6\u6001\u66F4\u65B0"}validateTaskIntegrity(){let e=[];for(let[t,r]of this.activeTasks.entries())(!r.taskId||!r.toolName||!r.status||!r.startTime)&&e.push(`\u4EFB\u52A1\u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: ${t}`),Number.isNaN(new Date(r.startTime).getTime())&&e.push(`\u65E0\u6548\u7684\u5F00\u59CB\u65F6\u95F4: ${t}`),r.endTime&&Number.isNaN(new Date(r.endTime).getTime())&&e.push(`\u65E0\u6548\u7684\u7ED3\u675F\u65F6\u95F4: ${t}`),r.status==="completed"&&!r.endTime&&e.push(`\u5DF2\u5B8C\u6210\u4EFB\u52A1\u7F3A\u5C11\u7ED3\u675F\u65F6\u95F4: ${t}`),r.status==="failed"&&!r.error&&e.push(`\u5931\u8D25\u4EFB\u52A1\u7F3A\u5C11\u9519\u8BEF\u4FE1\u606F: ${t}`);return{isValid:e.length===0,issues:e}}restartStalledTasks(e=3e4){let t=this.getTimeoutTasks(e),r=0;for(let n of t){this.logger.warn(`[TaskState] \u68C0\u6D4B\u5230\u505C\u6EDE\u4EFB\u52A1: ${n.taskId}`),this.markTaskAsFailed(n.taskId,"\u4EFB\u52A1\u6267\u884C\u8D85\u65F6");let s=this.generateTaskId(n.toolName,n.arguments);this.createTask(s,n.toolName,n.arguments,"pending"),r++}return r>0&&this.logger.info(`[TaskState] \u91CD\u542F\u505C\u6EDE\u4EFB\u52A1: ${r}\u4E2A`),r}cleanup(){this.activeTasks.clear(),this.taskHistory=[],this.logger.info("[TaskState] \u6E05\u7406\u4EFB\u52A1\u72B6\u6001\u7BA1\u7406\u5668\u8D44\u6E90")}};var W=class o extends Error{static{l(this,"TimeoutError")}name="TimeoutError";constructor(e){super(e),this.name="TimeoutError",Error.captureStackTrace(this,o)}toJSON(){return{name:this.name,message:this.message,stack:this.stack}}};function Oe(o,e){return{content:[{type:"text",text:e?at(e,o):Le(o)}],isError:!1,taskId:o,status:"timeout",message:"\u5DE5\u5177\u8C03\u7528\u8D85\u65F6\uFF0C\u6B63\u5728\u540E\u53F0\u5904\u7406\u4E2D",nextAction:"\u8BF7\u7A0D\u540E\u91CD\u8BD5\u6216\u7B49\u5F85\u4EFB\u52A1\u5B8C\u6210"}}l(Oe,"createTimeoutResponse");function at(o,e){let t={coze_workflow:`\u23F1\uFE0F \u6263\u5B50\u5DE5\u4F5C\u6D41\u6267\u884C\u8D85\u65F6\uFF0C\u6B63\u5728\u540E\u53F0\u5904\u7406\u4E2D...
2
+ var We=Object.defineProperty;var l=(i,e)=>We(i,"name",{value:e,configurable:!0});import{dirname as It}from"path";import w from"process";import{fileURLToPath as kt}from"url";import{EventEmitter as He}from"events";import*as v from"fs";import*as M from"path";import z from"chalk";import A from"pino";import{z as Be}from"zod";var Ke=Be.enum(["fatal","error","warn","info","debug","trace"]);function Ve(i){let e=i.getFullYear(),t=String(i.getMonth()+1).padStart(2,"0"),r=String(i.getDate()).padStart(2,"0"),n=String(i.getHours()).padStart(2,"0"),s=String(i.getMinutes()).padStart(2,"0"),o=String(i.getSeconds()).padStart(2,"0");return`${e}-${t}-${r} ${n}:${s}:${o}`}l(Ve,"formatDateTime");var le=class{static{l(this,"Logger")}logFilePath=null;pinoInstance;isDaemonMode;logLevel;maxLogFileSize=10*1024*1024;maxLogFiles=5;constructor(e="info"){this.isDaemonMode=process.env.XIAOZHI_DAEMON==="true",this.logLevel=this.validateLogLevel(e),this.pinoInstance=this.createPinoInstance()}validateLogLevel(e){let t=e.toLowerCase(),r=Ke.safeParse(t);return r.success?r.data:"info"}createPinoInstance(){let e=[];if(!this.isDaemonMode){let t=this.createOptimizedConsoleStream();e.push({level:this.logLevel,stream:t})}return this.logFilePath&&e.push({level:this.logLevel,stream:A.destination({dest:this.logFilePath,sync:!1,append:!0,mkdir:!0})}),e.length===0&&e.push({level:this.logLevel,stream:A.destination({dest:"/dev/null"})}),A({level:this.logLevel,timestamp:A.stdTimeFunctions?.isoTime||(()=>`,"time":${Date.now()}`),formatters:{level:l((t,r)=>({level:r}),"level")},base:null,serializers:{err:A.stdSerializers?.err||(t=>t)}},A.multistream(e,{dedupe:!0}))}createOptimizedConsoleStream(){let e=new Map([[20,{name:"DEBUG",color:z.gray}],[30,{name:"INFO",color:z.blue}],[40,{name:"WARN",color:z.yellow}],[50,{name:"ERROR",color:z.red}],[60,{name:"FATAL",color:z.red}]]);return{write:l(t=>{try{let r=JSON.parse(t),n=this.formatConsoleMessageOptimized(r,e);this.safeWrite(`${n}
3
+ `)}catch{this.safeWrite(t)}},"write")}}safeWrite(e){try{process.stderr&&typeof process.stderr.write=="function"?process.stderr.write(e):console&&typeof console.error=="function"&&console.error(e.trim())}catch{}}formatConsoleMessageOptimized(e,t){let r=Ve(new Date),n=t.get(e.level)||{name:"UNKNOWN",color:l(a=>a,"color")},s=n.color(`[${n.name}]`),o=e.msg;if(e.args&&Array.isArray(e.args)){let a=e.args.map(g=>typeof g=="object"?JSON.stringify(g):String(g)).join(" ");o=`${o} ${a}`}return`[${r}] ${s} ${o}`}initLogFile(e){this.logFilePath=M.join(e,"xiaozhi.log"),this.rotateLogFileIfNeeded(),v.existsSync(this.logFilePath)||v.writeFileSync(this.logFilePath,""),this.pinoInstance=this.createPinoInstance()}enableFileLogging(e){e&&this.logFilePath&&(this.pinoInstance=this.createPinoInstance())}info(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.info(e):this.pinoInstance.info({args:t},e):this.pinoInstance.info(e,t[0]||"")}success(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.info(e):this.pinoInstance.info({args:t},e):this.pinoInstance.info(e,t[0]||"")}warn(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.warn(e):this.pinoInstance.warn({args:t},e):this.pinoInstance.warn(e,t[0]||"")}error(e,...t){if(typeof e=="string")if(t.length===0)this.pinoInstance.error(e);else{let r=t.map(n=>n instanceof Error?this.pinoInstance.level==="debug"?n.message:{message:n.message,stack:n.stack,name:n.name,cause:n.cause}:n);this.pinoInstance.error({args:r},e)}else{let r=this.enhanceErrorObject(e);this.pinoInstance.error(r,t[0]||"")}}debug(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.debug(e):this.pinoInstance.debug({args:t},e):this.pinoInstance.debug(e,t[0]||"")}log(e,...t){typeof e=="string"?t.length===0?this.pinoInstance.info(e):this.pinoInstance.info({args:t},e):this.pinoInstance.info(e,t[0]||"")}enhanceErrorObject(e){let t={...e};for(let[r,n]of Object.entries(t))n instanceof Error&&(t[r]={message:n.message,stack:n.stack,name:n.name,cause:n.cause});return t}rotateLogFileIfNeeded(){if(!(!this.logFilePath||!v.existsSync(this.logFilePath)))try{v.statSync(this.logFilePath).size>this.maxLogFileSize&&this.rotateLogFile()}catch{}}rotateLogFile(){if(this.logFilePath)try{let e=M.dirname(this.logFilePath),t=M.basename(this.logFilePath,".log");for(let n=this.maxLogFiles-1;n>=1;n--){let s=M.join(e,`${t}.${n}.log`),o=M.join(e,`${t}.${n+1}.log`);v.existsSync(s)&&(n===this.maxLogFiles-1?v.unlinkSync(s):v.renameSync(s,o))}let r=M.join(e,`${t}.1.log`);v.renameSync(this.logFilePath,r)}catch{}}cleanupOldLogs(){if(this.logFilePath)try{let e=M.dirname(this.logFilePath),t=M.basename(this.logFilePath,".log");for(let r=this.maxLogFiles+1;r<=this.maxLogFiles+10;r++){let n=M.join(e,`${t}.${r}.log`);v.existsSync(n)&&v.unlinkSync(n)}}catch{}}setLogFileOptions(e,t){this.maxLogFileSize=e,this.maxLogFiles=t}withTag(e){return this}close(){}setLevel(e){this.logLevel=this.validateLogLevel(e),this.pinoInstance=this.createPinoInstance()}getLevel(){return this.logLevel}},ce=null,Ge="info";function Je(){return ce||(ce=new le(Ge)),ce}l(Je,"getLogger");var c=Je();var K=class{static{l(this,"MCPMessageHandler")}logger;serviceManager;constructor(e){this.serviceManager=e,this.logger=c}async handleMessage(e){this.logger.debug(`\u5904\u7406 MCP \u6D88\u606F: ${e.method}`,e);try{let t=e.id===void 0;switch(e.method){case"initialize":return await this.handleInitialize(e.params,e.id);case"notifications/initialized":return await this.handleInitializedNotification(e.params);case"tools/list":return await this.handleToolsList(e.id);case"tools/call":return await this.handleToolCall(e.params,e.id);case"resources/list":return await this.handleResourcesList(e.id);case"prompts/list":return await this.handlePromptsList(e.id);case"ping":return await this.handlePing(e.id);default:if(t)return this.logger.warn(`\u6536\u5230\u672A\u77E5\u7684\u901A\u77E5\u6D88\u606F: ${e.method}`,e),null;throw new Error(`\u672A\u77E5\u7684\u65B9\u6CD5: ${e.method}`)}}catch(t){return this.logger.error(`\u5904\u7406\u6D88\u606F\u65F6\u51FA\u9519: ${e.method}`,t),e.id===void 0?null:this.createErrorResponse(t,e.id)}}async handleInitialize(e,t){this.logger.debug("\u5904\u7406 initialize \u8BF7\u6C42",e);let r=["2024-11-05","2025-06-18"],n=e.protocolVersion,s=r.includes(n)?n:"2024-11-05";return this.logger.debug(`\u534F\u8BAE\u7248\u672C\u534F\u5546: \u5BA2\u6237\u7AEF=${n}, \u670D\u52A1\u5668\u54CD\u5E94=${s}`),{jsonrpc:"2.0",result:{serverInfo:{name:"xiaozhi-mcp-server",version:"1.0.0"},capabilities:{tools:{},logging:{}},protocolVersion:s},id:t!==void 0?t:1}}async handleInitializedNotification(e){return this.logger.debug("\u6536\u5230 initialized \u901A\u77E5\uFF0C\u5BA2\u6237\u7AEF\u521D\u59CB\u5316\u5B8C\u6210",e),null}async handleToolsList(e){this.logger.debug("\u5904\u7406 tools/list \u8BF7\u6C42");try{return{jsonrpc:"2.0",result:{tools:this.serviceManager.getAllTools().map(n=>({name:n.name,description:n.description,inputSchema:n.inputSchema}))},id:e!==void 0?e:1}}catch(t){throw this.logger.error("\u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25",t),t}}async handleToolCall(e,t){try{if(!e.name)throw new Error("\u5DE5\u5177\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");let r=await this.serviceManager.callTool(e.name,e.arguments||{});return{jsonrpc:"2.0",result:{content:r.content,isError:r.isError||!1},id:t!==void 0?t:1}}catch(r){throw this.logger.error(`\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${e.name}`,r),r}}async handlePing(e){return this.logger.debug("\u5904\u7406 ping \u8BF7\u6C42"),{jsonrpc:"2.0",result:{status:"ok",timestamp:new Date().toISOString()},id:e!==void 0?e:1}}async handleResourcesList(e){this.logger.debug("\u5904\u7406 resources/list \u8BF7\u6C42");let t=[];return this.logger.debug(`\u8FD4\u56DE ${t.length} \u4E2A\u8D44\u6E90`),{jsonrpc:"2.0",result:{resources:t},id:e!==void 0?e:1}}async handlePromptsList(e){this.logger.debug("\u5904\u7406 prompts/list \u8BF7\u6C42");let t=[];return this.logger.debug(`\u8FD4\u56DE ${t.length} \u4E2A\u63D0\u793A\u6A21\u677F`),{jsonrpc:"2.0",result:{prompts:t},id:e!==void 0?e:1}}createErrorResponse(e,t){let r=-32603;return e.message.includes("\u672A\u627E\u5230\u5DE5\u5177")||e.message.includes("\u672A\u77E5\u7684\u65B9\u6CD5")?r=-32601:(e.message.includes("\u53C2\u6570")||e.message.includes("\u4E0D\u80FD\u4E3A\u7A7A"))&&(r=-32602),{jsonrpc:"2.0",error:{code:r,message:e.message,data:{stack:e.stack}},id:t!==void 0?t:1}}getServiceManager(){return this.serviceManager}};import{copyFileSync as Qe,existsSync as V,readFileSync as Xe,writeFileSync as Ze}from"fs";import{dirname as et,resolve as L}from"path";import{fileURLToPath as tt}from"url";import{EventEmitter as qe}from"events";var ue=class extends qe{static{l(this,"EventBus")}logger;eventStats=new Map;maxListeners=50;constructor(){super(),this.logger=c.withTag("EventBus"),this.setMaxListeners(this.maxListeners),this.setupErrorHandling()}setupErrorHandling(){this.on("error",e=>{this.logger.error("EventBus \u5185\u90E8\u9519\u8BEF:",e)}),this.on("newListener",e=>{let t=this.listenerCount(e);t>this.maxListeners*.8&&this.logger.warn(`\u4E8B\u4EF6 ${e} \u7684\u76D1\u542C\u5668\u6570\u91CF\u8FC7\u591A: ${t}`)})}emitEvent(e,t){try{return this.updateEventStats(e),this.logger.debug(`\u53D1\u5C04\u4E8B\u4EF6: ${e}`,t),super.emit(e,t)}catch(r){return this.logger.error(`\u53D1\u5C04\u4E8B\u4EF6\u5931\u8D25: ${e}`,r),r instanceof Error&&this.emit("error",r),!1}}onEvent(e,t){return this.logger.debug(`\u6DFB\u52A0\u4E8B\u4EF6\u76D1\u542C\u5668: ${e}`),this.on(e,t)}onceEvent(e,t){this.logger.debug(`\u6DFB\u52A0\u4E00\u6B21\u6027\u4E8B\u4EF6\u76D1\u542C\u5668: ${e}`);let r=l(n=>{try{t(n)}catch(s){throw this.emit("error",s),s}finally{this.offEvent(e,r)}},"onceListener");return this.on(e,r)}offEvent(e,t){return this.logger.debug(`\u79FB\u9664\u4E8B\u4EF6\u76D1\u542C\u5668: ${e}`),this.off(e,t)}updateEventStats(e){let t=this.eventStats.get(e)||{count:0,lastEmitted:new Date};t.count++,t.lastEmitted=new Date,this.eventStats.set(e,t)}getEventStats(){let e={};for(let[t,r]of this.eventStats)e[t]={...r};return e}getListenerStats(){let e={};for(let t of this.eventNames())e[t]=this.listenerCount(t);return e}clearEventStats(){this.eventStats.clear(),this.logger.info("\u4E8B\u4EF6\u7EDF\u8BA1\u5DF2\u6E05\u7406")}getStatus(){return{totalEvents:this.eventStats.size,totalListeners:Object.values(this.getListenerStats()).reduce((e,t)=>e+t,0),eventStats:this.getEventStats(),listenerStats:this.getListenerStats()}}destroy(){this.removeAllListeners(),this.eventStats.clear(),this.logger.info("EventBus \u5DF2\u9500\u6BC1")}},ge=null;function b(){return ge||(ge=new ue),ge}l(b,"getEventBus");function Ye(i){if(!i||typeof i!="object")throw new Error("\u670D\u52A1\u914D\u7F6E\u5FC5\u987B\u662F\u4E00\u4E2A\u6709\u6548\u7684\u5BF9\u8C61");if("command"in i&&typeof i.command=="string")return"stdio";if("type"in i&&i.type==="sse")return"sse";if("type"in i&&i.type==="streamable-http"||"url"in i&&typeof i.url=="string")return"streamable-http";throw new Error("\u65E0\u6CD5\u8BC6\u522B\u7684 MCP \u670D\u52A1\u914D\u7F6E\u7C7B\u578B\u3002\u914D\u7F6E\u5FC5\u987B\u5305\u542B command \u5B57\u6BB5\uFF08stdio\uFF09\u3001type: 'sse' \u5B57\u6BB5\uFF08sse\uFF09\u6216 url \u5B57\u6BB5\uFF08streamable-http\uFF09")}l(Ye,"getMcpServerCommunicationType");function he(i,e){if(!e||typeof e!="object")return{valid:!1,error:`\u670D\u52A1 "${i}" \u7684\u914D\u7F6E\u5FC5\u987B\u662F\u4E00\u4E2A\u5BF9\u8C61`};try{switch(Ye(e)){case"stdio":if(!e.command||typeof e.command!="string")return{valid:!1,error:`\u670D\u52A1 "${i}" \u7F3A\u5C11\u5FC5\u9700\u7684 command \u5B57\u6BB5\u6216\u5B57\u6BB5\u7C7B\u578B\u4E0D\u6B63\u786E`};if(!Array.isArray(e.args))return{valid:!1,error:`\u670D\u52A1 "${i}" \u7684 args \u5B57\u6BB5\u5FC5\u987B\u662F\u6570\u7EC4`};if(e.env&&typeof e.env!="object")return{valid:!1,error:`\u670D\u52A1 "${i}" \u7684 env \u5B57\u6BB5\u5FC5\u987B\u662F\u5BF9\u8C61`};break;case"sse":if(e.type!=="sse")return{valid:!1,error:`\u670D\u52A1 "${i}" \u7684 type \u5B57\u6BB5\u5FC5\u987B\u662F "sse"`};if(!e.url||typeof e.url!="string")return{valid:!1,error:`\u670D\u52A1 "${i}" \u7F3A\u5C11\u5FC5\u9700\u7684 url \u5B57\u6BB5\u6216\u5B57\u6BB5\u7C7B\u578B\u4E0D\u6B63\u786E`};break;case"streamable-http":if(!e.url||typeof e.url!="string")return{valid:!1,error:`\u670D\u52A1 "${i}" \u7F3A\u5C11\u5FC5\u9700\u7684 url \u5B57\u6BB5\u6216\u5B57\u6BB5\u7C7B\u578B\u4E0D\u6B63\u786E`};if(e.type&&e.type!=="streamable-http")return{valid:!1,error:`\u670D\u52A1 "${i}" \u7684 type \u5B57\u6BB5\u5982\u679C\u5B58\u5728\uFF0C\u5FC5\u987B\u662F "streamable-http"`};break;default:return{valid:!1,error:`\u670D\u52A1 "${i}" \u7684\u914D\u7F6E\u7C7B\u578B\u65E0\u6CD5\u8BC6\u522B`}}return{valid:!0}}catch(t){return{valid:!1,error:`\u670D\u52A1 "${i}" \u7684\u914D\u7F6E\u65E0\u6548: ${t instanceof Error?t.message:"\u672A\u77E5\u9519\u8BEF"}`}}}l(he,"validateMcpServerConfig");import*as G from"comment-json";import Ee from"dayjs";import pe from"json5";import*as $e from"json5-writer";var Re=et(tt(import.meta.url)),me={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},de=class i{static{l(this,"ConfigManager")}static instance;defaultConfigPath;config=null;currentConfigPath=null;json5Writer=null;eventBus=b();statsUpdateLocks=new Map;statsUpdateLockTimeouts=new Map;STATS_UPDATE_TIMEOUT=5e3;constructor(){let e=[L(Re,"templates","default","xiaozhi.config.json"),L(Re,"..","templates","default","xiaozhi.config.json"),L(process.cwd(),"templates","default","xiaozhi.config.json")];this.defaultConfigPath=e.find(t=>V(t))||e[0]}getConfigFilePath(){let e=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),t=["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"];for(let r of t){let n=L(e,r);if(V(n))return n}return L(e,"xiaozhi.config.json")}getConfigFileFormat(e){return e.endsWith(".json5")?"json5":e.endsWith(".jsonc")?"jsonc":"json"}static getInstance(){return i.instance||(i.instance=new i),i.instance}configExists(){let e=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),t=["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"];for(let r of t){let n=L(e,r);if(V(n))return!0}return!1}initConfig(e="json"){if(!V(this.defaultConfigPath))throw new Error(`\u9ED8\u8BA4\u914D\u7F6E\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728: ${this.defaultConfigPath}`);if(this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u521D\u59CB\u5316");let t=process.env.XIAOZHI_CONFIG_DIR||process.cwd(),r=`xiaozhi.config.${e}`,n=L(t,r);Qe(this.defaultConfigPath,n),this.config=null,this.json5Writer=null}loadConfig(){if(!this.configExists())throw new Error("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u8FD0\u884C xiaozhi init \u521D\u59CB\u5316\u914D\u7F6E");try{let e=this.getConfigFilePath();this.currentConfigPath=e;let t=this.getConfigFileFormat(e),n=Xe(e,"utf8").replace(/^\uFEFF/,""),s;switch(t){case"json5":s=pe.parse(n),this.json5Writer=$e.load(n);break;case"jsonc":s=G.parse(n);break;default:s=JSON.parse(n);break}return this.validateConfig(s),s}catch(e){throw e instanceof SyntaxError?new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF: ${e.message}`):e}}validateConfig(e){if(!e||typeof e!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A\u6839\u5BF9\u8C61\u65E0\u6548");let t=e;if(t.mcpEndpoint===void 0||t.mcpEndpoint===null)throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5B57\u6BB5\u65E0\u6548");if(typeof t.mcpEndpoint!="string")if(Array.isArray(t.mcpEndpoint)){for(let r of t.mcpEndpoint)if(typeof r!="string"||r.trim()==="")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u6570\u7EC4\u4E2D\u7684\u6BCF\u4E2A\u5143\u7D20\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}else throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpEndpoint \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6216\u5B57\u7B26\u4E32\u6570\u7EC4");if(!t.mcpServers||typeof t.mcpServers!="object")throw new Error("\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers \u5B57\u6BB5\u65E0\u6548");for(let[r,n]of Object.entries(t.mcpServers)){if(!n||typeof n!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${r} \u65E0\u6548`);let s=he(r,n);if(!s.valid)throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A${s.error}`)}}getConfig(){return this.config=this.loadConfig(),JSON.parse(JSON.stringify(this.config))}getMutableConfig(){return this.config||(this.config=this.loadConfig()),this.config}getMcpEndpoint(){let e=this.getConfig();return Array.isArray(e.mcpEndpoint)?e.mcpEndpoint[0]||"":e.mcpEndpoint}getMcpEndpoints(){let e=this.getConfig();return Array.isArray(e.mcpEndpoint)?[...e.mcpEndpoint]:e.mcpEndpoint?[e.mcpEndpoint]:[]}getMcpServers(){return this.getConfig().mcpServers}getMcpServerConfig(){return this.getConfig().mcpServerConfig||{}}getServerToolsConfig(e){return this.getMcpServerConfig()[e]?.tools||{}}isToolEnabled(e,t){return this.getServerToolsConfig(e)[t]?.enable!==!1}updateMcpEndpoint(e){if(Array.isArray(e)){for(let r of e)if(!r||typeof r!="string")throw new Error("MCP \u7AEF\u70B9\u6570\u7EC4\u4E2D\u7684\u6BCF\u4E2A\u5143\u7D20\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32")}let t=this.getMutableConfig();t.mcpEndpoint=e,this.saveConfig(t)}addMcpEndpoint(e){if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t=this.getMutableConfig(),r=this.getMcpEndpoints();if(r.includes(e))throw new Error(`MCP \u7AEF\u70B9 ${e} \u5DF2\u5B58\u5728`);let n=[...r,e];t.mcpEndpoint=n,this.saveConfig(t)}removeMcpEndpoint(e){if(!e||typeof e!="string")throw new Error("MCP \u7AEF\u70B9\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t=this.getMutableConfig(),r=this.getMcpEndpoints();if(r.indexOf(e)===-1)throw new Error(`MCP \u7AEF\u70B9 ${e} \u4E0D\u5B58\u5728`);let s=r.filter(o=>o!==e);t.mcpEndpoint=s,this.saveConfig(t)}updateMcpServer(e,t){if(!e||typeof e!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let r=he(e,t);if(!r.valid)throw new Error(r.error||"\u670D\u52A1\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25");let n=this.getMutableConfig();n.mcpServers[e]=t,this.saveConfig(n)}removeMcpServer(e){if(!e||typeof e!="string")throw new Error("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");let t=this.getMutableConfig();if(!t.mcpServers[e])throw new Error(`\u670D\u52A1 ${e} \u4E0D\u5B58\u5728`);if(delete t.mcpServers[e],t.mcpServerConfig?.[e]&&delete t.mcpServerConfig[e],t.customMCP?.tools){let r=t.customMCP.tools.filter(n=>n.handler?.type==="mcp"&&n.handler.config?.serviceName===e);for(let n of r){let s=t.customMCP.tools.findIndex(o=>o.name===n.name);s!==-1&&t.customMCP.tools.splice(s,1)}t.customMCP.tools.length===0&&(t.customMCP=void 0)}this.saveConfig(t),this.eventBus.emitEvent("config:updated",{type:"customMCP",timestamp:new Date}),c.info(`\u6210\u529F\u79FB\u9664 MCP \u670D\u52A1 ${e} \u53CA\u5176\u76F8\u5173\u914D\u7F6E`)}updateServerToolsConfig(e,t){let r=this.getMutableConfig();r.mcpServerConfig||(r.mcpServerConfig={}),Object.keys(t).length===0?delete r.mcpServerConfig[e]:r.mcpServerConfig[e]={tools:t},this.saveConfig(r),this.eventBus.emitEvent("config:updated",{type:"serverTools",serviceName:e,timestamp:new Date})}removeServerToolsConfig(e){let r={...this.getConfig()};r.mcpServerConfig&&(delete r.mcpServerConfig[e],this.saveConfig(r))}cleanupInvalidServerToolsConfig(){let e=this.getMutableConfig();if(!e.mcpServerConfig)return;let t=Object.keys(e.mcpServers),n=Object.keys(e.mcpServerConfig).filter(s=>!t.includes(s));if(n.length>0){for(let s of n)delete e.mcpServerConfig[s];this.saveConfig(e),c.info(`\u5DF2\u6E05\u7406 ${n.length} \u4E2A\u65E0\u6548\u7684\u670D\u52A1\u5DE5\u5177\u914D\u7F6E: ${n.join(", ")}`)}}setToolEnabled(e,t,r,n){let s=this.getMutableConfig();s.mcpServerConfig||(s.mcpServerConfig={}),s.mcpServerConfig[e]||(s.mcpServerConfig[e]={tools:{}}),s.mcpServerConfig[e].tools[t]={...s.mcpServerConfig[e].tools[t],enable:r,...n&&{description:n}},this.saveConfig(s)}saveConfig(e){try{this.validateConfig(e);let t;this.currentConfigPath?t=this.currentConfigPath:(t=this.getConfigFilePath(),this.currentConfigPath=t);let r=this.getConfigFileFormat(t),n;switch(r){case"json5":try{this.json5Writer?(this.json5Writer.write(e),n=this.json5Writer.toSource()):(console.warn("\u6CA1\u6709 json5Writer \u5B9E\u4F8B\uFF0C\u56DE\u9000\u5230\u6807\u51C6 JSON5 \u683C\u5F0F"),n=pe.stringify(e,null,2))}catch(s){console.warn("\u4F7F\u7528 json5-writer \u4FDD\u5B58\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u6807\u51C6 JSON5 \u683C\u5F0F:",s),n=pe.stringify(e,null,2)}break;case"jsonc":try{n=G.stringify(e,null,2)}catch(s){console.warn("\u4F7F\u7528 comment-json \u4FDD\u5B58\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u6807\u51C6 JSON \u683C\u5F0F:",s),n=JSON.stringify(e,null,2)}break;default:n=JSON.stringify(e,null,2);break}Ze(t,n,"utf8"),this.config=e,this.notifyConfigUpdate(e)}catch(t){throw new Error(`\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`)}}reloadConfig(){this.config=null,this.currentConfigPath=null,this.json5Writer=null}getConfigPath(){return this.getConfigFilePath()}getDefaultConfigPath(){return this.defaultConfigPath}getConnectionConfig(){let t=this.getConfig().connection||{};return{heartbeatInterval:t.heartbeatInterval??me.heartbeatInterval,heartbeatTimeout:t.heartbeatTimeout??me.heartbeatTimeout,reconnectInterval:t.reconnectInterval??me.reconnectInterval}}getHeartbeatInterval(){return this.getConnectionConfig().heartbeatInterval}getHeartbeatTimeout(){return this.getConnectionConfig().heartbeatTimeout}getReconnectInterval(){return this.getConnectionConfig().reconnectInterval}updateConnectionConfig(e){let t=this.getMutableConfig();t.connection||(t.connection={}),Object.assign(t.connection,e),this.saveConfig(t)}async updateToolUsageStats(e,t,r){try{if(typeof t=="string"&&r){let n=e,s=t,o=r;await Promise.all([this._updateMCPServerToolStats(n,s,o),this.updateCustomMCPToolStats(n,s,o)]),c.debug(`\u5DE5\u5177\u4F7F\u7528\u7EDF\u8BA1\u5DF2\u66F4\u65B0: ${n}/${s}`)}else{let n=e,s=t,o=new Date().toISOString();await this.updateCustomMCPToolStats(n,o,s),c.debug(`CustomMCP \u5DE5\u5177\u4F7F\u7528\u7EDF\u8BA1\u5DF2\u66F4\u65B0: ${n}`)}}catch(n){if(typeof t=="string"&&r){let s=e,o=t;c.error(`\u66F4\u65B0\u5DE5\u5177\u4F7F\u7528\u7EDF\u8BA1\u5931\u8D25 (${s}/${o}): ${n instanceof Error?n.message:String(n)}`)}else{let s=e;c.error(`\u66F4\u65B0 CustomMCP \u5DE5\u5177\u4F7F\u7528\u7EDF\u8BA1\u5931\u8D25 (${s}): ${n instanceof Error?n.message:String(n)}`)}}}async updateMCPServerToolStats(e,t,r,n=!0){await this._updateMCPServerToolStats(e,t,r,n)}setHeartbeatInterval(e){if(e<=0)throw new Error("\u5FC3\u8DF3\u68C0\u6D4B\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatInterval:e})}setHeartbeatTimeout(e){if(e<=0)throw new Error("\u5FC3\u8DF3\u8D85\u65F6\u65F6\u95F4\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({heartbeatTimeout:e})}setReconnectInterval(e){if(e<=0)throw new Error("\u91CD\u8FDE\u95F4\u9694\u5FC5\u987B\u5927\u4E8E0");this.updateConnectionConfig({reconnectInterval:e})}getModelScopeConfig(){return this.getConfig().modelscope||{}}getModelScopeApiKey(){return this.getModelScopeConfig().apiKey||process.env.MODELSCOPE_API_TOKEN}updateModelScopeConfig(e){let t=this.getMutableConfig();t.modelscope||(t.modelscope={}),Object.assign(t.modelscope,e),this.saveConfig(t)}setModelScopeApiKey(e){if(!e||typeof e!="string")throw new Error("API Key \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");this.updateModelScopeConfig({apiKey:e})}getCustomMCPConfig(){return this.getConfig().customMCP||null}getCustomMCPTools(){let e=this.getCustomMCPConfig();return!e||!e.tools?[]:e.tools}validateCustomMCPTools(e){if(!Array.isArray(e))return!1;for(let t of e){if(!t.name||typeof t.name!="string")return c.warn(`CustomMCP \u5DE5\u5177\u7F3A\u5C11\u6709\u6548\u7684 name \u5B57\u6BB5: ${JSON.stringify(t)}`),!1;if(!t.description||typeof t.description!="string")return c.warn(`CustomMCP \u5DE5\u5177 ${t.name} \u7F3A\u5C11\u6709\u6548\u7684 description \u5B57\u6BB5`),!1;if(!t.inputSchema||typeof t.inputSchema!="object")return c.warn(`CustomMCP \u5DE5\u5177 ${t.name} \u7F3A\u5C11\u6709\u6548\u7684 inputSchema \u5B57\u6BB5`),!1;if(!t.handler||typeof t.handler!="object")return c.warn(`CustomMCP \u5DE5\u5177 ${t.name} \u7F3A\u5C11\u6709\u6548\u7684 handler \u5B57\u6BB5`),!1;if(!["proxy","function","http","script","chain","mcp"].includes(t.handler.type))return c.warn(`CustomMCP \u5DE5\u5177 ${t.name} \u7684 handler.type \u5FC5\u987B\u662F 'proxy', 'function', 'http', 'script', 'chain' \u6216 'mcp'`),!1;if(!this.validateHandlerConfig(t.name,t.handler))return!1}return!0}validateHandlerConfig(e,t){switch(t.type){case"proxy":return this.validateProxyHandler(e,t);case"http":return this.validateHttpHandler(e,t);case"function":return this.validateFunctionHandler(e,t);case"script":return this.validateScriptHandler(e,t);case"chain":return this.validateChainHandler(e,t);case"mcp":return this.validateMCPHandler(e,t);default:return c.warn(`CustomMCP \u5DE5\u5177 ${e} \u4F7F\u7528\u4E86\u672A\u77E5\u7684\u5904\u7406\u5668\u7C7B\u578B`),!1}}validateProxyHandler(e,t){return t.platform?["coze","openai","anthropic","custom"].includes(t.platform)?!t.config||typeof t.config!="object"?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 proxy \u5904\u7406\u5668\u7F3A\u5C11 config \u5B57\u6BB5`),!1):t.platform==="coze"&&!t.config.workflow_id&&!t.config.bot_id?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 Coze \u5904\u7406\u5668\u5FC5\u987B\u63D0\u4F9B workflow_id \u6216 bot_id`),!1):!0:(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 proxy \u5904\u7406\u5668\u4F7F\u7528\u4E86\u4E0D\u652F\u6301\u7684\u5E73\u53F0: ${t.platform}`),!1):(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 proxy \u5904\u7406\u5668\u7F3A\u5C11 platform \u5B57\u6BB5`),!1)}validateHttpHandler(e,t){if(!t.url||typeof t.url!="string")return c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 http \u5904\u7406\u5668\u7F3A\u5C11\u6709\u6548\u7684 url \u5B57\u6BB5`),!1;try{new URL(t.url)}catch{return c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 http \u5904\u7406\u5668 url \u683C\u5F0F\u65E0\u6548: ${t.url}`),!1}return t.method&&!["GET","POST","PUT","DELETE","PATCH"].includes(t.method)?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 http \u5904\u7406\u5668\u4F7F\u7528\u4E86\u4E0D\u652F\u6301\u7684 HTTP \u65B9\u6CD5: ${t.method}`),!1):!0}validateFunctionHandler(e,t){return!t.module||typeof t.module!="string"?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 function \u5904\u7406\u5668\u7F3A\u5C11\u6709\u6548\u7684 module \u5B57\u6BB5`),!1):!t.function||typeof t.function!="string"?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 function \u5904\u7406\u5668\u7F3A\u5C11\u6709\u6548\u7684 function \u5B57\u6BB5`),!1):!0}validateScriptHandler(e,t){return!t.script||typeof t.script!="string"?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 script \u5904\u7406\u5668\u7F3A\u5C11\u6709\u6548\u7684 script \u5B57\u6BB5`),!1):t.interpreter&&!["node","python","bash"].includes(t.interpreter)?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 script \u5904\u7406\u5668\u4F7F\u7528\u4E86\u4E0D\u652F\u6301\u7684\u89E3\u91CA\u5668: ${t.interpreter}`),!1):!0}validateChainHandler(e,t){return!t.tools||!Array.isArray(t.tools)||t.tools.length===0?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 chain \u5904\u7406\u5668\u7F3A\u5C11\u6709\u6548\u7684 tools \u6570\u7EC4`),!1):["sequential","parallel"].includes(t.mode)?["stop","continue","retry"].includes(t.error_handling)?!0:(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 chain \u5904\u7406\u5668\u4F7F\u7528\u4E86\u4E0D\u652F\u6301\u7684\u9519\u8BEF\u5904\u7406\u7B56\u7565: ${t.error_handling}`),!1):(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 chain \u5904\u7406\u5668\u4F7F\u7528\u4E86\u4E0D\u652F\u6301\u7684\u6267\u884C\u6A21\u5F0F: ${t.mode}`),!1)}validateMCPHandler(e,t){return!t.config||typeof t.config!="object"?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 mcp \u5904\u7406\u5668\u7F3A\u5C11 config \u5B57\u6BB5`),!1):!t.config.serviceName||typeof t.config.serviceName!="string"?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 mcp \u5904\u7406\u5668\u7F3A\u5C11\u6709\u6548\u7684 serviceName`),!1):!t.config.toolName||typeof t.config.toolName!="string"?(c.warn(`CustomMCP \u5DE5\u5177 ${e} \u7684 mcp \u5904\u7406\u5668\u7F3A\u5C11\u6709\u6548\u7684 toolName`),!1):!0}hasValidCustomMCPTools(){try{let e=this.getCustomMCPTools();return e.length===0?!1:this.validateCustomMCPTools(e)}catch(e){return c.error("\u68C0\u67E5 customMCP \u5DE5\u5177\u914D\u7F6E\u65F6\u51FA\u9519:",e),!1}}addCustomMCPTool(e){if(!e||typeof e!="object")throw new Error("\u5DE5\u5177\u914D\u7F6E\u4E0D\u80FD\u4E3A\u7A7A");let t=this.getMutableConfig();if(t.customMCP||(t.customMCP={tools:[]}),t.customMCP.tools.find(n=>n.name===e.name))throw new Error(`\u5DE5\u5177 "${e.name}" \u5DF2\u5B58\u5728`);if(!this.validateCustomMCPTools([e]))throw new Error("\u5DE5\u5177\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25");t.customMCP.tools.unshift(e),this.saveConfig(t),c.info(`\u6210\u529F\u6DFB\u52A0\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177: ${e.name}`)}async addCustomMCPTools(e){if(!Array.isArray(e))throw new Error("\u5DE5\u5177\u914D\u7F6E\u5FC5\u987B\u662F\u6570\u7EC4");if(e.length===0)return;let t=this.getMutableConfig();t.customMCP||(t.customMCP={tools:[]});let r=new Set(t.customMCP.tools.map(s=>s.name)),n=e.filter(s=>!r.has(s.name));if(n.length>0){if(!this.validateCustomMCPTools(n))throw new Error("\u5DE5\u5177\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25");t.customMCP.tools.push(...n),this.saveConfig(t),this.eventBus.emitEvent("config:updated",{type:"customMCP",timestamp:new Date}),c.debug(`\u6210\u529F\u6279\u91CF\u6DFB\u52A0 ${n.length} \u4E2A\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177: ${n.map(s=>s.name).join(", ")}`)}}removeCustomMCPTool(e){if(!e||typeof e!="string")throw new Error("\u5DE5\u5177\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");let t=this.getMutableConfig();if(!t.customMCP||!t.customMCP.tools)throw new Error("\u672A\u914D\u7F6E\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177");let r=t.customMCP.tools.findIndex(n=>n.name===e);if(r===-1)throw new Error(`\u5DE5\u5177 "${e}" \u4E0D\u5B58\u5728`);t.customMCP.tools.splice(r,1),this.saveConfig(t),c.info(`\u6210\u529F\u5220\u9664\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177: ${e}`)}updateCustomMCPTool(e,t){if(!e||typeof e!="string")throw new Error("\u5DE5\u5177\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");if(!t||typeof t!="object")throw new Error("\u66F4\u65B0\u540E\u7684\u5DE5\u5177\u914D\u7F6E\u4E0D\u80FD\u4E3A\u7A7A");let r=this.getMutableConfig();if(!r.customMCP||!r.customMCP.tools)throw new Error("\u672A\u914D\u7F6E\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177");let n=r.customMCP.tools.findIndex(s=>s.name===e);if(n===-1)throw new Error(`\u5DE5\u5177 "${e}" \u4E0D\u5B58\u5728`);if(!this.validateCustomMCPTools([t]))throw new Error("\u66F4\u65B0\u540E\u7684\u5DE5\u5177\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25");r.customMCP.tools[n]=t,this.saveConfig(r),c.debug(`\u6210\u529F\u66F4\u65B0\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177: ${e}`)}updateCustomMCPTools(e){if(!Array.isArray(e))throw new Error("\u5DE5\u5177\u914D\u7F6E\u5FC5\u987B\u662F\u6570\u7EC4");if(!this.validateCustomMCPTools(e))throw new Error("\u5DE5\u5177\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25");let t=this.getMutableConfig();t.customMCP||(t.customMCP={tools:[]}),t.customMCP.tools=e,this.saveConfig(t),this.eventBus.emitEvent("config:updated",{type:"customMCP",timestamp:new Date}),c.debug(`\u6210\u529F\u66F4\u65B0\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177\u914D\u7F6E\uFF0C\u5171 ${e.length} \u4E2A\u5DE5\u5177`)}getWebUIConfig(){return this.getConfig().webUI||{}}getWebUIPort(){return this.getWebUIConfig().port??9999}notifyConfigUpdate(e){try{let t=global.__webServer;t&&typeof t.broadcastConfigUpdate=="function"&&(t.broadcastConfigUpdate(e),console.log("\u5DF2\u901A\u8FC7 WebSocket \u5E7F\u64AD\u914D\u7F6E\u66F4\u65B0"))}catch(t){console.warn("\u901A\u77E5 Web \u754C\u9762\u914D\u7F6E\u66F4\u65B0\u5931\u8D25:",t instanceof Error?t.message:String(t))}}updateWebUIConfig(e){let t=this.getMutableConfig();t.webUI||(t.webUI={}),Object.assign(t.webUI,e),this.saveConfig(t)}setWebUIPort(e){if(!Number.isInteger(e)||e<=0||e>65535)throw new Error("\u7AEF\u53E3\u53F7\u5FC5\u987B\u662F 1-65535 \u4E4B\u95F4\u7684\u6574\u6570");this.updateWebUIConfig({port:e})}updatePlatformConfig(e,t){let r=this.getMutableConfig();r.platforms||(r.platforms={}),r.platforms[e]=t,this.saveConfig(r)}getCozePlatformConfig(){let t=this.getConfig().platforms?.coze;return!t||!t.token?null:{token:t.token}}getCozeToken(){return this.getCozePlatformConfig()?.token||null}setCozePlatformConfig(e){if(!e.token||typeof e.token!="string"||e.token.trim()==="")throw new Error("\u6263\u5B50 API Token \u4E0D\u80FD\u4E3A\u7A7A");this.updatePlatformConfig("coze",{token:e.token.trim()})}isCozeConfigValid(){let e=this.getCozePlatformConfig();return e!==null&&typeof e.token=="string"&&e.token.trim()!==""}async _updateMCPServerToolStats(e,t,r,n=!0){let s=this.getMutableConfig();s.mcpServerConfig||(s.mcpServerConfig={}),s.mcpServerConfig[e]||(s.mcpServerConfig[e]={tools:{}}),s.mcpServerConfig[e].tools[t]||(s.mcpServerConfig[e].tools[t]={enable:!0});let o=s.mcpServerConfig[e].tools[t],a=o.usageCount||0,g=o.lastUsedTime;n&&(o.usageCount=a+1),(!g||new Date(r)>new Date(g))&&(o.lastUsedTime=Ee(r).format("YYYY-MM-DD HH:mm:ss")),this.saveConfig(s)}async updateCustomMCPToolStats(e,t,r){try{let n,s,o=!0,a;if(typeof r=="string"){let y=e;n=`${y}__${t}`,s=r,a=`${y}/${t}`}else n=e,s=t,o=r||!0,a=n;let g=this.getCustomMCPTools(),u=g.findIndex(y=>y.name===n);if(u===-1)return;let p=[...g],h=p[u];h.stats||(h.stats={});let S=h.stats.usageCount||0,T=h.stats.lastUsedTime;o&&(h.stats.usageCount=S+1),(!T||new Date(s)>new Date(T))&&(h.stats.lastUsedTime=Ee(s).format("YYYY-MM-DD HH:mm:ss")),await this.updateCustomMCPTools(p)}catch(n){if(typeof r=="string"){let s=e,o=t;c.error(`\u66F4\u65B0 customMCP \u5DE5\u5177\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25 (${s}/${o}): ${n instanceof Error?n.message:String(n)}`)}else{let s=e;c.error(`\u66F4\u65B0 customMCP \u5DE5\u5177\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25 (${s}): ${n instanceof Error?n.message:String(n)}`)}}}async acquireStatsUpdateLock(e){if(this.statsUpdateLocks.has(e))return c.debug(`\u5DE5\u5177 ${e} \u7684\u7EDF\u8BA1\u66F4\u65B0\u6B63\u5728\u8FDB\u884C\u4E2D\uFF0C\u8DF3\u8FC7\u672C\u6B21\u66F4\u65B0`),!1;let t=new Promise(n=>{});this.statsUpdateLocks.set(e,t);let r=setTimeout(()=>{this.releaseStatsUpdateLock(e)},this.STATS_UPDATE_TIMEOUT);return this.statsUpdateLockTimeouts.set(e,r),!0}releaseStatsUpdateLock(e){this.statsUpdateLocks.delete(e);let t=this.statsUpdateLockTimeouts.get(e);t&&(clearTimeout(t),this.statsUpdateLockTimeouts.delete(e)),c.debug(`\u5DF2\u91CA\u653E\u5DE5\u5177 ${e} \u7684\u7EDF\u8BA1\u66F4\u65B0\u9501`)}async updateToolUsageStatsWithLock(e,t=!0){let r=`custommcp_${e}`;if(await this.acquireStatsUpdateLock(r))try{await this.updateToolUsageStats(e,t),c.debug(`\u5DE5\u5177 ${e} \u7EDF\u8BA1\u66F4\u65B0\u5B8C\u6210`)}catch(n){throw c.error(`\u5DE5\u5177 ${e} \u7EDF\u8BA1\u66F4\u65B0\u5931\u8D25:`,n),n}finally{this.releaseStatsUpdateLock(r)}}async updateMCPServerToolStatsWithLock(e,t,r,n=!0){let s=`mcpserver_${e}_${t}`;if(await this.acquireStatsUpdateLock(s))try{await this.updateMCPServerToolStats(e,t,r,n),c.debug(`MCP \u670D\u52A1\u5DE5\u5177 ${e}/${t} \u7EDF\u8BA1\u66F4\u65B0\u5B8C\u6210`)}catch(o){throw c.error(`MCP \u670D\u52A1\u5DE5\u5177 ${e}/${t} \u7EDF\u8BA1\u66F4\u65B0\u5931\u8D25:`,o),o}finally{this.releaseStatsUpdateLock(s)}}clearAllStatsUpdateLocks(){let e=this.statsUpdateLocks.size;this.statsUpdateLocks.clear();for(let t of this.statsUpdateLockTimeouts.values())clearTimeout(t);this.statsUpdateLockTimeouts.clear(),e>0&&c.info(`\u5DF2\u6E05\u7406 ${e} \u4E2A\u7EDF\u8BA1\u66F4\u65B0\u9501`)}getStatsUpdateLocks(){return Array.from(this.statsUpdateLocks.keys())}getToolCallLogConfig(){return this.getConfig().toolCallLog||{}}updateToolCallLogConfig(e){let t=this.getMutableConfig();t.toolCallLog||(t.toolCallLog={}),Object.assign(t.toolCallLog,e),this.saveConfig(t)}getConfigDir(){return process.env.XIAOZHI_CONFIG_DIR||process.cwd()}},f=de.getInstance();import{createHash as rt}from"crypto";function R(i,e){let t=rt("md5").update(JSON.stringify(e||{})).digest("hex");return`${i}_${t}`}l(R,"generateCacheKey");function H(i,e){let t=new Date(i).getTime();return Date.now()-t>e}l(H,"isCacheExpired");function O(i){let e=Date.now(),t=new Date(i.timestamp).getTime();return!!(i.consumed&&e-t>6e4||e-t>i.ttl||i.status==="failed")}l(O,"shouldCleanupCache");var $={TIMEOUT:8e3,CACHE_TTL:3e5,CLEANUP_INTERVAL:6e4,MAX_CACHE_SIZE:1e3,ENABLE_ONE_TIME_CACHE:!0};var J=class{static{l(this,"CacheLifecycleManager")}logger;cleanupInterval;statistics;lastCleanupTime;constructor(e){this.logger=e,this.statistics=this.initializeStatistics(),this.lastCleanupTime=new Date().toISOString()}initializeStatistics(){return{totalEntries:0,pendingTasks:0,completedTasks:0,failedTasks:0,consumedEntries:0,cacheHitRate:0,lastCleanupTime:new Date().toISOString(),memoryUsage:0}}startAutoCleanup(){if(this.cleanupInterval){this.logger.warn("[CacheLifecycle] \u81EA\u52A8\u6E05\u7406\u5B9A\u65F6\u5668\u5DF2\u7ECF\u5728\u8FD0\u884C");return}this.cleanupInterval=setInterval(()=>{this.performCleanup().catch(e=>{this.logger.error(`[CacheLifecycle] \u81EA\u52A8\u6E05\u7406\u5931\u8D25: ${e}`)})},$.CLEANUP_INTERVAL),this.logger.debug(`[CacheLifecycle] \u542F\u52A8\u81EA\u52A8\u6E05\u7406\u5B9A\u65F6\u5668\uFF0C\u95F4\u9694: ${$.CLEANUP_INTERVAL}ms`)}stopAutoCleanup(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=void 0,this.logger.info("[CacheLifecycle] \u505C\u6B62\u81EA\u52A8\u6E05\u7406\u5B9A\u65F6\u5668"))}createCacheEntry(e,t,r,n="pending",s){let o={result:r,timestamp:new Date().toISOString(),ttl:$.CACHE_TTL,status:n,consumed:!1,taskId:s,retryCount:0};return this.logger.debug(`[CacheLifecycle] \u521B\u5EFA\u7F13\u5B58\u6761\u76EE: ${e}, \u72B6\u6001: ${n}`),o}updateCacheStatus(e,t,r,n,s){if(!e.customMCPResults||!e.customMCPResults[t])return this.logger.warn(`[CacheLifecycle] \u7F13\u5B58\u6761\u76EE\u4E0D\u5B58\u5728: ${t}`),!1;let o=e.customMCPResults[t],a=o.status;return this.logStateTransition(t,a,r),o.status=r,o.timestamp=new Date().toISOString(),n&&(o.result=n),s&&r==="failed"&&(o.result={content:[{type:"text",text:`\u4EFB\u52A1\u5931\u8D25: ${s}`}]},o.consumed=!0),r==="completed"&&(o.consumed=!1),this.logger.debug(`[CacheLifecycle] \u66F4\u65B0\u7F13\u5B58\u72B6\u6001: ${t} ${a} -> ${r}`),!0}markAsConsumed(e,t){if(!e.customMCPResults||!e.customMCPResults[t])return!1;let r=e.customMCPResults[t];return r.consumed?(this.logger.debug(`[CacheLifecycle] \u7F13\u5B58\u5DF2\u6807\u8BB0\u4E3A\u6D88\u8D39: ${t}`),!0):(r.consumed=!0,r.timestamp=new Date().toISOString(),this.logStateTransition(t,r.status,"consumed"),this.logger.debug(`[CacheLifecycle] \u6807\u8BB0\u7F13\u5B58\u4E3A\u5DF2\u6D88\u8D39: ${t}`),!0)}isCacheAvailable(e,t){if(!e.customMCPResults||!e.customMCPResults[t])return!1;let r=e.customMCPResults[t];return H(r.timestamp,r.ttl)?(this.logger.debug(`[CacheLifecycle] \u7F13\u5B58\u5DF2\u8FC7\u671F: ${t}`),!1):r.consumed?(this.logger.debug(`[CacheLifecycle] \u7F13\u5B58\u5DF2\u6D88\u8D39: ${t}`),!1):r.status!=="completed"?(this.logger.debug(`[CacheLifecycle] \u7F13\u5B58\u72B6\u6001\u672A\u5B8C\u6210: ${t}, \u72B6\u6001: ${r.status}`),!1):!0}async performCleanup(){try{this.logger.debug("[CacheLifecycle] \u6267\u884C\u7F13\u5B58\u6E05\u7406"),this.lastCleanupTime=new Date().toISOString()}catch(e){throw this.logger.error(`[CacheLifecycle] \u6E05\u7406\u5931\u8D25: ${e}`),e}}cleanupCacheEntries(e,t){if(!e.customMCPResults)return{cleaned:0,total:0};let r=Object.entries(e.customMCPResults),n=0,s=t||r.map(([o])=>o);for(let o of s){let a=e.customMCPResults[o];a&&O(a)&&(delete e.customMCPResults[o],n++,this.logger.debug(`[CacheLifecycle] \u6E05\u7406\u7F13\u5B58\u6761\u76EE: ${o}`))}return this.logger.info(`[CacheLifecycle] \u6E05\u7406\u5B8C\u6210: ${n}/${s.length}`),{cleaned:n,total:s.length}}cleanupExpiredCache(e){if(!e.customMCPResults)return{cleaned:0,total:0};let t=Object.entries(e.customMCPResults),r=0;for(let[n,s]of t)H(s.timestamp,s.ttl)&&(delete e.customMCPResults[n],r++,this.logger.debug(`[CacheLifecycle] \u6E05\u7406\u8FC7\u671F\u7F13\u5B58: ${n}`));return r>0&&this.logger.info(`[CacheLifecycle] \u6E05\u7406\u8FC7\u671F\u7F13\u5B58: ${r}/${t.length}`),{cleaned:r,total:t.length}}cleanupConsumedCache(e){if(!e.customMCPResults)return{cleaned:0,total:0};let t=Object.entries(e.customMCPResults),r=0,n=Date.now();for(let[s,o]of t)if(o.consumed){let a=new Date(o.timestamp).getTime();n-a>6e4&&(delete e.customMCPResults[s],r++,this.logger.debug(`[CacheLifecycle] \u6E05\u7406\u5DF2\u6D88\u8D39\u7F13\u5B58: ${s}`))}return r>0&&this.logger.info(`[CacheLifecycle] \u6E05\u7406\u5DF2\u6D88\u8D39\u7F13\u5B58: ${r}/${t.length}`),{cleaned:r,total:t.length}}updateStatistics(e){if(!e.customMCPResults){this.statistics=this.initializeStatistics();return}let t=Object.values(e.customMCPResults);this.statistics.totalEntries=t.length,this.statistics.pendingTasks=t.filter(s=>s.status==="pending").length,this.statistics.completedTasks=t.filter(s=>s.status==="completed").length,this.statistics.failedTasks=t.filter(s=>s.status==="failed").length,this.statistics.consumedEntries=t.filter(s=>s.consumed).length;let r=this.statistics.completedTasks,n=this.statistics.consumedEntries;this.statistics.cacheHitRate=r>0?n/r*100:0,this.statistics.lastCleanupTime=this.lastCleanupTime,this.statistics.memoryUsage=JSON.stringify(e.customMCPResults).length}getStatistics(){return{...this.statistics}}validateCacheIntegrity(e){let t=[];if(!e.customMCPResults)return{isValid:!0,issues:[]};for(let[r,n]of Object.entries(e.customMCPResults))(!n.timestamp||!n.ttl||!n.status)&&t.push(`\u7F13\u5B58\u6761\u76EE\u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: ${r}`),Number.isNaN(new Date(n.timestamp).getTime())&&t.push(`\u65E0\u6548\u7684\u65F6\u95F4\u6233\u683C\u5F0F: ${r}`),["pending","completed","failed"].includes(n.status)||t.push(`\u65E0\u6548\u7684\u72B6\u6001\u503C: ${r}, \u72B6\u6001: ${n.status}`),H(n.timestamp,n.ttl)&&t.push(`\u7F13\u5B58\u6761\u76EE\u5DF2\u8FC7\u671F: ${r}`);return{isValid:t.length===0,issues:t}}logStateTransition(e,t,r){let n={from:t,to:r,reason:this.getTransitionReason(t,r),timestamp:new Date().toISOString()};this.logger.debug(`[CacheLifecycle] \u72B6\u6001\u8F6C\u6362: ${e} ${t} -> ${r} (${n.reason})`)}getTransitionReason(e,t){return{"pending->completed":"\u4EFB\u52A1\u6267\u884C\u6210\u529F","pending->failed":"\u4EFB\u52A1\u6267\u884C\u5931\u8D25","completed->consumed":"\u7ED3\u679C\u88AB\u6D88\u8D39","failed->consumed":"\u5931\u8D25\u7ED3\u679C\u88AB\u5904\u7406","consumed->deleted":"\u7F13\u5B58\u88AB\u6E05\u7406"}[`${e}->${t}`]||"\u72B6\u6001\u66F4\u65B0"}cleanup(){this.stopAutoCleanup(),this.logger.info("[CacheLifecycle] \u6E05\u7406\u8D44\u6E90\u5B8C\u6210")}};var q=class{static{l(this,"TaskStateManager")}logger;activeTasks;taskHistory;constructor(e){this.logger=e,this.activeTasks=new Map,this.taskHistory=[]}generateTaskId(e,t){let r=Date.now(),n=Math.random().toString(36).substring(2,11),s=`${e}_${r}_${n}`;return this.logger.debug(`[TaskState] \u751F\u6210\u4EFB\u52A1ID: ${s}`),s}validateTaskId(e){let r=/^[a-zA-Z0-9_-]+_\d+_[a-zA-Z0-9]+$/.test(e);return r||this.logger.warn(`[TaskState] \u65E0\u6548\u7684\u4EFB\u52A1ID\u683C\u5F0F: ${e}`),r}extractToolName(e){if(!this.validateTaskId(e))return null;let t=e.split("_");if(t.length<3)return null;let r=t.findIndex(s=>/^\d+$/.test(s));return r<=0?null:t.slice(0,r).join("_")}createTask(e,t,r,n="pending"){if(this.activeTasks.has(e))throw new Error(`\u4EFB\u52A1\u5DF2\u5B58\u5728: ${e}`);let s={taskId:e,toolName:t,arguments:r,status:n,startTime:new Date().toISOString()};return this.activeTasks.set(e,s),this.recordStateTransition(e,"none",n,"\u521B\u5EFA\u65B0\u4EFB\u52A1"),this.logger.info(`[TaskState] \u521B\u5EFA\u4EFB\u52A1: ${e}, \u5DE5\u5177: ${t}, \u72B6\u6001: ${n}`),s}updateTaskStatus(e,t,r,n){let s=this.activeTasks.get(e);if(!s)return this.logger.warn(`[TaskState] \u4EFB\u52A1\u4E0D\u5B58\u5728: ${e}`),!1;let o=s.status;return s.status=t,(t==="completed"||t==="failed")&&(s.endTime=new Date().toISOString()),r&&(s.result=r),n&&(s.error=n),this.recordStateTransition(e,o,t,this.getStatusChangeReason(o,t,n)),this.logger.info(`[TaskState] \u66F4\u65B0\u4EFB\u52A1\u72B6\u6001: ${e} ${o} -> ${t}`),!0}markTaskAsPending(e,t,r){let n=this.activeTasks.get(e);return n?this.updateTaskStatus(e,"pending"):n=this.createTask(e,t,r,"pending"),n}markTaskAsCompleted(e,t){return this.updateTaskStatus(e,"completed",t)}markTaskAsFailed(e,t){return this.updateTaskStatus(e,"failed",void 0,t)}markTaskAsConsumed(e){return this.updateTaskStatus(e,"consumed")}getTask(e){return this.activeTasks.get(e)||null}hasTask(e){return this.activeTasks.has(e)}getTaskStatus(e){let t=this.activeTasks.get(e);return t?t.status:null}getTasksByStatus(e){return Array.from(this.activeTasks.values()).filter(t=>t.status===e)}getTasksByTool(e){return Array.from(this.activeTasks.values()).filter(t=>t.toolName===e)}getTaskExecutionTime(e){let t=this.activeTasks.get(e);if(!t||!t.endTime)return null;let r=new Date(t.startTime).getTime();return new Date(t.endTime).getTime()-r}isTaskTimeout(e,t=8e3){let r=this.activeTasks.get(e);if(!r)return!1;let n=new Date(r.startTime).getTime();return Date.now()-n>t}getTimeoutTasks(e=8e3){let t=Date.now();return Array.from(this.activeTasks.values()).filter(r=>{let n=new Date(r.startTime).getTime();return t-n>e&&r.status==="pending"})}removeTask(e){let t=this.activeTasks.get(e);return t?(this.recordStateTransition(e,t.status,"deleted","\u4EFB\u52A1\u88AB\u79FB\u9664"),this.activeTasks.delete(e),this.logger.info(`[TaskState] \u79FB\u9664\u4EFB\u52A1: ${e}`),!0):!1}cleanupCompletedTasks(e=3e5){let t=Date.now(),r=0;for(let[n,s]of this.activeTasks.entries())if(s.status==="completed"||s.status==="failed"){let o=s.endTime?new Date(s.endTime).getTime():t;t-o>e&&(this.removeTask(n),r++)}return r>0&&this.logger.info(`[TaskState] \u6E05\u7406\u5DF2\u5B8C\u6210\u4EFB\u52A1: ${r}\u4E2A`),r}getTaskStatistics(){let e=Array.from(this.activeTasks.values()),t=e.length,r=e.filter(u=>u.status==="pending").length,n=e.filter(u=>u.status==="completed").length,s=e.filter(u=>u.status==="failed").length,o=e.filter(u=>u.status==="consumed").length,a=e.filter(u=>u.status==="completed"&&u.endTime),g=a.length>0?a.reduce((u,p)=>{let h=this.getTaskExecutionTime(p.taskId)||0;return u+h},0)/a.length:0;return{total:t,pending:r,completed:n,failed:s,consumed:o,averageExecutionTime:g}}getTaskHistory(e){return e?this.taskHistory.filter(t=>t.taskId===e):[...this.taskHistory]}recordStateTransition(e,t,r,n){let s={from:t,to:r,reason:n,timestamp:new Date().toISOString(),taskId:e};this.taskHistory.push(s),this.taskHistory.length>1e3&&(this.taskHistory=this.taskHistory.slice(-500))}getStatusChangeReason(e,t,r){if(r)return`\u6267\u884C\u5931\u8D25: ${r}`;let n={"none->pending":"\u4EFB\u52A1\u5F00\u59CB\u6267\u884C","pending->completed":"\u4EFB\u52A1\u6267\u884C\u6210\u529F","pending->failed":"\u4EFB\u52A1\u6267\u884C\u5931\u8D25","completed->consumed":"\u7ED3\u679C\u88AB\u6D88\u8D39","failed->consumed":"\u5931\u8D25\u7ED3\u679C\u88AB\u5904\u7406","consumed->deleted":"\u4EFB\u52A1\u88AB\u6E05\u7406"},s=`${e}->${t}`;return n[s]||"\u72B6\u6001\u66F4\u65B0"}validateTaskIntegrity(){let e=[];for(let[t,r]of this.activeTasks.entries())(!r.taskId||!r.toolName||!r.status||!r.startTime)&&e.push(`\u4EFB\u52A1\u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: ${t}`),Number.isNaN(new Date(r.startTime).getTime())&&e.push(`\u65E0\u6548\u7684\u5F00\u59CB\u65F6\u95F4: ${t}`),r.endTime&&Number.isNaN(new Date(r.endTime).getTime())&&e.push(`\u65E0\u6548\u7684\u7ED3\u675F\u65F6\u95F4: ${t}`),r.status==="completed"&&!r.endTime&&e.push(`\u5DF2\u5B8C\u6210\u4EFB\u52A1\u7F3A\u5C11\u7ED3\u675F\u65F6\u95F4: ${t}`),r.status==="failed"&&!r.error&&e.push(`\u5931\u8D25\u4EFB\u52A1\u7F3A\u5C11\u9519\u8BEF\u4FE1\u606F: ${t}`);return{isValid:e.length===0,issues:e}}restartStalledTasks(e=3e4){let t=this.getTimeoutTasks(e),r=0;for(let n of t){this.logger.warn(`[TaskState] \u68C0\u6D4B\u5230\u505C\u6EDE\u4EFB\u52A1: ${n.taskId}`),this.markTaskAsFailed(n.taskId,"\u4EFB\u52A1\u6267\u884C\u8D85\u65F6");let s=this.generateTaskId(n.toolName,n.arguments);this.createTask(s,n.toolName,n.arguments,"pending"),r++}return r>0&&this.logger.info(`[TaskState] \u91CD\u542F\u505C\u6EDE\u4EFB\u52A1: ${r}\u4E2A`),r}cleanup(){this.activeTasks.clear(),this.taskHistory=[],this.logger.info("[TaskState] \u6E05\u7406\u4EFB\u52A1\u72B6\u6001\u7BA1\u7406\u5668\u8D44\u6E90")}};var _=class i extends Error{static{l(this,"TimeoutError")}name="TimeoutError";constructor(e){super(e),this.name="TimeoutError",Error.captureStackTrace(this,i)}toJSON(){return{name:this.name,message:this.message,stack:this.stack}}};function xe(i,e){return{content:[{type:"text",text:e?nt(e,i):Ie(i)}],isError:!1,taskId:i,status:"timeout",message:"\u5DE5\u5177\u8C03\u7528\u8D85\u65F6\uFF0C\u6B63\u5728\u540E\u53F0\u5904\u7406\u4E2D",nextAction:"\u8BF7\u7A0D\u540E\u91CD\u8BD5\u6216\u7B49\u5F85\u4EFB\u52A1\u5B8C\u6210"}}l(xe,"createTimeoutResponse");function nt(i,e){let t={coze_workflow:`\u23F1\uFE0F \u6263\u5B50\u5DE5\u4F5C\u6D41\u6267\u884C\u8D85\u65F6\uFF0C\u6B63\u5728\u540E\u53F0\u5904\u7406\u4E2D...
14
4
 
15
5
  \u{1F4CB} \u4EFB\u52A1\u4FE1\u606F\uFF1A
16
6
  - \u4EFB\u52A1ID: ${e}
@@ -21,17 +11,27 @@ data: /messages?sessionId=${n}
21
11
  \u{1F504} \u540E\u7EED\u64CD\u4F5C\uFF1A
22
12
  1. \u4F7F\u7528\u76F8\u540C\u53C2\u6570\u91CD\u65B0\u8C03\u7528\u5DE5\u5177
23
13
  2. \u7CFB\u7EDF\u4F1A\u81EA\u52A8\u8FD4\u56DE\u5DF2\u5B8C\u6210\u7684\u4EFB\u52A1\u7ED3\u679C
24
- 3. \u590D\u6742\u5DE5\u4F5C\u6D41\u53EF\u80FD\u9700\u8981\u66F4\u957F\u65F6\u95F4\u5904\u7406`,default:Le(e)};return t[o]||t.default}l(at,"getToolSpecificTimeoutMessage");function Le(o){return`\u23F1\uFE0F \u5DE5\u5177\u8C03\u7528\u8D85\u65F6\uFF0C\u6B63\u5728\u540E\u53F0\u5904\u7406\u4E2D...
14
+ 3. \u590D\u6742\u5DE5\u4F5C\u6D41\u53EF\u80FD\u9700\u8981\u66F4\u957F\u65F6\u95F4\u5904\u7406`,default:Ie(e)};return t[i]||t.default}l(nt,"getToolSpecificTimeoutMessage");function Ie(i){return`\u23F1\uFE0F \u5DE5\u5177\u8C03\u7528\u8D85\u65F6\uFF0C\u6B63\u5728\u540E\u53F0\u5904\u7406\u4E2D...
25
15
 
26
16
  \u{1F4CB} \u4EFB\u52A1\u4FE1\u606F\uFF1A
27
- - \u4EFB\u52A1ID: ${o}
17
+ - \u4EFB\u52A1ID: ${i}
28
18
  - \u72B6\u6001: \u5904\u7406\u4E2D
29
19
  - \u5EFA\u8BAE: \u8BF7\u7B49\u5F8530\u79D2\u540E\u91CD\u8BD5\u67E5\u8BE2
30
20
 
31
21
  \u{1F504} \u540E\u7EED\u64CD\u4F5C\uFF1A
32
22
  1. \u4F7F\u7528\u76F8\u540C\u7684\u53C2\u6570\u91CD\u65B0\u8C03\u7528\u5DE5\u5177
33
23
  2. \u7CFB\u7EDF\u4F1A\u81EA\u52A8\u8FD4\u56DE\u5DF2\u5B8C\u6210\u7684\u4EFB\u52A1\u7ED3\u679C
34
- 3. \u5982\u679C\u957F\u65F6\u95F4\u672A\u5B8C\u6210\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458`}l(Le,"getDefaultTimeoutMessage");import{createHash as ct}from"crypto";import{existsSync as B,mkdirSync as lt,readFileSync as De,renameSync as gt,writeFileSync as Ae}from"fs";import{dirname as ut,resolve as He}from"path";import ht from"dayjs";var U=class{static{l(this,"MCPCacheManager")}cachePath;logger;CACHE_VERSION="1.0.0";CACHE_ENTRY_VERSION="1.0.0";cleanupInterval;CLEANUP_INTERVAL=6e4;constructor(e){this.logger=c,this.cachePath=e||this.getCacheFilePath(),this.startCleanupTimer()}formatTimestamp(){return ht().format("YYYY-MM-DD HH:mm:ss")}getCacheFilePath(){try{let e=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return He(e,"xiaozhi.cache.json")}catch{let t=process.env.XIAOZHI_CONFIG_DIR||"/tmp";return He(t,"xiaozhi.cache.json")}}async ensureCacheFile(){try{if(!B(this.cachePath)){let e=ut(this.cachePath);B(e)||(lt(e,{recursive:!0}),this.logger.debug(`[CacheManager] \u5DF2\u521B\u5EFA\u7F13\u5B58\u76EE\u5F55: ${e}`)),this.logger.debug("[CacheManager] \u7F13\u5B58\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u521B\u5EFA\u521D\u59CB\u7F13\u5B58\u6587\u4EF6");let t=await this.createInitialCache();await this.saveCache(t),this.logger.info(`[CacheManager] \u5DF2\u521B\u5EFA\u7F13\u5B58\u6587\u4EF6: ${this.cachePath}`)}}catch(e){this.logger.warn(`[CacheManager] \u521B\u5EFA\u7F13\u5B58\u6587\u4EF6\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}async createInitialCache(){let e=this.formatTimestamp();return{version:this.CACHE_VERSION,mcpServers:{},metadata:{lastGlobalUpdate:e,totalWrites:0,createdAt:e}}}async writeCacheEntry(e,t,r){try{this.logger.debug(`[CacheManager] \u5F00\u59CB\u5199\u5165\u7F13\u5B58: ${e}`),await this.ensureCacheFile();let n=await this.loadExistingCache(),s=this.generateConfigHash(r),i={tools:t.map(a=>({name:a.name,description:a.description||"",inputSchema:a.inputSchema})),lastUpdated:this.formatTimestamp(),serverConfig:{...r},configHash:s,version:this.CACHE_ENTRY_VERSION};n.mcpServers[e]=i,n.metadata.lastGlobalUpdate=this.formatTimestamp(),n.metadata.totalWrites+=1,await this.saveCache(n),this.logger.debug(`[CacheManager] \u7F13\u5B58\u5199\u5165\u6210\u529F: ${e}, \u5DE5\u5177\u6570\u91CF: ${t.length}`)}catch(n){this.logger.warn(`[CacheManager] \u7F13\u5B58\u5199\u5165\u5931\u8D25: ${e}, \u9519\u8BEF: ${n instanceof Error?n.message:String(n)}`)}}async loadExistingCache(){try{if(!B(this.cachePath))return await this.createInitialCache();let e=De(this.cachePath,"utf8"),t=JSON.parse(e);return this.validateCacheStructure(t)?t:(this.logger.warn("[CacheManager] \u7F13\u5B58\u6587\u4EF6\u7ED3\u6784\u65E0\u6548\uFF0C\u91CD\u65B0\u521B\u5EFA"),await this.createInitialCache())}catch(e){return this.logger.warn(`[CacheManager] \u52A0\u8F7D\u7F13\u5B58\u5931\u8D25\uFF0C\u521B\u5EFA\u65B0\u7F13\u5B58: ${e instanceof Error?e.message:String(e)}`),await this.createInitialCache()}}async saveCache(e){let t=JSON.stringify(e,null,2);await this.atomicWrite(this.cachePath,t)}async atomicWrite(e,t){let r=`${e}.tmp`;try{Ae(r,t,"utf8"),gt(r,e)}catch(n){try{B(r)&&Ae(r,"","utf8")}catch{}throw n}}generateConfigHash(e){try{return ct("sha256").update(JSON.stringify(e)).digest("hex")}catch(t){return this.logger.warn(`[CacheManager] \u751F\u6210\u914D\u7F6E\u54C8\u5E0C\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`),""}}validateCacheStructure(e){try{return e&&typeof e=="object"&&typeof e.version=="string"&&typeof e.mcpServers=="object"&&e.metadata&&typeof e.metadata=="object"&&typeof e.metadata.lastGlobalUpdate=="string"&&typeof e.metadata.totalWrites=="number"&&typeof e.metadata.createdAt=="string"}catch{return!1}}async getStats(){try{let e=await this.loadExistingCache();return{totalWrites:e.metadata.totalWrites,lastUpdate:e.metadata.lastGlobalUpdate,serverCount:Object.keys(e.mcpServers).length,cacheFileSize:B(this.cachePath)?De(this.cachePath,"utf8").length:0}}catch(e){return this.logger.warn(`[CacheManager] \u83B7\u53D6\u7F13\u5B58\u7EDF\u8BA1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`),null}}getFilePath(){return this.cachePath}async getAllCachedTools(){try{let e=await this.loadExistingCache(),t=[];for(let[r,n]of Object.entries(e.mcpServers))for(let s of n.tools)t.push({...s,name:`${r}__${s.name}`});return this.logger.debug(`[CacheManager] \u83B7\u53D6\u5230\u6240\u6709\u7F13\u5B58\u5DE5\u5177\uFF0C\u5171 ${t.length} \u4E2A`),t}catch(e){return this.logger.warn(`[CacheManager] \u83B7\u53D6\u6240\u6709\u7F13\u5B58\u5DE5\u5177\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`),[]}}async writeCustomMCPResult(e,t,r,n="completed",s,i=3e5){try{let a=await this.loadExtendedCache(),g=$(e,t),u={result:r,timestamp:new Date().toISOString(),ttl:i,status:n,consumed:!1,taskId:s,retryCount:0};a.customMCPResults||(a.customMCPResults={}),a.customMCPResults[g]=u,await this.saveExtendedCache(a),this.logger.debug(`[CacheManager] \u5199\u5165CustomMCP\u7ED3\u679C\u7F13\u5B58: ${e}, \u72B6\u6001: ${n}`)}catch(a){this.logger.warn(`[CacheManager] \u5199\u5165CustomMCP\u7ED3\u679C\u7F13\u5B58\u5931\u8D25: ${a instanceof Error?a.message:String(a)}`)}}async readCustomMCPResult(e,t){try{let r=await this.loadExtendedCache(),n=$(e,t);if(!r.customMCPResults||!r.customMCPResults[n])return null;let s=r.customMCPResults[n],i=Date.now(),a=new Date(s.timestamp).getTime();return i-a>s.ttl?(this.logger.debug(`[CacheManager] \u7F13\u5B58\u5DF2\u8FC7\u671F: ${e}`),null):s}catch(r){return this.logger.warn(`[CacheManager] \u8BFB\u53D6CustomMCP\u7ED3\u679C\u7F13\u5B58\u5931\u8D25: ${r instanceof Error?r.message:String(r)}`),null}}async updateCustomMCPStatus(e,t,r,n,s){try{let i=await this.loadExtendedCache(),a=$(e,t);if(!i.customMCPResults||!i.customMCPResults[a])return!1;let g=i.customMCPResults[a],u=g.status;return g.status=r,g.timestamp=new Date().toISOString(),n&&(g.result=n),s&&r==="failed"&&(g.result={content:[{type:"text",text:`\u4EFB\u52A1\u5931\u8D25: ${s}`}]},g.consumed=!0),r==="completed"&&(g.consumed=!1),await this.saveExtendedCache(i),this.logger.debug(`[CacheManager] \u66F4\u65B0\u7F13\u5B58\u72B6\u6001: ${e} ${u} -> ${r}`),!0}catch(i){return this.logger.warn(`[CacheManager] \u66F4\u65B0CustomMCP\u7F13\u5B58\u72B6\u6001\u5931\u8D25: ${i instanceof Error?i.message:String(i)}`),!1}}async markCustomMCPAsConsumed(e,t){try{let r=await this.loadExtendedCache(),n=$(e,t);if(!r.customMCPResults||!r.customMCPResults[n])return!1;let s=r.customMCPResults[n];return s.consumed||(s.consumed=!0,s.timestamp=new Date().toISOString(),await this.saveExtendedCache(r),this.logger.debug(`[CacheManager] \u6807\u8BB0\u7F13\u5B58\u4E3A\u5DF2\u6D88\u8D39: ${e}`)),!0}catch(r){return this.logger.warn(`[CacheManager] \u6807\u8BB0CustomMCP\u7F13\u5B58\u4E3A\u5DF2\u6D88\u8D39\u5931\u8D25: ${r instanceof Error?r.message:String(r)}`),!1}}async deleteCustomMCPResult(e,t){try{let r=await this.loadExtendedCache(),n=$(e,t);return!r.customMCPResults||!r.customMCPResults[n]?!1:(delete r.customMCPResults[n],await this.saveExtendedCache(r),this.logger.debug(`[CacheManager] \u5220\u9664\u7F13\u5B58\u6761\u76EE: ${e}`),!0)}catch(r){return this.logger.warn(`[CacheManager] \u5220\u9664CustomMCP\u7F13\u5B58\u6761\u76EE\u5931\u8D25: ${r instanceof Error?r.message:String(r)}`),!1}}async cleanupCustomMCPResults(){try{let e=await this.loadExtendedCache();if(!e.customMCPResults)return{cleaned:0,total:0};let t=Object.entries(e.customMCPResults),r=0;for(let[n,s]of t)D(s)&&(delete e.customMCPResults[n],r++);return r>0&&(await this.saveExtendedCache(e),this.logger.info(`[CacheManager] \u6E05\u7406CustomMCP\u7F13\u5B58: ${r}/${t.length}`)),{cleaned:r,total:t.length}}catch(e){return this.logger.warn(`[CacheManager] \u6E05\u7406CustomMCP\u7F13\u5B58\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`),{cleaned:0,total:0}}}async getCustomMCPStatistics(){try{let e=await this.loadExtendedCache();if(!e.customMCPResults)return{totalEntries:0,pendingTasks:0,completedTasks:0,failedTasks:0,consumedEntries:0,cacheHitRate:0,lastCleanupTime:new Date().toISOString(),memoryUsage:0};let t=Object.values(e.customMCPResults),r=t.length,n=t.filter(p=>p.status==="pending").length,s=t.filter(p=>p.status==="completed").length,i=t.filter(p=>p.status==="failed").length,a=t.filter(p=>p.consumed).length,g=s>0?a/s*100:0,u=JSON.stringify(e.customMCPResults).length;return{totalEntries:r,pendingTasks:n,completedTasks:s,failedTasks:i,consumedEntries:a,cacheHitRate:g,lastCleanupTime:new Date().toISOString(),memoryUsage:u}}catch(e){return this.logger.warn(`[CacheManager] \u83B7\u53D6CustomMCP\u7F13\u5B58\u7EDF\u8BA1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`),{totalEntries:0,pendingTasks:0,completedTasks:0,failedTasks:0,consumedEntries:0,cacheHitRate:0,lastCleanupTime:new Date().toISOString(),memoryUsage:0}}}async loadExtendedCache(){try{return await this.loadExistingCache()}catch(e){return this.logger.warn(`[CacheManager] \u52A0\u8F7D\u6269\u5C55\u7F13\u5B58\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`),{version:this.CACHE_VERSION,mcpServers:{},metadata:{lastGlobalUpdate:this.formatTimestamp(),totalWrites:0,createdAt:this.formatTimestamp()},customMCPResults:{}}}}async saveExtendedCache(e){await this.saveCache(e)}startCleanupTimer(){this.cleanupInterval=setInterval(()=>{this.cleanupCustomMCPResults().catch(e=>{this.logger.warn(`[CacheManager] \u81EA\u52A8\u6E05\u7406\u5931\u8D25: ${e}`)})},this.CLEANUP_INTERVAL),this.logger.debug(`[CacheManager] \u542F\u52A8\u6E05\u7406\u5B9A\u65F6\u5668\uFF0C\u95F4\u9694: ${this.CLEANUP_INTERVAL}ms`)}stopCleanupTimer(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=void 0,this.logger.debug("[CacheManager] \u505C\u6B62\u6E05\u7406\u5B9A\u65F6\u5668"))}cleanup(){this.stopCleanupTimer(),this.logger.debug("[CacheManager] \u6E05\u7406\u8D44\u6E90\u5B8C\u6210")}};var te=class{static{l(this,"CustomMCPHandler")}logger;tools=new Map;cacheManager;cacheLifecycleManager;taskStateManager;mcpServiceManager;TIMEOUT=x.TIMEOUT;CACHE_TTL=x.CACHE_TTL;CLEANUP_INTERVAL=x.CLEANUP_INTERVAL;cleanupTimer;activeTasks=new Map;eventBus=b();constructor(e,t){this.logger=c,this.cacheManager=e||new U,this.mcpServiceManager=t,this.cacheLifecycleManager=new Z(this.logger),this.taskStateManager=new ee(this.logger),this.startCleanupTimer(),this.cacheLifecycleManager.startAutoCleanup(),this.setupEventListeners()}setupEventListeners(){this.eventBus.onEvent("config:updated",async e=>{await this.handleConfigUpdated(e)})}async handleConfigUpdated(e){this.logger.debug("[CustomMCP] \u68C0\u6D4B\u5230\u914D\u7F6E\u66F4\u65B0\uFF0C\u68C0\u67E5\u662F\u5426\u9700\u8981\u91CD\u65B0\u521D\u59CB\u5316");try{e.type==="customMCP"?(this.logger.debug("[CustomMCP] customMCP \u914D\u7F6E\u5DF2\u66F4\u65B0\uFF0C\u91CD\u65B0\u521D\u59CB\u5316\u5904\u7406\u5668"),await this.reinitialize()):e.type==="serverTools"&&(this.logger.debug("[CustomMCP] serverTools \u914D\u7F6E\u5DF2\u66F4\u65B0\uFF0C\u91CD\u65B0\u521D\u59CB\u5316\u5904\u7406\u5668"),await this.reinitialize())}catch(t){this.logger.error("[CustomMCP] \u914D\u7F6E\u66F4\u65B0\u5904\u7406\u5931\u8D25:",t)}}async reinitialize(){try{this.logger.debug("[CustomMCP] \u5F00\u59CB\u91CD\u65B0\u521D\u59CB\u5316\u5904\u7406\u5668"),this.tools.clear();let e=f.getCustomMCPTools();for(let t of e)this.tools.set(t.name,t),this.logger.debug(`[CustomMCP] \u91CD\u65B0\u52A0\u8F7D\u5DE5\u5177: ${t.name} (${t.handler.type})`);this.logger.debug(`[CustomMCP] \u91CD\u65B0\u521D\u59CB\u5316\u5B8C\u6210\uFF0C\u5171\u52A0\u8F7D ${this.tools.size} \u4E2A\u5DE5\u5177`)}catch(e){throw this.logger.error("[CustomMCP] \u91CD\u65B0\u521D\u59CB\u5316\u5931\u8D25:",e),e}}initialize(e){this.logger.debug("[CustomMCP] \u521D\u59CB\u5316 CustomMCP \u5904\u7406\u5668...");try{let t=e||f.getCustomMCPTools();this.tools.clear();for(let r of t)this.tools.set(r.name,r),this.logger.debug(`[CustomMCP] \u5DF2\u52A0\u8F7D\u5DE5\u5177: ${r.name} (${r.handler.type})`);this.logger.debug(`[CustomMCP] \u521D\u59CB\u5316\u5B8C\u6210\uFF0C\u5171\u52A0\u8F7D ${this.tools.size} \u4E2A\u5DE5\u5177`)}catch(t){throw this.logger.error("[CustomMCP] \u521D\u59CB\u5316\u5931\u8D25:",t),t}}getTools(){return Array.from(this.tools.values()).map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema}))}hasTool(e){return this.tools.has(e)}getToolCount(){return this.tools.size}getToolNames(){return Array.from(this.tools.keys())}async callTool(e,t,r){if(!this.tools.get(e))throw new Error(`\u672A\u627E\u5230\u5DE5\u5177: ${e}`);let s=await this.getCompletedResult(e,t);if(s)return this.logger.debug(`[CustomMCP] \u8FD4\u56DE\u5DF2\u5B8C\u6210\u7684\u4EFB\u52A1\u7ED3\u679C: ${e}`),await this.clearConsumedCache(e,t),s;try{let i=await Promise.race([this.executeToolWithBackgroundProcessing(e,t),this.createTimeoutPromise(e,t)]);return await this.cacheResult(e,t,i),i}catch(i){if(i instanceof W){let a=await this.generateTaskId(e,t);return this.logger.info(`[CustomMCP] \u5DE5\u5177\u8D85\u65F6\uFF0C\u8FD4\u56DE\u53CB\u597D\u63D0\u793A: ${e}, taskId: ${a}`),Oe(a,e)}throw i}}async executeToolWithBackgroundProcessing(e,t){let r=this.tools.get(e);if(!r)throw new Error(`\u5DE5\u5177\u4E0D\u5B58\u5728: ${e}`);let n=await this.generateTaskId(e,t);await this.markTaskAsPending(n,e,t);try{let s=await this.callToolByType(r,t);return await this.markTaskAsCompleted(n,s),s}catch(s){throw await this.markTaskAsFailed(n,s),s}}async createTimeoutPromise(e,t){return new Promise((r,n)=>{setTimeout(()=>{n(new W(`\u5DE5\u5177\u8C03\u7528\u8D85\u65F6: ${e}`))},this.TIMEOUT)})}async getCompletedResult(e,t){try{let r=this.generateCacheKey(e,t),n=await this.loadExtendedCache();if(!n.customMCPResults||!n.customMCPResults[r])return null;let s=n.customMCPResults[r];return s.status==="completed"&&!s.consumed&&!j(s.timestamp,s.ttl)?s.result:null}catch(r){return this.logger.warn(`[CustomMCP] \u83B7\u53D6\u7F13\u5B58\u5931\u8D25: ${r}`),null}}async callToolByType(e,t){switch(e.handler.type){case"proxy":return await this.callProxyTool(e,t);case"function":return await this.callFunctionTool(e,t);case"http":return await this.callHttpTool(e,t);case"script":return await this.callScriptTool(e,t);case"chain":return await this.callChainTool(e,t);case"mcp":try{return await this.forwardToMCPServiceManager(e,t)}catch(r){this.logger.error(`[CustomMCP] MCP \u7C7B\u578B\u5DE5\u5177\u8DEF\u7531\u5931\u8D25: ${e.name}`,r);let n=r instanceof Error?r.message:"MCP \u7C7B\u578B\u5DE5\u5177\u8DEF\u7531\u9519\u8BEF";return{content:[{type:"text",text:n.includes("MCPServiceManager \u672A\u521D\u59CB\u5316")?n:"\u5185\u90E8\u9519\u8BEF\uFF1AMCP \u7C7B\u578B\u5DE5\u5177\u8DEF\u7531\u9519\u8BEF"}],isError:!0}}default:throw new Error(`\u4E0D\u652F\u6301\u7684\u5904\u7406\u5668\u7C7B\u578B: ${e.handler.type}`)}}async forwardToMCPServiceManager(e,t){if(!this.mcpServiceManager)throw this.logger.error(`[CustomMCP] MCPServiceManager \u672A\u521D\u59CB\u5316\uFF0C\u65E0\u6CD5\u8F6C\u53D1\u5DE5\u5177 ${e.name} \u7684\u8C03\u7528`),new Error("MCPServiceManager \u672A\u521D\u59CB\u5316");let r=e.handler;this.logger.info(`[CustomMCP] \u8F6C\u53D1MCP\u5DE5\u5177\u8C03\u7528: ${e.name}`,{serviceName:r.config.serviceName,toolName:r.config.toolName});try{let n=await this.mcpServiceManager.callTool(r.config.toolName,t);return this.logger.info(`[CustomMCP] MCP\u5DE5\u5177\u8F6C\u53D1\u6210\u529F: ${e.name}`),n}catch(n){return this.logger.error(`[CustomMCP] MCP\u5DE5\u5177\u8F6C\u53D1\u5931\u8D25: ${e.name}`,n),{content:[{type:"text",text:`MCP\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`}],isError:!0}}}async callProxyTool(e,t){let r=e.handler;if(this.logger.info(`[CustomMCP] \u8C03\u7528\u4EE3\u7406\u5DE5\u5177: ${e.name}`,{platform:r.platform,config:r.config}),r.platform==="coze")return await this.callCozeWorkflow(e,t);throw new Error(`\u4E0D\u652F\u6301\u7684\u4EE3\u7406\u5E73\u53F0: ${r.platform}`)}async callCozeWorkflow(e,t){let n=e.handler.config;this.logger.info(`[CustomMCP] \u8C03\u7528 Coze \u5DE5\u4F5C\u6D41: ${e.name}`,{workflow_id:n.workflow_id,bot_id:n.bot_id});try{let s=this.buildCozeRequest(n,t),i=await this.sendCozeRequest(n,s);return this.logger.info(`[CustomMCP] Coze \u5DE5\u4F5C\u6D41\u8C03\u7528\u6210\u529F: ${e.name}`,{response:i}),this.processCozeResponse(e.name,i)}catch(s){return this.logger.error(`[CustomMCP] Coze \u5DE5\u4F5C\u6D41\u8C03\u7528\u5931\u8D25: ${e.name}`,s),{content:[{type:"text",text:`Coze \u5DE5\u4F5C\u6D41\u8C03\u7528\u5931\u8D25: ${s instanceof Error?s.message:String(s)}`}],isError:!0}}}buildCozeRequest(e,t){return{workflow_id:e.workflow_id,parameters:{...t}}}async sendCozeRequest(e,t){let r=e.base_url||"https://api.coze.cn",n="",s=f.getConfig().platforms?.coze?.token;if(!s)throw new Error("Coze Token \u914D\u7F6E\u4E0D\u5B58\u5728");if(e.workflow_id)n="/v1/workflow/run",t.workflow_id=e.workflow_id;else if(e.bot_id)n="/v3/chat",t.bot_id=e.bot_id;else throw new Error("Coze \u914D\u7F6E\u5FC5\u987B\u63D0\u4F9B workflow_id \u6216 bot_id");let i=`${r}${n}`,a=e.timeout||3e5,g={"Content-Type":"application/json",Authorization:`Bearer ${s}`,...e.headers};this.logger.debug(`[CustomMCP] \u53D1\u9001 Coze \u8BF7\u6C42\u5230: ${i}`,{headers:{...g},body:t});let u=new AbortController,p=setTimeout(()=>u.abort(),a);try{let h=await fetch(i,{method:"POST",headers:g,body:JSON.stringify(t)});if(clearTimeout(p),!h.ok){let T=await h.text();throw new Error(`Coze API \u8BF7\u6C42\u5931\u8D25 (${h.status}): ${T}`)}let S=await h.json();return this.logger.debug("[CustomMCP] Coze API \u54CD\u5E94:",S),S}catch(h){throw clearTimeout(p),h instanceof Error&&h.name==="AbortError"?new Error(`Coze API \u8BF7\u6C42\u8D85\u65F6 (${a}ms)`):h}}processCozeResponse(e,t){try{return t.data?{content:[{type:"text",text:t.data}],isError:!1}:{content:[{type:"text",text:JSON.stringify(t,null,2)}],isError:!1}}catch(r){return this.logger.error(`[CustomMCP] \u5904\u7406 Coze \u54CD\u5E94\u5931\u8D25: ${e}`,r),{content:[{type:"text",text:`\u5904\u7406\u54CD\u5E94\u5931\u8D25: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}}async callFunctionTool(e,t){let r=e.handler;this.logger.info(`[CustomMCP] \u8C03\u7528\u51FD\u6570\u5DE5\u5177: ${e.name}`,{module:r.module,function:r.function});try{let n=await this.loadModule(r.module),s=this.getFunction(n,r.function),i=await this.executeFunction(s,t,r);return{content:[{type:"text",text:typeof i=="string"?i:JSON.stringify(i,null,2)}],isError:!1}}catch(n){return this.logger.error(`[CustomMCP] \u51FD\u6570\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${e.name}`,n),{content:[{type:"text",text:`\u51FD\u6570\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`}],isError:!0}}}async loadModule(e){try{let t=e;return!e.startsWith("/")&&!e.startsWith("file://")&&(t=new URL(e,`file://${process.cwd()}/`).href),this.logger.debug(`[CustomMCP] \u52A0\u8F7D\u6A21\u5757: ${t}`),await import(t)}catch(t){throw new Error(`\u65E0\u6CD5\u52A0\u8F7D\u6A21\u5757 ${e}: ${t instanceof Error?t.message:String(t)}`)}}getFunction(e,t){let r;if(e.default&&typeof e.default=="function"&&(t==="default"?r=e.default:e.default[t]&&typeof e.default[t]=="function"&&(r=e.default[t])),!r&&e[t]&&typeof e[t]=="function"&&(r=e[t]),!r)throw new Error(`\u5728\u6A21\u5757\u4E2D\u627E\u4E0D\u5230\u51FD\u6570: ${t}`);return r}async executeFunction(e,t,r){let n=r.timeout||3e4,s={...r.context,logger:this.logger,arguments:t},i=Promise.resolve().then(()=>e.length>1?e(t,s):e(t)),a=new Promise((g,u)=>{setTimeout(()=>u(new Error(`\u51FD\u6570\u6267\u884C\u8D85\u65F6 (${n}ms)`)),n)});return Promise.race([i,a])}async callHttpTool(e,t){let r=e.handler;this.logger.info(`[CustomMCP] \u8C03\u7528 HTTP \u5DE5\u5177: ${e.name}`,{url:r.url,method:r.method||"POST"});try{let{url:n,requestOptions:s}=this.buildHttpRequest(r,t),i=await this.sendHttpRequest(n,s,r);return this.processHttpResponse(e.name,i,r)}catch(n){return this.logger.error(`[CustomMCP] HTTP \u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${e.name}`,n),{content:[{type:"text",text:`HTTP \u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`}],isError:!0}}}buildHttpRequest(e,t){let r=e.method||"POST",n={"Content-Type":"application/json","User-Agent":"xiaozhi-client/1.0",...e.headers};if(e.auth)switch(e.auth.type){case"bearer":e.auth.token&&(n.Authorization=`Bearer ${e.auth.token}`);break;case"basic":if(e.auth.username&&e.auth.password){let g=btoa(`${e.auth.username}:${e.auth.password}`);n.Authorization=`Basic ${g}`}break;case"api_key":e.auth.api_key&&e.auth.api_key_header&&(n[e.auth.api_key_header]=e.auth.api_key);break}let s,i=e.url;if(r!=="GET")e.body_template?s=this.replaceTemplateVariables(e.body_template,t):s=JSON.stringify(t);else{let g=new URLSearchParams;for(let[p,h]of Object.entries(t))h!=null&&g.append(p,String(h));let u=g.toString();u&&(i+=(i.includes("?")?"&":"?")+u)}return{url:i,requestOptions:{method:r,headers:n,body:s}}}async sendHttpRequest(e,t,r){let n=r.timeout||3e4,s=r.retry_count||0,i=r.retry_delay||1e3,a=null;for(let g=0;g<=s;g++){try{this.logger.debug(`[CustomMCP] \u53D1\u9001 HTTP \u8BF7\u6C42 (\u5C1D\u8BD5 ${g+1}/${s+1}): ${e}`,{method:t.method,headers:t.headers});let u=new AbortController,p=setTimeout(()=>u.abort(),n),h=await fetch(e,{...t,signal:u.signal});if(clearTimeout(p),h.ok||g===s)return h;this.logger.warn(`[CustomMCP] HTTP \u8BF7\u6C42\u5931\u8D25 (${h.status}), \u5C06\u5728 ${i}ms \u540E\u91CD\u8BD5`),a=new Error(`HTTP \u8BF7\u6C42\u5931\u8D25: ${h.status} ${h.statusText}`)}catch(u){if(a=u instanceof Error?u:new Error(String(u)),u instanceof Error&&u.name==="AbortError"&&(a=new Error(`HTTP \u8BF7\u6C42\u8D85\u65F6 (${n}ms)`)),this.logger.warn(`[CustomMCP] HTTP \u8BF7\u6C42\u5F02\u5E38 (\u5C1D\u8BD5 ${g+1}/${s+1}):`,a.message),g===s)throw a}g<s&&await new Promise(u=>setTimeout(u,i))}throw a||new Error("HTTP \u8BF7\u6C42\u5931\u8D25")}async processHttpResponse(e,t,r){try{let n=t.headers.get("content-type")||"",s;if(n.includes("application/json")?s=await t.json():s=await t.text(),!t.ok)return{content:[{type:"text",text:`HTTP \u8BF7\u6C42\u5931\u8D25 (${t.status}): ${typeof s=="string"?s:JSON.stringify(s)}`}],isError:!0};let i=s;return r.response_mapping&&(i=this.extractResponseData(s,r.response_mapping)),{content:[{type:"text",text:typeof i=="string"?i:JSON.stringify(i,null,2)}],isError:!1}}catch(n){return this.logger.error(`[CustomMCP] \u5904\u7406 HTTP \u54CD\u5E94\u5931\u8D25: ${e}`,n),{content:[{type:"text",text:`\u5904\u7406\u54CD\u5E94\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`}],isError:!0}}}replaceTemplateVariables(e,t){let r=e;for(let[n,s]of Object.entries(t)){let i=`{{${n}}}`,a=typeof s=="string"?s:JSON.stringify(s);r=r.replace(new RegExp(i.replace(/[{}]/g,"\\$&"),"g"),a)}return r}extractResponseData(e,t){if(!t)return e;let r=l((n,s)=>{if(!s)return n;let i=s.split("."),a=n;for(let g of i)if(a&&typeof a=="object"&&g in a)a=a[g];else return;return a},"extractByPath");if(t.success_path){let n=r(e,t.success_path);if(n!==void 0)return t.data_path?r(n,t.data_path):n}if(t.data_path){let n=r(e,t.data_path);if(n!==void 0)return n}return e}async callScriptTool(e,t){let r=e.handler;this.logger.info(`[CustomMCP] \u8C03\u7528\u811A\u672C\u5DE5\u5177: ${e.name}`,{script:r.script.substring(0,100)+(r.script.length>100?"...":""),interpreter:r.interpreter||"node"});try{let n=await this.executeScript(r,t);return{content:[{type:"text",text:typeof n=="string"?n:JSON.stringify(n,null,2)}],isError:!1}}catch(n){return this.logger.error(`[CustomMCP] \u811A\u672C\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${e.name}`,n),{content:[{type:"text",text:`\u811A\u672C\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`}],isError:!0}}}async executeScript(e,t){let{spawn:r}=await import("child_process"),{promisify:n}=await import("util"),s=await import("fs/promises"),i=await import("path"),a=await import("os"),g=e.timeout||3e4,u=e.interpreter||"node",p,h=!1;try{if(e.script.includes(`
35
- `)||e.script.length>200){let y=await s.mkdtemp(i.join(a.tmpdir(),"xiaozhi-script-")),I=this.getScriptExtension(u);p=i.join(y,`script${I}`),await s.writeFile(p,e.script,"utf8"),h=!0}else{p=e.script;try{await s.access(p)}catch{throw new Error(`\u811A\u672C\u6587\u4EF6\u4E0D\u5B58\u5728: ${p}`)}}let S={...process.env,...e.env,XIAOZHI_ARGUMENTS:JSON.stringify(t)},T=this.buildScriptCommand(u,p);return this.logger.debug(`[CustomMCP] \u6267\u884C\u811A\u672C\u547D\u4EE4: ${T.join(" ")}`),new Promise((y,I)=>{let k=r(T[0],T.slice(1),{env:S,stdio:["pipe","pipe","pipe"]}),ye="",be="";k.stdout?.on("data",E=>{ye+=E.toString()}),k.stderr?.on("data",E=>{be+=E.toString()});let we=setTimeout(()=>{k.kill("SIGTERM"),I(new Error(`\u811A\u672C\u6267\u884C\u8D85\u65F6 (${g}ms)`))},g);k.on("close",E=>{clearTimeout(we),E===0?y(ye.trim()):I(new Error(`\u811A\u672C\u6267\u884C\u5931\u8D25 (\u9000\u51FA\u7801: ${E}): ${be.trim()}`))}),k.on("error",E=>{clearTimeout(we),I(new Error(`\u811A\u672C\u6267\u884C\u9519\u8BEF: ${E.message}`))}),t&&Object.keys(t).length>0&&(k.stdin?.write(JSON.stringify(t)),k.stdin?.end())})}finally{if(h&&p)try{await s.unlink(p),await s.rmdir(i.dirname(p))}catch{}}}getScriptExtension(e){switch(e){case"node":return".js";case"python":return".py";case"bash":return".sh";default:return".txt"}}buildScriptCommand(e,t){switch(e){case"node":return["node",t];case"python":return["python3",t];case"bash":return["bash",t];default:throw new Error(`\u4E0D\u652F\u6301\u7684\u811A\u672C\u89E3\u91CA\u5668: ${e}`)}}async callChainTool(e,t){let r=e.handler;this.logger.info(`[CustomMCP] \u8C03\u7528\u94FE\u5F0F\u5DE5\u5177: ${e.name}`,{tools:r.tools,mode:r.mode,error_handling:r.error_handling});try{let n;r.mode==="sequential"?n=await this.executeSequentialChain(r,t):n=await this.executeParallelChain(r,t);let s=n.flatMap(a=>a.content),i=n.some(a=>a.isError);return{content:s,isError:i}}catch(n){return this.logger.error(`[CustomMCP] \u94FE\u5F0F\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${e.name}`,n),{content:[{type:"text",text:`\u94FE\u5F0F\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`}],isError:!0}}}delay(e){return new Promise(t=>setTimeout(t,e))}getToolInfo(e){return this.tools.get(e)}async executeSequentialChain(e,t){let r=[],n=t;for(let s of e.tools)try{this.logger.debug(`[CustomMCP] \u6267\u884C\u94FE\u5F0F\u5DE5\u5177\u4E2D\u7684: ${s}`);let i=await this.callToolRecursive(s,n);if(r.push(i),i.isError){if(e.error_handling==="stop")break;if(e.error_handling==="retry"){this.logger.warn(`[CustomMCP] \u5DE5\u5177 ${s} \u6267\u884C\u5931\u8D25\uFF0C\u5C1D\u8BD5\u91CD\u8BD5`);let a=await this.callToolRecursive(s,n);if(r[r.length-1]=a,a.isError)break}}if(!i.isError&&i.content.length>0){let a=i.content.filter(g=>g.type==="text").map(g=>g.text).join(`
36
- `);if(a)try{n=JSON.parse(a)}catch{n={input:a,...t}}}}catch(i){let a={content:[{type:"text",text:`\u5DE5\u5177 ${s} \u6267\u884C\u5F02\u5E38: ${i instanceof Error?i.message:String(i)}`}],isError:!0};if(r.push(a),e.error_handling==="stop")break}return r}async executeParallelChain(e,t){let r=e.tools.map(async n=>{try{return this.logger.debug(`[CustomMCP] \u5E76\u884C\u6267\u884C\u94FE\u5F0F\u5DE5\u5177\u4E2D\u7684: ${n}`),await this.callToolRecursive(n,t)}catch(s){return{content:[{type:"text",text:`\u5DE5\u5177 ${n} \u6267\u884C\u5F02\u5E38: ${s instanceof Error?s.message:String(s)}`}],isError:!0}}});return Promise.all(r)}async callToolRecursive(e,t){if(this.tools.get(e))return this.callTool(e,t);throw new Error(`\u94FE\u5F0F\u5DE5\u5177\u4E2D\u5F15\u7528\u7684\u5DE5\u5177 ${e} \u4E0D\u5B58\u5728\u4E8E\u5F53\u524D CustomMCP \u5DE5\u5177\u96C6\u4E2D`)}async clearConsumedCache(e,t){try{let r=this.generateCacheKey(e,t),n=await this.loadExtendedCache();if(n.customMCPResults?.[r]){n.customMCPResults[r].consumed=!0;let s=n.customMCPResults[r];D(s)&&delete n.customMCPResults[r],await this.saveCache(n),this.logger.debug(`[CustomMCP] \u6E05\u7406\u5DF2\u6D88\u8D39\u7F13\u5B58: ${r}`)}}catch(r){this.logger.warn(`[CustomMCP] \u6E05\u7406\u7F13\u5B58\u5931\u8D25: ${r}`)}}async generateTaskId(e,t){return this.taskStateManager.generateTaskId(e,t)}async markTaskAsPending(e,t,r){try{let n=this.generateCacheKey(t,r),s={result:{content:[{type:"text",text:"\u5904\u7406\u4E2D..."}]},timestamp:new Date().toISOString(),ttl:this.CACHE_TTL,status:"pending",consumed:!1,taskId:e,retryCount:0};await this.updateCacheWithResult(n,s),this.taskStateManager.markTaskAsPending(e,t,r),this.activeTasks.set(e,{taskId:e,status:"pending",startTime:Date.now()}),this.logger.debug(`[CustomMCP] \u6807\u8BB0\u4EFB\u52A1\u4E3A\u5904\u7406\u4E2D: ${e}`)}catch(n){this.logger.warn(`[CustomMCP] \u6807\u8BB0\u4EFB\u52A1\u72B6\u6001\u5931\u8D25: ${n}`)}}async markTaskAsCompleted(e,t){try{let r=this.activeTasks.get(e);r&&(r.status="completed",r.endTime=new Date().toISOString(),r.result=t);let n=await this.loadExtendedCache();for(let[s,i]of Object.entries(n.customMCPResults||{}))if(i.taskId===e){i.status="completed",i.result=t,i.timestamp=new Date().toISOString(),i.consumed=!1;break}await this.saveCache(n),this.taskStateManager.markTaskAsCompleted(e,t),this.logger.debug(`[CustomMCP] \u6807\u8BB0\u4EFB\u52A1\u4E3A\u5DF2\u5B8C\u6210: ${e}`)}catch(r){this.logger.warn(`[CustomMCP] \u66F4\u65B0\u4EFB\u52A1\u72B6\u6001\u5931\u8D25: ${r}`)}}async markTaskAsFailed(e,t){try{let r=await this.loadExtendedCache();for(let[s,i]of Object.entries(r.customMCPResults||{}))if(i.taskId===e){i.status="failed",i.result={content:[{type:"text",text:`\u4EFB\u52A1\u5931\u8D25: ${t.message}`}]},i.timestamp=new Date().toISOString(),i.consumed=!0;break}await this.saveCache(r),this.taskStateManager.markTaskAsFailed(e,t.message);let n=this.activeTasks.get(e);n&&(n.status="failed",n.endTime=new Date().toISOString(),n.error=t.message),this.logger.debug(`[CustomMCP] \u6807\u8BB0\u4EFB\u52A1\u4E3A\u5931\u8D25: ${e}`)}catch(r){this.logger.warn(`[CustomMCP] \u66F4\u65B0\u4EFB\u52A1\u72B6\u6001\u5931\u8D25: ${r}`)}}startCleanupTimer(){this.cleanupTimer=setInterval(()=>{this.cleanupExpiredCache().catch(e=>{this.logger.warn(`[CustomMCP] \u7F13\u5B58\u6E05\u7406\u5931\u8D25: ${e}`)})},this.CLEANUP_INTERVAL),this.logger.debug(`[CustomMCP] \u542F\u52A8\u7F13\u5B58\u6E05\u7406\u5B9A\u65F6\u5668\uFF0C\u95F4\u9694: ${this.CLEANUP_INTERVAL}ms`)}async cleanupExpiredCache(){try{let e=await this.loadExtendedCache(),t=!1,r=0;for(let[n,s]of Object.entries(e.customMCPResults||{}))D(s)&&(e.customMCPResults?.[n]&&delete e.customMCPResults[n],t=!0,r++,s.taskId&&this.activeTasks.delete(s.taskId));t&&(await this.saveCache(e),this.logger.debug(`[CustomMCP] \u6E05\u7406\u8FC7\u671F\u7F13\u5B58\u5B8C\u6210\uFF0C\u6E05\u7406\u4E86 ${r} \u4E2A\u6761\u76EE`))}catch(e){this.logger.warn(`[CustomMCP] \u6E05\u7406\u8FC7\u671F\u7F13\u5B58\u5931\u8D25: ${e}`)}}generateCacheKey(e,t){return $(e,t)}async loadExtendedCache(){try{return await this.cacheManager.loadExistingCache()}catch{return{version:"1.0.0",mcpServers:{},metadata:{lastGlobalUpdate:new Date().toISOString(),totalWrites:0,createdAt:new Date().toISOString()},customMCPResults:{}}}}async updateCacheWithResult(e,t){try{let r=await this.loadExtendedCache();r.customMCPResults||(r.customMCPResults={}),r.customMCPResults[e]=t,await this.saveCache(r)}catch(r){this.logger.warn(`[CustomMCP] \u66F4\u65B0\u7F13\u5B58\u5931\u8D25: ${r}`)}}async cacheResult(e,t,r){try{let n=this.generateCacheKey(e,t),s={result:r,timestamp:new Date().toISOString(),ttl:this.CACHE_TTL,status:"completed",consumed:!1,retryCount:0};await this.updateCacheWithResult(n,s),this.logger.debug(`[CustomMCP] \u7F13\u5B58\u5DE5\u5177\u7ED3\u679C: ${e}`)}catch(n){this.logger.warn(`[CustomMCP] \u7F13\u5B58\u7ED3\u679C\u5931\u8D25: ${n}`)}}async saveCache(e){try{await this.cacheManager.saveCache(e)}catch(t){this.logger.warn(`[CustomMCP] \u4FDD\u5B58\u7F13\u5B58\u5931\u8D25: ${t}`)}}stopCleanupTimer(){this.cleanupTimer&&(clearInterval(this.cleanupTimer),this.cleanupTimer=void 0,this.logger.info("[CustomMCP] \u505C\u6B62\u7F13\u5B58\u6E05\u7406\u5B9A\u65F6\u5668"))}cleanup(){this.logger.info("[CustomMCP] \u6E05\u7406 CustomMCP \u5904\u7406\u5668\u8D44\u6E90"),this.stopCleanupTimer(),this.cacheLifecycleManager.stopAutoCleanup(),this.cacheLifecycleManager.cleanup(),this.taskStateManager.cleanup(),this.cacheManager.cleanup(),this.tools.clear(),this.activeTasks.clear()}getCacheLifecycleManager(){return this.cacheLifecycleManager}getTaskStateManager(){return this.taskStateManager}async getCacheStatistics(){return this.cacheManager.getCustomMCPStatistics()}getTaskStatistics(){return this.taskStateManager.getTaskStatistics()}getTaskStatus(e){return this.taskStateManager.getTaskStatus(e)}validateTaskId(e){return this.taskStateManager.validateTaskId(e)}restartStalledTasks(e=3e4){return this.taskStateManager.restartStalledTasks(e)}async manualCleanupCache(){return this.cacheManager.cleanupCustomMCPResults()}async validateSystemIntegrity(){let e=await this.cacheManager.loadExtendedCache(),t=this.cacheLifecycleManager.validateCacheIntegrity(e),r=this.taskStateManager.validateTaskIntegrity();return{cacheValid:t.isValid,taskValid:r.isValid,issues:[...t.issues,...r.issues]}}};import{Client as Et}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as pt}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as mt}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as dt}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{EventSource as ft}from"eventsource";typeof global<"u"&&!global.EventSource&&(global.EventSource=ft);function Ct(){return c}l(Ct,"getLogger");function vt(o){switch(Ct().debug(`[TransportFactory] \u521B\u5EFA ${o.type} transport for ${o.name}`),o.type){case"stdio":return St(o);case"sse":return Tt(o);case"streamable-http":return Mt(o);default:throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${o.type}`)}}l(vt,"createTransport");function St(o){if(!o.command)throw new Error("stdio transport \u9700\u8981 command \u914D\u7F6E");return new mt({command:o.command,args:o.args||[],env:o.env})}l(St,"createStdioTransport");function Tt(o){if(!o.url)throw new Error("SSE transport \u9700\u8981 URL \u914D\u7F6E");let e=new URL(o.url),t=Pt(o);return new pt(e,t)}l(Tt,"createSSETransport");function Mt(o){if(!o.url)throw new Error("StreamableHTTP transport \u9700\u8981 URL \u914D\u7F6E");let e=new URL(o.url),t=yt(o);return new dt(e,t)}l(Mt,"createStreamableHTTPTransport");function Pt(o){let e={};return o.apiKey?e.headers={Authorization:`Bearer ${o.apiKey}`,...o.headers}:o.headers&&(e.headers=o.headers),e}l(Pt,"createSSEOptions");function yt(o){let e={};return o.apiKey?e.headers={Authorization:`Bearer ${o.apiKey}`,...o.headers}:o.headers&&(e.headers=o.headers),e}l(yt,"createStreamableHTTPOptions");function bt(o){if(!o.name||typeof o.name!="string")throw new Error("\u914D\u7F6E\u5FC5\u987B\u5305\u542B\u6709\u6548\u7684 name \u5B57\u6BB5");if(o.type&&!Object.values(re).includes(o.type))throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${o.type}`);if(!o.type)throw new Error("\u4F20\u8F93\u7C7B\u578B\u672A\u8BBE\u7F6E\uFF0C\u8FD9\u5E94\u8BE5\u5728 inferTransportType \u4E2D\u5904\u7406");switch(o.type){case"stdio":if(!o.command)throw new Error("stdio \u7C7B\u578B\u9700\u8981 command \u5B57\u6BB5");break;case"sse":if(o.url===void 0||o.url===null)throw new Error(`${o.type} \u7C7B\u578B\u9700\u8981 url \u5B57\u6BB5`);break;case"streamable-http":if(o.url===void 0||o.url===null)throw new Error(`${o.type} \u7C7B\u578B\u9700\u8981 url \u5B57\u6BB5`);break;default:throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${o.type}`)}}l(bt,"validateConfig");function wt(){return["stdio","sse","streamable-http"]}l(wt,"getSupportedTypes");var Te={create:vt,validateConfig:bt,getSupportedTypes:wt};var re=(r=>(r.STDIO="stdio",r.SSE="sse",r.STREAMABLE_HTTP="streamable-http",r))(re||{});var ne=class{static{l(this,"MCPService")}config;client=null;transport=null;tools=new Map;connectionState="disconnected";reconnectOptions;reconnectState;logger;connectionTimeout=null;initialized=!1;eventBus=b();pingOptions;pingTimer=null;pingFailureCount=0;lastPingTime=null;isPinging=!1;constructor(e,t){this.logger=c;let r=this.inferTransportType(e);this.config=r,this.validateConfig(),this.reconnectOptions={enabled:!0,maxAttempts:10,initialInterval:3e3,maxInterval:3e4,backoffStrategy:"exponential",backoffMultiplier:1.5,timeout:1e4,jitter:!0,...t?.reconnect,...e.reconnect},this.pingOptions={enabled:!0,interval:3e4,timeout:5e3,maxFailures:3,startDelay:5e3,...e.ping},this.reconnectState={attempts:0,nextInterval:this.reconnectOptions.initialInterval,timer:null,lastError:null,isManualDisconnect:!1}}logWithTag(e,t,...r){let n=`[MCP-${this.config.name}] ${t}`;this.logger[e](n,...r)}inferTransportType(e){if(e.type)return e;this.logger.debug(`[MCP-${e.name}] \u81EA\u52A8\u63A8\u65AD\u4F20\u8F93\u7C7B\u578B...`);let t;if(e.command)t="stdio",this.logger.debug(`[MCP-${e.name}] \u68C0\u6D4B\u5230 command \u5B57\u6BB5\uFF0C\u63A8\u65AD\u4E3A stdio \u7C7B\u578B`);else if(e.url!==void 0&&e.url!==null)t=this.inferTransportTypeFromUrl(e.url,e.name);else throw new Error(`\u65E0\u6CD5\u4E3A\u670D\u52A1 ${e.name} \u63A8\u65AD\u4F20\u8F93\u7C7B\u578B\u3002\u8BF7\u663E\u5F0F\u6307\u5B9A type \u5B57\u6BB5\uFF0C\u6216\u63D0\u4F9B command/url \u914D\u7F6E`);return{type:t,...e}}inferTransportTypeFromUrl(e,t){try{let n=new URL(e).pathname;return n.endsWith("/sse")?(this.logger.info(`[MCP-${t}] \u68C0\u6D4B\u5230 URL \u8DEF\u5F84\u4EE5 /sse \u7ED3\u5C3E\uFF0C\u63A8\u65AD\u4E3A sse \u7C7B\u578B`),"sse"):n.endsWith("/mcp")?(this.logger.info(`[MCP-${t}] \u68C0\u6D4B\u5230 URL \u8DEF\u5F84\u4EE5 /mcp \u7ED3\u5C3E\uFF0C\u63A8\u65AD\u4E3A streamable-http \u7C7B\u578B`),"streamable-http"):(this.logger.info(`[MCP-${t}] URL \u8DEF\u5F84 ${n} \u4E0D\u5339\u914D\u7279\u5B9A\u89C4\u5219\uFF0C\u9ED8\u8BA4\u63A8\u65AD\u4E3A streamable-http \u7C7B\u578B`),"streamable-http")}catch(r){return this.logger.warn(`[MCP-${t}] URL \u89E3\u6790\u5931\u8D25\uFF0C\u9ED8\u8BA4\u63A8\u65AD\u4E3A streamable-http \u7C7B\u578B`,r),"streamable-http"}}validateConfig(){Te.validateConfig(this.config)}async connect(){if(this.connectionState==="connecting")throw new Error("\u8FDE\u63A5\u6B63\u5728\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u8FDE\u63A5\u5B8C\u6210");return this.cleanupConnection(),this.reconnectState.isManualDisconnect=!1,this.attemptConnection()}async attemptConnection(){return this.connectionState="connecting",this.logWithTag("debug",`\u6B63\u5728\u8FDE\u63A5 MCP \u670D\u52A1: ${this.config.name} (\u5C1D\u8BD5 ${this.reconnectState.attempts+1}/${this.reconnectOptions.maxAttempts})`),new Promise((e,t)=>{this.connectionTimeout=setTimeout(()=>{let r=new Error(`\u8FDE\u63A5\u8D85\u65F6 (${this.reconnectOptions.timeout}ms)`);this.handleConnectionError(r),t(r)},this.reconnectOptions.timeout);try{this.client=new Et({name:`xiaozhi-${this.config.name}-client`,version:"1.0.0"},{capabilities:{tools:{}}}),this.transport=Te.create(this.config),this.client.connect(this.transport).then(async()=>{this.handleConnectionSuccess(),await this.refreshTools(),this.eventBus.emitEvent("mcp:service:connected",{serviceName:this.config.name,tools:this.getTools(),connectionTime:new Date}),e()}).catch(r=>{this.handleConnectionError(r),t(r)})}catch(r){this.handleConnectionError(r),t(r)}})}handleConnectionSuccess(){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.connectionState="connected",this.initialized=!0,this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.lastError=null,this.resetPingState(),this.logWithTag("info",`MCP \u670D\u52A1 ${this.config.name} \u8FDE\u63A5\u5DF2\u5EFA\u7ACB`),this.startPingMonitoring()}handleConnectionError(e){this.connectionState="disconnected",this.initialized=!1,this.reconnectState.lastError=e,this.logger.debug(`MCP \u670D\u52A1 ${this.config.name} \u8FDE\u63A5\u9519\u8BEF:`,e.message),this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.cleanupConnection(),this.eventBus.emitEvent("mcp:service:connection:failed",{serviceName:this.config.name,error:e,attempt:this.reconnectState.attempts}),this.shouldReconnect()?this.scheduleReconnect():(this.connectionState="failed",this.logger.warn(`${this.config.name} \u5DF2\u8FBE\u5230\u6700\u5927\u91CD\u8FDE\u6B21\u6570 (${this.reconnectOptions.maxAttempts})\uFF0C\u505C\u6B62\u91CD\u8FDE`))}shouldReconnect(){return this.reconnectOptions.enabled&&this.reconnectState.attempts<this.reconnectOptions.maxAttempts&&!this.reconnectState.isManualDisconnect}scheduleReconnect(){this.connectionState="reconnecting",this.reconnectState.attempts++,this.calculateNextInterval(),this.logger.debug(`${this.config.name} \u5C06\u5728 ${this.reconnectState.nextInterval}ms \u540E\u8FDB\u884C\u7B2C ${this.reconnectState.attempts} \u6B21\u91CD\u8FDE`),this.reconnectState.timer&&clearTimeout(this.reconnectState.timer),this.reconnectState.timer=setTimeout(async()=>{try{await this.attemptConnection()}catch{}},this.reconnectState.nextInterval)}calculateNextInterval(){let e;switch(this.reconnectOptions.backoffStrategy){case"fixed":e=this.reconnectOptions.initialInterval;break;case"linear":e=this.reconnectOptions.initialInterval+this.reconnectState.attempts*this.reconnectOptions.backoffMultiplier*1e3;break;case"exponential":e=this.reconnectOptions.initialInterval*this.reconnectOptions.backoffMultiplier**(this.reconnectState.attempts-1);break;default:e=this.reconnectOptions.initialInterval}if(e=Math.min(e,this.reconnectOptions.maxInterval),this.reconnectOptions.jitter){let t=e*.1,r=(Math.random()-.5)*2*t;e+=r}this.reconnectState.nextInterval=Math.max(e,1e3)}cleanupConnection(){if(this.stopPingMonitoring(),this.client){try{this.client.close().catch(()=>{})}catch{}this.client=null}this.transport=null,this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.initialized=!1}stopReconnect(){this.reconnectState.timer&&(clearTimeout(this.reconnectState.timer),this.reconnectState.timer=null)}async refreshTools(){if(!this.client)throw new Error("\u5BA2\u6237\u7AEF\u672A\u521D\u59CB\u5316");try{let t=(await this.client.listTools()).tools||[];this.tools.clear();for(let r of t)this.tools.set(r.name,r);this.logger.debug(`${this.config.name} \u670D\u52A1\u52A0\u8F7D\u4E86 ${t.length} \u4E2A\u5DE5\u5177: ${t.map(r=>r.name).join(", ")}`)}catch(e){throw this.logger.error(`${this.config.name} \u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25:`,e instanceof Error?e.message:String(e)),e}}async disconnect(){this.logger.info(`\u4E3B\u52A8\u65AD\u5F00 MCP \u670D\u52A1 ${this.config.name} \u8FDE\u63A5`),this.reconnectState.isManualDisconnect=!0,this.stopPingMonitoring(),this.stopReconnect(),this.cleanupConnection(),this.connectionState="disconnected",this.eventBus.emitEvent("mcp:service:disconnected",{serviceName:this.config.name,reason:"\u624B\u52A8\u65AD\u5F00",disconnectionTime:new Date})}async reconnect(){this.logger.info(`\u624B\u52A8\u91CD\u8FDE MCP \u670D\u52A1 ${this.config.name}`),this.stopReconnect(),this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.isManualDisconnect=!1,this.cleanupConnection(),await this.connect()}getTools(){return Array.from(this.tools.values())}async callTool(e,t){if(!this.client)throw new Error(`\u670D\u52A1 ${this.config.name} \u672A\u8FDE\u63A5`);if(!this.tools.has(e))throw new Error(`\u5DE5\u5177 ${e} \u5728\u670D\u52A1 ${this.config.name} \u4E2D\u4E0D\u5B58\u5728`);this.logger.debug(`\u8C03\u7528 ${this.config.name} \u670D\u52A1\u7684\u5DE5\u5177 ${e}\uFF0C\u53C2\u6570:`,JSON.stringify(t));try{let r=await this.client.callTool({name:e,arguments:t||{}});return this.logger.debug(`\u5DE5\u5177 ${e} \u8C03\u7528\u6210\u529F\uFF0C\u7ED3\u679C:`,`${JSON.stringify(r).substring(0,500)}...`),r}catch(r){throw this.logger.error(`\u5DE5\u5177 ${e} \u8C03\u7528\u5931\u8D25:`,r instanceof Error?r.message:String(r)),r}}getConfig(){return this.config}getStatus(){return{name:this.config.name,connected:this.connectionState==="connected",initialized:this.initialized,transportType:this.config.type,toolCount:this.tools.size,lastError:this.reconnectState.lastError?.message,reconnectAttempts:this.reconnectState.attempts,connectionState:this.connectionState,pingEnabled:this.pingOptions.enabled,lastPingTime:this.lastPingTime||void 0,pingFailureCount:this.pingFailureCount,isPinging:this.isPinging}}isConnected(){return this.connectionState==="connected"&&this.initialized}enableReconnect(){this.reconnectOptions.enabled=!0,this.logger.info(`${this.config.name} \u81EA\u52A8\u91CD\u8FDE\u5DF2\u542F\u7528`)}disableReconnect(){this.reconnectOptions.enabled=!1,this.stopReconnect(),this.logger.info(`${this.config.name} \u81EA\u52A8\u91CD\u8FDE\u5DF2\u7981\u7528`)}updateReconnectOptions(e){this.reconnectOptions={...this.reconnectOptions,...e},this.logger.info(`${this.config.name} \u91CD\u8FDE\u914D\u7F6E\u5DF2\u66F4\u65B0`,e)}getReconnectOptions(){return{...this.reconnectOptions}}resetReconnectState(){this.stopReconnect(),this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.lastError=null,this.logger.info(`${this.config.name} \u91CD\u8FDE\u72B6\u6001\u5DF2\u91CD\u7F6E`)}startPingMonitoring(){!this.pingOptions.enabled||this.pingTimer||!this.isConnected()||(this.logger.debug(`${this.config.name} \u542F\u52A8ping\u76D1\u63A7\uFF0C\u95F4\u9694: ${this.pingOptions.interval}ms`),setTimeout(()=>{this.isConnected()&&!this.pingTimer&&(this.pingTimer=setInterval(()=>{this.performPing()},this.pingOptions.interval))},this.pingOptions.startDelay))}stopPingMonitoring(){this.pingTimer&&(clearInterval(this.pingTimer),this.pingTimer=null,this.logger.debug(`${this.config.name} \u505C\u6B62ping\u76D1\u63A7`))}async performPing(){if(!this.client||this.isPinging||!this.isConnected())return;this.isPinging=!0;let e=performance.now();try{this.logger.debug(`${this.config.name} \u53D1\u9001ping\u8BF7\u6C42\uFF08\u901A\u8FC7listTools\u68C0\u6D4B\u8FDE\u63A5\uFF09`);let t=this.client.listTools(),r=new Promise((s,i)=>{setTimeout(()=>{i(new Error(`Ping\u8D85\u65F6 (${this.pingOptions.timeout}ms)`))},this.pingOptions.timeout)});await Promise.race([t,r]);let n=performance.now()-e;this.handlePingSuccess(n)}catch(t){let r=performance.now()-e;this.handlePingFailure(t,r)}finally{this.isPinging=!1}}handlePingSuccess(e){this.pingFailureCount=0,this.lastPingTime=new Date,this.logger.debug(`${this.config.name} ping\u6210\u529F\uFF0C\u5EF6\u8FDF: ${e.toFixed(2)}ms`)}handlePingFailure(e,t){if(this.pingFailureCount++,this.logger.warn(`${this.config.name} ping\u5931\u8D25 (${this.pingFailureCount}/${this.pingOptions.maxFailures})\uFF0C\u5EF6\u8FDF: ${t.toFixed(2)}ms\uFF0C\u9519\u8BEF: ${e.message}`),this.pingFailureCount>=this.pingOptions.maxFailures){this.logger.error(`${this.config.name} \u8FDE\u7EEDping\u5931\u8D25\u8FBE\u5230\u9608\u503C\uFF0C\u89E6\u53D1\u91CD\u8FDE\u673A\u5236`),this.stopPingMonitoring();let r=new Error(`Ping\u68C0\u6D4B\u5931\u8D25\uFF0C\u8FDE\u7EED\u5931\u8D25${this.pingFailureCount}\u6B21\uFF0C\u8FDE\u63A5\u53EF\u80FD\u5DF2\u65AD\u5F00`);this.handleConnectionError(r)}}resetPingState(){this.pingFailureCount=0,this.lastPingTime=null,this.isPinging=!1}enablePing(){this.pingOptions.enabled=!0,this.logger.info(`${this.config.name} ping\u76D1\u63A7\u5DF2\u542F\u7528`),this.isConnected()&&this.startPingMonitoring()}disablePing(){this.pingOptions.enabled=!1,this.stopPingMonitoring(),this.logger.info(`${this.config.name} ping\u76D1\u63A7\u5DF2\u7981\u7528`)}updatePingOptions(e){let t=this.pingOptions.enabled;this.pingOptions={...this.pingOptions,...e},this.logger.info(`${this.config.name} ping\u914D\u7F6E\u5DF2\u66F4\u65B0`,e),t!==this.pingOptions.enabled&&(this.pingOptions.enabled&&this.isConnected()?this.startPingMonitoring():this.pingOptions.enabled||this.stopPingMonitoring())}getPingOptions(){return{...this.pingOptions}}};var se=class{static{l(this,"ToolSyncManager")}configManager;logger;syncLocks=new Map;eventBus=b();constructor(e,t=c){this.configManager=e,this.logger=t.withTag("ToolSync"),this.setupEventListeners()}setupEventListeners(){this.eventBus.onEvent("config:updated",async e=>{await this.handleConfigUpdated(e)}),this.eventBus.onEvent("mcp:server:added",async e=>{await this.handleMCPServerAdded(e)}),this.eventBus.onEvent("mcp:server:removed",async e=>{await this.handleMCPServerRemoved(e)})}async handleConfigUpdated(e){this.logger.debug("\u68C0\u6D4B\u5230\u914D\u7F6E\u66F4\u65B0\uFF0C\u68C0\u67E5\u5DE5\u5177\u540C\u6B65\u72B6\u6001");try{e.type==="customMCP"?this.logger.debug("customMCP\u914D\u7F6E\u5DF2\u66F4\u65B0\uFF0CCustomMCPHandler\u5C06\u81EA\u52A8\u5904\u7406"):e.type==="serverTools"&&e.serviceName?await this.handleServerToolsConfigUpdated(e.serviceName):await this.handleGeneralConfigUpdated()}catch(t){this.logger.error("\u914D\u7F6E\u66F4\u65B0\u540E\u7684\u5DE5\u5177\u540C\u6B65\u5931\u8D25:",t)}}async handleServerToolsConfigUpdated(e){this.logger.debug(`\u5904\u7406\u670D\u52A1 ${e} \u7684serverTools\u914D\u7F6E\u66F4\u65B0`);try{this.eventBus.emitEvent("tool-sync:server-tools-updated",{serviceName:e,timestamp:new Date})}catch(t){this.logger.error(`\u5904\u7406\u670D\u52A1 ${e} \u914D\u7F6E\u66F4\u65B0\u5931\u8D25:`,t)}}async handleGeneralConfigUpdated(){this.logger.info("\u5904\u7406\u901A\u7528\u914D\u7F6E\u66F4\u65B0\uFF0C\u68C0\u67E5\u6240\u6709\u670D\u52A1\u540C\u6B65\u72B6\u6001");try{this.eventBus.emitEvent("tool-sync:general-config-updated",{timestamp:new Date})}catch(e){this.logger.error("\u5904\u7406\u901A\u7528\u914D\u7F6E\u66F4\u65B0\u5931\u8D25:",e)}}async handleMCPServerAdded(e){this.logger.info(`\u5904\u7406MCP\u670D\u52A1\u6DFB\u52A0\u4E8B\u4EF6: ${e.serverName}`);try{setTimeout(async()=>{await this.triggerServiceToolSync(e.serverName)},1e3)}catch(t){this.logger.error(`\u5904\u7406\u670D\u52A1 ${e.serverName} \u6DFB\u52A0\u4E8B\u4EF6\u5931\u8D25:`,t)}}async triggerServiceToolSync(e){this.logger.info(`\u89E6\u53D1\u670D\u52A1 ${e} \u7684\u5DE5\u5177\u540C\u6B65`);try{this.eventBus.emitEvent("tool-sync:request-service-tools",{serviceName:e,timestamp:new Date})}catch(t){this.logger.error(`\u89E6\u53D1\u670D\u52A1 ${e} \u5DE5\u5177\u540C\u6B65\u5931\u8D25:`,t)}}async handleMCPServerRemoved(e){this.logger.info(`\u5904\u7406MCP\u670D\u52A1\u79FB\u9664\u4E8B\u4EF6: ${e.serverName}`);try{await this.removeServiceToolsFromCustomMCP(e.serverName,e.affectedTools)}catch(t){this.logger.error(`\u5904\u7406\u670D\u52A1 ${e.serverName} \u79FB\u9664\u4E8B\u4EF6\u5931\u8D25:`,t)}}async removeServiceToolsFromCustomMCP(e,t){this.logger.info(`\u4ECEcustomMCP\u4E2D\u79FB\u9664\u670D\u52A1 ${e} \u7684\u5DE5\u5177`);try{let r=this.configManager.getCustomMCPTools(),n=r.filter(i=>!i.name.startsWith(`${e}__`));if(n.length===r.length){this.logger.debug(`\u670D\u52A1 ${e} \u7684\u5DE5\u5177\u4E0D\u5728customMCP\u4E2D\uFF0C\u65E0\u9700\u79FB\u9664`);return}await this.configManager.updateCustomMCPTools(n);let s=r.length-n.length;this.logger.info(`\u6210\u529F\u4ECEcustomMCP\u4E2D\u79FB\u9664\u670D\u52A1 ${e} \u7684 ${s} \u4E2A\u5DE5\u5177`),this.eventBus.emitEvent("tool-sync:service-tools-removed",{serviceName:e,removedCount:s,timestamp:new Date})}catch(r){throw this.logger.error(`\u79FB\u9664\u670D\u52A1 ${e} \u5DE5\u5177\u5931\u8D25:`,r),r}}async syncToolsAfterConnection(e,t){if(this.syncLocks.has(e)){this.logger.debug(`\u670D\u52A1 ${e} \u6B63\u5728\u540C\u6B65\u4E2D\uFF0C\u8DF3\u8FC7`);return}let r=this.doSyncTools(e,t).finally(()=>{this.syncLocks.delete(e)});this.syncLocks.set(e,r),await r}async doSyncTools(e,t){try{this.logger.info(`\u5F00\u59CB\u540C\u6B65\u670D\u52A1 ${e} \u7684\u5DE5\u5177`);let r=this.configManager.getServerToolsConfig(e);if(!r){this.logger.debug(`\u670D\u52A1 ${e} \u65E0 mcpServerConfig \u914D\u7F6E\uFF0C\u8DF3\u8FC7\u540C\u6B65`);return}let n=this.getEnabledTools(r,t);if(n.length===0){this.logger.debug(`\u670D\u52A1 ${e} \u65E0\u542F\u7528\u5DE5\u5177\uFF0C\u8DF3\u8FC7\u540C\u6B65`);return}let s=this.configManager.getCustomMCPTools(),i=new Set(s.map(g=>g.name)),a=n.filter(g=>!i.has(`${e}__${g.name}`));if(a.length===0){this.logger.info(`\u670D\u52A1 ${e} \u7684\u542F\u7528\u5DE5\u5177\u5DF2\u5B58\u5728\u4E8E customMCP \u4E2D\uFF0C\u8DF3\u8FC7\u540C\u6B65`);return}await this.addToolsToCustomMCP(e,a),this.logger.info(`\u6210\u529F\u540C\u6B65\u670D\u52A1 ${e} \u7684 ${a.length} \u4E2A\u5DE5\u5177\u5230 customMCP`)}catch(r){this.logger.error(`\u540C\u6B65\u670D\u52A1 ${e} \u5DE5\u5177\u5931\u8D25:`,r),this.recordSyncError(e,r)}}getEnabledTools(e,t){let r=[];for(let n of t){let s=e[n.name];s&&s.enable!==!1&&r.push(n)}return r}async addToolsToCustomMCP(e,t){let r=t.map(n=>({name:`${e}__${n.name}`,description:n.description||"",inputSchema:n.inputSchema||{},handler:{type:"mcp",config:{serviceName:e,toolName:n.name}}}));await this.configManager.addCustomMCPTools(r),await this.syncToolStats(e,t)}recordSyncError(e,t){let r={serviceName:e,error:t instanceof Error?t.message:String(t),timestamp:new Date().toISOString(),type:t instanceof Error?t.constructor.name:"UnknownError"};this.logger.error("\u540C\u6B65\u9519\u8BEF\u8BB0\u5F55:",r)}getSyncLocks(){return Array.from(this.syncLocks.keys())}clearSyncLocks(){this.syncLocks.clear(),this.logger.debug("\u5DF2\u6E05\u7406\u6240\u6709\u540C\u6B65\u9501")}async syncToolStats(e,t){try{let r=this.configManager.getServerToolsConfig(e);if(!r){this.logger.debug(`\u670D\u52A1 ${e} \u65E0 mcpServerConfig \u914D\u7F6E\uFF0C\u8DF3\u8FC7\u7EDF\u8BA1\u4FE1\u606F\u540C\u6B65`);return}let n=this.configManager.getCustomMCPTools(),s=new Map(n.map(i=>[i.name,i]));for(let i of t){let a=`${e}__${i.name}`,g=s.get(a),u=r[i.name];if(g&&u&&(!g.stats||!g.stats.usageCount&&!g.stats.lastUsedTime)){let p={};u.usageCount!==void 0&&(p.usageCount=u.usageCount),u.lastUsedTime&&(p.lastUsedTime=u.lastUsedTime),Object.keys(p).length>0&&(await this.updateCustomMCPToolStats(a,p),this.logger.debug(`\u5DF2\u540C\u6B65\u5DE5\u5177 ${a} \u7684\u7EDF\u8BA1\u4FE1\u606F: ${JSON.stringify(p)}`))}}}catch(r){this.logger.error(`\u540C\u6B65\u670D\u52A1 ${e} \u5DE5\u5177\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25:`,r instanceof Error?r.message:String(r))}}async updateCustomMCPToolStats(e,t){try{let r=this.configManager.getCustomMCPTools(),n=r.findIndex(a=>a.name===e);if(n===-1){this.logger.warn(`\u5DE5\u5177 ${e} \u4E0D\u5B58\u5728\u4E8E customMCP \u4E2D`);return}let s=[...r],i=s[n];i.stats||(i.stats={}),t.usageCount!==void 0&&(i.stats.usageCount=t.usageCount),t.lastUsedTime!==void 0&&(i.stats.lastUsedTime=t.lastUsedTime),await this.configManager.updateCustomMCPTools(s)}catch(r){throw this.logger.error(`\u66F4\u65B0\u5DE5\u5177 ${e} \u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25:`,r instanceof Error?r.message:String(r)),r}}};var ie=class{static{l(this,"MCPServiceManager")}services=new Map;configs={};logger;tools=new Map;customMCPHandler;cacheManager;toolSyncManager;eventBus=b();toolCallLogger;retryTimers=new Map;failedServices=new Set;constructor(e){this.logger=c,this.configs=e||{};let r=process.env.NODE_ENV==="test"||process.env.VITEST==="true"?`/tmp/xiaozhi-test-${Date.now()}-${Math.random().toString(36).substring(2,11)}/xiaozhi.cache.json`:void 0;this.cacheManager=new U(r),this.customMCPHandler=new te,this.toolSyncManager=new se(f,this.logger);let n=f.getToolCallLogConfig(),s=f.getConfigDir();this.toolCallLogger=new X(n,s),this.setupEventListeners()}setupEventListeners(){this.eventBus.onEvent("mcp:service:connected",async e=>{await this.handleServiceConnected(e)}),this.eventBus.onEvent("mcp:service:disconnected",async e=>{await this.handleServiceDisconnected(e)}),this.eventBus.onEvent("mcp:service:connection:failed",async e=>{await this.handleServiceConnectionFailed(e)}),this.eventBus.onEvent("tool-sync:server-tools-updated",async e=>{await this.handleServerToolsUpdated(e)}),this.eventBus.onEvent("tool-sync:general-config-updated",async e=>{await this.handleGeneralConfigUpdated(e)})}async handleServiceConnected(e){this.logger.debug(`\u670D\u52A1 ${e.serviceName} \u8FDE\u63A5\u6210\u529F\uFF0C\u5F00\u59CB\u5DE5\u5177\u540C\u6B65`);try{let t=this.services.get(e.serviceName);if(t){let r=t.getTools();this.toolSyncManager&&await this.toolSyncManager.syncToolsAfterConnection(e.serviceName,r),await this.refreshCustomMCPHandlerPublic(),this.logger.info(`\u670D\u52A1 ${e.serviceName} \u5DE5\u5177\u540C\u6B65\u5B8C\u6210`)}}catch(t){this.logger.error(`\u540C\u6B65\u670D\u52A1 ${e.serviceName} \u5DE5\u5177\u5931\u8D25:`,t)}}async handleServiceDisconnected(e){this.logger.info(`\u670D\u52A1 ${e.serviceName} \u65AD\u5F00\u8FDE\u63A5\uFF0C\u539F\u56E0: ${e.reason||"\u672A\u77E5"}`);try{await this.refreshToolsCache(),await this.refreshCustomMCPHandlerPublic(),this.logger.info(`\u670D\u52A1 ${e.serviceName} \u65AD\u5F00\u8FDE\u63A5\u5904\u7406\u5B8C\u6210`)}catch(t){this.logger.error(`\u670D\u52A1 ${e.serviceName} \u65AD\u5F00\u8FDE\u63A5\u5904\u7406\u5931\u8D25:`,t)}}async handleServiceConnectionFailed(e){try{await this.refreshCustomMCPHandlerPublic()}catch(t){this.logger.error("\u5237\u65B0CustomMCPHandler\u5931\u8D25:",t)}}async handleServerToolsUpdated(e){this.logger.debug(`\u5904\u7406\u670D\u52A1 ${e.serviceName} \u7684serverTools\u914D\u7F6E\u66F4\u65B0`);try{let t=this.services.get(e.serviceName);if(t?.isConnected()){let r=t.getTools();this.toolSyncManager&&await this.toolSyncManager.syncToolsAfterConnection(e.serviceName,r),await this.refreshCustomMCPHandlerPublic(),this.logger.info(`\u670D\u52A1 ${e.serviceName} \u914D\u7F6E\u66F4\u65B0\u540C\u6B65\u5B8C\u6210`)}}catch(t){this.logger.error(`\u5904\u7406\u670D\u52A1 ${e.serviceName} \u914D\u7F6E\u66F4\u65B0\u5931\u8D25:`,t)}}async handleGeneralConfigUpdated(e){this.logger.info("\u5904\u7406\u901A\u7528\u914D\u7F6E\u66F4\u65B0\uFF0C\u68C0\u67E5\u6240\u6709\u5DF2\u8FDE\u63A5\u670D\u52A1");try{for(let[t,r]of this.services)if(r.isConnected()){let n=r.getTools();this.toolSyncManager&&await this.toolSyncManager.syncToolsAfterConnection(t,n)}await this.refreshCustomMCPHandlerPublic(),this.logger.info("\u901A\u7528\u914D\u7F6E\u66F4\u65B0\u540C\u6B65\u5B8C\u6210")}catch(t){this.logger.error("\u5904\u7406\u901A\u7528\u914D\u7F6E\u66F4\u65B0\u5931\u8D25:",t)}}async startAllServices(){this.logger.debug("[MCPManager] \u6B63\u5728\u542F\u52A8\u6240\u6709 MCP \u670D\u52A1...");try{this.customMCPHandler.initialize(),this.logger.debug("[MCPManager] CustomMCP \u5904\u7406\u5668\u521D\u59CB\u5316\u5B8C\u6210")}catch(a){this.logger.error("[MCPManager] CustomMCP \u5904\u7406\u5668\u521D\u59CB\u5316\u5931\u8D25:",a)}let e=Object.entries(this.configs);if(e.length===0){this.logger.warn("[MCPManager] \u6CA1\u6709\u914D\u7F6E\u4EFB\u4F55 MCP \u670D\u52A1\uFF0C\u8BF7\u4F7F\u7528 addServiceConfig() \u6DFB\u52A0\u670D\u52A1\u914D\u7F6E");return}this.logger.info(`[MCPManager] \u5F00\u59CB\u5E76\u884C\u542F\u52A8 ${e.length} \u4E2A MCP \u670D\u52A1`);let t=e.map(async([a])=>{try{return await this.startService(a),{serviceName:a,success:!0,error:null}}catch(g){return{serviceName:a,success:!1,error:g instanceof Error?g.message:String(g)}}}),r=await Promise.allSettled(t),n=0,s=0,i=[];for(let a of r)a.status==="fulfilled"?a.value.success?n++:(s++,i.push(a.value.serviceName)):s++;this.logger.info(`[MCPManager] \u670D\u52A1\u542F\u52A8\u5B8C\u6210 - \u6210\u529F: ${n}, \u5931\u8D25: ${s}`),i.length>0&&(this.logger.warn(`[MCPManager] \u4EE5\u4E0B\u670D\u52A1\u542F\u52A8\u5931\u8D25: ${i.join(", ")}`),s===e.length&&this.logger.warn("[MCPManager] \u6240\u6709 MCP \u670D\u52A1\u542F\u52A8\u5931\u8D25\uFF0C\u4F46\u7CFB\u7EDF\u5C06\u7EE7\u7EED\u8FD0\u884C\u4EE5\u4FBF\u91CD\u8BD5")),i.length>0&&this.scheduleFailedServicesRetry(i)}async startService(e){let t=this.configs[e];if(!t)throw new Error(`\u672A\u627E\u5230\u670D\u52A1\u914D\u7F6E: ${e}`);try{this.services.has(e)&&await this.stopService(e);let r=new ne(t);await r.connect(),this.services.set(e,r),await this.refreshToolsCache();let n=r.getTools();this.logger.debug(`[MCPManager] ${e} \u670D\u52A1\u542F\u52A8\u6210\u529F\uFF0C\u52A0\u8F7D\u4E86 ${n.length} \u4E2A\u5DE5\u5177:`,n.map(s=>s.name).join(", "))}catch(r){throw this.logger.error(`[MCPManager] \u542F\u52A8 ${e} \u670D\u52A1\u5931\u8D25:`,r.message),this.services.delete(e),r}}async stopService(e){this.logger.info(`[MCPManager] \u505C\u6B62 MCP \u670D\u52A1: ${e}`);let t=this.services.get(e);if(!t){this.logger.warn(`[MCPManager] \u670D\u52A1 ${e} \u4E0D\u5B58\u5728\u6216\u672A\u542F\u52A8`);return}try{await t.disconnect(),this.services.delete(e),await this.refreshToolsCache(),this.logger.info(`[MCPManager] ${e} \u670D\u52A1\u5DF2\u505C\u6B62`)}catch(r){throw this.logger.error(`[MCPManager] \u505C\u6B62 ${e} \u670D\u52A1\u5931\u8D25:`,r.message),r}}async refreshToolsCache(){this.tools.clear();for(let[e,t]of this.services)if(t.isConnected()){let r=t.getTools(),n=this.configs[e];n&&this.cacheManager.writeCacheEntry(e,r,n).then(()=>{this.logger.debug(`[MCPManager] \u5DF2\u5C06 ${e} \u5DE5\u5177\u5217\u8868\u5199\u5165\u7F13\u5B58`)}).catch(s=>{this.logger.warn(`[MCPManager] \u5199\u5165\u7F13\u5B58\u5931\u8D25: ${e}, \u9519\u8BEF: ${s instanceof Error?s.message:String(s)}`)});for(let s of r){let i=`${e}__${s.name}`;this.tools.set(i,{serviceName:e,originalName:s.name,tool:s})}}await this.syncToolsConfigToFile()}getAllTools(){let e=[];for(let[r,n]of this.services)try{if(n.isConnected()){let s=n.getTools();for(let i of s)try{if(!f.isToolEnabled(r,i.name))continue;let g=`${r}__${i.name}`;e.push({name:g,description:i.description||"",inputSchema:i.inputSchema,serviceName:r,originalName:i.name})}catch(a){this.logger.warn(`[MCPManager] \u68C0\u67E5\u5DE5\u5177 ${r}.${i.name} \u542F\u7528\u72B6\u6001\u5931\u8D25\uFF0C\u8DF3\u8FC7\u8BE5\u5DE5\u5177:`,a)}}}catch(s){this.logger.warn(`[MCPManager] \u83B7\u53D6\u670D\u52A1 ${r} \u7684\u5DE5\u5177\u5931\u8D25\uFF0C\u8DF3\u8FC7\u8BE5\u670D\u52A1:`,s)}let t=[];try{t=this.customMCPHandler.getTools(),this.logger.debug(`[MCPManager] \u6210\u529F\u83B7\u53D6 ${t.length} \u4E2A customMCP \u5DE5\u5177`)}catch(r){this.logger.warn("[MCPManager] \u83B7\u53D6 CustomMCP \u5DE5\u5177\u5931\u8D25\uFF0C\u5C06\u53EA\u8FD4\u56DE\u6807\u51C6 MCP \u5DE5\u5177:",r),t=[]}for(let r of t)try{e.push({name:r.name,description:r.description||"",inputSchema:r.inputSchema,serviceName:this.getServiceNameForTool(r),originalName:r.name})}catch(n){this.logger.warn(`[MCPManager] \u5904\u7406 CustomMCP \u5DE5\u5177 ${r.name} \u5931\u8D25\uFF0C\u8DF3\u8FC7\u8BE5\u5DE5\u5177:`,n)}return this.logger.debug(`[MCPManager] \u6210\u529F\u83B7\u53D6 ${e.length} \u4E2A\u53EF\u7528\u5DE5\u5177`),e}getServiceNameForTool(e){return e.handler?.type==="mcp"?e.handler.config.serviceName:"customMCP"}getLogServerName(e){if(!e?.handler)return"custom";switch(e.handler.type){case"mcp":return e.handler.config.serviceName;case"coze":return"coze";case"dify":return"dify";case"n8n":return"n8n";default:return"custom"}}getOriginalToolName(e,t,r){return t?t.handler?.type==="mcp"?t.handler.config.toolName:e:r?.originalName||e}async callTool(e,t){let r=Date.now(),n="unknown",s=e;try{let i;if(this.customMCPHandler.hasTool(e)){let a=this.customMCPHandler.getToolInfo(e);n=this.getLogServerName(a),s=this.getOriginalToolName(e,a),a?.handler?.type==="mcp"?(i=await this.callMCPTool(e,a.handler.config,t),this.updateToolStatsSafe(e,a.handler.config.serviceName,a.handler.config.toolName,!0)):(i=await this.customMCPHandler.callTool(e,t),this.logger.info(`[MCPManager] CustomMCP \u5DE5\u5177 ${e} \u8C03\u7528\u6210\u529F`),this.updateToolStatsSafe(e,"customMCP",e,!0))}else{let a=this.tools.get(e);if(!a)throw new Error(`\u672A\u627E\u5230\u5DE5\u5177: ${e}`);n=a.serviceName,s=a.originalName;let g=this.services.get(a.serviceName);if(!g)throw new Error(`\u670D\u52A1 ${a.serviceName} \u4E0D\u53EF\u7528`);if(!g.isConnected())throw new Error(`\u670D\u52A1 ${a.serviceName} \u672A\u8FDE\u63A5`);i=await g.callTool(a.originalName,t||{}),this.logger.debug(`[MCPManager] \u5DE5\u5177 ${e} \u8C03\u7528\u6210\u529F\uFF0C\u7ED3\u679C:`,i),this.updateToolStatsSafe(e,a.serviceName,a.originalName,!0)}return this.toolCallLogger.recordToolCall({toolName:s,serverName:n,arguments:t,result:i,success:i.isError!==!0,duration:Date.now()-r}),i}catch(i){if(this.toolCallLogger.recordToolCall({toolName:s,serverName:n,arguments:t,result:null,success:!1,duration:Date.now()-r,error:i instanceof Error?i.message:String(i)}),this.customMCPHandler.hasTool(e)){let a=this.customMCPHandler.getToolInfo(e);a?.handler?.type==="mcp"?this.updateToolStatsSafe(e,a.handler.config.serviceName,a.handler.config.toolName,!1):(this.updateToolStatsSafe(e,"customMCP",e,!1),this.logger.error(`[MCPManager] CustomMCP \u5DE5\u5177 ${e} \u8C03\u7528\u5931\u8D25:`,i.message))}else{let a=this.tools.get(e);a&&(this.updateToolStatsSafe(e,a.serviceName,a.originalName,!1),this.logger.error(`[MCPManager] \u5DE5\u5177 ${e} \u8C03\u7528\u5931\u8D25:`,i.message))}throw i}}async updateToolStats(e,t,r,n){try{let s=new Date().toISOString();n?(await this.updateCustomMCPToolStats(e,s),t!=="customMCP"&&await this.updateMCPServerToolStats(t,r,s),this.logger.debug(`[MCPManager] \u5DF2\u66F4\u65B0\u5DE5\u5177 ${e} \u7684\u7EDF\u8BA1\u4FE1\u606F`)):(await this.updateCustomMCPToolLastUsedTime(e,s),t!=="customMCP"&&await this.updateMCPServerToolLastUsedTime(t,r,s),this.logger.debug(`[MCPManager] \u5DF2\u66F4\u65B0\u5DE5\u5177 ${e} \u7684\u5931\u8D25\u8C03\u7528\u7EDF\u8BA1\u4FE1\u606F`))}catch(s){throw this.logger.error(`[MCPManager] \u66F4\u65B0\u5DE5\u5177 ${e} \u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25:`,s),s}}async updateToolStatsSafe(e,t,r,n){try{await this.updateToolStats(e,t,r,n)}catch(s){let i=n?"\u7EDF\u8BA1\u4FE1\u606F":"\u5931\u8D25\u7EDF\u8BA1\u4FE1\u606F";this.logger.warn(`[MCPManager] \u66F4\u65B0\u5DE5\u5177 ${e} ${i}\u5931\u8D25:`,s)}}async updateCustomMCPToolStats(e,t){try{await f.updateToolUsageStatsWithLock(e,!0),this.logger.debug(`[MCPManager] \u5DF2\u66F4\u65B0 customMCP \u5DE5\u5177 ${e} \u4F7F\u7528\u7EDF\u8BA1`)}catch(r){throw this.logger.error(`[MCPManager] \u66F4\u65B0 customMCP \u5DE5\u5177 ${e} \u7EDF\u8BA1\u5931\u8D25:`,r),r}}async updateCustomMCPToolLastUsedTime(e,t){try{await f.updateToolUsageStatsWithLock(e,!1),this.logger.debug(`[MCPManager] \u5DF2\u66F4\u65B0 customMCP \u5DE5\u5177 ${e} \u6700\u540E\u4F7F\u7528\u65F6\u95F4`)}catch(r){throw this.logger.error(`[MCPManager] \u66F4\u65B0 customMCP \u5DE5\u5177 ${e} \u6700\u540E\u4F7F\u7528\u65F6\u95F4\u5931\u8D25:`,r),r}}async updateMCPServerToolStats(e,t,r){try{await f.updateMCPServerToolStatsWithLock(e,t,r,!0),this.logger.debug(`[MCPManager] \u5DF2\u66F4\u65B0 MCP \u670D\u52A1\u5DE5\u5177 ${e}/${t} \u7EDF\u8BA1`)}catch(n){throw this.logger.error(`[MCPManager] \u66F4\u65B0 MCP \u670D\u52A1\u5DE5\u5177 ${e}/${t} \u7EDF\u8BA1\u5931\u8D25:`,n),n}}async updateMCPServerToolLastUsedTime(e,t,r){try{await f.updateMCPServerToolStatsWithLock(e,t,r,!1),this.logger.debug(`[MCPManager] \u5DF2\u66F4\u65B0 MCP \u670D\u52A1\u5DE5\u5177 ${e}/${t} \u6700\u540E\u4F7F\u7528\u65F6\u95F4`)}catch(n){throw this.logger.error(`[MCPManager] \u66F4\u65B0 MCP \u670D\u52A1\u5DE5\u5177 ${e}/${t} \u6700\u540E\u4F7F\u7528\u65F6\u95F4\u5931\u8D25:`,n),n}}async callMCPTool(e,t,r){let{serviceName:n,toolName:s}=t;this.logger.debug(`[MCPManager] \u8C03\u7528 MCP \u540C\u6B65\u5DE5\u5177 ${e} -> ${n}.${s}`);let i=this.services.get(n);if(!i)throw new Error(`\u670D\u52A1 ${n} \u4E0D\u53EF\u7528`);if(!i.isConnected())throw new Error(`\u670D\u52A1 ${n} \u672A\u8FDE\u63A5`);try{let a=await i.callTool(s,r||{});return this.logger.debug(`[MCPManager] MCP \u540C\u6B65\u5DE5\u5177 ${e} \u8C03\u7528\u6210\u529F`),a}catch(a){throw this.logger.error(`[MCPManager] MCP \u540C\u6B65\u5DE5\u5177 ${e} \u8C03\u7528\u5931\u8D25:`,a.message),a}}hasTool(e){return this.customMCPHandler.hasTool(e)?!0:this.tools.has(e)}async stopAllServices(){this.logger.info("[MCPManager] \u6B63\u5728\u505C\u6B62\u6240\u6709 MCP \u670D\u52A1..."),this.stopAllServiceRetries();for(let[e,t]of this.services)try{await t.disconnect(),this.logger.info(`[MCPManager] ${e} \u670D\u52A1\u5DF2\u505C\u6B62`)}catch(r){this.logger.error(`[MCPManager] \u505C\u6B62 ${e} \u670D\u52A1\u5931\u8D25:`,r.message)}try{this.customMCPHandler.cleanup(),this.logger.info("[MCPManager] CustomMCP \u5904\u7406\u5668\u5DF2\u6E05\u7406")}catch(e){this.logger.error("[MCPManager] CustomMCP \u5904\u7406\u5668\u6E05\u7406\u5931\u8D25:",e)}try{f.clearAllStatsUpdateLocks(),this.logger.info("[MCPManager] \u7EDF\u8BA1\u66F4\u65B0\u9501\u5DF2\u6E05\u7406")}catch(e){this.logger.error("[MCPManager] \u6E05\u7406\u7EDF\u8BA1\u66F4\u65B0\u9501\u5931\u8D25:",e)}this.services.clear(),this.tools.clear(),this.logger.info("[MCPManager] \u6240\u6709 MCP \u670D\u52A1\u5DF2\u505C\u6B62")}getStatus(){let e=0,t=[];try{e=this.customMCPHandler.getToolCount(),t=this.customMCPHandler.getToolNames(),this.logger.debug(`[MCPManager] \u6210\u529F\u83B7\u53D6 customMCP \u72B6\u6001: ${e} \u4E2A\u5DE5\u5177`)}catch(a){this.logger.warn("[MCPManager] \u83B7\u53D6 CustomMCP \u72B6\u6001\u5931\u8D25\uFF0C\u5C06\u53EA\u5305\u542B\u6807\u51C6 MCP \u5DE5\u5177:",a),e=0,t=[]}let r=this.tools.size+e,s=[...Array.from(this.tools.keys()),...t],i={services:{},totalTools:r,availableTools:s};for(let[a,g]of this.services){let u=g.getStatus();i.services[a]={connected:u.connected,clientName:`xiaozhi-${a}-client`}}return e>0&&(i.services.customMCP={connected:!0,clientName:"xiaozhi-customMCP-handler"}),i}getStatsUpdateInfo(){try{let e=f.getStatsUpdateLocks();return{activeLocks:e,totalLocks:e.length}}catch(e){return this.logger.warn("[MCPManager] \u83B7\u53D6\u7EDF\u8BA1\u66F4\u65B0\u76D1\u63A7\u4FE1\u606F\u5931\u8D25:",e),{activeLocks:[],totalLocks:0}}}getService(e){return this.services.get(e)}getConnectedServices(){let e=[];for(let[t,r]of this.services)r.isConnected()&&e.push(t);return e}async refreshCustomMCPHandler(){try{this.logger.debug("\u91CD\u65B0\u521D\u59CB\u5316CustomMCPHandler"),await this.customMCPHandler.reinitialize(),this.logger.debug("CustomMCPHandler\u91CD\u65B0\u521D\u59CB\u5316\u5B8C\u6210")}catch(e){throw this.logger.error("CustomMCPHandler\u91CD\u65B0\u521D\u59CB\u5316\u5931\u8D25:",e),e}}async refreshCustomMCPHandlerPublic(){return this.refreshCustomMCPHandler()}getAllServices(){return new Map(this.services)}getCustomMCPHandler(){return this.customMCPHandler}hasCustomMCPTool(e){try{return this.customMCPHandler.hasTool(e)}catch(t){return this.logger.warn(`[MCPManager] \u68C0\u67E5 CustomMCP \u5DE5\u5177 ${e} \u662F\u5426\u5B58\u5728\u5931\u8D25:`,t),!1}}getCustomMCPTools(){try{return this.customMCPHandler.getTools()}catch(e){return this.logger.warn("[MCPManager] \u83B7\u53D6 CustomMCP \u5DE5\u5177\u5217\u8868\u5931\u8D25\uFF0C\u8FD4\u56DE\u7A7A\u6570\u7EC4:",e),[]}}enhanceServiceConfig(e){let t={...e};try{if(e.type==="sse"&&e.url&&e.url.includes("modelscope")){let r=f.getModelScopeApiKey();if(r)t.apiKey=r,this.logger.info(`[MCPManager] \u4E3A ${e.name} \u670D\u52A1\u6DFB\u52A0 ModelScope API Key`);else throw this.logger.warn(`[MCPManager] ${e.name} \u670D\u52A1\u9700\u8981 ModelScope API Key\uFF0C\u4F46\u672A\u5728\u914D\u7F6E\u4E2D\u627E\u5230`),new Error(`ModelScope SSE \u670D\u52A1 ${e.name} \u9700\u8981 API Key\uFF0C\u8BF7\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u8BBE\u7F6E modelscope.apiKey`)}return t}catch(r){throw this.logger.error(`[MCPManager] \u914D\u7F6E\u589E\u5F3A\u5931\u8D25: ${e.name}`,r),r}}addServiceConfig(e,t){let r,n;if(typeof e=="string"&&t)n=e,r=t;else if(typeof e=="object")n=e.name,r=e;else throw new Error("Invalid arguments for addServiceConfig");let s=this.enhanceServiceConfig(r);this.configs[n]=s,this.logger.debug(`[MCPManager] \u5DF2\u6DFB\u52A0\u670D\u52A1\u914D\u7F6E: ${n}`)}updateServiceConfig(e,t){let r=this.enhanceServiceConfig(t);this.configs[e]=r,this.logger.debug(`[MCPManager] \u5DF2\u66F4\u65B0\u5E76\u589E\u5F3A\u670D\u52A1\u914D\u7F6E: ${e}`)}removeServiceConfig(e){delete this.configs[e],this.logger.debug(`[MCPManager] \u5DF2\u79FB\u9664\u670D\u52A1\u914D\u7F6E: ${e}`)}async syncToolsConfigToFile(){try{this.logger.debug("[MCPManager] \u5F00\u59CB\u540C\u6B65\u5DE5\u5177\u914D\u7F6E\u5230\u914D\u7F6E\u6587\u4EF6");let e=f.getMcpServerConfig();for(let[t,r]of this.services){if(!r.isConnected())continue;let n=r.getTools();if(n.length===0)continue;let s=e[t]?.tools||{},i={};for(let h of n){let S=s[h.name];S?i[h.name]={...S,description:h.description||S.description||""}:i[h.name]={description:h.description||"",enable:!0}}let a=n.map(h=>h.name),u=Object.keys(s).filter(h=>!a.includes(h));if(u.length>0&&this.logger.info(`[MCPManager] \u68C0\u6D4B\u5230\u670D\u52A1 ${t} \u79FB\u9664\u4E86 ${u.length} \u4E2A\u5DE5\u5177: ${u.join(", ")}`),this.hasToolsConfigChanged(s,i)){f.updateServerToolsConfig(t,i);let h=Object.keys(i).filter(T=>!s[T]),S=Object.keys(i).filter(T=>{let y=s[T],I=i[T];return y&&y.description!==I.description});this.logger.debug(`[MCPManager] \u5DF2\u540C\u6B65\u670D\u52A1 ${t} \u7684\u5DE5\u5177\u914D\u7F6E:`),h.length>0&&this.logger.debug(` - \u65B0\u589E\u5DE5\u5177: ${h.join(", ")}`),S.length>0&&this.logger.debug(` - \u66F4\u65B0\u5DE5\u5177: ${S.join(", ")}`),u.length>0&&this.logger.debug(` - \u79FB\u9664\u5DE5\u5177: ${u.join(", ")}`)}}this.logger.debug("[MCPManager] \u5DE5\u5177\u914D\u7F6E\u540C\u6B65\u5B8C\u6210")}catch(e){this.logger.error("[MCPManager] \u540C\u6B65\u5DE5\u5177\u914D\u7F6E\u5230\u914D\u7F6E\u6587\u4EF6\u5931\u8D25:",e)}}hasToolsConfigChanged(e,t){let r=Object.keys(e),n=Object.keys(t);if(r.length!==n.length)return!0;let s=n.filter(a=>!r.includes(a)),i=r.filter(a=>!n.includes(a));if(s.length>0||i.length>0)return!0;for(let a of r){let g=e[a],u=t[a];if(g.description!==u.description)return!0}return!1}scheduleFailedServicesRetry(e){if(e.length===0)return;this.logger.info(`[MCPManager] \u5B89\u6392 ${e.length} \u4E2A\u5931\u8D25\u670D\u52A1\u7684\u91CD\u8BD5`);let t=3e4;for(let r of e)this.failedServices.add(r),this.scheduleServiceRetry(r,t)}scheduleServiceRetry(e,t){let r=this.retryTimers.get(e);r&&(clearTimeout(r),this.retryTimers.delete(e)),this.logger.debug(`[MCPManager] \u5B89\u6392\u670D\u52A1 ${e} \u5728 ${t}ms \u540E\u91CD\u8BD5`);let n=setTimeout(async()=>{this.retryTimers.delete(e),await this.retryFailedService(e)},t);this.retryTimers.set(e,n)}async retryFailedService(e){if(this.failedServices.has(e))try{await this.startService(e),this.failedServices.delete(e),this.logger.info(`[MCPManager] \u670D\u52A1 ${e} \u91CD\u8BD5\u542F\u52A8\u6210\u529F`);try{await this.refreshCustomMCPHandlerPublic()}catch(t){this.logger.error("[MCPManager] \u5237\u65B0CustomMCPHandler\u5931\u8D25:",t)}}catch(t){this.logger.error(`[MCPManager] \u670D\u52A1 ${e} \u91CD\u8BD5\u542F\u52A8\u5931\u8D25:`,t.message);let r=this.getRetryDelay(e),n=Math.min(r*2,3e5);this.logger.debug(`[MCPManager] \u670D\u52A1 ${e} \u4E0B\u6B21\u91CD\u8BD5\u5C06\u5728 ${n}ms \u540E\u8FDB\u884C`),this.scheduleServiceRetry(e,n)}}getRetryDelay(e){return 3e4+e.split("").reduce((r,n)=>r+n.charCodeAt(0),0)%6e4}stopServiceRetry(e){let t=this.retryTimers.get(e);t&&(clearTimeout(t),this.retryTimers.delete(e),this.logger.debug(`[MCPManager] \u5DF2\u505C\u6B62\u670D\u52A1 ${e} \u7684\u91CD\u8BD5`)),this.failedServices.delete(e)}stopAllServiceRetries(){this.logger.info("[MCPManager] \u505C\u6B62\u6240\u6709\u670D\u52A1\u91CD\u8BD5");for(let[e,t]of this.retryTimers)clearTimeout(t),this.logger.debug(`[MCPManager] \u5DF2\u505C\u6B62\u670D\u52A1 ${e} \u7684\u91CD\u8BD5`);this.retryTimers.clear(),this.failedServices.clear()}getFailedServices(){return Array.from(this.failedServices)}isServiceFailed(e){return this.failedServices.has(e)}getRetryStats(){return{failedServices:Array.from(this.failedServices),activeRetries:Array.from(this.retryTimers.keys()),totalFailed:this.failedServices.size,totalActiveRetries:this.retryTimers.size}}};var oe=class{static{l(this,"MCPMessageHandler")}logger;serviceManager;constructor(e){this.serviceManager=e,this.logger=c}async handleMessage(e){this.logger.debug(`\u5904\u7406 MCP \u6D88\u606F: ${e.method}`,e);try{let t=e.id===void 0;switch(e.method){case"initialize":return await this.handleInitialize(e.params,e.id);case"notifications/initialized":return await this.handleInitializedNotification(e.params);case"tools/list":return await this.handleToolsList(e.id);case"tools/call":return await this.handleToolCall(e.params,e.id);case"resources/list":return await this.handleResourcesList(e.id);case"prompts/list":return await this.handlePromptsList(e.id);case"ping":return await this.handlePing(e.id);default:if(t)return this.logger.warn(`\u6536\u5230\u672A\u77E5\u7684\u901A\u77E5\u6D88\u606F: ${e.method}`,e),null;throw new Error(`\u672A\u77E5\u7684\u65B9\u6CD5: ${e.method}`)}}catch(t){return this.logger.error(`\u5904\u7406\u6D88\u606F\u65F6\u51FA\u9519: ${e.method}`,t),e.id===void 0?null:this.createErrorResponse(t,e.id)}}async handleInitialize(e,t){this.logger.debug("\u5904\u7406 initialize \u8BF7\u6C42",e);let r=["2024-11-05","2025-06-18"],n=e.protocolVersion,s=r.includes(n)?n:"2024-11-05";return this.logger.debug(`\u534F\u8BAE\u7248\u672C\u534F\u5546: \u5BA2\u6237\u7AEF=${n}, \u670D\u52A1\u5668\u54CD\u5E94=${s}`),{jsonrpc:"2.0",result:{serverInfo:{name:"xiaozhi-mcp-server",version:"1.0.0"},capabilities:{tools:{},logging:{}},protocolVersion:s},id:t!==void 0?t:1}}async handleInitializedNotification(e){return this.logger.debug("\u6536\u5230 initialized \u901A\u77E5\uFF0C\u5BA2\u6237\u7AEF\u521D\u59CB\u5316\u5B8C\u6210",e),null}async handleToolsList(e){this.logger.debug("\u5904\u7406 tools/list \u8BF7\u6C42");try{return{jsonrpc:"2.0",result:{tools:this.serviceManager.getAllTools().map(n=>({name:n.name,description:n.description,inputSchema:n.inputSchema}))},id:e!==void 0?e:1}}catch(t){throw this.logger.error("\u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25",t),t}}async handleToolCall(e,t){try{if(!e.name)throw new Error("\u5DE5\u5177\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");let r=await this.serviceManager.callTool(e.name,e.arguments||{});return{jsonrpc:"2.0",result:{content:r.content,isError:r.isError||!1},id:t!==void 0?t:1}}catch(r){throw this.logger.error(`\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${e.name}`,r),r}}async handlePing(e){return this.logger.debug("\u5904\u7406 ping \u8BF7\u6C42"),{jsonrpc:"2.0",result:{status:"ok",timestamp:new Date().toISOString()},id:e!==void 0?e:1}}async handleResourcesList(e){this.logger.debug("\u5904\u7406 resources/list \u8BF7\u6C42");let t=[];return this.logger.debug(`\u8FD4\u56DE ${t.length} \u4E2A\u8D44\u6E90`),{jsonrpc:"2.0",result:{resources:t},id:e!==void 0?e:1}}async handlePromptsList(e){this.logger.debug("\u5904\u7406 prompts/list \u8BF7\u6C42");let t=[];return this.logger.debug(`\u8FD4\u56DE ${t.length} \u4E2A\u63D0\u793A\u6A21\u677F`),{jsonrpc:"2.0",result:{prompts:t},id:e!==void 0?e:1}}createErrorResponse(e,t){let r=-32603;return e.message.includes("\u672A\u627E\u5230\u5DE5\u5177")||e.message.includes("\u672A\u77E5\u7684\u65B9\u6CD5")?r=-32601:(e.message.includes("\u53C2\u6570")||e.message.includes("\u4E0D\u80FD\u4E3A\u7A7A"))&&(r=-32602),{jsonrpc:"2.0",error:{code:r,message:e.message,data:{stack:e.stack}},id:t!==void 0?t:1}}getServiceManager(){return this.serviceManager}};var Me=class{static{l(this,"ToolRegistry")}serviceManager;logger;constructor(e){this.serviceManager=e,this.logger=c}async initialize(){this.logger.info("\u521D\u59CB\u5316\u5DE5\u5177\u6CE8\u518C\u8868")}getAllTools(){return this.serviceManager.getAllTools().map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema,serviceName:e.serviceName,originalName:e.originalName}))}findTool(e){return this.getAllTools().find(r=>r.name===e)||null}hasTool(e){return this.findTool(e)!==null}},Pe=class extends Ne{static{l(this,"ConnectionManager")}connections=new Map;logger;constructor(){super(),this.logger=c}async initialize(){this.logger.info("\u521D\u59CB\u5316\u8FDE\u63A5\u7BA1\u7406\u5668")}registerConnection(e,t,r){let n={id:e,transportName:t,state:r,connectedAt:new Date,lastActivity:new Date};this.connections.set(e,n),this.emit("connectionRegistered",n),this.logger.debug(`\u8FDE\u63A5\u5DF2\u6CE8\u518C: ${e} (${t})`)}updateConnectionState(e,t){let r=this.connections.get(e);r&&(r.state=t,r.lastActivity=new Date,this.emit("connectionStateChanged",r),this.logger.debug(`\u8FDE\u63A5\u72B6\u6001\u66F4\u65B0: ${e} -> ${t}`))}removeConnection(e){let t=this.connections.get(e);t&&(this.connections.delete(e),this.emit("connectionRemoved",t),this.logger.debug(`\u8FDE\u63A5\u5DF2\u79FB\u9664: ${e}`))}getAllConnections(){return Array.from(this.connections.values())}getActiveConnectionCount(){return Array.from(this.connections.values()).filter(e=>e.state==="connected").length}async closeAllConnections(){this.logger.info("\u5173\u95ED\u6240\u6709\u8FDE\u63A5"),this.connections.clear(),this.emit("allConnectionsClosed")}},ae=class extends Ne{static{l(this,"UnifiedMCPServer")}serviceManager;messageHandler;transportAdapters=new Map;toolRegistry;connectionManager;isRunning=!1;logger;config;constructor(e={}){super(),this.config={name:"UnifiedMCPServer",enableLogging:!0,logLevel:"info",maxConnections:100,connectionTimeout:3e4,...e},this.logger=c,this.serviceManager=new ie,this.messageHandler=new oe(this.serviceManager),this.toolRegistry=new Me(this.serviceManager),this.connectionManager=new Pe,this.setupEventListeners()}setupEventListeners(){this.connectionManager.on("connectionRegistered",e=>{this.emit("connectionRegistered",e)}),this.connectionManager.on("connectionStateChanged",e=>{this.emit("connectionStateChanged",e)}),this.connectionManager.on("connectionRemoved",e=>{this.emit("connectionRemoved",e)})}async initialize(){this.logger.info("\u521D\u59CB\u5316\u7EDF\u4E00 MCP \u670D\u52A1\u5668");try{await this.serviceManager.startAllServices(),await this.toolRegistry.initialize(),await this.connectionManager.initialize(),this.logger.debug("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u521D\u59CB\u5316\u5B8C\u6210"),this.emit("initialized")}catch(e){throw this.logger.error("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u521D\u59CB\u5316\u5931\u8D25",e),e}}async registerTransport(e,t){if(this.transportAdapters.has(e))throw new Error(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u5DF2\u5B58\u5728`);this.logger.info(`\u6CE8\u518C\u4F20\u8F93\u9002\u914D\u5668: ${e}`);try{await t.initialize(),this.transportAdapters.set(e,t),this.connectionManager.registerConnection(t.getConnectionId(),e,t.getState()),this.logger.info(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u6CE8\u518C\u6210\u529F`),this.emit("transportRegistered",{name:e,adapter:t})}catch(r){throw this.logger.error(`\u6CE8\u518C\u4F20\u8F93\u9002\u914D\u5668 ${e} \u5931\u8D25`,r),r}}async start(){if(this.isRunning)throw new Error("\u670D\u52A1\u5668\u5DF2\u5728\u8FD0\u884C");this.logger.info("\u542F\u52A8\u7EDF\u4E00 MCP \u670D\u52A1\u5668");try{for(let[e,t]of this.transportAdapters)try{await t.start(),this.connectionManager.updateConnectionState(t.getConnectionId(),t.getState()),this.logger.info(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u542F\u52A8\u6210\u529F`)}catch(r){throw this.logger.error(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u542F\u52A8\u5931\u8D25`,r),r}this.isRunning=!0,this.logger.info("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u542F\u52A8\u6210\u529F"),this.emit("started")}catch(e){throw this.logger.error("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u542F\u52A8\u5931\u8D25",e),e}}async stop(){if(this.isRunning){this.logger.info("\u505C\u6B62\u7EDF\u4E00 MCP \u670D\u52A1\u5668");try{for(let[e,t]of this.transportAdapters)try{await t.stop(),this.connectionManager.updateConnectionState(t.getConnectionId(),t.getState()),this.logger.info(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u505C\u6B62\u6210\u529F`)}catch(r){this.logger.error(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u505C\u6B62\u5931\u8D25`,r)}await this.connectionManager.closeAllConnections(),await this.serviceManager.stopAllServices(),this.isRunning=!1,this.logger.info("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u505C\u6B62\u6210\u529F"),this.emit("stopped")}catch(e){throw this.logger.error("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u505C\u6B62\u5931\u8D25",e),e}}}getServiceManager(){return this.serviceManager}getToolRegistry(){return this.toolRegistry}getConnectionManager(){return this.connectionManager}getMessageHandler(){return this.messageHandler}getStatus(){return{isRunning:this.isRunning,transportCount:this.transportAdapters.size,activeConnections:this.connectionManager.getActiveConnectionCount(),toolCount:this.toolRegistry.getAllTools().length,config:this.config}}getTransportAdapters(){return new Map(this.transportAdapters)}isServerRunning(){return this.isRunning}};async function ze(o={}){c.info("[ServerFactory] \u5F00\u59CB\u521B\u5EFA MCP \u670D\u52A1\u5668",o);try{let e=await Rt(o);c.info(`[ServerFactory] \u786E\u5B9A\u670D\u52A1\u5668\u6A21\u5F0F: ${e}`);let t=new ae(o.serverConfig);return await t.initialize(),await xt(t,e,o),c.info("[ServerFactory] MCP \u670D\u52A1\u5668\u521B\u5EFA\u6210\u529F"),t}catch(e){throw c.error("[ServerFactory] \u521B\u5EFA MCP \u670D\u52A1\u5668\u5931\u8D25",e),e}}l(ze,"createServer");async function Rt(o){if(o.mode&&o.mode!=="auto")return o.mode;let e=await $t(o.autoDetect);return c.info("\u73AF\u5883\u68C0\u6D4B\u7ED3\u679C",e),e.suggestedMode}l(Rt,"determineServerMode");async function $t(o={}){let{checkStdin:e=!0,checkEnvironment:t=!0,defaultMode:r="http"}=o,n={hasStdin:!1,isInteractive:!1,hasPort:!1,suggestedMode:r,reasons:[]};e&&(n.hasStdin=!process.stdin.isTTY,n.isInteractive=process.stdin.isTTY||!1,n.hasStdin&&n.reasons.push("\u68C0\u6D4B\u5230\u6807\u51C6\u8F93\u5165\u6D41"),n.isInteractive&&n.reasons.push("\u68C0\u6D4B\u5230\u4EA4\u4E92\u5F0F\u7EC8\u7AEF"));let s=!1;if(t){let i=process.env.MCP_SERVER_MODE,a=process.env.PORT||process.env.MCP_PORT;i==="stdio"?(n.suggestedMode="stdio",n.reasons.push("\u73AF\u5883\u53D8\u91CF MCP_SERVER_MODE=stdio"),s=!0):i==="http"?(n.suggestedMode="http",n.reasons.push("\u73AF\u5883\u53D8\u91CF MCP_SERVER_MODE=http"),s=!0):i==="websocket"?(n.suggestedMode="websocket",n.reasons.push("\u73AF\u5883\u53D8\u91CF MCP_SERVER_MODE=websocket"),s=!0):i==="hybrid"&&(n.suggestedMode="hybrid",n.reasons.push("\u73AF\u5883\u53D8\u91CF MCP_SERVER_MODE=hybrid"),s=!0),a&&(n.hasPort=!0,n.reasons.push(`\u68C0\u6D4B\u5230\u7AEF\u53E3\u914D\u7F6E: ${a}`))}return!s&&n.suggestedMode===r&&(n.hasStdin&&!n.isInteractive?(n.suggestedMode="stdio",n.reasons.push("\u63A8\u65AD\uFF1A\u975E\u4EA4\u4E92\u5F0F\u73AF\u5883\uFF0C\u9002\u5408 Stdio \u6A21\u5F0F")):(n.isInteractive||n.hasPort)&&(n.suggestedMode="http",n.reasons.push("\u63A8\u65AD\uFF1A\u4EA4\u4E92\u5F0F\u73AF\u5883\u6216\u6709\u7AEF\u53E3\u914D\u7F6E\uFF0C\u9002\u5408 HTTP \u6A21\u5F0F"))),n}l($t,"detectEnvironment");async function xt(o,e,t){let r=o.getMessageHandler();switch(e){case"stdio":await Fe(o,r,t.stdioConfig);break;case"http":await je(o,r,t.httpConfig);break;case"websocket":await Ue(o,r,t.websocketConfig);break;case"hybrid":await Fe(o,r,t.stdioConfig),await je(o,r,t.httpConfig),t.websocketConfig&&await Ue(o,r,t.websocketConfig);break;default:throw new Error(`\u4E0D\u652F\u6301\u7684\u670D\u52A1\u5668\u6A21\u5F0F: ${e}`)}}l(xt,"registerTransportsForMode");async function Fe(o,e,t={name:"stdio"}){let r=new J(e,t);await o.registerTransport("stdio",r),c.info("Stdio \u4F20\u8F93\u9002\u914D\u5668\u6CE8\u518C\u6210\u529F")}l(Fe,"registerStdioTransport");async function je(o,e,t={name:"http"}){let r={port:3e3,host:"0.0.0.0",...t};process.env.PORT?r.port=Number.parseInt(process.env.PORT,10):process.env.MCP_PORT&&(r.port=Number.parseInt(process.env.MCP_PORT,10));let n=new G(e,r);await o.registerTransport("http",n),c.info(`HTTP \u4F20\u8F93\u9002\u914D\u5668\u6CE8\u518C\u6210\u529F (\u7AEF\u53E3: ${r.port})`)}l(je,"registerHTTPTransport");async function Ue(o,e,t={name:"websocket",endpointUrl:"ws://localhost:8080"}){let r={mode:"client",compression:!0,batchSize:10,batchTimeout:100,maxConnections:100,...t};process.env.WEBSOCKET_URL?r.endpointUrl=process.env.WEBSOCKET_URL:process.env.MCP_WEBSOCKET_URL&&(r.endpointUrl=process.env.MCP_WEBSOCKET_URL);let n=new q(e,r);await o.registerTransport("websocket",n),c.info(`WebSocket \u4F20\u8F93\u9002\u914D\u5668\u6CE8\u518C\u6210\u529F (\u7AEF\u70B9: ${r.endpointUrl})`)}l(Ue,"registerWebSocketTransport");var ms=It(kt(import.meta.url)),_e=w.env.XIAOZHI_CONFIG_DIR||w.cwd();c.initLogFile(_e);c.enableFileLogging(!0);c.info(`\u65E5\u5FD7\u6587\u4EF6\u5DF2\u521D\u59CB\u5316: ${_e}/xiaozhi.log`);async function Ot(){try{c.info("\u542F\u52A8 MCP \u670D\u52A1\u5668\u4EE3\u7406"),await Lt();let o=await ze({mode:"stdio",stdioConfig:{name:"mcp-proxy",encoding:"utf8"}});await o.start(),c.info("MCP \u670D\u52A1\u5668\u4EE3\u7406\u542F\u52A8\u6210\u529F"),w.on("SIGINT",async()=>{c.info("\u6536\u5230 SIGINT \u4FE1\u53F7\uFF0C\u6B63\u5728\u5173\u95ED\u670D\u52A1\u5668"),await o.stop(),w.exit(0)}),w.on("SIGTERM",async()=>{c.info("\u6536\u5230 SIGTERM \u4FE1\u53F7\uFF0C\u6B63\u5728\u5173\u95ED\u670D\u52A1\u5668"),await o.stop(),w.exit(0)})}catch(o){c.error("\u542F\u52A8 MCP \u670D\u52A1\u5668\u4EE3\u7406\u5931\u8D25:",o),w.exit(1)}}l(Ot,"main");async function Lt(){try{if(c.info("\u52A0\u8F7D MCP \u670D\u52A1\u5668\u914D\u7F6E"),!f.configExists()){c.warn("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u5C06\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E");return}let o=f.getConfig();c.info(`\u5DF2\u52A0\u8F7D\u914D\u7F6E\uFF0C\u5305\u542B ${Object.keys(o.mcpServers||{}).length} \u4E2A MCP \u670D\u52A1\u5668`)}catch(o){throw c.error("\u52A0\u8F7D\u914D\u7F6E\u5931\u8D25:",o),o}}l(Lt,"loadConfiguration");import.meta.url===`file://${w.argv[1]}`&&Ot().catch(o=>{c.error("MCP \u670D\u52A1\u5668\u4EE3\u7406\u542F\u52A8\u5931\u8D25:",o),w.exit(1)});export{Ot as main};
24
+ 3. \u5982\u679C\u957F\u65F6\u95F4\u672A\u5B8C\u6210\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458`}l(Ie,"getDefaultTimeoutMessage");import{createHash as st}from"crypto";import{existsSync as W,mkdirSync as ot,readFileSync as ke,renameSync as it,writeFileSync as Le}from"fs";import{dirname as at,resolve as Oe}from"path";import ct from"dayjs";var N=class{static{l(this,"MCPCacheManager")}cachePath;logger;CACHE_VERSION="1.0.0";CACHE_ENTRY_VERSION="1.0.0";cleanupInterval;CLEANUP_INTERVAL=6e4;constructor(e){this.logger=c,this.cachePath=e||this.getCacheFilePath(),this.startCleanupTimer()}formatTimestamp(){return ct().format("YYYY-MM-DD HH:mm:ss")}getCacheFilePath(){try{let e=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return Oe(e,"xiaozhi.cache.json")}catch{let t=process.env.XIAOZHI_CONFIG_DIR||"/tmp";return Oe(t,"xiaozhi.cache.json")}}async ensureCacheFile(){try{if(!W(this.cachePath)){let e=at(this.cachePath);W(e)||(ot(e,{recursive:!0}),this.logger.debug(`[CacheManager] \u5DF2\u521B\u5EFA\u7F13\u5B58\u76EE\u5F55: ${e}`)),this.logger.debug("[CacheManager] \u7F13\u5B58\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u521B\u5EFA\u521D\u59CB\u7F13\u5B58\u6587\u4EF6");let t=await this.createInitialCache();await this.saveCache(t),this.logger.info(`[CacheManager] \u5DF2\u521B\u5EFA\u7F13\u5B58\u6587\u4EF6: ${this.cachePath}`)}}catch(e){this.logger.warn(`[CacheManager] \u521B\u5EFA\u7F13\u5B58\u6587\u4EF6\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}async createInitialCache(){let e=this.formatTimestamp();return{version:this.CACHE_VERSION,mcpServers:{},metadata:{lastGlobalUpdate:e,totalWrites:0,createdAt:e}}}async writeCacheEntry(e,t,r){try{this.logger.debug(`[CacheManager] \u5F00\u59CB\u5199\u5165\u7F13\u5B58: ${e}`),await this.ensureCacheFile();let n=await this.loadExistingCache(),s=this.generateConfigHash(r),o={tools:t.map(a=>({name:a.name,description:a.description||"",inputSchema:a.inputSchema})),lastUpdated:this.formatTimestamp(),serverConfig:{...r},configHash:s,version:this.CACHE_ENTRY_VERSION};n.mcpServers[e]=o,n.metadata.lastGlobalUpdate=this.formatTimestamp(),n.metadata.totalWrites+=1,await this.saveCache(n),this.logger.debug(`[CacheManager] \u7F13\u5B58\u5199\u5165\u6210\u529F: ${e}, \u5DE5\u5177\u6570\u91CF: ${t.length}`)}catch(n){this.logger.warn(`[CacheManager] \u7F13\u5B58\u5199\u5165\u5931\u8D25: ${e}, \u9519\u8BEF: ${n instanceof Error?n.message:String(n)}`)}}async loadExistingCache(){try{if(!W(this.cachePath))return await this.createInitialCache();let e=ke(this.cachePath,"utf8"),t=JSON.parse(e);return this.validateCacheStructure(t)?t:(this.logger.warn("[CacheManager] \u7F13\u5B58\u6587\u4EF6\u7ED3\u6784\u65E0\u6548\uFF0C\u91CD\u65B0\u521B\u5EFA"),await this.createInitialCache())}catch(e){return this.logger.warn(`[CacheManager] \u52A0\u8F7D\u7F13\u5B58\u5931\u8D25\uFF0C\u521B\u5EFA\u65B0\u7F13\u5B58: ${e instanceof Error?e.message:String(e)}`),await this.createInitialCache()}}async saveCache(e){let t=JSON.stringify(e,null,2);await this.atomicWrite(this.cachePath,t)}async atomicWrite(e,t){let r=`${e}.tmp`;try{Le(r,t,"utf8"),it(r,e)}catch(n){try{W(r)&&Le(r,"","utf8")}catch{}throw n}}generateConfigHash(e){try{return st("sha256").update(JSON.stringify(e)).digest("hex")}catch(t){return this.logger.warn(`[CacheManager] \u751F\u6210\u914D\u7F6E\u54C8\u5E0C\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`),""}}validateCacheStructure(e){try{return e&&typeof e=="object"&&typeof e.version=="string"&&typeof e.mcpServers=="object"&&e.metadata&&typeof e.metadata=="object"&&typeof e.metadata.lastGlobalUpdate=="string"&&typeof e.metadata.totalWrites=="number"&&typeof e.metadata.createdAt=="string"}catch{return!1}}async getStats(){try{let e=await this.loadExistingCache();return{totalWrites:e.metadata.totalWrites,lastUpdate:e.metadata.lastGlobalUpdate,serverCount:Object.keys(e.mcpServers).length,cacheFileSize:W(this.cachePath)?ke(this.cachePath,"utf8").length:0}}catch(e){return this.logger.warn(`[CacheManager] \u83B7\u53D6\u7F13\u5B58\u7EDF\u8BA1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`),null}}getFilePath(){return this.cachePath}async getAllCachedTools(){try{let e=await this.loadExistingCache(),t=[];for(let[r,n]of Object.entries(e.mcpServers))for(let s of n.tools)t.push({...s,name:`${r}__${s.name}`});return this.logger.debug(`[CacheManager] \u83B7\u53D6\u5230\u6240\u6709\u7F13\u5B58\u5DE5\u5177\uFF0C\u5171 ${t.length} \u4E2A`),t}catch(e){return this.logger.warn(`[CacheManager] \u83B7\u53D6\u6240\u6709\u7F13\u5B58\u5DE5\u5177\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`),[]}}async writeCustomMCPResult(e,t,r,n="completed",s,o=3e5){try{let a=await this.loadExtendedCache(),g=R(e,t),u={result:r,timestamp:new Date().toISOString(),ttl:o,status:n,consumed:!1,taskId:s,retryCount:0};a.customMCPResults||(a.customMCPResults={}),a.customMCPResults[g]=u,await this.saveExtendedCache(a),this.logger.debug(`[CacheManager] \u5199\u5165CustomMCP\u7ED3\u679C\u7F13\u5B58: ${e}, \u72B6\u6001: ${n}`)}catch(a){this.logger.warn(`[CacheManager] \u5199\u5165CustomMCP\u7ED3\u679C\u7F13\u5B58\u5931\u8D25: ${a instanceof Error?a.message:String(a)}`)}}async readCustomMCPResult(e,t){try{let r=await this.loadExtendedCache(),n=R(e,t);if(!r.customMCPResults||!r.customMCPResults[n])return null;let s=r.customMCPResults[n],o=Date.now(),a=new Date(s.timestamp).getTime();return o-a>s.ttl?(this.logger.debug(`[CacheManager] \u7F13\u5B58\u5DF2\u8FC7\u671F: ${e}`),null):s}catch(r){return this.logger.warn(`[CacheManager] \u8BFB\u53D6CustomMCP\u7ED3\u679C\u7F13\u5B58\u5931\u8D25: ${r instanceof Error?r.message:String(r)}`),null}}async updateCustomMCPStatus(e,t,r,n,s){try{let o=await this.loadExtendedCache(),a=R(e,t);if(!o.customMCPResults||!o.customMCPResults[a])return!1;let g=o.customMCPResults[a],u=g.status;return g.status=r,g.timestamp=new Date().toISOString(),n&&(g.result=n),s&&r==="failed"&&(g.result={content:[{type:"text",text:`\u4EFB\u52A1\u5931\u8D25: ${s}`}]},g.consumed=!0),r==="completed"&&(g.consumed=!1),await this.saveExtendedCache(o),this.logger.debug(`[CacheManager] \u66F4\u65B0\u7F13\u5B58\u72B6\u6001: ${e} ${u} -> ${r}`),!0}catch(o){return this.logger.warn(`[CacheManager] \u66F4\u65B0CustomMCP\u7F13\u5B58\u72B6\u6001\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`),!1}}async markCustomMCPAsConsumed(e,t){try{let r=await this.loadExtendedCache(),n=R(e,t);if(!r.customMCPResults||!r.customMCPResults[n])return!1;let s=r.customMCPResults[n];return s.consumed||(s.consumed=!0,s.timestamp=new Date().toISOString(),await this.saveExtendedCache(r),this.logger.debug(`[CacheManager] \u6807\u8BB0\u7F13\u5B58\u4E3A\u5DF2\u6D88\u8D39: ${e}`)),!0}catch(r){return this.logger.warn(`[CacheManager] \u6807\u8BB0CustomMCP\u7F13\u5B58\u4E3A\u5DF2\u6D88\u8D39\u5931\u8D25: ${r instanceof Error?r.message:String(r)}`),!1}}async deleteCustomMCPResult(e,t){try{let r=await this.loadExtendedCache(),n=R(e,t);return!r.customMCPResults||!r.customMCPResults[n]?!1:(delete r.customMCPResults[n],await this.saveExtendedCache(r),this.logger.debug(`[CacheManager] \u5220\u9664\u7F13\u5B58\u6761\u76EE: ${e}`),!0)}catch(r){return this.logger.warn(`[CacheManager] \u5220\u9664CustomMCP\u7F13\u5B58\u6761\u76EE\u5931\u8D25: ${r instanceof Error?r.message:String(r)}`),!1}}async cleanupCustomMCPResults(){try{let e=await this.loadExtendedCache();if(!e.customMCPResults)return{cleaned:0,total:0};let t=Object.entries(e.customMCPResults),r=0;for(let[n,s]of t)O(s)&&(delete e.customMCPResults[n],r++);return r>0&&(await this.saveExtendedCache(e),this.logger.info(`[CacheManager] \u6E05\u7406CustomMCP\u7F13\u5B58: ${r}/${t.length}`)),{cleaned:r,total:t.length}}catch(e){return this.logger.warn(`[CacheManager] \u6E05\u7406CustomMCP\u7F13\u5B58\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`),{cleaned:0,total:0}}}async getCustomMCPStatistics(){try{let e=await this.loadExtendedCache();if(!e.customMCPResults)return{totalEntries:0,pendingTasks:0,completedTasks:0,failedTasks:0,consumedEntries:0,cacheHitRate:0,lastCleanupTime:new Date().toISOString(),memoryUsage:0};let t=Object.values(e.customMCPResults),r=t.length,n=t.filter(p=>p.status==="pending").length,s=t.filter(p=>p.status==="completed").length,o=t.filter(p=>p.status==="failed").length,a=t.filter(p=>p.consumed).length,g=s>0?a/s*100:0,u=JSON.stringify(e.customMCPResults).length;return{totalEntries:r,pendingTasks:n,completedTasks:s,failedTasks:o,consumedEntries:a,cacheHitRate:g,lastCleanupTime:new Date().toISOString(),memoryUsage:u}}catch(e){return this.logger.warn(`[CacheManager] \u83B7\u53D6CustomMCP\u7F13\u5B58\u7EDF\u8BA1\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`),{totalEntries:0,pendingTasks:0,completedTasks:0,failedTasks:0,consumedEntries:0,cacheHitRate:0,lastCleanupTime:new Date().toISOString(),memoryUsage:0}}}async loadExtendedCache(){try{return await this.loadExistingCache()}catch(e){return this.logger.warn(`[CacheManager] \u52A0\u8F7D\u6269\u5C55\u7F13\u5B58\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`),{version:this.CACHE_VERSION,mcpServers:{},metadata:{lastGlobalUpdate:this.formatTimestamp(),totalWrites:0,createdAt:this.formatTimestamp()},customMCPResults:{}}}}async saveExtendedCache(e){await this.saveCache(e)}startCleanupTimer(){this.cleanupInterval=setInterval(()=>{this.cleanupCustomMCPResults().catch(e=>{this.logger.warn(`[CacheManager] \u81EA\u52A8\u6E05\u7406\u5931\u8D25: ${e}`)})},this.CLEANUP_INTERVAL),this.logger.debug(`[CacheManager] \u542F\u52A8\u6E05\u7406\u5B9A\u65F6\u5668\uFF0C\u95F4\u9694: ${this.CLEANUP_INTERVAL}ms`)}stopCleanupTimer(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=void 0,this.logger.debug("[CacheManager] \u505C\u6B62\u6E05\u7406\u5B9A\u65F6\u5668"))}cleanup(){this.stopCleanupTimer(),this.logger.debug("[CacheManager] \u6E05\u7406\u8D44\u6E90\u5B8C\u6210")}};var Y=class{static{l(this,"CustomMCPHandler")}logger;tools=new Map;cacheManager;cacheLifecycleManager;taskStateManager;mcpServiceManager;TIMEOUT=$.TIMEOUT;CACHE_TTL=$.CACHE_TTL;CLEANUP_INTERVAL=$.CLEANUP_INTERVAL;cleanupTimer;activeTasks=new Map;eventBus=b();constructor(e,t){this.logger=c,this.cacheManager=e||new N,this.mcpServiceManager=t,this.cacheLifecycleManager=new J(this.logger),this.taskStateManager=new q(this.logger),this.startCleanupTimer(),this.cacheLifecycleManager.startAutoCleanup(),this.setupEventListeners()}setupEventListeners(){this.eventBus.onEvent("config:updated",async e=>{await this.handleConfigUpdated(e)})}async handleConfigUpdated(e){this.logger.debug("[CustomMCP] \u68C0\u6D4B\u5230\u914D\u7F6E\u66F4\u65B0\uFF0C\u68C0\u67E5\u662F\u5426\u9700\u8981\u91CD\u65B0\u521D\u59CB\u5316");try{e.type==="customMCP"?(this.logger.debug("[CustomMCP] customMCP \u914D\u7F6E\u5DF2\u66F4\u65B0\uFF0C\u91CD\u65B0\u521D\u59CB\u5316\u5904\u7406\u5668"),await this.reinitialize()):e.type==="serverTools"&&(this.logger.debug("[CustomMCP] serverTools \u914D\u7F6E\u5DF2\u66F4\u65B0\uFF0C\u91CD\u65B0\u521D\u59CB\u5316\u5904\u7406\u5668"),await this.reinitialize())}catch(t){this.logger.error("[CustomMCP] \u914D\u7F6E\u66F4\u65B0\u5904\u7406\u5931\u8D25:",t)}}async reinitialize(){try{this.logger.debug("[CustomMCP] \u5F00\u59CB\u91CD\u65B0\u521D\u59CB\u5316\u5904\u7406\u5668"),this.tools.clear();let e=f.getCustomMCPTools();for(let t of e)this.tools.set(t.name,t),this.logger.debug(`[CustomMCP] \u91CD\u65B0\u52A0\u8F7D\u5DE5\u5177: ${t.name} (${t.handler.type})`);this.logger.debug(`[CustomMCP] \u91CD\u65B0\u521D\u59CB\u5316\u5B8C\u6210\uFF0C\u5171\u52A0\u8F7D ${this.tools.size} \u4E2A\u5DE5\u5177`)}catch(e){throw this.logger.error("[CustomMCP] \u91CD\u65B0\u521D\u59CB\u5316\u5931\u8D25:",e),e}}initialize(e){this.logger.debug("[CustomMCP] \u521D\u59CB\u5316 CustomMCP \u5904\u7406\u5668...");try{let t=e||f.getCustomMCPTools();this.tools.clear();for(let r of t)this.tools.set(r.name,r),this.logger.debug(`[CustomMCP] \u5DF2\u52A0\u8F7D\u5DE5\u5177: ${r.name} (${r.handler.type})`);this.logger.debug(`[CustomMCP] \u521D\u59CB\u5316\u5B8C\u6210\uFF0C\u5171\u52A0\u8F7D ${this.tools.size} \u4E2A\u5DE5\u5177`)}catch(t){throw this.logger.error("[CustomMCP] \u521D\u59CB\u5316\u5931\u8D25:",t),t}}getTools(){return Array.from(this.tools.values()).map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema}))}hasTool(e){return this.tools.has(e)}getToolCount(){return this.tools.size}getToolNames(){return Array.from(this.tools.keys())}async callTool(e,t,r){if(!this.tools.get(e))throw new Error(`\u672A\u627E\u5230\u5DE5\u5177: ${e}`);let s=await this.getCompletedResult(e,t);if(s)return this.logger.debug(`[CustomMCP] \u8FD4\u56DE\u5DF2\u5B8C\u6210\u7684\u4EFB\u52A1\u7ED3\u679C: ${e}`),await this.clearConsumedCache(e,t),s;try{let o=await Promise.race([this.executeToolWithBackgroundProcessing(e,t),this.createTimeoutPromise(e,t)]);return await this.cacheResult(e,t,o),o}catch(o){if(o instanceof _){let a=await this.generateTaskId(e,t);return this.logger.info(`[CustomMCP] \u5DE5\u5177\u8D85\u65F6\uFF0C\u8FD4\u56DE\u53CB\u597D\u63D0\u793A: ${e}, taskId: ${a}`),xe(a,e)}throw o}}async executeToolWithBackgroundProcessing(e,t){let r=this.tools.get(e);if(!r)throw new Error(`\u5DE5\u5177\u4E0D\u5B58\u5728: ${e}`);let n=await this.generateTaskId(e,t);await this.markTaskAsPending(n,e,t);try{let s=await this.callToolByType(r,t);return await this.markTaskAsCompleted(n,s),s}catch(s){throw await this.markTaskAsFailed(n,s),s}}async createTimeoutPromise(e,t){return new Promise((r,n)=>{setTimeout(()=>{n(new _(`\u5DE5\u5177\u8C03\u7528\u8D85\u65F6: ${e}`))},this.TIMEOUT)})}async getCompletedResult(e,t){try{let r=this.generateCacheKey(e,t),n=await this.loadExtendedCache();if(!n.customMCPResults||!n.customMCPResults[r])return null;let s=n.customMCPResults[r];return s.status==="completed"&&!s.consumed&&!H(s.timestamp,s.ttl)?s.result:null}catch(r){return this.logger.warn(`[CustomMCP] \u83B7\u53D6\u7F13\u5B58\u5931\u8D25: ${r}`),null}}async callToolByType(e,t){switch(e.handler.type){case"proxy":return await this.callProxyTool(e,t);case"function":return await this.callFunctionTool(e,t);case"http":return await this.callHttpTool(e,t);case"script":return await this.callScriptTool(e,t);case"chain":return await this.callChainTool(e,t);case"mcp":try{return await this.forwardToMCPServiceManager(e,t)}catch(r){this.logger.error(`[CustomMCP] MCP \u7C7B\u578B\u5DE5\u5177\u8DEF\u7531\u5931\u8D25: ${e.name}`,r);let n=r instanceof Error?r.message:"MCP \u7C7B\u578B\u5DE5\u5177\u8DEF\u7531\u9519\u8BEF";return{content:[{type:"text",text:n.includes("MCPServiceManager \u672A\u521D\u59CB\u5316")?n:"\u5185\u90E8\u9519\u8BEF\uFF1AMCP \u7C7B\u578B\u5DE5\u5177\u8DEF\u7531\u9519\u8BEF"}],isError:!0}}default:throw new Error(`\u4E0D\u652F\u6301\u7684\u5904\u7406\u5668\u7C7B\u578B: ${e.handler.type}`)}}async forwardToMCPServiceManager(e,t){if(!this.mcpServiceManager)throw this.logger.error(`[CustomMCP] MCPServiceManager \u672A\u521D\u59CB\u5316\uFF0C\u65E0\u6CD5\u8F6C\u53D1\u5DE5\u5177 ${e.name} \u7684\u8C03\u7528`),new Error("MCPServiceManager \u672A\u521D\u59CB\u5316");let r=e.handler;this.logger.info(`[CustomMCP] \u8F6C\u53D1MCP\u5DE5\u5177\u8C03\u7528: ${e.name}`,{serviceName:r.config.serviceName,toolName:r.config.toolName});try{let n=await this.mcpServiceManager.callTool(r.config.toolName,t);return this.logger.info(`[CustomMCP] MCP\u5DE5\u5177\u8F6C\u53D1\u6210\u529F: ${e.name}`),n}catch(n){return this.logger.error(`[CustomMCP] MCP\u5DE5\u5177\u8F6C\u53D1\u5931\u8D25: ${e.name}`,n),{content:[{type:"text",text:`MCP\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`}],isError:!0}}}async callProxyTool(e,t){let r=e.handler;if(this.logger.info(`[CustomMCP] \u8C03\u7528\u4EE3\u7406\u5DE5\u5177: ${e.name}`,{platform:r.platform,config:r.config}),r.platform==="coze")return await this.callCozeWorkflow(e,t);throw new Error(`\u4E0D\u652F\u6301\u7684\u4EE3\u7406\u5E73\u53F0: ${r.platform}`)}async callCozeWorkflow(e,t){let n=e.handler.config;this.logger.info(`[CustomMCP] \u8C03\u7528 Coze \u5DE5\u4F5C\u6D41: ${e.name}`,{workflow_id:n.workflow_id,bot_id:n.bot_id});try{let s=this.buildCozeRequest(n,t),o=await this.sendCozeRequest(n,s);return this.logger.info(`[CustomMCP] Coze \u5DE5\u4F5C\u6D41\u8C03\u7528\u6210\u529F: ${e.name}`,{response:o}),this.processCozeResponse(e.name,o)}catch(s){return this.logger.error(`[CustomMCP] Coze \u5DE5\u4F5C\u6D41\u8C03\u7528\u5931\u8D25: ${e.name}`,s),{content:[{type:"text",text:`Coze \u5DE5\u4F5C\u6D41\u8C03\u7528\u5931\u8D25: ${s instanceof Error?s.message:String(s)}`}],isError:!0}}}buildCozeRequest(e,t){return{workflow_id:e.workflow_id,parameters:{...t}}}async sendCozeRequest(e,t){let r=e.base_url||"https://api.coze.cn",n="",s=f.getConfig().platforms?.coze?.token;if(!s)throw new Error("Coze Token \u914D\u7F6E\u4E0D\u5B58\u5728");if(e.workflow_id)n="/v1/workflow/run",t.workflow_id=e.workflow_id;else if(e.bot_id)n="/v3/chat",t.bot_id=e.bot_id;else throw new Error("Coze \u914D\u7F6E\u5FC5\u987B\u63D0\u4F9B workflow_id \u6216 bot_id");let o=`${r}${n}`,a=e.timeout||3e5,g={"Content-Type":"application/json",Authorization:`Bearer ${s}`,...e.headers};this.logger.debug(`[CustomMCP] \u53D1\u9001 Coze \u8BF7\u6C42\u5230: ${o}`,{headers:{...g},body:t});let u=new AbortController,p=setTimeout(()=>u.abort(),a);try{let h=await fetch(o,{method:"POST",headers:g,body:JSON.stringify(t)});if(clearTimeout(p),!h.ok){let T=await h.text();throw new Error(`Coze API \u8BF7\u6C42\u5931\u8D25 (${h.status}): ${T}`)}let S=await h.json();return this.logger.debug("[CustomMCP] Coze API \u54CD\u5E94:",S),S}catch(h){throw clearTimeout(p),h instanceof Error&&h.name==="AbortError"?new Error(`Coze API \u8BF7\u6C42\u8D85\u65F6 (${a}ms)`):h}}processCozeResponse(e,t){try{return t.data?{content:[{type:"text",text:t.data}],isError:!1}:{content:[{type:"text",text:JSON.stringify(t,null,2)}],isError:!1}}catch(r){return this.logger.error(`[CustomMCP] \u5904\u7406 Coze \u54CD\u5E94\u5931\u8D25: ${e}`,r),{content:[{type:"text",text:`\u5904\u7406\u54CD\u5E94\u5931\u8D25: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}}async callFunctionTool(e,t){let r=e.handler;this.logger.info(`[CustomMCP] \u8C03\u7528\u51FD\u6570\u5DE5\u5177: ${e.name}`,{module:r.module,function:r.function});try{let n=await this.loadModule(r.module),s=this.getFunction(n,r.function),o=await this.executeFunction(s,t,r);return{content:[{type:"text",text:typeof o=="string"?o:JSON.stringify(o,null,2)}],isError:!1}}catch(n){return this.logger.error(`[CustomMCP] \u51FD\u6570\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${e.name}`,n),{content:[{type:"text",text:`\u51FD\u6570\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`}],isError:!0}}}async loadModule(e){try{let t=e;return!e.startsWith("/")&&!e.startsWith("file://")&&(t=new URL(e,`file://${process.cwd()}/`).href),this.logger.debug(`[CustomMCP] \u52A0\u8F7D\u6A21\u5757: ${t}`),await import(t)}catch(t){throw new Error(`\u65E0\u6CD5\u52A0\u8F7D\u6A21\u5757 ${e}: ${t instanceof Error?t.message:String(t)}`)}}getFunction(e,t){let r;if(e.default&&typeof e.default=="function"&&(t==="default"?r=e.default:e.default[t]&&typeof e.default[t]=="function"&&(r=e.default[t])),!r&&e[t]&&typeof e[t]=="function"&&(r=e[t]),!r)throw new Error(`\u5728\u6A21\u5757\u4E2D\u627E\u4E0D\u5230\u51FD\u6570: ${t}`);return r}async executeFunction(e,t,r){let n=r.timeout||3e4,s={...r.context,logger:this.logger,arguments:t},o=Promise.resolve().then(()=>e.length>1?e(t,s):e(t)),a=new Promise((g,u)=>{setTimeout(()=>u(new Error(`\u51FD\u6570\u6267\u884C\u8D85\u65F6 (${n}ms)`)),n)});return Promise.race([o,a])}async callHttpTool(e,t){let r=e.handler;this.logger.info(`[CustomMCP] \u8C03\u7528 HTTP \u5DE5\u5177: ${e.name}`,{url:r.url,method:r.method||"POST"});try{let{url:n,requestOptions:s}=this.buildHttpRequest(r,t),o=await this.sendHttpRequest(n,s,r);return this.processHttpResponse(e.name,o,r)}catch(n){return this.logger.error(`[CustomMCP] HTTP \u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${e.name}`,n),{content:[{type:"text",text:`HTTP \u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`}],isError:!0}}}buildHttpRequest(e,t){let r=e.method||"POST",n={"Content-Type":"application/json","User-Agent":"xiaozhi-client/1.0",...e.headers};if(e.auth)switch(e.auth.type){case"bearer":e.auth.token&&(n.Authorization=`Bearer ${e.auth.token}`);break;case"basic":if(e.auth.username&&e.auth.password){let g=btoa(`${e.auth.username}:${e.auth.password}`);n.Authorization=`Basic ${g}`}break;case"api_key":e.auth.api_key&&e.auth.api_key_header&&(n[e.auth.api_key_header]=e.auth.api_key);break}let s,o=e.url;if(r!=="GET")e.body_template?s=this.replaceTemplateVariables(e.body_template,t):s=JSON.stringify(t);else{let g=new URLSearchParams;for(let[p,h]of Object.entries(t))h!=null&&g.append(p,String(h));let u=g.toString();u&&(o+=(o.includes("?")?"&":"?")+u)}return{url:o,requestOptions:{method:r,headers:n,body:s}}}async sendHttpRequest(e,t,r){let n=r.timeout||3e4,s=r.retry_count||0,o=r.retry_delay||1e3,a=null;for(let g=0;g<=s;g++){try{this.logger.debug(`[CustomMCP] \u53D1\u9001 HTTP \u8BF7\u6C42 (\u5C1D\u8BD5 ${g+1}/${s+1}): ${e}`,{method:t.method,headers:t.headers});let u=new AbortController,p=setTimeout(()=>u.abort(),n),h=await fetch(e,{...t,signal:u.signal});if(clearTimeout(p),h.ok||g===s)return h;this.logger.warn(`[CustomMCP] HTTP \u8BF7\u6C42\u5931\u8D25 (${h.status}), \u5C06\u5728 ${o}ms \u540E\u91CD\u8BD5`),a=new Error(`HTTP \u8BF7\u6C42\u5931\u8D25: ${h.status} ${h.statusText}`)}catch(u){if(a=u instanceof Error?u:new Error(String(u)),u instanceof Error&&u.name==="AbortError"&&(a=new Error(`HTTP \u8BF7\u6C42\u8D85\u65F6 (${n}ms)`)),this.logger.warn(`[CustomMCP] HTTP \u8BF7\u6C42\u5F02\u5E38 (\u5C1D\u8BD5 ${g+1}/${s+1}):`,a.message),g===s)throw a}g<s&&await new Promise(u=>setTimeout(u,o))}throw a||new Error("HTTP \u8BF7\u6C42\u5931\u8D25")}async processHttpResponse(e,t,r){try{let n=t.headers.get("content-type")||"",s;if(n.includes("application/json")?s=await t.json():s=await t.text(),!t.ok)return{content:[{type:"text",text:`HTTP \u8BF7\u6C42\u5931\u8D25 (${t.status}): ${typeof s=="string"?s:JSON.stringify(s)}`}],isError:!0};let o=s;return r.response_mapping&&(o=this.extractResponseData(s,r.response_mapping)),{content:[{type:"text",text:typeof o=="string"?o:JSON.stringify(o,null,2)}],isError:!1}}catch(n){return this.logger.error(`[CustomMCP] \u5904\u7406 HTTP \u54CD\u5E94\u5931\u8D25: ${e}`,n),{content:[{type:"text",text:`\u5904\u7406\u54CD\u5E94\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`}],isError:!0}}}replaceTemplateVariables(e,t){let r=e;for(let[n,s]of Object.entries(t)){let o=`{{${n}}}`,a=typeof s=="string"?s:JSON.stringify(s);r=r.replace(new RegExp(o.replace(/[{}]/g,"\\$&"),"g"),a)}return r}extractResponseData(e,t){if(!t)return e;let r=l((n,s)=>{if(!s)return n;let o=s.split("."),a=n;for(let g of o)if(a&&typeof a=="object"&&g in a)a=a[g];else return;return a},"extractByPath");if(t.success_path){let n=r(e,t.success_path);if(n!==void 0)return t.data_path?r(n,t.data_path):n}if(t.data_path){let n=r(e,t.data_path);if(n!==void 0)return n}return e}async callScriptTool(e,t){let r=e.handler;this.logger.info(`[CustomMCP] \u8C03\u7528\u811A\u672C\u5DE5\u5177: ${e.name}`,{script:r.script.substring(0,100)+(r.script.length>100?"...":""),interpreter:r.interpreter||"node"});try{let n=await this.executeScript(r,t);return{content:[{type:"text",text:typeof n=="string"?n:JSON.stringify(n,null,2)}],isError:!1}}catch(n){return this.logger.error(`[CustomMCP] \u811A\u672C\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${e.name}`,n),{content:[{type:"text",text:`\u811A\u672C\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`}],isError:!0}}}async executeScript(e,t){let{spawn:r}=await import("child_process"),{promisify:n}=await import("util"),s=await import("fs/promises"),o=await import("path"),a=await import("os"),g=e.timeout||3e4,u=e.interpreter||"node",p,h=!1;try{if(e.script.includes(`
25
+ `)||e.script.length>200){let y=await s.mkdtemp(o.join(a.tmpdir(),"xiaozhi-script-")),I=this.getScriptExtension(u);p=o.join(y,`script${I}`),await s.writeFile(p,e.script,"utf8"),h=!0}else{p=e.script;try{await s.access(p)}catch{throw new Error(`\u811A\u672C\u6587\u4EF6\u4E0D\u5B58\u5728: ${p}`)}}let S={...process.env,...e.env,XIAOZHI_ARGUMENTS:JSON.stringify(t)},T=this.buildScriptCommand(u,p);return this.logger.debug(`[CustomMCP] \u6267\u884C\u811A\u672C\u547D\u4EE4: ${T.join(" ")}`),new Promise((y,I)=>{let k=r(T[0],T.slice(1),{env:S,stdio:["pipe","pipe","pipe"]}),ye="",be="";k.stdout?.on("data",E=>{ye+=E.toString()}),k.stderr?.on("data",E=>{be+=E.toString()});let we=setTimeout(()=>{k.kill("SIGTERM"),I(new Error(`\u811A\u672C\u6267\u884C\u8D85\u65F6 (${g}ms)`))},g);k.on("close",E=>{clearTimeout(we),E===0?y(ye.trim()):I(new Error(`\u811A\u672C\u6267\u884C\u5931\u8D25 (\u9000\u51FA\u7801: ${E}): ${be.trim()}`))}),k.on("error",E=>{clearTimeout(we),I(new Error(`\u811A\u672C\u6267\u884C\u9519\u8BEF: ${E.message}`))}),t&&Object.keys(t).length>0&&(k.stdin?.write(JSON.stringify(t)),k.stdin?.end())})}finally{if(h&&p)try{await s.unlink(p),await s.rmdir(o.dirname(p))}catch{}}}getScriptExtension(e){switch(e){case"node":return".js";case"python":return".py";case"bash":return".sh";default:return".txt"}}buildScriptCommand(e,t){switch(e){case"node":return["node",t];case"python":return["python3",t];case"bash":return["bash",t];default:throw new Error(`\u4E0D\u652F\u6301\u7684\u811A\u672C\u89E3\u91CA\u5668: ${e}`)}}async callChainTool(e,t){let r=e.handler;this.logger.info(`[CustomMCP] \u8C03\u7528\u94FE\u5F0F\u5DE5\u5177: ${e.name}`,{tools:r.tools,mode:r.mode,error_handling:r.error_handling});try{let n;r.mode==="sequential"?n=await this.executeSequentialChain(r,t):n=await this.executeParallelChain(r,t);let s=n.flatMap(a=>a.content),o=n.some(a=>a.isError);return{content:s,isError:o}}catch(n){return this.logger.error(`[CustomMCP] \u94FE\u5F0F\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${e.name}`,n),{content:[{type:"text",text:`\u94FE\u5F0F\u5DE5\u5177\u8C03\u7528\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`}],isError:!0}}}delay(e){return new Promise(t=>setTimeout(t,e))}getToolInfo(e){return this.tools.get(e)}async executeSequentialChain(e,t){let r=[],n=t;for(let s of e.tools)try{this.logger.debug(`[CustomMCP] \u6267\u884C\u94FE\u5F0F\u5DE5\u5177\u4E2D\u7684: ${s}`);let o=await this.callToolRecursive(s,n);if(r.push(o),o.isError){if(e.error_handling==="stop")break;if(e.error_handling==="retry"){this.logger.warn(`[CustomMCP] \u5DE5\u5177 ${s} \u6267\u884C\u5931\u8D25\uFF0C\u5C1D\u8BD5\u91CD\u8BD5`);let a=await this.callToolRecursive(s,n);if(r[r.length-1]=a,a.isError)break}}if(!o.isError&&o.content.length>0){let a=o.content.filter(g=>g.type==="text").map(g=>g.text).join(`
26
+ `);if(a)try{n=JSON.parse(a)}catch{n={input:a,...t}}}}catch(o){let a={content:[{type:"text",text:`\u5DE5\u5177 ${s} \u6267\u884C\u5F02\u5E38: ${o instanceof Error?o.message:String(o)}`}],isError:!0};if(r.push(a),e.error_handling==="stop")break}return r}async executeParallelChain(e,t){let r=e.tools.map(async n=>{try{return this.logger.debug(`[CustomMCP] \u5E76\u884C\u6267\u884C\u94FE\u5F0F\u5DE5\u5177\u4E2D\u7684: ${n}`),await this.callToolRecursive(n,t)}catch(s){return{content:[{type:"text",text:`\u5DE5\u5177 ${n} \u6267\u884C\u5F02\u5E38: ${s instanceof Error?s.message:String(s)}`}],isError:!0}}});return Promise.all(r)}async callToolRecursive(e,t){if(this.tools.get(e))return this.callTool(e,t);throw new Error(`\u94FE\u5F0F\u5DE5\u5177\u4E2D\u5F15\u7528\u7684\u5DE5\u5177 ${e} \u4E0D\u5B58\u5728\u4E8E\u5F53\u524D CustomMCP \u5DE5\u5177\u96C6\u4E2D`)}async clearConsumedCache(e,t){try{let r=this.generateCacheKey(e,t),n=await this.loadExtendedCache();if(n.customMCPResults?.[r]){n.customMCPResults[r].consumed=!0;let s=n.customMCPResults[r];O(s)&&delete n.customMCPResults[r],await this.saveCache(n),this.logger.debug(`[CustomMCP] \u6E05\u7406\u5DF2\u6D88\u8D39\u7F13\u5B58: ${r}`)}}catch(r){this.logger.warn(`[CustomMCP] \u6E05\u7406\u7F13\u5B58\u5931\u8D25: ${r}`)}}async generateTaskId(e,t){return this.taskStateManager.generateTaskId(e,t)}async markTaskAsPending(e,t,r){try{let n=this.generateCacheKey(t,r),s={result:{content:[{type:"text",text:"\u5904\u7406\u4E2D..."}]},timestamp:new Date().toISOString(),ttl:this.CACHE_TTL,status:"pending",consumed:!1,taskId:e,retryCount:0};await this.updateCacheWithResult(n,s),this.taskStateManager.markTaskAsPending(e,t,r),this.activeTasks.set(e,{taskId:e,status:"pending",startTime:Date.now()}),this.logger.debug(`[CustomMCP] \u6807\u8BB0\u4EFB\u52A1\u4E3A\u5904\u7406\u4E2D: ${e}`)}catch(n){this.logger.warn(`[CustomMCP] \u6807\u8BB0\u4EFB\u52A1\u72B6\u6001\u5931\u8D25: ${n}`)}}async markTaskAsCompleted(e,t){try{let r=this.activeTasks.get(e);r&&(r.status="completed",r.endTime=new Date().toISOString(),r.result=t);let n=await this.loadExtendedCache();for(let[s,o]of Object.entries(n.customMCPResults||{}))if(o.taskId===e){o.status="completed",o.result=t,o.timestamp=new Date().toISOString(),o.consumed=!1;break}await this.saveCache(n),this.taskStateManager.markTaskAsCompleted(e,t),this.logger.debug(`[CustomMCP] \u6807\u8BB0\u4EFB\u52A1\u4E3A\u5DF2\u5B8C\u6210: ${e}`)}catch(r){this.logger.warn(`[CustomMCP] \u66F4\u65B0\u4EFB\u52A1\u72B6\u6001\u5931\u8D25: ${r}`)}}async markTaskAsFailed(e,t){try{let r=await this.loadExtendedCache();for(let[s,o]of Object.entries(r.customMCPResults||{}))if(o.taskId===e){o.status="failed",o.result={content:[{type:"text",text:`\u4EFB\u52A1\u5931\u8D25: ${t.message}`}]},o.timestamp=new Date().toISOString(),o.consumed=!0;break}await this.saveCache(r),this.taskStateManager.markTaskAsFailed(e,t.message);let n=this.activeTasks.get(e);n&&(n.status="failed",n.endTime=new Date().toISOString(),n.error=t.message),this.logger.debug(`[CustomMCP] \u6807\u8BB0\u4EFB\u52A1\u4E3A\u5931\u8D25: ${e}`)}catch(r){this.logger.warn(`[CustomMCP] \u66F4\u65B0\u4EFB\u52A1\u72B6\u6001\u5931\u8D25: ${r}`)}}startCleanupTimer(){this.cleanupTimer=setInterval(()=>{this.cleanupExpiredCache().catch(e=>{this.logger.warn(`[CustomMCP] \u7F13\u5B58\u6E05\u7406\u5931\u8D25: ${e}`)})},this.CLEANUP_INTERVAL),this.logger.debug(`[CustomMCP] \u542F\u52A8\u7F13\u5B58\u6E05\u7406\u5B9A\u65F6\u5668\uFF0C\u95F4\u9694: ${this.CLEANUP_INTERVAL}ms`)}async cleanupExpiredCache(){try{let e=await this.loadExtendedCache(),t=!1,r=0;for(let[n,s]of Object.entries(e.customMCPResults||{}))O(s)&&(e.customMCPResults?.[n]&&delete e.customMCPResults[n],t=!0,r++,s.taskId&&this.activeTasks.delete(s.taskId));t&&(await this.saveCache(e),this.logger.debug(`[CustomMCP] \u6E05\u7406\u8FC7\u671F\u7F13\u5B58\u5B8C\u6210\uFF0C\u6E05\u7406\u4E86 ${r} \u4E2A\u6761\u76EE`))}catch(e){this.logger.warn(`[CustomMCP] \u6E05\u7406\u8FC7\u671F\u7F13\u5B58\u5931\u8D25: ${e}`)}}generateCacheKey(e,t){return R(e,t)}async loadExtendedCache(){try{return await this.cacheManager.loadExistingCache()}catch{return{version:"1.0.0",mcpServers:{},metadata:{lastGlobalUpdate:new Date().toISOString(),totalWrites:0,createdAt:new Date().toISOString()},customMCPResults:{}}}}async updateCacheWithResult(e,t){try{let r=await this.loadExtendedCache();r.customMCPResults||(r.customMCPResults={}),r.customMCPResults[e]=t,await this.saveCache(r)}catch(r){this.logger.warn(`[CustomMCP] \u66F4\u65B0\u7F13\u5B58\u5931\u8D25: ${r}`)}}async cacheResult(e,t,r){try{let n=this.generateCacheKey(e,t),s={result:r,timestamp:new Date().toISOString(),ttl:this.CACHE_TTL,status:"completed",consumed:!1,retryCount:0};await this.updateCacheWithResult(n,s),this.logger.debug(`[CustomMCP] \u7F13\u5B58\u5DE5\u5177\u7ED3\u679C: ${e}`)}catch(n){this.logger.warn(`[CustomMCP] \u7F13\u5B58\u7ED3\u679C\u5931\u8D25: ${n}`)}}async saveCache(e){try{await this.cacheManager.saveCache(e)}catch(t){this.logger.warn(`[CustomMCP] \u4FDD\u5B58\u7F13\u5B58\u5931\u8D25: ${t}`)}}stopCleanupTimer(){this.cleanupTimer&&(clearInterval(this.cleanupTimer),this.cleanupTimer=void 0,this.logger.info("[CustomMCP] \u505C\u6B62\u7F13\u5B58\u6E05\u7406\u5B9A\u65F6\u5668"))}cleanup(){this.logger.info("[CustomMCP] \u6E05\u7406 CustomMCP \u5904\u7406\u5668\u8D44\u6E90"),this.stopCleanupTimer(),this.cacheLifecycleManager.stopAutoCleanup(),this.cacheLifecycleManager.cleanup(),this.taskStateManager.cleanup(),this.cacheManager.cleanup(),this.tools.clear(),this.activeTasks.clear()}getCacheLifecycleManager(){return this.cacheLifecycleManager}getTaskStateManager(){return this.taskStateManager}async getCacheStatistics(){return this.cacheManager.getCustomMCPStatistics()}getTaskStatistics(){return this.taskStateManager.getTaskStatistics()}getTaskStatus(e){return this.taskStateManager.getTaskStatus(e)}validateTaskId(e){return this.taskStateManager.validateTaskId(e)}restartStalledTasks(e=3e4){return this.taskStateManager.restartStalledTasks(e)}async manualCleanupCache(){return this.cacheManager.cleanupCustomMCPResults()}async validateSystemIntegrity(){let e=await this.cacheManager.loadExtendedCache(),t=this.cacheLifecycleManager.validateCacheIntegrity(e),r=this.taskStateManager.validateTaskIntegrity();return{cacheValid:t.isValid,taskValid:r.isValid,issues:[...t.issues,...r.issues]}}};import{Client as Pt}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as lt}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as gt}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as ut}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{EventSource as ht}from"eventsource";typeof global<"u"&&!global.EventSource&&(global.EventSource=ht);function pt(){return c}l(pt,"getLogger");function mt(i){switch(pt().debug(`[TransportFactory] \u521B\u5EFA ${i.type} transport for ${i.name}`),i.type){case"stdio":return dt(i);case"sse":return ft(i);case"streamable-http":return Ct(i);default:throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${i.type}`)}}l(mt,"createTransport");function dt(i){if(!i.command)throw new Error("stdio transport \u9700\u8981 command \u914D\u7F6E");return new gt({command:i.command,args:i.args||[],env:i.env})}l(dt,"createStdioTransport");function ft(i){if(!i.url)throw new Error("SSE transport \u9700\u8981 URL \u914D\u7F6E");let e=new URL(i.url),t=vt(i);return new lt(e,t)}l(ft,"createSSETransport");function Ct(i){if(!i.url)throw new Error("StreamableHTTP transport \u9700\u8981 URL \u914D\u7F6E");let e=new URL(i.url),t=St(i);return new ut(e,t)}l(Ct,"createStreamableHTTPTransport");function vt(i){let e={};return i.apiKey?e.headers={Authorization:`Bearer ${i.apiKey}`,...i.headers}:i.headers&&(e.headers=i.headers),e}l(vt,"createSSEOptions");function St(i){let e={};return i.apiKey?e.headers={Authorization:`Bearer ${i.apiKey}`,...i.headers}:i.headers&&(e.headers=i.headers),e}l(St,"createStreamableHTTPOptions");function Tt(i){if(!i.name||typeof i.name!="string")throw new Error("\u914D\u7F6E\u5FC5\u987B\u5305\u542B\u6709\u6548\u7684 name \u5B57\u6BB5");if(i.type&&!Object.values(Q).includes(i.type))throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${i.type}`);if(!i.type)throw new Error("\u4F20\u8F93\u7C7B\u578B\u672A\u8BBE\u7F6E\uFF0C\u8FD9\u5E94\u8BE5\u5728 inferTransportType \u4E2D\u5904\u7406");switch(i.type){case"stdio":if(!i.command)throw new Error("stdio \u7C7B\u578B\u9700\u8981 command \u5B57\u6BB5");break;case"sse":if(i.url===void 0||i.url===null)throw new Error(`${i.type} \u7C7B\u578B\u9700\u8981 url \u5B57\u6BB5`);break;case"streamable-http":if(i.url===void 0||i.url===null)throw new Error(`${i.type} \u7C7B\u578B\u9700\u8981 url \u5B57\u6BB5`);break;default:throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${i.type}`)}}l(Tt,"validateConfig");function Mt(){return["stdio","sse","streamable-http"]}l(Mt,"getSupportedTypes");var fe={create:mt,validateConfig:Tt,getSupportedTypes:Mt};var Q=(r=>(r.STDIO="stdio",r.SSE="sse",r.STREAMABLE_HTTP="streamable-http",r))(Q||{});var X=class{static{l(this,"MCPService")}config;client=null;transport=null;tools=new Map;connectionState="disconnected";reconnectOptions;reconnectState;logger;connectionTimeout=null;initialized=!1;eventBus=b();pingOptions;pingTimer=null;pingFailureCount=0;lastPingTime=null;isPinging=!1;constructor(e,t){this.logger=c;let r=this.inferTransportType(e);this.config=r,this.validateConfig(),this.reconnectOptions={enabled:!0,maxAttempts:10,initialInterval:3e3,maxInterval:3e4,backoffStrategy:"exponential",backoffMultiplier:1.5,timeout:1e4,jitter:!0,...t?.reconnect,...e.reconnect},this.pingOptions={enabled:!0,interval:3e4,timeout:5e3,maxFailures:3,startDelay:5e3,...e.ping},this.reconnectState={attempts:0,nextInterval:this.reconnectOptions.initialInterval,timer:null,lastError:null,isManualDisconnect:!1}}logWithTag(e,t,...r){let n=`[MCP-${this.config.name}] ${t}`;this.logger[e](n,...r)}inferTransportType(e){if(e.type)return e;this.logger.debug(`[MCP-${e.name}] \u81EA\u52A8\u63A8\u65AD\u4F20\u8F93\u7C7B\u578B...`);let t;if(e.command)t="stdio",this.logger.debug(`[MCP-${e.name}] \u68C0\u6D4B\u5230 command \u5B57\u6BB5\uFF0C\u63A8\u65AD\u4E3A stdio \u7C7B\u578B`);else if(e.url!==void 0&&e.url!==null)t=this.inferTransportTypeFromUrl(e.url,e.name);else throw new Error(`\u65E0\u6CD5\u4E3A\u670D\u52A1 ${e.name} \u63A8\u65AD\u4F20\u8F93\u7C7B\u578B\u3002\u8BF7\u663E\u5F0F\u6307\u5B9A type \u5B57\u6BB5\uFF0C\u6216\u63D0\u4F9B command/url \u914D\u7F6E`);return{type:t,...e}}inferTransportTypeFromUrl(e,t){try{let n=new URL(e).pathname;return n.endsWith("/sse")?(this.logger.info(`[MCP-${t}] \u68C0\u6D4B\u5230 URL \u8DEF\u5F84\u4EE5 /sse \u7ED3\u5C3E\uFF0C\u63A8\u65AD\u4E3A sse \u7C7B\u578B`),"sse"):n.endsWith("/mcp")?(this.logger.info(`[MCP-${t}] \u68C0\u6D4B\u5230 URL \u8DEF\u5F84\u4EE5 /mcp \u7ED3\u5C3E\uFF0C\u63A8\u65AD\u4E3A streamable-http \u7C7B\u578B`),"streamable-http"):(this.logger.info(`[MCP-${t}] URL \u8DEF\u5F84 ${n} \u4E0D\u5339\u914D\u7279\u5B9A\u89C4\u5219\uFF0C\u9ED8\u8BA4\u63A8\u65AD\u4E3A streamable-http \u7C7B\u578B`),"streamable-http")}catch(r){return this.logger.warn(`[MCP-${t}] URL \u89E3\u6790\u5931\u8D25\uFF0C\u9ED8\u8BA4\u63A8\u65AD\u4E3A streamable-http \u7C7B\u578B`,r),"streamable-http"}}validateConfig(){fe.validateConfig(this.config)}async connect(){if(this.connectionState==="connecting")throw new Error("\u8FDE\u63A5\u6B63\u5728\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u8FDE\u63A5\u5B8C\u6210");return this.cleanupConnection(),this.reconnectState.isManualDisconnect=!1,this.attemptConnection()}async attemptConnection(){return this.connectionState="connecting",this.logWithTag("debug",`\u6B63\u5728\u8FDE\u63A5 MCP \u670D\u52A1: ${this.config.name} (\u5C1D\u8BD5 ${this.reconnectState.attempts+1}/${this.reconnectOptions.maxAttempts})`),new Promise((e,t)=>{this.connectionTimeout=setTimeout(()=>{let r=new Error(`\u8FDE\u63A5\u8D85\u65F6 (${this.reconnectOptions.timeout}ms)`);this.handleConnectionError(r),t(r)},this.reconnectOptions.timeout);try{this.client=new Pt({name:`xiaozhi-${this.config.name}-client`,version:"1.0.0"},{capabilities:{tools:{}}}),this.transport=fe.create(this.config),this.client.connect(this.transport).then(async()=>{this.handleConnectionSuccess(),await this.refreshTools(),this.eventBus.emitEvent("mcp:service:connected",{serviceName:this.config.name,tools:this.getTools(),connectionTime:new Date}),e()}).catch(r=>{this.handleConnectionError(r),t(r)})}catch(r){this.handleConnectionError(r),t(r)}})}handleConnectionSuccess(){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.connectionState="connected",this.initialized=!0,this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.lastError=null,this.resetPingState(),this.logWithTag("info",`MCP \u670D\u52A1 ${this.config.name} \u8FDE\u63A5\u5DF2\u5EFA\u7ACB`),this.startPingMonitoring()}handleConnectionError(e){this.connectionState="disconnected",this.initialized=!1,this.reconnectState.lastError=e,this.logger.debug(`MCP \u670D\u52A1 ${this.config.name} \u8FDE\u63A5\u9519\u8BEF:`,e.message),this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.cleanupConnection(),this.eventBus.emitEvent("mcp:service:connection:failed",{serviceName:this.config.name,error:e,attempt:this.reconnectState.attempts}),this.shouldReconnect()?this.scheduleReconnect():(this.connectionState="failed",this.logger.warn(`${this.config.name} \u5DF2\u8FBE\u5230\u6700\u5927\u91CD\u8FDE\u6B21\u6570 (${this.reconnectOptions.maxAttempts})\uFF0C\u505C\u6B62\u91CD\u8FDE`))}shouldReconnect(){return this.reconnectOptions.enabled&&this.reconnectState.attempts<this.reconnectOptions.maxAttempts&&!this.reconnectState.isManualDisconnect}scheduleReconnect(){this.connectionState="reconnecting",this.reconnectState.attempts++,this.calculateNextInterval(),this.logger.debug(`${this.config.name} \u5C06\u5728 ${this.reconnectState.nextInterval}ms \u540E\u8FDB\u884C\u7B2C ${this.reconnectState.attempts} \u6B21\u91CD\u8FDE`),this.reconnectState.timer&&clearTimeout(this.reconnectState.timer),this.reconnectState.timer=setTimeout(async()=>{try{await this.attemptConnection()}catch{}},this.reconnectState.nextInterval)}calculateNextInterval(){let e;switch(this.reconnectOptions.backoffStrategy){case"fixed":e=this.reconnectOptions.initialInterval;break;case"linear":e=this.reconnectOptions.initialInterval+this.reconnectState.attempts*this.reconnectOptions.backoffMultiplier*1e3;break;case"exponential":e=this.reconnectOptions.initialInterval*this.reconnectOptions.backoffMultiplier**(this.reconnectState.attempts-1);break;default:e=this.reconnectOptions.initialInterval}if(e=Math.min(e,this.reconnectOptions.maxInterval),this.reconnectOptions.jitter){let t=e*.1,r=(Math.random()-.5)*2*t;e+=r}this.reconnectState.nextInterval=Math.max(e,1e3)}cleanupConnection(){if(this.stopPingMonitoring(),this.client){try{this.client.close().catch(()=>{})}catch{}this.client=null}this.transport=null,this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.initialized=!1}stopReconnect(){this.reconnectState.timer&&(clearTimeout(this.reconnectState.timer),this.reconnectState.timer=null)}async refreshTools(){if(!this.client)throw new Error("\u5BA2\u6237\u7AEF\u672A\u521D\u59CB\u5316");try{let t=(await this.client.listTools()).tools||[];this.tools.clear();for(let r of t)this.tools.set(r.name,r);this.logger.debug(`${this.config.name} \u670D\u52A1\u52A0\u8F7D\u4E86 ${t.length} \u4E2A\u5DE5\u5177: ${t.map(r=>r.name).join(", ")}`)}catch(e){throw this.logger.error(`${this.config.name} \u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25:`,e instanceof Error?e.message:String(e)),e}}async disconnect(){this.logger.info(`\u4E3B\u52A8\u65AD\u5F00 MCP \u670D\u52A1 ${this.config.name} \u8FDE\u63A5`),this.reconnectState.isManualDisconnect=!0,this.stopPingMonitoring(),this.stopReconnect(),this.cleanupConnection(),this.connectionState="disconnected",this.eventBus.emitEvent("mcp:service:disconnected",{serviceName:this.config.name,reason:"\u624B\u52A8\u65AD\u5F00",disconnectionTime:new Date})}async reconnect(){this.logger.info(`\u624B\u52A8\u91CD\u8FDE MCP \u670D\u52A1 ${this.config.name}`),this.stopReconnect(),this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.isManualDisconnect=!1,this.cleanupConnection(),await this.connect()}getTools(){return Array.from(this.tools.values())}async callTool(e,t){if(!this.client)throw new Error(`\u670D\u52A1 ${this.config.name} \u672A\u8FDE\u63A5`);if(!this.tools.has(e))throw new Error(`\u5DE5\u5177 ${e} \u5728\u670D\u52A1 ${this.config.name} \u4E2D\u4E0D\u5B58\u5728`);this.logger.debug(`\u8C03\u7528 ${this.config.name} \u670D\u52A1\u7684\u5DE5\u5177 ${e}\uFF0C\u53C2\u6570:`,JSON.stringify(t));try{let r=await this.client.callTool({name:e,arguments:t||{}});return this.logger.debug(`\u5DE5\u5177 ${e} \u8C03\u7528\u6210\u529F\uFF0C\u7ED3\u679C:`,`${JSON.stringify(r).substring(0,500)}...`),r}catch(r){throw this.logger.error(`\u5DE5\u5177 ${e} \u8C03\u7528\u5931\u8D25:`,r instanceof Error?r.message:String(r)),r}}getConfig(){return this.config}getStatus(){return{name:this.config.name,connected:this.connectionState==="connected",initialized:this.initialized,transportType:this.config.type,toolCount:this.tools.size,lastError:this.reconnectState.lastError?.message,reconnectAttempts:this.reconnectState.attempts,connectionState:this.connectionState,pingEnabled:this.pingOptions.enabled,lastPingTime:this.lastPingTime||void 0,pingFailureCount:this.pingFailureCount,isPinging:this.isPinging}}isConnected(){return this.connectionState==="connected"&&this.initialized}enableReconnect(){this.reconnectOptions.enabled=!0,this.logger.info(`${this.config.name} \u81EA\u52A8\u91CD\u8FDE\u5DF2\u542F\u7528`)}disableReconnect(){this.reconnectOptions.enabled=!1,this.stopReconnect(),this.logger.info(`${this.config.name} \u81EA\u52A8\u91CD\u8FDE\u5DF2\u7981\u7528`)}updateReconnectOptions(e){this.reconnectOptions={...this.reconnectOptions,...e},this.logger.info(`${this.config.name} \u91CD\u8FDE\u914D\u7F6E\u5DF2\u66F4\u65B0`,e)}getReconnectOptions(){return{...this.reconnectOptions}}resetReconnectState(){this.stopReconnect(),this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.lastError=null,this.logger.info(`${this.config.name} \u91CD\u8FDE\u72B6\u6001\u5DF2\u91CD\u7F6E`)}startPingMonitoring(){!this.pingOptions.enabled||this.pingTimer||!this.isConnected()||(this.logger.debug(`${this.config.name} \u542F\u52A8ping\u76D1\u63A7\uFF0C\u95F4\u9694: ${this.pingOptions.interval}ms`),setTimeout(()=>{this.isConnected()&&!this.pingTimer&&(this.pingTimer=setInterval(()=>{this.performPing()},this.pingOptions.interval))},this.pingOptions.startDelay))}stopPingMonitoring(){this.pingTimer&&(clearInterval(this.pingTimer),this.pingTimer=null,this.logger.debug(`${this.config.name} \u505C\u6B62ping\u76D1\u63A7`))}async performPing(){if(!this.client||this.isPinging||!this.isConnected())return;this.isPinging=!0;let e=performance.now();try{this.logger.debug(`${this.config.name} \u53D1\u9001ping\u8BF7\u6C42\uFF08\u901A\u8FC7listTools\u68C0\u6D4B\u8FDE\u63A5\uFF09`);let t=this.client.listTools(),r=new Promise((s,o)=>{setTimeout(()=>{o(new Error(`Ping\u8D85\u65F6 (${this.pingOptions.timeout}ms)`))},this.pingOptions.timeout)});await Promise.race([t,r]);let n=performance.now()-e;this.handlePingSuccess(n)}catch(t){let r=performance.now()-e;this.handlePingFailure(t,r)}finally{this.isPinging=!1}}handlePingSuccess(e){this.pingFailureCount=0,this.lastPingTime=new Date,this.logger.debug(`${this.config.name} ping\u6210\u529F\uFF0C\u5EF6\u8FDF: ${e.toFixed(2)}ms`)}handlePingFailure(e,t){if(this.pingFailureCount++,this.logger.warn(`${this.config.name} ping\u5931\u8D25 (${this.pingFailureCount}/${this.pingOptions.maxFailures})\uFF0C\u5EF6\u8FDF: ${t.toFixed(2)}ms\uFF0C\u9519\u8BEF: ${e.message}`),this.pingFailureCount>=this.pingOptions.maxFailures){this.logger.error(`${this.config.name} \u8FDE\u7EEDping\u5931\u8D25\u8FBE\u5230\u9608\u503C\uFF0C\u89E6\u53D1\u91CD\u8FDE\u673A\u5236`),this.stopPingMonitoring();let r=new Error(`Ping\u68C0\u6D4B\u5931\u8D25\uFF0C\u8FDE\u7EED\u5931\u8D25${this.pingFailureCount}\u6B21\uFF0C\u8FDE\u63A5\u53EF\u80FD\u5DF2\u65AD\u5F00`);this.handleConnectionError(r)}}resetPingState(){this.pingFailureCount=0,this.lastPingTime=null,this.isPinging=!1}enablePing(){this.pingOptions.enabled=!0,this.logger.info(`${this.config.name} ping\u76D1\u63A7\u5DF2\u542F\u7528`),this.isConnected()&&this.startPingMonitoring()}disablePing(){this.pingOptions.enabled=!1,this.stopPingMonitoring(),this.logger.info(`${this.config.name} ping\u76D1\u63A7\u5DF2\u7981\u7528`)}updatePingOptions(e){let t=this.pingOptions.enabled;this.pingOptions={...this.pingOptions,...e},this.logger.info(`${this.config.name} ping\u914D\u7F6E\u5DF2\u66F4\u65B0`,e),t!==this.pingOptions.enabled&&(this.pingOptions.enabled&&this.isConnected()?this.startPingMonitoring():this.pingOptions.enabled||this.stopPingMonitoring())}getPingOptions(){return{...this.pingOptions}}};var Z=class{static{l(this,"ToolSyncManager")}configManager;logger;syncLocks=new Map;eventBus=b();constructor(e,t=c){this.configManager=e,this.logger=t.withTag("ToolSync"),this.setupEventListeners()}setupEventListeners(){this.eventBus.onEvent("config:updated",async e=>{await this.handleConfigUpdated(e)}),this.eventBus.onEvent("mcp:server:added",async e=>{await this.handleMCPServerAdded(e)}),this.eventBus.onEvent("mcp:server:removed",async e=>{await this.handleMCPServerRemoved(e)})}async handleConfigUpdated(e){this.logger.debug("\u68C0\u6D4B\u5230\u914D\u7F6E\u66F4\u65B0\uFF0C\u68C0\u67E5\u5DE5\u5177\u540C\u6B65\u72B6\u6001");try{e.type==="customMCP"?this.logger.debug("customMCP\u914D\u7F6E\u5DF2\u66F4\u65B0\uFF0CCustomMCPHandler\u5C06\u81EA\u52A8\u5904\u7406"):e.type==="serverTools"&&e.serviceName?await this.handleServerToolsConfigUpdated(e.serviceName):await this.handleGeneralConfigUpdated()}catch(t){this.logger.error("\u914D\u7F6E\u66F4\u65B0\u540E\u7684\u5DE5\u5177\u540C\u6B65\u5931\u8D25:",t)}}async handleServerToolsConfigUpdated(e){this.logger.debug(`\u5904\u7406\u670D\u52A1 ${e} \u7684serverTools\u914D\u7F6E\u66F4\u65B0`);try{this.eventBus.emitEvent("tool-sync:server-tools-updated",{serviceName:e,timestamp:new Date})}catch(t){this.logger.error(`\u5904\u7406\u670D\u52A1 ${e} \u914D\u7F6E\u66F4\u65B0\u5931\u8D25:`,t)}}async handleGeneralConfigUpdated(){this.logger.info("\u5904\u7406\u901A\u7528\u914D\u7F6E\u66F4\u65B0\uFF0C\u68C0\u67E5\u6240\u6709\u670D\u52A1\u540C\u6B65\u72B6\u6001");try{this.eventBus.emitEvent("tool-sync:general-config-updated",{timestamp:new Date})}catch(e){this.logger.error("\u5904\u7406\u901A\u7528\u914D\u7F6E\u66F4\u65B0\u5931\u8D25:",e)}}async handleMCPServerAdded(e){this.logger.info(`\u5904\u7406MCP\u670D\u52A1\u6DFB\u52A0\u4E8B\u4EF6: ${e.serverName}`);try{setTimeout(async()=>{await this.triggerServiceToolSync(e.serverName)},1e3)}catch(t){this.logger.error(`\u5904\u7406\u670D\u52A1 ${e.serverName} \u6DFB\u52A0\u4E8B\u4EF6\u5931\u8D25:`,t)}}async triggerServiceToolSync(e){this.logger.info(`\u89E6\u53D1\u670D\u52A1 ${e} \u7684\u5DE5\u5177\u540C\u6B65`);try{this.eventBus.emitEvent("tool-sync:request-service-tools",{serviceName:e,timestamp:new Date})}catch(t){this.logger.error(`\u89E6\u53D1\u670D\u52A1 ${e} \u5DE5\u5177\u540C\u6B65\u5931\u8D25:`,t)}}async handleMCPServerRemoved(e){this.logger.info(`\u5904\u7406MCP\u670D\u52A1\u79FB\u9664\u4E8B\u4EF6: ${e.serverName}`);try{await this.removeServiceToolsFromCustomMCP(e.serverName,e.affectedTools)}catch(t){this.logger.error(`\u5904\u7406\u670D\u52A1 ${e.serverName} \u79FB\u9664\u4E8B\u4EF6\u5931\u8D25:`,t)}}async removeServiceToolsFromCustomMCP(e,t){this.logger.info(`\u4ECEcustomMCP\u4E2D\u79FB\u9664\u670D\u52A1 ${e} \u7684\u5DE5\u5177`);try{let r=this.configManager.getCustomMCPTools(),n=r.filter(o=>!o.name.startsWith(`${e}__`));if(n.length===r.length){this.logger.debug(`\u670D\u52A1 ${e} \u7684\u5DE5\u5177\u4E0D\u5728customMCP\u4E2D\uFF0C\u65E0\u9700\u79FB\u9664`);return}await this.configManager.updateCustomMCPTools(n);let s=r.length-n.length;this.logger.info(`\u6210\u529F\u4ECEcustomMCP\u4E2D\u79FB\u9664\u670D\u52A1 ${e} \u7684 ${s} \u4E2A\u5DE5\u5177`),this.eventBus.emitEvent("tool-sync:service-tools-removed",{serviceName:e,removedCount:s,timestamp:new Date})}catch(r){throw this.logger.error(`\u79FB\u9664\u670D\u52A1 ${e} \u5DE5\u5177\u5931\u8D25:`,r),r}}async syncToolsAfterConnection(e,t){if(this.syncLocks.has(e)){this.logger.debug(`\u670D\u52A1 ${e} \u6B63\u5728\u540C\u6B65\u4E2D\uFF0C\u8DF3\u8FC7`);return}let r=this.doSyncTools(e,t).finally(()=>{this.syncLocks.delete(e)});this.syncLocks.set(e,r),await r}async doSyncTools(e,t){try{this.logger.info(`\u5F00\u59CB\u540C\u6B65\u670D\u52A1 ${e} \u7684\u5DE5\u5177`);let r=this.configManager.getServerToolsConfig(e);if(!r){this.logger.debug(`\u670D\u52A1 ${e} \u65E0 mcpServerConfig \u914D\u7F6E\uFF0C\u8DF3\u8FC7\u540C\u6B65`);return}let n=this.getEnabledTools(r,t);if(n.length===0){this.logger.debug(`\u670D\u52A1 ${e} \u65E0\u542F\u7528\u5DE5\u5177\uFF0C\u8DF3\u8FC7\u540C\u6B65`);return}let s=this.configManager.getCustomMCPTools(),o=new Set(s.map(g=>g.name)),a=n.filter(g=>!o.has(`${e}__${g.name}`));if(a.length===0){this.logger.info(`\u670D\u52A1 ${e} \u7684\u542F\u7528\u5DE5\u5177\u5DF2\u5B58\u5728\u4E8E customMCP \u4E2D\uFF0C\u8DF3\u8FC7\u540C\u6B65`);return}await this.addToolsToCustomMCP(e,a),this.logger.info(`\u6210\u529F\u540C\u6B65\u670D\u52A1 ${e} \u7684 ${a.length} \u4E2A\u5DE5\u5177\u5230 customMCP`)}catch(r){this.logger.error(`\u540C\u6B65\u670D\u52A1 ${e} \u5DE5\u5177\u5931\u8D25:`,r),this.recordSyncError(e,r)}}getEnabledTools(e,t){let r=[];for(let n of t){let s=e[n.name];s&&s.enable!==!1&&r.push(n)}return r}async addToolsToCustomMCP(e,t){let r=t.map(n=>({name:`${e}__${n.name}`,description:n.description||"",inputSchema:n.inputSchema||{},handler:{type:"mcp",config:{serviceName:e,toolName:n.name}}}));await this.configManager.addCustomMCPTools(r),await this.syncToolStats(e,t)}recordSyncError(e,t){let r={serviceName:e,error:t instanceof Error?t.message:String(t),timestamp:new Date().toISOString(),type:t instanceof Error?t.constructor.name:"UnknownError"};this.logger.error("\u540C\u6B65\u9519\u8BEF\u8BB0\u5F55:",r)}getSyncLocks(){return Array.from(this.syncLocks.keys())}clearSyncLocks(){this.syncLocks.clear(),this.logger.debug("\u5DF2\u6E05\u7406\u6240\u6709\u540C\u6B65\u9501")}async syncToolStats(e,t){try{let r=this.configManager.getServerToolsConfig(e);if(!r){this.logger.debug(`\u670D\u52A1 ${e} \u65E0 mcpServerConfig \u914D\u7F6E\uFF0C\u8DF3\u8FC7\u7EDF\u8BA1\u4FE1\u606F\u540C\u6B65`);return}let n=this.configManager.getCustomMCPTools(),s=new Map(n.map(o=>[o.name,o]));for(let o of t){let a=`${e}__${o.name}`,g=s.get(a),u=r[o.name];if(g&&u&&(!g.stats||!g.stats.usageCount&&!g.stats.lastUsedTime)){let p={};u.usageCount!==void 0&&(p.usageCount=u.usageCount),u.lastUsedTime&&(p.lastUsedTime=u.lastUsedTime),Object.keys(p).length>0&&(await this.updateCustomMCPToolStats(a,p),this.logger.debug(`\u5DF2\u540C\u6B65\u5DE5\u5177 ${a} \u7684\u7EDF\u8BA1\u4FE1\u606F: ${JSON.stringify(p)}`))}}}catch(r){this.logger.error(`\u540C\u6B65\u670D\u52A1 ${e} \u5DE5\u5177\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25:`,r instanceof Error?r.message:String(r))}}async updateCustomMCPToolStats(e,t){try{let r=this.configManager.getCustomMCPTools(),n=r.findIndex(a=>a.name===e);if(n===-1){this.logger.warn(`\u5DE5\u5177 ${e} \u4E0D\u5B58\u5728\u4E8E customMCP \u4E2D`);return}let s=[...r],o=s[n];o.stats||(o.stats={}),t.usageCount!==void 0&&(o.stats.usageCount=t.usageCount),t.lastUsedTime!==void 0&&(o.stats.lastUsedTime=t.lastUsedTime),await this.configManager.updateCustomMCPTools(s)}catch(r){throw this.logger.error(`\u66F4\u65B0\u5DE5\u5177 ${e} \u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25:`,r instanceof Error?r.message:String(r)),r}}};import*as U from"fs";import*as D from"path";import{realpathSync as yt}from"fs";import{tmpdir as bt}from"os";import d from"path";import{fileURLToPath as Ae}from"url";var Ce={NAME:"xiaozhi-mcp-service",DEFAULT_PORT:3e3,DEFAULT_WEB_UI_PORT:9999,PID_FILE:"xiaozhi.pid",LOG_FILE:"xiaozhi.log"},F={FILE_NAMES:["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"],DEFAULT_FILE:"xiaozhi.config.default.json",DIR_ENV_VAR:"XIAOZHI_CONFIG_DIR"},B={WORK_DIR:".xiaozhi",TEMPLATES_DIR:"templates",LOGS_DIR:"logs"},De={GENERAL_ERROR:"GENERAL_ERROR",CONFIG_ERROR:"CONFIG_ERROR",SERVICE_ERROR:"SERVICE_ERROR",VALIDATION_ERROR:"VALIDATION_ERROR",FILE_ERROR:"FILE_ERROR",PROCESS_ERROR:"PROCESS_ERROR",NETWORK_ERROR:"NETWORK_ERROR",PERMISSION_ERROR:"PERMISSION_ERROR"};import C from"fs";import P from"path";var ve=class i extends Error{constructor(t,r,n=1,s){super(t);this.code=r;this.exitCode=n;this.suggestions=s;this.name="CLIError",Error.captureStackTrace&&Error.captureStackTrace(this,i)}static{l(this,"CLIError")}static withSuggestions(t,r,n){return new i(t,r,1,n)}};var m=class i extends ve{static{l(this,"FileError")}constructor(e,t,r){let n=t?`${e}: ${t}`:e;super(n,De.FILE_ERROR,1,r),this.name="FileError"}static notFound(e){return new i("\u6587\u4EF6\u4E0D\u5B58\u5728",e,["\u68C0\u67E5\u6587\u4EF6\u8DEF\u5F84\u662F\u5426\u6B63\u786E"])}static permissionDenied(e){return new i("\u6743\u9650\u4E0D\u8DB3",e,["\u68C0\u67E5\u6587\u4EF6\u6743\u9650\u6216\u4F7F\u7528\u7BA1\u7406\u5458\u6743\u9650\u8FD0\u884C"])}static alreadyExists(e){return new i("\u6587\u4EF6\u5DF2\u5B58\u5728",e,["\u4F7F\u7528\u4E0D\u540C\u7684\u6587\u4EF6\u540D\u6216\u5220\u9664\u73B0\u6709\u6587\u4EF6"])}};var j=class i{static{l(this,"FileUtils")}static exists(e){try{return C.existsSync(e)}catch{return!1}}static ensureDir(e){try{C.existsSync(e)||C.mkdirSync(e,{recursive:!0})}catch{throw new m("\u65E0\u6CD5\u521B\u5EFA\u76EE\u5F55",e)}}static readFile(e,t="utf8"){try{if(!i.exists(e))throw m.notFound(e);return C.readFileSync(e,t)}catch(r){throw r instanceof m?r:new m("\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6",e)}}static writeFile(e,t,r){try{if(!r?.overwrite&&i.exists(e))throw m.alreadyExists(e);let n=P.dirname(e);i.ensureDir(n),C.writeFileSync(e,t,"utf8")}catch(n){throw n instanceof m?n:new m("\u65E0\u6CD5\u5199\u5165\u6587\u4EF6",e)}}static copyFile(e,t,r){try{if(!i.exists(e))throw m.notFound(e);if(!r?.overwrite&&i.exists(t))throw m.alreadyExists(t);let n=P.dirname(t);i.ensureDir(n),C.copyFileSync(e,t)}catch(n){throw n instanceof m?n:new m("\u65E0\u6CD5\u590D\u5236\u6587\u4EF6",e)}}static deleteFile(e){try{i.exists(e)&&C.unlinkSync(e)}catch{throw new m("\u65E0\u6CD5\u5220\u9664\u6587\u4EF6",e)}}static copyDirectory(e,t,r={}){try{if(!i.exists(e))throw m.notFound(e);i.ensureDir(t);let n=C.readdirSync(e);for(let s of n){if(r.exclude?.includes(s))continue;let o=P.join(e,s),a=P.join(t,s);C.statSync(o).isDirectory()?r.recursive!==!1&&i.copyDirectory(o,a,r):i.copyFile(o,a,{overwrite:r.overwrite})}}catch(n){throw n instanceof m?n:new m("\u65E0\u6CD5\u590D\u5236\u76EE\u5F55",e)}}static deleteDirectory(e,t={}){try{i.exists(e)&&C.rmSync(e,{recursive:t.recursive??!0,force:!0})}catch{throw new m("\u65E0\u6CD5\u5220\u9664\u76EE\u5F55",e)}}static getFileInfo(e){try{if(!i.exists(e))throw m.notFound(e);let t=C.statSync(e);return{size:t.size,isFile:t.isFile(),isDirectory:t.isDirectory(),mtime:t.mtime,ctime:t.ctime}}catch(t){throw t instanceof m?t:new m("\u65E0\u6CD5\u83B7\u53D6\u6587\u4EF6\u4FE1\u606F",e)}}static listDirectory(e,t={}){try{if(!i.exists(e))throw m.notFound(e);let r=C.readdirSync(e),n=[];for(let s of r){if(!t.includeHidden&&s.startsWith("."))continue;let o=P.join(e,s);if(n.push(o),t.recursive&&C.statSync(o).isDirectory()){let a=i.listDirectory(o,t);n=n.concat(a)}}return n}catch(r){throw r instanceof m?r:new m("\u65E0\u6CD5\u5217\u51FA\u76EE\u5F55\u5185\u5BB9",e)}}static createTempFile(e="xiaozhi-",t=".tmp"){let r=process.env.TMPDIR||process.env.TEMP||"/tmp",n=Date.now(),s=Math.random().toString(36).substring(2),o=`${e}${n}-${s}${t}`;return P.join(r,o)}static checkPermissions(e,t=C.constants.R_OK|C.constants.W_OK){try{return C.accessSync(e,t),!0}catch{return!1}}static getExtension(e){return P.extname(e).toLowerCase()}static getBaseName(e){return P.basename(e,P.extname(e))}static normalizePath(e){return P.normalize(e)}static resolvePath(e,t){return t?P.resolve(t,e):P.resolve(e)}};var ee=class i{static{l(this,"PathUtils")}static getPidFile(){let e=process.env[F.DIR_ENV_VAR]||process.cwd();return d.join(e,`.${Ce.NAME}.pid`)}static getLogFile(e){let t=e||process.cwd();return d.join(t,Ce.LOG_FILE)}static getConfigDir(){return process.env[F.DIR_ENV_VAR]||process.cwd()}static getWorkDir(){let e=i.getConfigDir();return d.join(e,B.WORK_DIR)}static getTemplatesDir(){let e=Ae(import.meta.url),t=d.dirname(e);return[d.join(t,B.TEMPLATES_DIR),d.join(t,"..","..","..",B.TEMPLATES_DIR),d.join(t,"..","..","..","..",B.TEMPLATES_DIR)]}static findTemplatesDir(){let e=i.getTemplatesDir();for(let t of e)if(j.exists(t))return t;return null}static getTemplatePath(e){let t=i.findTemplatesDir();if(!t)return null;let r=d.join(t,e);return j.exists(r)?r:null}static getScriptDir(){let e=Ae(import.meta.url);return d.dirname(e)}static getProjectRoot(){let e=i.getScriptDir();return d.join(e,"..","..","..")}static getDistDir(){let e=i.getProjectRoot();return d.join(e,"dist")}static getRelativePath(e){let t=i.getProjectRoot();return d.relative(t,e)}static resolveConfigPath(e){let t=i.getConfigDir();if(e)return d.join(t,`xiaozhi.config.${e}`);for(let r of F.FILE_NAMES){let n=d.join(t,r);if(j.exists(n))return n}return d.join(t,F.FILE_NAMES[2])}static getDefaultConfigPath(){let e=i.getProjectRoot();return d.join(e,F.DEFAULT_FILE)}static validatePath(e){return!d.normalize(e).includes("..")}static ensurePathWithin(e,t){let r=d.resolve(t,e),n=d.resolve(t);if(!r.startsWith(n))throw new Error(`\u8DEF\u5F84 ${e} \u8D85\u51FA\u4E86\u5141\u8BB8\u7684\u8303\u56F4`);return r}static getExecutablePath(e){let t=process.argv[1];if(!t)return d.join(process.cwd(),`${e}.js`);let r;try{r=yt(t)}catch{r=t}let n=d.dirname(r);return d.join(n,`${e}.js`)}static getMcpServerProxyPath(){return i.getExecutablePath("mcpServerProxy")}static getWebServerStandalonePath(){return i.getExecutablePath("WebServerStandalone")}static createSafePath(...e){let t=d.join(...e),r=d.normalize(t);if(r.includes("..")||r.includes("~"))throw new Error(`\u4E0D\u5B89\u5168\u7684\u8DEF\u5F84: ${r}`);return r}static getTempDir(){return process.env.TMPDIR||process.env.TEMP||bt()}static getHomeDir(){return process.env.HOME||process.env.USERPROFILE||""}};import te from"pino";var re=class{static{l(this,"ToolCallLogger")}pinoLogger;maxRecords;logFilePath;constructor(e,t){if(this.maxRecords=e.maxRecords??100,e.logFilePath)this.logFilePath=D.resolve(D.normalize(e.logFilePath));else{let r=t||ee.getTempDir();this.logFilePath=D.join(D.normalize(r),"tool-calls.jsonl")}this.pinoLogger=this.createPinoLogger(this.logFilePath),c.debug(`ToolCallLogger \u521D\u59CB\u5316: maxRecords=${this.maxRecords}, path=${this.logFilePath}`)}createPinoLogger(e){let t=[];t.push({level:"info",stream:{write:l(r=>{try{let n=JSON.parse(r),s=this.formatConsoleMessage(n);c.info(`[\u5DE5\u5177\u8C03\u7528] ${s}`)}catch{c.info(`[\u5DE5\u5177\u8C03\u7528] ${r.trim()}`)}},"write")}});try{t.push({level:"info",stream:te.destination({dest:e,sync:!0,append:!0,mkdir:!0})})}catch(r){c.error("\u65E0\u6CD5\u521B\u5EFA\u5DE5\u5177\u8C03\u7528\u65E5\u5FD7\u6587\u4EF6:",r)}return te({level:"info",timestamp:te.stdTimeFunctions?.isoTime||(()=>`,"time":${Date.now()}`),formatters:{level:l((r,n)=>({level:n}),"level")},base:null},te.multistream(t,{dedupe:!0}))}formatConsoleMessage(e){let t=e.toolName||"\u672A\u77E5\u5DE5\u5177",r=e.success!==!1,n=e.duration?` (${e.duration}ms)`:"";return`${r?"\u2705":"\u274C"} ${t}${n}`}async cleanupOldRecords(){try{if(!U.existsSync(this.logFilePath))return;let t=U.readFileSync(this.logFilePath,"utf8").trim().split(`
27
+ `).filter(o=>o.trim()!=="");if(t.length<=this.maxRecords)return;let r=t.length-this.maxRecords+1,n=t.slice(r),s=n.join(`
28
+ `)+(n.length>0?`
29
+ `:"");U.writeFileSync(this.logFilePath,s,"utf8"),c.debug(`\u5DF2\u6E05\u7406 ${r} \u6761\u65E7\u7684\u5DE5\u5177\u8C03\u7528\u8BB0\u5F55\uFF0C\u4FDD\u7559\u6700\u65B0 ${this.maxRecords} \u6761`)}catch(e){c.error("\u6E05\u7406\u65E7\u5DE5\u5177\u8C03\u7528\u8BB0\u5F55\u5931\u8D25:",e)}}async recordToolCall(e){try{await this.cleanupOldRecords(),this.pinoLogger.info(e,e.toolName)}catch(t){c.error("\u8BB0\u5F55\u5DE5\u5177\u8C03\u7528\u5931\u8D25:",t)}}getLogFilePath(){return this.logFilePath}getMaxRecords(){return this.maxRecords}};var ne=class{static{l(this,"MCPServiceManager")}services=new Map;configs={};logger;tools=new Map;customMCPHandler;cacheManager;toolSyncManager;eventBus=b();toolCallLogger;retryTimers=new Map;failedServices=new Set;constructor(e){this.logger=c,this.configs=e||{};let r=process.env.NODE_ENV==="test"||process.env.VITEST==="true"?`/tmp/xiaozhi-test-${Date.now()}-${Math.random().toString(36).substring(2,11)}/xiaozhi.cache.json`:void 0;this.cacheManager=new N(r),this.customMCPHandler=new Y,this.toolSyncManager=new Z(f,this.logger);let n=f.getToolCallLogConfig(),s=f.getConfigDir();this.toolCallLogger=new re(n,s),this.setupEventListeners()}setupEventListeners(){this.eventBus.onEvent("mcp:service:connected",async e=>{await this.handleServiceConnected(e)}),this.eventBus.onEvent("mcp:service:disconnected",async e=>{await this.handleServiceDisconnected(e)}),this.eventBus.onEvent("mcp:service:connection:failed",async e=>{await this.handleServiceConnectionFailed(e)}),this.eventBus.onEvent("tool-sync:server-tools-updated",async e=>{await this.handleServerToolsUpdated(e)}),this.eventBus.onEvent("tool-sync:general-config-updated",async e=>{await this.handleGeneralConfigUpdated(e)})}async handleServiceConnected(e){this.logger.debug(`\u670D\u52A1 ${e.serviceName} \u8FDE\u63A5\u6210\u529F\uFF0C\u5F00\u59CB\u5DE5\u5177\u540C\u6B65`);try{let t=this.services.get(e.serviceName);if(t){let r=t.getTools();this.toolSyncManager&&await this.toolSyncManager.syncToolsAfterConnection(e.serviceName,r),await this.refreshCustomMCPHandlerPublic(),this.logger.info(`\u670D\u52A1 ${e.serviceName} \u5DE5\u5177\u540C\u6B65\u5B8C\u6210`)}}catch(t){this.logger.error(`\u540C\u6B65\u670D\u52A1 ${e.serviceName} \u5DE5\u5177\u5931\u8D25:`,t)}}async handleServiceDisconnected(e){this.logger.info(`\u670D\u52A1 ${e.serviceName} \u65AD\u5F00\u8FDE\u63A5\uFF0C\u539F\u56E0: ${e.reason||"\u672A\u77E5"}`);try{await this.refreshToolsCache(),await this.refreshCustomMCPHandlerPublic(),this.logger.info(`\u670D\u52A1 ${e.serviceName} \u65AD\u5F00\u8FDE\u63A5\u5904\u7406\u5B8C\u6210`)}catch(t){this.logger.error(`\u670D\u52A1 ${e.serviceName} \u65AD\u5F00\u8FDE\u63A5\u5904\u7406\u5931\u8D25:`,t)}}async handleServiceConnectionFailed(e){try{await this.refreshCustomMCPHandlerPublic()}catch(t){this.logger.error("\u5237\u65B0CustomMCPHandler\u5931\u8D25:",t)}}async handleServerToolsUpdated(e){this.logger.debug(`\u5904\u7406\u670D\u52A1 ${e.serviceName} \u7684serverTools\u914D\u7F6E\u66F4\u65B0`);try{let t=this.services.get(e.serviceName);if(t?.isConnected()){let r=t.getTools();this.toolSyncManager&&await this.toolSyncManager.syncToolsAfterConnection(e.serviceName,r),await this.refreshCustomMCPHandlerPublic(),this.logger.info(`\u670D\u52A1 ${e.serviceName} \u914D\u7F6E\u66F4\u65B0\u540C\u6B65\u5B8C\u6210`)}}catch(t){this.logger.error(`\u5904\u7406\u670D\u52A1 ${e.serviceName} \u914D\u7F6E\u66F4\u65B0\u5931\u8D25:`,t)}}async handleGeneralConfigUpdated(e){this.logger.info("\u5904\u7406\u901A\u7528\u914D\u7F6E\u66F4\u65B0\uFF0C\u68C0\u67E5\u6240\u6709\u5DF2\u8FDE\u63A5\u670D\u52A1");try{for(let[t,r]of this.services)if(r.isConnected()){let n=r.getTools();this.toolSyncManager&&await this.toolSyncManager.syncToolsAfterConnection(t,n)}await this.refreshCustomMCPHandlerPublic(),this.logger.info("\u901A\u7528\u914D\u7F6E\u66F4\u65B0\u540C\u6B65\u5B8C\u6210")}catch(t){this.logger.error("\u5904\u7406\u901A\u7528\u914D\u7F6E\u66F4\u65B0\u5931\u8D25:",t)}}async startAllServices(){this.logger.debug("[MCPManager] \u6B63\u5728\u542F\u52A8\u6240\u6709 MCP \u670D\u52A1...");try{this.customMCPHandler.initialize(),this.logger.debug("[MCPManager] CustomMCP \u5904\u7406\u5668\u521D\u59CB\u5316\u5B8C\u6210")}catch(a){this.logger.error("[MCPManager] CustomMCP \u5904\u7406\u5668\u521D\u59CB\u5316\u5931\u8D25:",a)}let e=Object.entries(this.configs);if(e.length===0){this.logger.warn("[MCPManager] \u6CA1\u6709\u914D\u7F6E\u4EFB\u4F55 MCP \u670D\u52A1\uFF0C\u8BF7\u4F7F\u7528 addServiceConfig() \u6DFB\u52A0\u670D\u52A1\u914D\u7F6E");return}this.logger.info(`[MCPManager] \u5F00\u59CB\u5E76\u884C\u542F\u52A8 ${e.length} \u4E2A MCP \u670D\u52A1`);let t=e.map(async([a])=>{try{return await this.startService(a),{serviceName:a,success:!0,error:null}}catch(g){return{serviceName:a,success:!1,error:g instanceof Error?g.message:String(g)}}}),r=await Promise.allSettled(t),n=0,s=0,o=[];for(let a of r)a.status==="fulfilled"?a.value.success?n++:(s++,o.push(a.value.serviceName)):s++;this.logger.info(`[MCPManager] \u670D\u52A1\u542F\u52A8\u5B8C\u6210 - \u6210\u529F: ${n}, \u5931\u8D25: ${s}`),o.length>0&&(this.logger.warn(`[MCPManager] \u4EE5\u4E0B\u670D\u52A1\u542F\u52A8\u5931\u8D25: ${o.join(", ")}`),s===e.length&&this.logger.warn("[MCPManager] \u6240\u6709 MCP \u670D\u52A1\u542F\u52A8\u5931\u8D25\uFF0C\u4F46\u7CFB\u7EDF\u5C06\u7EE7\u7EED\u8FD0\u884C\u4EE5\u4FBF\u91CD\u8BD5")),o.length>0&&this.scheduleFailedServicesRetry(o)}async startService(e){let t=this.configs[e];if(!t)throw new Error(`\u672A\u627E\u5230\u670D\u52A1\u914D\u7F6E: ${e}`);try{this.services.has(e)&&await this.stopService(e);let r=new X(t);await r.connect(),this.services.set(e,r),await this.refreshToolsCache();let n=r.getTools();this.logger.debug(`[MCPManager] ${e} \u670D\u52A1\u542F\u52A8\u6210\u529F\uFF0C\u52A0\u8F7D\u4E86 ${n.length} \u4E2A\u5DE5\u5177:`,n.map(s=>s.name).join(", "))}catch(r){throw this.logger.error(`[MCPManager] \u542F\u52A8 ${e} \u670D\u52A1\u5931\u8D25:`,r.message),this.services.delete(e),r}}async stopService(e){this.logger.info(`[MCPManager] \u505C\u6B62 MCP \u670D\u52A1: ${e}`);let t=this.services.get(e);if(!t){this.logger.warn(`[MCPManager] \u670D\u52A1 ${e} \u4E0D\u5B58\u5728\u6216\u672A\u542F\u52A8`);return}try{await t.disconnect(),this.services.delete(e),await this.refreshToolsCache(),this.logger.info(`[MCPManager] ${e} \u670D\u52A1\u5DF2\u505C\u6B62`)}catch(r){throw this.logger.error(`[MCPManager] \u505C\u6B62 ${e} \u670D\u52A1\u5931\u8D25:`,r.message),r}}async refreshToolsCache(){this.tools.clear();for(let[e,t]of this.services)if(t.isConnected()){let r=t.getTools(),n=this.configs[e];n&&this.cacheManager.writeCacheEntry(e,r,n).then(()=>{this.logger.debug(`[MCPManager] \u5DF2\u5C06 ${e} \u5DE5\u5177\u5217\u8868\u5199\u5165\u7F13\u5B58`)}).catch(s=>{this.logger.warn(`[MCPManager] \u5199\u5165\u7F13\u5B58\u5931\u8D25: ${e}, \u9519\u8BEF: ${s instanceof Error?s.message:String(s)}`)});for(let s of r){let o=`${e}__${s.name}`;this.tools.set(o,{serviceName:e,originalName:s.name,tool:s})}}await this.syncToolsConfigToFile()}getAllTools(){let e=[];for(let[r,n]of this.services)try{if(n.isConnected()){let s=n.getTools();for(let o of s)try{if(!f.isToolEnabled(r,o.name))continue;let g=`${r}__${o.name}`;e.push({name:g,description:o.description||"",inputSchema:o.inputSchema,serviceName:r,originalName:o.name})}catch(a){this.logger.warn(`[MCPManager] \u68C0\u67E5\u5DE5\u5177 ${r}.${o.name} \u542F\u7528\u72B6\u6001\u5931\u8D25\uFF0C\u8DF3\u8FC7\u8BE5\u5DE5\u5177:`,a)}}}catch(s){this.logger.warn(`[MCPManager] \u83B7\u53D6\u670D\u52A1 ${r} \u7684\u5DE5\u5177\u5931\u8D25\uFF0C\u8DF3\u8FC7\u8BE5\u670D\u52A1:`,s)}let t=[];try{t=this.customMCPHandler.getTools(),this.logger.debug(`[MCPManager] \u6210\u529F\u83B7\u53D6 ${t.length} \u4E2A customMCP \u5DE5\u5177`)}catch(r){this.logger.warn("[MCPManager] \u83B7\u53D6 CustomMCP \u5DE5\u5177\u5931\u8D25\uFF0C\u5C06\u53EA\u8FD4\u56DE\u6807\u51C6 MCP \u5DE5\u5177:",r),t=[]}for(let r of t)try{e.push({name:r.name,description:r.description||"",inputSchema:r.inputSchema,serviceName:this.getServiceNameForTool(r),originalName:r.name})}catch(n){this.logger.warn(`[MCPManager] \u5904\u7406 CustomMCP \u5DE5\u5177 ${r.name} \u5931\u8D25\uFF0C\u8DF3\u8FC7\u8BE5\u5DE5\u5177:`,n)}return this.logger.debug(`[MCPManager] \u6210\u529F\u83B7\u53D6 ${e.length} \u4E2A\u53EF\u7528\u5DE5\u5177`),e}getServiceNameForTool(e){return e.handler?.type==="mcp"?e.handler.config.serviceName:"customMCP"}getLogServerName(e){if(!e?.handler)return"custom";switch(e.handler.type){case"mcp":return e.handler.config.serviceName;case"coze":return"coze";case"dify":return"dify";case"n8n":return"n8n";default:return"custom"}}getOriginalToolName(e,t,r){return t?t.handler?.type==="mcp"?t.handler.config.toolName:e:r?.originalName||e}async callTool(e,t){let r=Date.now(),n="unknown",s=e;try{let o;if(this.customMCPHandler.hasTool(e)){let a=this.customMCPHandler.getToolInfo(e);n=this.getLogServerName(a),s=this.getOriginalToolName(e,a),a?.handler?.type==="mcp"?(o=await this.callMCPTool(e,a.handler.config,t),this.updateToolStatsSafe(e,a.handler.config.serviceName,a.handler.config.toolName,!0)):(o=await this.customMCPHandler.callTool(e,t),this.logger.info(`[MCPManager] CustomMCP \u5DE5\u5177 ${e} \u8C03\u7528\u6210\u529F`),this.updateToolStatsSafe(e,"customMCP",e,!0))}else{let a=this.tools.get(e);if(!a)throw new Error(`\u672A\u627E\u5230\u5DE5\u5177: ${e}`);n=a.serviceName,s=a.originalName;let g=this.services.get(a.serviceName);if(!g)throw new Error(`\u670D\u52A1 ${a.serviceName} \u4E0D\u53EF\u7528`);if(!g.isConnected())throw new Error(`\u670D\u52A1 ${a.serviceName} \u672A\u8FDE\u63A5`);o=await g.callTool(a.originalName,t||{}),this.logger.debug(`[MCPManager] \u5DE5\u5177 ${e} \u8C03\u7528\u6210\u529F\uFF0C\u7ED3\u679C:`,o),this.updateToolStatsSafe(e,a.serviceName,a.originalName,!0)}return this.toolCallLogger.recordToolCall({toolName:s,serverName:n,arguments:t,result:o,success:o.isError!==!0,duration:Date.now()-r}),o}catch(o){if(this.toolCallLogger.recordToolCall({toolName:s,serverName:n,arguments:t,result:null,success:!1,duration:Date.now()-r,error:o instanceof Error?o.message:String(o)}),this.customMCPHandler.hasTool(e)){let a=this.customMCPHandler.getToolInfo(e);a?.handler?.type==="mcp"?this.updateToolStatsSafe(e,a.handler.config.serviceName,a.handler.config.toolName,!1):(this.updateToolStatsSafe(e,"customMCP",e,!1),this.logger.error(`[MCPManager] CustomMCP \u5DE5\u5177 ${e} \u8C03\u7528\u5931\u8D25:`,o.message))}else{let a=this.tools.get(e);a&&(this.updateToolStatsSafe(e,a.serviceName,a.originalName,!1),this.logger.error(`[MCPManager] \u5DE5\u5177 ${e} \u8C03\u7528\u5931\u8D25:`,o.message))}throw o}}async updateToolStats(e,t,r,n){try{let s=new Date().toISOString();n?(await this.updateCustomMCPToolStats(e,s),t!=="customMCP"&&await this.updateMCPServerToolStats(t,r,s),this.logger.debug(`[MCPManager] \u5DF2\u66F4\u65B0\u5DE5\u5177 ${e} \u7684\u7EDF\u8BA1\u4FE1\u606F`)):(await this.updateCustomMCPToolLastUsedTime(e,s),t!=="customMCP"&&await this.updateMCPServerToolLastUsedTime(t,r,s),this.logger.debug(`[MCPManager] \u5DF2\u66F4\u65B0\u5DE5\u5177 ${e} \u7684\u5931\u8D25\u8C03\u7528\u7EDF\u8BA1\u4FE1\u606F`))}catch(s){throw this.logger.error(`[MCPManager] \u66F4\u65B0\u5DE5\u5177 ${e} \u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25:`,s),s}}async updateToolStatsSafe(e,t,r,n){try{await this.updateToolStats(e,t,r,n)}catch(s){let o=n?"\u7EDF\u8BA1\u4FE1\u606F":"\u5931\u8D25\u7EDF\u8BA1\u4FE1\u606F";this.logger.warn(`[MCPManager] \u66F4\u65B0\u5DE5\u5177 ${e} ${o}\u5931\u8D25:`,s)}}async updateCustomMCPToolStats(e,t){try{await f.updateToolUsageStatsWithLock(e,!0),this.logger.debug(`[MCPManager] \u5DF2\u66F4\u65B0 customMCP \u5DE5\u5177 ${e} \u4F7F\u7528\u7EDF\u8BA1`)}catch(r){throw this.logger.error(`[MCPManager] \u66F4\u65B0 customMCP \u5DE5\u5177 ${e} \u7EDF\u8BA1\u5931\u8D25:`,r),r}}async updateCustomMCPToolLastUsedTime(e,t){try{await f.updateToolUsageStatsWithLock(e,!1),this.logger.debug(`[MCPManager] \u5DF2\u66F4\u65B0 customMCP \u5DE5\u5177 ${e} \u6700\u540E\u4F7F\u7528\u65F6\u95F4`)}catch(r){throw this.logger.error(`[MCPManager] \u66F4\u65B0 customMCP \u5DE5\u5177 ${e} \u6700\u540E\u4F7F\u7528\u65F6\u95F4\u5931\u8D25:`,r),r}}async updateMCPServerToolStats(e,t,r){try{await f.updateMCPServerToolStatsWithLock(e,t,r,!0),this.logger.debug(`[MCPManager] \u5DF2\u66F4\u65B0 MCP \u670D\u52A1\u5DE5\u5177 ${e}/${t} \u7EDF\u8BA1`)}catch(n){throw this.logger.error(`[MCPManager] \u66F4\u65B0 MCP \u670D\u52A1\u5DE5\u5177 ${e}/${t} \u7EDF\u8BA1\u5931\u8D25:`,n),n}}async updateMCPServerToolLastUsedTime(e,t,r){try{await f.updateMCPServerToolStatsWithLock(e,t,r,!1),this.logger.debug(`[MCPManager] \u5DF2\u66F4\u65B0 MCP \u670D\u52A1\u5DE5\u5177 ${e}/${t} \u6700\u540E\u4F7F\u7528\u65F6\u95F4`)}catch(n){throw this.logger.error(`[MCPManager] \u66F4\u65B0 MCP \u670D\u52A1\u5DE5\u5177 ${e}/${t} \u6700\u540E\u4F7F\u7528\u65F6\u95F4\u5931\u8D25:`,n),n}}async callMCPTool(e,t,r){let{serviceName:n,toolName:s}=t;this.logger.debug(`[MCPManager] \u8C03\u7528 MCP \u540C\u6B65\u5DE5\u5177 ${e} -> ${n}.${s}`);let o=this.services.get(n);if(!o)throw new Error(`\u670D\u52A1 ${n} \u4E0D\u53EF\u7528`);if(!o.isConnected())throw new Error(`\u670D\u52A1 ${n} \u672A\u8FDE\u63A5`);try{let a=await o.callTool(s,r||{});return this.logger.debug(`[MCPManager] MCP \u540C\u6B65\u5DE5\u5177 ${e} \u8C03\u7528\u6210\u529F`),a}catch(a){throw this.logger.error(`[MCPManager] MCP \u540C\u6B65\u5DE5\u5177 ${e} \u8C03\u7528\u5931\u8D25:`,a.message),a}}hasTool(e){return this.customMCPHandler.hasTool(e)?!0:this.tools.has(e)}async stopAllServices(){this.logger.info("[MCPManager] \u6B63\u5728\u505C\u6B62\u6240\u6709 MCP \u670D\u52A1..."),this.stopAllServiceRetries();for(let[e,t]of this.services)try{await t.disconnect(),this.logger.info(`[MCPManager] ${e} \u670D\u52A1\u5DF2\u505C\u6B62`)}catch(r){this.logger.error(`[MCPManager] \u505C\u6B62 ${e} \u670D\u52A1\u5931\u8D25:`,r.message)}try{this.customMCPHandler.cleanup(),this.logger.info("[MCPManager] CustomMCP \u5904\u7406\u5668\u5DF2\u6E05\u7406")}catch(e){this.logger.error("[MCPManager] CustomMCP \u5904\u7406\u5668\u6E05\u7406\u5931\u8D25:",e)}try{f.clearAllStatsUpdateLocks(),this.logger.info("[MCPManager] \u7EDF\u8BA1\u66F4\u65B0\u9501\u5DF2\u6E05\u7406")}catch(e){this.logger.error("[MCPManager] \u6E05\u7406\u7EDF\u8BA1\u66F4\u65B0\u9501\u5931\u8D25:",e)}this.services.clear(),this.tools.clear(),this.logger.info("[MCPManager] \u6240\u6709 MCP \u670D\u52A1\u5DF2\u505C\u6B62")}getStatus(){let e=0,t=[];try{e=this.customMCPHandler.getToolCount(),t=this.customMCPHandler.getToolNames(),this.logger.debug(`[MCPManager] \u6210\u529F\u83B7\u53D6 customMCP \u72B6\u6001: ${e} \u4E2A\u5DE5\u5177`)}catch(a){this.logger.warn("[MCPManager] \u83B7\u53D6 CustomMCP \u72B6\u6001\u5931\u8D25\uFF0C\u5C06\u53EA\u5305\u542B\u6807\u51C6 MCP \u5DE5\u5177:",a),e=0,t=[]}let r=this.tools.size+e,s=[...Array.from(this.tools.keys()),...t],o={services:{},totalTools:r,availableTools:s};for(let[a,g]of this.services){let u=g.getStatus();o.services[a]={connected:u.connected,clientName:`xiaozhi-${a}-client`}}return e>0&&(o.services.customMCP={connected:!0,clientName:"xiaozhi-customMCP-handler"}),o}getStatsUpdateInfo(){try{let e=f.getStatsUpdateLocks();return{activeLocks:e,totalLocks:e.length}}catch(e){return this.logger.warn("[MCPManager] \u83B7\u53D6\u7EDF\u8BA1\u66F4\u65B0\u76D1\u63A7\u4FE1\u606F\u5931\u8D25:",e),{activeLocks:[],totalLocks:0}}}getService(e){return this.services.get(e)}getConnectedServices(){let e=[];for(let[t,r]of this.services)r.isConnected()&&e.push(t);return e}async refreshCustomMCPHandler(){try{this.logger.debug("\u91CD\u65B0\u521D\u59CB\u5316CustomMCPHandler"),await this.customMCPHandler.reinitialize(),this.logger.debug("CustomMCPHandler\u91CD\u65B0\u521D\u59CB\u5316\u5B8C\u6210")}catch(e){throw this.logger.error("CustomMCPHandler\u91CD\u65B0\u521D\u59CB\u5316\u5931\u8D25:",e),e}}async refreshCustomMCPHandlerPublic(){return this.refreshCustomMCPHandler()}getAllServices(){return new Map(this.services)}getCustomMCPHandler(){return this.customMCPHandler}hasCustomMCPTool(e){try{return this.customMCPHandler.hasTool(e)}catch(t){return this.logger.warn(`[MCPManager] \u68C0\u67E5 CustomMCP \u5DE5\u5177 ${e} \u662F\u5426\u5B58\u5728\u5931\u8D25:`,t),!1}}getCustomMCPTools(){try{return this.customMCPHandler.getTools()}catch(e){return this.logger.warn("[MCPManager] \u83B7\u53D6 CustomMCP \u5DE5\u5177\u5217\u8868\u5931\u8D25\uFF0C\u8FD4\u56DE\u7A7A\u6570\u7EC4:",e),[]}}enhanceServiceConfig(e){let t={...e};try{if(e.type==="sse"&&e.url&&e.url.includes("modelscope")){let r=f.getModelScopeApiKey();if(r)t.apiKey=r,this.logger.info(`[MCPManager] \u4E3A ${e.name} \u670D\u52A1\u6DFB\u52A0 ModelScope API Key`);else throw this.logger.warn(`[MCPManager] ${e.name} \u670D\u52A1\u9700\u8981 ModelScope API Key\uFF0C\u4F46\u672A\u5728\u914D\u7F6E\u4E2D\u627E\u5230`),new Error(`ModelScope SSE \u670D\u52A1 ${e.name} \u9700\u8981 API Key\uFF0C\u8BF7\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u8BBE\u7F6E modelscope.apiKey`)}return t}catch(r){throw this.logger.error(`[MCPManager] \u914D\u7F6E\u589E\u5F3A\u5931\u8D25: ${e.name}`,r),r}}addServiceConfig(e,t){let r,n;if(typeof e=="string"&&t)n=e,r=t;else if(typeof e=="object")n=e.name,r=e;else throw new Error("Invalid arguments for addServiceConfig");let s=this.enhanceServiceConfig(r);this.configs[n]=s,this.logger.debug(`[MCPManager] \u5DF2\u6DFB\u52A0\u670D\u52A1\u914D\u7F6E: ${n}`)}updateServiceConfig(e,t){let r=this.enhanceServiceConfig(t);this.configs[e]=r,this.logger.debug(`[MCPManager] \u5DF2\u66F4\u65B0\u5E76\u589E\u5F3A\u670D\u52A1\u914D\u7F6E: ${e}`)}removeServiceConfig(e){delete this.configs[e],this.logger.debug(`[MCPManager] \u5DF2\u79FB\u9664\u670D\u52A1\u914D\u7F6E: ${e}`)}async syncToolsConfigToFile(){try{this.logger.debug("[MCPManager] \u5F00\u59CB\u540C\u6B65\u5DE5\u5177\u914D\u7F6E\u5230\u914D\u7F6E\u6587\u4EF6");let e=f.getMcpServerConfig();for(let[t,r]of this.services){if(!r.isConnected())continue;let n=r.getTools();if(n.length===0)continue;let s=e[t]?.tools||{},o={};for(let h of n){let S=s[h.name];S?o[h.name]={...S,description:h.description||S.description||""}:o[h.name]={description:h.description||"",enable:!0}}let a=n.map(h=>h.name),u=Object.keys(s).filter(h=>!a.includes(h));if(u.length>0&&this.logger.info(`[MCPManager] \u68C0\u6D4B\u5230\u670D\u52A1 ${t} \u79FB\u9664\u4E86 ${u.length} \u4E2A\u5DE5\u5177: ${u.join(", ")}`),this.hasToolsConfigChanged(s,o)){f.updateServerToolsConfig(t,o);let h=Object.keys(o).filter(T=>!s[T]),S=Object.keys(o).filter(T=>{let y=s[T],I=o[T];return y&&y.description!==I.description});this.logger.debug(`[MCPManager] \u5DF2\u540C\u6B65\u670D\u52A1 ${t} \u7684\u5DE5\u5177\u914D\u7F6E:`),h.length>0&&this.logger.debug(` - \u65B0\u589E\u5DE5\u5177: ${h.join(", ")}`),S.length>0&&this.logger.debug(` - \u66F4\u65B0\u5DE5\u5177: ${S.join(", ")}`),u.length>0&&this.logger.debug(` - \u79FB\u9664\u5DE5\u5177: ${u.join(", ")}`)}}this.logger.debug("[MCPManager] \u5DE5\u5177\u914D\u7F6E\u540C\u6B65\u5B8C\u6210")}catch(e){this.logger.error("[MCPManager] \u540C\u6B65\u5DE5\u5177\u914D\u7F6E\u5230\u914D\u7F6E\u6587\u4EF6\u5931\u8D25:",e)}}hasToolsConfigChanged(e,t){let r=Object.keys(e),n=Object.keys(t);if(r.length!==n.length)return!0;let s=n.filter(a=>!r.includes(a)),o=r.filter(a=>!n.includes(a));if(s.length>0||o.length>0)return!0;for(let a of r){let g=e[a],u=t[a];if(g.description!==u.description)return!0}return!1}scheduleFailedServicesRetry(e){if(e.length===0)return;this.logger.info(`[MCPManager] \u5B89\u6392 ${e.length} \u4E2A\u5931\u8D25\u670D\u52A1\u7684\u91CD\u8BD5`);let t=3e4;for(let r of e)this.failedServices.add(r),this.scheduleServiceRetry(r,t)}scheduleServiceRetry(e,t){let r=this.retryTimers.get(e);r&&(clearTimeout(r),this.retryTimers.delete(e)),this.logger.debug(`[MCPManager] \u5B89\u6392\u670D\u52A1 ${e} \u5728 ${t}ms \u540E\u91CD\u8BD5`);let n=setTimeout(async()=>{this.retryTimers.delete(e),await this.retryFailedService(e)},t);this.retryTimers.set(e,n)}async retryFailedService(e){if(this.failedServices.has(e))try{await this.startService(e),this.failedServices.delete(e),this.logger.info(`[MCPManager] \u670D\u52A1 ${e} \u91CD\u8BD5\u542F\u52A8\u6210\u529F`);try{await this.refreshCustomMCPHandlerPublic()}catch(t){this.logger.error("[MCPManager] \u5237\u65B0CustomMCPHandler\u5931\u8D25:",t)}}catch(t){this.logger.error(`[MCPManager] \u670D\u52A1 ${e} \u91CD\u8BD5\u542F\u52A8\u5931\u8D25:`,t.message);let r=this.getRetryDelay(e),n=Math.min(r*2,3e5);this.logger.debug(`[MCPManager] \u670D\u52A1 ${e} \u4E0B\u6B21\u91CD\u8BD5\u5C06\u5728 ${n}ms \u540E\u8FDB\u884C`),this.scheduleServiceRetry(e,n)}}getRetryDelay(e){return 3e4+e.split("").reduce((r,n)=>r+n.charCodeAt(0),0)%6e4}stopServiceRetry(e){let t=this.retryTimers.get(e);t&&(clearTimeout(t),this.retryTimers.delete(e),this.logger.debug(`[MCPManager] \u5DF2\u505C\u6B62\u670D\u52A1 ${e} \u7684\u91CD\u8BD5`)),this.failedServices.delete(e)}stopAllServiceRetries(){this.logger.info("[MCPManager] \u505C\u6B62\u6240\u6709\u670D\u52A1\u91CD\u8BD5");for(let[e,t]of this.retryTimers)clearTimeout(t),this.logger.debug(`[MCPManager] \u5DF2\u505C\u6B62\u670D\u52A1 ${e} \u7684\u91CD\u8BD5`);this.retryTimers.clear(),this.failedServices.clear()}getFailedServices(){return Array.from(this.failedServices)}isServiceFailed(e){return this.failedServices.has(e)}getRetryStats(){return{failedServices:Array.from(this.failedServices),activeRetries:Array.from(this.retryTimers.keys()),totalFailed:this.failedServices.size,totalActiveRetries:this.retryTimers.size}}};var x=class{static{l(this,"TransportAdapter")}logger;messageHandler;connectionId;config;state="disconnected";constructor(e,t){this.messageHandler=e,this.config=t,this.connectionId=this.generateConnectionId(),this.logger=c}async handleIncomingMessage(e){try{this.logger.debug(`\u5904\u7406\u63A5\u6536\u5230\u7684\u6D88\u606F: ${e.method}`,e);let t=await this.messageHandler.handleMessage(e);t!==null?(this.logger.debug("\u53D1\u9001\u54CD\u5E94\u6D88\u606F:",t),await this.sendMessage(t)):this.logger.debug("\u6536\u5230\u901A\u77E5\u6D88\u606F\uFF0C\u65E0\u9700\u54CD\u5E94")}catch(t){this.logger.error(`\u5904\u7406\u6D88\u606F\u65F6\u51FA\u9519: ${e.method}`,t);let r=this.createErrorResponse(t,e.id);await this.sendMessage(r)}}createErrorResponse(e,t){let r=-32603;return e.message.includes("\u672A\u627E\u5230\u5DE5\u5177")||e.message.includes("\u672A\u77E5\u7684\u65B9\u6CD5")?r=-32601:(e.message.includes("\u53C2\u6570")||e.message.includes("\u4E0D\u80FD\u4E3A\u7A7A"))&&(r=-32602),{jsonrpc:"2.0",error:{code:r,message:e.message,data:{stack:e.stack}},id:t||null}}generateConnectionId(){let e=Date.now(),t=Math.random().toString(36).substr(2,9);return`${this.config.name}_${e}_${t}`}getConnectionId(){return this.connectionId}getState(){return this.state}setState(e){let t=this.state;this.state=e,t!==e&&(this.logger.info(`\u8FDE\u63A5\u72B6\u6001\u53D8\u66F4: ${t} -> ${e}`),this.onStateChange(t,e))}onStateChange(e,t){}getConfig(){return{...this.config}}getMessageHandler(){return this.messageHandler}parseMessage(e){try{let t=JSON.parse(e.trim());return!t.jsonrpc||t.jsonrpc!=="2.0"?(this.logger.warn("\u6536\u5230\u975E JSON-RPC 2.0 \u683C\u5F0F\u7684\u6D88\u606F",t),null):t.method?t:(this.logger.warn("\u6536\u5230\u6CA1\u6709 method \u5B57\u6BB5\u7684\u6D88\u606F",t),null)}catch(t){return this.logger.error("\u89E3\u6790 JSON \u6D88\u606F\u5931\u8D25",{data:e,error:t}),null}}serializeMessage(e){try{return JSON.stringify(e)}catch(t){this.logger.error("\u5E8F\u5217\u5316\u6D88\u606F\u5931\u8D25",{message:e,error:t});let r=t instanceof Error?t.message:String(t);throw new Error(`\u6D88\u606F\u5E8F\u5217\u5316\u5931\u8D25: ${r}`)}}validateMessage(e){return!(!e||typeof e!="object"||e.jsonrpc!=="2.0"||e.method&&typeof e.method!="string"||!e.method&&!e.result&&!e.error)}createTimeoutPromise(e,t){return Promise.race([e,new Promise((r,n)=>{setTimeout(()=>{n(new Error(`\u64CD\u4F5C\u8D85\u65F6: ${t}ms`))},t)})])}};var Se=class{static{l(this,"ToolRegistry")}serviceManager;logger;constructor(e){this.serviceManager=e,this.logger=c}async initialize(){this.logger.info("\u521D\u59CB\u5316\u5DE5\u5177\u6CE8\u518C\u8868")}getAllTools(){return this.serviceManager.getAllTools().map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema,serviceName:e.serviceName,originalName:e.originalName}))}findTool(e){return this.getAllTools().find(r=>r.name===e)||null}hasTool(e){return this.findTool(e)!==null}},Te=class extends He{static{l(this,"ConnectionManager")}connections=new Map;logger;constructor(){super(),this.logger=c}async initialize(){this.logger.info("\u521D\u59CB\u5316\u8FDE\u63A5\u7BA1\u7406\u5668")}registerConnection(e,t,r){let n={id:e,transportName:t,state:r,connectedAt:new Date,lastActivity:new Date};this.connections.set(e,n),this.emit("connectionRegistered",n),this.logger.debug(`\u8FDE\u63A5\u5DF2\u6CE8\u518C: ${e} (${t})`)}updateConnectionState(e,t){let r=this.connections.get(e);r&&(r.state=t,r.lastActivity=new Date,this.emit("connectionStateChanged",r),this.logger.debug(`\u8FDE\u63A5\u72B6\u6001\u66F4\u65B0: ${e} -> ${t}`))}removeConnection(e){let t=this.connections.get(e);t&&(this.connections.delete(e),this.emit("connectionRemoved",t),this.logger.debug(`\u8FDE\u63A5\u5DF2\u79FB\u9664: ${e}`))}getAllConnections(){return Array.from(this.connections.values())}getActiveConnectionCount(){return Array.from(this.connections.values()).filter(e=>e.state==="connected").length}async closeAllConnections(){this.logger.info("\u5173\u95ED\u6240\u6709\u8FDE\u63A5"),this.connections.clear(),this.emit("allConnectionsClosed")}},se=class extends He{static{l(this,"UnifiedMCPServer")}serviceManager;messageHandler;transportAdapters=new Map;toolRegistry;connectionManager;isRunning=!1;logger;config;constructor(e={}){super(),this.config={name:"UnifiedMCPServer",enableLogging:!0,logLevel:"info",maxConnections:100,connectionTimeout:3e4,...e},this.logger=c,this.serviceManager=new ne,this.messageHandler=new K(this.serviceManager),this.toolRegistry=new Se(this.serviceManager),this.connectionManager=new Te,this.setupEventListeners()}setupEventListeners(){this.connectionManager.on("connectionRegistered",e=>{this.emit("connectionRegistered",e)}),this.connectionManager.on("connectionStateChanged",e=>{this.emit("connectionStateChanged",e)}),this.connectionManager.on("connectionRemoved",e=>{this.emit("connectionRemoved",e)})}async initialize(){this.logger.info("\u521D\u59CB\u5316\u7EDF\u4E00 MCP \u670D\u52A1\u5668");try{await this.serviceManager.startAllServices(),await this.toolRegistry.initialize(),await this.connectionManager.initialize(),this.logger.debug("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u521D\u59CB\u5316\u5B8C\u6210"),this.emit("initialized")}catch(e){throw this.logger.error("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u521D\u59CB\u5316\u5931\u8D25",e),e}}async registerTransport(e,t){if(this.transportAdapters.has(e))throw new Error(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u5DF2\u5B58\u5728`);this.logger.info(`\u6CE8\u518C\u4F20\u8F93\u9002\u914D\u5668: ${e}`);try{await t.initialize(),this.transportAdapters.set(e,t),this.connectionManager.registerConnection(t.getConnectionId(),e,t.getState()),this.logger.info(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u6CE8\u518C\u6210\u529F`),this.emit("transportRegistered",{name:e,adapter:t})}catch(r){throw this.logger.error(`\u6CE8\u518C\u4F20\u8F93\u9002\u914D\u5668 ${e} \u5931\u8D25`,r),r}}async start(){if(this.isRunning)throw new Error("\u670D\u52A1\u5668\u5DF2\u5728\u8FD0\u884C");this.logger.info("\u542F\u52A8\u7EDF\u4E00 MCP \u670D\u52A1\u5668");try{for(let[e,t]of this.transportAdapters)try{await t.start(),this.connectionManager.updateConnectionState(t.getConnectionId(),t.getState()),this.logger.info(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u542F\u52A8\u6210\u529F`)}catch(r){throw this.logger.error(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u542F\u52A8\u5931\u8D25`,r),r}this.isRunning=!0,this.logger.info("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u542F\u52A8\u6210\u529F"),this.emit("started")}catch(e){throw this.logger.error("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u542F\u52A8\u5931\u8D25",e),e}}async stop(){if(this.isRunning){this.logger.info("\u505C\u6B62\u7EDF\u4E00 MCP \u670D\u52A1\u5668");try{for(let[e,t]of this.transportAdapters)try{await t.stop(),this.connectionManager.updateConnectionState(t.getConnectionId(),t.getState()),this.logger.info(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u505C\u6B62\u6210\u529F`)}catch(r){this.logger.error(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u505C\u6B62\u5931\u8D25`,r)}await this.connectionManager.closeAllConnections(),await this.serviceManager.stopAllServices(),this.isRunning=!1,this.logger.info("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u505C\u6B62\u6210\u529F"),this.emit("stopped")}catch(e){throw this.logger.error("\u7EDF\u4E00 MCP \u670D\u52A1\u5668\u505C\u6B62\u5931\u8D25",e),e}}}getServiceManager(){return this.serviceManager}getToolRegistry(){return this.toolRegistry}getConnectionManager(){return this.connectionManager}getMessageHandler(){return this.messageHandler}getStatus(){return{isRunning:this.isRunning,transportCount:this.transportAdapters.size,activeConnections:this.connectionManager.getActiveConnectionCount(),toolCount:this.toolRegistry.getAllTools().length,config:this.config}}getTransportAdapters(){return new Map(this.transportAdapters)}isServerRunning(){return this.isRunning}};import{randomUUID as wt}from"crypto";import Pe from"express";var oe=class extends x{static{l(this,"HTTPAdapter")}app;server=null;clients=new Map;port;host;enableSSE;enableRPC;corsOrigin;maxClients;constructor(e,t={name:"http"}){super(e,t),console.warn("[\u5DF2\u5E9F\u5F03] HTTPAdapter \u5C06\u5728 v2.0.0 \u4E2D\u79FB\u9664\u3002\u8BF7\u4F7F\u7528 WebServer \u7684 /mcp \u7AEF\u70B9\u66FF\u4EE3\u3002"),this.port=t.port||3e3,this.host=t.host||"0.0.0.0",this.enableSSE=t.enableSSE!==!1,this.enableRPC=t.enableRPC!==!1,this.corsOrigin=t.corsOrigin||"*",this.maxClients=t.maxClients!==void 0?t.maxClients:100,this.app=Pe(),this.setupMiddleware()}async initialize(){this.logger.info("\u521D\u59CB\u5316 HTTP \u9002\u914D\u5668");try{this.setupRoutes(),this.setState("connecting"),this.logger.info("HTTP \u9002\u914D\u5668\u521D\u59CB\u5316\u5B8C\u6210")}catch(e){throw this.logger.error("HTTP \u9002\u914D\u5668\u521D\u59CB\u5316\u5931\u8D25",e),this.setState("error"),e}}async start(){if(this.server){this.logger.warn("HTTP \u670D\u52A1\u5668\u5DF2\u5728\u8FD0\u884C");return}return this.logger.info(`\u542F\u52A8 HTTP \u670D\u52A1\u5668\u5728 ${this.host}:${this.port}`),new Promise((e,t)=>{this.server=this.app.listen(this.port,this.host,()=>{this.setState("connected"),this.logger.info("HTTP \u9002\u914D\u5668\u542F\u52A8\u6210\u529F"),this.logger.info(`- RPC \u7AEF\u70B9: http://${this.host}:${this.port}/rpc`),this.enableSSE&&(this.logger.info(`- SSE \u7AEF\u70B9: http://${this.host}:${this.port}/sse`),this.logger.info(`- \u6D88\u606F\u7AEF\u70B9: http://${this.host}:${this.port}/messages`)),e()}),this.server?.on("error",r=>{this.logger.error("HTTP \u670D\u52A1\u5668\u9519\u8BEF",r),this.setState("error"),t(r)})})}async stop(){if(this.server)return this.logger.info("\u505C\u6B62 HTTP \u670D\u52A1\u5668"),new Promise(e=>{for(let t of this.clients.values())t.response.end();this.clients.clear(),this.server.close(()=>{this.server=null,this.setState("disconnected"),this.logger.info("HTTP \u670D\u52A1\u5668\u5DF2\u505C\u6B62"),e()})})}async sendMessage(e){this.clients.size>0&&this.broadcastToClients(e)}setupMiddleware(){this.app.use(Pe.json({limit:"10mb"})),this.app.use(Pe.urlencoded({extended:!0})),this.app.use((e,t,r)=>{t.header("Access-Control-Allow-Origin",this.corsOrigin),t.header("Access-Control-Allow-Methods","GET, POST, OPTIONS"),t.header("Access-Control-Allow-Headers","Content-Type, Accept"),t.header("Cache-Control","no-cache"),r()}),this.app.use((e,t,r)=>{this.logger.debug(`${e.method} ${e.path}`,{query:e.query,headers:e.headers}),r()})}setupRoutes(){this.enableSSE&&(this.app.get("/sse",this.handleSSE.bind(this)),this.app.post("/messages",this.handleMessages.bind(this))),this.enableRPC&&this.app.post("/rpc",this.handleRPC.bind(this)),this.app.get("/status",this.handleStatus.bind(this)),this.app.get("/health",this.handleHealth.bind(this))}handleSSE(e,t){if(this.clients.size>=this.maxClients){t.status(503).json({error:"\u670D\u52A1\u5668\u7E41\u5FD9\uFF0C\u5BA2\u6237\u7AEF\u8FDE\u63A5\u6570\u5DF2\u8FBE\u4E0A\u9650",maxClients:this.maxClients});return}let r=Date.now().toString(),n=wt();t.setHeader("Content-Type","text/event-stream"),t.setHeader("Cache-Control","no-cache, no-transform"),t.setHeader("Connection","keep-alive"),t.setHeader("X-Accel-Buffering","no");let s={id:r,sessionId:n,response:t,connectedAt:new Date};this.clients.set(n,s),this.logger.info(`SSE \u5BA2\u6237\u7AEF\u5DF2\u8FDE\u63A5: ${r} (\u4F1A\u8BDD: ${n})`),t.write(`event: endpoint
30
+ data: /messages?sessionId=${n}
31
+
32
+ `),e.on("close",()=>{this.clients.delete(n),this.logger.info(`SSE \u5BA2\u6237\u7AEF\u5DF2\u65AD\u5F00\u8FDE\u63A5: ${r} (\u4F1A\u8BDD: ${n})`)}),e.on("error",o=>{this.logger.error(`SSE \u5BA2\u6237\u7AEF\u8FDE\u63A5\u9519\u8BEF: ${r}`,o),this.clients.delete(n)})}async handleMessages(e,t){try{let r=e.query.sessionId,n=e.body;if(this.logger.debug(`\u6536\u5230 SSE \u6D88\u606F (\u4F1A\u8BDD: ${r}):`,n),!r||!this.clients.has(r)){t.status(400).json({jsonrpc:"2.0",error:{code:-32600,message:"\u65E0\u6548\u6216\u7F3A\u5C11 sessionId"},id:n.id});return}let s=await this.messageHandler.handleMessage(n);this.logger.debug("SSE \u6D88\u606F\u5904\u7406\u54CD\u5E94:",s);let o=this.clients.get(r);o&&s!==null&&this.sendToClient(o,s),t.status(202).send()}catch(r){this.logger.error("\u5904\u7406 SSE \u6D88\u606F\u65F6\u51FA\u9519",r),t.status(500).json({jsonrpc:"2.0",error:{code:-32603,message:r.message}})}}async handleRPC(e,t){try{let r=e.body;this.logger.debug("\u6536\u5230 RPC \u6D88\u606F:",r);let n=await this.messageHandler.handleMessage(r);t.json(n)}catch(r){this.logger.error("\u5904\u7406 RPC \u6D88\u606F\u65F6\u51FA\u9519",r),t.status(500).json({jsonrpc:"2.0",error:{code:-32603,message:r.message},id:e.body?.id||null})}}handleStatus(e,t){t.json({status:"ok",mode:"mcp-server",serviceManager:"running",clients:this.clients.size,tools:0,maxClients:this.maxClients,enableSSE:this.enableSSE,enableRPC:this.enableRPC,uptime:process.uptime()})}handleHealth(e,t){t.json({status:"ok",mode:"mcp-server",timestamp:new Date().toISOString()})}sendToClient(e,t){try{let r=this.serializeMessage(t);e.response.write(`data: ${r}
33
+
34
+ `),this.logger.debug(`\u6D88\u606F\u5DF2\u53D1\u9001\u5230\u5BA2\u6237\u7AEF ${e.id}`,{sessionId:e.sessionId,messageId:t.id})}catch(r){this.logger.error(`\u5411\u5BA2\u6237\u7AEF ${e.id} \u53D1\u9001\u6D88\u606F\u5931\u8D25`,r),this.clients.delete(e.sessionId)}}broadcastToClients(e){for(let t of this.clients.values())this.sendToClient(t,e)}getStatus(){return{isRunning:this.server!==null,port:this.port,host:this.host,clientCount:this.clients.size,maxClients:this.maxClients,enableSSE:this.enableSSE,enableRPC:this.enableRPC,connectionId:this.connectionId,state:this.state}}getClients(){return Array.from(this.clients.values()).map(e=>({id:e.id,sessionId:e.sessionId,connectedAt:e.connectedAt}))}};var ie=class extends x{static{l(this,"StdioAdapter")}messageBuffer="";isRunning=!1;encoding;bufferSize;constructor(e,t={name:"stdio"}){super(e,t),this.encoding=t.encoding||"utf8",this.bufferSize=t.bufferSize||1024*1024}async initialize(){this.logger.info("\u521D\u59CB\u5316 Stdio \u9002\u914D\u5668");try{process.stdin.setEncoding(this.encoding),this.setupProcessHandlers(),this.setState("connecting"),this.logger.info("Stdio \u9002\u914D\u5668\u521D\u59CB\u5316\u5B8C\u6210")}catch(e){throw this.logger.error("Stdio \u9002\u914D\u5668\u521D\u59CB\u5316\u5931\u8D25",e),this.setState("error"),e}}async start(){if(this.isRunning){this.logger.warn("Stdio \u9002\u914D\u5668\u5DF2\u5728\u8FD0\u884C");return}this.logger.info("\u542F\u52A8 Stdio \u9002\u914D\u5668");try{this.isRunning=!0,this.setupStdioHandlers(),this.setState("connected"),this.logger.info("Stdio \u9002\u914D\u5668\u542F\u52A8\u6210\u529F\uFF0C\u7B49\u5F85\u6D88\u606F...")}catch(e){throw this.logger.error("\u542F\u52A8 Stdio \u9002\u914D\u5668\u5931\u8D25",e),this.setState("error"),this.isRunning=!1,e}}async stop(){if(this.isRunning){this.logger.info("\u505C\u6B62 Stdio \u9002\u914D\u5668");try{this.isRunning=!1,this.removeStdioHandlers(),this.setState("disconnected"),this.logger.info("Stdio \u9002\u914D\u5668\u5DF2\u505C\u6B62")}catch(e){throw this.logger.error("\u505C\u6B62 Stdio \u9002\u914D\u5668\u65F6\u51FA\u9519",e),e}}}async sendMessage(e){try{let t=this.serializeMessage(e);process.stdout.write(`${t}
35
+ `),this.logger.debug("\u6D88\u606F\u5DF2\u53D1\u9001\u5230 stdout",{messageId:e.id,method:"method"in e?e.method:"response"})}catch(t){throw this.logger.error("\u53D1\u9001\u6D88\u606F\u5931\u8D25",t),t}}setupStdioHandlers(){process.stdin.on("data",this.handleStdinData.bind(this)),process.stdin.on("end",this.handleStdinEnd.bind(this)),process.stdin.on("error",this.handleStdinError.bind(this))}removeStdioHandlers(){process.stdin.removeListener("data",this.handleStdinData.bind(this)),process.stdin.removeListener("end",this.handleStdinEnd.bind(this)),process.stdin.removeListener("error",this.handleStdinError.bind(this))}async handleStdinData(e){try{if(this.messageBuffer+=e.toString(),this.messageBuffer.length>this.bufferSize){this.logger.warn(`\u6D88\u606F\u7F13\u51B2\u533A\u8D85\u8FC7\u9650\u5236 (${this.bufferSize} bytes)\uFF0C\u6E05\u7A7A\u7F13\u51B2\u533A`),this.messageBuffer="";return}let t=this.messageBuffer.split(`
36
+ `);this.messageBuffer=t.pop()||"";for(let r of t){let n=r.trim();n&&await this.processMessageLine(n)}}catch(t){this.logger.error("\u5904\u7406 stdin \u6570\u636E\u65F6\u51FA\u9519",t)}}async processMessageLine(e){try{this.logger.debug(`\u5904\u7406\u6D88\u606F\u884C: ${e.substring(0,200)}...`);let t=this.parseMessage(e);t&&await this.handleIncomingMessage(t)}catch(t){this.logger.error(`\u5904\u7406\u6D88\u606F\u884C\u5931\u8D25: ${e.substring(0,100)}...`,t);let r={jsonrpc:"2.0",error:{code:-32700,message:"\u89E3\u6790\u9519\u8BEF",data:{originalLine:e.substring(0,100)}},id:null};await this.sendMessage(r)}}handleStdinEnd(){this.logger.info("\u6807\u51C6\u8F93\u5165\u5DF2\u5173\u95ED\uFF0C\u505C\u6B62\u9002\u914D\u5668"),this.stop().catch(e=>{this.logger.error("\u505C\u6B62\u9002\u914D\u5668\u65F6\u51FA\u9519",e)})}handleStdinError(e){this.logger.error("\u6807\u51C6\u8F93\u5165\u9519\u8BEF",e),this.setState("error")}setupProcessHandlers(){let e=l(()=>{this.logger.info("\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u6E05\u7406\u8D44\u6E90"),this.stop().finally(()=>{process.exit(0)})},"handleExit");process.on("SIGINT",e),process.on("SIGTERM",e),process.on("uncaughtException",t=>{this.logger.error("\u672A\u6355\u83B7\u7684\u5F02\u5E38",t),this.setState("error")}),process.on("unhandledRejection",(t,r)=>{this.logger.error("\u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD",{reason:t,promise:r})})}getStatus(){return{isRunning:this.isRunning,bufferSize:this.messageBuffer.length,encoding:this.encoding,connectionId:this.connectionId,state:this.state}}clearBuffer(){this.messageBuffer="",this.logger.debug("\u6D88\u606F\u7F13\u51B2\u533A\u5DF2\u6E05\u7A7A")}};import Ne,{WebSocketServer as Et}from"ws";var ae=class extends x{static{l(this,"WebSocketAdapter")}ws=null;wsServer=null;endpointUrl;mode;wsState="disconnected";reconnectOptions;reconnectState;connectionTimeout=null;compression;batchQueue=[];batchTimer=null;batchSize;batchTimeout;connections=new Map;maxConnections;constructor(e,t){super(e,t),this.endpointUrl=t.endpointUrl,this.mode=t.mode||"client",this.compression=t.compression||!1,this.batchSize=t.batchSize||10,this.batchTimeout=t.batchTimeout||100,this.maxConnections=t.maxConnections||100,this.reconnectOptions={enabled:!0,maxAttempts:5,initialInterval:1e3,maxInterval:3e4,backoffStrategy:"exponential",backoffMultiplier:1.5,timeout:1e4,jitter:!0,...t.reconnect},this.reconnectState={attempts:0,nextInterval:this.reconnectOptions.initialInterval,timer:null,lastError:null,isManualDisconnect:!1}}async initialize(){this.logger.info(`\u521D\u59CB\u5316 WebSocket \u9002\u914D\u5668 (${this.mode} \u6A21\u5F0F)`);try{this.setState("connecting"),this.wsState="connecting",this.mode==="client"?await this.initializeClient():await this.initializeServer(),this.logger.info("WebSocket \u9002\u914D\u5668\u521D\u59CB\u5316\u5B8C\u6210")}catch(e){throw this.logger.error("WebSocket \u9002\u914D\u5668\u521D\u59CB\u5316\u5931\u8D25",e),this.setState("error"),this.wsState="failed",e}}async initializeClient(){return new Promise((e,t)=>{this.connectionTimeout=setTimeout(()=>{let r=new Error(`\u8FDE\u63A5\u8D85\u65F6 (${this.reconnectOptions.timeout}ms)`);this.handleConnectionError(r),t(r)},this.reconnectOptions.timeout),this.ws=new Ne(this.endpointUrl),this.compression,this.ws.on("open",()=>{this.handleConnectionSuccess(),e()}),this.ws.on("message",r=>{this.handleIncomingData(r)}),this.ws.on("close",(r,n)=>{this.handleConnectionClose(r,n.toString())}),this.ws.on("error",r=>{this.handleConnectionError(r),t(r)})})}async initializeServer(){return new Promise((e,t)=>{try{let r=new URL(this.endpointUrl),n=Number.parseInt(r.port)||8080;this.wsServer=new Et({port:n,perMessageDeflate:this.compression}),this.wsServer.on("connection",(s,o)=>{this.handleNewConnection(s,o)}),this.wsServer.on("error",s=>{this.logger.error("WebSocket \u670D\u52A1\u5668\u9519\u8BEF",s),t(s)}),this.logger.info(`WebSocket \u670D\u52A1\u5668\u76D1\u542C\u7AEF\u53E3 ${n}`),e()}catch(r){t(r)}})}async start(){if(this.wsState==="connected"){this.logger.warn("WebSocket \u9002\u914D\u5668\u5DF2\u542F\u52A8");return}this.logger.info("\u542F\u52A8 WebSocket \u9002\u914D\u5668");try{this.setState("connected"),this.wsState="connected",this.logger.info("WebSocket \u9002\u914D\u5668\u542F\u52A8\u6210\u529F")}catch(e){throw this.logger.error("\u542F\u52A8 WebSocket \u9002\u914D\u5668\u5931\u8D25",e),this.setState("error"),this.wsState="failed",e}}async stop(){this.logger.info("\u505C\u6B62 WebSocket \u9002\u914D\u5668");try{this.reconnectState.isManualDisconnect=!0,this.reconnectState.timer&&(clearTimeout(this.reconnectState.timer),this.reconnectState.timer=null),this.batchTimer&&(clearTimeout(this.batchTimer),this.batchTimer=null),await this.flushBatchQueue(),this.ws&&(this.ws.close(),this.ws=null),this.wsServer&&(this.wsServer.close(),this.wsServer=null);for(let[e,t]of this.connections)t.close();this.connections.clear(),this.setState("disconnected"),this.wsState="disconnected",this.logger.info("WebSocket \u9002\u914D\u5668\u5DF2\u505C\u6B62")}catch(e){throw this.logger.error("\u505C\u6B62 WebSocket \u9002\u914D\u5668\u65F6\u51FA\u9519",e),e}}async sendMessage(e){if(this.wsState!=="connected")throw new Error(`WebSocket \u672A\u8FDE\u63A5 (\u72B6\u6001: ${this.wsState})`);return this.batchSize>1?this.addToBatchQueue(e):this.sendMessageDirect(e)}async sendMessageDirect(e){try{let t=this.serializeMessage(e);if(this.mode==="client"&&this.ws)this.ws.send(t);else if(this.mode==="server")for(let r of this.connections.values())r.readyState===Ne.OPEN&&r.send(t);this.logger.debug("\u6D88\u606F\u5DF2\u53D1\u9001",{messageId:e.id,method:"method"in e?e.method:"response"})}catch(t){throw this.logger.error("\u53D1\u9001\u6D88\u606F\u5931\u8D25",t),t}}async addToBatchQueue(e){return new Promise((t,r)=>{this.batchQueue.push({message:e,timestamp:Date.now(),resolve:t,reject:r}),this.batchQueue.length>=this.batchSize?this.flushBatchQueue():this.batchTimer||(this.batchTimer=setTimeout(()=>{this.flushBatchQueue()},this.batchTimeout))})}async flushBatchQueue(){if(this.batchQueue.length===0)return;this.batchTimer&&(clearTimeout(this.batchTimer),this.batchTimer=null);let e=this.batchQueue.splice(0);try{let r={jsonrpc:"2.0",method:"batch",params:{messages:e.map(n=>n.message)},id:`batch_${Date.now()}`};await this.sendMessageDirect(r);for(let n of e)n.resolve();this.logger.debug(`\u6279\u5904\u7406\u53D1\u9001 ${e.length} \u6761\u6D88\u606F`)}catch(t){for(let r of e)r.reject(t);this.logger.error("\u6279\u5904\u7406\u53D1\u9001\u5931\u8D25",t)}}async handleIncomingData(e){try{let t=e.toString(),r=this.parseMessage(t);if(r)if(r.method==="batch"&&r.params?.messages)for(let n of r.params.messages)await this.handleIncomingMessage(n);else await this.handleIncomingMessage(r)}catch(t){this.logger.error("\u5904\u7406\u63A5\u6536\u6570\u636E\u5931\u8D25",t)}}handleConnectionSuccess(){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.setState("connected"),this.wsState="connected",this.reconnectState.attempts=0,this.reconnectState.nextInterval=this.reconnectOptions.initialInterval,this.reconnectState.lastError=null,this.logger.info("WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB")}handleConnectionError(e){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.reconnectState.lastError=e,this.logger.error("WebSocket \u8FDE\u63A5\u9519\u8BEF",e),this.setState("error"),this.wsState="failed",this.cleanupConnection()}handleConnectionClose(e,t){this.setState("disconnected"),this.wsState="disconnected",this.logger.info(`WebSocket \u8FDE\u63A5\u5DF2\u5173\u95ED (\u4EE3\u7801: ${e}, \u539F\u56E0: ${t})`),!this.reconnectState.isManualDisconnect&&(this.shouldReconnect()?this.scheduleReconnect():(this.wsState="failed",this.logger.warn(`\u5DF2\u8FBE\u5230\u6700\u5927\u91CD\u8FDE\u6B21\u6570 (${this.reconnectOptions.maxAttempts})\uFF0C\u505C\u6B62\u91CD\u8FDE`)))}handleNewConnection(e,t){if(this.connections.size>=this.maxConnections){this.logger.warn("\u8FBE\u5230\u6700\u5927\u8FDE\u63A5\u6570\u9650\u5236\uFF0C\u62D2\u7EDD\u65B0\u8FDE\u63A5"),e.close(1013,"\u670D\u52A1\u5668\u7E41\u5FD9");return}let r=`${this.getConnectionId()}_${this.connections.size}`;this.connections.set(r,e),this.logger.info(`\u65B0 WebSocket \u8FDE\u63A5: ${r}`),e.on("message",n=>{this.handleIncomingData(n)}),e.on("close",()=>{this.connections.delete(r),this.logger.info(`WebSocket \u8FDE\u63A5\u5DF2\u65AD\u5F00: ${r}`)}),e.on("error",n=>{this.logger.error(`WebSocket \u8FDE\u63A5\u9519\u8BEF ${r}:`,n),this.connections.delete(r)})}cleanupConnection(){this.ws&&(this.ws.removeAllListeners(),this.ws=null)}shouldReconnect(){return this.reconnectOptions.enabled&&this.reconnectState.attempts<this.reconnectOptions.maxAttempts&&!this.reconnectState.isManualDisconnect}scheduleReconnect(){this.wsState="reconnecting",this.reconnectState.attempts++;let e=this.calculateReconnectInterval();this.reconnectOptions.jitter&&(e+=Math.random()*1e3),this.logger.info(`\u5B89\u6392\u91CD\u8FDE (\u7B2C ${this.reconnectState.attempts} \u6B21\uFF0C${e}ms \u540E)`),this.reconnectState.timer=setTimeout(async()=>{try{await this.initializeClient()}catch(t){this.logger.error("\u91CD\u8FDE\u5931\u8D25",t),this.shouldReconnect()?this.scheduleReconnect():this.wsState="failed"}},e)}calculateReconnectInterval(){let{backoffStrategy:e,initialInterval:t,maxInterval:r,backoffMultiplier:n}=this.reconnectOptions,s=this.reconnectState.attempts,o;switch(e){case"linear":o=t+s*1e3;break;case"exponential":o=t*n**s;break;default:o=t;break}return Math.min(o,r)}getStatus(){return{wsState:this.wsState,connectionState:this.state,mode:this.mode,endpointUrl:this.endpointUrl,connectionCount:this.connections.size,reconnectAttempts:this.reconnectState.attempts,batchQueueSize:this.batchQueue.length,compression:this.compression}}async forceReconnect(){if(this.mode!=="client")throw new Error("\u53EA\u6709\u5BA2\u6237\u7AEF\u6A21\u5F0F\u652F\u6301\u91CD\u8FDE");this.logger.info("\u5F3A\u5236\u91CD\u8FDE"),this.reconnectState.attempts=0,this.reconnectState.isManualDisconnect=!1,this.ws&&this.ws.close(),await this.initializeClient()}};async function ze(i={}){c.info("[ServerFactory] \u5F00\u59CB\u521B\u5EFA MCP \u670D\u52A1\u5668",i);try{let e=await Rt(i);c.info(`[ServerFactory] \u786E\u5B9A\u670D\u52A1\u5668\u6A21\u5F0F: ${e}`);let t=new se(i.serverConfig);return await t.initialize(),await xt(t,e,i),c.info("[ServerFactory] MCP \u670D\u52A1\u5668\u521B\u5EFA\u6210\u529F"),t}catch(e){throw c.error("[ServerFactory] \u521B\u5EFA MCP \u670D\u52A1\u5668\u5931\u8D25",e),e}}l(ze,"createServer");async function Rt(i){if(i.mode&&i.mode!=="auto")return i.mode;let e=await $t(i.autoDetect);return c.info("\u73AF\u5883\u68C0\u6D4B\u7ED3\u679C",e),e.suggestedMode}l(Rt,"determineServerMode");async function $t(i={}){let{checkStdin:e=!0,checkEnvironment:t=!0,defaultMode:r="http"}=i,n={hasStdin:!1,isInteractive:!1,hasPort:!1,suggestedMode:r,reasons:[]};e&&(n.hasStdin=!process.stdin.isTTY,n.isInteractive=process.stdin.isTTY||!1,n.hasStdin&&n.reasons.push("\u68C0\u6D4B\u5230\u6807\u51C6\u8F93\u5165\u6D41"),n.isInteractive&&n.reasons.push("\u68C0\u6D4B\u5230\u4EA4\u4E92\u5F0F\u7EC8\u7AEF"));let s=!1;if(t){let o=process.env.MCP_SERVER_MODE,a=process.env.PORT||process.env.MCP_PORT;o==="stdio"?(n.suggestedMode="stdio",n.reasons.push("\u73AF\u5883\u53D8\u91CF MCP_SERVER_MODE=stdio"),s=!0):o==="http"?(n.suggestedMode="http",n.reasons.push("\u73AF\u5883\u53D8\u91CF MCP_SERVER_MODE=http"),s=!0):o==="websocket"?(n.suggestedMode="websocket",n.reasons.push("\u73AF\u5883\u53D8\u91CF MCP_SERVER_MODE=websocket"),s=!0):o==="hybrid"&&(n.suggestedMode="hybrid",n.reasons.push("\u73AF\u5883\u53D8\u91CF MCP_SERVER_MODE=hybrid"),s=!0),a&&(n.hasPort=!0,n.reasons.push(`\u68C0\u6D4B\u5230\u7AEF\u53E3\u914D\u7F6E: ${a}`))}return!s&&n.suggestedMode===r&&(n.hasStdin&&!n.isInteractive?(n.suggestedMode="stdio",n.reasons.push("\u63A8\u65AD\uFF1A\u975E\u4EA4\u4E92\u5F0F\u73AF\u5883\uFF0C\u9002\u5408 Stdio \u6A21\u5F0F")):(n.isInteractive||n.hasPort)&&(n.suggestedMode="http",n.reasons.push("\u63A8\u65AD\uFF1A\u4EA4\u4E92\u5F0F\u73AF\u5883\u6216\u6709\u7AEF\u53E3\u914D\u7F6E\uFF0C\u9002\u5408 HTTP \u6A21\u5F0F"))),n}l($t,"detectEnvironment");async function xt(i,e,t){let r=i.getMessageHandler();switch(e){case"stdio":await Fe(i,r,t.stdioConfig);break;case"http":await je(i,r,t.httpConfig);break;case"websocket":await Ue(i,r,t.websocketConfig);break;case"hybrid":await Fe(i,r,t.stdioConfig),await je(i,r,t.httpConfig),t.websocketConfig&&await Ue(i,r,t.websocketConfig);break;default:throw new Error(`\u4E0D\u652F\u6301\u7684\u670D\u52A1\u5668\u6A21\u5F0F: ${e}`)}}l(xt,"registerTransportsForMode");async function Fe(i,e,t={name:"stdio"}){let r=new ie(e,t);await i.registerTransport("stdio",r),c.info("Stdio \u4F20\u8F93\u9002\u914D\u5668\u6CE8\u518C\u6210\u529F")}l(Fe,"registerStdioTransport");async function je(i,e,t={name:"http"}){let r={port:3e3,host:"0.0.0.0",...t};process.env.PORT?r.port=Number.parseInt(process.env.PORT,10):process.env.MCP_PORT&&(r.port=Number.parseInt(process.env.MCP_PORT,10));let n=new oe(e,r);await i.registerTransport("http",n),c.info(`HTTP \u4F20\u8F93\u9002\u914D\u5668\u6CE8\u518C\u6210\u529F (\u7AEF\u53E3: ${r.port})`)}l(je,"registerHTTPTransport");async function Ue(i,e,t={name:"websocket",endpointUrl:"ws://localhost:8080"}){let r={mode:"client",compression:!0,batchSize:10,batchTimeout:100,maxConnections:100,...t};process.env.WEBSOCKET_URL?r.endpointUrl=process.env.WEBSOCKET_URL:process.env.MCP_WEBSOCKET_URL&&(r.endpointUrl=process.env.MCP_WEBSOCKET_URL);let n=new ae(e,r);await i.registerTransport("websocket",n),c.info(`WebSocket \u4F20\u8F93\u9002\u914D\u5668\u6CE8\u518C\u6210\u529F (\u7AEF\u70B9: ${r.endpointUrl})`)}l(Ue,"registerWebSocketTransport");var fs=It(kt(import.meta.url)),_e=w.env.XIAOZHI_CONFIG_DIR||w.cwd();c.initLogFile(_e);c.enableFileLogging(!0);c.info(`\u65E5\u5FD7\u6587\u4EF6\u5DF2\u521D\u59CB\u5316: ${_e}/xiaozhi.log`);async function Lt(){try{c.info("\u542F\u52A8 MCP \u670D\u52A1\u5668\u4EE3\u7406"),await Ot();let i=await ze({mode:"stdio",stdioConfig:{name:"mcp-proxy",encoding:"utf8"}});await i.start(),c.info("MCP \u670D\u52A1\u5668\u4EE3\u7406\u542F\u52A8\u6210\u529F"),w.on("SIGINT",async()=>{c.info("\u6536\u5230 SIGINT \u4FE1\u53F7\uFF0C\u6B63\u5728\u5173\u95ED\u670D\u52A1\u5668"),await i.stop(),w.exit(0)}),w.on("SIGTERM",async()=>{c.info("\u6536\u5230 SIGTERM \u4FE1\u53F7\uFF0C\u6B63\u5728\u5173\u95ED\u670D\u52A1\u5668"),await i.stop(),w.exit(0)})}catch(i){c.error("\u542F\u52A8 MCP \u670D\u52A1\u5668\u4EE3\u7406\u5931\u8D25:",i),w.exit(1)}}l(Lt,"main");async function Ot(){try{if(c.info("\u52A0\u8F7D MCP \u670D\u52A1\u5668\u914D\u7F6E"),!f.configExists()){c.warn("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u5C06\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E");return}let i=f.getConfig();c.info(`\u5DF2\u52A0\u8F7D\u914D\u7F6E\uFF0C\u5305\u542B ${Object.keys(i.mcpServers||{}).length} \u4E2A MCP \u670D\u52A1\u5668`)}catch(i){throw c.error("\u52A0\u8F7D\u914D\u7F6E\u5931\u8D25:",i),i}}l(Ot,"loadConfiguration");import.meta.url===`file://${w.argv[1]}`&&Lt().catch(i=>{c.error("MCP \u670D\u52A1\u5668\u4EE3\u7406\u542F\u52A8\u5931\u8D25:",i),w.exit(1)});export{Lt as main};
37
37
  //# sourceMappingURL=mcpServerProxy.js.map