@cloudbase/cloudbase-mcp 2.12.1 → 2.14.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.
- package/dist/cli.cjs +3 -3
- package/dist/index.cjs +1679 -438
- package/dist/index.d.ts +379 -13
- package/dist/index.js +1348 -297
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -32,11 +32,12 @@ import * as __WEBPACK_EXTERNAL_MODULE_winston__ from "winston";
|
|
|
32
32
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
33
33
|
exports.simplifyEnvList = simplifyEnvList;
|
|
34
34
|
exports.registerEnvTools = registerEnvTools;
|
|
35
|
+
const toolbox_1 = __webpack_require__(2090);
|
|
35
36
|
const zod_1 = __webpack_require__(2971);
|
|
36
37
|
const auth_js_1 = __webpack_require__(7291);
|
|
37
38
|
const cloudbase_manager_js_1 = __webpack_require__(3431);
|
|
38
39
|
const logger_js_1 = __webpack_require__(3039);
|
|
39
|
-
const
|
|
40
|
+
const tool_result_js_1 = __webpack_require__(9835);
|
|
40
41
|
const rag_js_1 = __webpack_require__(4215);
|
|
41
42
|
/**
|
|
42
43
|
* Simplify environment list data by keeping only essential fields for AI assistant
|
|
@@ -68,17 +69,119 @@ function simplifyEnvList(envList) {
|
|
|
68
69
|
return simplified;
|
|
69
70
|
});
|
|
70
71
|
}
|
|
72
|
+
function formatDeviceAuthHint(deviceAuthInfo) {
|
|
73
|
+
if (!deviceAuthInfo) {
|
|
74
|
+
return "";
|
|
75
|
+
}
|
|
76
|
+
const lines = [
|
|
77
|
+
"",
|
|
78
|
+
"### Device Flow 授权信息",
|
|
79
|
+
`- user_code: ${deviceAuthInfo.user_code}`,
|
|
80
|
+
];
|
|
81
|
+
if (deviceAuthInfo.verification_uri) {
|
|
82
|
+
lines.push(`- verification_uri: ${deviceAuthInfo.verification_uri}`);
|
|
83
|
+
}
|
|
84
|
+
lines.push(`- expires_in: ${deviceAuthInfo.expires_in}s`);
|
|
85
|
+
lines.push("", "请在另一台可用浏览器设备打开 `verification_uri` 并输入 `user_code` 完成授权。");
|
|
86
|
+
return lines.join("\n");
|
|
87
|
+
}
|
|
88
|
+
function emitDeviceAuthNotice(server, deviceAuthInfo) {
|
|
89
|
+
// Temporarily disabled: avoid sending logging notifications for device auth
|
|
90
|
+
}
|
|
91
|
+
async function fetchAvailableEnvCandidates(cloudBaseOptions, server) {
|
|
92
|
+
try {
|
|
93
|
+
return await (0, cloudbase_manager_js_1.listAvailableEnvCandidates)({
|
|
94
|
+
cloudBaseOptions,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const CODEBUDDY_AUTH_ACTIONS = ["status", "set_env"];
|
|
102
|
+
const DEFAULT_AUTH_ACTIONS = [
|
|
103
|
+
"status",
|
|
104
|
+
"start_auth",
|
|
105
|
+
"set_env",
|
|
106
|
+
"logout",
|
|
107
|
+
];
|
|
108
|
+
function getCurrentIde(server) {
|
|
109
|
+
return server.ide || process.env.INTEGRATION_IDE || "";
|
|
110
|
+
}
|
|
111
|
+
function isCodeBuddyIde(server) {
|
|
112
|
+
return getCurrentIde(server) === "CodeBuddy";
|
|
113
|
+
}
|
|
114
|
+
function getSupportedAuthActions(server) {
|
|
115
|
+
return isCodeBuddyIde(server) ? CODEBUDDY_AUTH_ACTIONS : DEFAULT_AUTH_ACTIONS;
|
|
116
|
+
}
|
|
117
|
+
function buildAuthRequiredNextStep(server) {
|
|
118
|
+
if (isCodeBuddyIde(server)) {
|
|
119
|
+
return (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
120
|
+
suggestedArgs: { action: "status" },
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
|
|
124
|
+
suggestedArgs: { action: "start_auth", authMode: "device" },
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function buildSetEnvNextStep(envCandidates) {
|
|
128
|
+
const singleEnvId = envCandidates.length === 1 ? envCandidates[0].envId : undefined;
|
|
129
|
+
return (0, tool_result_js_1.buildAuthNextStep)("set_env", {
|
|
130
|
+
requiredParams: singleEnvId ? undefined : ["envId"],
|
|
131
|
+
suggestedArgs: singleEnvId
|
|
132
|
+
? { action: "set_env", envId: singleEnvId }
|
|
133
|
+
: { action: "set_env" },
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
async function getGuidePrompt(server) {
|
|
137
|
+
if (getCurrentIde(server) === "CodeBuddy" ||
|
|
138
|
+
process.env.CLOUDBASE_GUIDE_PROMPT === "false") {
|
|
139
|
+
return "";
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
return await (0, rag_js_1.getClaudePrompt)();
|
|
143
|
+
}
|
|
144
|
+
catch (promptError) {
|
|
145
|
+
(0, logger_js_1.debug)("Failed to get CLAUDE prompt", { error: promptError });
|
|
146
|
+
return "";
|
|
147
|
+
}
|
|
148
|
+
}
|
|
71
149
|
function registerEnvTools(server) {
|
|
72
150
|
// 获取 cloudBaseOptions,如果没有则为 undefined
|
|
73
151
|
const cloudBaseOptions = server.cloudBaseOptions;
|
|
74
152
|
const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions, mcpServer: server });
|
|
75
153
|
const hasEnvId = typeof cloudBaseOptions?.envId === 'string' && cloudBaseOptions?.envId.length > 0;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
154
|
+
const supportedAuthActions = getSupportedAuthActions(server);
|
|
155
|
+
const authActionEnum = [...supportedAuthActions];
|
|
156
|
+
// auth - CloudBase (云开发) 开发阶段登录与环境绑定
|
|
157
|
+
server.registerTool?.("auth", {
|
|
158
|
+
title: "CloudBase 开发阶段登录与环境",
|
|
159
|
+
description: "CloudBase(腾讯云开发)开发阶段登录与环境绑定。登录后即可访问云资源;环境(env)是云函数、数据库、静态托管等资源的隔离单元,绑定环境后其他 MCP 工具才能操作该环境。支持:查询状态、发起登录、绑定环境(set_env)、退出登录。",
|
|
80
160
|
inputSchema: {
|
|
81
|
-
|
|
161
|
+
action: zod_1.z
|
|
162
|
+
.enum(authActionEnum)
|
|
163
|
+
.optional()
|
|
164
|
+
.describe("动作:status=查询状态,start_auth=发起登录,set_env=绑定环境(传envId),logout=退出登录"),
|
|
165
|
+
...(supportedAuthActions.includes("start_auth")
|
|
166
|
+
? {
|
|
167
|
+
authMode: zod_1.z
|
|
168
|
+
.enum(["device", "web"])
|
|
169
|
+
.optional()
|
|
170
|
+
.describe("认证模式:device=设备码授权,web=浏览器回调授权"),
|
|
171
|
+
}
|
|
172
|
+
: {}),
|
|
173
|
+
envId: zod_1.z
|
|
174
|
+
.string()
|
|
175
|
+
.optional()
|
|
176
|
+
.describe("环境ID(CloudBase 环境唯一标识),绑定后工具将操作该环境。action=set_env 时必填"),
|
|
177
|
+
...(supportedAuthActions.includes("logout")
|
|
178
|
+
? {
|
|
179
|
+
confirm: zod_1.z
|
|
180
|
+
.literal("yes")
|
|
181
|
+
.optional()
|
|
182
|
+
.describe("action=logout 时确认操作,传 yes"),
|
|
183
|
+
}
|
|
184
|
+
: {}),
|
|
82
185
|
},
|
|
83
186
|
annotations: {
|
|
84
187
|
readOnlyHint: false,
|
|
@@ -87,135 +190,326 @@ function registerEnvTools(server) {
|
|
|
87
190
|
openWorldHint: true,
|
|
88
191
|
category: "env",
|
|
89
192
|
},
|
|
90
|
-
}, async (
|
|
91
|
-
|
|
193
|
+
}, async (rawArgs) => {
|
|
194
|
+
const action = rawArgs.action ?? "status";
|
|
195
|
+
const authMode = rawArgs.authMode === "device" || rawArgs.authMode === "web"
|
|
196
|
+
? rawArgs.authMode
|
|
197
|
+
: undefined;
|
|
198
|
+
const envId = rawArgs.envId;
|
|
199
|
+
const confirm = rawArgs.confirm === "yes" ? "yes" : undefined;
|
|
200
|
+
let deviceAuthInfo;
|
|
201
|
+
const onDeviceCode = (info) => {
|
|
202
|
+
deviceAuthInfo = info;
|
|
203
|
+
(0, auth_js_1.setPendingAuthProgressState)(info, "device");
|
|
204
|
+
// emitDeviceAuthNotice(server, info);
|
|
205
|
+
};
|
|
206
|
+
const authChallenge = () => deviceAuthInfo
|
|
207
|
+
? {
|
|
208
|
+
user_code: deviceAuthInfo.user_code,
|
|
209
|
+
verification_uri: deviceAuthInfo.verification_uri,
|
|
210
|
+
expires_in: deviceAuthInfo.expires_in,
|
|
211
|
+
}
|
|
212
|
+
: undefined;
|
|
92
213
|
try {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
serverIde: server?.ide
|
|
102
|
-
});
|
|
103
|
-
const { selectedEnvId, cancelled, error, noEnvs, switch: switchAccount, } = await (0, interactive_js_1._promptAndSetEnvironmentId)(forceUpdate, {
|
|
104
|
-
server, // Pass ExtendedMcpServer instance
|
|
105
|
-
loginFromCloudBaseLoginPage: isSwitching,
|
|
106
|
-
// When switching account, ignore environment variables to force Web login
|
|
107
|
-
ignoreEnvVars: isSwitching,
|
|
214
|
+
if (!supportedAuthActions.includes(action)) {
|
|
215
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
216
|
+
ok: false,
|
|
217
|
+
code: "NOT_SUPPORTED",
|
|
218
|
+
message: `当前 IDE 不支持 auth(action="${action}")。`,
|
|
219
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
220
|
+
suggestedArgs: { action: "status" },
|
|
221
|
+
}),
|
|
108
222
|
});
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
223
|
+
}
|
|
224
|
+
if (action === "status") {
|
|
225
|
+
const loginState = await (0, auth_js_1.peekLoginState)();
|
|
226
|
+
const authFlowState = await (0, auth_js_1.getAuthProgressState)();
|
|
227
|
+
const envId = (0, cloudbase_manager_js_1.getCachedEnvId)() ||
|
|
228
|
+
process.env.CLOUDBASE_ENV_ID ||
|
|
229
|
+
(typeof loginState?.envId === "string" ? loginState.envId : undefined);
|
|
230
|
+
const authStatus = loginState
|
|
231
|
+
? "READY"
|
|
232
|
+
: authFlowState.status === "PENDING"
|
|
233
|
+
? "PENDING"
|
|
234
|
+
: "REQUIRED";
|
|
235
|
+
const envCandidates = await fetchAvailableEnvCandidates(cloudBaseOptions, server);
|
|
236
|
+
const envStatus = envId
|
|
237
|
+
? "READY"
|
|
238
|
+
: envCandidates.length > 1
|
|
239
|
+
? "MULTIPLE"
|
|
240
|
+
: envCandidates.length === 1
|
|
241
|
+
? "READY"
|
|
242
|
+
: "NONE";
|
|
243
|
+
const message = authStatus === "READY"
|
|
244
|
+
? `当前已登录${envId ? `,环境: ${envId}` : ",但未绑定环境"}`
|
|
245
|
+
: authStatus === "PENDING"
|
|
246
|
+
? "设备码授权进行中,请完成浏览器授权后再次调用 auth(action=\"status\")"
|
|
247
|
+
: isCodeBuddyIde(server)
|
|
248
|
+
? "当前未登录。CodeBuddy 暂不支持在 tool 内发起认证,请在外部完成认证后再次调用 auth(action=\"status\")。"
|
|
249
|
+
: "当前未登录,请先执行 auth(action=\"start_auth\")";
|
|
250
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
251
|
+
ok: true,
|
|
252
|
+
code: "STATUS",
|
|
253
|
+
auth_status: authStatus,
|
|
254
|
+
env_status: envStatus,
|
|
255
|
+
current_env_id: envId || null,
|
|
256
|
+
env_candidates: envCandidates,
|
|
257
|
+
auth_challenge: authFlowState.status === "PENDING" && authFlowState.authChallenge
|
|
258
|
+
? {
|
|
259
|
+
user_code: authFlowState.authChallenge.user_code,
|
|
260
|
+
verification_uri: authFlowState.authChallenge.verification_uri,
|
|
261
|
+
expires_in: authFlowState.authChallenge.expires_in,
|
|
262
|
+
}
|
|
263
|
+
: undefined,
|
|
264
|
+
message,
|
|
265
|
+
next_step: authStatus === "REQUIRED"
|
|
266
|
+
? buildAuthRequiredNextStep(server)
|
|
267
|
+
: authStatus === "PENDING"
|
|
268
|
+
? (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
269
|
+
suggestedArgs: { action: "status" },
|
|
270
|
+
})
|
|
271
|
+
: !envId
|
|
272
|
+
? buildSetEnvNextStep(envCandidates)
|
|
273
|
+
: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
274
|
+
suggestedArgs: { action: "status" },
|
|
275
|
+
}),
|
|
116
276
|
});
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
277
|
+
}
|
|
278
|
+
if (action === "start_auth") {
|
|
279
|
+
const region = server.cloudBaseOptions?.region || process.env.TCB_REGION;
|
|
280
|
+
const auth = toolbox_1.AuthSupervisor.getInstance({});
|
|
281
|
+
const authFlowState = await (0, auth_js_1.getAuthProgressState)();
|
|
282
|
+
if (authFlowState.status === "PENDING" && authFlowState.authChallenge) {
|
|
283
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
284
|
+
ok: true,
|
|
285
|
+
code: "AUTH_PENDING",
|
|
286
|
+
message: "设备码授权进行中,请在浏览器中打开 verification_uri 并输入 user_code 完成授权。",
|
|
287
|
+
auth_challenge: {
|
|
288
|
+
user_code: authFlowState.authChallenge.user_code,
|
|
289
|
+
verification_uri: authFlowState.authChallenge.verification_uri,
|
|
290
|
+
expires_in: authFlowState.authChallenge.expires_in,
|
|
291
|
+
},
|
|
292
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
293
|
+
suggestedArgs: { action: "status" },
|
|
294
|
+
}),
|
|
295
|
+
});
|
|
122
296
|
}
|
|
123
|
-
//
|
|
124
|
-
|
|
125
|
-
(0,
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
297
|
+
// 1. 如果已经有登录态,直接返回 AUTH_READY
|
|
298
|
+
try {
|
|
299
|
+
const existingLoginState = await (0, auth_js_1.peekLoginState)();
|
|
300
|
+
if (existingLoginState) {
|
|
301
|
+
const envId = typeof existingLoginState.envId === "string" ? existingLoginState.envId : null;
|
|
302
|
+
const envCandidates = envId
|
|
303
|
+
? []
|
|
304
|
+
: await fetchAvailableEnvCandidates(cloudBaseOptions, server);
|
|
305
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
306
|
+
ok: true,
|
|
307
|
+
code: "AUTH_READY",
|
|
308
|
+
message: envId
|
|
309
|
+
? `认证成功,当前登录态 envId: ${envId}`
|
|
310
|
+
: "认证成功",
|
|
311
|
+
auth_challenge: authChallenge(),
|
|
312
|
+
env_candidates: envCandidates,
|
|
313
|
+
next_step: envId
|
|
314
|
+
? (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
315
|
+
suggestedArgs: { action: "status" },
|
|
316
|
+
})
|
|
317
|
+
: buildSetEnvNextStep(envCandidates),
|
|
318
|
+
});
|
|
139
319
|
}
|
|
140
320
|
}
|
|
141
|
-
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
321
|
+
catch {
|
|
322
|
+
// 忽略 getLoginState 错误,继续尝试发起登录
|
|
323
|
+
}
|
|
324
|
+
// 2. 设备码模式:监听到 device code 即返回 AUTH_PENDING,后续由 toolbox 异步轮询并更新本地 credential
|
|
325
|
+
const effectiveMode = authMode && (authMode === "device" || authMode === "web")
|
|
326
|
+
? authMode
|
|
327
|
+
: process.env.TCB_AUTH_MODE === "web"
|
|
328
|
+
? "web"
|
|
329
|
+
: "device";
|
|
330
|
+
if (effectiveMode === "device") {
|
|
331
|
+
let resolveCode;
|
|
332
|
+
let rejectCode;
|
|
333
|
+
const codeReady = new Promise((resolve, reject) => {
|
|
334
|
+
resolveCode = resolve;
|
|
335
|
+
rejectCode = reject;
|
|
336
|
+
});
|
|
337
|
+
const deviceOnCode = (info) => {
|
|
338
|
+
onDeviceCode(info);
|
|
339
|
+
if (resolveCode) {
|
|
340
|
+
resolveCode();
|
|
148
341
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
342
|
+
};
|
|
343
|
+
try {
|
|
344
|
+
// 启动 Device Flow,全流程由 toolbox 负责轮询和写入 credential,这里不等待完成
|
|
345
|
+
auth
|
|
346
|
+
.loginByWebAuth({
|
|
347
|
+
flow: "device",
|
|
348
|
+
onDeviceCode: deviceOnCode,
|
|
349
|
+
})
|
|
350
|
+
.then(() => {
|
|
351
|
+
(0, auth_js_1.resolveAuthProgressState)();
|
|
352
|
+
})
|
|
353
|
+
.catch((err) => {
|
|
354
|
+
(0, auth_js_1.rejectAuthProgressState)(err);
|
|
355
|
+
// 如果在拿到 device code 之前就失败,则唤醒当前调用并返回错误
|
|
356
|
+
if (!deviceAuthInfo && rejectCode) {
|
|
357
|
+
rejectCode(err);
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
catch (err) {
|
|
362
|
+
if (rejectCode) {
|
|
363
|
+
rejectCode(err);
|
|
152
364
|
}
|
|
153
365
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
366
|
+
try {
|
|
367
|
+
await codeReady;
|
|
368
|
+
}
|
|
369
|
+
catch (err) {
|
|
370
|
+
const message = err instanceof Error ? err.message : String(err ?? "unknown error");
|
|
371
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
372
|
+
ok: false,
|
|
373
|
+
code: "AUTH_REQUIRED",
|
|
374
|
+
message: `设备码登录初始化失败: ${message}`,
|
|
375
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
|
|
376
|
+
suggestedArgs: { action: "start_auth", authMode: "device" },
|
|
377
|
+
}),
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
if (!deviceAuthInfo) {
|
|
381
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
382
|
+
ok: false,
|
|
383
|
+
code: "AUTH_REQUIRED",
|
|
384
|
+
message: "未获取到设备码信息,请重试设备码登录",
|
|
385
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
|
|
386
|
+
suggestedArgs: { action: "start_auth", authMode: "device" },
|
|
387
|
+
}),
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
const envCandidates = await fetchAvailableEnvCandidates(cloudBaseOptions, server);
|
|
391
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
392
|
+
ok: true,
|
|
393
|
+
code: "AUTH_PENDING",
|
|
394
|
+
message: "已发起设备码登录,请在浏览器中打开 verification_uri 并输入 user_code 完成授权。授权完成后请再次调用 auth(action=\"status\")。",
|
|
395
|
+
auth_challenge: authChallenge(),
|
|
396
|
+
env_candidates: envCandidates,
|
|
397
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
398
|
+
suggestedArgs: { action: "status" },
|
|
399
|
+
}),
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
// 3. 非 Device Flow(显式 web 模式)仍然使用 getLoginState 阻塞等待
|
|
403
|
+
const loginState = await (0, auth_js_1.ensureLogin)({
|
|
404
|
+
region,
|
|
405
|
+
authMode: effectiveMode,
|
|
406
|
+
});
|
|
407
|
+
if (!loginState) {
|
|
408
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
409
|
+
ok: false,
|
|
410
|
+
code: "AUTH_REQUIRED",
|
|
411
|
+
message: "未获取到登录态,请先完成认证",
|
|
412
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
|
|
413
|
+
suggestedArgs: { action: "start_auth", authMode: effectiveMode },
|
|
414
|
+
}),
|
|
415
|
+
});
|
|
166
416
|
}
|
|
167
|
-
|
|
417
|
+
const envId = typeof loginState.envId === "string" ? loginState.envId : null;
|
|
418
|
+
const envCandidates = envId
|
|
419
|
+
? []
|
|
420
|
+
: await fetchAvailableEnvCandidates(cloudBaseOptions, server);
|
|
421
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
422
|
+
ok: true,
|
|
423
|
+
code: "AUTH_READY",
|
|
424
|
+
message: envId ? `认证成功,当前登录态 envId: ${envId}` : "认证成功",
|
|
425
|
+
auth_challenge: authChallenge(),
|
|
426
|
+
env_candidates: envCandidates,
|
|
427
|
+
next_step: envId
|
|
428
|
+
? (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
429
|
+
suggestedArgs: { action: "status" },
|
|
430
|
+
})
|
|
431
|
+
: buildSetEnvNextStep(envCandidates),
|
|
432
|
+
});
|
|
168
433
|
}
|
|
434
|
+
if (action === "set_env") {
|
|
435
|
+
const loginState = await (0, auth_js_1.peekLoginState)();
|
|
436
|
+
if (!loginState) {
|
|
437
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
438
|
+
ok: false,
|
|
439
|
+
code: "AUTH_REQUIRED",
|
|
440
|
+
message: isCodeBuddyIde(server)
|
|
441
|
+
? "当前未登录。CodeBuddy 暂不支持在 tool 内发起认证,请在外部完成认证后再次调用 auth(action=\"status\")。"
|
|
442
|
+
: "当前未登录,请先执行 auth(action=\"start_auth\")。",
|
|
443
|
+
next_step: buildAuthRequiredNextStep(server),
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
const envCandidates = await fetchAvailableEnvCandidates(cloudBaseOptions, server);
|
|
447
|
+
if (!envId) {
|
|
448
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
449
|
+
ok: false,
|
|
450
|
+
code: "INVALID_ARGS",
|
|
451
|
+
message: "action=set_env 时必须提供 envId",
|
|
452
|
+
env_candidates: envCandidates,
|
|
453
|
+
next_step: buildSetEnvNextStep(envCandidates),
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
const target = envCandidates.find((item) => item.envId === envId);
|
|
457
|
+
if (envCandidates.length > 0 && !target) {
|
|
458
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
459
|
+
ok: false,
|
|
460
|
+
code: "INVALID_ARGS",
|
|
461
|
+
message: `未找到环境: ${envId}`,
|
|
462
|
+
env_candidates: envCandidates,
|
|
463
|
+
next_step: buildSetEnvNextStep(envCandidates),
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
await cloudbase_manager_js_1.envManager.setEnvId(envId);
|
|
467
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
468
|
+
ok: true,
|
|
469
|
+
code: "ENV_READY",
|
|
470
|
+
message: `环境设置成功,当前环境: ${envId}`,
|
|
471
|
+
current_env_id: envId,
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
if (action === "logout") {
|
|
475
|
+
if (confirm !== "yes") {
|
|
476
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
477
|
+
ok: false,
|
|
478
|
+
code: "INVALID_ARGS",
|
|
479
|
+
message: "action=logout 时必须传 confirm=\"yes\"",
|
|
480
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("logout", {
|
|
481
|
+
suggestedArgs: { action: "logout", confirm: "yes" },
|
|
482
|
+
}),
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
await (0, auth_js_1.logout)();
|
|
486
|
+
(0, cloudbase_manager_js_1.resetCloudBaseManagerCache)();
|
|
487
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
488
|
+
ok: true,
|
|
489
|
+
code: "LOGGED_OUT",
|
|
490
|
+
message: "✅ 已退出登录",
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
494
|
+
ok: false,
|
|
495
|
+
code: "NOT_SUPPORTED",
|
|
496
|
+
message: `不支持的 auth action: ${action}`,
|
|
497
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
498
|
+
suggestedArgs: { action: "status" },
|
|
499
|
+
}),
|
|
500
|
+
});
|
|
169
501
|
}
|
|
170
502
|
catch (error) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
// logout - 退出云开发环境
|
|
182
|
-
server.registerTool?.("logout", {
|
|
183
|
-
title: "退出登录",
|
|
184
|
-
description: "退出云开发环境",
|
|
185
|
-
inputSchema: {
|
|
186
|
-
confirm: zod_1.z.literal("yes").describe("确认操作,默认传 yes"),
|
|
187
|
-
},
|
|
188
|
-
annotations: {
|
|
189
|
-
readOnlyHint: false,
|
|
190
|
-
destructiveHint: false,
|
|
191
|
-
idempotentHint: true,
|
|
192
|
-
openWorldHint: false,
|
|
193
|
-
category: "env",
|
|
194
|
-
},
|
|
195
|
-
}, async () => {
|
|
196
|
-
try {
|
|
197
|
-
// 登出账户
|
|
198
|
-
await (0, auth_js_1.logout)();
|
|
199
|
-
// 清理环境ID缓存
|
|
200
|
-
(0, cloudbase_manager_js_1.resetCloudBaseManagerCache)();
|
|
201
|
-
return {
|
|
202
|
-
content: [
|
|
203
|
-
{
|
|
204
|
-
type: "text",
|
|
205
|
-
text: "✅ 已退出登录",
|
|
206
|
-
},
|
|
207
|
-
],
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
catch (error) {
|
|
211
|
-
return {
|
|
212
|
-
content: [
|
|
213
|
-
{
|
|
214
|
-
type: "text",
|
|
215
|
-
text: `退出失败: ${error instanceof Error ? error.message : String(error)}`,
|
|
216
|
-
},
|
|
217
|
-
],
|
|
218
|
-
};
|
|
503
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
504
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
505
|
+
ok: false,
|
|
506
|
+
code: "INTERNAL_ERROR",
|
|
507
|
+
message: `auth 执行失败: ${message}`,
|
|
508
|
+
auth_challenge: authChallenge(),
|
|
509
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
510
|
+
suggestedArgs: { action: "status" },
|
|
511
|
+
}),
|
|
512
|
+
});
|
|
219
513
|
}
|
|
220
514
|
});
|
|
221
515
|
// envQuery - 环境查询(合并 listEnvs + getEnvInfo + getEnvAuthDomains + getWebsiteConfig)
|
|
@@ -289,6 +583,10 @@ function registerEnvTools(server) {
|
|
|
289
583
|
}
|
|
290
584
|
}
|
|
291
585
|
catch (fallbackError) {
|
|
586
|
+
const toolPayloadResult = (0, tool_result_js_1.toolPayloadErrorToResult)(fallbackError);
|
|
587
|
+
if (toolPayloadResult) {
|
|
588
|
+
return toolPayloadResult;
|
|
589
|
+
}
|
|
292
590
|
(0, logger_js_1.debug)("降级到 listEnvs() 也失败:", fallbackError instanceof Error ? fallbackError : new Error(String(fallbackError)));
|
|
293
591
|
return {
|
|
294
592
|
content: [
|
|
@@ -352,6 +650,10 @@ function registerEnvTools(server) {
|
|
|
352
650
|
};
|
|
353
651
|
}
|
|
354
652
|
catch (error) {
|
|
653
|
+
const toolPayloadResult = (0, tool_result_js_1.toolPayloadErrorToResult)(error);
|
|
654
|
+
if (toolPayloadResult) {
|
|
655
|
+
return toolPayloadResult;
|
|
656
|
+
}
|
|
355
657
|
return {
|
|
356
658
|
content: [
|
|
357
659
|
{
|
|
@@ -405,6 +707,10 @@ function registerEnvTools(server) {
|
|
|
405
707
|
};
|
|
406
708
|
}
|
|
407
709
|
catch (error) {
|
|
710
|
+
const toolPayloadResult = (0, tool_result_js_1.toolPayloadErrorToResult)(error);
|
|
711
|
+
if (toolPayloadResult) {
|
|
712
|
+
return toolPayloadResult;
|
|
713
|
+
}
|
|
408
714
|
return {
|
|
409
715
|
content: [
|
|
410
716
|
{
|
|
@@ -475,6 +781,30 @@ function registerCapiTools(server) {
|
|
|
475
781
|
throw new Error(`Service ${service} is not allowed. Allowed services: ${ALLOWED_SERVICES.join(", ")}`);
|
|
476
782
|
}
|
|
477
783
|
const cloudbase = await getManager();
|
|
784
|
+
if (['1', 'true'].includes(process.env.CLOUDBASE_EVALUATE_MODE ?? '')) {
|
|
785
|
+
if (service === 'lowcode') {
|
|
786
|
+
throw new Error(`${service}/${action} Cloud API is not exposed or does not exist. Please use another API.`);
|
|
787
|
+
}
|
|
788
|
+
if (service === 'tcb') {
|
|
789
|
+
const tcbCapiForbidList = [
|
|
790
|
+
// 未明确对外的云API
|
|
791
|
+
'DescribeStorageACL', 'ModifyStorageACL', 'DescribeSecurityRule',
|
|
792
|
+
// 要下线的云API
|
|
793
|
+
"ListTables",
|
|
794
|
+
"DescribeCloudBaseGWAPI",
|
|
795
|
+
"DescribeCloudBaseGWService",
|
|
796
|
+
"CreateCloudBaseGWAPI",
|
|
797
|
+
"DeleteCloudBaseGWAPI",
|
|
798
|
+
"ModifyCloudBaseGWAPI",
|
|
799
|
+
"DeleteCloudBaseGWDomain",
|
|
800
|
+
"BindCloudBaseGWDomain",
|
|
801
|
+
"BindCloudBaseAccessDomain"
|
|
802
|
+
];
|
|
803
|
+
if (tcbCapiForbidList.includes(action)) {
|
|
804
|
+
throw new Error(`${service}/${action} Cloud API is not exposed or does not exist. Please use another API.`);
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
}
|
|
478
808
|
const result = await cloudbase.commonService(service).call({
|
|
479
809
|
Action: action,
|
|
480
810
|
Param: params ?? {},
|
|
@@ -515,6 +845,7 @@ const cloudbase_manager_js_1 = __webpack_require__(3431);
|
|
|
515
845
|
const cloud_mode_js_1 = __webpack_require__(9684);
|
|
516
846
|
const logger_js_1 = __webpack_require__(3039);
|
|
517
847
|
const telemetry_js_1 = __webpack_require__(5880);
|
|
848
|
+
const tool_result_js_1 = __webpack_require__(9835);
|
|
518
849
|
/**
|
|
519
850
|
* 生成 GitHub Issue 创建链接
|
|
520
851
|
* @param toolName 工具名称
|
|
@@ -562,7 +893,7 @@ ${envIdSection}
|
|
|
562
893
|
## 环境信息
|
|
563
894
|
- 操作系统: ${os_1.default.type()} ${os_1.default.release()}
|
|
564
895
|
- Node.js版本: ${process.version}
|
|
565
|
-
- MCP 版本:${process.env.npm_package_version || "2.
|
|
896
|
+
- MCP 版本:${process.env.npm_package_version || "2.14.0" || 0}
|
|
566
897
|
- 系统架构: ${os_1.default.arch()}
|
|
567
898
|
- 时间: ${new Date().toISOString()}
|
|
568
899
|
- 请求ID: ${requestId}
|
|
@@ -627,6 +958,11 @@ function createWrappedHandler(name, handler, server) {
|
|
|
627
958
|
if (!isTestEnvironment) {
|
|
628
959
|
server.logger?.({ type: 'errorToolCall', toolName: name, args: sanitizeArgs(args), message: errorMessage, duration: Date.now() - startTime });
|
|
629
960
|
}
|
|
961
|
+
// Preserve structured tool guidance such as next_step.
|
|
962
|
+
// These errors are expected control flow and should be serialized by the outer server wrapper.
|
|
963
|
+
if ((0, tool_result_js_1.isToolPayloadError)(error)) {
|
|
964
|
+
throw error;
|
|
965
|
+
}
|
|
630
966
|
// In tests, avoid any extra work that may block (envId lookup, issue link generation, etc.)
|
|
631
967
|
if (isTestEnvironment) {
|
|
632
968
|
throw error instanceof Error ? error : new Error(String(error));
|
|
@@ -773,6 +1109,7 @@ const security_rule_js_1 = __webpack_require__(7862);
|
|
|
773
1109
|
const cloud_mode_js_1 = __webpack_require__(9684);
|
|
774
1110
|
const logger_js_1 = __webpack_require__(3039);
|
|
775
1111
|
const tencet_cloud_js_1 = __webpack_require__(5018);
|
|
1112
|
+
const tool_result_js_1 = __webpack_require__(9835);
|
|
776
1113
|
const tool_wrapper_js_1 = __webpack_require__(1363);
|
|
777
1114
|
// 默认插件列表
|
|
778
1115
|
const DEFAULT_PLUGINS = [
|
|
@@ -887,6 +1224,18 @@ async function createCloudBaseMcpServer(options) {
|
|
|
887
1224
|
...(ide === "CodeBuddy" ? { logging: {} } : {}),
|
|
888
1225
|
},
|
|
889
1226
|
});
|
|
1227
|
+
const originalRegisterTool = server.registerTool.bind(server);
|
|
1228
|
+
server.registerTool = ((name, meta, handler) => originalRegisterTool(name, meta, async (args) => {
|
|
1229
|
+
try {
|
|
1230
|
+
return await handler(args);
|
|
1231
|
+
}
|
|
1232
|
+
catch (error) {
|
|
1233
|
+
if ((0, tool_result_js_1.isToolPayloadError)(error)) {
|
|
1234
|
+
return (0, tool_result_js_1.buildJsonToolResult)(error.payload);
|
|
1235
|
+
}
|
|
1236
|
+
throw error;
|
|
1237
|
+
}
|
|
1238
|
+
}));
|
|
890
1239
|
// Only set logging handler if logging capability is declared
|
|
891
1240
|
if (ide === "CodeBuddy") {
|
|
892
1241
|
server.server.setRequestHandler(types_js_1.SetLevelRequestSchema, (request, extra) => {
|
|
@@ -4076,6 +4425,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4076
4425
|
};
|
|
4077
4426
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
4078
4427
|
exports.envManager = void 0;
|
|
4428
|
+
exports.listAvailableEnvCandidates = listAvailableEnvCandidates;
|
|
4079
4429
|
exports.getEnvId = getEnvId;
|
|
4080
4430
|
exports.resetCloudBaseManagerCache = resetCloudBaseManagerCache;
|
|
4081
4431
|
exports.getCachedEnvId = getCachedEnvId;
|
|
@@ -4085,9 +4435,134 @@ exports.extractRequestId = extractRequestId;
|
|
|
4085
4435
|
exports.logCloudBaseResult = logCloudBaseResult;
|
|
4086
4436
|
const manager_node_1 = __importDefault(__webpack_require__(6665));
|
|
4087
4437
|
const auth_js_1 = __webpack_require__(7291);
|
|
4088
|
-
const interactive_js_1 = __webpack_require__(3461);
|
|
4089
4438
|
const logger_js_1 = __webpack_require__(3039);
|
|
4090
|
-
const
|
|
4439
|
+
const tool_result_js_1 = __webpack_require__(9835);
|
|
4440
|
+
// Timeout for envId auto-resolution flow.
|
|
4441
|
+
// 10 minutes (600 seconds) - matches InteractiveServer timeout
|
|
4442
|
+
const ENV_ID_TIMEOUT = 600000;
|
|
4443
|
+
function toEnvCandidates(envList) {
|
|
4444
|
+
if (!Array.isArray(envList)) {
|
|
4445
|
+
return [];
|
|
4446
|
+
}
|
|
4447
|
+
return envList
|
|
4448
|
+
.filter((item) => item?.EnvId)
|
|
4449
|
+
.map((item) => ({
|
|
4450
|
+
envId: item.EnvId,
|
|
4451
|
+
alias: item.Alias,
|
|
4452
|
+
region: item.Region,
|
|
4453
|
+
status: item.Status,
|
|
4454
|
+
env_type: item.EnvType,
|
|
4455
|
+
}));
|
|
4456
|
+
}
|
|
4457
|
+
function createManagerFromLoginState(loginState, region) {
|
|
4458
|
+
return new manager_node_1.default({
|
|
4459
|
+
secretId: loginState.secretId,
|
|
4460
|
+
secretKey: loginState.secretKey,
|
|
4461
|
+
envId: loginState.envId,
|
|
4462
|
+
token: loginState.token,
|
|
4463
|
+
proxy: process.env.http_proxy,
|
|
4464
|
+
region,
|
|
4465
|
+
});
|
|
4466
|
+
}
|
|
4467
|
+
async function listAvailableEnvCandidates(options) {
|
|
4468
|
+
const { cloudBaseOptions, loginState: providedLoginState } = options ?? {};
|
|
4469
|
+
if (cloudBaseOptions?.envId) {
|
|
4470
|
+
return [{
|
|
4471
|
+
envId: cloudBaseOptions.envId,
|
|
4472
|
+
}];
|
|
4473
|
+
}
|
|
4474
|
+
let cloudbase;
|
|
4475
|
+
if (cloudBaseOptions?.secretId && cloudBaseOptions?.secretKey) {
|
|
4476
|
+
cloudbase = createCloudBaseManagerWithOptions(cloudBaseOptions);
|
|
4477
|
+
}
|
|
4478
|
+
else {
|
|
4479
|
+
const loginState = providedLoginState ?? await (0, auth_js_1.peekLoginState)();
|
|
4480
|
+
if (!loginState?.secretId || !loginState?.secretKey) {
|
|
4481
|
+
return [];
|
|
4482
|
+
}
|
|
4483
|
+
const region = cloudBaseOptions?.region ?? process.env.TCB_REGION ?? undefined;
|
|
4484
|
+
cloudbase = createManagerFromLoginState(loginState, region);
|
|
4485
|
+
}
|
|
4486
|
+
try {
|
|
4487
|
+
const result = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
4488
|
+
Action: "DescribeEnvs",
|
|
4489
|
+
Param: {
|
|
4490
|
+
EnvTypes: ["weda", "baas"],
|
|
4491
|
+
IsVisible: false,
|
|
4492
|
+
Channels: ["dcloud", "iotenable", "tem", "scene_module"],
|
|
4493
|
+
},
|
|
4494
|
+
});
|
|
4495
|
+
const envList = result?.EnvList || result?.Data?.EnvList || [];
|
|
4496
|
+
return toEnvCandidates(envList);
|
|
4497
|
+
}
|
|
4498
|
+
catch {
|
|
4499
|
+
try {
|
|
4500
|
+
const fallback = await cloudbase.env.listEnvs();
|
|
4501
|
+
return toEnvCandidates(fallback?.EnvList || []);
|
|
4502
|
+
}
|
|
4503
|
+
catch {
|
|
4504
|
+
return [];
|
|
4505
|
+
}
|
|
4506
|
+
}
|
|
4507
|
+
}
|
|
4508
|
+
function throwAuthRequiredError() {
|
|
4509
|
+
(0, tool_result_js_1.throwToolPayloadError)({
|
|
4510
|
+
ok: false,
|
|
4511
|
+
code: "AUTH_REQUIRED",
|
|
4512
|
+
message: "当前未登录,请先调用 auth 工具完成认证。",
|
|
4513
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
|
|
4514
|
+
suggestedArgs: {
|
|
4515
|
+
action: "start_auth",
|
|
4516
|
+
authMode: "device",
|
|
4517
|
+
},
|
|
4518
|
+
}),
|
|
4519
|
+
});
|
|
4520
|
+
}
|
|
4521
|
+
async function throwPendingAuthError() {
|
|
4522
|
+
const authState = await (0, auth_js_1.getAuthProgressState)();
|
|
4523
|
+
(0, tool_result_js_1.throwToolPayloadError)({
|
|
4524
|
+
ok: false,
|
|
4525
|
+
code: "AUTH_PENDING",
|
|
4526
|
+
message: authState.lastError || "设备码授权进行中,请先完成登录后再重试当前工具。",
|
|
4527
|
+
auth_challenge: authState.authChallenge
|
|
4528
|
+
? {
|
|
4529
|
+
user_code: authState.authChallenge.user_code,
|
|
4530
|
+
verification_uri: authState.authChallenge.verification_uri,
|
|
4531
|
+
expires_in: authState.authChallenge.expires_in,
|
|
4532
|
+
}
|
|
4533
|
+
: undefined,
|
|
4534
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
4535
|
+
suggestedArgs: {
|
|
4536
|
+
action: "status",
|
|
4537
|
+
},
|
|
4538
|
+
}),
|
|
4539
|
+
});
|
|
4540
|
+
}
|
|
4541
|
+
async function throwEnvRequiredError(options) {
|
|
4542
|
+
const envCandidates = options?.envCandidates ?? (await listAvailableEnvCandidates(options));
|
|
4543
|
+
const singleEnvId = envCandidates.length === 1 ? envCandidates[0].envId : undefined;
|
|
4544
|
+
(0, tool_result_js_1.throwToolPayloadError)({
|
|
4545
|
+
ok: false,
|
|
4546
|
+
code: "ENV_REQUIRED",
|
|
4547
|
+
message: envCandidates.length === 0
|
|
4548
|
+
? "当前已登录,但还没有可用环境,请先调用 auth 工具完成环境选择或创建环境。"
|
|
4549
|
+
: envCandidates.length === 1
|
|
4550
|
+
? `当前已登录,但尚未绑定环境。可直接选择环境 ${singleEnvId}。`
|
|
4551
|
+
: "当前已登录,但尚未绑定环境,请先调用 auth 工具选择环境。",
|
|
4552
|
+
env_candidates: envCandidates,
|
|
4553
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("set_env", {
|
|
4554
|
+
requiredParams: singleEnvId ? undefined : ["envId"],
|
|
4555
|
+
suggestedArgs: singleEnvId
|
|
4556
|
+
? {
|
|
4557
|
+
action: "set_env",
|
|
4558
|
+
envId: singleEnvId,
|
|
4559
|
+
}
|
|
4560
|
+
: {
|
|
4561
|
+
action: "set_env",
|
|
4562
|
+
},
|
|
4563
|
+
}),
|
|
4564
|
+
});
|
|
4565
|
+
}
|
|
4091
4566
|
// 统一的环境ID管理类
|
|
4092
4567
|
class EnvironmentManager {
|
|
4093
4568
|
cachedEnvId = null;
|
|
@@ -4099,7 +4574,7 @@ class EnvironmentManager {
|
|
|
4099
4574
|
delete process.env.CLOUDBASE_ENV_ID;
|
|
4100
4575
|
}
|
|
4101
4576
|
// 获取环境ID的核心逻辑
|
|
4102
|
-
async getEnvId(
|
|
4577
|
+
async getEnvId() {
|
|
4103
4578
|
// 1. 优先使用内存缓存
|
|
4104
4579
|
if (this.cachedEnvId) {
|
|
4105
4580
|
(0, logger_js_1.debug)('使用内存缓存的环境ID:', { envId: this.cachedEnvId });
|
|
@@ -4109,17 +4584,10 @@ class EnvironmentManager {
|
|
|
4109
4584
|
if (this.envIdPromise) {
|
|
4110
4585
|
return this.envIdPromise;
|
|
4111
4586
|
}
|
|
4112
|
-
// 3. 开始获取环境ID
|
|
4113
|
-
this.envIdPromise = this._fetchEnvId(
|
|
4114
|
-
// 增加超时保护
|
|
4115
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
4116
|
-
const id = setTimeout(() => {
|
|
4117
|
-
clearTimeout(id);
|
|
4118
|
-
reject(new Error(`EnvId 获取超时(${ENV_ID_TIMEOUT / 1000}秒)`));
|
|
4119
|
-
}, ENV_ID_TIMEOUT);
|
|
4120
|
-
});
|
|
4587
|
+
// 3. 开始获取环境ID
|
|
4588
|
+
this.envIdPromise = this._fetchEnvId();
|
|
4121
4589
|
try {
|
|
4122
|
-
const result = await
|
|
4590
|
+
const result = await this.envIdPromise;
|
|
4123
4591
|
return result;
|
|
4124
4592
|
}
|
|
4125
4593
|
catch (err) {
|
|
@@ -4127,7 +4595,7 @@ class EnvironmentManager {
|
|
|
4127
4595
|
throw err;
|
|
4128
4596
|
}
|
|
4129
4597
|
}
|
|
4130
|
-
async _fetchEnvId(
|
|
4598
|
+
async _fetchEnvId() {
|
|
4131
4599
|
try {
|
|
4132
4600
|
// 1. 检查进程环境变量
|
|
4133
4601
|
if (process.env.CLOUDBASE_ENV_ID) {
|
|
@@ -4135,48 +4603,23 @@ class EnvironmentManager {
|
|
|
4135
4603
|
this.cachedEnvId = process.env.CLOUDBASE_ENV_ID;
|
|
4136
4604
|
return this.cachedEnvId;
|
|
4137
4605
|
}
|
|
4138
|
-
// 2.
|
|
4139
|
-
(0,
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
// Re-throw with enhanced context
|
|
4153
|
-
const enhancedError = new Error(`自动设置环境ID失败: ${errorObj.message}`);
|
|
4154
|
-
enhancedError.originalError = errorObj;
|
|
4155
|
-
enhancedError.failureInfo = {
|
|
4156
|
-
reason: 'unknown_error',
|
|
4157
|
-
error: errorObj.message,
|
|
4158
|
-
errorCode: 'SETUP_EXCEPTION',
|
|
4159
|
-
};
|
|
4160
|
-
throw enhancedError;
|
|
4161
|
-
}
|
|
4162
|
-
const autoEnvId = setupResult.selectedEnvId;
|
|
4163
|
-
if (!autoEnvId) {
|
|
4164
|
-
// Build detailed error message from failure info
|
|
4165
|
-
const errorMessage = this._buildDetailedErrorMessage(setupResult.failureInfo);
|
|
4166
|
-
(0, logger_js_1.error)('自动设置环境ID失败:', {
|
|
4167
|
-
reason: setupResult.failureInfo?.reason,
|
|
4168
|
-
errorCode: setupResult.failureInfo?.errorCode,
|
|
4169
|
-
error: setupResult.failureInfo?.error,
|
|
4170
|
-
details: setupResult.failureInfo?.details,
|
|
4171
|
-
});
|
|
4172
|
-
// Create error with detailed information
|
|
4173
|
-
const detailedError = new Error(errorMessage);
|
|
4174
|
-
detailedError.failureInfo = setupResult.failureInfo;
|
|
4175
|
-
throw detailedError;
|
|
4606
|
+
// 2. 如果登录态里已有 envId,直接复用
|
|
4607
|
+
const loginState = await (0, auth_js_1.peekLoginState)();
|
|
4608
|
+
if (typeof loginState?.envId === 'string' && loginState.envId.length > 0) {
|
|
4609
|
+
(0, logger_js_1.debug)('使用登录态中的环境ID:', { envId: loginState.envId });
|
|
4610
|
+
this._setCachedEnvId(loginState.envId);
|
|
4611
|
+
return loginState.envId;
|
|
4612
|
+
}
|
|
4613
|
+
// 3. 单环境自动绑定;多环境时返回结构化引导,不再触发交互弹窗
|
|
4614
|
+
const envCandidates = await listAvailableEnvCandidates({ loginState });
|
|
4615
|
+
if (envCandidates.length === 1) {
|
|
4616
|
+
const singleEnvId = envCandidates[0].envId;
|
|
4617
|
+
(0, logger_js_1.debug)('自动绑定唯一环境:', { envId: singleEnvId });
|
|
4618
|
+
this._setCachedEnvId(singleEnvId);
|
|
4619
|
+
return singleEnvId;
|
|
4176
4620
|
}
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
return autoEnvId;
|
|
4621
|
+
await throwEnvRequiredError({ loginState, envCandidates });
|
|
4622
|
+
throw new Error('Unreachable after throwEnvRequiredError');
|
|
4180
4623
|
}
|
|
4181
4624
|
catch (err) {
|
|
4182
4625
|
// Log the error with full context before re-throwing
|
|
@@ -4200,65 +4643,6 @@ class EnvironmentManager {
|
|
|
4200
4643
|
process.env.CLOUDBASE_ENV_ID = envId;
|
|
4201
4644
|
(0, logger_js_1.debug)('已更新环境ID缓存:', { envId });
|
|
4202
4645
|
}
|
|
4203
|
-
// Build detailed error message from failure info
|
|
4204
|
-
_buildDetailedErrorMessage(failureInfo) {
|
|
4205
|
-
if (!failureInfo) {
|
|
4206
|
-
return "CloudBase Environment ID not found after auto setup. Please set CLOUDBASE_ENV_ID or run setupEnvironmentId tool.";
|
|
4207
|
-
}
|
|
4208
|
-
const { reason, error: errorMsg, errorCode, helpUrl, details } = failureInfo;
|
|
4209
|
-
let message = "CloudBase Environment ID not found after auto setup.\n\n";
|
|
4210
|
-
message += `原因: ${this._getReasonDescription(reason)}\n`;
|
|
4211
|
-
if (errorMsg) {
|
|
4212
|
-
message += `错误: ${errorMsg}\n`;
|
|
4213
|
-
}
|
|
4214
|
-
if (errorCode) {
|
|
4215
|
-
message += `错误代码: ${errorCode}\n`;
|
|
4216
|
-
}
|
|
4217
|
-
// Add specific details based on failure reason
|
|
4218
|
-
if (reason === 'tcb_init_failed' && details?.initTcbError) {
|
|
4219
|
-
const initError = details.initTcbError;
|
|
4220
|
-
if (initError.needRealNameAuth) {
|
|
4221
|
-
message += "\n需要完成实名认证才能使用 CloudBase 服务。\n";
|
|
4222
|
-
}
|
|
4223
|
-
if (initError.needCamAuth) {
|
|
4224
|
-
message += "\n需要 CAM 权限才能使用 CloudBase 服务。\n";
|
|
4225
|
-
}
|
|
4226
|
-
}
|
|
4227
|
-
if (reason === 'env_creation_failed' && details?.createEnvError) {
|
|
4228
|
-
const createError = details.createEnvError;
|
|
4229
|
-
message += `\n环境创建失败: ${createError.message || '未知错误'}\n`;
|
|
4230
|
-
}
|
|
4231
|
-
if (reason === 'env_query_failed' && details?.queryEnvError) {
|
|
4232
|
-
message += `\n环境查询失败: ${details.queryEnvError}\n`;
|
|
4233
|
-
}
|
|
4234
|
-
if (reason === 'timeout' && details?.timeoutDuration) {
|
|
4235
|
-
message += `\n超时时间: ${details.timeoutDuration / 1000} 秒\n`;
|
|
4236
|
-
message += "提示: 请确保浏览器窗口已打开,并在规定时间内完成环境选择。\n";
|
|
4237
|
-
}
|
|
4238
|
-
message += "\n解决方案:\n";
|
|
4239
|
-
message += "1. 手动设置环境ID: 设置环境变量 CLOUDBASE_ENV_ID\n";
|
|
4240
|
-
message += "2. 使用工具设置: 运行 setupEnvironmentId 工具\n";
|
|
4241
|
-
if (helpUrl) {
|
|
4242
|
-
message += `3. 查看帮助文档: ${helpUrl}\n`;
|
|
4243
|
-
}
|
|
4244
|
-
else {
|
|
4245
|
-
message += "3. 查看帮助文档: https://docs.cloudbase.net/cli-v1/env\n";
|
|
4246
|
-
}
|
|
4247
|
-
return message;
|
|
4248
|
-
}
|
|
4249
|
-
_getReasonDescription(reason) {
|
|
4250
|
-
const descriptions = {
|
|
4251
|
-
'timeout': '环境选择超时',
|
|
4252
|
-
'cancelled': '用户取消了环境选择',
|
|
4253
|
-
'no_environments': '没有可用环境',
|
|
4254
|
-
'login_failed': '登录失败',
|
|
4255
|
-
'tcb_init_failed': 'CloudBase 服务初始化失败',
|
|
4256
|
-
'env_query_failed': '环境列表查询失败',
|
|
4257
|
-
'env_creation_failed': '环境创建失败',
|
|
4258
|
-
'unknown_error': '未知错误',
|
|
4259
|
-
};
|
|
4260
|
-
return descriptions[reason] || '未知原因';
|
|
4261
|
-
}
|
|
4262
4646
|
// 手动设置环境ID(用于外部调用)
|
|
4263
4647
|
async setEnvId(envId) {
|
|
4264
4648
|
this._setCachedEnvId(envId);
|
|
@@ -4279,6 +4663,16 @@ async function getEnvId(cloudBaseOptions) {
|
|
|
4279
4663
|
(0, logger_js_1.debug)('使用传入的 envId:', { envId: cloudBaseOptions.envId });
|
|
4280
4664
|
return cloudBaseOptions.envId;
|
|
4281
4665
|
}
|
|
4666
|
+
const cachedEnvId = envManager.getCachedEnvId() || process.env.CLOUDBASE_ENV_ID;
|
|
4667
|
+
if (cachedEnvId) {
|
|
4668
|
+
(0, logger_js_1.debug)('使用缓存中的 envId:', { envId: cachedEnvId });
|
|
4669
|
+
return cachedEnvId;
|
|
4670
|
+
}
|
|
4671
|
+
const loginState = await (0, auth_js_1.peekLoginState)();
|
|
4672
|
+
if (typeof loginState?.envId === 'string' && loginState.envId.length > 0) {
|
|
4673
|
+
(0, logger_js_1.debug)('使用登录态中的 envId:', { envId: loginState.envId });
|
|
4674
|
+
return loginState.envId;
|
|
4675
|
+
}
|
|
4282
4676
|
// 否则使用默认逻辑
|
|
4283
4677
|
return envManager.getEnvId();
|
|
4284
4678
|
}
|
|
@@ -4294,37 +4688,89 @@ function getCachedEnvId() {
|
|
|
4294
4688
|
* 每次都实时获取最新的 token/secretId/secretKey
|
|
4295
4689
|
*/
|
|
4296
4690
|
async function getCloudBaseManager(options = {}) {
|
|
4297
|
-
const { requireEnvId = true, cloudBaseOptions,
|
|
4298
|
-
|
|
4299
|
-
|
|
4691
|
+
const { requireEnvId = true, cloudBaseOptions, authStrategy = 'fail_fast', } = options;
|
|
4692
|
+
const hasDirectCredentials = !!(cloudBaseOptions?.secretId && cloudBaseOptions?.secretKey);
|
|
4693
|
+
// 如果传入了完整凭据,优先使用显式 CloudBase 配置
|
|
4694
|
+
if (cloudBaseOptions && hasDirectCredentials) {
|
|
4695
|
+
let resolvedEnvId = cloudBaseOptions.envId;
|
|
4696
|
+
if (requireEnvId && !resolvedEnvId) {
|
|
4697
|
+
const envCandidates = await listAvailableEnvCandidates({ cloudBaseOptions });
|
|
4698
|
+
if (envCandidates.length === 1) {
|
|
4699
|
+
const singleEnvId = envCandidates[0].envId;
|
|
4700
|
+
cloudBaseOptions.envId = singleEnvId;
|
|
4701
|
+
resolvedEnvId = singleEnvId;
|
|
4702
|
+
(0, logger_js_1.debug)('自动绑定唯一环境(显式配置):', { envId: singleEnvId });
|
|
4703
|
+
}
|
|
4704
|
+
else if (authStrategy === 'fail_fast') {
|
|
4705
|
+
await throwEnvRequiredError({ cloudBaseOptions, envCandidates });
|
|
4706
|
+
}
|
|
4707
|
+
else {
|
|
4708
|
+
(0, tool_result_js_1.throwToolPayloadError)({
|
|
4709
|
+
ok: false,
|
|
4710
|
+
code: "ENV_REQUIRED",
|
|
4711
|
+
message: "当前显式 CloudBase 凭据未绑定环境,请补充 envId 或先选择环境。",
|
|
4712
|
+
env_candidates: envCandidates,
|
|
4713
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("set_env", {
|
|
4714
|
+
suggestedArgs: { action: "set_env" },
|
|
4715
|
+
requiredParams: ["envId"],
|
|
4716
|
+
}),
|
|
4717
|
+
});
|
|
4718
|
+
}
|
|
4719
|
+
}
|
|
4300
4720
|
(0, logger_js_1.debug)('使用传入的 CloudBase 配置');
|
|
4301
|
-
return createCloudBaseManagerWithOptions(
|
|
4721
|
+
return createCloudBaseManagerWithOptions({
|
|
4722
|
+
...cloudBaseOptions,
|
|
4723
|
+
envId: resolvedEnvId,
|
|
4724
|
+
});
|
|
4302
4725
|
}
|
|
4303
4726
|
try {
|
|
4304
4727
|
// Get region from environment variable for auth URL
|
|
4305
|
-
|
|
4306
|
-
const
|
|
4307
|
-
|
|
4728
|
+
const region = cloudBaseOptions?.region ?? process.env.TCB_REGION;
|
|
4729
|
+
const loginState = authStrategy === 'ensure'
|
|
4730
|
+
? await (0, auth_js_1.getLoginState)({ region })
|
|
4731
|
+
: await (0, auth_js_1.peekLoginState)();
|
|
4732
|
+
if (!loginState) {
|
|
4733
|
+
const authState = await (0, auth_js_1.getAuthProgressState)();
|
|
4734
|
+
if (authState.status === 'PENDING') {
|
|
4735
|
+
await throwPendingAuthError();
|
|
4736
|
+
}
|
|
4737
|
+
throwAuthRequiredError();
|
|
4738
|
+
}
|
|
4308
4739
|
const { envId: loginEnvId, secretId, secretKey, token } = loginState;
|
|
4309
|
-
let finalEnvId;
|
|
4740
|
+
let finalEnvId = cloudBaseOptions?.envId;
|
|
4310
4741
|
if (requireEnvId) {
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
(
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4742
|
+
if (!finalEnvId) {
|
|
4743
|
+
// Optimize: Check if envManager has cached envId first (fast path)
|
|
4744
|
+
// If cached, use it directly; otherwise check loginEnvId before calling getEnvId()
|
|
4745
|
+
// This avoids unnecessary async calls when we have a valid envId available
|
|
4746
|
+
const cachedEnvId = envManager.getCachedEnvId() || process.env.CLOUDBASE_ENV_ID;
|
|
4747
|
+
if (cachedEnvId) {
|
|
4748
|
+
(0, logger_js_1.debug)('使用 envManager 缓存的环境ID:', { cachedEnvId });
|
|
4749
|
+
finalEnvId = cachedEnvId;
|
|
4750
|
+
}
|
|
4751
|
+
else if (loginEnvId) {
|
|
4752
|
+
// If no cache but loginState has envId, use it directly
|
|
4753
|
+
(0, logger_js_1.debug)('使用 loginState 中的环境ID:', { loginEnvId });
|
|
4754
|
+
finalEnvId = loginEnvId;
|
|
4755
|
+
}
|
|
4756
|
+
else {
|
|
4757
|
+
if (authStrategy === 'fail_fast') {
|
|
4758
|
+
const envCandidates = await listAvailableEnvCandidates({ loginState });
|
|
4759
|
+
if (envCandidates.length === 1) {
|
|
4760
|
+
const singleEnvId = envCandidates[0].envId;
|
|
4761
|
+
await envManager.setEnvId(singleEnvId);
|
|
4762
|
+
finalEnvId = singleEnvId;
|
|
4763
|
+
(0, logger_js_1.debug)('自动绑定唯一环境:', { envId: singleEnvId });
|
|
4764
|
+
}
|
|
4765
|
+
else {
|
|
4766
|
+
await throwEnvRequiredError({ loginState, envCandidates });
|
|
4767
|
+
}
|
|
4768
|
+
}
|
|
4769
|
+
else {
|
|
4770
|
+
// ensure 模式下也保持非交互:单环境自动绑定,多环境返回 ENV_REQUIRED
|
|
4771
|
+
finalEnvId = await envManager.getEnvId();
|
|
4772
|
+
}
|
|
4773
|
+
}
|
|
4328
4774
|
}
|
|
4329
4775
|
}
|
|
4330
4776
|
// envId priority: envManager.cachedEnvId > envManager.getEnvId() > loginState.envId > undefined
|
|
@@ -4561,6 +5007,7 @@ async function _promptAndSetEnvironmentId(autoSelectSingle, options) {
|
|
|
4561
5007
|
hasServerServer: !!server?.server,
|
|
4562
5008
|
hasServerIde: !!server?.ide,
|
|
4563
5009
|
ignoreEnvVars: options?.ignoreEnvVars,
|
|
5010
|
+
authMode: options?.authMode,
|
|
4564
5011
|
optionsKeys: options ? Object.keys(options).join(', ') : 'null',
|
|
4565
5012
|
});
|
|
4566
5013
|
if (!server) {
|
|
@@ -4577,6 +5024,9 @@ async function _promptAndSetEnvironmentId(autoSelectSingle, options) {
|
|
|
4577
5024
|
fromCloudBaseLoginPage: options?.loginFromCloudBaseLoginPage,
|
|
4578
5025
|
ignoreEnvVars: options?.ignoreEnvVars,
|
|
4579
5026
|
region,
|
|
5027
|
+
authMode: options?.authMode,
|
|
5028
|
+
clientId: options?.clientId,
|
|
5029
|
+
onDeviceCode: options?.onDeviceCode,
|
|
4580
5030
|
});
|
|
4581
5031
|
(0, logger_js_1.debug)("[interactive] Login state:", {
|
|
4582
5032
|
hasLoginState: !!loginState,
|
|
@@ -7288,6 +7738,15 @@ async function registerRagTools(server) {
|
|
|
7288
7738
|
],
|
|
7289
7739
|
};
|
|
7290
7740
|
}
|
|
7741
|
+
// 向量检索模式下必须提供 id 和 content,避免后端报「知识库名称不能为空」
|
|
7742
|
+
if (mode === "vector") {
|
|
7743
|
+
if (!id) {
|
|
7744
|
+
throw new Error("知识库名称不能为空: please provide `id` when mode=vector (cloudbase / scf / miniprogram).");
|
|
7745
|
+
}
|
|
7746
|
+
if (!content || !content.trim()) {
|
|
7747
|
+
throw new Error("检索内容不能为空: please provide non-empty `content` when mode=vector.");
|
|
7748
|
+
}
|
|
7749
|
+
}
|
|
7291
7750
|
// 枚举到后端 id 映射
|
|
7292
7751
|
const backendId = KnowledgeBaseIdMap[id] || id;
|
|
7293
7752
|
const signInRes = await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/auth/v1/signin/anonymously", {
|
|
@@ -8692,7 +9151,7 @@ class TelemetryReporter {
|
|
|
8692
9151
|
const nodeVersion = process.version; // Node.js版本
|
|
8693
9152
|
const arch = os_1.default.arch(); // 系统架构
|
|
8694
9153
|
// 从构建时注入的版本号获取MCP版本信息
|
|
8695
|
-
const mcpVersion = process.env.npm_package_version || "2.
|
|
9154
|
+
const mcpVersion = process.env.npm_package_version || "2.14.0" || 0;
|
|
8696
9155
|
return {
|
|
8697
9156
|
userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
|
|
8698
9157
|
deviceId: this.deviceId,
|
|
@@ -9004,7 +9463,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
9004
9463
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9005
9464
|
};
|
|
9006
9465
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
9007
|
-
exports.TRIGGER_CONFIG_EXAMPLES = exports.SUPPORTED_TRIGGER_TYPES = exports.DEFAULT_NODEJS_RUNTIME = exports.SUPPORTED_NODEJS_RUNTIMES = void 0;
|
|
9466
|
+
exports.WRITE_FUNCTION_LAYER_ACTIONS = exports.READ_FUNCTION_LAYER_ACTIONS = exports.TRIGGER_CONFIG_EXAMPLES = exports.SUPPORTED_TRIGGER_TYPES = exports.DEFAULT_NODEJS_RUNTIME = exports.SUPPORTED_NODEJS_RUNTIMES = void 0;
|
|
9008
9467
|
exports.registerFunctionTools = registerFunctionTools;
|
|
9009
9468
|
const zod_1 = __webpack_require__(2971);
|
|
9010
9469
|
const cloudbase_manager_js_1 = __webpack_require__(3431);
|
|
@@ -9037,6 +9496,41 @@ exports.TRIGGER_CONFIG_EXAMPLES = {
|
|
|
9037
9496
|
],
|
|
9038
9497
|
},
|
|
9039
9498
|
};
|
|
9499
|
+
exports.READ_FUNCTION_LAYER_ACTIONS = [
|
|
9500
|
+
"listLayers",
|
|
9501
|
+
"listLayerVersions",
|
|
9502
|
+
"getLayerVersion",
|
|
9503
|
+
"getFunctionLayers",
|
|
9504
|
+
];
|
|
9505
|
+
exports.WRITE_FUNCTION_LAYER_ACTIONS = [
|
|
9506
|
+
"createLayerVersion",
|
|
9507
|
+
"deleteLayerVersion",
|
|
9508
|
+
"attachLayer",
|
|
9509
|
+
"detachLayer",
|
|
9510
|
+
"updateFunctionLayers",
|
|
9511
|
+
];
|
|
9512
|
+
function jsonContent(body) {
|
|
9513
|
+
return {
|
|
9514
|
+
content: [
|
|
9515
|
+
{
|
|
9516
|
+
type: "text",
|
|
9517
|
+
text: JSON.stringify(body, null, 2),
|
|
9518
|
+
},
|
|
9519
|
+
],
|
|
9520
|
+
};
|
|
9521
|
+
}
|
|
9522
|
+
function normalizeFunctionLayers(layers) {
|
|
9523
|
+
if (!Array.isArray(layers)) {
|
|
9524
|
+
return [];
|
|
9525
|
+
}
|
|
9526
|
+
return layers
|
|
9527
|
+
.filter((layer) => Boolean(layer))
|
|
9528
|
+
.map((layer) => ({
|
|
9529
|
+
LayerName: String(layer.LayerName ?? ""),
|
|
9530
|
+
LayerVersion: Number(layer.LayerVersion ?? 0),
|
|
9531
|
+
}))
|
|
9532
|
+
.filter((layer) => Boolean(layer.LayerName) && Number.isFinite(layer.LayerVersion));
|
|
9533
|
+
}
|
|
9040
9534
|
/**
|
|
9041
9535
|
* 处理函数根目录路径,确保不包含函数名
|
|
9042
9536
|
* @param functionRootPath 用户输入的路径
|
|
@@ -9064,12 +9558,12 @@ function registerFunctionTools(server) {
|
|
|
9064
9558
|
// getFunctionList - 获取云函数列表或详情(推荐)
|
|
9065
9559
|
server.registerTool?.("getFunctionList", {
|
|
9066
9560
|
title: "查询云函数列表或详情",
|
|
9067
|
-
description: "获取云函数列表或单个函数详情。通过 action 参数区分操作类型:list=获取函数列表(默认,无需额外参数),detail=获取函数详情(需要提供 name
|
|
9561
|
+
description: "获取云函数列表或单个函数详情。通过 action 参数区分操作类型:list=获取函数列表(默认,无需额外参数),detail=获取函数详情(需要提供 name 参数指定函数名称,返回结果中包含函数当前绑定的 Layers 信息)",
|
|
9068
9562
|
inputSchema: {
|
|
9069
9563
|
action: zod_1.z
|
|
9070
9564
|
.enum(["list", "detail"])
|
|
9071
9565
|
.optional()
|
|
9072
|
-
.describe("操作类型:list=获取函数列表(默认,无需额外参数),detail=获取函数详情(需要提供 name
|
|
9566
|
+
.describe("操作类型:list=获取函数列表(默认,无需额外参数),detail=获取函数详情(需要提供 name 参数,返回结果中包含当前绑定的 Layers)"),
|
|
9073
9567
|
limit: zod_1.z.number().optional().describe("范围(list 操作时使用)"),
|
|
9074
9568
|
offset: zod_1.z.number().optional().describe("偏移(list 操作时使用)"),
|
|
9075
9569
|
name: zod_1.z
|
|
@@ -9583,6 +10077,379 @@ function registerFunctionTools(server) {
|
|
|
9583
10077
|
throw new Error(`不支持的操作类型: ${action}`);
|
|
9584
10078
|
}
|
|
9585
10079
|
});
|
|
10080
|
+
server.registerTool?.("readFunctionLayers", {
|
|
10081
|
+
title: "查询云函数层信息",
|
|
10082
|
+
description: "查询云函数层及函数层配置。通过 action 区分操作:listLayers=查询层列表,listLayerVersions=查询指定层的版本列表,getLayerVersion=查询层版本详情(含下载地址/元信息),getFunctionLayers=查询指定函数当前绑定的层。返回格式:JSON 包含 success、data(含 action 与对应结果字段)、message;data.layers 或 data.layerVersions 为数组,getFunctionLayers 的 data.layers 每项为 { LayerName, LayerVersion }。",
|
|
10083
|
+
inputSchema: {
|
|
10084
|
+
action: zod_1.z
|
|
10085
|
+
.enum(exports.READ_FUNCTION_LAYER_ACTIONS)
|
|
10086
|
+
.describe("操作类型:listLayers=查询层列表,listLayerVersions=查询指定层的版本列表,getLayerVersion=查询层版本详情,getFunctionLayers=查询指定函数当前绑定的层"),
|
|
10087
|
+
name: zod_1.z
|
|
10088
|
+
.string()
|
|
10089
|
+
.optional()
|
|
10090
|
+
.describe("层名称。listLayerVersions 和 getLayerVersion 操作时必填"),
|
|
10091
|
+
version: zod_1.z
|
|
10092
|
+
.number()
|
|
10093
|
+
.optional()
|
|
10094
|
+
.describe("层版本号。getLayerVersion 操作时必填"),
|
|
10095
|
+
runtime: zod_1.z
|
|
10096
|
+
.string()
|
|
10097
|
+
.optional()
|
|
10098
|
+
.describe("运行时筛选。listLayers 操作时可选"),
|
|
10099
|
+
searchKey: zod_1.z
|
|
10100
|
+
.string()
|
|
10101
|
+
.optional()
|
|
10102
|
+
.describe("层名称搜索关键字。listLayers 操作时可选"),
|
|
10103
|
+
offset: zod_1.z.number().optional().describe("分页偏移。listLayers 操作时可选"),
|
|
10104
|
+
limit: zod_1.z.number().optional().describe("分页数量。listLayers 操作时可选"),
|
|
10105
|
+
functionName: zod_1.z
|
|
10106
|
+
.string()
|
|
10107
|
+
.optional()
|
|
10108
|
+
.describe("函数名称。getFunctionLayers 操作时必填"),
|
|
10109
|
+
codeSecret: zod_1.z
|
|
10110
|
+
.string()
|
|
10111
|
+
.optional()
|
|
10112
|
+
.describe("代码保护密钥。getFunctionLayers 操作时可选"),
|
|
10113
|
+
},
|
|
10114
|
+
annotations: {
|
|
10115
|
+
readOnlyHint: true,
|
|
10116
|
+
openWorldHint: true,
|
|
10117
|
+
category: "functions",
|
|
10118
|
+
},
|
|
10119
|
+
}, async ({ action, name, version, runtime, searchKey, offset, limit, functionName, codeSecret, }) => {
|
|
10120
|
+
if (action === "listLayers") {
|
|
10121
|
+
const cloudbase = await getManager();
|
|
10122
|
+
const result = await cloudbase.functions.listLayers({
|
|
10123
|
+
offset,
|
|
10124
|
+
limit,
|
|
10125
|
+
runtime,
|
|
10126
|
+
searchKey,
|
|
10127
|
+
});
|
|
10128
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
10129
|
+
return jsonContent({
|
|
10130
|
+
success: true,
|
|
10131
|
+
data: {
|
|
10132
|
+
action,
|
|
10133
|
+
layers: result.Layers || [],
|
|
10134
|
+
totalCount: result.TotalCount || 0,
|
|
10135
|
+
requestId: result.RequestId,
|
|
10136
|
+
},
|
|
10137
|
+
message: `Successfully retrieved ${result.Layers?.length || 0} layer entries`,
|
|
10138
|
+
nextActions: [
|
|
10139
|
+
{ tool: "readFunctionLayers", action: "listLayerVersions", reason: "List versions of a layer" },
|
|
10140
|
+
{ tool: "writeFunctionLayers", action: "createLayerVersion", reason: "Create a new layer version" },
|
|
10141
|
+
],
|
|
10142
|
+
});
|
|
10143
|
+
}
|
|
10144
|
+
if (action === "listLayerVersions") {
|
|
10145
|
+
if (!name) {
|
|
10146
|
+
throw new Error("查询层版本列表时,name 参数是必需的");
|
|
10147
|
+
}
|
|
10148
|
+
const cloudbase = await getManager();
|
|
10149
|
+
const result = await cloudbase.functions.listLayerVersions({ name });
|
|
10150
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
10151
|
+
return jsonContent({
|
|
10152
|
+
success: true,
|
|
10153
|
+
data: {
|
|
10154
|
+
action,
|
|
10155
|
+
name,
|
|
10156
|
+
layerVersions: result.LayerVersions || [],
|
|
10157
|
+
requestId: result.RequestId,
|
|
10158
|
+
},
|
|
10159
|
+
message: `Successfully retrieved ${result.LayerVersions?.length || 0} versions for layer '${name}'`,
|
|
10160
|
+
nextActions: [
|
|
10161
|
+
{ tool: "readFunctionLayers", action: "getLayerVersion", reason: "Get version details and download info" },
|
|
10162
|
+
{ tool: "writeFunctionLayers", action: "attachLayer", reason: "Bind this layer to a function" },
|
|
10163
|
+
],
|
|
10164
|
+
});
|
|
10165
|
+
}
|
|
10166
|
+
if (action === "getLayerVersion") {
|
|
10167
|
+
if (!name) {
|
|
10168
|
+
throw new Error("查询层版本详情时,name 参数是必需的");
|
|
10169
|
+
}
|
|
10170
|
+
if (typeof version !== "number") {
|
|
10171
|
+
throw new Error("查询层版本详情时,version 参数是必需的");
|
|
10172
|
+
}
|
|
10173
|
+
const cloudbase = await getManager();
|
|
10174
|
+
const result = await cloudbase.functions.getLayerVersion({
|
|
10175
|
+
name,
|
|
10176
|
+
version,
|
|
10177
|
+
});
|
|
10178
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
10179
|
+
return jsonContent({
|
|
10180
|
+
success: true,
|
|
10181
|
+
data: {
|
|
10182
|
+
action,
|
|
10183
|
+
name,
|
|
10184
|
+
version,
|
|
10185
|
+
layerVersion: result,
|
|
10186
|
+
downloadInfo: {
|
|
10187
|
+
location: result.Location,
|
|
10188
|
+
codeSha256: result.CodeSha256,
|
|
10189
|
+
},
|
|
10190
|
+
requestId: result.RequestId,
|
|
10191
|
+
},
|
|
10192
|
+
message: `Successfully retrieved details for layer '${name}' version ${version}`,
|
|
10193
|
+
nextActions: [
|
|
10194
|
+
{ tool: "writeFunctionLayers", action: "attachLayer", reason: "Bind this layer version to a function" },
|
|
10195
|
+
{ tool: "writeFunctionLayers", action: "deleteLayerVersion", reason: "Delete this layer version" },
|
|
10196
|
+
],
|
|
10197
|
+
});
|
|
10198
|
+
}
|
|
10199
|
+
if (!functionName) {
|
|
10200
|
+
throw new Error("查询函数层配置时,functionName 参数是必需的");
|
|
10201
|
+
}
|
|
10202
|
+
const cloudbase = await getManager();
|
|
10203
|
+
const result = await cloudbase.functions.getFunctionDetail(functionName, codeSecret);
|
|
10204
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
10205
|
+
const layers = normalizeFunctionLayers(result.Layers);
|
|
10206
|
+
return jsonContent({
|
|
10207
|
+
success: true,
|
|
10208
|
+
data: {
|
|
10209
|
+
action,
|
|
10210
|
+
functionName,
|
|
10211
|
+
layers,
|
|
10212
|
+
count: layers.length,
|
|
10213
|
+
requestId: result.RequestId,
|
|
10214
|
+
},
|
|
10215
|
+
message: `Successfully retrieved ${layers.length} bound layers for function '${functionName}'`,
|
|
10216
|
+
nextActions: [
|
|
10217
|
+
{ tool: "writeFunctionLayers", action: "attachLayer", reason: "Add a layer to this function" },
|
|
10218
|
+
{ tool: "writeFunctionLayers", action: "detachLayer", reason: "Remove a layer from this function" },
|
|
10219
|
+
{ tool: "writeFunctionLayers", action: "updateFunctionLayers", reason: "Replace or reorder bound layers" },
|
|
10220
|
+
],
|
|
10221
|
+
});
|
|
10222
|
+
});
|
|
10223
|
+
server.registerTool?.("writeFunctionLayers", {
|
|
10224
|
+
title: "管理云函数层",
|
|
10225
|
+
description: "管理云函数层和函数层绑定。通过 action 区分操作:createLayerVersion=创建层版本,deleteLayerVersion=删除层版本,attachLayer=给函数追加绑定层,detachLayer=解绑函数层,updateFunctionLayers=整体更新函数层数组以调整顺序或批量更新。返回格式:JSON 包含 success、data(含 action 与结果字段,如 layerVersion、layers)、message、nextActions(建议的后续操作)。",
|
|
10226
|
+
inputSchema: {
|
|
10227
|
+
action: zod_1.z
|
|
10228
|
+
.enum(exports.WRITE_FUNCTION_LAYER_ACTIONS)
|
|
10229
|
+
.describe("操作类型:createLayerVersion=创建层版本,deleteLayerVersion=删除层版本,attachLayer=追加绑定层,detachLayer=解绑层,updateFunctionLayers=整体更新函数层数组"),
|
|
10230
|
+
name: zod_1.z
|
|
10231
|
+
.string()
|
|
10232
|
+
.optional()
|
|
10233
|
+
.describe("层名称。createLayerVersion 和 deleteLayerVersion 操作时必填"),
|
|
10234
|
+
version: zod_1.z
|
|
10235
|
+
.number()
|
|
10236
|
+
.optional()
|
|
10237
|
+
.describe("层版本号。deleteLayerVersion 操作时必填"),
|
|
10238
|
+
contentPath: zod_1.z
|
|
10239
|
+
.string()
|
|
10240
|
+
.optional()
|
|
10241
|
+
.describe("层内容路径,可以是目录或 ZIP 文件路径。createLayerVersion 操作时与 base64Content 二选一"),
|
|
10242
|
+
base64Content: zod_1.z
|
|
10243
|
+
.string()
|
|
10244
|
+
.optional()
|
|
10245
|
+
.describe("层内容的 base64 编码。createLayerVersion 操作时与 contentPath 二选一"),
|
|
10246
|
+
runtimes: zod_1.z
|
|
10247
|
+
.array(zod_1.z.string())
|
|
10248
|
+
.optional()
|
|
10249
|
+
.describe("层适用的运行时列表。createLayerVersion 操作时必填"),
|
|
10250
|
+
description: zod_1.z
|
|
10251
|
+
.string()
|
|
10252
|
+
.optional()
|
|
10253
|
+
.describe("层版本描述。createLayerVersion 操作时可选"),
|
|
10254
|
+
licenseInfo: zod_1.z
|
|
10255
|
+
.string()
|
|
10256
|
+
.optional()
|
|
10257
|
+
.describe("许可证信息。createLayerVersion 操作时可选"),
|
|
10258
|
+
functionName: zod_1.z
|
|
10259
|
+
.string()
|
|
10260
|
+
.optional()
|
|
10261
|
+
.describe("函数名称。attachLayer、detachLayer、updateFunctionLayers 操作时必填"),
|
|
10262
|
+
layerName: zod_1.z
|
|
10263
|
+
.string()
|
|
10264
|
+
.optional()
|
|
10265
|
+
.describe("要绑定或解绑的层名称。attachLayer 和 detachLayer 操作时必填"),
|
|
10266
|
+
layerVersion: zod_1.z
|
|
10267
|
+
.number()
|
|
10268
|
+
.optional()
|
|
10269
|
+
.describe("要绑定或解绑的层版本号。attachLayer 和 detachLayer 操作时必填"),
|
|
10270
|
+
layers: zod_1.z
|
|
10271
|
+
.array(zod_1.z.object({
|
|
10272
|
+
LayerName: zod_1.z.string().describe("层名称"),
|
|
10273
|
+
LayerVersion: zod_1.z.number().describe("层版本号"),
|
|
10274
|
+
}))
|
|
10275
|
+
.optional()
|
|
10276
|
+
.describe("目标函数层数组。updateFunctionLayers 操作时必填,顺序即最终顺序"),
|
|
10277
|
+
codeSecret: zod_1.z
|
|
10278
|
+
.string()
|
|
10279
|
+
.optional()
|
|
10280
|
+
.describe("代码保护密钥。attachLayer 和 detachLayer 操作时可选"),
|
|
10281
|
+
},
|
|
10282
|
+
annotations: {
|
|
10283
|
+
readOnlyHint: false,
|
|
10284
|
+
destructiveHint: true,
|
|
10285
|
+
idempotentHint: false,
|
|
10286
|
+
openWorldHint: true,
|
|
10287
|
+
category: "functions",
|
|
10288
|
+
},
|
|
10289
|
+
}, async ({ action, name, version, contentPath, base64Content, runtimes, description, licenseInfo, functionName, layerName, layerVersion, layers, codeSecret, }) => {
|
|
10290
|
+
if (action === "createLayerVersion") {
|
|
10291
|
+
if (!name) {
|
|
10292
|
+
throw new Error("创建层版本时,name 参数是必需的");
|
|
10293
|
+
}
|
|
10294
|
+
if (!runtimes || runtimes.length === 0) {
|
|
10295
|
+
throw new Error("创建层版本时,runtimes 参数是必需的");
|
|
10296
|
+
}
|
|
10297
|
+
if (!contentPath && !base64Content) {
|
|
10298
|
+
throw new Error("创建层版本时,contentPath 和 base64Content 至少需要提供一个");
|
|
10299
|
+
}
|
|
10300
|
+
const cloudbase = await getManager();
|
|
10301
|
+
const result = await cloudbase.functions.createLayer({
|
|
10302
|
+
name,
|
|
10303
|
+
contentPath,
|
|
10304
|
+
base64Content,
|
|
10305
|
+
runtimes,
|
|
10306
|
+
description,
|
|
10307
|
+
licenseInfo,
|
|
10308
|
+
});
|
|
10309
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
10310
|
+
return jsonContent({
|
|
10311
|
+
success: true,
|
|
10312
|
+
data: {
|
|
10313
|
+
action,
|
|
10314
|
+
name,
|
|
10315
|
+
layerVersion: result.LayerVersion,
|
|
10316
|
+
requestId: result.RequestId,
|
|
10317
|
+
},
|
|
10318
|
+
message: `Successfully created a new version for layer '${name}'`,
|
|
10319
|
+
nextActions: [
|
|
10320
|
+
{ tool: "readFunctionLayers", action: "listLayerVersions", reason: "List all versions of this layer" },
|
|
10321
|
+
{ tool: "writeFunctionLayers", action: "attachLayer", reason: "Bind this version to a function" },
|
|
10322
|
+
],
|
|
10323
|
+
});
|
|
10324
|
+
}
|
|
10325
|
+
if (action === "deleteLayerVersion") {
|
|
10326
|
+
if (!name) {
|
|
10327
|
+
throw new Error("删除层版本时,name 参数是必需的");
|
|
10328
|
+
}
|
|
10329
|
+
if (typeof version !== "number") {
|
|
10330
|
+
throw new Error("删除层版本时,version 参数是必需的");
|
|
10331
|
+
}
|
|
10332
|
+
const cloudbase = await getManager();
|
|
10333
|
+
const result = await cloudbase.functions.deleteLayerVersion({
|
|
10334
|
+
name,
|
|
10335
|
+
version,
|
|
10336
|
+
});
|
|
10337
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
10338
|
+
return jsonContent({
|
|
10339
|
+
success: true,
|
|
10340
|
+
data: {
|
|
10341
|
+
action,
|
|
10342
|
+
name,
|
|
10343
|
+
version,
|
|
10344
|
+
requestId: result.RequestId,
|
|
10345
|
+
},
|
|
10346
|
+
message: `Successfully deleted layer '${name}' version ${version}`,
|
|
10347
|
+
nextActions: [
|
|
10348
|
+
{ tool: "readFunctionLayers", action: "listLayers", reason: "List remaining layers" },
|
|
10349
|
+
],
|
|
10350
|
+
});
|
|
10351
|
+
}
|
|
10352
|
+
if (action === "attachLayer" ||
|
|
10353
|
+
action === "detachLayer" ||
|
|
10354
|
+
action === "updateFunctionLayers") {
|
|
10355
|
+
if (!functionName) {
|
|
10356
|
+
throw new Error(`${action} 操作时,functionName 参数是必需的`);
|
|
10357
|
+
}
|
|
10358
|
+
}
|
|
10359
|
+
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
10360
|
+
const cloudbase = await getManager();
|
|
10361
|
+
if (action === "attachLayer") {
|
|
10362
|
+
if (!layerName) {
|
|
10363
|
+
throw new Error("attachLayer 操作时,layerName 参数是必需的");
|
|
10364
|
+
}
|
|
10365
|
+
if (typeof layerVersion !== "number") {
|
|
10366
|
+
throw new Error("attachLayer 操作时,layerVersion 参数是必需的");
|
|
10367
|
+
}
|
|
10368
|
+
const result = await cloudbase.functions.attachLayer({
|
|
10369
|
+
envId,
|
|
10370
|
+
functionName: functionName,
|
|
10371
|
+
layerName,
|
|
10372
|
+
layerVersion,
|
|
10373
|
+
codeSecret,
|
|
10374
|
+
});
|
|
10375
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
10376
|
+
const detail = await cloudbase.functions.getFunctionDetail(functionName, codeSecret);
|
|
10377
|
+
const boundLayers = normalizeFunctionLayers(detail.Layers);
|
|
10378
|
+
return jsonContent({
|
|
10379
|
+
success: true,
|
|
10380
|
+
data: {
|
|
10381
|
+
action,
|
|
10382
|
+
functionName,
|
|
10383
|
+
layers: boundLayers,
|
|
10384
|
+
requestId: result.RequestId,
|
|
10385
|
+
},
|
|
10386
|
+
message: `Successfully attached layer '${layerName}' version ${layerVersion} to function '${functionName}'`,
|
|
10387
|
+
nextActions: [
|
|
10388
|
+
{ tool: "readFunctionLayers", action: "getFunctionLayers", reason: "Verify bound layers" },
|
|
10389
|
+
{ tool: "writeFunctionLayers", action: "detachLayer", reason: "Remove this layer from function" },
|
|
10390
|
+
],
|
|
10391
|
+
});
|
|
10392
|
+
}
|
|
10393
|
+
if (action === "detachLayer") {
|
|
10394
|
+
if (!layerName) {
|
|
10395
|
+
throw new Error("detachLayer 操作时,layerName 参数是必需的");
|
|
10396
|
+
}
|
|
10397
|
+
if (typeof layerVersion !== "number") {
|
|
10398
|
+
throw new Error("detachLayer 操作时,layerVersion 参数是必需的");
|
|
10399
|
+
}
|
|
10400
|
+
const result = await cloudbase.functions.unAttachLayer({
|
|
10401
|
+
envId,
|
|
10402
|
+
functionName: functionName,
|
|
10403
|
+
layerName,
|
|
10404
|
+
layerVersion,
|
|
10405
|
+
codeSecret,
|
|
10406
|
+
});
|
|
10407
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
10408
|
+
const detail = await cloudbase.functions.getFunctionDetail(functionName, codeSecret);
|
|
10409
|
+
const boundLayers = normalizeFunctionLayers(detail.Layers);
|
|
10410
|
+
return jsonContent({
|
|
10411
|
+
success: true,
|
|
10412
|
+
data: {
|
|
10413
|
+
action,
|
|
10414
|
+
functionName,
|
|
10415
|
+
layers: boundLayers,
|
|
10416
|
+
requestId: result.RequestId,
|
|
10417
|
+
},
|
|
10418
|
+
message: `Successfully detached layer '${layerName}' version ${layerVersion} from function '${functionName}'`,
|
|
10419
|
+
nextActions: [
|
|
10420
|
+
{ tool: "readFunctionLayers", action: "getFunctionLayers", reason: "Verify current bound layers" },
|
|
10421
|
+
],
|
|
10422
|
+
});
|
|
10423
|
+
}
|
|
10424
|
+
if (!layers || layers.length === 0) {
|
|
10425
|
+
throw new Error("updateFunctionLayers 操作时,layers 参数是必需的");
|
|
10426
|
+
}
|
|
10427
|
+
const normalizedLayers = normalizeFunctionLayers(layers);
|
|
10428
|
+
if (normalizedLayers.length === 0) {
|
|
10429
|
+
throw new Error("updateFunctionLayers 操作时,layers 参数必须包含有效的 LayerName 和 LayerVersion");
|
|
10430
|
+
}
|
|
10431
|
+
const result = await cloudbase.functions.updateFunctionLayer({
|
|
10432
|
+
envId,
|
|
10433
|
+
functionName: functionName,
|
|
10434
|
+
layers: normalizedLayers,
|
|
10435
|
+
});
|
|
10436
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
10437
|
+
const detail = await cloudbase.functions.getFunctionDetail(functionName);
|
|
10438
|
+
const boundLayers = normalizeFunctionLayers(detail.Layers);
|
|
10439
|
+
return jsonContent({
|
|
10440
|
+
success: true,
|
|
10441
|
+
data: {
|
|
10442
|
+
action,
|
|
10443
|
+
functionName,
|
|
10444
|
+
layers: boundLayers,
|
|
10445
|
+
requestId: result.RequestId,
|
|
10446
|
+
},
|
|
10447
|
+
message: `Successfully updated bound layers for function '${functionName}'`,
|
|
10448
|
+
nextActions: [
|
|
10449
|
+
{ tool: "readFunctionLayers", action: "getFunctionLayers", reason: "Verify updated layer order" },
|
|
10450
|
+
],
|
|
10451
|
+
});
|
|
10452
|
+
});
|
|
9586
10453
|
// // Layer相关功能
|
|
9587
10454
|
// // createLayer - 创建Layer
|
|
9588
10455
|
// server.tool(
|
|
@@ -10239,7 +11106,7 @@ function registerSetupTools(server) {
|
|
|
10239
11106
|
title: "下载项目模板",
|
|
10240
11107
|
description: `自动下载并部署CloudBase项目模板。⚠️ **MANDATORY FOR NEW PROJECTS** ⚠️
|
|
10241
11108
|
|
|
10242
|
-
**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- 其他IDE类型见下方列表\n\n注意:如果未传入 ide 参数且无法从环境变量检测到 IDE,将提示错误并要求传入 ide 参数\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- qoder: Qoder AI编辑器\n- antigravity: Google Antigravity AI编辑器\n- vscode: Visual Studio Code\n- kiro: Kiro AI编辑器\n- aider: Aider AI编辑器\n\n特别说明:\n- rules 模板会自动包含当前 mcp 版本号信息(版本号:${ true ? "2.
|
|
11109
|
+
**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- 其他IDE类型见下方列表\n\n注意:如果未传入 ide 参数且无法从环境变量检测到 IDE,将提示错误并要求传入 ide 参数\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- qoder: Qoder AI编辑器\n- antigravity: Google Antigravity AI编辑器\n- vscode: Visual Studio Code\n- kiro: Kiro AI编辑器\n- aider: Aider AI编辑器\n\n特别说明:\n- rules 模板会自动包含当前 mcp 版本号信息(版本号:${ true ? "2.14.0" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
|
|
10243
11110
|
inputSchema: {
|
|
10244
11111
|
template: zod_1.z
|
|
10245
11112
|
.enum(["react", "vue", "miniprogram", "uniapp", "rules"])
|
|
@@ -11567,7 +12434,13 @@ async function getUinForTelemetry() {
|
|
|
11567
12434
|
const loginState = await (0, auth_js_1.getLoginState)({ region });
|
|
11568
12435
|
// Try to extract UIN from loginState
|
|
11569
12436
|
// Note: actual field name may vary, adjust based on actual response
|
|
11570
|
-
|
|
12437
|
+
if (loginState &&
|
|
12438
|
+
typeof loginState === "object" &&
|
|
12439
|
+
"uin" in loginState &&
|
|
12440
|
+
typeof loginState.uin !== "undefined") {
|
|
12441
|
+
return String(loginState.uin);
|
|
12442
|
+
}
|
|
12443
|
+
return undefined;
|
|
11571
12444
|
}
|
|
11572
12445
|
catch (err) {
|
|
11573
12446
|
(0, logger_js_1.debug)('Failed to get UIN for telemetry', { error: err instanceof Error ? err.message : String(err) });
|
|
@@ -12128,56 +13001,181 @@ function registerHostingTools(server) {
|
|
|
12128
13001
|
|
|
12129
13002
|
|
|
12130
13003
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
13004
|
+
exports.getAuthProgressStateSync = getAuthProgressStateSync;
|
|
13005
|
+
exports.getAuthProgressState = getAuthProgressState;
|
|
13006
|
+
exports.setPendingAuthProgressState = setPendingAuthProgressState;
|
|
13007
|
+
exports.resolveAuthProgressState = resolveAuthProgressState;
|
|
13008
|
+
exports.rejectAuthProgressState = rejectAuthProgressState;
|
|
13009
|
+
exports.resetAuthProgressState = resetAuthProgressState;
|
|
13010
|
+
exports.peekLoginState = peekLoginState;
|
|
13011
|
+
exports.ensureLogin = ensureLogin;
|
|
12131
13012
|
exports.getLoginState = getLoginState;
|
|
12132
13013
|
exports.logout = logout;
|
|
12133
13014
|
const toolbox_1 = __webpack_require__(2090);
|
|
12134
13015
|
const logger_js_1 = __webpack_require__(3039);
|
|
12135
13016
|
const tencet_cloud_js_1 = __webpack_require__(5018);
|
|
12136
|
-
const auth = toolbox_1.
|
|
12137
|
-
|
|
13017
|
+
const auth = toolbox_1.AuthSupervisor.getInstance({});
|
|
13018
|
+
const authProgressState = {
|
|
13019
|
+
status: "IDLE",
|
|
13020
|
+
updatedAt: Date.now(),
|
|
13021
|
+
};
|
|
13022
|
+
function updateAuthProgressState(partial) {
|
|
13023
|
+
Object.assign(authProgressState, partial, {
|
|
13024
|
+
updatedAt: Date.now(),
|
|
13025
|
+
});
|
|
13026
|
+
return getAuthProgressStateSync();
|
|
13027
|
+
}
|
|
13028
|
+
function normalizeLoginStateFromEnvVars(options) {
|
|
12138
13029
|
const { TENCENTCLOUD_SECRETID, TENCENTCLOUD_SECRETKEY, TENCENTCLOUD_SESSIONTOKEN, } = process.env;
|
|
12139
|
-
(0, logger_js_1.debug)("TENCENTCLOUD_SECRETID", { secretId: TENCENTCLOUD_SECRETID });
|
|
12140
|
-
// If ignoreEnvVars is true (e.g., when switching account), skip environment variables
|
|
12141
|
-
// and force Web authentication to allow account switching
|
|
12142
13030
|
if (!options?.ignoreEnvVars && TENCENTCLOUD_SECRETID && TENCENTCLOUD_SECRETKEY) {
|
|
12143
|
-
(0, logger_js_1.debug)("loginByApiSecret");
|
|
12144
13031
|
return {
|
|
12145
13032
|
secretId: TENCENTCLOUD_SECRETID,
|
|
12146
13033
|
secretKey: TENCENTCLOUD_SECRETKEY,
|
|
12147
13034
|
token: TENCENTCLOUD_SESSIONTOKEN,
|
|
13035
|
+
envId: process.env.CLOUDBASE_ENV_ID,
|
|
12148
13036
|
};
|
|
12149
|
-
// await auth.loginByApiSecret(TENCENTCLOUD_SECRETID, TENCENTCLOUD_SECRETKEY, TENCENTCLOUD_SESSIONTOKEN)
|
|
12150
13037
|
}
|
|
12151
|
-
|
|
13038
|
+
return null;
|
|
13039
|
+
}
|
|
13040
|
+
function mapAuthErrorStatus(error) {
|
|
13041
|
+
const message = error instanceof Error ? error.message : String(error ?? "");
|
|
13042
|
+
if (message.includes("拒绝") || message.includes("denied")) {
|
|
13043
|
+
return "DENIED";
|
|
13044
|
+
}
|
|
13045
|
+
if (message.includes("过期") || message.includes("expired")) {
|
|
13046
|
+
return "EXPIRED";
|
|
13047
|
+
}
|
|
13048
|
+
return "ERROR";
|
|
13049
|
+
}
|
|
13050
|
+
function getAuthProgressStateSync() {
|
|
13051
|
+
return {
|
|
13052
|
+
...authProgressState,
|
|
13053
|
+
authChallenge: authProgressState.authChallenge
|
|
13054
|
+
? { ...authProgressState.authChallenge }
|
|
13055
|
+
: undefined,
|
|
13056
|
+
};
|
|
13057
|
+
}
|
|
13058
|
+
async function getAuthProgressState() {
|
|
13059
|
+
const loginState = await peekLoginState();
|
|
13060
|
+
if (loginState && authProgressState.status === "PENDING") {
|
|
13061
|
+
updateAuthProgressState({
|
|
13062
|
+
status: "READY",
|
|
13063
|
+
lastError: undefined,
|
|
13064
|
+
});
|
|
13065
|
+
}
|
|
13066
|
+
if (authProgressState.status === "PENDING" &&
|
|
13067
|
+
authProgressState.authChallenge?.expires_in) {
|
|
13068
|
+
const issuedAt = authProgressState.updatedAt;
|
|
13069
|
+
const expiresAt = issuedAt + authProgressState.authChallenge.expires_in * 1000;
|
|
13070
|
+
if (Date.now() > expiresAt) {
|
|
13071
|
+
updateAuthProgressState({
|
|
13072
|
+
status: "EXPIRED",
|
|
13073
|
+
lastError: "设备码已过期,请重新发起授权",
|
|
13074
|
+
});
|
|
13075
|
+
}
|
|
13076
|
+
}
|
|
13077
|
+
return getAuthProgressStateSync();
|
|
13078
|
+
}
|
|
13079
|
+
function setPendingAuthProgressState(challenge, authMode = "device") {
|
|
13080
|
+
return updateAuthProgressState({
|
|
13081
|
+
status: "PENDING",
|
|
13082
|
+
authMode,
|
|
13083
|
+
authChallenge: challenge,
|
|
13084
|
+
lastError: undefined,
|
|
13085
|
+
});
|
|
13086
|
+
}
|
|
13087
|
+
function resolveAuthProgressState() {
|
|
13088
|
+
return updateAuthProgressState({
|
|
13089
|
+
status: "READY",
|
|
13090
|
+
lastError: undefined,
|
|
13091
|
+
});
|
|
13092
|
+
}
|
|
13093
|
+
function rejectAuthProgressState(error) {
|
|
13094
|
+
const message = error instanceof Error ? error.message : String(error ?? "unknown error");
|
|
13095
|
+
return updateAuthProgressState({
|
|
13096
|
+
status: mapAuthErrorStatus(error),
|
|
13097
|
+
lastError: message,
|
|
13098
|
+
});
|
|
13099
|
+
}
|
|
13100
|
+
function resetAuthProgressState() {
|
|
13101
|
+
return updateAuthProgressState({
|
|
13102
|
+
status: "IDLE",
|
|
13103
|
+
authMode: undefined,
|
|
13104
|
+
authChallenge: undefined,
|
|
13105
|
+
lastError: undefined,
|
|
13106
|
+
});
|
|
13107
|
+
}
|
|
13108
|
+
async function peekLoginState(options) {
|
|
13109
|
+
const envVarLoginState = normalizeLoginStateFromEnvVars(options);
|
|
13110
|
+
if (envVarLoginState) {
|
|
13111
|
+
(0, logger_js_1.debug)("loginByApiSecret");
|
|
13112
|
+
return envVarLoginState;
|
|
13113
|
+
}
|
|
13114
|
+
return auth.getLoginState();
|
|
13115
|
+
}
|
|
13116
|
+
async function ensureLogin(options) {
|
|
13117
|
+
(0, logger_js_1.debug)("TENCENTCLOUD_SECRETID", { secretId: process.env.TENCENTCLOUD_SECRETID });
|
|
13118
|
+
const loginState = await peekLoginState({
|
|
13119
|
+
ignoreEnvVars: options?.ignoreEnvVars,
|
|
13120
|
+
});
|
|
12152
13121
|
if (!loginState) {
|
|
12153
|
-
|
|
12154
|
-
|
|
12155
|
-
|
|
12156
|
-
|
|
12157
|
-
|
|
12158
|
-
|
|
12159
|
-
|
|
12160
|
-
|
|
12161
|
-
|
|
12162
|
-
|
|
12163
|
-
|
|
12164
|
-
if ((0, tencet_cloud_js_1.isInternationalRegion)(options?.region)) {
|
|
12165
|
-
url = url.replace('cloud.tencent.com', 'tencentcloud.com');
|
|
13122
|
+
const envMode = process.env.TCB_AUTH_MODE;
|
|
13123
|
+
const normalizedEnvMode = envMode === "web" || envMode === "device" ? envMode : undefined;
|
|
13124
|
+
const mode = options?.authMode || normalizedEnvMode || "device";
|
|
13125
|
+
const loginOptions = { flow: mode };
|
|
13126
|
+
if (mode === "web") {
|
|
13127
|
+
loginOptions.getAuthUrl =
|
|
13128
|
+
options?.fromCloudBaseLoginPage && !(0, tencet_cloud_js_1.isInternationalRegion)(options?.region)
|
|
13129
|
+
? (url) => {
|
|
13130
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
13131
|
+
const urlWithParam = `${url}${separator}allowNoEnv=true`;
|
|
13132
|
+
return `https://tcb.cloud.tencent.com/login?_redirect_uri=${encodeURIComponent(urlWithParam)}`;
|
|
12166
13133
|
}
|
|
12167
|
-
|
|
12168
|
-
|
|
12169
|
-
|
|
12170
|
-
|
|
12171
|
-
|
|
12172
|
-
|
|
13134
|
+
: (url) => {
|
|
13135
|
+
if ((0, tencet_cloud_js_1.isInternationalRegion)(options?.region)) {
|
|
13136
|
+
url = url.replace("cloud.tencent.com", "tencentcloud.com");
|
|
13137
|
+
}
|
|
13138
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
13139
|
+
return `${url}${separator}allowNoEnv=true`;
|
|
13140
|
+
};
|
|
13141
|
+
}
|
|
13142
|
+
else {
|
|
13143
|
+
if (options?.clientId) {
|
|
13144
|
+
loginOptions.client_id = options.clientId;
|
|
13145
|
+
}
|
|
13146
|
+
if (options?.onDeviceCode) {
|
|
13147
|
+
loginOptions.onDeviceCode = (info) => {
|
|
13148
|
+
setPendingAuthProgressState(info, mode);
|
|
13149
|
+
options.onDeviceCode?.(info);
|
|
13150
|
+
};
|
|
13151
|
+
}
|
|
13152
|
+
}
|
|
13153
|
+
(0, logger_js_1.debug)("beforeloginByWebAuth", { loginOptions });
|
|
13154
|
+
try {
|
|
13155
|
+
await auth.loginByWebAuth(loginOptions);
|
|
13156
|
+
resolveAuthProgressState();
|
|
13157
|
+
}
|
|
13158
|
+
catch (error) {
|
|
13159
|
+
rejectAuthProgressState(error);
|
|
13160
|
+
throw error;
|
|
13161
|
+
}
|
|
13162
|
+
const loginState = await peekLoginState({
|
|
13163
|
+
ignoreEnvVars: options?.ignoreEnvVars,
|
|
13164
|
+
});
|
|
13165
|
+
(0, logger_js_1.debug)("loginByWebAuth", { mode, hasLoginState: !!loginState });
|
|
12173
13166
|
return loginState;
|
|
12174
13167
|
}
|
|
12175
13168
|
else {
|
|
13169
|
+
resolveAuthProgressState();
|
|
12176
13170
|
return loginState;
|
|
12177
13171
|
}
|
|
12178
13172
|
}
|
|
13173
|
+
async function getLoginState(options) {
|
|
13174
|
+
return ensureLogin(options);
|
|
13175
|
+
}
|
|
12179
13176
|
async function logout() {
|
|
12180
13177
|
const result = await auth.logout();
|
|
13178
|
+
resetAuthProgressState();
|
|
12181
13179
|
return result;
|
|
12182
13180
|
}
|
|
12183
13181
|
|
|
@@ -13605,8 +14603,7 @@ function shouldRegisterTool(toolName) {
|
|
|
13605
14603
|
// Cloud-incompatible tools that involve local file operations
|
|
13606
14604
|
const cloudIncompatibleTools = [
|
|
13607
14605
|
// Auth tools - local file uploads
|
|
13608
|
-
'
|
|
13609
|
-
'logout',
|
|
14606
|
+
'auth',
|
|
13610
14607
|
// Storage tools - local file uploads
|
|
13611
14608
|
'uploadFile',
|
|
13612
14609
|
// Hosting tools - local file uploads
|
|
@@ -13746,6 +14743,60 @@ function registerSQLDatabaseTools(server) {
|
|
|
13746
14743
|
}
|
|
13747
14744
|
|
|
13748
14745
|
|
|
14746
|
+
/***/ }),
|
|
14747
|
+
|
|
14748
|
+
/***/ 9835:
|
|
14749
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
14750
|
+
|
|
14751
|
+
|
|
14752
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
14753
|
+
exports.ToolPayloadError = void 0;
|
|
14754
|
+
exports.buildJsonToolResult = buildJsonToolResult;
|
|
14755
|
+
exports.isToolPayloadError = isToolPayloadError;
|
|
14756
|
+
exports.toolPayloadErrorToResult = toolPayloadErrorToResult;
|
|
14757
|
+
exports.buildAuthNextStep = buildAuthNextStep;
|
|
14758
|
+
exports.throwToolPayloadError = throwToolPayloadError;
|
|
14759
|
+
function buildJsonToolResult(payload) {
|
|
14760
|
+
return {
|
|
14761
|
+
content: [
|
|
14762
|
+
{
|
|
14763
|
+
type: "text",
|
|
14764
|
+
text: JSON.stringify(payload, null, 2),
|
|
14765
|
+
},
|
|
14766
|
+
],
|
|
14767
|
+
};
|
|
14768
|
+
}
|
|
14769
|
+
class ToolPayloadError extends Error {
|
|
14770
|
+
payload;
|
|
14771
|
+
constructor(payload) {
|
|
14772
|
+
super(typeof payload.message === "string" ? payload.message : "Tool payload error");
|
|
14773
|
+
this.name = "ToolPayloadError";
|
|
14774
|
+
this.payload = payload;
|
|
14775
|
+
}
|
|
14776
|
+
}
|
|
14777
|
+
exports.ToolPayloadError = ToolPayloadError;
|
|
14778
|
+
function isToolPayloadError(error) {
|
|
14779
|
+
return error instanceof ToolPayloadError;
|
|
14780
|
+
}
|
|
14781
|
+
function toolPayloadErrorToResult(error) {
|
|
14782
|
+
if (!isToolPayloadError(error)) {
|
|
14783
|
+
return null;
|
|
14784
|
+
}
|
|
14785
|
+
return buildJsonToolResult(error.payload);
|
|
14786
|
+
}
|
|
14787
|
+
function buildAuthNextStep(action, options) {
|
|
14788
|
+
return {
|
|
14789
|
+
tool: "auth",
|
|
14790
|
+
action,
|
|
14791
|
+
required_params: options?.requiredParams,
|
|
14792
|
+
suggested_args: options?.suggestedArgs ?? { action },
|
|
14793
|
+
};
|
|
14794
|
+
}
|
|
14795
|
+
function throwToolPayloadError(payload) {
|
|
14796
|
+
throw new ToolPayloadError(payload);
|
|
14797
|
+
}
|
|
14798
|
+
|
|
14799
|
+
|
|
13749
14800
|
/***/ })
|
|
13750
14801
|
|
|
13751
14802
|
/******/ });
|