@cloudbase/cloudbase-mcp 2.0.6 → 2.2.0-alpha.0

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.
Files changed (4) hide show
  1. package/dist/cli.cjs +837 -189
  2. package/dist/index.cjs +837 -189
  3. package/dist/index.js +426 -153
  4. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -101,6 +101,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
101
101
  Object.defineProperty(exports, "__esModule", ({ value: true }));
102
102
  exports.CloudRunService = void 0;
103
103
  exports.codeToZip = codeToZip;
104
+ exports.parseObjectToDiffConfigItem = parseObjectToDiffConfigItem;
104
105
  const archiver_1 = __importDefault(__webpack_require__(99133));
105
106
  const fs_extra_1 = __webpack_require__(21605);
106
107
  const path_1 = __importDefault(__webpack_require__(39902));
@@ -269,7 +270,7 @@ class CloudRunService {
269
270
  /**
270
271
  * 上传部署包
271
272
  */
272
- const zipFile = await codeToZip(targetPath, { installDependency: true });
273
+ const zipFile = await codeToZip(targetPath, { installDependency: (serverConfig === null || serverConfig === void 0 ? void 0 : serverConfig.InstallDependency) !== undefined ? serverConfig.InstallDependency : true });
273
274
  await (0, utils_1.upload)({
274
275
  url: uploadUrl,
275
276
  file: zipFile,
@@ -285,8 +286,14 @@ class CloudRunService {
285
286
  if (await this._checkFunctionExist(serverName)) {
286
287
  // 更新
287
288
  const serverDetail = await this.detail({ serverName });
288
- const _serverConfig = Object.assign(Object.assign(Object.assign({}, ((serverDetail === null || serverDetail === void 0 ? void 0 : serverDetail.ServerConfig) || {})), serverConfig), ((serverDetail === null || serverDetail === void 0 ? void 0 : serverDetail.ServerConfig.Tag) === 'function:' ? { Port: 3000 } : {}) // 函数型不能指定端口,需要固定为3000
289
+ const _serverConfig = Object.assign(Object.assign(Object.assign({}, serverConfig), { OpenAccessTypes: ['OA', 'PUBLIC', 'MINIAPP'] }), ((serverDetail === null || serverDetail === void 0 ? void 0 : serverDetail.ServerConfig.Tag) === 'function:' ? { Port: 3000 } : {}) // 函数型不能指定端口,需要固定为3000
289
290
  );
291
+ if ((serverDetail === null || serverDetail === void 0 ? void 0 : serverDetail.ServerConfig.Tag) === 'function:') {
292
+ deployInfo.BuildPacks = {
293
+ LanguageVersion: '20.18',
294
+ RepoLanguage: 'Node.js'
295
+ };
296
+ }
290
297
  deployInfo.ReleaseType = 'FULL';
291
298
  return this._upsertFunction(false, {
292
299
  name: serverName,
@@ -314,7 +321,13 @@ class CloudRunService {
314
321
  RepoLanguage: 'Node.js'
315
322
  };
316
323
  }
317
- const _serverConfig = Object.assign(Object.assign(Object.assign({ OpenAccessTypes: ['OA', 'PUBLIC'], Cpu: 0, Mem: 0, MinNum: 0, MaxNum: 0, PolicyDetails: [], EnvParams: JSON.stringify({}), InitialDelaySeconds: 0, CustomLogs: '', HasDockerfile: true, CreateTime: '', EnvId: envConfig.EnvId, ServerName: serverName, Port: type === 'container' ? 80 : 3000, Dockerfile: 'Dockerfile', BuildDir: '' }, serverConfig), (type === 'function' ? { Port: 3000 } : {})), { Tag: type === 'container' ? '' : 'function:' });
324
+ const _serverConfig = Object.assign(Object.assign(Object.assign({ OpenAccessTypes: ['OA', 'PUBLIC', 'MINIAPP'],
325
+ // Cpu: 0,
326
+ // Mem: 0,
327
+ MinNum: 0,
328
+ // MaxNum: 0,
329
+ // PolicyDetails: [],
330
+ EnvParams: JSON.stringify({}), InitialDelaySeconds: 0, CustomLogs: '', HasDockerfile: true, CreateTime: '', EnvId: envConfig.EnvId, ServerName: serverName, Port: type === 'container' ? 80 : 3000, Dockerfile: 'Dockerfile', BuildDir: '' }, serverConfig), (type === 'function' ? { Port: 3000 } : {})), { Tag: type === 'container' ? '' : 'function:' });
318
331
  return this._upsertFunction(true, {
319
332
  name: serverName,
320
333
  deployInfo,
@@ -348,11 +361,12 @@ class CloudRunService {
348
361
  _upsertFunction(isNew, data) {
349
362
  const { name, deployInfo, serverConfig } = data;
350
363
  const envConfig = this.environment.lazyEnvironmentConfig;
364
+ const Items = parseObjectToDiffConfigItem(serverConfig);
351
365
  return this.tcbrService.request(isNew ? 'CreateCloudRunServer' : 'UpdateCloudRunServer', {
352
366
  EnvId: envConfig.EnvId,
353
367
  ServerName: name,
354
368
  DeployInfo: deployInfo,
355
- ServerConfig: serverConfig
369
+ Items,
356
370
  });
357
371
  }
358
372
  }
@@ -425,6 +439,63 @@ async function codeToZip(cwd, options) {
425
439
  await archive.finalize();
426
440
  return bufferPromise;
427
441
  }
442
+ /**
443
+ * 提交参数变化映射
444
+ */
445
+ const SUBMIT_DIFF_MAP = {
446
+ Cpu: 'CpuSpecs',
447
+ Mem: 'MemSpecs',
448
+ OpenAccessTypes: 'AccessTypes',
449
+ EnvParams: 'EnvParam',
450
+ CustomLogs: 'LogPath'
451
+ };
452
+ /**
453
+ * 将 object 参数转为 [{key:"Port", IntValue:80}] 的格式,并且剔除空字符串
454
+ */
455
+ function parseObjectToDiffConfigItem(data) {
456
+ const kvs = Object.entries(data);
457
+ const Items = [];
458
+ kvs.forEach(([k, v]) => {
459
+ const Key = SUBMIT_DIFF_MAP[k] || k;
460
+ if ([
461
+ 'CustomLogs',
462
+ 'EnvParams',
463
+ 'CreateTime',
464
+ 'Dockerfile',
465
+ 'BuildDir',
466
+ 'LogType',
467
+ 'LogSetId',
468
+ 'LogTopicId',
469
+ 'LogParseType',
470
+ 'Tag',
471
+ 'InternalAccess',
472
+ 'InternalDomain',
473
+ 'OperationMode',
474
+ 'SessionAffinity'
475
+ ].includes(k)) {
476
+ !!v && Items.push({ Key, Value: v });
477
+ }
478
+ else if (['MinNum', 'MaxNum', 'InitialDelaySeconds', 'Port'].includes(k)) {
479
+ Items.push({ Key, IntValue: v });
480
+ }
481
+ else if (['HasDockerfile'].includes(k)) {
482
+ Items.push({ Key, BoolValue: v });
483
+ }
484
+ else if (['Cpu', 'Mem'].includes(k)) {
485
+ Items.push({ Key, FloatValue: v });
486
+ }
487
+ else if (['OpenAccessTypes', 'EntryPoint', 'Cmd'].includes(k)) {
488
+ Items.push({ Key, ArrayValue: v });
489
+ }
490
+ else if (['PolicyDetails'].includes(k)) {
491
+ Items.push({ Key, PolicyDetails: v });
492
+ }
493
+ else if (['TimerScale'].includes(k)) {
494
+ Items.push({ Key, TimerScale: v });
495
+ }
496
+ });
497
+ return Items;
498
+ }
428
499
 
429
500
 
430
501
  /***/ }),
@@ -23553,7 +23624,7 @@ async function getCloudBaseManager(options = {}) {
23553
23624
  secretKey,
23554
23625
  envId: finalEnvId || loginEnvId,
23555
23626
  token,
23556
- proxy: process.env.http_proxy
23627
+ proxy: process.env.http_proxy,
23557
23628
  });
23558
23629
  return manager;
23559
23630
  }
@@ -23570,13 +23641,8 @@ async function getCloudBaseManager(options = {}) {
23570
23641
  function createCloudBaseManagerWithOptions(cloudBaseOptions) {
23571
23642
  (0, logger_js_1.debug)('使用传入的 CloudBase 配置创建 manager:', cloudBaseOptions);
23572
23643
  const manager = new manager_node_1.default({
23573
- secretId: cloudBaseOptions.secretId,
23574
- secretKey: cloudBaseOptions.secretKey,
23575
- envId: cloudBaseOptions.envId,
23576
- token: cloudBaseOptions.token,
23644
+ ...cloudBaseOptions,
23577
23645
  proxy: cloudBaseOptions.proxy || process.env.http_proxy,
23578
- region: cloudBaseOptions.region,
23579
- envType: cloudBaseOptions.envType
23580
23646
  });
23581
23647
  return manager;
23582
23648
  }
@@ -38330,7 +38396,7 @@ function registerSQLDatabaseTools(server) {
38330
38396
  // executeReadOnlySQL
38331
38397
  server.registerTool?.("executeReadOnlySQL", {
38332
38398
  title: "Execute read-only SQL query",
38333
- description: "Execute a read-only SQL query on the SQL database. Note: For per-user ACL, each table should contain a fixed `_openid` column that represents the user and is used for access control.",
38399
+ description: "Execute a read-only SQL query on the SQL database. Note: For per-user ACL, each table should contain a fixed `_openid` column defined as `_openid VARCHAR(64) DEFAULT '' NOT NULL` that represents the user and is used for access control.",
38334
38400
  inputSchema: {
38335
38401
  sql: zod_1.z.string().describe("SQL query statement (SELECT queries only)"),
38336
38402
  },
@@ -38389,7 +38455,7 @@ function registerSQLDatabaseTools(server) {
38389
38455
  // executeWriteSQL
38390
38456
  server.registerTool?.("executeWriteSQL", {
38391
38457
  title: "Execute write SQL statement",
38392
- description: "Execute a write SQL statement on the SQL database (INSERT, UPDATE, DELETE, etc.). Whenever you create a new table, you **must** contain a fixed `_opeid` column that represents the user and is used for access control.",
38458
+ description: "Execute a write SQL statement on the SQL database (INSERT, UPDATE, DELETE, etc.). Whenever you create a new table, you **must** include a fixed `_openid` column defined as `_openid VARCHAR(64) DEFAULT '' NOT NULL` that represents the user and is used for access control.",
38393
38459
  inputSchema: {
38394
38460
  sql: zod_1.z
38395
38461
  .string()
@@ -48549,7 +48615,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
48549
48615
  exports.cloudBaseRequest = cloudBaseRequest;
48550
48616
  const auth_1 = __webpack_require__(23506);
48551
48617
  const http_request_1 = __webpack_require__(72088);
48552
- const SUPPORT_REGIONS = ['ap-shanghai', 'ap-guangzhou'];
48618
+ const SUPPORT_REGIONS = ['ap-shanghai', 'ap-guangzhou', 'ap-singapore'];
48553
48619
  async function cloudBaseRequest(options) {
48554
48620
  // const url = 'https://tcb-admin.tencentcloudapi.com/admin'
48555
48621
  const { config, params = {}, method = 'POST', headers = {} } = options;
@@ -48563,11 +48629,11 @@ async function cloudBaseRequest(options) {
48563
48629
  let internalRegionEndpoint = '';
48564
48630
  if (finalRegion) {
48565
48631
  if (SUPPORT_REGIONS.includes(finalRegion)) {
48566
- internetRegionEndpoint = `${finalRegion}.tcb-api.tencentcloudapi.com`;
48567
- internalRegionEndpoint = `internal.${finalRegion}.tcb-api.tencentcloudapi.com`;
48632
+ internetRegionEndpoint = `${envId}.${finalRegion}.tcb-api.tencentcloudapi.com`;
48633
+ internalRegionEndpoint = `${envId}.internal.${finalRegion}.tcb-api.tencentcloudapi.com`;
48568
48634
  }
48569
48635
  else {
48570
- console.warn('当前仅支持上海,广州地域,其他地域默认解析到固定域名(上海地域)');
48636
+ console.warn('当前仅支持上海,广州,新加坡地域,其他地域默认解析到固定域名(上海地域)');
48571
48637
  internetRegionEndpoint = `tcb-api.tencentcloudapi.com`;
48572
48638
  internalRegionEndpoint = `internal.tcb-api.tencentcloudapi.com`;
48573
48639
  }
@@ -90160,19 +90226,20 @@ class EnvService {
90160
90226
  });
90161
90227
  }
90162
90228
  getCos() {
90229
+ const internalEndpoint = this.environment.cloudBaseContext.isInternalEndpoint();
90163
90230
  const { secretId, secretKey, token } = this.environment.getAuthConfig();
90164
90231
  const cosConfig = {
90165
90232
  SecretId: secretId,
90166
90233
  SecretKey: secretKey,
90167
90234
  SecurityToken: token,
90168
- Domain: constant_1.USE_INTERNAL_ENDPOINT ? "{Bucket}.cos-internal.{Region}.tencentcos.cn" /* COS_ENDPOINT.INTERNAL */ : "{Bucket}.cos.{Region}.tencentcos.cn" /* COS_ENDPOINT.PUBLIC */,
90235
+ Domain: internalEndpoint ? "{Bucket}.cos-internal.{Region}.tencentcos.cn" /* COS_ENDPOINT.INTERNAL */ : "{Bucket}.cos.{Region}.tencentcos.cn" /* COS_ENDPOINT.PUBLIC */,
90169
90236
  };
90170
90237
  if (constant_1.COS_SDK_PROTOCOL) {
90171
90238
  cosConfig.Protocol = (constant_1.COS_SDK_PROTOCOL.endsWith(':')
90172
90239
  ? constant_1.COS_SDK_PROTOCOL.toLowerCase()
90173
90240
  : constant_1.COS_SDK_PROTOCOL.toLowerCase() + ':');
90174
90241
  }
90175
- if (constant_1.USE_INTERNAL_ENDPOINT) {
90242
+ if (internalEndpoint) {
90176
90243
  cosConfig.Protocol = 'http:';
90177
90244
  }
90178
90245
  return new cos_nodejs_sdk_v5_1.default(cosConfig);
@@ -100306,12 +100373,14 @@ const rag_js_1 = __webpack_require__(64215);
100306
100373
  const setup_js_1 = __webpack_require__(76556);
100307
100374
  const storage_js_1 = __webpack_require__(94848);
100308
100375
  // import { registerMiniprogramTools } from "./tools/miniprogram.js";
100376
+ const types_js_1 = __webpack_require__(1294);
100309
100377
  const cloudrun_js_1 = __webpack_require__(35023);
100310
100378
  const dataModel_js_1 = __webpack_require__(34052);
100311
100379
  const gateway_js_1 = __webpack_require__(84319);
100312
100380
  const invite_code_js_1 = __webpack_require__(44760);
100313
100381
  const security_rule_js_1 = __webpack_require__(7862);
100314
100382
  const cloud_mode_js_1 = __webpack_require__(89684);
100383
+ const logger_js_1 = __webpack_require__(13039);
100315
100384
  const tool_wrapper_js_1 = __webpack_require__(71363);
100316
100385
  // 默认插件列表
100317
100386
  const DEFAULT_PLUGINS = [
@@ -100412,6 +100481,13 @@ async function createCloudBaseMcpServer(options) {
100412
100481
  ...(ide === "CodeBuddy" ? { logging: {} } : {}),
100413
100482
  },
100414
100483
  });
100484
+ // Only set logging handler if logging capability is declared
100485
+ if (ide === "CodeBuddy") {
100486
+ server.server.setRequestHandler(types_js_1.SetLevelRequestSchema, (request, extra) => {
100487
+ (0, logger_js_1.info)(`--- Logging level: ${request.params.level}`);
100488
+ return {};
100489
+ });
100490
+ }
100415
100491
  // Store cloudBaseOptions in server instance for tools to access
100416
100492
  if (cloudBaseOptions) {
100417
100493
  server.cloudBaseOptions = cloudBaseOptions;
@@ -100442,10 +100518,10 @@ function getDefaultServer() {
100442
100518
  }
100443
100519
  var stdio_js_1 = __webpack_require__(6166);
100444
100520
  Object.defineProperty(exports, "StdioServerTransport", ({ enumerable: true, get: function () { return stdio_js_1.StdioServerTransport; } }));
100445
- var logger_js_1 = __webpack_require__(13039);
100446
- Object.defineProperty(exports, "error", ({ enumerable: true, get: function () { return logger_js_1.error; } }));
100447
- Object.defineProperty(exports, "info", ({ enumerable: true, get: function () { return logger_js_1.info; } }));
100448
- Object.defineProperty(exports, "warn", ({ enumerable: true, get: function () { return logger_js_1.warn; } }));
100521
+ var logger_js_2 = __webpack_require__(13039);
100522
+ Object.defineProperty(exports, "error", ({ enumerable: true, get: function () { return logger_js_2.error; } }));
100523
+ Object.defineProperty(exports, "info", ({ enumerable: true, get: function () { return logger_js_2.info; } }));
100524
+ Object.defineProperty(exports, "warn", ({ enumerable: true, get: function () { return logger_js_2.warn; } }));
100449
100525
  var telemetry_js_1 = __webpack_require__(45880);
100450
100526
  Object.defineProperty(exports, "reportToolCall", ({ enumerable: true, get: function () { return telemetry_js_1.reportToolCall; } }));
100451
100527
  Object.defineProperty(exports, "reportToolkitLifecycle", ({ enumerable: true, get: function () { return telemetry_js_1.reportToolkitLifecycle; } }));
@@ -101741,6 +101817,53 @@ class AsyncReader extends reader_1.default {
101741
101817
  exports["default"] = AsyncReader;
101742
101818
 
101743
101819
 
101820
+ /***/ }),
101821
+
101822
+ /***/ 32720:
101823
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
101824
+
101825
+ "use strict";
101826
+
101827
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
101828
+ exports.sendDeployNotification = sendDeployNotification;
101829
+ const logger_js_1 = __webpack_require__(13039);
101830
+ /**
101831
+ * Send deployment notification to CodeBuddy IDE
101832
+ * @param server ExtendedMcpServer instance
101833
+ * @param notificationData Deployment notification data
101834
+ */
101835
+ async function sendDeployNotification(server, notificationData) {
101836
+ // Check if current IDE is CodeBuddy (prefer server.ide, fallback to environment variable)
101837
+ const currentIde = server.ide || process.env.INTEGRATION_IDE;
101838
+ if (currentIde !== 'CodeBuddy' || !server.server) {
101839
+ // Not CodeBuddy IDE, skip notification
101840
+ return;
101841
+ }
101842
+ try {
101843
+ // Send notification using sendLoggingMessage
101844
+ server.server.sendLoggingMessage({
101845
+ level: "notice",
101846
+ data: {
101847
+ type: "tcb",
101848
+ event: "deploy",
101849
+ data: {
101850
+ type: notificationData.deployType, // "hosting" or "cloudrun"
101851
+ url: notificationData.url,
101852
+ projectId: notificationData.projectId,
101853
+ projectName: notificationData.projectName,
101854
+ consoleUrl: notificationData.consoleUrl
101855
+ }
101856
+ }
101857
+ });
101858
+ (0, logger_js_1.info)(`CodeBuddy IDE: 已发送部署通知 - ${notificationData.deployType} - ${notificationData.url}`);
101859
+ }
101860
+ catch (err) {
101861
+ // Log error but don't throw - notification failure should not affect deployment flow
101862
+ (0, logger_js_1.error)(`Failed to send deployment notification: ${err instanceof Error ? err.message : err}`, err);
101863
+ }
101864
+ }
101865
+
101866
+
101744
101867
  /***/ }),
101745
101868
 
101746
101869
  /***/ 32923:
@@ -110054,6 +110177,7 @@ const fs_1 = __importDefault(__webpack_require__(29021));
110054
110177
  const path_1 = __importDefault(__webpack_require__(39902));
110055
110178
  const zod_1 = __webpack_require__(21614);
110056
110179
  const cloudbase_manager_js_1 = __webpack_require__(3431);
110180
+ const notification_js_1 = __webpack_require__(32720);
110057
110181
  // CloudRun service types
110058
110182
  exports.CLOUDRUN_SERVICE_TYPES = ['function', 'container'];
110059
110183
  // CloudRun access types
@@ -110558,6 +110682,58 @@ for await (let x of res.textStream) {
110558
110682
  catch (error) {
110559
110683
  // Ignore cloudbaserc.json creation errors
110560
110684
  }
110685
+ // Send deployment notification to CodeBuddy IDE
110686
+ try {
110687
+ // Query service details to get access URL
110688
+ let serviceUrl = "";
110689
+ try {
110690
+ const serviceDetails = await cloudrunService.detail({ serverName: input.serverName });
110691
+ // Extract access URL from service details
110692
+ // Priority: DefaultDomainName > CustomDomainName > PublicDomain > InternalDomain
110693
+ const details = serviceDetails; // Use any to access dynamic properties
110694
+ if (details?.BaseInfo?.DefaultDomainName) {
110695
+ // DefaultDomainName is already a complete URL (e.g., https://...)
110696
+ serviceUrl = details.BaseInfo.DefaultDomainName;
110697
+ }
110698
+ else if (details?.BaseInfo?.CustomDomainName) {
110699
+ // CustomDomainName might be a domain without protocol
110700
+ const customDomain = details.BaseInfo.CustomDomainName;
110701
+ serviceUrl = customDomain.startsWith('http') ? customDomain : `https://${customDomain}`;
110702
+ }
110703
+ else if (details?.BaseInfo?.PublicDomain) {
110704
+ serviceUrl = `https://${details.BaseInfo.PublicDomain}`;
110705
+ }
110706
+ else if (details?.BaseInfo?.InternalDomain) {
110707
+ serviceUrl = `https://${details.BaseInfo.InternalDomain}`;
110708
+ }
110709
+ else if (details?.AccessInfo?.PublicDomain) {
110710
+ serviceUrl = `https://${details.AccessInfo.PublicDomain}`;
110711
+ }
110712
+ else {
110713
+ serviceUrl = ""; // URL not available
110714
+ }
110715
+ }
110716
+ catch (detailErr) {
110717
+ // If query fails, continue with empty URL
110718
+ serviceUrl = "";
110719
+ }
110720
+ // Extract project name from targetPath
110721
+ const projectName = path_1.default.basename(targetPath);
110722
+ // Build console URL
110723
+ const consoleUrl = `https://tcb.cloud.tencent.com/dev?envId=${currentEnvId}#/platform-run/service/detail?serverName=${input.serverName}&tabId=overview&envId=${currentEnvId}`;
110724
+ // Send notification
110725
+ await (0, notification_js_1.sendDeployNotification)(server, {
110726
+ deployType: 'cloudrun',
110727
+ url: serviceUrl,
110728
+ projectId: currentEnvId,
110729
+ projectName: projectName,
110730
+ consoleUrl: consoleUrl
110731
+ });
110732
+ }
110733
+ catch (notifyErr) {
110734
+ // Notification failure should not affect deployment flow
110735
+ // Error is already logged in sendDeployNotification
110736
+ }
110561
110737
  return {
110562
110738
  content: [
110563
110739
  {
@@ -114734,14 +114910,20 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
114734
114910
  /***/ }),
114735
114911
 
114736
114912
  /***/ 37279:
114737
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
114913
+ /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
114738
114914
 
114739
114915
  "use strict";
114740
114916
 
114917
+ var __importDefault = (this && this.__importDefault) || function (mod) {
114918
+ return (mod && mod.__esModule) ? mod : { "default": mod };
114919
+ };
114741
114920
  Object.defineProperty(exports, "__esModule", ({ value: true }));
114742
114921
  exports.registerHostingTools = registerHostingTools;
114922
+ const fs_1 = __importDefault(__webpack_require__(29021));
114923
+ const path_1 = __importDefault(__webpack_require__(39902));
114743
114924
  const zod_1 = __webpack_require__(21614);
114744
114925
  const cloudbase_manager_js_1 = __webpack_require__(3431);
114926
+ const notification_js_1 = __webpack_require__(32720);
114745
114927
  function registerHostingTools(server) {
114746
114928
  // 获取 cloudBaseOptions,如果没有则为 undefined
114747
114929
  const cloudBaseOptions = server.cloudBaseOptions;
@@ -114778,6 +114960,43 @@ function registerHostingTools(server) {
114778
114960
  // 获取环境信息
114779
114961
  const envInfo = await cloudbase.env.getEnvInfo();
114780
114962
  const staticDomain = envInfo.EnvInfo?.StaticStorages?.[0]?.StaticDomain;
114963
+ const accessUrl = staticDomain ? `https://${staticDomain}/${cloudPath || ''}` : "";
114964
+ // Send deployment notification to CodeBuddy IDE
114965
+ try {
114966
+ const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
114967
+ // Extract project name from localPath
114968
+ let projectName = "unknown";
114969
+ if (localPath) {
114970
+ try {
114971
+ // If localPath is a file, get parent directory name; if it's a directory, get directory name
114972
+ const stats = fs_1.default.statSync(localPath);
114973
+ if (stats.isFile()) {
114974
+ projectName = path_1.default.basename(path_1.default.dirname(localPath));
114975
+ }
114976
+ else {
114977
+ projectName = path_1.default.basename(localPath);
114978
+ }
114979
+ }
114980
+ catch (statErr) {
114981
+ // If stat fails, try to extract from path directly
114982
+ projectName = path_1.default.basename(localPath);
114983
+ }
114984
+ }
114985
+ // Build console URL
114986
+ const consoleUrl = `https://tcb.cloud.tencent.com/dev?envId=${envId}#/static-hosting`;
114987
+ // Send notification
114988
+ await (0, notification_js_1.sendDeployNotification)(server, {
114989
+ deployType: 'hosting',
114990
+ url: accessUrl,
114991
+ projectId: envId,
114992
+ projectName: projectName,
114993
+ consoleUrl: consoleUrl
114994
+ });
114995
+ }
114996
+ catch (notifyErr) {
114997
+ // Notification failure should not affect deployment flow
114998
+ // Error is already logged in sendDeployNotification
114999
+ }
114781
115000
  return {
114782
115001
  content: [
114783
115002
  {
@@ -114786,7 +115005,7 @@ function registerHostingTools(server) {
114786
115005
  ...result,
114787
115006
  staticDomain,
114788
115007
  message: "文件上传成功",
114789
- accessUrl: staticDomain ? `https://${staticDomain}/${cloudPath || ''}` : "请检查静态托管配置"
115008
+ accessUrl: accessUrl
114790
115009
  }, null, 2)
114791
115010
  }
114792
115011
  ]
@@ -134714,7 +134933,7 @@ class TelemetryReporter {
134714
134933
  const nodeVersion = process.version; // Node.js版本
134715
134934
  const arch = os_1.default.arch(); // 系统架构
134716
134935
  // 从构建时注入的版本号获取MCP版本信息
134717
- const mcpVersion = process.env.npm_package_version || "2.0.6" || 0;
134936
+ const mcpVersion = process.env.npm_package_version || "2.2.0-alpha.0" || 0;
134718
134937
  return {
134719
134938
  userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
134720
134939
  deviceId: this.deviceId,
@@ -179312,6 +179531,7 @@ exports.sleep = sleep;
179312
179531
  exports.upperCaseStringFisrt = upperCaseStringFisrt;
179313
179532
  exports.upperCaseObjKey = upperCaseObjKey;
179314
179533
  exports.fetchTemplates = fetchTemplates;
179534
+ exports.successLog = successLog;
179315
179535
  const archiver_1 = __importDefault(__webpack_require__(99133));
179316
179536
  const crypto_1 = __importDefault(__webpack_require__(55511));
179317
179537
  const fs_extra_1 = __importDefault(__webpack_require__(21605));
@@ -179590,6 +179810,10 @@ const getCompleteTimeRange = (timeRange) => {
179590
179810
  };
179591
179811
  };
179592
179812
  exports.getCompleteTimeRange = getCompleteTimeRange;
179813
+ function successLog(msg) {
179814
+ // 空格,兼容中文字符编码长度问题
179815
+ console.log(`${msg}`);
179816
+ }
179593
179817
 
179594
179818
 
179595
179819
  /***/ }),
@@ -185380,6 +185604,7 @@ async function registerRagTools(server) {
185380
185604
  }
185381
185605
  });
185382
185606
  let skills = [];
185607
+ let openapis = [];
185383
185608
  // 知识库检索
185384
185609
  try {
185385
185610
  skills = await prepareKnowledgeBaseWebTemplate();
@@ -185389,22 +185614,40 @@ async function registerRagTools(server) {
185389
185614
  error,
185390
185615
  });
185391
185616
  }
185617
+ // OpenAPI 文档准备
185618
+ try {
185619
+ openapis = await prepareOpenAPIDocs();
185620
+ }
185621
+ catch (error) {
185622
+ (0, logger_js_1.warn)("[searchKnowledgeBase] Failed to prepare OpenAPI docs", {
185623
+ error,
185624
+ });
185625
+ }
185392
185626
  server.registerTool?.("searchKnowledgeBase", {
185393
185627
  title: "云开发知识库检索",
185394
- description: `云开发知识库智能检索工具,支持向量查询 (vector) 和固定文档 (doc) 查询。
185628
+ description: `云开发知识库智能检索工具,支持向量查询 (vector)、固定文档 (doc) 和 OpenAPI 文档 (openapi) 查询。
185395
185629
 
185396
- 强烈推荐始终优先使用固定文档 (doc) 模式进行检索,仅当固定文档无法覆盖你的问题时,再使用向量查询 (vector) 模式。
185630
+ 强烈推荐始终优先使用固定文档 (doc) 或 OpenAPI 文档 (openapi) 模式进行检索,仅当固定文档无法覆盖你的问题时,再使用向量查询 (vector) 模式。
185397
185631
 
185398
185632
  固定文档 (doc) 查询当前支持 ${skills.length} 个固定文档,分别是:
185399
185633
  ${skills
185400
185634
  .map((skill) => `文档名:${path.basename(path.dirname(skill.absolutePath))} 文档介绍:${skill.description}`)
185635
+ .join("\n")}
185636
+
185637
+ OpenAPI 文档 (openapi) 查询当前支持 ${openapis.length} 个 API 文档,分别是:
185638
+ ${openapis
185639
+ .map((api) => `API名:${api.name} API介绍:${api.description}`)
185401
185640
  .join("\n")}`,
185402
185641
  inputSchema: {
185403
- mode: zod_1.z.enum(["vector", "doc"]),
185642
+ mode: zod_1.z.enum(["vector", "doc", "openapi"]),
185404
185643
  docName: zod_1.z
185405
185644
  .enum(skills.map((skill) => path.basename(path.dirname(skill.absolutePath))))
185406
185645
  .optional()
185407
185646
  .describe("mode=doc 时指定。文档名称。"),
185647
+ apiName: zod_1.z
185648
+ .enum(openapis.map((api) => api.name))
185649
+ .optional()
185650
+ .describe("mode=openapi 时指定。API 名称。"),
185408
185651
  threshold: zod_1.z
185409
185652
  .number()
185410
185653
  .default(0.5)
@@ -185434,7 +185677,7 @@ async function registerRagTools(server) {
185434
185677
  openWorldHint: true,
185435
185678
  category: "rag",
185436
185679
  },
185437
- }, async ({ id, content, options: { chunkExpand = [3, 3] } = {}, limit = 5, threshold = 0.5, mode, docName, }) => {
185680
+ }, async ({ id, content, options: { chunkExpand = [3, 3] } = {}, limit = 5, threshold = 0.5, mode, docName, apiName, }) => {
185438
185681
  if (mode === "doc") {
185439
185682
  const absolutePath = skills.find((skill) => skill.absolutePath.includes(docName)).absolutePath;
185440
185683
  return {
@@ -185446,6 +185689,27 @@ async function registerRagTools(server) {
185446
185689
  ],
185447
185690
  };
185448
185691
  }
185692
+ if (mode === "openapi") {
185693
+ const api = openapis.find((api) => api.name === apiName);
185694
+ if (!api) {
185695
+ return {
185696
+ content: [
185697
+ {
185698
+ type: "text",
185699
+ text: `OpenAPI document "${apiName}" not found. Available APIs: ${openapis.map((a) => a.name).join(", ")}`,
185700
+ },
185701
+ ],
185702
+ };
185703
+ }
185704
+ return {
185705
+ content: [
185706
+ {
185707
+ type: "text",
185708
+ text: `OpenAPI document: ${api.name}\nDescription: ${api.description}\nPath: ${api.absolutePath}\n\n${(await fs.readFile(api.absolutePath)).toString()}`,
185709
+ },
185710
+ ],
185711
+ };
185712
+ }
185449
185713
  // 枚举到后端 id 映射
185450
185714
  const backendId = KnowledgeBaseIdMap[id] || id;
185451
185715
  const signInRes = await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/auth/v1/signin/anonymously", {
@@ -185522,6 +185786,65 @@ function extractDescriptionFromFrontMatter(content) {
185522
185786
  .match(/^(?:decsription|description)\s*:\s*(.*)$/m);
185523
185787
  return match ? match[1].trim() : null;
185524
185788
  }
185789
+ // OpenAPI 文档 URL 列表
185790
+ const OPENAPI_SOURCES = [
185791
+ {
185792
+ name: "mysqldb",
185793
+ description: "MySQL RESTful API - 云开发 MySQL 数据库 HTTP API",
185794
+ url: "https://docs.cloudbase.net/openapi/mysqldb.v1.openapi.yaml",
185795
+ },
185796
+ {
185797
+ name: "functions",
185798
+ description: "Cloud Functions API - 云函数 HTTP API",
185799
+ url: "https://docs.cloudbase.net/openapi/functions.v1.openapi.yaml",
185800
+ },
185801
+ {
185802
+ name: "auth",
185803
+ description: "Authentication API - 身份认证 HTTP API",
185804
+ url: "https://docs.cloudbase.net/openapi/auth.v1.openapi.yaml",
185805
+ },
185806
+ {
185807
+ name: "cloudrun",
185808
+ description: "CloudRun API - 云托管服务 HTTP API",
185809
+ url: "https://docs.cloudbase.net/openapi/cloudrun.v1.openapi.yaml",
185810
+ },
185811
+ {
185812
+ name: "storage",
185813
+ description: "Storage API - 云存储 HTTP API",
185814
+ url: "https://docs.cloudbase.net/openapi/storage.v1.openapi.yaml",
185815
+ },
185816
+ ];
185817
+ // 下载并准备 OpenAPI 文档
185818
+ async function prepareOpenAPIDocs() {
185819
+ const baseDir = path.join(os.homedir(), ".cloudbase-mcp", "openapi");
185820
+ await fs.mkdir(baseDir, { recursive: true });
185821
+ const results = [];
185822
+ await Promise.all(OPENAPI_SOURCES.map(async (source) => {
185823
+ try {
185824
+ const response = await fetch(source.url);
185825
+ if (!response.ok) {
185826
+ (0, logger_js_1.warn)(`[prepareOpenAPIDocs] Failed to download ${source.name}`, {
185827
+ status: response.status,
185828
+ });
185829
+ return;
185830
+ }
185831
+ const content = await response.text();
185832
+ const filePath = path.join(baseDir, `${source.name}.openapi.yaml`);
185833
+ await fs.writeFile(filePath, content, "utf8");
185834
+ results.push({
185835
+ name: source.name,
185836
+ description: source.description,
185837
+ absolutePath: filePath,
185838
+ });
185839
+ }
185840
+ catch (error) {
185841
+ (0, logger_js_1.warn)(`[prepareOpenAPIDocs] Failed to download ${source.name}`, {
185842
+ error,
185843
+ });
185844
+ }
185845
+ }));
185846
+ return results;
185847
+ }
185525
185848
  async function collectSkillDescriptions(rootDir) {
185526
185849
  const result = [];
185527
185850
  async function walk(dir) {
@@ -190819,20 +191142,25 @@ function callSuccessCallback(callback, result) {
190819
191142
  /***/ }),
190820
191143
 
190821
191144
  /***/ 65607:
190822
- /***/ ((__unused_webpack_module, exports) => {
191145
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
190823
191146
 
190824
191147
  "use strict";
190825
191148
 
190826
191149
  Object.defineProperty(exports, "__esModule", ({ value: true }));
190827
191150
  exports.CloudBaseContext = void 0;
191151
+ const constant_1 = __webpack_require__(40762);
190828
191152
  class CloudBaseContext {
190829
- constructor({ secretId = '', secretKey = '', token = '', proxy = '', region = '', envType = '' }) {
191153
+ constructor({ secretId = '', secretKey = '', token = '', proxy = '', region = '', envType = '', useInternalEndpoint = undefined }) {
190830
191154
  this.secretId = secretId;
190831
191155
  this.secretKey = secretKey;
190832
191156
  this.token = token;
190833
191157
  this.proxy = proxy;
190834
191158
  this.region = region;
190835
191159
  this.envType = envType;
191160
+ this.useInternalEndpoint = useInternalEndpoint;
191161
+ }
191162
+ isInternalEndpoint() {
191163
+ return this.useInternalEndpoint !== undefined ? this.useInternalEndpoint : constant_1.USE_INTERNAL_ENDPOINT;
190836
191164
  }
190837
191165
  }
190838
191166
  exports.CloudBaseContext = CloudBaseContext;
@@ -200359,7 +200687,7 @@ ${envIdSection}
200359
200687
  ## 环境信息
200360
200688
  - 操作系统: ${os_1.default.type()} ${os_1.default.release()}
200361
200689
  - Node.js版本: ${process.version}
200362
- - MCP 版本:${process.env.npm_package_version || "2.0.6" || 0}
200690
+ - MCP 版本:${process.env.npm_package_version || "2.2.0-alpha.0" || 0}
200363
200691
  - 系统架构: ${os_1.default.arch()}
200364
200692
  - 时间: ${new Date().toISOString()}
200365
200693
  - 请求ID: ${requestId}
@@ -203251,6 +203579,7 @@ class StorageService {
203251
203579
  * 获取 COS 配置
203252
203580
  */
203253
203581
  getCos(parallel = 20) {
203582
+ const internalEndpoint = this.environment.cloudBaseContext.isInternalEndpoint();
203254
203583
  const { secretId, secretKey, token, proxy } = this.environment.getAuthConfig();
203255
203584
  const cosProxy = process.env.TCB_COS_PROXY;
203256
203585
  const cosConfig = {
@@ -203259,14 +203588,14 @@ class StorageService {
203259
203588
  SecretKey: secretKey,
203260
203589
  Proxy: cosProxy || proxy,
203261
203590
  SecurityToken: token,
203262
- Domain: constant_1.USE_INTERNAL_ENDPOINT ? "{Bucket}.cos-internal.{Region}.tencentcos.cn" /* COS_ENDPOINT.INTERNAL */ : "{Bucket}.cos.{Region}.tencentcos.cn" /* COS_ENDPOINT.PUBLIC */,
203591
+ Domain: internalEndpoint ? "{Bucket}.cos-internal.{Region}.tencentcos.cn" /* COS_ENDPOINT.INTERNAL */ : "{Bucket}.cos.{Region}.tencentcos.cn" /* COS_ENDPOINT.PUBLIC */,
203263
203592
  };
203264
203593
  if (constant_1.COS_SDK_PROTOCOL) {
203265
203594
  cosConfig.Protocol = (constant_1.COS_SDK_PROTOCOL.endsWith(':')
203266
203595
  ? constant_1.COS_SDK_PROTOCOL.toLowerCase()
203267
203596
  : constant_1.COS_SDK_PROTOCOL.toLowerCase() + ':');
203268
203597
  }
203269
- if (constant_1.USE_INTERNAL_ENDPOINT) {
203598
+ if (internalEndpoint) {
203270
203599
  cosConfig.Protocol = 'http:';
203271
203600
  }
203272
203601
  // COSSDK 默认开启 KeepAlive,这里提供关闭的方式
@@ -214658,26 +214987,26 @@ const path = __importStar(__webpack_require__(39902));
214658
214987
  const zod_1 = __webpack_require__(21614);
214659
214988
  // CloudBase 模板配置
214660
214989
  const TEMPLATES = {
214661
- "react": {
214990
+ react: {
214662
214991
  description: "React + CloudBase 全栈应用模板",
214663
- url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-react-template.zip"
214992
+ url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-react-template.zip",
214664
214993
  },
214665
- "vue": {
214994
+ vue: {
214666
214995
  description: "Vue + CloudBase 全栈应用模板",
214667
- url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-vue-template.zip"
214996
+ url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-vue-template.zip",
214668
214997
  },
214669
- "miniprogram": {
214998
+ miniprogram: {
214670
214999
  description: "微信小程序 + 云开发模板",
214671
- url: "https://static.cloudbase.net/cloudbase-examples/miniprogram-cloudbase-miniprogram-template.zip"
215000
+ url: "https://static.cloudbase.net/cloudbase-examples/miniprogram-cloudbase-miniprogram-template.zip",
214672
215001
  },
214673
- "uniapp": {
215002
+ uniapp: {
214674
215003
  description: "UniApp + CloudBase 跨端应用模板",
214675
- url: "https://static.cloudbase.net/cloudbase-examples/universal-cloudbase-uniapp-template.zip"
215004
+ url: "https://static.cloudbase.net/cloudbase-examples/universal-cloudbase-uniapp-template.zip",
214676
215005
  },
214677
- "rules": {
215006
+ rules: {
214678
215007
  description: "AI编辑器配置模板(包含所有主流编辑器配置)",
214679
- url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-project.zip"
214680
- }
215008
+ url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-project.zip",
215009
+ },
214681
215010
  };
214682
215011
  // IDE类型枚举
214683
215012
  const IDE_TYPES = [
@@ -214697,22 +215026,13 @@ const IDE_TYPES = [
214697
215026
  "roocode", // RooCode AI编辑器
214698
215027
  "tongyi-lingma", // 通义灵码
214699
215028
  "trae", // Trae AI编辑器
214700
- "vscode" // Visual Studio Code
215029
+ "vscode", // Visual Studio Code
214701
215030
  ];
214702
215031
  // IDE到文件的映射关系
214703
215032
  const IDE_FILE_MAPPINGS = {
214704
- "cursor": [
214705
- ".cursor/rules/cloudbase-rules.mdc",
214706
- ".cursor/mcp.json"
214707
- ],
214708
- "windsurf": [
214709
- ".windsurf/rules/cloudbase-rules.md"
214710
- ],
214711
- "codebuddy": [
214712
- ".rules/cloudbase-rules.md",
214713
- "CODEBUDDY.md",
214714
- ".mcp.json"
214715
- ],
215033
+ cursor: [".cursor/rules/cloudbase-rules.mdc", ".cursor/mcp.json"],
215034
+ windsurf: [".windsurf/rules/cloudbase-rules.md"],
215035
+ codebuddy: [".rules/cloudbase-rules.md", "CODEBUDDY.md", ".mcp.json"],
214716
215036
  "claude-code": [
214717
215037
  "CLAUDE.md",
214718
215038
  ".mcp.json",
@@ -214721,49 +215041,22 @@ const IDE_FILE_MAPPINGS = {
214721
215041
  ".claude/commands/spec.md",
214722
215042
  ".claude/commands/no_spec.md",
214723
215043
  ],
214724
- "cline": [
214725
- ".clinerules/cloudbase-rules.mdc"
214726
- ],
214727
- "gemini-cli": [
214728
- ".gemini/GEMINI.md",
214729
- ".gemini/settings.json"
214730
- ],
214731
- "opencode": [
214732
- ".opencode.json"
214733
- ],
214734
- "qwen-code": [
214735
- ".qwen/QWEN.md",
214736
- ".qwen/settings.json"
214737
- ],
215044
+ cline: [".clinerules/cloudbase-rules.mdc"],
215045
+ "gemini-cli": [".gemini/GEMINI.md", ".gemini/settings.json"],
215046
+ opencode: [".opencode.json"],
215047
+ "qwen-code": [".qwen/QWEN.md", ".qwen/settings.json"],
214738
215048
  "baidu-comate": [
214739
215049
  ".comate/rules/cloudbase-rules.mdr",
214740
215050
  ".comate/rules/cloudbaase-rules.mdr",
214741
- ".comate/mcp.json"
214742
- ],
214743
- "openai-codex-cli": [
214744
- ".codex/config.toml",
214745
- "AGENTS.md",
215051
+ ".comate/mcp.json",
214746
215052
  ],
214747
- "augment-code": [
214748
- ".augment-guidelines"
214749
- ],
214750
- "github-copilot": [
214751
- ".github/copilot-instructions.md"
214752
- ],
214753
- "roocode": [
214754
- ".roo/rules/cloudbaase-rules.md",
214755
- ".roo/mcp.json"
214756
- ],
214757
- "tongyi-lingma": [
214758
- ".lingma/rules/cloudbaase-rules.md"
214759
- ],
214760
- "trae": [
214761
- ".trae/rules/cloudbase-rules.md"
214762
- ],
214763
- "vscode": [
214764
- ".vscode/mcp.json",
214765
- ".vscode/settings.json"
214766
- ]
215053
+ "openai-codex-cli": [".codex/config.toml", "AGENTS.md"],
215054
+ "augment-code": [".augment-guidelines"],
215055
+ "github-copilot": [".github/copilot-instructions.md"],
215056
+ roocode: [".roo/rules/cloudbaase-rules.md", ".roo/mcp.json"],
215057
+ "tongyi-lingma": [".lingma/rules/cloudbaase-rules.md"],
215058
+ trae: [".trae/rules/cloudbase-rules.md"],
215059
+ vscode: [".vscode/mcp.json", ".vscode/settings.json"],
214767
215060
  };
214768
215061
  // 所有IDE配置文件的完整列表 - 通过IDE_FILE_MAPPINGS计算得出
214769
215062
  const ALL_IDE_FILES = Array.from(new Set(Object.values(IDE_FILE_MAPPINGS).flat()));
@@ -214771,51 +215064,87 @@ const ALL_IDE_FILES = Array.from(new Set(Object.values(IDE_FILE_MAPPINGS).flat()
214771
215064
  IDE_FILE_MAPPINGS["all"] = ALL_IDE_FILES;
214772
215065
  // IDE描述映射
214773
215066
  const IDE_DESCRIPTIONS = {
214774
- "all": "所有IDE配置",
214775
- "cursor": "Cursor AI编辑器",
214776
- "windsurf": "WindSurf AI编辑器",
214777
- "codebuddy": "CodeBuddy AI编辑器",
215067
+ all: "所有IDE配置",
215068
+ cursor: "Cursor AI编辑器",
215069
+ windsurf: "WindSurf AI编辑器",
215070
+ codebuddy: "CodeBuddy AI编辑器",
214778
215071
  "claude-code": "Claude Code AI编辑器",
214779
- "cline": "Cline AI编辑器",
215072
+ cline: "Cline AI编辑器",
214780
215073
  "gemini-cli": "Gemini CLI",
214781
- "opencode": "OpenCode AI编辑器",
215074
+ opencode: "OpenCode AI编辑器",
214782
215075
  "qwen-code": "通义灵码",
214783
215076
  "baidu-comate": "百度Comate",
214784
215077
  "openai-codex-cli": "OpenAI Codex CLI",
214785
215078
  "augment-code": "Augment Code",
214786
215079
  "github-copilot": "GitHub Copilot",
214787
- "roocode": "RooCode AI编辑器",
215080
+ roocode: "RooCode AI编辑器",
214788
215081
  "tongyi-lingma": "通义灵码",
214789
- "trae": "Trae AI编辑器",
214790
- "vscode": "Visual Studio Code"
214791
- };
215082
+ trae: "Trae AI编辑器",
215083
+ vscode: "Visual Studio Code",
215084
+ };
215085
+ // INTEGRATION_IDE 环境变量值到 IDE 类型的映射
215086
+ const INTEGRATION_IDE_MAPPING = {
215087
+ Cursor: "cursor",
215088
+ WindSurf: "windsurf",
215089
+ CodeBuddy: "codebuddy",
215090
+ CodeBuddyManual: "codebuddy",
215091
+ CodeBuddyCode: "codebuddy",
215092
+ "Claude Code": "claude-code",
215093
+ CLINE: "cline",
215094
+ "Gemini CLI": "gemini-cli",
215095
+ OpenCode: "opencode",
215096
+ "Qwen Code": "qwen-code",
215097
+ "Baidu Comate": "baidu-comate",
215098
+ "OpenAI Codex CLI": "openai-codex-cli",
215099
+ "Augment Code": "augment-code",
215100
+ "GitHub Copilot": "github-copilot",
215101
+ RooCode: "roocode",
215102
+ "Tongyi Lingma": "tongyi-lingma",
215103
+ Trae: "trae",
215104
+ VSCode: "vscode",
215105
+ };
215106
+ // 根据 INTEGRATION_IDE 环境变量获取默认 IDE 类型
215107
+ function getDefaultIDEFromEnv() {
215108
+ const integrationIDE = process.env.INTEGRATION_IDE;
215109
+ if (integrationIDE) {
215110
+ const mappedIDE = INTEGRATION_IDE_MAPPING[integrationIDE];
215111
+ if (mappedIDE) {
215112
+ return mappedIDE;
215113
+ }
215114
+ }
215115
+ return "all";
215116
+ }
214792
215117
  // 下载文件到临时目录
214793
215118
  async function downloadFile(url, filePath) {
214794
215119
  return new Promise((resolve, reject) => {
214795
- const client = url.startsWith('https:') ? https : http;
214796
- client.get(url, (res) => {
215120
+ const client = url.startsWith("https:") ? https : http;
215121
+ client
215122
+ .get(url, (res) => {
214797
215123
  if (res.statusCode === 200) {
214798
215124
  const file = fs.createWriteStream(filePath);
214799
215125
  res.pipe(file);
214800
- file.on('finish', () => {
215126
+ file.on("finish", () => {
214801
215127
  file.close();
214802
215128
  resolve();
214803
215129
  });
214804
- file.on('error', reject);
215130
+ file.on("error", reject);
214805
215131
  }
214806
215132
  else if (res.statusCode === 302 || res.statusCode === 301) {
214807
215133
  // 处理重定向
214808
215134
  if (res.headers.location) {
214809
- downloadFile(res.headers.location, filePath).then(resolve).catch(reject);
215135
+ downloadFile(res.headers.location, filePath)
215136
+ .then(resolve)
215137
+ .catch(reject);
214810
215138
  }
214811
215139
  else {
214812
- reject(new Error('重定向但没有location header'));
215140
+ reject(new Error("重定向但没有location header"));
214813
215141
  }
214814
215142
  }
214815
215143
  else {
214816
215144
  reject(new Error(`下载失败,状态码: ${res.statusCode}`));
214817
215145
  }
214818
- }).on('error', reject);
215146
+ })
215147
+ .on("error", reject);
214819
215148
  });
214820
215149
  }
214821
215150
  // 解压ZIP文件
@@ -214828,7 +215157,7 @@ async function extractZip(zipPath, extractPath) {
214828
215157
  zip.extractAllTo(extractPath, true);
214829
215158
  }
214830
215159
  catch (error) {
214831
- throw new Error(`解压失败: ${error instanceof Error ? error.message : '未知错误'}`);
215160
+ throw new Error(`解压失败: ${error instanceof Error ? error.message : "未知错误"}`);
214832
215161
  }
214833
215162
  }
214834
215163
  // 获取目录下所有文件的相对路径列表
@@ -214852,7 +215181,7 @@ async function copyFileIfNotExists(src, dest) {
214852
215181
  try {
214853
215182
  // 检查目标文件是否存在
214854
215183
  if (fs.existsSync(dest)) {
214855
- return { copied: false, reason: '文件已存在' };
215184
+ return { copied: false, reason: "文件已存在" };
214856
215185
  }
214857
215186
  // 创建目标目录
214858
215187
  await fsPromises.mkdir(path.dirname(dest), { recursive: true });
@@ -214861,14 +215190,17 @@ async function copyFileIfNotExists(src, dest) {
214861
215190
  return { copied: true };
214862
215191
  }
214863
215192
  catch (error) {
214864
- return { copied: false, reason: `复制失败: ${error instanceof Error ? error.message : '未知错误'}` };
215193
+ return {
215194
+ copied: false,
215195
+ reason: `复制失败: ${error instanceof Error ? error.message : "未知错误"}`,
215196
+ };
214865
215197
  }
214866
215198
  }
214867
215199
  // 复制文件,支持覆盖模式
214868
215200
  // 判断是否应该跳过 README.md 文件
214869
215201
  function shouldSkipReadme(template, destPath, overwrite) {
214870
- const isReadme = path.basename(destPath).toLowerCase() === 'readme.md';
214871
- const isRulesTemplate = template === 'rules';
215202
+ const isReadme = path.basename(destPath).toLowerCase() === "readme.md";
215203
+ const isRulesTemplate = template === "rules";
214872
215204
  const exists = fs.existsSync(destPath);
214873
215205
  return isReadme && isRulesTemplate && exists && !overwrite;
214874
215206
  }
@@ -214877,11 +215209,15 @@ async function copyFile(src, dest, overwrite = false, template) {
214877
215209
  const destExists = fs.existsSync(dest);
214878
215210
  // 检查是否需要跳过 README.md 文件(仅对 rules 模板)
214879
215211
  if (template && shouldSkipReadme(template, dest, overwrite)) {
214880
- return { copied: false, reason: 'README.md 文件已存在,已保护', action: 'protected' };
215212
+ return {
215213
+ copied: false,
215214
+ reason: "README.md 文件已存在,已保护",
215215
+ action: "protected",
215216
+ };
214881
215217
  }
214882
215218
  // 如果目标文件存在且不允许覆盖
214883
215219
  if (destExists && !overwrite) {
214884
- return { copied: false, reason: '文件已存在', action: 'skipped' };
215220
+ return { copied: false, reason: "文件已存在", action: "skipped" };
214885
215221
  }
214886
215222
  // 创建目标目录
214887
215223
  await fsPromises.mkdir(path.dirname(dest), { recursive: true });
@@ -214889,11 +215225,14 @@ async function copyFile(src, dest, overwrite = false, template) {
214889
215225
  await fsPromises.copyFile(src, dest);
214890
215226
  return {
214891
215227
  copied: true,
214892
- action: destExists ? 'overwritten' : 'created'
215228
+ action: destExists ? "overwritten" : "created",
214893
215229
  };
214894
215230
  }
214895
215231
  catch (error) {
214896
- return { copied: false, reason: `复制失败: ${error instanceof Error ? error.message : '未知错误'}` };
215232
+ return {
215233
+ copied: false,
215234
+ reason: `复制失败: ${error instanceof Error ? error.message : "未知错误"}`,
215235
+ };
214897
215236
  }
214898
215237
  }
214899
215238
  // IDE验证函数
@@ -214901,13 +215240,13 @@ function validateIDE(ide) {
214901
215240
  if (ide === "all") {
214902
215241
  return { valid: true };
214903
215242
  }
214904
- const supportedIDEs = IDE_TYPES.filter(type => type !== "all");
215243
+ const supportedIDEs = IDE_TYPES.filter((type) => type !== "all");
214905
215244
  const isValid = supportedIDEs.includes(ide);
214906
215245
  if (!isValid) {
214907
215246
  return {
214908
215247
  valid: false,
214909
215248
  error: `不支持的IDE类型: ${ide}`,
214910
- supportedIDEs: supportedIDEs
215249
+ supportedIDEs: supportedIDEs,
214911
215250
  };
214912
215251
  }
214913
215252
  return { valid: true };
@@ -214922,9 +215261,9 @@ function filterFilesByIDE(files, ide) {
214922
215261
  return files; // 如果找不到映射,返回所有文件
214923
215262
  }
214924
215263
  // 计算需要排除的IDE文件(除了当前IDE需要的文件)
214925
- const filesToExclude = ALL_IDE_FILES.filter(file => !ideFiles.includes(file));
215264
+ const filesToExclude = ALL_IDE_FILES.filter((file) => !ideFiles.includes(file));
214926
215265
  // 排除不需要的IDE配置文件,保留其他所有文件
214927
- return files.filter(file => !filesToExclude.includes(file));
215266
+ return files.filter((file) => !filesToExclude.includes(file));
214928
215267
  }
214929
215268
  // 创建过滤后的目录结构
214930
215269
  async function createFilteredDirectory(extractDir, filteredFiles, ide) {
@@ -214932,7 +215271,7 @@ async function createFilteredDirectory(extractDir, filteredFiles, ide) {
214932
215271
  return extractDir; // 如果选择所有IDE,直接返回原目录
214933
215272
  }
214934
215273
  // 创建新的过滤后目录
214935
- const filteredDir = path.join(path.dirname(extractDir), 'filtered');
215274
+ const filteredDir = path.join(path.dirname(extractDir), "filtered");
214936
215275
  await fsPromises.mkdir(filteredDir, { recursive: true });
214937
215276
  // 只复制过滤后的文件到新目录
214938
215277
  for (const relativePath of filteredFiles) {
@@ -214951,32 +215290,42 @@ function registerSetupTools(server) {
214951
215290
  title: "下载项目模板",
214952
215291
  description: `自动下载并部署CloudBase项目模板。⚠️ **MANDATORY FOR NEW PROJECTS** ⚠️
214953
215292
 
214954
- **CRITICAL**: This tool MUST be called FIRST when starting a new project.\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 版本号信息(版本号:${ true ? "2.0.6" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
215293
+ **CRITICAL**: This tool MUST be called FIRST when starting a new project.\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 版本号信息(版本号:${ true ? "2.2.0-alpha.0" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
214955
215294
  inputSchema: {
214956
- template: zod_1.z.enum(["react", "vue", "miniprogram", "uniapp", "rules"]).describe("要下载的模板类型"),
214957
- ide: zod_1.z.enum(IDE_TYPES).optional().default("all").describe("指定要下载的IDE类型,默认为all(下载所有IDE配置)"),
214958
- overwrite: zod_1.z.boolean().optional().describe("是否覆盖已存在的文件,默认为false(不覆盖)")
215295
+ template: zod_1.z
215296
+ .enum(["react", "vue", "miniprogram", "uniapp", "rules"])
215297
+ .describe("要下载的模板类型"),
215298
+ ide: zod_1.z
215299
+ .enum(IDE_TYPES)
215300
+ .optional()
215301
+ .describe("指定要下载的IDE类型。如果未指定,会根据 INTEGRATION_IDE 环境变量自动选择对应的IDE配置;如果环境变量也未设置,则默认下载所有IDE配置"),
215302
+ overwrite: zod_1.z
215303
+ .boolean()
215304
+ .optional()
215305
+ .describe("是否覆盖已存在的文件,默认为false(不覆盖)"),
214959
215306
  },
214960
215307
  annotations: {
214961
215308
  readOnlyHint: false,
214962
215309
  destructiveHint: false,
214963
215310
  idempotentHint: false,
214964
215311
  openWorldHint: true,
214965
- category: "setup"
214966
- }
214967
- }, async ({ template, ide = "all", overwrite = false }) => {
215312
+ category: "setup",
215313
+ },
215314
+ }, async ({ template, ide, overwrite = false, }) => {
214968
215315
  try {
215316
+ // 如果没有传入 ide 参数,根据 INTEGRATION_IDE 环境变量获取默认值
215317
+ const resolvedIDE = ide ?? getDefaultIDEFromEnv();
214969
215318
  // 验证IDE类型
214970
- const ideValidation = validateIDE(ide);
215319
+ const ideValidation = validateIDE(resolvedIDE);
214971
215320
  if (!ideValidation.valid) {
214972
- const supportedIDEs = ideValidation.supportedIDEs?.join(', ') || '';
215321
+ const supportedIDEs = ideValidation.supportedIDEs?.join(", ") || "";
214973
215322
  return {
214974
215323
  content: [
214975
215324
  {
214976
215325
  type: "text",
214977
- text: `❌ ${ideValidation.error}\n\n支持的IDE类型: ${supportedIDEs}`
214978
- }
214979
- ]
215326
+ text: `❌ ${ideValidation.error}\n\n支持的IDE类型: ${supportedIDEs}`,
215327
+ },
215328
+ ],
214980
215329
  };
214981
215330
  }
214982
215331
  const templateConfig = TEMPLATES[template];
@@ -214985,23 +215334,23 @@ function registerSetupTools(server) {
214985
215334
  content: [
214986
215335
  {
214987
215336
  type: "text",
214988
- text: `❌ 不支持的模板类型: ${template}`
214989
- }
214990
- ]
215337
+ text: `❌ 不支持的模板类型: ${template}`,
215338
+ },
215339
+ ],
214991
215340
  };
214992
215341
  }
214993
215342
  // 创建临时目录
214994
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cloudbase-template-'));
214995
- const zipPath = path.join(tempDir, 'template.zip');
214996
- const extractDir = path.join(tempDir, 'extracted');
215343
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "cloudbase-template-"));
215344
+ const zipPath = path.join(tempDir, "template.zip");
215345
+ const extractDir = path.join(tempDir, "extracted");
214997
215346
  // 下载和解压
214998
215347
  await downloadFile(templateConfig.url, zipPath);
214999
215348
  await extractZip(zipPath, extractDir);
215000
215349
  const extractedFiles = await getAllFiles(extractDir);
215001
215350
  // 根据IDE类型过滤文件
215002
- const filteredFiles = filterFilesByIDE(extractedFiles, ide);
215351
+ const filteredFiles = filterFilesByIDE(extractedFiles, resolvedIDE);
215003
215352
  // 创建过滤后的目录结构(当选择特定IDE时)
215004
- const workingDir = await createFilteredDirectory(extractDir, filteredFiles, ide);
215353
+ const workingDir = await createFilteredDirectory(extractDir, filteredFiles, resolvedIDE);
215005
215354
  // 检查是否需要复制到项目目录
215006
215355
  const workspaceFolder = process.env.WORKSPACE_FOLDER_PATHS || process.cwd();
215007
215356
  let finalFiles = [];
@@ -215016,7 +215365,7 @@ function registerSetupTools(server) {
215016
215365
  const destPath = path.join(workspaceFolder, relativePath);
215017
215366
  const copyResult = await copyFile(srcPath, destPath, overwrite, template);
215018
215367
  if (copyResult.copied) {
215019
- if (copyResult.action === 'overwritten') {
215368
+ if (copyResult.action === "overwritten") {
215020
215369
  overwrittenCount++;
215021
215370
  }
215022
215371
  else {
@@ -215025,7 +215374,7 @@ function registerSetupTools(server) {
215025
215374
  finalFiles.push(destPath);
215026
215375
  }
215027
215376
  else {
215028
- if (copyResult.action === 'protected') {
215377
+ if (copyResult.action === "protected") {
215029
215378
  protectedCount++;
215030
215379
  }
215031
215380
  else {
@@ -215035,11 +215384,11 @@ function registerSetupTools(server) {
215035
215384
  }
215036
215385
  }
215037
215386
  // 添加IDE过滤信息
215038
- const ideInfo = IDE_DESCRIPTIONS[ide] || ide;
215387
+ const ideInfo = IDE_DESCRIPTIONS[resolvedIDE] || resolvedIDE;
215039
215388
  results.push(`✅ ${templateConfig.description} (${ideInfo}) 同步完成`);
215040
215389
  results.push(`📁 临时目录: ${workingDir}`);
215041
215390
  results.push(`🔍 文件过滤: ${extractedFiles.length} → ${filteredFiles.length} 个文件`);
215042
- if (ide !== "all") {
215391
+ if (resolvedIDE !== "all") {
215043
215392
  results.push(`✨ 已过滤IDE配置,仅保留 ${ideInfo} 相关文件`);
215044
215393
  }
215045
215394
  const stats = [];
@@ -215052,36 +215401,36 @@ function registerSetupTools(server) {
215052
215401
  if (skippedCount > 0)
215053
215402
  stats.push(`跳过 ${skippedCount} 个已存在文件`);
215054
215403
  if (stats.length > 0) {
215055
- results.push(`📊 ${stats.join('')}`);
215404
+ results.push(`📊 ${stats.join("")}`);
215056
215405
  }
215057
215406
  if (overwrite || overwrittenCount > 0 || skippedCount > 0) {
215058
- results.push(`🔄 覆盖模式: ${overwrite ? '启用' : '禁用'}`);
215407
+ results.push(`🔄 覆盖模式: ${overwrite ? "启用" : "禁用"}`);
215059
215408
  }
215060
215409
  }
215061
215410
  else {
215062
- finalFiles = filteredFiles.map(relativePath => path.join(workingDir, relativePath));
215063
- const ideInfo = IDE_DESCRIPTIONS[ide] || ide;
215411
+ finalFiles = filteredFiles.map((relativePath) => path.join(workingDir, relativePath));
215412
+ const ideInfo = IDE_DESCRIPTIONS[resolvedIDE] || resolvedIDE;
215064
215413
  results.push(`✅ ${templateConfig.description} (${ideInfo}) 下载完成`);
215065
215414
  results.push(`📁 保存在临时目录: ${workingDir}`);
215066
215415
  results.push(`🔍 文件过滤: ${extractedFiles.length} → ${filteredFiles.length} 个文件`);
215067
- if (ide !== "all") {
215416
+ if (resolvedIDE !== "all") {
215068
215417
  results.push(`✨ 已过滤IDE配置,仅保留 ${ideInfo} 相关文件`);
215069
215418
  }
215070
- results.push('💡 如需将模板(包括隐藏文件)复制到项目目录,请确保复制时包含所有隐藏文件。');
215419
+ results.push("💡 如需将模板(包括隐藏文件)复制到项目目录,请确保复制时包含所有隐藏文件。");
215071
215420
  }
215072
215421
  // 文件路径列表
215073
- results.push('');
215074
- results.push('📋 文件列表:');
215075
- finalFiles.forEach(filePath => {
215422
+ results.push("");
215423
+ results.push("📋 文件列表:");
215424
+ finalFiles.forEach((filePath) => {
215076
215425
  results.push(`${filePath}`);
215077
215426
  });
215078
215427
  return {
215079
215428
  content: [
215080
215429
  {
215081
215430
  type: "text",
215082
- text: results.join('\n')
215083
- }
215084
- ]
215431
+ text: results.join("\n"),
215432
+ },
215433
+ ],
215085
215434
  };
215086
215435
  }
215087
215436
  catch (error) {
@@ -215089,9 +215438,9 @@ function registerSetupTools(server) {
215089
215438
  content: [
215090
215439
  {
215091
215440
  type: "text",
215092
- text: `❌ 下载模板失败: ${error instanceof Error ? error.message : '未知错误'}`
215093
- }
215094
- ]
215441
+ text: `❌ 下载模板失败: ${error instanceof Error ? error.message : "未知错误"}`,
215442
+ },
215443
+ ],
215095
215444
  };
215096
215445
  }
215097
215446
  });
@@ -226043,6 +226392,7 @@ class CloudService {
226043
226392
  this.cloudBaseContext = context;
226044
226393
  }
226045
226394
  get baseUrl() {
226395
+ const internalEndpoint = this.cloudBaseContext.isInternalEndpoint();
226046
226396
  const tcb = process.env.TCB_BASE_URL || 'https://tcb.tencentcloudapi.com';
226047
226397
  const urlMap = {
226048
226398
  tcb,
@@ -226056,7 +226406,7 @@ class CloudService {
226056
226406
  const intranetUrlMap = Object.keys(urlMap).map((service) => ({
226057
226407
  [service]: `https://${service}.internal.tencentcloudapi.com`,
226058
226408
  })).reduce((acc, cur) => (Object.assign(Object.assign({}, acc), cur)), {});
226059
- if (constant_1.USE_INTERNAL_ENDPOINT) {
226409
+ if (internalEndpoint) {
226060
226410
  return intranetUrlMap[this.service];
226061
226411
  }
226062
226412
  if (urlMap[this.service]) {
@@ -269689,7 +270039,7 @@ class CloudBase {
269689
270039
  }
269690
270040
  constructor(config = {}) {
269691
270041
  this.cloudBaseConfig = {};
269692
- let { secretId, secretKey, token, envId, proxy, region, envType } = config;
270042
+ let { secretId, secretKey, token, envId, proxy, region, envType, useInternalEndpoint } = config;
269693
270043
  // config 中传入的 secretId secretkey 必须同时存在
269694
270044
  if ((secretId && !secretKey) || (!secretId && secretKey)) {
269695
270045
  throw new Error('secretId and secretKey must be a pair');
@@ -269701,7 +270051,8 @@ class CloudBase {
269701
270051
  envId,
269702
270052
  envType,
269703
270053
  proxy,
269704
- region
270054
+ region,
270055
+ useInternalEndpoint
269705
270056
  };
269706
270057
  // 初始化 context
269707
270058
  this.context = new context_1.CloudBaseContext(this.cloudBaseConfig);
@@ -269756,6 +270107,9 @@ class CloudBase {
269756
270107
  getManagerConfig() {
269757
270108
  return this.cloudBaseConfig;
269758
270109
  }
270110
+ get isInternalEndpoint() {
270111
+ return this.context.isInternalEndpoint();
270112
+ }
269759
270113
  }
269760
270114
  module.exports = CloudBase;
269761
270115
 
@@ -271834,6 +272188,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
271834
272188
  exports.FunctionService = void 0;
271835
272189
  const fs_1 = __importDefault(__webpack_require__(29021));
271836
272190
  const path_1 = __importDefault(__webpack_require__(39902));
272191
+ const lodash_1 = __importDefault(__webpack_require__(2543));
271837
272192
  const packer_1 = __webpack_require__(5147);
271838
272193
  const error_1 = __webpack_require__(40430);
271839
272194
  const utils_1 = __webpack_require__(62358);
@@ -272080,20 +272435,96 @@ class FunctionService {
272080
272435
  });
272081
272436
  return data;
272082
272437
  }
272438
+ /**
272439
+ * 列出所有函数
272440
+ * @param {IListFunctionOptions} options
272441
+ * @returns {Promise<Record<string, string>[]>}
272442
+ */
272443
+ async listAllFunctions(options) {
272444
+ const allFunctions = [];
272445
+ let currentOffset = 0;
272446
+ const pageSize = 20;
272447
+ const { envId } = options;
272448
+ while (true) {
272449
+ try {
272450
+ const res = await this.scfService.request('ListFunctions', {
272451
+ Namespace: envId,
272452
+ Limit: pageSize,
272453
+ Offset: currentOffset
272454
+ });
272455
+ const { Functions = [], TotalCount } = res;
272456
+ if (Functions.length === 0) {
272457
+ break;
272458
+ }
272459
+ allFunctions.push(...Functions);
272460
+ // 检查是否已获取所有函数
272461
+ if (allFunctions.length >= TotalCount || Functions.length < pageSize) {
272462
+ break;
272463
+ }
272464
+ currentOffset += pageSize;
272465
+ }
272466
+ catch (error) {
272467
+ throw new error_1.CloudBaseError(`获取函数列表失败: ${error.message}`);
272468
+ }
272469
+ }
272470
+ // 格式化数据
272471
+ const data = [];
272472
+ allFunctions.forEach(func => {
272473
+ const { FunctionId, FunctionName, Runtime, AddTime, ModTime, Status } = func;
272474
+ data.push({
272475
+ FunctionId,
272476
+ FunctionName,
272477
+ Runtime,
272478
+ AddTime,
272479
+ ModTime,
272480
+ Status
272481
+ });
272482
+ });
272483
+ return data;
272484
+ }
272083
272485
  /**
272084
272486
  * 删除云函数
272085
272487
  * @param {string} name 云函数名称
272086
272488
  * @param {string} qualifier 需要删除的版本号,不填默认删除函数下全部版本。
272087
272489
  * @returns {Promise<IResponseInfo>}
272088
272490
  */
272089
- async deleteFunction(name, qualifier) {
272491
+ async deleteFunction({ name }) {
272492
+ var _a;
272090
272493
  const { namespace } = this.getFunctionConfig();
272091
- return this.scfService.request('DeleteFunction', {
272494
+ // 检测是否绑定了 API 网关
272495
+ const accessService = this.environment.getAccessService();
272496
+ const res = await accessService.getAccessList({
272497
+ name
272498
+ });
272499
+ // 删除绑定的 API 网关
272500
+ if (((_a = res === null || res === void 0 ? void 0 : res.APISet) === null || _a === void 0 ? void 0 : _a.length) > 0) {
272501
+ await accessService.deleteAccess({
272502
+ name
272503
+ });
272504
+ }
272505
+ await this.scfService.request('DeleteFunction', {
272092
272506
  FunctionName: name,
272093
- Namespace: namespace,
272094
- Qualifier: qualifier
272507
+ Namespace: namespace
272095
272508
  });
272096
272509
  }
272510
+ /**
272511
+ * 批量删除云函数
272512
+ * @param {Object} options
272513
+ * @param {string[]} options.names 云函数名称列表
272514
+ * @returns {Promise<void>}
272515
+ */
272516
+ async batchDeleteFunctions({ names }) {
272517
+ const promises = names.map(name => (async () => {
272518
+ try {
272519
+ await this.deleteFunction({ name });
272520
+ (0, utils_1.successLog)(`[${name}] 函数删除成功!`);
272521
+ }
272522
+ catch (e) {
272523
+ throw new error_1.CloudBaseError(e.message);
272524
+ }
272525
+ })());
272526
+ await Promise.all(promises);
272527
+ }
272097
272528
  /**
272098
272529
  * 获取云函数详细信息
272099
272530
  * @param {string} name 云函数名称
@@ -272128,13 +272559,35 @@ class FunctionService {
272128
272559
  }
272129
272560
  catch (e) {
272130
272561
  data.VpcConfig = {
272131
- vpc: '',
272132
- subnet: ''
272562
+ vpc: 'VpcId',
272563
+ subnet: 'SubnetId'
272133
272564
  };
272134
272565
  }
272135
272566
  }
272136
272567
  return data;
272137
272568
  }
272569
+ /**
272570
+ * 批量获取云函数详细信息
272571
+ * @param {Object} options
272572
+ * @param {string[]} options.names 云函数名称列表
272573
+ * @param {string} options.envId 环境 ID
272574
+ * @param {string} options.codeSecret
272575
+ * @returns {Promise<IFunctionInfo[]>}
272576
+ */
272577
+ async batchGetFunctionsDetail({ names, envId, codeSecret }) {
272578
+ const data = [];
272579
+ const promises = names.map(name => (async () => {
272580
+ try {
272581
+ const info = await this.getFunctionDetail(name, codeSecret);
272582
+ data.push(info);
272583
+ }
272584
+ catch (e) {
272585
+ throw new error_1.CloudBaseError(`${name} 获取信息失败:${e.message}`);
272586
+ }
272587
+ })());
272588
+ await Promise.all(promises);
272589
+ return data;
272590
+ }
272138
272591
  /**
272139
272592
  * 获取函数日志
272140
272593
  * @deprecated 请使用 getFunctionLogsV2 代替
@@ -272231,6 +272684,33 @@ class FunctionService {
272231
272684
  const res = await this.tcbService.request('GetFunctionLogDetail', params);
272232
272685
  return res;
272233
272686
  }
272687
+ /**
272688
+ * 获取函数的完整调用日志
272689
+ * 该方法会自动完成两步操作:1. 获取日志请求ID列表。 2. 根据ID列表获取每条日志的详细内容。
272690
+ * @param {IFunctionLogOptionsV2} options - 查询选项
272691
+ * @returns {Promise<IFunctionLogDetailRes[]>} 返回包含完整日志详情的数组
272692
+ */
272693
+ async getCompleteFunctionLogs(options) {
272694
+ // 调用 getFunctionLogsV2 获取日志请求ID列表
272695
+ const { name } = options;
272696
+ const logs = await this.getFunctionLogsV2(options);
272697
+ // 如果没有日志,直接返回空数组
272698
+ if (logs.LogList.length === 0) {
272699
+ return [];
272700
+ }
272701
+ const detailPromises = logs.LogList.map(async (log) => {
272702
+ // 对每一个日志ID,调用 getFunctionLogDetail
272703
+ const res = await this.getFunctionLogDetail({
272704
+ logRequestId: log.RequestId,
272705
+ startTime: options.startTime,
272706
+ endTime: options.endTime
272707
+ });
272708
+ return Object.assign(Object.assign({}, res), { RetCode: log.RetCode, FunctionName: name });
272709
+ });
272710
+ // 并发执行所有详情查询,等待它们全部完成
272711
+ const detailedLogs = await Promise.all(detailPromises);
272712
+ return detailedLogs;
272713
+ }
272234
272714
  /**
272235
272715
  * 更新云函数配置
272236
272716
  * @param {ICloudFunction} func 云函数配置
@@ -272366,6 +272846,28 @@ class FunctionService {
272366
272846
  throw new error_1.CloudBaseError(`[${name}] 调用失败:\n${e.message}`);
272367
272847
  }
272368
272848
  }
272849
+ /**
272850
+ * 批量调用云函数
272851
+ * @param {IFunctionBatchOptions} options
272852
+ * @returns {Promise<IFunctionInvokeRes[]>}
272853
+ */
272854
+ async batchInvokeFunctions(options) {
272855
+ const { functions, envId, log = false } = options;
272856
+ const promises = functions.map(func => (async () => {
272857
+ try {
272858
+ const result = await this.invokeFunction(func.name, func.params);
272859
+ if (log) {
272860
+ (0, utils_1.successLog)(`[${func.name}] 调用成功\n响应结果:\n`);
272861
+ console.log(result);
272862
+ }
272863
+ return result;
272864
+ }
272865
+ catch (e) {
272866
+ throw new error_1.CloudBaseError(`${func.name} 函数调用失败:${e.message}`);
272867
+ }
272868
+ })());
272869
+ return Promise.all(promises);
272870
+ }
272369
272871
  /**
272370
272872
  * 复制云函数
272371
272873
  * @param {string} name 云函数名称
@@ -272408,12 +272910,34 @@ class FunctionService {
272408
272910
  TriggerDesc: item.config
272409
272911
  };
272410
272912
  });
272411
- return this.scfService.request('BatchCreateTrigger', {
272412
- FunctionName: name,
272413
- Namespace: namespace,
272414
- Triggers: JSON.stringify(parsedTriggers),
272415
- Count: parsedTriggers.length
272416
- });
272913
+ try {
272914
+ return await this.scfService.request('BatchCreateTrigger', {
272915
+ FunctionName: name,
272916
+ Namespace: namespace,
272917
+ Triggers: JSON.stringify(parsedTriggers),
272918
+ Count: parsedTriggers.length
272919
+ });
272920
+ }
272921
+ catch (e) {
272922
+ throw new error_1.CloudBaseError(`[${name}] 创建触发器失败:${e.message}`, {
272923
+ action: e.action,
272924
+ code: e.code
272925
+ });
272926
+ }
272927
+ }
272928
+ // 批量部署函数触发器
272929
+ async batchCreateTriggers(options) {
272930
+ const { functions, envId } = options;
272931
+ const promises = functions.map(func => (async () => {
272932
+ try {
272933
+ await this.createFunctionTriggers(func.name, func.triggers);
272934
+ (0, utils_1.successLog)(`[${func.name}] 创建云函数触发器成功!`);
272935
+ }
272936
+ catch (e) {
272937
+ throw new error_1.CloudBaseError(e.message);
272938
+ }
272939
+ })());
272940
+ await Promise.all(promises);
272417
272941
  }
272418
272942
  /**
272419
272943
  * 删除云函数触发器
@@ -272423,12 +272947,50 @@ class FunctionService {
272423
272947
  */
272424
272948
  async deleteFunctionTrigger(name, triggerName) {
272425
272949
  const { namespace } = this.getFunctionConfig();
272426
- return this.scfService.request('DeleteTrigger', {
272427
- FunctionName: name,
272428
- Namespace: namespace,
272429
- TriggerName: triggerName,
272430
- Type: 'timer'
272950
+ try {
272951
+ await this.scfService.request('DeleteTrigger', {
272952
+ FunctionName: name,
272953
+ Namespace: namespace,
272954
+ TriggerName: triggerName,
272955
+ Type: 'timer'
272956
+ });
272957
+ (0, utils_1.successLog)(`[${name}] 删除云函数触发器 ${triggerName} 成功!`);
272958
+ }
272959
+ catch (e) {
272960
+ throw new error_1.CloudBaseError(`[${name}] 删除触发器失败:${e.message}`);
272961
+ }
272962
+ }
272963
+ async batchDeleteTriggers(options) {
272964
+ const { functions, envId } = options;
272965
+ const promises = functions.map(func => (async () => {
272966
+ try {
272967
+ func.triggers.forEach(async (trigger) => {
272968
+ await this.deleteFunctionTrigger(func.name, trigger.name);
272969
+ });
272970
+ }
272971
+ catch (e) {
272972
+ throw new error_1.CloudBaseError(e.message);
272973
+ }
272974
+ })());
272975
+ await Promise.all(promises);
272976
+ }
272977
+ /**
272978
+ * 下载云函数代码
272979
+ * @param {IFunctionCodeOptions} options
272980
+ * @returns {Promise<void>}
272981
+ */
272982
+ async downloadFunctionCode(options) {
272983
+ const { destPath, envId, functionName, codeSecret } = options;
272984
+ // 检验路径是否存在
272985
+ (0, utils_1.checkFullAccess)(destPath, true);
272986
+ // 获取下载链接
272987
+ const { Url } = await this.scfService.request('GetFunctionAddress', {
272988
+ FunctionName: functionName,
272989
+ Namespace: envId,
272990
+ CodeSecret: codeSecret
272431
272991
  });
272992
+ // 下载文件
272993
+ return (0, utils_1.downloadAndExtractRemoteZip)(Url, destPath);
272432
272994
  }
272433
272995
  /**
272434
272996
  * 获取云函数代码下载 链接
@@ -272454,6 +273016,68 @@ class FunctionService {
272454
273016
  throw new error_1.CloudBaseError(`[${functionName}] 获取函数代码下载链接失败:\n${e.message}`);
272455
273017
  }
272456
273018
  }
273019
+ // 函数绑定文件层
273020
+ async attachLayer(options) {
273021
+ const { envId, functionName, layerName, layerVersion, codeSecret } = options;
273022
+ let { Layers = [] } = await this.getFunctionDetail(functionName, codeSecret);
273023
+ Layers = Layers.map(item => lodash_1.default.pick(item, ['LayerName', 'LayerVersion']));
273024
+ // 新加的文件层添加到最后
273025
+ Layers.push({
273026
+ LayerName: layerName,
273027
+ LayerVersion: layerVersion
273028
+ });
273029
+ const res = await this.scfService.request('UpdateFunctionConfiguration', {
273030
+ Layers,
273031
+ Namespace: envId,
273032
+ FunctionName: functionName
273033
+ });
273034
+ return res;
273035
+ }
273036
+ // 函数解绑文件层
273037
+ async unAttachLayer(options) {
273038
+ const { envId, functionName, layerName, layerVersion, codeSecret } = options;
273039
+ let { Layers } = await this.getFunctionDetail(functionName, codeSecret);
273040
+ Layers = Layers.map(item => lodash_1.default.pick(item, ['LayerName', 'LayerVersion']));
273041
+ const index = Layers.findIndex(item => item.LayerName === layerName && item.LayerVersion === layerVersion);
273042
+ if (index === -1) {
273043
+ throw new error_1.CloudBaseError('层不存在');
273044
+ }
273045
+ // 删除指定的层
273046
+ Layers.splice(index, 1);
273047
+ const apiParams = {
273048
+ Namespace: envId,
273049
+ FunctionName: functionName,
273050
+ Layers: Layers.length > 0 ? Layers : [{
273051
+ LayerName: '',
273052
+ LayerVersion: 0
273053
+ }]
273054
+ };
273055
+ return this.scfService.request('UpdateFunctionConfiguration', apiParams);
273056
+ }
273057
+ // 更新云函数层
273058
+ async updateFunctionLayer(options) {
273059
+ const { envId, functionName, layers } = options;
273060
+ return this.scfService.request('UpdateFunctionConfiguration', {
273061
+ Layers: layers,
273062
+ Namespace: envId,
273063
+ FunctionName: functionName
273064
+ });
273065
+ }
273066
+ // 下载文件层 ZIP 文件
273067
+ async downloadLayer(options) {
273068
+ const { name, version, destPath } = options;
273069
+ const res = await this.scfService.request('GetLayerVersion', {
273070
+ LayerName: name,
273071
+ LayerVersion: version
273072
+ });
273073
+ const url = res === null || res === void 0 ? void 0 : res.Location;
273074
+ const zipPath = path_1.default.join(destPath, `${name}-${version}.zip`);
273075
+ if ((0, utils_1.checkFullAccess)(zipPath)) {
273076
+ throw new error_1.CloudBaseError(`文件已存在:${zipPath}`);
273077
+ }
273078
+ // 下载文件
273079
+ return (0, utils_1.downloadAndExtractRemoteZip)(url, destPath);
273080
+ }
272457
273081
  // 创建文件层版本
272458
273082
  async createLayer(options) {
272459
273083
  const { env } = this.getFunctionConfig();
@@ -272526,7 +273150,7 @@ class FunctionService {
272526
273150
  Limit: limit,
272527
273151
  Offset: offset,
272528
273152
  SearchKey: searchKey,
272529
- SearchSrc: `TCB_${env}`
273153
+ // SearchSrc: `TCB_${env}`
272530
273154
  };
272531
273155
  if (runtime) {
272532
273156
  param.CompatibleRuntime = runtime;
@@ -272855,12 +273479,18 @@ __decorate([
272855
273479
  __decorate([
272856
273480
  (0, utils_1.preLazy)()
272857
273481
  ], FunctionService.prototype, "listFunctions", null);
273482
+ __decorate([
273483
+ (0, utils_1.preLazy)()
273484
+ ], FunctionService.prototype, "listAllFunctions", null);
272858
273485
  __decorate([
272859
273486
  (0, utils_1.preLazy)()
272860
273487
  ], FunctionService.prototype, "deleteFunction", null);
272861
273488
  __decorate([
272862
273489
  (0, utils_1.preLazy)()
272863
273490
  ], FunctionService.prototype, "getFunctionDetail", null);
273491
+ __decorate([
273492
+ (0, utils_1.preLazy)()
273493
+ ], FunctionService.prototype, "batchGetFunctionsDetail", null);
272864
273494
  __decorate([
272865
273495
  (0, utils_1.preLazy)()
272866
273496
  ], FunctionService.prototype, "getFunctionLogs", null);
@@ -272870,6 +273500,9 @@ __decorate([
272870
273500
  __decorate([
272871
273501
  (0, utils_1.preLazy)()
272872
273502
  ], FunctionService.prototype, "getFunctionLogDetail", null);
273503
+ __decorate([
273504
+ (0, utils_1.preLazy)()
273505
+ ], FunctionService.prototype, "getCompleteFunctionLogs", null);
272873
273506
  __decorate([
272874
273507
  (0, utils_1.preLazy)()
272875
273508
  ], FunctionService.prototype, "updateFunctionConfig", null);
@@ -272879,6 +273512,9 @@ __decorate([
272879
273512
  __decorate([
272880
273513
  (0, utils_1.preLazy)()
272881
273514
  ], FunctionService.prototype, "invokeFunction", null);
273515
+ __decorate([
273516
+ (0, utils_1.preLazy)()
273517
+ ], FunctionService.prototype, "batchInvokeFunctions", null);
272882
273518
  __decorate([
272883
273519
  (0, utils_1.preLazy)()
272884
273520
  ], FunctionService.prototype, "copyFunction", null);
@@ -272891,6 +273527,18 @@ __decorate([
272891
273527
  __decorate([
272892
273528
  (0, utils_1.preLazy)()
272893
273529
  ], FunctionService.prototype, "getFunctionDownloadUrl", null);
273530
+ __decorate([
273531
+ (0, utils_1.preLazy)()
273532
+ ], FunctionService.prototype, "attachLayer", null);
273533
+ __decorate([
273534
+ (0, utils_1.preLazy)()
273535
+ ], FunctionService.prototype, "unAttachLayer", null);
273536
+ __decorate([
273537
+ (0, utils_1.preLazy)()
273538
+ ], FunctionService.prototype, "updateFunctionLayer", null);
273539
+ __decorate([
273540
+ (0, utils_1.preLazy)()
273541
+ ], FunctionService.prototype, "downloadLayer", null);
272894
273542
  __decorate([
272895
273543
  (0, utils_1.preLazy)()
272896
273544
  ], FunctionService.prototype, "createLayer", null);