Skip to content

feat(gemini_oauth): GLM Coding Plan 账号登录核心(z.ai/bigmodel OAuth)— MOC-252 Stage 1#499

Merged
Cmochance merged 8 commits into
mainfrom
worktree-moc-252
Jun 17, 2026
Merged

feat(gemini_oauth): GLM Coding Plan 账号登录核心(z.ai/bigmodel OAuth)— MOC-252 Stage 1#499
Cmochance merged 8 commits into
mainfrom
worktree-moc-252

Conversation

@Cmochance

Copy link
Copy Markdown
Owner

做了什么

MOC-252 Stage 1:为本项目新增 GLM Coding Plan 账号登录(OAuth,免 apikey)的纯 Rust 核心,镜像 gemini_oauth::antigravity provider。

新增 crates/gemini_oauth/src/zai/ 模块:

  • 两套账号体系:z.ai(国际)+ bigmodel(国内智谱)
  • loopback OAuth(动态端口)+ 两套 authorize 样式 + JSON 信封 token 交换
  • Coding Plan 换组织 API key(getCustomerInfo → api_keys → copy → <apiKey>.<secretKey>)
  • per-provider 凭证持久化(~/.codex-app-transfer/{zai,bigmodel}-oauth.json,atomic + 0600,Debug 脱敏 secret)

wire 借鉴 ZCode 3.1.0 解包源,逐项核对端点/参数/字段。

用户影响

当前无:Stage 1 是 dormant 核心,尚未接入 proxy(Stage 2 接 AuthScheme::ZaiOauth + forward.rs 注入 + presets;Stage 3 接 admin UI 登录入口)。不改任何用户可见 wire 行为,故本 PR 不动 README/provider matrix(留 Stage 2 接线时同步)。

测试

  • 29 个单测(authorize 两套样式、token 信封解析、换 key 链路、凭证 store + 0600、Debug 脱敏)全绿;full crate 89 lib 测试通过,zai 代码 clippy-clean。
  • 交互式真登录 e2e harness(#[ignore]):收敛前需用真账号跑一遍验证完整 run_zai_login(loopback → token 交换 → 换组织 key → 落盘)。push 前已过 3-agent 本地审查(code-reviewer 独立核对 wire 零事实错误;silent-failure / type-design 的 CRITICAL/IMPORTANT 已修)。

详细 wire spec 与分阶段方案见 Linear。

Refs MOC-252

MOC-252 Stage 1:纯 Rust OAuth 登录核心,镜像 antigravity provider,免 apikey。

- 新增 zai 模块:两套 provider 配置(z.ai 国际 / bigmodel 国内)+ loopback OAuth
  + JSON 信封 token 交换 + Coding Plan 换组织 API key + per-provider 凭证持久化
  (~/.codex-app-transfer/{zai,bigmodel}-oauth.json,atomic + 0600)
- wire 借鉴 ZCode 3.1.0 解包源,逐项核对端点/参数/字段
- 29 单测 + 交互式真登录 e2e harness(#[ignore],需浏览器授权驱动)

尚未接入 proxy(Stage 2 接 AuthScheme/forward.rs),当前为 dormant 代码,
不改任何用户可见 wire 行为;README/provider matrix 留 Stage 2 接线时同步。

Refs MOC-252
@Cmochance

Copy link
Copy Markdown
Owner Author

收敛前需你跑的真登录 e2e(两套账号)

Stage 1 是纯 Rust 核心,单测覆盖了转换逻辑,但换组织 key 的真实端点链路只有真登录能验(loopback 回跳 → token 交换 → getCustomerInfo/api_keys/copy → 落盘)。按 feedback_e2e_test_before_convergence,合并前请用真账号各跑一遍:

# z.ai(国际账号)
cargo test -p codex-app-transfer-gemini-oauth --test zai_login_e2e \
  e2e_login_zai -- --ignored --nocapture

# bigmodel(智谱国内账号)
cargo test -p codex-app-transfer-gemini-oauth --test zai_login_e2e \
  e2e_login_bigmodel -- --ignored --nocapture

跑起来后浏览器会弹出对应登录页(没弹出时终端会打印 URL 让你手动粘贴),登录授权完成即可。安全:凭证写到临时目录(不碰真实 ~/.codex-app-transfer/),终端只打打码的 key,完整值不外泄、不入库。

看到 ✅ 登录成功 + 非空 org_api_key + 落盘路径即通过;任一报错把终端输出贴回来我排查。两套都通过后这条 PR 才算收敛可合并。

也可等我这边在你的协助下驱动(你登录、我读结果),你定。

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 56ded12a9f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/gemini_oauth/src/zai/flow.rs Outdated
localhost 在部分系统先解析成 IPv6 ::1,而 OAuth 回调 listener 只绑 IPv4
127.0.0.1 → 回调 connection refused 卡到超时。改用 127.0.0.1(同栈 +
对齐 gemini parent flow + RFC 8252 推荐)。

Refs MOC-252
新增 examples/zai_login.rs:跑一次真实登录把凭证永久存进
~/.codex-app-transfer/{provider}-oauth.json(不像 e2e test 隔离到 tempdir)。
组织 key 长期有效,Stage 2 直接复用,故为「最后一次登录」。

Refs MOC-252

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 51fc35ff97

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/gemini_oauth/src/zai/constants.rs
浏览器 OAuth 授权(消耗登录的部分)一旦成功,立即把 token 落盘 pending
(<provider>-oauth-pending.json);之后换组织 key 失败,可用 resume_zai_login
不重走浏览器地重试(限 token 有效期内)。换 key 成功后删 pending。

- 新增 ZaiPendingTokens + ZaiPendingStore(Debug 脱敏,共用 atomic+0600 helper)
- run_zai_login 拆出 finalize_from_pending,run/resume 共用
- example 加 --resume 子命令
- +4 单测(pending roundtrip / 文件名隔离 / Debug 脱敏 / 0600)

Refs MOC-252
按 AGENTS.md「上游借鉴致谢」规则,zai 登录模块借鉴 ZCode 3.1.0 解包的登录 wire,
同 PR 补:① README/README.en 致谢概览各一行 ② ACKNOWLEDGEMENTS.md 完整 entry
(反向工程产物借鉴 + Wire-level 对齐,标注 loopback/0600 本地差异 + TOS 注意)。

Refs MOC-252

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1e668615be

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/gemini_oauth/src/zai/constants.rs
…e 实证)

真登录 e2e 抓到的 wire 错(源码核对+单测都漏掉):
- bigmodel 换组织 key 的 biz base 应是 https://bigmodel.cn(ZCode resolveBigModelApiOrigin
  production 值),此前误用 zcode.z.ai → getCustomerInfo 404
- bigmodel biz 面 Authorization 不带 Bearer(裸 token);z.ai 仍带 Bearer
  → 新增 ZaiProviderConfig.biz_auth_bearer per-provider 区分

两套账号真机登录均已验证落盘(z.ai 一次过;bigmodel 修复后用安全网 resume 续传、
无需重新走浏览器)。

Refs MOC-252
@Cmochance

Copy link
Copy Markdown
Owner Author

真机登录 e2e 通过(两套账号)

z.ai + bigmodel 真账号实跑 run_zai_login,均验证组织 key 落盘成功(0600,<apiKey>.<secretKey> 形态)。

真 e2e 抓到并修复一个 bigmodel wire 错(源码核对+单测都漏掉):换组织 key 的 biz base 应是 bigmodel.cn(此前误用 zcode.z.ai → 404),且 bigmodel biz Authorization 不带 Bearer(z.ai 带)。commit 2828cf6。安全网实战生效:bigmodel 修复后用 --resume 续传、未让用户重登。

详细 wire 分析见 Linear MOC-252。

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2828cf6c96

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/gemini_oauth/src/zai/mod.rs
bot P2:cancel 之前只覆盖 OAuth flow,返回后的换 key / 落盘不再检查取消 →
UI 抢占旧登录时,被取消的旧登录仍可能完成并覆盖 <provider>-oauth.json。

- clone cancel 句柄(watch::Receiver Clone),OAuth 返回后 + 换 key 落盘前各查一次
- 被取消 / 被抢占即返回 Cancelled,绝不写盘
- +2 单测(is_cancelled 语义 / wiremock 验落盘前中止)

Stage 1 当前 example 传 None 触发不到,此为 Stage 3 admin UI 抢占场景的语义修正。

Refs MOC-252
@Cmochance Cmochance merged commit 6cf7b11 into main Jun 17, 2026
5 checks passed
@Cmochance Cmochance deleted the worktree-moc-252 branch June 17, 2026 04:16
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.

1 participant