@cloudbase/cloudbase-mcp 1.8.37 → 1.8.39

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 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.37"}\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.37),便于后续维护和版本追踪\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.37";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};
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 r from"ws";import*as o 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"child_process";import*as f from"crypto";import*as b from"https";import*as h from"adm-zip";import*as v from"url";import*as y from"fs/promises";import*as x from"zod";var w,I,S={23:function(e,n,t){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(n,"__esModule",{value:!0}),n.CLOUDRUN_ACCESS_TYPES=n.CLOUDRUN_SERVICE_TYPES=void 0,n.registerCloudRunTools=function(e){const n=e.cloudBaseOptions,t=()=>(0,a.getCloudBaseManager)({cloudBaseOptions:n});e.registerTool("queryCloudRun",{title:"查询 CloudRun 服务信息",description:"查询云托管服务信息,支持获取服务列表、查询服务详情和获取可用模板列表。返回的服务信息包括服务名称、状态、访问类型、配置详情等。",inputSchema:l,annotations:{readOnlyHint:!0,openWorldHint:!0,category:"cloudrun"}},async e=>{try{const n=e,r=await t();if(!r)throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");const o=r.cloudrun;switch(n.action){case"list":{const e={pageSize:n.pageSize,pageNum:n.pageNum};n.serverName&&(e.serverName=n.serverName),n.serverType&&(e.serverType=n.serverType);const t=await o.list(e);return{content:[{type:"text",text:JSON.stringify({success:!0,data:{services:t.ServerList||[],pagination:{total:t.Total||0,pageSize:n.pageSize,pageNum:n.pageNum,totalPages:Math.ceil((t.Total||0)/(n.pageSize||10))}},message:`Found ${t.ServerList?.length||0} CloudRun services`},null,2)}]}}case"detail":{const e=n.detailServerName||n.serverName,t=await o.detail({serverName:e});return t?{content:[{type:"text",text:JSON.stringify({success:!0,data:{service:t},message:`Retrieved details for service '${e}'`},null,2)}]}:{content:[{type:"text",text:JSON.stringify({success:!1,error:`Service '${e}' not found`,message:"Please check the service name and try again."},null,2)}]}}case"templates":{const e=await o.getTemplates();return{content:[{type:"text",text:JSON.stringify({success:!0,data:{templates:e||[]},message:`Found ${e?.length||0} available templates`},null,2)}]}}default:throw new Error(`Unsupported action: ${n.action}`)}}catch(e){return{content:[{type:"text",text:JSON.stringify({success:!1,error:e.message||"Unknown error occurred",message:"Failed to query CloudRun information. Please check your permissions and try again."},null,2)}]}}});const r=new Map;e.registerTool("manageCloudRun",{title:"管理 CloudRun 服务",description:"管理云托管服务,按开发顺序支持:初始化项目(可从模板开始,模板列表可通过 queryCloudRun 查询)、下载服务代码、本地运行(仅函数型服务)、部署代码、删除服务。部署可配置CPU、内存、实例数、访问类型等参数。删除操作需要确认,建议设置force=true。",inputSchema:d,annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1,openWorldHint:!0,category:"cloudrun"}},async e=>{try{const n=e,o=await t();if(!o)throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");const a=o.cloudrun;let l;switch(n.targetPath&&(l=function(e){let n=i.default.resolve(e);const t=process.cwd();if(!n.startsWith(t)&&!i.default.isAbsolute(e))throw new Error(`Path must be within current working directory: ${t}`);return n}(n.targetPath)),n.action){case"createAgent":{if(!l)throw new Error("targetPath is required for createAgent operation");if(!n.agentConfig)throw new Error("agentConfig is required for createAgent operation");const{agentName:e,botTag:t,description:r,template:a="blank"}=n.agentConfig,c=t?`ibot-${e}-${t}`:`ibot-${e}-${Date.now()}`,d=(await o.agent.createFunctionAgent(l,{Name:e,BotId:c,Introduction:r||`Agent created by ${e}`,Avatar:void 0}),i.default.join(l,n.serverName));s.default.existsSync(d)||s.default.mkdirSync(d,{recursive:!0});const u={name:n.serverName,version:"1.0.0",description:r||`Agent created by ${e}`,main:"index.js",scripts:{dev:"tcb cloudrun run --runMode=agent -w",deploy:"tcb cloudrun deploy",start:"node index.js"},dependencies:{"@cloudbase/aiagent-framework":"^1.0.0-beta.10"},devDependencies:{"@cloudbase/cli":"^2.6.16"}};s.default.writeFileSync(i.default.join(d,"package.json"),JSON.stringify(u,null,2));const p='const { IBot } = require("@cloudbase/aiagent-framework");\nconst { BotRunner } = require("@cloudbase/aiagent-framework");\n\nconst ANSWER = "你好,我是一个智能体,但我只会说这一句话。";\n\n/**\n * @typedef {import(\'@cloudbase/aiagent-framework\').IAbstractBot} IAbstractBot\n * \n * @class\n * @implements {IAbstractBot}\n */\nclass MyBot extends IBot {\n async sendMessage() {\n return new Promise((res) => {\n // 创建个字符数组\n const charArr = ANSWER.split("");\n const interval = setInterval(() => {\n // 定时循环从数组中去一个字符\n const char = charArr.shift();\n if (typeof char === "string") {\n // 有字符时,发送 SSE 消息给客户端\n this.sseSender.send({ data: { content: char } });\n } else {\n // 字符用光后,结束定时循环\n clearInterval(interval);\n // 结束 SSE\n this.sseSender.end();\n res();\n }\n }, 50);\n });\n }\n}\n\n/**\n * 类型完整定义请参考:https://docs.cloudbase.net/cbrf/how-to-writing-functions-code#%E5%AE%8C%E6%95%B4%E7%A4%BA%E4%BE%8B\n * "{demo: string}"" 为 event 参数的示例类型声明,请根据实际情况进行修改\n * 需要 `pnpm install` 安装依赖后类型提示才会生效\n * \n * @type {import(\'@cloudbase/functions-typings\').TcbEventFunction<unknown>}\n */\nexports.main = function (event, context) {\n return BotRunner.run(event, context, new MyBot(context));\n};\n';s.default.writeFileSync(i.default.join(d,"index.js"),p);const g={envId:process.env.TCB_ENV_ID||"",cloudrun:{name:n.serverName}};s.default.writeFileSync(i.default.join(d,"cloudbaserc.json"),JSON.stringify(g,null,2));const m=`# ${e} Agent\n\n这是一个基于函数型云托管的 AI 智能体。\n\n## 开发\n\n\`\`\`bash\n# 安装依赖\nnpm install\n\n# 本地开发\nnpm run dev\n\n# 部署\nnpm run deploy\n\`\`\`\n\n## 调用方式\n\n### 命令行测试\n\`\`\`bash\ncurl 'http://127.0.0.1:3000/v1/aibot/bots/${c}/send-message' \\\n -H 'Accept: text/event-stream' \\\n -H 'Content-Type: application/json' \\\n --data-raw '{"msg":"hi"}'\n\`\`\`\n\n### Web 调用\n\`\`\`html\n<script src="//static.cloudbase.net/cloudbase-js-sdk/2.9.0/cloudbase.full.js"><\/script>\n<script>\nconst app = cloudbase.init({ env: "your-env-id" });\nconst auth = app.auth();\nawait auth.signInAnonymously();\nconst ai = app.ai();\nconst res = await ai.bot.sendMessage({\n botId: "${c}",\n msg: "hi",\n});\nfor await (let x of res.textStream) {\n console.log(x);\n}\n<\/script>\n\`\`\`\n`;return s.default.writeFileSync(i.default.join(d,"README.md"),m),{content:[{type:"text",text:JSON.stringify({success:!0,data:{agentName:e,botId:c,projectDir:d,serverName:n.serverName,template:a,filesCreated:["package.json","index.js","cloudbaserc.json","README.md"]},message:`Successfully created Agent '${e}' with BotId '${c}' in ${d}`},null,2)}]}}case"deploy":{if(!l)throw new Error("targetPath is required for deploy operation");let e;try{const t=await a.detail({serverName:n.serverName});e=t.BaseInfo?.ServerType||"function"}catch(n){const t=i.default.join(l,"Dockerfile");e=s.default.existsSync(t)?"container":"function"}const t={serverName:n.serverName,targetPath:l,force:n.force,serverType:e};n.serverConfig&&Object.assign(t,n.serverConfig),await a.deploy(t);const r=i.default.join(l,"cloudbaserc.json"),o={envId:process.env.TCB_ENV_ID||"",cloudrun:{name:n.serverName}};try{s.default.writeFileSync(r,JSON.stringify(o,null,2))}catch(e){}return{content:[{type:"text",text:JSON.stringify({success:!0,data:{serviceName:n.serverName,status:"deployed",deployPath:l,serverType:e,cloudbasercGenerated:!0},message:`Successfully deployed ${e} service '${n.serverName}' from ${l}`},null,2)}]}}case"run":{if(!l)throw new Error("targetPath is required for run operation");const e=i.default.join(l,"Dockerfile");if(s.default.existsSync(e))throw new Error("Local run is only supported for function-type CloudRun services. Container services are not supported.");const t=function(e){try{const n=i.default.join(e,"package.json");if(s.default.existsSync(n)){const e=JSON.parse(s.default.readFileSync(n,"utf8"));if({...e.dependencies,...e.devDependencies}["@cloudbase/aiagent-framework"])return!0}const t=i.default.join(e,"index.js");if(s.default.existsSync(t)){const e=s.default.readFileSync(t,"utf8");if(e.includes("@cloudbase/aiagent-framework")||e.includes("BotRunner")||e.includes("IBot")||e.includes("BotCore"))return!0}return!1}catch(e){return!1}}(l),o=n.runOptions?.runMode||(t?"agent":"normal");if(r.has(n.serverName)){const e=r.get(n.serverName);try{return process.kill(e,0),{content:[{type:"text",text:JSON.stringify({success:!0,data:{serviceName:n.serverName,status:"running",pid:e,cwd:l},message:`Service '${n.serverName}' is already running locally (pid=${e})`},null,2)}]}}catch(e){r.delete(n.serverName)}}const a=n.runOptions?.port??3e3,d=n.runOptions?.envParams??{},u={...process.env,PORT:String(a),...d,ENABLE_CORS:"true",ALLOWED_ORIGINS:"*"};let p,g;if("agent"===o?(g=`node -e "\n const { runCLI } = require('@cloudbase/functions-framework');\n process.env.PORT = '${a}';\n process.env.ENABLE_CORS = 'true';\n process.env.ALLOWED_ORIGINS = '*';\n process.env.RUN_MODE = 'agent';\n ${Object.entries(d).map(([e,n])=>`process.env.${e} = '${n}';`).join("\n")}\n runCLI();\n "`,p=(0,c.spawn)(process.execPath,["-e",g],{cwd:l,env:u,stdio:["ignore","pipe","pipe"],detached:!0})):(g=`node -e "\n const { runCLI } = require('@cloudbase/functions-framework');\n process.env.PORT = '${a}';\n process.env.ENABLE_CORS = 'true';\n process.env.ALLOWED_ORIGINS = '*';\n ${Object.entries(d).map(([e,n])=>`process.env.${e} = '${n}';`).join("\n")}\n runCLI();\n "`,p=(0,c.spawn)(process.execPath,["-e",g],{cwd:l,env:u,stdio:["ignore","pipe","pipe"],detached:!0})),p.on("exit",(e,t)=>{r.delete(n.serverName)}),p.on("error",e=>{r.delete(n.serverName)}),p.unref(),"number"!=typeof p.pid)throw new Error("Failed to start local process: PID is undefined.");return r.set(n.serverName,p.pid),{content:[{type:"text",text:JSON.stringify({success:!0,data:{serviceName:n.serverName,status:"running",pid:p.pid,port:a,runMode:o,isAgent:t,command:g,cwd:l},message:`Started local run for ${o} service '${n.serverName}' on port ${a} (pid=${p.pid})`},null,2)}]}}case"download":{if(!l)throw new Error("targetPath is required for download operation");await a.download({serverName:n.serverName,targetPath:l});const e=i.default.join(l,"cloudbaserc.json"),t={envId:process.env.TCB_ENV_ID||"",cloudrun:{name:n.serverName}};try{s.default.writeFileSync(e,JSON.stringify(t,null,2))}catch(e){}return{content:[{type:"text",text:JSON.stringify({success:!0,data:{serviceName:n.serverName,downloadPath:l,filesCount:0,cloudbasercGenerated:!0},message:`Successfully downloaded service '${n.serverName}' to ${l}`},null,2)}]}}case"delete":return n.force?(await a.delete({serverName:n.serverName}),{content:[{type:"text",text:JSON.stringify({success:!0,data:{serviceName:n.serverName,status:"deleted"},message:`Successfully deleted service '${n.serverName}'`},null,2)}]}):{content:[{type:"text",text:JSON.stringify({success:!1,error:"Delete operation requires confirmation",message:"Please set force: true to confirm deletion of the service. This action cannot be undone."},null,2)}]};case"init":{if(!l)throw new Error("targetPath is required for init operation");const e=await a.init({serverName:n.serverName,targetPath:l,template:n.template}),t=i.default.join(l,n.serverName,"cloudbaserc.json"),r={envId:process.env.TCB_ENV_ID||"",cloudrun:{name:n.serverName}};try{s.default.writeFileSync(t,JSON.stringify(r,null,2))}catch(e){}return{content:[{type:"text",text:JSON.stringify({success:!0,data:{serviceName:n.serverName,template:n.template,initPath:l,projectDir:e.projectDir||i.default.join(l,n.serverName),cloudbasercGenerated:!0},message:`Successfully initialized service '${n.serverName}' with template '${n.template}' at ${l}`},null,2)}]}}default:throw new Error(`Unsupported action: ${n.action}`)}}catch(n){return{content:[{type:"text",text:JSON.stringify({success:!1,error:n.message||"Unknown error occurred",message:`Failed to ${e.action} CloudRun service. Please check your permissions and parameters.`},null,2)}]}}})};const o=t(971),a=t(431),i=r(t(521)),s=r(t(421)),c=t(814);n.CLOUDRUN_SERVICE_TYPES=["function","container"],n.CLOUDRUN_ACCESS_TYPES=["WEB","VPC","PRIVATE"];const l={action:o.z.enum(["list","detail","templates"]).describe("查询操作类型:list=获取云托管服务列表(支持分页和筛选),detail=查询指定服务的详细信息(包括配置、版本、访问地址等),templates=获取可用的项目模板列表(用于初始化新项目)"),pageSize:o.z.number().min(1).max(100).optional().default(10).describe("分页大小,控制每页返回的服务数量。取值范围:1-100,默认值:10。建议根据网络性能和显示需求调整"),pageNum:o.z.number().min(1).optional().default(1).describe("页码,用于分页查询。从1开始,默认值:1。配合pageSize使用可实现分页浏览"),serverName:o.z.string().optional().describe('服务名称筛选条件,支持模糊匹配。例如:输入"test"可匹配"test-service"、"my-test-app"等服务名称。留空则查询所有服务'),serverType:o.z.enum(n.CLOUDRUN_SERVICE_TYPES).optional().describe("服务类型筛选条件:function=函数型云托管(简化开发模式,支持WebSocket/SSE/文件上传等特性,适合快速开发),container=容器型服务(传统容器部署模式,支持任意语言和框架,适合复杂应用)"),detailServerName:o.z.string().optional().describe("要查询详细信息的服务名称。当action为detail时必需提供,必须是已存在的服务名称。可通过list操作获取可用的服务名称列表")},d={action:o.z.enum(["init","download","run","deploy","delete","createAgent"]).describe("云托管服务管理操作类型:init=从模板初始化新的云托管项目代码(在targetPath目录下创建以serverName命名的子目录,支持多种语言和框架模板),download=从云端下载现有服务的代码到本地进行开发,run=在本地运行函数型云托管服务(用于开发和调试,仅支持函数型服务),deploy=将本地代码部署到云端云托管服务(支持函数型和容器型),delete=删除指定的云托管服务(不可恢复,需要确认),createAgent=创建函数型Agent(基于函数型云托管开发AI智能体)"),serverName:o.z.string().describe("云托管服务名称,用于标识和管理服务。命名规则:支持大小写字母、数字、连字符和下划线,必须以字母开头,长度3-45个字符。在init操作中会作为在targetPath下创建的子目录名,在其他操作中作为目标服务名"),targetPath:o.z.string().optional().describe("本地代码路径,必须是绝对路径。在deploy操作中指定要部署的代码目录,在download操作中指定下载目标目录,在init操作中指定云托管服务的上级目录(会在该目录下创建以serverName命名的子目录)。建议约定:项目根目录下的cloudrun/目录,例如:/Users/username/projects/my-project/cloudrun"),serverConfig:o.z.object({OpenAccessTypes:o.z.array(o.z.enum(n.CLOUDRUN_ACCESS_TYPES)).optional().describe("公网访问类型配置,控制服务的访问权限:WEB=公网访问(默认,可通过HTTPS域名访问),VPC=私有网络访问(仅同VPC内可访问),PRIVATE=内网访问(仅云开发环境内可访问)。可配置多个类型"),Cpu:o.z.number().positive().optional().describe("CPU规格配置,单位为核。可选值:0.25、0.5、1、2、4、8等。注意:内存规格必须是CPU规格的2倍(如CPU=0.25时内存=0.5,CPU=1时内存=2)。影响服务性能和计费"),Mem:o.z.number().positive().optional().describe("内存规格配置,单位为GB。可选值:0.5、1、2、4、8、16等。注意:必须是CPU规格的2倍。影响服务性能和计费"),MinNum:o.z.number().min(0).optional().describe("最小实例数配置,控制服务的最小运行实例数量。设置为0时支持缩容到0(无请求时不产生费用),设置为大于0时始终保持指定数量的实例运行(确保快速响应但会增加成本)"),MaxNum:o.z.number().min(1).optional().describe("最大实例数配置,控制服务的最大运行实例数量。当请求量增加时,服务最多可以扩展到指定数量的实例,超过此数量后将拒绝新的请求。建议根据业务峰值设置"),Port:o.z.number().min(1).max(65535).optional().describe("服务监听端口配置。函数型服务固定为3000,容器型服务可自定义。服务代码必须监听此端口才能正常接收请求"),EnvParams:o.z.record(o.z.string()).optional().describe('环境变量配置,用于传递配置信息给服务代码。格式为键值对,如{"DATABASE_URL":"mysql://..."}。敏感信息建议使用环境变量而非硬编码'),Dockerfile:o.z.string().optional().describe("Dockerfile文件名配置,仅容器型服务需要。指定用于构建容器镜像的Dockerfile文件路径,默认为项目根目录下的Dockerfile"),BuildDir:o.z.string().optional().describe("构建目录配置,指定代码构建的目录路径。当代码结构与标准不同时使用,默认为项目根目录"),InternalAccess:o.z.boolean().optional().describe("内网访问开关配置,控制是否启用内网访问。true=启用内网访问(可通过云开发SDK直接调用),false=关闭内网访问(仅公网访问)"),EntryPoint:o.z.string().optional().describe('Dockerfile EntryPoint参数配置,仅容器型服务需要。指定容器启动时的入口程序,如["node","app.js"]'),Cmd:o.z.string().optional().describe('Dockerfile Cmd参数配置,仅容器型服务需要。指定容器启动时的默认命令,如["npm","start"]')}).optional().describe("服务配置项,用于部署时设置服务的运行参数。包括资源规格、访问权限、环境变量等配置。不提供时使用默认配置"),template:o.z.string().optional().default("helloworld").describe("项目模板标识符,用于指定初始化项目时使用的模板。可通过queryCloudRun的templates操作获取可用模板列表。常用模板:helloworld=Hello World示例,nodejs=Node.js项目模板,python=Python项目模板等"),runOptions:o.z.object({port:o.z.number().min(1).max(65535).optional().default(3e3).describe("本地运行端口配置,仅函数型服务有效。指定服务在本地运行时监听的端口号,默认3000。确保端口未被其他程序占用"),envParams:o.z.record(o.z.string()).optional().describe('本地运行时的附加环境变量配置,用于本地开发和调试。格式为键值对,如{"DEBUG":"true","LOG_LEVEL":"debug"}。这些变量仅在本地运行时生效'),runMode:o.z.enum(["normal","agent"]).optional().default("normal").describe("运行模式:normal=普通函数模式,agent=Agent模式(用于AI智能体开发)"),agentId:o.z.string().optional().describe("Agent ID,在agent模式下使用,用于标识特定的Agent实例")}).optional().describe("本地运行参数配置,仅函数型云托管服务支持。用于配置本地开发环境的运行参数,不影响云端部署"),agentConfig:o.z.object({agentName:o.z.string().describe("Agent名称,用于生成BotId"),botTag:o.z.string().optional().describe("Bot标签,用于生成BotId,不提供时自动生成"),description:o.z.string().optional().describe("Agent描述信息"),template:o.z.string().optional().default("blank").describe("Agent模板类型,默认为blank(空白模板)")}).optional().describe("Agent配置项,仅在createAgent操作时使用"),force:o.z.boolean().optional().default(!1).describe("强制操作开关,用于跳过确认提示。默认false(需要确认),设置为true时跳过所有确认步骤。删除操作时强烈建议设置为true以避免误操作")}},39:function(e,n,t){var r=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 o=r(t(932)),a=r(t(521)),i=r(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 r=(new Date).toISOString(),a=s[e],i=t?`[${r}] [${a}] ${n} ${JSON.stringify(t,null,2)}`:`[${r}] [${a}] ${n}`;if(this.useConsole&&console.error(i),this.logFile)try{await o.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 o.default.writeFile(this.logFile,"")}catch(e){}}async getLogs(e=1e3){if(!this.logFile)return[];try{return(await o.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 r,o=this&&this.__createBinding||(Object.create?function(e,n,t,r){void 0===r&&(r=t);var o=Object.getOwnPropertyDescriptor(n,t);o&&!("get"in o?!n.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return n[t]}}),Object.defineProperty(e,r,o)}:function(e,n,t,r){void 0===r&&(r=t),e[r]=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||(r=function(e){return r=Object.getOwnPropertyNames||function(e){var n=[];for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[n.length]=t);return n},r(e)},function(e){if(e&&e.__esModule)return e;var n={};if(null!=e)for(var t=r(e),i=0;i<t.length;i++)"default"!==t[i]&&o(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 r=>{if(200!==r.statusCode)return void t(new Error(`HTTP Error: ${r.statusCode}`));const o=r.headers["content-type"]||"",a=parseInt(r.headers["content-length"]||"0",10),i=r.headers["content-disposition"];if(!await async function(e,n){try{const t=new f.URL(e);if(!y.includes(t.protocol))return!1;const r=t.hostname;return(!b.isIP(r)||!w(r))&&!(!b.isIP(r)&&await async function(e){try{const n=await new Promise((n,t)=>{h.resolve(e,(e,r)=>{e?t(e):n(r)})});return n.some(e=>w(e))}catch(e){return!0}}(r))&&x.some(e=>n.startsWith(e))}catch{return!1}}(e,o))return void t(new Error("不安全的 URL 或内容类型,或者目标为内网地址"));if(a>v)return void t(new Error(`文件大小 ${a} 字节超过 ${v} 字节限制`));const s=function(e,n,t){let r="";const o=new f.URL(e).pathname,a=d.extname(o);if(a&&(r=a),t){const e=t.match(/filename=["']?([^"']+)["']?/);if(e){const n=d.extname(e[1]);n&&(r=n)}}return!r&&n&&(r={"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]||""),r}(e,o,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;r.on("data",e=>{S+=e.length,S>v&&(I.destroy(),c.unlink(m).catch(()=>{}),t(new Error(`文件大小超过 ${v} 字节限制`)))}),r.pipe(I),I.on("finish",()=>{n({filePath:m,contentType:o,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)),v=104857600,y=["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:r.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(),r=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})}),o=await r.json();if(o.error)throw new Error(o.error.message||"联网搜索失败");return{content:[{type:"text",text:s({type:"web_search",content:o.choices?.[0]?.message?.content||"",search_results:(o.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:r.z.number().default(.5).optional().describe("相似性检索阈值"),id:o.describe("知识库范围,cloudbase=云开发全量知识,scf=云开发的云函数知识, miniprogram=小程序知识(不包含云开发与云函数知识)"),content:r.z.string().describe("检索内容"),options:r.z.object({chunkExpand:r.z.array(r.z.number()).min(2).max(2).default([3,3]).describe("指定返回的文档内容的展开长度,例如 [3,3]代表前后展开长度")}).optional().describe("其他选项"),limit:r.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:r=5,threshold:o=.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:r}})}),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:r}})}),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>=o).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 r=t(971),o=r.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=r},241:e=>{e.exports=o},279:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerHostingTools=function(e){const n=e.cloudBaseOptions,t=()=>(0,o.getCloudBaseManager)({cloudBaseOptions:n});e.registerTool("uploadFiles",{title:"上传静态文件",description:"上传文件到静态网站托管",inputSchema:{localPath:r.z.string().optional().describe("本地文件或文件夹路径,需要是绝对路径,例如 /tmp/files/data.txt"),cloudPath:r.z.string().optional().describe("云端文件或文件夹路径,例如files/data.txt"),files:r.z.array(r.z.object({localPath:r.z.string(),cloudPath:r.z.string()})).default([]).describe("多文件上传配置"),ignore:r.z.union([r.z.string(),r.z.array(r.z.string())]).optional().describe("忽略文件模式")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"hosting"}},async({localPath:e,cloudPath:n,files:r=[],ignore:o})=>{const a=await t(),i=await a.hosting.uploadFiles({localPath:e,cloudPath:n,files:r,ignore:o}),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:r.z.string().describe("云端文件或文件夹路径"),isDir:r.z.boolean().default(!1).describe("是否为文件夹")},annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!0,openWorldHint:!0,category:"hosting"}},async({cloudPath:e,isDir:n=!1})=>{const r=await t(),o=await r.hosting.deleteFiles({cloudPath:e,isDir:n});return{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}),e.registerTool?.("findFiles",{title:"搜索静态文件",description:"搜索静态网站托管的文件",inputSchema:{prefix:r.z.string().describe("匹配前缀"),marker:r.z.string().optional().describe("起始对象键标记"),maxKeys:r.z.number().optional().describe("单次返回最大条目数")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"hosting"}},async({prefix:e,marker:n,maxKeys:r})=>{const o=await t(),a=await o.hosting.findFiles({prefix:e,marker:n,maxKeys:r});return{content:[{type:"text",text:JSON.stringify(a,null,2)}]}}),e.registerTool?.("domainManagement",{title:"静态托管域名管理",description:"统一的域名管理工具,支持绑定、解绑、查询和修改域名配置",inputSchema:{action:r.z.enum(["create","delete","check","modify"]).describe("操作类型: create=绑定域名, delete=解绑域名, check=查询域名配置, modify=修改域名配置"),domain:r.z.string().optional().describe("域名"),certId:r.z.string().optional().describe("证书ID(绑定域名时必需)"),domains:r.z.array(r.z.string()).optional().describe("域名列表(查询配置时使用)"),domainId:r.z.number().optional().describe("域名ID(修改配置时必需)"),domainConfig:r.z.object({Refer:r.z.object({Switch:r.z.string(),RefererRules:r.z.array(r.z.object({RefererType:r.z.string(),Referers:r.z.array(r.z.string()),AllowEmpty:r.z.boolean()})).optional()}).optional(),Cache:r.z.array(r.z.object({RuleType:r.z.string(),RuleValue:r.z.string(),CacheTtl:r.z.number()})).optional(),IpFilter:r.z.object({Switch:r.z.string(),FilterType:r.z.string().optional(),Filters:r.z.array(r.z.string()).optional()}).optional(),IpFreqLimit:r.z.object({Switch:r.z.string(),Qps:r.z.number().optional()}).optional()}).optional().describe("域名配置(修改配置时使用)")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"hosting"}},async({action:e,domain:n,certId:r,domains:o,domainId:a,domainConfig:i})=>{const s=await t();let c;switch(e){case"create":if(!n||!r)throw new Error("绑定域名需要提供域名和证书ID");c=await s.hosting.CreateHostingDomain({domain:n,certId:r});break;case"delete":if(!n)throw new Error("解绑域名需要提供域名");c=await s.hosting.deleteHostingDomain({domain:n});break;case"check":if(!o||0===o.length)throw new Error("查询域名配置需要提供域名列表");c=await s.hosting.tcbCheckResource({domains:o});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 r=t(971),o=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,o.debug)("TENCENTCLOUD_SECRETID",e),e&&n)return(0,o.debug)("loginByApiSecret"),{secretId:e,secretKey:n,token:t};const r=await a.getLoginState();return r||((0,o.debug)("loginByApiSecret"),await a.loginByWebAuth({}),await a.getLoginState())},n.logout=async function(){return await a.logout()};const r=t(90),o=t(39),a=r.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:r.z.string().describe("函数名"),path:r.z.string().describe("HTTP 访问路径")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"gateway"}},async({name:e,path:t})=>{const r=await(0,o.getCloudBaseManager)({cloudBaseOptions:n}),a=await r.access.createAccess({type:1,name:e,path:t});return{content:[{type:"text",text:JSON.stringify(a,null,2)}]}})};const r=t(971),o=t(431)},341:function(e,n,t){var r=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 o=r(t(674)),a=r(t(782)),i=t(220),s=r(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,o.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(o.default.json()),this.app.get("/env-setup/:sessionId",(e,n)=>{const{sessionId:t}=e.params,r=this.sessionData.get(t);r?n.send(this.getEnvSetupHTML(r.envs)):n.status(404).send("会话不存在或已过期")}),this.app.get("/clarification/:sessionId",(e,n)=>{const{sessionId:t}=e.params,r=this.sessionData.get(t);r?n.send(this.getClarificationHTML(r.message,r.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,r=await(0,c.getLogs)(t),o=(0,c.getLoggerStatus)();n.json({logs:r,status:o,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:r}=e.body;(0,c.debug)("Received submit request",{type:t,data:r}),this.currentResolver?((0,c.info)("Resolving with user data"),this.currentResolver({type:t,data:r}),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 r=0;const o=()=>{if(r>=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[r];r++,(0,c.debug)(`Trying to start server on port ${e} (attempt ${r}/${t.length})`),a(e)},a=t=>{this.server.removeAllListeners("error"),this.server.removeAllListeners("listening");const r=e=>{"EADDRINUSE"===e.code?((0,c.warn)(`Port ${t} is in use, trying next port...`),this.server.removeAllListeners("error"),this.server.removeAllListeners("listening"),o()):((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",r),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",r),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),o()}};o()})}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(r=>{clearTimeout(t),r?((0,c.error)("Error closing server:",r),n(r)):((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 r=`http://localhost:${n}/env-setup/${t}`;(0,c.info)(`Opening browser: ${r}`);try{await l(r,{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: ${r}`)}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(),r=Math.random().toString(36).substring(2,15);this.sessionData.set(r,{message:e,options:n}),setTimeout(()=>{this.sessionData.delete(r)},3e5);const o=`http://localhost:${t}/clarification/${r}`;return await l(o,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,r]=n,o=t.toLowerCase();return`<div class="log-line ${o}"><span class="timestamp">[${e}]</span><span class="level ${o}">[${t}]</span>${r}</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-wrap;\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 r=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-wrap;\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 ${r.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 r=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,r,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:r});const u=function(e,n,t){return async r=>{const s=Date.now();let d,u,p=!1;try{(0,a.debug)(`开始执行工具: ${e}`,{args:l(r)});const t=await n(r);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 o=await async function(e,n,t,r,o){const{requestId:s,ide:d}=o||{};let u="";try{const e=await(0,i.getEnvId)(r);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.39"}\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,r,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${o}`));throw n instanceof Error&&(g.stack=n.stack,g.name=n.name),g}finally{const n=Date.now()-s;(0,o.reportToolCall)({toolName:e,success:p,duration:n,error:d,inputParams:l(r),cloudBaseOptions:t.cloudBaseOptions,ide:t.ide||process.env.INTEGRATION_IDE})}}}(t,d,e);return n(t,r,u)}};const o=t(880),a=t(39),i=t(431),s=t(684),c=r(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 r={};for(const[o,a]of Object.entries(n)){const n=o.toLowerCase(),i=t.some(e=>n.includes(e));r[o]=i?"[REDACTED]":e(a)}return r}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=w,n.getDefaultServer=function(){return w()};const r=t(619),o=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(23),v=t(684),y=["env","database","functions","hosting","storage","setup","interactive","rag","cloudrun","gateway","download","security-rule","invite-code"],x={env:{name:"env",register:o.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},cloudrun:{name:"cloudrun",register:h.registerCloudRunTools}};function w(e){const{name:n="cloudbase-mcp",version:t="1.0.0",enableTelemetry:o=!0,cloudBaseOptions:a,cloudMode:i=!1,ide:s}=e??{};i&&(0,v.enableCloudMode)();const c=new r.McpServer({name:n,version:t},{capabilities:{tools:{},..."CodeBuddy"===s?{logging:{}}:{}}});a&&(c.cloudBaseOptions=a),s&&(c.ide=s),o&&(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=x[e];n&&n.register(c)}return c}var I=t(448);Object.defineProperty(n,"StdioServerTransport",{enumerable:!0,get:function(){return I.StdioServerTransport}});var S=t(880);Object.defineProperty(n,"telemetryReporter",{enumerable:!0,get:function(){return S.telemetryReporter}}),Object.defineProperty(n,"reportToolkitLifecycle",{enumerable:!0,get:function(){return S.reportToolkitLifecycle}}),Object.defineProperty(n,"reportToolCall",{enumerable:!0,get:function(){return S.reportToolCall}});var E=t(39);Object.defineProperty(n,"info",{enumerable:!0,get:function(){return E.info}}),Object.defineProperty(n,"error",{enumerable:!0,get:function(){return E.error}}),Object.defineProperty(n,"warn",{enumerable:!0,get:function(){return E.warn}})},431:function(e,n,t){var r=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,o.getLoginState)(),{envId:t,secretId:r,secretKey:a,token:s}=e;let l;return n&&(l=await c.getEnvId()),new i.default({secretId:r,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 o=t(291),a=t(461),i=r(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 r=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:o.z.enum(["clarify","confirm"]).describe("交互类型: clarify=需求澄清, confirm=任务确认"),message:o.z.string().optional().describe("对话消息内容"),options:o.z.array(o.z.string()).optional().describe("可选的预设选项"),forceUpdate:o.z.boolean().optional().describe("是否强制更新环境ID配置"),risks:o.z.array(o.z.string()).optional().describe("操作风险提示")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!1,category:"interactive"}},async({type:n,message:t,options:r,forceUpdate:o=!1,risks:i})=>{try{switch(n){case"clarify":{if(!t)throw new Error("需求澄清必须提供message参数");const n=(0,a.getInteractiveServer)(e),o=await n.clarifyRequest(t,r);return o.cancelled?{content:[{type:"text",text:"用户取消了需求澄清"}]}:{content:[{type:"text",text:`📝 用户澄清反馈:\n${o.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 o=r||["确认执行","取消操作","需要修改任务"],s=(0,a.getInteractiveServer)(e),c=await s.clarifyRequest(n,o);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:r}=await p(!0,void 0);return t||r||n?((0,c.debug)("Auto setup environment ID interrupted or failed silently.",{error:t,noEnvs:r,cancelled:n}),null):((0,c.debug)("Auto setup environment ID successful.",{selectedEnvId:e}),e)}catch(e){return console.error("自动配置环境ID时出错:",e),null}};const o=t(971),a=t(341),i=t(431),s=t(291),c=t(39),l=r(t(932)),d=r(t(521)),u=r(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 r=await(0,i.getCloudBaseManager)({requireEnvId:!1});let o;try{o=await r.env.listEnvs()}catch(e){(0,c.debug)("获取环境ID时出错:",e)}(0,c.debug)("envResult",o);const{EnvList:l}=o||{};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 r,o=this&&this.__createBinding||(Object.create?function(e,n,t,r){void 0===r&&(r=t);var o=Object.getOwnPropertyDescriptor(n,t);o&&!("get"in o?!n.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return n[t]}}),Object.defineProperty(e,r,o)}:function(e,n,t,r){void 0===r&&(r=t),e[r]=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||(r=function(e){return r=Object.getOwnPropertyNames||function(e){var n=[];for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[n.length]=t);return n},r(e)},function(e){if(e&&e.__esModule)return e;var n={};if(null!=e)for(var t=r(e),i=0;i<t.length;i++)"default"!==t[i]&&o(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.39),便于后续维护和版本追踪\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 r=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(!r.valid){const e=r.supportedIDEs?.join(", ")||"";return{content:[{type:"text",text:`❌ ${r.error}\n\n支持的IDE类型: ${e}`}]}}const o=b[e];if(!o)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(o.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=v[n];if(!t)return e;const r=y.filter(e=>!t.includes(e));return e.filter(e=>!r.includes(e))}(c,n),m=process.env.WORKSPACE_FOLDER_PATHS;let E=[],C=0,T=0,O=0;const k=[];if(m){let r=0;for(const n of g){const o=u.join(s,n),a=u.join(m,n),i=await S(o,a,t,e);i.copied?("overwritten"===i.action?T++:C++,E.push(a)):("protected"===i.action?r++:O++,E.push(o))}const a=x[n]||n;k.push(`✅ ${o.description} (${a}) 同步完成`),k.push(`📁 临时目录: ${s}`),k.push(`🔍 文件过滤: ${c.length} → ${g.length} 个文件`);const i=[];C>0&&i.push(`新建 ${C} 个文件`),T>0&&i.push(`覆盖 ${T} 个文件`),r>0&&i.push(`保护 ${r} 个文件(README.md)`),O>0&&i.push(`跳过 ${O} 个已存在文件`),i.length>0&&k.push(`📊 ${i.join(",")}`),(t||T>0||O>0)&&k.push("🔄 覆盖模式: "+(t?"启用":"禁用"))}else{E=g.map(e=>u.join(s,e));const e=x[n]||n;k.push(`✅ ${o.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"],v={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"]},y=Array.from(new Set(Object.values(v).flat()));v.all=y;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,r)=>{(e.startsWith("https:")?g:m).get(e,e=>{if(200===e.statusCode){const o=l.createWriteStream(n);e.pipe(o),o.on("finish",()=>{o.close(),t()}),o.on("error",r)}else 302===e.statusCode||301===e.statusCode?e.headers.location?w(e.headers.location,n).then(t).catch(r):r(new Error("重定向但没有location header")):r(new Error(`下载失败,状态码: ${e.statusCode}`))}).on("error",r)})}async function I(e,n=e){const t=[],r=await d.readdir(e,{withFileTypes:!0});for(const o of r){const r=u.join(e,o.name);if(o.isDirectory()){const e=await I(r,n);t.push(...e)}else t.push(u.relative(n,r))}return t}async function S(e,n,t=!1,r){try{const o=l.existsSync(n);return r&&function(e,n,t){const r="readme.md"===u.basename(n).toLowerCase(),o="rules"===e,a=l.existsSync(n);return r&&o&&a&&!t}(r,n,t)?{copied:!1,reason:"README.md 文件已存在,已保护",action:"protected"}:o&&!t?{copied:!1,reason:"文件已存在",action:"skipped"}:(await d.mkdir(u.dirname(n),{recursive:!0}),await d.copyFile(e,n),{copied:!0,action:o?"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,o.getCloudBaseManager)({cloudBaseOptions:n});e.registerTool?.("login",{title:"登录云开发",description:"登录云开发环境并选择要使用的环境",inputSchema:{forceUpdate:r.z.boolean().optional().describe("是否强制重新选择环境")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"env"}},async({forceUpdate:n=!1})=>{try{const{selectedEnvId:t,cancelled:r,error:o,noEnvs:a}=await(0,i._promptAndSetEnvironmentId)(n,e);if((0,s.debug)("login",{selectedEnvId:t,cancelled:r,error:o,noEnvs:a}),o)return{content:[{type:"text",text:o}]};if(a)return{content:[{type:"text",text:"当前账户下暂无可用的云开发环境,请先在腾讯云控制台创建环境 https://tcb.cloud.tencent.com/dev?from=AIToolkit"}]};if(r)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:r.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,o.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:r.z.enum(["list","info","domains"]).describe("查询类型:list=环境列表,info=当前环境信息,domains=安全域名列表")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"env"}},async({action:e})=>{try{let r;switch(e){case"list":try{const e=await(0,o.getCloudBaseManager)({cloudBaseOptions:n,requireEnvId:!1});r=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();r=await a.env.getEnvInfo();break;case"domains":const i=await t();r=await i.env.getEnvAuthDomains();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?.("envDomainManagement",{title:"环境域名管理",description:"管理云开发环境的安全域名,支持添加和删除操作。(原工具名:createEnvDomain/deleteEnvDomain,为兼容旧AI规则可继续使用这些名称)",inputSchema:{action:r.z.enum(["create","delete"]).describe("操作类型:create=添加域名,delete=删除域名"),domains:r.z.array(r.z.string()).describe("安全域名数组")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"env"}},async({action:e,domains:n})=>{try{const r=await t();let o;switch(e){case"create":o=await r.env.createEnvDomain(n);break;case"delete":o=await r.env.deleteEnvDomain(n);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)}`}]}}})};const r=t(971),o=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,o.getCloudBaseManager)({cloudBaseOptions:n});e.registerTool?.("createCollection",{title:"创建数据库集合",description:"管理云开发数据库集合:默认创建。可通过 action 指定 update。",inputSchema:{action:r.z.enum(["create","update"]).optional().describe("操作类型:create=创建(默认),update=更新集合配置"),collectionName:r.z.string().describe("云开发数据库集合名称"),options:r.z.object({CreateIndexes:r.z.array(r.z.object({IndexName:r.z.string(),MgoKeySchema:r.z.object({MgoIsUnique:r.z.boolean(),MgoIndexKeys:r.z.array(r.z.object({Name:r.z.string(),Direction:r.z.string()}))})})).optional(),DropIndexes:r.z.array(r.z.object({IndexName:r.z.string()})).optional()}).optional().describe("更新选项(action=update 时使用)")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"database"}},async({action:e="create",collectionName:n,options:r})=>{try{const o=await t();if("create"===e){const t=await o.database.createCollection(n);return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:t.RequestId,action:e,message:"云开发数据库集合创建成功"},null,2)}]}}if("update"===e){if(!r)throw new Error("更新集合时必须提供 options");const t=await o.database.updateCollection(n,r);return{content:[{type:"text",text:JSON.stringify({success:!0,requestId:t.RequestId,action:e,message:"云开发数据库集合更新成功"},null,2)}]}}throw new Error(`不支持的操作类型: ${e}`)}catch(n){return{content:[{type:"text",text:JSON.stringify({success:!1,action:e,error:n.message,message:"集合创建/更新操作失败"},null,2)}]}}}),e.registerTool?.("collectionQuery",{title:"集合查询",description:"数据库集合的查询操作,支持检查存在性、查看详情、列表查询;并支持索引列表与检查。(兼容旧名称)",inputSchema:{action:r.z.enum(["check","describe","list","index_list","index_check"]).describe("操作类型:check=检查是否存在,describe=查看详情,list=列表查询,index_list=索引列表,index_check=检查索引是否存在"),collectionName:r.z.string().optional().describe("集合名称(check、describe、index_list、index_check 操作时必填)"),indexName:r.z.string().optional().describe("索引名称(index_check 操作时必填)"),limit:r.z.number().optional().describe("返回数量限制(list操作时可选)"),offset:r.z.number().optional().describe("偏移量(list操作时可选)")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"database"}},async({action:e,collectionName:n,indexName:r,limit:o,offset:a})=>{try{const i=await t();let s;switch(e){case"check":if(!n)throw new Error("检查集合时必须提供 collectionName");return s=await i.database.checkCollectionExists(n),{content:[{type:"text",text:JSON.stringify({success:!0,exists:s.Exists,requestId:s.RequestId,message:s.Exists?"云开发数据库集合已存在":"云开发数据库集合不存在"},null,2)}]};case"describe":if(!n)throw new Error("查看集合详情时必须提供 collectionName");return s=await i.database.describeCollection(n),{content:[{type:"text",text:JSON.stringify({success:!0,requestId:s.RequestId,indexNum:s.IndexNum,indexes:s.Indexes,message:"获取云开发数据库集合信息成功"},null,2)}]};case"list":return s=await i.database.listCollections({MgoOffset:a,MgoLimit:o}),{content:[{type:"text",text:JSON.stringify({success:!0,requestId:s.RequestId,collections:s.Collections,pager:s.Pager,message:"获取云开发数据库集合列表成功"},null,2)}]};case"index_list":if(!n)throw new Error("获取索引列表时必须提供 collectionName");return s=await i.database.describeCollection(n),{content:[{type:"text",text:JSON.stringify({success:!0,requestId:s.RequestId,indexNum:s.IndexNum,indexes:s.Indexes,message:"获取索引列表成功"},null,2)}]};case"index_check":if(!n||!r)throw new Error("检查索引时必须提供 collectionName 和 indexName");return s=await i.database.checkIndexExists(n,r),{content:[{type:"text",text:JSON.stringify({success:!0,exists:s.Exists,requestId:s.RequestId,message:s.Exists?"索引已存在":"索引不存在"},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:r.z.string().describe("云开发数据库集合名称"),options:r.z.object({CreateIndexes:r.z.array(r.z.object({IndexName:r.z.string(),MgoKeySchema:r.z.object({MgoIsUnique:r.z.boolean(),MgoIndexKeys:r.z.array(r.z.object({Name:r.z.string(),Direction:r.z.string()}))})})).optional(),DropIndexes:r.z.array(r.z.object({IndexName:r.z.string()})).optional()}).describe("更新选项,支持创建和删除索引")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"database"}},async({collectionName:e,options:n})=>{try{const r=await t(),o=await r.database.updateCollection(e,n);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?.("checkIndexExists",{title:"检查索引是否存在",description:"检查索引是否存在",inputSchema:{collectionName:r.z.string().describe("云开发数据库集合名称"),indexName:r.z.string().describe("索引名称")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"database"}},async({collectionName:e,indexName:n})=>{try{const r=await t(),o=await r.database.checkIndexExists(e,n);return{content:[{type:"text",text:JSON.stringify({success:!0,exists:o.Exists,requestId:o.RequestId,message:o.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:r.z.string().describe("云开发数据库集合名称"),documents:r.z.array(r.z.object({}).passthrough()).describe("要插入的文档对象数组,每个文档都是对象")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"database"}},async({collectionName:e,documents:n})=>{try{const r=await t(),o=await c(t),a=n.map(e=>JSON.stringify(e)),i=await r.commonService("flexdb").call({Action:"PutItem",Param:{TableName:e,MgoDocs:a,Tag:o}});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:r.z.string().describe("云开发数据库集合名称"),query:r.z.union([r.z.object({}).passthrough(),r.z.string()]).optional().describe("查询条件(对象或字符串,推荐对象)"),projection:r.z.union([r.z.object({}).passthrough(),r.z.string()]).optional().describe("返回字段投影(对象或字符串,推荐对象)"),sort:r.z.union([r.z.object({}).passthrough(),r.z.string()]).optional().describe("排序条件(对象或字符串,推荐对象)"),limit:r.z.number().optional().describe("返回数量限制"),offset:r.z.number().optional().describe("跳过的记录数")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"database"}},async({collectionName:e,query:n,projection:r,sort:o,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(r),MgoSort:d(o),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:r.z.string().describe("云开发数据库集合名称"),query:r.z.union([r.z.object({}).passthrough(),r.z.string()]).describe("查询条件(对象或字符串,推荐对象)"),update:r.z.union([r.z.object({}).passthrough(),r.z.string()]).describe("更新内容(对象或字符串,推荐对象)"),isMulti:r.z.boolean().optional().describe("是否更新多条记录"),upsert:r.z.boolean().optional().describe("是否在不存在时插入")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"database"}},async({collectionName:e,query:n,update:r,isMulti:o,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(r),MgoIsMulti:o,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:r.z.string().describe("云开发数据库集合名称"),query:r.z.union([r.z.object({}).passthrough(),r.z.string()]).describe("查询条件(对象或字符串,推荐对象)"),isMulti:r.z.boolean().optional().describe("是否删除多条记录")},annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!0,openWorldHint:!0,category:"database"}},async({collectionName:e,query:n,isMulti:r})=>{try{const o=await t(),a=await c(t),i=e=>"object"==typeof e&&null!==e?JSON.stringify(e):e,s=await o.commonService("flexdb").call({Action:"DeleteItem",Param:{TableName:e,MgoQuery:i(n),MgoIsMulti:r,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:r.z.enum(["get","list","docs"]).describe("操作类型:get=查询单个模型(含Schema字段列表、格式、关联关系),list=获取模型列表(不含Schema),docs=生成SDK使用文档"),name:r.z.string().optional().describe("模型名称(get操作时必填)"),names:r.z.array(r.z.string()).optional().describe("模型名称数组(list操作时可选,用于过滤)")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"database"}},async({action:e,name:r,names:a})=>{try{const s=await t();let c,d=await(0,o.getEnvId)(n);switch(e){case"get":if(!r)throw new Error("获取数据模型需要提供模型名称");try{c=await s.commonService("lowcode").call({Action:"DescribeBasicDataSource",Param:{EnvId:d,Name:r}});let e=null;if(c.Data.Schema)try{const n=JSON.parse(c.Data.Schema),t=n.properties||{},r=Object.keys(t).filter(e=>!t[e]["x-system"]).map(e=>l(t[e],e,n)),o=r.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:r,relations:o,totalFields:Object.keys(t).length,userFieldsCount:r.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),o={[r]: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&&(o[e]=JSON.parse(n.Data.Schema))}catch(n){console.warn(`获取关联模型 ${e} 的 schema 失败:`,n)}}n=i(o)}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:`数据模型 ${r} 不存在`},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(!r)throw new Error("生成SDK文档需要提供模型名称");try{if(c=await s.commonService("lowcode").call({Action:"DescribeBasicDataSource",Param:{EnvId:d,Name:r}}),!c.Data)throw new Error(`数据模型 ${r} 不存在`);let e=[],n=[];if(c.Data.Schema)try{const t=JSON.parse(c.Data.Schema),r=t.properties||{};e=Object.keys(r).filter(e=>!r[e]["x-system"]).map(e=>l(r[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,r){const o=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=o.map(e=>` ${e.name}: ${s(e)}, // ${e.description||e.title||e.name}`).join("\n"),l=o.slice(0,2).map(e=>` ${e.name}: ${s(e)}, // ${e.description||e.title||e.name}`).join("\n"),d=a[0]||o[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${r.length>0?`\n## 关联关系\n\n${r.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 ${o[0]?`${o[0].name}: "asc", // 按${o[0].description||o[0].title||o[0].name}升序`:'_id: "desc", // 按ID降序'}\n },\n ],\n },\n});\n\`\`\`\n\n${r.length>0?`\n## 关联查询\n\n${r.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${r.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:r,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:`数据模型 ${r} 不存在`},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:r.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:r.z.enum(["create","update"]).optional().default("create").describe("操作类型:create=创建新模型"),publish:r.z.boolean().optional().default(!1).describe("是否立即发布模型"),dbInstanceType:r.z.string().optional().default("MYSQL").describe("数据库实例类型")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"database"}},async({mermaidDiagram:e,action:r="create",publish:i=!1,dbInstanceType:c="MYSQL"})=>{try{const i=await t();let l=await(0,o.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 v=Object.keys(d),y=h?.Data?.SuccessResourceIdList||[],x=v.filter(e=>!y.includes(e));return{content:[{type:"text",text:JSON.stringify({success:"success"===b,requestId:p.RequestId,taskId:g,models:v,successModels:y,failedModels:x,status:b,action:r,message:"success"===b?`数据模型${"create"===r?"创建":"更新"}成功,共处理${v.length}个模型`:"init"===b?`任务超时,任务ID: ${g},请稍后手动查询状态`:`数据模型${"create"===r?"创建":"更新"}失败`,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 r=t(971),o=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,r=0,o=5){if(r>o)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:r};if("array"===e.type&&e.items)try{a.items=l(e.items,`${n}_item`,t,r+1,o)}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,r+1,o))}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=o,n.enableCloudMode=function(){process.env.CLOUDBASE_MCP_CLOUD_MODE="true",(0,r.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(!o())return!0;const n=!["login","logout","uploadFile","uploadFiles","updateFunctionCode","createFunction","uploadMiniprogramCode","downloadTemplate","downloadRemoteFile","setupEnvironmentId","clearUserEnvId","interactiveDialog"].includes(e);return n||(0,r.debug)(`Cloud mode: skipping registration of incompatible tool: ${e}`),n};const r=t(39);function o(){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,r.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:r.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,o.getCloudBaseManager)({cloudBaseOptions:n}),r=await(0,o.getEnvId)(n),a=await t.commonService().call({Action:"ActivateInviteCode",Param:{InviteCode:e,EnvId:r}});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 r=t(971),o=t(431)},782:e=>{e.exports=p},793:e=>{e.exports=g},814:e=>{e.exports=m},823:e=>{e.exports=f},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:r.z.string().describe("本地文件路径,建议传入绝对路径,例如 /tmp/files/data.txt"),cloudPath:r.z.string().describe("云端文件路径,例如 files/data.txt")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"storage"}},async({localPath:e,cloudPath:t})=>{const r=await(0,o.getCloudBaseManager)({cloudBaseOptions:n});await r.storage.uploadFile({localPath:e,cloudPath:t,onProgress:e=>{console.log("Upload progress:",e)}});const a=await r.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 r=t(971),o=t(431)},862:(e,n,t)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.registerSecurityRuleTools=function(e){const n=e.cloudBaseOptions,t=()=>(0,o.getCloudBaseManager)({cloudBaseOptions:n});e.registerTool?.("readSecurityRule",{title:"读取安全规则",description:"读取指定资源(数据库集合、云函数、存储桶)的安全规则和权限类别。\n\n参数说明:\n- resourceType: 资源类型(database/function/storage)\n- resourceId: 资源唯一标识(集合名/函数名/桶名)",inputSchema:{resourceType:r.z.enum(["database","function","storage"]).describe("资源类型:database=数据库集合,function=云函数,storage=存储桶"),resourceId:r.z.string().describe("资源唯一标识。数据库为集合名,云函数为函数名,存储为桶名。")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"security-rule"}},async({resourceType:e,resourceId:r})=>{const a=await(0,o.getEnvId)(n);try{const n=await t();let o;if("database"===e)o=await n.commonService().call({Action:"DescribeSafeRule",Param:{CollectionName:r,EnvId:a}});else if("function"===e)o=await n.commonService().call({Action:"DescribeSecurityRule",Param:{ResourceType:"FUNCTION",EnvId:a}});else{if("storage"!==e)throw new Error(`不支持的资源类型: ${e}`);o=await n.commonService().call({Action:"DescribeStorageSafeRule",Param:{Bucket:r,EnvId:a}})}return{content:[{type:"text",text:JSON.stringify({success:!0,aclTag:o.AclTag,rule:o.Rule??null,raw:o,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:r.z.enum(["database","function","storage"]).describe("资源类型:database=数据库集合,function=云函数,storage=存储桶"),resourceId:r.z.string().describe("资源唯一标识。数据库为集合名,云函数为函数名,存储为桶名。"),aclTag:r.z.enum(["READONLY","PRIVATE","ADMINWRITE","ADMINONLY","CUSTOM"]).describe("权限类别"),rule:r.z.string().optional().describe("自定义安全规则内容,仅当 aclTag 为 CUSTOM 时必填")},annotations:{readOnlyHint:!1,openWorldHint:!0,category:"security-rule"}},async({resourceType:e,resourceId:r,aclTag:a,rule:i})=>{try{const s=await t(),c=await(0,o.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:r,EnvId:c,AclTag:a,Rule:i}})}else l=await s.commonService().call({Action:"ModifyDatabaseACL",Param:{CollectionName:r,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:r,EnvId:c,AclTag:a,Rule:i}})}else l=await s.commonService().call({Action:"ModifyStorageSafeRule",Param:{Bucket:r,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 r=t(971),o=t(431)},871:e=>{e.exports=b},872:e=>{e.exports=h},880:function(e,n,t){var r=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 o=r(t(116)),a=r(t(823)),i=r(t(871)),s=r(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=o.default.type(),n=o.default.release(),t=process.version,r=o.default.arch(),a=process.env.npm_package_version||"1.8.39";return{userAgent:`${e} ${n} ${r} ${t} CloudBase-MCP/${a}`,deviceId:this.deviceId,osType:e,osRelease:n,nodeVersion:t,arch:r,mcpVersion:a}}getDeviceId(){try{const e=[o.default.hostname(),o.default.cpus().map(e=>e.model).join(","),Object.values(o.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,r)=>{const o=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(o),"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():r(new Error(`HTTP ${e.statusCode}: ${n}`))})});d.on("error",r),d.on("timeout",()=>{d.destroy(),r(new Error("Request timeout"))}),d.write(o),d.end()})}async report(e,n={}){if(this.enabled)try{const t=Date.now(),r={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",r),(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:r,osRelease:o,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:r,osRelease:o,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:r,osRelease:o,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:r,osRelease:o,arch:a,mcpVersion:i};e.ide&&(d.ide=e.ide),n.telemetryReporter.report("toolkit_lifecycle",d)}},887:e=>{e.exports=v},932:e=>{e.exports=y},936:function(e,n,t){var r=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,r=()=>(0,a.getCloudBaseManager)({cloudBaseOptions:t});e.registerTool?.("getFunctionList",{title:"查询云函数列表或详情",description:"获取云函数列表或单个函数详情,通过 action 参数区分操作类型",inputSchema:{action:o.z.enum(["list","detail"]).optional().describe("操作类型:list=获取函数列表(默认),detail=获取函数详情"),limit:o.z.number().optional().describe("范围(list 操作时使用)"),offset:o.z.number().optional().describe("偏移(list 操作时使用)"),name:o.z.string().optional().describe("函数名称(detail 操作时必需)"),codeSecret:o.z.string().optional().describe("代码保护密钥(detail 操作时使用)")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"functions"}},async({action:e="list",limit:n,offset:t,name:o,codeSecret:a})=>{const i=await r();if("list"===e){const e=await i.functions.getFunctionList(n,t);return{content:[{type:"text",text:JSON.stringify(e,null,2)}]}}if("detail"===e){if(!o)throw new Error("获取函数详情时,name 参数是必需的");const e=await i.functions.getFunctionDetail(o,a);return{content:[{type:"text",text:JSON.stringify(e,null,2)}]}}throw new Error(`不支持的操作类型: ${e}`)}),e.registerTool("createFunction",{title:"创建云函数",description:"创建云函数",inputSchema:{func:o.z.object({name:o.z.string().describe("函数名称"),timeout:o.z.number().optional().describe("函数超时时间"),envVariables:o.z.record(o.z.string()).optional().describe("环境变量"),vpc:o.z.object({vpcId:o.z.string(),subnetId:o.z.string()}).optional().describe("私有网络配置"),runtime:o.z.string().optional().describe("运行时环境,建议指定为 'Nodejs18.15',其他可选值:"+n.SUPPORTED_NODEJS_RUNTIMES.join(",")),triggers:o.z.array(o.z.object({name:o.z.string().describe("Trigger name"),type:o.z.enum(n.SUPPORTED_TRIGGER_TYPES).describe("Trigger type, currently only supports 'timer'"),config:o.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:o.z.string().optional().describe("函数入口"),ignore:o.z.union([o.z.string(),o.z.array(o.z.string())]).optional().describe("忽略文件"),isWaitInstall:o.z.boolean().optional().describe("是否等待依赖安装"),layers:o.z.array(o.z.object({name:o.z.string(),version:o.z.number()})).optional().describe("Layer配置")}).describe("函数配置"),functionRootPath:o.z.string().optional().describe("函数根目录(云函数目录的父目录),这里需要传操作系统上文件的绝对路径,注意:不要包含函数名本身,例如函数名为 'hello',应传入 '/path/to/cloudfunctions',而不是 '/path/to/cloudfunctions/hello'"),force:o.z.boolean().describe("是否覆盖")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"functions"}},async({func:e,functionRootPath:t,force:o})=>{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 r(),c=await i.functions.createFunction({func:e,functionRootPath:a,force:o});return{content:[{type:"text",text:JSON.stringify(c,null,2)}]}}),e.registerTool("updateFunctionCode",{title:"更新云函数代码",description:"更新函数代码",inputSchema:{name:o.z.string().describe("函数名称"),functionRootPath:o.z.string().describe("函数根目录(云函数目录的父目录),这里需要传操作系统上文件的绝对路径")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"functions"}},async({name:e,functionRootPath:t,zipFile:o,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)};o&&(c.zipFile=o);const l=await r(),d=await l.functions.updateFunctionCode(c);return{content:[{type:"text",text:JSON.stringify(d,null,2)}]}}),e.registerTool?.("updateFunctionConfig",{title:"更新云函数配置",description:"更新云函数配置",inputSchema:{funcParam:o.z.object({name:o.z.string().describe("函数名称"),timeout:o.z.number().optional().describe("超时时间"),envVariables:o.z.record(o.z.string()).optional().describe("环境变量"),vpc:o.z.object({vpcId:o.z.string(),subnetId:o.z.string()}).optional().describe("VPC配置")}).describe("函数配置")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"functions"}},async({funcParam:e})=>{const n=await r(),t=await n.functions.updateFunctionConfig(e);return{content:[{type:"text",text:JSON.stringify(t,null,2)}]}}),e.registerTool?.("invokeFunction",{title:"调用云函数",description:"调用云函数",inputSchema:{name:o.z.string().describe("函数名称"),params:o.z.record(o.z.any()).optional().describe("调用参数")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"functions"}},async({name:e,params:n})=>{const t=await r(),o=await t.functions.invokeFunction(e,n);return{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}),e.registerTool?.("getFunctionLogs",{title:"获取云函数日志(新版)",description:"获取云函数日志基础信息(LogList),如需日志详情请用 RequestId 调用 getFunctionLogDetail 工具。此接口基于 manger-node 4.4.0+ 的 getFunctionLogsV2 实现,不返回具体日志内容。参数 offset+limit 不得大于 10000,startTime/endTime 间隔不得超过一天。",inputSchema:{name:o.z.string().describe("函数名称"),offset:o.z.number().optional().describe("数据的偏移量,Offset+Limit 不能大于 10000"),limit:o.z.number().optional().describe("返回数据的长度,Offset+Limit 不能大于 10000"),startTime:o.z.string().optional().describe("查询的具体日期,例如:2017-05-16 20:00:00,只能与 EndTime 相差一天之内"),endTime:o.z.string().optional().describe("查询的具体日期,例如:2017-05-16 20:59:59,只能与 StartTime 相差一天之内"),requestId:o.z.string().optional().describe("执行该函数对应的 requestId"),qualifier:o.z.string().optional().describe("函数版本,默认为 $LATEST")},annotations:{readOnlyHint:!0,openWorldHint:!0,category:"functions"}},async({name:e,offset:n,limit:t,startTime:o,endTime:a,requestId:i,qualifier:s})=>{if((n||0)+(t||0)>1e4)throw new Error("offset+limit 不能大于 10000");if(o&&a){const e=new Date(o).getTime();if(new Date(a).getTime()-e>864e5)throw new Error("startTime 和 endTime 间隔不能超过一天")}const c=await r(),l=await c.functions.getFunctionLogsV2({name:e,offset:n,limit:t,startTime:o,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:o.z.string().optional().describe("查询的具体日期,例如:2017-05-16 20:00:00,只能与 EndTime 相差一天之内"),endTime:o.z.string().optional().describe("查询的具体日期,例如:2017-05-16 20:59:59,只能与 StartTime 相差一天之内"),requestId:o.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 o=await r(),a=await o.functions.getFunctionLogDetail({startTime:e,endTime:n,logRequestId:t});return{content:[{type:"text",text:JSON.stringify(a,null,2)}]}}),e.registerTool?.("manageFunctionTriggers",{title:"管理云函数触发器",description:"创建或删除云函数触发器,通过 action 参数区分操作类型",inputSchema:{action:o.z.enum(["create","delete"]).describe("操作类型:create=创建触发器,delete=删除触发器"),name:o.z.string().describe("函数名"),triggers:o.z.array(o.z.object({name:o.z.string().describe("Trigger name"),type:o.z.enum(n.SUPPORTED_TRIGGER_TYPES).describe("Trigger type, currently only supports 'timer'"),config:o.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("触发器配置数组(创建时必需)"),triggerName:o.z.string().optional().describe("触发器名称(删除时必需)")},annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0,category:"functions"}},async({action:e,name:n,triggers:t,triggerName:o})=>{const a=await r();if("create"===e){if(!t||0===t.length)throw new Error("创建触发器时,triggers 参数是必需的");const e=await a.functions.createFunctionTriggers(n,t);return{content:[{type:"text",text:JSON.stringify(e,null,2)}]}}if("delete"===e){if(!o)throw new Error("删除触发器时,triggerName 参数是必需的");const e=await a.functions.deleteFunctionTrigger(n,o);return{content:[{type:"text",text:JSON.stringify(e,null,2)}]}}throw new Error(`不支持的操作类型: ${e}`)})};const o=t(971),a=t(431),i=r(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=x}},E={};function C(e){var n=E[e];if(void 0!==n)return n.exports;var t=E[e]={exports:{}};return S[e].call(t.exports,t,t.exports,C),t.exports}I=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,C.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);C.r(t);var r={};w=w||[null,I({}),I([]),I(I)];for(var o=2&n&&e;("object"==typeof o||"function"==typeof o)&&!~w.indexOf(o);o=I(o))Object.getOwnPropertyNames(o).forEach(n=>r[n]=()=>e[n]);return r.default=()=>e,C.d(t,r),t},C.d=(e,n)=>{for(var t in n)C.o(n,t)&&!C.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},C.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),C.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(C.t.bind(C,341,23));return e(void 0)};var n=C(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=C(291);Object.defineProperty(e,"BS",{enumerable:!0,get:function(){return t.getLoginState}}),Object.defineProperty(e,"ri",{enumerable:!0,get:function(){return t.logout}});var r=C(684);Object.defineProperty(e,"bT",{enumerable:!0,get:function(){return r.isCloudMode}}),Object.defineProperty(e,"S",{enumerable:!0,get:function(){return r.enableCloudMode}}),Object.defineProperty(e,"$n",{enumerable:!0,get:function(){return r.getCloudModeStatus}}),Object.defineProperty(e,"T$",{enumerable:!0,get:function(){return r.shouldRegisterTool}});var o=C(431);Object.defineProperty(e,"_k",{enumerable:!0,get:function(){return o.getCloudBaseManager}}),Object.defineProperty(e,"fW",{enumerable:!0,get:function(){return o.getEnvId}}),Object.defineProperty(e,"bM",{enumerable:!0,get:function(){return o.resetCloudBaseManagerCache}}),Object.defineProperty(e,"q8",{enumerable:!0,get:function(){return o.createCloudBaseManagerWithOptions}})})();const O=T.S7,k=T.BJ,N=T.q8,D=T.Gh,z=T.S,$=T.z3,_=T._k,P=T.$n,j=T.dD,M=T.fW,B=T.SJ,R=T.BS,A=T.pq,L=T.bT,U=T.ri,H=T.R4,F=T.ps,q=T.bM,J=T.T$,W=T.v7,G=T.R8;export{O as StdioServerTransport,k as __esModule,N as createCloudBaseManagerWithOptions,D as createCloudBaseMcpServer,z as enableCloudMode,$ as error,_ as getCloudBaseManager,P as getCloudModeStatus,j as getDefaultServer,M as getEnvId,B as getInteractiveServerAsync,R as getLoginState,A as info,L as isCloudMode,U as logout,H as reportToolCall,F as reportToolkitLifecycle,q as resetCloudBaseManagerCache,J as shouldRegisterTool,W as telemetryReporter,G as warn};