Skip to content

Latest commit

 

History

History
224 lines (159 loc) · 5.73 KB

File metadata and controls

224 lines (159 loc) · 5.73 KB

认证延迟刷新优化

问题描述

在CLI启动后,即使主界面已经显示,输入框也会突然变为 "⠼ Authenticating and preparing environment..." 的提示,需要等待几秒才能恢复使用。

问题原因

useAuthCommand hook 在启动时执行两个阶段:

  1. 第一阶段 (checkAuthOnStartup): 快速检查认证状态是否有效
  2. 第二阶段 (authFlow): 主动调用 config.refreshAuth() 刷新认证

第二阶段的问题:

  • 调用 refreshAuth() 会重新初始化 GeminiClient
  • 这个过程涉及网络请求、模型配置等,需要2-5秒
  • 期间会设置 isAuthenticatingisPreparingEnvironment 状态为 true
  • 导致输入框被 <AuthInProgress> 组件替换,阻塞用户输入

解决方案

优化策略:延迟认证刷新

核心思想:启动时只检查认证是否有效,但不主动刷新。真正的认证刷新会在用户发送第一个请求时由API调用自动触发。

实现细节

修改前的逻辑

useEffect(() => {
  const authFlow = async () => {
    // ... 检查条件

    try {
      setIsAuthenticating(true);  // ❌ 阻塞UI

      // ❌ 主动刷新认证,导致启动慢
      await config.refreshAuth(authType);

      setIsPreparingEnvironment(true);  // ❌ 继续阻塞UI
      await new Promise(resolve => setTimeout(resolve, 100));

    } catch (e) {
      // 处理错误
    } finally {
      setIsAuthenticating(false);
      setIsPreparingEnvironment(false);
    }
  };

  void authFlow();
}, [isAuthDialogOpen, settings, config, ...]);

修改后的逻辑

useEffect(() => {
  const authFlow = async () => {
    // ... 检查条件

    try {
      // ✅ 只检查认证状态,不刷新
      if (authType === AuthType.USE_PROXY_AUTH) {
        const { ProxyAuthManager } = await import('deepv-code-core');
        const proxyAuthManager = ProxyAuthManager.getInstance();

        const userInfo = proxyAuthManager.getUserInfo();
        if (userInfo) {
          console.log(`✅ 已登录用户: ${userInfo.name}`);
          // ✅ 有用户信息说明认证有效,不需要立即刷新
          return;
        }
      }

      // ✅ 对于其他认证类型,也延迟到真正需要时再刷新
      console.log(`✅ 认证类型: ${authType} (将在首次使用时刷新)`);

    } catch (e) {
      console.warn('⚠️ 认证检查失败:', e);
      // ✅ 检查失败不影响CLI启动,用户发送消息时会重新认证
    }
  };

  void authFlow();
}, [isAuthDialogOpen, settings, config, ...]);

认证何时真正发生?

认证刷新会在以下时机自动触发

  1. 用户发送第一个消息时:调用GeminiClient的API
  2. API调用前:GeminiClient内部会检查认证状态
  3. Token过期时:自动触发刷新流程

因此,启动时不需要主动刷新认证,可以节省2-5秒的启动时间。

效果对比

优化前

启动CLI
  ↓
显示主界面(输入框可见)
  ↓
⚠️ 输入框突然变为 "⠼ Authenticating..."
  ↓
等待 2-5 秒
  ↓
输入框恢复可用

用户体验

  • ❌ 输入框"假可用",用户可能开始输入然后被打断
  • ❌ 等待时间长,体验差
  • ❌ 不清楚在做什么

优化后

启动CLI
  ↓
显示主界面(输入框可用)
  ↓
✅ 用户立即可以输入
  ↓
发送第一个消息时才进行认证(如果需要)

用户体验

  • ✅ 输入框真正立即可用
  • ✅ 无等待,体验流畅
  • ✅ 认证在后台透明进行

安全性考虑

问题:认证过期怎么办?

回答:没有问题,认证系统有多层保护:

  1. 启动检查 (checkAuthOnStartup):

    • 快速检查认证是否有效
    • 如果过期,会自动打开认证对话框
  2. API调用前检查

    • GeminiClient在每次API调用前都会验证token
    • 如果过期,会触发刷新或提示用户重新登录
  3. 错误处理

    • 如果认证失败,会通过 onAuthError 回调通知用户
    • 用户可以重新选择认证方式

问题:会影响功能吗?

回答:不会,所有功能保持不变:

  • ✅ 认证检查机制完整
  • ✅ Token刷新机制完整
  • ✅ 错误处理机制完整
  • ✅ 只是改变了刷新的时机,不是删除刷新

代码修改

修改文件

  • packages/cli/src/ui/hooks/useAuthCommand.ts

关键改动

  1. 移除 authFlow 中的主动认证刷新逻辑
  2. 保留认证状态检查(快速、非阻塞)
  3. 依赖GeminiClient的自动认证机制

测试验证

测试场景

  1. 正常启动

    • ✅ 验证CLI启动后输入框立即可用
    • ✅ 验证不会出现 "Authenticating..." 提示
  2. 认证过期场景

    • ✅ 启动时检测到认证过期,自动打开认证对话框
    • ✅ 用户重新登录后可正常使用
  3. 首次使用场景

    • ✅ 发送第一个消息时自动完成认证
    • ✅ 后续消息正常发送
  4. Token刷新场景

    • ✅ Token临近过期时自动刷新
    • ✅ 用户无感知

后续改进

  1. 预加载优化

    • 在用户开始输入时就预先刷新认证
    • 进一步减少首次消息的延迟
  2. 状态提示

    • 在状态栏显示认证状态(已登录用户名等)
    • 让用户更清楚当前状态
  3. 后台刷新

    • 定期在后台刷新token
    • 避免使用过程中token过期

注意事项

  1. 向后兼容:所有认证流程保持不变,只是延迟执行
  2. 错误处理:认证失败时依然会提示用户
  3. 性能提升:启动时间减少2-5秒

修改日期

2025-01-10

相关文档