xiaozhi-client 1.9.4-beta.1 → 1.9.4-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backend/Logger.js +3 -0
- package/dist/backend/Logger.js.map +1 -0
- package/dist/backend/WebServer.js +93 -0
- package/dist/backend/WebServer.js.map +1 -0
- package/dist/backend/WebServerLauncher.js +11 -17
- package/dist/backend/WebServerLauncher.js.map +1 -1
- package/dist/backend/managers/MCPServiceManagerSingleton.js +27 -0
- package/dist/backend/managers/MCPServiceManagerSingleton.js.map +1 -0
- package/dist/backend/package.json +28 -52
- package/dist/backend/templates/json5/xiaozhi.config.json5 +14 -14
- package/dist/cli/index.js +29 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/index.js +2 -0
- package/dist/config/index.js.map +1 -0
- package/dist/frontend/assets/index-88NfCOo9.js.map +1 -1
- package/dist/shared-types/api-aP8BHcbg.d.ts +97 -0
- package/dist/shared-types/api.d.ts +202 -0
- package/dist/shared-types/api.js +50 -0
- package/dist/shared-types/api.js.map +1 -0
- package/dist/shared-types/app-oAmColIN.d.ts +91 -0
- package/dist/shared-types/chunk-BMOKIX3Q.js +51 -0
- package/dist/shared-types/chunk-BMOKIX3Q.js.map +1 -0
- package/dist/shared-types/config.d.ts +97 -0
- package/dist/shared-types/config.js +1 -0
- package/dist/shared-types/config.js.map +1 -0
- package/dist/shared-types/coze.d.ts +30 -0
- package/dist/shared-types/coze.js +1 -0
- package/dist/shared-types/coze.js.map +1 -0
- package/dist/shared-types/index.d.ts +186 -0
- package/dist/shared-types/index.js +4 -17
- package/dist/shared-types/index.js.map +1 -1
- package/dist/shared-types/mcp.d.ts +91 -0
- package/dist/shared-types/mcp.js +22 -0
- package/dist/shared-types/mcp.js.map +1 -0
- package/dist/shared-types/message-xoOM7ZuT.d.ts +154 -0
- package/dist/shared-types/timeout-CCp_IFHg.d.ts +39 -0
- package/dist/shared-types/toolApi-DYSy8ebd.d.ts +208 -0
- package/dist/shared-types/utils.d.ts +115 -0
- package/dist/shared-types/utils.js +15 -0
- package/dist/shared-types/utils.js.map +1 -0
- package/dist/shared-types/workflow-DDqq5Jgp.d.ts +83 -0
- package/package.json +28 -52
- package/templates/json5/xiaozhi.config.json5 +14 -14
- package/dist/backend/WebServerLauncher.d.ts +0 -1
- package/dist/backend/cli.d.ts +0 -1
- package/dist/backend/cli.js +0 -129
- package/dist/backend/cli.js.map +0 -1
- package/dist/cli.js +0 -2
- package/dist/docs/404/index.html +0 -19
- package/dist/docs/404.html +0 -19
- package/dist/docs/_next/static/JZ0ESgtaHnsqkxSabOqqU/_buildManifest.js +0 -1
- package/dist/docs/_next/static/JZ0ESgtaHnsqkxSabOqqU/_ssgManifest.js +0 -1
- package/dist/docs/_next/static/chunks/112-c9cbd8401d35f825.js +0 -4
- package/dist/docs/_next/static/chunks/2a9bc5d7-4c434acf20ba934a.js +0 -1
- package/dist/docs/_next/static/chunks/782-c26ca6c69e488d48.js +0 -1
- package/dist/docs/_next/static/chunks/799-fe0d35806fd12012.js +0 -1
- package/dist/docs/_next/static/chunks/9b1cb2c3-cc9ed703e6aef1a2.js +0 -1
- package/dist/docs/_next/static/chunks/app/[[...mdxPath]]/page-48f5c8f3210e0a8a.js +0 -1
- package/dist/docs/_next/static/chunks/app/_not-found/page-2e38866a1cbb77e4.js +0 -1
- package/dist/docs/_next/static/chunks/app/layout-e8f420537fd59e8d.js +0 -1
- package/dist/docs/_next/static/chunks/framework-b73126dabbf07067.js +0 -1
- package/dist/docs/_next/static/chunks/main-75dc65850b89d90d.js +0 -1
- package/dist/docs/_next/static/chunks/main-app-3303134270964ce6.js +0 -1
- package/dist/docs/_next/static/chunks/pages/_app-e698a68d07c8993d.js +0 -1
- package/dist/docs/_next/static/chunks/pages/_error-189a41ab5833da03.js +0 -1
- package/dist/docs/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
- package/dist/docs/_next/static/chunks/webpack-10e2bf7d852ddb6e.js +0 -1
- package/dist/docs/_next/static/css/2d82b615fcca1590.css +0 -1
- package/dist/docs/_next/static/css/b03484a3c350cf6e.css +0 -1
- package/dist/docs/_next/static/css/b289318ef4b60b0a.css +0 -1
- package/dist/docs/_next/static/media/get-parameter.62eee93d.png +0 -0
- package/dist/docs/changelog/index.html +0 -585
- package/dist/docs/changelog/index.txt +0 -1079
- package/dist/docs/images/add-to-cherry-studio/step-1.png +0 -0
- package/dist/docs/images/add-to-cherry-studio/step-2.png +0 -0
- package/dist/docs/images/add-to-cherry-studio/step-3.png +0 -0
- package/dist/docs/images/add-to-cherry-studio/step-4.png +0 -0
- package/dist/docs/images/add-to-cherry-studio/step-5.png +0 -0
- package/dist/docs/images/add-to-cursor/step-1.png +0 -0
- package/dist/docs/images/add-to-cursor/step-2.png +0 -0
- package/dist/docs/images/add-to-cursor/step-3.png +0 -0
- package/dist/docs/images/coze-workflow/config-workflow-step-1.png +0 -0
- package/dist/docs/images/coze-workflow/config-workflow-step-2.png +0 -0
- package/dist/docs/images/coze-workflow/config-workflow-step-3.png +0 -0
- package/dist/docs/images/coze-workflow/get-parameter.png +0 -0
- package/dist/docs/images/integrate-to-cherry-studio.png +0 -0
- package/dist/docs/images/integrate-to-cursor.png +0 -0
- package/dist/docs/images/modelscope/step-1.png +0 -0
- package/dist/docs/images/modelscope/step-2.png +0 -0
- package/dist/docs/images/modelscope/step-3.png +0 -0
- package/dist/docs/images/modelscope/step-4.png +0 -0
- package/dist/docs/images/preview.png +0 -0
- package/dist/docs/images/use-multi-xiaozhi-mcp-endpoints/step-1.png +0 -0
- package/dist/docs/images/use-multi-xiaozhi-mcp-endpoints/step-2.png +0 -0
- package/dist/docs/images/use-multi-xiaozhi-mcp-endpoints/step-3.png +0 -0
- package/dist/docs/images/use-multi-xiaozhi-mcp-endpoints/step-4.png +0 -0
- package/dist/docs/images/use-multi-xiaozhi-mcp-endpoints/step-5.png +0 -0
- package/dist/docs/images/web-ui-preview.png +0 -0
- package/dist/docs/index.html +0 -22
- package/dist/docs/index.txt +0 -41
- package/dist/docs/quickstart/index.html +0 -64
- package/dist/docs/quickstart/index.txt +0 -185
- package/dist/docs/reference/command/index.html +0 -20
- package/dist/docs/reference/command/index.txt +0 -42
- package/dist/docs/usage/as-mcp/index.html +0 -36
- package/dist/docs/usage/as-mcp/index.txt +0 -101
- package/dist/docs/usage/coze-workflow/index.html +0 -35
- package/dist/docs/usage/coze-workflow/index.txt +0 -120
- package/dist/docs/usage/docker/index.html +0 -40
- package/dist/docs/usage/docker/index.txt +0 -154
- package/dist/docs/usage/modelscope/index.html +0 -32
- package/dist/docs/usage/modelscope/index.txt +0 -109
- package/dist/docs/usage/multi-endpoint/index.html +0 -32
- package/dist/docs/usage/multi-endpoint/index.txt +0 -118
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
var K=Object.defineProperty;var pe=Object.getOwnPropertyDescriptor;var de=Object.getOwnPropertyNames;var fe=Object.prototype.hasOwnProperty;var c=(s,e)=>K(s,"name",{value:e,configurable:!0});var Ce=(s,e)=>{for(var t in e)K(s,t,{get:e[t],enumerable:!0})},re=(s,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of de(e))!fe.call(s,o)&&o!==t&&K(s,o,{get:()=>e[o],enumerable:!(r=pe(e,o))||r.enumerable});return s},R=(s,e,t)=>(re(s,e,"default"),t&&re(t,e,"default"));import{EventEmitter as ke}from"events";import{EventEmitter as ye}from"events";import*as u from"fs";import*as g from"path";import x from"chalk";import P from"pino";import{z as ve}from"zod";var Se=ve.enum(["fatal","error","warn","info","debug","trace"]);function Me(s){let e=s.getFullYear(),t=String(s.getMonth()+1).padStart(2,"0"),r=String(s.getDate()).padStart(2,"0"),o=String(s.getHours()).padStart(2,"0"),n=String(s.getMinutes()).padStart(2,"0"),i=String(s.getSeconds()).padStart(2,"0");return`${e}-${t}-${r} ${o}:${n}:${i}`}c(Me,"formatDateTime");var J=class{static{c(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=Se.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:P.destination({dest:this.logFilePath,sync:!1,append:!0,mkdir:!0})}),e.length===0&&e.push({level:this.logLevel,stream:P.destination({dest:"/dev/null"})}),P({level:this.logLevel,timestamp:P.stdTimeFunctions?.isoTime||(()=>`,"time":${Date.now()}`),formatters:{level:c((t,r)=>({level:r}),"level")},base:null,serializers:{err:P.stdSerializers?.err||(t=>t)}},P.multistream(e,{dedupe:!0}))}createOptimizedConsoleStream(){let e=new Map([[20,{name:"DEBUG",color:x.gray}],[30,{name:"INFO",color:x.blue}],[40,{name:"WARN",color:x.yellow}],[50,{name:"ERROR",color:x.red}],[60,{name:"FATAL",color:x.red}]]);return{write:c(t=>{try{let r=JSON.parse(t),o=this.formatConsoleMessageOptimized(r,e);this.safeWrite(`${o}
|
|
2
|
+
`)}catch{this.safeWrite(t)}},"write")}}safeWrite(e){try{process.stderr&&typeof process.stderr.write=="function"&&process.stderr.write(e)}catch{}}formatConsoleMessageOptimized(e,t){let r=Me(new Date),o=t.get(e.level)||{name:"UNKNOWN",color:c(a=>a,"color")},n=o.color(`[${o.name}]`),i=e.msg;if(e.args&&Array.isArray(e.args)){let a=e.args.map(l=>typeof l=="object"?JSON.stringify(l):String(l)).join(" ");i=`${i} ${a}`}return`[${r}] ${n} ${i}`}initLogFile(e){this.logFilePath=g.join(e,"xiaozhi.log"),this.rotateLogFileIfNeeded(),u.existsSync(this.logFilePath)||u.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(o=>o instanceof Error?this.pinoInstance.level==="debug"?o.message:{message:o.message,stack:o.stack,name:o.name,cause:o.cause}:o);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,o]of Object.entries(t))o instanceof Error&&(t[r]={message:o.message,stack:o.stack,name:o.name,cause:o.cause});return t}rotateLogFileIfNeeded(){if(!(!this.logFilePath||!u.existsSync(this.logFilePath)))try{u.statSync(this.logFilePath).size>this.maxLogFileSize&&this.rotateLogFile()}catch{}}rotateLogFile(){if(this.logFilePath)try{let e=g.dirname(this.logFilePath),t=g.basename(this.logFilePath,".log");for(let o=this.maxLogFiles-1;o>=1;o--){let n=g.join(e,`${t}.${o}.log`),i=g.join(e,`${t}.${o+1}.log`);u.existsSync(n)&&(o===this.maxLogFiles-1?u.unlinkSync(n):u.renameSync(n,i))}let r=g.join(e,`${t}.1.log`);u.renameSync(this.logFilePath,r)}catch{}}cleanupOldLogs(){if(this.logFilePath)try{let e=g.dirname(this.logFilePath),t=g.basename(this.logFilePath,".log");for(let r=this.maxLogFiles+1;r<=this.maxLogFiles+10;r++){let o=g.join(e,`${t}.${r}.log`);u.existsSync(o)&&u.unlinkSync(o)}}catch{}}setLogFileOptions(e,t){this.maxLogFileSize=e,this.maxLogFiles=t}close(){}setLevel(e){this.logLevel=this.validateLogLevel(e),this.pinoInstance=this.createPinoInstance()}getLevel(){return this.logLevel}},V=null,Pe="info";function Te(){return V||(V=new J(Pe)),V}c(Te,"getLogger");var v=Te();var Q=class extends ye{static{c(this,"EventBus")}logger;eventStats=new Map;maxListeners=50;constructor(){super(),this.logger=v,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=c(o=>{try{t(o)}catch(n){throw this.emit("error",n),n}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")}},G=null;function T(){return G||(G=new Q),G}c(T,"getEventBus");import{isModelScopeURL as Ie}from"@xiaozhi-client/config";import{configManager as h}from"@xiaozhi-client/config";var d={};Ce(d,{CozeApiService:()=>y,config:()=>N,createCozeClient:()=>D});var N={zh:{COZE_BASE_URL:"https://api.coze.cn",COZE_BASE_WS_URL:"wss://ws.coze.cn"},en:{COZE_BASE_URL:"https://api.coze.com",COZE_BASE_WS_URL:"wss://ws.coze.com"}};R(d,St);import*as St from"@coze/api";function D(s,e="zh"){if(!s||typeof s!="string"||s.trim()==="")throw new Error("\u6263\u5B50 API Token \u4E0D\u80FD\u4E3A\u7A7A");let t=N[e]||N.zh;return new d.CozeAPI({baseURL:t.COZE_BASE_URL,token:s.trim(),baseWsURL:t.COZE_BASE_WS_URL,debug:!1})}c(D,"createCozeClient");import be from"node-cache";var y=class{static{c(this,"CozeApiService")}cache;token;client;constructor(e){this.token=e.trim(),this.client=D(this.token),this.cache=new be({stdTTL:300})}async getWorkspaces(){let e="workspaces",t=this.cache.get(e);if(t)return t;let{workspaces:r=[]}=await this.client.workspaces.list();return this.cache.set(e,r,1800),r}async getWorkflows(e){let{workspace_id:t,page_num:r=1,page_size:o=20}=e;if(!t||typeof t!="string")throw new Error("\u5DE5\u4F5C\u7A7A\u95F4ID\u4E0D\u80FD\u4E3A\u7A7A");let n=`workflows:${t}:${r}:${o}`,i=this.cache.get(n);if(i)return i;let l=(await this.client.get("/v1/workflows",{workspace_id:t,page_num:r,page_size:o,workflow_mode:"workflow"})).data;return this.cache.set(n,l),l}callWorkflow(e,t){return this.client.workflows.runs.create({workflow_id:e,parameters:t})}clearCache(e){if(!e){this.cache.flushAll();return}let r=this.cache.keys().filter(o=>o.startsWith(e));this.cache.del(r)}getCacheStats(){let e=this.cache.getStats(),t=this.cache.keys(),r=e.hits+e.misses,o=r>0?e.hits/r:0;return{size:e.keys,keys:t,hits:e.hits,misses:e.misses,hitRate:o,ksize:e.ksize,vsize:e.vsize}}};var $=(r=>(r.STDIO="stdio",r.SSE="sse",r.STREAMABLE_HTTP="streamable-http",r))($||{});function we(s){return typeof s=="object"&&s!==null&&"type"in s&&s.type==="object"}c(we,"isValidToolJSONSchema");function oe(s){return we(s)?s:{type:"object",properties:{},required:[],additionalProperties:!0}}c(oe,"ensureToolJSONSchema");var S=class extends Error{constructor(t,r,o){super(r);this.code=t;this.data=o;this.name="ToolCallError"}static{c(this,"ToolCallError")}};import{createHash as Ee}from"crypto";function f(s,e){let t=Ee("md5").update(JSON.stringify(e||{})).digest("hex");return`${s}_${t}`}c(f,"generateCacheKey");function Z(s,e){let t=new Date(s).getTime();return Date.now()-t>e}c(Z,"isCacheExpired");function k(s){let e=Date.now(),t=new Date(s.timestamp).getTime();return!!(s.consumed&&e-t>6e4||e-t>s.ttl||s.status==="failed")}c(k,"shouldCleanupCache");var z={TIMEOUT:8e3,CACHE_TTL:3e5,CLEANUP_INTERVAL:6e4,MAX_CACHE_SIZE:1e3,ENABLE_ONE_TIME_CACHE:!0};var I=class s extends Error{static{c(this,"TimeoutError")}name="TimeoutError";constructor(e){super(e),this.name="TimeoutError",Error.captureStackTrace(this,s)}toJSON(){return{name:this.name,message:this.message,stack:this.stack}}};function se(s,e){return{content:[{type:"text",text:e?Re(e,s):ne(s)}],isError:!1,taskId:s,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"}}c(se,"createTimeoutResponse");function Re(s,e){let t={coze_workflow:`\u23F1\uFE0F \u6263\u5B50\u5DE5\u4F5C\u6D41\u6267\u884C\u8D85\u65F6\uFF0C\u6B63\u5728\u540E\u53F0\u5904\u7406\u4E2D...
|
|
3
|
+
|
|
4
|
+
\u{1F4CB} \u4EFB\u52A1\u4FE1\u606F\uFF1A
|
|
5
|
+
- \u4EFB\u52A1ID: ${e}
|
|
6
|
+
- \u5DE5\u5177\u7C7B\u578B: \u6263\u5B50\u5DE5\u4F5C\u6D41
|
|
7
|
+
- \u72B6\u6001: \u5904\u7406\u4E2D
|
|
8
|
+
- \u5EFA\u8BAE: \u8BF7\u7B49\u5F8530-60\u79D2\u540E\u91CD\u8BD5\u67E5\u8BE2
|
|
9
|
+
|
|
10
|
+
\u{1F504} \u540E\u7EED\u64CD\u4F5C\uFF1A
|
|
11
|
+
1. \u4F7F\u7528\u76F8\u540C\u53C2\u6570\u91CD\u65B0\u8C03\u7528\u5DE5\u5177
|
|
12
|
+
2. \u7CFB\u7EDF\u4F1A\u81EA\u52A8\u8FD4\u56DE\u5DF2\u5B8C\u6210\u7684\u4EFB\u52A1\u7ED3\u679C
|
|
13
|
+
3. \u590D\u6742\u5DE5\u4F5C\u6D41\u53EF\u80FD\u9700\u8981\u66F4\u957F\u65F6\u95F4\u5904\u7406`,default:ne(e)};return t[s]||t.default}c(Re,"getToolSpecificTimeoutMessage");function ne(s){return`\u23F1\uFE0F \u5DE5\u5177\u8C03\u7528\u8D85\u65F6\uFF0C\u6B63\u5728\u540E\u53F0\u5904\u7406\u4E2D...
|
|
14
|
+
|
|
15
|
+
\u{1F4CB} \u4EFB\u52A1\u4FE1\u606F\uFF1A
|
|
16
|
+
- \u4EFB\u52A1ID: ${s}
|
|
17
|
+
- \u72B6\u6001: \u5904\u7406\u4E2D
|
|
18
|
+
- \u5EFA\u8BAE: \u8BF7\u7B49\u5F8530\u79D2\u540E\u91CD\u8BD5\u67E5\u8BE2
|
|
19
|
+
|
|
20
|
+
\u{1F504} \u540E\u7EED\u64CD\u4F5C\uFF1A
|
|
21
|
+
1. \u4F7F\u7528\u76F8\u540C\u7684\u53C2\u6570\u91CD\u65B0\u8C03\u7528\u5DE5\u5177
|
|
22
|
+
2. \u7CFB\u7EDF\u4F1A\u81EA\u52A8\u8FD4\u56DE\u5DF2\u5B8C\u6210\u7684\u4EFB\u52A1\u7ED3\u679C
|
|
23
|
+
3. \u5982\u679C\u957F\u65F6\u95F4\u672A\u5B8C\u6210\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458`}c(ne,"getDefaultTimeoutMessage");import{configManager as ie}from"@xiaozhi-client/config";function ae(s){return s.type==="proxy"}c(ae,"isProxyHandler");var O=class{static{c(this,"CustomMCPHandler")}logger;tools=new Map;cacheManager;mcpServiceManager;TIMEOUT=z.TIMEOUT;CACHE_TTL=z.CACHE_TTL;constructor(e,t){this.logger=v,this.cacheManager=e||new b,this.mcpServiceManager=t,this.setupEventListeners()}getCozeApiService(){let e=ie.getConfig().platforms?.coze?.token;if(!e)throw new Error("Coze Token \u914D\u7F6E\u4E0D\u5B58\u5728");return new y(e)}setupEventListeners(){T().onEvent("config:updated",async t=>{if(t.type==="customMCP"){this.logger.info("[CustomMCP] \u68C0\u6D4B\u5230\u914D\u7F6E\u66F4\u65B0\uFF0C\u91CD\u65B0\u521D\u59CB\u5316...");try{this.reinitialize()}catch(r){this.logger.error("[CustomMCP] \u914D\u7F6E\u66F4\u65B0\u5904\u7406\u5931\u8D25:",r)}}})}initialize(e){this.logger.debug("[CustomMCP] \u521D\u59CB\u5316 CustomMCP \u5904\u7406\u5668...");try{let t=e||ie.getCustomMCPTools();this.tools.clear();for(let r of t)if(ae(r.handler)&&r.handler.platform==="coze")this.tools.set(r.name,r),this.logger.debug(`[CustomMCP] \u5DF2\u52A0\u8F7D Coze \u5DE5\u5177: ${r.name} (workflow_id: ${r.handler.config.workflow_id})`);else{let o=ae(r.handler)?`/${r.handler.platform}`:"";this.logger.warn(`[CustomMCP] \u8DF3\u8FC7\u4E0D\u652F\u6301\u7684\u5DE5\u5177\u7C7B\u578B: ${r.name} (${r.handler.type}${o})`)}this.logger.debug(`[CustomMCP] \u521D\u59CB\u5316\u5B8C\u6210\uFF0C\u5171\u52A0\u8F7D ${this.tools.size} \u4E2A Coze \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:oe(e.inputSchema)}))}hasTool(e){return this.tools.has(e)}getToolCount(){return this.tools.size}getToolNames(){return Array.from(this.tools.keys())}getToolInfo(e){return this.tools.get(e)}reinitialize(){this.logger.debug("[CustomMCP] \u91CD\u65B0\u521D\u59CB\u5316 CustomMCP \u5904\u7406\u5668..."),this.initialize()}async callTool(e,t,r){let o=this.tools.get(e);if(!o)throw new Error(`\u672A\u627E\u5230\u5DE5\u5177: ${e}`);let n=await this.getCompletedResult(e,t);if(n)return this.logger.debug(`[CustomMCP] \u8FD4\u56DE\u5DF2\u5B8C\u6210\u7684\u4EFB\u52A1\u7ED3\u679C: ${e}`),await this.clearConsumedCache(e,t),n;try{let i=r?.timeout||this.TIMEOUT,a=await Promise.race([this.callCozeWorkflow(o,t),this.createTimeoutPromise(e,i)]);return await this.cacheResult(e,t,a),a}catch(i){if(i instanceof I){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}`),se(a,e)}throw i}}async createTimeoutPromise(e,t){return new Promise((r,o)=>{setTimeout(()=>{o(new I(`\u5DE5\u5177\u8C03\u7528\u8D85\u65F6: ${e}`))},t)})}async getCompletedResult(e,t){try{let r=this.generateCacheKey(e,t),o=await this.loadExtendedCache();if(!o.customMCPResults||!o.customMCPResults[r])return null;let n=o.customMCPResults[r];return n.status==="completed"&&!n.consumed&&!Z(n.timestamp,n.ttl)?n.result:null}catch(r){return this.logger.warn(`[CustomMCP] \u83B7\u53D6\u7F13\u5B58\u5931\u8D25: ${r}`),null}}processWorkflowResponse(e,t){try{let r=t.data||t;return typeof r=="string"?{content:[{type:"text",text:r}],isError:!1}:{content:[{type:"text",text:JSON.stringify(r,null,2)}],isError:!1}}catch(r){return this.logger.error(`[CustomMCP] \u5904\u7406\u5DE5\u4F5C\u6D41\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 callCozeWorkflow(e,t){let o=e.handler.config;this.logger.info(`[CustomMCP] \u8C03\u7528 Coze \u5DE5\u4F5C\u6D41: ${e.name}`,{workflow_id:o.workflow_id});try{let n=this.getCozeApiService();if(!o.workflow_id)throw new Error("\u5DE5\u4F5C\u6D41ID\u672A\u914D\u7F6E");let i=await n.callWorkflow(o.workflow_id,t);return this.logger.info(`[CustomMCP] Coze \u5DE5\u4F5C\u6D41\u8C03\u7528\u6210\u529F: ${e.name}`),this.processWorkflowResponse(e.name,i)}catch(n){return this.logger.error(`[CustomMCP] Coze \u5DE5\u4F5C\u6D41\u8C03\u7528\u5931\u8D25: ${e.name}`,n),{content:[{type:"text",text:`Coze \u5DE5\u4F5C\u6D41\u8C03\u7528\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`}],isError:!0}}}async clearConsumedCache(e,t){try{let r=this.generateCacheKey(e,t),o=await this.loadExtendedCache();if(o.customMCPResults?.[r]){o.customMCPResults[r].consumed=!0;let n=o.customMCPResults[r];k(n)&&delete o.customMCPResults[r],await this.saveCache(o),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 f(e,t)}generateCacheKey(e,t){return f(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 o=this.generateCacheKey(e,t),n={result:r,timestamp:new Date().toISOString(),ttl:this.CACHE_TTL,status:"completed",consumed:!1,retryCount:0};await this.updateCacheWithResult(o,n),this.logger.debug(`[CustomMCP] \u7F13\u5B58\u5DE5\u5177\u7ED3\u679C: ${e}`)}catch(o){this.logger.warn(`[CustomMCP] \u7F13\u5B58\u7ED3\u679C\u5931\u8D25: ${o}`)}}async saveCache(e){try{await this.cacheManager.saveCache(e)}catch(t){this.logger.warn(`[CustomMCP] \u4FDD\u5B58\u7F13\u5B58\u5931\u8D25: ${t}`)}}cleanup(){this.logger.info("[CustomMCP] \u6E05\u7406 CustomMCP \u5904\u7406\u5668\u8D44\u6E90"),this.tools.clear(),this.cacheManager.cleanup()}};import*as w from"fs";import*as M from"path";import{tmpdir as xe}from"os";var H=class{static{c(this,"PathUtils")}static getConfigDir(){return process.env.XIAOZHI_CONFIG_DIR||process.cwd()}static getTempDir(){return process.env.TMPDIR||process.env.TEMP||xe()}static getHomeDir(){return process.env.HOME||process.env.USERPROFILE||""}};import F from"pino";var j=class{static{c(this,"ToolCallLogger")}pinoLogger;maxRecords;logFilePath;constructor(e,t){if(this.maxRecords=e?.maxRecords??100,e?.logFilePath)this.logFilePath=M.resolve(M.normalize(e.logFilePath));else{let r=t||H.getTempDir();this.logFilePath=M.join(M.normalize(r),"tool-calls.jsonl")}this.pinoLogger=this.createPinoLogger(this.logFilePath)}createPinoLogger(e){let t=[];t.push({level:"info",stream:{write:c(r=>{try{let o=JSON.parse(r),n=this.formatConsoleMessage(o)}catch{}},"write")}});try{t.push({level:"info",stream:F.destination({dest:e,sync:!0,append:!0,mkdir:!0})})}catch{}return F({level:"info",timestamp:F.stdTimeFunctions?.isoTime||(()=>`,"time":${Date.now()}`),formatters:{level:c((r,o)=>({level:o}),"level")},base:null},F.multistream(t,{dedupe:!0}))}formatConsoleMessage(e){let t=e.toolName||"\u672A\u77E5\u5DE5\u5177",r=e.success!==!1,o=e.duration?` (${e.duration}ms)`:"";return`${r?"\u2705":"\u274C"} ${t}${o}`}async cleanupOldRecords(){try{if(!w.existsSync(this.logFilePath))return;let t=w.readFileSync(this.logFilePath,"utf8").trim().split(`
|
|
24
|
+
`).filter(i=>i.trim()!=="");if(t.length<=this.maxRecords)return;let r=t.length-this.maxRecords+1,o=t.slice(r),n=o.join(`
|
|
25
|
+
`)+(o.length>0?`
|
|
26
|
+
`:"");w.writeFileSync(this.logFilePath,n,"utf8")}catch{}}async recordToolCall(e){try{await this.cleanupOldRecords(),this.pinoLogger.info(e,e.toolName)}catch{}}getLogFilePath(){return this.logFilePath}getMaxRecords(){return this.maxRecords}};var W=class{static{c(this,"MCPMessageHandler")}logger;serviceManager;constructor(e){this.serviceManager=e,this.logger=v}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"],o=e.protocolVersion,n=r.includes(o)?o:"2024-11-05";return this.logger.debug(`\u534F\u8BAE\u7248\u672C\u534F\u5546: \u5BA2\u6237\u7AEF=${o}, \u670D\u52A1\u5668\u54CD\u5E94=${n}`),{jsonrpc:"2.0",result:{serverInfo:{name:"xiaozhi-mcp-server",version:"1.0.0"},capabilities:{tools:{},logging:{}},protocolVersion:n},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(o=>({name:o.name,description:o.description,inputSchema:o.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{let r=ce(e),o=await this.serviceManager.callTool(r.name,r.arguments||{});return{jsonrpc:"2.0",result:{content:o.content,isError:o.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 rr,{WebSocketServer as or}from"ws";var U=class extends ke{static{c(this,"MCPServiceManager")}services=new Map;configs={};tools=new Map;customMCPHandler;cacheManager;eventBus=T();toolCallLogger;retryTimers=new Map;failedServices=new Set;transportAdapters=new Map;messageHandler;isRunning=!1;config;constructor(e){super(),e&&this.isUnifiedServerConfig(e)?(this.config={name:"MCPServiceManager",enableLogging:!0,logLevel:"info",...e},this.configs=e.configs||{}):(this.config={name:"MCPServiceManager",enableLogging:!0,logLevel:"info"},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 b(r),this.customMCPHandler=new O(this.cacheManager,this);let o=h.getToolCallLogConfig(),n=h.getConfigDir();this.toolCallLogger=new j(o,n),this.setupEventListeners(),this.messageHandler=new W(this)}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)})}async handleServiceConnected(e){try{this.services.get(e.serviceName)&&await this.refreshCustomMCPHandlerPublic()}catch{}}async handleServiceDisconnected(e){try{await this.refreshToolsCache(),await this.refreshCustomMCPHandlerPublic()}catch{}}async handleServiceConnectionFailed(e){try{await this.refreshCustomMCPHandlerPublic()}catch{}}async startAllServices(){try{this.customMCPHandler.initialize()}catch{}let e=Object.entries(this.configs);if(e.length===0)return;let t=e.map(async([a])=>{try{return await this.startService(a),{serviceName:a,success:!0,error:null}}catch(l){return{serviceName:a,success:!1,error:l instanceof Error?l.message:String(l)}}}),r=await Promise.allSettled(t),o=0,n=0,i=[];for(let a of r)a.status==="fulfilled"?a.value.success?o++:(n++,i.push(a.value.serviceName)):n++;i.length>0&&e.length,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 _(t);await r.connect(),this.services.set(e,r),await this.refreshToolsCache();let o=r.getTools()}catch(r){throw this.services.delete(e),r}}async stopService(e){let t=this.services.get(e);if(t)try{await t.disconnect(),this.services.delete(e),await this.refreshToolsCache()}catch(r){throw r}}async refreshToolsCache(){this.tools.clear();for(let[e,t]of this.services)if(t.isConnected()){let r=t.getTools(),o=this.configs[e];o&&this.cacheManager.writeCacheEntry(e,r,o).then(()=>{}).catch(n=>{});for(let n of r){let i=`${e}__${n.name}`;this.tools.set(i,{serviceName:e,originalName:n.name,tool:n})}}await this.syncToolsConfigToFile()}getAllTools(){let e=[];for(let[r,o]of this.services)try{if(o.isConnected()){let n=o.getTools();for(let i of n)try{if(!h.isToolEnabled(r,i.name))continue;let l=`${r}__${i.name}`;e.push({name:l,description:i.description||"",inputSchema:i.inputSchema,serviceName:r,originalName:i.name})}catch{}}}catch{}let t=[];try{t=this.customMCPHandler.getTools()}catch{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{}return 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||"customMCP";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,r){let o=Date.now(),n="unknown",i=e;try{let a;if(this.customMCPHandler.hasTool(e)){let l=this.customMCPHandler.getToolInfo(e);l&&(n=this.getLogServerName(l),i=this.getOriginalToolName(e,l)),l?.handler?.type==="mcp"?(a=await this.callMCPTool(e,l.handler.config,t),this.updateToolStatsSafe(e,l.handler.config.serviceName,l.handler.config.toolName,!0)):(a=await this.customMCPHandler.callTool(e,t,r),this.updateToolStatsSafe(e,"customMCP",e,!0))}else{let l=this.tools.get(e);if(!l)throw new Error(`\u672A\u627E\u5230\u5DE5\u5177: ${e}`);n=l.serviceName,i=l.originalName;let m=this.services.get(l.serviceName);if(!m)throw new Error(`\u670D\u52A1 ${l.serviceName} \u4E0D\u53EF\u7528`);if(!m.isConnected())throw new Error(`\u670D\u52A1 ${l.serviceName} \u672A\u8FDE\u63A5`);a=await m.callTool(l.originalName,t||{}),this.updateToolStatsSafe(e,l.serviceName,l.originalName,!0)}return this.toolCallLogger.recordToolCall({toolName:i,serverName:n,arguments:t,result:a,success:a.isError!==!0,duration:Date.now()-o}),a}catch(a){if(this.toolCallLogger.recordToolCall({toolName:i,serverName:n,arguments:t,result:null,success:!1,duration:Date.now()-o,error:a instanceof Error?a.message:String(a)}),this.customMCPHandler.hasTool(e)){let l=this.customMCPHandler.getToolInfo(e);l?.handler?.type==="mcp"?this.updateToolStatsSafe(e,l.handler.config.serviceName,l.handler.config.toolName,!1):this.updateToolStatsSafe(e,"customMCP",e,!1)}else{let l=this.tools.get(e);l&&this.updateToolStatsSafe(e,l.serviceName,l.originalName,!1)}throw a}}async updateToolStats(e,t,r,o){try{let n=new Date().toISOString();o?(await this.updateCustomMCPToolStats(e,n),t!=="customMCP"&&await this.updateMCPServerToolStats(t,r,n)):(await this.updateCustomMCPToolLastUsedTime(e,n),t!=="customMCP"&&await this.updateMCPServerToolLastUsedTime(t,r,n))}catch(n){throw n}}async updateToolStatsSafe(e,t,r,o){try{await this.updateToolStats(e,t,r,o)}catch{let i=o?"\u7EDF\u8BA1\u4FE1\u606F":"\u5931\u8D25\u7EDF\u8BA1\u4FE1\u606F"}}async updateCustomMCPToolStats(e,t){try{await h.updateToolUsageStatsWithLock(e,!0)}catch(r){throw r}}async updateCustomMCPToolLastUsedTime(e,t){try{await h.updateToolUsageStatsWithLock(e,!1)}catch(r){throw r}}async updateMCPServerToolStats(e,t,r){try{await h.updateMCPServerToolStatsWithLock(e,t,r,!0)}catch(o){throw o}}async updateMCPServerToolLastUsedTime(e,t,r){try{await h.updateMCPServerToolStatsWithLock(e,t,r,!1)}catch(o){throw o}}async callMCPTool(e,t,r){let{serviceName:o,toolName:n}=t,i=this.services.get(o);if(!i)throw new Error(`\u670D\u52A1 ${o} \u4E0D\u53EF\u7528`);if(!i.isConnected())throw new Error(`\u670D\u52A1 ${o} \u672A\u8FDE\u63A5`);try{return await i.callTool(n,r||{})}catch(a){throw a}}hasTool(e){return this.customMCPHandler.hasTool(e)?!0:this.tools.has(e)}async stopAllServices(){this.stopAllServiceRetries();for(let[e,t]of this.services)try{await t.disconnect()}catch{}try{this.customMCPHandler.cleanup()}catch{}try{h.clearAllStatsUpdateLocks()}catch{}this.services.clear(),this.tools.clear()}getStatus(){return this.getUnifiedStatus()}getStatsUpdateInfo(){try{let e=h.getStatsUpdateLocks();return{activeLocks:e,totalLocks:e.length}}catch{return{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.customMCPHandler.initialize()}catch(e){throw 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{return!1}}getCustomMCPTools(){try{return this.customMCPHandler.getTools()}catch{return[]}}isModelScopeService(e){return e.url?Ie(e.url):!1}handleModelScopeAuth(e,t){if(e.headers?.Authorization)return;let o=h.getModelScopeApiKey();if(o){t.apiKey=o;return}let n=e.url||"\u672A\u77E5",i=e.name||"\u672A\u77E5";throw new Error(`ModelScope \u670D\u52A1 "${i}" \u9700\u8981\u8BA4\u8BC1\u4FE1\u606F\uFF0C\u4F46\u672A\u627E\u5230\u6709\u6548\u7684\u8BA4\u8BC1\u914D\u7F6E\u3002\u670D\u52A1 URL: ${n}\u8BF7\u9009\u62E9\u4EE5\u4E0B\u4EFB\u4E00\u65B9\u5F0F\u914D\u7F6E\u8BA4\u8BC1\uFF1A1. \u5728\u670D\u52A1\u914D\u7F6E\u4E2D\u6DFB\u52A0 headers.Authorization2. \u6216\u8005\u5728\u5168\u5C40\u914D\u7F6E\u4E2D\u8BBE\u7F6E modelscope.apiKey3. \u6216\u8005\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF MODELSCOPE_API_TOKEN\u83B7\u53D6 ModelScope API Key: https://modelscope.cn/my?myInfo=true`)}enhanceServiceConfig(e){let t={...e};try{return this.isModelScopeService(e)&&this.handleModelScopeAuth(e,t),t}catch(r){throw r}}addServiceConfig(e,t){let r,o;if(typeof e=="string"&&t)o=e,r=t;else if(typeof e=="object")o=e.name,r=e;else throw new Error("Invalid arguments for addServiceConfig");let n=this.enhanceServiceConfig(r);this.configs[o]=n}updateServiceConfig(e,t){let r=this.enhanceServiceConfig(t);this.configs[e]=r}removeServiceConfig(e){delete this.configs[e]}async syncToolsConfigToFile(){try{let e=h.getMcpServerConfig();for(let[t,r]of this.services){if(!r.isConnected())continue;let o=r.getTools();if(o.length===0)continue;let n=e[t]?.tools||{},i={};for(let p of o){let E=n[p.name];E?i[p.name]={...E,description:p.description||E.description||""}:i[p.name]={description:p.description||"",enable:!0}}let a=o.map(p=>p.name),m=Object.keys(n).filter(p=>!a.includes(p));if(m.length>0,this.hasToolsConfigChanged(n,i)){h.updateServerToolsConfig(t,i);let p=Object.keys(i).filter(A=>!n[A]),E=Object.keys(i).filter(A=>{let te=n[A],he=i[A];return te&&te.description!==he.description});p.length>0,E.length>0,m.length>0}}}catch{}}hasToolsConfigChanged(e,t){let r=Object.keys(e),o=Object.keys(t);if(r.length!==o.length)return!0;let n=o.filter(a=>!r.includes(a)),i=r.filter(a=>!o.includes(a));if(n.length>0||i.length>0)return!0;for(let a of r){let l=e[a],m=t[a];if(l.description!==m.description)return!0}return!1}scheduleFailedServicesRetry(e){if(e.length===0)return;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));let o=setTimeout(async()=>{this.retryTimers.delete(e),await this.retryFailedService(e)},t);this.retryTimers.set(e,o)}async retryFailedService(e){if(this.failedServices.has(e))try{await this.startService(e),this.failedServices.delete(e);try{await this.refreshCustomMCPHandlerPublic()}catch{}}catch{let r=this.getRetryDelay(e),o=Math.min(r*2,3e5);this.scheduleServiceRetry(e,o)}}getRetryDelay(e){return 3e4+e.split("").reduce((r,o)=>r+o.charCodeAt(0),0)%6e4}stopServiceRetry(e){let t=this.retryTimers.get(e);t&&(clearTimeout(t),this.retryTimers.delete(e)),this.failedServices.delete(e)}stopAllServiceRetries(){for(let[e,t]of this.retryTimers)clearTimeout(t);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}}async registerTransport(e,t){if(this.transportAdapters.has(e))throw new Error(`\u4F20\u8F93\u9002\u914D\u5668 ${e} \u5DF2\u5B58\u5728`);try{await t.initialize(),this.transportAdapters.set(e,t),this.emit("transportRegistered",{name:e,adapter:t})}catch(r){throw r}}async startTransports(){let e=[],t=[];for(let[r,o]of this.transportAdapters)try{await o.start(),e.push(r)}catch{t.push(r)}if(e.length===0&&t.length>0){let r=`\u6240\u6709\u4F20\u8F93\u9002\u914D\u5668\u542F\u52A8\u5931\u8D25\uFF0C\u5931\u8D25\u7684\u9002\u914D\u5668: ${t.join(", ")}`;throw new Error(r)}t.length>0}async stopTransports(){try{for(let[e,t]of this.transportAdapters)try{await t.stop()}catch{}}catch(e){throw e}}getTransportAdapters(){return new Map(this.transportAdapters)}getMessageHandler(){return this.messageHandler}async start(){if(this.isRunning)throw new Error("\u670D\u52A1\u5668\u5DF2\u5728\u8FD0\u884C");try{await this.startAllServices(),await this.startTransports(),this.isRunning=!0,this.emit("started")}catch(e){throw e}}async stop(){if(this.isRunning)try{await this.stopTransports(),await this.stopAllServices(),this.isRunning=!1,this.emit("stopped")}catch(e){throw e}}getAllConnections(){let e=[];for(let[t,r]of this.services)r.isConnected()&&e.push({id:`service-${t}`,name:t,state:"connected"});for(let[t,r]of this.transportAdapters)e.push({id:r.getConnectionId(),name:t,state:r.getState()});return e}getActiveConnectionCount(){return this.getAllConnections().filter(e=>e.state==="connected").length}getUnifiedStatus(){let e=this.getServiceManagerStatus();return{isRunning:this.isRunning,serviceStatus:e,transportCount:this.getTransportAdapters().size,activeConnections:this.getActiveConnectionCount(),config:this.config,services:e.services,totalTools:e.totalTools,availableTools:e.availableTools}}getServiceManagerStatus(){let e=0,t=[];try{e=this.customMCPHandler.getToolCount(),t=this.customMCPHandler.getToolNames()}catch{e=0,t=[]}let r=this.tools.size+e,n=[...Array.from(this.tools.keys()),...t],i={services:{},totalTools:r,availableTools:n};for(let[a,l]of this.services){let m=l.getStatus();i.services[a]={connected:m.connected,clientName:`xiaozhi-${a}-client`}}return e>0&&(i.services.customMCP={connected:!0,clientName:"xiaozhi-customMCP-handler"}),i}isServerRunning(){return this.isRunning}isUnifiedServerConfig(e){return e!==null&&typeof e=="object"&&"configs"in e}async routeMessage(e){let t=await this.messageHandler.handleMessage(e);return t===null?null:{jsonrpc:"2.0",method:"response",params:t,id:t.id}}async initialize(){await this.start()}getToolRegistry(){return this}getConnectionManager(){return this}};import{Client as Ve}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as Le}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as Ae}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as De}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{EventSource as ze}from"eventsource";typeof global<"u"&&!global.EventSource&&(global.EventSource=ze);function Oe(s){switch(s.type){case"stdio":return He(s);case"sse":return Fe(s);case"streamable-http":return je(s);default:throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${s.type}`)}}c(Oe,"createTransport");function He(s){if(!s.command)throw new Error("stdio transport \u9700\u8981 command \u914D\u7F6E");return new Ae({command:s.command,args:s.args||[],env:s.env})}c(He,"createStdioTransport");function Fe(s){if(!s.url)throw new Error("SSE transport \u9700\u8981 URL \u914D\u7F6E");let e=new URL(s.url),t=We(s);return new Le(e,t)}c(Fe,"createSSETransport");function je(s){if(!s.url)throw new Error("StreamableHTTP transport \u9700\u8981 URL \u914D\u7F6E");let e=new URL(s.url),t=Ue(s);return new De(e,t)}c(je,"createStreamableHTTPTransport");function We(s){let e={};return s.apiKey?e.requestInit={headers:{Authorization:`Bearer ${s.apiKey}`,...s.headers}}:s.headers&&(e.requestInit={headers:s.headers}),e}c(We,"createSSEOptions");function Ue(s){let e={};return s.apiKey?e.requestInit={headers:{Authorization:`Bearer ${s.apiKey}`,...s.headers}}:s.headers&&(e.requestInit={headers:s.headers}),e}c(Ue,"createStreamableHTTPOptions");function _e(s){if(!s.name||typeof s.name!="string")throw new Error("\u914D\u7F6E\u5FC5\u987B\u5305\u542B\u6709\u6548\u7684 name \u5B57\u6BB5");if(s.type&&!Object.values($).includes(s.type))throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${s.type}`);if(!s.type)throw new Error("\u4F20\u8F93\u7C7B\u578B\u672A\u8BBE\u7F6E\uFF0C\u8FD9\u5E94\u8BE5\u5728 inferTransportType \u4E2D\u5904\u7406");switch(s.type){case"stdio":if(!s.command)throw new Error("stdio \u7C7B\u578B\u9700\u8981 command \u5B57\u6BB5");break;case"sse":if(s.url===void 0||s.url===null)throw new Error(`${s.type} \u7C7B\u578B\u9700\u8981 url \u5B57\u6BB5`);break;case"streamable-http":if(s.url===void 0||s.url===null)throw new Error(`${s.type} \u7C7B\u578B\u9700\u8981 url \u5B57\u6BB5`);break;default:throw new Error(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${s.type}`)}}c(_e,"validateConfig");function Be(){return["stdio","sse","streamable-http"]}c(Be,"getSupportedTypes");var X={create:Oe,validateConfig:_e,getSupportedTypes:Be};var ee;(t=>{function s(r){if(!r||typeof r!="object")return r;let o=JSON.parse(JSON.stringify(r));if(!("type"in o))return o;let n=o.type;if(n==="sse"||n==="streamable-http")return o;let i;return n==="streamableHttp"||n==="streamable_http"?i="streamable-http":n==="s_se"||n==="s-se"?i="sse":i=e(n),(i==="sse"||i==="streamable-http")&&(o.type=i),o}t.normalizeTypeField=s,c(s,"normalizeTypeField");function e(r){return r.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/_/g,"-").toLowerCase()}c(e,"convertToKebabCase")})(ee||={});function Ke(s,e){try{let r=new URL(s).pathname;return r.endsWith("/sse")?"sse":r.endsWith("/mcp")?"streamable-http":(e?.serviceName,"streamable-http")}catch{return e?.serviceName,"streamable-http"}}c(Ke,"inferTransportTypeFromUrl");function le(s){if(s.type)return ee.normalizeTypeField(s);if(s.command)return{...s,type:"stdio"};if(s.url!==void 0&&s.url!==null){let e=Ke(s.url,{serviceName:s.name});return{...s,type:e}}throw new Error(`\u65E0\u6CD5\u4E3A\u670D\u52A1 ${s.name} \u63A8\u65AD\u4F20\u8F93\u7C7B\u578B\u3002\u8BF7\u663E\u5F0F\u6307\u5B9A type \u5B57\u6BB5\uFF0C\u6216\u63D0\u4F9B command/url \u914D\u7F6E`)}c(le,"inferTransportTypeFromConfig");function ce(s,e){let t={validateName:!0,validateArguments:!0,allowEmptyArguments:!0,...e};if(!s||typeof s!="object")throw new S(-32602,"\u8BF7\u6C42\u53C2\u6570\u5FC5\u987B\u662F\u5BF9\u8C61");let r=s;if(t.validateName&&(!r.name||typeof r.name!="string"))throw new S(-32602,"\u5DE5\u5177\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(t.validateArguments&&r.arguments!==void 0&&r.arguments!==null&&(typeof r.arguments!="object"||Array.isArray(r.arguments)))throw new S(-32602,"\u5DE5\u5177\u53C2\u6570\u5FC5\u987B\u662F\u5BF9\u8C61");if(!t.allowEmptyArguments&&r.arguments!==void 0&&r.arguments!==null){let o=r.arguments;if(Object.keys(o).length===0)throw new S(-32602,"\u5DE5\u5177\u53C2\u6570\u4E0D\u80FD\u4E3A\u7A7A")}if(t.customValidator){let o=t.customValidator(r);if(o)throw new S(-32602,o)}return{name:r.name,arguments:r.arguments}}c(ce,"validateToolCallParams");var _=class{static{c(this,"MCPService")}config;client=null;transport=null;tools=new Map;connectionState="disconnected";connectionTimeout=null;initialized=!1;eventBus=T();constructor(e){this.config=le(e),this.validateConfig()}validateConfig(){X.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.attemptConnection()}async attemptConnection(){return this.connectionState="connecting",new Promise((e,t)=>{this.connectionTimeout=setTimeout(()=>{let r=new Error(`\u8FDE\u63A5\u8D85\u65F6 (${this.config.timeout||1e4}ms)`);this.handleConnectionError(r),t(r)},this.config.timeout||1e4);try{this.client=new Ve({name:`xiaozhi-${this.config.name}-client`,version:"1.0.0"},{capabilities:{}}),this.transport=X.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}handleConnectionError(e){this.connectionState="disconnected",this.initialized=!1,this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.cleanupConnection(),this.eventBus.emitEvent("mcp:service:connection:failed",{serviceName:this.config.name,error:e,attempt:0})}cleanupConnection(){if(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}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)}catch(e){throw e}}async disconnect(){this.cleanupConnection(),this.connectionState="disconnected",this.eventBus.emitEvent("mcp:service:disconnected",{serviceName:this.config.name,reason:"\u624B\u52A8\u65AD\u5F00",disconnectionTime:new Date})}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`);try{return await this.client.callTool({name:e,arguments:t||{}})}catch(r){throw r}}getConfig(){return this.config}getStatus(){return{name:this.config.name,connected:this.connectionState==="connected",initialized:this.initialized,transportType:this.config.type||"streamable-http",toolCount:this.tools.size,connectionState:this.connectionState}}isConnected(){return this.connectionState==="connected"&&this.initialized}};import{createHash as Je}from"crypto";import{existsSync as L,mkdirSync as Ge,readFileSync as me,renameSync as Qe,writeFileSync as ue}from"fs";import{dirname as Ze,resolve as ge}from"path";import{Hono as Vr}from"hono";import qe from"dayjs";var b=class{static{c(this,"MCPCacheManager")}cachePath;logger;CACHE_VERSION="1.0.0";CACHE_ENTRY_VERSION="1.0.0";cleanupInterval;CLEANUP_INTERVAL=6e4;constructor(e){this.logger=v,this.cachePath=e||this.getCacheFilePath(),this.startCleanupTimer()}formatTimestamp(){return qe().format("YYYY-MM-DD HH:mm:ss")}getCacheFilePath(){try{let e=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return ge(e,"xiaozhi.cache.json")}catch{let t=process.env.XIAOZHI_CONFIG_DIR||"/tmp";return ge(t,"xiaozhi.cache.json")}}async ensureCacheFile(){try{if(!L(this.cachePath)){let e=Ze(this.cachePath);L(e)||(Ge(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 o=await this.loadExistingCache(),n=this.generateConfigHash(r),i={tools:t.map(a=>({name:a.name,description:a.description||"",inputSchema:a.inputSchema})),lastUpdated:this.formatTimestamp(),serverConfig:{...r},configHash:n,version:this.CACHE_ENTRY_VERSION};o.mcpServers[e]=i,o.metadata.lastGlobalUpdate=this.formatTimestamp(),o.metadata.totalWrites+=1,await this.saveCache(o),this.logger.debug(`[CacheManager] \u7F13\u5B58\u5199\u5165\u6210\u529F: ${e}, \u5DE5\u5177\u6570\u91CF: ${t.length}`)}catch(o){this.logger.warn(`[CacheManager] \u7F13\u5B58\u5199\u5165\u5931\u8D25: ${e}, \u9519\u8BEF: ${o instanceof Error?o.message:String(o)}`)}}async loadExistingCache(){try{if(!L(this.cachePath))return await this.createInitialCache();let e=me(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{ue(r,t,"utf8"),Qe(r,e)}catch(o){try{L(r)&&ue(r,"","utf8")}catch{}throw o}}generateConfigHash(e){try{return Je("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{if(!e||typeof e!="object")return!1;let t=e,r=t.metadata;return typeof t.version=="string"&&typeof t.mcpServers=="object"&&t.mcpServers!==null&&t.metadata!==null&&t.metadata!==void 0&&typeof r=="object"&&r!==null&&typeof r.lastGlobalUpdate=="string"&&typeof r.totalWrites=="number"&&typeof r.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:L(this.cachePath)?me(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,o]of Object.entries(e.mcpServers))for(let n of o.tools)t.push({...n,name:`${r}__${n.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,o="completed",n,i=3e5){try{let a=await this.loadExtendedCache(),l=f(e,t),m={result:r,timestamp:new Date().toISOString(),ttl:i,status:o,consumed:!1,taskId:n,retryCount:0};a.customMCPResults||(a.customMCPResults={}),a.customMCPResults[l]=m,await this.saveExtendedCache(a),this.logger.debug(`[CacheManager] \u5199\u5165CustomMCP\u7ED3\u679C\u7F13\u5B58: ${e}, \u72B6\u6001: ${o}`)}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(),o=f(e,t);if(!r.customMCPResults||!r.customMCPResults[o])return null;let n=r.customMCPResults[o],i=Date.now(),a=new Date(n.timestamp).getTime();return i-a>n.ttl?(this.logger.debug(`[CacheManager] \u7F13\u5B58\u5DF2\u8FC7\u671F: ${e}`),null):n}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,o,n){try{let i=await this.loadExtendedCache(),a=f(e,t);if(!i.customMCPResults||!i.customMCPResults[a])return!1;let l=i.customMCPResults[a],m=l.status;return l.status=r,l.timestamp=new Date().toISOString(),o&&(l.result=o),n&&r==="failed"&&(l.result={content:[{type:"text",text:`\u4EFB\u52A1\u5931\u8D25: ${n}`}]},l.consumed=!0),r==="completed"&&(l.consumed=!1),await this.saveExtendedCache(i),this.logger.debug(`[CacheManager] \u66F4\u65B0\u7F13\u5B58\u72B6\u6001: ${e} ${m} -> ${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(),o=f(e,t);if(!r.customMCPResults||!r.customMCPResults[o])return!1;let n=r.customMCPResults[o];return n.consumed||(n.consumed=!0,n.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(),o=f(e,t);return!r.customMCPResults||!r.customMCPResults[o]?!1:(delete r.customMCPResults[o],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[o,n]of t)k(n)&&(delete e.customMCPResults[o],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,o=t.filter(C=>C.status==="pending").length,n=t.filter(C=>C.status==="completed").length,i=t.filter(C=>C.status==="failed").length,a=t.filter(C=>C.consumed).length,l=n>0?a/n*100:0,m=JSON.stringify(e.customMCPResults).length;return{totalEntries:r,pendingTasks:o,completedTasks:n,failedTasks:i,consumedEntries:a,cacheHitRate:l,lastCleanupTime:new Date().toISOString(),memoryUsage:m}}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")}};import{configManager as Ye}from"@xiaozhi-client/config";var B=class s{static{c(this,"MCPServiceManagerSingleton")}static instance=null;static getInstance(){if(!s.instance){let e=Ye.getMcpServers();s.instance=new U(e)}return s.instance}static reset(){s.instance=null}},Eo=B.getInstance(),Ro=B;export{Ro as default,Eo as mcpServiceManager};
|
|
27
|
+
//# sourceMappingURL=MCPServiceManagerSingleton.js.map
|