@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/index.cjs CHANGED
@@ -1763,11 +1763,12 @@ warn.forProperties(exports, 'deprecated', ['emitErrs', 'levelLength']);
1763
1763
  Object.defineProperty(exports, "__esModule", ({ value: true }));
1764
1764
  exports.simplifyEnvList = simplifyEnvList;
1765
1765
  exports.registerEnvTools = registerEnvTools;
1766
+ const toolbox_1 = __webpack_require__(25901);
1766
1767
  const zod_1 = __webpack_require__(21614);
1767
1768
  const auth_js_1 = __webpack_require__(77291);
1768
1769
  const cloudbase_manager_js_1 = __webpack_require__(3431);
1769
1770
  const logger_js_1 = __webpack_require__(13039);
1770
- const interactive_js_1 = __webpack_require__(3461);
1771
+ const tool_result_js_1 = __webpack_require__(9835);
1771
1772
  const rag_js_1 = __webpack_require__(64215);
1772
1773
  /**
1773
1774
  * Simplify environment list data by keeping only essential fields for AI assistant
@@ -1799,17 +1800,119 @@ function simplifyEnvList(envList) {
1799
1800
  return simplified;
1800
1801
  });
1801
1802
  }
1803
+ function formatDeviceAuthHint(deviceAuthInfo) {
1804
+ if (!deviceAuthInfo) {
1805
+ return "";
1806
+ }
1807
+ const lines = [
1808
+ "",
1809
+ "### Device Flow 授权信息",
1810
+ `- user_code: ${deviceAuthInfo.user_code}`,
1811
+ ];
1812
+ if (deviceAuthInfo.verification_uri) {
1813
+ lines.push(`- verification_uri: ${deviceAuthInfo.verification_uri}`);
1814
+ }
1815
+ lines.push(`- expires_in: ${deviceAuthInfo.expires_in}s`);
1816
+ lines.push("", "请在另一台可用浏览器设备打开 `verification_uri` 并输入 `user_code` 完成授权。");
1817
+ return lines.join("\n");
1818
+ }
1819
+ function emitDeviceAuthNotice(server, deviceAuthInfo) {
1820
+ // Temporarily disabled: avoid sending logging notifications for device auth
1821
+ }
1822
+ async function fetchAvailableEnvCandidates(cloudBaseOptions, server) {
1823
+ try {
1824
+ return await (0, cloudbase_manager_js_1.listAvailableEnvCandidates)({
1825
+ cloudBaseOptions,
1826
+ });
1827
+ }
1828
+ catch {
1829
+ return [];
1830
+ }
1831
+ }
1832
+ const CODEBUDDY_AUTH_ACTIONS = ["status", "set_env"];
1833
+ const DEFAULT_AUTH_ACTIONS = [
1834
+ "status",
1835
+ "start_auth",
1836
+ "set_env",
1837
+ "logout",
1838
+ ];
1839
+ function getCurrentIde(server) {
1840
+ return server.ide || process.env.INTEGRATION_IDE || "";
1841
+ }
1842
+ function isCodeBuddyIde(server) {
1843
+ return getCurrentIde(server) === "CodeBuddy";
1844
+ }
1845
+ function getSupportedAuthActions(server) {
1846
+ return isCodeBuddyIde(server) ? CODEBUDDY_AUTH_ACTIONS : DEFAULT_AUTH_ACTIONS;
1847
+ }
1848
+ function buildAuthRequiredNextStep(server) {
1849
+ if (isCodeBuddyIde(server)) {
1850
+ return (0, tool_result_js_1.buildAuthNextStep)("status", {
1851
+ suggestedArgs: { action: "status" },
1852
+ });
1853
+ }
1854
+ return (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
1855
+ suggestedArgs: { action: "start_auth", authMode: "device" },
1856
+ });
1857
+ }
1858
+ function buildSetEnvNextStep(envCandidates) {
1859
+ const singleEnvId = envCandidates.length === 1 ? envCandidates[0].envId : undefined;
1860
+ return (0, tool_result_js_1.buildAuthNextStep)("set_env", {
1861
+ requiredParams: singleEnvId ? undefined : ["envId"],
1862
+ suggestedArgs: singleEnvId
1863
+ ? { action: "set_env", envId: singleEnvId }
1864
+ : { action: "set_env" },
1865
+ });
1866
+ }
1867
+ async function getGuidePrompt(server) {
1868
+ if (getCurrentIde(server) === "CodeBuddy" ||
1869
+ process.env.CLOUDBASE_GUIDE_PROMPT === "false") {
1870
+ return "";
1871
+ }
1872
+ try {
1873
+ return await (0, rag_js_1.getClaudePrompt)();
1874
+ }
1875
+ catch (promptError) {
1876
+ (0, logger_js_1.debug)("Failed to get CLAUDE prompt", { error: promptError });
1877
+ return "";
1878
+ }
1879
+ }
1802
1880
  function registerEnvTools(server) {
1803
1881
  // 获取 cloudBaseOptions,如果没有则为 undefined
1804
1882
  const cloudBaseOptions = server.cloudBaseOptions;
1805
1883
  const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions, mcpServer: server });
1806
1884
  const hasEnvId = typeof cloudBaseOptions?.envId === 'string' && cloudBaseOptions?.envId.length > 0;
1807
- // login - 登录云开发环境
1808
- server.registerTool?.("login", {
1809
- title: "登录云开发",
1810
- description: "登录云开发环境,在生成包含云开发 CloudBase 相关功能前**必须**先调用此工具进行登录。登录云开发环境并选择要使用的环境。",
1885
+ const supportedAuthActions = getSupportedAuthActions(server);
1886
+ const authActionEnum = [...supportedAuthActions];
1887
+ // auth - CloudBase (云开发) 开发阶段登录与环境绑定
1888
+ server.registerTool?.("auth", {
1889
+ title: "CloudBase 开发阶段登录与环境",
1890
+ description: "CloudBase(腾讯云开发)开发阶段登录与环境绑定。登录后即可访问云资源;环境(env)是云函数、数据库、静态托管等资源的隔离单元,绑定环境后其他 MCP 工具才能操作该环境。支持:查询状态、发起登录、绑定环境(set_env)、退出登录。",
1811
1891
  inputSchema: {
1812
- forceUpdate: zod_1.z.boolean().optional().describe("是否强制重新选择环境"),
1892
+ action: zod_1.z
1893
+ .enum(authActionEnum)
1894
+ .optional()
1895
+ .describe("动作:status=查询状态,start_auth=发起登录,set_env=绑定环境(传envId),logout=退出登录"),
1896
+ ...(supportedAuthActions.includes("start_auth")
1897
+ ? {
1898
+ authMode: zod_1.z
1899
+ .enum(["device", "web"])
1900
+ .optional()
1901
+ .describe("认证模式:device=设备码授权,web=浏览器回调授权"),
1902
+ }
1903
+ : {}),
1904
+ envId: zod_1.z
1905
+ .string()
1906
+ .optional()
1907
+ .describe("环境ID(CloudBase 环境唯一标识),绑定后工具将操作该环境。action=set_env 时必填"),
1908
+ ...(supportedAuthActions.includes("logout")
1909
+ ? {
1910
+ confirm: zod_1.z
1911
+ .literal("yes")
1912
+ .optional()
1913
+ .describe("action=logout 时确认操作,传 yes"),
1914
+ }
1915
+ : {}),
1813
1916
  },
1814
1917
  annotations: {
1815
1918
  readOnlyHint: false,
@@ -1818,135 +1921,326 @@ function registerEnvTools(server) {
1818
1921
  openWorldHint: true,
1819
1922
  category: "env",
1820
1923
  },
1821
- }, async ({ forceUpdate = false }) => {
1822
- let isSwitching = false;
1924
+ }, async (rawArgs) => {
1925
+ const action = rawArgs.action ?? "status";
1926
+ const authMode = rawArgs.authMode === "device" || rawArgs.authMode === "web"
1927
+ ? rawArgs.authMode
1928
+ : undefined;
1929
+ const envId = rawArgs.envId;
1930
+ const confirm = rawArgs.confirm === "yes" ? "yes" : undefined;
1931
+ let deviceAuthInfo;
1932
+ const onDeviceCode = (info) => {
1933
+ deviceAuthInfo = info;
1934
+ (0, auth_js_1.setPendingAuthProgressState)(info, "device");
1935
+ // emitDeviceAuthNotice(server, info);
1936
+ };
1937
+ const authChallenge = () => deviceAuthInfo
1938
+ ? {
1939
+ user_code: deviceAuthInfo.user_code,
1940
+ verification_uri: deviceAuthInfo.verification_uri,
1941
+ expires_in: deviceAuthInfo.expires_in,
1942
+ }
1943
+ : undefined;
1823
1944
  try {
1824
- // 使用 while 循环处理用户切换账号的情况
1825
- while (true) {
1826
- // CRITICAL: Ensure server is passed correctly
1827
- (0, logger_js_1.debug)("[env] Calling _promptAndSetEnvironmentId with server:", {
1828
- hasServer: !!server,
1829
- serverType: typeof server,
1830
- hasServerServer: !!server?.server,
1831
- hasServerIde: !!server?.ide,
1832
- serverIde: server?.ide
1833
- });
1834
- const { selectedEnvId, cancelled, error, noEnvs, switch: switchAccount, } = await (0, interactive_js_1._promptAndSetEnvironmentId)(forceUpdate, {
1835
- server, // Pass ExtendedMcpServer instance
1836
- loginFromCloudBaseLoginPage: isSwitching,
1837
- // When switching account, ignore environment variables to force Web login
1838
- ignoreEnvVars: isSwitching,
1945
+ if (!supportedAuthActions.includes(action)) {
1946
+ return (0, tool_result_js_1.buildJsonToolResult)({
1947
+ ok: false,
1948
+ code: "NOT_SUPPORTED",
1949
+ message: `当前 IDE 不支持 auth(action="${action}")。`,
1950
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
1951
+ suggestedArgs: { action: "status" },
1952
+ }),
1839
1953
  });
1840
- isSwitching = Boolean(switchAccount);
1841
- (0, logger_js_1.debug)("login", {
1842
- selectedEnvId,
1843
- cancelled,
1844
- error,
1845
- noEnvs,
1846
- switchAccount,
1954
+ }
1955
+ if (action === "status") {
1956
+ const loginState = await (0, auth_js_1.peekLoginState)();
1957
+ const authFlowState = await (0, auth_js_1.getAuthProgressState)();
1958
+ const envId = (0, cloudbase_manager_js_1.getCachedEnvId)() ||
1959
+ process.env.CLOUDBASE_ENV_ID ||
1960
+ (typeof loginState?.envId === "string" ? loginState.envId : undefined);
1961
+ const authStatus = loginState
1962
+ ? "READY"
1963
+ : authFlowState.status === "PENDING"
1964
+ ? "PENDING"
1965
+ : "REQUIRED";
1966
+ const envCandidates = await fetchAvailableEnvCandidates(cloudBaseOptions, server);
1967
+ const envStatus = envId
1968
+ ? "READY"
1969
+ : envCandidates.length > 1
1970
+ ? "MULTIPLE"
1971
+ : envCandidates.length === 1
1972
+ ? "READY"
1973
+ : "NONE";
1974
+ const message = authStatus === "READY"
1975
+ ? `当前已登录${envId ? `,环境: ${envId}` : ",但未绑定环境"}`
1976
+ : authStatus === "PENDING"
1977
+ ? "设备码授权进行中,请完成浏览器授权后再次调用 auth(action=\"status\")"
1978
+ : isCodeBuddyIde(server)
1979
+ ? "当前未登录。CodeBuddy 暂不支持在 tool 内发起认证,请在外部完成认证后再次调用 auth(action=\"status\")。"
1980
+ : "当前未登录,请先执行 auth(action=\"start_auth\")";
1981
+ return (0, tool_result_js_1.buildJsonToolResult)({
1982
+ ok: true,
1983
+ code: "STATUS",
1984
+ auth_status: authStatus,
1985
+ env_status: envStatus,
1986
+ current_env_id: envId || null,
1987
+ env_candidates: envCandidates,
1988
+ auth_challenge: authFlowState.status === "PENDING" && authFlowState.authChallenge
1989
+ ? {
1990
+ user_code: authFlowState.authChallenge.user_code,
1991
+ verification_uri: authFlowState.authChallenge.verification_uri,
1992
+ expires_in: authFlowState.authChallenge.expires_in,
1993
+ }
1994
+ : undefined,
1995
+ message,
1996
+ next_step: authStatus === "REQUIRED"
1997
+ ? buildAuthRequiredNextStep(server)
1998
+ : authStatus === "PENDING"
1999
+ ? (0, tool_result_js_1.buildAuthNextStep)("status", {
2000
+ suggestedArgs: { action: "status" },
2001
+ })
2002
+ : !envId
2003
+ ? buildSetEnvNextStep(envCandidates)
2004
+ : (0, tool_result_js_1.buildAuthNextStep)("status", {
2005
+ suggestedArgs: { action: "status" },
2006
+ }),
1847
2007
  });
1848
- if (error) {
1849
- return { content: [{ type: "text", text: error }] };
1850
- }
1851
- if (cancelled) {
1852
- return { content: [{ type: "text", text: "用户取消了登录" }] };
2008
+ }
2009
+ if (action === "start_auth") {
2010
+ const region = server.cloudBaseOptions?.region || process.env.TCB_REGION;
2011
+ const auth = toolbox_1.AuthSupervisor.getInstance({});
2012
+ const authFlowState = await (0, auth_js_1.getAuthProgressState)();
2013
+ if (authFlowState.status === "PENDING" && authFlowState.authChallenge) {
2014
+ return (0, tool_result_js_1.buildJsonToolResult)({
2015
+ ok: true,
2016
+ code: "AUTH_PENDING",
2017
+ message: "设备码授权进行中,请在浏览器中打开 verification_uri 并输入 user_code 完成授权。",
2018
+ auth_challenge: {
2019
+ user_code: authFlowState.authChallenge.user_code,
2020
+ verification_uri: authFlowState.authChallenge.verification_uri,
2021
+ expires_in: authFlowState.authChallenge.expires_in,
2022
+ },
2023
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
2024
+ suggestedArgs: { action: "status" },
2025
+ }),
2026
+ });
1853
2027
  }
1854
- // 用户选择切换账号,先 logout 再重新登录
1855
- if (switchAccount) {
1856
- (0, logger_js_1.debug)("User requested switch account, logging out...");
1857
- try {
1858
- await (0, auth_js_1.logout)();
1859
- (0, cloudbase_manager_js_1.resetCloudBaseManagerCache)();
1860
- (0, logger_js_1.debug)("Logged out successfully, restarting login flow...");
1861
- // Set isSwitching to true so next iteration will ignore env vars
1862
- // and force Web authentication to allow account switching
1863
- isSwitching = true;
1864
- // 继续循环,重新显示登录界面
1865
- continue;
1866
- }
1867
- catch (logoutError) {
1868
- (0, logger_js_1.debug)("Logout failed during switch", { error: logoutError });
1869
- continue;
2028
+ // 1. 如果已经有登录态,直接返回 AUTH_READY
2029
+ try {
2030
+ const existingLoginState = await (0, auth_js_1.peekLoginState)();
2031
+ if (existingLoginState) {
2032
+ const envId = typeof existingLoginState.envId === "string" ? existingLoginState.envId : null;
2033
+ const envCandidates = envId
2034
+ ? []
2035
+ : await fetchAvailableEnvCandidates(cloudBaseOptions, server);
2036
+ return (0, tool_result_js_1.buildJsonToolResult)({
2037
+ ok: true,
2038
+ code: "AUTH_READY",
2039
+ message: envId
2040
+ ? `认证成功,当前登录态 envId: ${envId}`
2041
+ : "认证成功",
2042
+ auth_challenge: authChallenge(),
2043
+ env_candidates: envCandidates,
2044
+ next_step: envId
2045
+ ? (0, tool_result_js_1.buildAuthNextStep)("status", {
2046
+ suggestedArgs: { action: "status" },
2047
+ })
2048
+ : buildSetEnvNextStep(envCandidates),
2049
+ });
1870
2050
  }
1871
2051
  }
1872
- if (selectedEnvId) {
1873
- // Get CLAUDE.md prompt content (skip for CodeBuddy IDE)
1874
- let promptContent = "";
1875
- const currentIde = server.ide || process.env.INTEGRATION_IDE;
1876
- if (currentIde !== "CodeBuddy" && process.env.CLOUDBASE_GUIDE_PROMPT !== "false") {
1877
- try {
1878
- promptContent = await (0, rag_js_1.getClaudePrompt)();
2052
+ catch {
2053
+ // 忽略 getLoginState 错误,继续尝试发起登录
2054
+ }
2055
+ // 2. 设备码模式:监听到 device code 即返回 AUTH_PENDING,后续由 toolbox 异步轮询并更新本地 credential
2056
+ const effectiveMode = authMode && (authMode === "device" || authMode === "web")
2057
+ ? authMode
2058
+ : process.env.TCB_AUTH_MODE === "web"
2059
+ ? "web"
2060
+ : "device";
2061
+ if (effectiveMode === "device") {
2062
+ let resolveCode;
2063
+ let rejectCode;
2064
+ const codeReady = new Promise((resolve, reject) => {
2065
+ resolveCode = resolve;
2066
+ rejectCode = reject;
2067
+ });
2068
+ const deviceOnCode = (info) => {
2069
+ onDeviceCode(info);
2070
+ if (resolveCode) {
2071
+ resolveCode();
1879
2072
  }
1880
- catch (promptError) {
1881
- (0, logger_js_1.debug)("Failed to get CLAUDE prompt", { error: promptError });
1882
- // Continue with login success even if prompt fetch fails
2073
+ };
2074
+ try {
2075
+ // 启动 Device Flow,全流程由 toolbox 负责轮询和写入 credential,这里不等待完成
2076
+ auth
2077
+ .loginByWebAuth({
2078
+ flow: "device",
2079
+ onDeviceCode: deviceOnCode,
2080
+ })
2081
+ .then(() => {
2082
+ (0, auth_js_1.resolveAuthProgressState)();
2083
+ })
2084
+ .catch((err) => {
2085
+ (0, auth_js_1.rejectAuthProgressState)(err);
2086
+ // 如果在拿到 device code 之前就失败,则唤醒当前调用并返回错误
2087
+ if (!deviceAuthInfo && rejectCode) {
2088
+ rejectCode(err);
2089
+ }
2090
+ });
2091
+ }
2092
+ catch (err) {
2093
+ if (rejectCode) {
2094
+ rejectCode(err);
1883
2095
  }
1884
2096
  }
1885
- const successMessage = `✅ 登录成功,当前环境: ${selectedEnvId}`;
1886
- const promptMessage = promptContent
1887
- ? `\n\n⚠️ 重要提示:后续所有云开发相关的开发工作必须严格遵循以下开发规范和最佳实践:\n\n${promptContent}`
1888
- : "";
1889
- return {
1890
- content: [
1891
- {
1892
- type: "text",
1893
- text: successMessage + promptMessage,
1894
- },
1895
- ],
1896
- };
2097
+ try {
2098
+ await codeReady;
2099
+ }
2100
+ catch (err) {
2101
+ const message = err instanceof Error ? err.message : String(err ?? "unknown error");
2102
+ return (0, tool_result_js_1.buildJsonToolResult)({
2103
+ ok: false,
2104
+ code: "AUTH_REQUIRED",
2105
+ message: `设备码登录初始化失败: ${message}`,
2106
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
2107
+ suggestedArgs: { action: "start_auth", authMode: "device" },
2108
+ }),
2109
+ });
2110
+ }
2111
+ if (!deviceAuthInfo) {
2112
+ return (0, tool_result_js_1.buildJsonToolResult)({
2113
+ ok: false,
2114
+ code: "AUTH_REQUIRED",
2115
+ message: "未获取到设备码信息,请重试设备码登录",
2116
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
2117
+ suggestedArgs: { action: "start_auth", authMode: "device" },
2118
+ }),
2119
+ });
2120
+ }
2121
+ const envCandidates = await fetchAvailableEnvCandidates(cloudBaseOptions, server);
2122
+ return (0, tool_result_js_1.buildJsonToolResult)({
2123
+ ok: true,
2124
+ code: "AUTH_PENDING",
2125
+ message: "已发起设备码登录,请在浏览器中打开 verification_uri 并输入 user_code 完成授权。授权完成后请再次调用 auth(action=\"status\")。",
2126
+ auth_challenge: authChallenge(),
2127
+ env_candidates: envCandidates,
2128
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
2129
+ suggestedArgs: { action: "status" },
2130
+ }),
2131
+ });
1897
2132
  }
1898
- throw new Error("登录失败");
2133
+ // 3. 非 Device Flow(显式 web 模式)仍然使用 getLoginState 阻塞等待
2134
+ const loginState = await (0, auth_js_1.ensureLogin)({
2135
+ region,
2136
+ authMode: effectiveMode,
2137
+ });
2138
+ if (!loginState) {
2139
+ return (0, tool_result_js_1.buildJsonToolResult)({
2140
+ ok: false,
2141
+ code: "AUTH_REQUIRED",
2142
+ message: "未获取到登录态,请先完成认证",
2143
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
2144
+ suggestedArgs: { action: "start_auth", authMode: effectiveMode },
2145
+ }),
2146
+ });
2147
+ }
2148
+ const envId = typeof loginState.envId === "string" ? loginState.envId : null;
2149
+ const envCandidates = envId
2150
+ ? []
2151
+ : await fetchAvailableEnvCandidates(cloudBaseOptions, server);
2152
+ return (0, tool_result_js_1.buildJsonToolResult)({
2153
+ ok: true,
2154
+ code: "AUTH_READY",
2155
+ message: envId ? `认证成功,当前登录态 envId: ${envId}` : "认证成功",
2156
+ auth_challenge: authChallenge(),
2157
+ env_candidates: envCandidates,
2158
+ next_step: envId
2159
+ ? (0, tool_result_js_1.buildAuthNextStep)("status", {
2160
+ suggestedArgs: { action: "status" },
2161
+ })
2162
+ : buildSetEnvNextStep(envCandidates),
2163
+ });
1899
2164
  }
2165
+ if (action === "set_env") {
2166
+ const loginState = await (0, auth_js_1.peekLoginState)();
2167
+ if (!loginState) {
2168
+ return (0, tool_result_js_1.buildJsonToolResult)({
2169
+ ok: false,
2170
+ code: "AUTH_REQUIRED",
2171
+ message: isCodeBuddyIde(server)
2172
+ ? "当前未登录。CodeBuddy 暂不支持在 tool 内发起认证,请在外部完成认证后再次调用 auth(action=\"status\")。"
2173
+ : "当前未登录,请先执行 auth(action=\"start_auth\")。",
2174
+ next_step: buildAuthRequiredNextStep(server),
2175
+ });
2176
+ }
2177
+ const envCandidates = await fetchAvailableEnvCandidates(cloudBaseOptions, server);
2178
+ if (!envId) {
2179
+ return (0, tool_result_js_1.buildJsonToolResult)({
2180
+ ok: false,
2181
+ code: "INVALID_ARGS",
2182
+ message: "action=set_env 时必须提供 envId",
2183
+ env_candidates: envCandidates,
2184
+ next_step: buildSetEnvNextStep(envCandidates),
2185
+ });
2186
+ }
2187
+ const target = envCandidates.find((item) => item.envId === envId);
2188
+ if (envCandidates.length > 0 && !target) {
2189
+ return (0, tool_result_js_1.buildJsonToolResult)({
2190
+ ok: false,
2191
+ code: "INVALID_ARGS",
2192
+ message: `未找到环境: ${envId}`,
2193
+ env_candidates: envCandidates,
2194
+ next_step: buildSetEnvNextStep(envCandidates),
2195
+ });
2196
+ }
2197
+ await cloudbase_manager_js_1.envManager.setEnvId(envId);
2198
+ return (0, tool_result_js_1.buildJsonToolResult)({
2199
+ ok: true,
2200
+ code: "ENV_READY",
2201
+ message: `环境设置成功,当前环境: ${envId}`,
2202
+ current_env_id: envId,
2203
+ });
2204
+ }
2205
+ if (action === "logout") {
2206
+ if (confirm !== "yes") {
2207
+ return (0, tool_result_js_1.buildJsonToolResult)({
2208
+ ok: false,
2209
+ code: "INVALID_ARGS",
2210
+ message: "action=logout 时必须传 confirm=\"yes\"",
2211
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("logout", {
2212
+ suggestedArgs: { action: "logout", confirm: "yes" },
2213
+ }),
2214
+ });
2215
+ }
2216
+ await (0, auth_js_1.logout)();
2217
+ (0, cloudbase_manager_js_1.resetCloudBaseManagerCache)();
2218
+ return (0, tool_result_js_1.buildJsonToolResult)({
2219
+ ok: true,
2220
+ code: "LOGGED_OUT",
2221
+ message: "✅ 已退出登录",
2222
+ });
2223
+ }
2224
+ return (0, tool_result_js_1.buildJsonToolResult)({
2225
+ ok: false,
2226
+ code: "NOT_SUPPORTED",
2227
+ message: `不支持的 auth action: ${action}`,
2228
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
2229
+ suggestedArgs: { action: "status" },
2230
+ }),
2231
+ });
1900
2232
  }
1901
2233
  catch (error) {
1902
- return {
1903
- content: [
1904
- {
1905
- type: "text",
1906
- text: `登录失败: ${error instanceof Error ? error.message : String(error)}`,
1907
- },
1908
- ],
1909
- };
1910
- }
1911
- });
1912
- // logout - 退出云开发环境
1913
- server.registerTool?.("logout", {
1914
- title: "退出登录",
1915
- description: "退出云开发环境",
1916
- inputSchema: {
1917
- confirm: zod_1.z.literal("yes").describe("确认操作,默认传 yes"),
1918
- },
1919
- annotations: {
1920
- readOnlyHint: false,
1921
- destructiveHint: false,
1922
- idempotentHint: true,
1923
- openWorldHint: false,
1924
- category: "env",
1925
- },
1926
- }, async () => {
1927
- try {
1928
- // 登出账户
1929
- await (0, auth_js_1.logout)();
1930
- // 清理环境ID缓存
1931
- (0, cloudbase_manager_js_1.resetCloudBaseManagerCache)();
1932
- return {
1933
- content: [
1934
- {
1935
- type: "text",
1936
- text: "✅ 已退出登录",
1937
- },
1938
- ],
1939
- };
1940
- }
1941
- catch (error) {
1942
- return {
1943
- content: [
1944
- {
1945
- type: "text",
1946
- text: `退出失败: ${error instanceof Error ? error.message : String(error)}`,
1947
- },
1948
- ],
1949
- };
2234
+ const message = error instanceof Error ? error.message : String(error);
2235
+ return (0, tool_result_js_1.buildJsonToolResult)({
2236
+ ok: false,
2237
+ code: "INTERNAL_ERROR",
2238
+ message: `auth 执行失败: ${message}`,
2239
+ auth_challenge: authChallenge(),
2240
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
2241
+ suggestedArgs: { action: "status" },
2242
+ }),
2243
+ });
1950
2244
  }
1951
2245
  });
1952
2246
  // envQuery - 环境查询(合并 listEnvs + getEnvInfo + getEnvAuthDomains + getWebsiteConfig)
@@ -2020,6 +2314,10 @@ function registerEnvTools(server) {
2020
2314
  }
2021
2315
  }
2022
2316
  catch (fallbackError) {
2317
+ const toolPayloadResult = (0, tool_result_js_1.toolPayloadErrorToResult)(fallbackError);
2318
+ if (toolPayloadResult) {
2319
+ return toolPayloadResult;
2320
+ }
2023
2321
  (0, logger_js_1.debug)("降级到 listEnvs() 也失败:", fallbackError instanceof Error ? fallbackError : new Error(String(fallbackError)));
2024
2322
  return {
2025
2323
  content: [
@@ -2083,6 +2381,10 @@ function registerEnvTools(server) {
2083
2381
  };
2084
2382
  }
2085
2383
  catch (error) {
2384
+ const toolPayloadResult = (0, tool_result_js_1.toolPayloadErrorToResult)(error);
2385
+ if (toolPayloadResult) {
2386
+ return toolPayloadResult;
2387
+ }
2086
2388
  return {
2087
2389
  content: [
2088
2390
  {
@@ -2136,6 +2438,10 @@ function registerEnvTools(server) {
2136
2438
  };
2137
2439
  }
2138
2440
  catch (error) {
2441
+ const toolPayloadResult = (0, tool_result_js_1.toolPayloadErrorToResult)(error);
2442
+ if (toolPayloadResult) {
2443
+ return toolPayloadResult;
2444
+ }
2139
2445
  return {
2140
2446
  content: [
2141
2447
  {
@@ -5336,7 +5642,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;/**
5336
5642
  var undefined;
5337
5643
 
5338
5644
  /** Used as the semantic version number. */
5339
- var VERSION = '4.17.21';
5645
+ var VERSION = '4.17.23';
5340
5646
 
5341
5647
  /** Used as the size to enable large array optimizations. */
5342
5648
  var LARGE_ARRAY_SIZE = 200;
@@ -9090,7 +9396,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;/**
9090
9396
  if (isArray(iteratee)) {
9091
9397
  return function(value) {
9092
9398
  return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);
9093
- }
9399
+ };
9094
9400
  }
9095
9401
  return iteratee;
9096
9402
  });
@@ -9694,8 +10000,47 @@ var __WEBPACK_AMD_DEFINE_RESULT__;/**
9694
10000
  */
9695
10001
  function baseUnset(object, path) {
9696
10002
  path = castPath(path, object);
9697
- object = parent(object, path);
9698
- return object == null || delete object[toKey(last(path))];
10003
+
10004
+ // Prevent prototype pollution, see: https://github.com/lodash/lodash/security/advisories/GHSA-xxjr-mmjv-4gpg
10005
+ var index = -1,
10006
+ length = path.length;
10007
+
10008
+ if (!length) {
10009
+ return true;
10010
+ }
10011
+
10012
+ var isRootPrimitive = object == null || (typeof object !== 'object' && typeof object !== 'function');
10013
+
10014
+ while (++index < length) {
10015
+ var key = path[index];
10016
+
10017
+ // skip non-string keys (e.g., Symbols, numbers)
10018
+ if (typeof key !== 'string') {
10019
+ continue;
10020
+ }
10021
+
10022
+ // Always block "__proto__" anywhere in the path if it's not expected
10023
+ if (key === '__proto__' && !hasOwnProperty.call(object, '__proto__')) {
10024
+ return false;
10025
+ }
10026
+
10027
+ // Block "constructor.prototype" chains
10028
+ if (key === 'constructor' &&
10029
+ (index + 1) < length &&
10030
+ typeof path[index + 1] === 'string' &&
10031
+ path[index + 1] === 'prototype') {
10032
+
10033
+ // Allow ONLY when the path starts at a primitive root, e.g., _.unset(0, 'constructor.prototype.a')
10034
+ if (isRootPrimitive && index === 0) {
10035
+ continue;
10036
+ }
10037
+
10038
+ return false;
10039
+ }
10040
+ }
10041
+
10042
+ var obj = parent(object, path);
10043
+ return obj == null || delete obj[toKey(last(path))];
9699
10044
  }
9700
10045
 
9701
10046
  /**
@@ -23781,6 +24126,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
23781
24126
  };
23782
24127
  Object.defineProperty(exports, "__esModule", ({ value: true }));
23783
24128
  exports.envManager = void 0;
24129
+ exports.listAvailableEnvCandidates = listAvailableEnvCandidates;
23784
24130
  exports.getEnvId = getEnvId;
23785
24131
  exports.resetCloudBaseManagerCache = resetCloudBaseManagerCache;
23786
24132
  exports.getCachedEnvId = getCachedEnvId;
@@ -23790,9 +24136,134 @@ exports.extractRequestId = extractRequestId;
23790
24136
  exports.logCloudBaseResult = logCloudBaseResult;
23791
24137
  const manager_node_1 = __importDefault(__webpack_require__(95492));
23792
24138
  const auth_js_1 = __webpack_require__(77291);
23793
- const interactive_js_1 = __webpack_require__(3461);
23794
24139
  const logger_js_1 = __webpack_require__(13039);
23795
- const ENV_ID_TIMEOUT = 600000; // 10 minutes (600 seconds) - matches InteractiveServer timeout
24140
+ const tool_result_js_1 = __webpack_require__(9835);
24141
+ // Timeout for envId auto-resolution flow.
24142
+ // 10 minutes (600 seconds) - matches InteractiveServer timeout
24143
+ const ENV_ID_TIMEOUT = 600000;
24144
+ function toEnvCandidates(envList) {
24145
+ if (!Array.isArray(envList)) {
24146
+ return [];
24147
+ }
24148
+ return envList
24149
+ .filter((item) => item?.EnvId)
24150
+ .map((item) => ({
24151
+ envId: item.EnvId,
24152
+ alias: item.Alias,
24153
+ region: item.Region,
24154
+ status: item.Status,
24155
+ env_type: item.EnvType,
24156
+ }));
24157
+ }
24158
+ function createManagerFromLoginState(loginState, region) {
24159
+ return new manager_node_1.default({
24160
+ secretId: loginState.secretId,
24161
+ secretKey: loginState.secretKey,
24162
+ envId: loginState.envId,
24163
+ token: loginState.token,
24164
+ proxy: process.env.http_proxy,
24165
+ region,
24166
+ });
24167
+ }
24168
+ async function listAvailableEnvCandidates(options) {
24169
+ const { cloudBaseOptions, loginState: providedLoginState } = options ?? {};
24170
+ if (cloudBaseOptions?.envId) {
24171
+ return [{
24172
+ envId: cloudBaseOptions.envId,
24173
+ }];
24174
+ }
24175
+ let cloudbase;
24176
+ if (cloudBaseOptions?.secretId && cloudBaseOptions?.secretKey) {
24177
+ cloudbase = createCloudBaseManagerWithOptions(cloudBaseOptions);
24178
+ }
24179
+ else {
24180
+ const loginState = providedLoginState ?? await (0, auth_js_1.peekLoginState)();
24181
+ if (!loginState?.secretId || !loginState?.secretKey) {
24182
+ return [];
24183
+ }
24184
+ const region = cloudBaseOptions?.region ?? process.env.TCB_REGION ?? undefined;
24185
+ cloudbase = createManagerFromLoginState(loginState, region);
24186
+ }
24187
+ try {
24188
+ const result = await cloudbase.commonService("tcb", "2018-06-08").call({
24189
+ Action: "DescribeEnvs",
24190
+ Param: {
24191
+ EnvTypes: ["weda", "baas"],
24192
+ IsVisible: false,
24193
+ Channels: ["dcloud", "iotenable", "tem", "scene_module"],
24194
+ },
24195
+ });
24196
+ const envList = result?.EnvList || result?.Data?.EnvList || [];
24197
+ return toEnvCandidates(envList);
24198
+ }
24199
+ catch {
24200
+ try {
24201
+ const fallback = await cloudbase.env.listEnvs();
24202
+ return toEnvCandidates(fallback?.EnvList || []);
24203
+ }
24204
+ catch {
24205
+ return [];
24206
+ }
24207
+ }
24208
+ }
24209
+ function throwAuthRequiredError() {
24210
+ (0, tool_result_js_1.throwToolPayloadError)({
24211
+ ok: false,
24212
+ code: "AUTH_REQUIRED",
24213
+ message: "当前未登录,请先调用 auth 工具完成认证。",
24214
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
24215
+ suggestedArgs: {
24216
+ action: "start_auth",
24217
+ authMode: "device",
24218
+ },
24219
+ }),
24220
+ });
24221
+ }
24222
+ async function throwPendingAuthError() {
24223
+ const authState = await (0, auth_js_1.getAuthProgressState)();
24224
+ (0, tool_result_js_1.throwToolPayloadError)({
24225
+ ok: false,
24226
+ code: "AUTH_PENDING",
24227
+ message: authState.lastError || "设备码授权进行中,请先完成登录后再重试当前工具。",
24228
+ auth_challenge: authState.authChallenge
24229
+ ? {
24230
+ user_code: authState.authChallenge.user_code,
24231
+ verification_uri: authState.authChallenge.verification_uri,
24232
+ expires_in: authState.authChallenge.expires_in,
24233
+ }
24234
+ : undefined,
24235
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
24236
+ suggestedArgs: {
24237
+ action: "status",
24238
+ },
24239
+ }),
24240
+ });
24241
+ }
24242
+ async function throwEnvRequiredError(options) {
24243
+ const envCandidates = options?.envCandidates ?? (await listAvailableEnvCandidates(options));
24244
+ const singleEnvId = envCandidates.length === 1 ? envCandidates[0].envId : undefined;
24245
+ (0, tool_result_js_1.throwToolPayloadError)({
24246
+ ok: false,
24247
+ code: "ENV_REQUIRED",
24248
+ message: envCandidates.length === 0
24249
+ ? "当前已登录,但还没有可用环境,请先调用 auth 工具完成环境选择或创建环境。"
24250
+ : envCandidates.length === 1
24251
+ ? `当前已登录,但尚未绑定环境。可直接选择环境 ${singleEnvId}。`
24252
+ : "当前已登录,但尚未绑定环境,请先调用 auth 工具选择环境。",
24253
+ env_candidates: envCandidates,
24254
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("set_env", {
24255
+ requiredParams: singleEnvId ? undefined : ["envId"],
24256
+ suggestedArgs: singleEnvId
24257
+ ? {
24258
+ action: "set_env",
24259
+ envId: singleEnvId,
24260
+ }
24261
+ : {
24262
+ action: "set_env",
24263
+ },
24264
+ }),
24265
+ });
24266
+ }
23796
24267
  // 统一的环境ID管理类
23797
24268
  class EnvironmentManager {
23798
24269
  cachedEnvId = null;
@@ -23804,7 +24275,7 @@ class EnvironmentManager {
23804
24275
  delete process.env.CLOUDBASE_ENV_ID;
23805
24276
  }
23806
24277
  // 获取环境ID的核心逻辑
23807
- async getEnvId(mcpServer) {
24278
+ async getEnvId() {
23808
24279
  // 1. 优先使用内存缓存
23809
24280
  if (this.cachedEnvId) {
23810
24281
  (0, logger_js_1.debug)('使用内存缓存的环境ID:', { envId: this.cachedEnvId });
@@ -23814,17 +24285,10 @@ class EnvironmentManager {
23814
24285
  if (this.envIdPromise) {
23815
24286
  return this.envIdPromise;
23816
24287
  }
23817
- // 3. 开始获取环境ID (pass mcpServer for IDE detection)
23818
- this.envIdPromise = this._fetchEnvId(mcpServer);
23819
- // 增加超时保护
23820
- const timeoutPromise = new Promise((_, reject) => {
23821
- const id = setTimeout(() => {
23822
- clearTimeout(id);
23823
- reject(new Error(`EnvId 获取超时(${ENV_ID_TIMEOUT / 1000}秒)`));
23824
- }, ENV_ID_TIMEOUT);
23825
- });
24288
+ // 3. 开始获取环境ID
24289
+ this.envIdPromise = this._fetchEnvId();
23826
24290
  try {
23827
- const result = await Promise.race([this.envIdPromise, timeoutPromise]);
24291
+ const result = await this.envIdPromise;
23828
24292
  return result;
23829
24293
  }
23830
24294
  catch (err) {
@@ -23832,7 +24296,7 @@ class EnvironmentManager {
23832
24296
  throw err;
23833
24297
  }
23834
24298
  }
23835
- async _fetchEnvId(mcpServer) {
24299
+ async _fetchEnvId() {
23836
24300
  try {
23837
24301
  // 1. 检查进程环境变量
23838
24302
  if (process.env.CLOUDBASE_ENV_ID) {
@@ -23840,48 +24304,23 @@ class EnvironmentManager {
23840
24304
  this.cachedEnvId = process.env.CLOUDBASE_ENV_ID;
23841
24305
  return this.cachedEnvId;
23842
24306
  }
23843
- // 2. 自动设置环境ID (pass mcpServer for IDE detection)
23844
- (0, logger_js_1.debug)('未找到环境ID,尝试自动设置...');
23845
- let setupResult;
23846
- try {
23847
- setupResult = await (0, interactive_js_1._promptAndSetEnvironmentId)(true, { server: mcpServer });
23848
- }
23849
- catch (setupError) {
23850
- // Preserve original error information
23851
- const errorObj = setupError instanceof Error ? setupError : new Error(String(setupError));
23852
- (0, logger_js_1.error)('自动设置环境ID时发生异常:', {
23853
- error: errorObj.message,
23854
- stack: errorObj.stack,
23855
- name: errorObj.name,
23856
- });
23857
- // Re-throw with enhanced context
23858
- const enhancedError = new Error(`自动设置环境ID失败: ${errorObj.message}`);
23859
- enhancedError.originalError = errorObj;
23860
- enhancedError.failureInfo = {
23861
- reason: 'unknown_error',
23862
- error: errorObj.message,
23863
- errorCode: 'SETUP_EXCEPTION',
23864
- };
23865
- throw enhancedError;
23866
- }
23867
- const autoEnvId = setupResult.selectedEnvId;
23868
- if (!autoEnvId) {
23869
- // Build detailed error message from failure info
23870
- const errorMessage = this._buildDetailedErrorMessage(setupResult.failureInfo);
23871
- (0, logger_js_1.error)('自动设置环境ID失败:', {
23872
- reason: setupResult.failureInfo?.reason,
23873
- errorCode: setupResult.failureInfo?.errorCode,
23874
- error: setupResult.failureInfo?.error,
23875
- details: setupResult.failureInfo?.details,
23876
- });
23877
- // Create error with detailed information
23878
- const detailedError = new Error(errorMessage);
23879
- detailedError.failureInfo = setupResult.failureInfo;
23880
- throw detailedError;
24307
+ // 2. 如果登录态里已有 envId,直接复用
24308
+ const loginState = await (0, auth_js_1.peekLoginState)();
24309
+ if (typeof loginState?.envId === 'string' && loginState.envId.length > 0) {
24310
+ (0, logger_js_1.debug)('使用登录态中的环境ID:', { envId: loginState.envId });
24311
+ this._setCachedEnvId(loginState.envId);
24312
+ return loginState.envId;
24313
+ }
24314
+ // 3. 单环境自动绑定;多环境时返回结构化引导,不再触发交互弹窗
24315
+ const envCandidates = await listAvailableEnvCandidates({ loginState });
24316
+ if (envCandidates.length === 1) {
24317
+ const singleEnvId = envCandidates[0].envId;
24318
+ (0, logger_js_1.debug)('自动绑定唯一环境:', { envId: singleEnvId });
24319
+ this._setCachedEnvId(singleEnvId);
24320
+ return singleEnvId;
23881
24321
  }
23882
- (0, logger_js_1.debug)('自动设置环境ID成功:', { envId: autoEnvId });
23883
- this._setCachedEnvId(autoEnvId);
23884
- return autoEnvId;
24322
+ await throwEnvRequiredError({ loginState, envCandidates });
24323
+ throw new Error('Unreachable after throwEnvRequiredError');
23885
24324
  }
23886
24325
  catch (err) {
23887
24326
  // Log the error with full context before re-throwing
@@ -23905,65 +24344,6 @@ class EnvironmentManager {
23905
24344
  process.env.CLOUDBASE_ENV_ID = envId;
23906
24345
  (0, logger_js_1.debug)('已更新环境ID缓存:', { envId });
23907
24346
  }
23908
- // Build detailed error message from failure info
23909
- _buildDetailedErrorMessage(failureInfo) {
23910
- if (!failureInfo) {
23911
- return "CloudBase Environment ID not found after auto setup. Please set CLOUDBASE_ENV_ID or run setupEnvironmentId tool.";
23912
- }
23913
- const { reason, error: errorMsg, errorCode, helpUrl, details } = failureInfo;
23914
- let message = "CloudBase Environment ID not found after auto setup.\n\n";
23915
- message += `原因: ${this._getReasonDescription(reason)}\n`;
23916
- if (errorMsg) {
23917
- message += `错误: ${errorMsg}\n`;
23918
- }
23919
- if (errorCode) {
23920
- message += `错误代码: ${errorCode}\n`;
23921
- }
23922
- // Add specific details based on failure reason
23923
- if (reason === 'tcb_init_failed' && details?.initTcbError) {
23924
- const initError = details.initTcbError;
23925
- if (initError.needRealNameAuth) {
23926
- message += "\n需要完成实名认证才能使用 CloudBase 服务。\n";
23927
- }
23928
- if (initError.needCamAuth) {
23929
- message += "\n需要 CAM 权限才能使用 CloudBase 服务。\n";
23930
- }
23931
- }
23932
- if (reason === 'env_creation_failed' && details?.createEnvError) {
23933
- const createError = details.createEnvError;
23934
- message += `\n环境创建失败: ${createError.message || '未知错误'}\n`;
23935
- }
23936
- if (reason === 'env_query_failed' && details?.queryEnvError) {
23937
- message += `\n环境查询失败: ${details.queryEnvError}\n`;
23938
- }
23939
- if (reason === 'timeout' && details?.timeoutDuration) {
23940
- message += `\n超时时间: ${details.timeoutDuration / 1000} 秒\n`;
23941
- message += "提示: 请确保浏览器窗口已打开,并在规定时间内完成环境选择。\n";
23942
- }
23943
- message += "\n解决方案:\n";
23944
- message += "1. 手动设置环境ID: 设置环境变量 CLOUDBASE_ENV_ID\n";
23945
- message += "2. 使用工具设置: 运行 setupEnvironmentId 工具\n";
23946
- if (helpUrl) {
23947
- message += `3. 查看帮助文档: ${helpUrl}\n`;
23948
- }
23949
- else {
23950
- message += "3. 查看帮助文档: https://docs.cloudbase.net/cli-v1/env\n";
23951
- }
23952
- return message;
23953
- }
23954
- _getReasonDescription(reason) {
23955
- const descriptions = {
23956
- 'timeout': '环境选择超时',
23957
- 'cancelled': '用户取消了环境选择',
23958
- 'no_environments': '没有可用环境',
23959
- 'login_failed': '登录失败',
23960
- 'tcb_init_failed': 'CloudBase 服务初始化失败',
23961
- 'env_query_failed': '环境列表查询失败',
23962
- 'env_creation_failed': '环境创建失败',
23963
- 'unknown_error': '未知错误',
23964
- };
23965
- return descriptions[reason] || '未知原因';
23966
- }
23967
24347
  // 手动设置环境ID(用于外部调用)
23968
24348
  async setEnvId(envId) {
23969
24349
  this._setCachedEnvId(envId);
@@ -23984,6 +24364,16 @@ async function getEnvId(cloudBaseOptions) {
23984
24364
  (0, logger_js_1.debug)('使用传入的 envId:', { envId: cloudBaseOptions.envId });
23985
24365
  return cloudBaseOptions.envId;
23986
24366
  }
24367
+ const cachedEnvId = envManager.getCachedEnvId() || process.env.CLOUDBASE_ENV_ID;
24368
+ if (cachedEnvId) {
24369
+ (0, logger_js_1.debug)('使用缓存中的 envId:', { envId: cachedEnvId });
24370
+ return cachedEnvId;
24371
+ }
24372
+ const loginState = await (0, auth_js_1.peekLoginState)();
24373
+ if (typeof loginState?.envId === 'string' && loginState.envId.length > 0) {
24374
+ (0, logger_js_1.debug)('使用登录态中的 envId:', { envId: loginState.envId });
24375
+ return loginState.envId;
24376
+ }
23987
24377
  // 否则使用默认逻辑
23988
24378
  return envManager.getEnvId();
23989
24379
  }
@@ -23999,37 +24389,89 @@ function getCachedEnvId() {
23999
24389
  * 每次都实时获取最新的 token/secretId/secretKey
24000
24390
  */
24001
24391
  async function getCloudBaseManager(options = {}) {
24002
- const { requireEnvId = true, cloudBaseOptions, mcpServer } = options;
24003
- // 如果传入了 cloudBaseOptions,直接使用传入的配置
24004
- if (cloudBaseOptions) {
24392
+ const { requireEnvId = true, cloudBaseOptions, authStrategy = 'fail_fast', } = options;
24393
+ const hasDirectCredentials = !!(cloudBaseOptions?.secretId && cloudBaseOptions?.secretKey);
24394
+ // 如果传入了完整凭据,优先使用显式 CloudBase 配置
24395
+ if (cloudBaseOptions && hasDirectCredentials) {
24396
+ let resolvedEnvId = cloudBaseOptions.envId;
24397
+ if (requireEnvId && !resolvedEnvId) {
24398
+ const envCandidates = await listAvailableEnvCandidates({ cloudBaseOptions });
24399
+ if (envCandidates.length === 1) {
24400
+ const singleEnvId = envCandidates[0].envId;
24401
+ cloudBaseOptions.envId = singleEnvId;
24402
+ resolvedEnvId = singleEnvId;
24403
+ (0, logger_js_1.debug)('自动绑定唯一环境(显式配置):', { envId: singleEnvId });
24404
+ }
24405
+ else if (authStrategy === 'fail_fast') {
24406
+ await throwEnvRequiredError({ cloudBaseOptions, envCandidates });
24407
+ }
24408
+ else {
24409
+ (0, tool_result_js_1.throwToolPayloadError)({
24410
+ ok: false,
24411
+ code: "ENV_REQUIRED",
24412
+ message: "当前显式 CloudBase 凭据未绑定环境,请补充 envId 或先选择环境。",
24413
+ env_candidates: envCandidates,
24414
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("set_env", {
24415
+ suggestedArgs: { action: "set_env" },
24416
+ requiredParams: ["envId"],
24417
+ }),
24418
+ });
24419
+ }
24420
+ }
24005
24421
  (0, logger_js_1.debug)('使用传入的 CloudBase 配置');
24006
- return createCloudBaseManagerWithOptions(cloudBaseOptions);
24422
+ return createCloudBaseManagerWithOptions({
24423
+ ...cloudBaseOptions,
24424
+ envId: resolvedEnvId,
24425
+ });
24007
24426
  }
24008
24427
  try {
24009
24428
  // Get region from environment variable for auth URL
24010
- // Note: At this point, cloudBaseOptions is undefined (checked above), so only use env var
24011
- const region = process.env.TCB_REGION;
24012
- const loginState = await (0, auth_js_1.getLoginState)({ region });
24429
+ const region = cloudBaseOptions?.region ?? process.env.TCB_REGION;
24430
+ const loginState = authStrategy === 'ensure'
24431
+ ? await (0, auth_js_1.getLoginState)({ region })
24432
+ : await (0, auth_js_1.peekLoginState)();
24433
+ if (!loginState) {
24434
+ const authState = await (0, auth_js_1.getAuthProgressState)();
24435
+ if (authState.status === 'PENDING') {
24436
+ await throwPendingAuthError();
24437
+ }
24438
+ throwAuthRequiredError();
24439
+ }
24013
24440
  const { envId: loginEnvId, secretId, secretKey, token } = loginState;
24014
- let finalEnvId;
24441
+ let finalEnvId = cloudBaseOptions?.envId;
24015
24442
  if (requireEnvId) {
24016
- // Optimize: Check if envManager has cached envId first (fast path)
24017
- // If cached, use it directly; otherwise check loginEnvId before calling getEnvId()
24018
- // This avoids unnecessary async calls when we have a valid envId available
24019
- const cachedEnvId = envManager.getCachedEnvId();
24020
- if (cachedEnvId) {
24021
- (0, logger_js_1.debug)('使用 envManager 缓存的环境ID:', { cachedEnvId });
24022
- finalEnvId = cachedEnvId;
24023
- }
24024
- else if (loginEnvId) {
24025
- // If no cache but loginState has envId, use it to avoid triggering auto-setup
24026
- (0, logger_js_1.debug)('使用 loginState 中的环境ID:', { loginEnvId });
24027
- finalEnvId = loginEnvId;
24028
- }
24029
- else {
24030
- // Only call envManager.getEnvId() when neither cache nor loginState has envId
24031
- // This may trigger auto-setup flow (pass mcpServer for IDE detection)
24032
- finalEnvId = await envManager.getEnvId(mcpServer);
24443
+ if (!finalEnvId) {
24444
+ // Optimize: Check if envManager has cached envId first (fast path)
24445
+ // If cached, use it directly; otherwise check loginEnvId before calling getEnvId()
24446
+ // This avoids unnecessary async calls when we have a valid envId available
24447
+ const cachedEnvId = envManager.getCachedEnvId() || process.env.CLOUDBASE_ENV_ID;
24448
+ if (cachedEnvId) {
24449
+ (0, logger_js_1.debug)('使用 envManager 缓存的环境ID:', { cachedEnvId });
24450
+ finalEnvId = cachedEnvId;
24451
+ }
24452
+ else if (loginEnvId) {
24453
+ // If no cache but loginState has envId, use it directly
24454
+ (0, logger_js_1.debug)('使用 loginState 中的环境ID:', { loginEnvId });
24455
+ finalEnvId = loginEnvId;
24456
+ }
24457
+ else {
24458
+ if (authStrategy === 'fail_fast') {
24459
+ const envCandidates = await listAvailableEnvCandidates({ loginState });
24460
+ if (envCandidates.length === 1) {
24461
+ const singleEnvId = envCandidates[0].envId;
24462
+ await envManager.setEnvId(singleEnvId);
24463
+ finalEnvId = singleEnvId;
24464
+ (0, logger_js_1.debug)('自动绑定唯一环境:', { envId: singleEnvId });
24465
+ }
24466
+ else {
24467
+ await throwEnvRequiredError({ loginState, envCandidates });
24468
+ }
24469
+ }
24470
+ else {
24471
+ // ensure 模式下也保持非交互:单环境自动绑定,多环境返回 ENV_REQUIRED
24472
+ finalEnvId = await envManager.getEnvId();
24473
+ }
24474
+ }
24033
24475
  }
24034
24476
  }
24035
24477
  // envId priority: envManager.cachedEnvId > envManager.getEnvId() > loginState.envId > undefined
@@ -24267,6 +24709,7 @@ async function _promptAndSetEnvironmentId(autoSelectSingle, options) {
24267
24709
  hasServerServer: !!server?.server,
24268
24710
  hasServerIde: !!server?.ide,
24269
24711
  ignoreEnvVars: options?.ignoreEnvVars,
24712
+ authMode: options?.authMode,
24270
24713
  optionsKeys: options ? Object.keys(options).join(', ') : 'null',
24271
24714
  });
24272
24715
  if (!server) {
@@ -24283,6 +24726,9 @@ async function _promptAndSetEnvironmentId(autoSelectSingle, options) {
24283
24726
  fromCloudBaseLoginPage: options?.loginFromCloudBaseLoginPage,
24284
24727
  ignoreEnvVars: options?.ignoreEnvVars,
24285
24728
  region,
24729
+ authMode: options?.authMode,
24730
+ clientId: options?.clientId,
24731
+ onDeviceCode: options?.onDeviceCode,
24286
24732
  });
24287
24733
  (0, logger_js_1.debug)("[interactive] Login state:", {
24288
24734
  hasLoginState: !!loginState,
@@ -33910,7 +34356,13 @@ async function getUinForTelemetry() {
33910
34356
  const loginState = await (0, auth_js_1.getLoginState)({ region });
33911
34357
  // Try to extract UIN from loginState
33912
34358
  // Note: actual field name may vary, adjust based on actual response
33913
- return loginState.uin || undefined;
34359
+ if (loginState &&
34360
+ typeof loginState === "object" &&
34361
+ "uin" in loginState &&
34362
+ typeof loginState.uin !== "undefined") {
34363
+ return String(loginState.uin);
34364
+ }
34365
+ return undefined;
33914
34366
  }
33915
34367
  catch (err) {
33916
34368
  (0, logger_js_1.debug)('Failed to get UIN for telemetry', { error: err instanceof Error ? err.message : String(err) });
@@ -40675,6 +41127,61 @@ module.exports = (inputFunction, options = {}) => {
40675
41127
  };
40676
41128
 
40677
41129
 
41130
+ /***/ }),
41131
+
41132
+ /***/ 9835:
41133
+ /***/ ((__unused_webpack_module, exports) => {
41134
+
41135
+ "use strict";
41136
+
41137
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
41138
+ exports.ToolPayloadError = void 0;
41139
+ exports.buildJsonToolResult = buildJsonToolResult;
41140
+ exports.isToolPayloadError = isToolPayloadError;
41141
+ exports.toolPayloadErrorToResult = toolPayloadErrorToResult;
41142
+ exports.buildAuthNextStep = buildAuthNextStep;
41143
+ exports.throwToolPayloadError = throwToolPayloadError;
41144
+ function buildJsonToolResult(payload) {
41145
+ return {
41146
+ content: [
41147
+ {
41148
+ type: "text",
41149
+ text: JSON.stringify(payload, null, 2),
41150
+ },
41151
+ ],
41152
+ };
41153
+ }
41154
+ class ToolPayloadError extends Error {
41155
+ payload;
41156
+ constructor(payload) {
41157
+ super(typeof payload.message === "string" ? payload.message : "Tool payload error");
41158
+ this.name = "ToolPayloadError";
41159
+ this.payload = payload;
41160
+ }
41161
+ }
41162
+ exports.ToolPayloadError = ToolPayloadError;
41163
+ function isToolPayloadError(error) {
41164
+ return error instanceof ToolPayloadError;
41165
+ }
41166
+ function toolPayloadErrorToResult(error) {
41167
+ if (!isToolPayloadError(error)) {
41168
+ return null;
41169
+ }
41170
+ return buildJsonToolResult(error.payload);
41171
+ }
41172
+ function buildAuthNextStep(action, options) {
41173
+ return {
41174
+ tool: "auth",
41175
+ action,
41176
+ required_params: options?.requiredParams,
41177
+ suggested_args: options?.suggestedArgs ?? { action },
41178
+ };
41179
+ }
41180
+ function throwToolPayloadError(payload) {
41181
+ throw new ToolPayloadError(payload);
41182
+ }
41183
+
41184
+
40678
41185
  /***/ }),
40679
41186
 
40680
41187
  /***/ 9880:
@@ -83015,12 +83522,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
83015
83522
  Object.defineProperty(exports, "__esModule", ({ value: true }));
83016
83523
  exports.AuthSupevisor = exports.AuthSupervisor = void 0;
83017
83524
  const web_auth_1 = __webpack_require__(76097);
83525
+ const oauth_1 = __webpack_require__(92423);
83018
83526
  const common_1 = __webpack_require__(96711);
83019
83527
  const credential_1 = __webpack_require__(99795);
83020
83528
  const error_1 = __webpack_require__(64119);
83021
83529
  __exportStar(__webpack_require__(96711), exports);
83022
83530
  __exportStar(__webpack_require__(99795), exports);
83023
83531
  __exportStar(__webpack_require__(76097), exports);
83532
+ __exportStar(__webpack_require__(92423), exports);
83024
83533
  class AuthSupervisor {
83025
83534
  /**
83026
83535
  * 单例模式,全局缓存
@@ -83070,7 +83579,7 @@ class AuthSupervisor {
83070
83579
  */
83071
83580
  loginByWebAuth(options = {}) {
83072
83581
  return __awaiter(this, void 0, void 0, function* () {
83073
- const { getAuthUrl, throwError, noBrowser, callbackTimeout } = options;
83582
+ const { getAuthUrl, throwError, noBrowser, callbackTimeout, flow = 'device', client_id, onDeviceCode, getOAuthEndpoint, silent } = options;
83074
83583
  if (this.cacheCredential && this.needCache && !this.isCacheExpire()) {
83075
83584
  return this.cacheCredential;
83076
83585
  }
@@ -83078,12 +83587,19 @@ class AuthSupervisor {
83078
83587
  let credential = yield (0, credential_1.checkAndGetCredential)(this.requestConfig);
83079
83588
  if (credential)
83080
83589
  return credential;
83081
- // 兼容临时秘钥
83082
- credential = yield (0, web_auth_1.getAuthTokenFromWeb)({
83083
- getAuthUrl,
83084
- noBrowser,
83085
- callbackTimeout
83086
- });
83590
+ // 根据授权方式获取凭证
83591
+ if (flow === 'web') {
83592
+ credential = yield (0, web_auth_1.getAuthTokenFromWeb)({
83593
+ getAuthUrl,
83594
+ noBrowser,
83595
+ callbackTimeout,
83596
+ silent
83597
+ });
83598
+ }
83599
+ else {
83600
+ credential = yield (0, oauth_1.getAuthTokenByDeviceFlow)({ client_id, onDeviceCode, getOAuthEndpoint, getAuthUrl, silent });
83601
+ }
83602
+ credential = (0, common_1.resolveCredential)(credential);
83087
83603
  try {
83088
83604
  yield (0, common_1.checkAuth)(credential, this.requestConfig);
83089
83605
  }
@@ -85007,7 +85523,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
85007
85523
  return (mod && mod.__esModule) ? mod : { "default": mod };
85008
85524
  };
85009
85525
  Object.defineProperty(exports, "__esModule", ({ value: true }));
85010
- exports.getDataFromWeb = void 0;
85526
+ exports.getDataFromWeb = exports.openUrl = exports.isTruthyFlag = void 0;
85011
85527
  const open_1 = __importDefault(__webpack_require__(30353));
85012
85528
  const query_string_1 = __importDefault(__webpack_require__(86663));
85013
85529
  const http_1 = __importDefault(__webpack_require__(81630));
@@ -85054,6 +85570,7 @@ function isTruthyFlag(value) {
85054
85570
  }
85055
85571
  return ['1', 'true', 'yes', 'on'].includes(String(value).trim().toLowerCase());
85056
85572
  }
85573
+ exports.isTruthyFlag = isTruthyFlag;
85057
85574
  function isVSCodeEnvironment() {
85058
85575
  return Boolean(process.env.VSCODE_IPC_HOOK_CLI
85059
85576
  || process.env.VSCODE_PID
@@ -85109,19 +85626,23 @@ function openUrl(url) {
85109
85626
  }
85110
85627
  });
85111
85628
  }
85629
+ exports.openUrl = openUrl;
85112
85630
  // 从 Web 页面中获取数据
85113
85631
  function getDataFromWeb(getUrl, type, options = {}) {
85114
- var _a, _b;
85632
+ var _a, _b, _c;
85115
85633
  return __awaiter(this, void 0, void 0, function* () {
85116
85634
  const { server, port } = yield createLocalServer();
85117
85635
  const noBrowser = (_a = options.noBrowser) !== null && _a !== void 0 ? _a : isTruthyFlag(process.env.TCB_NO_BROWSER);
85118
85636
  const callbackTimeout = (_b = options.callbackTimeout) !== null && _b !== void 0 ? _b : 180000;
85637
+ const silent = (_c = options.silent) !== null && _c !== void 0 ? _c : false;
85119
85638
  if (!Number.isFinite(callbackTimeout) || callbackTimeout <= 0) {
85120
85639
  throw new error_1.CloudBaseError('callbackTimeout must be a positive number');
85121
85640
  }
85122
85641
  const url = getUrl(port);
85123
- console.log('\n\n若链接未自动打开,请手动复制至浏览器,或尝试其他登录方式:');
85124
- console.log(`\n${url}\n`);
85642
+ if (!silent) {
85643
+ console.log('\n\n若链接未自动打开,请手动复制至浏览器,或尝试其他登录方式:');
85644
+ console.log(`\n${url}\n`);
85645
+ }
85125
85646
  if (!noBrowser) {
85126
85647
  // 对 url 转码, 避免 wsl 无法正常打开地址
85127
85648
  // https://www.npmjs.com/package/open#url
@@ -86080,6 +86601,126 @@ class Profiler {
86080
86601
  module.exports = Profiler;
86081
86602
 
86082
86603
 
86604
+ /***/ }),
86605
+
86606
+ /***/ 23670:
86607
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
86608
+
86609
+ /* @flow */
86610
+ /*::
86611
+
86612
+ type DotenvParseOptions = {
86613
+ debug?: boolean
86614
+ }
86615
+
86616
+ // keys and values from src
86617
+ type DotenvParseOutput = { [string]: string }
86618
+
86619
+ type DotenvConfigOptions = {
86620
+ path?: string, // path to .env file
86621
+ encoding?: string, // encoding of .env file
86622
+ debug?: string // turn on logging for debugging purposes
86623
+ }
86624
+
86625
+ type DotenvConfigOutput = {
86626
+ parsed?: DotenvParseOutput,
86627
+ error?: Error
86628
+ }
86629
+
86630
+ */
86631
+
86632
+ const fs = __webpack_require__(29021)
86633
+ const path = __webpack_require__(39902)
86634
+
86635
+ function log (message /*: string */) {
86636
+ console.log(`[dotenv][DEBUG] ${message}`)
86637
+ }
86638
+
86639
+ const NEWLINE = '\n'
86640
+ const RE_INI_KEY_VAL = /^\s*([\w.-]+)\s*=\s*(.*)?\s*$/
86641
+ const RE_NEWLINES = /\\n/g
86642
+ const NEWLINES_MATCH = /\n|\r|\r\n/
86643
+
86644
+ // Parses src into an Object
86645
+ function parse (src /*: string | Buffer */, options /*: ?DotenvParseOptions */) /*: DotenvParseOutput */ {
86646
+ const debug = Boolean(options && options.debug)
86647
+ const obj = {}
86648
+
86649
+ // convert Buffers before splitting into lines and processing
86650
+ src.toString().split(NEWLINES_MATCH).forEach(function (line, idx) {
86651
+ // matching "KEY' and 'VAL' in 'KEY=VAL'
86652
+ const keyValueArr = line.match(RE_INI_KEY_VAL)
86653
+ // matched?
86654
+ if (keyValueArr != null) {
86655
+ const key = keyValueArr[1]
86656
+ // default undefined or missing values to empty string
86657
+ let val = (keyValueArr[2] || '')
86658
+ const end = val.length - 1
86659
+ const isDoubleQuoted = val[0] === '"' && val[end] === '"'
86660
+ const isSingleQuoted = val[0] === "'" && val[end] === "'"
86661
+
86662
+ // if single or double quoted, remove quotes
86663
+ if (isSingleQuoted || isDoubleQuoted) {
86664
+ val = val.substring(1, end)
86665
+
86666
+ // if double quoted, expand newlines
86667
+ if (isDoubleQuoted) {
86668
+ val = val.replace(RE_NEWLINES, NEWLINE)
86669
+ }
86670
+ } else {
86671
+ // remove surrounding whitespace
86672
+ val = val.trim()
86673
+ }
86674
+
86675
+ obj[key] = val
86676
+ } else if (debug) {
86677
+ log(`did not match key and value when parsing line ${idx + 1}: ${line}`)
86678
+ }
86679
+ })
86680
+
86681
+ return obj
86682
+ }
86683
+
86684
+ // Populates process.env from .env file
86685
+ function config (options /*: ?DotenvConfigOptions */) /*: DotenvConfigOutput */ {
86686
+ let dotenvPath = path.resolve(process.cwd(), '.env')
86687
+ let encoding /*: string */ = 'utf8'
86688
+ let debug = false
86689
+
86690
+ if (options) {
86691
+ if (options.path != null) {
86692
+ dotenvPath = options.path
86693
+ }
86694
+ if (options.encoding != null) {
86695
+ encoding = options.encoding
86696
+ }
86697
+ if (options.debug != null) {
86698
+ debug = true
86699
+ }
86700
+ }
86701
+
86702
+ try {
86703
+ // specifying an encoding returns a string instead of a buffer
86704
+ const parsed = parse(fs.readFileSync(dotenvPath, { encoding }), { debug })
86705
+
86706
+ Object.keys(parsed).forEach(function (key) {
86707
+ if (!Object.prototype.hasOwnProperty.call(process.env, key)) {
86708
+ process.env[key] = parsed[key]
86709
+ } else if (debug) {
86710
+ log(`"${key}" is already defined in \`process.env\` and will not be overwritten`)
86711
+ }
86712
+ })
86713
+
86714
+ return { parsed }
86715
+ } catch (e) {
86716
+ return { error: e }
86717
+ }
86718
+ }
86719
+
86720
+ module.exports.config = config
86721
+ module.exports.parse = parse
86722
+
86723
+
86083
86724
  /***/ }),
86084
86725
 
86085
86726
  /***/ 23697:
@@ -89404,7 +90045,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
89404
90045
  return (mod && mod.__esModule) ? mod : { "default": mod };
89405
90046
  };
89406
90047
  Object.defineProperty(exports, "__esModule", ({ value: true }));
89407
- exports.TRIGGER_CONFIG_EXAMPLES = exports.SUPPORTED_TRIGGER_TYPES = exports.DEFAULT_NODEJS_RUNTIME = exports.SUPPORTED_NODEJS_RUNTIMES = void 0;
90048
+ 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;
89408
90049
  exports.registerFunctionTools = registerFunctionTools;
89409
90050
  const zod_1 = __webpack_require__(21614);
89410
90051
  const cloudbase_manager_js_1 = __webpack_require__(3431);
@@ -89437,6 +90078,41 @@ exports.TRIGGER_CONFIG_EXAMPLES = {
89437
90078
  ],
89438
90079
  },
89439
90080
  };
90081
+ exports.READ_FUNCTION_LAYER_ACTIONS = [
90082
+ "listLayers",
90083
+ "listLayerVersions",
90084
+ "getLayerVersion",
90085
+ "getFunctionLayers",
90086
+ ];
90087
+ exports.WRITE_FUNCTION_LAYER_ACTIONS = [
90088
+ "createLayerVersion",
90089
+ "deleteLayerVersion",
90090
+ "attachLayer",
90091
+ "detachLayer",
90092
+ "updateFunctionLayers",
90093
+ ];
90094
+ function jsonContent(body) {
90095
+ return {
90096
+ content: [
90097
+ {
90098
+ type: "text",
90099
+ text: JSON.stringify(body, null, 2),
90100
+ },
90101
+ ],
90102
+ };
90103
+ }
90104
+ function normalizeFunctionLayers(layers) {
90105
+ if (!Array.isArray(layers)) {
90106
+ return [];
90107
+ }
90108
+ return layers
90109
+ .filter((layer) => Boolean(layer))
90110
+ .map((layer) => ({
90111
+ LayerName: String(layer.LayerName ?? ""),
90112
+ LayerVersion: Number(layer.LayerVersion ?? 0),
90113
+ }))
90114
+ .filter((layer) => Boolean(layer.LayerName) && Number.isFinite(layer.LayerVersion));
90115
+ }
89440
90116
  /**
89441
90117
  * 处理函数根目录路径,确保不包含函数名
89442
90118
  * @param functionRootPath 用户输入的路径
@@ -89464,12 +90140,12 @@ function registerFunctionTools(server) {
89464
90140
  // getFunctionList - 获取云函数列表或详情(推荐)
89465
90141
  server.registerTool?.("getFunctionList", {
89466
90142
  title: "查询云函数列表或详情",
89467
- description: "获取云函数列表或单个函数详情。通过 action 参数区分操作类型:list=获取函数列表(默认,无需额外参数),detail=获取函数详情(需要提供 name 参数指定函数名称)",
90143
+ description: "获取云函数列表或单个函数详情。通过 action 参数区分操作类型:list=获取函数列表(默认,无需额外参数),detail=获取函数详情(需要提供 name 参数指定函数名称,返回结果中包含函数当前绑定的 Layers 信息)",
89468
90144
  inputSchema: {
89469
90145
  action: zod_1.z
89470
90146
  .enum(["list", "detail"])
89471
90147
  .optional()
89472
- .describe("操作类型:list=获取函数列表(默认,无需额外参数),detail=获取函数详情(需要提供 name 参数)"),
90148
+ .describe("操作类型:list=获取函数列表(默认,无需额外参数),detail=获取函数详情(需要提供 name 参数,返回结果中包含当前绑定的 Layers)"),
89473
90149
  limit: zod_1.z.number().optional().describe("范围(list 操作时使用)"),
89474
90150
  offset: zod_1.z.number().optional().describe("偏移(list 操作时使用)"),
89475
90151
  name: zod_1.z
@@ -89983,6 +90659,379 @@ function registerFunctionTools(server) {
89983
90659
  throw new Error(`不支持的操作类型: ${action}`);
89984
90660
  }
89985
90661
  });
90662
+ server.registerTool?.("readFunctionLayers", {
90663
+ title: "查询云函数层信息",
90664
+ description: "查询云函数层及函数层配置。通过 action 区分操作:listLayers=查询层列表,listLayerVersions=查询指定层的版本列表,getLayerVersion=查询层版本详情(含下载地址/元信息),getFunctionLayers=查询指定函数当前绑定的层。返回格式:JSON 包含 success、data(含 action 与对应结果字段)、message;data.layers 或 data.layerVersions 为数组,getFunctionLayers 的 data.layers 每项为 { LayerName, LayerVersion }。",
90665
+ inputSchema: {
90666
+ action: zod_1.z
90667
+ .enum(exports.READ_FUNCTION_LAYER_ACTIONS)
90668
+ .describe("操作类型:listLayers=查询层列表,listLayerVersions=查询指定层的版本列表,getLayerVersion=查询层版本详情,getFunctionLayers=查询指定函数当前绑定的层"),
90669
+ name: zod_1.z
90670
+ .string()
90671
+ .optional()
90672
+ .describe("层名称。listLayerVersions 和 getLayerVersion 操作时必填"),
90673
+ version: zod_1.z
90674
+ .number()
90675
+ .optional()
90676
+ .describe("层版本号。getLayerVersion 操作时必填"),
90677
+ runtime: zod_1.z
90678
+ .string()
90679
+ .optional()
90680
+ .describe("运行时筛选。listLayers 操作时可选"),
90681
+ searchKey: zod_1.z
90682
+ .string()
90683
+ .optional()
90684
+ .describe("层名称搜索关键字。listLayers 操作时可选"),
90685
+ offset: zod_1.z.number().optional().describe("分页偏移。listLayers 操作时可选"),
90686
+ limit: zod_1.z.number().optional().describe("分页数量。listLayers 操作时可选"),
90687
+ functionName: zod_1.z
90688
+ .string()
90689
+ .optional()
90690
+ .describe("函数名称。getFunctionLayers 操作时必填"),
90691
+ codeSecret: zod_1.z
90692
+ .string()
90693
+ .optional()
90694
+ .describe("代码保护密钥。getFunctionLayers 操作时可选"),
90695
+ },
90696
+ annotations: {
90697
+ readOnlyHint: true,
90698
+ openWorldHint: true,
90699
+ category: "functions",
90700
+ },
90701
+ }, async ({ action, name, version, runtime, searchKey, offset, limit, functionName, codeSecret, }) => {
90702
+ if (action === "listLayers") {
90703
+ const cloudbase = await getManager();
90704
+ const result = await cloudbase.functions.listLayers({
90705
+ offset,
90706
+ limit,
90707
+ runtime,
90708
+ searchKey,
90709
+ });
90710
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
90711
+ return jsonContent({
90712
+ success: true,
90713
+ data: {
90714
+ action,
90715
+ layers: result.Layers || [],
90716
+ totalCount: result.TotalCount || 0,
90717
+ requestId: result.RequestId,
90718
+ },
90719
+ message: `Successfully retrieved ${result.Layers?.length || 0} layer entries`,
90720
+ nextActions: [
90721
+ { tool: "readFunctionLayers", action: "listLayerVersions", reason: "List versions of a layer" },
90722
+ { tool: "writeFunctionLayers", action: "createLayerVersion", reason: "Create a new layer version" },
90723
+ ],
90724
+ });
90725
+ }
90726
+ if (action === "listLayerVersions") {
90727
+ if (!name) {
90728
+ throw new Error("查询层版本列表时,name 参数是必需的");
90729
+ }
90730
+ const cloudbase = await getManager();
90731
+ const result = await cloudbase.functions.listLayerVersions({ name });
90732
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
90733
+ return jsonContent({
90734
+ success: true,
90735
+ data: {
90736
+ action,
90737
+ name,
90738
+ layerVersions: result.LayerVersions || [],
90739
+ requestId: result.RequestId,
90740
+ },
90741
+ message: `Successfully retrieved ${result.LayerVersions?.length || 0} versions for layer '${name}'`,
90742
+ nextActions: [
90743
+ { tool: "readFunctionLayers", action: "getLayerVersion", reason: "Get version details and download info" },
90744
+ { tool: "writeFunctionLayers", action: "attachLayer", reason: "Bind this layer to a function" },
90745
+ ],
90746
+ });
90747
+ }
90748
+ if (action === "getLayerVersion") {
90749
+ if (!name) {
90750
+ throw new Error("查询层版本详情时,name 参数是必需的");
90751
+ }
90752
+ if (typeof version !== "number") {
90753
+ throw new Error("查询层版本详情时,version 参数是必需的");
90754
+ }
90755
+ const cloudbase = await getManager();
90756
+ const result = await cloudbase.functions.getLayerVersion({
90757
+ name,
90758
+ version,
90759
+ });
90760
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
90761
+ return jsonContent({
90762
+ success: true,
90763
+ data: {
90764
+ action,
90765
+ name,
90766
+ version,
90767
+ layerVersion: result,
90768
+ downloadInfo: {
90769
+ location: result.Location,
90770
+ codeSha256: result.CodeSha256,
90771
+ },
90772
+ requestId: result.RequestId,
90773
+ },
90774
+ message: `Successfully retrieved details for layer '${name}' version ${version}`,
90775
+ nextActions: [
90776
+ { tool: "writeFunctionLayers", action: "attachLayer", reason: "Bind this layer version to a function" },
90777
+ { tool: "writeFunctionLayers", action: "deleteLayerVersion", reason: "Delete this layer version" },
90778
+ ],
90779
+ });
90780
+ }
90781
+ if (!functionName) {
90782
+ throw new Error("查询函数层配置时,functionName 参数是必需的");
90783
+ }
90784
+ const cloudbase = await getManager();
90785
+ const result = await cloudbase.functions.getFunctionDetail(functionName, codeSecret);
90786
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
90787
+ const layers = normalizeFunctionLayers(result.Layers);
90788
+ return jsonContent({
90789
+ success: true,
90790
+ data: {
90791
+ action,
90792
+ functionName,
90793
+ layers,
90794
+ count: layers.length,
90795
+ requestId: result.RequestId,
90796
+ },
90797
+ message: `Successfully retrieved ${layers.length} bound layers for function '${functionName}'`,
90798
+ nextActions: [
90799
+ { tool: "writeFunctionLayers", action: "attachLayer", reason: "Add a layer to this function" },
90800
+ { tool: "writeFunctionLayers", action: "detachLayer", reason: "Remove a layer from this function" },
90801
+ { tool: "writeFunctionLayers", action: "updateFunctionLayers", reason: "Replace or reorder bound layers" },
90802
+ ],
90803
+ });
90804
+ });
90805
+ server.registerTool?.("writeFunctionLayers", {
90806
+ title: "管理云函数层",
90807
+ description: "管理云函数层和函数层绑定。通过 action 区分操作:createLayerVersion=创建层版本,deleteLayerVersion=删除层版本,attachLayer=给函数追加绑定层,detachLayer=解绑函数层,updateFunctionLayers=整体更新函数层数组以调整顺序或批量更新。返回格式:JSON 包含 success、data(含 action 与结果字段,如 layerVersion、layers)、message、nextActions(建议的后续操作)。",
90808
+ inputSchema: {
90809
+ action: zod_1.z
90810
+ .enum(exports.WRITE_FUNCTION_LAYER_ACTIONS)
90811
+ .describe("操作类型:createLayerVersion=创建层版本,deleteLayerVersion=删除层版本,attachLayer=追加绑定层,detachLayer=解绑层,updateFunctionLayers=整体更新函数层数组"),
90812
+ name: zod_1.z
90813
+ .string()
90814
+ .optional()
90815
+ .describe("层名称。createLayerVersion 和 deleteLayerVersion 操作时必填"),
90816
+ version: zod_1.z
90817
+ .number()
90818
+ .optional()
90819
+ .describe("层版本号。deleteLayerVersion 操作时必填"),
90820
+ contentPath: zod_1.z
90821
+ .string()
90822
+ .optional()
90823
+ .describe("层内容路径,可以是目录或 ZIP 文件路径。createLayerVersion 操作时与 base64Content 二选一"),
90824
+ base64Content: zod_1.z
90825
+ .string()
90826
+ .optional()
90827
+ .describe("层内容的 base64 编码。createLayerVersion 操作时与 contentPath 二选一"),
90828
+ runtimes: zod_1.z
90829
+ .array(zod_1.z.string())
90830
+ .optional()
90831
+ .describe("层适用的运行时列表。createLayerVersion 操作时必填"),
90832
+ description: zod_1.z
90833
+ .string()
90834
+ .optional()
90835
+ .describe("层版本描述。createLayerVersion 操作时可选"),
90836
+ licenseInfo: zod_1.z
90837
+ .string()
90838
+ .optional()
90839
+ .describe("许可证信息。createLayerVersion 操作时可选"),
90840
+ functionName: zod_1.z
90841
+ .string()
90842
+ .optional()
90843
+ .describe("函数名称。attachLayer、detachLayer、updateFunctionLayers 操作时必填"),
90844
+ layerName: zod_1.z
90845
+ .string()
90846
+ .optional()
90847
+ .describe("要绑定或解绑的层名称。attachLayer 和 detachLayer 操作时必填"),
90848
+ layerVersion: zod_1.z
90849
+ .number()
90850
+ .optional()
90851
+ .describe("要绑定或解绑的层版本号。attachLayer 和 detachLayer 操作时必填"),
90852
+ layers: zod_1.z
90853
+ .array(zod_1.z.object({
90854
+ LayerName: zod_1.z.string().describe("层名称"),
90855
+ LayerVersion: zod_1.z.number().describe("层版本号"),
90856
+ }))
90857
+ .optional()
90858
+ .describe("目标函数层数组。updateFunctionLayers 操作时必填,顺序即最终顺序"),
90859
+ codeSecret: zod_1.z
90860
+ .string()
90861
+ .optional()
90862
+ .describe("代码保护密钥。attachLayer 和 detachLayer 操作时可选"),
90863
+ },
90864
+ annotations: {
90865
+ readOnlyHint: false,
90866
+ destructiveHint: true,
90867
+ idempotentHint: false,
90868
+ openWorldHint: true,
90869
+ category: "functions",
90870
+ },
90871
+ }, async ({ action, name, version, contentPath, base64Content, runtimes, description, licenseInfo, functionName, layerName, layerVersion, layers, codeSecret, }) => {
90872
+ if (action === "createLayerVersion") {
90873
+ if (!name) {
90874
+ throw new Error("创建层版本时,name 参数是必需的");
90875
+ }
90876
+ if (!runtimes || runtimes.length === 0) {
90877
+ throw new Error("创建层版本时,runtimes 参数是必需的");
90878
+ }
90879
+ if (!contentPath && !base64Content) {
90880
+ throw new Error("创建层版本时,contentPath 和 base64Content 至少需要提供一个");
90881
+ }
90882
+ const cloudbase = await getManager();
90883
+ const result = await cloudbase.functions.createLayer({
90884
+ name,
90885
+ contentPath,
90886
+ base64Content,
90887
+ runtimes,
90888
+ description,
90889
+ licenseInfo,
90890
+ });
90891
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
90892
+ return jsonContent({
90893
+ success: true,
90894
+ data: {
90895
+ action,
90896
+ name,
90897
+ layerVersion: result.LayerVersion,
90898
+ requestId: result.RequestId,
90899
+ },
90900
+ message: `Successfully created a new version for layer '${name}'`,
90901
+ nextActions: [
90902
+ { tool: "readFunctionLayers", action: "listLayerVersions", reason: "List all versions of this layer" },
90903
+ { tool: "writeFunctionLayers", action: "attachLayer", reason: "Bind this version to a function" },
90904
+ ],
90905
+ });
90906
+ }
90907
+ if (action === "deleteLayerVersion") {
90908
+ if (!name) {
90909
+ throw new Error("删除层版本时,name 参数是必需的");
90910
+ }
90911
+ if (typeof version !== "number") {
90912
+ throw new Error("删除层版本时,version 参数是必需的");
90913
+ }
90914
+ const cloudbase = await getManager();
90915
+ const result = await cloudbase.functions.deleteLayerVersion({
90916
+ name,
90917
+ version,
90918
+ });
90919
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
90920
+ return jsonContent({
90921
+ success: true,
90922
+ data: {
90923
+ action,
90924
+ name,
90925
+ version,
90926
+ requestId: result.RequestId,
90927
+ },
90928
+ message: `Successfully deleted layer '${name}' version ${version}`,
90929
+ nextActions: [
90930
+ { tool: "readFunctionLayers", action: "listLayers", reason: "List remaining layers" },
90931
+ ],
90932
+ });
90933
+ }
90934
+ if (action === "attachLayer" ||
90935
+ action === "detachLayer" ||
90936
+ action === "updateFunctionLayers") {
90937
+ if (!functionName) {
90938
+ throw new Error(`${action} 操作时,functionName 参数是必需的`);
90939
+ }
90940
+ }
90941
+ const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
90942
+ const cloudbase = await getManager();
90943
+ if (action === "attachLayer") {
90944
+ if (!layerName) {
90945
+ throw new Error("attachLayer 操作时,layerName 参数是必需的");
90946
+ }
90947
+ if (typeof layerVersion !== "number") {
90948
+ throw new Error("attachLayer 操作时,layerVersion 参数是必需的");
90949
+ }
90950
+ const result = await cloudbase.functions.attachLayer({
90951
+ envId,
90952
+ functionName: functionName,
90953
+ layerName,
90954
+ layerVersion,
90955
+ codeSecret,
90956
+ });
90957
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
90958
+ const detail = await cloudbase.functions.getFunctionDetail(functionName, codeSecret);
90959
+ const boundLayers = normalizeFunctionLayers(detail.Layers);
90960
+ return jsonContent({
90961
+ success: true,
90962
+ data: {
90963
+ action,
90964
+ functionName,
90965
+ layers: boundLayers,
90966
+ requestId: result.RequestId,
90967
+ },
90968
+ message: `Successfully attached layer '${layerName}' version ${layerVersion} to function '${functionName}'`,
90969
+ nextActions: [
90970
+ { tool: "readFunctionLayers", action: "getFunctionLayers", reason: "Verify bound layers" },
90971
+ { tool: "writeFunctionLayers", action: "detachLayer", reason: "Remove this layer from function" },
90972
+ ],
90973
+ });
90974
+ }
90975
+ if (action === "detachLayer") {
90976
+ if (!layerName) {
90977
+ throw new Error("detachLayer 操作时,layerName 参数是必需的");
90978
+ }
90979
+ if (typeof layerVersion !== "number") {
90980
+ throw new Error("detachLayer 操作时,layerVersion 参数是必需的");
90981
+ }
90982
+ const result = await cloudbase.functions.unAttachLayer({
90983
+ envId,
90984
+ functionName: functionName,
90985
+ layerName,
90986
+ layerVersion,
90987
+ codeSecret,
90988
+ });
90989
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
90990
+ const detail = await cloudbase.functions.getFunctionDetail(functionName, codeSecret);
90991
+ const boundLayers = normalizeFunctionLayers(detail.Layers);
90992
+ return jsonContent({
90993
+ success: true,
90994
+ data: {
90995
+ action,
90996
+ functionName,
90997
+ layers: boundLayers,
90998
+ requestId: result.RequestId,
90999
+ },
91000
+ message: `Successfully detached layer '${layerName}' version ${layerVersion} from function '${functionName}'`,
91001
+ nextActions: [
91002
+ { tool: "readFunctionLayers", action: "getFunctionLayers", reason: "Verify current bound layers" },
91003
+ ],
91004
+ });
91005
+ }
91006
+ if (!layers || layers.length === 0) {
91007
+ throw new Error("updateFunctionLayers 操作时,layers 参数是必需的");
91008
+ }
91009
+ const normalizedLayers = normalizeFunctionLayers(layers);
91010
+ if (normalizedLayers.length === 0) {
91011
+ throw new Error("updateFunctionLayers 操作时,layers 参数必须包含有效的 LayerName 和 LayerVersion");
91012
+ }
91013
+ const result = await cloudbase.functions.updateFunctionLayer({
91014
+ envId,
91015
+ functionName: functionName,
91016
+ layers: normalizedLayers,
91017
+ });
91018
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
91019
+ const detail = await cloudbase.functions.getFunctionDetail(functionName);
91020
+ const boundLayers = normalizeFunctionLayers(detail.Layers);
91021
+ return jsonContent({
91022
+ success: true,
91023
+ data: {
91024
+ action,
91025
+ functionName,
91026
+ layers: boundLayers,
91027
+ requestId: result.RequestId,
91028
+ },
91029
+ message: `Successfully updated bound layers for function '${functionName}'`,
91030
+ nextActions: [
91031
+ { tool: "readFunctionLayers", action: "getFunctionLayers", reason: "Verify updated layer order" },
91032
+ ],
91033
+ });
91034
+ });
89986
91035
  // // Layer相关功能
89987
91036
  // // createLayer - 创建Layer
89988
91037
  // server.tool(
@@ -102898,6 +103947,7 @@ const security_rule_js_1 = __webpack_require__(7862);
102898
103947
  const cloud_mode_js_1 = __webpack_require__(89684);
102899
103948
  const logger_js_1 = __webpack_require__(13039);
102900
103949
  const tencet_cloud_js_1 = __webpack_require__(95018);
103950
+ const tool_result_js_1 = __webpack_require__(9835);
102901
103951
  const tool_wrapper_js_1 = __webpack_require__(71363);
102902
103952
  // 默认插件列表
102903
103953
  const DEFAULT_PLUGINS = [
@@ -103012,6 +104062,18 @@ async function createCloudBaseMcpServer(options) {
103012
104062
  ...(ide === "CodeBuddy" ? { logging: {} } : {}),
103013
104063
  },
103014
104064
  });
104065
+ const originalRegisterTool = server.registerTool.bind(server);
104066
+ server.registerTool = ((name, meta, handler) => originalRegisterTool(name, meta, async (args) => {
104067
+ try {
104068
+ return await handler(args);
104069
+ }
104070
+ catch (error) {
104071
+ if ((0, tool_result_js_1.isToolPayloadError)(error)) {
104072
+ return (0, tool_result_js_1.buildJsonToolResult)(error.payload);
104073
+ }
104074
+ throw error;
104075
+ }
104076
+ }));
103015
104077
  // Only set logging handler if logging capability is declared
103016
104078
  if (ide === "CodeBuddy") {
103017
104079
  server.server.setRequestHandler(types_js_1.SetLevelRequestSchema, (request, extra) => {
@@ -125906,6 +126968,30 @@ function registerCapiTools(server) {
125906
126968
  throw new Error(`Service ${service} is not allowed. Allowed services: ${ALLOWED_SERVICES.join(", ")}`);
125907
126969
  }
125908
126970
  const cloudbase = await getManager();
126971
+ if (['1', 'true'].includes(process.env.CLOUDBASE_EVALUATE_MODE ?? '')) {
126972
+ if (service === 'lowcode') {
126973
+ throw new Error(`${service}/${action} Cloud API is not exposed or does not exist. Please use another API.`);
126974
+ }
126975
+ if (service === 'tcb') {
126976
+ const tcbCapiForbidList = [
126977
+ // 未明确对外的云API
126978
+ 'DescribeStorageACL', 'ModifyStorageACL', 'DescribeSecurityRule',
126979
+ // 要下线的云API
126980
+ "ListTables",
126981
+ "DescribeCloudBaseGWAPI",
126982
+ "DescribeCloudBaseGWService",
126983
+ "CreateCloudBaseGWAPI",
126984
+ "DeleteCloudBaseGWAPI",
126985
+ "ModifyCloudBaseGWAPI",
126986
+ "DeleteCloudBaseGWDomain",
126987
+ "BindCloudBaseGWDomain",
126988
+ "BindCloudBaseAccessDomain"
126989
+ ];
126990
+ if (tcbCapiForbidList.includes(action)) {
126991
+ throw new Error(`${service}/${action} Cloud API is not exposed or does not exist. Please use another API.`);
126992
+ }
126993
+ }
126994
+ }
125909
126995
  const result = await cloudbase.commonService(service).call({
125910
126996
  Action: action,
125911
126997
  Param: params ?? {},
@@ -137511,7 +138597,7 @@ class TelemetryReporter {
137511
138597
  const nodeVersion = process.version; // Node.js版本
137512
138598
  const arch = os_1.default.arch(); // 系统架构
137513
138599
  // 从构建时注入的版本号获取MCP版本信息
137514
- const mcpVersion = process.env.npm_package_version || "2.12.1" || 0;
138600
+ const mcpVersion = process.env.npm_package_version || "2.14.0" || 0;
137515
138601
  return {
137516
138602
  userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
137517
138603
  deviceId: this.deviceId,
@@ -155623,7 +156709,7 @@ const fs_1 = __importDefault(__webpack_require__(29021));
155623
156709
  const lodash_1 = __importDefault(__webpack_require__(2543));
155624
156710
  const path_1 = __importDefault(__webpack_require__(39902));
155625
156711
  const yargs_1 = __importDefault(__webpack_require__(5945));
155626
- const dotenv_1 = __importDefault(__webpack_require__(80998));
156712
+ const dotenv_1 = __importDefault(__webpack_require__(23670));
155627
156713
  exports.dotenv = dotenv_1.default;
155628
156714
  function readFile(target) {
155629
156715
  try {
@@ -189006,6 +190092,15 @@ async function registerRagTools(server) {
189006
190092
  ],
189007
190093
  };
189008
190094
  }
190095
+ // 向量检索模式下必须提供 id 和 content,避免后端报「知识库名称不能为空」
190096
+ if (mode === "vector") {
190097
+ if (!id) {
190098
+ throw new Error("知识库名称不能为空: please provide `id` when mode=vector (cloudbase / scf / miniprogram).");
190099
+ }
190100
+ if (!content || !content.trim()) {
190101
+ throw new Error("检索内容不能为空: please provide non-empty `content` when mode=vector.");
190102
+ }
190103
+ }
189009
190104
  // 枚举到后端 id 映射
189010
190105
  const backendId = KnowledgeBaseIdMap[id] || id;
189011
190106
  const signInRes = await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/auth/v1/signin/anonymously", {
@@ -204163,6 +205258,7 @@ const cloudbase_manager_js_1 = __webpack_require__(3431);
204163
205258
  const cloud_mode_js_1 = __webpack_require__(89684);
204164
205259
  const logger_js_1 = __webpack_require__(13039);
204165
205260
  const telemetry_js_1 = __webpack_require__(45880);
205261
+ const tool_result_js_1 = __webpack_require__(9835);
204166
205262
  /**
204167
205263
  * 生成 GitHub Issue 创建链接
204168
205264
  * @param toolName 工具名称
@@ -204210,7 +205306,7 @@ ${envIdSection}
204210
205306
  ## 环境信息
204211
205307
  - 操作系统: ${os_1.default.type()} ${os_1.default.release()}
204212
205308
  - Node.js版本: ${process.version}
204213
- - MCP 版本:${process.env.npm_package_version || "2.12.1" || 0}
205309
+ - MCP 版本:${process.env.npm_package_version || "2.14.0" || 0}
204214
205310
  - 系统架构: ${os_1.default.arch()}
204215
205311
  - 时间: ${new Date().toISOString()}
204216
205312
  - 请求ID: ${requestId}
@@ -204275,6 +205371,11 @@ function createWrappedHandler(name, handler, server) {
204275
205371
  if (!isTestEnvironment) {
204276
205372
  server.logger?.({ type: 'errorToolCall', toolName: name, args: sanitizeArgs(args), message: errorMessage, duration: Date.now() - startTime });
204277
205373
  }
205374
+ // Preserve structured tool guidance such as next_step.
205375
+ // These errors are expected control flow and should be serialized by the outer server wrapper.
205376
+ if ((0, tool_result_js_1.isToolPayloadError)(error)) {
205377
+ throw error;
205378
+ }
204278
205379
  // In tests, avoid any extra work that may block (envId lookup, issue link generation, etc.)
204279
205380
  if (isTestEnvironment) {
204280
205381
  throw error instanceof Error ? error : new Error(String(error));
@@ -218094,16 +219195,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
218094
219195
  });
218095
219196
  };
218096
219197
  Object.defineProperty(exports, "__esModule", ({ value: true }));
218097
- exports.getAuthTokenFromWeb = void 0;
219198
+ exports.getAuthTokenFromWeb = exports.CLI_AUTH_BASE_URL = void 0;
218098
219199
  const common_1 = __webpack_require__(96711);
218099
219200
  const coding_1 = __webpack_require__(40540);
218100
219201
  const web_1 = __webpack_require__(2240);
218101
219202
  const system_1 = __webpack_require__(62179);
218102
- const CliAuthBaseUrl = 'https://tcb.cloud.tencent.com/dev';
219203
+ exports.CLI_AUTH_BASE_URL = 'https://tcb.cloud.tencent.com/dev';
218103
219204
  // 打开云开发控制台,获取授权
218104
219205
  function getAuthTokenFromWeb(options = {}) {
218105
219206
  return __awaiter(this, void 0, void 0, function* () {
218106
- const { getAuthUrl, noBrowser, callbackTimeout } = options;
219207
+ const { getAuthUrl, noBrowser, callbackTimeout, silent } = options;
218107
219208
  const mac = yield (0, system_1.getMacAddress)();
218108
219209
  const os = (0, system_1.getOSInfo)();
218109
219210
  const macHash = (0, coding_1.md5Encoding)(mac);
@@ -218116,7 +219217,7 @@ function getAuthTokenFromWeb(options = {}) {
218116
219217
  + '&from=cli';
218117
219218
  const encodedCallbackUrl = encodeURIComponent(callbackUrl);
218118
219219
  // 授权链接
218119
- const rawAuthUrl = `${CliAuthBaseUrl}?authCallbackUrl=${encodedCallbackUrl}#/cli-auth?${encodedQuery}`;
219220
+ const rawAuthUrl = `${exports.CLI_AUTH_BASE_URL}?authCallbackUrl=${encodedCallbackUrl}#/cli-auth?${encodedQuery}`;
218120
219221
  let cliAuthUrl = rawAuthUrl;
218121
219222
  if (getAuthUrl) {
218122
219223
  try {
@@ -218129,7 +219230,8 @@ function getAuthTokenFromWeb(options = {}) {
218129
219230
  return cliAuthUrl;
218130
219231
  }, 'login', {
218131
219232
  noBrowser,
218132
- callbackTimeout
219233
+ callbackTimeout,
219234
+ silent
218133
219235
  });
218134
219236
  const credential = (0, common_1.resolveCredential)(query);
218135
219237
  return credential;
@@ -218970,7 +220072,7 @@ function registerSetupTools(server) {
218970
220072
  title: "下载项目模板",
218971
220073
  description: `自动下载并部署CloudBase项目模板。⚠️ **MANDATORY FOR NEW PROJECTS** ⚠️
218972
220074
 
218973
- **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.12.1" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
220075
+ **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)`,
218974
220076
  inputSchema: {
218975
220077
  template: zod_1.z
218976
220078
  .enum(["react", "vue", "miniprogram", "uniapp", "rules"])
@@ -220262,56 +221364,181 @@ module.exports.sync = path => {
220262
221364
  "use strict";
220263
221365
 
220264
221366
  Object.defineProperty(exports, "__esModule", ({ value: true }));
221367
+ exports.getAuthProgressStateSync = getAuthProgressStateSync;
221368
+ exports.getAuthProgressState = getAuthProgressState;
221369
+ exports.setPendingAuthProgressState = setPendingAuthProgressState;
221370
+ exports.resolveAuthProgressState = resolveAuthProgressState;
221371
+ exports.rejectAuthProgressState = rejectAuthProgressState;
221372
+ exports.resetAuthProgressState = resetAuthProgressState;
221373
+ exports.peekLoginState = peekLoginState;
221374
+ exports.ensureLogin = ensureLogin;
220265
221375
  exports.getLoginState = getLoginState;
220266
221376
  exports.logout = logout;
220267
221377
  const toolbox_1 = __webpack_require__(25901);
220268
221378
  const logger_js_1 = __webpack_require__(13039);
220269
221379
  const tencet_cloud_js_1 = __webpack_require__(95018);
220270
- const auth = toolbox_1.AuthSupevisor.getInstance({});
220271
- async function getLoginState(options) {
221380
+ const auth = toolbox_1.AuthSupervisor.getInstance({});
221381
+ const authProgressState = {
221382
+ status: "IDLE",
221383
+ updatedAt: Date.now(),
221384
+ };
221385
+ function updateAuthProgressState(partial) {
221386
+ Object.assign(authProgressState, partial, {
221387
+ updatedAt: Date.now(),
221388
+ });
221389
+ return getAuthProgressStateSync();
221390
+ }
221391
+ function normalizeLoginStateFromEnvVars(options) {
220272
221392
  const { TENCENTCLOUD_SECRETID, TENCENTCLOUD_SECRETKEY, TENCENTCLOUD_SESSIONTOKEN, } = process.env;
220273
- (0, logger_js_1.debug)("TENCENTCLOUD_SECRETID", { secretId: TENCENTCLOUD_SECRETID });
220274
- // If ignoreEnvVars is true (e.g., when switching account), skip environment variables
220275
- // and force Web authentication to allow account switching
220276
221393
  if (!options?.ignoreEnvVars && TENCENTCLOUD_SECRETID && TENCENTCLOUD_SECRETKEY) {
220277
- (0, logger_js_1.debug)("loginByApiSecret");
220278
221394
  return {
220279
221395
  secretId: TENCENTCLOUD_SECRETID,
220280
221396
  secretKey: TENCENTCLOUD_SECRETKEY,
220281
221397
  token: TENCENTCLOUD_SESSIONTOKEN,
221398
+ envId: process.env.CLOUDBASE_ENV_ID,
220282
221399
  };
220283
- // await auth.loginByApiSecret(TENCENTCLOUD_SECRETID, TENCENTCLOUD_SECRETKEY, TENCENTCLOUD_SESSIONTOKEN)
220284
221400
  }
220285
- const loginState = await auth.getLoginState();
221401
+ return null;
221402
+ }
221403
+ function mapAuthErrorStatus(error) {
221404
+ const message = error instanceof Error ? error.message : String(error ?? "");
221405
+ if (message.includes("拒绝") || message.includes("denied")) {
221406
+ return "DENIED";
221407
+ }
221408
+ if (message.includes("过期") || message.includes("expired")) {
221409
+ return "EXPIRED";
221410
+ }
221411
+ return "ERROR";
221412
+ }
221413
+ function getAuthProgressStateSync() {
221414
+ return {
221415
+ ...authProgressState,
221416
+ authChallenge: authProgressState.authChallenge
221417
+ ? { ...authProgressState.authChallenge }
221418
+ : undefined,
221419
+ };
221420
+ }
221421
+ async function getAuthProgressState() {
221422
+ const loginState = await peekLoginState();
221423
+ if (loginState && authProgressState.status === "PENDING") {
221424
+ updateAuthProgressState({
221425
+ status: "READY",
221426
+ lastError: undefined,
221427
+ });
221428
+ }
221429
+ if (authProgressState.status === "PENDING" &&
221430
+ authProgressState.authChallenge?.expires_in) {
221431
+ const issuedAt = authProgressState.updatedAt;
221432
+ const expiresAt = issuedAt + authProgressState.authChallenge.expires_in * 1000;
221433
+ if (Date.now() > expiresAt) {
221434
+ updateAuthProgressState({
221435
+ status: "EXPIRED",
221436
+ lastError: "设备码已过期,请重新发起授权",
221437
+ });
221438
+ }
221439
+ }
221440
+ return getAuthProgressStateSync();
221441
+ }
221442
+ function setPendingAuthProgressState(challenge, authMode = "device") {
221443
+ return updateAuthProgressState({
221444
+ status: "PENDING",
221445
+ authMode,
221446
+ authChallenge: challenge,
221447
+ lastError: undefined,
221448
+ });
221449
+ }
221450
+ function resolveAuthProgressState() {
221451
+ return updateAuthProgressState({
221452
+ status: "READY",
221453
+ lastError: undefined,
221454
+ });
221455
+ }
221456
+ function rejectAuthProgressState(error) {
221457
+ const message = error instanceof Error ? error.message : String(error ?? "unknown error");
221458
+ return updateAuthProgressState({
221459
+ status: mapAuthErrorStatus(error),
221460
+ lastError: message,
221461
+ });
221462
+ }
221463
+ function resetAuthProgressState() {
221464
+ return updateAuthProgressState({
221465
+ status: "IDLE",
221466
+ authMode: undefined,
221467
+ authChallenge: undefined,
221468
+ lastError: undefined,
221469
+ });
221470
+ }
221471
+ async function peekLoginState(options) {
221472
+ const envVarLoginState = normalizeLoginStateFromEnvVars(options);
221473
+ if (envVarLoginState) {
221474
+ (0, logger_js_1.debug)("loginByApiSecret");
221475
+ return envVarLoginState;
221476
+ }
221477
+ return auth.getLoginState();
221478
+ }
221479
+ async function ensureLogin(options) {
221480
+ (0, logger_js_1.debug)("TENCENTCLOUD_SECRETID", { secretId: process.env.TENCENTCLOUD_SECRETID });
221481
+ const loginState = await peekLoginState({
221482
+ ignoreEnvVars: options?.ignoreEnvVars,
221483
+ });
220286
221484
  if (!loginState) {
220287
- await auth.loginByWebAuth((options?.fromCloudBaseLoginPage && !(0, tencet_cloud_js_1.isInternationalRegion)(options?.region))
220288
- ? {
220289
- getAuthUrl: (url) => {
220290
- // 国际站
220291
- const separator = url.includes('?') ? '&' : '?';
220292
- const urlWithParam = `${url}${separator}allowNoEnv=true`;
220293
- return `https://tcb.cloud.tencent.com/login?_redirect_uri=${encodeURIComponent(urlWithParam)}`;
220294
- },
220295
- }
220296
- : {
220297
- getAuthUrl: (url) => {
220298
- if ((0, tencet_cloud_js_1.isInternationalRegion)(options?.region)) {
220299
- url = url.replace('cloud.tencent.com', 'tencentcloud.com');
221485
+ const envMode = process.env.TCB_AUTH_MODE;
221486
+ const normalizedEnvMode = envMode === "web" || envMode === "device" ? envMode : undefined;
221487
+ const mode = options?.authMode || normalizedEnvMode || "device";
221488
+ const loginOptions = { flow: mode };
221489
+ if (mode === "web") {
221490
+ loginOptions.getAuthUrl =
221491
+ options?.fromCloudBaseLoginPage && !(0, tencet_cloud_js_1.isInternationalRegion)(options?.region)
221492
+ ? (url) => {
221493
+ const separator = url.includes("?") ? "&" : "?";
221494
+ const urlWithParam = `${url}${separator}allowNoEnv=true`;
221495
+ return `https://tcb.cloud.tencent.com/login?_redirect_uri=${encodeURIComponent(urlWithParam)}`;
220300
221496
  }
220301
- const separator = url.includes('?') ? '&' : '?';
220302
- return `${url}${separator}allowNoEnv=true`;
220303
- },
220304
- });
220305
- const loginState = await auth.getLoginState();
220306
- (0, logger_js_1.debug)("loginByWebAuth", loginState);
221497
+ : (url) => {
221498
+ if ((0, tencet_cloud_js_1.isInternationalRegion)(options?.region)) {
221499
+ url = url.replace("cloud.tencent.com", "tencentcloud.com");
221500
+ }
221501
+ const separator = url.includes("?") ? "&" : "?";
221502
+ return `${url}${separator}allowNoEnv=true`;
221503
+ };
221504
+ }
221505
+ else {
221506
+ if (options?.clientId) {
221507
+ loginOptions.client_id = options.clientId;
221508
+ }
221509
+ if (options?.onDeviceCode) {
221510
+ loginOptions.onDeviceCode = (info) => {
221511
+ setPendingAuthProgressState(info, mode);
221512
+ options.onDeviceCode?.(info);
221513
+ };
221514
+ }
221515
+ }
221516
+ (0, logger_js_1.debug)("beforeloginByWebAuth", { loginOptions });
221517
+ try {
221518
+ await auth.loginByWebAuth(loginOptions);
221519
+ resolveAuthProgressState();
221520
+ }
221521
+ catch (error) {
221522
+ rejectAuthProgressState(error);
221523
+ throw error;
221524
+ }
221525
+ const loginState = await peekLoginState({
221526
+ ignoreEnvVars: options?.ignoreEnvVars,
221527
+ });
221528
+ (0, logger_js_1.debug)("loginByWebAuth", { mode, hasLoginState: !!loginState });
220307
221529
  return loginState;
220308
221530
  }
220309
221531
  else {
221532
+ resolveAuthProgressState();
220310
221533
  return loginState;
220311
221534
  }
220312
221535
  }
221536
+ async function getLoginState(options) {
221537
+ return ensureLogin(options);
221538
+ }
220313
221539
  async function logout() {
220314
221540
  const result = await auth.logout();
221541
+ resetAuthProgressState();
220315
221542
  return result;
220316
221543
  }
220317
221544
 
@@ -229844,126 +231071,6 @@ function onError(sender, err, cb) {
229844
231071
  }
229845
231072
 
229846
231073
 
229847
- /***/ }),
229848
-
229849
- /***/ 80998:
229850
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
229851
-
229852
- /* @flow */
229853
- /*::
229854
-
229855
- type DotenvParseOptions = {
229856
- debug?: boolean
229857
- }
229858
-
229859
- // keys and values from src
229860
- type DotenvParseOutput = { [string]: string }
229861
-
229862
- type DotenvConfigOptions = {
229863
- path?: string, // path to .env file
229864
- encoding?: string, // encoding of .env file
229865
- debug?: string // turn on logging for debugging purposes
229866
- }
229867
-
229868
- type DotenvConfigOutput = {
229869
- parsed?: DotenvParseOutput,
229870
- error?: Error
229871
- }
229872
-
229873
- */
229874
-
229875
- const fs = __webpack_require__(29021)
229876
- const path = __webpack_require__(39902)
229877
-
229878
- function log (message /*: string */) {
229879
- console.log(`[dotenv][DEBUG] ${message}`)
229880
- }
229881
-
229882
- const NEWLINE = '\n'
229883
- const RE_INI_KEY_VAL = /^\s*([\w.-]+)\s*=\s*(.*)?\s*$/
229884
- const RE_NEWLINES = /\\n/g
229885
- const NEWLINES_MATCH = /\n|\r|\r\n/
229886
-
229887
- // Parses src into an Object
229888
- function parse (src /*: string | Buffer */, options /*: ?DotenvParseOptions */) /*: DotenvParseOutput */ {
229889
- const debug = Boolean(options && options.debug)
229890
- const obj = {}
229891
-
229892
- // convert Buffers before splitting into lines and processing
229893
- src.toString().split(NEWLINES_MATCH).forEach(function (line, idx) {
229894
- // matching "KEY' and 'VAL' in 'KEY=VAL'
229895
- const keyValueArr = line.match(RE_INI_KEY_VAL)
229896
- // matched?
229897
- if (keyValueArr != null) {
229898
- const key = keyValueArr[1]
229899
- // default undefined or missing values to empty string
229900
- let val = (keyValueArr[2] || '')
229901
- const end = val.length - 1
229902
- const isDoubleQuoted = val[0] === '"' && val[end] === '"'
229903
- const isSingleQuoted = val[0] === "'" && val[end] === "'"
229904
-
229905
- // if single or double quoted, remove quotes
229906
- if (isSingleQuoted || isDoubleQuoted) {
229907
- val = val.substring(1, end)
229908
-
229909
- // if double quoted, expand newlines
229910
- if (isDoubleQuoted) {
229911
- val = val.replace(RE_NEWLINES, NEWLINE)
229912
- }
229913
- } else {
229914
- // remove surrounding whitespace
229915
- val = val.trim()
229916
- }
229917
-
229918
- obj[key] = val
229919
- } else if (debug) {
229920
- log(`did not match key and value when parsing line ${idx + 1}: ${line}`)
229921
- }
229922
- })
229923
-
229924
- return obj
229925
- }
229926
-
229927
- // Populates process.env from .env file
229928
- function config (options /*: ?DotenvConfigOptions */) /*: DotenvConfigOutput */ {
229929
- let dotenvPath = path.resolve(process.cwd(), '.env')
229930
- let encoding /*: string */ = 'utf8'
229931
- let debug = false
229932
-
229933
- if (options) {
229934
- if (options.path != null) {
229935
- dotenvPath = options.path
229936
- }
229937
- if (options.encoding != null) {
229938
- encoding = options.encoding
229939
- }
229940
- if (options.debug != null) {
229941
- debug = true
229942
- }
229943
- }
229944
-
229945
- try {
229946
- // specifying an encoding returns a string instead of a buffer
229947
- const parsed = parse(fs.readFileSync(dotenvPath, { encoding }), { debug })
229948
-
229949
- Object.keys(parsed).forEach(function (key) {
229950
- if (!Object.prototype.hasOwnProperty.call(process.env, key)) {
229951
- process.env[key] = parsed[key]
229952
- } else if (debug) {
229953
- log(`"${key}" is already defined in \`process.env\` and will not be overwritten`)
229954
- }
229955
- })
229956
-
229957
- return { parsed }
229958
- } catch (e) {
229959
- return { error: e }
229960
- }
229961
- }
229962
-
229963
- module.exports.config = config
229964
- module.exports.parse = parse
229965
-
229966
-
229967
231074
  /***/ }),
229968
231075
 
229969
231076
  /***/ 81115:
@@ -247309,8 +248416,7 @@ function shouldRegisterTool(toolName) {
247309
248416
  // Cloud-incompatible tools that involve local file operations
247310
248417
  const cloudIncompatibleTools = [
247311
248418
  // Auth tools - local file uploads
247312
- 'login',
247313
- 'logout',
248419
+ 'auth',
247314
248420
  // Storage tools - local file uploads
247315
248421
  'uploadFile',
247316
248422
  // Hosting tools - local file uploads
@@ -259853,6 +260959,141 @@ async function getInteractiveServerSafe(mcpServer) {
259853
260959
  }
259854
260960
 
259855
260961
 
260962
+ /***/ }),
260963
+
260964
+ /***/ 92423:
260965
+ /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
260966
+
260967
+ "use strict";
260968
+
260969
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
260970
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
260971
+ return new (P || (P = Promise))(function (resolve, reject) {
260972
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
260973
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
260974
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
260975
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
260976
+ });
260977
+ };
260978
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
260979
+ exports.getAuthTokenByDeviceFlow = void 0;
260980
+ const net_1 = __webpack_require__(31153);
260981
+ const web_1 = __webpack_require__(2240);
260982
+ const error_1 = __webpack_require__(64119);
260983
+ const coding_1 = __webpack_require__(40540);
260984
+ const system_1 = __webpack_require__(62179);
260985
+ const web_auth_1 = __webpack_require__(76097);
260986
+ /** 默认国内站 应用侧可通过 getOAuthEndpoint 覆写 */
260987
+ const OAUTH_ENDPOINT = process.env.TCB_OAUTH_ENDPOINT || 'https://tcb-api.cloud.tencent.com/qcloud-tcb/v1/oauth';
260988
+ const DEFAULT_CLIENT_ID = 'cloudbase-toolbox';
260989
+ const POLL_ERROR_CODES = {
260990
+ AUTHORIZATION_PENDING: 'authorization_pending',
260991
+ SLOW_DOWN: 'slow_down',
260992
+ EXPIRED_TOKEN: 'expired_token',
260993
+ ACCESS_DENIED: 'access_denied',
260994
+ };
260995
+ const SUCCESS_CODE = 'NORMAL';
260996
+ function fetchDeviceCode(options = {}) {
260997
+ const { client_id = DEFAULT_CLIENT_ID, endpoint = OAUTH_ENDPOINT } = options;
260998
+ return (0, net_1.postFetch)(`${endpoint}/device/code`, { client_id });
260999
+ }
261000
+ function fetchPollToken(options) {
261001
+ return __awaiter(this, void 0, void 0, function* () {
261002
+ const { device_code, client_id = DEFAULT_CLIENT_ID, endpoint = OAUTH_ENDPOINT } = options;
261003
+ const mac = yield (0, system_1.getMacAddress)();
261004
+ return (0, net_1.postFetch)(`${endpoint}/token`, {
261005
+ device_code,
261006
+ client_id,
261007
+ grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
261008
+ device_info: {
261009
+ mac,
261010
+ os: (0, system_1.getOSInfo)(),
261011
+ hash: (0, coding_1.md5Encoding)(mac),
261012
+ }
261013
+ });
261014
+ });
261015
+ }
261016
+ function sleep(ms) {
261017
+ return new Promise((resolve) => {
261018
+ setTimeout(resolve, ms);
261019
+ });
261020
+ }
261021
+ function getAuthTokenByDeviceFlow(options = {}) {
261022
+ return __awaiter(this, void 0, void 0, function* () {
261023
+ const { client_id, onDeviceCode, getOAuthEndpoint, getAuthUrl, silent } = options;
261024
+ const endpoint = getOAuthEndpoint ? getOAuthEndpoint(OAUTH_ENDPOINT) : OAUTH_ENDPOINT;
261025
+ const deviceCodeResp = yield fetchDeviceCode({ client_id, endpoint });
261026
+ if (deviceCodeResp.code !== SUCCESS_CODE) {
261027
+ throw new error_1.CloudBaseError('Device Flow fetchDeviceCode failed', {
261028
+ code: deviceCodeResp.code,
261029
+ requestId: deviceCodeResp.reqId,
261030
+ });
261031
+ }
261032
+ const { device_code, user_code, expires_in, interval } = deviceCodeResp.result;
261033
+ // 暂时不消费 verification_uri,由客户端控制跳转
261034
+ const defaultVerificationUri = `${web_auth_1.CLI_AUTH_BASE_URL}#/cli-auth`;
261035
+ // from=cli 后续考虑改用 client_id,因为 toolbox 作为公共依赖,可能被不同 client 所引用
261036
+ const rawVerificationUri = `${defaultVerificationUri}?user_code=${user_code}&from=cli&flow=device`;
261037
+ const verification_uri = getAuthUrl ? getAuthUrl(rawVerificationUri) : rawVerificationUri;
261038
+ if (!silent) {
261039
+ // 打印授权信息,引导用户操作
261040
+ console.log('\n\n若链接未自动打开,请手动复制至浏览器,或尝试其他登录方式:');
261041
+ console.log(`\n${verification_uri}`);
261042
+ console.log(`\n用户码: ${user_code}\n`);
261043
+ }
261044
+ // 尝试自动打开授权页面
261045
+ yield (0, web_1.openUrl)(verification_uri);
261046
+ if (onDeviceCode) {
261047
+ onDeviceCode({ user_code, verification_uri, device_code, expires_in });
261048
+ }
261049
+ let pollInterval = interval;
261050
+ const deadline = Date.now() + expires_in * 1000;
261051
+ while (Date.now() < deadline) {
261052
+ yield sleep(pollInterval * 1000);
261053
+ let resp;
261054
+ try {
261055
+ resp = yield fetchPollToken({ device_code, interval: pollInterval, client_id, endpoint });
261056
+ }
261057
+ catch (e) {
261058
+ throw new error_1.CloudBaseError('Device Flow 轮询请求失败', { original: e });
261059
+ }
261060
+ const { code, result } = resp;
261061
+ // 服务端返回业务错误(result 中携带 error 字段)
261062
+ if (result && 'error' in result) {
261063
+ const { error, error_description } = result;
261064
+ if (error === POLL_ERROR_CODES.AUTHORIZATION_PENDING) {
261065
+ continue;
261066
+ }
261067
+ if (error === POLL_ERROR_CODES.SLOW_DOWN) {
261068
+ pollInterval += 5;
261069
+ continue;
261070
+ }
261071
+ if (error === POLL_ERROR_CODES.EXPIRED_TOKEN) {
261072
+ throw new error_1.CloudBaseError('设备码已过期,请重新发起授权');
261073
+ }
261074
+ if (error === POLL_ERROR_CODES.ACCESS_DENIED) {
261075
+ throw new error_1.CloudBaseError('用户拒绝了授权请求');
261076
+ }
261077
+ throw new error_1.CloudBaseError(error_description || `Device Flow 授权失败,错误: ${error}`, {
261078
+ code: error,
261079
+ requestId: resp.reqId,
261080
+ });
261081
+ }
261082
+ // 服务端返回成功的 Credential
261083
+ if (code === SUCCESS_CODE && result) {
261084
+ return result;
261085
+ }
261086
+ throw new error_1.CloudBaseError(`Device Flow 授权失败,错误码: ${code}`, {
261087
+ code,
261088
+ requestId: resp.reqId,
261089
+ });
261090
+ }
261091
+ throw new error_1.CloudBaseError('授权超时,用户未在有效期内完成授权,请重试');
261092
+ });
261093
+ }
261094
+ exports.getAuthTokenByDeviceFlow = getAuthTokenByDeviceFlow;
261095
+
261096
+
259856
261097
  /***/ }),
259857
261098
 
259858
261099
  /***/ 92472: