@xiaozhi-client/config 1.9.7-beta.17 → 1.9.7-beta.18

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/index.d.ts CHANGED
@@ -552,8 +552,7 @@ declare const configManager: ConfigManager;
552
552
  * 配置验证错误类
553
553
  */
554
554
  declare class ConfigValidationError extends Error {
555
- readonly configName?: string | undefined;
556
- constructor(message: string, configName?: string | undefined);
555
+ constructor(message: string);
557
556
  }
558
557
  declare enum MCPTransportType {
559
558
  STDIO = "stdio",
@@ -561,23 +560,21 @@ declare enum MCPTransportType {
561
560
  HTTP = "http"
562
561
  }
563
562
  interface MCPServiceConfig {
564
- name: string;
565
563
  type: MCPTransportType;
566
564
  command?: string;
567
565
  args?: string[];
568
566
  env?: Record<string, string>;
569
567
  url?: string;
570
568
  headers?: Record<string, string>;
571
- modelScopeAuth?: boolean;
572
569
  }
573
570
  /**
574
- * 将旧的 MCPServerConfig 转换为新的 MCPServiceConfig
571
+ * 将各种配置格式标准化为统一的服务配置格式
575
572
  */
576
- declare function convertLegacyToNew(serviceName: string, legacyConfig: MCPServerConfig): MCPServiceConfig;
573
+ declare function normalizeServiceConfig(config: MCPServerConfig): MCPServiceConfig;
577
574
  /**
578
- * 批量转换配置
575
+ * 批量标准化配置
579
576
  */
580
- declare function convertLegacyConfigBatch(legacyConfigs: Record<string, MCPServerConfig>): Record<string, MCPServiceConfig>;
577
+ declare function normalizeServiceConfigBatch(legacyConfigs: Record<string, MCPServerConfig>): Record<string, MCPServiceConfig>;
581
578
  /**
582
579
  * 检查是否为 ModelScope URL
583
580
  * 使用 URL hostname 检查而非简单的字符串包含检查,防止安全绕过
@@ -662,4 +659,4 @@ declare class ConfigInitializer {
662
659
  private static getDefaultTemplateDir;
663
660
  }
664
661
 
665
- export { type AppConfig, type ChainHandlerConfig, ConfigInitializer, ConfigManager, ConfigResolver, ConfigValidationError, type ConnectionConfig, type CozePlatformConfig, type CustomMCPConfig, type CustomMCPTool, type FunctionHandlerConfig, type HTTPMCPServerConfig, type HandlerConfig, type HttpHandlerConfig, type LocalMCPServerConfig, type MCPHandlerConfig, type MCPServerConfig, type MCPServerToolsConfig, type MCPServiceConfig, type MCPToolConfig, MCPTransportType, type ModelScopeConfig, type PlatformConfig, type PlatformsConfig, type ProxyHandlerConfig, type SSEMCPServerConfig, type ScriptHandlerConfig, type StreamableHTTPMCPServerConfig, type ToolCallLogConfig, type WebServerInstance, type WebUIConfig, configManager, convertLegacyConfigBatch, convertLegacyToNew, getConfigTypeDescription, isModelScopeURL };
662
+ export { type AppConfig, type ChainHandlerConfig, ConfigInitializer, ConfigManager, ConfigResolver, ConfigValidationError, type ConnectionConfig, type CozePlatformConfig, type CustomMCPConfig, type CustomMCPTool, type FunctionHandlerConfig, type HTTPMCPServerConfig, type HandlerConfig, type HttpHandlerConfig, type LocalMCPServerConfig, type MCPHandlerConfig, type MCPServerConfig, type MCPServerToolsConfig, type MCPServiceConfig, type MCPToolConfig, MCPTransportType, type ModelScopeConfig, type PlatformConfig, type PlatformsConfig, type ProxyHandlerConfig, type SSEMCPServerConfig, type ScriptHandlerConfig, type StreamableHTTPMCPServerConfig, type ToolCallLogConfig, type WebServerInstance, type WebUIConfig, configManager, getConfigTypeDescription, isModelScopeURL, normalizeServiceConfig, normalizeServiceConfigBatch };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var $=Object.defineProperty;var a=(r,e)=>$(r,"name",{value:e,configurable:!0});import{copyFileSync as G,existsSync as U,readFileSync as Y,writeFileSync as q}from"fs";import{dirname as X,resolve as u}from"path";import{fileURLToPath as Z}from"url";import*as m from"comment-json";import j from"dayjs";import*as C from"comment-json";function x(r){let e=C.parse(r);return{write(t){e&&typeof e=="object"&&t&&Object.assign(e,t)},toSource(){return C.stringify(e,null,2)}}}a(x,"createJson5Writer");function k(r){return C.parse(r)}a(k,"parseJson5");import P from"path";import{existsSync as J}from"fs";var f=class{static{a(this,"ConfigResolver")}static resolveConfigPath(){if(process.env.XIAOZHI_CONFIG_DIR){let o=this.findConfigInDir(process.env.XIAOZHI_CONFIG_DIR);if(o)return o}let e=this.findConfigInDir(process.cwd());if(e)return e;let t=process.env.HOME||process.env.USERPROFILE;if(t){let o=P.join(t,".xiaozhi-client"),n=this.findConfigInDir(o);if(n)return n}return null}static findConfigInDir(e){let t=["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"];for(let o of t){let n=P.join(e,o);if(J(n))return n}return null}static getDefaultConfigDir(){let e=process.env.HOME||process.env.USERPROFILE;return e?P.join(e,".xiaozhi-client"):null}};var H=X(Z(import.meta.url)),b={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},S=class r{static{a(this,"ConfigManager")}static instance;defaultConfigPath;config=null;currentConfigPath=null;json5Writer=null;statsUpdateLocks=new Map;statsUpdateLockTimeouts=new Map;STATS_UPDATE_TIMEOUT=5e3;eventCallbacks=new Map;constructor(){let e=[u(H,"templates","default","xiaozhi.config.json"),u(H,"..","templates","default","xiaozhi.config.json"),u(process.cwd(),"templates","default","xiaozhi.config.json")];this.defaultConfigPath=e.find(t=>U(t))||e[0]}on(e,t){this.eventCallbacks.has(e)||this.eventCallbacks.set(e,[]),this.eventCallbacks.get(e)?.push(t)}emitEvent(e,t){let o=this.eventCallbacks.get(e);if(o)for(let n of o)try{n(t)}catch{}}getConfigFilePath(){let e=f.resolveConfigPath();if(e)return e;let t=f.getDefaultConfigDir();if(t)return u(t,"xiaozhi.config.json");let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return u(o,"xiaozhi.config.json")}getConfigFileFormat(e){return e.endsWith(".json5")?"json5":e.endsWith(".jsonc")?"jsonc":"json"}static getInstance(){return r.instance||(r.instance=new r),r.instance}configExists(){return f.resolveConfigPath()!==null}initConfig(e="json"){if(!U(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(),o=`xiaozhi.config.${e}`,n=u(t,o);G(this.defaultConfigPath,n),this.config=null,this.json5Writer=null}loadConfig(){if(!this.configExists()){let e=new Error("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u8FD0\u884C xiaozhi init \u521D\u59CB\u5316\u914D\u7F6E");throw this.emitEvent("config:error",{error:e,operation:"loadConfig"}),e}try{let e=this.getConfigFilePath();this.currentConfigPath=e;let t=this.getConfigFileFormat(e),n=Y(e,"utf8").replace(/^\uFEFF/,""),i;switch(t){case"json5":i=k(n),this.json5Writer=x(n);break;case"jsonc":i=m.parse(n);break;default:i=JSON.parse(n);break}return this.validateConfig(i),i}catch(e){throw this.emitEvent("config:error",{error:e instanceof Error?e:new Error(String(e)),operation:"loadConfig"}),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 o of t.mcpEndpoint)if(typeof o!="string"||o.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[o,n]of Object.entries(t.mcpServers))if(!n||typeof n!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${o} \u65E0\u6548`)}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 o of e)if(!o||typeof o!="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),this.emitEvent("config:updated",{type:"endpoint",timestamp:new Date})}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(),o=this.getMcpEndpoints();if(o.includes(e))throw new Error(`MCP \u7AEF\u70B9 ${e} \u5DF2\u5B58\u5728`);let n=[...o,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(),o=this.getMcpEndpoints();if(o.indexOf(e)===-1)throw new Error(`MCP \u7AEF\u70B9 ${e} \u4E0D\u5B58\u5728`);let i=o.filter(s=>s!==e);t.mcpEndpoint=i,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 o=this.getMutableConfig();o.mcpServers[e]=t,this.saveConfig(o)}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 o=t.customMCP.tools.filter(n=>n.handler?.type==="mcp"&&n.handler.config?.serviceName===e);for(let n of o){let i=t.customMCP.tools.findIndex(s=>s.name===n.name);i!==-1&&t.customMCP.tools.splice(i,1)}t.customMCP.tools.length===0&&(t.customMCP=void 0)}this.saveConfig(t),this.emitEvent("config:updated",{type:"customMCP",timestamp:new Date})}updateConfig(e){let t=this.getMutableConfig();if(e.mcpEndpoint!==void 0&&(t.mcpEndpoint=e.mcpEndpoint),e.mcpServers){let o={...t.mcpServers};for(let[n,i]of Object.entries(e.mcpServers))t.mcpServers[n]=i;for(let n of Object.keys(o))n in e.mcpServers||(delete t.mcpServers[n],t.mcpServerConfig?.[n]&&delete t.mcpServerConfig[n])}if(e.connection&&(t.connection||(t.connection={}),Object.assign(t.connection,e.connection)),e.modelscope&&(t.modelscope||(t.modelscope={}),Object.assign(t.modelscope,e.modelscope)),e.webUI&&(t.webUI||(t.webUI={}),Object.assign(t.webUI,e.webUI)),e.mcpServerConfig)for(let[o,n]of Object.entries(e.mcpServerConfig))t.mcpServerConfig?.[o]&&(t.mcpServerConfig[o]=n);if(e.platforms)for(let[o,n]of Object.entries(e.platforms))t.platforms||(t.platforms={}),t.platforms[o]=n;this.saveConfig(t),this.emitEvent("config:updated",{type:"config",timestamp:new Date})}updateServerToolsConfig(e,t){let o=this.getMutableConfig();o.mcpServerConfig||(o.mcpServerConfig={}),Object.keys(t).length===0?delete o.mcpServerConfig[e]:o.mcpServerConfig[e]={tools:t},this.saveConfig(o),this.emitEvent("config:updated",{type:"serverTools",serviceName:e,timestamp:new Date})}removeServerToolsConfig(e){let o={...this.getConfig()};o.mcpServerConfig&&(delete o.mcpServerConfig[e],this.saveConfig(o))}cleanupInvalidServerToolsConfig(){let e=this.getMutableConfig();if(!e.mcpServerConfig)return;let t=Object.keys(e.mcpServers),n=Object.keys(e.mcpServerConfig).filter(i=>!t.includes(i));if(n.length>0){for(let i of n)delete e.mcpServerConfig[i];this.saveConfig(e)}}setToolEnabled(e,t,o,n){let i=this.getMutableConfig();i.mcpServerConfig||(i.mcpServerConfig={}),i.mcpServerConfig[e]||(i.mcpServerConfig[e]={tools:{}}),i.mcpServerConfig[e].tools[t]={...i.mcpServerConfig[e].tools[t],enable:o,...n&&{description:n}},this.saveConfig(i)}saveConfig(e){try{this.validateConfig(e);let t;this.currentConfigPath?t=this.currentConfigPath:(t=this.getConfigFilePath(),this.currentConfigPath=t);let o=this.getConfigFileFormat(t),n;switch(o){case"json5":try{this.json5Writer?(this.json5Writer.write(e),n=this.json5Writer.toSource()):n=m.stringify(e,null,2)}catch{n=m.stringify(e,null,2)}break;case"jsonc":try{n=m.stringify(e,null,2)}catch{n=JSON.stringify(e,null,2)}break;default:n=JSON.stringify(e,null,2);break}q(t,n,"utf8"),this.config=e,this.notifyConfigUpdate(e)}catch(t){throw this.emitEvent("config:error",{error:t instanceof Error?t:new Error(String(t)),operation:"saveConfig"}),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??b.heartbeatInterval,heartbeatTimeout:t.heartbeatTimeout??b.heartbeatTimeout,reconnectInterval:t.reconnectInterval??b.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),this.emitEvent("config:updated",{type:"connection",timestamp:new Date})}async updateToolUsageStats(e,t,o){try{if(typeof t=="string"&&o){let n=e,i=t,s=o;await Promise.all([this._updateMCPServerToolStats(n,i,s),this.updateCustomMCPToolStats(n,i,s)])}else{let n=e,i=t,s=new Date().toISOString();await this.updateCustomMCPToolStats(n,s,i)}}catch{if(typeof t=="string"&&o){let i=e,s=t}else{let i=e}}}async updateMCPServerToolStats(e,t,o,n=!0){await this._updateMCPServerToolStats(e,t,o,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),this.emitEvent("config:updated",{type:"modelscope",timestamp:new Date})}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"||!t.description||typeof t.description!="string"||!t.inputSchema||typeof t.inputSchema!="object"||!t.handler||typeof t.handler!="object"||!["proxy","function","http","script","chain","mcp"].includes(t.handler.type)||!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!1}}validateProxyHandler(e,t){return!(!t.platform||!["coze","openai","anthropic","custom"].includes(t.platform)||!t.config||typeof t.config!="object"||t.platform==="coze"&&!t.config.workflow_id&&!t.config.bot_id)}validateHttpHandler(e,t){if(!t.url||typeof t.url!="string")return!1;try{new URL(t.url)}catch{return!1}return!(t.method&&!["GET","POST","PUT","DELETE","PATCH"].includes(t.method))}validateFunctionHandler(e,t){return!(!t.module||typeof t.module!="string"||!t.function||typeof t.function!="string")}validateScriptHandler(e,t){return!(!t.script||typeof t.script!="string"||t.interpreter&&!["node","python","bash"].includes(t.interpreter))}validateChainHandler(e,t){return!(!t.tools||!Array.isArray(t.tools)||t.tools.length===0||!["sequential","parallel"].includes(t.mode)||!["stop","continue","retry"].includes(t.error_handling))}validateMCPHandler(e,t){return!(!t.config||typeof t.config!="object"||!t.config.serviceName||typeof t.config.serviceName!="string"||!t.config.toolName||typeof t.config.toolName!="string")}hasValidCustomMCPTools(){try{let e=this.getCustomMCPTools();return e.length===0?!1:this.validateCustomMCPTools(e)}catch{return!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)}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 o=new Set(t.customMCP.tools.map(i=>i.name)),n=e.filter(i=>!o.has(i.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.emitEvent("config:updated",{type:"customMCP",timestamp:new Date})}}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 o=t.customMCP.tools.findIndex(n=>n.name===e);if(o===-1)throw new Error(`\u5DE5\u5177 "${e}" \u4E0D\u5B58\u5728`);t.customMCP.tools.splice(o,1),this.saveConfig(t)}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 o=this.getMutableConfig();if(!o.customMCP||!o.customMCP.tools)throw new Error("\u672A\u914D\u7F6E\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177");let n=o.customMCP.tools.findIndex(i=>i.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");o.customMCP.tools[n]=t,this.saveConfig(o)}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.emitEvent("config:updated",{type:"customMCP",timestamp:new Date})}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)}catch{}}updateWebUIConfig(e){let t=this.getMutableConfig();t.webUI||(t.webUI={}),Object.assign(t.webUI,e),this.saveConfig(t),this.emitEvent("config:updated",{type:"webui",timestamp:new Date})}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 o=this.getMutableConfig();o.platforms||(o.platforms={}),o.platforms[e]=t,this.saveConfig(o),this.emitEvent("config:updated",{type:"platform",platformName:e,timestamp:new Date})}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,o,n=!0){let i=this.getMutableConfig();i.mcpServerConfig||(i.mcpServerConfig={}),i.mcpServerConfig[e]||(i.mcpServerConfig[e]={tools:{}}),i.mcpServerConfig[e].tools[t]||(i.mcpServerConfig[e].tools[t]={enable:!0});let s=i.mcpServerConfig[e].tools[t],l=s.usageCount||0,g=s.lastUsedTime;n&&(s.usageCount=l+1),(!g||new Date(o)>new Date(g))&&(s.lastUsedTime=j(o).format("YYYY-MM-DD HH:mm:ss")),this.saveConfig(i)}async updateCustomMCPToolStats(e,t,o){try{let n,i,s=!0,l;if(typeof o=="string"){let h=e;n=`${h}__${t}`,i=o,l=`${h}/${t}`}else n=e,i=t,s=o||!0,l=n;let g=this.getCustomMCPTools(),T=g.findIndex(h=>h.name===n);if(T===-1)return;let E=[...g],p=E[T];p.stats||(p.stats={});let W=p.stats.usageCount||0,I=p.stats.lastUsedTime;s&&(p.stats.usageCount=W+1),(!I||new Date(i)>new Date(I))&&(p.stats.lastUsedTime=j(i).format("YYYY-MM-DD HH:mm:ss")),await this.updateCustomMCPTools(E)}catch{if(typeof o=="string"){let i=e,s=t}else{let i=e}}}async acquireStatsUpdateLock(e){if(this.statsUpdateLocks.has(e))return!1;let t=new Promise(n=>{});this.statsUpdateLocks.set(e,t);let o=setTimeout(()=>{this.releaseStatsUpdateLock(e)},this.STATS_UPDATE_TIMEOUT);return this.statsUpdateLockTimeouts.set(e,o),!0}releaseStatsUpdateLock(e){this.statsUpdateLocks.delete(e);let t=this.statsUpdateLockTimeouts.get(e);t&&(clearTimeout(t),this.statsUpdateLockTimeouts.delete(e))}async updateToolUsageStatsWithLock(e,t=!0){let o=`custommcp_${e}`;if(await this.acquireStatsUpdateLock(o))try{await this.updateToolUsageStats(e,t)}catch(n){throw n}finally{this.releaseStatsUpdateLock(o)}}async updateMCPServerToolStatsWithLock(e,t,o,n=!0){let i=`mcpserver_${e}_${t}`;if(await this.acquireStatsUpdateLock(i))try{await this.updateMCPServerToolStats(e,t,o,n)}catch(s){throw s}finally{this.releaseStatsUpdateLock(i)}}clearAllStatsUpdateLocks(){let e=this.statsUpdateLocks.size;this.statsUpdateLocks.clear();for(let t of this.statsUpdateLockTimeouts.values())clearTimeout(t);this.statsUpdateLockTimeouts.clear(),e>0}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()}},be=S.getInstance();import{isAbsolute as K,resolve as D,dirname as B}from"path";var c=class extends Error{constructor(t,o){super(t);this.configName=o;this.name="ConfigValidationError"}static{a(this,"ConfigValidationError")}},L=(o=>(o.STDIO="stdio",o.SSE="sse",o.HTTP="http",o))(L||{});function M(r){try{let t=new URL(r).pathname;return t.endsWith("/sse")?"sse":(t.endsWith("/mcp"),"http")}catch{return"http"}}a(M,"inferTransportTypeFromUrl");function V(r,e){try{if(!r||typeof r!="string")throw new c("\u670D\u52A1\u540D\u79F0\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!e||typeof e!="object")throw new c("\u914D\u7F6E\u5BF9\u8C61\u4E0D\u80FD\u4E3A\u7A7A",r);let t=Q(r,e);return te(t),t}catch(t){throw t instanceof c?t:new c(`\u914D\u7F6E\u8F6C\u6362\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`,r)}}a(V,"convertLegacyToNew");function Q(r,e){if(_(e))return ee(r,e);if("type"in e)switch(e.type){case"sse":return N(r,e);case"http":case"streamable-http":return O(r,e);default:throw new c(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${e.type}`,r)}if("url"in e){if(e.url===void 0||e.url===null)throw new c("\u7F51\u7EDC\u914D\u7F6E\u5FC5\u987B\u5305\u542B\u6709\u6548\u7684 url \u5B57\u6BB5",r);if(M(e.url||"")==="sse"){let n={...e,type:"sse"};return N(r,n)}let o={...e,type:"http"};return O(r,o)}throw new c("\u65E0\u6CD5\u8BC6\u522B\u7684\u914D\u7F6E\u7C7B\u578B",r)}a(Q,"convertByConfigType");function ee(r,e){if(!e.command)throw new c("\u672C\u5730\u914D\u7F6E\u5FC5\u987B\u5305\u542B command \u5B57\u6BB5",r);let t;if(process.env.XIAOZHI_CONFIG_DIR)t=process.env.XIAOZHI_CONFIG_DIR;else{let i=f.resolveConfigPath();i?t=B(i):t=process.cwd()}let o=e.command;R(e.command)&&(o=D(t,e.command));let n=(e.args||[]).map(i=>R(i)?D(t,i):i);return{name:r,type:"stdio",command:o,args:n,env:e.env}}a(ee,"convertLocalConfig");function N(r,e){if(e.url===void 0||e.url===null)throw new c("SSE \u914D\u7F6E\u5FC5\u987B\u5305\u542B url \u5B57\u6BB5",r);let t=e.type==="sse"?"sse":M(e.url||""),o=e.url?w(e.url):!1,n={name:r,type:t,url:e.url,headers:e.headers};return o&&(n.modelScopeAuth=!0),n}a(N,"convertSSEConfig");function O(r,e){if(e.url===void 0||e.url===null)throw new c("HTTP \u914D\u7F6E\u5FC5\u987B\u5305\u542B url \u5B57\u6BB5",r);let t=e.url||"";return{name:r,type:"http",url:t,headers:e.headers}}a(O,"convertHTTPConfig");function Te(r){let e={},t=[];for(let[o,n]of Object.entries(r))try{e[o]=V(o,n)}catch(i){t.push({serviceName:o,error:i instanceof Error?i:new Error(String(i))})}if(t.length>0){let o=t.map(({serviceName:n,error:i})=>`${n}: ${i.message}`).join("; ");throw new c(`\u6279\u91CF\u914D\u7F6E\u8F6C\u6362\u5931\u8D25: ${o}`)}return e}a(Te,"convertLegacyConfigBatch");function R(r){return K(r)?!1:!!(r.startsWith("./")||r.startsWith("../")||/\.(js|py|ts|mjs|cjs)$/i.test(r))}a(R,"isRelativePath");function _(r){return"command"in r&&typeof r.command=="string"}a(_,"isLocalConfig");function w(r){try{let t=new URL(r).hostname.toLowerCase();return t.endsWith(".modelscope.net")||t.endsWith(".modelscope.cn")||t==="modelscope.net"||t==="modelscope.cn"}catch{return!1}}a(w,"isModelScopeURL");function te(r){if(!r.name||typeof r.name!="string")throw new c("\u914D\u7F6E\u5FC5\u987B\u5305\u542B\u6709\u6548\u7684 name \u5B57\u6BB5");if(r.type&&!Object.values(L).includes(r.type))throw new c(`\u65E0\u6548\u7684\u4F20\u8F93\u7C7B\u578B: ${r.type}`);if(!r.type)throw new c("\u4F20\u8F93\u7C7B\u578B\u672A\u6307\u5B9A\uFF0C\u8BF7\u68C0\u67E5\u914D\u7F6E\u6216\u542F\u7528\u81EA\u52A8\u63A8\u65AD");switch(r.type){case"stdio":if(!r.command)throw new c("STDIO \u914D\u7F6E\u5FC5\u987B\u5305\u542B command \u5B57\u6BB5");break;case"sse":if(r.url===void 0||r.url===null)throw new c("SSE \u914D\u7F6E\u5FC5\u987B\u5305\u542B url \u5B57\u6BB5");break;case"http":if(r.url===void 0||r.url===null)throw new c("HTTP \u914D\u7F6E\u5FC5\u987B\u5305\u542B url \u5B57\u6BB5");break;default:throw new c(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${r.type}`)}}a(te,"validateNewConfig");function Ee(r){if(_(r))return`\u672C\u5730\u8FDB\u7A0B (${r.command})`;if("url"in r){if("type"in r&&(r.type==="http"||r.type==="streamable-http"))return`HTTP (${r.url})`;if("type"in r&&r.type==="sse")return`SSE${w(r.url)?" (ModelScope)":""} (${r.url})`;let e=M(r.url),t=w(r.url);return e==="sse"?`SSE${t?" (ModelScope)":""} (${r.url})`:`HTTP (${r.url})`}return"\u672A\u77E5\u7C7B\u578B"}a(Ee,"getConfigTypeDescription");import y from"path";import{mkdirSync as A,existsSync as F,readdirSync as oe,statSync as ne,copyFileSync as re}from"fs";import{dirname as ie,resolve as d}from"path";import{fileURLToPath as se}from"url";var v=ie(se(import.meta.url)),z=class{static{a(this,"ConfigInitializer")}static async initializeDefaultConfig(){let e=process.env.HOME||process.env.USERPROFILE;if(!e)throw new Error("\u65E0\u6CD5\u83B7\u53D6\u7528\u6237\u5BB6\u76EE\u5F55");let t=y.join(e,".xiaozhi-client");if(F(t))return t;A(t,{recursive:!0});let o=this.getDefaultTemplateDir();if(!o)throw new Error("\u9ED8\u8BA4\u914D\u7F6E\u6A21\u677F\u4E0D\u5B58\u5728\uFF0C\u8BF7\u68C0\u67E5\u9879\u76EE\u6A21\u677F\u6587\u4EF6\u662F\u5426\u5B58\u5728");return this.copyDirectoryRecursive(o,t,["template.json",".git","node_modules"]),t}static copyDirectoryRecursive(e,t,o=[]){let n=oe(e);for(let i of n){if(o.includes(i))continue;let s=y.join(e,i),l=y.join(t,i);ne(s).isDirectory()?(A(l,{recursive:!0}),this.copyDirectoryRecursive(s,l,o)):re(s,l)}}static getDefaultTemplateDir(){let e=[d(v,"templates","default"),d(v,"..","templates","default"),d(process.cwd(),"templates","default"),d(v,"..","..","..","templates","default"),d(v,"..","..","..","..","templates","default")];for(let t of e)if(F(t))return t;return null}};export{z as ConfigInitializer,S as ConfigManager,f as ConfigResolver,c as ConfigValidationError,L as MCPTransportType,be as configManager,Te as convertLegacyConfigBatch,V as convertLegacyToNew,Ee as getConfigTypeDescription,w as isModelScopeURL};
1
+ var $=Object.defineProperty;var a=(r,e)=>$(r,"name",{value:e,configurable:!0});import{copyFileSync as G,existsSync as j,readFileSync as Y,writeFileSync as q}from"fs";import{dirname as X,resolve as u}from"path";import{fileURLToPath as Z}from"url";import*as m from"comment-json";import H from"dayjs";import*as C from"comment-json";function k(r){let e=C.parse(r);return{write(t){e&&typeof e=="object"&&t&&Object.assign(e,t)},toSource(){return C.stringify(e,null,2)}}}a(k,"createJson5Writer");function U(r){return C.parse(r)}a(U,"parseJson5");import P from"path";import{existsSync as J}from"fs";var f=class{static{a(this,"ConfigResolver")}static resolveConfigPath(){if(process.env.XIAOZHI_CONFIG_DIR){let o=this.findConfigInDir(process.env.XIAOZHI_CONFIG_DIR);if(o)return o}let e=this.findConfigInDir(process.cwd());if(e)return e;let t=process.env.HOME||process.env.USERPROFILE;if(t){let o=P.join(t,".xiaozhi-client"),n=this.findConfigInDir(o);if(n)return n}return null}static findConfigInDir(e){let t=["xiaozhi.config.json5","xiaozhi.config.jsonc","xiaozhi.config.json"];for(let o of t){let n=P.join(e,o);if(J(n))return n}return null}static getDefaultConfigDir(){let e=process.env.HOME||process.env.USERPROFILE;return e?P.join(e,".xiaozhi-client"):null}};var N=X(Z(import.meta.url)),b={heartbeatInterval:3e4,heartbeatTimeout:1e4,reconnectInterval:5e3},S=class r{static{a(this,"ConfigManager")}static instance;defaultConfigPath;config=null;currentConfigPath=null;json5Writer=null;statsUpdateLocks=new Map;statsUpdateLockTimeouts=new Map;STATS_UPDATE_TIMEOUT=5e3;eventCallbacks=new Map;constructor(){let e=[u(N,"templates","default","xiaozhi.config.json"),u(N,"..","templates","default","xiaozhi.config.json"),u(process.cwd(),"templates","default","xiaozhi.config.json")];this.defaultConfigPath=e.find(t=>j(t))||e[0]}on(e,t){this.eventCallbacks.has(e)||this.eventCallbacks.set(e,[]),this.eventCallbacks.get(e)?.push(t)}emitEvent(e,t){let o=this.eventCallbacks.get(e);if(o)for(let n of o)try{n(t)}catch{}}getConfigFilePath(){let e=f.resolveConfigPath();if(e)return e;let t=f.getDefaultConfigDir();if(t)return u(t,"xiaozhi.config.json");let o=process.env.XIAOZHI_CONFIG_DIR||process.cwd();return u(o,"xiaozhi.config.json")}getConfigFileFormat(e){return e.endsWith(".json5")?"json5":e.endsWith(".jsonc")?"jsonc":"json"}static getInstance(){return r.instance||(r.instance=new r),r.instance}configExists(){return f.resolveConfigPath()!==null}initConfig(e="json"){if(!j(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(),o=`xiaozhi.config.${e}`,n=u(t,o);G(this.defaultConfigPath,n),this.config=null,this.json5Writer=null}loadConfig(){if(!this.configExists()){let e=new Error("\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u8FD0\u884C xiaozhi init \u521D\u59CB\u5316\u914D\u7F6E");throw this.emitEvent("config:error",{error:e,operation:"loadConfig"}),e}try{let e=this.getConfigFilePath();this.currentConfigPath=e;let t=this.getConfigFileFormat(e),n=Y(e,"utf8").replace(/^\uFEFF/,""),i;switch(t){case"json5":i=U(n),this.json5Writer=k(n);break;case"jsonc":i=m.parse(n);break;default:i=JSON.parse(n);break}return this.validateConfig(i),i}catch(e){throw this.emitEvent("config:error",{error:e instanceof Error?e:new Error(String(e)),operation:"loadConfig"}),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 o of t.mcpEndpoint)if(typeof o!="string"||o.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[o,n]of Object.entries(t.mcpServers))if(!n||typeof n!="object")throw new Error(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1AmcpServers.${o} \u65E0\u6548`)}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 o of e)if(!o||typeof o!="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),this.emitEvent("config:updated",{type:"endpoint",timestamp:new Date})}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(),o=this.getMcpEndpoints();if(o.includes(e))throw new Error(`MCP \u7AEF\u70B9 ${e} \u5DF2\u5B58\u5728`);let n=[...o,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(),o=this.getMcpEndpoints();if(o.indexOf(e)===-1)throw new Error(`MCP \u7AEF\u70B9 ${e} \u4E0D\u5B58\u5728`);let i=o.filter(s=>s!==e);t.mcpEndpoint=i,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 o=this.getMutableConfig();o.mcpServers[e]=t,this.saveConfig(o)}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 o=t.customMCP.tools.filter(n=>n.handler?.type==="mcp"&&n.handler.config?.serviceName===e);for(let n of o){let i=t.customMCP.tools.findIndex(s=>s.name===n.name);i!==-1&&t.customMCP.tools.splice(i,1)}t.customMCP.tools.length===0&&(t.customMCP=void 0)}this.saveConfig(t),this.emitEvent("config:updated",{type:"customMCP",timestamp:new Date})}updateConfig(e){let t=this.getMutableConfig();if(e.mcpEndpoint!==void 0&&(t.mcpEndpoint=e.mcpEndpoint),e.mcpServers){let o={...t.mcpServers};for(let[n,i]of Object.entries(e.mcpServers))t.mcpServers[n]=i;for(let n of Object.keys(o))n in e.mcpServers||(delete t.mcpServers[n],t.mcpServerConfig?.[n]&&delete t.mcpServerConfig[n])}if(e.connection&&(t.connection||(t.connection={}),Object.assign(t.connection,e.connection)),e.modelscope&&(t.modelscope||(t.modelscope={}),Object.assign(t.modelscope,e.modelscope)),e.webUI&&(t.webUI||(t.webUI={}),Object.assign(t.webUI,e.webUI)),e.mcpServerConfig)for(let[o,n]of Object.entries(e.mcpServerConfig))t.mcpServerConfig?.[o]&&(t.mcpServerConfig[o]=n);if(e.platforms)for(let[o,n]of Object.entries(e.platforms))t.platforms||(t.platforms={}),t.platforms[o]=n;this.saveConfig(t),this.emitEvent("config:updated",{type:"config",timestamp:new Date})}updateServerToolsConfig(e,t){let o=this.getMutableConfig();o.mcpServerConfig||(o.mcpServerConfig={}),Object.keys(t).length===0?delete o.mcpServerConfig[e]:o.mcpServerConfig[e]={tools:t},this.saveConfig(o),this.emitEvent("config:updated",{type:"serverTools",serviceName:e,timestamp:new Date})}removeServerToolsConfig(e){let o={...this.getConfig()};o.mcpServerConfig&&(delete o.mcpServerConfig[e],this.saveConfig(o))}cleanupInvalidServerToolsConfig(){let e=this.getMutableConfig();if(!e.mcpServerConfig)return;let t=Object.keys(e.mcpServers),n=Object.keys(e.mcpServerConfig).filter(i=>!t.includes(i));if(n.length>0){for(let i of n)delete e.mcpServerConfig[i];this.saveConfig(e)}}setToolEnabled(e,t,o,n){let i=this.getMutableConfig();i.mcpServerConfig||(i.mcpServerConfig={}),i.mcpServerConfig[e]||(i.mcpServerConfig[e]={tools:{}}),i.mcpServerConfig[e].tools[t]={...i.mcpServerConfig[e].tools[t],enable:o,...n&&{description:n}},this.saveConfig(i)}saveConfig(e){try{this.validateConfig(e);let t;this.currentConfigPath?t=this.currentConfigPath:(t=this.getConfigFilePath(),this.currentConfigPath=t);let o=this.getConfigFileFormat(t),n;switch(o){case"json5":try{this.json5Writer?(this.json5Writer.write(e),n=this.json5Writer.toSource()):n=m.stringify(e,null,2)}catch{n=m.stringify(e,null,2)}break;case"jsonc":try{n=m.stringify(e,null,2)}catch{n=JSON.stringify(e,null,2)}break;default:n=JSON.stringify(e,null,2);break}q(t,n,"utf8"),this.config=e,this.notifyConfigUpdate(e)}catch(t){throw this.emitEvent("config:error",{error:t instanceof Error?t:new Error(String(t)),operation:"saveConfig"}),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??b.heartbeatInterval,heartbeatTimeout:t.heartbeatTimeout??b.heartbeatTimeout,reconnectInterval:t.reconnectInterval??b.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),this.emitEvent("config:updated",{type:"connection",timestamp:new Date})}async updateToolUsageStats(e,t,o){try{if(typeof t=="string"&&o){let n=e,i=t,s=o;await Promise.all([this._updateMCPServerToolStats(n,i,s),this.updateCustomMCPToolStats(n,i,s)])}else{let n=e,i=t,s=new Date().toISOString();await this.updateCustomMCPToolStats(n,s,i)}}catch{if(typeof t=="string"&&o){let i=e,s=t}else{let i=e}}}async updateMCPServerToolStats(e,t,o,n=!0){await this._updateMCPServerToolStats(e,t,o,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),this.emitEvent("config:updated",{type:"modelscope",timestamp:new Date})}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"||!t.description||typeof t.description!="string"||!t.inputSchema||typeof t.inputSchema!="object"||!t.handler||typeof t.handler!="object"||!["proxy","function","http","script","chain","mcp"].includes(t.handler.type)||!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!1}}validateProxyHandler(e,t){return!(!t.platform||!["coze","openai","anthropic","custom"].includes(t.platform)||!t.config||typeof t.config!="object"||t.platform==="coze"&&!t.config.workflow_id&&!t.config.bot_id)}validateHttpHandler(e,t){if(!t.url||typeof t.url!="string")return!1;try{new URL(t.url)}catch{return!1}return!(t.method&&!["GET","POST","PUT","DELETE","PATCH"].includes(t.method))}validateFunctionHandler(e,t){return!(!t.module||typeof t.module!="string"||!t.function||typeof t.function!="string")}validateScriptHandler(e,t){return!(!t.script||typeof t.script!="string"||t.interpreter&&!["node","python","bash"].includes(t.interpreter))}validateChainHandler(e,t){return!(!t.tools||!Array.isArray(t.tools)||t.tools.length===0||!["sequential","parallel"].includes(t.mode)||!["stop","continue","retry"].includes(t.error_handling))}validateMCPHandler(e,t){return!(!t.config||typeof t.config!="object"||!t.config.serviceName||typeof t.config.serviceName!="string"||!t.config.toolName||typeof t.config.toolName!="string")}hasValidCustomMCPTools(){try{let e=this.getCustomMCPTools();return e.length===0?!1:this.validateCustomMCPTools(e)}catch{return!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)}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 o=new Set(t.customMCP.tools.map(i=>i.name)),n=e.filter(i=>!o.has(i.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.emitEvent("config:updated",{type:"customMCP",timestamp:new Date})}}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 o=t.customMCP.tools.findIndex(n=>n.name===e);if(o===-1)throw new Error(`\u5DE5\u5177 "${e}" \u4E0D\u5B58\u5728`);t.customMCP.tools.splice(o,1),this.saveConfig(t)}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 o=this.getMutableConfig();if(!o.customMCP||!o.customMCP.tools)throw new Error("\u672A\u914D\u7F6E\u81EA\u5B9A\u4E49 MCP \u5DE5\u5177");let n=o.customMCP.tools.findIndex(i=>i.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");o.customMCP.tools[n]=t,this.saveConfig(o)}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.emitEvent("config:updated",{type:"customMCP",timestamp:new Date})}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)}catch{}}updateWebUIConfig(e){let t=this.getMutableConfig();t.webUI||(t.webUI={}),Object.assign(t.webUI,e),this.saveConfig(t),this.emitEvent("config:updated",{type:"webui",timestamp:new Date})}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 o=this.getMutableConfig();o.platforms||(o.platforms={}),o.platforms[e]=t,this.saveConfig(o),this.emitEvent("config:updated",{type:"platform",platformName:e,timestamp:new Date})}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,o,n=!0){let i=this.getMutableConfig();i.mcpServerConfig||(i.mcpServerConfig={}),i.mcpServerConfig[e]||(i.mcpServerConfig[e]={tools:{}}),i.mcpServerConfig[e].tools[t]||(i.mcpServerConfig[e].tools[t]={enable:!0});let s=i.mcpServerConfig[e].tools[t],l=s.usageCount||0,g=s.lastUsedTime;n&&(s.usageCount=l+1),(!g||new Date(o)>new Date(g))&&(s.lastUsedTime=H(o).format("YYYY-MM-DD HH:mm:ss")),this.saveConfig(i)}async updateCustomMCPToolStats(e,t,o){try{let n,i,s=!0,l;if(typeof o=="string"){let h=e;n=`${h}__${t}`,i=o,l=`${h}/${t}`}else n=e,i=t,s=o||!0,l=n;let g=this.getCustomMCPTools(),E=g.findIndex(h=>h.name===n);if(E===-1)return;let I=[...g],p=I[E];p.stats||(p.stats={});let W=p.stats.usageCount||0,x=p.stats.lastUsedTime;s&&(p.stats.usageCount=W+1),(!x||new Date(i)>new Date(x))&&(p.stats.lastUsedTime=H(i).format("YYYY-MM-DD HH:mm:ss")),await this.updateCustomMCPTools(I)}catch{if(typeof o=="string"){let i=e,s=t}else{let i=e}}}async acquireStatsUpdateLock(e){if(this.statsUpdateLocks.has(e))return!1;let t=new Promise(n=>{});this.statsUpdateLocks.set(e,t);let o=setTimeout(()=>{this.releaseStatsUpdateLock(e)},this.STATS_UPDATE_TIMEOUT);return this.statsUpdateLockTimeouts.set(e,o),!0}releaseStatsUpdateLock(e){this.statsUpdateLocks.delete(e);let t=this.statsUpdateLockTimeouts.get(e);t&&(clearTimeout(t),this.statsUpdateLockTimeouts.delete(e))}async updateToolUsageStatsWithLock(e,t=!0){let o=`custommcp_${e}`;if(await this.acquireStatsUpdateLock(o))try{await this.updateToolUsageStats(e,t)}catch(n){throw n}finally{this.releaseStatsUpdateLock(o)}}async updateMCPServerToolStatsWithLock(e,t,o,n=!0){let i=`mcpserver_${e}_${t}`;if(await this.acquireStatsUpdateLock(i))try{await this.updateMCPServerToolStats(e,t,o,n)}catch(s){throw s}finally{this.releaseStatsUpdateLock(i)}}clearAllStatsUpdateLocks(){let e=this.statsUpdateLocks.size;this.statsUpdateLocks.clear();for(let t of this.statsUpdateLockTimeouts.values())clearTimeout(t);this.statsUpdateLockTimeouts.clear(),e>0}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()}},be=S.getInstance();import{isAbsolute as K,resolve as D,dirname as B}from"path";var c=class extends Error{static{a(this,"ConfigValidationError")}constructor(e){super(e),this.name="ConfigValidationError"}},L=(o=>(o.STDIO="stdio",o.SSE="sse",o.HTTP="http",o))(L||{});function w(r){try{let t=new URL(r).pathname;return t.endsWith("/sse")?"sse":(t.endsWith("/mcp"),"http")}catch{return"http"}}a(w,"inferTransportTypeFromUrl");function V(r){try{if(!r||typeof r!="object")throw new c("\u914D\u7F6E\u5BF9\u8C61\u4E0D\u80FD\u4E3A\u7A7A");let e=Q(r);return te(e),e}catch(e){throw e instanceof c?e:new c(`\u914D\u7F6E\u8F6C\u6362\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`)}}a(V,"normalizeServiceConfig");function Q(r){if(M(r))return ee(r);if("type"in r)switch(r.type){case"sse":return O(r);case"http":case"streamable-http":return R(r);default:throw new c(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${r.type}`)}if("url"in r){if(r.url===void 0||r.url===null)throw new c("\u7F51\u7EDC\u914D\u7F6E\u5FC5\u987B\u5305\u542B\u6709\u6548\u7684 url \u5B57\u6BB5");if(w(r.url||"")==="sse"){let o={...r,type:"sse"};return O(o)}let t={...r,type:"http"};return R(t)}throw new c("\u65E0\u6CD5\u8BC6\u522B\u7684\u914D\u7F6E\u7C7B\u578B")}a(Q,"convertByConfigType");function ee(r){if(!M(r))throw new c("\u65E0\u6548\u7684\u672C\u5730\u914D\u7F6E\u7C7B\u578B");let{command:e,args:t,env:o}=r;if(!e)throw new c("\u672C\u5730\u914D\u7F6E\u5FC5\u987B\u5305\u542B command \u5B57\u6BB5");let n;if(process.env.XIAOZHI_CONFIG_DIR)n=process.env.XIAOZHI_CONFIG_DIR;else{let l=f.resolveConfigPath();l?n=B(l):n=process.cwd()}let i=e;_(e)&&(i=D(n,e));let s=(t||[]).map(l=>_(l)?D(n,l):l);return{type:"stdio",command:i,args:s,...o!==void 0&&{env:o}}}a(ee,"convertLocalConfig");function O(r){let e=r.url,t=r.type,o=r.headers;if(e==null)throw new c("SSE \u914D\u7F6E\u5FC5\u987B\u5305\u542B url \u5B57\u6BB5");let n=t==="sse"?"sse":w(e||""),i=e?y(e):!1;return{type:n,url:e,headers:o}}a(O,"convertSSEConfig");function R(r){let e=r.url,t=r.headers;if(e==null)throw new c("HTTP \u914D\u7F6E\u5FC5\u987B\u5305\u542B url \u5B57\u6BB5");return{type:"http",url:e||"",headers:t}}a(R,"convertHTTPConfig");function Te(r){let e={},t=[];for(let[o,n]of Object.entries(r))try{e[o]=V(n)}catch(i){t.push({error:i instanceof Error?i:new Error(String(i))})}if(t.length>0){let o=t.map(({error:n},i)=>`[${i}]: ${n.message}`).join("; ");throw new c(`\u6279\u91CF\u914D\u7F6E\u8F6C\u6362\u5931\u8D25: ${o}`)}return e}a(Te,"normalizeServiceConfigBatch");function _(r){return K(r)?!1:!!(r.startsWith("./")||r.startsWith("../")||/\.(js|py|ts|mjs|cjs)$/i.test(r))}a(_,"isRelativePath");function M(r){return"command"in r&&typeof r.command=="string"}a(M,"isLocalConfig");function y(r){try{let t=new URL(r).hostname.toLowerCase();return t.endsWith(".modelscope.net")||t.endsWith(".modelscope.cn")||t==="modelscope.net"||t==="modelscope.cn"}catch{return!1}}a(y,"isModelScopeURL");function te(r){if(r.type&&!Object.values(L).includes(r.type))throw new c(`\u65E0\u6548\u7684\u4F20\u8F93\u7C7B\u578B: ${r.type}`);if(!r.type)throw new c("\u4F20\u8F93\u7C7B\u578B\u672A\u6307\u5B9A\uFF0C\u8BF7\u68C0\u67E5\u914D\u7F6E\u6216\u542F\u7528\u81EA\u52A8\u63A8\u65AD");switch(r.type){case"stdio":if(!r.command)throw new c("STDIO \u914D\u7F6E\u5FC5\u987B\u5305\u542B command \u5B57\u6BB5");break;case"sse":if(r.url===void 0||r.url===null)throw new c("SSE \u914D\u7F6E\u5FC5\u987B\u5305\u542B url \u5B57\u6BB5");break;case"http":if(r.url===void 0||r.url===null)throw new c("HTTP \u914D\u7F6E\u5FC5\u987B\u5305\u542B url \u5B57\u6BB5");break;default:throw new c(`\u4E0D\u652F\u6301\u7684\u4F20\u8F93\u7C7B\u578B: ${r.type}`)}}a(te,"validateNewConfig");function Ee(r){if(M(r))return`\u672C\u5730\u8FDB\u7A0B (${r.command})`;if("url"in r){if("type"in r&&(r.type==="http"||r.type==="streamable-http"))return`HTTP (${r.url})`;if("type"in r&&r.type==="sse")return`SSE${y(r.url)?" (ModelScope)":""} (${r.url})`;let e=w(r.url),t=y(r.url);return e==="sse"?`SSE${t?" (ModelScope)":""} (${r.url})`:`HTTP (${r.url})`}return"\u672A\u77E5\u7C7B\u578B"}a(Ee,"getConfigTypeDescription");import T from"path";import{mkdirSync as A,existsSync as F,readdirSync as oe,statSync as ne,copyFileSync as re}from"fs";import{dirname as ie,resolve as d}from"path";import{fileURLToPath as se}from"url";var v=ie(se(import.meta.url)),z=class{static{a(this,"ConfigInitializer")}static async initializeDefaultConfig(){let e=process.env.HOME||process.env.USERPROFILE;if(!e)throw new Error("\u65E0\u6CD5\u83B7\u53D6\u7528\u6237\u5BB6\u76EE\u5F55");let t=T.join(e,".xiaozhi-client");if(F(t))return t;A(t,{recursive:!0});let o=this.getDefaultTemplateDir();if(!o)throw new Error("\u9ED8\u8BA4\u914D\u7F6E\u6A21\u677F\u4E0D\u5B58\u5728\uFF0C\u8BF7\u68C0\u67E5\u9879\u76EE\u6A21\u677F\u6587\u4EF6\u662F\u5426\u5B58\u5728");return this.copyDirectoryRecursive(o,t,["template.json",".git","node_modules"]),t}static copyDirectoryRecursive(e,t,o=[]){let n=oe(e);for(let i of n){if(o.includes(i))continue;let s=T.join(e,i),l=T.join(t,i);ne(s).isDirectory()?(A(l,{recursive:!0}),this.copyDirectoryRecursive(s,l,o)):re(s,l)}}static getDefaultTemplateDir(){let e=[d(v,"templates","default"),d(v,"..","templates","default"),d(process.cwd(),"templates","default"),d(v,"..","..","..","templates","default"),d(v,"..","..","..","..","templates","default")];for(let t of e)if(F(t))return t;return null}};export{z as ConfigInitializer,S as ConfigManager,f as ConfigResolver,c as ConfigValidationError,L as MCPTransportType,be as configManager,Ee as getConfigTypeDescription,y as isModelScopeURL,V as normalizeServiceConfig,Te as normalizeServiceConfigBatch};
2
2
  //# sourceMappingURL=index.js.map