mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-22 01:37:50 +00:00
wip(vscode-ide-companion): 实现 quick win 功能
- 将 WebView 调整到编辑器右侧 - 添加 ChatHeader 组件,实现会话下拉菜单 - 替换模态框为紧凑型下拉菜单 - 更新会话切换逻辑,显示当前标题 - 清理旧的会话选择器样式 基于 Claude Code v2.0.43 UI 分析实现。
This commit is contained in:
378
packages/vscode-ide-companion/docs-tmp/AUTH_FLOW.md
Normal file
378
packages/vscode-ide-companion/docs-tmp/AUTH_FLOW.md
Normal file
@@ -0,0 +1,378 @@
|
||||
# Qwen Code 认证流程说明
|
||||
|
||||
## 🔐 认证流程概览
|
||||
|
||||
```
|
||||
用户打开 Chat UI
|
||||
↓
|
||||
WebViewProvider.show()
|
||||
↓
|
||||
检查 agentInitialized 标志
|
||||
├─ 如果为 true → 跳过初始化(使用现有连接)
|
||||
└─ 如果为 false → 继续初始化
|
||||
↓
|
||||
authStateManager.hasValidAuth()
|
||||
├─ 有效缓存 → needsAuth = false
|
||||
└─ 无缓存/过期 → needsAuth = true
|
||||
↓
|
||||
尝试恢复本地 session
|
||||
├─ 成功 → sessionRestored = true, needsAuth = false
|
||||
└─ 失败 → 继续
|
||||
↓
|
||||
如果 !sessionRestored && needsAuth
|
||||
↓
|
||||
authenticate() (仅一次!) ✅
|
||||
↓
|
||||
newSession()
|
||||
↓
|
||||
saveAuthState()
|
||||
↓
|
||||
agentInitialized = true
|
||||
```
|
||||
|
||||
## ✅ 已修复的问题
|
||||
|
||||
### 问题 1: 嵌套 try-catch 导致重复认证(已修复)
|
||||
|
||||
**之前的代码**:
|
||||
|
||||
```typescript
|
||||
try {
|
||||
if (switchSession fails) {
|
||||
authenticate(); // 第 1 次
|
||||
} else {
|
||||
authenticate(); // 第 1 次
|
||||
}
|
||||
} catch {
|
||||
authenticate(); // 第 2 次!❌
|
||||
}
|
||||
```
|
||||
|
||||
**修复后的代码**:
|
||||
|
||||
```typescript
|
||||
let needsAuth = true;
|
||||
let sessionRestored = false;
|
||||
|
||||
// 检查缓存
|
||||
if (hasValidAuth) {
|
||||
needsAuth = false;
|
||||
}
|
||||
|
||||
// 尝试恢复 session
|
||||
try {
|
||||
if (switchSession succeeds) {
|
||||
sessionRestored = true;
|
||||
needsAuth = false;
|
||||
}
|
||||
} catch {
|
||||
// 只记录日志,不触发认证
|
||||
}
|
||||
|
||||
// 只在必要时认证(最多一次)
|
||||
if (!sessionRestored && needsAuth) {
|
||||
authenticate(); // 只会执行一次!✅
|
||||
newSession();
|
||||
}
|
||||
```
|
||||
|
||||
### 问题 2: agentInitialized 标志未重置(已修复)
|
||||
|
||||
**问题描述**:
|
||||
清除认证缓存后,`agentInitialized` 标志仍为 `true`,导致不会重新初始化。
|
||||
|
||||
**修复方案**:
|
||||
|
||||
```typescript
|
||||
// WebViewProvider.ts
|
||||
resetAgentState(): void {
|
||||
this.agentInitialized = false;
|
||||
this.agentManager.disconnect();
|
||||
}
|
||||
|
||||
// extension.ts
|
||||
vscode.commands.registerCommand('qwenCode.clearAuthCache', async () => {
|
||||
await authStateManager.clearAuthState();
|
||||
webViewProvider.resetAgentState(); // ✅ 重置状态
|
||||
});
|
||||
```
|
||||
|
||||
## 🎯 正确的使用方式
|
||||
|
||||
### 场景 1: 正常使用(无需手动操作)
|
||||
|
||||
```
|
||||
第1次打开 Chat UI:
|
||||
→ 没有缓存
|
||||
→ 需要登录 (1 次)
|
||||
→ 保存缓存 (24小时)
|
||||
|
||||
第2次打开 Chat UI (24小时内):
|
||||
→ 有缓存
|
||||
→ 不需要登录 ✅
|
||||
|
||||
第3次打开 Chat UI (24小时后):
|
||||
→ 缓存过期
|
||||
→ 需要登录 (1 次)
|
||||
→ 更新缓存
|
||||
```
|
||||
|
||||
### 场景 2: 手动清除缓存
|
||||
|
||||
```
|
||||
1. 执行命令: Qwen Code: Clear Authentication Cache
|
||||
→ 清除缓存
|
||||
→ 重置 agentInitialized 标志
|
||||
→ 断开现有连接
|
||||
|
||||
2. 下次打开 Chat UI:
|
||||
→ 没有缓存
|
||||
→ 需要登录 (1 次) ✅
|
||||
→ 保存新缓存
|
||||
```
|
||||
|
||||
### 场景 3: 缓存有效但 token 失效
|
||||
|
||||
```
|
||||
打开 Chat UI:
|
||||
→ 缓存有效,跳过认证
|
||||
→ 尝试创建 session
|
||||
→ Session 创建失败(token 已过期)
|
||||
↓
|
||||
【自动恢复】✅
|
||||
→ 清除缓存
|
||||
→ 重新认证 (1 次)
|
||||
→ 保存新缓存
|
||||
→ 重新创建 session
|
||||
```
|
||||
|
||||
## ⚠️ 可能导致多次登录的情况
|
||||
|
||||
### 情况 1: Session 恢复失败 + 认证重试
|
||||
|
||||
如果 session 恢复失败,且认证也失败,会触发重试(最多 3 次):
|
||||
|
||||
```
|
||||
尝试恢复 session → 失败
|
||||
↓
|
||||
认证尝试 #1 → 失败
|
||||
↓ (等待 1 秒)
|
||||
认证尝试 #2 → 失败
|
||||
↓ (等待 2 秒)
|
||||
认证尝试 #3 → 失败
|
||||
↓
|
||||
抛出错误
|
||||
```
|
||||
|
||||
**这是正常的重试机制**,用于处理网络临时故障。
|
||||
|
||||
### 情况 2: 多次打开/关闭 Chat UI
|
||||
|
||||
如果频繁打开关闭 Chat UI:
|
||||
|
||||
```
|
||||
打开 #1 → 登录 → agentInitialized = true
|
||||
关闭
|
||||
打开 #2 → 使用现有连接 ✅ (不需要登录)
|
||||
关闭
|
||||
打开 #3 → 使用现有连接 ✅ (不需要登录)
|
||||
```
|
||||
|
||||
**这是正常行为**,不会重复登录。
|
||||
|
||||
## 🐛 如何诊断"两次登录"问题
|
||||
|
||||
### 1. 查看详细日志
|
||||
|
||||
打开 VSCode 输出面板:
|
||||
|
||||
```
|
||||
View → Output → 选择 "Qwen Code Companion"
|
||||
```
|
||||
|
||||
查找以下关键日志:
|
||||
|
||||
#### 正常流程(只登录一次):
|
||||
|
||||
```
|
||||
[WebViewProvider] Starting initialization, workingDir: /path/to/workspace
|
||||
[QwenAgentManager] Using cached authentication ← 或者跳过这行(首次登录)
|
||||
[QwenAgentManager] Creating new session...
|
||||
[QwenAgentManager] 🔐 AUTHENTICATION CALL STARTED at 2025-11-17T... ← 只出现一次!
|
||||
[QwenAgentManager] Call stack: ...
|
||||
[QwenAgentManager] 📝 Authenticating (attempt 1/3)...
|
||||
[QwenAgentManager] ✅ Authentication successful on attempt 1
|
||||
[QwenAgentManager] New session created successfully
|
||||
[AuthStateManager] Auth state saved
|
||||
```
|
||||
|
||||
#### 异常流程(登录多次):
|
||||
|
||||
```
|
||||
[QwenAgentManager] 🔐 AUTHENTICATION CALL STARTED at 2025-11-17T10:00:00 ← 第 1 次
|
||||
[QwenAgentManager] Call stack: ...
|
||||
[QwenAgentManager] ✅ Authentication successful on attempt 1
|
||||
[QwenAgentManager] 🔐 AUTHENTICATION CALL STARTED at 2025-11-17T10:00:05 ← 第 2 次!❌
|
||||
[QwenAgentManager] Call stack: ...
|
||||
```
|
||||
|
||||
**如果看到两个 "AUTHENTICATION CALL STARTED",说明 `authenticateWithRetry()` 被调用了两次!**
|
||||
|
||||
### 2. 分析调用栈
|
||||
|
||||
查看每次认证调用的堆栈信息:
|
||||
|
||||
```
|
||||
[QwenAgentManager] Call stack:
|
||||
at QwenAgentManager.authenticateWithRetry (/path/to/QwenAgentManager.ts:206)
|
||||
at QwenAgentManager.connect (/path/to/QwenAgentManager.ts:162) ← 正常调用
|
||||
at WebViewProvider.show (/path/to/WebViewProvider.ts:131)
|
||||
```
|
||||
|
||||
或者:
|
||||
|
||||
```
|
||||
[QwenAgentManager] Call stack:
|
||||
at QwenAgentManager.authenticateWithRetry (/path/to/QwenAgentManager.ts:206)
|
||||
at QwenAgentManager.connect (/path/to/QwenAgentManager.ts:184) ← 缓存失效重试!
|
||||
at WebViewProvider.show (/path/to/WebViewProvider.ts:131)
|
||||
```
|
||||
|
||||
### 3. 区分"重试"和"重复调用"
|
||||
|
||||
**重要**:需要区分以下两种情况:
|
||||
|
||||
#### 情况 A: 认证重试(正常)
|
||||
|
||||
```
|
||||
[QwenAgentManager] 🔐 AUTHENTICATION CALL STARTED ← 只有一次 CALL STARTED
|
||||
[QwenAgentManager] 📝 Authenticating (attempt 1/3)... ← 第 1 次尝试
|
||||
[QwenAgentManager] ❌ Authentication attempt 1 failed
|
||||
[QwenAgentManager] ⏳ Retrying in 1000ms...
|
||||
[QwenAgentManager] 📝 Authenticating (attempt 2/3)... ← 第 2 次尝试
|
||||
[QwenAgentManager] ✅ Authentication successful on attempt 2
|
||||
```
|
||||
|
||||
**这是正常的!** 这是同一个认证调用的多次尝试。
|
||||
|
||||
#### 情况 B: 重复认证调用(异常)
|
||||
|
||||
```
|
||||
[QwenAgentManager] 🔐 AUTHENTICATION CALL STARTED at ... ← 第 1 个认证调用
|
||||
[QwenAgentManager] 📝 Authenticating (attempt 1/3)...
|
||||
[QwenAgentManager] ✅ Authentication successful on attempt 1
|
||||
[QwenAgentManager] 🔐 AUTHENTICATION CALL STARTED at ... ← 第 2 个认证调用!❌
|
||||
[QwenAgentManager] 📝 Authenticating (attempt 1/3)...
|
||||
```
|
||||
|
||||
**这是异常的!** `authenticateWithRetry()` 被调用了两次。
|
||||
|
||||
### 4. 检查 agentInitialized 标志
|
||||
|
||||
查找以下日志:
|
||||
|
||||
```
|
||||
[WebViewProvider] Agent already initialized, reusing existing connection
|
||||
```
|
||||
|
||||
如果每次打开都看到 "Starting initialization",说明标志没有正确保持。
|
||||
|
||||
### 5. 检查是否是 OAuth 流程本身的问题
|
||||
|
||||
如果日志显示只有一次 "AUTHENTICATION CALL STARTED",但浏览器弹出了两次授权页面,那可能是 **Qwen CLI 的 OAuth 流程本身需要两次交互**。
|
||||
|
||||
这种情况需要检查 Qwen CLI 的实现,不是 VSCode 扩展的问题。
|
||||
|
||||
## 🔧 手动测试步骤
|
||||
|
||||
### 测试 1: 正常流程
|
||||
|
||||
```bash
|
||||
1. 清除缓存: Cmd+Shift+P → "Clear Authentication Cache"
|
||||
2. 打开 Chat UI
|
||||
3. 应该看到: 登录提示 (1 次)
|
||||
4. 关闭 Chat UI
|
||||
5. 重新打开 Chat UI
|
||||
6. 应该看到: 直接连接,不需要登录 ✅
|
||||
```
|
||||
|
||||
### 测试 2: 缓存过期
|
||||
|
||||
```bash
|
||||
1. 修改 AUTH_CACHE_DURATION 为 1 分钟:
|
||||
// AuthStateManager.ts:21
|
||||
private static readonly AUTH_CACHE_DURATION = 1 * 60 * 1000;
|
||||
|
||||
2. 打开 Chat UI → 登录
|
||||
3. 等待 2 分钟
|
||||
4. 重新打开 Chat UI
|
||||
5. 应该看到: 需要重新登录 (1 次) ✅
|
||||
```
|
||||
|
||||
### 测试 3: 清除缓存
|
||||
|
||||
```bash
|
||||
1. 打开 Chat UI (已登录)
|
||||
2. 执行: "Clear Authentication Cache"
|
||||
3. 关闭 Chat UI
|
||||
4. 重新打开 Chat UI
|
||||
5. 应该看到: 需要重新登录 (1 次) ✅
|
||||
```
|
||||
|
||||
## 📊 认证状态管理
|
||||
|
||||
### 缓存存储位置
|
||||
|
||||
```
|
||||
macOS: ~/Library/Application Support/Code/User/globalStorage/
|
||||
Linux: ~/.config/Code/User/globalStorage/
|
||||
Windows: %APPDATA%\Code\User\globalStorage\
|
||||
```
|
||||
|
||||
### 缓存内容
|
||||
|
||||
```typescript
|
||||
{
|
||||
isAuthenticated: true,
|
||||
authMethod: "qwen-oauth", // 或 "openai"
|
||||
workingDir: "/path/to/workspace",
|
||||
timestamp: 1700000000000 // Unix timestamp
|
||||
}
|
||||
```
|
||||
|
||||
### 缓存有效期
|
||||
|
||||
- **默认**: 24 小时
|
||||
- **修改方式**: 编辑 `AuthStateManager.ts:21`
|
||||
- **检查方式**: 执行命令(如果添加了)或查看日志
|
||||
|
||||
## 🎯 关键代码位置
|
||||
|
||||
| 功能 | 文件 | 行号 |
|
||||
| ------------ | --------------------- | ------- |
|
||||
| 认证缓存管理 | `AuthStateManager.ts` | 全文 |
|
||||
| 认证逻辑 | `QwenAgentManager.ts` | 61-195 |
|
||||
| 初始化控制 | `WebViewProvider.ts` | 113-154 |
|
||||
| 清除缓存命令 | `extension.ts` | 148-160 |
|
||||
| 缓存有效期 | `AuthStateManager.ts` | 21 |
|
||||
|
||||
## ✅ 总结
|
||||
|
||||
**当前实现已经修复了重复登录的问题**:
|
||||
|
||||
1. ✅ 使用 `needsAuth` 标志确保最多认证一次
|
||||
2. ✅ 缓存有效时跳过认证
|
||||
3. ✅ Session 恢复成功时跳过认证
|
||||
4. ✅ 清除缓存时重置 `agentInitialized` 标志
|
||||
5. ✅ 缓存失效时自动重新认证(只一次)
|
||||
|
||||
**如果仍然遇到多次登录**,请:
|
||||
|
||||
1. 检查日志确认是否真的登录了多次
|
||||
2. 确认是否是重试机制(3 次尝试是正常的)
|
||||
3. 检查是否多次打开了不同的 Chat UI 实例
|
||||
4. 提供详细的日志帮助诊断
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2025-11-17
|
||||
Reference in New Issue
Block a user