@cloudbase/cloudbase-mcp 2.21.0 → 2.21.1-beta.1
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/README.md +1 -1
- package/dist/cli.cjs +3 -3
- package/dist/index.cjs +801 -700
- package/dist/index.d.ts +109 -1
- package/dist/index.js +770 -695
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1914,17 +1914,17 @@ function buildEnvDomainManagementResult(params) {
|
|
|
1914
1914
|
operation: action,
|
|
1915
1915
|
targetDomains: domains,
|
|
1916
1916
|
asyncState: "PENDING",
|
|
1917
|
-
message: '安全域名已提交添加请求。该变更通常需要约 10 分钟传播,请继续轮询
|
|
1917
|
+
message: '安全域名已提交添加请求。该变更通常需要约 10 分钟传播,请继续轮询 queryEnv(action="domains"),直到目标域名状态为 ENABLE。',
|
|
1918
1918
|
propagation: {
|
|
1919
1919
|
requiresPolling: true,
|
|
1920
|
-
pollTool: "
|
|
1920
|
+
pollTool: "queryEnv",
|
|
1921
1921
|
pollAction: "domains",
|
|
1922
1922
|
pollIntervalSuggestionSeconds: 10,
|
|
1923
1923
|
timeoutSuggestionSeconds: 600,
|
|
1924
|
-
successCondition: '目标域名出现在
|
|
1924
|
+
successCondition: '目标域名出现在 queryEnv(action="domains") 返回中,且 Status 为 ENABLE。',
|
|
1925
1925
|
},
|
|
1926
1926
|
next_step: {
|
|
1927
|
-
tool: "
|
|
1927
|
+
tool: "queryEnv",
|
|
1928
1928
|
action: "domains",
|
|
1929
1929
|
suggested_args: {
|
|
1930
1930
|
action: "domains",
|
|
@@ -1939,17 +1939,17 @@ function buildEnvDomainManagementResult(params) {
|
|
|
1939
1939
|
operation: action,
|
|
1940
1940
|
targetDomains: domains,
|
|
1941
1941
|
asyncState: "PENDING",
|
|
1942
|
-
message: '安全域名已提交删除请求。该变更可能需要数分钟传播,请继续轮询
|
|
1942
|
+
message: '安全域名已提交删除请求。该变更可能需要数分钟传播,请继续轮询 queryEnv(action="domains"),直到目标域名不再出现。',
|
|
1943
1943
|
propagation: {
|
|
1944
1944
|
requiresPolling: true,
|
|
1945
|
-
pollTool: "
|
|
1945
|
+
pollTool: "queryEnv",
|
|
1946
1946
|
pollAction: "domains",
|
|
1947
1947
|
pollIntervalSuggestionSeconds: 10,
|
|
1948
1948
|
timeoutSuggestionSeconds: 600,
|
|
1949
|
-
successCondition: '目标域名不再出现在
|
|
1949
|
+
successCondition: '目标域名不再出现在 queryEnv(action="domains") 返回中。',
|
|
1950
1950
|
},
|
|
1951
1951
|
next_step: {
|
|
1952
|
-
tool: "
|
|
1952
|
+
tool: "queryEnv",
|
|
1953
1953
|
action: "domains",
|
|
1954
1954
|
suggested_args: {
|
|
1955
1955
|
action: "domains",
|
|
@@ -2223,7 +2223,7 @@ function buildEnvQueryListResult(params) {
|
|
|
2223
2223
|
const paginated = paginateEnvList(filteredList, params.filters.offset, params.filters.limit);
|
|
2224
2224
|
const exactEnvIdSummaryHint = params.filters.envId
|
|
2225
2225
|
? {
|
|
2226
|
-
tool: "
|
|
2226
|
+
tool: "queryEnv",
|
|
2227
2227
|
action: "info",
|
|
2228
2228
|
reason: "action=list with envId only returns a concise summary. Use action=info to fetch detailed environment information such as full resource metadata and additional environment details.",
|
|
2229
2229
|
}
|
|
@@ -2294,7 +2294,7 @@ function normalizeOptionalToolString(value) {
|
|
|
2294
2294
|
: undefined;
|
|
2295
2295
|
}
|
|
2296
2296
|
/**
|
|
2297
|
-
* Build enhanced error message for
|
|
2297
|
+
* Build enhanced error message for queryEnv tool errors
|
|
2298
2298
|
* Provides actionable guidance based on error patterns
|
|
2299
2299
|
*/
|
|
2300
2300
|
function buildEnvQueryErrorMessage(error, action) {
|
|
@@ -2310,7 +2310,7 @@ function buildEnvQueryErrorMessage(error, action) {
|
|
|
2310
2310
|
suggestions.push("参数错误:可能是认证信息无效或已过期,请尝试以下步骤:");
|
|
2311
2311
|
suggestions.push("1. 先调用 auth(action=\"status\") 检查当前登录状态");
|
|
2312
2312
|
suggestions.push("2. 如果未登录,调用 auth(action=\"start_auth\", authMode=\"device\") 完成登录");
|
|
2313
|
-
suggestions.push("3. 登录完成后再次调用
|
|
2313
|
+
suggestions.push("3. 登录完成后再次调用 queryEnv(action=\"list\")");
|
|
2314
2314
|
}
|
|
2315
2315
|
if (hasAuthError) {
|
|
2316
2316
|
suggestions.push("认证错误:当前未登录或认证已过期。");
|
|
@@ -2322,7 +2322,7 @@ function buildEnvQueryErrorMessage(error, action) {
|
|
|
2322
2322
|
}
|
|
2323
2323
|
if (hasEnvNotFoundError) {
|
|
2324
2324
|
suggestions.push("环境错误:指定的环境不存在或无法访问。");
|
|
2325
|
-
suggestions.push("请使用
|
|
2325
|
+
suggestions.push("请使用 queryEnv(action=\"list\") 查看可用的环境列表。");
|
|
2326
2326
|
}
|
|
2327
2327
|
if (hasNetworkError) {
|
|
2328
2328
|
suggestions.push("网络错误:请检查网络连接,稍后重试。");
|
|
@@ -2334,7 +2334,7 @@ function buildEnvQueryErrorMessage(error, action) {
|
|
|
2334
2334
|
suggestions.push("2. 如未登录,执行 auth(action=\"start_auth\") 完成认证");
|
|
2335
2335
|
suggestions.push("3. 确认环境 ID 正确且可访问");
|
|
2336
2336
|
}
|
|
2337
|
-
return `[
|
|
2337
|
+
return `[queryEnv/${action}] 调用失败: ${baseMessage}\n\n解决建议:\n${suggestions.join("\n")}`;
|
|
2338
2338
|
}
|
|
2339
2339
|
function normalizeOptionalToolBoolean(value) {
|
|
2340
2340
|
return typeof value === "boolean" ? value : undefined;
|
|
@@ -2363,519 +2363,500 @@ function registerEnvTools(server) {
|
|
|
2363
2363
|
const supportedAuthActions = getSupportedAuthActions(server);
|
|
2364
2364
|
const authActionEnum = [...supportedAuthActions];
|
|
2365
2365
|
// auth - CloudBase (云开发) 开发阶段登录与环境绑定
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
.
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
.
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
.
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
.
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
.
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
envId: zod_1.z
|
|
2395
|
-
.string()
|
|
2396
|
-
.optional()
|
|
2397
|
-
.describe("环境ID(CloudBase 环境唯一标识),绑定后工具将操作该环境。action=set_env 时必填"),
|
|
2398
|
-
...(supportedAuthActions.includes("logout")
|
|
2399
|
-
? {
|
|
2400
|
-
confirm: zod_1.z
|
|
2401
|
-
.literal("yes")
|
|
2402
|
-
.optional()
|
|
2403
|
-
.describe("action=logout 时确认操作,传 yes"),
|
|
2404
|
-
}
|
|
2405
|
-
: {}),
|
|
2406
|
-
...(supportedAuthActions.includes("get_temp_credentials")
|
|
2407
|
-
? {
|
|
2408
|
-
reveal: zod_1.z
|
|
2409
|
-
.boolean()
|
|
2410
|
-
.optional()
|
|
2411
|
-
.describe("action=get_temp_credentials 时可选。true=返回明文临时密钥;默认 false 仅返回脱敏结果"),
|
|
2412
|
-
}
|
|
2413
|
-
: {}),
|
|
2414
|
-
},
|
|
2415
|
-
annotations: {
|
|
2416
|
-
readOnlyHint: false,
|
|
2417
|
-
destructiveHint: false,
|
|
2418
|
-
idempotentHint: false,
|
|
2419
|
-
openWorldHint: true,
|
|
2420
|
-
category: "env",
|
|
2421
|
-
},
|
|
2422
|
-
}, async (rawArgs) => {
|
|
2423
|
-
const action = rawArgs.action ?? "status";
|
|
2424
|
-
const authMode = rawArgs.authMode === "device" || rawArgs.authMode === "web"
|
|
2425
|
-
? rawArgs.authMode
|
|
2426
|
-
: undefined;
|
|
2427
|
-
const oauthEndpoint = normalizeOptionalToolString(rawArgs.oauthEndpoint);
|
|
2428
|
-
const clientId = normalizeOptionalToolString(rawArgs.clientId);
|
|
2429
|
-
const oauthCustom = normalizeOptionalToolBoolean(rawArgs.oauthCustom);
|
|
2430
|
-
const envId = rawArgs.envId;
|
|
2431
|
-
const confirm = rawArgs.confirm === "yes" ? "yes" : undefined;
|
|
2432
|
-
const reveal = normalizeOptionalToolBoolean(rawArgs.reveal) === true;
|
|
2433
|
-
const resolvedAuthOptions = resolveToolAuthOptions(server, {
|
|
2434
|
-
authMode,
|
|
2435
|
-
oauthEndpoint,
|
|
2436
|
-
clientId,
|
|
2437
|
-
oauthCustom,
|
|
2438
|
-
});
|
|
2439
|
-
const authConfigSummary = (0, auth_js_1.buildAuthConfigSummary)(resolvedAuthOptions);
|
|
2440
|
-
let deviceAuthInfo;
|
|
2441
|
-
const onDeviceCode = (info) => {
|
|
2442
|
-
deviceAuthInfo = info;
|
|
2443
|
-
(0, auth_js_1.setPendingAuthProgressState)(info, "device");
|
|
2444
|
-
// emitDeviceAuthNotice(server, info);
|
|
2445
|
-
};
|
|
2446
|
-
const authChallenge = () => (0, auth_js_1.buildDeviceAuthChallengePayload)(deviceAuthInfo);
|
|
2447
|
-
try {
|
|
2448
|
-
if (!supportedAuthActions.includes(action)) {
|
|
2449
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2450
|
-
ok: false,
|
|
2451
|
-
code: "NOT_SUPPORTED",
|
|
2452
|
-
message: `当前 IDE 不支持 auth(action="${action}")。`,
|
|
2453
|
-
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
2454
|
-
suggestedArgs: { action: "status" },
|
|
2455
|
-
}),
|
|
2456
|
-
});
|
|
2457
|
-
}
|
|
2458
|
-
if (action === "status") {
|
|
2459
|
-
const loginState = await (0, auth_js_1.peekLoginState)();
|
|
2460
|
-
const authFlowState = await (0, auth_js_1.getAuthProgressState)();
|
|
2461
|
-
// 判断是否为 API Key 模式
|
|
2462
|
-
const isApiKeyMode = !!(process.env.CLOUDBASE_API_KEY && process.env.CLOUDBASE_ENV_ID);
|
|
2463
|
-
const authStatus = loginState
|
|
2464
|
-
? "READY"
|
|
2465
|
-
: authFlowState.status === "PENDING"
|
|
2466
|
-
? "PENDING"
|
|
2467
|
-
: "REQUIRED";
|
|
2468
|
-
let envPreparation;
|
|
2469
|
-
const message = authStatus === "READY"
|
|
2470
|
-
? undefined
|
|
2471
|
-
: authStatus === "PENDING"
|
|
2472
|
-
? "设备码授权进行中,请完成浏览器授权后再次调用 auth(action=\"status\")"
|
|
2473
|
-
: isCodeBuddyIde(server)
|
|
2474
|
-
? "当前未登录。CodeBuddy 暂不支持在 tool 内发起认证,请在外部完成认证后再次调用 auth(action=\"status\")。"
|
|
2475
|
-
: "当前未登录,请先执行 auth(action=\"start_auth\")";
|
|
2476
|
-
if (authStatus === "READY" && loginState) {
|
|
2477
|
-
envPreparation = await prepareAuthEnvironment({
|
|
2478
|
-
server,
|
|
2479
|
-
cloudBaseOptions,
|
|
2480
|
-
loginState,
|
|
2481
|
-
});
|
|
2482
|
-
}
|
|
2483
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2484
|
-
ok: true,
|
|
2485
|
-
code: "STATUS",
|
|
2486
|
-
auth_status: authStatus,
|
|
2487
|
-
...(isApiKeyMode ? { auth_mode: "api_key" } : {}),
|
|
2488
|
-
auth_config: authConfigSummary,
|
|
2489
|
-
...(envPreparation
|
|
2490
|
-
? buildAuthEnvSetupPayload(envPreparation)
|
|
2491
|
-
: {
|
|
2492
|
-
env_status: "NONE",
|
|
2493
|
-
current_env_id: null,
|
|
2494
|
-
...buildEnvCandidatePayload([]),
|
|
2495
|
-
}),
|
|
2496
|
-
auth_challenge: authFlowState.status === "PENDING"
|
|
2497
|
-
? (0, auth_js_1.buildDeviceAuthChallengePayload)(authFlowState.authChallenge)
|
|
2498
|
-
: undefined,
|
|
2499
|
-
message,
|
|
2500
|
-
next_step: authStatus === "REQUIRED"
|
|
2501
|
-
? buildAuthRequiredNextStep(server)
|
|
2502
|
-
: authStatus === "PENDING"
|
|
2503
|
-
? (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
2504
|
-
suggestedArgs: { action: "status" },
|
|
2505
|
-
})
|
|
2506
|
-
: envPreparation?.nextStep,
|
|
2507
|
-
});
|
|
2508
|
-
}
|
|
2509
|
-
if (action === "start_auth") {
|
|
2510
|
-
// API Key 模式:尝试换取临时密钥
|
|
2511
|
-
if (process.env.CLOUDBASE_API_KEY && process.env.CLOUDBASE_ENV_ID) {
|
|
2512
|
-
try {
|
|
2513
|
-
const existingLoginState = await (0, auth_js_1.peekLoginState)();
|
|
2514
|
-
if (existingLoginState) {
|
|
2515
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2516
|
-
ok: true,
|
|
2517
|
-
code: "AUTH_READY",
|
|
2518
|
-
message: "当前使用 API Key 认证模式,已自动完成登录,无需手动授权。",
|
|
2519
|
-
auth_mode: "api_key",
|
|
2520
|
-
envId: process.env.CLOUDBASE_ENV_ID,
|
|
2521
|
-
});
|
|
2522
|
-
}
|
|
2366
|
+
// 微信 IDE 使用票据认证,不需要登录工具
|
|
2367
|
+
if (server.ide !== 'wxide') {
|
|
2368
|
+
server.registerTool?.("auth", {
|
|
2369
|
+
title: "CloudBase 开发阶段登录与环境",
|
|
2370
|
+
description: "CloudBase(腾讯云开发)开发阶段登录与环境绑定。登录后即可访问云资源;环境(env)是云函数、数据库、静态托管等资源的隔离单元,绑定环境后其他 MCP 工具才能操作该环境。支持:查询状态、发起登录、绑定环境(set_env)、退出登录。",
|
|
2371
|
+
inputSchema: {
|
|
2372
|
+
action: zod_1.z
|
|
2373
|
+
.enum(authActionEnum)
|
|
2374
|
+
.optional()
|
|
2375
|
+
.describe("动作:status=查询状态,start_auth=发起登录,set_env=绑定环境(传envId),logout=退出登录"),
|
|
2376
|
+
...(supportedAuthActions.includes("start_auth")
|
|
2377
|
+
? {
|
|
2378
|
+
authMode: zod_1.z
|
|
2379
|
+
.enum(["device", "web"])
|
|
2380
|
+
.optional()
|
|
2381
|
+
.describe("认证模式:device=设备码授权,web=浏览器回调授权"),
|
|
2382
|
+
oauthEndpoint: zod_1.z
|
|
2383
|
+
.string()
|
|
2384
|
+
.optional()
|
|
2385
|
+
.describe("高级可选:自定义 device-code 登录 endpoint。配置后 oauthCustom 默认按 true 处理"),
|
|
2386
|
+
clientId: zod_1.z
|
|
2387
|
+
.string()
|
|
2388
|
+
.optional()
|
|
2389
|
+
.describe("高级可选:自定义 device-code 登录 client_id,不传则使用默认值"),
|
|
2390
|
+
oauthCustom: zod_1.z
|
|
2391
|
+
.boolean()
|
|
2392
|
+
.optional()
|
|
2393
|
+
.describe("高级可选:自定义 endpoint 返回格式开关。未配置 endpoint 时默认 false;配置 endpoint 后默认 true,且不能设为 false"),
|
|
2523
2394
|
}
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2395
|
+
: {}),
|
|
2396
|
+
envId: zod_1.z
|
|
2397
|
+
.string()
|
|
2398
|
+
.optional()
|
|
2399
|
+
.describe("环境ID(CloudBase 环境唯一标识),绑定后工具将操作该环境。action=set_env 时必填"),
|
|
2400
|
+
...(supportedAuthActions.includes("logout")
|
|
2401
|
+
? {
|
|
2402
|
+
confirm: zod_1.z
|
|
2403
|
+
.literal("yes")
|
|
2404
|
+
.optional()
|
|
2405
|
+
.describe("action=logout 时确认操作,传 yes"),
|
|
2406
|
+
}
|
|
2407
|
+
: {}),
|
|
2408
|
+
...(supportedAuthActions.includes("get_temp_credentials")
|
|
2409
|
+
? {
|
|
2410
|
+
reveal: zod_1.z
|
|
2411
|
+
.boolean()
|
|
2412
|
+
.optional()
|
|
2413
|
+
.describe("action=get_temp_credentials 时可选。true=返回明文临时密钥;默认 false 仅返回脱敏结果"),
|
|
2527
2414
|
}
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2415
|
+
: {}),
|
|
2416
|
+
},
|
|
2417
|
+
annotations: {
|
|
2418
|
+
readOnlyHint: false,
|
|
2419
|
+
destructiveHint: false,
|
|
2420
|
+
idempotentHint: false,
|
|
2421
|
+
openWorldHint: true,
|
|
2422
|
+
category: "env",
|
|
2423
|
+
},
|
|
2424
|
+
}, async (rawArgs) => {
|
|
2425
|
+
const action = rawArgs.action ?? "status";
|
|
2426
|
+
const authMode = rawArgs.authMode === "device" || rawArgs.authMode === "web"
|
|
2427
|
+
? rawArgs.authMode
|
|
2428
|
+
: undefined;
|
|
2429
|
+
const oauthEndpoint = normalizeOptionalToolString(rawArgs.oauthEndpoint);
|
|
2430
|
+
const clientId = normalizeOptionalToolString(rawArgs.clientId);
|
|
2431
|
+
const oauthCustom = normalizeOptionalToolBoolean(rawArgs.oauthCustom);
|
|
2432
|
+
const envId = rawArgs.envId;
|
|
2433
|
+
const confirm = rawArgs.confirm === "yes" ? "yes" : undefined;
|
|
2434
|
+
const reveal = normalizeOptionalToolBoolean(rawArgs.reveal) === true;
|
|
2435
|
+
const resolvedAuthOptions = resolveToolAuthOptions(server, {
|
|
2436
|
+
authMode,
|
|
2437
|
+
oauthEndpoint,
|
|
2438
|
+
clientId,
|
|
2439
|
+
oauthCustom,
|
|
2440
|
+
});
|
|
2441
|
+
const authConfigSummary = (0, auth_js_1.buildAuthConfigSummary)(resolvedAuthOptions);
|
|
2442
|
+
let deviceAuthInfo;
|
|
2443
|
+
const onDeviceCode = (info) => {
|
|
2444
|
+
deviceAuthInfo = info;
|
|
2445
|
+
(0, auth_js_1.setPendingAuthProgressState)(info, "device");
|
|
2446
|
+
// emitDeviceAuthNotice(server, info);
|
|
2447
|
+
};
|
|
2448
|
+
const authChallenge = () => (0, auth_js_1.buildDeviceAuthChallengePayload)(deviceAuthInfo);
|
|
2449
|
+
try {
|
|
2450
|
+
if (!supportedAuthActions.includes(action)) {
|
|
2541
2451
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2542
2452
|
ok: false,
|
|
2543
|
-
code: "
|
|
2544
|
-
message:
|
|
2545
|
-
auth_mode: "api_key",
|
|
2546
|
-
envId: process.env.CLOUDBASE_ENV_ID,
|
|
2547
|
-
endpoint,
|
|
2548
|
-
});
|
|
2549
|
-
}
|
|
2550
|
-
const region = server.cloudBaseOptions?.region || process.env.TCB_REGION;
|
|
2551
|
-
const auth = toolbox_1.AuthSupervisor.getInstance({});
|
|
2552
|
-
const authFlowState = await (0, auth_js_1.getAuthProgressState)();
|
|
2553
|
-
if (authFlowState.status === "PENDING" && authFlowState.authChallenge) {
|
|
2554
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2555
|
-
ok: true,
|
|
2556
|
-
code: "AUTH_PENDING",
|
|
2557
|
-
message: "设备码授权进行中,请在浏览器中打开 verification_uri 并输入 user_code 完成授权。",
|
|
2558
|
-
auth_challenge: (0, auth_js_1.buildDeviceAuthChallengePayload)(authFlowState.authChallenge),
|
|
2453
|
+
code: "NOT_SUPPORTED",
|
|
2454
|
+
message: `当前 IDE 不支持 auth(action="${action}")。`,
|
|
2559
2455
|
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
2560
2456
|
suggestedArgs: { action: "status" },
|
|
2561
2457
|
}),
|
|
2562
2458
|
});
|
|
2563
2459
|
}
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
const
|
|
2567
|
-
|
|
2568
|
-
|
|
2460
|
+
if (action === "status") {
|
|
2461
|
+
const loginState = await (0, auth_js_1.peekLoginState)();
|
|
2462
|
+
const authFlowState = await (0, auth_js_1.getAuthProgressState)();
|
|
2463
|
+
// 判断是否为 API Key 模式
|
|
2464
|
+
const isApiKeyMode = !!(process.env.CLOUDBASE_API_KEY && process.env.CLOUDBASE_ENV_ID);
|
|
2465
|
+
const authStatus = loginState
|
|
2466
|
+
? "READY"
|
|
2467
|
+
: authFlowState.status === "PENDING"
|
|
2468
|
+
? "PENDING"
|
|
2469
|
+
: "REQUIRED";
|
|
2470
|
+
let envPreparation;
|
|
2471
|
+
const message = authStatus === "READY"
|
|
2472
|
+
? undefined
|
|
2473
|
+
: authStatus === "PENDING"
|
|
2474
|
+
? "设备码授权进行中,请完成浏览器授权后再次调用 auth(action=\"status\")"
|
|
2475
|
+
: isCodeBuddyIde(server)
|
|
2476
|
+
? "当前未登录。CodeBuddy 暂不支持在 tool 内发起认证,请在外部完成认证后再次调用 auth(action=\"status\")。"
|
|
2477
|
+
: "当前未登录,请先执行 auth(action=\"start_auth\")";
|
|
2478
|
+
if (authStatus === "READY" && loginState) {
|
|
2479
|
+
envPreparation = await prepareAuthEnvironment({
|
|
2569
2480
|
server,
|
|
2570
2481
|
cloudBaseOptions,
|
|
2571
|
-
loginState
|
|
2572
|
-
});
|
|
2573
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2574
|
-
ok: true,
|
|
2575
|
-
code: "AUTH_READY",
|
|
2576
|
-
message: envPreparation.message,
|
|
2577
|
-
auth_challenge: authChallenge(),
|
|
2578
|
-
...buildAuthEnvSetupPayload(envPreparation),
|
|
2579
|
-
next_step: envPreparation.nextStep,
|
|
2482
|
+
loginState,
|
|
2580
2483
|
});
|
|
2581
2484
|
}
|
|
2582
|
-
}
|
|
2583
|
-
catch {
|
|
2584
|
-
// 忽略 getLoginState 错误,继续尝试发起登录
|
|
2585
|
-
}
|
|
2586
|
-
const validationError = (0, auth_js_1.getAuthConfigValidationError)(resolvedAuthOptions);
|
|
2587
|
-
if (validationError) {
|
|
2588
2485
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2589
|
-
ok:
|
|
2590
|
-
code: "
|
|
2591
|
-
|
|
2486
|
+
ok: true,
|
|
2487
|
+
code: "STATUS",
|
|
2488
|
+
auth_status: authStatus,
|
|
2489
|
+
...(isApiKeyMode ? { auth_mode: "api_key" } : {}),
|
|
2592
2490
|
auth_config: authConfigSummary,
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2491
|
+
...(envPreparation
|
|
2492
|
+
? buildAuthEnvSetupPayload(envPreparation)
|
|
2493
|
+
: {
|
|
2494
|
+
env_status: "NONE",
|
|
2495
|
+
current_env_id: null,
|
|
2496
|
+
...buildEnvCandidatePayload([]),
|
|
2497
|
+
}),
|
|
2498
|
+
auth_challenge: authFlowState.status === "PENDING"
|
|
2499
|
+
? (0, auth_js_1.buildDeviceAuthChallengePayload)(authFlowState.authChallenge)
|
|
2500
|
+
: undefined,
|
|
2501
|
+
message,
|
|
2502
|
+
next_step: authStatus === "REQUIRED"
|
|
2503
|
+
? buildAuthRequiredNextStep(server)
|
|
2504
|
+
: authStatus === "PENDING"
|
|
2505
|
+
? (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
2506
|
+
suggestedArgs: { action: "status" },
|
|
2507
|
+
})
|
|
2508
|
+
: envPreparation?.nextStep,
|
|
2596
2509
|
});
|
|
2597
2510
|
}
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
}
|
|
2612
|
-
};
|
|
2613
|
-
try {
|
|
2614
|
-
// 启动 Device Flow,全流程由 toolbox 负责轮询和写入 credential,这里不等待完成
|
|
2615
|
-
auth
|
|
2616
|
-
.loginByWebAuth({
|
|
2617
|
-
flow: "device",
|
|
2618
|
-
...(resolvedAuthOptions.clientId
|
|
2619
|
-
? { client_id: resolvedAuthOptions.clientId }
|
|
2620
|
-
: {}),
|
|
2621
|
-
...(resolvedAuthOptions.oauthEndpoint
|
|
2622
|
-
? { getOAuthEndpoint: () => resolvedAuthOptions.oauthEndpoint }
|
|
2623
|
-
: {}),
|
|
2624
|
-
...(resolvedAuthOptions.oauthCustom
|
|
2625
|
-
? { custom: true }
|
|
2626
|
-
: {}),
|
|
2627
|
-
onDeviceCode: deviceOnCode,
|
|
2628
|
-
})
|
|
2629
|
-
.then(() => {
|
|
2630
|
-
(0, auth_js_1.resolveAuthProgressState)();
|
|
2631
|
-
})
|
|
2632
|
-
.catch((err) => {
|
|
2633
|
-
(0, auth_js_1.rejectAuthProgressState)(err);
|
|
2634
|
-
// 如果在拿到 device code 之前就失败,则唤醒当前调用并返回错误
|
|
2635
|
-
if (!deviceAuthInfo && rejectCode) {
|
|
2636
|
-
rejectCode(err);
|
|
2511
|
+
if (action === "start_auth") {
|
|
2512
|
+
// API Key 模式:尝试换取临时密钥
|
|
2513
|
+
if (process.env.CLOUDBASE_API_KEY && process.env.CLOUDBASE_ENV_ID) {
|
|
2514
|
+
try {
|
|
2515
|
+
const existingLoginState = await (0, auth_js_1.peekLoginState)();
|
|
2516
|
+
if (existingLoginState) {
|
|
2517
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2518
|
+
ok: true,
|
|
2519
|
+
code: "AUTH_READY",
|
|
2520
|
+
message: "当前使用 API Key 认证模式,已自动完成登录,无需手动授权。",
|
|
2521
|
+
auth_mode: "api_key",
|
|
2522
|
+
envId: process.env.CLOUDBASE_ENV_ID,
|
|
2523
|
+
});
|
|
2637
2524
|
}
|
|
2525
|
+
}
|
|
2526
|
+
catch (e) {
|
|
2527
|
+
// peekLoginState 内部异常,记录后 fall through
|
|
2528
|
+
(0, logger_js_1.debug)("start_auth: peekLoginState threw", { error: e instanceof Error ? e.message : String(e) });
|
|
2529
|
+
}
|
|
2530
|
+
// API Key 换取失败:返回详细诊断信息
|
|
2531
|
+
// 尝试获取更详细的错误信息
|
|
2532
|
+
let diagMessage = "当前配置了 API Key 认证模式,但换取临时密钥失败。";
|
|
2533
|
+
const endpoint = process.env.CLOUDBASE_API_ENDPOINT || `https://${process.env.CLOUDBASE_ENV_ID}.ap-shanghai.tcb-api.tencentcloudapi.com`;
|
|
2534
|
+
diagMessage += `\n\n诊断信息:`;
|
|
2535
|
+
diagMessage += `\n- CLOUDBASE_ENV_ID: ${process.env.CLOUDBASE_ENV_ID}`;
|
|
2536
|
+
diagMessage += `\n- CLOUDBASE_API_KEY: ${process.env.CLOUDBASE_API_KEY.slice(0, 20)}...(已截断)`;
|
|
2537
|
+
diagMessage += `\n- Endpoint: ${endpoint}`;
|
|
2538
|
+
diagMessage += `\n\n可能原因:`;
|
|
2539
|
+
diagMessage += `\n1. API Key 已过期或被删除`;
|
|
2540
|
+
diagMessage += `\n2. Endpoint 不可达(网络/DNS 问题)`;
|
|
2541
|
+
diagMessage += `\n3. CLOUDBASE_ENV_ID 与 API Key 所属环境不匹配`;
|
|
2542
|
+
diagMessage += `\n\n建议:检查 MCP 配置中的 CLOUDBASE_API_KEY 和 CLOUDBASE_ENV_ID 环境变量是否正确。`;
|
|
2543
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2544
|
+
ok: false,
|
|
2545
|
+
code: "API_KEY_AUTH_FAILED",
|
|
2546
|
+
message: diagMessage,
|
|
2547
|
+
auth_mode: "api_key",
|
|
2548
|
+
envId: process.env.CLOUDBASE_ENV_ID,
|
|
2549
|
+
endpoint,
|
|
2638
2550
|
});
|
|
2639
2551
|
}
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2552
|
+
const region = server.cloudBaseOptions?.region || process.env.TCB_REGION;
|
|
2553
|
+
const auth = toolbox_1.AuthSupervisor.getInstance({});
|
|
2554
|
+
const authFlowState = await (0, auth_js_1.getAuthProgressState)();
|
|
2555
|
+
if (authFlowState.status === "PENDING" && authFlowState.authChallenge) {
|
|
2556
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2557
|
+
ok: true,
|
|
2558
|
+
code: "AUTH_PENDING",
|
|
2559
|
+
message: "设备码授权进行中,请在浏览器中打开 verification_uri 并输入 user_code 完成授权。",
|
|
2560
|
+
auth_challenge: (0, auth_js_1.buildDeviceAuthChallengePayload)(authFlowState.authChallenge),
|
|
2561
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
2562
|
+
suggestedArgs: { action: "status" },
|
|
2563
|
+
}),
|
|
2564
|
+
});
|
|
2644
2565
|
}
|
|
2566
|
+
// 1. 如果已经有登录态,直接返回 AUTH_READY
|
|
2645
2567
|
try {
|
|
2646
|
-
await
|
|
2568
|
+
const existingLoginState = await (0, auth_js_1.peekLoginState)();
|
|
2569
|
+
if (existingLoginState) {
|
|
2570
|
+
const envPreparation = await prepareAuthEnvironment({
|
|
2571
|
+
server,
|
|
2572
|
+
cloudBaseOptions,
|
|
2573
|
+
loginState: existingLoginState,
|
|
2574
|
+
});
|
|
2575
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2576
|
+
ok: true,
|
|
2577
|
+
code: "AUTH_READY",
|
|
2578
|
+
message: envPreparation.message,
|
|
2579
|
+
auth_challenge: authChallenge(),
|
|
2580
|
+
...buildAuthEnvSetupPayload(envPreparation),
|
|
2581
|
+
next_step: envPreparation.nextStep,
|
|
2582
|
+
});
|
|
2583
|
+
}
|
|
2647
2584
|
}
|
|
2648
|
-
catch
|
|
2649
|
-
|
|
2585
|
+
catch {
|
|
2586
|
+
// 忽略 getLoginState 错误,继续尝试发起登录
|
|
2587
|
+
}
|
|
2588
|
+
const validationError = (0, auth_js_1.getAuthConfigValidationError)(resolvedAuthOptions);
|
|
2589
|
+
if (validationError) {
|
|
2650
2590
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2651
2591
|
ok: false,
|
|
2652
|
-
code: "
|
|
2653
|
-
message:
|
|
2592
|
+
code: "INVALID_ARGS",
|
|
2593
|
+
message: validationError,
|
|
2594
|
+
auth_config: authConfigSummary,
|
|
2654
2595
|
next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
|
|
2655
2596
|
suggestedArgs: { action: "start_auth", authMode: "device" },
|
|
2656
2597
|
}),
|
|
2657
2598
|
});
|
|
2658
2599
|
}
|
|
2659
|
-
|
|
2600
|
+
// 2. 设备码模式:监听到 device code 即返回 AUTH_PENDING,后续由 toolbox 异步轮询并更新本地 credential
|
|
2601
|
+
const effectiveMode = resolvedAuthOptions.authMode;
|
|
2602
|
+
if (effectiveMode === "device") {
|
|
2603
|
+
let resolveCode;
|
|
2604
|
+
let rejectCode;
|
|
2605
|
+
const codeReady = new Promise((resolve, reject) => {
|
|
2606
|
+
resolveCode = resolve;
|
|
2607
|
+
rejectCode = reject;
|
|
2608
|
+
});
|
|
2609
|
+
const deviceOnCode = (info) => {
|
|
2610
|
+
onDeviceCode(info);
|
|
2611
|
+
if (resolveCode) {
|
|
2612
|
+
resolveCode();
|
|
2613
|
+
}
|
|
2614
|
+
};
|
|
2615
|
+
try {
|
|
2616
|
+
// 启动 Device Flow,全流程由 toolbox 负责轮询和写入 credential,这里不等待完成
|
|
2617
|
+
auth
|
|
2618
|
+
.loginByWebAuth({
|
|
2619
|
+
flow: "device",
|
|
2620
|
+
...(resolvedAuthOptions.clientId
|
|
2621
|
+
? { client_id: resolvedAuthOptions.clientId }
|
|
2622
|
+
: {}),
|
|
2623
|
+
...(resolvedAuthOptions.oauthEndpoint
|
|
2624
|
+
? { getOAuthEndpoint: () => resolvedAuthOptions.oauthEndpoint }
|
|
2625
|
+
: {}),
|
|
2626
|
+
...(resolvedAuthOptions.oauthCustom
|
|
2627
|
+
? { custom: true }
|
|
2628
|
+
: {}),
|
|
2629
|
+
onDeviceCode: deviceOnCode,
|
|
2630
|
+
})
|
|
2631
|
+
.then(() => {
|
|
2632
|
+
(0, auth_js_1.resolveAuthProgressState)();
|
|
2633
|
+
})
|
|
2634
|
+
.catch((err) => {
|
|
2635
|
+
(0, auth_js_1.rejectAuthProgressState)(err);
|
|
2636
|
+
// 如果在拿到 device code 之前就失败,则唤醒当前调用并返回错误
|
|
2637
|
+
if (!deviceAuthInfo && rejectCode) {
|
|
2638
|
+
rejectCode(err);
|
|
2639
|
+
}
|
|
2640
|
+
});
|
|
2641
|
+
}
|
|
2642
|
+
catch (err) {
|
|
2643
|
+
if (rejectCode) {
|
|
2644
|
+
rejectCode(err);
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
try {
|
|
2648
|
+
await codeReady;
|
|
2649
|
+
}
|
|
2650
|
+
catch (err) {
|
|
2651
|
+
const message = err instanceof Error ? err.message : String(err ?? "unknown error");
|
|
2652
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2653
|
+
ok: false,
|
|
2654
|
+
code: "AUTH_REQUIRED",
|
|
2655
|
+
message: `设备码登录初始化失败: ${message}`,
|
|
2656
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
|
|
2657
|
+
suggestedArgs: { action: "start_auth", authMode: "device" },
|
|
2658
|
+
}),
|
|
2659
|
+
});
|
|
2660
|
+
}
|
|
2661
|
+
if (!deviceAuthInfo) {
|
|
2662
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2663
|
+
ok: false,
|
|
2664
|
+
code: "AUTH_REQUIRED",
|
|
2665
|
+
message: "未获取到设备码信息,请重试设备码登录",
|
|
2666
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
|
|
2667
|
+
suggestedArgs: { action: "start_auth", authMode: "device" },
|
|
2668
|
+
}),
|
|
2669
|
+
});
|
|
2670
|
+
}
|
|
2671
|
+
const envCandidates = await fetchAvailableEnvCandidates(cloudBaseOptions, server);
|
|
2672
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2673
|
+
ok: true,
|
|
2674
|
+
code: "AUTH_PENDING",
|
|
2675
|
+
message: "已发起设备码登录,请在浏览器中打开 verification_uri 并输入 user_code 完成授权。授权完成后请再次调用 auth(action=\"status\")。",
|
|
2676
|
+
auth_challenge: authChallenge(),
|
|
2677
|
+
...buildEnvCandidatePayload(envCandidates),
|
|
2678
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
2679
|
+
suggestedArgs: { action: "status" },
|
|
2680
|
+
}),
|
|
2681
|
+
});
|
|
2682
|
+
}
|
|
2683
|
+
// 3. 非 Device Flow(显式 web 模式)仍然使用 getLoginState 阻塞等待
|
|
2684
|
+
const loginState = await (0, auth_js_1.ensureLogin)({
|
|
2685
|
+
region,
|
|
2686
|
+
authMode: effectiveMode,
|
|
2687
|
+
clientId: resolvedAuthOptions.clientId,
|
|
2688
|
+
oauthEndpoint: resolvedAuthOptions.oauthEndpoint,
|
|
2689
|
+
oauthCustom: resolvedAuthOptions.oauthCustom,
|
|
2690
|
+
});
|
|
2691
|
+
if (!loginState) {
|
|
2660
2692
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2661
2693
|
ok: false,
|
|
2662
2694
|
code: "AUTH_REQUIRED",
|
|
2663
|
-
message: "
|
|
2695
|
+
message: "未获取到登录态,请先完成认证",
|
|
2664
2696
|
next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
|
|
2665
|
-
suggestedArgs: { action: "start_auth", authMode:
|
|
2697
|
+
suggestedArgs: { action: "start_auth", authMode: effectiveMode },
|
|
2666
2698
|
}),
|
|
2667
2699
|
});
|
|
2668
2700
|
}
|
|
2669
|
-
const
|
|
2701
|
+
const envPreparation = await prepareAuthEnvironment({
|
|
2702
|
+
server,
|
|
2703
|
+
cloudBaseOptions,
|
|
2704
|
+
loginState,
|
|
2705
|
+
});
|
|
2670
2706
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2671
2707
|
ok: true,
|
|
2672
|
-
code: "
|
|
2673
|
-
message:
|
|
2708
|
+
code: "AUTH_READY",
|
|
2709
|
+
message: envPreparation.message,
|
|
2674
2710
|
auth_challenge: authChallenge(),
|
|
2675
|
-
...
|
|
2676
|
-
next_step:
|
|
2677
|
-
suggestedArgs: { action: "status" },
|
|
2678
|
-
}),
|
|
2711
|
+
...buildAuthEnvSetupPayload(envPreparation),
|
|
2712
|
+
next_step: envPreparation.nextStep,
|
|
2679
2713
|
});
|
|
2680
2714
|
}
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
const loginState = await (0, auth_js_1.peekLoginState)();
|
|
2715
|
-
if (!loginState) {
|
|
2716
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2717
|
-
ok: false,
|
|
2718
|
-
code: "AUTH_REQUIRED",
|
|
2719
|
-
message: isCodeBuddyIde(server)
|
|
2720
|
-
? "当前未登录。CodeBuddy 暂不支持在 tool 内发起认证,请在外部完成认证后再次调用 auth(action=\"status\")。"
|
|
2721
|
-
: "当前未登录,请先执行 auth(action=\"start_auth\")。",
|
|
2722
|
-
next_step: buildAuthRequiredNextStep(server),
|
|
2723
|
-
});
|
|
2724
|
-
}
|
|
2725
|
-
const envCandidates = await fetchAvailableEnvCandidates(cloudBaseOptions, server);
|
|
2726
|
-
if (!envId) {
|
|
2727
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2728
|
-
ok: false,
|
|
2729
|
-
code: "INVALID_ARGS",
|
|
2730
|
-
message: "action=set_env 时必须提供 envId",
|
|
2731
|
-
...buildEnvCandidatePayload(envCandidates),
|
|
2732
|
-
next_step: buildSetEnvNextStep(envCandidates),
|
|
2733
|
-
});
|
|
2734
|
-
}
|
|
2735
|
-
const target = envCandidates.find((item) => item.envId === envId);
|
|
2736
|
-
if (envCandidates.length > 0 && !target) {
|
|
2715
|
+
if (action === "set_env") {
|
|
2716
|
+
const loginState = await (0, auth_js_1.peekLoginState)();
|
|
2717
|
+
if (!loginState) {
|
|
2718
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2719
|
+
ok: false,
|
|
2720
|
+
code: "AUTH_REQUIRED",
|
|
2721
|
+
message: isCodeBuddyIde(server)
|
|
2722
|
+
? "当前未登录。CodeBuddy 暂不支持在 tool 内发起认证,请在外部完成认证后再次调用 auth(action=\"status\")。"
|
|
2723
|
+
: "当前未登录,请先执行 auth(action=\"start_auth\")。",
|
|
2724
|
+
next_step: buildAuthRequiredNextStep(server),
|
|
2725
|
+
});
|
|
2726
|
+
}
|
|
2727
|
+
const envCandidates = await fetchAvailableEnvCandidates(cloudBaseOptions, server);
|
|
2728
|
+
if (!envId) {
|
|
2729
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2730
|
+
ok: false,
|
|
2731
|
+
code: "INVALID_ARGS",
|
|
2732
|
+
message: "action=set_env 时必须提供 envId",
|
|
2733
|
+
...buildEnvCandidatePayload(envCandidates),
|
|
2734
|
+
next_step: buildSetEnvNextStep(envCandidates),
|
|
2735
|
+
});
|
|
2736
|
+
}
|
|
2737
|
+
const target = envCandidates.find((item) => item.envId === envId);
|
|
2738
|
+
if (envCandidates.length > 0 && !target) {
|
|
2739
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2740
|
+
ok: false,
|
|
2741
|
+
code: "INVALID_ARGS",
|
|
2742
|
+
message: `未找到环境: ${envId}`,
|
|
2743
|
+
...buildEnvCandidatePayload(envCandidates),
|
|
2744
|
+
next_step: buildSetEnvNextStep(envCandidates),
|
|
2745
|
+
});
|
|
2746
|
+
}
|
|
2747
|
+
await cloudbase_manager_js_1.envManager.setEnvId(envId);
|
|
2737
2748
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2738
|
-
ok:
|
|
2739
|
-
code: "
|
|
2740
|
-
message:
|
|
2741
|
-
|
|
2742
|
-
next_step: buildSetEnvNextStep(envCandidates),
|
|
2749
|
+
ok: true,
|
|
2750
|
+
code: "ENV_READY",
|
|
2751
|
+
message: `环境设置成功,当前环境: ${envId}`,
|
|
2752
|
+
current_env_id: envId,
|
|
2743
2753
|
});
|
|
2744
2754
|
}
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2755
|
+
if (action === "logout") {
|
|
2756
|
+
// API Key 模式下不允许 logout
|
|
2757
|
+
if (process.env.CLOUDBASE_API_KEY && process.env.CLOUDBASE_ENV_ID) {
|
|
2758
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2759
|
+
ok: false,
|
|
2760
|
+
code: "LOGOUT_NOT_ALLOWED",
|
|
2761
|
+
message: "当前使用 API Key 认证模式,不支持退出登录。如需切换认证方式,请移除 CLOUDBASE_API_KEY 环境变量后重启。",
|
|
2762
|
+
auth_mode: "api_key",
|
|
2763
|
+
});
|
|
2764
|
+
}
|
|
2765
|
+
if (confirm !== "yes") {
|
|
2766
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2767
|
+
ok: false,
|
|
2768
|
+
code: "INVALID_ARGS",
|
|
2769
|
+
message: "action=logout 时必须传 confirm=\"yes\"",
|
|
2770
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("logout", {
|
|
2771
|
+
suggestedArgs: { action: "logout", confirm: "yes" },
|
|
2772
|
+
}),
|
|
2773
|
+
});
|
|
2774
|
+
}
|
|
2775
|
+
await (0, auth_js_1.logout)();
|
|
2776
|
+
(0, cloudbase_manager_js_1.resetCloudBaseManagerCache)();
|
|
2756
2777
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2757
|
-
ok:
|
|
2758
|
-
code: "
|
|
2759
|
-
message: "
|
|
2760
|
-
auth_mode: "api_key",
|
|
2778
|
+
ok: true,
|
|
2779
|
+
code: "LOGGED_OUT",
|
|
2780
|
+
message: "✅ 已退出登录",
|
|
2761
2781
|
});
|
|
2762
2782
|
}
|
|
2763
|
-
if (
|
|
2783
|
+
if (action === "get_temp_credentials") {
|
|
2784
|
+
const loginState = (await (0, auth_js_1.peekLoginState)());
|
|
2785
|
+
if (!loginState) {
|
|
2786
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2787
|
+
ok: false,
|
|
2788
|
+
code: "AUTH_REQUIRED",
|
|
2789
|
+
message: "当前未登录,请先完成管理端认证后再获取临时密钥。",
|
|
2790
|
+
next_step: buildAuthRequiredNextStep(server),
|
|
2791
|
+
});
|
|
2792
|
+
}
|
|
2793
|
+
if (confirm !== "yes") {
|
|
2794
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2795
|
+
ok: false,
|
|
2796
|
+
code: "INVALID_ARGS",
|
|
2797
|
+
message: "action=get_temp_credentials 时必须显式传 confirm=\"yes\",以确认你要导出当前管理端临时密钥。",
|
|
2798
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("get_temp_credentials", {
|
|
2799
|
+
suggestedArgs: { action: "get_temp_credentials", confirm: "yes" },
|
|
2800
|
+
}),
|
|
2801
|
+
});
|
|
2802
|
+
}
|
|
2803
|
+
if (!isTemporaryCredentialLoginState(loginState)) {
|
|
2804
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2805
|
+
ok: false,
|
|
2806
|
+
code: "UNSUPPORTED_CREDENTIAL_TYPE",
|
|
2807
|
+
message: "当前登录态不是可导出的临时密钥。仅支持通过 Web / device 登录得到的临时密钥,永久密钥登录不允许导出。",
|
|
2808
|
+
});
|
|
2809
|
+
}
|
|
2810
|
+
const secretId = normalizeOptionalToolString(loginState.secretId);
|
|
2811
|
+
const secretKey = normalizeOptionalToolString(loginState.secretKey);
|
|
2812
|
+
const token = normalizeOptionalToolString(loginState.token);
|
|
2813
|
+
if (!secretId || !secretKey || !token) {
|
|
2814
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2815
|
+
ok: false,
|
|
2816
|
+
code: "INTERNAL_ERROR",
|
|
2817
|
+
message: "当前登录态缺少完整的临时密钥字段,请重新登录后再试。",
|
|
2818
|
+
});
|
|
2819
|
+
}
|
|
2764
2820
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2765
|
-
ok:
|
|
2766
|
-
code: "
|
|
2767
|
-
message:
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2821
|
+
ok: true,
|
|
2822
|
+
code: "TEMP_CREDENTIALS_READY",
|
|
2823
|
+
message: reveal
|
|
2824
|
+
? "当前管理端临时密钥已准备好,请注意避免泄露。"
|
|
2825
|
+
: "当前管理端临时密钥已准备好,默认仅返回脱敏结果。",
|
|
2826
|
+
env_id: normalizeOptionalToolString(loginState.envId) ?? null,
|
|
2827
|
+
credentials: {
|
|
2828
|
+
secretId: reveal ? secretId : maskSensitiveValue(secretId),
|
|
2829
|
+
secretKey: reveal ? secretKey : maskSensitiveValue(secretKey),
|
|
2830
|
+
token: reveal ? token : maskSensitiveValue(token),
|
|
2831
|
+
masked: !reveal,
|
|
2832
|
+
},
|
|
2771
2833
|
});
|
|
2772
2834
|
}
|
|
2773
|
-
await (0, auth_js_1.logout)();
|
|
2774
|
-
(0, cloudbase_manager_js_1.resetCloudBaseManagerCache)();
|
|
2775
2835
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2776
|
-
ok:
|
|
2777
|
-
code: "
|
|
2778
|
-
message:
|
|
2836
|
+
ok: false,
|
|
2837
|
+
code: "NOT_SUPPORTED",
|
|
2838
|
+
message: `不支持的 auth action: ${action}`,
|
|
2839
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
2840
|
+
suggestedArgs: { action: "status" },
|
|
2841
|
+
}),
|
|
2779
2842
|
});
|
|
2780
2843
|
}
|
|
2781
|
-
|
|
2782
|
-
const
|
|
2783
|
-
if (!loginState) {
|
|
2784
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2785
|
-
ok: false,
|
|
2786
|
-
code: "AUTH_REQUIRED",
|
|
2787
|
-
message: "当前未登录,请先完成管理端认证后再获取临时密钥。",
|
|
2788
|
-
next_step: buildAuthRequiredNextStep(server),
|
|
2789
|
-
});
|
|
2790
|
-
}
|
|
2791
|
-
if (confirm !== "yes") {
|
|
2792
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2793
|
-
ok: false,
|
|
2794
|
-
code: "INVALID_ARGS",
|
|
2795
|
-
message: "action=get_temp_credentials 时必须显式传 confirm=\"yes\",以确认你要导出当前管理端临时密钥。",
|
|
2796
|
-
next_step: (0, tool_result_js_1.buildAuthNextStep)("get_temp_credentials", {
|
|
2797
|
-
suggestedArgs: { action: "get_temp_credentials", confirm: "yes" },
|
|
2798
|
-
}),
|
|
2799
|
-
});
|
|
2800
|
-
}
|
|
2801
|
-
if (!isTemporaryCredentialLoginState(loginState)) {
|
|
2802
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2803
|
-
ok: false,
|
|
2804
|
-
code: "UNSUPPORTED_CREDENTIAL_TYPE",
|
|
2805
|
-
message: "当前登录态不是可导出的临时密钥。仅支持通过 Web / device 登录得到的临时密钥,永久密钥登录不允许导出。",
|
|
2806
|
-
});
|
|
2807
|
-
}
|
|
2808
|
-
const secretId = normalizeOptionalToolString(loginState.secretId);
|
|
2809
|
-
const secretKey = normalizeOptionalToolString(loginState.secretKey);
|
|
2810
|
-
const token = normalizeOptionalToolString(loginState.token);
|
|
2811
|
-
if (!secretId || !secretKey || !token) {
|
|
2812
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2813
|
-
ok: false,
|
|
2814
|
-
code: "INTERNAL_ERROR",
|
|
2815
|
-
message: "当前登录态缺少完整的临时密钥字段,请重新登录后再试。",
|
|
2816
|
-
});
|
|
2817
|
-
}
|
|
2844
|
+
catch (error) {
|
|
2845
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2818
2846
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2819
|
-
ok:
|
|
2820
|
-
code: "
|
|
2821
|
-
message:
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
secretId: reveal ? secretId : maskSensitiveValue(secretId),
|
|
2827
|
-
secretKey: reveal ? secretKey : maskSensitiveValue(secretKey),
|
|
2828
|
-
token: reveal ? token : maskSensitiveValue(token),
|
|
2829
|
-
masked: !reveal,
|
|
2830
|
-
},
|
|
2847
|
+
ok: false,
|
|
2848
|
+
code: "INTERNAL_ERROR",
|
|
2849
|
+
message: `auth 执行失败: ${message}`,
|
|
2850
|
+
auth_challenge: authChallenge(),
|
|
2851
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
2852
|
+
suggestedArgs: { action: "status" },
|
|
2853
|
+
}),
|
|
2831
2854
|
});
|
|
2832
2855
|
}
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
2838
|
-
suggestedArgs: { action: "status" },
|
|
2839
|
-
}),
|
|
2840
|
-
});
|
|
2841
|
-
}
|
|
2842
|
-
catch (error) {
|
|
2843
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
2844
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2845
|
-
ok: false,
|
|
2846
|
-
code: "INTERNAL_ERROR",
|
|
2847
|
-
message: `auth 执行失败: ${message}`,
|
|
2848
|
-
auth_challenge: authChallenge(),
|
|
2849
|
-
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
2850
|
-
suggestedArgs: { action: "status" },
|
|
2851
|
-
}),
|
|
2852
|
-
});
|
|
2853
|
-
}
|
|
2854
|
-
});
|
|
2855
|
-
// envQuery - 环境查询(合并 listEnvs + getEnvInfo + getEnvAuthDomains)
|
|
2856
|
-
server.registerTool?.("envQuery", {
|
|
2857
|
-
title: "CloudBase 环境查询",
|
|
2858
|
-
description: "查询 CloudBase 环境相关信息,支持查询环境列表、指定环境详情和安全域名。(原工具名:listEnvs/getEnvInfo/getEnvAuthDomains,为兼容旧AI规则可继续使用这些名称)当 action=list 时,会按 DescribeEnvs 语义做列表/筛选,标准返回字段为 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault,并支持通过 fields 白名单裁剪这些字段;aliasExact=true 时会按别名精确筛选,避免把前缀相近的环境误当作候选;即使传入 envId,action=list 也只返回摘要,不会返回完整资源明细或 expiry。如需查询某个已知 EnvId 对应环境的详细信息(包括资源字段和计费信息),必须使用 action=info 并传入目标环境的 envId 参数。action=info 会在可用时补充 BillingInfo(如 ExpireTime、PayMode、IsAutoRenew 等计费字段)。",
|
|
2859
|
-
inputSchema: {
|
|
2860
|
-
action: zod_1.z
|
|
2861
|
-
.enum(["list", "info", "domains"])
|
|
2862
|
-
.describe("查询类型:list=环境列表/摘要筛选(按 DescribeEnvs 语义筛选,支持通过 envId 筛选,返回 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault,不支持 expiry),info=指定环境的详细信息(必须传入 envId,返回资源字段和计费信息),domains=安全域名列表"),
|
|
2863
|
-
alias: zod_1.z.string().optional().describe("按环境别名筛选。action=list 时可选"),
|
|
2864
|
-
aliasExact: zod_1.z.boolean().optional().describe("按环境别名精确筛选。action=list 时可选;与 alias 配合使用"),
|
|
2865
|
-
envId: zod_1.z.string().optional().describe("按环境 ID 筛选。action=list 时可选(仅按 DescribeEnvs 语义做筛选,仍返回摘要);action=info 时必填(返回该环境的详细信息,包含资源字段和计费信息)。如果任务已经给出了明确的 EnvId 并要求查询详情,请直接使用 action=info + envId,而不是 action=list"),
|
|
2866
|
-
limit: zod_1.z.number().int().positive().optional().describe("返回数量上限。action=list 时可选"),
|
|
2867
|
-
offset: zod_1.z.number().int().min(0).optional().describe("分页偏移。action=list 时可选"),
|
|
2868
|
-
fields: zod_1.z
|
|
2869
|
-
.array(zod_1.z.enum(DEFAULT_ENV_FIELDS))
|
|
2870
|
-
.optional()
|
|
2871
|
-
.describe("返回字段白名单。仅支持 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault。action=list 时可选"),
|
|
2872
|
-
},
|
|
2873
|
-
annotations: {
|
|
2874
|
-
readOnlyHint: true,
|
|
2875
|
-
openWorldHint: true,
|
|
2876
|
-
category: "env",
|
|
2877
|
-
},
|
|
2878
|
-
}, async ({ action, alias, aliasExact, envId, limit, offset, fields, }) => {
|
|
2856
|
+
});
|
|
2857
|
+
} // end: wxide guard for auth tool
|
|
2858
|
+
// queryEnv - 环境查询(合并 listEnvs + getEnvInfo + getEnvAuthDomains)
|
|
2859
|
+
const queryEnvHandler = async ({ action, alias, aliasExact, envId, limit, offset, fields, }) => {
|
|
2879
2860
|
try {
|
|
2880
2861
|
let result;
|
|
2881
2862
|
switch (action) {
|
|
@@ -2889,7 +2870,8 @@ function registerEnvTools(server) {
|
|
|
2889
2870
|
// 当环境变量设置了 CLOUDBASE_ENV_ID 时(如 API Key 模式),
|
|
2890
2871
|
// 避免调用 DescribeEnvs(临时密钥可能不支持该接口),
|
|
2891
2872
|
// 改为通过 DescribeEnvInfo 获取单环境信息
|
|
2892
|
-
|
|
2873
|
+
// 注意:requestFn 模式(如微信 IDE)使用 DescribeEnvs,不走此分支
|
|
2874
|
+
const envIdFromEnv = !cloudBaseOptions?.requestFn && process.env.CLOUDBASE_ENV_ID;
|
|
2893
2875
|
if (envIdFromEnv) {
|
|
2894
2876
|
try {
|
|
2895
2877
|
const envInfo = await cloudbaseList.env.describeEnvInfo({ EnvId: envIdFromEnv });
|
|
@@ -3056,61 +3038,91 @@ function registerEnvTools(server) {
|
|
|
3056
3038
|
],
|
|
3057
3039
|
};
|
|
3058
3040
|
}
|
|
3059
|
-
}
|
|
3060
|
-
//
|
|
3061
|
-
|
|
3062
|
-
title: "CloudBase
|
|
3063
|
-
description: "
|
|
3041
|
+
};
|
|
3042
|
+
// Register primary tool name (queryEnv)
|
|
3043
|
+
const queryEnvToolSchema = {
|
|
3044
|
+
title: "CloudBase 环境查询",
|
|
3045
|
+
description: "查询 CloudBase 环境相关信息,支持查询环境列表、指定环境详情和安全域名。(曾用名:envQuery、listEnvs、getEnvInfo、getEnvAuthDomains)当 action=list 时,会按 DescribeEnvs 语义做列表/筛选,标准返回字段为 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault,并支持通过 fields 白名单裁剪这些字段;aliasExact=true 时会按别名精确筛选,避免把前缀相近的环境误当作候选;即使传入 envId,action=list 也只返回摘要,不会返回完整资源明细或 expiry。如需查询某个已知 EnvId 对应环境的详细信息(包括资源字段和计费信息),必须使用 action=info 并传入目标环境的 envId 参数。action=info 会在可用时补充 BillingInfo(如 ExpireTime、PayMode、IsAutoRenew 等计费字段)。",
|
|
3064
3046
|
inputSchema: {
|
|
3065
3047
|
action: zod_1.z
|
|
3066
|
-
.enum(["
|
|
3067
|
-
.describe("
|
|
3068
|
-
|
|
3048
|
+
.enum(["list", "info", "domains"])
|
|
3049
|
+
.describe("查询类型:list=环境列表/摘要筛选(按 DescribeEnvs 语义筛选,支持通过 envId 筛选,返回 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault,不支持 expiry),info=指定环境的详细信息(必须传入 envId,返回资源字段和计费信息),domains=安全域名列表"),
|
|
3050
|
+
alias: zod_1.z.string().optional().describe("按环境别名筛选。action=list 时可选"),
|
|
3051
|
+
aliasExact: zod_1.z.boolean().optional().describe("按环境别名精确筛选。action=list 时可选;与 alias 配合使用"),
|
|
3052
|
+
envId: zod_1.z.string().optional().describe("按环境 ID 筛选。action=list 时可选(仅按 DescribeEnvs 语义做筛选,仍返回摘要);action=info 时必填(返回该环境的详细信息,包含资源字段和计费信息)。如果任务已经给出了明确的 EnvId 并要求查询详情,请直接使用 action=info + envId,而不是 action=list"),
|
|
3053
|
+
limit: zod_1.z.number().int().positive().optional().describe("返回数量上限。action=list 时可选"),
|
|
3054
|
+
offset: zod_1.z.number().int().min(0).optional().describe("分页偏移。action=list 时可选"),
|
|
3055
|
+
fields: zod_1.z
|
|
3056
|
+
.array(zod_1.z.enum(DEFAULT_ENV_FIELDS))
|
|
3057
|
+
.optional()
|
|
3058
|
+
.describe("返回字段白名单。仅支持 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault。action=list 时可选"),
|
|
3069
3059
|
},
|
|
3070
3060
|
annotations: {
|
|
3071
|
-
readOnlyHint:
|
|
3072
|
-
destructiveHint: false, // 注意:delete操作虽然是破坏性的,但这里采用较宽松的标注
|
|
3073
|
-
idempotentHint: false,
|
|
3061
|
+
readOnlyHint: true,
|
|
3074
3062
|
openWorldHint: true,
|
|
3075
3063
|
category: "env",
|
|
3076
3064
|
},
|
|
3077
|
-
}
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3065
|
+
};
|
|
3066
|
+
server.registerTool?.("queryEnv", queryEnvToolSchema, queryEnvHandler);
|
|
3067
|
+
// 向后兼容:envQuery 作为 queryEnv 的别名注册
|
|
3068
|
+
server.registerTool?.("envQuery", queryEnvToolSchema, queryEnvHandler);
|
|
3069
|
+
// envDomainManagement - 环境域名管理(合并 createEnvDomain + deleteEnvDomain)
|
|
3070
|
+
// 微信 IDE 场景不需要域名管理
|
|
3071
|
+
if (server.ide !== 'wxide') {
|
|
3072
|
+
server.registerTool?.("envDomainManagement", {
|
|
3073
|
+
title: "CloudBase 环境域名管理(安全域名 / CORS 白名单)",
|
|
3074
|
+
description: "管理 CloudBase 环境的安全域名(安全域名 / CORS 白名单),支持添加和删除操作。(原工具名:createEnvDomain/deleteEnvDomain,为兼容旧AI规则可继续使用这些名称)当浏览器 Web 应用需要从本地 Vite / dev server 直接访问 CloudBase 资源时,应先用 queryEnv(action=domains) 检查当前实际浏览器 origin 对应的 host:port 是否已在白名单中,再按该实际值添加。新增或删除后通常需要继续轮询 queryEnv(action=domains) 确认状态收敛;安全域名一般约 10 分钟生效。⚠️ 重要:此工具仅用于 CORS/请求来源验证,不涉及 SSL 证书。如需绑定自定义域名供公网 HTTPS 访问,请使用 manageGateway(action=\"bindCustomDomain\")。",
|
|
3075
|
+
inputSchema: {
|
|
3076
|
+
action: zod_1.z
|
|
3077
|
+
.enum(["create", "delete"])
|
|
3078
|
+
.describe("操作类型:create=添加安全域名,delete=删除安全域名"),
|
|
3079
|
+
domains: zod_1.z.array(zod_1.z.string()).describe("安全域名数组(格式:host:port,例如 localhost:5173 或 127.0.0.1:4173)。注意:不是自定义域名,不需要证书。"),
|
|
3080
|
+
},
|
|
3081
|
+
annotations: {
|
|
3082
|
+
readOnlyHint: false,
|
|
3083
|
+
destructiveHint: false, // 注意:delete操作虽然是破坏性的,但这里采用较宽松的标注
|
|
3084
|
+
idempotentHint: false,
|
|
3085
|
+
openWorldHint: true,
|
|
3086
|
+
category: "env",
|
|
3087
|
+
},
|
|
3088
|
+
}, async ({ action, domains, }) => {
|
|
3089
|
+
try {
|
|
3090
|
+
const cloudbase = await getManager();
|
|
3091
|
+
let result;
|
|
3092
|
+
switch (action) {
|
|
3093
|
+
case "create":
|
|
3094
|
+
result = await cloudbase.env.createEnvDomain(domains);
|
|
3095
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
3096
|
+
break;
|
|
3097
|
+
case "delete":
|
|
3098
|
+
result = await cloudbase.env.deleteEnvDomain(domains);
|
|
3099
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
3100
|
+
break;
|
|
3101
|
+
default:
|
|
3102
|
+
throw new Error(`不支持的操作类型: ${action}`);
|
|
3103
|
+
}
|
|
3104
|
+
return (0, tool_result_js_1.buildJsonToolResult)(buildEnvDomainManagementResult({
|
|
3105
|
+
action,
|
|
3106
|
+
domains,
|
|
3107
|
+
result,
|
|
3108
|
+
}));
|
|
3092
3109
|
}
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3110
|
+
catch (error) {
|
|
3111
|
+
const toolPayloadResult = (0, tool_result_js_1.toolPayloadErrorToResult)(error);
|
|
3112
|
+
if (toolPayloadResult) {
|
|
3113
|
+
return toolPayloadResult;
|
|
3114
|
+
}
|
|
3115
|
+
return {
|
|
3116
|
+
content: [
|
|
3117
|
+
{
|
|
3118
|
+
type: "text",
|
|
3119
|
+
text: `域名管理操作失败: ${error instanceof Error ? error.message : String(error)}`,
|
|
3120
|
+
},
|
|
3121
|
+
],
|
|
3122
|
+
};
|
|
3103
3123
|
}
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
{
|
|
3107
|
-
type: "text",
|
|
3108
|
-
text: `域名管理操作失败: ${error instanceof Error ? error.message : String(error)}`,
|
|
3109
|
-
},
|
|
3110
|
-
],
|
|
3111
|
-
};
|
|
3112
|
-
}
|
|
3113
|
-
});
|
|
3124
|
+
});
|
|
3125
|
+
} // end: wxide guard for envDomainManagement
|
|
3114
3126
|
}
|
|
3115
3127
|
|
|
3116
3128
|
|
|
@@ -24985,8 +24997,9 @@ async function getDatabaseInstanceId(options) {
|
|
|
24985
24997
|
async function getCloudBaseManager(options = {}) {
|
|
24986
24998
|
const { requireEnvId = true, cloudBaseOptions, authStrategy = 'fail_fast', } = options;
|
|
24987
24999
|
const hasDirectCredentials = !!(cloudBaseOptions?.secretId && cloudBaseOptions?.secretKey);
|
|
24988
|
-
|
|
24989
|
-
|
|
25000
|
+
const hasRequestFn = !!(cloudBaseOptions?.requestFn);
|
|
25001
|
+
// 如果传入了完整凭据或 requestFn,优先使用显式 CloudBase 配置
|
|
25002
|
+
if (cloudBaseOptions && (hasDirectCredentials || hasRequestFn)) {
|
|
24990
25003
|
let resolvedEnvId = cloudBaseOptions.envId;
|
|
24991
25004
|
if (requireEnvId && !resolvedEnvId) {
|
|
24992
25005
|
const envCandidates = await listAvailableEnvCandidates({ cloudBaseOptions });
|
|
@@ -40929,8 +40942,8 @@ function registerSQLDatabaseTools(server) {
|
|
|
40929
40942
|
server,
|
|
40930
40943
|
};
|
|
40931
40944
|
server.registerTool?.(QUERY_SQL_DATABASE, {
|
|
40932
|
-
title: "
|
|
40933
|
-
description: "
|
|
40945
|
+
title: "查询 CloudBase MySQL 数据库状态或执行只读 SQL",
|
|
40946
|
+
description: "查询 CloudBase MySQL 数据库信息。支持执行只读 SQL、查询 MySQL 开通结果、查询 MySQL 任务状态,以及获取当前实例上下文信息。",
|
|
40934
40947
|
inputSchema: {
|
|
40935
40948
|
action: zod_1.z
|
|
40936
40949
|
.enum(QUERY_ACTIONS)
|
|
@@ -40972,8 +40985,8 @@ function registerSQLDatabaseTools(server) {
|
|
|
40972
40985
|
}
|
|
40973
40986
|
});
|
|
40974
40987
|
server.registerTool?.(MANAGE_SQL_DATABASE, {
|
|
40975
|
-
title: "
|
|
40976
|
-
description: "
|
|
40988
|
+
title: "管理 CloudBase MySQL 数据库生命周期或执行写入 SQL",
|
|
40989
|
+
description: "管理 CloudBase MySQL 数据库资源。支持开通 MySQL、销毁 MySQL、执行写入 SQL/DDL,以及初始化数据库 Schema。注意:必须先开通 MySQL(action=provisionMySQL,confirm=true)才能执行 runStatement 或 initializeSchema。若 MySQL 尚未开通,工具会返回 MYSQL_NOT_CREATED 并给出开通的 nextAction 提示。",
|
|
40977
40990
|
inputSchema: {
|
|
40978
40991
|
action: zod_1.z
|
|
40979
40992
|
.enum(MANAGE_ACTIONS)
|
|
@@ -55763,7 +55776,7 @@ if (shouldUseConsole()) {
|
|
|
55763
55776
|
stderrLevels: ['error', 'warn', 'info', 'debug'], // All logs go to stderr
|
|
55764
55777
|
}));
|
|
55765
55778
|
}
|
|
55766
|
-
if (!(0, cloud_mode_js_1.isCloudMode)()) {
|
|
55779
|
+
if (!(0, cloud_mode_js_1.isCloudMode)() && process.env.CLOUDBASE_MCP_DISABLE_LOG_FILE !== 'true') {
|
|
55767
55780
|
// File transport with daily rotation
|
|
55768
55781
|
transports.push(new DailyRotateFile({
|
|
55769
55782
|
dirname: logDir,
|
|
@@ -88853,6 +88866,7 @@ exports.MANAGE_FUNCTION_ACTIONS = [
|
|
|
88853
88866
|
"attachLayer",
|
|
88854
88867
|
"detachLayer",
|
|
88855
88868
|
"updateFunctionLayers",
|
|
88869
|
+
"incrementalDeployFunction", // 增量部署,需通过 pluginOptions.functions 注入实现
|
|
88856
88870
|
];
|
|
88857
88871
|
const VPC_SCHEMA = zod_1.z.object({
|
|
88858
88872
|
vpcId: zod_1.z.string(),
|
|
@@ -89034,6 +89048,7 @@ function wrapFunctionOperationError(operation, functionName, functionRootPath, e
|
|
|
89034
89048
|
}
|
|
89035
89049
|
function registerFunctionTools(server) {
|
|
89036
89050
|
const cloudBaseOptions = server.cloudBaseOptions;
|
|
89051
|
+
const deployOverrides = server.pluginOptions?.functions;
|
|
89037
89052
|
const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions });
|
|
89038
89053
|
const buildEnvelope = (data, message, nextActions) => ({
|
|
89039
89054
|
success: true,
|
|
@@ -89398,6 +89413,16 @@ function registerFunctionTools(server) {
|
|
|
89398
89413
|
ensureActionAllowedInCloudMode(input);
|
|
89399
89414
|
switch (input.action) {
|
|
89400
89415
|
case "createFunction": {
|
|
89416
|
+
if (deployOverrides?.createFunction) {
|
|
89417
|
+
const result = await deployOverrides.createFunction({
|
|
89418
|
+
functionName: String(input.func?.name ?? input.functionName ?? ''),
|
|
89419
|
+
functionRootPath: input.functionRootPath ?? '',
|
|
89420
|
+
runtime: input.func?.runtime,
|
|
89421
|
+
force: input.force,
|
|
89422
|
+
installDependency: input.func?.installDependency,
|
|
89423
|
+
});
|
|
89424
|
+
return buildEnvelope({ action: input.action, result }, '云函数部署成功(override)');
|
|
89425
|
+
}
|
|
89401
89426
|
if (!input.func?.name || typeof input.func.name !== "string") {
|
|
89402
89427
|
throw new Error("createFunction 操作时,func.name 参数是必需的");
|
|
89403
89428
|
}
|
|
@@ -89485,6 +89510,15 @@ function registerFunctionTools(server) {
|
|
|
89485
89510
|
}, message, nextActions);
|
|
89486
89511
|
}
|
|
89487
89512
|
case "updateFunctionCode": {
|
|
89513
|
+
if (deployOverrides?.updateFunctionCode) {
|
|
89514
|
+
const result = await deployOverrides.updateFunctionCode({
|
|
89515
|
+
functionName: input.functionName ?? '',
|
|
89516
|
+
functionRootPath: input.functionRootPath ?? '',
|
|
89517
|
+
force: input.force,
|
|
89518
|
+
installDependency: input.func?.installDependency,
|
|
89519
|
+
});
|
|
89520
|
+
return buildEnvelope({ action: input.action, result }, '云函数代码更新成功(override)');
|
|
89521
|
+
}
|
|
89488
89522
|
if (!input.functionName) {
|
|
89489
89523
|
throw new Error("updateFunctionCode 操作时,functionName 参数是必需的");
|
|
89490
89524
|
}
|
|
@@ -89818,6 +89852,19 @@ function registerFunctionTools(server) {
|
|
|
89818
89852
|
]);
|
|
89819
89853
|
}
|
|
89820
89854
|
default:
|
|
89855
|
+
// incrementalDeployFunction:无默认实现,必须通过 pluginOptions 注入
|
|
89856
|
+
if (input.action === 'incrementalDeployFunction') {
|
|
89857
|
+
const fn = deployOverrides?.incrementalDeployFunction;
|
|
89858
|
+
if (!fn) {
|
|
89859
|
+
throw new Error('incrementalDeployFunction 需要通过 pluginOptions.functions.incrementalDeployFunction 注入实现(仅在支持的 IDE 环境中可用)');
|
|
89860
|
+
}
|
|
89861
|
+
const result = await fn({
|
|
89862
|
+
functionName: input.functionName ?? '',
|
|
89863
|
+
functionRootPath: input.functionRootPath ?? '',
|
|
89864
|
+
incrementalFile: input.incrementalFile ?? '',
|
|
89865
|
+
});
|
|
89866
|
+
return buildEnvelope({ action: input.action, result }, '云函数增量部署成功');
|
|
89867
|
+
}
|
|
89821
89868
|
throw new Error(`不支持的操作类型: ${input.action}`);
|
|
89822
89869
|
}
|
|
89823
89870
|
};
|
|
@@ -89890,7 +89937,7 @@ function registerFunctionTools(server) {
|
|
|
89890
89937
|
inputSchema: {
|
|
89891
89938
|
action: zod_1.z
|
|
89892
89939
|
.enum(exports.MANAGE_FUNCTION_ACTIONS)
|
|
89893
|
-
.describe("写操作类型,例如 createFunction、updateFunctionCode、invokeFunction、deleteFunction、" +
|
|
89940
|
+
.describe("写操作类型,例如 createFunction、updateFunctionCode、incrementalDeployFunction、invokeFunction、deleteFunction、" +
|
|
89894
89941
|
"createFunctionTrigger(定时任务 / cron / timer)、deleteFunctionTrigger、attachLayer、detachLayer"),
|
|
89895
89942
|
func: CREATE_FUNCTION_SCHEMA.optional().describe("createFunction 操作的函数配置"),
|
|
89896
89943
|
functionRootPath: zod_1.z.string().optional().describe("创建或更新函数代码时默认推荐的本地目录方式。" +
|
|
@@ -89926,6 +89973,7 @@ function registerFunctionTools(server) {
|
|
|
89926
89973
|
.describe("updateFunctionLayers 的目标层列表,顺序即最终顺序"),
|
|
89927
89974
|
codeSecret: zod_1.z.string().optional().describe("层绑定时的代码保护密钥"),
|
|
89928
89975
|
confirm: zod_1.z.boolean().optional().describe("危险操作确认开关。deleteFunction、deleteFunctionTrigger、deleteLayerVersion、detachLayer 等删除类操作需要显式传入 confirm=true"),
|
|
89976
|
+
incrementalFile: zod_1.z.string().optional().describe("incrementalDeployFunction 增量部署时的变更文件路径"),
|
|
89929
89977
|
},
|
|
89930
89978
|
annotations: {
|
|
89931
89979
|
readOnlyHint: false,
|
|
@@ -102126,10 +102174,19 @@ function registerDatabase(server) {
|
|
|
102126
102174
|
(0, databaseSQL_js_1.registerSQLDatabaseTools)(server);
|
|
102127
102175
|
(0, dataModel_js_1.registerDataModelTools)(server);
|
|
102128
102176
|
}
|
|
102177
|
+
function registerNoSQLDatabase(server) {
|
|
102178
|
+
const region = server.cloudBaseOptions?.region || process.env.TCB_REGION;
|
|
102179
|
+
if (!(0, tencent_cloud_js_1.isInternationalRegion)(region)) {
|
|
102180
|
+
(0, databaseNoSQL_js_1.registerDatabaseTools)(server);
|
|
102181
|
+
}
|
|
102182
|
+
}
|
|
102129
102183
|
// 可用插件映射
|
|
102130
102184
|
const AVAILABLE_PLUGINS = {
|
|
102131
102185
|
env: { name: "env", register: env_js_1.registerEnvTools },
|
|
102132
102186
|
database: { name: "database", register: registerDatabase },
|
|
102187
|
+
"database-nosql": { name: "database-nosql", register: registerNoSQLDatabase },
|
|
102188
|
+
"database-sql": { name: "database-sql", register: databaseSQL_js_1.registerSQLDatabaseTools },
|
|
102189
|
+
"data-model": { name: "data-model", register: dataModel_js_1.registerDataModelTools },
|
|
102133
102190
|
functions: { name: "functions", register: functions_js_1.registerFunctionTools },
|
|
102134
102191
|
hosting: { name: "hosting", register: hosting_js_1.registerHostingTools },
|
|
102135
102192
|
storage: { name: "storage", register: storage_js_1.registerStorageTools },
|
|
@@ -102217,7 +102274,7 @@ function parseEnabledPlugins(pluginsEnabled, pluginsDisabled) {
|
|
|
102217
102274
|
* await server.connect(transport);
|
|
102218
102275
|
*/
|
|
102219
102276
|
async function createCloudBaseMcpServer(options) {
|
|
102220
|
-
const { name = "cloudbase-mcp", version = "1.0.0", enableTelemetry = true, cloudBaseOptions, authOptions, cloudMode = false, ide, logger, pluginsEnabled, pluginsDisabled, } = options ?? {};
|
|
102277
|
+
const { name = "cloudbase-mcp", version = "1.0.0", enableTelemetry = true, cloudBaseOptions, authOptions, cloudMode = false, ide, logger, pluginsEnabled, pluginsDisabled, pluginOptions, } = options ?? {};
|
|
102221
102278
|
// Enable cloud mode if specified
|
|
102222
102279
|
if (cloudMode) {
|
|
102223
102280
|
(0, cloud_mode_js_1.enableCloudMode)();
|
|
@@ -102232,20 +102289,31 @@ async function createCloudBaseMcpServer(options) {
|
|
|
102232
102289
|
...(ide === "CodeBuddy" ? { logging: {} } : {}),
|
|
102233
102290
|
},
|
|
102234
102291
|
});
|
|
102292
|
+
// 初始化 toolDefs,用于外部提取工具列表(如微信 IDE)
|
|
102293
|
+
server.toolDefs = [];
|
|
102235
102294
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
102236
|
-
server.registerTool = ((name, meta, handler) =>
|
|
102237
|
-
|
|
102238
|
-
|
|
102239
|
-
|
|
102240
|
-
|
|
102241
|
-
|
|
102242
|
-
|
|
102243
|
-
|
|
102244
|
-
|
|
102295
|
+
server.registerTool = ((name, meta, handler) => {
|
|
102296
|
+
// 同步记录到 toolDefs
|
|
102297
|
+
server.toolDefs.push({
|
|
102298
|
+
name,
|
|
102299
|
+
description: meta?.description ?? meta?.title ?? '',
|
|
102300
|
+
inputSchema: meta?.inputSchema ?? {},
|
|
102301
|
+
handler,
|
|
102302
|
+
});
|
|
102303
|
+
return originalRegisterTool(name, meta, async (args) => {
|
|
102304
|
+
try {
|
|
102305
|
+
return await handler(args);
|
|
102245
102306
|
}
|
|
102246
|
-
|
|
102247
|
-
|
|
102248
|
-
|
|
102307
|
+
catch (error) {
|
|
102308
|
+
if ((0, tool_result_js_1.isToolPayloadError)(error)) {
|
|
102309
|
+
// 在结构化错误返回中注入 MCP 版本号
|
|
102310
|
+
const payload = { ...error.payload, mcpVersion: version };
|
|
102311
|
+
return (0, tool_result_js_1.buildJsonToolResult)(payload);
|
|
102312
|
+
}
|
|
102313
|
+
throw error;
|
|
102314
|
+
}
|
|
102315
|
+
});
|
|
102316
|
+
});
|
|
102249
102317
|
// Only set logging handler if logging capability is declared
|
|
102250
102318
|
if (ide === "CodeBuddy") {
|
|
102251
102319
|
server.server.setRequestHandler(types_js_1.SetLevelRequestSchema, (request, extra) => {
|
|
@@ -102260,6 +102328,10 @@ async function createCloudBaseMcpServer(options) {
|
|
|
102260
102328
|
if (authOptions) {
|
|
102261
102329
|
server.authOptions = authOptions;
|
|
102262
102330
|
}
|
|
102331
|
+
// Store pluginOptions in server instance for plugins to access
|
|
102332
|
+
if (pluginOptions) {
|
|
102333
|
+
server.pluginOptions = pluginOptions;
|
|
102334
|
+
}
|
|
102263
102335
|
// Store ide in server instance for telemetry
|
|
102264
102336
|
if (ide) {
|
|
102265
102337
|
server.ide = ide;
|
|
@@ -117979,13 +118051,16 @@ async function resolveHostingStaticDomain(cloudbase, logger) {
|
|
|
117979
118051
|
return undefined;
|
|
117980
118052
|
}
|
|
117981
118053
|
}
|
|
117982
|
-
|
|
118054
|
+
// Returns the first hosting store record from DescribeStaticStore, which is
|
|
118055
|
+
// the authoritative source for Mini Program-sourced environments (those envs
|
|
118056
|
+
// do not populate StaticStorages in DescribeEnvs / getEnvInfo).
|
|
118057
|
+
// Throws when no valid store is found so upload can fail fast with a clear msg.
|
|
118058
|
+
async function getHostingStoreOrThrow(cloudbase, cloudBaseOptions, logger) {
|
|
117983
118059
|
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
117984
|
-
const
|
|
117985
|
-
|
|
117986
|
-
|
|
117987
|
-
|
|
117988
|
-
return;
|
|
118060
|
+
const result = await callTcbHostingAction(cloudbase, 'DescribeStaticStore', { EnvId: envId }, logger);
|
|
118061
|
+
const hostingInfo = extractStaticStores(result);
|
|
118062
|
+
if (hostingInfo.length > 0 && hostingInfo[0].Bucket) {
|
|
118063
|
+
return hostingInfo[0];
|
|
117989
118064
|
}
|
|
117990
118065
|
throw new Error(`当前环境 ${envId} 未发现静态托管资源配置,无法上传文件。请先确认 MCP 已绑定到已开通静态托管的 CloudBase 环境;如需切换环境,请调用 auth(action="set_env", envId="目标环境ID") 后重试。`);
|
|
117991
118066
|
}
|
|
@@ -118193,8 +118268,9 @@ function registerHostingTools(server) {
|
|
|
118193
118268
|
throw new Error('manageHosting(action="upload") 需要提供 localPath + cloudPath,或提供 files 多文件上传列表。');
|
|
118194
118269
|
}
|
|
118195
118270
|
let result;
|
|
118271
|
+
let store;
|
|
118196
118272
|
try {
|
|
118197
|
-
await
|
|
118273
|
+
store = await getHostingStoreOrThrow(cloudbase, cloudBaseOptions, server.logger);
|
|
118198
118274
|
result = await cloudbase.hosting.uploadFiles({
|
|
118199
118275
|
localPath: input.localPath,
|
|
118200
118276
|
cloudPath: input.cloudPath,
|
|
@@ -118206,7 +118282,11 @@ function registerHostingTools(server) {
|
|
|
118206
118282
|
throw new Error(buildUploadErrorMessage(error, input.localPath));
|
|
118207
118283
|
}
|
|
118208
118284
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
118209
|
-
|
|
118285
|
+
// Prefer CdnDomain from the DescribeStaticStore result we already
|
|
118286
|
+
// fetched; fall back to getEnvInfo for environments that populate
|
|
118287
|
+
// StaticDomain there but not in DescribeStaticStore.
|
|
118288
|
+
const cdnFromStore = (store.CdnDomain ?? store.StaticDomain);
|
|
118289
|
+
const staticDomain = cdnFromStore || await resolveHostingStaticDomain(cloudbase, server.logger);
|
|
118210
118290
|
const accessUrl = buildHostingAccessUrl(staticDomain, input.cloudPath, input.localPath);
|
|
118211
118291
|
try {
|
|
118212
118292
|
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
@@ -135149,7 +135229,7 @@ class TelemetryReporter {
|
|
|
135149
135229
|
const nodeVersion = process.version; // Node.js版本
|
|
135150
135230
|
const arch = os_1.default.arch(); // 系统架构
|
|
135151
135231
|
// 从构建时注入的版本号获取MCP版本信息
|
|
135152
|
-
const mcpVersion = process.env.npm_package_version || "2.21.
|
|
135232
|
+
const mcpVersion = process.env.npm_package_version || "2.21.1-beta.1" || 0;
|
|
135153
135233
|
return {
|
|
135154
135234
|
userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
|
|
135155
135235
|
deviceId: this.deviceId,
|
|
@@ -180374,99 +180454,6 @@ async function downloadResources() {
|
|
|
180374
180454
|
return resourceDownloadPromise;
|
|
180375
180455
|
}
|
|
180376
180456
|
async function registerRagTools(server) {
|
|
180377
|
-
// 联网搜索
|
|
180378
|
-
server.registerTool?.("searchWeb", {
|
|
180379
|
-
title: "联网搜索",
|
|
180380
|
-
description: "使用联网来进行信息检索,如查询最新的新闻、文章、股价、天气等。支持自然语言查询,也可以直接输入网址获取网页内容",
|
|
180381
|
-
inputSchema: {
|
|
180382
|
-
query: zod_1.z.string().describe("搜索关键词、问题或网址,支持自然语言"),
|
|
180383
|
-
},
|
|
180384
|
-
annotations: {
|
|
180385
|
-
readOnlyHint: true,
|
|
180386
|
-
openWorldHint: true,
|
|
180387
|
-
category: "web",
|
|
180388
|
-
},
|
|
180389
|
-
}, async ({ query }) => {
|
|
180390
|
-
try {
|
|
180391
|
-
// 使用混元进行联网搜索
|
|
180392
|
-
const signInRes = await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/auth/v1/signin/anonymously", {
|
|
180393
|
-
method: "POST",
|
|
180394
|
-
headers: {
|
|
180395
|
-
"Content-Type": "application/json",
|
|
180396
|
-
Accept: "application/json",
|
|
180397
|
-
"x-device-id": "cloudbase-ai-toolkit",
|
|
180398
|
-
},
|
|
180399
|
-
body: safeStringify({}),
|
|
180400
|
-
});
|
|
180401
|
-
const { access_token } = await signInRes.json();
|
|
180402
|
-
// 调用混元API进行联网搜索
|
|
180403
|
-
const searchRes = await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/v1/ai/hunyuan-beta/openapi/v1/chat/completions", {
|
|
180404
|
-
method: "POST",
|
|
180405
|
-
headers: {
|
|
180406
|
-
"Content-Type": "application/json",
|
|
180407
|
-
Authorization: `Bearer ${access_token}`,
|
|
180408
|
-
},
|
|
180409
|
-
body: safeStringify({
|
|
180410
|
-
model: "hunyuan",
|
|
180411
|
-
messages: [
|
|
180412
|
-
{
|
|
180413
|
-
role: "user",
|
|
180414
|
-
content: `你好,你将扮演一个知识库的角色,联网查询到问题的答案之后回答给我`,
|
|
180415
|
-
},
|
|
180416
|
-
{
|
|
180417
|
-
role: "assistant",
|
|
180418
|
-
content: "好的",
|
|
180419
|
-
},
|
|
180420
|
-
{
|
|
180421
|
-
role: "user",
|
|
180422
|
-
content: query,
|
|
180423
|
-
},
|
|
180424
|
-
],
|
|
180425
|
-
enable_enhancement: true,
|
|
180426
|
-
search_info: true,
|
|
180427
|
-
enable_speed_search: true,
|
|
180428
|
-
force_search_enhancement: true,
|
|
180429
|
-
}),
|
|
180430
|
-
});
|
|
180431
|
-
const result = await searchRes.json();
|
|
180432
|
-
if (result.error) {
|
|
180433
|
-
throw new Error(result.error.message || "联网搜索失败");
|
|
180434
|
-
}
|
|
180435
|
-
const content = result.choices?.[0]?.message?.content || "";
|
|
180436
|
-
const searchResults = result.search_info?.search_results || [];
|
|
180437
|
-
return {
|
|
180438
|
-
content: [
|
|
180439
|
-
{
|
|
180440
|
-
type: "text",
|
|
180441
|
-
text: safeStringify({
|
|
180442
|
-
type: "web_search",
|
|
180443
|
-
content: content,
|
|
180444
|
-
search_results: searchResults.map((item) => ({
|
|
180445
|
-
title: item.title,
|
|
180446
|
-
url: item.url,
|
|
180447
|
-
snippet: item.snippet,
|
|
180448
|
-
})),
|
|
180449
|
-
status: "success",
|
|
180450
|
-
}),
|
|
180451
|
-
},
|
|
180452
|
-
],
|
|
180453
|
-
};
|
|
180454
|
-
}
|
|
180455
|
-
catch (error) {
|
|
180456
|
-
return {
|
|
180457
|
-
content: [
|
|
180458
|
-
{
|
|
180459
|
-
type: "text",
|
|
180460
|
-
text: safeStringify({
|
|
180461
|
-
type: "error",
|
|
180462
|
-
message: error instanceof Error ? error.message : "联网搜索失败",
|
|
180463
|
-
status: "error",
|
|
180464
|
-
}),
|
|
180465
|
-
},
|
|
180466
|
-
],
|
|
180467
|
-
};
|
|
180468
|
-
}
|
|
180469
|
-
});
|
|
180470
180457
|
let openapis = [];
|
|
180471
180458
|
let skills = [];
|
|
180472
180459
|
let fallbackSkillsRoot;
|
|
@@ -185849,7 +185836,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
185849
185836
|
exports.CloudBaseContext = void 0;
|
|
185850
185837
|
const constant_1 = __webpack_require__(40762);
|
|
185851
185838
|
class CloudBaseContext {
|
|
185852
|
-
constructor({ secretId = '', secretKey = '', token = '', proxy = '', region = '', envType = '', useInternalEndpoint = undefined, internalEndpointRegion = undefined }) {
|
|
185839
|
+
constructor({ secretId = '', secretKey = '', token = '', proxy = '', region = '', envType = '', useInternalEndpoint = undefined, internalEndpointRegion = undefined, requestFn = undefined }) {
|
|
185853
185840
|
this.secretId = secretId;
|
|
185854
185841
|
this.secretKey = secretKey;
|
|
185855
185842
|
this.token = token;
|
|
@@ -185858,6 +185845,7 @@ class CloudBaseContext {
|
|
|
185858
185845
|
this.envType = envType;
|
|
185859
185846
|
this.useInternalEndpoint = useInternalEndpoint;
|
|
185860
185847
|
this.internalEndpointRegion = internalEndpointRegion;
|
|
185848
|
+
this.requestFn = requestFn;
|
|
185861
185849
|
}
|
|
185862
185850
|
isInternalEndpoint() {
|
|
185863
185851
|
return this.useInternalEndpoint !== undefined ? this.useInternalEndpoint : constant_1.USE_INTERNAL_ENDPOINT;
|
|
@@ -193754,7 +193742,7 @@ ${envIdSection}
|
|
|
193754
193742
|
## 环境信息
|
|
193755
193743
|
- 操作系统: ${os_1.default.type()} ${os_1.default.release()}
|
|
193756
193744
|
- Node.js版本: ${process.version}
|
|
193757
|
-
- MCP 版本:${process.env.npm_package_version || "2.21.
|
|
193745
|
+
- MCP 版本:${process.env.npm_package_version || "2.21.1-beta.1" || 0}
|
|
193758
193746
|
- 系统架构: ${os_1.default.arch()}
|
|
193759
193747
|
- 时间: ${new Date().toISOString()}
|
|
193760
193748
|
- 请求ID: ${requestId}
|
|
@@ -193835,7 +193823,7 @@ function createWrappedHandler(name, handler, server) {
|
|
|
193835
193823
|
requestId: (typeof error === 'object' && error && 'requestId' in error) ? error.requestId : '',
|
|
193836
193824
|
ide: server.ide || process.env.INTEGRATION_IDE || ''
|
|
193837
193825
|
});
|
|
193838
|
-
const mcpVersion = true ? "2.21.
|
|
193826
|
+
const mcpVersion = true ? "2.21.1-beta.1" : 0;
|
|
193839
193827
|
const requestIdSuffix = requestId ? `\n🆔 RequestId: ${requestId}` : '';
|
|
193840
193828
|
const enhancedErrorMessage = `${errorMessage}${requestIdSuffix}\n\n📦 CloudBase MCP v${mcpVersion}\n🔗 遇到问题?请复制以下链接到浏览器打开\n即可自动携带错误详情快速创建 GitHub Issue:\n${issueLink}`;
|
|
193841
193829
|
// 创建新的错误对象,保持原有的错误类型但更新消息
|
|
@@ -203264,6 +203252,13 @@ async function callNoSqlContentApi(options) {
|
|
|
203264
203252
|
instanceIdSource: "envId",
|
|
203265
203253
|
requestId: result?.RequestId,
|
|
203266
203254
|
});
|
|
203255
|
+
// 检查 API 层返回的业务错误(如集合不存在)并抛出
|
|
203256
|
+
if (result?.Error) {
|
|
203257
|
+
const err = new Error(`${result.Error.Code}: ${result.Error.Message}`);
|
|
203258
|
+
err.code = result.Error.Code;
|
|
203259
|
+
err.requestId = result.RequestId;
|
|
203260
|
+
throw err;
|
|
203261
|
+
}
|
|
203267
203262
|
return result;
|
|
203268
203263
|
}
|
|
203269
203264
|
catch (error) {
|
|
@@ -203277,7 +203272,7 @@ async function callNoSqlContentApi(options) {
|
|
|
203277
203272
|
throw error;
|
|
203278
203273
|
}
|
|
203279
203274
|
}
|
|
203280
|
-
async function waitForCollectionReady({ cloudbase, collectionName, logger, timeoutMs = COLLECTION_READY_TIMEOUT_MS, pollIntervalMs = COLLECTION_READY_POLL_INTERVAL_MS, }) {
|
|
203275
|
+
async function waitForCollectionReady({ cloudbase, collectionName, logger, cloudBaseOptions, timeoutMs = COLLECTION_READY_TIMEOUT_MS, pollIntervalMs = COLLECTION_READY_POLL_INTERVAL_MS, }) {
|
|
203281
203276
|
const startedAt = Date.now();
|
|
203282
203277
|
const deadline = startedAt + timeoutMs;
|
|
203283
203278
|
let lastError;
|
|
@@ -203291,17 +203286,40 @@ async function waitForCollectionReady({ cloudbase, collectionName, logger, timeo
|
|
|
203291
203286
|
});
|
|
203292
203287
|
while (Date.now() <= deadline) {
|
|
203293
203288
|
try {
|
|
203294
|
-
//
|
|
203295
|
-
|
|
203296
|
-
const
|
|
203297
|
-
|
|
203289
|
+
// 用 PutItem 探测集合是否真正就绪(DescribeTable 可能误报),插入一个空占位文档
|
|
203290
|
+
// 如果成功,立即删除该文档;如果仍 ResourceNotFound,继续等待
|
|
203291
|
+
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
203292
|
+
const probeDoc = JSON.stringify({ _readyProbe: true, _ts: Date.now() });
|
|
203293
|
+
const probeResult = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
203294
|
+
Action: "PutItem",
|
|
203298
203295
|
Param: {
|
|
203299
203296
|
EnvId: envId,
|
|
203300
203297
|
TableName: collectionName,
|
|
203298
|
+
MgoDocs: [probeDoc],
|
|
203301
203299
|
},
|
|
203302
203300
|
});
|
|
203303
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(logger,
|
|
203304
|
-
|
|
203301
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(logger, probeResult);
|
|
203302
|
+
if (probeResult?.Error) {
|
|
203303
|
+
// 集合还未就绪,继续轮询
|
|
203304
|
+
throw new Error(probeResult.Error.Message);
|
|
203305
|
+
}
|
|
203306
|
+
// 集合就绪,清理探测文档
|
|
203307
|
+
if (Array.isArray(probeResult?.InsertedIds) && probeResult.InsertedIds.length > 0) {
|
|
203308
|
+
try {
|
|
203309
|
+
await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
203310
|
+
Action: "DeleteItem",
|
|
203311
|
+
Param: {
|
|
203312
|
+
EnvId: envId,
|
|
203313
|
+
TableName: collectionName,
|
|
203314
|
+
MgoQuery: JSON.stringify({ _readyProbe: true }),
|
|
203315
|
+
MgoIsMulti: true,
|
|
203316
|
+
},
|
|
203317
|
+
});
|
|
203318
|
+
}
|
|
203319
|
+
catch {
|
|
203320
|
+
// 清理失败不影响主流程
|
|
203321
|
+
}
|
|
203322
|
+
}
|
|
203305
203323
|
logger?.({
|
|
203306
203324
|
type: "toolInfo",
|
|
203307
203325
|
toolName: "writeNoSqlDatabaseStructure",
|
|
@@ -203340,8 +203358,8 @@ function registerDatabaseTools(server) {
|
|
|
203340
203358
|
const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions });
|
|
203341
203359
|
// readNoSqlDatabaseStructure
|
|
203342
203360
|
server.registerTool?.("readNoSqlDatabaseStructure", {
|
|
203343
|
-
title: "读取 NoSQL 数据库结构",
|
|
203344
|
-
description: "读取 NoSQL 数据库集合与索引结构,支持列出集合、查看集合详情、列出索引以及检查索引是否存在。本工具为服务端管理工具,用于管理端查询数据库结构,不用于编写客户端代码。",
|
|
203361
|
+
title: "读取 CloudBase NoSQL 数据库结构",
|
|
203362
|
+
description: "读取 CloudBase NoSQL 数据库集合与索引结构,支持列出集合、查看集合详情、列出索引以及检查索引是否存在。本工具为服务端管理工具,用于管理端查询数据库结构,不用于编写客户端代码。",
|
|
203345
203363
|
inputSchema: {
|
|
203346
203364
|
action: zod_1.z.enum([
|
|
203347
203365
|
"listCollections",
|
|
@@ -203528,8 +203546,8 @@ checkIndex: 检查指定索引是否存在`),
|
|
|
203528
203546
|
});
|
|
203529
203547
|
// writeNoSqlDatabaseStructure
|
|
203530
203548
|
server.registerTool?.("writeNoSqlDatabaseStructure", {
|
|
203531
|
-
title: "创建并管理 NoSQL 数据库集合",
|
|
203532
|
-
description: "创建、删除和管理 NoSQL 数据库集合(collection)。支持创建新集合、删除现有集合,以及通过 updateCollection 的 updateOptions.CreateIndexes / updateOptions.DropIndexes 添加索引和删除索引。当需要新建集合时,使用 action=createCollection。本工具为服务端管理工具,用于管理端操作集合和索引结构,不用于编写客户端代码。",
|
|
203549
|
+
title: "创建并管理 CloudBase NoSQL 数据库集合",
|
|
203550
|
+
description: "创建、删除和管理 CloudBase NoSQL 数据库集合(collection)。支持创建新集合、删除现有集合,以及通过 updateCollection 的 updateOptions.CreateIndexes / updateOptions.DropIndexes 添加索引和删除索引。当需要新建集合时,使用 action=createCollection。本工具为服务端管理工具,用于管理端操作集合和索引结构,不用于编写客户端代码。",
|
|
203533
203551
|
inputSchema: {
|
|
203534
203552
|
action: zod_1.z.enum([
|
|
203535
203553
|
"createCollection",
|
|
@@ -203589,8 +203607,14 @@ deleteCollection: 删除集合`),
|
|
|
203589
203607
|
Action: "DescribeTable",
|
|
203590
203608
|
Param: { EnvId: envId, TableName: collectionName },
|
|
203591
203609
|
});
|
|
203592
|
-
|
|
203593
|
-
|
|
203610
|
+
if (descResult?.Error) {
|
|
203611
|
+
// 集合不存在(ResourceNotFound)或其他错误,继续创建
|
|
203612
|
+
existsRequestId = descResult.RequestId ?? "";
|
|
203613
|
+
}
|
|
203614
|
+
else {
|
|
203615
|
+
collectionExists = true;
|
|
203616
|
+
existsRequestId = descResult?.RequestId ?? "";
|
|
203617
|
+
}
|
|
203594
203618
|
}
|
|
203595
203619
|
catch (e) {
|
|
203596
203620
|
existsRequestId = e?.requestId ?? "";
|
|
@@ -203623,6 +203647,7 @@ deleteCollection: 删除集合`),
|
|
|
203623
203647
|
cloudbase,
|
|
203624
203648
|
collectionName,
|
|
203625
203649
|
logger: server.logger,
|
|
203650
|
+
cloudBaseOptions: server.cloudBaseOptions,
|
|
203626
203651
|
});
|
|
203627
203652
|
return {
|
|
203628
203653
|
content: [
|
|
@@ -203705,8 +203730,8 @@ deleteCollection: 删除集合`),
|
|
|
203705
203730
|
});
|
|
203706
203731
|
// readNoSqlDatabaseContent
|
|
203707
203732
|
server.registerTool?.("readNoSqlDatabaseContent", {
|
|
203708
|
-
title: "查询并获取 NoSQL 数据库数据记录",
|
|
203709
|
-
description: "
|
|
203733
|
+
title: "查询并获取 CloudBase NoSQL 数据库数据记录",
|
|
203734
|
+
description: "查询 CloudBase NoSQL 数据库中的数据记录。支持按条件筛选、分页、排序,适用于管理端数据查询与运维。",
|
|
203710
203735
|
inputSchema: {
|
|
203711
203736
|
collectionName: zod_1.z.string().describe("集合名称"),
|
|
203712
203737
|
instanceId: zod_1.z
|
|
@@ -203792,8 +203817,10 @@ deleteCollection: 删除集合`),
|
|
|
203792
203817
|
});
|
|
203793
203818
|
// writeNoSqlDatabaseContent
|
|
203794
203819
|
server.registerTool?.("writeNoSqlDatabaseContent", {
|
|
203795
|
-
title: "修改 NoSQL 数据库数据记录",
|
|
203796
|
-
description: "修改 NoSQL
|
|
203820
|
+
title: "修改 CloudBase NoSQL 数据库数据记录",
|
|
203821
|
+
description: "修改 CloudBase NoSQL 数据库中的数据记录。支持插入、更新(含 $set/$inc/$push 等操作符)、删除、upsert 等操作,适用于管理端数据写入与运维。" +
|
|
203822
|
+
"⚠️ 服务端写入不含 _openid:若集合依赖客户端 SDK(@cloudbase/js-sdk 或微信小程序 wx.cloud.database())的行级安全规则(如 doc._openid == auth.openid),服务端写入时需手动补充 _openid 字段,否则客户端将无法读取到该数据。" +
|
|
203823
|
+
"⚠️ 部分更新嵌套字段须使用点号路径,如 `$set: {\"shipping.city\": \"guangzhou\"}`,直接传嵌套对象会覆盖整个字段。",
|
|
203797
203824
|
inputSchema: {
|
|
203798
203825
|
action: zod_1.z
|
|
203799
203826
|
.enum(["insert", "update", "delete"])
|
|
@@ -209808,7 +209835,7 @@ function registerSetupTools(server) {
|
|
|
209808
209835
|
server.registerTool("downloadTemplate", {
|
|
209809
209836
|
title: "下载项目模板",
|
|
209810
209837
|
description: `自动下载并部署CloudBase项目模板。
|
|
209811
|
-
**Note**: Call this tool when the user requests to create a new project using a CloudBase template.\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.21.
|
|
209838
|
+
**Note**: Call this tool when the user requests to create a new project using a CloudBase template.\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.21.1-beta.1" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
|
|
209812
209839
|
inputSchema: {
|
|
209813
209840
|
template: zod_1.z
|
|
209814
209841
|
.enum(["react", "vue", "miniprogram", "uniapp", "rules"])
|
|
@@ -219995,12 +220022,13 @@ function getDate(timestamp) {
|
|
|
219995
220022
|
}
|
|
219996
220023
|
class CloudService {
|
|
219997
220024
|
/* eslint-disable-next-line */
|
|
219998
|
-
constructor(context, service, version, baseParams) {
|
|
220025
|
+
constructor(context, service, version, baseParams, requestFn) {
|
|
219999
220026
|
this.service = service;
|
|
220000
220027
|
this.version = version;
|
|
220001
220028
|
this.timeout = 60000;
|
|
220002
220029
|
this.baseParams = baseParams || {};
|
|
220003
220030
|
this.cloudBaseContext = context;
|
|
220031
|
+
this.requestFn = requestFn !== null && requestFn !== void 0 ? requestFn : context.requestFn;
|
|
220004
220032
|
}
|
|
220005
220033
|
get baseUrl() {
|
|
220006
220034
|
const internalEndpoint = this.cloudBaseContext.isInternalEndpoint();
|
|
@@ -220032,8 +220060,31 @@ class CloudService {
|
|
|
220032
220060
|
}
|
|
220033
220061
|
}
|
|
220034
220062
|
async request(action, data = {}, method = 'POST') {
|
|
220063
|
+
var _a;
|
|
220035
220064
|
this.action = action;
|
|
220036
220065
|
this.data = deepRemoveVoid(Object.assign(Object.assign({}, data), this.baseParams));
|
|
220066
|
+
// 如果注入了 requestFn,直接委托,跳过 TC3 签名逻辑
|
|
220067
|
+
if (this.requestFn) {
|
|
220068
|
+
try {
|
|
220069
|
+
const result = await this.requestFn({
|
|
220070
|
+
service: this.service,
|
|
220071
|
+
action,
|
|
220072
|
+
version: this.version,
|
|
220073
|
+
region: (_a = this.cloudBaseContext.region) !== null && _a !== void 0 ? _a : '',
|
|
220074
|
+
payload: this.data,
|
|
220075
|
+
});
|
|
220076
|
+
return result;
|
|
220077
|
+
}
|
|
220078
|
+
catch (e) {
|
|
220079
|
+
if (e.name === 'CloudBaseError') {
|
|
220080
|
+
throw e;
|
|
220081
|
+
}
|
|
220082
|
+
throw new error_1.CloudBaseError(e.message, {
|
|
220083
|
+
action,
|
|
220084
|
+
code: e.code
|
|
220085
|
+
});
|
|
220086
|
+
}
|
|
220087
|
+
}
|
|
220037
220088
|
this.method = method;
|
|
220038
220089
|
this.url = this.baseUrl;
|
|
220039
220090
|
let { secretId, secretKey, token } = this.cloudBaseContext;
|
|
@@ -244772,8 +244823,8 @@ function registerLogTools(server) {
|
|
|
244772
244823
|
const cloudBaseOptions = server.cloudBaseOptions;
|
|
244773
244824
|
const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions });
|
|
244774
244825
|
server.registerTool?.("queryLogs", {
|
|
244775
|
-
title: "
|
|
244776
|
-
description: "日志域统一只读入口。支持检查日志服务状态并搜索 CLS 日志。" +
|
|
244826
|
+
title: "查询 CloudBase 日志服务",
|
|
244827
|
+
description: "CloudBase 日志域统一只读入口。支持检查日志服务状态并搜索 CLS 日志。" +
|
|
244777
244828
|
"\n\n**重要区分**:" +
|
|
244778
244829
|
"\n- 查询云函数日志:使用 `queryFunctions(action=\"listFunctionLogs\", functionName=\"xxx\")`" +
|
|
244779
244830
|
"\n- 查询 CLS 日志(跨服务日志聚合):使用本工具 `queryLogs(action=\"searchLogs\")`" +
|
|
@@ -250850,6 +250901,7 @@ async function resolveStoragePublicAccess(params) {
|
|
|
250850
250901
|
function registerStorageTools(server) {
|
|
250851
250902
|
// 获取 cloudBaseOptions,如果没有则为 undefined
|
|
250852
250903
|
const cloudBaseOptions = server.cloudBaseOptions;
|
|
250904
|
+
const storageOverrides = server.pluginOptions?.storage;
|
|
250853
250905
|
// 创建闭包函数来获取 CloudBase Manager
|
|
250854
250906
|
const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions });
|
|
250855
250907
|
// Tool 1: queryStorage - 查询存储信息(只读操作)
|
|
@@ -250871,7 +250923,14 @@ function registerStorageTools(server) {
|
|
|
250871
250923
|
const storageService = manager.storage;
|
|
250872
250924
|
switch (input.action) {
|
|
250873
250925
|
case 'list': {
|
|
250874
|
-
|
|
250926
|
+
let files;
|
|
250927
|
+
if (storageOverrides?.listFiles) {
|
|
250928
|
+
files = await storageOverrides.listFiles({ cloudPath: input.cloudPath });
|
|
250929
|
+
}
|
|
250930
|
+
else {
|
|
250931
|
+
const result = await storageService.listDirectoryFiles(input.cloudPath);
|
|
250932
|
+
files = result || [];
|
|
250933
|
+
}
|
|
250875
250934
|
return {
|
|
250876
250935
|
content: [
|
|
250877
250936
|
{
|
|
@@ -250881,17 +250940,23 @@ function registerStorageTools(server) {
|
|
|
250881
250940
|
data: {
|
|
250882
250941
|
action: 'list',
|
|
250883
250942
|
cloudPath: input.cloudPath,
|
|
250884
|
-
files
|
|
250885
|
-
totalCount:
|
|
250943
|
+
files,
|
|
250944
|
+
totalCount: files.length
|
|
250886
250945
|
},
|
|
250887
|
-
message: `Successfully listed ${
|
|
250946
|
+
message: `Successfully listed ${files.length} files in directory '${input.cloudPath}'`
|
|
250888
250947
|
}, null, 2)
|
|
250889
250948
|
}
|
|
250890
250949
|
]
|
|
250891
250950
|
};
|
|
250892
250951
|
}
|
|
250893
250952
|
case 'info': {
|
|
250894
|
-
|
|
250953
|
+
let fileInfo;
|
|
250954
|
+
if (storageOverrides?.getFileInfo) {
|
|
250955
|
+
fileInfo = await storageOverrides.getFileInfo({ cloudPath: input.cloudPath });
|
|
250956
|
+
}
|
|
250957
|
+
else {
|
|
250958
|
+
fileInfo = await storageService.getFileInfo(input.cloudPath);
|
|
250959
|
+
}
|
|
250895
250960
|
return {
|
|
250896
250961
|
content: [
|
|
250897
250962
|
{
|
|
@@ -250901,7 +250966,7 @@ function registerStorageTools(server) {
|
|
|
250901
250966
|
data: {
|
|
250902
250967
|
action: 'info',
|
|
250903
250968
|
cloudPath: input.cloudPath,
|
|
250904
|
-
fileInfo
|
|
250969
|
+
fileInfo
|
|
250905
250970
|
},
|
|
250906
250971
|
message: `Successfully retrieved file info for '${input.cloudPath}'`
|
|
250907
250972
|
}, null, 2)
|
|
@@ -250945,10 +251010,15 @@ function registerStorageTools(server) {
|
|
|
250945
251010
|
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), STORAGE_READ_TEMP_PREFIX));
|
|
250946
251011
|
const localPath = path.join(tempDir, getStorageTempFileName(input.cloudPath));
|
|
250947
251012
|
try {
|
|
250948
|
-
|
|
250949
|
-
cloudPath: input.cloudPath,
|
|
250950
|
-
|
|
250951
|
-
|
|
251013
|
+
if (storageOverrides?.downloadFile) {
|
|
251014
|
+
await storageOverrides.downloadFile({ cloudPath: input.cloudPath, localPath });
|
|
251015
|
+
}
|
|
251016
|
+
else {
|
|
251017
|
+
await storageService.downloadFile({
|
|
251018
|
+
cloudPath: input.cloudPath,
|
|
251019
|
+
localPath
|
|
251020
|
+
});
|
|
251021
|
+
}
|
|
250952
251022
|
const buffer = await fs.readFile(localPath);
|
|
250953
251023
|
const decoded = decodeInlineTextContent(buffer);
|
|
250954
251024
|
return {
|
|
@@ -251003,22 +251073,32 @@ function registerStorageTools(server) {
|
|
|
251003
251073
|
switch (input.action) {
|
|
251004
251074
|
case 'upload': {
|
|
251005
251075
|
if (input.isDirectory) {
|
|
251006
|
-
|
|
251007
|
-
localPath: input.localPath,
|
|
251008
|
-
|
|
251009
|
-
|
|
251010
|
-
|
|
251011
|
-
|
|
251012
|
-
|
|
251076
|
+
if (storageOverrides?.uploadDirectory) {
|
|
251077
|
+
await storageOverrides.uploadDirectory({ localPath: input.localPath, cloudPath: input.cloudPath });
|
|
251078
|
+
}
|
|
251079
|
+
else {
|
|
251080
|
+
await storageService.uploadDirectory({
|
|
251081
|
+
localPath: input.localPath,
|
|
251082
|
+
cloudPath: input.cloudPath,
|
|
251083
|
+
onProgress: (progressData) => {
|
|
251084
|
+
console.log("Upload directory progress:", progressData);
|
|
251085
|
+
}
|
|
251086
|
+
});
|
|
251087
|
+
}
|
|
251013
251088
|
}
|
|
251014
251089
|
else {
|
|
251015
|
-
|
|
251016
|
-
localPath: input.localPath,
|
|
251017
|
-
|
|
251018
|
-
|
|
251019
|
-
|
|
251020
|
-
|
|
251021
|
-
|
|
251090
|
+
if (storageOverrides?.uploadFile) {
|
|
251091
|
+
await storageOverrides.uploadFile({ localPath: input.localPath, cloudPath: input.cloudPath });
|
|
251092
|
+
}
|
|
251093
|
+
else {
|
|
251094
|
+
await storageService.uploadFile({
|
|
251095
|
+
localPath: input.localPath,
|
|
251096
|
+
cloudPath: input.cloudPath,
|
|
251097
|
+
onProgress: (progressData) => {
|
|
251098
|
+
console.log("Upload file progress:", progressData);
|
|
251099
|
+
}
|
|
251100
|
+
});
|
|
251101
|
+
}
|
|
251022
251102
|
}
|
|
251023
251103
|
const fileUrls = await storageService.getTemporaryUrl([{
|
|
251024
251104
|
cloudPath: input.cloudPath,
|
|
@@ -251054,16 +251134,26 @@ function registerStorageTools(server) {
|
|
|
251054
251134
|
}
|
|
251055
251135
|
case 'download': {
|
|
251056
251136
|
if (input.isDirectory) {
|
|
251057
|
-
|
|
251058
|
-
cloudPath: input.cloudPath,
|
|
251059
|
-
|
|
251060
|
-
|
|
251137
|
+
if (storageOverrides?.downloadDirectory) {
|
|
251138
|
+
await storageOverrides.downloadDirectory({ cloudPath: input.cloudPath, localPath: input.localPath });
|
|
251139
|
+
}
|
|
251140
|
+
else {
|
|
251141
|
+
await storageService.downloadDirectory({
|
|
251142
|
+
cloudPath: input.cloudPath,
|
|
251143
|
+
localPath: input.localPath
|
|
251144
|
+
});
|
|
251145
|
+
}
|
|
251061
251146
|
}
|
|
251062
251147
|
else {
|
|
251063
|
-
|
|
251064
|
-
cloudPath: input.cloudPath,
|
|
251065
|
-
|
|
251066
|
-
|
|
251148
|
+
if (storageOverrides?.downloadFile) {
|
|
251149
|
+
await storageOverrides.downloadFile({ cloudPath: input.cloudPath, localPath: input.localPath });
|
|
251150
|
+
}
|
|
251151
|
+
else {
|
|
251152
|
+
await storageService.downloadFile({
|
|
251153
|
+
cloudPath: input.cloudPath,
|
|
251154
|
+
localPath: input.localPath
|
|
251155
|
+
});
|
|
251156
|
+
}
|
|
251067
251157
|
}
|
|
251068
251158
|
return {
|
|
251069
251159
|
content: [
|
|
@@ -251099,10 +251189,20 @@ function registerStorageTools(server) {
|
|
|
251099
251189
|
};
|
|
251100
251190
|
}
|
|
251101
251191
|
if (input.isDirectory) {
|
|
251102
|
-
|
|
251192
|
+
if (storageOverrides?.deleteDirectory) {
|
|
251193
|
+
await storageOverrides.deleteDirectory({ cloudPath: input.cloudPath });
|
|
251194
|
+
}
|
|
251195
|
+
else {
|
|
251196
|
+
await storageService.deleteDirectory(input.cloudPath);
|
|
251197
|
+
}
|
|
251103
251198
|
}
|
|
251104
251199
|
else {
|
|
251105
|
-
|
|
251200
|
+
if (storageOverrides?.deleteFiles) {
|
|
251201
|
+
await storageOverrides.deleteFiles({ cloudPaths: [input.cloudPath] });
|
|
251202
|
+
}
|
|
251203
|
+
else {
|
|
251204
|
+
await storageService.deleteFile([input.cloudPath]);
|
|
251205
|
+
}
|
|
251106
251206
|
}
|
|
251107
251207
|
return {
|
|
251108
251208
|
content: [
|
|
@@ -259387,9 +259487,9 @@ class CloudBase {
|
|
|
259387
259487
|
}
|
|
259388
259488
|
constructor(config = {}) {
|
|
259389
259489
|
this.cloudBaseConfig = {};
|
|
259390
|
-
let { secretId, secretKey, token, envId, proxy, region, envType, useInternalEndpoint, internalEndpointRegion } = config;
|
|
259391
|
-
// config 中传入的 secretId secretkey
|
|
259392
|
-
if ((secretId && !secretKey) || (!secretId && secretKey)) {
|
|
259490
|
+
let { secretId, secretKey, token, envId, proxy, region, envType, useInternalEndpoint, internalEndpointRegion, requestFn } = config;
|
|
259491
|
+
// config 中传入的 secretId secretkey 必须同时存在(有 requestFn 时可以不传)
|
|
259492
|
+
if (!requestFn && ((secretId && !secretKey) || (!secretId && secretKey))) {
|
|
259393
259493
|
throw new Error('secretId and secretKey must be a pair');
|
|
259394
259494
|
}
|
|
259395
259495
|
this.cloudBaseConfig = {
|
|
@@ -259402,6 +259502,7 @@ class CloudBase {
|
|
|
259402
259502
|
region,
|
|
259403
259503
|
useInternalEndpoint,
|
|
259404
259504
|
internalEndpointRegion,
|
|
259505
|
+
requestFn,
|
|
259405
259506
|
};
|
|
259406
259507
|
// 初始化 context
|
|
259407
259508
|
this.context = new context_1.CloudBaseContext(this.cloudBaseConfig);
|