32 KiB
Plus 模式 SUB2API Session 接入策略开发方案
1. 文档定位
本文档只做完整开发设计,不修改功能代码。
本文档中的“开发阶段”仅表示实施顺序和每阶段自检顺序,不是产品分期,不表示“先做一半、后面再补”。
本方案的目标是把 OpenAI flow + Plus 模式 + SUB2API 的账号接入方式,从当前固定的 OAuth 尾链,扩展为一个正式的“账号接入策略”能力,并且一次性把相关联的 UI、步骤、后台状态、自动运行、测试、自检边界全部设计完整。
2. 分析基线
2.1 当前分析基线
codex注册扩展当前工作树分支名为feature/kiro-desktop-auth-rebuild,但它与本地dev指向同一提交4aa459e,本地dev比origin/dev还新 8 个提交,因此本次分析不需要先回退或切换到远端origin/devsub2api已在本次分析前同步到远端最新main,当前基线为1d78dde8GPTSession2CPAandSub2API已本地拉取,用于分析“session 导入类逻辑”的取精华方向,而不是复制其代码
2.2 已完整阅读的关联代码范围
主仓库 codex注册扩展 已重点阅读:
data/step-definitions.jsshared/flow-capabilities.jsshared/flow-registry.jsshared/settings-schema.jssidepanel/sidepanel.htmlsidepanel/sidepanel.jsbackground.jsbackground/runtime-state.jsbackground/message-router.jsbackground/panel-bridge.jsbackground/sub2api-api.jsbackground/steps/platform-verify.jsbackground/steps/create-plus-checkout.jsbackground/steps/fill-plus-checkout.jsbackground/steps/plus-return-confirm.jscontent/plus-checkout.jstests/step-definitions-module.test.jstests/sidepanel-plus-payment-method.test.jstests/flow-capabilities-module.test.jstests/background-settings-schema-persistence.test.jstests/background-account-history-settings.test.jstests/background-message-router-module.test.jstests/background-message-router-plus-final-step.test.jstests/background-auth-chain-guard.test.jstests/auto-run-step6-restart.test.js
接入端 sub2api 已重点阅读:
backend/internal/server/routes/admin.gobackend/internal/handler/admin/account_codex_import.gofrontend/src/api/admin/accounts.ts
参考项目 GPTSession2CPAandSub2API 已重点阅读:
README.md
3. 需求校准与硬边界
本方案按以下真实需求设计,不能偏离:
- 这不是新增一个独立 flow,而是 OpenAI flow 的 Plus 模式下,替换账号接入尾链策略
- Plus 流程不是固定步骤号流程,必须按动态步骤定义设计,不能写死“第几步一定是什么”
- Plus 模式不能走手机号注册,本方案只围绕 Plus + 邮箱注册 + sub2api 设计,不再扩展任何手机号分支
- 新功能名按你的要求设计成 Plus 模式下的“账号接入策略”
- 当前只允许
sub2api真正切换到 session 导入策略;cpa / codex2api在 Plus 下仍固定走 OAuth,UI 上直接禁用策略切换 - 这里说的“使用拉下来的项目逻辑”,是借用其 session 导入思路和行为结论,不是把外部项目代码复制进来
- 必须走
sub2api自己的账号导入逻辑,即调用其原生import/codex-session,而不是扩展自己再手写一套 token 转换器 - 方案必须把和本功能无关、但逻辑有关联的地方一并覆盖,例如:
- 动态步骤切换
- 设置持久化与导入导出
- 自动运行重开
- 最终成功节点判定
- 固定 OAuth 文案
- runtime 清理
- 测试基线
4. 当前真实实现现状
4.1 Plus 步骤是动态生成的,不是固定步号
data/step-definitions.js 当前会根据以下条件动态生成 OpenAI 步骤集合:
plusModeEnabledplusPaymentMethodsignupMethodphoneSignupReloginAfterBindEmailEnabled
当前 Plus 邮箱链路的尾部不是单个“平台验证”,而是一段完整 OAuth 尾链:
oauth-loginfetch-login-codepost-login-phone-verificationconfirm-oauthplatform-verify
不同 Plus 支付方式的接入锚点也不同:
- PayPal:接在
plus-checkout-return后 - GoPay:接在
gopay-subscription-confirm后 - GPC:接在
plus-checkout-billing后
因此本次改造不能说“替换第 10 步”,必须说:
- 替换 Plus 动态步骤集合中的 OAuth 尾链插槽
4.2 Plus 模式当前不允许手机号注册
现有能力注册表和侧栏逻辑已经明确限制:
- Plus 开启时,手机号注册不可选
- 如果当前选中手机号,再开 Plus,会被切回邮箱注册
所以本方案不再设计任何:
- Plus 手机号注册
- Plus 手机绑定后再改邮箱
- Plus 手机验证码尾链兼容
4.3 当前 SUB2API 主链路是 OAuth,不是 session 导入
当前 SUB2API Plus 尾链的真实做法是:
- 通过
background/panel-bridge.js请求background/sub2api-api.js生成 OAuth URL - 保存
oauthUrl / sub2apiSessionId / sub2apiOAuthState - 页面完成 OAuth 回调,拿到
localhostUrl background/steps/platform-verify.js调submitOpenAiCallback- SUB2API 用
exchange-code交换 OAuth code,再创建账号
这条链路是“完整 OAuth 账号创建”,不是导入现有 ChatGPT Web session。
4.4 扩展本身已经具备读取 ChatGPT session 的能力
当前项目并不是没有 session 能力,已有代码已经能在 ChatGPT 页面读取:
/api/auth/sessionsessionaccessToken
现成能力位置:
content/plus-checkout.jsbackground/steps/create-plus-checkout.js
这意味着新功能不需要再发明“如何拿 session”,只需要把这份能力接到 Plus 尾链上。
4.5 SUB2API 已原生支持 codex session 导入
sub2api 当前已原生提供:
- 路由:
POST /api/v1/admin/accounts/import/codex-session - 前端 API:
importCodexSession
其导入逻辑当前已支持:
- 直接导入 raw
accessToken - 导入完整 session JSON
- 导入 JSON 数组
- 导入多行混合内容
- 自动从 JWT claims 补
email / account_id / plan_type - 忽略
sessionToken - 没有
refresh_token时,按 access token 过期时间处理,并开启过期自动暂停 - 默认
update_existing = true,同身份账号会走“更新已有账号”语义,而不是强制重复创建
这说明本次扩展应该做的是:
- 读取当前 ChatGPT Web session
- 直接调用
sub2api原生导入接口
而不是:
- 在扩展里复制外部项目的 JSON 转换代码
- 在扩展里伪造一套 OAuth 账号结构
4.6 外部参考项目给出的结论必须正视
GPTSession2CPAandSub2API 的核心结论很明确:
- ChatGPT Web session 通常没有真实
refresh_token - 这类导入数据主要依赖
access_token access_token过期后不能自动刷新
所以本方案必须明确接受一个事实:
- Plus 下走 session 导入策略时,导入到 SUB2API 的将是“当前 Web session 账号”,不是“可长期自动刷新的 OAuth 完整账号”
这不是缺陷描述,而是该策略的真实工作方式,必须在设计里被明确建模,而不是模糊带过。
5. 最终设计
5.1 功能命名与策略枚举
新功能统一命名为:
Plus 模式 -> 账号接入策略
新增设置字段建议命名为:
plusAccountAccessStrategy
枚举值建议固定为:
oauthsub2api_codex_session
命名原则:
oauth保持通用sub2api_codex_session明确说明这是 SUB2API + Codex Session 导入- 不用泛化的
session或import,避免以后 CPA/Codex2API 也有 session 方案时语义冲突
默认值:
oauth
5.2 请求值与生效值分离
这里不能简单把 plusAccountAccessStrategy 当成“永远立即生效值”,而应沿用现有 signupMethod 的思路,区分:
- 用户请求值:持久化保存在设置中的选择
- 当前生效值:根据 flow、target、plus 开关、注册方式实时归一化后的结果
最终规则:
- 持久化字段只保存用户偏好值
- 当
activeFlowId !== openai时,生效值强制为oauth - 当
plusModeEnabled !== true时,生效值强制为oauth - 当
panelMode !== sub2api时,生效值强制为oauth - 当
signupMethod !== email时,生效值强制为oauth - 只有同时满足:
openaiplusModeEnabled = truepanelMode = sub2apisignupMethod = email时,才允许sub2api_codex_session真正生效
这样设计的好处是:
- 切到
cpa / codex2api时,不会把用户原来的 sub2api strategy 偏好永久覆盖掉 - 切回
sub2api时,可以恢复原来的选择 - 运行时又不会真的拿着 session strategy 去跑不支持的目标
5.3 侧栏 UI 设计
5.3.1 位置
新 UI 放在 Plus 设置组内,紧跟在:
Plus 模式Plus 支付
之后。
新增行建议:
row-plus-account-access-strategyselect-plus-account-access-strategyplus-account-access-strategy-caption
shared/flow-registry.js 的 openai-plus 设置组应扩展为同时包含:
row-plus-moderow-plus-payment-methodrow-plus-account-access-strategy
5.3.2 展示与禁用规则
展示规则:
- 只有
supportsPlusMode = true时显示整组 Plus 控件 plusModeEnabled = false时隐藏“支付方式”和“账号接入策略”两行plusModeEnabled = true且panelMode = sub2api时,策略选择器启用plusModeEnabled = true且panelMode = cpa / codex2api时,策略选择器显示但禁用,视觉值固定显示oauth
文案建议:
- 标签:
账号接入策略 - 选项 1:
OAuth - 选项 2:
导入当前 ChatGPT 会话到 SUB2API
禁用态说明建议:
当前来源仅支持 OAuth
sub2api 可用态说明建议:
复用当前 Plus 已登录会话,直接导入到 SUB2API,不再走 OAuth 回调
5.3.3 不允许继续保留的 UI 文案问题
当前代码里有多处 Plus 相关文案写死了“第 10 步 OAuth 登录”或“继续 OAuth 登录”,这些在新策略下都会变错。
本次必须统一改为:
- 通过当前动态尾链的下一节点标题
- 或当前账号接入策略标签
生成文案,不能继续写死:
第 10 步OAuth 登录
尤其要覆盖:
- Plus 手动确认弹窗
- GoPay/GPC 支付完成后的 toast
- Plus 模式切换日志
5.4 步骤与节点设计
5.4.1 不新增独立 flow,只替换 Plus 尾链
本方案不创建新 flow,不额外创建“Plus-Session flow”。
最终做法是:
- 在
data/step-definitions.js中,为 Plus 动态步骤集合增加plusAccountAccessStrategy维度 - 当策略为
oauth时,保留现有 OAuth 尾链 - 当策略为
sub2api_codex_session时,用新的 session 导入尾节点替换整段 OAuth 尾链
5.4.2 新尾节点设计
建议新增单节点:
sub2api-session-import
标题建议:
导入当前 ChatGPT 会话到 SUB2API
这里刻意设计成单节点,而不是再拆成“读取 session”“上传 session”两个节点,原因是:
- 当前 session 获取能力已经是内聚能力,不值得再拆成一个对外步骤
- 该尾链不再需要 OAuth 多步状态机
- 节点越多,自动运行重试、成功判定、模式切换、node status 重建越复杂
- 单节点更符合“支付完成后直接接入账号”的实际语义
5.4.3 替换锚点
Session 导入策略生效时,替换锚点如下:
- PayPal:
plus-checkout-return后接sub2api-session-import - GoPay:
gopay-subscription-confirm后接sub2api-session-import - GPC:
plus-checkout-billing后接sub2api-session-import
因此这次不是“替换 platform-verify”,而是:
- 按支付链路不同,替换整段 OAuth 尾链接入口
5.4.4 Plus 下不再保留任何手机号 session 分支
即使代码层面未来仍存在 phone 相关动态定义,这次策略分支也必须硬性限制为:
- 只支持
signupMethod = email
如果后续状态异常导致 plusModeEnabled = true 且 signupMethod = phone 同时出现,也必须在步骤解析时回退到:
oauth
不能让 session strategy 意外落到 phone 分支。
5.5 新节点执行逻辑
建议新增后台执行器文件:
background/steps/sub2api-session-import.js
执行器职责:
- 定位当前 Plus 会话页对应 tab
- 确认当前 tab 已回到 ChatGPT / OpenAI 域名页面,且可访问
/api/auth/session - 通过现有
content/plus-checkout.js能力读取:sessionaccessToken
- 用现有
background/sub2api-api.js登录 SUB2API - 解析当前配置的:
- 分组
- 默认代理
- 优先级
- 调用 SUB2API 的
import/codex-session - 解析返回的 created/updated 结果
- 用
completeNodeFromBackground('sub2api-session-import', payload)收尾
5.5.1 Tab 选择原则
该节点不应新开 tab,而应复用当前 Plus 付款结束后已经存在的 tab。
候选顺序建议:
plusCheckoutTabIdplus-return-confirm已解析到的返回 tab- 当前
plus-checkoutsource 绑定 tab
如果拿到的页面不在:
chatgpt.comchat.openai.comopenai.com
则直接失败,不进入导入。
5.5.2 Session 组装原则
扩展不要自己做外部项目那种“多平台 JSON 转换器”。
扩展只做最小组装:
- 优先传完整
sessionJSON - 若
session.accessToken为空,但独立读到了accessToken,则把accessToken补回 session payload 再提交 - 不伪造
refresh_token - 不把
sessionToken当作refresh_token - 不生成占位
refresh_token - 不构造伪 OAuth 交换结果
5.5.3 SUB2API 请求体设计
建议调用 import/codex-session 时传:
content: 完整 session JSON 字符串group_ids: 由现有 group name 配置解析出的 group id 数组proxy_id: 由现有默认代理解析出的 proxy idpriority: 复用当前sub2apiAccountPriorityauto_pause_on_expired:true
可以不新增任何新配置字段。
关于导入语义,本方案明确采用:
- 沿用 sub2api 原生导入逻辑
也就是:
- 不强制改成“永远创建新账号”
- 接受
update_existing默认值为true
这意味着:
- 同身份账号重复跑流程时,SUB2API 更可能更新已有账号,而不是无限重复创建
这属于该策略的既定行为,不再在扩展里另造一套“重复创建模式”。
5.5.4 成功判定
单条 session 导入的成功判定建议统一为:
- HTTP 成功
failed = 0created > 0或updated > 0
日志层面建议区分:
created:新建成功updated:更新已有账号成功warnings:照常记日志,但不判失败
5.5.5 关于 access token 生命周期
这里必须作为功能设计的一部分明确下来:
sub2api_codex_session策略导入的是当前 Web session- 通常只有
access_token,没有真实refresh_token - 因此账号生命周期取决于当前 access token
- token 过期后,SUB2API 应按其原生逻辑自动暂停
扩展侧不做以下事情:
- 不假装它是完整 OAuth 账号
- 不伪造 refresh token 续期能力
- 不偷偷降级回 OAuth 交换
5.6 SUB2API API 层设计
新逻辑应当落在:
background/sub2api-api.js
而不是去复用旧的:
content/sub2api-panel.js
原因:
- 当前主链路已迁移到
background/sub2api-api.js - session 导入需要登录、查分组、查代理、发导入请求,这些都属于后台 API 编排
- 继续往
content/sub2api-panel.js塞逻辑会造成双实现
建议新增 API 方法:
importCodexSessionAccount- 或
importCurrentChatGptSession
该方法内部复用已有:
loginSub2ApigetGroupsByNamesresolveSub2ApiProxyresolveSub2ApiAccountPriority
不要重复造这几套解析逻辑。
同时需要明确职责边界:
background/panel-bridge.js继续只负责“跨 target 的 OAuth URL 申请桥接”- session 导入不要硬塞进
requestOAuthUrlFromPanel background/steps/platform-verify.js继续只处理 callback 型平台验证sub2api-session-import走独立后台执行器,不混进platform-verify
5.7 后台总控与运行态设计
5.7.1 OAuth 相关总控必须按策略显式分流
当前后台总控明显带有强 OAuth 假设:
refreshOAuthUrlBeforeStep6AUTH_CHAIN_NODE_IDS- OAuth 总超时窗口
- localhost callback 捕获与恢复
platform-verify失败后的 auth-chain 重开
这些逻辑在 session strategy 下都不能继续生效。
最终要求:
oauth策略时,保持现有行为sub2api_codex_session策略时:- 不刷新 OAuth URL
- 不进入 AUTH_CHAIN
- 不等待 localhost callback
- 不启动 OAuth 总超时
- 不走 confirm/platform-verify 的重开策略
5.7.2 新策略不属于 AUTH_CHAIN
sub2api-session-import 不能被加入:
AUTH_CHAIN_NODE_IDS
原因:
- 它不是 OAuth 过程
- 它没有 localhost callback
- 它的失败不应该触发“回到 oauth-login / confirm-oauth 重试”
其失败处理方式应为:
- 节点内部有限次网络重试
- 最终失败则停止当前流程,保留现场,不自动回退到支付或 OAuth 节点
这是必须明确的边界,否则会把“已支付成功的账号接入失败”错误地重开成“重新支付/重新授权类流程”。
5.7.3 runtime state 处理原则
这次不建议新增一套新的 session runtime 大字段组。
原因是:
- session 获取可以现读现用
- 分组、代理、优先级都来自现有设置
- 单节点完成,不需要跨多个中间节点传递临时状态
因此运行态设计应尽量简化为:
- 新增持久化设置字段
plusAccountAccessStrategy - 不新增 OAuth 等价的 session 中间态字段
- 切换到 session strategy 时,需要清理旧 OAuth 残留字段
- 切回 OAuth 时,也要让旧 session 节点状态失效并重建
nodeStatuses
必须清理或确保失效的旧字段包括:
oauthUrllocalhostUrlsub2apiSessionIdsub2apiOAuthState- 以及围绕 OAuth deadline 的状态
5.7.4 nodeStatuses 重建规则
当前 message-router 已在以下变更时重建节点状态:
plusModeEnabledplusPaymentMethodphoneSignupReloginAfterBindEmailEnabled
本次必须补上:
plusAccountAccessStrategy
因为它直接改变尾链拓扑。
否则会出现:
- 新步骤定义已经换成 session tail
- 旧的
oauth-login / confirm-oauth / platform-verify状态还残留在nodeStatuses
导致自动运行、最终成功判定、跳步恢复全部错位。
5.8 settings schema / 持久化 / 导入导出设计
5.8.1 settings-schema
shared/settings-schema.js 需要在:
flows.openai.plus
下新增:
plusAccountAccessStrategy
并同步到扁平导出字段:
next.plusAccountAccessStrategy
同时需要处理:
- 默认值
- 旧状态兼容
- 扁平导入
settingsState嵌套结构
5.8.2 background normalizePersistentSettingValue
background.js 当前有显式的持久化字段归一化开关,必须新增:
case 'plusAccountAccessStrategy'
非法值一律回退到:
oauth
5.8.3 历史记录与设置导出测试
当前已有针对以下方向的测试:
- settings 持久化
- account history 归一化
- flow settings schema 映射
因此本次不能只改 schema 而不补测试,否则很容易出现:
- UI 能选
- 但设置导出没带上
- 设置导入后丢失
- background state 恢复后策略回默认
5.9 flow capability 设计
5.9.1 不要把策略可用性写死在 UI
应扩展 shared/flow-capabilities.js,让它输出:
requestedPlusAccountAccessStrategyeffectivePlusAccountAccessStrategyavailablePlusAccountAccessStrategiescanEditPlusAccountAccessStrategy
目标能力建议定义为:
cpa: 只支持oauthsub2api: 支持oauth和sub2api_codex_sessioncodex2api: 只支持oauth
这样可以把:
- UI 可编辑性
- 实际步骤生效值
- 后台模式归一化
统一建立在同一套 capability 结论上,避免 sidepanel / background / step-definitions 三边各写一套 if 判断。
5.10 message-router 设计
本方案不建议为了 session import 再新增一套复杂 handleStepData(step, payload) 分支。
更合理的做法是:
sub2api-session-import作为后台节点,直接在执行器内完成 session 读取和 SUB2API 导入- 完成后直接
completeNodeFromBackground
这样 message-router 主要需要承担的是:
- 保存新设置字段
- 模式切换时重建 nodeStatuses
- 最终成功节点判定不能再隐式依赖
platform-verify - Plus 相关日志、提示语不能再硬编码 OAuth
5.10.1 最终成功节点判定
当前已有测试说明“Plus 最终成功记录不能写死某个固定 step”。
本次需要继续泛化为:
- 以当前动态步骤集合的最后一个节点为准
这样 session strategy 下最后一步可以自然变为:
sub2api-session-import
而不需要继续假设最后节点一定是:
platform-verify
5.11 自动运行与重试设计
5.11.1 OAuth 失败重开逻辑只保留给 OAuth
当前自动运行在 Plus 后半段有大量“回到 oauth-login / confirm-oauth 重开”的逻辑。
session strategy 下这些逻辑全部不适用。
必须改为:
- 仅当当前策略生效值为
oauth时,才进入原有 OAuth 重开路径
5.11.2 session import 节点的重试策略
sub2api-session-import 节点建议只做:
- 有限次的 API 级重试
可重试错误类型:
- SUB2API 登录瞬时失败
- 分组/代理查询瞬时失败
- 导入接口的短暂网络波动
不自动重试的错误类型:
- session 为空
- access token 不可解析或已过期
- 当前 tab 不在可读 session 的域名页面
- 分组不存在
- 配置缺失
- 后端明确业务错误
最终失败后直接停止,不自动回退到支付链路,也不自动跳回 OAuth 节点。
6. 方案自检结论
6.1 是否符合需求
符合,原因如下:
- 名称已按要求设计成“Plus 模式下的账号接入策略”
- 只对
sub2api真正开放 session 导入 cpa / codex2api保持 OAuth,UI 禁用- 明确采用
sub2api原生导入逻辑 - 没有再引入 Plus 手机号注册方案
- 没有再按固定步号设计
6.2 是否完整
完整,覆盖了:
- UI
- schema
- settings 持久化
- capability
- step definitions
- 节点执行器
- sub2api API 封装
- runtime 清理
- message-router
- auto-run
- 最终成功判定
- 文案修正
- 测试与验收
6.3 是否存在上下冲突
当前方案内部无冲突,关键原因:
- “请求策略”和“生效策略”分离,避免 target 切换时既要禁用又要保留用户偏好的矛盾
- session strategy 只在 Plus 邮箱链路下生效,避免与 phone 分支冲突
- session strategy 不加入 AUTH_CHAIN,避免与 OAuth 重开机制冲突
- 不新增独立 flow,只替换动态尾链,避免与现有 flow registry 冲突
6.4 是否存在逻辑遗漏
当前已主动补齐的高风险遗漏点有:
- Plus 手动确认弹窗的固定“第 10 步 OAuth 登录”文案
- 最终成功节点不能假设是
platform-verify nodeStatuses必须把plusAccountAccessStrategy纳入重建条件settings-schema的扁平导出与导入恢复normalizePersistentSettingValue的新字段归一化- 旧 OAuth runtime 字段切换时的清理
- session 导入并不具备 refresh_token 自动续期能力
6.5 是否存在规范不一致风险
有风险,但已在方案中明确规避路径:
- 代码库当前存在
background.js与模块文件并存的结构,修改时必须按仓库现有组织方式保持一致,不能只改其中一处 - Plus 文案当前在多个入口分散存在,新增策略后必须统一改成基于“当前尾链/当前策略”的动态文案
- 任何新增枚举值都必须同时同步:
- schema
- capability
- sidepanel
- background normalize
- tests
6.6 是否有乱码风险
有,需要明确纳入开发自检:
- 新增和改动文件统一使用 UTF-8
- 新增中文文案直接写 UTF-8,不要复制外部工具里的转码残留
- 更新测试断言时,不要引入乱码字符串快照
- Markdown 文档、HTML 文案、JS 字符串三处都要做肉眼检查
7. 开发清单
以下阶段仅表示实施顺序与每阶段自检顺序。
阶段 A:设置模型、能力注册、UI 入口
目标
让 Plus 模式先具备正式的“账号接入策略”配置入口,并且在 sub2api / cpa / codex2api 三种 target 下表现正确。
涉及文件
shared/settings-schema.jsshared/flow-capabilities.jsshared/flow-registry.jssidepanel/sidepanel.htmlsidepanel/sidepanel.jsbackground.js
完成标准
- 新增
plusAccountAccessStrategy - 默认值为
oauth - Plus 开启后显示策略行
sub2api下可编辑cpa / codex2api下显示但禁用,运行生效值固定为oauth- Plus 关闭时该行隐藏
- 所有相关文案不再写死“第 10 步 OAuth”
阶段自检
- 检查 schema 嵌套结构和扁平结构是否双向一致
- 检查导入导出设置后,新字段是否保留
- 检查 UI 显隐是否跟
plusModeEnabled和 target 联动,而不是只靠写死判断 - 检查 target 从
sub2api切到cpa/codex2api时,UI 是否禁用且展示值正确 - 检查从
cpa/codex2api切回sub2api时,用户原来的偏好是否能恢复 - 检查中文文案是否有乱码
阶段 B:动态步骤与节点拓扑切换
目标
让 Plus 模式在 session strategy 生效时,真正替换掉 OAuth 尾链,而不是只在 UI 上多一个选择框。
涉及文件
data/step-definitions.jssidepanel/sidepanel.jsbackground.js- 相关 step definitions / sidepanel 测试
完成标准
plusAccountAccessStrategy被纳入步骤定义选项- PayPal / GoPay / GPC 三条 Plus 前缀链路都能在正确锚点接入
sub2api-session-import - session strategy 下不再出现:
oauth-loginfetch-login-codepost-login-phone-verificationconfirm-oauthplatform-verify
- Plus 手机号链路不会意外生成 session tail
阶段自检
- 检查三种支付方式的尾链是否都正确替换
- 检查“步骤标题 / 最后一步 / 节点列表 / step ids”是否都随策略变化
- 检查切换策略后
nodeStatuses是否被重建 - 检查没有任何代码还在用固定 step number 判断 Plus 尾链
- 检查 session strategy 下的最后节点是否已经是
sub2api-session-import
阶段 C:SUB2API session 导入执行器与 API 封装
目标
真正接上“读取当前 ChatGPT 会话并导入到 SUB2API”的执行逻辑。
涉及文件
background/sub2api-api.jsbackground/steps/sub2api-session-import.jsbackground/steps/registry.js或后台节点注册处content/plus-checkout.jsbackground/steps/create-plus-checkout.js
完成标准
- 能从当前 Plus 会话页读出
session/accessToken - 能复用现有 SUB2API 登录、查分组、查代理逻辑
- 能调用
import/codex-session - 能正确处理
created / updated / warnings / failed - 成功后以
sub2api-session-import节点完成
阶段自检
- 检查没有复制外部项目的转换代码
- 检查没有把
sessionToken当refresh_token - 检查没有伪造 placeholder refresh token
- 检查 group/proxy/priority 是否复用了现有设置,不新增重复配置
- 检查 session 为空、tab 域名不对、access token 过期时是否能直接明确失败
- 检查日志是否能区分 created 和 updated
阶段 D:后台总控、自动运行、状态清理
目标
让 session strategy 在后台真正成为一条独立于 OAuth 的 Plus 尾链,而不是继续被旧 OAuth 控制逻辑误伤。
涉及文件
background.jsbackground/runtime-state.jsbackground/message-router.jsbackground/steps/platform-verify.jsbackground/panel-bridge.js- 自动运行 / auth-chain 相关测试
完成标准
- session strategy 下不会再刷新 OAuth URL
- session strategy 下不会再依赖 localhost callback
- session strategy 下不会进入 AUTH_CHAIN
- 切换到 session strategy 时会清理旧 OAuth 残留状态
- 最终成功节点判定支持
sub2api-session-import - auto-run 不会把 session import 失败错误地重开到 OAuth 或支付节点
阶段自检
- 检查
AUTH_CHAIN_NODE_IDS是否仍然只包含 OAuth 节点 - 检查
refreshOAuthUrlBeforeStep6是否已经按策略分流 - 检查
oauthFlowDeadlineAt / oauthFlowDeadlineSourceUrl / localhostUrl / oauthUrl等状态在 session strategy 下不会继续参与流程 - 检查
message-router的 Plus 模式日志和成功判定没有写死 OAuth - 检查从
oauth -> session、session -> oauth双向切换时,状态清理是否完整
阶段 E:测试补齐、回归验证、编码自检
目标
把所有会被此次设计影响的行为补成自动测试,并做最终一致性回归。
涉及文件
tests/step-definitions-module.test.jstests/sidepanel-plus-payment-method.test.jstests/flow-capabilities-module.test.jstests/background-settings-schema-persistence.test.jstests/background-account-history-settings.test.jstests/background-message-router-module.test.jstests/background-message-router-plus-final-step.test.jstests/background-auth-chain-guard.test.jstests/auto-run-step6-restart.test.js- 新增的
sub2api session import相关测试文件
完成标准
- UI、schema、步骤、后台、auto-run 都有对应测试
- session strategy 下的最终成功节点有专门测试
- OAuth 旧行为回归不被破坏
- Plus 不走手机号注册的约束仍然成立
阶段自检
- 检查所有新增测试都不是基于固定步号,而是基于动态 step key / last step 推导
- 检查
sub2api、cpa、codex2api三种 target 都覆盖到 - 检查
paypal / gopay / gpc-helper三种 Plus 支付方式都覆盖到 - 检查 session strategy 下没有任何测试仍假设最后节点是
platform-verify - 检查断言文案和快照没有乱码
8. 验收标准
以下条件全部满足,才算本功能真正做完:
- Plus 模式新增“账号接入策略”配置
sub2api下可以在OAuth与导入当前 ChatGPT 会话到 SUB2API之间切换cpa / codex2api下该策略显示但禁用,实际始终走 OAuth- Plus 下仍只允许邮箱注册
- session strategy 下,Plus 尾链不再出现 OAuth 节点
- session strategy 下,导入逻辑走
sub2api原生import/codex-session - session strategy 下,不依赖
oauthUrl / localhostUrl / sub2apiSessionId / sub2apiOAuthState - session strategy 下,最终成功节点为
sub2api-session-import - session strategy 下失败不会误触发 OAuth auth-chain 重开
- 设置导出、导入、恢复后,新策略不会丢失
- 所有新增中文文案无乱码
- 旧 OAuth Plus 路径在
sub2api / cpa / codex2api下仍可正常工作
9. 明确禁止事项
本次开发明确禁止以下做法:
- 复制
GPTSession2CPAandSub2API的前端转换代码进入扩展 - 在扩展里自己手搓一套 sub2api 导入 JSON 转换器来替代
import/codex-session - 把
sessionToken当作refresh_token - 伪造 placeholder
refresh_token - 继续把 Plus 尾链写死为固定步骤号
- 在 Plus 模式下再设计手机号注册兼容路径
- 让 session strategy 继续复用 OAuth 的 localhost 回调、auth-chain 超时、step7/step9 重开逻辑
- 只改 UI 不改后台,或者只改步骤定义不改总控
10. 最终结论
这项功能应该按“Plus 模式账号接入策略”来做,而不是“在某个固定步骤后插一个小补丁”。
从当前代码结构看,正确实现方式不是复制外部项目代码,而是:
- 复用扩展现有的 ChatGPT session 读取能力
- 复用
sub2api原生import/codex-session - 在 Plus 动态步骤体系里,用
sub2api-session-import替换整段 OAuth 尾链 - 把设置、能力、步骤、后台状态、自动运行、最终成功判定、测试一起改完整
只要按本方案实施,就能在不破坏现有 OAuth 方案的前提下,把 sub2api 的 Plus 账号接入正式扩展成一套完整、闭环、可维护的策略能力。