Skip to content

Commit 8915eb4

Browse files
committed
feat(env-setup): 🔧 optimize interactive flow and add debug documentation
- Add DEBUG_CALL_CHAIN.md for debugging call chain analysis - Optimize env-setup components, scripts and styles - Improve interactive tools and interactive-server implementation - Update doc components (ErrorCodeIDEButton, TutorialsGrid) - Refactor auth and cloudbase-manager for better error handling
1 parent 40e948b commit 8915eb4

12 files changed

Lines changed: 461 additions & 231 deletions

File tree

DEBUG_CALL_CHAIN.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# 调用链分析
2+
3+
## 完整调用链
4+
5+
```
6+
1. CLI 启动 (cli.ts)
7+
└─> const server = createCloudBaseMcpServer({ ide: "CodeBuddy" })
8+
└─> 返回 Promise<ExtendedMcpServer>
9+
10+
2. Server 创建 (server.ts)
11+
└─> await createCloudBaseMcpServer()
12+
├─> 创建 ExtendedMcpServer 实例
13+
├─> server.ide = "CodeBuddy"
14+
├─> server.server = McpServer 内部实例(有 sendLoggingMessage)
15+
└─> await plugin.register(server) // 注册所有插件
16+
└─> registerEnvTools(server) // server 是 ExtendedMcpServer 实例
17+
18+
3. 工具注册 (env.ts)
19+
└─> registerEnvTools(server) // server 是 ExtendedMcpServer 实例
20+
└─> server.registerTool("login", async handler)
21+
└─> handler 中调用: await _promptAndSetEnvironmentId(forceUpdate, { server })
22+
// 这里的 server 是闭包中的 ExtendedMcpServer 实例
23+
24+
4. 环境选择流程 (interactive.ts)
25+
└─> _promptAndSetEnvironmentId(autoSelectSingle, { server })
26+
├─> const server = options?.server // ExtendedMcpServer 实例
27+
├─> const resolvedServer = server instanceof Promise ? await server : server
28+
│ └─> resolvedServer = server (因为 server 不是 Promise)
29+
├─> const interactiveServer = getInteractiveServer(resolvedServer)
30+
│ └─> 更新或创建 InteractiveServer 实例,设置 this._mcpServer = resolvedServer
31+
└─> await interactiveServer.collectEnvId(..., resolvedServer)
32+
// 传递 resolvedServer (ExtendedMcpServer 实例)
33+
34+
5. InteractiveServer (interactive-server.ts)
35+
└─> collectEnvId(..., mcpServer)
36+
├─> if (mcpServer) { this._mcpServer = mcpServer }
37+
└─> await openUrl(url, { wait: false }, this._mcpServer)
38+
// 使用 this._mcpServer
39+
40+
6. openUrl (interactive-server.ts)
41+
└─> openUrl(url, options, mcpServer)
42+
├─> const currentIde = mcpServer?.ide || process.env.INTEGRATION_IDE
43+
├─> const internalServer = mcpServer?.server
44+
└─> if (currentIde === "CodeBuddy" && internalServer?.sendLoggingMessage)
45+
└─> internalServer.sendLoggingMessage({ ... })
46+
```
47+
48+
## 问题分析
49+
50+
从日志看:
51+
- `[collectEnvId] this._mcpServer type: undefined` - 说明 `this._mcpServer``undefined`
52+
- `[openUrl] mcpServer type: undefined` - 说明传递给 `openUrl``mcpServer``undefined`
53+
54+
**可能的原因:**
55+
1. `collectEnvId``mcpServer` 参数是 `undefined`,所以 `this._mcpServer` 没有被更新
56+
2. 或者 `this._mcpServer` 被更新了,但在调用 `openUrl` 时又变成了 `undefined`
57+
58+
**需要检查的点:**
59+
1. `resolvedServer``_promptAndSetEnvironmentId` 中是否正确
60+
2. `collectEnvId``mcpServer` 参数是否正确传递
61+
3. `this._mcpServer``collectEnvId` 中是否被正确更新
62+

doc/components/ErrorCodeIDEButton.tsx

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
21
import { useLocation } from '@docusaurus/router';
3-
import React, { useState, useMemo, useEffect } from 'react';
4-
import IDESelector from './IDESelector';
2+
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
3+
import React, { useEffect, useMemo, useState } from 'react';
54
import styles from './ErrorCodeIDEButton.module.css';
5+
import IDESelector from './IDESelector';
66
import { reportEvent } from './analytics';
77

88
// IDE list for icons (from IDESelector)
@@ -58,24 +58,22 @@ function generatePrompt(pageUrl: string, locale: string): string {
5858
5959
请帮助我解决这个问题:
6060
61-
1. **建议修复方案**:分析我的代码库上下文,提出需要更改什么来解决这个错误
62-
63-
2. **解释根本原因**:分析为什么会出现这个错误:
64-
- 代码实际在做什么 vs. 它需要做什么?
65-
- 什么条件触发了这个特定错误?
66-
- 是什么误解或疏忽导致了这个问题?
61+
1. **分析代码库并使用 CloudBase MCP 工具解决问题**:
62+
- 深入分析我的代码库上下文,理解代码结构和相关模块
63+
- 阅读 CloudBase 的 AI rules 和 MCP 工具文档,理解问题的本质
64+
- 尝试使用 CloudBase MCP 工具(如 envQuery、login、executeReadOnlySQL 等)来诊断和解决这个问题
65+
- 如果需要修改代码,提出具体的修改方案,包括需要修改的文件、函数和代码行
6766
68-
3. **教授概念**:帮助我理解底层原理
69-
- 为什么这个错误存在,它保护我免受什么
70-
- 这个概念的正确心智模型是什么
71-
- 这如何融入更广泛的框架/语言设计
67+
2. **解释根本原因**
68+
- 代码实际在做什么 vs. 它应该做什么
69+
- 什么条件或场景触发了这个特定错误
70+
- 是什么误解、疏忽或不当使用导致了这个问题
7271
73-
4. **展示警告信号**:帮助我在未来识别这种模式:
74-
- 我应该注意什么可能导致这种情况再次发生?
75-
- 在相关场景中我可能犯哪些类似的错误?
76-
- 哪些代码异味或模式表明这个问题?
77-
78-
5. **讨论替代方案**:解释是否有不同的有效方法及其权衡
72+
3. **用费曼学习法教授概念**:
73+
- 用简单易懂的语言解释底层原理,就像教一个初学者一样
74+
- 如果涉及我不熟悉的概念(如 MCP 工具、CloudBase API、框架特性等),请先解释这些基础概念
75+
- 用类比和具体例子帮助我建立正确的心智模型
76+
- 解释这个概念在整个系统中的作用和重要性
7977
8078
我的目标是修复眼前的问题,同时建立持久的理解,这样我就可以在未来独立避免和解决类似的错误。`;
8179
}
@@ -84,24 +82,22 @@ function generatePrompt(pageUrl: string, locale: string): string {
8482
8583
Please help me resolve this by:
8684
87-
1. **Suggest the fix**: Analyze my codebase context and propose what needs to be changed to resolve this error
88-
89-
2. **Explain the root cause**: Break down why this error occurred:
90-
- What was the code actually doing vs. what it needed to do?
91-
- What conditions triggered this specific error?
92-
- What misconception or oversight led to this?
93-
94-
3. **Teach the concept**: Help me understand the underlying principle:
95-
- Why does this error exist and what is it protecting me from?
96-
- What's the correct mental model for this concept?
97-
- How does this fit into the broader framework/language design?
98-
99-
4. **Show warning signs**: Help me recognize this pattern in the future:
100-
- What should I look out for that might cause this again?
101-
- Are there similar mistakes I might make in related scenarios?
102-
- What code smells or patterns indicate this issue?
103-
104-
5. **Discuss alternatives**: Explain if there are different valid approaches and their trade-offs
85+
1. **Analyze codebase and solve using CloudBase MCP tools**:
86+
- Deeply analyze my codebase context to understand the code structure and related modules
87+
- Read CloudBase AI rules and MCP tools documentation to understand the root cause
88+
- Try using CloudBase MCP tools (such as envQuery, login, executeReadOnlySQL, etc.) to diagnose and solve this problem
89+
- If code changes are needed, propose specific modifications including files, functions, and code lines to modify
90+
91+
2. **Explain the root cause**:
92+
- What was the code actually doing vs. what it should be doing?
93+
- What conditions or scenarios triggered this specific error?
94+
- What misconception, oversight, or improper usage led to this problem?
95+
96+
3. **Teach concepts using the Feynman technique**:
97+
- Explain underlying principles in simple, accessible language, as if teaching a beginner
98+
- If unfamiliar concepts are involved (like MCP tools, CloudBase APIs, framework features, etc.), explain these fundamentals first
99+
- Use analogies and concrete examples to help me build the correct mental model
100+
- Explain how this concept fits into and matters within the broader system
105101
106102
My goal is to fix the immediate issue while building lasting understanding so I can avoid and resolve similar errors independently in the future.`;
107103
}

doc/components/TutorialsGrid.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,13 @@ const tutorials: Tutorial[] = [
120120
},
121121
// 视频
122122
{
123-
id: 'video-ai-programming-deploy',
124-
title: 'AI编程,一键部署',
125-
description: '腾讯云云开发',
123+
id: 'video-bilibili-ai-assistant',
124+
title: '【教程】不写一行代码,开发B站热门选题AI助手 | 数据分析 | 爬虫',
125+
description: '熠辉IndieDev',
126126
category: '视频教程',
127-
url: 'https://www.bilibili.com/video/BV1Honwz1E64/?share_source=copy_web&vd_source=068decbd00a3d00ff8662b6a358e5e1e',
127+
url: 'https://www.bilibili.com/video/BV1JBmKBBEZa/?share_source=copy_web&vd_source=068decbd00a3d00ff8662b6a358e5e1e',
128128
type: 'video',
129-
thumbnail: 'https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/video-thumbnails/BV1Honwz1E64.jpg',
129+
thumbnail: 'https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/video-thumbnails/BV1JBmKBBEZa.jpg',
130130
},
131131
{
132132
id: 'video-mbti-dating',
@@ -380,6 +380,15 @@ const tutorials: Tutorial[] = [
380380
type: 'video',
381381
thumbnail: 'https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/video-thumbnails/BV1YReMz7EKn.jpg',
382382
},
383+
{
384+
id: 'video-ai-programming-deploy',
385+
title: 'AI编程,一键部署',
386+
description: '腾讯云云开发',
387+
category: '视频教程',
388+
url: 'https://www.bilibili.com/video/BV1Honwz1E64/?share_source=copy_web&vd_source=068decbd00a3d00ff8662b6a358e5e1e',
389+
type: 'video',
390+
thumbnail: 'https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/video-thumbnails/BV1Honwz1E64.jpg',
391+
},
383392
// 应用项目
384393
{
385394
id: 'project-resume',

mcp/src/auth.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@ const auth = AuthSupevisor.getInstance({});
55

66
export async function getLoginState(options?: {
77
fromCloudBaseLoginPage?: boolean;
8+
ignoreEnvVars?: boolean;
89
}) {
910
const {
1011
TENCENTCLOUD_SECRETID,
1112
TENCENTCLOUD_SECRETKEY,
1213
TENCENTCLOUD_SESSIONTOKEN,
1314
} = process.env;
1415
debug("TENCENTCLOUD_SECRETID", { secretId: TENCENTCLOUD_SECRETID });
15-
if (TENCENTCLOUD_SECRETID && TENCENTCLOUD_SECRETKEY) {
16+
17+
// If ignoreEnvVars is true (e.g., when switching account), skip environment variables
18+
// and force Web authentication to allow account switching
19+
if (!options?.ignoreEnvVars && TENCENTCLOUD_SECRETID && TENCENTCLOUD_SECRETKEY) {
1620
debug("loginByApiSecret");
1721
return {
1822
secretId: TENCENTCLOUD_SECRETID,

mcp/src/cloudbase-manager.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class EnvironmentManager {
1818
}
1919

2020
// 获取环境ID的核心逻辑
21-
async getEnvId(): Promise<string> {
21+
async getEnvId(mcpServer?: any): Promise<string> {
2222
// 1. 优先使用内存缓存
2323
if (this.cachedEnvId) {
2424
debug('使用内存缓存的环境ID:', { envId: this.cachedEnvId });
@@ -30,8 +30,8 @@ class EnvironmentManager {
3030
return this.envIdPromise;
3131
}
3232

33-
// 3. 开始获取环境ID
34-
this.envIdPromise = this._fetchEnvId();
33+
// 3. 开始获取环境ID (pass mcpServer for IDE detection)
34+
this.envIdPromise = this._fetchEnvId(mcpServer);
3535

3636
// 增加超时保护
3737
const timeoutPromise = new Promise<string>((_, reject) => {
@@ -50,7 +50,7 @@ class EnvironmentManager {
5050
}
5151
}
5252

53-
private async _fetchEnvId(): Promise<string> {
53+
private async _fetchEnvId(mcpServer?: any): Promise<string> {
5454
try {
5555
// 1. 检查进程环境变量
5656
if (process.env.CLOUDBASE_ENV_ID) {
@@ -59,9 +59,9 @@ class EnvironmentManager {
5959
return this.cachedEnvId;
6060
}
6161

62-
// 2. 自动设置环境ID
62+
// 2. 自动设置环境ID (pass mcpServer for IDE detection)
6363
debug('未找到环境ID,尝试自动设置...');
64-
const autoEnvId = await autoSetupEnvironmentId();
64+
const autoEnvId = await autoSetupEnvironmentId(mcpServer);
6565
if (!autoEnvId) {
6666
throw new Error("CloudBase Environment ID not found after auto setup. Please set CLOUDBASE_ENV_ID or run setupEnvironmentId tool.");
6767
}
@@ -122,13 +122,14 @@ export function getCachedEnvId(): string | null {
122122
export interface GetManagerOptions {
123123
requireEnvId?: boolean;
124124
cloudBaseOptions?: CloudBaseOptions;
125+
mcpServer?: any; // Optional MCP server instance for IDE detection (e.g., CodeBuddy)
125126
}
126127

127128
/**
128129
* 每次都实时获取最新的 token/secretId/secretKey
129130
*/
130131
export async function getCloudBaseManager(options: GetManagerOptions = {}): Promise<CloudBase> {
131-
const { requireEnvId = true, cloudBaseOptions } = options;
132+
const { requireEnvId = true, cloudBaseOptions, mcpServer } = options;
132133

133134
// 如果传入了 cloudBaseOptions,直接使用传入的配置
134135
if (cloudBaseOptions) {
@@ -160,8 +161,8 @@ export async function getCloudBaseManager(options: GetManagerOptions = {}): Prom
160161
finalEnvId = loginEnvId;
161162
} else {
162163
// Only call envManager.getEnvId() when neither cache nor loginState has envId
163-
// This may trigger auto-setup flow
164-
finalEnvId = await envManager.getEnvId();
164+
// This may trigger auto-setup flow (pass mcpServer for IDE detection)
165+
finalEnvId = await envManager.getEnvId(mcpServer);
165166
}
166167
}
167168

0 commit comments

Comments
 (0)