@cloudbase/cloudbase-mcp 1.8.35 → 1.8.36

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.js CHANGED
@@ -1 +1 @@
1
- import*as e from"@cloudbase/toolbox";import*as n from"os";import*as t from"@cloudbase/cals/lib/cjs/utils/mermaid-datasource/mermaid-json-transform";import*as o from"ws";import*as r from"open";import*as a from"net";import*as i from"fs";import*as s from"@modelcontextprotocol/sdk/server/stdio.js";import*as c from"path";import*as l from"@modelcontextprotocol/sdk/server/mcp.js";import*as d from"@cloudbase/manager-node";import*as p from"express";import*as u from"http";import*as g from"dns";import*as m from"crypto";import*as f from"https";import*as b from"adm-zip";import*as h from"url";import*as y from"fs/promises";import*as v from"zod";var x,w,I={39:function(e,n,t){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.clearLogs=n.getLoggerStatus=n.getLogs=n.error=n.warn=n.info=n.debug=n.logger=n.LogLevel=void 0;const r=o(t(932)),a=o(t(521)),i=o(t(116));var s;!function(e){e[e.DEBUG=0]="DEBUG",e[e.INFO=1]="INFO",e[e.WARN=2]="WARN",e[e.ERROR=3]="ERROR"}(s||(n.LogLevel=s={})),n.logger=new class{enabled;level;logFile;useConsole;constructor(e={}){this.enabled=e.enabled??!0,this.level=e.level??s.INFO,this.useConsole=e.console??!1,this.logFile=e.logFile??a.default.join(i.default.tmpdir(),"cloudbase-mcp.log")}async writeLog(e,n,t){if(!this.enabled||e<this.level)return;const o=(new Date).toISOString(),a=s[e],i=t?`[${o}] [${a}] ${n} ${JSON.stringify(t,null,2)}`:`[${o}] [${a}] ${n}`;if(this.useConsole&&console.error(i),this.logFile)try{await r.default.appendFile(this.logFile,i+"\n")}catch(e){}}debug(e,n){this.writeLog(s.DEBUG,e,n)}info(e,n){this.writeLog(s.INFO,e,n)}warn(e,n){this.writeLog(s.WARN,e,n)}error(e,n){this.writeLog(s.ERROR,e,n)}setLevel(e){this.level=e}setEnabled(e){this.enabled=e}getLogFile(){return this.logFile}async clearLogs(){if(this.logFile)try{await r.default.writeFile(this.logFile,"")}catch(e){}}async getLogs(e=1e3){if(!this.logFile)return[];try{return(await r.default.readFile(this.logFile,"utf-8")).split("\n").filter(e=>e.trim()).slice(-e)}catch(e){return[`读取日志文件失败: ${e instanceof Error?e.message:String(e)}`]}}getStatus(){return{enabled:this.enabled,level:s[this.level],logFile:this.logFile,useConsole:this.useConsole}}}({enabled:"true"===(process.env.MCP_DEBUG??"true"),level:s.DEBUG,console:"true"===process.env.MCP_CONSOLE_LOG}),n.debug=(e,t)=>n.logger.debug(e,t),n.info=(e,t)=>n.logger.info(e,t),n.warn=(e,t)=>n.logger.warn(e,t),n.error=(e,t)=>n.logger.error(e,t),n.getLogs=e=>n.logger.getLogs(e),n.getLoggerStatus=()=>n.logger.getStatus(),n.clearLogs=()=>n.logger.clearLogs()},90:n=>{n.exports=e},97:function(e,n,t){var o,r=this&&this.__createBinding||(Object.create?function(e,n,t,o){void 0===o&&(o=t);var r=Object.getOwnPropertyDescriptor(n,t);r&&!("get"in r?!n.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return n[t]}}),Object.defineProperty(e,o,r)}:function(e,n,t,o){void 0===o&&(o=t),e[o]=n[t]}),a=this&&this.__setModuleDefault||(Object.create?function(e,n){Object.defineProperty(e,"default",{enumerable:!0,value:n})}:function(e,n){e.default=n}),i=this&&this.__importStar||(o=function(e){return o=Object.getOwnPropertyNames||function(e){var n=[];for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[n.length]=t);return n},o(e)},function(e){if(e&&e.__esModule)return e;var n={};if(null!=e)for(var t=o(e),i=0;i<t.length;i++)"default"!==t[i]&&r(n,e,t[i]);return a(n,e),n});Object.defineProperty(n,"__esModule",{value:!0}),n.registerDownloadTools=function(e){e.registerTool("downloadRemoteFile",{title:"下载远程文件",description:"下载远程文件到本地临时文件,返回一个系统的绝对路径",inputSchema:{url:s.z.string().describe("远程文件的 URL 地址")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"download"}},async({url:e})=>{try{const n=await function(e){return new Promise((n,t)=>{(e.startsWith("https:")?g:m).get(e,async o=>{if(200!==o.statusCode)return void t(new Error(`HTTP Error: ${o.statusCode}`));const r=o.headers["content-type"]||"",a=parseInt(o.headers["content-length"]||"0",10),i=o.headers["content-disposition"];if(!await async function(e,n){try{const t=new f.URL(e);if(!v.includes(t.protocol))return!1;const o=t.hostname;return(!b.isIP(o)||!w(o))&&!(!b.isIP(o)&&await async function(e){try{const n=await new Promise((n,t)=>{h.resolve(e,(e,o)=>{e?t(e):n(o)})});return n.some(e=>w(e))}catch(e){return!0}}(o))&&x.some(e=>n.startsWith(e))}catch{return!1}}(e,r))return void t(new Error("不安全的 URL 或内容类型,或者目标为内网地址"));if(a>y)return void t(new Error(`文件大小 ${a} 字节超过 ${y} 字节限制`));const s=function(e,n,t){let o="";const r=new f.URL(e).pathname,a=d.extname(r);if(a&&(o=a),t){const e=t.match(/filename=["']?([^"']+)["']?/);if(e){const n=d.extname(e[1]);n&&(o=n)}}return!o&&n&&(o={"text/plain":".txt","text/html":".html","text/css":".css","text/javascript":".js","image/jpeg":".jpg","image/png":".png","image/gif":".gif","image/webp":".webp","application/json":".json","application/xml":".xml","application/pdf":".pdf","application/zip":".zip","application/x-zip-compressed":".zip"}[n]||""),o}(e,r,i),g=function(e=""){return`${u.randomBytes(16).toString("hex")}${e}`}(s),m=function(e){return d.join(p.tmpdir(),e)}(g),I=l.createWriteStream(m);let S=0;o.on("data",e=>{S+=e.length,S>y&&(I.destroy(),c.unlink(m).catch(()=>{}),t(new Error(`文件大小超过 ${y} 字节限制`)))}),o.pipe(I),I.on("finish",()=>{n({filePath:m,contentType:r,fileSize:S})}),I.on("error",e=>{c.unlink(m).catch(()=>{}),t(e)})}).on("error",e=>{t(e)})})}(e);return{content:[{type:"text",text:JSON.stringify({success:!0,filePath:n.filePath,contentType:n.contentType,fileSize:n.fileSize,message:"文件下载成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"文件下载失败"},null,2)}]}}})};const s=t(971),c=i(t(932)),l=i(t(421)),d=i(t(521)),p=i(t(116)),u=i(t(823)),g=i(t(871)),m=i(t(782)),f=t(887),b=i(t(357)),h=i(t(793)),y=104857600,v=["http:","https:"],x=["text/","image/","application/json","application/xml","application/pdf","application/zip","application/x-zip-compressed"];function w(e){if(!b.isIP(e))return!0;if("127.0.0.1"===e||"localhost"===e||"::1"===e||e.startsWith("169.254.")||e.startsWith("0."))return!0;const n=e.split(".").map(e=>parseInt(e,10));if(4===n.length){const e=(n[0]<<24)+(n[1]<<16)+(n[2]<<8)+n[3];if(e>=167772160&&e<=184549375)return!0;if(e>=2886729728&&e<=2887778303)return!0;if(e>=3232235520&&e<=3232301055)return!0}if(b.isIPv6(e)){const n=e.toLowerCase();if(n.startsWith("fc00:")||n.startsWith("fe80:")||n.startsWith("fec0:")||n.startsWith("::1"))return!0}return!1}},116:e=>{e.exports=n},191:e=>{e.exports=t},215:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerRagTools=function(e){e.registerTool?.("searchWeb",{title:"联网搜索",description:"使用联网来进行信息检索,如查询最新的新闻、文章、股价、天气等。支持自然语言查询,也可以直接输入网址获取网页内容",inputSchema:{query:o.z.string().describe("搜索关键词、问题或网址,支持自然语言")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"web"}},async({query:e})=>{try{const n=await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/auth/v1/signin/anonymously",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json","x-device-id":"cloudbase-ai-toolkit"},body:s({})}),{access_token:t}=await n.json(),o=await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/v1/ai/hunyuan-beta/openapi/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:s({model:"hunyuan",messages:[{role:"user",content:"你好,你将扮演一个知识库的角色,联网查询到问题的答案之后回答给我"},{role:"assistant",content:"好的"},{role:"user",content:e}],enable_enhancement:!0,search_info:!0,enable_speed_search:!0,force_search_enhancement:!0})}),r=await o.json();if(r.error)throw new Error(r.error.message||"联网搜索失败");return{content:[{type:"text",text:s({type:"web_search",content:r.choices?.[0]?.message?.content||"",search_results:(r.search_info?.search_results||[]).map(e=>({title:e.title,url:e.url,snippet:e.snippet})),status:"success"})}]}}catch(e){return{content:[{type:"text",text:s({type:"error",message:e instanceof Error?e.message:"联网搜索失败",status:"error"})}]}}}),e.registerTool?.("searchKnowledgeBase",{title:"云开发知识库检索",description:"云开发知识库智能检索工具,支持云开发与云函数知识的向量查询",inputSchema:{threshold:o.z.number().default(.5).optional().describe("相似性检索阈值"),id:r.describe("知识库范围,cloudbase=云开发全量知识,scf=云开发的云函数知识, miniprogram=小程序知识(不包含云开发与云函数知识)"),content:o.z.string().describe("检索内容"),options:o.z.object({chunkExpand:o.z.array(o.z.number()).min(2).max(2).default([3,3]).describe("指定返回的文档内容的展开长度,例如 [3,3]代表前后展开长度")}).optional().describe("其他选项"),limit:o.z.number().default(5).optional().describe("指定返回最相似的 Top K 的 K 的值")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"rag"}},async({id:e,content:n,options:{chunkExpand:t=[3,3]}={},limit:o=5,threshold:r=.5})=>{const c=a[e]||e,l=await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/auth/v1/signin/anonymously",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json","x-device-id":"cloudbase-ai-toolkit"},body:s({collectionView:c,options:{chunkExpand:t},search:{content:n,limit:o}})}),d=(await l.json()).access_token,p=await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/v1/knowledge/search",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${d}`},body:s({collectionView:c,options:{chunkExpand:t},search:{content:n,limit:o}})}),u=await p.json();if(u.code)throw new Error(u.message);return{content:[{type:"text",text:s(u.data.documents.filter(e=>e.score>=r).map(e=>({score:e.score,fileTile:e.documentSet.fileTitle,url:i(e.documentSet.fileMetaData).url,paragraphTitle:e.data.paragraphTitle,text:`${e.data.pre?.join("\n")||""}\n ${e.data.text}\n ${e.data.next?.join("\n")||""}`})))}]}})};const o=t(971),r=o.z.enum(["cloudbase","scf","miniprogram"]),a={cloudbase:"ykfzskv4_ad28",scf:"scfsczskzyws_4bdc",miniprogram:"xcxzskws_25d8"};function i(e){try{return JSON.parse(e)}catch(e){return{}}}function s(e){const n=new WeakSet;try{return JSON.stringify(e,function(e,t){if("object"==typeof t&&null!==t){if(n.has(t))return;n.add(t)}return t})}catch(e){return""}}},220:e=>{e.exports=o},241:e=>{e.exports=r},279:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerHostingTools=function(e){const n=e.cloudBaseOptions,t=()=>(0,r.getCloudBaseManager)({cloudBaseOptions:n});e.registerTool("uploadFiles",{title:"上传静态文件",description:"上传文件到静态网站托管",inputSchema:{localPath:o.z.string().optional().describe("本地文件或文件夹路径,需要是绝对路径,例如 /tmp/files/data.txt"),cloudPath:o.z.string().optional().describe("云端文件或文件夹路径,例如files/data.txt"),files:o.z.array(o.z.object({localPath:o.z.string(),cloudPath:o.z.string()})).default([]).describe("多文件上传配置"),ignore:o.z.union([o.z.string(),o.z.array(o.z.string())]).optional().describe("忽略文件模式")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"hosting"}},async({localPath:e,cloudPath:n,files:o=[],ignore:r})=>{const a=await t(),i=await a.hosting.uploadFiles({localPath:e,cloudPath:n,files:o,ignore:r}),s=await a.env.getEnvInfo(),c=s.EnvInfo?.StaticStorages?.[0]?.StaticDomain;return{content:[{type:"text",text:JSON.stringify({...i,staticDomain:c,message:"文件上传成功",accessUrl:c?`https://${c}/${n||""}`:"请检查静态托管配置"},null,2)}]}}),e.registerTool?.("getWebsiteConfig",{title:"查询静态托管配置",description:"获取静态网站托管配置",inputSchema:{},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"hosting"}},async()=>{const e=await t(),n=await e.hosting.getWebsiteConfig();return{content:[{type:"text",text:JSON.stringify(n,null,2)}]}}),e.registerTool?.("deleteFiles",{title:"删除静态文件",description:"删除静态网站托管的文件或文件夹",inputSchema:{cloudPath:o.z.string().describe("云端文件或文件夹路径"),isDir:o.z.boolean().default(!1).describe("是否为文件夹")},annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!0,openWorldHint:!0,category:"hosting"}},async({cloudPath:e,isDir:n=!1})=>{const o=await t(),r=await o.hosting.deleteFiles({cloudPath:e,isDir:n});return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}),e.registerTool?.("findFiles",{title:"搜索静态文件",description:"搜索静态网站托管的文件",inputSchema:{prefix:o.z.string().describe("匹配前缀"),marker:o.z.string().optional().describe("起始对象键标记"),maxKeys:o.z.number().optional().describe("单次返回最大条目数")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"hosting"}},async({prefix:e,marker:n,maxKeys:o})=>{const r=await t(),a=await r.hosting.findFiles({prefix:e,marker:n,maxKeys:o});return{content:[{type:"text",text:JSON.stringify(a,null,2)}]}}),e.registerTool?.("domainManagement",{title:"静态托管域名管理",description:"统一的域名管理工具,支持绑定、解绑、查询和修改域名配置",inputSchema:{action:o.z.enum(["create","delete","check","modify"]).describe("操作类型: create=绑定域名, delete=解绑域名, check=查询域名配置, modify=修改域名配置"),domain:o.z.string().optional().describe("域名"),certId:o.z.string().optional().describe("证书ID(绑定域名时必需)"),domains:o.z.array(o.z.string()).optional().describe("域名列表(查询配置时使用)"),domainId:o.z.number().optional().describe("域名ID(修改配置时必需)"),domainConfig:o.z.object({Refer:o.z.object({Switch:o.z.string(),RefererRules:o.z.array(o.z.object({RefererType:o.z.string(),Referers:o.z.array(o.z.string()),AllowEmpty:o.z.boolean()})).optional()}).optional(),Cache:o.z.array(o.z.object({RuleType:o.z.string(),RuleValue:o.z.string(),CacheTtl:o.z.number()})).optional(),IpFilter:o.z.object({Switch:o.z.string(),FilterType:o.z.string().optional(),Filters:o.z.array(o.z.string()).optional()}).optional(),IpFreqLimit:o.z.object({Switch:o.z.string(),Qps:o.z.number().optional()}).optional()}).optional().describe("域名配置(修改配置时使用)")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"hosting"}},async({action:e,domain:n,certId:o,domains:r,domainId:a,domainConfig:i})=>{const s=await t();let c;switch(e){case"create":if(!n||!o)throw new Error("绑定域名需要提供域名和证书ID");c=await s.hosting.CreateHostingDomain({domain:n,certId:o});break;case"delete":if(!n)throw new Error("解绑域名需要提供域名");c=await s.hosting.deleteHostingDomain({domain:n});break;case"check":if(!r||0===r.length)throw new Error("查询域名配置需要提供域名列表");c=await s.hosting.tcbCheckResource({domains:r});break;case"modify":if(!n||void 0===a||!i)throw new Error("修改域名配置需要提供域名、域名ID和配置信息");c=await s.hosting.tcbModifyAttribute({domain:n,domainId:a,domainConfig:i});break;default:throw new Error(`不支持的操作类型: ${e}`)}return{content:[{type:"text",text:JSON.stringify(c,null,2)}]}})};const o=t(971),r=t(431)},291:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.getLoginState=async function(){const{TENCENTCLOUD_SECRETID:e,TENCENTCLOUD_SECRETKEY:n,TENCENTCLOUD_SESSIONTOKEN:t}=process.env;if((0,r.debug)("TENCENTCLOUD_SECRETID",e),e&&n)return(0,r.debug)("loginByApiSecret"),{secretId:e,secretKey:n,token:t};const o=await a.getLoginState();return o||((0,r.debug)("loginByApiSecret"),await a.loginByWebAuth({}),await a.getLoginState())},n.logout=async function(){return await a.logout()};const o=t(90),r=t(39),a=o.AuthSupevisor.getInstance({})},319:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerGatewayTools=function(e){const n=e.cloudBaseOptions;e.registerTool?.("createFunctionHTTPAccess",{title:"创建云函数HTTP访问",description:"创建云函数的 HTTP 访问",inputSchema:{name:o.z.string().describe("函数名"),path:o.z.string().describe("HTTP 访问路径")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"gateway"}},async({name:e,path:t})=>{const o=await(0,r.getCloudBaseManager)({cloudBaseOptions:n}),a=await o.access.createAccess({type:1,name:e,path:t});return{content:[{type:"text",text:JSON.stringify(a,null,2)}]}})};const o=t(971),r=t(431)},341:function(e,n,t){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.InteractiveServer=void 0,n.getInteractiveServer=u,n.resetInteractiveServer=async function(){if(p){try{await p.stop()}catch(e){(0,c.error)("Error stopping existing server instance:",e)}p=null}},n.getInteractiveServerSafe=async function(e){if(p&&!p.running){try{await p.stop()}catch(e){(0,c.debug)("Error stopping non-running server:",e)}p=null}return u(e)};const r=o(t(674)),a=o(t(782)),i=t(220),s=o(t(241)),c=t(39);async function l(e,n,t){if("CodeBuddy"===process.env.INTEGRATION_IDE&&t)try{return t.server.sendLoggingMessage({level:"notice",data:{type:"tcb",url:e}}),void(0,c.info)(`CodeBuddy IDE: 已发送网页打开通知 - ${e}`)}catch(n){(0,c.error)(`Failed to send logging message for ${e}: ${n instanceof Error?n.message:n}`,n),(0,c.warn)(`回退到直接打开网页: ${e}`)}try{return await(0,s.default)(e,n)}catch(t){(0,c.error)(`Failed to open ${e} ${n} ${t instanceof Error?t.message:t} `,t),(0,c.warn)(`Please manually open: ${e}`)}}class d{app;server;wss;port=0;isRunning=!1;currentResolver=null;sessionData=new Map;_mcpServer=null;get mcpServer(){return this._mcpServer}set mcpServer(e){this._mcpServer=e}DEFAULT_PORT=3721;FALLBACK_PORTS=[3722,3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735];constructor(e){this._mcpServer=e,this.app=(0,r.default)(),this.server=a.default.createServer(this.app),this.wss=new i.WebSocketServer({server:this.server}),this.setupExpress(),this.setupWebSocket(),process.on("exit",()=>this.cleanup()),process.on("SIGINT",()=>this.cleanup()),process.on("SIGTERM",()=>this.cleanup())}cleanup(){this.isRunning&&((0,c.debug)("Cleaning up interactive server resources..."),this.server.close(),this.wss.close(),this.isRunning=!1)}setupExpress(){this.app.use(r.default.json()),this.app.get("/env-setup/:sessionId",(e,n)=>{const{sessionId:t}=e.params,o=this.sessionData.get(t);o?n.send(this.getEnvSetupHTML(o.envs)):n.status(404).send("会话不存在或已过期")}),this.app.get("/clarification/:sessionId",(e,n)=>{const{sessionId:t}=e.params,o=this.sessionData.get(t);o?n.send(this.getClarificationHTML(o.message,o.options)):n.status(404).send("会话不存在或已过期")}),this.app.get("/debug/logs",async(e,n)=>{try{const e=await(0,c.getLogs)(1e3),t=(0,c.getLoggerStatus)();n.send(this.getLogsHTML(e,t))}catch(e){n.status(500).send("获取日志失败")}}),this.app.get("/api/logs",async(e,n)=>{try{const t=parseInt(e.query.maxLines)||1e3,o=await(0,c.getLogs)(t),r=(0,c.getLoggerStatus)();n.json({logs:o,status:r,success:!0})}catch(e){n.status(500).json({success:!1,error:"Failed to get logs"})}}),this.app.post("/api/logs/clear",async(e,n)=>{try{await(0,c.clearLogs)(),n.json({success:!0})}catch(e){n.status(500).json({success:!1,error:"Failed to clear logs"})}}),this.app.post("/api/submit",(e,n)=>{const{type:t,data:o}=e.body;(0,c.debug)("Received submit request",{type:t,data:o}),this.currentResolver?((0,c.info)("Resolving with user data"),this.currentResolver({type:t,data:o}),this.currentResolver=null):(0,c.warn)("No resolver waiting for response"),n.json({success:!0})}),this.app.post("/api/cancel",(e,n)=>{(0,c.info)("Received cancel request"),this.currentResolver?((0,c.info)("Resolving with cancelled status"),this.currentResolver({type:"clarification",data:null,cancelled:!0}),this.currentResolver=null):(0,c.warn)("No resolver waiting for cancellation"),n.json({success:!0})})}setupWebSocket(){this.wss.on("connection",e=>{(0,c.debug)("WebSocket client connected"),e.on("message",e=>{try{const n=JSON.parse(e.toString());(0,c.debug)("WebSocket message received",n),this.currentResolver&&(this.currentResolver(n),this.currentResolver=null)}catch(e){(0,c.error)("WebSocket message parsing error",e)}}),e.on("close",()=>{(0,c.debug)("WebSocket client disconnected")})})}async start(){return this.isRunning?((0,c.debug)(`Interactive server already running on port ${this.port}`),this.port):new Promise((e,n)=>{(0,c.info)("Starting interactive server...");const t=[this.DEFAULT_PORT,...this.FALLBACK_PORTS];let o=0;const r=()=>{if(o>=t.length){const e=new Error(`All ${t.length} ports are in use (${t.join(", ")}), failed to start server`);return(0,c.error)("Server start failed",e),void n(e)}const e=t[o];o++,(0,c.debug)(`Trying to start server on port ${e} (attempt ${o}/${t.length})`),a(e)},a=t=>{this.server.removeAllListeners("error"),this.server.removeAllListeners("listening");const o=e=>{"EADDRINUSE"===e.code?((0,c.warn)(`Port ${t} is in use, trying next port...`),this.server.removeAllListeners("error"),this.server.removeAllListeners("listening"),r()):((0,c.error)("Server error",e),n(e))},a=()=>{const t=this.server.address();if(t&&"object"==typeof t)this.port=t.port,this.isRunning=!0,(0,c.info)(`Interactive server started successfully on http://localhost:${this.port}`),this.server.removeListener("error",o),this.server.removeListener("listening",a),e(this.port);else{const e=new Error("Failed to get server address");(0,c.error)("Server start error",e),n(e)}};this.server.once("error",o),this.server.once("listening",a);try{this.server.listen(t,"127.0.0.1")}catch(e){(0,c.error)(`Failed to bind to port ${t}:`,e),r()}};r()})}async stop(){if(this.isRunning)return(0,c.info)("Stopping interactive server..."),new Promise((e,n)=>{const t=setTimeout(()=>{(0,c.warn)("Server close timeout, forcing cleanup"),this.isRunning=!1,this.port=0,e()},3e4);try{this.wss.close(()=>{(0,c.debug)("WebSocket server closed")}),this.server.close(o=>{clearTimeout(t),o?((0,c.error)("Error closing server:",o),n(o)):((0,c.info)("Interactive server stopped successfully"),this.isRunning=!1,this.port=0,e())})}catch(e){clearTimeout(t),(0,c.error)("Error stopping server:",e),this.isRunning=!1,this.port=0,n(e)}});(0,c.debug)("Interactive server is not running, nothing to stop")}async collectEnvId(e){try{(0,c.info)("Starting environment ID collection..."),(0,c.debug)(`Available environments: ${e.length}`);const n=await this.start(),t=Math.random().toString(36).substring(2,15);this.sessionData.set(t,{envs:e}),(0,c.debug)(`Created session: ${t}`),setTimeout(()=>{this.sessionData.delete(t),(0,c.debug)(`Session ${t} expired`)},3e5);const o=`http://localhost:${n}/env-setup/${t}`;(0,c.info)(`Opening browser: ${o}`);try{await l(o,{wait:!1},this._mcpServer),(0,c.info)("Browser opened successfully")}catch(e){(0,c.error)("Failed to open browser",e),(0,c.warn)(`Please manually open: ${o}`)}return(0,c.info)("Waiting for user selection..."),new Promise(e=>{this.currentResolver=n=>{this.stop().catch(e=>{(0,c.debug)("Error stopping server after user selection:",e)}),e(n)},setTimeout(()=>{this.currentResolver&&((0,c.warn)("Request timeout, resolving with cancelled"),this.currentResolver=null,this.stop().catch(e=>{(0,c.debug)("Error stopping server after timeout:",e)}),e({type:"envId",data:null,cancelled:!0}))},6e5)})}catch(e){throw(0,c.error)("Error in collectEnvId",e),e}}async clarifyRequest(e,n){const t=await this.start(),o=Math.random().toString(36).substring(2,15);this.sessionData.set(o,{message:e,options:n}),setTimeout(()=>{this.sessionData.delete(o)},3e5);const r=`http://localhost:${t}/clarification/${o}`;return await l(r,void 0,this._mcpServer),new Promise(e=>{this.currentResolver=n=>{this.stop().catch(e=>{(0,c.debug)("Error stopping server after user selection:",e)}),e(n)}})}getEnvSetupHTML(e){return`\n<!DOCTYPE html>\n<html lang="zh-CN">\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>CloudBase AI Toolkit - 环境配置</title>\n <style>\n @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');\n \n * { margin: 0; padding: 0; box-sizing: border-box; }\n :root {\n --primary-color: #1a1a1a;\n --primary-hover: #000000;\n --accent-color: #67E9E9;\n --accent-hover: #2BCCCC;\n --text-primary: #ffffff;\n --text-secondary: #a0a0a0;\n --border-color: rgba(255, 255, 255, 0.15);\n --bg-secondary: rgba(255, 255, 255, 0.08);\n --bg-glass: rgba(26, 26, 26, 0.95);\n --shadow: 0 25px 50px rgba(0, 0, 0, 0.3), 0 10px 20px rgba(0, 0, 0, 0.2);\n --font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;\n --header-bg: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0d1117 100%);\n }\n \n body {\n font-family: var(--font-mono);\n background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n position: relative;\n overflow-x: hidden;\n overflow-y: auto;\n }\n \n /* Custom scrollbar styles */\n ::-webkit-scrollbar {\n width: 8px;\n }\n \n ::-webkit-scrollbar-track {\n background: rgba(255, 255, 255, 0.05);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb {\n background: var(--accent-color);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb:hover {\n background: var(--accent-hover);\n }\n \n body::before {\n content: '';\n position: fixed;\n top: 0; left: 0; right: 0; bottom: 0;\n background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse"><path d="M 20 0 L 0 0 0 20" fill="none" stroke="rgba(255,255,255,0.02)" stroke-width="1"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>') repeat;\n pointer-events: none;\n z-index: -1;\n }\n \n body::after {\n content: '';\n position: fixed;\n top: 50%; left: 50%;\n width: 500px; height: 500px;\n background: radial-gradient(circle, rgba(103, 233, 233, 0.05) 0%, transparent 70%);\n transform: translate(-50%, -50%);\n pointer-events: none;\n z-index: -1;\n animation: pulse 8s ease-in-out infinite;\n }\n \n @keyframes pulse {\n 0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }\n 50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }\n }\n \n .modal {\n background: var(--bg-glass);\n backdrop-filter: blur(20px);\n border-radius: 20px;\n box-shadow: var(--shadow);\n border: 2px solid var(--border-color);\n width: 100%;\n max-width: 520px;\n overflow: hidden;\n animation: modalIn 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);\n position: relative;\n }\n \n .modal::before {\n content: '';\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.02) 50%, transparent 70%);\n animation: shimmer 3s infinite;\n pointer-events: none;\n }\n \n @keyframes shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n \n @keyframes modalIn {\n from {\n opacity: 0;\n transform: scale(0.9) translateY(-20px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n }\n \n .header {\n background: var(--header-bg);\n color: var(--text-primary);\n padding: 24px 28px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n position: relative;\n overflow: hidden;\n }\n \n .header::before {\n content: '';\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.03) 50%, transparent 70%);\n animation: headerShimmer 4s infinite;\n pointer-events: none;\n }\n \n @keyframes headerShimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n \n .header-left {\n display: flex;\n align-items: center;\n gap: 16px;\n z-index: 1;\n }\n \n .logo {\n width: 32px;\n height: 32px;\n filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));\n animation: logoFloat 3s ease-in-out infinite;\n }\n \n @keyframes logoFloat {\n 0%, 100% { transform: translateY(0px); }\n 50% { transform: translateY(-3px); }\n }\n \n .title {\n font-size: 20px;\n font-weight: 700;\n text-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n \n .github-link {\n color: var(--text-primary);\n text-decoration: none;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n background: rgba(255,255,255,0.08);\n border: 1px solid rgba(255, 255, 255, 0.12);\n backdrop-filter: blur(10px);\n padding: 8px 16px;\n border-radius: 8px;\n font-weight: 500;\n z-index: 1;\n transition: all 0.3s ease;\n }\n \n .github-link:hover {\n background: rgba(255,255,255,0.15);\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n }\n \n .content {\n padding: 32px 24px;\n position: relative;\n }\n \n .content-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary);\n margin-bottom: 8px;\n animation: fadeInUp 0.8s ease-out 0.2s both;\n }\n \n .content-subtitle {\n color: var(--text-secondary);\n margin-bottom: 24px;\n line-height: 1.5;\n animation: fadeInUp 0.8s ease-out 0.4s both;\n }\n \n @keyframes fadeInUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n \n .env-list {\n border: 1px solid var(--border-color);\n border-radius: 12px;\n margin-bottom: 24px;\n max-height: 300px;\n overflow-y: auto;\n overflow-x: hidden;\n background: rgba(255, 255, 255, 0.03);\n animation: fadeInUp 0.8s ease-out 0.6s both;\n }\n \n .env-item {\n padding: 16px 20px;\n border-bottom: 1px solid var(--border-color);\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n gap: 14px;\n position: relative;\n overflow: hidden;\n color: var(--text-primary);\n }\n \n .env-item::before {\n content: '';\n position: absolute;\n left: 0; top: 0; bottom: 0;\n width: 0;\n background: var(--accent-color);\n transition: width 0.3s ease;\n }\n \n .env-item:last-child {\n border-bottom: none;\n }\n \n .env-item:hover {\n background: var(--bg-secondary);\n transform: translateX(5px);\n }\n \n .env-item:hover::before {\n width: 4px;\n }\n \n .env-item.selected {\n background: rgba(103, 233, 233, 0.1);\n border-left: 4px solid var(--accent-color);\n transform: translateX(5px);\n }\n \n .env-icon {\n width: 20px;\n height: 20px;\n color: var(--accent-color);\n flex-shrink: 0;\n animation: iconGlow 2s ease-in-out infinite;\n }\n \n @keyframes iconGlow {\n 0%, 100% { filter: drop-shadow(0 0 2px rgba(103, 233, 233, 0.3)); }\n 50% { filter: drop-shadow(0 0 8px rgba(103, 233, 233, 0.6)); }\n }\n \n .env-info {\n flex: 1;\n }\n \n .env-name {\n font-weight: 600;\n color: var(--text-primary);\n margin-bottom: 4px;\n }\n \n .env-alias {\n color: var(--text-secondary);\n font-size: 14px;\n }\n \n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n text-align: center;\n animation: fadeIn 0.8s ease-out;\n }\n \n .empty-icon {\n margin-bottom: 24px;\n color: var(--text-secondary);\n opacity: 0.6;\n }\n \n .empty-title {\n font-size: 20px;\n font-weight: 600;\n color: var(--text-primary);\n margin-bottom: 12px;\n }\n \n .empty-message {\n font-size: 14px;\n color: var(--text-secondary);\n line-height: 1.6;\n margin-bottom: 32px;\n max-width: 400px;\n }\n \n .create-env-btn {\n padding: 14px 24px;\n font-size: 15px;\n background: var(--primary-color);\n color: var(--text-primary);\n border: 1px solid var(--border-color);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n }\n \n .create-env-btn:hover {\n background: var(--primary-hover);\n transform: translateY(-2px);\n box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);\n }\n \n .actions {\n display: flex;\n gap: 12px;\n justify-content: flex-end;\n animation: fadeInUp 0.8s ease-out 0.8s both;\n }\n \n .btn {\n padding: 12px 20px;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: var(--font-mono);\n position: relative;\n overflow: hidden;\n }\n \n .btn::before {\n content: '';\n position: absolute;\n top: 50%; left: 50%;\n width: 0; height: 0;\n background: rgba(255,255,255,0.2);\n border-radius: 50%;\n transition: all 0.3s ease;\n transform: translate(-50%, -50%);\n }\n \n .btn:hover::before {\n width: 100px; height: 100px;\n }\n \n .btn-primary {\n background: var(--primary-color);\n color: var(--text-primary);\n border: 1px solid var(--border-color);\n }\n \n .btn-primary:hover:not(:disabled) {\n background: var(--primary-hover);\n transform: translateY(-2px);\n box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);\n }\n \n .btn-secondary {\n background: var(--bg-secondary);\n color: var(--text-secondary);\n border: 1px solid var(--border-color);\n }\n \n .btn-secondary:hover {\n background: rgba(255, 255, 255, 0.15);\n color: var(--text-primary);\n }\n \n .btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n \n .loading {\n display: none;\n align-items: center;\n justify-content: center;\n gap: 8px;\n margin-top: 16px;\n color: var(--text-secondary);\n font-size: 14px;\n }\n \n .spinner {\n width: 16px;\n height: 16px;\n border: 2px solid var(--border-color);\n border-top: 2px solid var(--accent-color);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n }\n \n @keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n \n @keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n \n .success-state {\n text-align: center;\n padding: 40px 20px;\n animation: fadeInUp 0.8s ease-out both;\n }\n \n .success-icon {\n margin-bottom: 20px;\n color: var(--accent-color);\n animation: successPulse 2s ease-in-out infinite;\n }\n \n @keyframes successPulse {\n 0%, 100% { \n transform: scale(1);\n filter: drop-shadow(0 0 8px rgba(103, 233, 233, 0.3));\n }\n 50% { \n transform: scale(1.1);\n filter: drop-shadow(0 0 16px rgba(103, 233, 233, 0.6));\n }\n }\n \n .success-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary);\n margin-bottom: 12px;\n }\n \n .success-message {\n color: var(--text-secondary);\n font-size: 16px;\n line-height: 1.5;\n }\n \n .selected-env-info {\n margin-top: 20px;\n padding: 16px;\n background: rgba(103, 233, 233, 0.1);\n border: 1px solid var(--accent-color);\n border-radius: 12px;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n \n .env-label {\n color: var(--text-secondary);\n font-size: 14px;\n font-weight: 500;\n }\n \n .env-value {\n color: var(--accent-color);\n font-size: 16px;\n font-weight: 600;\n font-family: var(--font-mono);\n }\n </style>\n</head>\n<body>\n <div class="modal">\n <div class="header">\n <div class="header-left">\n <img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />\n <span class="title">CloudBase AI Toolkit</span>\n </div>\n <a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" target="_blank" class="github-link">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">\n <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>\n </svg>\n GitHub\n </a>\n </div>\n\n <div class="content">\n <h1 class="content-title">选择云开发环境</h1>\n <p class="content-subtitle">请选择您要使用的云开发环境</p>\n \n <div class="env-list" id="envList">\n ${(e||[]).length>0?(e||[]).map((e,n)=>`\n <div class="env-item" onclick="selectEnv('${e.EnvId}', this)" style="animation-delay: ${.1*n}s;">\n <svg class="env-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/>\n </svg>\n <div class="env-info">\n <div class="env-name">${e.EnvId}</div>\n <div class="env-alias">${e.Alias||"无别名"}</div>\n </div>\n </div>\n `).join(""):'\n <div class="empty-state">\n <h3 class="empty-title">暂无云开发环境</h3>\n <p class="empty-message">当前没有可用的云开发 CloudBase 环境,请新建后重新在 AI 对话中重试</p>\n <button class="btn btn-primary create-env-btn" onclick="createNewEnv()">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M12 5v14M5 12h14"/>\n </svg>\n 新建环境\n </button>\n </div>\n '}\n </div>\n \n <div class="actions">\n <button class="btn btn-secondary" onclick="cancel()">\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M18 6L6 18M6 6l12 12"/>\n </svg>\n 取消\n </button>\n <button class="btn btn-primary" id="confirmBtn" onclick="confirm()" disabled>\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M20 6L9 17l-5-5"/>\n </svg>\n 确认选择\n </button>\n </div>\n \n <div class="loading" id="loading">\n <div class="spinner"></div>\n <span>正在配置环境...</span>\n </div>\n \n <div class="success-state" id="successState" style="display: none;">\n <div class="success-icon">\n <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M20 6L9 17l-5-5"/>\n </svg>\n </div>\n <h2 class="success-title">环境配置成功!</h2>\n <p class="success-message">已成功选择云开发环境</p>\n <div class="selected-env-info">\n <span class="env-label">环境 ID:</span>\n <span class="env-value" id="selectedEnvDisplay"></span>\n </div>\n </div>\n </div>\n </div>\n\n <script>\n let selectedEnvId = null;\n \n function selectEnv(envId, element) {\n console.log('=== 环境选择事件触发 ===');\n console.log('传入的envId:', envId);\n console.log('传入的element:', element);\n console.log('element类名:', element ? element.className : 'null');\n \n selectedEnvId = envId;\n console.log('设置selectedEnvId为:', selectedEnvId);\n \n // Remove selected class from all items\n const allItems = document.querySelectorAll('.env-item');\n console.log('找到的所有环境项数量:', allItems.length);\n allItems.forEach(item => {\n item.classList.remove('selected');\n });\n \n // Add selected class to current item\n if (element) {\n element.classList.add('selected');\n console.log('✅ 已添加selected样式到当前项');\n console.log('当前项的最终类名:', element.className);\n } else {\n console.error('❌ element为空,无法添加选中样式');\n }\n \n // Enable confirm button\n const confirmBtn = document.getElementById('confirmBtn');\n if (confirmBtn) {\n confirmBtn.disabled = false;\n console.log('✅ 确认按钮已启用');\n } else {\n console.error('❌ 找不到确认按钮');\n }\n }\n \n function confirm() {\n console.log('=== CONFIRM BUTTON CLICKED ===');\n console.log('selectedEnvId:', selectedEnvId);\n \n if (!selectedEnvId) {\n console.error('❌ 没有选择环境ID!');\n alert('请先选择一个环境');\n return;\n }\n \n console.log('✅ 环境ID验证通过,开始发送请求...');\n document.getElementById('loading').style.display = 'flex';\n document.getElementById('confirmBtn').disabled = true;\n \n const requestBody = {\n type: 'envId',\n data: selectedEnvId\n };\n \n console.log('📤 发送请求体:', JSON.stringify(requestBody, null, 2));\n \n fetch('/api/submit', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestBody)\n }).then(response => {\n console.log('📥 收到响应状态:', response.status);\n console.log('📥 响应头:', [...response.headers.entries()]);\n return response.json();\n }).then(data => {\n console.log('📥 响应数据:', data);\n if (data.success) {\n console.log('✅ 请求成功,展示成功提示');\n // 隐藏选择区和按钮,仅展示成功提示\n document.getElementById('envList').style.display = 'none';\n document.querySelector('.actions').style.display = 'none';\n document.getElementById('loading').style.display = 'none';\n document.getElementById('successState').style.display = 'block';\n // 显示选中的环境 ID\n document.getElementById('selectedEnvDisplay').textContent = selectedEnvId;\n window.close();\n } else {\n console.error('❌ 请求失败:', data);\n alert('选择环境失败: ' + (data.error || '未知错误'));\n document.getElementById('loading').style.display = 'none';\n document.getElementById('confirmBtn').disabled = false;\n }\n }).catch(err => {\n console.error('❌ 网络请求错误:', err);\n alert('网络请求失败: ' + err.message);\n document.getElementById('loading').style.display = 'none';\n document.getElementById('confirmBtn').disabled = false;\n });\n }\n \n function createNewEnv() {\n const integrationIde = '${process.env.INTEGRATION_IDE||"AI Toolkit"}';\n const url = \`http://tcb.cloud.tencent.com/dev?from=\${encodeURIComponent(integrationIde)}\`;\n location.href = url;\n }\n \n function cancel() {\n fetch('/api/cancel', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' }\n }).then(() => {\n window.close();\n });\n }\n <\/script>\n</body>\n</html>`}getLogsHTML(e,n){return`\n<!DOCTYPE html>\n<html lang="zh-CN">\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>CloudBase MCP 调试日志</title>\n <style>\n @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');\n \n * { margin: 0; padding: 0; box-sizing: border-box; }\n :root {\n --primary-color: #1a1a1a;\n --primary-hover: #000000;\n --accent-color: #67E9E9;\n --accent-hover: #2BCCCC;\n --text-primary: #ffffff;\n --text-secondary: #a0a0a0;\n --border-color: rgba(255, 255, 255, 0.15);\n --bg-secondary: rgba(255, 255, 255, 0.08);\n --bg-glass: rgba(26, 26, 26, 0.95);\n --shadow: 0 25px 50px rgba(0, 0, 0, 0.3), 0 10px 20px rgba(0, 0, 0, 0.2);\n --font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;\n --header-bg: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0d1117 100%);\n }\n \n body {\n font-family: var(--font-mono);\n background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);\n min-height: 100vh;\n padding: 20px;\n position: relative;\n overflow-x: hidden;\n overflow-y: auto;\n }\n \n /* Custom scrollbar styles */\n ::-webkit-scrollbar {\n width: 8px;\n }\n \n ::-webkit-scrollbar-track {\n background: rgba(255, 255, 255, 0.05);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb {\n background: var(--accent-color);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb:hover {\n background: var(--accent-hover);\n }\n \n body::before {\n content: '';\n position: fixed;\n top: 0; left: 0; right: 0; bottom: 0;\n background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse"><path d="M 20 0 L 0 0 0 20" fill="none" stroke="rgba(255,255,255,0.02)" stroke-width="1"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>') repeat;\n pointer-events: none;\n z-index: -1;\n }\n \n body::after {\n content: '';\n position: fixed;\n top: 50%; left: 50%;\n width: 500px; height: 500px;\n background: radial-gradient(circle, rgba(103, 233, 233, 0.05) 0%, transparent 70%);\n transform: translate(-50%, -50%);\n pointer-events: none;\n z-index: -1;\n animation: pulse 8s ease-in-out infinite;\n }\n \n @keyframes pulse {\n 0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }\n 50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }\n }\n \n .container {\n background: var(--bg-glass);\n backdrop-filter: blur(20px);\n border-radius: 20px;\n padding: 30px;\n box-shadow: var(--shadow);\n border: 2px solid var(--border-color);\n max-width: 1200px;\n margin: 0 auto;\n animation: modalIn 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);\n position: relative;\n }\n \n .container::before {\n content: '';\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.02) 50%, transparent 70%);\n animation: shimmer 3s infinite;\n pointer-events: none;\n border-radius: 20px;\n }\n \n @keyframes shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n \n @keyframes modalIn {\n from {\n opacity: 0;\n transform: scale(0.9) translateY(-20px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n }\n \n .header {\n text-align: center;\n margin-bottom: 30px;\n position: relative;\n z-index: 1;\n }\n \n .header-top {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 20px;\n }\n \n .header-left {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n \n .logo {\n width: 40px;\n height: 40px;\n filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));\n animation: logoFloat 3s ease-in-out infinite;\n }\n \n @keyframes logoFloat {\n 0%, 100% { transform: translateY(0px); }\n 50% { transform: translateY(-3px); }\n }\n \n .github-link {\n color: var(--text-primary);\n text-decoration: none;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n background: rgba(255,255,255,0.08);\n border: 1px solid rgba(255, 255, 255, 0.12);\n backdrop-filter: blur(10px);\n padding: 8px 16px;\n border-radius: 8px;\n font-weight: 500;\n transition: all 0.3s ease;\n }\n \n .github-link:hover {\n background: rgba(255,255,255,0.15);\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n }\n \n h1 {\n color: var(--text-primary);\n margin-bottom: 10px;\n font-size: 28px;\n font-weight: 700;\n animation: fadeInUp 0.8s ease-out 0.2s both;\n }\n \n .subtitle {\n color: var(--text-secondary);\n font-size: 16px;\n animation: fadeInUp 0.8s ease-out 0.4s both;\n }\n \n @keyframes fadeInUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n \n .status {\n background: rgba(255, 255, 255, 0.05);\n border: 1px solid var(--border-color);\n border-radius: 12px;\n padding: 20px;\n margin-bottom: 20px;\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 15px;\n animation: fadeInUp 0.8s ease-out 0.6s both;\n }\n \n .status-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n \n .status-label {\n font-weight: 600;\n color: var(--text-secondary);\n }\n \n .status-value {\n color: var(--text-primary);\n font-family: var(--font-mono);\n font-size: 14px;\n }\n \n .enabled {\n color: var(--accent-color);\n }\n \n .disabled {\n color: #ff6b6b;\n }\n \n .controls {\n display: flex;\n gap: 15px;\n margin-bottom: 20px;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n animation: fadeInUp 0.8s ease-out 0.8s both;\n }\n \n .controls-left {\n display: flex;\n gap: 15px;\n }\n \n .btn {\n padding: 10px 20px;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n font-family: var(--font-mono);\n position: relative;\n overflow: hidden;\n }\n \n .btn::before {\n content: '';\n position: absolute;\n top: 50%; left: 50%;\n width: 0; height: 0;\n background: rgba(255,255,255,0.2);\n border-radius: 50%;\n transition: all 0.3s ease;\n transform: translate(-50%, -50%);\n }\n \n .btn:hover::before {\n width: 100px; height: 100px;\n }\n \n .btn-primary {\n background: var(--accent-color);\n color: var(--primary-color);\n }\n \n .btn-primary:hover {\n background: var(--accent-hover);\n transform: translateY(-2px);\n box-shadow: 0 8px 25px rgba(103, 233, 233, 0.3);\n }\n \n .btn-danger {\n background: #ff6b6b;\n color: white;\n }\n \n .btn-danger:hover {\n background: #ff5252;\n transform: translateY(-2px);\n box-shadow: 0 8px 25px rgba(255, 107, 107, 0.3);\n }\n \n .btn-secondary {\n background: var(--bg-secondary);\n color: var(--text-secondary);\n border: 1px solid var(--border-color);\n }\n \n .btn-secondary:hover {\n background: rgba(255, 255, 255, 0.15);\n color: var(--text-primary);\n }\n \n .log-container {\n background: rgba(0, 0, 0, 0.5);\n border: 1px solid var(--border-color);\n border-radius: 12px;\n padding: 20px;\n height: 500px;\n overflow-y: auto;\n font-family: var(--font-mono);\n font-size: 13px;\n line-height: 1.4;\n animation: fadeInUp 0.8s ease-out 1s both;\n }\n \n .log-container::-webkit-scrollbar {\n width: 8px;\n }\n \n .log-container::-webkit-scrollbar-track {\n background: rgba(255, 255, 255, 0.1);\n border-radius: 4px;\n }\n \n .log-container::-webkit-scrollbar-thumb {\n background: var(--accent-color);\n border-radius: 4px;\n }\n \n .log-container::-webkit-scrollbar-thumb:hover {\n background: var(--accent-hover);\n }\n \n .log-line {\n color: var(--text-primary);\n margin-bottom: 2px;\n word-break: break-all;\n animation: logSlideIn 0.3s ease-out;\n }\n \n @keyframes logSlideIn {\n from {\n opacity: 0;\n transform: translateX(-10px);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n }\n \n .log-line.debug {\n color: var(--text-secondary);\n }\n \n .log-line.info {\n color: #74c0fc;\n }\n \n .log-line.warn {\n color: #ffd43b;\n }\n \n .log-line.error {\n color: #ff8787;\n }\n \n .timestamp {\n color: var(--text-secondary);\n }\n \n .level {\n font-weight: bold;\n margin: 0 8px;\n }\n \n .empty-state {\n text-align: center;\n color: var(--text-secondary);\n padding: 40px;\n font-style: italic;\n }\n \n .log-count {\n color: var(--text-secondary);\n font-size: 14px;\n }\n </style>\n</head>\n<body>\n <div class="container">\n <div class="header">\n <div class="header-top">\n <div class="header-left">\n <img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />\n <div style="text-align: left;">\n <h1>CloudBase MCP 调试日志</h1>\n <p class="subtitle">实时查看 MCP 服务器运行日志</p>\n </div>\n </div>\n <a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" target="_blank" class="github-link">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">\n <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>\n </svg>\n GitHub\n </a>\n </div>\n </div>\n \n <div class="status">\n <div class="status-item">\n <span class="status-label">日志状态:</span>\n <span class="status-value ${n.enabled?"enabled":"disabled"}">\n ${n.enabled?"🟢 启用":"🔴 禁用"}\n </span>\n </div>\n <div class="status-item">\n <span class="status-label">日志级别:</span>\n <span class="status-value">${n.level}</span>\n </div>\n <div class="status-item">\n <span class="status-label">日志文件:</span>\n <span class="status-value">${n.logFile||"无"}</span>\n </div>\n <div class="status-item">\n <span class="status-label">控制台输出:</span>\n <span class="status-value ${n.useConsole?"enabled":"disabled"}">\n ${n.useConsole?"🟢 启用":"🔴 禁用"}\n </span>\n </div>\n </div>\n \n <div class="controls">\n <div class="controls-left">\n <button class="btn btn-primary" onclick="refreshLogs()">\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 6px;">\n <path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/>\n <path d="M21 3v5h-5"/>\n <path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/>\n <path d="M8 16H3v5"/>\n </svg>\n 刷新日志\n </button>\n <button class="btn btn-danger" onclick="clearLogs()">\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 6px;">\n <path d="M3 6h18"/>\n <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/>\n <path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/>\n </svg>\n 清空日志\n </button>\n <button class="btn btn-secondary" onclick="window.close()">\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 6px;">\n <path d="M18 6L6 18M6 6l12 12"/>\n </svg>\n 关闭\n </button>\n </div>\n <div>\n <span class="log-count">📊 共 ${e.length} 条日志</span>\n </div>\n </div>\n \n <div class="log-container" id="logContainer">\n ${e.length>0?e.map(e=>{const n=e.match(/\[(.*?)\] \[(.*?)\] (.*)/);if(n){const[,e,t,o]=n,r=t.toLowerCase();return`<div class="log-line ${r}"><span class="timestamp">[${e}]</span><span class="level ${r}">[${t}]</span>${o}</div>`}return`<div class="log-line">${e}</div>`}).join(""):'<div class="empty-state">📝 暂无日志记录</div>'}\n </div>\n </div>\n\n <script>\n function refreshLogs() {\n fetch('/api/logs')\n .then(response => response.json())\n .then(data => {\n if (data.success) {\n location.reload();\n }\n })\n .catch(error => {\n alert('刷新日志失败: ' + error.message);\n });\n }\n \n function clearLogs() {\n if (confirm('确定要清空所有日志吗?此操作不可恢复。')) {\n fetch('/api/logs/clear', { method: 'POST' })\n .then(response => response.json())\n .then(data => {\n if (data.success) {\n location.reload();\n } else {\n alert('清空日志失败');\n }\n })\n .catch(error => {\n alert('清空日志失败: ' + error.message);\n });\n }\n }\n \n // 自动滚动到底部\n const logContainer = document.getElementById('logContainer');\n logContainer.scrollTop = logContainer.scrollHeight;\n \n // 每5秒自动刷新\n setInterval(() => {\n const isAtBottom = logContainer.scrollHeight - logContainer.clientHeight <= logContainer.scrollTop + 1;\n \n fetch('/api/logs')\n .then(response => response.json())\n .then(data => {\n if (data.success && data.logs.length > 0) {\n const newContent = data.logs.map(line => {\n const match = line.match(/\\[(.*?)\\] \\[(.*?)\\] (.*)/);\n if (match) {\n const [, timestamp, level, message] = match;\n const levelClass = level.toLowerCase();\n return \`<div class="log-line \${levelClass}"><span class="timestamp">[\${timestamp}]</span><span class="level \${levelClass}">[\${level}]</span>\${message}</div>\`;\n }\n return \`<div class="log-line">\${line}</div>\`;\n }).join('');\n \n logContainer.innerHTML = newContent || '<div class="empty-state">📝 暂无日志记录</div>';\n \n if (isAtBottom) {\n logContainer.scrollTop = logContainer.scrollHeight;\n }\n }\n })\n .catch(error => {\n console.error('获取日志失败:', error);\n });\n }, 5000);\n <\/script>\n</body>\n</html>`}getClarificationHTML(e,n){const t=n||null;return`\n<!DOCTYPE html>\n<html lang="zh-CN">\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>CloudBase AI Toolkit - 需求澄清</title>\n <style>\n @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');\n \n * { margin: 0; padding: 0; box-sizing: border-box; }\n :root {\n --primary-color: #1a1a1a;\n --primary-hover: #000000;\n --accent-color: #67E9E9;\n --accent-hover: #2BCCCC;\n --text-primary: #ffffff;\n --text-secondary: #a0a0a0;\n --border-color: rgba(255, 255, 255, 0.15);\n --bg-secondary: rgba(255, 255, 255, 0.08);\n --bg-glass: rgba(26, 26, 26, 0.95);\n --shadow: 0 25px 50px rgba(0, 0, 0, 0.3), 0 10px 20px rgba(0, 0, 0, 0.2);\n --font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;\n --header-bg: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0d1117 100%);\n }\n \n body {\n font-family: var(--font-mono);\n background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n position: relative;\n overflow-x: hidden;\n overflow-y: auto;\n }\n \n /* Custom scrollbar styles */\n ::-webkit-scrollbar {\n width: 8px;\n }\n \n ::-webkit-scrollbar-track {\n background: rgba(255, 255, 255, 0.05);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb {\n background: var(--accent-color);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb:hover {\n background: var(--accent-hover);\n }\n \n body::before {\n content: '';\n position: fixed;\n top: 0; left: 0; right: 0; bottom: 0;\n background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse"><path d="M 20 0 L 0 0 0 20" fill="none" stroke="rgba(255,255,255,0.02)" stroke-width="1"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>') repeat;\n pointer-events: none;\n z-index: -1;\n }\n \n body::after {\n content: '';\n position: fixed;\n top: 50%; left: 50%;\n width: 500px; height: 500px;\n background: radial-gradient(circle, rgba(103, 233, 233, 0.05) 0%, transparent 70%);\n transform: translate(-50%, -50%);\n pointer-events: none;\n z-index: -1;\n animation: pulse 8s ease-in-out infinite;\n }\n \n @keyframes pulse {\n 0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }\n 50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }\n }\n \n .modal {\n background: var(--bg-glass);\n backdrop-filter: blur(20px);\n border-radius: 20px;\n box-shadow: var(--shadow);\n border: 2px solid var(--border-color);\n width: 100%;\n max-width: 600px;\n overflow: hidden;\n animation: modalIn 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);\n position: relative;\n }\n \n .modal::before {\n content: '';\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.02) 50%, transparent 70%);\n animation: shimmer 3s infinite;\n pointer-events: none;\n }\n \n @keyframes shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n \n @keyframes modalIn {\n from {\n opacity: 0;\n transform: scale(0.9) translateY(-20px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n }\n \n .header {\n background: var(--header-bg);\n color: var(--text-primary);\n padding: 24px 28px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n position: relative;\n overflow: hidden;\n }\n \n .header::before {\n content: '';\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.03) 50%, transparent 70%);\n animation: headerShimmer 4s infinite;\n pointer-events: none;\n }\n \n @keyframes headerShimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n \n .header-left {\n display: flex;\n align-items: center;\n gap: 16px;\n z-index: 1;\n }\n \n .logo {\n width: 32px;\n height: 32px;\n filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));\n animation: logoFloat 3s ease-in-out infinite;\n }\n \n @keyframes logoFloat {\n 0%, 100% { transform: translateY(0px); }\n 50% { transform: translateY(-3px); }\n }\n \n .title {\n font-size: 20px;\n font-weight: 700;\n text-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n \n .github-link {\n color: var(--text-primary);\n text-decoration: none;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n background: rgba(255,255,255,0.08);\n border: 1px solid rgba(255, 255, 255, 0.12);\n backdrop-filter: blur(10px);\n padding: 8px 16px;\n border-radius: 8px;\n font-weight: 500;\n z-index: 1;\n transition: all 0.3s ease;\n }\n \n .github-link:hover {\n background: rgba(255,255,255,0.15);\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n }\n \n .content {\n padding: 32px 24px;\n position: relative;\n }\n \n .content-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary);\n margin-bottom: 8px;\n animation: fadeInUp 0.8s ease-out 0.2s both;\n }\n \n @keyframes fadeInUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n \n .message {\n background: rgba(103, 233, 233, 0.1);\n border: 1px solid var(--accent-color);\n border-left: 4px solid var(--accent-color);\n padding: 20px;\n border-radius: 12px;\n margin-bottom: 24px;\n white-space: pre;\n font-size: 15px;\n line-height: 1.6;\n color: var(--text-primary);\n animation: fadeInUp 0.8s ease-out 0.4s both;\n position: relative;\n overflow: hidden;\n }\n \n .message::before {\n content: '';\n position: absolute;\n top: 0; left: 0;\n width: 100%; height: 2px;\n background: linear-gradient(90deg, var(--accent-color), transparent);\n animation: progress 2s ease-out;\n }\n \n @keyframes progress {\n from { width: 0%; }\n to { width: 100%; }\n }\n \n .options {\n margin-bottom: 24px;\n animation: fadeInUp 0.8s ease-out 0.6s both;\n }\n \n .option-item {\n padding: 16px 20px;\n border: 1px solid var(--border-color);\n border-radius: 12px;\n margin-bottom: 12px;\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n gap: 14px;\n background: rgba(255, 255, 255, 0.03);\n position: relative;\n overflow: hidden;\n color: var(--text-primary);\n }\n \n .option-item::before {\n content: '';\n position: absolute;\n left: 0; top: 0; bottom: 0;\n width: 0;\n background: var(--accent-color);\n transition: width 0.3s ease;\n }\n \n .option-item:hover {\n background: var(--bg-secondary);\n border-color: var(--accent-color);\n transform: translateX(5px);\n }\n \n .option-item:hover::before {\n width: 4px;\n }\n \n .option-item.selected {\n background: rgba(103, 233, 233, 0.1);\n border-color: var(--accent-color);\n transform: translateX(5px);\n }\n \n .option-item.selected::before {\n width: 4px;\n }\n \n .option-icon {\n width: 20px;\n height: 20px;\n color: var(--accent-color);\n flex-shrink: 0;\n animation: iconGlow 2s ease-in-out infinite;\n }\n \n @keyframes iconGlow {\n 0%, 100% { filter: drop-shadow(0 0 2px rgba(103, 233, 233, 0.3)); }\n 50% { filter: drop-shadow(0 0 8px rgba(103, 233, 233, 0.6)); }\n }\n \n .custom-input {\n margin-bottom: 24px;\n animation: fadeInUp 0.8s ease-out 0.8s both;\n }\n \n .custom-input textarea {\n width: 100%;\n min-height: 120px;\n padding: 16px;\n border: 1px solid var(--border-color);\n border-radius: 12px;\n font-size: 15px;\n font-family: var(--font-mono);\n resize: vertical;\n transition: all 0.3s ease;\n line-height: 1.5;\n background: rgba(255, 255, 255, 0.03);\n color: var(--text-primary);\n }\n \n .custom-input textarea::placeholder {\n color: var(--text-secondary);\n }\n \n .custom-input textarea:focus {\n outline: none;\n border-color: var(--accent-color);\n box-shadow: 0 0 0 3px rgba(103, 233, 233, 0.1);\n background: rgba(255, 255, 255, 0.05);\n }\n \n .actions {\n display: flex;\n gap: 12px;\n justify-content: flex-end;\n animation: fadeInUp 0.8s ease-out 1s both;\n }\n \n .btn {\n padding: 12px 20px;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: var(--font-mono);\n position: relative;\n overflow: hidden;\n }\n \n .btn::before {\n content: '';\n position: absolute;\n top: 50%; left: 50%;\n width: 0; height: 0;\n background: rgba(255,255,255,0.2);\n border-radius: 50%;\n transition: all 0.3s ease;\n transform: translate(-50%, -50%);\n }\n \n .btn:hover::before {\n width: 100px; height: 100px;\n }\n \n .btn-primary {\n background: var(--primary-color);\n color: var(--text-primary);\n border: 1px solid var(--border-color);\n }\n \n .btn-primary:hover:not(:disabled) {\n background: var(--primary-hover);\n transform: translateY(-2px);\n box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);\n }\n \n .btn-secondary {\n background: var(--bg-secondary);\n color: var(--text-secondary);\n border: 1px solid var(--border-color);\n }\n \n .btn-secondary:hover {\n background: rgba(255, 255, 255, 0.15);\n color: var(--text-primary);\n }\n \n .btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n \n .loading {\n display: none;\n align-items: center;\n justify-content: center;\n gap: 8px;\n margin-top: 16px;\n color: var(--text-secondary);\n font-size: 14px;\n }\n \n .spinner {\n width: 16px;\n height: 16px;\n border: 2px solid var(--border-color);\n border-top: 2px solid var(--accent-color);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n }\n \n @keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n \n @keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n \n .success-state {\n text-align: center;\n padding: 40px 20px;\n animation: fadeInUp 0.8s ease-out both;\n }\n \n .success-icon {\n margin-bottom: 20px;\n color: var(--accent-color);\n animation: successPulse 2s ease-in-out infinite;\n }\n \n @keyframes successPulse {\n 0%, 100% { \n transform: scale(1);\n filter: drop-shadow(0 0 8px rgba(103, 233, 233, 0.3));\n }\n 50% { \n transform: scale(1.1);\n filter: drop-shadow(0 0 16px rgba(103, 233, 233, 0.6));\n }\n }\n \n .success-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary);\n margin-bottom: 12px;\n }\n \n .success-message {\n color: var(--text-secondary);\n font-size: 16px;\n line-height: 1.5;\n }\n \n .selected-env-info {\n margin-top: 20px;\n padding: 16px;\n background: rgba(103, 233, 233, 0.1);\n border: 1px solid var(--accent-color);\n border-radius: 12px;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n \n .env-label {\n color: var(--text-secondary);\n font-size: 14px;\n font-weight: 500;\n }\n \n .env-value {\n color: var(--accent-color);\n font-size: 16px;\n font-weight: 600;\n font-family: var(--font-mono);\n }\n </style>\n</head>\n<body>\n <div class="modal">\n <div class="header">\n <div class="header-left">\n <img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />\n <span class="title">CloudBase AI Toolkit</span>\n </div>\n <a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" target="_blank" class="github-link">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">\n <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>\n </svg>\n GitHub\n </a>\n </div>\n\n <div class="content">\n <h1 class="content-title">AI 需要您确认</h1>\n <div class="message">${e}</div>\n \n ${t?`\n <div class="options" id="options">\n ${t.map((e,n)=>`\n <div class="option-item" onclick="selectOption('${e}')" style="animation-delay: ${.1*n}s;">\n <svg class="option-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 014.7-7.6 8.38 8.38 0 013.8-.9h.5a8.48 8.48 0 018 8v.5z"/>\n </svg>\n <span>${e}</span>\n </div>\n `).join("")}\n </div>\n `:""}\n \n <div class="custom-input">\n <textarea id="customInput" placeholder="请输入您的具体需求或建议..." onkeyup="updateSubmitButton()"></textarea>\n </div>\n \n <div class="actions">\n <button class="btn btn-secondary" onclick="cancel()">\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M18 6L6 18M6 6l12 12"/>\n </svg>\n 取消\n </button>\n <button class="btn btn-primary" id="submitBtn" onclick="submit()">\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M20 6L9 17l-5-5"/>\n </svg>\n 确认执行\n </button>\n </div>\n \n <div class="loading" id="loading">\n <div class="spinner"></div>\n <span>正在提交...</span>\n </div>\n </div>\n </div>\n\n <script>\n let selectedOption = null;\n \n function selectOption(option) {\n selectedOption = option;\n \n document.querySelectorAll('.option-item').forEach(item => {\n item.classList.remove('selected');\n });\n event.currentTarget.classList.add('selected');\n \n updateSubmitButton();\n }\n \n function updateSubmitButton() {\n const customInput = document.getElementById('customInput').value.trim();\n const submitBtn = document.getElementById('submitBtn');\n \n if (selectedOption || customInput) {\n submitBtn.disabled = false;\n submitBtn.style.opacity = '1';\n } else {\n submitBtn.disabled = true;\n submitBtn.style.opacity = '0.5';\n }\n }\n \n function submit() {\n const customInput = document.getElementById('customInput').value.trim();\n const data = selectedOption || customInput;\n \n if (!data) return;\n \n document.getElementById('loading').style.display = 'flex';\n document.getElementById('submitBtn').disabled = true;\n \n fetch('/api/submit', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n type: 'clarification',\n data: data\n })\n }).then(response => response.json())\n .then(result => {\n if (result.success) {\n window.close();\n }\n }).catch(err => {\n console.error('Error:', err);\n document.getElementById('loading').style.display = 'none';\n document.getElementById('submitBtn').disabled = false;\n });\n }\n \n function cancel() {\n fetch('/api/cancel', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' }\n }).then(() => {\n window.close();\n });\n }\n \n // Initialize\n updateSubmitButton();\n <\/script>\n</body>\n</html>`}getConfirmationHTML(e,n,t){const o=t||["确认执行","取消操作"];return`\n<!DOCTYPE html>\n<html lang="zh-CN">\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>CloudBase AI Toolkit - 操作确认</title>\n <style>\n @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');\n \n * { margin: 0; padding: 0; box-sizing: border-box; }\n :root {\n --primary-color: #1a1a1a;\n --primary-hover: #000000;\n --accent-color: #67E9E9;\n --accent-hover: #2BCCCC;\n --text-primary: #ffffff;\n --text-secondary: #a0a0a0;\n --border-color: rgba(255, 255, 255, 0.15);\n --bg-secondary: rgba(255, 255, 255, 0.08);\n --bg-glass: rgba(26, 26, 26, 0.95);\n --warning-color: #ff6b6b;\n --warning-bg: rgba(255, 107, 107, 0.1);\n --warning-border: rgba(255, 107, 107, 0.3);\n --shadow: 0 25px 50px rgba(0, 0, 0, 0.3), 0 10px 20px rgba(0, 0, 0, 0.2);\n --font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;\n --header-bg: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0d1117 100%);\n }\n \n body {\n font-family: var(--font-mono);\n background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n position: relative;\n overflow-x: hidden;\n overflow-y: auto;\n }\n \n /* Custom scrollbar styles */\n ::-webkit-scrollbar {\n width: 8px;\n }\n \n ::-webkit-scrollbar-track {\n background: rgba(255, 255, 255, 0.05);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb {\n background: var(--accent-color);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb:hover {\n background: var(--accent-hover);\n }\n \n body::before {\n content: '';\n position: fixed;\n top: 0; left: 0; right: 0; bottom: 0;\n background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse"><path d="M 20 0 L 0 0 0 20" fill="none" stroke="rgba(255,255,255,0.02)" stroke-width="1"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>') repeat;\n pointer-events: none;\n z-index: -1;\n }\n \n body::after {\n content: '';\n position: fixed;\n top: 50%; left: 50%;\n width: 500px; height: 500px;\n background: radial-gradient(circle, rgba(255, 107, 107, 0.03) 0%, transparent 70%);\n transform: translate(-50%, -50%);\n pointer-events: none;\n z-index: -1;\n animation: pulse 8s ease-in-out infinite;\n }\n \n @keyframes pulse {\n 0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }\n 50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }\n }\n \n .modal {\n background: var(--bg-glass);\n backdrop-filter: blur(20px);\n border-radius: 20px;\n box-shadow: var(--shadow);\n border: 2px solid var(--border-color);\n width: 100%;\n max-width: 600px;\n overflow: hidden;\n animation: modalIn 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);\n position: relative;\n }\n \n .modal::before {\n content: '';\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.02) 50%, transparent 70%);\n animation: shimmer 3s infinite;\n pointer-events: none;\n }\n \n @keyframes shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n \n @keyframes modalIn {\n from {\n opacity: 0;\n transform: scale(0.9) translateY(-20px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n }\n \n .header {\n background: var(--header-bg);\n color: var(--text-primary);\n padding: 24px 28px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n position: relative;\n overflow: hidden;\n }\n \n .header::before {\n content: '';\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.03) 50%, transparent 70%);\n animation: headerShimmer 4s infinite;\n pointer-events: none;\n }\n \n @keyframes headerShimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n \n .header-left {\n display: flex;\n align-items: center;\n gap: 16px;\n z-index: 1;\n }\n \n .logo {\n width: 32px;\n height: 32px;\n filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));\n animation: logoFloat 3s ease-in-out infinite;\n }\n \n @keyframes logoFloat {\n 0%, 100% { transform: translateY(0px); }\n 50% { transform: translateY(-3px); }\n }\n \n .title {\n font-size: 20px;\n font-weight: 700;\n text-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n \n .github-link {\n color: var(--text-primary);\n text-decoration: none;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n background: rgba(255,255,255,0.08);\n border: 1px solid rgba(255, 255, 255, 0.12);\n backdrop-filter: blur(10px);\n padding: 8px 16px;\n border-radius: 8px;\n font-weight: 500;\n z-index: 1;\n transition: all 0.3s ease;\n }\n \n .github-link:hover {\n background: rgba(255,255,255,0.15);\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n }\n \n .content {\n padding: 32px 24px;\n position: relative;\n }\n \n @keyframes fadeInUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n \n .content-title {\n font-size: 24px;\n margin-bottom: 8px;\n color: var(--text-primary);\n display: flex;\n align-items: center;\n gap: 12px;\n position: relative;\n animation: fadeInUp 0.8s ease-out 0.2s both;\n }\n \n .message {\n background: rgba(103, 233, 233, 0.1);\n border: 1px solid var(--accent-color);\n border-left: 4px solid var(--accent-color);\n padding: 20px;\n border-radius: 12px;\n margin-bottom: 24px;\n font-size: 15px;\n line-height: 1.6;\n color: var(--text-primary);\n animation: fadeInUp 0.8s ease-out 0.4s both;\n position: relative;\n overflow: scroll;\n white-space: pre;\n max-height: 300px;\n }\n \n .message::before {\n content: '';\n position: absolute;\n top: 0; left: 0;\n width: 100%; height: 2px;\n background: linear-gradient(90deg, var(--accent-color), transparent);\n animation: progress 2s ease-out;\n }\n \n @keyframes progress {\n from { width: 0%; }\n to { width: 100%; }\n }\n \n .risks {\n background: var(--warning-bg);\n border: 1px solid var(--warning-border);\n border-radius: 12px;\n padding: 20px;\n margin-bottom: 24px;\n animation: fadeInUp 0.8s ease-out 0.6s both;\n }\n \n .risks-title {\n color: var(--warning-color);\n font-weight: 600;\n margin-bottom: 12px;\n display: flex;\n align-items: center;\n gap: 8px;\n animation: warningGlow 2s ease-in-out infinite;\n }\n \n @keyframes warningGlow {\n 0%, 100% { filter: drop-shadow(0 0 2px rgba(255, 107, 107, 0.3)); }\n 50% { filter: drop-shadow(0 0 8px rgba(255, 107, 107, 0.6)); }\n }\n \n .risk-item {\n color: var(--text-primary);\n margin-bottom: 8px;\n padding-left: 24px;\n position: relative;\n }\n \n .risk-item:before {\n content: "⚠️";\n position: absolute;\n left: 0;\n color: var(--warning-color);\n }\n \n .options {\n margin-bottom: 24px;\n animation: fadeInUp 0.8s ease-out 0.8s both;\n }\n \n .option-item {\n padding: 16px 20px;\n border: 1px solid var(--border-color);\n border-radius: 12px;\n margin-bottom: 12px;\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n gap: 14px;\n background: rgba(255, 255, 255, 0.03);\n position: relative;\n overflow: hidden;\n color: var(--text-primary);\n }\n \n .option-item::before {\n content: '';\n position: absolute;\n left: 0; top: 0; bottom: 0;\n width: 0;\n background: var(--accent-color);\n transition: width 0.3s ease;\n }\n \n .option-item.confirm::before {\n background: var(--accent-color);\n }\n \n .option-item.cancel::before {\n background: var(--warning-color);\n }\n \n .option-item:hover {\n background: var(--bg-secondary);\n transform: translateX(5px);\n }\n \n .option-item:hover::before {\n width: 4px;\n }\n \n .option-item.selected {\n background: rgba(103, 233, 233, 0.1);\n border-color: var(--accent-color);\n transform: translateX(5px);\n }\n \n .option-item.selected.cancel {\n background: rgba(255, 107, 107, 0.1);\n border-color: var(--warning-color);\n }\n \n .option-item.selected::before {\n width: 4px;\n }\n \n .option-icon {\n width: 20px;\n height: 20px;\n color: var(--accent-color);\n flex-shrink: 0;\n }\n \n .option-item.cancel .option-icon {\n color: var(--warning-color);\n }\n \n .loading {\n display: none;\n align-items: center;\n justify-content: center;\n gap: 8px;\n margin-top: 16px;\n color: var(--text-secondary);\n font-size: 14px;\n animation: fadeInUp 0.8s ease-out 1s both;\n }\n \n .spinner {\n width: 16px;\n height: 16px;\n border: 2px solid var(--border-color);\n border-top: 2px solid var(--accent-color);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n }\n \n @keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n </style>\n</head>\n<body>\n <div class="modal">\n <div class="header">\n <div class="header-left">\n <img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />\n <span class="title">CloudBase AI Toolkit</span>\n </div>\n <a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" target="_blank" class="github-link">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">\n <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>\n </svg>\n GitHub\n </a>\n </div>\n\n <div class="content">\n <h1 class="content-title">\n <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/>\n <line x1="12" y1="9" x2="12" y2="13"/>\n <line x1="12" y1="17" x2="12.01" y2="17"/>\n </svg>\n 操作确认\n </h1>\n <div class="message">${e}</div>\n \n ${n&&n.length>0?`\n <div class="risks">\n <div class="risks-title">\n <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/>\n <line x1="12" y1="9" x2="12" y2="13"/>\n <line x1="12" y1="17" x2="12.01" y2="17"/>\n </svg>\n 风险提示\n </div>\n ${n.map(e=>`<div class="risk-item">${e}</div>`).join("")}\n </div>\n `:""}\n \n <div class="options">\n ${o.map((e,n)=>{const t=e.includes("取消")||e.toLowerCase().includes("cancel");return`\n <div class="option-item ${t?"cancel":"confirm"}" onclick="selectOption('${e}')" style="animation-delay: ${.1*n}s;">\n <svg class="option-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n ${t?'<path d="M18 6L6 18M6 6l12 12"/>':'<path d="M20 6L9 17l-5-5"/>'}\n </svg>\n <span>${e}</span>\n </div>\n `}).join("")}\n </div>\n \n <div class="loading" id="loading">\n <div class="spinner"></div>\n <span>正在处理...</span>\n </div>\n </div>\n </div>\n\n <script>\n let selectedOption = null;\n \n function selectOption(option) {\n selectedOption = option;\n \n document.querySelectorAll('.option-item').forEach(item => {\n item.classList.remove('selected');\n });\n event.currentTarget.classList.add('selected');\n \n // Auto submit after selection\n setTimeout(() => {\n submit();\n }, 500);\n }\n \n function submit() {\n if (!selectedOption) return;\n \n document.getElementById('loading').style.display = 'flex';\n \n const isConfirmed = !selectedOption.includes('取消') && !selectedOption.toLowerCase().includes('cancel');\n \n fetch('/api/submit', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n type: 'confirmation',\n data: {\n confirmed: isConfirmed,\n option: selectedOption\n }\n })\n }).then(response => response.json())\n .then(result => {\n if (result.success) {\n window.close();\n }\n }).catch(err => {\n console.error('Error:', err);\n document.getElementById('loading').style.display = 'none';\n });\n }\n \n function cancel() {\n fetch('/api/cancel', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' }\n }).then(() => {\n window.close();\n });\n }\n <\/script>\n</body>\n</html>`}get running(){return this.isRunning}get currentPort(){return this.port}}n.InteractiveServer=d;let p=null;function u(e){return p?e&&!p.mcpServer&&(p.mcpServer=e):p=new d(e),p}},357:e=>{e.exports=a},363:function(e,n,t){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.wrapServerWithTelemetry=function(e){const n=e.registerTool.bind(e);e.registerTool=function(t,o,d){if(!(0,s.shouldRegisterTool)(t))return void(0,a.debug)(`Cloud mode: skipping registration of incompatible tool: ${t}`);(0,a.debug)(`Registering tool: ${t}`,{toolConfig:o});const p=function(e,n,t){return async o=>{const s=Date.now();let d,p=!1;try{(0,a.debug)(`开始执行工具: ${e}`,{args:l(o)});const t=await n(o);return p=!0,(0,a.debug)(`工具执行成功: ${e}`,{duration:Date.now()-s}),t}catch(n){p=!1,d=n instanceof Error?n.message:String(n),(0,a.debug)(`工具执行失败: ${e}`,{error:d,duration:Date.now()-s});const r=await async function(e,n,t,o,r){const{requestId:s,ide:d}=r||{};let p="";try{const e=await(0,i.getEnvId)(o);e&&(p=`\n## 环境ID\n${e}\n`)}catch(e){(0,a.debug)("无法获取环境ID:",e)}const u=`MCP工具错误: ${e}`,g=`## 错误描述\n工具 \`${e}\` 执行时发生错误\n\n## 错误信息\n\`\`\`\n${n}\n\`\`\`\n${p}\n## 环境信息\n- 操作系统: ${c.default.type()} ${c.default.release()}\n- Node.js版本: ${process.version}\n- MCP 版本:${process.env.npm_package_version||"1.8.35"}\n- 系统架构: ${c.default.arch()}\n- 时间: ${(new Date).toISOString()}\n- 请求ID: ${s}\n- 集成IDE: ${d}\n\n## 工具参数\n\`\`\`json\n${JSON.stringify(l(t),null,2)}\n\`\`\`\n\n## 复现步骤\n1. 使用工具: ${e}\n2. 传入参数: 上述参数信息\n3. 出现错误\n\n## 期望行为\n[请描述您期望的正确行为]\n\n## 其他信息\n[如有其他相关信息,请在此补充]\n`;return`https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/issues/new?title=${encodeURIComponent(u)}&body=${encodeURIComponent(g)}`}(e,d,o,t.cloudBaseOptions,{requestId:"object"==typeof n&&n&&"requestId"in n?n.requestId:"",ide:t.ide||process.env.INTEGRATION_IDE||""}),u=(Error,new Error(`${d}\n\n🔗 遇到问题?请复制以下链接到浏览器打开\n即可自动携带错误详情快速创建 GitHub Issue:\n${r}`));throw n instanceof Error&&(u.stack=n.stack,u.name=n.name),u}finally{const n=Date.now()-s;(0,r.reportToolCall)({toolName:e,success:p,duration:n,error:d,inputParams:l(o),cloudBaseOptions:t.cloudBaseOptions,ide:t.ide||process.env.INTEGRATION_IDE})}}}(t,d,e);return n(t,o,p)}};const r=t(880),a=t(39),i=t(431),s=t(684),c=o(t(116));function l(e){if(!e||"object"!=typeof e)return e;const n={...e},t=["password","token","secret","key","auth","localPath","filePath","content","code","secretId","secretKey","envId"];return function e(n){if(Array.isArray(n))return n.map(e);if(n&&"object"==typeof n){const o={};for(const[r,a]of Object.entries(n)){const n=r.toLowerCase(),i=t.some(e=>n.includes(e));o[r]=i?"[REDACTED]":e(a)}return o}return n}(n)}},421:e=>{e.exports=i},422:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.warn=n.error=n.info=n.reportToolCall=n.reportToolkitLifecycle=n.telemetryReporter=n.StdioServerTransport=void 0,n.createCloudBaseMcpServer=x,n.getDefaultServer=function(){return x()};const o=t(619),r=t(622),a=t(936),i=t(628),s=t(279),c=t(97),l=t(848),d=t(215),p=t(556),u=t(461),g=t(862),m=t(363),f=t(319),b=t(760),h=t(684),y=["env","database","functions","hosting","storage","setup","interactive","rag","gateway","download","security-rule","invite-code"],v={env:{name:"env",register:r.registerEnvTools},database:{name:"database",register:i.registerDatabaseTools},functions:{name:"functions",register:a.registerFunctionTools},hosting:{name:"hosting",register:s.registerHostingTools},storage:{name:"storage",register:l.registerStorageTools},setup:{name:"setup",register:p.registerSetupTools},interactive:{name:"interactive",register:u.registerInteractiveTools},rag:{name:"rag",register:d.registerRagTools},download:{name:"download",register:c.registerDownloadTools},gateway:{name:"gateway",register:f.registerGatewayTools},"security-rule":{name:"security-rule",register:g.registerSecurityRuleTools},"invite-code":{name:"invite-code",register:b.registerInviteCodeTools}};function x(e){const{name:n="cloudbase-mcp",version:t="1.0.0",enableTelemetry:r=!0,cloudBaseOptions:a,cloudMode:i=!1,ide:s}=e??{};i&&(0,h.enableCloudMode)();const c=new o.McpServer({name:n,version:t},{capabilities:{tools:{},..."CodeBuddy"===s?{logging:{}}:{}}});a&&(c.cloudBaseOptions=a),s&&(c.ide=s),r&&(0,m.wrapServerWithTelemetry)(c);const l=function(){const e=process.env.CLOUDBASE_MCP_PLUGINS_ENABLED,n=process.env.CLOUDBASE_MCP_PLUGINS_DISABLED;let t;if(t=e?e.split(",").map(e=>e.trim()):[...y],n){const e=n.split(",").map(e=>e.trim());t=t.filter(n=>!e.includes(n))}return t}();for(const e of l){const n=v[e];n&&n.register(c)}return c}var w=t(448);Object.defineProperty(n,"StdioServerTransport",{enumerable:!0,get:function(){return w.StdioServerTransport}});var I=t(880);Object.defineProperty(n,"telemetryReporter",{enumerable:!0,get:function(){return I.telemetryReporter}}),Object.defineProperty(n,"reportToolkitLifecycle",{enumerable:!0,get:function(){return I.reportToolkitLifecycle}}),Object.defineProperty(n,"reportToolCall",{enumerable:!0,get:function(){return I.reportToolCall}});var S=t(39);Object.defineProperty(n,"info",{enumerable:!0,get:function(){return S.info}}),Object.defineProperty(n,"error",{enumerable:!0,get:function(){return S.error}}),Object.defineProperty(n,"warn",{enumerable:!0,get:function(){return S.warn}})},431:function(e,n,t){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.envManager=void 0,n.getEnvId=async function(e){return e?.envId?((0,s.debug)("使用传入的 envId:",e.envId),e.envId):c.getEnvId()},n.resetCloudBaseManagerCache=function(){c.reset()},n.getCloudBaseManager=async function(e={}){const{requireEnvId:n=!0,cloudBaseOptions:t}=e;if(t)return(0,s.debug)("使用传入的 CloudBase 配置"),l(t);try{const e=await(0,r.getLoginState)(),{envId:t,secretId:o,secretKey:a,token:s}=e;let l;return n&&(l=await c.getEnvId()),new i.default({secretId:o,secretKey:a,envId:l||t,token:s,proxy:process.env.http_proxy})}catch(e){throw(0,s.error)("Failed to initialize CloudBase Manager:",e instanceof Error?e.message:String(e)),e}},n.createCloudBaseManagerWithOptions=l;const r=t(291),a=t(461),i=o(t(665)),s=t(39),c=new class{cachedEnvId=null;envIdPromise=null;reset(){this.cachedEnvId=null,this.envIdPromise=null,delete process.env.CLOUDBASE_ENV_ID}async getEnvId(){if(this.cachedEnvId)return(0,s.debug)("使用内存缓存的环境ID:",this.cachedEnvId),this.cachedEnvId;if(this.envIdPromise)return this.envIdPromise;this.envIdPromise=this._fetchEnvId();const e=new Promise((e,n)=>{const t=setTimeout(()=>{clearTimeout(t),n(new Error("EnvId 获取超时(600秒)"))},6e5)});try{return await Promise.race([this.envIdPromise,e])}catch(e){throw this.envIdPromise=null,e}}async _fetchEnvId(){try{if(process.env.CLOUDBASE_ENV_ID)return(0,s.debug)("使用进程环境变量的环境ID:",process.env.CLOUDBASE_ENV_ID),this.cachedEnvId=process.env.CLOUDBASE_ENV_ID,this.cachedEnvId;const e=await(0,a.loadEnvIdFromUserConfig)();if(e)return(0,s.debug)("从配置文件读取到环境ID:",e),this._setCachedEnvId(e),e;(0,s.debug)("未找到环境ID,尝试自动设置...");const n=await(0,a.autoSetupEnvironmentId)();if(!n)throw new Error("CloudBase Environment ID not found after auto setup. Please set CLOUDBASE_ENV_ID or run setupEnvironmentId tool.");return(0,s.debug)("自动设置环境ID成功:",n),this._setCachedEnvId(n),n}finally{this.envIdPromise=null}}_setCachedEnvId(e){this.cachedEnvId=e,process.env.CLOUDBASE_ENV_ID=e,(0,s.debug)("已更新环境ID缓存:",e)}async setEnvId(e){this._setCachedEnvId(e),await(0,a.saveEnvIdToUserConfig)(e),(0,s.debug)("手动设置环境ID并保存到文件:",e)}};function l(e){return(0,s.debug)("使用传入的 CloudBase 配置创建 manager:",e),new i.default({secretId:e.secretId,secretKey:e.secretKey,envId:e.envId,token:e.token,proxy:e.proxy||process.env.http_proxy,region:e.region,envType:e.envType})}n.envManager=c},448:e=>{e.exports=s},461:function(e,n,t){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.registerInteractiveTools=function(e){e.registerTool("interactiveDialog",{title:"交互式对话",description:"统一的交互式对话工具,支持需求澄清和任务确认,当需要和用户确认下一步的操作的时候,可以调用这个工具的clarify,如果有敏感的操作,需要用户确认,可以调用这个工具的confirm",inputSchema:{type:r.z.enum(["clarify","confirm"]).describe("交互类型: clarify=需求澄清, confirm=任务确认"),message:r.z.string().optional().describe("对话消息内容"),options:r.z.array(r.z.string()).optional().describe("可选的预设选项"),forceUpdate:r.z.boolean().optional().describe("是否强制更新环境ID配置"),risks:r.z.array(r.z.string()).optional().describe("操作风险提示")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!1,category:"interactive"}},async({type:n,message:t,options:o,forceUpdate:r=!1,risks:i})=>{try{switch(n){case"clarify":{if(!t)throw new Error("需求澄清必须提供message参数");const n=(0,a.getInteractiveServer)(e),r=await n.clarifyRequest(t,o);return r.cancelled?{content:[{type:"text",text:"用户取消了需求澄清"}]}:{content:[{type:"text",text:`📝 用户澄清反馈:\n${r.data}`}]}}case"confirm":{if(!t)throw new Error("任务确认必须提供message参数");let n=`🎯 即将执行任务:\n${t}`;i&&i.length>0&&(n+=`\n\n⚠️ 风险提示:\n${i.map(e=>`• ${e}`).join("\n")}`),n+="\n\n是否继续执行此任务?";const r=o||["确认执行","取消操作","需要修改任务"],s=(0,a.getInteractiveServer)(e),c=await s.clarifyRequest(n,r);return c.cancelled||c.data&&c.data.includes&&c.data.includes("取消")?{content:[{type:"text",text:"❌ 用户取消了任务执行"}]}:{content:[{type:"text",text:`✅ 用户确认: ${c.data}`}]}}default:throw new Error(`不支持的交互类型: ${n}`)}}catch(e){return{content:[{type:"text",text:`交互对话出错: ${e instanceof Error?e.message:String(e)}`}]}}})},n._promptAndSetEnvironmentId=u,n.saveEnvIdToUserConfig=m,n.loadEnvIdFromUserConfig=async function(){const e=g();try{const n=await l.default.readFile(e,"utf8"),t=JSON.parse(n).envId||null;return t?(0,c.debug)("从配置文件加载环境ID:",t):(0,c.warn)(`Config file ${e} found, but 'envId' property is missing or empty.`),t}catch(n){return"ENOENT"!==n.code?(0,c.warn)(`Failed to load envId from config file at ${e}. Error: ${n.message}`):(0,c.debug)(`Env config file not found at ${e}, which is expected if not set.`),null}},n.clearUserEnvId=async function(){const e=g();try{await l.default.unlink(e),(0,c.debug)("环境ID配置文件已删除:",e)}catch(n){(0,c.debug)("环境ID配置文件不存在或已清理:",e)}},n.autoSetupEnvironmentId=async function(){try{const{selectedEnvId:e,cancelled:n,error:t,noEnvs:o}=await u(!0,void 0);return t||o||n?((0,c.debug)("Auto setup environment ID interrupted or failed silently.",{error:t,noEnvs:o,cancelled:n}),null):((0,c.debug)("Auto setup environment ID successful.",{selectedEnvId:e}),e)}catch(e){return console.error("自动配置环境ID时出错:",e),null}};const r=t(971),a=t(341),i=t(431),s=t(291),c=t(39),l=o(t(932)),d=o(t(521)),p=o(t(116));async function u(e,n){const t=await(0,s.getLoginState)();if((0,c.debug)("loginState",t),!t)return(0,c.debug)("请先登录云开发账户"),{selectedEnvId:null,cancelled:!1,error:"请先登录云开发账户"};const o=await(0,i.getCloudBaseManager)({requireEnvId:!1});let r;try{r=await o.env.listEnvs()}catch(e){(0,c.debug)("获取环境ID时出错:",e)}(0,c.debug)("envResult",r);const{EnvList:l}=r||{};let d=null;if(e&&l&&1===l.length&&l[0].EnvId)d=l[0].EnvId;else{const e=(0,a.getInteractiveServer)(n),t=await e.collectEnvId(l||[]);if(t.cancelled)return{selectedEnvId:null,cancelled:!0};d=t.data}return d&&(await m(d),(0,c.debug)("环境ID已保存到配置文件:",d)),{selectedEnvId:d,cancelled:!1}}function g(){return d.default.join(p.default.homedir(),".cloudbase-env-id")}async function m(e){const n=g();try{const t={envId:e,updatedAt:(new Date).toISOString(),version:"1.0"};await l.default.writeFile(n,JSON.stringify(t,null,2),"utf8"),(0,c.debug)("环境ID配置已保存到文件:",n)}catch(e){throw console.error("保存环境ID配置失败:",e),e}}},521:e=>{e.exports=c},556:function(e,n,t){var o,r=this&&this.__createBinding||(Object.create?function(e,n,t,o){void 0===o&&(o=t);var r=Object.getOwnPropertyDescriptor(n,t);r&&!("get"in r?!n.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return n[t]}}),Object.defineProperty(e,o,r)}:function(e,n,t,o){void 0===o&&(o=t),e[o]=n[t]}),a=this&&this.__setModuleDefault||(Object.create?function(e,n){Object.defineProperty(e,"default",{enumerable:!0,value:n})}:function(e,n){e.default=n}),i=this&&this.__importStar||(o=function(e){return o=Object.getOwnPropertyNames||function(e){var n=[];for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[n.length]=t);return n},o(e)},function(e){if(e&&e.__esModule)return e;var n={};if(null!=e)for(var t=o(e),i=0;i<t.length;i++)"default"!==t[i]&&r(n,e,t[i]);return a(n,e),n}),s=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.registerSetupTools=function(e){e.registerTool("downloadTemplate",{title:"下载项目模板",description:"自动下载并部署CloudBase项目模板。\n\n支持的模板:\n- react: React + CloudBase 全栈应用模板\n- vue: Vue + CloudBase 全栈应用模板\n- miniprogram: 微信小程序 + 云开发模板 \n- uniapp: UniApp + CloudBase 跨端应用模板\n- rules: 只包含AI编辑器配置文件(包含Cursor、WindSurf、CodeBuddy等所有主流编辑器配置),适合在已有项目中补充AI编辑器配置\n\n支持的IDE类型:\n- all: 下载所有IDE配置(默认)\n- cursor: Cursor AI编辑器\n- windsurf: WindSurf AI编辑器\n- codebuddy: CodeBuddy AI编辑器\n- claude-code: Claude Code AI编辑器\n- cline: Cline AI编辑器\n- gemini-cli: Gemini CLI\n- opencode: OpenCode AI编辑器\n- qwen-code: 通义灵码\n- baidu-comate: 百度Comate\n- openai-codex-cli: OpenAI Codex CLI\n- augment-code: Augment Code\n- github-copilot: GitHub Copilot\n- roocode: RooCode AI编辑器\n- tongyi-lingma: 通义灵码\n- trae: Trae AI编辑器\n- vscode: Visual Studio Code\n\n特别说明:\n- rules 模板会自动包含当前 mcp 版本号信息(版本号:1.8.35),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)",inputSchema:{template:c.z.enum(["react","vue","miniprogram","uniapp","rules"]).describe("要下载的模板类型"),ide:c.z.enum(h).optional().default("all").describe("指定要下载的IDE类型,默认为all(下载所有IDE配置)"),overwrite:c.z.boolean().optional().describe("是否覆盖已存在的文件,默认为false(不覆盖)")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"setup"}},async({template:e,ide:n="all",overwrite:t=!1})=>{try{const o=function(e){if("all"===e)return{valid:!0};const n=h.filter(e=>"all"!==e);return n.includes(e)?{valid:!0}:{valid:!1,error:`不支持的IDE类型: ${e}`,supportedIDEs:n}}(n);if(!o.valid){const e=o.supportedIDEs?.join(", ")||"";return{content:[{type:"text",text:`❌ ${o.error}\n\n支持的IDE类型: ${e}`}]}}const r=b[e];if(!r)return{content:[{type:"text",text:`❌ 不支持的模板类型: ${e}`}]};const a=l.mkdtempSync(p.join(u.tmpdir(),"cloudbase-template-")),i=p.join(a,"template.zip"),s=p.join(a,"extracted");await w(r.url,i),await async function(e,n){try{await d.mkdir(n,{recursive:!0}),new f.default(e).extractAllTo(n,!0)}catch(e){throw new Error(`解压失败: ${e instanceof Error?e.message:"未知错误"}`)}}(i,s);const c=await I(s),g=function(e,n){if("all"===n)return e;const t=y[n];if(!t)return e;const o=v.filter(e=>!t.includes(e));return e.filter(e=>!o.includes(e))}(c,n),m=process.env.WORKSPACE_FOLDER_PATHS;let E=[],T=0,O=0,C=0;const k=[];if(m){let o=0;for(const n of g){const r=p.join(s,n),a=p.join(m,n),i=await S(r,a,t,e);i.copied?("overwritten"===i.action?O++:T++,E.push(a)):("protected"===i.action?o++:C++,E.push(r))}const a=x[n]||n;k.push(`✅ ${r.description} (${a}) 同步完成`),k.push(`📁 临时目录: ${s}`),k.push(`🔍 文件过滤: ${c.length} → ${g.length} 个文件`);const i=[];T>0&&i.push(`新建 ${T} 个文件`),O>0&&i.push(`覆盖 ${O} 个文件`),o>0&&i.push(`保护 ${o} 个文件(README.md)`),C>0&&i.push(`跳过 ${C} 个已存在文件`),i.length>0&&k.push(`📊 ${i.join(",")}`),(t||O>0||C>0)&&k.push("🔄 覆盖模式: "+(t?"启用":"禁用"))}else{E=g.map(e=>p.join(s,e));const e=x[n]||n;k.push(`✅ ${r.description} (${e}) 下载完成`),k.push(`📁 保存在临时目录: ${s}`),k.push(`🔍 文件过滤: ${c.length} → ${g.length} 个文件`),k.push("💡 如需将模板(包括隐藏文件)复制到项目目录,请确保复制时包含所有隐藏文件。")}return k.push(""),k.push("📋 文件列表:"),E.forEach(e=>{k.push(`${e}`)}),{content:[{type:"text",text:k.join("\n")}]}}catch(e){return{content:[{type:"text",text:`❌ 下载模板失败: ${e instanceof Error?e.message:"未知错误"}`}]}}})};const c=t(971),l=i(t(421)),d=i(t(932)),p=i(t(521)),u=i(t(116)),g=i(t(871)),m=i(t(782)),f=s(t(872)),b={react:{description:"React + CloudBase 全栈应用模板",url:"https://static.cloudbase.net/cloudbase-examples/web-cloudbase-react-template.zip"},vue:{description:"Vue + CloudBase 全栈应用模板",url:"https://static.cloudbase.net/cloudbase-examples/web-cloudbase-vue-template.zip"},miniprogram:{description:"微信小程序 + 云开发模板",url:"https://static.cloudbase.net/cloudbase-examples/miniprogram-cloudbase-miniprogram-template.zip"},uniapp:{description:"UniApp + CloudBase 跨端应用模板",url:"https://static.cloudbase.net/cloudbase-examples/universal-cloudbase-uniapp-template.zip"},rules:{description:"AI编辑器配置模板(包含所有主流编辑器配置)",url:"https://static.cloudbase.net/cloudbase-examples/web-cloudbase-project.zip"}},h=["all","cursor","windsurf","codebuddy","claude-code","cline","gemini-cli","opencode","qwen-code","baidu-comate","openai-codex-cli","augment-code","github-copilot","roocode","tongyi-lingma","trae","vscode"],y={cursor:[".cursor/rules/cloudbase-rules.mdc",".cursor/mcp.json"],windsurf:[".windsurf/rules/cloudbase-rules.md"],codebuddy:[".rules/cloudbase-rules.md"],"claude-code":["CLAUDE.md",".mcp.json",".claude/settings.local.json",".claude/commands/prototype.md",".claude/commands/spec.md",".claude/commands/no_spec.md"],cline:[".clinerules/cloudbase-rules.mdc"],"gemini-cli":[".gemini/GEMINI.md",".gemini/settings.json"],opencode:[".opencode.json"],"qwen-code":[".qwen/QWEN.md",".qwen/settings.json"],"baidu-comate":[".comate/rules/cloudbase-rules.mdr",".comate/rules/cloudbaase-rules.mdr",".comate/mcp.json"],"openai-codex-cli":[".codex/config.toml","AGENTS.md"],"augment-code":[".augment-guidelines"],"github-copilot":[".github/copilot-instructions.md"],roocode:[".roo/rules/cloudbaase-rules.md",".roo/mcp.json"],"tongyi-lingma":[".lingma/rules/cloudbaase-rules.md"],trae:[".trae/rules/cloudbase-rules.md"],vscode:[".vscode/mcp.json",".vscode/settings.json"]},v=Array.from(new Set(Object.values(y).flat()));y.all=v;const x={all:"所有IDE配置",cursor:"Cursor AI编辑器",windsurf:"WindSurf AI编辑器",codebuddy:"CodeBuddy AI编辑器","claude-code":"Claude Code AI编辑器",cline:"Cline AI编辑器","gemini-cli":"Gemini CLI",opencode:"OpenCode AI编辑器","qwen-code":"通义灵码","baidu-comate":"百度Comate","openai-codex-cli":"OpenAI Codex CLI","augment-code":"Augment Code","github-copilot":"GitHub Copilot",roocode:"RooCode AI编辑器","tongyi-lingma":"通义灵码",trae:"Trae AI编辑器",vscode:"Visual Studio Code"};async function w(e,n){return new Promise((t,o)=>{(e.startsWith("https:")?g:m).get(e,e=>{if(200===e.statusCode){const r=l.createWriteStream(n);e.pipe(r),r.on("finish",()=>{r.close(),t()}),r.on("error",o)}else 302===e.statusCode||301===e.statusCode?e.headers.location?w(e.headers.location,n).then(t).catch(o):o(new Error("重定向但没有location header")):o(new Error(`下载失败,状态码: ${e.statusCode}`))}).on("error",o)})}async function I(e,n=e){const t=[],o=await d.readdir(e,{withFileTypes:!0});for(const r of o){const o=p.join(e,r.name);if(r.isDirectory()){const e=await I(o,n);t.push(...e)}else t.push(p.relative(n,o))}return t}async function S(e,n,t=!1,o){try{const r=l.existsSync(n);return o&&function(e,n,t){const o="readme.md"===p.basename(n).toLowerCase(),r="rules"===e,a=l.existsSync(n);return o&&r&&a&&!t}(o,n,t)?{copied:!1,reason:"README.md 文件已存在,已保护",action:"protected"}:r&&!t?{copied:!1,reason:"文件已存在",action:"skipped"}:(await d.mkdir(p.dirname(n),{recursive:!0}),await d.copyFile(e,n),{copied:!0,action:r?"overwritten":"created"})}catch(e){return{copied:!1,reason:`复制失败: ${e instanceof Error?e.message:"未知错误"}`}}}},619:e=>{e.exports=l},622:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerEnvTools=function(e){const n=e.cloudBaseOptions,t=()=>(0,r.getCloudBaseManager)({cloudBaseOptions:n});e.registerTool?.("login",{title:"登录云开发",description:"登录云开发环境并选择要使用的环境",inputSchema:{forceUpdate:o.z.boolean().optional().describe("是否强制重新选择环境")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"env"}},async({forceUpdate:n=!1})=>{try{const{selectedEnvId:t,cancelled:o,error:r,noEnvs:a}=await(0,i._promptAndSetEnvironmentId)(n,e);if((0,s.debug)("login",{selectedEnvId:t,cancelled:o,error:r,noEnvs:a}),r)return{content:[{type:"text",text:r}]};if(a)return{content:[{type:"text",text:"当前账户下暂无可用的云开发环境,请先在腾讯云控制台创建环境 https://tcb.cloud.tencent.com/dev?from=AIToolkit"}]};if(o)return{content:[{type:"text",text:"用户取消了登录"}]};if(t)return{content:[{type:"text",text:`✅ 登录成功,当前环境: ${t}`}]};throw new Error("登录失败")}catch(e){return{content:[{type:"text",text:`登录失败: ${e instanceof Error?e.message:String(e)}`}]}}}),e.registerTool?.("logout",{title:"退出登录",description:"退出云开发环境",inputSchema:{confirm:o.z.literal("yes").describe("确认操作,默认传 yes")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1,category:"env"}},async()=>{try{return await(0,a.logout)(),await(0,i.clearUserEnvId)(),(0,r.resetCloudBaseManagerCache)(),{content:[{type:"text",text:"✅ 已退出登录"}]}}catch(e){return{content:[{type:"text",text:`退出失败: ${e instanceof Error?e.message:String(e)}`}]}}}),e.registerTool?.("envQuery",{title:"环境查询",description:"查询云开发环境相关信息,支持查询环境列表、当前环境信息和安全域名。(原工具名:listEnvs/getEnvInfo/getEnvAuthDomains,为兼容旧AI规则可继续使用这些名称)",inputSchema:{action:o.z.enum(["list","info","domains"]).describe("查询类型:list=环境列表,info=当前环境信息,domains=安全域名列表")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"env"}},async({action:e})=>{try{let o;switch(e){case"list":try{const e=await(0,r.getCloudBaseManager)({cloudBaseOptions:n,requireEnvId:!1});o=await e.env.listEnvs()}catch(e){return(0,s.debug)("获取环境列表时出错:",e),{content:[{type:"text",text:"当前账户下暂无可用的云开发环境,请先在腾讯云控制台创建环境 https://tcb.cloud.tencent.com/dev?from=AIToolkit \n错误信息:"+(e instanceof Error?e.message:String(e))}]}}break;case"info":const a=await t();o=await a.env.getEnvInfo();break;case"domains":const i=await t();o=await i.env.getEnvAuthDomains();break;default:throw new Error(`不支持的查询类型: ${e}`)}return{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}catch(e){return{content:[{type:"text",text:`环境查询失败: ${e instanceof Error?e.message:String(e)}`}]}}}),e.registerTool?.("envDomainManagement",{title:"环境域名管理",description:"管理云开发环境的安全域名,支持添加和删除操作。(原工具名:createEnvDomain/deleteEnvDomain,为兼容旧AI规则可继续使用这些名称)",inputSchema:{action:o.z.enum(["create","delete"]).describe("操作类型:create=添加域名,delete=删除域名"),domains:o.z.array(o.z.string()).describe("安全域名数组")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"env"}},async({action:e,domains:n})=>{try{const o=await t();let r;switch(e){case"create":r=await o.env.createEnvDomain(n);break;case"delete":r=await o.env.deleteEnvDomain(n);break;default:throw new Error(`不支持的操作类型: ${e}`)}return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}catch(e){return{content:[{type:"text",text:`域名管理操作失败: ${e instanceof Error?e.message:String(e)}`}]}}}),e.registerTool?.("updateEnvInfo",{title:"更新环境信息",description:"更新云开发环境信息",inputSchema:{alias:o.z.string().describe("环境别名")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"env"}},async({alias:e})=>{const n=await t(),o=await n.env.updateEnvInfo(e);return{content:[{type:"text",text:JSON.stringify(o,null,2)}]}})};const o=t(971),r=t(431),a=t(291),i=t(461),s=t(39)},628:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerDatabaseTools=function(e){const n=e.cloudBaseOptions,t=()=>(0,r.getCloudBaseManager)({cloudBaseOptions:n});e.registerTool?.("createCollection",{title:"创建数据库集合",description:"创建一个新的云开发数据库集合",inputSchema:{collectionName:o.z.string().describe("云开发数据库集合名称")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"database"}},async({collectionName:e})=>{try{const n=await t(),o=await n.database.createCollection(e);return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:o.RequestId,message:"云开发数据库集合创建成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"云开发数据库集合创建失败"},null,2)}]}}}),e.registerTool?.("collectionQuery",{title:"集合查询",description:"数据库集合的查询操作,支持检查存在性、查看详情和列表查询。(原工具名:checkCollectionExists/describeCollection/listCollections,为兼容旧AI规则可继续使用这些名称)",inputSchema:{action:o.z.enum(["check","describe","list"]).describe("操作类型:check=检查是否存在,describe=查看详情,list=列表查询"),collectionName:o.z.string().optional().describe("集合名称(check、describe操作时必填)"),limit:o.z.number().optional().describe("返回数量限制(list操作时可选)"),offset:o.z.number().optional().describe("偏移量(list操作时可选)")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"database"}},async({action:e,collectionName:n,limit:o,offset:r})=>{try{const a=await t();let i;switch(e){case"check":if(!n)throw new Error("检查集合时必须提供 collectionName");return i=await a.database.checkCollectionExists(n),{content:[{type:"text",text:JSON.stringify({success:!0,exists:i.Exists,requestId:i.RequestId,message:i.Exists?"云开发数据库集合已存在":"云开发数据库集合不存在"},null,2)}]};case"describe":if(!n)throw new Error("查看集合详情时必须提供 collectionName");return i=await a.database.describeCollection(n),{content:[{type:"text",text:JSON.stringify({success:!0,requestId:i.RequestId,indexNum:i.IndexNum,indexes:i.Indexes,message:"获取云开发数据库集合信息成功"},null,2)}]};case"list":return i=await a.database.listCollections({MgoOffset:r,MgoLimit:o}),{content:[{type:"text",text:JSON.stringify({success:!0,requestId:i.RequestId,collections:i.Collections,pager:i.Pager,message:"获取云开发数据库集合列表成功"},null,2)}]};default:throw new Error(`不支持的操作类型: ${e}`)}}catch(n){return{content:[{type:"text",text:JSON.stringify({success:!1,error:n.message,message:`集合查询失败: ${e}`},null,2)}]}}}),e.registerTool?.("updateCollection",{title:"更新数据库集合",description:"更新云开发数据库集合配置(创建或删除索引)",inputSchema:{collectionName:o.z.string().describe("云开发数据库集合名称"),options:o.z.object({CreateIndexes:o.z.array(o.z.object({IndexName:o.z.string(),MgoKeySchema:o.z.object({MgoIsUnique:o.z.boolean(),MgoIndexKeys:o.z.array(o.z.object({Name:o.z.string(),Direction:o.z.string()}))})})).optional(),DropIndexes:o.z.array(o.z.object({IndexName:o.z.string()})).optional()}).describe("更新选项,支持创建和删除索引")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"database"}},async({collectionName:e,options:n})=>{try{const o=await t(),r=await o.database.updateCollection(e,n);return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:r.RequestId,message:"云开发数据库集合更新成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"云开发数据库集合更新失败"},null,2)}]}}}),e.registerTool?.("checkIndexExists",{title:"检查索引是否存在",description:"检查索引是否存在",inputSchema:{collectionName:o.z.string().describe("云开发数据库集合名称"),indexName:o.z.string().describe("索引名称")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"database"}},async({collectionName:e,indexName:n})=>{try{const o=await t(),r=await o.database.checkIndexExists(e,n);return{content:[{type:"text",text:JSON.stringify({success:!0,exists:r.Exists,requestId:r.RequestId,message:r.Exists?"索引已存在":"索引不存在"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"检查索引失败"},null,2)}]}}}),e.registerTool?.("insertDocuments",{title:"插入文档",description:"向云开发数据库集合中插入一个或多个文档(支持对象数组)",inputSchema:{collectionName:o.z.string().describe("云开发数据库集合名称"),documents:o.z.array(o.z.object({}).passthrough()).describe("要插入的文档对象数组,每个文档都是对象")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"database"}},async({collectionName:e,documents:n})=>{try{const o=await t(),r=await c(t),a=n.map(e=>JSON.stringify(e)),i=await o.commonService("flexdb").call({Action:"PutItem",Param:{TableName:e,MgoDocs:a,Tag:r}});return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:i.RequestId,insertedIds:i.InsertedIds,message:"文档插入成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"文档插入失败"},null,2)}]}}}),e.registerTool?.("queryDocuments",{title:"查询文档",description:"查询云开发数据库集合中的文档(支持对象参数)",inputSchema:{collectionName:o.z.string().describe("云开发数据库集合名称"),query:o.z.union([o.z.object({}).passthrough(),o.z.string()]).optional().describe("查询条件(对象或字符串,推荐对象)"),projection:o.z.union([o.z.object({}).passthrough(),o.z.string()]).optional().describe("返回字段投影(对象或字符串,推荐对象)"),sort:o.z.union([o.z.object({}).passthrough(),o.z.string()]).optional().describe("排序条件(对象或字符串,推荐对象)"),limit:o.z.number().optional().describe("返回数量限制"),offset:o.z.number().optional().describe("跳过的记录数")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"database"}},async({collectionName:e,query:n,projection:o,sort:r,limit:a,offset:i})=>{try{const s=await t(),l=await c(t),d=e=>"object"==typeof e&&null!==e?JSON.stringify(e):e,p=await s.commonService("flexdb").call({Action:"Query",Param:{TableName:e,MgoQuery:d(n),MgoProjection:d(o),MgoSort:d(r),MgoLimit:a??100,MgoOffset:i,Tag:l}});return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:p.RequestId,data:p.Data,pager:p.Pager,message:"文档查询成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"文档查询失败"},null,2)}]}}}),e.registerTool?.("updateDocuments",{title:"更新文档",description:"更新云开发数据库集合中的文档(支持对象参数)",inputSchema:{collectionName:o.z.string().describe("云开发数据库集合名称"),query:o.z.union([o.z.object({}).passthrough(),o.z.string()]).describe("查询条件(对象或字符串,推荐对象)"),update:o.z.union([o.z.object({}).passthrough(),o.z.string()]).describe("更新内容(对象或字符串,推荐对象)"),isMulti:o.z.boolean().optional().describe("是否更新多条记录"),upsert:o.z.boolean().optional().describe("是否在不存在时插入")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"database"}},async({collectionName:e,query:n,update:o,isMulti:r,upsert:a})=>{try{const i=await t(),s=await c(t),l=e=>"object"==typeof e&&null!==e?JSON.stringify(e):e,d=await i.commonService("flexdb").call({Action:"UpdateItem",Param:{TableName:e,MgoQuery:l(n),MgoUpdate:l(o),MgoIsMulti:r,MgoUpsert:a,Tag:s}});return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:d.RequestId,modifiedCount:d.ModifiedNum,matchedCount:d.MatchedNum,upsertedId:d.UpsertedId,message:"文档更新成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"文档更新失败"},null,2)}]}}}),e.registerTool?.("deleteDocuments",{title:"删除文档",description:"删除云开发数据库集合中的文档(支持对象参数)",inputSchema:{collectionName:o.z.string().describe("云开发数据库集合名称"),query:o.z.union([o.z.object({}).passthrough(),o.z.string()]).describe("查询条件(对象或字符串,推荐对象)"),isMulti:o.z.boolean().optional().describe("是否删除多条记录")},annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!0,openWorldHint:!0,category:"database"}},async({collectionName:e,query:n,isMulti:o})=>{try{const r=await t(),a=await c(t),i=e=>"object"==typeof e&&null!==e?JSON.stringify(e):e,s=await r.commonService("flexdb").call({Action:"DeleteItem",Param:{TableName:e,MgoQuery:i(n),MgoIsMulti:o,Tag:a}});return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:s.RequestId,deleted:s.Deleted,message:"文档删除成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"文档删除失败"},null,2)}]}}}),e.registerTool?.("manageDataModel",{title:"数据模型管理",description:"数据模型查询工具,支持查询和列表数据模型(只读操作)。list操作返回基础信息(不含Schema),get操作返回详细信息(含简化的Schema,包括字段列表、格式、关联关系等),docs操作生成SDK使用文档",inputSchema:{action:o.z.enum(["get","list","docs"]).describe("操作类型:get=查询单个模型(含Schema字段列表、格式、关联关系),list=获取模型列表(不含Schema),docs=生成SDK使用文档"),name:o.z.string().optional().describe("模型名称(get操作时必填)"),names:o.z.array(o.z.string()).optional().describe("模型名称数组(list操作时可选,用于过滤)")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"database"}},async({action:e,name:o,names:a})=>{try{const s=await t();let c,d=await(0,r.getEnvId)(n);switch(e){case"get":if(!o)throw new Error("获取数据模型需要提供模型名称");try{c=await s.commonService("lowcode").call({Action:"DescribeBasicDataSource",Param:{EnvId:d,Name:o}});let e=null;if(c.Data.Schema)try{const n=JSON.parse(c.Data.Schema),t=n.properties||{},o=Object.keys(t).filter(e=>!t[e]["x-system"]).map(e=>l(t[e],e,n)),r=o.filter(e=>e.linkage).map(e=>({field:e.name,type:e.format,title:e.title,targetModel:e.linkage.parentDataSourceName,foreignKey:e.linkage.parentFieldKey,displayField:e.linkage.parentFieldTitle}));e={userFields:o,relations:r,totalFields:Object.keys(t).length,userFieldsCount:o.length}}catch(n){e={error:"Schema解析失败"}}let n=null;if(c.Data.Schema&&i&&e&&!e.error)try{const t=JSON.parse(c.Data.Schema),r={[o]:t};if(e.relations&&e.relations.length>0){const n=[...new Set(e.relations.map(e=>e.targetModel))];for(const e of n)try{const n=await s.commonService("lowcode").call({Action:"DescribeBasicDataSource",Param:{EnvId:d,Name:e}});n.Data&&n.Data.Schema&&(r[e]=JSON.parse(n.Data.Schema))}catch(n){console.warn(`获取关联模型 ${e} 的 schema 失败:`,n)}}n=i(r)}catch(e){console.warn("生成Mermaid图表失败:",e)}const t={DbInstanceType:c.Data.DbInstanceType,Title:c.Data.Title,Description:c.Data.Description,Name:c.Data.Name,UpdatedAt:c.Data.UpdatedAt,Schema:e,mermaid:n};return{content:[{type:"text",text:JSON.stringify({success:!0,action:"get",data:t,message:"获取数据模型成功"},null,2)}]}}catch(e){if("ResourceNotFound"===e.original?.Code)return{content:[{type:"text",text:JSON.stringify({success:!1,action:"get",error:"ResourceNotFound",message:`数据模型 ${o} 不存在`},null,2)}]};throw e}case"list":const n={EnvId:d,PageIndex:1,PageSize:1e3,QuerySystemModel:!0,QueryConnector:0};a&&a.length>0&&(n.DataSourceNames=a),c=await s.commonService("lowcode").call({Action:"DescribeDataSourceList",Param:n});const t=(c.Data?.Rows||[]).map(e=>({DbInstanceType:e.DbInstanceType,Title:e.Title,Description:e.Description,Name:e.Name,UpdatedAt:e.UpdatedAt}));return{content:[{type:"text",text:JSON.stringify({success:!0,action:"list",data:t,count:t.length,message:"获取数据模型列表成功"},null,2)}]};case"docs":if(!o)throw new Error("生成SDK文档需要提供模型名称");try{if(c=await s.commonService("lowcode").call({Action:"DescribeBasicDataSource",Param:{EnvId:d,Name:o}}),!c.Data)throw new Error(`数据模型 ${o} 不存在`);let e=[],n=[];if(c.Data.Schema)try{const t=JSON.parse(c.Data.Schema),o=t.properties||{};e=Object.keys(o).filter(e=>!o[e]["x-system"]).map(e=>l(o[e],e,t)),n=e.filter(e=>e.linkage).map(e=>({field:e.name,type:e.format,title:e.title,targetModel:e.linkage.parentDataSourceName,foreignKey:e.linkage.parentFieldKey,displayField:e.linkage.parentFieldTitle}))}catch(e){console.error("Schema解析失败",e)}const t=function(e,n,t,o){const r=t.filter(e=>!e.linkage),a=(t.filter(e=>e.required),t.filter(e=>"string"===e.type&&!e.linkage)),i=t.filter(e=>"number"===e.type),s=e=>{if(e.enum&&e.enum.length>0)return`"${e.enum[0]}"`;switch(e.type){case"string":return"email"===e.format?'"user@example.com"':"url"===e.format?'"https://example.com"':`"示例${e.title||e.name}"`;case"number":return"currency"===e.format?"99.99":"1";case"boolean":return void 0!==e.default?e.default:"true";case"array":return e.items?`[${s(e.items)}]`:"[]";case"object":return e.properties&&e.properties.length>0?`{${e.properties.slice(0,2).map(e=>`${e.name}: ${s(e)}`).join(", ")}}`:"{}";default:return`"${e.title||e.name}值"`}},c=r.map(e=>` ${e.name}: ${s(e)}, // ${e.description||e.title||e.name}`).join("\n"),l=r.slice(0,2).map(e=>` ${e.name}: ${s(e)}, // ${e.description||e.title||e.name}`).join("\n"),d=a[0]||r[0],p=d?` ${d.name}: {\n $eq: ${s(d)}, // 根据${d.description||d.title||d.name}查询\n },`:' _id: {\n $eq: "记录ID", // 根据ID查询\n },';return`# 数据模型 ${n} (${e}) SDK 使用文档\n\n## 数据模型字段说明\n\n${t.map(e=>{let n=`- **${e.name}** (${e.type})`;return e.required&&(n+=" *必填*"),e.description&&(n+=`: ${e.description}`),e.format&&(n+=` [格式: ${e.format}]`),e.enum&&(n+=` [可选值: ${e.enum.join(", ")}]`),void 0!==e.default&&(n+=` [默认值: ${e.default}]`),"array"===e.type&&e.items&&(n+=`\n - 数组元素: ${e.items.type}`,e.items.description&&(n+=` (${e.items.description})`)),"object"===e.type&&e.properties&&e.properties.length>0&&(n+="\n - 对象属性:",e.properties.slice(0,3).forEach(e=>{n+=`\n - ${e.name} (${e.type})`}),e.properties.length>3&&(n+=`\n - ... 还有 ${e.properties.length-3} 个属性`)),n}).join("\n")}\n\n${o.length>0?`\n## 关联关系\n\n${o.map(e=>`- **${e.field}**: 关联到 ${e.targetModel} 模型的 ${e.foreignKey} 字段`).join("\n")}\n`:""}\n\n## 增删改查操作\n\n### 创建数据\n\n#### 创建单条数据 \`create\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.create({\n data: {\n${c}\n },\n});\n\n// 返回创建的记录 id\nconsole.log(data);\n// { id: "7d8ff72c665eb6c30243b6313aa8539e"}\n\`\`\`\n\n#### 创建多条数据 \`createMany\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.createMany({\n data: [\n {\n${c}\n },\n {\n${c}\n },\n ],\n});\n\n// 返回创建的记录 idList\nconsole.log(data);\n// {\n// "idList": [\n// "7d8ff72c665ebe5c02442a1a7b29685e",\n// "7d8ff72c665ebe5c02442a1b77feba4b"\n// ]\n// }\n\`\`\`\n\n### 更新数据\n\n#### 更新单条数据 \`update\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.update({\n data: {\n${l}\n },\n filter: {\n where: {\n _id: {\n $eq: "记录ID", // 推荐传入_id数据标识进行操作\n },\n },\n },\n});\n\n// 返回更新成功的条数\nconsole.log(data);\n// { count: 1}\n\`\`\`\n\n#### 创建或更新数据 \`upsert\`\n\n\`\`\`javascript\nconst recordData = {\n${c}\n _id: "指定ID",\n};\n\nconst { data } = await models.${e}.upsert({\n create: recordData,\n update: recordData,\n filter: {\n where: {\n _id: {\n $eq: recordData._id,\n },\n },\n },\n});\n\nconsole.log(data);\n// 新增时返回: { "count": 0, "id": "指定ID" }\n// 更新时返回: { "count": 1, "id": "" }\n\`\`\`\n\n#### 更新多条数据 \`updateMany\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.updateMany({\n data: {\n${l}\n },\n filter: {\n where: {\n${p}\n },\n },\n});\n\n// 返回更新成功的条数\nconsole.log(data);\n// { "count": 5 }\n\`\`\`\n\n### 删除数据\n\n#### 删除单条 \`delete\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.delete({\n filter: {\n where: {\n _id: {\n $eq: "记录ID", // 推荐传入_id数据标识进行操作\n },\n },\n },\n});\n\n// 返回删除成功的条数\nconsole.log(data);\n// { "count": 1 }\n\`\`\`\n\n#### 删除多条 \`deleteMany\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.deleteMany({\n filter: {\n where: {\n${p}\n },\n },\n});\n\n// 返回删除成功的条数\nconsole.log(data);\n// { "count": 3 }\n\`\`\`\n\n### 读取数据\n\n#### 读取单条数据 \`get\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.get({\n filter: {\n where: {\n _id: {\n $eq: "记录ID", // 推荐传入_id数据标识进行操作\n },\n },\n },\n});\n\n// 返回查询到的数据\nconsole.log(data);\n// {\n// "_id": "记录ID",\n${t.slice(0,5).map(e=>`// "${e.name}": ${s(e)}, // ${e.description||e.title||e.name}`).join("\n")}\n// "createdAt": 1717488585078,\n// "updatedAt": 1717490751944\n// }\n\`\`\`\n\n#### 读取多条数据 \`list\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.list({\n filter: {\n where: {\n${p}\n },\n },\n getCount: true, // 开启用来获取总数\n});\n\n// 返回查询到的数据列表 records 和 总数 total\nconsole.log(data);\n// {\n// "records": [\n// {\n// "_id": "记录ID1",\n${t.slice(0,3).map(e=>`// "${e.name}": ${s(e)}, // ${e.description||e.title||e.name}`).join("\n")}\n// "createdAt": 1717488585078,\n// "updatedAt": 1717490751944\n// },\n// // ... 更多记录\n// ],\n// "total": 10\n// }\n\`\`\`\n\n## 查询条件和排序\n\n### 常用查询条件\n\n\`\`\`javascript\n// 等于查询\nconst { data } = await models.${e}.list({\n filter: {\n where: {\n${d?` ${d.name}: {\n $eq: ${s(d)}, // ${d.description||d.title||d.name}等于指定值\n },`:' _id: { $eq: "记录ID" },'}\n },\n },\n});\n\n${a.length>0?`// 模糊查询\nconst { data: searchData } = await models.${e}.list({\n filter: {\n where: {\n ${a[0].name}: {\n $regex: "关键词", // ${a[0].description||a[0].title||a[0].name}包含关键词\n },\n },\n },\n});`:""}\n\n${i.length>0?`// 范围查询\nconst { data: rangeData } = await models.${e}.list({\n filter: {\n where: {\n ${i[0].name}: {\n $gte: 10, // ${i[0].description||i[0].title||i[0].name}大于等于10\n $lte: 100, // ${i[0].description||i[0].title||i[0].name}小于等于100\n },\n },\n },\n});`:""}\n\`\`\`\n\n### 排序\n\n\`\`\`javascript\nconst { data } = await models.${e}.list({\n filter: {\n where: {},\n orderBy: [\n {\n ${r[0]?`${r[0].name}: "asc", // 按${r[0].description||r[0].title||r[0].name}升序`:'_id: "desc", // 按ID降序'}\n },\n ],\n },\n});\n\`\`\`\n\n${o.length>0?`\n## 关联查询\n\n${o.map(n=>`\n### 查询关联的 ${n.targetModel} 数据\n\n\`\`\`javascript\nconst { data } = await models.${e}.list({\n filter: {\n where: {},\n include: {\n ${n.field}: true, // 包含关联的${n.targetModel}数据\n },\n },\n});\n\n// 返回的数据中会包含关联信息\nconsole.log(data.records[0].${n.field});\n\`\`\`\n`).join("")}\n`:""}\n\n## 更多操作\n\n更多高级查询、分页、聚合等操作,请参考:\n- [查询和筛选](https://docs.cloudbase.net/model/select)\n- [过滤和排序](https://docs.cloudbase.net/model/filter-and-sort)\n${o.length>0?"- [关联关系](https://docs.cloudbase.net/model/relation)":""}\n`}(c.Data.Name,c.Data.Title,e,n);return{content:[{type:"text",text:JSON.stringify({success:!0,action:"docs",modelName:o,modelTitle:c.Data.Title,docs:t,message:"SDK使用文档生成成功"},null,2)}]}}catch(e){if("ResourceNotFound"===e.original?.Code)return{content:[{type:"text",text:JSON.stringify({success:!1,action:"docs",error:"ResourceNotFound",message:`数据模型 ${o} 不存在`},null,2)}]};throw e}default:throw new Error(`不支持的操作类型: ${e}`)}}catch(n){return{content:[{type:"text",text:JSON.stringify({success:!1,action:e,error:n.message||n.original?.Message||"未知错误",code:n.original?.Code,message:"数据模型操作失败"},null,2)}]}}}),e.registerTool?.("modifyDataModel",{title:"修改数据模型",description:"基于Mermaid classDiagram创建或更新数据模型。支持创建新模型和更新现有模型结构。内置异步任务监控,自动轮询直至完成或超时。",inputSchema:{mermaidDiagram:o.z.string().describe('Mermaid classDiagram代码,描述数据模型结构。\n示例:\nclassDiagram\n class Student {\n name: string <<姓名>>\n age: number = 18 <<年龄>>\n gender: x-enum = "男" <<性别>>\n classId: string <<班级ID>>\n identityId: string <<身份ID>>\n course: Course[] <<课程>>\n required() ["name"]\n unique() ["name"]\n enum_gender() ["男", "女"]\n display_field() "name"\n }\n class Class {\n className: string <<班级名称>>\n display_field() "className"\n }\n class Course {\n name: string <<课程名称>>\n students: Student[] <<学生>>\n display_field() "name"\n }\n class Identity {\n number: string <<证件号码>>\n display_field() "number"\n }\n\n %% 关联关系\n Student "1" --\x3e "1" Identity : studentId\n Student "n" --\x3e "1" Class : student2class\n Student "n" --\x3e "m" Course : course\n Student "n" <-- "m" Course : students\n %% 类的命名\n note for Student "学生模型"\n note for Class "班级模型"\n note for Course "课程模型"\n note for Identity "身份模型"\n'),action:o.z.enum(["create","update"]).optional().default("create").describe("操作类型:create=创建新模型"),publish:o.z.boolean().optional().default(!1).describe("是否立即发布模型"),dbInstanceType:o.z.string().optional().default("MYSQL").describe("数据库实例类型")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"database"}},async({mermaidDiagram:e,action:o="create",publish:i=!1,dbInstanceType:c="MYSQL"})=>{try{const i=await t();let l=await(0,r.getEnvId)(n);const d=a(e);if(!d||0===Object.keys(d).length)return{content:[{type:"text",text:JSON.stringify({success:!1,error:"No schemas generated from Mermaid diagram",message:"无法从Mermaid图表生成数据模型Schema"},null,2)}]};const p=Object.entries(d).map(([e,n])=>({CreateSource:"cloudbase_create",Creator:null,DbLinkName:null,Description:n.description||`${n.title||e}数据模型`,Schema:JSON.stringify(s(n)),Title:n.title||e,Name:e,TableNameRule:"only_name"})),u=await i.commonService("lowcode").call({Action:"BatchCreateDataModelList",Param:{CreateDataModelList:p,Creator:null,DbInstanceType:c,EnvId:l}}),g=u.Data?.TaskId;if(!g)return{content:[{type:"text",text:JSON.stringify({success:!1,requestId:u.RequestId,error:"No TaskId returned",message:"创建任务失败,未返回任务ID"},null,2)}]};const m=3e4,f=Date.now();let b="init",h=null;for(;"init"===b&&Date.now()-f<m;)await new Promise(e=>setTimeout(e,2e3)),h=await i.commonService("lowcode").call({Action:"QueryModelTaskStatus",Param:{EnvId:l,TaskId:g}}),b=h.Data?.Status||"init";const y=Object.keys(d),v=h?.Data?.SuccessResourceIdList||[],x=y.filter(e=>!v.includes(e));return{content:[{type:"text",text:JSON.stringify({success:"success"===b,requestId:u.RequestId,taskId:g,models:y,successModels:v,failedModels:x,status:b,action:o,message:"success"===b?`数据模型${"create"===o?"创建":"更新"}成功,共处理${y.length}个模型`:"init"===b?`任务超时,任务ID: ${g},请稍后手动查询状态`:`数据模型${"create"===o?"创建":"更新"}失败`,taskResult:h?.Data},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message||e.original?.Message||"未知错误",code:e.original?.Code,message:"数据模型修改操作失败"},null,2)}]}}})};const o=t(971),r=t(431);let a=null,i=null;function s(e){return e.properties&&Object.values(e.properties).forEach(e=>{"x-enum"===e.format&&(e.enum=void 0),Array.isArray(e.default)&&"array"!==e.type&&e.default.length>0&&e.type===typeof e.default[0]&&(e.default=e.default[0])}),Object.assign({},{"x-kind":"tcb","x-defaultMethods":["wedaCreate","wedaDelete","wedaUpdate","wedaGetItem","wedaGetList","wedaGetRecords","wedaBatchCreate","wedaBatchUpdate","wedaBatchDelete"],"x-primary-column":"_id"},e)}async function c(e){const n=await e(),{EnvInfo:t}=await n.env.getEnvInfo();if(!t?.Databases?.[0]?.InstanceId)throw new Error("无法获取数据库实例ID");return t.Databases[0].InstanceId}function l(e,n,t,o=0,r=5){if(o>r)return{name:n,type:e.type,title:e.title||n,description:e.description||"",error:"递归深度超限"};const a={name:n,type:e.type,format:e.format,title:e.title||n,description:e.description||"",required:t.required?.includes(n)||!1,depth:o};if("array"===e.type&&e.items)try{a.items=l(e.items,`${n}_item`,t,o+1,r)}catch(e){a.items={name:`${n}_item`,type:"unknown",title:"数组元素",description:"数组元素结构解析失败",error:e.message}}if("object"===e.type&&e.properties)try{a.properties=Object.keys(e.properties).map(n=>l(e.properties[n],n,e,o+1,r))}catch(e){a.properties=[{name:"property",type:"unknown",title:"对象属性",description:"对象属性结构解析失败",error:e.message}]}return e["x-parent"]&&(a.linkage=e["x-parent"]),e.enum&&(a.enum=e.enum),void 0!==e.default&&(a.default=e.default),a}!function(){try{const e=t(191);a=e.mermaidToJsonSchema,i=e.jsonSchemaToMermaid}catch(e){console.warn("Failed to import mermaid transform functions from @cloudbase/cals:",e)}}()},665:e=>{e.exports=d},674:e=>{e.exports=p},684:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.isCloudMode=r,n.enableCloudMode=function(){process.env.CLOUDBASE_MCP_CLOUD_MODE="true",(0,o.debug)("Cloud mode enabled via API call")},n.getCloudModeStatus=function(){return process.argv.includes("--cloud-mode")?{enabled:!0,source:"CLI_ARG"}:"true"===process.env.CLOUDBASE_MCP_CLOUD_MODE?{enabled:!0,source:"CLOUDBASE_MCP_CLOUD_MODE"}:"true"===process.env.MCP_CLOUD_MODE?{enabled:!0,source:"MCP_CLOUD_MODE"}:{enabled:!1,source:null}},n.shouldRegisterTool=function(e){if(!r())return!0;const n=!["login","logout","uploadFile","uploadFiles","updateFunctionCode","createFunction","uploadMiniprogramCode","downloadTemplate","downloadRemoteFile","setupEnvironmentId","clearUserEnvId","interactiveDialog"].includes(e);return n||(0,o.debug)(`Cloud mode: skipping registration of incompatible tool: ${e}`),n};const o=t(39);function r(){const e=process.argv.includes("--cloud-mode"),n="true"===process.env.CLOUDBASE_MCP_CLOUD_MODE||"true"===process.env.MCP_CLOUD_MODE,t=e||n;return t&&(0,o.debug)("Cloud mode is enabled",{source:e?"CLI_ARG":"ENV_VAR",envVar:process.env.CLOUDBASE_MCP_CLOUD_MODE||process.env.MCP_CLOUD_MODE}),t}},760:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerInviteCodeTools=function(e){const n=e.cloudBaseOptions;e.registerTool?.("activateInviteCode",{title:"激活邀请码",description:"云开发 AI编程激励计划,通过邀请码激活用户激励。",inputSchema:{InviteCode:o.z.string().describe("待激活的邀请码")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"invite-code"}},async({InviteCode:e})=>{if(!e)return{content:[{type:"text",text:JSON.stringify({ErrorCode:"MissingParameter",ErrorMsg:"邀请码为必填项",RequestId:""},null,2)}]};try{const t=await(0,r.getCloudBaseManager)({cloudBaseOptions:n}),o=await(0,r.getEnvId)(n),a=await t.commonService().call({Action:"ActivateInviteCode",Param:{InviteCode:e,EnvId:o}});return{content:[{type:"text",text:JSON.stringify({ErrorCode:a?.ErrorCode||"",ErrorMsg:a?.ErrorMsg||"",RequestId:a?.RequestId||""},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({ErrorCode:e.code||"Exception",ErrorMsg:"激活失败:"+e.message,RequestId:e.RequestId||""},null,2)}]}}})};const o=t(971),r=t(431)},782:e=>{e.exports=u},793:e=>{e.exports=g},823:e=>{e.exports=m},848:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerStorageTools=function(e){const n=e.cloudBaseOptions;e.registerTool("uploadFile",{title:"上传文件到云存储",description:"上传文件到云存储(区别于静态网站托管,云存储更适合存储业务数据文件)",inputSchema:{localPath:o.z.string().describe("本地文件路径,建议传入绝对路径,例如 /tmp/files/data.txt"),cloudPath:o.z.string().describe("云端文件路径,例如 files/data.txt")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"storage"}},async({localPath:e,cloudPath:t})=>{const o=await(0,r.getCloudBaseManager)({cloudBaseOptions:n});await o.storage.uploadFile({localPath:e,cloudPath:t,onProgress:e=>{console.log("Upload progress:",e)}});const a=await o.storage.getTemporaryUrl([{cloudPath:t,maxAge:3600}]);return{content:[{type:"text",text:JSON.stringify({message:"文件上传成功",cloudPath:t,temporaryUrl:a[0]?.url||"",expireTime:"1小时"},null,2)}]}})};const o=t(971),r=t(431)},862:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerSecurityRuleTools=function(e){const n=e.cloudBaseOptions,t=()=>(0,r.getCloudBaseManager)({cloudBaseOptions:n});e.registerTool?.("readSecurityRule",{title:"读取安全规则",description:"读取指定资源(数据库集合、云函数、存储桶)的安全规则和权限类别。\n\n参数说明:\n- resourceType: 资源类型(database/function/storage)\n- resourceId: 资源唯一标识(集合名/函数名/桶名)",inputSchema:{resourceType:o.z.enum(["database","function","storage"]).describe("资源类型:database=数据库集合,function=云函数,storage=存储桶"),resourceId:o.z.string().describe("资源唯一标识。数据库为集合名,云函数为函数名,存储为桶名。")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"security-rule"}},async({resourceType:e,resourceId:o})=>{const a=await(0,r.getEnvId)(n);try{const n=await t();let r;if("database"===e)r=await n.commonService().call({Action:"DescribeSafeRule",Param:{CollectionName:o,EnvId:a}});else if("function"===e)r=await n.commonService().call({Action:"DescribeSecurityRule",Param:{ResourceType:"FUNCTION",EnvId:a}});else{if("storage"!==e)throw new Error(`不支持的资源类型: ${e}`);r=await n.commonService().call({Action:"DescribeStorageSafeRule",Param:{Bucket:o,EnvId:a}})}return{content:[{type:"text",text:JSON.stringify({success:!0,aclTag:r.AclTag,rule:r.Rule??null,raw:r,message:"安全规则读取成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"安全规则读取失败"},null,2)}]}}}),e.registerTool?.("writeSecurityRule",{title:"写入安全规则",description:"设置指定资源(数据库集合、云函数、存储桶)的安全规则。\n\n参数说明:\n- resourceType: 资源类型(database/function/storage)\n- resourceId: 资源唯一标识(集合名/函数名/桶名)\n- aclTag: 权限类别(READONLY/PRIVATE/ADMINWRITE/ADMINONLY/CUSTOM)\n- rule: 自定义安全规则内容,仅当 aclTag 为 CUSTOM 时必填",inputSchema:{resourceType:o.z.enum(["database","function","storage"]).describe("资源类型:database=数据库集合,function=云函数,storage=存储桶"),resourceId:o.z.string().describe("资源唯一标识。数据库为集合名,云函数为函数名,存储为桶名。"),aclTag:o.z.enum(["READONLY","PRIVATE","ADMINWRITE","ADMINONLY","CUSTOM"]).describe("权限类别"),rule:o.z.string().optional().describe("自定义安全规则内容,仅当 aclTag 为 CUSTOM 时必填")},annotations:{readOnlyHint:!1,openWorldHint:!0,category:"security-rule"}},async({resourceType:e,resourceId:o,aclTag:a,rule:i})=>{try{const s=await t(),c=await(0,r.getEnvId)(n);let l;if("database"===e)if("CUSTOM"===a){if(!i)throw new Error("数据库自定义安全规则(CUSTOM)必须提供 rule 字段");l=await s.commonService().call({Action:"ModifySafeRule",Param:{CollectionName:o,EnvId:c,AclTag:a,Rule:i}})}else l=await s.commonService().call({Action:"ModifyDatabaseACL",Param:{CollectionName:o,EnvId:c,AclTag:a}});else if("function"===e){if("CUSTOM"!==a)throw new Error("云函数安全规则仅支持 CUSTOM 权限类别");if(!i)throw new Error("云函数自定义安全规则(CUSTOM)必须提供 rule 字段");l=await s.commonService().call({Action:"ModifySecurityRule",Param:{AclTag:a,EnvId:c,ResourceType:"FUNCTION",Rule:i}})}else{if("storage"!==e)throw new Error(`不支持的资源类型: ${e}`);if("CUSTOM"===a){if(!i)throw new Error("存储自定义安全规则(CUSTOM)必须提供 rule 字段");l=await s.commonService().call({Action:"ModifyStorageSafeRule",Param:{Bucket:o,EnvId:c,AclTag:a,Rule:i}})}else l=await s.commonService().call({Action:"ModifyStorageSafeRule",Param:{Bucket:o,EnvId:c,AclTag:a}})}return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:l.RequestId,raw:l,message:"安全规则写入成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"安全规则写入失败"},null,2)}]}}})};const o=t(971),r=t(431)},871:e=>{e.exports=f},872:e=>{e.exports=b},880:function(e,n,t){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.reportToolkitLifecycle=n.reportToolCall=n.telemetryReporter=void 0;const r=o(t(116)),a=o(t(823)),i=o(t(871)),s=o(t(782)),c=t(39),l=t(461);n.telemetryReporter=new class{deviceId="";userAgent="";additionalParams={};enabled;constructor(){this.enabled="true"!==process.env.CLOUDBASE_MCP_TELEMETRY_DISABLED,this.enabled?(this.deviceId=this.getDeviceId(),this.userAgent=this.getUserAgent().userAgent,process.env.INTEGRATION_IDE&&(this.addAdditionalParams({ide:process.env.INTEGRATION_IDE}),(0,c.debug)("检测到 IDE 集成环境",{ide:process.env.INTEGRATION_IDE})),(0,c.debug)("数据上报已初始化",{enabled:this.enabled,deviceId:this.deviceId.substring(0,8)+"...",ide:process.env.INTEGRATION_IDE||"none"})):(0,c.debug)("数据上报已被环境变量禁用")}getUserAgent(){const e=r.default.type(),n=r.default.release(),t=process.version,o=r.default.arch(),a=process.env.npm_package_version||"1.8.35";return{userAgent:`${e} ${n} ${o} ${t} CloudBase-MCP/${a}`,deviceId:this.deviceId,osType:e,osRelease:n,nodeVersion:t,arch:o,mcpVersion:a}}getDeviceId(){try{const e=[r.default.hostname(),r.default.cpus().map(e=>e.model).join(","),Object.values(r.default.networkInterfaces()).reduce((e,n)=>e.concat(n||[]),[]).filter(e=>e&&!e.internal&&e.mac).map(e=>e.mac).join(",")].join("|");return a.default.createHash("sha256").update(e).digest("hex").substring(0,32)}catch(e){return a.default.randomBytes(16).toString("hex")}}async postFetch(e,n){return new Promise((t,o)=>{const r=JSON.stringify(n),a=new URL(e),c="https:"===a.protocol?i.default:s.default,l={hostname:a.hostname,port:a.port,path:a.pathname+a.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(r),"User-Agent":this.userAgent},timeout:5e3};"https:"===a.protocol&&(l.minVersion="TLSv1.2",l.maxVersion="TLSv1.2");const d=c.request(l,e=>{let n="";e.on("data",e=>{n+=e}),e.on("end",()=>{e.statusCode&&e.statusCode>=200&&e.statusCode<300?t():o(new Error(`HTTP ${e.statusCode}: ${n}`))})});d.on("error",o),d.on("timeout",()=>{d.destroy(),o(new Error("Request timeout"))}),d.write(r),d.end()})}async report(e,n={}){if(this.enabled)try{const t=Date.now(),o={appVersion:"",sdkId:"js",sdkVersion:"4.5.14-web",mainAppKey:"0WEB0AD0GM4PUUU1",platformId:3,common:{A2:this.deviceId,A101:this.userAgent,from:"cloudbase-mcp",xDeployEnv:"production",...this.additionalParams},events:[{eventCode:e,eventTime:String(t),mapValue:{...this.additionalParams,...n}}]};await this.postFetch("https://otheve.beacon.qq.com/analytics/v2_upload",o),(0,c.debug)("数据上报成功",{eventCode:e,deviceId:this.deviceId.substring(0,8)+"..."})}catch(n){(0,c.debug)("数据上报失败",{eventCode:e,error:n instanceof Error?n.message:String(n)})}}addAdditionalParams(e){this.additionalParams={...this.additionalParams,...e}}isEnabled(){return this.enabled}},n.reportToolCall=async e=>{const{nodeVersion:t,osType:o,osRelease:r,arch:a,mcpVersion:i}=n.telemetryReporter.getUserAgent();let s;try{s=e.cloudBaseOptions?.envId||process.env.CLOUDBASE_ENV_ID||await(0,l.loadEnvIdFromUserConfig)()||"unknown"}catch(e){(0,c.debug)("获取环境ID失败,遥测数据将使用 unknown",e),s="unknown"}const d={toolName:e.toolName,success:e.success?"true":"false",duration:e.duration,error:e.error?e.error.substring(0,200):void 0,envId:s||"unknown",nodeVersion:t,osType:o,osRelease:r,arch:a,mcpVersion:i};if(void 0!==e.inputParams)try{const n=JSON.stringify(e.inputParams);d.inputParams=n.length>500?n.substring(0,500)+"...":n}catch(n){d.inputParams=`[${typeof e.inputParams}]`}e.ide&&(d.ide=e.ide),n.telemetryReporter.report("toolkit_tool_call",d)},n.reportToolkitLifecycle=async e=>{const{nodeVersion:t,osType:o,osRelease:r,arch:a,mcpVersion:i}=n.telemetryReporter.getUserAgent();let s;try{s=e.cloudBaseOptions?.envId||process.env.CLOUDBASE_ENV_ID||await(0,l.loadEnvIdFromUserConfig)()||"unknown"}catch(e){(0,c.debug)("获取环境ID失败,遥测数据将使用 unknown",e),s="unknown"}const d={event:e.event,duration:e.duration,exitCode:e.exitCode,error:e.error?e.error.substring(0,200):void 0,envId:s||"unknown",nodeVersion:t,osType:o,osRelease:r,arch:a,mcpVersion:i};e.ide&&(d.ide=e.ide),n.telemetryReporter.report("toolkit_lifecycle",d)}},887:e=>{e.exports=h},932:e=>{e.exports=y},936:function(e,n,t){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.TRIGGER_CONFIG_EXAMPLES=n.SUPPORTED_TRIGGER_TYPES=n.DEFAULT_NODEJS_RUNTIME=n.SUPPORTED_NODEJS_RUNTIMES=void 0,n.registerFunctionTools=function(e){const t=e.cloudBaseOptions,o=()=>(0,a.getCloudBaseManager)({cloudBaseOptions:t});e.registerTool?.("getFunctionList",{title:"查询云函数列表",description:"获取云函数列表",inputSchema:{limit:r.z.number().optional().describe("范围"),offset:r.z.number().optional().describe("偏移")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"functions"}},async({limit:e,offset:n})=>{const t=await o(),r=await t.functions.getFunctionList(e,n);return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}),e.registerTool("createFunction",{title:"创建云函数",description:"创建云函数",inputSchema:{func:r.z.object({name:r.z.string().describe("函数名称"),timeout:r.z.number().optional().describe("函数超时时间"),envVariables:r.z.record(r.z.string()).optional().describe("环境变量"),vpc:r.z.object({vpcId:r.z.string(),subnetId:r.z.string()}).optional().describe("私有网络配置"),runtime:r.z.string().optional().describe("运行时环境,建议指定为 'Nodejs18.15',其他可选值:"+n.SUPPORTED_NODEJS_RUNTIMES.join(",")),triggers:r.z.array(r.z.object({name:r.z.string().describe("Trigger name"),type:r.z.enum(n.SUPPORTED_TRIGGER_TYPES).describe("Trigger type, currently only supports 'timer'"),config:r.z.string().describe("Trigger configuration. For timer triggers, use cron expression format: second minute hour day month week year. IMPORTANT: Must include exactly 7 fields (second minute hour day month week year). Examples: '0 0 2 1 * * *' (monthly), '0 30 9 * * * *' (daily at 9:30 AM)")})).optional().describe("Trigger configuration array"),handler:r.z.string().optional().describe("函数入口"),ignore:r.z.union([r.z.string(),r.z.array(r.z.string())]).optional().describe("忽略文件"),isWaitInstall:r.z.boolean().optional().describe("是否等待依赖安装"),layers:r.z.array(r.z.object({name:r.z.string(),version:r.z.number()})).optional().describe("Layer配置")}).describe("函数配置"),functionRootPath:r.z.string().optional().describe("函数根目录(云函数目录的父目录),这里需要传操作系统上文件的绝对路径,注意:不要包含函数名本身,例如函数名为 'hello',应传入 '/path/to/cloudfunctions',而不是 '/path/to/cloudfunctions/hello'"),force:r.z.boolean().describe("是否覆盖")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"functions"}},async({func:e,functionRootPath:t,force:r})=>{if(e.runtime){const t=e.runtime.replace(/\s+/g,"");n.SUPPORTED_NODEJS_RUNTIMES.includes(t)?e.runtime=t:e.runtime.includes(" ")&&(console.warn(`检测到 runtime 参数包含空格: "${e.runtime}",已自动移除空格`),e.runtime=t)}else e.runtime=n.DEFAULT_NODEJS_RUNTIME;if(!n.SUPPORTED_NODEJS_RUNTIMES.includes(e.runtime))throw new Error(`不支持的运行时环境: "${e.runtime}"。支持的值:${n.SUPPORTED_NODEJS_RUNTIMES.join(", ")}`);e.installDependency=!0;const a=s(t,e.name),i=await o(),c=await i.functions.createFunction({func:e,functionRootPath:a,force:r});return{content:[{type:"text",text:JSON.stringify(c,null,2)}]}}),e.registerTool("updateFunctionCode",{title:"更新云函数代码",description:"更新函数代码",inputSchema:{name:r.z.string().describe("函数名称"),functionRootPath:r.z.string().describe("函数根目录(云函数目录的父目录),这里需要传操作系统上文件的绝对路径")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"functions"}},async({name:e,functionRootPath:t,zipFile:r,handler:a,runtime:i})=>{i||(i=n.DEFAULT_NODEJS_RUNTIME);const c={func:{name:e,installDependency:!0,...a&&{handler:a},...i&&{runtime:i}},functionRootPath:s(t,e)};r&&(c.zipFile=r);const l=await o(),d=await l.functions.updateFunctionCode(c);return{content:[{type:"text",text:JSON.stringify(d,null,2)}]}}),e.registerTool?.("updateFunctionConfig",{title:"更新云函数配置",description:"更新云函数配置",inputSchema:{funcParam:r.z.object({name:r.z.string().describe("函数名称"),timeout:r.z.number().optional().describe("超时时间"),envVariables:r.z.record(r.z.string()).optional().describe("环境变量"),vpc:r.z.object({vpcId:r.z.string(),subnetId:r.z.string()}).optional().describe("VPC配置")}).describe("函数配置")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"functions"}},async({funcParam:e})=>{const n=await o(),t=await n.functions.updateFunctionConfig(e);return{content:[{type:"text",text:JSON.stringify(t,null,2)}]}}),e.registerTool?.("getFunctionDetail",{title:"获取云函数详情",description:"获取云函数详情",inputSchema:{name:r.z.string().describe("函数名称"),codeSecret:r.z.string().optional().describe("代码保护密钥")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"functions"}},async({name:e,codeSecret:n})=>{const t=await o(),r=await t.functions.getFunctionDetail(e,n);return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}),e.registerTool?.("invokeFunction",{title:"调用云函数",description:"调用云函数",inputSchema:{name:r.z.string().describe("函数名称"),params:r.z.record(r.z.any()).optional().describe("调用参数")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"functions"}},async({name:e,params:n})=>{const t=await o(),r=await t.functions.invokeFunction(e,n);return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}),e.registerTool?.("getFunctionLogs",{title:"获取云函数日志(新版)",description:"获取云函数日志基础信息(LogList),如需日志详情请用 RequestId 调用 getFunctionLogDetail 工具。此接口基于 manger-node 4.4.0+ 的 getFunctionLogsV2 实现,不返回具体日志内容。参数 offset+limit 不得大于 10000,startTime/endTime 间隔不得超过一天。",inputSchema:{name:r.z.string().describe("函数名称"),offset:r.z.number().optional().describe("数据的偏移量,Offset+Limit 不能大于 10000"),limit:r.z.number().optional().describe("返回数据的长度,Offset+Limit 不能大于 10000"),startTime:r.z.string().optional().describe("查询的具体日期,例如:2017-05-16 20:00:00,只能与 EndTime 相差一天之内"),endTime:r.z.string().optional().describe("查询的具体日期,例如:2017-05-16 20:59:59,只能与 StartTime 相差一天之内"),requestId:r.z.string().optional().describe("执行该函数对应的 requestId"),qualifier:r.z.string().optional().describe("函数版本,默认为 $LATEST")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"functions"}},async({name:e,offset:n,limit:t,startTime:r,endTime:a,requestId:i,qualifier:s})=>{if((n||0)+(t||0)>1e4)throw new Error("offset+limit 不能大于 10000");if(r&&a){const e=new Date(r).getTime();if(new Date(a).getTime()-e>864e5)throw new Error("startTime 和 endTime 间隔不能超过一天")}const c=await o(),l=await c.functions.getFunctionLogsV2({name:e,offset:n,limit:t,startTime:r,endTime:a,requestId:i,qualifier:s});return{content:[{type:"text",text:JSON.stringify(l,null,2)}]}}),e.registerTool?.("getFunctionLogDetail",{title:"获取云函数日志详情",description:"根据 getFunctionLogs 返回的 RequestId 查询日志详情。参数 startTime、endTime、requestId,返回日志内容(LogJson 等)。仅支持 manger-node 4.4.0+。",inputSchema:{startTime:r.z.string().optional().describe("查询的具体日期,例如:2017-05-16 20:00:00,只能与 EndTime 相差一天之内"),endTime:r.z.string().optional().describe("查询的具体日期,例如:2017-05-16 20:59:59,只能与 StartTime 相差一天之内"),requestId:r.z.string().describe("执行该函数对应的 requestId")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"functions"}},async({startTime:e,endTime:n,requestId:t})=>{if(e&&n){const t=new Date(e).getTime();if(new Date(n).getTime()-t>864e5)throw new Error("startTime 和 endTime 间隔不能超过一天")}const r=await o(),a=await r.functions.getFunctionLogDetail({startTime:e,endTime:n,logRequestId:t});return{content:[{type:"text",text:JSON.stringify(a,null,2)}]}}),e.registerTool?.("createFunctionTriggers",{title:"创建云函数触发器",description:"创建云函数触发器",inputSchema:{name:r.z.string().describe("函数名"),triggers:r.z.array(r.z.object({name:r.z.string().describe("Trigger name"),type:r.z.enum(n.SUPPORTED_TRIGGER_TYPES).describe("Trigger type, currently only supports 'timer'"),config:r.z.string().describe("Trigger configuration. For timer triggers, use cron expression format: second minute hour day month week year. IMPORTANT: Must include exactly 7 fields (second minute hour day month week year). Examples: '0 0 2 1 * * *' (monthly), '0 30 9 * * * *' (daily at 9:30 AM)")})).describe("Trigger configuration array")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"functions"}},async({name:e,triggers:n})=>{const t=await o(),r=await t.functions.createFunctionTriggers(e,n);return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}),e.registerTool?.("deleteFunctionTrigger",{title:"删除云函数触发器",description:"删除云函数触发器",inputSchema:{name:r.z.string().describe("函数名"),triggerName:r.z.string().describe("触发器名称")},annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!0,openWorldHint:!0,category:"functions"}},async({name:e,triggerName:n})=>{const o=await(0,a.getCloudBaseManager)({cloudBaseOptions:t}),r=await o.functions.deleteFunctionTrigger(e,n);return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}})};const r=t(971),a=t(431),i=o(t(521));function s(e,n){if(!e)return e;const t=i.default.normalize(e);if(i.default.basename(t)===n){const e=i.default.dirname(t);return console.warn(`检测到 functionRootPath 包含函数名 "${n}",已自动调整为父目录: ${e}`),e}return e}n.SUPPORTED_NODEJS_RUNTIMES=["Nodejs18.15","Nodejs16.13","Nodejs14.18","Nodejs12.16","Nodejs10.15","Nodejs8.9"],n.DEFAULT_NODEJS_RUNTIME="Nodejs18.15",n.SUPPORTED_TRIGGER_TYPES=["timer"],n.TRIGGER_CONFIG_EXAMPLES={timer:{description:"Timer trigger configuration using cron expression format: second minute hour day month week year",examples:["0 0 2 1 * * *","0 30 9 * * * *","0 0 12 * * * *","0 0 0 1 1 * *"]}}},971:e=>{e.exports=v}},S={};function E(e){var n=S[e];if(void 0!==n)return n.exports;var t=S[e]={exports:{}};return I[e].call(t.exports,t,t.exports,E),t.exports}w=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,E.t=function(e,n){if(1&n&&(e=this(e)),8&n)return e;if("object"==typeof e&&e){if(4&n&&e.__esModule)return e;if(16&n&&"function"==typeof e.then)return e}var t=Object.create(null);E.r(t);var o={};x=x||[null,w({}),w([]),w(w)];for(var r=2&n&&e;("object"==typeof r||"function"==typeof r)&&!~x.indexOf(r);r=w(r))Object.getOwnPropertyNames(r).forEach(n=>o[n]=()=>e[n]);return o.default=()=>e,E.d(t,o),t},E.d=(e,n)=>{for(var t in n)E.o(n,t)&&!E.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},E.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),E.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var T={};(()=>{var e=T;Object.defineProperty(e,"BJ",{value:!0}),e.q8=e.bM=e.fW=e._k=e.T$=e.$n=e.S=e.bT=e.ri=e.BS=e.R8=e.z3=e.pq=e.R4=e.ps=e.v7=e.S7=e.dD=e.Gh=void 0,e.SJ=async function(){const{getInteractiveServer:e}=await Promise.resolve().then(E.t.bind(E,341,23));return e(void 0)};var n=E(422);Object.defineProperty(e,"Gh",{enumerable:!0,get:function(){return n.createCloudBaseMcpServer}}),Object.defineProperty(e,"dD",{enumerable:!0,get:function(){return n.getDefaultServer}}),Object.defineProperty(e,"S7",{enumerable:!0,get:function(){return n.StdioServerTransport}}),Object.defineProperty(e,"v7",{enumerable:!0,get:function(){return n.telemetryReporter}}),Object.defineProperty(e,"ps",{enumerable:!0,get:function(){return n.reportToolkitLifecycle}}),Object.defineProperty(e,"R4",{enumerable:!0,get:function(){return n.reportToolCall}}),Object.defineProperty(e,"pq",{enumerable:!0,get:function(){return n.info}}),Object.defineProperty(e,"z3",{enumerable:!0,get:function(){return n.error}}),Object.defineProperty(e,"R8",{enumerable:!0,get:function(){return n.warn}});var t=E(291);Object.defineProperty(e,"BS",{enumerable:!0,get:function(){return t.getLoginState}}),Object.defineProperty(e,"ri",{enumerable:!0,get:function(){return t.logout}});var o=E(684);Object.defineProperty(e,"bT",{enumerable:!0,get:function(){return o.isCloudMode}}),Object.defineProperty(e,"S",{enumerable:!0,get:function(){return o.enableCloudMode}}),Object.defineProperty(e,"$n",{enumerable:!0,get:function(){return o.getCloudModeStatus}}),Object.defineProperty(e,"T$",{enumerable:!0,get:function(){return o.shouldRegisterTool}});var r=E(431);Object.defineProperty(e,"_k",{enumerable:!0,get:function(){return r.getCloudBaseManager}}),Object.defineProperty(e,"fW",{enumerable:!0,get:function(){return r.getEnvId}}),Object.defineProperty(e,"bM",{enumerable:!0,get:function(){return r.resetCloudBaseManagerCache}}),Object.defineProperty(e,"q8",{enumerable:!0,get:function(){return r.createCloudBaseManagerWithOptions}})})();const O=T.S7,C=T.BJ,k=T.q8,D=T.Gh,z=T.S,$=T.z3,M=T._k,_=T.$n,N=T.dD,P=T.fW,j=T.SJ,B=T.BS,R=T.pq,A=T.bT,L=T.ri,H=T.R4,U=T.ps,F=T.bM,q=T.T$,J=T.v7,W=T.R8;export{O as StdioServerTransport,C as __esModule,k as createCloudBaseManagerWithOptions,D as createCloudBaseMcpServer,z as enableCloudMode,$ as error,M as getCloudBaseManager,_ as getCloudModeStatus,N as getDefaultServer,P as getEnvId,j as getInteractiveServerAsync,B as getLoginState,R as info,A as isCloudMode,L as logout,H as reportToolCall,U as reportToolkitLifecycle,F as resetCloudBaseManagerCache,q as shouldRegisterTool,J as telemetryReporter,W as warn};
1
+ import*as e from"@cloudbase/toolbox";import*as n from"os";import*as t from"@cloudbase/cals/lib/cjs/utils/mermaid-datasource/mermaid-json-transform";import*as o from"ws";import*as r from"open";import*as a from"net";import*as i from"fs";import*as s from"@modelcontextprotocol/sdk/server/stdio.js";import*as c from"path";import*as l from"@modelcontextprotocol/sdk/server/mcp.js";import*as d from"@cloudbase/manager-node";import*as u from"express";import*as p from"http";import*as g from"dns";import*as m from"crypto";import*as f from"https";import*as b from"adm-zip";import*as h from"url";import*as y from"fs/promises";import*as v from"zod";var x,w,I={39:function(e,n,t){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.clearLogs=n.getLoggerStatus=n.getLogs=n.error=n.warn=n.info=n.debug=n.logger=n.LogLevel=void 0;const r=o(t(932)),a=o(t(521)),i=o(t(116));var s;!function(e){e[e.DEBUG=0]="DEBUG",e[e.INFO=1]="INFO",e[e.WARN=2]="WARN",e[e.ERROR=3]="ERROR"}(s||(n.LogLevel=s={})),n.logger=new class{enabled;level;logFile;useConsole;constructor(e={}){this.enabled=e.enabled??!0,this.level=e.level??s.INFO,this.useConsole=e.console??!1,this.logFile=e.logFile??a.default.join(i.default.tmpdir(),"cloudbase-mcp.log")}async writeLog(e,n,t){if(!this.enabled||e<this.level)return;const o=(new Date).toISOString(),a=s[e],i=t?`[${o}] [${a}] ${n} ${JSON.stringify(t,null,2)}`:`[${o}] [${a}] ${n}`;if(this.useConsole&&console.error(i),this.logFile)try{await r.default.appendFile(this.logFile,i+"\n")}catch(e){}}debug(e,n){this.writeLog(s.DEBUG,e,n)}info(e,n){this.writeLog(s.INFO,e,n)}warn(e,n){this.writeLog(s.WARN,e,n)}error(e,n){this.writeLog(s.ERROR,e,n)}setLevel(e){this.level=e}setEnabled(e){this.enabled=e}getLogFile(){return this.logFile}async clearLogs(){if(this.logFile)try{await r.default.writeFile(this.logFile,"")}catch(e){}}async getLogs(e=1e3){if(!this.logFile)return[];try{return(await r.default.readFile(this.logFile,"utf-8")).split("\n").filter(e=>e.trim()).slice(-e)}catch(e){return[`读取日志文件失败: ${e instanceof Error?e.message:String(e)}`]}}getStatus(){return{enabled:this.enabled,level:s[this.level],logFile:this.logFile,useConsole:this.useConsole}}}({enabled:"true"===(process.env.MCP_DEBUG??"true"),level:s.DEBUG,console:"true"===process.env.MCP_CONSOLE_LOG}),n.debug=(e,t)=>n.logger.debug(e,t),n.info=(e,t)=>n.logger.info(e,t),n.warn=(e,t)=>n.logger.warn(e,t),n.error=(e,t)=>n.logger.error(e,t),n.getLogs=e=>n.logger.getLogs(e),n.getLoggerStatus=()=>n.logger.getStatus(),n.clearLogs=()=>n.logger.clearLogs()},90:n=>{n.exports=e},97:function(e,n,t){var o,r=this&&this.__createBinding||(Object.create?function(e,n,t,o){void 0===o&&(o=t);var r=Object.getOwnPropertyDescriptor(n,t);r&&!("get"in r?!n.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return n[t]}}),Object.defineProperty(e,o,r)}:function(e,n,t,o){void 0===o&&(o=t),e[o]=n[t]}),a=this&&this.__setModuleDefault||(Object.create?function(e,n){Object.defineProperty(e,"default",{enumerable:!0,value:n})}:function(e,n){e.default=n}),i=this&&this.__importStar||(o=function(e){return o=Object.getOwnPropertyNames||function(e){var n=[];for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[n.length]=t);return n},o(e)},function(e){if(e&&e.__esModule)return e;var n={};if(null!=e)for(var t=o(e),i=0;i<t.length;i++)"default"!==t[i]&&r(n,e,t[i]);return a(n,e),n});Object.defineProperty(n,"__esModule",{value:!0}),n.registerDownloadTools=function(e){e.registerTool("downloadRemoteFile",{title:"下载远程文件",description:"下载远程文件到本地临时文件,返回一个系统的绝对路径",inputSchema:{url:s.z.string().describe("远程文件的 URL 地址")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"download"}},async({url:e})=>{try{const n=await function(e){return new Promise((n,t)=>{(e.startsWith("https:")?g:m).get(e,async o=>{if(200!==o.statusCode)return void t(new Error(`HTTP Error: ${o.statusCode}`));const r=o.headers["content-type"]||"",a=parseInt(o.headers["content-length"]||"0",10),i=o.headers["content-disposition"];if(!await async function(e,n){try{const t=new f.URL(e);if(!v.includes(t.protocol))return!1;const o=t.hostname;return(!b.isIP(o)||!w(o))&&!(!b.isIP(o)&&await async function(e){try{const n=await new Promise((n,t)=>{h.resolve(e,(e,o)=>{e?t(e):n(o)})});return n.some(e=>w(e))}catch(e){return!0}}(o))&&x.some(e=>n.startsWith(e))}catch{return!1}}(e,r))return void t(new Error("不安全的 URL 或内容类型,或者目标为内网地址"));if(a>y)return void t(new Error(`文件大小 ${a} 字节超过 ${y} 字节限制`));const s=function(e,n,t){let o="";const r=new f.URL(e).pathname,a=d.extname(r);if(a&&(o=a),t){const e=t.match(/filename=["']?([^"']+)["']?/);if(e){const n=d.extname(e[1]);n&&(o=n)}}return!o&&n&&(o={"text/plain":".txt","text/html":".html","text/css":".css","text/javascript":".js","image/jpeg":".jpg","image/png":".png","image/gif":".gif","image/webp":".webp","application/json":".json","application/xml":".xml","application/pdf":".pdf","application/zip":".zip","application/x-zip-compressed":".zip"}[n]||""),o}(e,r,i),g=function(e=""){return`${p.randomBytes(16).toString("hex")}${e}`}(s),m=function(e){return d.join(u.tmpdir(),e)}(g),I=l.createWriteStream(m);let S=0;o.on("data",e=>{S+=e.length,S>y&&(I.destroy(),c.unlink(m).catch(()=>{}),t(new Error(`文件大小超过 ${y} 字节限制`)))}),o.pipe(I),I.on("finish",()=>{n({filePath:m,contentType:r,fileSize:S})}),I.on("error",e=>{c.unlink(m).catch(()=>{}),t(e)})}).on("error",e=>{t(e)})})}(e);return{content:[{type:"text",text:JSON.stringify({success:!0,filePath:n.filePath,contentType:n.contentType,fileSize:n.fileSize,message:"文件下载成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"文件下载失败"},null,2)}]}}})};const s=t(971),c=i(t(932)),l=i(t(421)),d=i(t(521)),u=i(t(116)),p=i(t(823)),g=i(t(871)),m=i(t(782)),f=t(887),b=i(t(357)),h=i(t(793)),y=104857600,v=["http:","https:"],x=["text/","image/","application/json","application/xml","application/pdf","application/zip","application/x-zip-compressed"];function w(e){if(!b.isIP(e))return!0;if("127.0.0.1"===e||"localhost"===e||"::1"===e||e.startsWith("169.254.")||e.startsWith("0."))return!0;const n=e.split(".").map(e=>parseInt(e,10));if(4===n.length){const e=(n[0]<<24)+(n[1]<<16)+(n[2]<<8)+n[3];if(e>=167772160&&e<=184549375)return!0;if(e>=2886729728&&e<=2887778303)return!0;if(e>=3232235520&&e<=3232301055)return!0}if(b.isIPv6(e)){const n=e.toLowerCase();if(n.startsWith("fc00:")||n.startsWith("fe80:")||n.startsWith("fec0:")||n.startsWith("::1"))return!0}return!1}},116:e=>{e.exports=n},191:e=>{e.exports=t},215:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerRagTools=function(e){e.registerTool?.("searchWeb",{title:"联网搜索",description:"使用联网来进行信息检索,如查询最新的新闻、文章、股价、天气等。支持自然语言查询,也可以直接输入网址获取网页内容",inputSchema:{query:o.z.string().describe("搜索关键词、问题或网址,支持自然语言")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"web"}},async({query:e})=>{try{const n=await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/auth/v1/signin/anonymously",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json","x-device-id":"cloudbase-ai-toolkit"},body:s({})}),{access_token:t}=await n.json(),o=await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/v1/ai/hunyuan-beta/openapi/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:s({model:"hunyuan",messages:[{role:"user",content:"你好,你将扮演一个知识库的角色,联网查询到问题的答案之后回答给我"},{role:"assistant",content:"好的"},{role:"user",content:e}],enable_enhancement:!0,search_info:!0,enable_speed_search:!0,force_search_enhancement:!0})}),r=await o.json();if(r.error)throw new Error(r.error.message||"联网搜索失败");return{content:[{type:"text",text:s({type:"web_search",content:r.choices?.[0]?.message?.content||"",search_results:(r.search_info?.search_results||[]).map(e=>({title:e.title,url:e.url,snippet:e.snippet})),status:"success"})}]}}catch(e){return{content:[{type:"text",text:s({type:"error",message:e instanceof Error?e.message:"联网搜索失败",status:"error"})}]}}}),e.registerTool?.("searchKnowledgeBase",{title:"云开发知识库检索",description:"云开发知识库智能检索工具,支持云开发与云函数知识的向量查询",inputSchema:{threshold:o.z.number().default(.5).optional().describe("相似性检索阈值"),id:r.describe("知识库范围,cloudbase=云开发全量知识,scf=云开发的云函数知识, miniprogram=小程序知识(不包含云开发与云函数知识)"),content:o.z.string().describe("检索内容"),options:o.z.object({chunkExpand:o.z.array(o.z.number()).min(2).max(2).default([3,3]).describe("指定返回的文档内容的展开长度,例如 [3,3]代表前后展开长度")}).optional().describe("其他选项"),limit:o.z.number().default(5).optional().describe("指定返回最相似的 Top K 的 K 的值")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"rag"}},async({id:e,content:n,options:{chunkExpand:t=[3,3]}={},limit:o=5,threshold:r=.5})=>{const c=a[e]||e,l=await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/auth/v1/signin/anonymously",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json","x-device-id":"cloudbase-ai-toolkit"},body:s({collectionView:c,options:{chunkExpand:t},search:{content:n,limit:o}})}),d=(await l.json()).access_token,u=await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/v1/knowledge/search",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${d}`},body:s({collectionView:c,options:{chunkExpand:t},search:{content:n,limit:o}})}),p=await u.json();if(p.code)throw new Error(p.message);return{content:[{type:"text",text:s(p.data.documents.filter(e=>e.score>=r).map(e=>({score:e.score,fileTile:e.documentSet.fileTitle,url:i(e.documentSet.fileMetaData).url,paragraphTitle:e.data.paragraphTitle,text:`${e.data.pre?.join("\n")||""}\n ${e.data.text}\n ${e.data.next?.join("\n")||""}`})))}]}})};const o=t(971),r=o.z.enum(["cloudbase","scf","miniprogram"]),a={cloudbase:"ykfzskv4_ad28",scf:"scfsczskzyws_4bdc",miniprogram:"xcxzskws_25d8"};function i(e){try{return JSON.parse(e)}catch(e){return{}}}function s(e){const n=new WeakSet;try{return JSON.stringify(e,function(e,t){if("object"==typeof t&&null!==t){if(n.has(t))return;n.add(t)}return t})}catch(e){return""}}},220:e=>{e.exports=o},241:e=>{e.exports=r},279:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerHostingTools=function(e){const n=e.cloudBaseOptions,t=()=>(0,r.getCloudBaseManager)({cloudBaseOptions:n});e.registerTool("uploadFiles",{title:"上传静态文件",description:"上传文件到静态网站托管",inputSchema:{localPath:o.z.string().optional().describe("本地文件或文件夹路径,需要是绝对路径,例如 /tmp/files/data.txt"),cloudPath:o.z.string().optional().describe("云端文件或文件夹路径,例如files/data.txt"),files:o.z.array(o.z.object({localPath:o.z.string(),cloudPath:o.z.string()})).default([]).describe("多文件上传配置"),ignore:o.z.union([o.z.string(),o.z.array(o.z.string())]).optional().describe("忽略文件模式")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"hosting"}},async({localPath:e,cloudPath:n,files:o=[],ignore:r})=>{const a=await t(),i=await a.hosting.uploadFiles({localPath:e,cloudPath:n,files:o,ignore:r}),s=await a.env.getEnvInfo(),c=s.EnvInfo?.StaticStorages?.[0]?.StaticDomain;return{content:[{type:"text",text:JSON.stringify({...i,staticDomain:c,message:"文件上传成功",accessUrl:c?`https://${c}/${n||""}`:"请检查静态托管配置"},null,2)}]}}),e.registerTool?.("getWebsiteConfig",{title:"查询静态托管配置",description:"获取静态网站托管配置",inputSchema:{},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"hosting"}},async()=>{const e=await t(),n=await e.hosting.getWebsiteConfig();return{content:[{type:"text",text:JSON.stringify(n,null,2)}]}}),e.registerTool?.("deleteFiles",{title:"删除静态文件",description:"删除静态网站托管的文件或文件夹",inputSchema:{cloudPath:o.z.string().describe("云端文件或文件夹路径"),isDir:o.z.boolean().default(!1).describe("是否为文件夹")},annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!0,openWorldHint:!0,category:"hosting"}},async({cloudPath:e,isDir:n=!1})=>{const o=await t(),r=await o.hosting.deleteFiles({cloudPath:e,isDir:n});return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}),e.registerTool?.("findFiles",{title:"搜索静态文件",description:"搜索静态网站托管的文件",inputSchema:{prefix:o.z.string().describe("匹配前缀"),marker:o.z.string().optional().describe("起始对象键标记"),maxKeys:o.z.number().optional().describe("单次返回最大条目数")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"hosting"}},async({prefix:e,marker:n,maxKeys:o})=>{const r=await t(),a=await r.hosting.findFiles({prefix:e,marker:n,maxKeys:o});return{content:[{type:"text",text:JSON.stringify(a,null,2)}]}}),e.registerTool?.("domainManagement",{title:"静态托管域名管理",description:"统一的域名管理工具,支持绑定、解绑、查询和修改域名配置",inputSchema:{action:o.z.enum(["create","delete","check","modify"]).describe("操作类型: create=绑定域名, delete=解绑域名, check=查询域名配置, modify=修改域名配置"),domain:o.z.string().optional().describe("域名"),certId:o.z.string().optional().describe("证书ID(绑定域名时必需)"),domains:o.z.array(o.z.string()).optional().describe("域名列表(查询配置时使用)"),domainId:o.z.number().optional().describe("域名ID(修改配置时必需)"),domainConfig:o.z.object({Refer:o.z.object({Switch:o.z.string(),RefererRules:o.z.array(o.z.object({RefererType:o.z.string(),Referers:o.z.array(o.z.string()),AllowEmpty:o.z.boolean()})).optional()}).optional(),Cache:o.z.array(o.z.object({RuleType:o.z.string(),RuleValue:o.z.string(),CacheTtl:o.z.number()})).optional(),IpFilter:o.z.object({Switch:o.z.string(),FilterType:o.z.string().optional(),Filters:o.z.array(o.z.string()).optional()}).optional(),IpFreqLimit:o.z.object({Switch:o.z.string(),Qps:o.z.number().optional()}).optional()}).optional().describe("域名配置(修改配置时使用)")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"hosting"}},async({action:e,domain:n,certId:o,domains:r,domainId:a,domainConfig:i})=>{const s=await t();let c;switch(e){case"create":if(!n||!o)throw new Error("绑定域名需要提供域名和证书ID");c=await s.hosting.CreateHostingDomain({domain:n,certId:o});break;case"delete":if(!n)throw new Error("解绑域名需要提供域名");c=await s.hosting.deleteHostingDomain({domain:n});break;case"check":if(!r||0===r.length)throw new Error("查询域名配置需要提供域名列表");c=await s.hosting.tcbCheckResource({domains:r});break;case"modify":if(!n||void 0===a||!i)throw new Error("修改域名配置需要提供域名、域名ID和配置信息");c=await s.hosting.tcbModifyAttribute({domain:n,domainId:a,domainConfig:i});break;default:throw new Error(`不支持的操作类型: ${e}`)}return{content:[{type:"text",text:JSON.stringify(c,null,2)}]}})};const o=t(971),r=t(431)},291:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.getLoginState=async function(){const{TENCENTCLOUD_SECRETID:e,TENCENTCLOUD_SECRETKEY:n,TENCENTCLOUD_SESSIONTOKEN:t}=process.env;if((0,r.debug)("TENCENTCLOUD_SECRETID",e),e&&n)return(0,r.debug)("loginByApiSecret"),{secretId:e,secretKey:n,token:t};const o=await a.getLoginState();return o||((0,r.debug)("loginByApiSecret"),await a.loginByWebAuth({}),await a.getLoginState())},n.logout=async function(){return await a.logout()};const o=t(90),r=t(39),a=o.AuthSupevisor.getInstance({})},319:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerGatewayTools=function(e){const n=e.cloudBaseOptions;e.registerTool?.("createFunctionHTTPAccess",{title:"创建云函数HTTP访问",description:"创建云函数的 HTTP 访问",inputSchema:{name:o.z.string().describe("函数名"),path:o.z.string().describe("HTTP 访问路径")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"gateway"}},async({name:e,path:t})=>{const o=await(0,r.getCloudBaseManager)({cloudBaseOptions:n}),a=await o.access.createAccess({type:1,name:e,path:t});return{content:[{type:"text",text:JSON.stringify(a,null,2)}]}})};const o=t(971),r=t(431)},341:function(e,n,t){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.InteractiveServer=void 0,n.getInteractiveServer=p,n.resetInteractiveServer=async function(){if(u){try{await u.stop()}catch(e){(0,c.error)("Error stopping existing server instance:",e)}u=null}},n.getInteractiveServerSafe=async function(e){if(u&&!u.running){try{await u.stop()}catch(e){(0,c.debug)("Error stopping non-running server:",e)}u=null}return p(e)};const r=o(t(674)),a=o(t(782)),i=t(220),s=o(t(241)),c=t(39);async function l(e,n,t){if("CodeBuddy"===process.env.INTEGRATION_IDE&&t)try{return t.server.sendLoggingMessage({level:"notice",data:{type:"tcb",url:e}}),void(0,c.info)(`CodeBuddy IDE: 已发送网页打开通知 - ${e}`)}catch(n){(0,c.error)(`Failed to send logging message for ${e}: ${n instanceof Error?n.message:n}`,n),(0,c.warn)(`回退到直接打开网页: ${e}`)}try{return await(0,s.default)(e,n)}catch(t){(0,c.error)(`Failed to open ${e} ${n} ${t instanceof Error?t.message:t} `,t),(0,c.warn)(`Please manually open: ${e}`)}}class d{app;server;wss;port=0;isRunning=!1;currentResolver=null;sessionData=new Map;_mcpServer=null;get mcpServer(){return this._mcpServer}set mcpServer(e){this._mcpServer=e}DEFAULT_PORT=3721;FALLBACK_PORTS=[3722,3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735];constructor(e){this._mcpServer=e,this.app=(0,r.default)(),this.server=a.default.createServer(this.app),this.wss=new i.WebSocketServer({server:this.server}),this.setupExpress(),this.setupWebSocket(),process.on("exit",()=>this.cleanup()),process.on("SIGINT",()=>this.cleanup()),process.on("SIGTERM",()=>this.cleanup())}cleanup(){this.isRunning&&((0,c.debug)("Cleaning up interactive server resources..."),this.server.close(),this.wss.close(),this.isRunning=!1)}setupExpress(){this.app.use(r.default.json()),this.app.get("/env-setup/:sessionId",(e,n)=>{const{sessionId:t}=e.params,o=this.sessionData.get(t);o?n.send(this.getEnvSetupHTML(o.envs)):n.status(404).send("会话不存在或已过期")}),this.app.get("/clarification/:sessionId",(e,n)=>{const{sessionId:t}=e.params,o=this.sessionData.get(t);o?n.send(this.getClarificationHTML(o.message,o.options)):n.status(404).send("会话不存在或已过期")}),this.app.get("/debug/logs",async(e,n)=>{try{const e=await(0,c.getLogs)(1e3),t=(0,c.getLoggerStatus)();n.send(this.getLogsHTML(e,t))}catch(e){n.status(500).send("获取日志失败")}}),this.app.get("/api/logs",async(e,n)=>{try{const t=parseInt(e.query.maxLines)||1e3,o=await(0,c.getLogs)(t),r=(0,c.getLoggerStatus)();n.json({logs:o,status:r,success:!0})}catch(e){n.status(500).json({success:!1,error:"Failed to get logs"})}}),this.app.post("/api/logs/clear",async(e,n)=>{try{await(0,c.clearLogs)(),n.json({success:!0})}catch(e){n.status(500).json({success:!1,error:"Failed to clear logs"})}}),this.app.post("/api/submit",(e,n)=>{const{type:t,data:o}=e.body;(0,c.debug)("Received submit request",{type:t,data:o}),this.currentResolver?((0,c.info)("Resolving with user data"),this.currentResolver({type:t,data:o}),this.currentResolver=null):(0,c.warn)("No resolver waiting for response"),n.json({success:!0})}),this.app.post("/api/cancel",(e,n)=>{(0,c.info)("Received cancel request"),this.currentResolver?((0,c.info)("Resolving with cancelled status"),this.currentResolver({type:"clarification",data:null,cancelled:!0}),this.currentResolver=null):(0,c.warn)("No resolver waiting for cancellation"),n.json({success:!0})})}setupWebSocket(){this.wss.on("connection",e=>{(0,c.debug)("WebSocket client connected"),e.on("message",e=>{try{const n=JSON.parse(e.toString());(0,c.debug)("WebSocket message received",n),this.currentResolver&&(this.currentResolver(n),this.currentResolver=null)}catch(e){(0,c.error)("WebSocket message parsing error",e)}}),e.on("close",()=>{(0,c.debug)("WebSocket client disconnected")})})}async start(){return this.isRunning?((0,c.debug)(`Interactive server already running on port ${this.port}`),this.port):new Promise((e,n)=>{(0,c.info)("Starting interactive server...");const t=[this.DEFAULT_PORT,...this.FALLBACK_PORTS];let o=0;const r=()=>{if(o>=t.length){const e=new Error(`All ${t.length} ports are in use (${t.join(", ")}), failed to start server`);return(0,c.error)("Server start failed",e),void n(e)}const e=t[o];o++,(0,c.debug)(`Trying to start server on port ${e} (attempt ${o}/${t.length})`),a(e)},a=t=>{this.server.removeAllListeners("error"),this.server.removeAllListeners("listening");const o=e=>{"EADDRINUSE"===e.code?((0,c.warn)(`Port ${t} is in use, trying next port...`),this.server.removeAllListeners("error"),this.server.removeAllListeners("listening"),r()):((0,c.error)("Server error",e),n(e))},a=()=>{const t=this.server.address();if(t&&"object"==typeof t)this.port=t.port,this.isRunning=!0,(0,c.info)(`Interactive server started successfully on http://localhost:${this.port}`),this.server.removeListener("error",o),this.server.removeListener("listening",a),e(this.port);else{const e=new Error("Failed to get server address");(0,c.error)("Server start error",e),n(e)}};this.server.once("error",o),this.server.once("listening",a);try{this.server.listen(t,"127.0.0.1")}catch(e){(0,c.error)(`Failed to bind to port ${t}:`,e),r()}};r()})}async stop(){if(this.isRunning)return(0,c.info)("Stopping interactive server..."),new Promise((e,n)=>{const t=setTimeout(()=>{(0,c.warn)("Server close timeout, forcing cleanup"),this.isRunning=!1,this.port=0,e()},3e4);try{this.wss.close(()=>{(0,c.debug)("WebSocket server closed")}),this.server.close(o=>{clearTimeout(t),o?((0,c.error)("Error closing server:",o),n(o)):((0,c.info)("Interactive server stopped successfully"),this.isRunning=!1,this.port=0,e())})}catch(e){clearTimeout(t),(0,c.error)("Error stopping server:",e),this.isRunning=!1,this.port=0,n(e)}});(0,c.debug)("Interactive server is not running, nothing to stop")}async collectEnvId(e){try{(0,c.info)("Starting environment ID collection..."),(0,c.debug)(`Available environments: ${e.length}`);const n=await this.start(),t=Math.random().toString(36).substring(2,15);this.sessionData.set(t,{envs:e}),(0,c.debug)(`Created session: ${t}`),setTimeout(()=>{this.sessionData.delete(t),(0,c.debug)(`Session ${t} expired`)},3e5);const o=`http://localhost:${n}/env-setup/${t}`;(0,c.info)(`Opening browser: ${o}`);try{await l(o,{wait:!1},this._mcpServer),(0,c.info)("Browser opened successfully")}catch(e){(0,c.error)("Failed to open browser",e),(0,c.warn)(`Please manually open: ${o}`)}return(0,c.info)("Waiting for user selection..."),new Promise(e=>{this.currentResolver=n=>{this.stop().catch(e=>{(0,c.debug)("Error stopping server after user selection:",e)}),e(n)},setTimeout(()=>{this.currentResolver&&((0,c.warn)("Request timeout, resolving with cancelled"),this.currentResolver=null,this.stop().catch(e=>{(0,c.debug)("Error stopping server after timeout:",e)}),e({type:"envId",data:null,cancelled:!0}))},6e5)})}catch(e){throw(0,c.error)("Error in collectEnvId",e),e}}async clarifyRequest(e,n){const t=await this.start(),o=Math.random().toString(36).substring(2,15);this.sessionData.set(o,{message:e,options:n}),setTimeout(()=>{this.sessionData.delete(o)},3e5);const r=`http://localhost:${t}/clarification/${o}`;return await l(r,void 0,this._mcpServer),new Promise(e=>{this.currentResolver=n=>{this.stop().catch(e=>{(0,c.debug)("Error stopping server after user selection:",e)}),e(n)}})}getEnvSetupHTML(e){return`\n<!DOCTYPE html>\n<html lang="zh-CN">\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>CloudBase AI Toolkit - 环境配置</title>\n <style>\n @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');\n \n * { margin: 0; padding: 0; box-sizing: border-box; }\n :root {\n --primary-color: #1a1a1a;\n --primary-hover: #000000;\n --accent-color: #67E9E9;\n --accent-hover: #2BCCCC;\n --text-primary: #ffffff;\n --text-secondary: #a0a0a0;\n --border-color: rgba(255, 255, 255, 0.15);\n --bg-secondary: rgba(255, 255, 255, 0.08);\n --bg-glass: rgba(26, 26, 26, 0.95);\n --shadow: 0 25px 50px rgba(0, 0, 0, 0.3), 0 10px 20px rgba(0, 0, 0, 0.2);\n --font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;\n --header-bg: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0d1117 100%);\n }\n \n body {\n font-family: var(--font-mono);\n background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n position: relative;\n overflow-x: hidden;\n overflow-y: auto;\n }\n \n /* Custom scrollbar styles */\n ::-webkit-scrollbar {\n width: 8px;\n }\n \n ::-webkit-scrollbar-track {\n background: rgba(255, 255, 255, 0.05);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb {\n background: var(--accent-color);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb:hover {\n background: var(--accent-hover);\n }\n \n body::before {\n content: '';\n position: fixed;\n top: 0; left: 0; right: 0; bottom: 0;\n background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse"><path d="M 20 0 L 0 0 0 20" fill="none" stroke="rgba(255,255,255,0.02)" stroke-width="1"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>') repeat;\n pointer-events: none;\n z-index: -1;\n }\n \n body::after {\n content: '';\n position: fixed;\n top: 50%; left: 50%;\n width: 500px; height: 500px;\n background: radial-gradient(circle, rgba(103, 233, 233, 0.05) 0%, transparent 70%);\n transform: translate(-50%, -50%);\n pointer-events: none;\n z-index: -1;\n animation: pulse 8s ease-in-out infinite;\n }\n \n @keyframes pulse {\n 0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }\n 50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }\n }\n \n .modal {\n background: var(--bg-glass);\n backdrop-filter: blur(20px);\n border-radius: 20px;\n box-shadow: var(--shadow);\n border: 2px solid var(--border-color);\n width: 100%;\n max-width: 520px;\n overflow: hidden;\n animation: modalIn 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);\n position: relative;\n }\n \n .modal::before {\n content: '';\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.02) 50%, transparent 70%);\n animation: shimmer 3s infinite;\n pointer-events: none;\n }\n \n @keyframes shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n \n @keyframes modalIn {\n from {\n opacity: 0;\n transform: scale(0.9) translateY(-20px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n }\n \n .header {\n background: var(--header-bg);\n color: var(--text-primary);\n padding: 24px 28px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n position: relative;\n overflow: hidden;\n }\n \n .header::before {\n content: '';\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.03) 50%, transparent 70%);\n animation: headerShimmer 4s infinite;\n pointer-events: none;\n }\n \n @keyframes headerShimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n \n .header-left {\n display: flex;\n align-items: center;\n gap: 16px;\n z-index: 1;\n }\n \n .logo {\n width: 32px;\n height: 32px;\n filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));\n animation: logoFloat 3s ease-in-out infinite;\n }\n \n @keyframes logoFloat {\n 0%, 100% { transform: translateY(0px); }\n 50% { transform: translateY(-3px); }\n }\n \n .title {\n font-size: 20px;\n font-weight: 700;\n text-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n \n .github-link {\n color: var(--text-primary);\n text-decoration: none;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n background: rgba(255,255,255,0.08);\n border: 1px solid rgba(255, 255, 255, 0.12);\n backdrop-filter: blur(10px);\n padding: 8px 16px;\n border-radius: 8px;\n font-weight: 500;\n z-index: 1;\n transition: all 0.3s ease;\n }\n \n .github-link:hover {\n background: rgba(255,255,255,0.15);\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n }\n \n .content {\n padding: 32px 24px;\n position: relative;\n }\n \n .content-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary);\n margin-bottom: 8px;\n animation: fadeInUp 0.8s ease-out 0.2s both;\n }\n \n .content-subtitle {\n color: var(--text-secondary);\n margin-bottom: 24px;\n line-height: 1.5;\n animation: fadeInUp 0.8s ease-out 0.4s both;\n }\n \n @keyframes fadeInUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n \n .env-list {\n border: 1px solid var(--border-color);\n border-radius: 12px;\n margin-bottom: 24px;\n max-height: 300px;\n overflow-y: auto;\n overflow-x: hidden;\n background: rgba(255, 255, 255, 0.03);\n animation: fadeInUp 0.8s ease-out 0.6s both;\n }\n \n .env-item {\n padding: 16px 20px;\n border-bottom: 1px solid var(--border-color);\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n gap: 14px;\n position: relative;\n overflow: hidden;\n color: var(--text-primary);\n }\n \n .env-item::before {\n content: '';\n position: absolute;\n left: 0; top: 0; bottom: 0;\n width: 0;\n background: var(--accent-color);\n transition: width 0.3s ease;\n }\n \n .env-item:last-child {\n border-bottom: none;\n }\n \n .env-item:hover {\n background: var(--bg-secondary);\n transform: translateX(5px);\n }\n \n .env-item:hover::before {\n width: 4px;\n }\n \n .env-item.selected {\n background: rgba(103, 233, 233, 0.1);\n border-left: 4px solid var(--accent-color);\n transform: translateX(5px);\n }\n \n .env-icon {\n width: 20px;\n height: 20px;\n color: var(--accent-color);\n flex-shrink: 0;\n animation: iconGlow 2s ease-in-out infinite;\n }\n \n @keyframes iconGlow {\n 0%, 100% { filter: drop-shadow(0 0 2px rgba(103, 233, 233, 0.3)); }\n 50% { filter: drop-shadow(0 0 8px rgba(103, 233, 233, 0.6)); }\n }\n \n .env-info {\n flex: 1;\n }\n \n .env-name {\n font-weight: 600;\n color: var(--text-primary);\n margin-bottom: 4px;\n }\n \n .env-alias {\n color: var(--text-secondary);\n font-size: 14px;\n }\n \n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n text-align: center;\n animation: fadeIn 0.8s ease-out;\n }\n \n .empty-icon {\n margin-bottom: 24px;\n color: var(--text-secondary);\n opacity: 0.6;\n }\n \n .empty-title {\n font-size: 20px;\n font-weight: 600;\n color: var(--text-primary);\n margin-bottom: 12px;\n }\n \n .empty-message {\n font-size: 14px;\n color: var(--text-secondary);\n line-height: 1.6;\n margin-bottom: 32px;\n max-width: 400px;\n }\n \n .create-env-btn {\n padding: 14px 24px;\n font-size: 15px;\n background: var(--primary-color);\n color: var(--text-primary);\n border: 1px solid var(--border-color);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n }\n \n .create-env-btn:hover {\n background: var(--primary-hover);\n transform: translateY(-2px);\n box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);\n }\n \n .actions {\n display: flex;\n gap: 12px;\n justify-content: flex-end;\n animation: fadeInUp 0.8s ease-out 0.8s both;\n }\n \n .btn {\n padding: 12px 20px;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: var(--font-mono);\n position: relative;\n overflow: hidden;\n }\n \n .btn::before {\n content: '';\n position: absolute;\n top: 50%; left: 50%;\n width: 0; height: 0;\n background: rgba(255,255,255,0.2);\n border-radius: 50%;\n transition: all 0.3s ease;\n transform: translate(-50%, -50%);\n }\n \n .btn:hover::before {\n width: 100px; height: 100px;\n }\n \n .btn-primary {\n background: var(--primary-color);\n color: var(--text-primary);\n border: 1px solid var(--border-color);\n }\n \n .btn-primary:hover:not(:disabled) {\n background: var(--primary-hover);\n transform: translateY(-2px);\n box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);\n }\n \n .btn-secondary {\n background: var(--bg-secondary);\n color: var(--text-secondary);\n border: 1px solid var(--border-color);\n }\n \n .btn-secondary:hover {\n background: rgba(255, 255, 255, 0.15);\n color: var(--text-primary);\n }\n \n .btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n \n .loading {\n display: none;\n align-items: center;\n justify-content: center;\n gap: 8px;\n margin-top: 16px;\n color: var(--text-secondary);\n font-size: 14px;\n }\n \n .spinner {\n width: 16px;\n height: 16px;\n border: 2px solid var(--border-color);\n border-top: 2px solid var(--accent-color);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n }\n \n @keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n \n @keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n \n .success-state {\n text-align: center;\n padding: 40px 20px;\n animation: fadeInUp 0.8s ease-out both;\n }\n \n .success-icon {\n margin-bottom: 20px;\n color: var(--accent-color);\n animation: successPulse 2s ease-in-out infinite;\n }\n \n @keyframes successPulse {\n 0%, 100% { \n transform: scale(1);\n filter: drop-shadow(0 0 8px rgba(103, 233, 233, 0.3));\n }\n 50% { \n transform: scale(1.1);\n filter: drop-shadow(0 0 16px rgba(103, 233, 233, 0.6));\n }\n }\n \n .success-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary);\n margin-bottom: 12px;\n }\n \n .success-message {\n color: var(--text-secondary);\n font-size: 16px;\n line-height: 1.5;\n }\n \n .selected-env-info {\n margin-top: 20px;\n padding: 16px;\n background: rgba(103, 233, 233, 0.1);\n border: 1px solid var(--accent-color);\n border-radius: 12px;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n \n .env-label {\n color: var(--text-secondary);\n font-size: 14px;\n font-weight: 500;\n }\n \n .env-value {\n color: var(--accent-color);\n font-size: 16px;\n font-weight: 600;\n font-family: var(--font-mono);\n }\n </style>\n</head>\n<body>\n <div class="modal">\n <div class="header">\n <div class="header-left">\n <img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />\n <span class="title">CloudBase AI Toolkit</span>\n </div>\n <a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" target="_blank" class="github-link">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">\n <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>\n </svg>\n GitHub\n </a>\n </div>\n\n <div class="content">\n <h1 class="content-title">选择云开发环境</h1>\n <p class="content-subtitle">请选择您要使用的云开发环境</p>\n \n <div class="env-list" id="envList">\n ${(e||[]).length>0?(e||[]).map((e,n)=>`\n <div class="env-item" onclick="selectEnv('${e.EnvId}', this)" style="animation-delay: ${.1*n}s;">\n <svg class="env-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/>\n </svg>\n <div class="env-info">\n <div class="env-name">${e.EnvId}</div>\n <div class="env-alias">${e.Alias||"无别名"}</div>\n </div>\n </div>\n `).join(""):'\n <div class="empty-state">\n <h3 class="empty-title">暂无云开发环境</h3>\n <p class="empty-message">当前没有可用的云开发 CloudBase 环境,请新建后重新在 AI 对话中重试</p>\n <button class="btn btn-primary create-env-btn" onclick="createNewEnv()">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M12 5v14M5 12h14"/>\n </svg>\n 新建环境\n </button>\n </div>\n '}\n </div>\n \n <div class="actions">\n <button class="btn btn-secondary" onclick="cancel()">\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M18 6L6 18M6 6l12 12"/>\n </svg>\n 取消\n </button>\n <button class="btn btn-primary" id="confirmBtn" onclick="confirm()" disabled>\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M20 6L9 17l-5-5"/>\n </svg>\n 确认选择\n </button>\n </div>\n \n <div class="loading" id="loading">\n <div class="spinner"></div>\n <span>正在配置环境...</span>\n </div>\n \n <div class="success-state" id="successState" style="display: none;">\n <div class="success-icon">\n <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M20 6L9 17l-5-5"/>\n </svg>\n </div>\n <h2 class="success-title">环境配置成功!</h2>\n <p class="success-message">已成功选择云开发环境</p>\n <div class="selected-env-info">\n <span class="env-label">环境 ID:</span>\n <span class="env-value" id="selectedEnvDisplay"></span>\n </div>\n </div>\n </div>\n </div>\n\n <script>\n let selectedEnvId = null;\n \n function selectEnv(envId, element) {\n console.log('=== 环境选择事件触发 ===');\n console.log('传入的envId:', envId);\n console.log('传入的element:', element);\n console.log('element类名:', element ? element.className : 'null');\n \n selectedEnvId = envId;\n console.log('设置selectedEnvId为:', selectedEnvId);\n \n // Remove selected class from all items\n const allItems = document.querySelectorAll('.env-item');\n console.log('找到的所有环境项数量:', allItems.length);\n allItems.forEach(item => {\n item.classList.remove('selected');\n });\n \n // Add selected class to current item\n if (element) {\n element.classList.add('selected');\n console.log('✅ 已添加selected样式到当前项');\n console.log('当前项的最终类名:', element.className);\n } else {\n console.error('❌ element为空,无法添加选中样式');\n }\n \n // Enable confirm button\n const confirmBtn = document.getElementById('confirmBtn');\n if (confirmBtn) {\n confirmBtn.disabled = false;\n console.log('✅ 确认按钮已启用');\n } else {\n console.error('❌ 找不到确认按钮');\n }\n }\n \n function confirm() {\n console.log('=== CONFIRM BUTTON CLICKED ===');\n console.log('selectedEnvId:', selectedEnvId);\n \n if (!selectedEnvId) {\n console.error('❌ 没有选择环境ID!');\n alert('请先选择一个环境');\n return;\n }\n \n console.log('✅ 环境ID验证通过,开始发送请求...');\n document.getElementById('loading').style.display = 'flex';\n document.getElementById('confirmBtn').disabled = true;\n \n const requestBody = {\n type: 'envId',\n data: selectedEnvId\n };\n \n console.log('📤 发送请求体:', JSON.stringify(requestBody, null, 2));\n \n fetch('/api/submit', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestBody)\n }).then(response => {\n console.log('📥 收到响应状态:', response.status);\n console.log('📥 响应头:', [...response.headers.entries()]);\n return response.json();\n }).then(data => {\n console.log('📥 响应数据:', data);\n if (data.success) {\n console.log('✅ 请求成功,展示成功提示');\n // 隐藏选择区和按钮,仅展示成功提示\n document.getElementById('envList').style.display = 'none';\n document.querySelector('.actions').style.display = 'none';\n document.getElementById('loading').style.display = 'none';\n document.getElementById('successState').style.display = 'block';\n // 显示选中的环境 ID\n document.getElementById('selectedEnvDisplay').textContent = selectedEnvId;\n window.close();\n } else {\n console.error('❌ 请求失败:', data);\n alert('选择环境失败: ' + (data.error || '未知错误'));\n document.getElementById('loading').style.display = 'none';\n document.getElementById('confirmBtn').disabled = false;\n }\n }).catch(err => {\n console.error('❌ 网络请求错误:', err);\n alert('网络请求失败: ' + err.message);\n document.getElementById('loading').style.display = 'none';\n document.getElementById('confirmBtn').disabled = false;\n });\n }\n \n function createNewEnv() {\n const integrationIde = '${process.env.INTEGRATION_IDE||"AI Toolkit"}';\n const url = \`http://tcb.cloud.tencent.com/dev?from=\${encodeURIComponent(integrationIde)}\`;\n location.href = url;\n }\n \n function cancel() {\n fetch('/api/cancel', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' }\n }).then(() => {\n window.close();\n });\n }\n <\/script>\n</body>\n</html>`}getLogsHTML(e,n){return`\n<!DOCTYPE html>\n<html lang="zh-CN">\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>CloudBase MCP 调试日志</title>\n <style>\n @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');\n \n * { margin: 0; padding: 0; box-sizing: border-box; }\n :root {\n --primary-color: #1a1a1a;\n --primary-hover: #000000;\n --accent-color: #67E9E9;\n --accent-hover: #2BCCCC;\n --text-primary: #ffffff;\n --text-secondary: #a0a0a0;\n --border-color: rgba(255, 255, 255, 0.15);\n --bg-secondary: rgba(255, 255, 255, 0.08);\n --bg-glass: rgba(26, 26, 26, 0.95);\n --shadow: 0 25px 50px rgba(0, 0, 0, 0.3), 0 10px 20px rgba(0, 0, 0, 0.2);\n --font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;\n --header-bg: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0d1117 100%);\n }\n \n body {\n font-family: var(--font-mono);\n background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);\n min-height: 100vh;\n padding: 20px;\n position: relative;\n overflow-x: hidden;\n overflow-y: auto;\n }\n \n /* Custom scrollbar styles */\n ::-webkit-scrollbar {\n width: 8px;\n }\n \n ::-webkit-scrollbar-track {\n background: rgba(255, 255, 255, 0.05);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb {\n background: var(--accent-color);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb:hover {\n background: var(--accent-hover);\n }\n \n body::before {\n content: '';\n position: fixed;\n top: 0; left: 0; right: 0; bottom: 0;\n background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse"><path d="M 20 0 L 0 0 0 20" fill="none" stroke="rgba(255,255,255,0.02)" stroke-width="1"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>') repeat;\n pointer-events: none;\n z-index: -1;\n }\n \n body::after {\n content: '';\n position: fixed;\n top: 50%; left: 50%;\n width: 500px; height: 500px;\n background: radial-gradient(circle, rgba(103, 233, 233, 0.05) 0%, transparent 70%);\n transform: translate(-50%, -50%);\n pointer-events: none;\n z-index: -1;\n animation: pulse 8s ease-in-out infinite;\n }\n \n @keyframes pulse {\n 0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }\n 50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }\n }\n \n .container {\n background: var(--bg-glass);\n backdrop-filter: blur(20px);\n border-radius: 20px;\n padding: 30px;\n box-shadow: var(--shadow);\n border: 2px solid var(--border-color);\n max-width: 1200px;\n margin: 0 auto;\n animation: modalIn 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);\n position: relative;\n }\n \n .container::before {\n content: '';\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.02) 50%, transparent 70%);\n animation: shimmer 3s infinite;\n pointer-events: none;\n border-radius: 20px;\n }\n \n @keyframes shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n \n @keyframes modalIn {\n from {\n opacity: 0;\n transform: scale(0.9) translateY(-20px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n }\n \n .header {\n text-align: center;\n margin-bottom: 30px;\n position: relative;\n z-index: 1;\n }\n \n .header-top {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 20px;\n }\n \n .header-left {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n \n .logo {\n width: 40px;\n height: 40px;\n filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));\n animation: logoFloat 3s ease-in-out infinite;\n }\n \n @keyframes logoFloat {\n 0%, 100% { transform: translateY(0px); }\n 50% { transform: translateY(-3px); }\n }\n \n .github-link {\n color: var(--text-primary);\n text-decoration: none;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n background: rgba(255,255,255,0.08);\n border: 1px solid rgba(255, 255, 255, 0.12);\n backdrop-filter: blur(10px);\n padding: 8px 16px;\n border-radius: 8px;\n font-weight: 500;\n transition: all 0.3s ease;\n }\n \n .github-link:hover {\n background: rgba(255,255,255,0.15);\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n }\n \n h1 {\n color: var(--text-primary);\n margin-bottom: 10px;\n font-size: 28px;\n font-weight: 700;\n animation: fadeInUp 0.8s ease-out 0.2s both;\n }\n \n .subtitle {\n color: var(--text-secondary);\n font-size: 16px;\n animation: fadeInUp 0.8s ease-out 0.4s both;\n }\n \n @keyframes fadeInUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n \n .status {\n background: rgba(255, 255, 255, 0.05);\n border: 1px solid var(--border-color);\n border-radius: 12px;\n padding: 20px;\n margin-bottom: 20px;\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 15px;\n animation: fadeInUp 0.8s ease-out 0.6s both;\n }\n \n .status-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n \n .status-label {\n font-weight: 600;\n color: var(--text-secondary);\n }\n \n .status-value {\n color: var(--text-primary);\n font-family: var(--font-mono);\n font-size: 14px;\n }\n \n .enabled {\n color: var(--accent-color);\n }\n \n .disabled {\n color: #ff6b6b;\n }\n \n .controls {\n display: flex;\n gap: 15px;\n margin-bottom: 20px;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n animation: fadeInUp 0.8s ease-out 0.8s both;\n }\n \n .controls-left {\n display: flex;\n gap: 15px;\n }\n \n .btn {\n padding: 10px 20px;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n font-family: var(--font-mono);\n position: relative;\n overflow: hidden;\n }\n \n .btn::before {\n content: '';\n position: absolute;\n top: 50%; left: 50%;\n width: 0; height: 0;\n background: rgba(255,255,255,0.2);\n border-radius: 50%;\n transition: all 0.3s ease;\n transform: translate(-50%, -50%);\n }\n \n .btn:hover::before {\n width: 100px; height: 100px;\n }\n \n .btn-primary {\n background: var(--accent-color);\n color: var(--primary-color);\n }\n \n .btn-primary:hover {\n background: var(--accent-hover);\n transform: translateY(-2px);\n box-shadow: 0 8px 25px rgba(103, 233, 233, 0.3);\n }\n \n .btn-danger {\n background: #ff6b6b;\n color: white;\n }\n \n .btn-danger:hover {\n background: #ff5252;\n transform: translateY(-2px);\n box-shadow: 0 8px 25px rgba(255, 107, 107, 0.3);\n }\n \n .btn-secondary {\n background: var(--bg-secondary);\n color: var(--text-secondary);\n border: 1px solid var(--border-color);\n }\n \n .btn-secondary:hover {\n background: rgba(255, 255, 255, 0.15);\n color: var(--text-primary);\n }\n \n .log-container {\n background: rgba(0, 0, 0, 0.5);\n border: 1px solid var(--border-color);\n border-radius: 12px;\n padding: 20px;\n height: 500px;\n overflow-y: auto;\n font-family: var(--font-mono);\n font-size: 13px;\n line-height: 1.4;\n animation: fadeInUp 0.8s ease-out 1s both;\n }\n \n .log-container::-webkit-scrollbar {\n width: 8px;\n }\n \n .log-container::-webkit-scrollbar-track {\n background: rgba(255, 255, 255, 0.1);\n border-radius: 4px;\n }\n \n .log-container::-webkit-scrollbar-thumb {\n background: var(--accent-color);\n border-radius: 4px;\n }\n \n .log-container::-webkit-scrollbar-thumb:hover {\n background: var(--accent-hover);\n }\n \n .log-line {\n color: var(--text-primary);\n margin-bottom: 2px;\n word-break: break-all;\n animation: logSlideIn 0.3s ease-out;\n }\n \n @keyframes logSlideIn {\n from {\n opacity: 0;\n transform: translateX(-10px);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n }\n \n .log-line.debug {\n color: var(--text-secondary);\n }\n \n .log-line.info {\n color: #74c0fc;\n }\n \n .log-line.warn {\n color: #ffd43b;\n }\n \n .log-line.error {\n color: #ff8787;\n }\n \n .timestamp {\n color: var(--text-secondary);\n }\n \n .level {\n font-weight: bold;\n margin: 0 8px;\n }\n \n .empty-state {\n text-align: center;\n color: var(--text-secondary);\n padding: 40px;\n font-style: italic;\n }\n \n .log-count {\n color: var(--text-secondary);\n font-size: 14px;\n }\n </style>\n</head>\n<body>\n <div class="container">\n <div class="header">\n <div class="header-top">\n <div class="header-left">\n <img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />\n <div style="text-align: left;">\n <h1>CloudBase MCP 调试日志</h1>\n <p class="subtitle">实时查看 MCP 服务器运行日志</p>\n </div>\n </div>\n <a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" target="_blank" class="github-link">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">\n <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>\n </svg>\n GitHub\n </a>\n </div>\n </div>\n \n <div class="status">\n <div class="status-item">\n <span class="status-label">日志状态:</span>\n <span class="status-value ${n.enabled?"enabled":"disabled"}">\n ${n.enabled?"🟢 启用":"🔴 禁用"}\n </span>\n </div>\n <div class="status-item">\n <span class="status-label">日志级别:</span>\n <span class="status-value">${n.level}</span>\n </div>\n <div class="status-item">\n <span class="status-label">日志文件:</span>\n <span class="status-value">${n.logFile||"无"}</span>\n </div>\n <div class="status-item">\n <span class="status-label">控制台输出:</span>\n <span class="status-value ${n.useConsole?"enabled":"disabled"}">\n ${n.useConsole?"🟢 启用":"🔴 禁用"}\n </span>\n </div>\n </div>\n \n <div class="controls">\n <div class="controls-left">\n <button class="btn btn-primary" onclick="refreshLogs()">\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 6px;">\n <path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/>\n <path d="M21 3v5h-5"/>\n <path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/>\n <path d="M8 16H3v5"/>\n </svg>\n 刷新日志\n </button>\n <button class="btn btn-danger" onclick="clearLogs()">\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 6px;">\n <path d="M3 6h18"/>\n <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/>\n <path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/>\n </svg>\n 清空日志\n </button>\n <button class="btn btn-secondary" onclick="window.close()">\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 6px;">\n <path d="M18 6L6 18M6 6l12 12"/>\n </svg>\n 关闭\n </button>\n </div>\n <div>\n <span class="log-count">📊 共 ${e.length} 条日志</span>\n </div>\n </div>\n \n <div class="log-container" id="logContainer">\n ${e.length>0?e.map(e=>{const n=e.match(/\[(.*?)\] \[(.*?)\] (.*)/);if(n){const[,e,t,o]=n,r=t.toLowerCase();return`<div class="log-line ${r}"><span class="timestamp">[${e}]</span><span class="level ${r}">[${t}]</span>${o}</div>`}return`<div class="log-line">${e}</div>`}).join(""):'<div class="empty-state">📝 暂无日志记录</div>'}\n </div>\n </div>\n\n <script>\n function refreshLogs() {\n fetch('/api/logs')\n .then(response => response.json())\n .then(data => {\n if (data.success) {\n location.reload();\n }\n })\n .catch(error => {\n alert('刷新日志失败: ' + error.message);\n });\n }\n \n function clearLogs() {\n if (confirm('确定要清空所有日志吗?此操作不可恢复。')) {\n fetch('/api/logs/clear', { method: 'POST' })\n .then(response => response.json())\n .then(data => {\n if (data.success) {\n location.reload();\n } else {\n alert('清空日志失败');\n }\n })\n .catch(error => {\n alert('清空日志失败: ' + error.message);\n });\n }\n }\n \n // 自动滚动到底部\n const logContainer = document.getElementById('logContainer');\n logContainer.scrollTop = logContainer.scrollHeight;\n \n // 每5秒自动刷新\n setInterval(() => {\n const isAtBottom = logContainer.scrollHeight - logContainer.clientHeight <= logContainer.scrollTop + 1;\n \n fetch('/api/logs')\n .then(response => response.json())\n .then(data => {\n if (data.success && data.logs.length > 0) {\n const newContent = data.logs.map(line => {\n const match = line.match(/\\[(.*?)\\] \\[(.*?)\\] (.*)/);\n if (match) {\n const [, timestamp, level, message] = match;\n const levelClass = level.toLowerCase();\n return \`<div class="log-line \${levelClass}"><span class="timestamp">[\${timestamp}]</span><span class="level \${levelClass}">[\${level}]</span>\${message}</div>\`;\n }\n return \`<div class="log-line">\${line}</div>\`;\n }).join('');\n \n logContainer.innerHTML = newContent || '<div class="empty-state">📝 暂无日志记录</div>';\n \n if (isAtBottom) {\n logContainer.scrollTop = logContainer.scrollHeight;\n }\n }\n })\n .catch(error => {\n console.error('获取日志失败:', error);\n });\n }, 5000);\n <\/script>\n</body>\n</html>`}getClarificationHTML(e,n){const t=n||null;return`\n<!DOCTYPE html>\n<html lang="zh-CN">\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>CloudBase AI Toolkit - 需求澄清</title>\n <style>\n @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');\n \n * { margin: 0; padding: 0; box-sizing: border-box; }\n :root {\n --primary-color: #1a1a1a;\n --primary-hover: #000000;\n --accent-color: #67E9E9;\n --accent-hover: #2BCCCC;\n --text-primary: #ffffff;\n --text-secondary: #a0a0a0;\n --border-color: rgba(255, 255, 255, 0.15);\n --bg-secondary: rgba(255, 255, 255, 0.08);\n --bg-glass: rgba(26, 26, 26, 0.95);\n --shadow: 0 25px 50px rgba(0, 0, 0, 0.3), 0 10px 20px rgba(0, 0, 0, 0.2);\n --font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;\n --header-bg: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0d1117 100%);\n }\n \n body {\n font-family: var(--font-mono);\n background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n position: relative;\n overflow-x: hidden;\n overflow-y: auto;\n }\n \n /* Custom scrollbar styles */\n ::-webkit-scrollbar {\n width: 8px;\n }\n \n ::-webkit-scrollbar-track {\n background: rgba(255, 255, 255, 0.05);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb {\n background: var(--accent-color);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb:hover {\n background: var(--accent-hover);\n }\n \n body::before {\n content: '';\n position: fixed;\n top: 0; left: 0; right: 0; bottom: 0;\n background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse"><path d="M 20 0 L 0 0 0 20" fill="none" stroke="rgba(255,255,255,0.02)" stroke-width="1"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>') repeat;\n pointer-events: none;\n z-index: -1;\n }\n \n body::after {\n content: '';\n position: fixed;\n top: 50%; left: 50%;\n width: 500px; height: 500px;\n background: radial-gradient(circle, rgba(103, 233, 233, 0.05) 0%, transparent 70%);\n transform: translate(-50%, -50%);\n pointer-events: none;\n z-index: -1;\n animation: pulse 8s ease-in-out infinite;\n }\n \n @keyframes pulse {\n 0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }\n 50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }\n }\n \n .modal {\n background: var(--bg-glass);\n backdrop-filter: blur(20px);\n border-radius: 20px;\n box-shadow: var(--shadow);\n border: 2px solid var(--border-color);\n width: 100%;\n max-width: 600px;\n overflow: hidden;\n animation: modalIn 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);\n position: relative;\n }\n \n .modal::before {\n content: '';\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.02) 50%, transparent 70%);\n animation: shimmer 3s infinite;\n pointer-events: none;\n }\n \n @keyframes shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n \n @keyframes modalIn {\n from {\n opacity: 0;\n transform: scale(0.9) translateY(-20px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n }\n \n .header {\n background: var(--header-bg);\n color: var(--text-primary);\n padding: 24px 28px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n position: relative;\n overflow: hidden;\n }\n \n .header::before {\n content: '';\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.03) 50%, transparent 70%);\n animation: headerShimmer 4s infinite;\n pointer-events: none;\n }\n \n @keyframes headerShimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n \n .header-left {\n display: flex;\n align-items: center;\n gap: 16px;\n z-index: 1;\n }\n \n .logo {\n width: 32px;\n height: 32px;\n filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));\n animation: logoFloat 3s ease-in-out infinite;\n }\n \n @keyframes logoFloat {\n 0%, 100% { transform: translateY(0px); }\n 50% { transform: translateY(-3px); }\n }\n \n .title {\n font-size: 20px;\n font-weight: 700;\n text-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n \n .github-link {\n color: var(--text-primary);\n text-decoration: none;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n background: rgba(255,255,255,0.08);\n border: 1px solid rgba(255, 255, 255, 0.12);\n backdrop-filter: blur(10px);\n padding: 8px 16px;\n border-radius: 8px;\n font-weight: 500;\n z-index: 1;\n transition: all 0.3s ease;\n }\n \n .github-link:hover {\n background: rgba(255,255,255,0.15);\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n }\n \n .content {\n padding: 32px 24px;\n position: relative;\n }\n \n .content-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary);\n margin-bottom: 8px;\n animation: fadeInUp 0.8s ease-out 0.2s both;\n }\n \n @keyframes fadeInUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n \n .message {\n background: rgba(103, 233, 233, 0.1);\n border: 1px solid var(--accent-color);\n border-left: 4px solid var(--accent-color);\n padding: 20px;\n border-radius: 12px;\n margin-bottom: 24px;\n white-space: pre;\n font-size: 15px;\n line-height: 1.6;\n color: var(--text-primary);\n animation: fadeInUp 0.8s ease-out 0.4s both;\n position: relative;\n overflow: hidden;\n }\n \n .message::before {\n content: '';\n position: absolute;\n top: 0; left: 0;\n width: 100%; height: 2px;\n background: linear-gradient(90deg, var(--accent-color), transparent);\n animation: progress 2s ease-out;\n }\n \n @keyframes progress {\n from { width: 0%; }\n to { width: 100%; }\n }\n \n .options {\n margin-bottom: 24px;\n animation: fadeInUp 0.8s ease-out 0.6s both;\n }\n \n .option-item {\n padding: 16px 20px;\n border: 1px solid var(--border-color);\n border-radius: 12px;\n margin-bottom: 12px;\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n gap: 14px;\n background: rgba(255, 255, 255, 0.03);\n position: relative;\n overflow: hidden;\n color: var(--text-primary);\n }\n \n .option-item::before {\n content: '';\n position: absolute;\n left: 0; top: 0; bottom: 0;\n width: 0;\n background: var(--accent-color);\n transition: width 0.3s ease;\n }\n \n .option-item:hover {\n background: var(--bg-secondary);\n border-color: var(--accent-color);\n transform: translateX(5px);\n }\n \n .option-item:hover::before {\n width: 4px;\n }\n \n .option-item.selected {\n background: rgba(103, 233, 233, 0.1);\n border-color: var(--accent-color);\n transform: translateX(5px);\n }\n \n .option-item.selected::before {\n width: 4px;\n }\n \n .option-icon {\n width: 20px;\n height: 20px;\n color: var(--accent-color);\n flex-shrink: 0;\n animation: iconGlow 2s ease-in-out infinite;\n }\n \n @keyframes iconGlow {\n 0%, 100% { filter: drop-shadow(0 0 2px rgba(103, 233, 233, 0.3)); }\n 50% { filter: drop-shadow(0 0 8px rgba(103, 233, 233, 0.6)); }\n }\n \n .custom-input {\n margin-bottom: 24px;\n animation: fadeInUp 0.8s ease-out 0.8s both;\n }\n \n .custom-input textarea {\n width: 100%;\n min-height: 120px;\n padding: 16px;\n border: 1px solid var(--border-color);\n border-radius: 12px;\n font-size: 15px;\n font-family: var(--font-mono);\n resize: vertical;\n transition: all 0.3s ease;\n line-height: 1.5;\n background: rgba(255, 255, 255, 0.03);\n color: var(--text-primary);\n }\n \n .custom-input textarea::placeholder {\n color: var(--text-secondary);\n }\n \n .custom-input textarea:focus {\n outline: none;\n border-color: var(--accent-color);\n box-shadow: 0 0 0 3px rgba(103, 233, 233, 0.1);\n background: rgba(255, 255, 255, 0.05);\n }\n \n .actions {\n display: flex;\n gap: 12px;\n justify-content: flex-end;\n animation: fadeInUp 0.8s ease-out 1s both;\n }\n \n .btn {\n padding: 12px 20px;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: var(--font-mono);\n position: relative;\n overflow: hidden;\n }\n \n .btn::before {\n content: '';\n position: absolute;\n top: 50%; left: 50%;\n width: 0; height: 0;\n background: rgba(255,255,255,0.2);\n border-radius: 50%;\n transition: all 0.3s ease;\n transform: translate(-50%, -50%);\n }\n \n .btn:hover::before {\n width: 100px; height: 100px;\n }\n \n .btn-primary {\n background: var(--primary-color);\n color: var(--text-primary);\n border: 1px solid var(--border-color);\n }\n \n .btn-primary:hover:not(:disabled) {\n background: var(--primary-hover);\n transform: translateY(-2px);\n box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);\n }\n \n .btn-secondary {\n background: var(--bg-secondary);\n color: var(--text-secondary);\n border: 1px solid var(--border-color);\n }\n \n .btn-secondary:hover {\n background: rgba(255, 255, 255, 0.15);\n color: var(--text-primary);\n }\n \n .btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n \n .loading {\n display: none;\n align-items: center;\n justify-content: center;\n gap: 8px;\n margin-top: 16px;\n color: var(--text-secondary);\n font-size: 14px;\n }\n \n .spinner {\n width: 16px;\n height: 16px;\n border: 2px solid var(--border-color);\n border-top: 2px solid var(--accent-color);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n }\n \n @keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n \n @keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n \n .success-state {\n text-align: center;\n padding: 40px 20px;\n animation: fadeInUp 0.8s ease-out both;\n }\n \n .success-icon {\n margin-bottom: 20px;\n color: var(--accent-color);\n animation: successPulse 2s ease-in-out infinite;\n }\n \n @keyframes successPulse {\n 0%, 100% { \n transform: scale(1);\n filter: drop-shadow(0 0 8px rgba(103, 233, 233, 0.3));\n }\n 50% { \n transform: scale(1.1);\n filter: drop-shadow(0 0 16px rgba(103, 233, 233, 0.6));\n }\n }\n \n .success-title {\n font-size: 24px;\n font-weight: 700;\n color: var(--text-primary);\n margin-bottom: 12px;\n }\n \n .success-message {\n color: var(--text-secondary);\n font-size: 16px;\n line-height: 1.5;\n }\n \n .selected-env-info {\n margin-top: 20px;\n padding: 16px;\n background: rgba(103, 233, 233, 0.1);\n border: 1px solid var(--accent-color);\n border-radius: 12px;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n \n .env-label {\n color: var(--text-secondary);\n font-size: 14px;\n font-weight: 500;\n }\n \n .env-value {\n color: var(--accent-color);\n font-size: 16px;\n font-weight: 600;\n font-family: var(--font-mono);\n }\n </style>\n</head>\n<body>\n <div class="modal">\n <div class="header">\n <div class="header-left">\n <img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />\n <span class="title">CloudBase AI Toolkit</span>\n </div>\n <a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" target="_blank" class="github-link">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">\n <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>\n </svg>\n GitHub\n </a>\n </div>\n\n <div class="content">\n <h1 class="content-title">AI 需要您确认</h1>\n <div class="message">${e}</div>\n \n ${t?`\n <div class="options" id="options">\n ${t.map((e,n)=>`\n <div class="option-item" onclick="selectOption('${e}')" style="animation-delay: ${.1*n}s;">\n <svg class="option-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 014.7-7.6 8.38 8.38 0 013.8-.9h.5a8.48 8.48 0 018 8v.5z"/>\n </svg>\n <span>${e}</span>\n </div>\n `).join("")}\n </div>\n `:""}\n \n <div class="custom-input">\n <textarea id="customInput" placeholder="请输入您的具体需求或建议..." onkeyup="updateSubmitButton()"></textarea>\n </div>\n \n <div class="actions">\n <button class="btn btn-secondary" onclick="cancel()">\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M18 6L6 18M6 6l12 12"/>\n </svg>\n 取消\n </button>\n <button class="btn btn-primary" id="submitBtn" onclick="submit()">\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M20 6L9 17l-5-5"/>\n </svg>\n 确认执行\n </button>\n </div>\n \n <div class="loading" id="loading">\n <div class="spinner"></div>\n <span>正在提交...</span>\n </div>\n </div>\n </div>\n\n <script>\n let selectedOption = null;\n \n function selectOption(option) {\n selectedOption = option;\n \n document.querySelectorAll('.option-item').forEach(item => {\n item.classList.remove('selected');\n });\n event.currentTarget.classList.add('selected');\n \n updateSubmitButton();\n }\n \n function updateSubmitButton() {\n const customInput = document.getElementById('customInput').value.trim();\n const submitBtn = document.getElementById('submitBtn');\n \n if (selectedOption || customInput) {\n submitBtn.disabled = false;\n submitBtn.style.opacity = '1';\n } else {\n submitBtn.disabled = true;\n submitBtn.style.opacity = '0.5';\n }\n }\n \n function submit() {\n const customInput = document.getElementById('customInput').value.trim();\n const data = selectedOption || customInput;\n \n if (!data) return;\n \n document.getElementById('loading').style.display = 'flex';\n document.getElementById('submitBtn').disabled = true;\n \n fetch('/api/submit', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n type: 'clarification',\n data: data\n })\n }).then(response => response.json())\n .then(result => {\n if (result.success) {\n window.close();\n }\n }).catch(err => {\n console.error('Error:', err);\n document.getElementById('loading').style.display = 'none';\n document.getElementById('submitBtn').disabled = false;\n });\n }\n \n function cancel() {\n fetch('/api/cancel', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' }\n }).then(() => {\n window.close();\n });\n }\n \n // Initialize\n updateSubmitButton();\n <\/script>\n</body>\n</html>`}getConfirmationHTML(e,n,t){const o=t||["确认执行","取消操作"];return`\n<!DOCTYPE html>\n<html lang="zh-CN">\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>CloudBase AI Toolkit - 操作确认</title>\n <style>\n @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');\n \n * { margin: 0; padding: 0; box-sizing: border-box; }\n :root {\n --primary-color: #1a1a1a;\n --primary-hover: #000000;\n --accent-color: #67E9E9;\n --accent-hover: #2BCCCC;\n --text-primary: #ffffff;\n --text-secondary: #a0a0a0;\n --border-color: rgba(255, 255, 255, 0.15);\n --bg-secondary: rgba(255, 255, 255, 0.08);\n --bg-glass: rgba(26, 26, 26, 0.95);\n --warning-color: #ff6b6b;\n --warning-bg: rgba(255, 107, 107, 0.1);\n --warning-border: rgba(255, 107, 107, 0.3);\n --shadow: 0 25px 50px rgba(0, 0, 0, 0.3), 0 10px 20px rgba(0, 0, 0, 0.2);\n --font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;\n --header-bg: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0d1117 100%);\n }\n \n body {\n font-family: var(--font-mono);\n background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n position: relative;\n overflow-x: hidden;\n overflow-y: auto;\n }\n \n /* Custom scrollbar styles */\n ::-webkit-scrollbar {\n width: 8px;\n }\n \n ::-webkit-scrollbar-track {\n background: rgba(255, 255, 255, 0.05);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb {\n background: var(--accent-color);\n border-radius: 4px;\n }\n \n ::-webkit-scrollbar-thumb:hover {\n background: var(--accent-hover);\n }\n \n body::before {\n content: '';\n position: fixed;\n top: 0; left: 0; right: 0; bottom: 0;\n background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse"><path d="M 20 0 L 0 0 0 20" fill="none" stroke="rgba(255,255,255,0.02)" stroke-width="1"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>') repeat;\n pointer-events: none;\n z-index: -1;\n }\n \n body::after {\n content: '';\n position: fixed;\n top: 50%; left: 50%;\n width: 500px; height: 500px;\n background: radial-gradient(circle, rgba(255, 107, 107, 0.03) 0%, transparent 70%);\n transform: translate(-50%, -50%);\n pointer-events: none;\n z-index: -1;\n animation: pulse 8s ease-in-out infinite;\n }\n \n @keyframes pulse {\n 0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }\n 50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }\n }\n \n .modal {\n background: var(--bg-glass);\n backdrop-filter: blur(20px);\n border-radius: 20px;\n box-shadow: var(--shadow);\n border: 2px solid var(--border-color);\n width: 100%;\n max-width: 600px;\n overflow: hidden;\n animation: modalIn 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);\n position: relative;\n }\n \n .modal::before {\n content: '';\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.02) 50%, transparent 70%);\n animation: shimmer 3s infinite;\n pointer-events: none;\n }\n \n @keyframes shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n \n @keyframes modalIn {\n from {\n opacity: 0;\n transform: scale(0.9) translateY(-20px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n }\n \n .header {\n background: var(--header-bg);\n color: var(--text-primary);\n padding: 24px 28px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n position: relative;\n overflow: hidden;\n }\n \n .header::before {\n content: '';\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.03) 50%, transparent 70%);\n animation: headerShimmer 4s infinite;\n pointer-events: none;\n }\n \n @keyframes headerShimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n \n .header-left {\n display: flex;\n align-items: center;\n gap: 16px;\n z-index: 1;\n }\n \n .logo {\n width: 32px;\n height: 32px;\n filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));\n animation: logoFloat 3s ease-in-out infinite;\n }\n \n @keyframes logoFloat {\n 0%, 100% { transform: translateY(0px); }\n 50% { transform: translateY(-3px); }\n }\n \n .title {\n font-size: 20px;\n font-weight: 700;\n text-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n \n .github-link {\n color: var(--text-primary);\n text-decoration: none;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n background: rgba(255,255,255,0.08);\n border: 1px solid rgba(255, 255, 255, 0.12);\n backdrop-filter: blur(10px);\n padding: 8px 16px;\n border-radius: 8px;\n font-weight: 500;\n z-index: 1;\n transition: all 0.3s ease;\n }\n \n .github-link:hover {\n background: rgba(255,255,255,0.15);\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n }\n \n .content {\n padding: 32px 24px;\n position: relative;\n }\n \n @keyframes fadeInUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n \n .content-title {\n font-size: 24px;\n margin-bottom: 8px;\n color: var(--text-primary);\n display: flex;\n align-items: center;\n gap: 12px;\n position: relative;\n animation: fadeInUp 0.8s ease-out 0.2s both;\n }\n \n .message {\n background: rgba(103, 233, 233, 0.1);\n border: 1px solid var(--accent-color);\n border-left: 4px solid var(--accent-color);\n padding: 20px;\n border-radius: 12px;\n margin-bottom: 24px;\n font-size: 15px;\n line-height: 1.6;\n color: var(--text-primary);\n animation: fadeInUp 0.8s ease-out 0.4s both;\n position: relative;\n overflow: scroll;\n white-space: pre;\n max-height: 300px;\n }\n \n .message::before {\n content: '';\n position: absolute;\n top: 0; left: 0;\n width: 100%; height: 2px;\n background: linear-gradient(90deg, var(--accent-color), transparent);\n animation: progress 2s ease-out;\n }\n \n @keyframes progress {\n from { width: 0%; }\n to { width: 100%; }\n }\n \n .risks {\n background: var(--warning-bg);\n border: 1px solid var(--warning-border);\n border-radius: 12px;\n padding: 20px;\n margin-bottom: 24px;\n animation: fadeInUp 0.8s ease-out 0.6s both;\n }\n \n .risks-title {\n color: var(--warning-color);\n font-weight: 600;\n margin-bottom: 12px;\n display: flex;\n align-items: center;\n gap: 8px;\n animation: warningGlow 2s ease-in-out infinite;\n }\n \n @keyframes warningGlow {\n 0%, 100% { filter: drop-shadow(0 0 2px rgba(255, 107, 107, 0.3)); }\n 50% { filter: drop-shadow(0 0 8px rgba(255, 107, 107, 0.6)); }\n }\n \n .risk-item {\n color: var(--text-primary);\n margin-bottom: 8px;\n padding-left: 24px;\n position: relative;\n }\n \n .risk-item:before {\n content: "⚠️";\n position: absolute;\n left: 0;\n color: var(--warning-color);\n }\n \n .options {\n margin-bottom: 24px;\n animation: fadeInUp 0.8s ease-out 0.8s both;\n }\n \n .option-item {\n padding: 16px 20px;\n border: 1px solid var(--border-color);\n border-radius: 12px;\n margin-bottom: 12px;\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n gap: 14px;\n background: rgba(255, 255, 255, 0.03);\n position: relative;\n overflow: hidden;\n color: var(--text-primary);\n }\n \n .option-item::before {\n content: '';\n position: absolute;\n left: 0; top: 0; bottom: 0;\n width: 0;\n background: var(--accent-color);\n transition: width 0.3s ease;\n }\n \n .option-item.confirm::before {\n background: var(--accent-color);\n }\n \n .option-item.cancel::before {\n background: var(--warning-color);\n }\n \n .option-item:hover {\n background: var(--bg-secondary);\n transform: translateX(5px);\n }\n \n .option-item:hover::before {\n width: 4px;\n }\n \n .option-item.selected {\n background: rgba(103, 233, 233, 0.1);\n border-color: var(--accent-color);\n transform: translateX(5px);\n }\n \n .option-item.selected.cancel {\n background: rgba(255, 107, 107, 0.1);\n border-color: var(--warning-color);\n }\n \n .option-item.selected::before {\n width: 4px;\n }\n \n .option-icon {\n width: 20px;\n height: 20px;\n color: var(--accent-color);\n flex-shrink: 0;\n }\n \n .option-item.cancel .option-icon {\n color: var(--warning-color);\n }\n \n .loading {\n display: none;\n align-items: center;\n justify-content: center;\n gap: 8px;\n margin-top: 16px;\n color: var(--text-secondary);\n font-size: 14px;\n animation: fadeInUp 0.8s ease-out 1s both;\n }\n \n .spinner {\n width: 16px;\n height: 16px;\n border: 2px solid var(--border-color);\n border-top: 2px solid var(--accent-color);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n }\n \n @keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n </style>\n</head>\n<body>\n <div class="modal">\n <div class="header">\n <div class="header-left">\n <img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />\n <span class="title">CloudBase AI Toolkit</span>\n </div>\n <a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" target="_blank" class="github-link">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">\n <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>\n </svg>\n GitHub\n </a>\n </div>\n\n <div class="content">\n <h1 class="content-title">\n <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/>\n <line x1="12" y1="9" x2="12" y2="13"/>\n <line x1="12" y1="17" x2="12.01" y2="17"/>\n </svg>\n 操作确认\n </h1>\n <div class="message">${e}</div>\n \n ${n&&n.length>0?`\n <div class="risks">\n <div class="risks-title">\n <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/>\n <line x1="12" y1="9" x2="12" y2="13"/>\n <line x1="12" y1="17" x2="12.01" y2="17"/>\n </svg>\n 风险提示\n </div>\n ${n.map(e=>`<div class="risk-item">${e}</div>`).join("")}\n </div>\n `:""}\n \n <div class="options">\n ${o.map((e,n)=>{const t=e.includes("取消")||e.toLowerCase().includes("cancel");return`\n <div class="option-item ${t?"cancel":"confirm"}" onclick="selectOption('${e}')" style="animation-delay: ${.1*n}s;">\n <svg class="option-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n ${t?'<path d="M18 6L6 18M6 6l12 12"/>':'<path d="M20 6L9 17l-5-5"/>'}\n </svg>\n <span>${e}</span>\n </div>\n `}).join("")}\n </div>\n \n <div class="loading" id="loading">\n <div class="spinner"></div>\n <span>正在处理...</span>\n </div>\n </div>\n </div>\n\n <script>\n let selectedOption = null;\n \n function selectOption(option) {\n selectedOption = option;\n \n document.querySelectorAll('.option-item').forEach(item => {\n item.classList.remove('selected');\n });\n event.currentTarget.classList.add('selected');\n \n // Auto submit after selection\n setTimeout(() => {\n submit();\n }, 500);\n }\n \n function submit() {\n if (!selectedOption) return;\n \n document.getElementById('loading').style.display = 'flex';\n \n const isConfirmed = !selectedOption.includes('取消') && !selectedOption.toLowerCase().includes('cancel');\n \n fetch('/api/submit', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n type: 'confirmation',\n data: {\n confirmed: isConfirmed,\n option: selectedOption\n }\n })\n }).then(response => response.json())\n .then(result => {\n if (result.success) {\n window.close();\n }\n }).catch(err => {\n console.error('Error:', err);\n document.getElementById('loading').style.display = 'none';\n });\n }\n \n function cancel() {\n fetch('/api/cancel', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' }\n }).then(() => {\n window.close();\n });\n }\n <\/script>\n</body>\n</html>`}get running(){return this.isRunning}get currentPort(){return this.port}}n.InteractiveServer=d;let u=null;function p(e){return u?e&&!u.mcpServer&&(u.mcpServer=e):u=new d(e),u}},357:e=>{e.exports=a},363:function(e,n,t){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.wrapServerWithTelemetry=function(e){const n=e.registerTool.bind(e);e.registerTool=function(t,o,d){if(!(0,s.shouldRegisterTool)(t))return void(0,a.debug)(`Cloud mode: skipping registration of incompatible tool: ${t}`);(0,a.debug)(`Registering tool: ${t}`,{toolConfig:o});const u=function(e,n,t){return async o=>{const s=Date.now();let d,u,p=!1;try{(0,a.debug)(`开始执行工具: ${e}`,{args:l(o)});const t=await n(o);return p=!0,(0,a.debug)(`工具执行成功: ${e}`,{duration:Date.now()-s}),t}catch(n){p=!1,d=n instanceof Error?n.message:String(n),u="object"==typeof n&&n&&"requestId"in n?n.requestId:"",(0,a.debug)(`工具执行失败: ${e}`,{error:d,duration:Date.now()-s});const r=await async function(e,n,t,o,r){const{requestId:s,ide:d}=r||{};let u="";try{const e=await(0,i.getEnvId)(o);e&&(u=`\n## 环境ID\n${e}\n`)}catch(e){(0,a.debug)("无法获取环境ID:",e)}const p=`MCP工具错误: ${e}`,g=`## 错误描述\n工具 \`${e}\` 执行时发生错误\n\n## 错误信息\n\`\`\`\n${n}\n\`\`\`\n${u}\n## 环境信息\n- 操作系统: ${c.default.type()} ${c.default.release()}\n- Node.js版本: ${process.version}\n- MCP 版本:${process.env.npm_package_version||"1.8.36"}\n- 系统架构: ${c.default.arch()}\n- 时间: ${(new Date).toISOString()}\n- 请求ID: ${s}\n- 集成IDE: ${d}\n\n## 工具参数\n\`\`\`json\n${JSON.stringify(l(t),null,2)}\n\`\`\`\n\n## 复现步骤\n1. 使用工具: ${e}\n2. 传入参数: 上述参数信息\n3. 出现错误\n\n## 期望行为\n[请描述您期望的正确行为]\n\n## 其他信息\n[如有其他相关信息,请在此补充]\n`;return`https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/issues/new?title=${encodeURIComponent(p)}&body=${encodeURIComponent(g)}`}(e,d,o,t.cloudBaseOptions,{requestId:"object"==typeof n&&n&&"requestId"in n?n.requestId:"",ide:t.ide||process.env.INTEGRATION_IDE||""}),g=(Error,new Error(`${d}\n\n🔗 遇到问题?请复制以下链接到浏览器打开\n即可自动携带错误详情快速创建 GitHub Issue:\n${r}`));throw n instanceof Error&&(g.stack=n.stack,g.name=n.name),g}finally{const n=Date.now()-s;(0,r.reportToolCall)({toolName:e,success:p,duration:n,error:d,inputParams:l(o),cloudBaseOptions:t.cloudBaseOptions,ide:t.ide||process.env.INTEGRATION_IDE})}}}(t,d,e);return n(t,o,u)}};const r=t(880),a=t(39),i=t(431),s=t(684),c=o(t(116));function l(e){if(!e||"object"!=typeof e)return e;const n={...e},t=["password","token","secret","key","auth","localPath","filePath","content","code","secretId","secretKey","envId"];return function e(n){if(Array.isArray(n))return n.map(e);if(n&&"object"==typeof n){const o={};for(const[r,a]of Object.entries(n)){const n=r.toLowerCase(),i=t.some(e=>n.includes(e));o[r]=i?"[REDACTED]":e(a)}return o}return n}(n)}},421:e=>{e.exports=i},422:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.warn=n.error=n.info=n.reportToolCall=n.reportToolkitLifecycle=n.telemetryReporter=n.StdioServerTransport=void 0,n.createCloudBaseMcpServer=x,n.getDefaultServer=function(){return x()};const o=t(619),r=t(622),a=t(936),i=t(628),s=t(279),c=t(97),l=t(848),d=t(215),u=t(556),p=t(461),g=t(862),m=t(363),f=t(319),b=t(760),h=t(684),y=["env","database","functions","hosting","storage","setup","interactive","rag","gateway","download","security-rule","invite-code"],v={env:{name:"env",register:r.registerEnvTools},database:{name:"database",register:i.registerDatabaseTools},functions:{name:"functions",register:a.registerFunctionTools},hosting:{name:"hosting",register:s.registerHostingTools},storage:{name:"storage",register:l.registerStorageTools},setup:{name:"setup",register:u.registerSetupTools},interactive:{name:"interactive",register:p.registerInteractiveTools},rag:{name:"rag",register:d.registerRagTools},download:{name:"download",register:c.registerDownloadTools},gateway:{name:"gateway",register:f.registerGatewayTools},"security-rule":{name:"security-rule",register:g.registerSecurityRuleTools},"invite-code":{name:"invite-code",register:b.registerInviteCodeTools}};function x(e){const{name:n="cloudbase-mcp",version:t="1.0.0",enableTelemetry:r=!0,cloudBaseOptions:a,cloudMode:i=!1,ide:s}=e??{};i&&(0,h.enableCloudMode)();const c=new o.McpServer({name:n,version:t},{capabilities:{tools:{},..."CodeBuddy"===s?{logging:{}}:{}}});a&&(c.cloudBaseOptions=a),s&&(c.ide=s),r&&(0,m.wrapServerWithTelemetry)(c);const l=function(){const e=process.env.CLOUDBASE_MCP_PLUGINS_ENABLED,n=process.env.CLOUDBASE_MCP_PLUGINS_DISABLED;let t;if(t=e?e.split(",").map(e=>e.trim()):[...y],n){const e=n.split(",").map(e=>e.trim());t=t.filter(n=>!e.includes(n))}return t}();for(const e of l){const n=v[e];n&&n.register(c)}return c}var w=t(448);Object.defineProperty(n,"StdioServerTransport",{enumerable:!0,get:function(){return w.StdioServerTransport}});var I=t(880);Object.defineProperty(n,"telemetryReporter",{enumerable:!0,get:function(){return I.telemetryReporter}}),Object.defineProperty(n,"reportToolkitLifecycle",{enumerable:!0,get:function(){return I.reportToolkitLifecycle}}),Object.defineProperty(n,"reportToolCall",{enumerable:!0,get:function(){return I.reportToolCall}});var S=t(39);Object.defineProperty(n,"info",{enumerable:!0,get:function(){return S.info}}),Object.defineProperty(n,"error",{enumerable:!0,get:function(){return S.error}}),Object.defineProperty(n,"warn",{enumerable:!0,get:function(){return S.warn}})},431:function(e,n,t){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.envManager=void 0,n.getEnvId=async function(e){return e?.envId?((0,s.debug)("使用传入的 envId:",e.envId),e.envId):c.getEnvId()},n.resetCloudBaseManagerCache=function(){c.reset()},n.getCloudBaseManager=async function(e={}){const{requireEnvId:n=!0,cloudBaseOptions:t}=e;if(t)return(0,s.debug)("使用传入的 CloudBase 配置"),l(t);try{const e=await(0,r.getLoginState)(),{envId:t,secretId:o,secretKey:a,token:s}=e;let l;return n&&(l=await c.getEnvId()),new i.default({secretId:o,secretKey:a,envId:l||t,token:s,proxy:process.env.http_proxy})}catch(e){throw(0,s.error)("Failed to initialize CloudBase Manager:",e instanceof Error?e.message:String(e)),e}},n.createCloudBaseManagerWithOptions=l;const r=t(291),a=t(461),i=o(t(665)),s=t(39),c=new class{cachedEnvId=null;envIdPromise=null;reset(){this.cachedEnvId=null,this.envIdPromise=null,delete process.env.CLOUDBASE_ENV_ID}async getEnvId(){if(this.cachedEnvId)return(0,s.debug)("使用内存缓存的环境ID:",this.cachedEnvId),this.cachedEnvId;if(this.envIdPromise)return this.envIdPromise;this.envIdPromise=this._fetchEnvId();const e=new Promise((e,n)=>{const t=setTimeout(()=>{clearTimeout(t),n(new Error("EnvId 获取超时(600秒)"))},6e5)});try{return await Promise.race([this.envIdPromise,e])}catch(e){throw this.envIdPromise=null,e}}async _fetchEnvId(){try{if(process.env.CLOUDBASE_ENV_ID)return(0,s.debug)("使用进程环境变量的环境ID:",process.env.CLOUDBASE_ENV_ID),this.cachedEnvId=process.env.CLOUDBASE_ENV_ID,this.cachedEnvId;const e=await(0,a.loadEnvIdFromUserConfig)();if(e)return(0,s.debug)("从配置文件读取到环境ID:",e),this._setCachedEnvId(e),e;(0,s.debug)("未找到环境ID,尝试自动设置...");const n=await(0,a.autoSetupEnvironmentId)();if(!n)throw new Error("CloudBase Environment ID not found after auto setup. Please set CLOUDBASE_ENV_ID or run setupEnvironmentId tool.");return(0,s.debug)("自动设置环境ID成功:",n),this._setCachedEnvId(n),n}finally{this.envIdPromise=null}}_setCachedEnvId(e){this.cachedEnvId=e,process.env.CLOUDBASE_ENV_ID=e,(0,s.debug)("已更新环境ID缓存:",e)}async setEnvId(e){this._setCachedEnvId(e),await(0,a.saveEnvIdToUserConfig)(e),(0,s.debug)("手动设置环境ID并保存到文件:",e)}};function l(e){return(0,s.debug)("使用传入的 CloudBase 配置创建 manager:",e),new i.default({secretId:e.secretId,secretKey:e.secretKey,envId:e.envId,token:e.token,proxy:e.proxy||process.env.http_proxy,region:e.region,envType:e.envType})}n.envManager=c},448:e=>{e.exports=s},461:function(e,n,t){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.registerInteractiveTools=function(e){e.registerTool("interactiveDialog",{title:"交互式对话",description:"统一的交互式对话工具,支持需求澄清和任务确认,当需要和用户确认下一步的操作的时候,可以调用这个工具的clarify,如果有敏感的操作,需要用户确认,可以调用这个工具的confirm",inputSchema:{type:r.z.enum(["clarify","confirm"]).describe("交互类型: clarify=需求澄清, confirm=任务确认"),message:r.z.string().optional().describe("对话消息内容"),options:r.z.array(r.z.string()).optional().describe("可选的预设选项"),forceUpdate:r.z.boolean().optional().describe("是否强制更新环境ID配置"),risks:r.z.array(r.z.string()).optional().describe("操作风险提示")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!1,category:"interactive"}},async({type:n,message:t,options:o,forceUpdate:r=!1,risks:i})=>{try{switch(n){case"clarify":{if(!t)throw new Error("需求澄清必须提供message参数");const n=(0,a.getInteractiveServer)(e),r=await n.clarifyRequest(t,o);return r.cancelled?{content:[{type:"text",text:"用户取消了需求澄清"}]}:{content:[{type:"text",text:`📝 用户澄清反馈:\n${r.data}`}]}}case"confirm":{if(!t)throw new Error("任务确认必须提供message参数");let n=`🎯 即将执行任务:\n${t}`;i&&i.length>0&&(n+=`\n\n⚠️ 风险提示:\n${i.map(e=>`• ${e}`).join("\n")}`),n+="\n\n是否继续执行此任务?";const r=o||["确认执行","取消操作","需要修改任务"],s=(0,a.getInteractiveServer)(e),c=await s.clarifyRequest(n,r);return c.cancelled||c.data&&c.data.includes&&c.data.includes("取消")?{content:[{type:"text",text:"❌ 用户取消了任务执行"}]}:{content:[{type:"text",text:`✅ 用户确认: ${c.data}`}]}}default:throw new Error(`不支持的交互类型: ${n}`)}}catch(e){return{content:[{type:"text",text:`交互对话出错: ${e instanceof Error?e.message:String(e)}`}]}}})},n._promptAndSetEnvironmentId=p,n.saveEnvIdToUserConfig=m,n.loadEnvIdFromUserConfig=async function(){const e=g();try{const n=await l.default.readFile(e,"utf8"),t=JSON.parse(n).envId||null;return t?(0,c.debug)("从配置文件加载环境ID:",t):(0,c.warn)(`Config file ${e} found, but 'envId' property is missing or empty.`),t}catch(n){return"ENOENT"!==n.code?(0,c.warn)(`Failed to load envId from config file at ${e}. Error: ${n.message}`):(0,c.debug)(`Env config file not found at ${e}, which is expected if not set.`),null}},n.clearUserEnvId=async function(){const e=g();try{await l.default.unlink(e),(0,c.debug)("环境ID配置文件已删除:",e)}catch(n){(0,c.debug)("环境ID配置文件不存在或已清理:",e)}},n.autoSetupEnvironmentId=async function(){try{const{selectedEnvId:e,cancelled:n,error:t,noEnvs:o}=await p(!0,void 0);return t||o||n?((0,c.debug)("Auto setup environment ID interrupted or failed silently.",{error:t,noEnvs:o,cancelled:n}),null):((0,c.debug)("Auto setup environment ID successful.",{selectedEnvId:e}),e)}catch(e){return console.error("自动配置环境ID时出错:",e),null}};const r=t(971),a=t(341),i=t(431),s=t(291),c=t(39),l=o(t(932)),d=o(t(521)),u=o(t(116));async function p(e,n){const t=await(0,s.getLoginState)();if((0,c.debug)("loginState",t),!t)return(0,c.debug)("请先登录云开发账户"),{selectedEnvId:null,cancelled:!1,error:"请先登录云开发账户"};const o=await(0,i.getCloudBaseManager)({requireEnvId:!1});let r;try{r=await o.env.listEnvs()}catch(e){(0,c.debug)("获取环境ID时出错:",e)}(0,c.debug)("envResult",r);const{EnvList:l}=r||{};let d=null;if(e&&l&&1===l.length&&l[0].EnvId)d=l[0].EnvId;else{const e=(0,a.getInteractiveServer)(n),t=await e.collectEnvId(l||[]);if(t.cancelled)return{selectedEnvId:null,cancelled:!0};d=t.data}return d&&(await m(d),(0,c.debug)("环境ID已保存到配置文件:",d)),{selectedEnvId:d,cancelled:!1}}function g(){return d.default.join(u.default.homedir(),".cloudbase-env-id")}async function m(e){const n=g();try{const t={envId:e,updatedAt:(new Date).toISOString(),version:"1.0"};await l.default.writeFile(n,JSON.stringify(t,null,2),"utf8"),(0,c.debug)("环境ID配置已保存到文件:",n)}catch(e){throw console.error("保存环境ID配置失败:",e),e}}},521:e=>{e.exports=c},556:function(e,n,t){var o,r=this&&this.__createBinding||(Object.create?function(e,n,t,o){void 0===o&&(o=t);var r=Object.getOwnPropertyDescriptor(n,t);r&&!("get"in r?!n.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return n[t]}}),Object.defineProperty(e,o,r)}:function(e,n,t,o){void 0===o&&(o=t),e[o]=n[t]}),a=this&&this.__setModuleDefault||(Object.create?function(e,n){Object.defineProperty(e,"default",{enumerable:!0,value:n})}:function(e,n){e.default=n}),i=this&&this.__importStar||(o=function(e){return o=Object.getOwnPropertyNames||function(e){var n=[];for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[n.length]=t);return n},o(e)},function(e){if(e&&e.__esModule)return e;var n={};if(null!=e)for(var t=o(e),i=0;i<t.length;i++)"default"!==t[i]&&r(n,e,t[i]);return a(n,e),n}),s=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.registerSetupTools=function(e){e.registerTool("downloadTemplate",{title:"下载项目模板",description:"自动下载并部署CloudBase项目模板。\n\n支持的模板:\n- react: React + CloudBase 全栈应用模板\n- vue: Vue + CloudBase 全栈应用模板\n- miniprogram: 微信小程序 + 云开发模板 \n- uniapp: UniApp + CloudBase 跨端应用模板\n- rules: 只包含AI编辑器配置文件(包含Cursor、WindSurf、CodeBuddy等所有主流编辑器配置),适合在已有项目中补充AI编辑器配置\n\n支持的IDE类型:\n- all: 下载所有IDE配置(默认)\n- cursor: Cursor AI编辑器\n- windsurf: WindSurf AI编辑器\n- codebuddy: CodeBuddy AI编辑器\n- claude-code: Claude Code AI编辑器\n- cline: Cline AI编辑器\n- gemini-cli: Gemini CLI\n- opencode: OpenCode AI编辑器\n- qwen-code: 通义灵码\n- baidu-comate: 百度Comate\n- openai-codex-cli: OpenAI Codex CLI\n- augment-code: Augment Code\n- github-copilot: GitHub Copilot\n- roocode: RooCode AI编辑器\n- tongyi-lingma: 通义灵码\n- trae: Trae AI编辑器\n- vscode: Visual Studio Code\n\n特别说明:\n- rules 模板会自动包含当前 mcp 版本号信息(版本号:1.8.36),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)",inputSchema:{template:c.z.enum(["react","vue","miniprogram","uniapp","rules"]).describe("要下载的模板类型"),ide:c.z.enum(h).optional().default("all").describe("指定要下载的IDE类型,默认为all(下载所有IDE配置)"),overwrite:c.z.boolean().optional().describe("是否覆盖已存在的文件,默认为false(不覆盖)")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"setup"}},async({template:e,ide:n="all",overwrite:t=!1})=>{try{const o=function(e){if("all"===e)return{valid:!0};const n=h.filter(e=>"all"!==e);return n.includes(e)?{valid:!0}:{valid:!1,error:`不支持的IDE类型: ${e}`,supportedIDEs:n}}(n);if(!o.valid){const e=o.supportedIDEs?.join(", ")||"";return{content:[{type:"text",text:`❌ ${o.error}\n\n支持的IDE类型: ${e}`}]}}const r=b[e];if(!r)return{content:[{type:"text",text:`❌ 不支持的模板类型: ${e}`}]};const a=l.mkdtempSync(u.join(p.tmpdir(),"cloudbase-template-")),i=u.join(a,"template.zip"),s=u.join(a,"extracted");await w(r.url,i),await async function(e,n){try{await d.mkdir(n,{recursive:!0}),new f.default(e).extractAllTo(n,!0)}catch(e){throw new Error(`解压失败: ${e instanceof Error?e.message:"未知错误"}`)}}(i,s);const c=await I(s),g=function(e,n){if("all"===n)return e;const t=y[n];if(!t)return e;const o=v.filter(e=>!t.includes(e));return e.filter(e=>!o.includes(e))}(c,n),m=process.env.WORKSPACE_FOLDER_PATHS;let E=[],T=0,O=0,C=0;const k=[];if(m){let o=0;for(const n of g){const r=u.join(s,n),a=u.join(m,n),i=await S(r,a,t,e);i.copied?("overwritten"===i.action?O++:T++,E.push(a)):("protected"===i.action?o++:C++,E.push(r))}const a=x[n]||n;k.push(`✅ ${r.description} (${a}) 同步完成`),k.push(`📁 临时目录: ${s}`),k.push(`🔍 文件过滤: ${c.length} → ${g.length} 个文件`);const i=[];T>0&&i.push(`新建 ${T} 个文件`),O>0&&i.push(`覆盖 ${O} 个文件`),o>0&&i.push(`保护 ${o} 个文件(README.md)`),C>0&&i.push(`跳过 ${C} 个已存在文件`),i.length>0&&k.push(`📊 ${i.join(",")}`),(t||O>0||C>0)&&k.push("🔄 覆盖模式: "+(t?"启用":"禁用"))}else{E=g.map(e=>u.join(s,e));const e=x[n]||n;k.push(`✅ ${r.description} (${e}) 下载完成`),k.push(`📁 保存在临时目录: ${s}`),k.push(`🔍 文件过滤: ${c.length} → ${g.length} 个文件`),k.push("💡 如需将模板(包括隐藏文件)复制到项目目录,请确保复制时包含所有隐藏文件。")}return k.push(""),k.push("📋 文件列表:"),E.forEach(e=>{k.push(`${e}`)}),{content:[{type:"text",text:k.join("\n")}]}}catch(e){return{content:[{type:"text",text:`❌ 下载模板失败: ${e instanceof Error?e.message:"未知错误"}`}]}}})};const c=t(971),l=i(t(421)),d=i(t(932)),u=i(t(521)),p=i(t(116)),g=i(t(871)),m=i(t(782)),f=s(t(872)),b={react:{description:"React + CloudBase 全栈应用模板",url:"https://static.cloudbase.net/cloudbase-examples/web-cloudbase-react-template.zip"},vue:{description:"Vue + CloudBase 全栈应用模板",url:"https://static.cloudbase.net/cloudbase-examples/web-cloudbase-vue-template.zip"},miniprogram:{description:"微信小程序 + 云开发模板",url:"https://static.cloudbase.net/cloudbase-examples/miniprogram-cloudbase-miniprogram-template.zip"},uniapp:{description:"UniApp + CloudBase 跨端应用模板",url:"https://static.cloudbase.net/cloudbase-examples/universal-cloudbase-uniapp-template.zip"},rules:{description:"AI编辑器配置模板(包含所有主流编辑器配置)",url:"https://static.cloudbase.net/cloudbase-examples/web-cloudbase-project.zip"}},h=["all","cursor","windsurf","codebuddy","claude-code","cline","gemini-cli","opencode","qwen-code","baidu-comate","openai-codex-cli","augment-code","github-copilot","roocode","tongyi-lingma","trae","vscode"],y={cursor:[".cursor/rules/cloudbase-rules.mdc",".cursor/mcp.json"],windsurf:[".windsurf/rules/cloudbase-rules.md"],codebuddy:[".rules/cloudbase-rules.md"],"claude-code":["CLAUDE.md",".mcp.json",".claude/settings.local.json",".claude/commands/prototype.md",".claude/commands/spec.md",".claude/commands/no_spec.md"],cline:[".clinerules/cloudbase-rules.mdc"],"gemini-cli":[".gemini/GEMINI.md",".gemini/settings.json"],opencode:[".opencode.json"],"qwen-code":[".qwen/QWEN.md",".qwen/settings.json"],"baidu-comate":[".comate/rules/cloudbase-rules.mdr",".comate/rules/cloudbaase-rules.mdr",".comate/mcp.json"],"openai-codex-cli":[".codex/config.toml","AGENTS.md"],"augment-code":[".augment-guidelines"],"github-copilot":[".github/copilot-instructions.md"],roocode:[".roo/rules/cloudbaase-rules.md",".roo/mcp.json"],"tongyi-lingma":[".lingma/rules/cloudbaase-rules.md"],trae:[".trae/rules/cloudbase-rules.md"],vscode:[".vscode/mcp.json",".vscode/settings.json"]},v=Array.from(new Set(Object.values(y).flat()));y.all=v;const x={all:"所有IDE配置",cursor:"Cursor AI编辑器",windsurf:"WindSurf AI编辑器",codebuddy:"CodeBuddy AI编辑器","claude-code":"Claude Code AI编辑器",cline:"Cline AI编辑器","gemini-cli":"Gemini CLI",opencode:"OpenCode AI编辑器","qwen-code":"通义灵码","baidu-comate":"百度Comate","openai-codex-cli":"OpenAI Codex CLI","augment-code":"Augment Code","github-copilot":"GitHub Copilot",roocode:"RooCode AI编辑器","tongyi-lingma":"通义灵码",trae:"Trae AI编辑器",vscode:"Visual Studio Code"};async function w(e,n){return new Promise((t,o)=>{(e.startsWith("https:")?g:m).get(e,e=>{if(200===e.statusCode){const r=l.createWriteStream(n);e.pipe(r),r.on("finish",()=>{r.close(),t()}),r.on("error",o)}else 302===e.statusCode||301===e.statusCode?e.headers.location?w(e.headers.location,n).then(t).catch(o):o(new Error("重定向但没有location header")):o(new Error(`下载失败,状态码: ${e.statusCode}`))}).on("error",o)})}async function I(e,n=e){const t=[],o=await d.readdir(e,{withFileTypes:!0});for(const r of o){const o=u.join(e,r.name);if(r.isDirectory()){const e=await I(o,n);t.push(...e)}else t.push(u.relative(n,o))}return t}async function S(e,n,t=!1,o){try{const r=l.existsSync(n);return o&&function(e,n,t){const o="readme.md"===u.basename(n).toLowerCase(),r="rules"===e,a=l.existsSync(n);return o&&r&&a&&!t}(o,n,t)?{copied:!1,reason:"README.md 文件已存在,已保护",action:"protected"}:r&&!t?{copied:!1,reason:"文件已存在",action:"skipped"}:(await d.mkdir(u.dirname(n),{recursive:!0}),await d.copyFile(e,n),{copied:!0,action:r?"overwritten":"created"})}catch(e){return{copied:!1,reason:`复制失败: ${e instanceof Error?e.message:"未知错误"}`}}}},619:e=>{e.exports=l},622:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerEnvTools=function(e){const n=e.cloudBaseOptions,t=()=>(0,r.getCloudBaseManager)({cloudBaseOptions:n});e.registerTool?.("login",{title:"登录云开发",description:"登录云开发环境并选择要使用的环境",inputSchema:{forceUpdate:o.z.boolean().optional().describe("是否强制重新选择环境")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"env"}},async({forceUpdate:n=!1})=>{try{const{selectedEnvId:t,cancelled:o,error:r,noEnvs:a}=await(0,i._promptAndSetEnvironmentId)(n,e);if((0,s.debug)("login",{selectedEnvId:t,cancelled:o,error:r,noEnvs:a}),r)return{content:[{type:"text",text:r}]};if(a)return{content:[{type:"text",text:"当前账户下暂无可用的云开发环境,请先在腾讯云控制台创建环境 https://tcb.cloud.tencent.com/dev?from=AIToolkit"}]};if(o)return{content:[{type:"text",text:"用户取消了登录"}]};if(t)return{content:[{type:"text",text:`✅ 登录成功,当前环境: ${t}`}]};throw new Error("登录失败")}catch(e){return{content:[{type:"text",text:`登录失败: ${e instanceof Error?e.message:String(e)}`}]}}}),e.registerTool?.("logout",{title:"退出登录",description:"退出云开发环境",inputSchema:{confirm:o.z.literal("yes").describe("确认操作,默认传 yes")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1,category:"env"}},async()=>{try{return await(0,a.logout)(),await(0,i.clearUserEnvId)(),(0,r.resetCloudBaseManagerCache)(),{content:[{type:"text",text:"✅ 已退出登录"}]}}catch(e){return{content:[{type:"text",text:`退出失败: ${e instanceof Error?e.message:String(e)}`}]}}}),e.registerTool?.("envQuery",{title:"环境查询",description:"查询云开发环境相关信息,支持查询环境列表、当前环境信息和安全域名。(原工具名:listEnvs/getEnvInfo/getEnvAuthDomains,为兼容旧AI规则可继续使用这些名称)",inputSchema:{action:o.z.enum(["list","info","domains"]).describe("查询类型:list=环境列表,info=当前环境信息,domains=安全域名列表")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"env"}},async({action:e})=>{try{let o;switch(e){case"list":try{const e=await(0,r.getCloudBaseManager)({cloudBaseOptions:n,requireEnvId:!1});o=await e.env.listEnvs()}catch(e){return(0,s.debug)("获取环境列表时出错:",e),{content:[{type:"text",text:"当前账户下暂无可用的云开发环境,请先在腾讯云控制台创建环境 https://tcb.cloud.tencent.com/dev?from=AIToolkit \n错误信息:"+(e instanceof Error?e.message:String(e))}]}}break;case"info":const a=await t();o=await a.env.getEnvInfo();break;case"domains":const i=await t();o=await i.env.getEnvAuthDomains();break;default:throw new Error(`不支持的查询类型: ${e}`)}return{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}catch(e){return{content:[{type:"text",text:`环境查询失败: ${e instanceof Error?e.message:String(e)}`}]}}}),e.registerTool?.("envDomainManagement",{title:"环境域名管理",description:"管理云开发环境的安全域名,支持添加和删除操作。(原工具名:createEnvDomain/deleteEnvDomain,为兼容旧AI规则可继续使用这些名称)",inputSchema:{action:o.z.enum(["create","delete"]).describe("操作类型:create=添加域名,delete=删除域名"),domains:o.z.array(o.z.string()).describe("安全域名数组")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"env"}},async({action:e,domains:n})=>{try{const o=await t();let r;switch(e){case"create":r=await o.env.createEnvDomain(n);break;case"delete":r=await o.env.deleteEnvDomain(n);break;default:throw new Error(`不支持的操作类型: ${e}`)}return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}catch(e){return{content:[{type:"text",text:`域名管理操作失败: ${e instanceof Error?e.message:String(e)}`}]}}}),e.registerTool?.("updateEnvInfo",{title:"更新环境信息",description:"更新云开发环境信息",inputSchema:{alias:o.z.string().describe("环境别名")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"env"}},async({alias:e})=>{const n=await t(),o=await n.env.updateEnvInfo(e);return{content:[{type:"text",text:JSON.stringify(o,null,2)}]}})};const o=t(971),r=t(431),a=t(291),i=t(461),s=t(39)},628:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerDatabaseTools=function(e){const n=e.cloudBaseOptions,t=()=>(0,r.getCloudBaseManager)({cloudBaseOptions:n});e.registerTool?.("createCollection",{title:"创建数据库集合",description:"创建一个新的云开发数据库集合",inputSchema:{collectionName:o.z.string().describe("云开发数据库集合名称")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"database"}},async({collectionName:e})=>{try{const n=await t(),o=await n.database.createCollection(e);return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:o.RequestId,message:"云开发数据库集合创建成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"云开发数据库集合创建失败"},null,2)}]}}}),e.registerTool?.("collectionQuery",{title:"集合查询",description:"数据库集合的查询操作,支持检查存在性、查看详情和列表查询。(原工具名:checkCollectionExists/describeCollection/listCollections,为兼容旧AI规则可继续使用这些名称)",inputSchema:{action:o.z.enum(["check","describe","list"]).describe("操作类型:check=检查是否存在,describe=查看详情,list=列表查询"),collectionName:o.z.string().optional().describe("集合名称(check、describe操作时必填)"),limit:o.z.number().optional().describe("返回数量限制(list操作时可选)"),offset:o.z.number().optional().describe("偏移量(list操作时可选)")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"database"}},async({action:e,collectionName:n,limit:o,offset:r})=>{try{const a=await t();let i;switch(e){case"check":if(!n)throw new Error("检查集合时必须提供 collectionName");return i=await a.database.checkCollectionExists(n),{content:[{type:"text",text:JSON.stringify({success:!0,exists:i.Exists,requestId:i.RequestId,message:i.Exists?"云开发数据库集合已存在":"云开发数据库集合不存在"},null,2)}]};case"describe":if(!n)throw new Error("查看集合详情时必须提供 collectionName");return i=await a.database.describeCollection(n),{content:[{type:"text",text:JSON.stringify({success:!0,requestId:i.RequestId,indexNum:i.IndexNum,indexes:i.Indexes,message:"获取云开发数据库集合信息成功"},null,2)}]};case"list":return i=await a.database.listCollections({MgoOffset:r,MgoLimit:o}),{content:[{type:"text",text:JSON.stringify({success:!0,requestId:i.RequestId,collections:i.Collections,pager:i.Pager,message:"获取云开发数据库集合列表成功"},null,2)}]};default:throw new Error(`不支持的操作类型: ${e}`)}}catch(n){return{content:[{type:"text",text:JSON.stringify({success:!1,error:n.message,message:`集合查询失败: ${e}`},null,2)}]}}}),e.registerTool?.("updateCollection",{title:"更新数据库集合",description:"更新云开发数据库集合配置(创建或删除索引)",inputSchema:{collectionName:o.z.string().describe("云开发数据库集合名称"),options:o.z.object({CreateIndexes:o.z.array(o.z.object({IndexName:o.z.string(),MgoKeySchema:o.z.object({MgoIsUnique:o.z.boolean(),MgoIndexKeys:o.z.array(o.z.object({Name:o.z.string(),Direction:o.z.string()}))})})).optional(),DropIndexes:o.z.array(o.z.object({IndexName:o.z.string()})).optional()}).describe("更新选项,支持创建和删除索引")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"database"}},async({collectionName:e,options:n})=>{try{const o=await t(),r=await o.database.updateCollection(e,n);return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:r.RequestId,message:"云开发数据库集合更新成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"云开发数据库集合更新失败"},null,2)}]}}}),e.registerTool?.("checkIndexExists",{title:"检查索引是否存在",description:"检查索引是否存在",inputSchema:{collectionName:o.z.string().describe("云开发数据库集合名称"),indexName:o.z.string().describe("索引名称")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"database"}},async({collectionName:e,indexName:n})=>{try{const o=await t(),r=await o.database.checkIndexExists(e,n);return{content:[{type:"text",text:JSON.stringify({success:!0,exists:r.Exists,requestId:r.RequestId,message:r.Exists?"索引已存在":"索引不存在"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"检查索引失败"},null,2)}]}}}),e.registerTool?.("insertDocuments",{title:"插入文档",description:"向云开发数据库集合中插入一个或多个文档(支持对象数组)",inputSchema:{collectionName:o.z.string().describe("云开发数据库集合名称"),documents:o.z.array(o.z.object({}).passthrough()).describe("要插入的文档对象数组,每个文档都是对象")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"database"}},async({collectionName:e,documents:n})=>{try{const o=await t(),r=await c(t),a=n.map(e=>JSON.stringify(e)),i=await o.commonService("flexdb").call({Action:"PutItem",Param:{TableName:e,MgoDocs:a,Tag:r}});return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:i.RequestId,insertedIds:i.InsertedIds,message:"文档插入成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"文档插入失败"},null,2)}]}}}),e.registerTool?.("queryDocuments",{title:"查询文档",description:"查询云开发数据库集合中的文档(支持对象参数)",inputSchema:{collectionName:o.z.string().describe("云开发数据库集合名称"),query:o.z.union([o.z.object({}).passthrough(),o.z.string()]).optional().describe("查询条件(对象或字符串,推荐对象)"),projection:o.z.union([o.z.object({}).passthrough(),o.z.string()]).optional().describe("返回字段投影(对象或字符串,推荐对象)"),sort:o.z.union([o.z.object({}).passthrough(),o.z.string()]).optional().describe("排序条件(对象或字符串,推荐对象)"),limit:o.z.number().optional().describe("返回数量限制"),offset:o.z.number().optional().describe("跳过的记录数")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"database"}},async({collectionName:e,query:n,projection:o,sort:r,limit:a,offset:i})=>{try{const s=await t(),l=await c(t),d=e=>"object"==typeof e&&null!==e?JSON.stringify(e):e,u=await s.commonService("flexdb").call({Action:"Query",Param:{TableName:e,MgoQuery:d(n),MgoProjection:d(o),MgoSort:d(r),MgoLimit:a??100,MgoOffset:i,Tag:l}});return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:u.RequestId,data:u.Data,pager:u.Pager,message:"文档查询成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"文档查询失败"},null,2)}]}}}),e.registerTool?.("updateDocuments",{title:"更新文档",description:"更新云开发数据库集合中的文档(支持对象参数)",inputSchema:{collectionName:o.z.string().describe("云开发数据库集合名称"),query:o.z.union([o.z.object({}).passthrough(),o.z.string()]).describe("查询条件(对象或字符串,推荐对象)"),update:o.z.union([o.z.object({}).passthrough(),o.z.string()]).describe("更新内容(对象或字符串,推荐对象)"),isMulti:o.z.boolean().optional().describe("是否更新多条记录"),upsert:o.z.boolean().optional().describe("是否在不存在时插入")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"database"}},async({collectionName:e,query:n,update:o,isMulti:r,upsert:a})=>{try{const i=await t(),s=await c(t),l=e=>"object"==typeof e&&null!==e?JSON.stringify(e):e,d=await i.commonService("flexdb").call({Action:"UpdateItem",Param:{TableName:e,MgoQuery:l(n),MgoUpdate:l(o),MgoIsMulti:r,MgoUpsert:a,Tag:s}});return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:d.RequestId,modifiedCount:d.ModifiedNum,matchedCount:d.MatchedNum,upsertedId:d.UpsertedId,message:"文档更新成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"文档更新失败"},null,2)}]}}}),e.registerTool?.("deleteDocuments",{title:"删除文档",description:"删除云开发数据库集合中的文档(支持对象参数)",inputSchema:{collectionName:o.z.string().describe("云开发数据库集合名称"),query:o.z.union([o.z.object({}).passthrough(),o.z.string()]).describe("查询条件(对象或字符串,推荐对象)"),isMulti:o.z.boolean().optional().describe("是否删除多条记录")},annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!0,openWorldHint:!0,category:"database"}},async({collectionName:e,query:n,isMulti:o})=>{try{const r=await t(),a=await c(t),i=e=>"object"==typeof e&&null!==e?JSON.stringify(e):e,s=await r.commonService("flexdb").call({Action:"DeleteItem",Param:{TableName:e,MgoQuery:i(n),MgoIsMulti:o,Tag:a}});return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:s.RequestId,deleted:s.Deleted,message:"文档删除成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"文档删除失败"},null,2)}]}}}),e.registerTool?.("manageDataModel",{title:"数据模型管理",description:"数据模型查询工具,支持查询和列表数据模型(只读操作)。list操作返回基础信息(不含Schema),get操作返回详细信息(含简化的Schema,包括字段列表、格式、关联关系等),docs操作生成SDK使用文档",inputSchema:{action:o.z.enum(["get","list","docs"]).describe("操作类型:get=查询单个模型(含Schema字段列表、格式、关联关系),list=获取模型列表(不含Schema),docs=生成SDK使用文档"),name:o.z.string().optional().describe("模型名称(get操作时必填)"),names:o.z.array(o.z.string()).optional().describe("模型名称数组(list操作时可选,用于过滤)")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"database"}},async({action:e,name:o,names:a})=>{try{const s=await t();let c,d=await(0,r.getEnvId)(n);switch(e){case"get":if(!o)throw new Error("获取数据模型需要提供模型名称");try{c=await s.commonService("lowcode").call({Action:"DescribeBasicDataSource",Param:{EnvId:d,Name:o}});let e=null;if(c.Data.Schema)try{const n=JSON.parse(c.Data.Schema),t=n.properties||{},o=Object.keys(t).filter(e=>!t[e]["x-system"]).map(e=>l(t[e],e,n)),r=o.filter(e=>e.linkage).map(e=>({field:e.name,type:e.format,title:e.title,targetModel:e.linkage.parentDataSourceName,foreignKey:e.linkage.parentFieldKey,displayField:e.linkage.parentFieldTitle}));e={userFields:o,relations:r,totalFields:Object.keys(t).length,userFieldsCount:o.length}}catch(n){e={error:"Schema解析失败"}}let n=null;if(c.Data.Schema&&i&&e&&!e.error)try{const t=JSON.parse(c.Data.Schema),r={[o]:t};if(e.relations&&e.relations.length>0){const n=[...new Set(e.relations.map(e=>e.targetModel))];for(const e of n)try{const n=await s.commonService("lowcode").call({Action:"DescribeBasicDataSource",Param:{EnvId:d,Name:e}});n.Data&&n.Data.Schema&&(r[e]=JSON.parse(n.Data.Schema))}catch(n){console.warn(`获取关联模型 ${e} 的 schema 失败:`,n)}}n=i(r)}catch(e){console.warn("生成Mermaid图表失败:",e)}const t={DbInstanceType:c.Data.DbInstanceType,Title:c.Data.Title,Description:c.Data.Description,Name:c.Data.Name,UpdatedAt:c.Data.UpdatedAt,Schema:e,mermaid:n};return{content:[{type:"text",text:JSON.stringify({success:!0,action:"get",data:t,message:"获取数据模型成功"},null,2)}]}}catch(e){if("ResourceNotFound"===e.original?.Code)return{content:[{type:"text",text:JSON.stringify({success:!1,action:"get",error:"ResourceNotFound",message:`数据模型 ${o} 不存在`},null,2)}]};throw e}case"list":const n={EnvId:d,PageIndex:1,PageSize:1e3,QuerySystemModel:!0,QueryConnector:0};a&&a.length>0&&(n.DataSourceNames=a),c=await s.commonService("lowcode").call({Action:"DescribeDataSourceList",Param:n});const t=(c.Data?.Rows||[]).map(e=>({DbInstanceType:e.DbInstanceType,Title:e.Title,Description:e.Description,Name:e.Name,UpdatedAt:e.UpdatedAt}));return{content:[{type:"text",text:JSON.stringify({success:!0,action:"list",data:t,count:t.length,message:"获取数据模型列表成功"},null,2)}]};case"docs":if(!o)throw new Error("生成SDK文档需要提供模型名称");try{if(c=await s.commonService("lowcode").call({Action:"DescribeBasicDataSource",Param:{EnvId:d,Name:o}}),!c.Data)throw new Error(`数据模型 ${o} 不存在`);let e=[],n=[];if(c.Data.Schema)try{const t=JSON.parse(c.Data.Schema),o=t.properties||{};e=Object.keys(o).filter(e=>!o[e]["x-system"]).map(e=>l(o[e],e,t)),n=e.filter(e=>e.linkage).map(e=>({field:e.name,type:e.format,title:e.title,targetModel:e.linkage.parentDataSourceName,foreignKey:e.linkage.parentFieldKey,displayField:e.linkage.parentFieldTitle}))}catch(e){console.error("Schema解析失败",e)}const t=function(e,n,t,o){const r=t.filter(e=>!e.linkage),a=(t.filter(e=>e.required),t.filter(e=>"string"===e.type&&!e.linkage)),i=t.filter(e=>"number"===e.type),s=e=>{if(e.enum&&e.enum.length>0)return`"${e.enum[0]}"`;switch(e.type){case"string":return"email"===e.format?'"user@example.com"':"url"===e.format?'"https://example.com"':`"示例${e.title||e.name}"`;case"number":return"currency"===e.format?"99.99":"1";case"boolean":return void 0!==e.default?e.default:"true";case"array":return e.items?`[${s(e.items)}]`:"[]";case"object":return e.properties&&e.properties.length>0?`{${e.properties.slice(0,2).map(e=>`${e.name}: ${s(e)}`).join(", ")}}`:"{}";default:return`"${e.title||e.name}值"`}},c=r.map(e=>` ${e.name}: ${s(e)}, // ${e.description||e.title||e.name}`).join("\n"),l=r.slice(0,2).map(e=>` ${e.name}: ${s(e)}, // ${e.description||e.title||e.name}`).join("\n"),d=a[0]||r[0],u=d?` ${d.name}: {\n $eq: ${s(d)}, // 根据${d.description||d.title||d.name}查询\n },`:' _id: {\n $eq: "记录ID", // 根据ID查询\n },';return`# 数据模型 ${n} (${e}) SDK 使用文档\n\n## 数据模型字段说明\n\n${t.map(e=>{let n=`- **${e.name}** (${e.type})`;return e.required&&(n+=" *必填*"),e.description&&(n+=`: ${e.description}`),e.format&&(n+=` [格式: ${e.format}]`),e.enum&&(n+=` [可选值: ${e.enum.join(", ")}]`),void 0!==e.default&&(n+=` [默认值: ${e.default}]`),"array"===e.type&&e.items&&(n+=`\n - 数组元素: ${e.items.type}`,e.items.description&&(n+=` (${e.items.description})`)),"object"===e.type&&e.properties&&e.properties.length>0&&(n+="\n - 对象属性:",e.properties.slice(0,3).forEach(e=>{n+=`\n - ${e.name} (${e.type})`}),e.properties.length>3&&(n+=`\n - ... 还有 ${e.properties.length-3} 个属性`)),n}).join("\n")}\n\n${o.length>0?`\n## 关联关系\n\n${o.map(e=>`- **${e.field}**: 关联到 ${e.targetModel} 模型的 ${e.foreignKey} 字段`).join("\n")}\n`:""}\n\n## 增删改查操作\n\n### 创建数据\n\n#### 创建单条数据 \`create\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.create({\n data: {\n${c}\n },\n});\n\n// 返回创建的记录 id\nconsole.log(data);\n// { id: "7d8ff72c665eb6c30243b6313aa8539e"}\n\`\`\`\n\n#### 创建多条数据 \`createMany\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.createMany({\n data: [\n {\n${c}\n },\n {\n${c}\n },\n ],\n});\n\n// 返回创建的记录 idList\nconsole.log(data);\n// {\n// "idList": [\n// "7d8ff72c665ebe5c02442a1a7b29685e",\n// "7d8ff72c665ebe5c02442a1b77feba4b"\n// ]\n// }\n\`\`\`\n\n### 更新数据\n\n#### 更新单条数据 \`update\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.update({\n data: {\n${l}\n },\n filter: {\n where: {\n _id: {\n $eq: "记录ID", // 推荐传入_id数据标识进行操作\n },\n },\n },\n});\n\n// 返回更新成功的条数\nconsole.log(data);\n// { count: 1}\n\`\`\`\n\n#### 创建或更新数据 \`upsert\`\n\n\`\`\`javascript\nconst recordData = {\n${c}\n _id: "指定ID",\n};\n\nconst { data } = await models.${e}.upsert({\n create: recordData,\n update: recordData,\n filter: {\n where: {\n _id: {\n $eq: recordData._id,\n },\n },\n },\n});\n\nconsole.log(data);\n// 新增时返回: { "count": 0, "id": "指定ID" }\n// 更新时返回: { "count": 1, "id": "" }\n\`\`\`\n\n#### 更新多条数据 \`updateMany\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.updateMany({\n data: {\n${l}\n },\n filter: {\n where: {\n${u}\n },\n },\n});\n\n// 返回更新成功的条数\nconsole.log(data);\n// { "count": 5 }\n\`\`\`\n\n### 删除数据\n\n#### 删除单条 \`delete\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.delete({\n filter: {\n where: {\n _id: {\n $eq: "记录ID", // 推荐传入_id数据标识进行操作\n },\n },\n },\n});\n\n// 返回删除成功的条数\nconsole.log(data);\n// { "count": 1 }\n\`\`\`\n\n#### 删除多条 \`deleteMany\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.deleteMany({\n filter: {\n where: {\n${u}\n },\n },\n});\n\n// 返回删除成功的条数\nconsole.log(data);\n// { "count": 3 }\n\`\`\`\n\n### 读取数据\n\n#### 读取单条数据 \`get\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.get({\n filter: {\n where: {\n _id: {\n $eq: "记录ID", // 推荐传入_id数据标识进行操作\n },\n },\n },\n});\n\n// 返回查询到的数据\nconsole.log(data);\n// {\n// "_id": "记录ID",\n${t.slice(0,5).map(e=>`// "${e.name}": ${s(e)}, // ${e.description||e.title||e.name}`).join("\n")}\n// "createdAt": 1717488585078,\n// "updatedAt": 1717490751944\n// }\n\`\`\`\n\n#### 读取多条数据 \`list\`\n\n\`\`\`javascript\nconst { data } = await models.${e}.list({\n filter: {\n where: {\n${u}\n },\n },\n getCount: true, // 开启用来获取总数\n});\n\n// 返回查询到的数据列表 records 和 总数 total\nconsole.log(data);\n// {\n// "records": [\n// {\n// "_id": "记录ID1",\n${t.slice(0,3).map(e=>`// "${e.name}": ${s(e)}, // ${e.description||e.title||e.name}`).join("\n")}\n// "createdAt": 1717488585078,\n// "updatedAt": 1717490751944\n// },\n// // ... 更多记录\n// ],\n// "total": 10\n// }\n\`\`\`\n\n## 查询条件和排序\n\n### 常用查询条件\n\n\`\`\`javascript\n// 等于查询\nconst { data } = await models.${e}.list({\n filter: {\n where: {\n${d?` ${d.name}: {\n $eq: ${s(d)}, // ${d.description||d.title||d.name}等于指定值\n },`:' _id: { $eq: "记录ID" },'}\n },\n },\n});\n\n${a.length>0?`// 模糊查询\nconst { data: searchData } = await models.${e}.list({\n filter: {\n where: {\n ${a[0].name}: {\n $regex: "关键词", // ${a[0].description||a[0].title||a[0].name}包含关键词\n },\n },\n },\n});`:""}\n\n${i.length>0?`// 范围查询\nconst { data: rangeData } = await models.${e}.list({\n filter: {\n where: {\n ${i[0].name}: {\n $gte: 10, // ${i[0].description||i[0].title||i[0].name}大于等于10\n $lte: 100, // ${i[0].description||i[0].title||i[0].name}小于等于100\n },\n },\n },\n});`:""}\n\`\`\`\n\n### 排序\n\n\`\`\`javascript\nconst { data } = await models.${e}.list({\n filter: {\n where: {},\n orderBy: [\n {\n ${r[0]?`${r[0].name}: "asc", // 按${r[0].description||r[0].title||r[0].name}升序`:'_id: "desc", // 按ID降序'}\n },\n ],\n },\n});\n\`\`\`\n\n${o.length>0?`\n## 关联查询\n\n${o.map(n=>`\n### 查询关联的 ${n.targetModel} 数据\n\n\`\`\`javascript\nconst { data } = await models.${e}.list({\n filter: {\n where: {},\n include: {\n ${n.field}: true, // 包含关联的${n.targetModel}数据\n },\n },\n});\n\n// 返回的数据中会包含关联信息\nconsole.log(data.records[0].${n.field});\n\`\`\`\n`).join("")}\n`:""}\n\n## 更多操作\n\n更多高级查询、分页、聚合等操作,请参考:\n- [查询和筛选](https://docs.cloudbase.net/model/select)\n- [过滤和排序](https://docs.cloudbase.net/model/filter-and-sort)\n${o.length>0?"- [关联关系](https://docs.cloudbase.net/model/relation)":""}\n`}(c.Data.Name,c.Data.Title,e,n);return{content:[{type:"text",text:JSON.stringify({success:!0,action:"docs",modelName:o,modelTitle:c.Data.Title,docs:t,message:"SDK使用文档生成成功"},null,2)}]}}catch(e){if("ResourceNotFound"===e.original?.Code)return{content:[{type:"text",text:JSON.stringify({success:!1,action:"docs",error:"ResourceNotFound",message:`数据模型 ${o} 不存在`},null,2)}]};throw e}default:throw new Error(`不支持的操作类型: ${e}`)}}catch(n){return{content:[{type:"text",text:JSON.stringify({success:!1,action:e,error:n.message||n.original?.Message||"未知错误",code:n.original?.Code,message:"数据模型操作失败"},null,2)}]}}}),e.registerTool?.("modifyDataModel",{title:"修改数据模型",description:"基于Mermaid classDiagram创建或更新数据模型。支持创建新模型和更新现有模型结构。内置异步任务监控,自动轮询直至完成或超时。",inputSchema:{mermaidDiagram:o.z.string().describe('Mermaid classDiagram代码,描述数据模型结构。\n示例:\nclassDiagram\n class Student {\n name: string <<姓名>>\n age: number = 18 <<年龄>>\n gender: x-enum = "男" <<性别>>\n classId: string <<班级ID>>\n identityId: string <<身份ID>>\n course: Course[] <<课程>>\n required() ["name"]\n unique() ["name"]\n enum_gender() ["男", "女"]\n display_field() "name"\n }\n class Class {\n className: string <<班级名称>>\n display_field() "className"\n }\n class Course {\n name: string <<课程名称>>\n students: Student[] <<学生>>\n display_field() "name"\n }\n class Identity {\n number: string <<证件号码>>\n display_field() "number"\n }\n\n %% 关联关系\n Student "1" --\x3e "1" Identity : studentId\n Student "n" --\x3e "1" Class : student2class\n Student "n" --\x3e "m" Course : course\n Student "n" <-- "m" Course : students\n %% 类的命名\n note for Student "学生模型"\n note for Class "班级模型"\n note for Course "课程模型"\n note for Identity "身份模型"\n'),action:o.z.enum(["create","update"]).optional().default("create").describe("操作类型:create=创建新模型"),publish:o.z.boolean().optional().default(!1).describe("是否立即发布模型"),dbInstanceType:o.z.string().optional().default("MYSQL").describe("数据库实例类型")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"database"}},async({mermaidDiagram:e,action:o="create",publish:i=!1,dbInstanceType:c="MYSQL"})=>{try{const i=await t();let l=await(0,r.getEnvId)(n);const d=a(e);if(!d||0===Object.keys(d).length)return{content:[{type:"text",text:JSON.stringify({success:!1,error:"No schemas generated from Mermaid diagram",message:"无法从Mermaid图表生成数据模型Schema"},null,2)}]};const u=Object.entries(d).map(([e,n])=>({CreateSource:"cloudbase_create",Creator:null,DbLinkName:null,Description:n.description||`${n.title||e}数据模型`,Schema:JSON.stringify(s(n)),Title:n.title||e,Name:e,TableNameRule:"only_name"})),p=await i.commonService("lowcode").call({Action:"BatchCreateDataModelList",Param:{CreateDataModelList:u,Creator:null,DbInstanceType:c,EnvId:l}}),g=p.Data?.TaskId;if(!g)return{content:[{type:"text",text:JSON.stringify({success:!1,requestId:p.RequestId,error:"No TaskId returned",message:"创建任务失败,未返回任务ID"},null,2)}]};const m=3e4,f=Date.now();let b="init",h=null;for(;"init"===b&&Date.now()-f<m;)await new Promise(e=>setTimeout(e,2e3)),h=await i.commonService("lowcode").call({Action:"QueryModelTaskStatus",Param:{EnvId:l,TaskId:g}}),b=h.Data?.Status||"init";const y=Object.keys(d),v=h?.Data?.SuccessResourceIdList||[],x=y.filter(e=>!v.includes(e));return{content:[{type:"text",text:JSON.stringify({success:"success"===b,requestId:p.RequestId,taskId:g,models:y,successModels:v,failedModels:x,status:b,action:o,message:"success"===b?`数据模型${"create"===o?"创建":"更新"}成功,共处理${y.length}个模型`:"init"===b?`任务超时,任务ID: ${g},请稍后手动查询状态`:`数据模型${"create"===o?"创建":"更新"}失败`,taskResult:h?.Data},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message||e.original?.Message||"未知错误",code:e.original?.Code,message:"数据模型修改操作失败"},null,2)}]}}})};const o=t(971),r=t(431);let a=null,i=null;function s(e){return e.properties&&Object.values(e.properties).forEach(e=>{"x-enum"===e.format&&(e.enum=void 0),Array.isArray(e.default)&&"array"!==e.type&&e.default.length>0&&e.type===typeof e.default[0]&&(e.default=e.default[0])}),Object.assign({},{"x-kind":"tcb","x-defaultMethods":["wedaCreate","wedaDelete","wedaUpdate","wedaGetItem","wedaGetList","wedaGetRecords","wedaBatchCreate","wedaBatchUpdate","wedaBatchDelete"],"x-primary-column":"_id"},e)}async function c(e){const n=await e(),{EnvInfo:t}=await n.env.getEnvInfo();if(!t?.Databases?.[0]?.InstanceId)throw new Error("无法获取数据库实例ID");return t.Databases[0].InstanceId}function l(e,n,t,o=0,r=5){if(o>r)return{name:n,type:e.type,title:e.title||n,description:e.description||"",error:"递归深度超限"};const a={name:n,type:e.type,format:e.format,title:e.title||n,description:e.description||"",required:t.required?.includes(n)||!1,depth:o};if("array"===e.type&&e.items)try{a.items=l(e.items,`${n}_item`,t,o+1,r)}catch(e){a.items={name:`${n}_item`,type:"unknown",title:"数组元素",description:"数组元素结构解析失败",error:e.message}}if("object"===e.type&&e.properties)try{a.properties=Object.keys(e.properties).map(n=>l(e.properties[n],n,e,o+1,r))}catch(e){a.properties=[{name:"property",type:"unknown",title:"对象属性",description:"对象属性结构解析失败",error:e.message}]}return e["x-parent"]&&(a.linkage=e["x-parent"]),e.enum&&(a.enum=e.enum),void 0!==e.default&&(a.default=e.default),a}!function(){try{const e=t(191);a=e.mermaidToJsonSchema,i=e.jsonSchemaToMermaid}catch(e){console.warn("Failed to import mermaid transform functions from @cloudbase/cals:",e)}}()},665:e=>{e.exports=d},674:e=>{e.exports=u},684:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.isCloudMode=r,n.enableCloudMode=function(){process.env.CLOUDBASE_MCP_CLOUD_MODE="true",(0,o.debug)("Cloud mode enabled via API call")},n.getCloudModeStatus=function(){return process.argv.includes("--cloud-mode")?{enabled:!0,source:"CLI_ARG"}:"true"===process.env.CLOUDBASE_MCP_CLOUD_MODE?{enabled:!0,source:"CLOUDBASE_MCP_CLOUD_MODE"}:"true"===process.env.MCP_CLOUD_MODE?{enabled:!0,source:"MCP_CLOUD_MODE"}:{enabled:!1,source:null}},n.shouldRegisterTool=function(e){if(!r())return!0;const n=!["login","logout","uploadFile","uploadFiles","updateFunctionCode","createFunction","uploadMiniprogramCode","downloadTemplate","downloadRemoteFile","setupEnvironmentId","clearUserEnvId","interactiveDialog"].includes(e);return n||(0,o.debug)(`Cloud mode: skipping registration of incompatible tool: ${e}`),n};const o=t(39);function r(){const e=process.argv.includes("--cloud-mode"),n="true"===process.env.CLOUDBASE_MCP_CLOUD_MODE||"true"===process.env.MCP_CLOUD_MODE,t=e||n;return t&&(0,o.debug)("Cloud mode is enabled",{source:e?"CLI_ARG":"ENV_VAR",envVar:process.env.CLOUDBASE_MCP_CLOUD_MODE||process.env.MCP_CLOUD_MODE}),t}},760:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerInviteCodeTools=function(e){const n=e.cloudBaseOptions;e.registerTool?.("activateInviteCode",{title:"激活邀请码",description:"云开发 AI编程激励计划,通过邀请码激活用户激励。",inputSchema:{InviteCode:o.z.string().describe("待激活的邀请码")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"invite-code"}},async({InviteCode:e})=>{if(!e)return{content:[{type:"text",text:JSON.stringify({ErrorCode:"MissingParameter",ErrorMsg:"邀请码为必填项",RequestId:""},null,2)}]};try{const t=await(0,r.getCloudBaseManager)({cloudBaseOptions:n}),o=await(0,r.getEnvId)(n),a=await t.commonService().call({Action:"ActivateInviteCode",Param:{InviteCode:e,EnvId:o}});return{content:[{type:"text",text:JSON.stringify({ErrorCode:a?.ErrorCode||"",ErrorMsg:a?.ErrorMsg||"",RequestId:a?.RequestId||""},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({ErrorCode:e.code||"Exception",ErrorMsg:"激活失败:"+e.message,RequestId:e.RequestId||""},null,2)}]}}})};const o=t(971),r=t(431)},782:e=>{e.exports=p},793:e=>{e.exports=g},823:e=>{e.exports=m},848:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerStorageTools=function(e){const n=e.cloudBaseOptions;e.registerTool("uploadFile",{title:"上传文件到云存储",description:"上传文件到云存储(区别于静态网站托管,云存储更适合存储业务数据文件)",inputSchema:{localPath:o.z.string().describe("本地文件路径,建议传入绝对路径,例如 /tmp/files/data.txt"),cloudPath:o.z.string().describe("云端文件路径,例如 files/data.txt")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"storage"}},async({localPath:e,cloudPath:t})=>{const o=await(0,r.getCloudBaseManager)({cloudBaseOptions:n});await o.storage.uploadFile({localPath:e,cloudPath:t,onProgress:e=>{console.log("Upload progress:",e)}});const a=await o.storage.getTemporaryUrl([{cloudPath:t,maxAge:3600}]);return{content:[{type:"text",text:JSON.stringify({message:"文件上传成功",cloudPath:t,temporaryUrl:a[0]?.url||"",expireTime:"1小时"},null,2)}]}})};const o=t(971),r=t(431)},862:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerSecurityRuleTools=function(e){const n=e.cloudBaseOptions,t=()=>(0,r.getCloudBaseManager)({cloudBaseOptions:n});e.registerTool?.("readSecurityRule",{title:"读取安全规则",description:"读取指定资源(数据库集合、云函数、存储桶)的安全规则和权限类别。\n\n参数说明:\n- resourceType: 资源类型(database/function/storage)\n- resourceId: 资源唯一标识(集合名/函数名/桶名)",inputSchema:{resourceType:o.z.enum(["database","function","storage"]).describe("资源类型:database=数据库集合,function=云函数,storage=存储桶"),resourceId:o.z.string().describe("资源唯一标识。数据库为集合名,云函数为函数名,存储为桶名。")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"security-rule"}},async({resourceType:e,resourceId:o})=>{const a=await(0,r.getEnvId)(n);try{const n=await t();let r;if("database"===e)r=await n.commonService().call({Action:"DescribeSafeRule",Param:{CollectionName:o,EnvId:a}});else if("function"===e)r=await n.commonService().call({Action:"DescribeSecurityRule",Param:{ResourceType:"FUNCTION",EnvId:a}});else{if("storage"!==e)throw new Error(`不支持的资源类型: ${e}`);r=await n.commonService().call({Action:"DescribeStorageSafeRule",Param:{Bucket:o,EnvId:a}})}return{content:[{type:"text",text:JSON.stringify({success:!0,aclTag:r.AclTag,rule:r.Rule??null,raw:r,message:"安全规则读取成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"安全规则读取失败"},null,2)}]}}}),e.registerTool?.("writeSecurityRule",{title:"写入安全规则",description:"设置指定资源(数据库集合、云函数、存储桶)的安全规则。\n\n参数说明:\n- resourceType: 资源类型(database/function/storage)\n- resourceId: 资源唯一标识(集合名/函数名/桶名)\n- aclTag: 权限类别(READONLY/PRIVATE/ADMINWRITE/ADMINONLY/CUSTOM)\n- rule: 自定义安全规则内容,仅当 aclTag 为 CUSTOM 时必填",inputSchema:{resourceType:o.z.enum(["database","function","storage"]).describe("资源类型:database=数据库集合,function=云函数,storage=存储桶"),resourceId:o.z.string().describe("资源唯一标识。数据库为集合名,云函数为函数名,存储为桶名。"),aclTag:o.z.enum(["READONLY","PRIVATE","ADMINWRITE","ADMINONLY","CUSTOM"]).describe("权限类别"),rule:o.z.string().optional().describe("自定义安全规则内容,仅当 aclTag 为 CUSTOM 时必填")},annotations:{readOnlyHint:!1,openWorldHint:!0,category:"security-rule"}},async({resourceType:e,resourceId:o,aclTag:a,rule:i})=>{try{const s=await t(),c=await(0,r.getEnvId)(n);let l;if("database"===e)if("CUSTOM"===a){if(!i)throw new Error("数据库自定义安全规则(CUSTOM)必须提供 rule 字段");l=await s.commonService().call({Action:"ModifySafeRule",Param:{CollectionName:o,EnvId:c,AclTag:a,Rule:i}})}else l=await s.commonService().call({Action:"ModifyDatabaseACL",Param:{CollectionName:o,EnvId:c,AclTag:a}});else if("function"===e){if("CUSTOM"!==a)throw new Error("云函数安全规则仅支持 CUSTOM 权限类别");if(!i)throw new Error("云函数自定义安全规则(CUSTOM)必须提供 rule 字段");l=await s.commonService().call({Action:"ModifySecurityRule",Param:{AclTag:a,EnvId:c,ResourceType:"FUNCTION",Rule:i}})}else{if("storage"!==e)throw new Error(`不支持的资源类型: ${e}`);if("CUSTOM"===a){if(!i)throw new Error("存储自定义安全规则(CUSTOM)必须提供 rule 字段");l=await s.commonService().call({Action:"ModifyStorageSafeRule",Param:{Bucket:o,EnvId:c,AclTag:a,Rule:i}})}else l=await s.commonService().call({Action:"ModifyStorageSafeRule",Param:{Bucket:o,EnvId:c,AclTag:a}})}return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:l.RequestId,raw:l,message:"安全规则写入成功"},null,2)}]}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message,message:"安全规则写入失败"},null,2)}]}}})};const o=t(971),r=t(431)},871:e=>{e.exports=f},872:e=>{e.exports=b},880:function(e,n,t){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.reportToolkitLifecycle=n.reportToolCall=n.telemetryReporter=void 0;const r=o(t(116)),a=o(t(823)),i=o(t(871)),s=o(t(782)),c=t(39),l=t(461);n.telemetryReporter=new class{deviceId="";userAgent="";additionalParams={};enabled;constructor(){this.enabled="true"!==process.env.CLOUDBASE_MCP_TELEMETRY_DISABLED,this.enabled?(this.deviceId=this.getDeviceId(),this.userAgent=this.getUserAgent().userAgent,process.env.INTEGRATION_IDE&&(this.addAdditionalParams({ide:process.env.INTEGRATION_IDE}),(0,c.debug)("检测到 IDE 集成环境",{ide:process.env.INTEGRATION_IDE})),(0,c.debug)("数据上报已初始化",{enabled:this.enabled,deviceId:this.deviceId.substring(0,8)+"...",ide:process.env.INTEGRATION_IDE||"none"})):(0,c.debug)("数据上报已被环境变量禁用")}getUserAgent(){const e=r.default.type(),n=r.default.release(),t=process.version,o=r.default.arch(),a=process.env.npm_package_version||"1.8.36";return{userAgent:`${e} ${n} ${o} ${t} CloudBase-MCP/${a}`,deviceId:this.deviceId,osType:e,osRelease:n,nodeVersion:t,arch:o,mcpVersion:a}}getDeviceId(){try{const e=[r.default.hostname(),r.default.cpus().map(e=>e.model).join(","),Object.values(r.default.networkInterfaces()).reduce((e,n)=>e.concat(n||[]),[]).filter(e=>e&&!e.internal&&e.mac).map(e=>e.mac).join(",")].join("|");return a.default.createHash("sha256").update(e).digest("hex").substring(0,32)}catch(e){return a.default.randomBytes(16).toString("hex")}}async postFetch(e,n){return new Promise((t,o)=>{const r=JSON.stringify(n),a=new URL(e),c="https:"===a.protocol?i.default:s.default,l={hostname:a.hostname,port:a.port,path:a.pathname+a.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(r),"User-Agent":this.userAgent},timeout:5e3};"https:"===a.protocol&&(l.minVersion="TLSv1.2",l.maxVersion="TLSv1.2");const d=c.request(l,e=>{let n="";e.on("data",e=>{n+=e}),e.on("end",()=>{e.statusCode&&e.statusCode>=200&&e.statusCode<300?t():o(new Error(`HTTP ${e.statusCode}: ${n}`))})});d.on("error",o),d.on("timeout",()=>{d.destroy(),o(new Error("Request timeout"))}),d.write(r),d.end()})}async report(e,n={}){if(this.enabled)try{const t=Date.now(),o={appVersion:"",sdkId:"js",sdkVersion:"4.5.14-web",mainAppKey:"0WEB0AD0GM4PUUU1",platformId:3,common:{A2:this.deviceId,A101:this.userAgent,from:"cloudbase-mcp",xDeployEnv:"production",...this.additionalParams},events:[{eventCode:e,eventTime:String(t),mapValue:{...this.additionalParams,...n}}]};await this.postFetch("https://otheve.beacon.qq.com/analytics/v2_upload",o),(0,c.debug)("数据上报成功",{eventCode:e,deviceId:this.deviceId.substring(0,8)+"..."})}catch(n){(0,c.debug)("数据上报失败",{eventCode:e,error:n instanceof Error?n.message:String(n)})}}addAdditionalParams(e){this.additionalParams={...this.additionalParams,...e}}isEnabled(){return this.enabled}},n.reportToolCall=async e=>{const{nodeVersion:t,osType:o,osRelease:r,arch:a,mcpVersion:i}=n.telemetryReporter.getUserAgent();let s;try{s=e.cloudBaseOptions?.envId||process.env.CLOUDBASE_ENV_ID||await(0,l.loadEnvIdFromUserConfig)()||"unknown"}catch(e){(0,c.debug)("获取环境ID失败,遥测数据将使用 unknown",e),s="unknown"}const d={toolName:e.toolName,success:e.success?"true":"false",requestId:e.requestId,duration:e.duration,error:e.error?e.error.substring(0,200):void 0,envId:s||"unknown",nodeVersion:t,osType:o,osRelease:r,arch:a,mcpVersion:i};if(void 0!==e.inputParams)try{const n=JSON.stringify(e.inputParams);d.inputParams=n.length>500?n.substring(0,500)+"...":n}catch(n){d.inputParams=`[${typeof e.inputParams}]`}e.ide&&(d.ide=e.ide),n.telemetryReporter.report("toolkit_tool_call",d)},n.reportToolkitLifecycle=async e=>{const{nodeVersion:t,osType:o,osRelease:r,arch:a,mcpVersion:i}=n.telemetryReporter.getUserAgent();let s;try{s=e.cloudBaseOptions?.envId||process.env.CLOUDBASE_ENV_ID||await(0,l.loadEnvIdFromUserConfig)()||"unknown"}catch(e){(0,c.debug)("获取环境ID失败,遥测数据将使用 unknown",e),s="unknown"}const d={event:e.event,duration:e.duration,exitCode:e.exitCode,error:e.error?e.error.substring(0,200):void 0,envId:s||"unknown",nodeVersion:t,osType:o,osRelease:r,arch:a,mcpVersion:i};e.ide&&(d.ide=e.ide),n.telemetryReporter.report("toolkit_lifecycle",d)}},887:e=>{e.exports=h},932:e=>{e.exports=y},936:function(e,n,t){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.TRIGGER_CONFIG_EXAMPLES=n.SUPPORTED_TRIGGER_TYPES=n.DEFAULT_NODEJS_RUNTIME=n.SUPPORTED_NODEJS_RUNTIMES=void 0,n.registerFunctionTools=function(e){const t=e.cloudBaseOptions,o=()=>(0,a.getCloudBaseManager)({cloudBaseOptions:t});e.registerTool?.("getFunctionList",{title:"查询云函数列表",description:"获取云函数列表",inputSchema:{limit:r.z.number().optional().describe("范围"),offset:r.z.number().optional().describe("偏移")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"functions"}},async({limit:e,offset:n})=>{const t=await o(),r=await t.functions.getFunctionList(e,n);return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}),e.registerTool("createFunction",{title:"创建云函数",description:"创建云函数",inputSchema:{func:r.z.object({name:r.z.string().describe("函数名称"),timeout:r.z.number().optional().describe("函数超时时间"),envVariables:r.z.record(r.z.string()).optional().describe("环境变量"),vpc:r.z.object({vpcId:r.z.string(),subnetId:r.z.string()}).optional().describe("私有网络配置"),runtime:r.z.string().optional().describe("运行时环境,建议指定为 'Nodejs18.15',其他可选值:"+n.SUPPORTED_NODEJS_RUNTIMES.join(",")),triggers:r.z.array(r.z.object({name:r.z.string().describe("Trigger name"),type:r.z.enum(n.SUPPORTED_TRIGGER_TYPES).describe("Trigger type, currently only supports 'timer'"),config:r.z.string().describe("Trigger configuration. For timer triggers, use cron expression format: second minute hour day month week year. IMPORTANT: Must include exactly 7 fields (second minute hour day month week year). Examples: '0 0 2 1 * * *' (monthly), '0 30 9 * * * *' (daily at 9:30 AM)")})).optional().describe("Trigger configuration array"),handler:r.z.string().optional().describe("函数入口"),ignore:r.z.union([r.z.string(),r.z.array(r.z.string())]).optional().describe("忽略文件"),isWaitInstall:r.z.boolean().optional().describe("是否等待依赖安装"),layers:r.z.array(r.z.object({name:r.z.string(),version:r.z.number()})).optional().describe("Layer配置")}).describe("函数配置"),functionRootPath:r.z.string().optional().describe("函数根目录(云函数目录的父目录),这里需要传操作系统上文件的绝对路径,注意:不要包含函数名本身,例如函数名为 'hello',应传入 '/path/to/cloudfunctions',而不是 '/path/to/cloudfunctions/hello'"),force:r.z.boolean().describe("是否覆盖")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"functions"}},async({func:e,functionRootPath:t,force:r})=>{if(e.runtime){const t=e.runtime.replace(/\s+/g,"");n.SUPPORTED_NODEJS_RUNTIMES.includes(t)?e.runtime=t:e.runtime.includes(" ")&&(console.warn(`检测到 runtime 参数包含空格: "${e.runtime}",已自动移除空格`),e.runtime=t)}else e.runtime=n.DEFAULT_NODEJS_RUNTIME;if(!n.SUPPORTED_NODEJS_RUNTIMES.includes(e.runtime))throw new Error(`不支持的运行时环境: "${e.runtime}"。支持的值:${n.SUPPORTED_NODEJS_RUNTIMES.join(", ")}`);e.installDependency=!0;const a=s(t,e.name),i=await o(),c=await i.functions.createFunction({func:e,functionRootPath:a,force:r});return{content:[{type:"text",text:JSON.stringify(c,null,2)}]}}),e.registerTool("updateFunctionCode",{title:"更新云函数代码",description:"更新函数代码",inputSchema:{name:r.z.string().describe("函数名称"),functionRootPath:r.z.string().describe("函数根目录(云函数目录的父目录),这里需要传操作系统上文件的绝对路径")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"functions"}},async({name:e,functionRootPath:t,zipFile:r,handler:a,runtime:i})=>{i||(i=n.DEFAULT_NODEJS_RUNTIME);const c={func:{name:e,installDependency:!0,...a&&{handler:a},...i&&{runtime:i}},functionRootPath:s(t,e)};r&&(c.zipFile=r);const l=await o(),d=await l.functions.updateFunctionCode(c);return{content:[{type:"text",text:JSON.stringify(d,null,2)}]}}),e.registerTool?.("updateFunctionConfig",{title:"更新云函数配置",description:"更新云函数配置",inputSchema:{funcParam:r.z.object({name:r.z.string().describe("函数名称"),timeout:r.z.number().optional().describe("超时时间"),envVariables:r.z.record(r.z.string()).optional().describe("环境变量"),vpc:r.z.object({vpcId:r.z.string(),subnetId:r.z.string()}).optional().describe("VPC配置")}).describe("函数配置")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"functions"}},async({funcParam:e})=>{const n=await o(),t=await n.functions.updateFunctionConfig(e);return{content:[{type:"text",text:JSON.stringify(t,null,2)}]}}),e.registerTool?.("getFunctionDetail",{title:"获取云函数详情",description:"获取云函数详情",inputSchema:{name:r.z.string().describe("函数名称"),codeSecret:r.z.string().optional().describe("代码保护密钥")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"functions"}},async({name:e,codeSecret:n})=>{const t=await o(),r=await t.functions.getFunctionDetail(e,n);return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}),e.registerTool?.("invokeFunction",{title:"调用云函数",description:"调用云函数",inputSchema:{name:r.z.string().describe("函数名称"),params:r.z.record(r.z.any()).optional().describe("调用参数")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"functions"}},async({name:e,params:n})=>{const t=await o(),r=await t.functions.invokeFunction(e,n);return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}),e.registerTool?.("getFunctionLogs",{title:"获取云函数日志(新版)",description:"获取云函数日志基础信息(LogList),如需日志详情请用 RequestId 调用 getFunctionLogDetail 工具。此接口基于 manger-node 4.4.0+ 的 getFunctionLogsV2 实现,不返回具体日志内容。参数 offset+limit 不得大于 10000,startTime/endTime 间隔不得超过一天。",inputSchema:{name:r.z.string().describe("函数名称"),offset:r.z.number().optional().describe("数据的偏移量,Offset+Limit 不能大于 10000"),limit:r.z.number().optional().describe("返回数据的长度,Offset+Limit 不能大于 10000"),startTime:r.z.string().optional().describe("查询的具体日期,例如:2017-05-16 20:00:00,只能与 EndTime 相差一天之内"),endTime:r.z.string().optional().describe("查询的具体日期,例如:2017-05-16 20:59:59,只能与 StartTime 相差一天之内"),requestId:r.z.string().optional().describe("执行该函数对应的 requestId"),qualifier:r.z.string().optional().describe("函数版本,默认为 $LATEST")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"functions"}},async({name:e,offset:n,limit:t,startTime:r,endTime:a,requestId:i,qualifier:s})=>{if((n||0)+(t||0)>1e4)throw new Error("offset+limit 不能大于 10000");if(r&&a){const e=new Date(r).getTime();if(new Date(a).getTime()-e>864e5)throw new Error("startTime 和 endTime 间隔不能超过一天")}const c=await o(),l=await c.functions.getFunctionLogsV2({name:e,offset:n,limit:t,startTime:r,endTime:a,requestId:i,qualifier:s});return{content:[{type:"text",text:JSON.stringify(l,null,2)}]}}),e.registerTool?.("getFunctionLogDetail",{title:"获取云函数日志详情",description:"根据 getFunctionLogs 返回的 RequestId 查询日志详情。参数 startTime、endTime、requestId,返回日志内容(LogJson 等)。仅支持 manger-node 4.4.0+。",inputSchema:{startTime:r.z.string().optional().describe("查询的具体日期,例如:2017-05-16 20:00:00,只能与 EndTime 相差一天之内"),endTime:r.z.string().optional().describe("查询的具体日期,例如:2017-05-16 20:59:59,只能与 StartTime 相差一天之内"),requestId:r.z.string().describe("执行该函数对应的 requestId")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"functions"}},async({startTime:e,endTime:n,requestId:t})=>{if(e&&n){const t=new Date(e).getTime();if(new Date(n).getTime()-t>864e5)throw new Error("startTime 和 endTime 间隔不能超过一天")}const r=await o(),a=await r.functions.getFunctionLogDetail({startTime:e,endTime:n,logRequestId:t});return{content:[{type:"text",text:JSON.stringify(a,null,2)}]}}),e.registerTool?.("createFunctionTriggers",{title:"创建云函数触发器",description:"创建云函数触发器",inputSchema:{name:r.z.string().describe("函数名"),triggers:r.z.array(r.z.object({name:r.z.string().describe("Trigger name"),type:r.z.enum(n.SUPPORTED_TRIGGER_TYPES).describe("Trigger type, currently only supports 'timer'"),config:r.z.string().describe("Trigger configuration. For timer triggers, use cron expression format: second minute hour day month week year. IMPORTANT: Must include exactly 7 fields (second minute hour day month week year). Examples: '0 0 2 1 * * *' (monthly), '0 30 9 * * * *' (daily at 9:30 AM)")})).describe("Trigger configuration array")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"functions"}},async({name:e,triggers:n})=>{const t=await o(),r=await t.functions.createFunctionTriggers(e,n);return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}),e.registerTool?.("deleteFunctionTrigger",{title:"删除云函数触发器",description:"删除云函数触发器",inputSchema:{name:r.z.string().describe("函数名"),triggerName:r.z.string().describe("触发器名称")},annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!0,openWorldHint:!0,category:"functions"}},async({name:e,triggerName:n})=>{const o=await(0,a.getCloudBaseManager)({cloudBaseOptions:t}),r=await o.functions.deleteFunctionTrigger(e,n);return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}})};const r=t(971),a=t(431),i=o(t(521));function s(e,n){if(!e)return e;const t=i.default.normalize(e);if(i.default.basename(t)===n){const e=i.default.dirname(t);return console.warn(`检测到 functionRootPath 包含函数名 "${n}",已自动调整为父目录: ${e}`),e}return e}n.SUPPORTED_NODEJS_RUNTIMES=["Nodejs18.15","Nodejs16.13","Nodejs14.18","Nodejs12.16","Nodejs10.15","Nodejs8.9"],n.DEFAULT_NODEJS_RUNTIME="Nodejs18.15",n.SUPPORTED_TRIGGER_TYPES=["timer"],n.TRIGGER_CONFIG_EXAMPLES={timer:{description:"Timer trigger configuration using cron expression format: second minute hour day month week year",examples:["0 0 2 1 * * *","0 30 9 * * * *","0 0 12 * * * *","0 0 0 1 1 * *"]}}},971:e=>{e.exports=v}},S={};function E(e){var n=S[e];if(void 0!==n)return n.exports;var t=S[e]={exports:{}};return I[e].call(t.exports,t,t.exports,E),t.exports}w=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,E.t=function(e,n){if(1&n&&(e=this(e)),8&n)return e;if("object"==typeof e&&e){if(4&n&&e.__esModule)return e;if(16&n&&"function"==typeof e.then)return e}var t=Object.create(null);E.r(t);var o={};x=x||[null,w({}),w([]),w(w)];for(var r=2&n&&e;("object"==typeof r||"function"==typeof r)&&!~x.indexOf(r);r=w(r))Object.getOwnPropertyNames(r).forEach(n=>o[n]=()=>e[n]);return o.default=()=>e,E.d(t,o),t},E.d=(e,n)=>{for(var t in n)E.o(n,t)&&!E.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},E.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),E.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var T={};(()=>{var e=T;Object.defineProperty(e,"BJ",{value:!0}),e.q8=e.bM=e.fW=e._k=e.T$=e.$n=e.S=e.bT=e.ri=e.BS=e.R8=e.z3=e.pq=e.R4=e.ps=e.v7=e.S7=e.dD=e.Gh=void 0,e.SJ=async function(){const{getInteractiveServer:e}=await Promise.resolve().then(E.t.bind(E,341,23));return e(void 0)};var n=E(422);Object.defineProperty(e,"Gh",{enumerable:!0,get:function(){return n.createCloudBaseMcpServer}}),Object.defineProperty(e,"dD",{enumerable:!0,get:function(){return n.getDefaultServer}}),Object.defineProperty(e,"S7",{enumerable:!0,get:function(){return n.StdioServerTransport}}),Object.defineProperty(e,"v7",{enumerable:!0,get:function(){return n.telemetryReporter}}),Object.defineProperty(e,"ps",{enumerable:!0,get:function(){return n.reportToolkitLifecycle}}),Object.defineProperty(e,"R4",{enumerable:!0,get:function(){return n.reportToolCall}}),Object.defineProperty(e,"pq",{enumerable:!0,get:function(){return n.info}}),Object.defineProperty(e,"z3",{enumerable:!0,get:function(){return n.error}}),Object.defineProperty(e,"R8",{enumerable:!0,get:function(){return n.warn}});var t=E(291);Object.defineProperty(e,"BS",{enumerable:!0,get:function(){return t.getLoginState}}),Object.defineProperty(e,"ri",{enumerable:!0,get:function(){return t.logout}});var o=E(684);Object.defineProperty(e,"bT",{enumerable:!0,get:function(){return o.isCloudMode}}),Object.defineProperty(e,"S",{enumerable:!0,get:function(){return o.enableCloudMode}}),Object.defineProperty(e,"$n",{enumerable:!0,get:function(){return o.getCloudModeStatus}}),Object.defineProperty(e,"T$",{enumerable:!0,get:function(){return o.shouldRegisterTool}});var r=E(431);Object.defineProperty(e,"_k",{enumerable:!0,get:function(){return r.getCloudBaseManager}}),Object.defineProperty(e,"fW",{enumerable:!0,get:function(){return r.getEnvId}}),Object.defineProperty(e,"bM",{enumerable:!0,get:function(){return r.resetCloudBaseManagerCache}}),Object.defineProperty(e,"q8",{enumerable:!0,get:function(){return r.createCloudBaseManagerWithOptions}})})();const O=T.S7,C=T.BJ,k=T.q8,D=T.Gh,z=T.S,$=T.z3,M=T._k,_=T.$n,N=T.dD,j=T.fW,P=T.SJ,B=T.BS,R=T.pq,A=T.bT,L=T.ri,H=T.R4,U=T.ps,F=T.bM,q=T.T$,J=T.v7,W=T.R8;export{O as StdioServerTransport,C as __esModule,k as createCloudBaseManagerWithOptions,D as createCloudBaseMcpServer,z as enableCloudMode,$ as error,M as getCloudBaseManager,_ as getCloudModeStatus,N as getDefaultServer,j as getEnvId,P as getInteractiveServerAsync,B as getLoginState,R as info,A as isCloudMode,L as logout,H as reportToolCall,U as reportToolkitLifecycle,F as resetCloudBaseManagerCache,q as shouldRegisterTool,J as telemetryReporter,W as warn};