feat(openai-reauth): 新增 OpenAI OAuth 重新授权独立流程#295
Open
ranger1112 wants to merge 22 commits into
Open
Conversation
- flows/openai-reauth/: 独立 flow definition + workflow + mail-rules - background/oauth-client.js: PKCE 生成 + URL 构造 + Token 交换 (fetchImpl 注入) - background/cookie-cleanup.js: 清 OpenAI/ChatGPT cookies (复用 step1 模式) - background/steps/: 4 个 step executor (prepare → submit-email → fetch-code → capture-callback) - 注册到 flows/index.js + manifest.json + background.js (importScripts/mailRuleRegistry/stepExecutorsByKey) - 复用 oauth-login content handler、pollFlowVerificationCode、FILL_CODE - 测试: oauth-client (14) / mail-rules (10) / cookie-cleanup (6) / capture-callback (8) = 38 个新测试 - 全量回归 1307/1307 通过 注: sidepanel UI 留待下一期 (需要 message-router 与 sidepanel 主 UI 配合升级)
- .omc/: oh-my-claudecode 状态目录 - /tmp/: 本地实验脚本与含真实 token 的账号 JSON 临时存放区,不入库
- flows/openai-reauth/index.js: settingsGroups 加 reauth-input + baseGroups 追加 - flows/openai-reauth/reauth-account-validator.js: 独立校验函数模块(新建,可单测) - sidepanel/sidepanel.html: 新增 row-reauth-account-json 和 row-reauth-result(含 textarea/pre/复制按钮) - sidepanel/sidepanel.css: textarea / readonly pre 样式 - sidepanel/sidepanel.js: DOM 常量、ensurePendingReauthAccount、renderReauthResultAccount、step 按钮 payload 注入、复制按钮绑定 - background/message-router.js: EXECUTE_NODE case 内提取 reauthInputAccount 写入 state - tests/openai-reauth-oauth-client.test.js: 用 node:crypto webcrypto 替代 globalThis.crypto,修复 Node 18 sandbox - tests/openai-reauth-validate-account-json.test.js: 13 个校验函数边界测试(新建) reauth 测试 50/50 通过;全量回归 1316/1320,4 个失败是 master 原本的 kiro Node 18 sandbox 问题,与 P2 无关
1. row 的 hidden 属性会被 [hidden] !important CSS 锁死,改用 inline style=display:none - applyFlowSettingsGroupVisibility 用 style.display 切换,无法盖过 [hidden] !important 2. NODE_STATUS_CHANGED handler 完成时没刷新 reauthResultAccount - step 4 跑完后 sidepanel 不会渲染新 JSON 到结果区 review 后端到端集成验证全通,reauth 50/50 测试全绿
- reauth-account-validator.js: 重写为 parseAccountsFromJson + buildResolvedAccount 支持单账号 / accounts 数组 / sub2api 整文件三种输入形态 不再要求 JSON 含 mailProvider 字段(改由 UI 注入) - sidepanel.html: 加邮箱来源下拉(7 个 provider)+ 多账号下拉选择器 - sidepanel.js: 改 ensurePendingReauthAccount 为多账号选择 + provider 注入 account 选择器仅在 accounts.length > 1 时显示 - tests: 重写 15 个用例覆盖整文件 / 单账号 / 多账号 / 边界 reauth 测试 52/52 通过
复盘:截图显示 sidepanel 已识别账号但 step 1 仍报"缺少待重新授权的账号 JSON" 根因:用户点的是"自动"按钮走 AUTO_RUN 消息,本仙女只在 step 按钮 (EXECUTE_NODE) 路径上注入了 reauthInputAccount 修复: - sidepanel.js: AUTO_RUN 启动前若 activeFlowId === 'openai-reauth' 调 ensurePendingReauthAccount() 解析当前选中账号 + provider 注入 payload 校验失败时恢复按钮状态并中止 - background/message-router.js: AUTO_RUN case 内提取 reauthInputAccount 写入 session state(与 EXECUTE_NODE case 同步行为)
师兄反馈三件事:
1. JSON 输入改为文件选择器(后续批量也是导入文件)
2. 不需要邮箱服务区(reauth 自己有邮箱来源下拉,凭证仍在 OpenAI flow 配)
3. 不需要来源选择器和账户密码 row
实现:
- flows/openai-reauth/index.js: services 改 [] 不再自动加 service-account/email
- sidepanel.html: textarea 替换为 input[type=file] + 校验按钮删除(选文件即触发)
- sidepanel.js:
* inputReauthAccountFile change handler: FileReader 读 → 缓存 lastReauthFileText → 解析
* lastReauthFileText 缓存供 step 按钮 / AUTO_RUN 复用
* applyOpenAiReauthRowVisibility: 切到 reauth 时隐藏 row-source-selector 和 row-custom-password
(用 dataset.reauthHidden 标记,切回其他 flow 时恢复)
reauth 测试 52/52 通过
- 复用注册流程 step9 的多策略点击编排(content / debugger)+ 多轮重试 + 刷新降级 - capture-reauth-callback 新增 drivePrimaryContinueClick 并行任务,与 localhost 回调监听并行运行 - 守护 consentClickEnabled:依赖未注入时优雅降级为原"干等回调"行为 - background.js 装配处注入 16 个 deps(10 函数 + 4 常量 + 2 工具),全部复用 step9 已有实现 - 修复 codex_cli_simplified_flow=true 并不会让 OAuth 跳过同意页的假设破产 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- REAUTH_HIDDEN_ROW_IDS 扩展隐藏 row-mail-provider / row-email-generator / row-auto-run-controls - 新增 syncReauthMailProviderToGlobal:reauth 邮箱来源选择同步到全局 mailProvider,复用 provider 配置卡片可见性 - 拆分 persist 参数:用户主动 change 时 persist=true 写 storage,UI 刷新调用时 persist=false 仅同步显示 - 修复 applyOpenAiReauthRowVisibility → syncReauthMailProviderToGlobal → saveSettings → STATE_CHANGED 广播回环导致的 SAVE_SETTING 死循环刷屏 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- fetch-reauth-code 包装 pollFlowVerificationCode 为 4 轮 poll+resend 循环(最多 3 次主动重发) - 失败后通过 sendToContentScriptResilient 复用 openai-auth 的 RESEND_VERIFICATION_CODE handler - 2925 单轮 poll attempts 从默认 15 缩到 6(90s),让 resend 在 ~1.5 分钟即可介入 - 错误处理:stop 信号秒抛、resend 失败不中断主轮询、用完所有轮 throw 最终 error - background.js 注入 sleepWithStop 让 cooldown 等待可被 stop 中断 - 新增 tests/openai-reauth-fetch-code.test.js 11 个用例,覆盖 skip/首轮成功/二轮 resend/全失败/stop/payload overrides/FILL_CODE 错误 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 新建 flows/openai-reauth/background/batch-runner.js,按队列依次跑每个账号 step1→step4 - 单账号失败默认自动跳过(skipOnFailure=true),累计到 failed 数组不中断 - 维护 reauthBatchRunning / reauthBatchProgress / reauthBatchResult 三个 state 字段 - mergeBatchResultsIntoFile 支持 sub2api 整文件 / accounts 数组 / 顶层数组 / 单账号 4 种 schema - 失败账号保留原 entry,成功账号 merge 新 token 字段(保留 priority / concurrency 等 metadata) - background.js 加载 batch-runner.js,通过 getReauthBatchRunner getter 解决与 messageRouter 的依赖时序 - message-router 新增 START_REAUTH_BATCH case,fire-and-forget 后台执行,进度通过 setState 广播 - flows/openai-reauth/index.js settingsGroups.reauth-input.rowIds 增加 row-reauth-batch-progress - manifest.json 新增 downloads 权限,为 sidepanel 一键下载整文件 JSON 做准备 - STOP 复用现有 STOP_FLOW + throwIfStopped 路径,batch-runner 内部 stop 信号秒抛 + 写 aborted=true Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- sidepanel.html 加批量模式 toggle(>=2 账号时可见),开启后隐藏单账号下拉 - 新增 row-reauth-batch-progress 行,实时显示「[当前/总数] 邮箱 状态」与 summary - 加「开始批量授权」「停止」「下载文件」三个按钮,按批量模式动态显示 - sidepanel.js 新增 applyReauthBatchUiVisibility / applyReauthBatchProgress / applyReauthBatchResult - buildReauthBatchAccounts 把 pendingReauthAccounts 注入 mailProvider 后构造 batch 队列 - handleReauthBatchStart 发送 START_REAUTH_BATCH 消息(fire-and-forget) - handleReauthBatchStop 复用 STOP_FLOW 消息 - handleReauthBatchDownload 优先用 chrome.downloads.download 弹保存对话框,失败 fallback 到剪贴板 - 文件名格式:sub2api-reauth-YYYYMMDD-HHmmss.json - GET_STATE / NODE_STATUS_CHANGED 路径都调用 applyReauthBatchProgress / Result,保持 UI 与 storage 同步 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…nelModeUI 测试 - tests/openai-reauth-batch-runner.test.js 覆盖 extractAccountEmail / mergeBatchResultsIntoFile 纯函数 - 覆盖 executeReauthBatch 主流程:顺序 3 账号全成功 / 中间失败 skip 继续 / skipOnFailure=false 中断 - 覆盖 stop 信号立即终止并写 aborted=true & stopReason=user_stop - 覆盖 progress currentStatus 流转、runSingleAccount 注入 mailProvider、每账号 reset state - 覆盖 interAccountDelayMs > 0 时账号间 sleep(最后一个不 sleep) - 修复 sidepanel-flow-source-registry.test.js 在 sandbox 中漏 mock applyOpenAiReauthRowVisibility - 同步 assert 链增加 reauth-visibility 调用顺序检查 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 拆分 reauth-input 节点 rowIds,引入 mode-picker / provider-picker / batch-actions 三个新行 - 重组 reauth UI 容器:账号文件 / 处理模式 / 邮箱来源 / 批量操作 / 进度 / 结果分区 - 新增 reauth 专属样式:status-chip / mode-zone / progress-bar / result-summary Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- background.setState 写入 chrome.storage.session 后广播 STATE_PATCH,让 sidepanel 即时同步增量 - sidepanel onMessage 新增 STATE_PATCH 处理,按字段 dispatch 到 applyReauthBatchProgress / applyReauthBatchResult - 修复 batch 完成时下载按钮卡 disabled / summary 卡「等待…」/ 进度 badge 卡「处理中」的 race condition - 移除 reauth 流程 UI 残留 emoji(✅ ❌ ⚠) - 同步重组后的 reauth DOM 引用与批量模式/邮箱来源/批量操作 handler Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- S1: MAIL_PROVIDER_OPTIONS 双端单一数据源,sidepanel 动态渲染 - S2: fetch-reauth-code totalRounds 计算逻辑注释 - S3: openai-reauth 版本公告草稿 - S5: .gitattributes 强制 LF 行尾
…H 日志 / consentClick 日志 / CLIENT_ID 可注入 - batch-runner 改用 validator 统一 extractAccountEmail,保留 fallback - STATE_PATCH 广播 catch 区分「无接收方」与真实错误 - capture-reauth-callback 在 deps 校验处输出 consentClick 能力日志 - oauth-client 的 buildAuthorizeUrl / exchangeAuthorizationCode / buildUpdatedAccount 接受可选 clientId 参数
检测调用从 waitForStep8Ready(30s超时) 之后移到之前,新增 tab 激活后立即预检。
- 接入批量授权账号邮箱提取的依赖注入,避免运行器隐式依赖全局校验器 - 修复批量终止状态写入、构造期日志、下载链接释放和状态样式清理的边界问题 - 补齐批量运行器与回调捕获执行器的防回归测试覆盖
- 识别 OAuth 重新授权后的手机验证页与手机号补充页 - 将手机验证要求转换为账号级 fatal 错误,批量流程可跳过当前账号继续执行 - 补充步骤 4 手机验证场景测试,覆盖监听器清理与不误完成节点
- 在步骤4监听回调前后增加认证页即时预检 - 通过标签页快照、登录状态消息和页面文本识别手机验证阻断 - 补充启动预检测试,确保不会等待 OAuth ready 超时才跳过账号
- 为 reauth 批量结果生成仅成功账号 JSON,保留原始文件结构与 metadata - 在授权结果区新增“只下载成功账号 JSON”按钮,并复用完整 JSON 下载按钮的主状态闸门 - 收紧复制与下载按钮的无结果态,避免流程未开始时复制或下载占位内容 - 补充批量结果合并与 sidepanel 按钮状态测试 Constraint: 仅提交本次 reauth 成功账号导出与按钮状态相关文件 Rejected: 为每个结果按钮维护独立状态机 | 容易与完整 JSON 下载按钮状态漂移 Confidence: high Scope-risk: narrow Directive: 后续新增 reauth 结果按钮应复用 syncReauthResultActionButtons 的状态闸门 Tested: node --check sidepanel/sidepanel.js; node --test tests/sidepanel-reauth-success-download.test.js tests/openai-reauth-batch-runner.test.js; npm test Not-tested: 未执行浏览器手动点击回归
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
关联 PR
Related: #292
此 PR 是 #292 的
dev分支重提版本,用于满足维护者要求:新 PR 需基于dev分支。变更说明
本 PR 新增 OpenAI 重新授权流程,并支持从账号 JSON 文件批量处理账号。
主要包含:
openai-reauthflow,支持 OAuth 重新授权链路验证
已本地执行:
npm test结果:
备注
本 PR 已基于原仓库 dev 分支重新整理,用于替代原先基于 master 的 #292。