Skip to content

修复 GitHub Copilot 认证与登录流程问题#1894

Open
Mason-mengze wants to merge 9 commits intofarion1231:mainfrom
Mason-mengze:fix/copilot-auth-headers-1777
Open

修复 GitHub Copilot 认证与登录流程问题#1894
Mason-mengze wants to merge 9 commits intofarion1231:mainfrom
Mason-mengze:fix/copilot-auth-headers-1777

Conversation

@Mason-mengze
Copy link
Copy Markdown
Contributor

@Mason-mengze Mason-mengze commented Apr 4, 2026

概要

这个 PR 主要围绕 GitHub Copilot 的认证链路做修复,解决 400 认证错误、不同 Copilot 账号类型兼容性,多账号兼容性、企业端点路由、会话标识刷新等问题。

主要改动

  • 修复 GitHub Copilot 400 认证错误,补齐 Copilot 请求所需的认证头与标识信息
  • 为每个账号生成独立的 Machine ID,并支持 1 小时内复用、超时后刷新 Session ID
  • 在应用启动恢复账号时校正过期的 Copilot Session ID,避免重启后继续使用陈旧会话
  • 增加 endpoint 缓存与清理逻辑,移除账号或清空认证时同步清理相关内存状态
  • 清空认证时终止后台 session 刷新任务,并保持内存状态优先清理的行为
  • 将设备码登录时的验证码复制改为异步处理,修复 macOS / Linux 下可能未正确复制的问题
  • 在 proxy hyper client 中补充 write_all 后的 flush,减少流式转发中的边界问题
  • 补充和更新 Copilot 认证、endpoint 缓存、session 恢复等相关测试

测试

  • env CARGO_TARGET_DIR=/tmp/cc-switch-target cargo test test_load_from_disk_refreshes_stale_session_id --manifest-path src-tauri/Cargo.toml

Copilot AI review requested due to automatic review settings April 4, 2026 20:19
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 聚焦修复 GitHub Copilot 的认证与登录链路,并补齐企业/动态 endpoint、会话标识刷新、以及设备码登录复制验证码等体验与兼容性问题,覆盖前端到 Tauri 后端代理转发的完整链路。

Changes:

  • 新增并完善 Copilot 请求所需的关键 headers、machine/session 标识注入,以及流式转发写入后的 flush。
  • 引入 Copilot 动态 API endpoint 获取与进程内缓存,并在清理账号/认证时同步清理相关内存状态与后台任务。
  • 设备码登录复制验证码改为优先走原生剪贴板(Tauri command),失败再回退 Web Clipboard,并补充相关 Rust 侧测试。

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/lib/clipboard.ts 新增跨平台复制封装:优先 Tauri invoke,失败回退 Web Clipboard。
src/components/providers/forms/hooks/useManagedAuth.ts 复制验证码逻辑改为使用 copyText
src/components/providers/forms/CopilotAuthSection.tsx Copilot 设备码复制逻辑改为使用 copyText
src-tauri/src/services/stream_check.rs stream check 支持 base_url override,并补齐 Copilot headers。
src-tauri/src/proxy/providers/gemini.rs ProviderAdapter trait 变更:auth headers 生成函数新增 request_body 参数。
src-tauri/src/proxy/providers/codex.rs 同上:适配新的 ProviderAdapter trait 签名。
src-tauri/src/proxy/providers/claude.rs Copilot 场景生成确定性 request id,补齐 Copilot headers,并注入 machine/session id。
src-tauri/src/proxy/providers/auth.rs AuthInfo 增加 machine_id/session_id 字段与构造函数。
src-tauri/src/proxy/providers/adapter.rs ProviderAdapter trait 更新:get_auth_headers 增加 request_body 参数。
src-tauri/src/proxy/providers/copilot_auth.rs 动态 endpoint 缓存、每账号 machine/session id、启动时修正过期 session id、后台刷新任务与清理逻辑、相关测试。
src-tauri/src/proxy/hyper_client.rs raw write 后补 flush,改善流式转发边界问题。
src-tauri/src/proxy/forwarder.rs Copilot 动态 endpoint 路由、auth headers 注入携带 machine/session id、去重新增 headers。
src-tauri/src/lib.rs 注册复制剪贴板 command;启动时初始化 CopilotAuthManager 后台任务。
src-tauri/src/commands/stream_check.rs stream check 解析 Copilot base_url override 并传入服务层。
src-tauri/src/commands/misc.rs 新增 copy_text_to_clipboard Tauri command(spawn_blocking + arboard)。
src-tauri/Cargo.toml 新增 arboard/mac_address/rand 依赖。
src-tauri/Cargo.lock 锁文件更新以包含新增依赖。

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +396 to +397
.header("x-request-id", &request_id)
.header("x-agent-task-id", &request_id);
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reqwest::RequestBuilder::header 通常不接受 &String 作为 value(需要 &str / String / HeaderValue 等)。这里传 &request_id 很可能导致编译失败;建议改为 request_id.as_str() 或直接传 request_id.clone()x-agent-task-id 同理。

Suggested change
.header("x-request-id", &request_id)
.header("x-agent-task-id", &request_id);
.header("x-request-id", request_id.as_str())
.header("x-agent-task-id", request_id.as_str());

Copilot uses AI. Check for mistakes.
Comment on lines +947 to +950
// 用锁串行化同一账号的并发拉取,避免对 GitHub API 的重复请求
let lock = self.get_endpoint_lock(account_id).await;
let _guard = lock.lock().await;

Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_api_endpoint 在确认账号是否存在之前就调用 get_endpoint_lock(account_id),当 provider 配置里出现不存在/陈旧的 account_id 时,会为每个不同的 id 永久插入一把锁到 endpoint_locks,造成内存状态无上限增长。建议在加锁前先检查 accounts 是否包含该 account_id(不存在直接返回默认 endpoint),或在 fetch_and_cache_endpoint 返回 AccountNotFound 时清理对应 lock。

Copilot uses AI. Check for mistakes.
uuid = { version = "1.11", features = ["v4"] }
sha2 = "0.10"
mac_address = "1.1"
rand = "0.8"
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

新增了 rand 依赖,但当前仓库内未找到 rand:: 的引用(PR 中的 jitter 也已改用 SystemTime 生成)。如果没有其它未展示的用途,建议移除该依赖,避免增加构建体积和依赖面。

Suggested change
rand = "0.8"

Copilot uses AI. Check for mistakes.
Comment on lines +903 to +906
"[Copilot] 成功获取 Copilot token (account={}, machine_id={}, session_id={})",
account_id.as_deref().unwrap_or("default"),
machine_id.as_ref().map(|s| &s[..16]).unwrap_or("none"),
session_id.as_ref().map(|s| &s[..16]).unwrap_or("none"),
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

日志里输出 machine_id/session_id(即使截断到 16 位)仍是稳定标识符,可能在 debug 日志收集/上传时造成隐私泄露风险。建议改为仅记录是否存在(例如 has_machine_id/has_session_id),或进一步做不可逆脱敏(例如固定长度的 hash 前缀)并确保默认日志级别不会包含这些字段。

Suggested change
"[Copilot] 成功获取 Copilot token (account={}, machine_id={}, session_id={})",
account_id.as_deref().unwrap_or("default"),
machine_id.as_ref().map(|s| &s[..16]).unwrap_or("none"),
session_id.as_ref().map(|s| &s[..16]).unwrap_or("none"),
"[Copilot] 成功获取 Copilot token (account={}, has_machine_id={}, has_session_id={})",
account_id.as_deref().unwrap_or("default"),
machine_id.is_some(),
session_id.is_some(),

Copilot uses AI. Check for mistakes.
Comment on lines +794 to +798
log::debug!(
"[Copilot] 使用动态 API endpoint: {} (原: {})",
dynamic_endpoint,
base_url
);
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里 log::debug! 会直接输出动态 endpoint 和原 base_url;对于企业版 Copilot,endpoint 可能是内部域名,debug 日志被收集时仍可能造成信息泄露。建议仅记录“已启用动态 endpoint”并避免打印完整 URL(或只保留 host 的部分/做脱敏)。

Suggested change
log::debug!(
"[Copilot] 使用动态 API endpoint: {} (原: {})",
dynamic_endpoint,
base_url
);
log::debug!("[Copilot] 已启用动态 API endpoint");

Copilot uses AI. Check for mistakes.
Comment on lines +666 to +670
log::info!(
"[CopilotAuth] 账号 {} 超过 1 小时后重新登录,生成新 Machine ID: {}",
account_id,
&new_machine_id[..16]
);
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里用 info 级别打印了 machine_id 的前 16 位;machine_id 属于稳定设备/账号指纹,哪怕截断也可能被用于关联用户行为。建议避免在 info 日志中输出该类标识符(降到 debug 并默认关闭,或仅打印是否已生成)。

Copilot uses AI. Check for mistakes.
@Mason-mengze
Copy link
Copy Markdown
Contributor Author

Mason-mengze commented Apr 4, 2026

这次才真正修复异常消耗问题,排查了路由转发过程中对话ID和请求头字段没处理好导致的

Mason-mengze and others added 7 commits April 5, 2026 16:46
问题:使用 GitHub Copilot provider 时报错 400 bad request

根因:与 copilot-api 项目对比发现多处差异

修复内容:
- 更新版本号 0.26.7 到 0.38.2
- 更新 API 版本 2025-04-01 到 2025-10-01
- 添加缺失的关键 headers
- 修正 openai-intent 值
- 添加动态 API endpoint 支持
- 同步更新 stream_check.rs headers

Closes farion1231#1777

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
│                                                                                                                      │
│ - Fix clipboard blocking by using spawn_blocking for arboard ops                                                     │
│ - Implement dynamic endpoint routing for enterprise Copilot users                                                    │
│ - Add api_endpoints cache cleanup in remove_account() and clear_auth()                                               │
│ - Change API endpoint log level from info to debug                                                                   │
│ - Fix clear_auth() to continue cleanup even if file deletion fails                                                   │
│ - Add 9 unit tests for Copilot detection and api_endpoints cachin
  - Machine ID 生成逻辑改为每账号独立(基于 MAC
  地址+账号ID),不同账号不同机器码,避免账号间关联
  - 同一账号 1 小时内多次登录复用旧的 Machine ID,超过 1 小时则重新生成覆盖
  - Session ID 每账号独立且定期自动刷新
  - x-request-id 按
  session_id+machine_id+最后用户消息内容确定性生成(避免会话消耗过快)
  - Codex/Gemini/Claude 各 provider 和 forwarder.rs 适配新接口
  - 数据迁移逻辑完善,旧账号首次使用时自动生成缺失machine_id字段
  - Machine ID 生成逻辑改为每账号独立(基于 MAC
  地址+账号ID),不同账号不同机器码,避免账号间关联
  - 同一账号 1 小时内多次登录复用旧的 Machine ID,超过 1 小时则重新生成覆盖
  - Session ID 每账号独立且定期自动刷新
  - x-request-id 按
  session_id+machine_id+最后用户消息内容确定性生成(避免会话消耗过快)
  - Codex/Gemini/Claude 各 provider 和 forwarder.rs 适配新接口
  - 数据迁移逻辑完善,旧账号首次使用时自动生成缺失machine_id字段
@Mason-mengze Mason-mengze force-pushed the fix/copilot-auth-headers-1777 branch from cbe1c59 to 85d25fb Compare April 5, 2026 08:59
@farion1231
Copy link
Copy Markdown
Owner

很抱歉让你等了这么久。这个项目目前只有我一个人在维护,之前有段时间确实没能及时跟进。这是我的错。你的贡献对项目很重要,我会安排 review。如果需要 rebase 到最新代码,告诉我或者我直接来处理都可以。感谢你的付出和耐心。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants