* fix(web-shell): wait for session before checking subscription commands * fix(cli): keep signed-out subscription startup in the composer * fix(subscription): preserve model selection across sign-in * fix(subscription): align sign-in with model selection scope * fix(subscription): apply reasoning defaults across models * fix(subscription): tag Qwen web links by client * fix(subscription): prefix Qwen web client tags * fix(subscription): attribute Qwen web links by paywall scene * fix(subscription): recover historical sessions with saved API models * fix(cli): remove the signed-out subscription startup notice * fix(subscription): support standalone desktop activation and expose errors * fix(subscription): isolate activation and session model selection * fix(subscription): enforce auth policy and restore home login * test(cli): preserve the default initializer mock on restore --------- Co-authored-by: luoyun <[email protected]> Co-authored-by: 易良 <[email protected]>
22 KiB
Qwen Subscription 接入
关联 Issue:#15180。
范围与可用性
CLI(Ink/OpenTUI)、桌面端和 VS Code 共用 Core 的会员凭证、会员查询及 OpenAI Chat 推理。订阅登录、激活、模型加载、推理、搜索和账号命令不再依赖 DEV=true,打包客户端也默认可用。订阅客户端使用固定的生产地址。移除产品模拟开关、模拟 transport、预览页面和原生调试启动器;保留回归测试替身。
桌面端在现有供应商弹窗增加 Qwen,不增加独立引导页或常驻订阅按钮。VS Code 保留原生供应商选择器,选择 Qwen 后进入共用侧栏会员流程;原生 QuickPick 账号操作只负责退出和升级。
授权、购买与恢复
- 申请设备码,显示并打开授权链接,轮询 Token。Core 按返回的
expires_in控制期限;GUI 不另设固定 600 秒。链接复制截止于原始授权期限。旧 OAuth 保留独立标题、倒计时和取消行为。 - 保存完整 Token 对,再查询身份和
member_type。首次会员查询失败保留凭证,Check again 只重新查询,不重新授权;无需浏览器回调。 - 套餐展示只调整大小写,保留 Free、Lite 及其他返回名称。只有忽略大小写的 Plus/Pro 可以激活。仅在用户选择 View Plans(查看套餐)时打开套餐页,会员查询恢复时也不自动打开。新授权流程仍打开授权页,不自动打开第二个套餐标签页。
- 从首次确认未付费状态起,每五秒查询一次,最多自动查询两分钟。超时或查询失败允许手动 Check again,同时保留 Open plans again 和退出登录。查询期间禁止重复查询。
- 关闭取消待完成任务。临时网络错误保留已保存的 token。显式重新登录时,原账号可继续使用,直到兑换成功并保存新凭证。授权、兑换、存储、会员、刷新、清理和撤销错误区分阶段,不暴露任意响应正文。只有刷新阶段的
invalid_grant表示刷新凭证过期。共享持久化冷却期限让申请授权、刷新和 userinfo 遵守 Retry-After。 - 退出先删除本地凭证,再撤销远端会话。远端失败仍需同步本地退出并说明远端未撤销;本地删除失败不能宣称退出成功。宿主视图取消后不能更新新的归属。
桌面端与侧栏展示
桌面文案跟随语言设置,包括入口描述、新标记、弹窗标题、错误和操作。产品名、套餐名、模型 ID、命令和 URL 保留原值。中英文入口均为 Qwen;能力可用时默认选中首项,高亮、直接点击和下一步对应同一可见选择。其他类型索引包含首项偏移;能力不可用时默认选择首个普通类型。
桌面授权是连接供应商的第二步。上一步取消授权并返回选择;授权、会员确认和错误期间下一步禁用,确认成功自动激活模型,并在第二步保留结果摘要,直到关闭弹窗。授权失败不提供重新登录按钮。浏览器兜底说明和等待文字使用供应商描述的弱化颜色,链接保持蓝色;查询失败保留重新检查。
购买引导使用独立可访问弹窗,保留授权流程生命周期。内容顺序对齐 CLI,并按桌面语言翻译:标题、未付费套餐说明、等待状态、重新打开套餐页、改用阿里云百炼、退出及弱化描述。省略重复账号行,保留等宽字体,取消位于独立底栏。复用供应商选项样式:整行次级背景、6px 圆角、选中标题蓝色。上下键只移动选择,不触发操作;移除终端箭头和浏览器焦点描边。关闭返回选择,不撤销凭证。
侧栏使用 VS Code 字体和语义颜色、13px 字号、1.6 行高、14px 区块间距及可换行宿主按钮。按已确认要求,购买引导在两种宿主语言中均保留英文;授权和就绪状态继续本地化。购买标题前显示登录邮箱和实际套餐,随后为说明与等待状态。查看套餐为主按钮,切换供应商为描边按钮,使用其他账号为下方独立居中的文字操作。保留既有重试操作及弱化说明。使用标准 Tab/Shift+Tab 和 Enter/Space。授权错误返回 Get Started 下方;购买和查询错误保留流程内恢复操作。
激活、模型与归属
新授权、查询恢复或购买轮询确认 Plus/Pro 后,均在每个授权/transport 生命周期内自动激活一次。回调重渲染不能重复激活;等待时显示进度,普通失败提供显式重试。取消、卸载和归属替换抑制迟到成功。首个会话尚未创建时,关闭认证前先更新欢迎页输入框待用模型,避免首条请求恢复旧供应商模型。
通过 GET /compatible-mode/v1/models 获取全部 ID,不设白名单。已记录的预发列表包含 qwen3.8-max、qwen3.7-flash 和 qwen3.7-plus。每次显式登录订阅账号都优先使用返回的 qwen3.8-max,否则选择首项,不沿用上次保存的模型。普通启动和模型刷新仍保留已保存的选择,模型下线时不能静默替换。网络或服务端故障保留凭证,可使用上次成功列表;无缓存时明确报错,不虚构模型。HTTP 错误保留状态,展示公开的 error.message,并保留既有 error_description 兜底。HTTP 403 原样显示该文案,不返回缓存列表。退出或新账号授权清除账号所属缓存。
已认证的 Config 在切换会员模型时,复用同一持久化登录 revision 下已加载的模型列表。仍正常重建模型客户端,保持模态、上下文限制和推理设置同步。复用前在本地读取当前登录 revision;Token 轮换保留该值,退出和新授权使复用失效。启动、显式认证/列表刷新以及从其他供应商切回时,仍加载最新列表。显式刷新失败或刷新期间登录身份变化时,不能据此继续复用列表。CLI、桌面端和 VS Code 共用此 Core 行为。
会员 qwen3.8-max 和 qwen3.8-flash 在模型注册与请求配置中明确支持图片、视频输入。其他服务端返回的 ID 继续保留,在网关能力确认前使用保守的纯文本模态。
模型选择器顺序
Qwen 账号授权成功并取得会员模型列表后,CLI(Ink/OpenTUI)、桌面端和 VS Code 的主模型列表依次展示 Qwen 3.8 Max(qwen3.8-max)、Qwen 3.8 Flash(qwen3.8-flash)、其他可见 Qwen 账号模型、其他 provider;后两组内保持原有相对顺序。可从有效凭证缓存恢复该顺序;没有非运行时会员条目时保留原排序,仅有运行时覆盖项不视为会员授权成功。按认证来源和准确模型 ID 匹配,避免误将 API provider 的同名模型置顶,不补出不存在的模型。
在 CLI 最终主模型条目及 ACP 模型选项上应用同一个共享展示排序函数,覆盖欢迎页及已有会话刷新。保留注册表数据、展示名称、当前选中模型、带端点身份的路由 ID、持久化和现有可见性筛选。CLI 辅助模型选择器保留原排序。通过定向测试和共用 Web Shell 选择器验证乱序及不完整列表、未授权、运行时覆盖、API 同名模型、稳定排序、输入不变和路由选择。
CLI 模型恢复提示 /model,启动时也允许 Esc 返回输入框。桌面和 VS Code 遇到 subscription_models_unavailable 或 subscription_model_unavailable 时关闭会员认证,保留凭证及现有会话模型,不增加专用重试或模型选择页,也不宣称激活成功。HTTP 403 为例外:在当前错误区保留后端业务文案;普通模型加载、选择和刷新仍由现有输入框处理。显式登录激活从账号模型列表选择默认模型,不提供临时覆盖模型的参数。
激活在两个宿主间传递错误阶段、HTTP 状态、文案及 Retry-After。OAuth 保留既有 error/error_description 解析,以及轮询、刷新凭证所需的业务码判断;网关错误直接展示公开的 error.message,仅订阅额度耗尽使用下文定义的客户端文案。刷新凭证过期时退出就绪态,不隐式重新授权;激活重试遵守返回的冷却期限。推理取凭证失败和 MCP 搜索失败保留刷新、权限、限流分类,不再统一替换为重新登录提示。不展示未知本地异常和非 JSON 响应正文;GUI 兜底文案跟随宿主语言。
账号 daemon 路由属于进程级。Desktop 无工作区时,POST /auth/subscription/model 先检查全局认证策略,再确认会员身份并从账号目录选择模型,此接口没有工作区目标,也不写入设置。项目激活解析选定工作区并遵守其信任状态、认证策略和生命周期。即使事件流正在重连,Desktop 和 Web Shell 也会切换发起授权的活跃会话。bridge 先校验客户端,ACP 再检查目标会话生效的认证策略,通过后才能刷新模型目录或切换模型。独立草稿在首次创建会话时携带所选模型。保存设置前切换工作区或会话会取消原流程。保存一旦开始,设置事务会完整结束。
VS Code 捕获 daemon、规范工作区和选定会话。侧栏激活通过带 flow/request 关联的桥接访问捕获工作区,验证运行时同步后只更新捕获会话。初始引导不能发送未注册的 Web Shell client ID。重新 bootstrap、会话/工作区变化、daemon 替换和视图销毁均终止归属。短生命周期账号 client 保留原 daemon 地址和 Token,晚到的登录请求仍向正确 daemon 取消。
VS Code 打开订阅授权时在 WebShellWithProviders 上设置 viewHidden,卸载聊天视图和 portals,保持工作区/会话 providers 挂载并保留活跃会话连接,在显示授权前释放弹窗焦点和指针锁。完成、取消或授权失败后返回同一个活跃会话并保留历史。显式重新授权期间保留原订阅凭证,直到保存新 token。首次未登录欢迎页不挂载隐藏 providers。桌面授权保留在已有 Web Shell 内的弹窗中,CLI 激活直接更新已有 Config,两者都不经过 VS Code 的视图替换路径。
退出/升级命令使用原生状态行及完成/重试操作。命令注册不依赖开发模式;提供账号操作前仍需查询实际 daemon 能力和当前订阅连接。冷启动等待 bootstrap,并限制超时、清理销毁/错误路径。不能替换进行中的账号操作,不可取消的退出必须完成并同步结果。日志只记录安全错误码、HTTP 状态和操作名。浏览器拒绝打开时提供重试。
协议与凭证安全
| 用途 | 接口 |
|---|---|
| 设备授权 | POST /api/oauth/device/code |
| Token 兑换/刷新 | POST /api/oauth/token |
| 身份/会员 | GET /api/oauth/userinfo |
| 撤销 | POST /api/oauth/revoke |
订阅认证域名为 https://auth.qwen.ai,OAuth client_id=qwen-code-cli。跳往 chat.qwen.ai 的网页链接携带 entry=qwen_code 和 paywallScene。授权地址 /authorize 还带 user_code 和 client,其中 client 与 paywallScene 取值一致。升级和购买共用 /,还带 memberPlan=qwen_code。两个网页入口都需要登录网页账号。
终端和文档使用 paywallScene=cli,Desktop 和独立 Web Shell 使用 paywallScene=desktop,VS Code 插件使用 paywallScene=plugin。daemon 从订阅能力查询和授权流程创建请求接收 paywallScene,默认取 desktop,轮询同一流程时沿用创建时生成的授权链接。指向 chat.qwen.ai 的旧版网页授权链接也加相同的归因字段,并保留原有查询参数。
Core 负责私有权限的原子存储、恢复、跨进程刷新锁和撤销。宿主只在有效 QWEN_HOME 相同时共享会话。会员与旧 OAuth 分开存储;刷新替换完整 Token 对;Token 和设备码不进入 GUI 响应。
推理固定使用 https://api.qwen.ai/compatible-mode/v1 和 OpenAI Chat Completions。配置仅保存鉴权选择、模型 ID、固定网关及凭证占位符。传输边界注入 Bearer Token,保留代理/取消,在发凭证前拒绝重定向或其他目标。HTTP 请求在凭证锁外运行;401 时刷新被拒 Token 并重试一次,在锁内比较当前/被拒 Token,避免重复轮换。403/404/429 不刷新,已开始交付的流不重放。缺失凭证直接失败,不隐式授权;退出清除后续请求缓存凭证。
额度耗尽展示
CLI(Ink/OpenTUI)、桌面端和 VS Code 的订阅聊天及 MCP 搜索错误共用 Core 的转换。仅通过 HTTP 402 与 error.code = insufficient_quota 同时成立来识别额度耗尽,错误文案及可选 error.quota 不参与分类。已知 lite/plus 展示周额度提示并引导 /upgrade;pro 展示周额度提示并等待恢复。未知或缺失档位使用通用额度文案,不推断升级权益。额度上下文缺失或异常时仍展示额度提示。
quota.reset_at 是 Unix 秒级整数时间戳,缺失、非法或已过期时省略恢复时间。剩余小时向上取整,不足一天仅显示小时,否则显示天和小时。Core 仅在确认 HTTP 402 与 insufficient_quota 后附加带类型的 subscription_quota 展示数据,同时保留可读英文供纯文本宿主使用。展示数据包含可选档位、重置时间和请求 ID,通过既有错误及工具结果通道传递。两个 CLI 渲染器及桌面端/VS Code 的共享组件通过现有 i18n 翻译函数生成提示。提供好的英文、简体和繁体文案均放入对应语言资源,包括恢复时间模板和时间单位。Core 共享错误判定和倒计时计算,不选择语言;纯文本宿主保留英文兜底。i18n 键检查覆盖共享 Core 工具。普通工具输出和后端文案不再通过匹配文字来识别或改写为额度提示。其他后端文案保持原值。本次不调整认证、重试及会员缓存。
侧栏购买界面的查看套餐为主按钮,切换供应商为描边按钮,使用其他账号为下方独立居中的文字操作。保留回调、键盘焦点及既有重试操作。
验证中英文、已知及未知档位、额度字段部分缺失及异常、时间边界、流式/非流式聊天、MCP 搜索、状态/错误码/请求 ID 保留,以及侧栏操作样式与回调。模拟测试不代表真实网关或原生宿主验收。
思考与搜索
复用 ModelReasoningControls 和现有 session/ACP reasoning 设置。Qwen 订阅来源的所有模型在控件和请求中都默认使用中等思考强度,用户显式选择优先。关闭时发送顶层 enable_thinking: false 且不带预算。低、中、高发送 true,预算分别为 4096、16384、32768,已有 xhigh/max 映射高档。移除冲突 reasoning/reasoning_effort 和嵌套 chat-template 思考开关,保留无关选项。显式原生预算继续有效。单次请求关闭会移除预算,仍遵守强制思考元数据。
真实 Max 网关已接受关闭和三档预算,关闭无 reasoning_content、开启有;这证明参数接受和开关行为,不证明长推理预算严格执行或 Flash 支持。会员搜索复用现有 MCP 后端,动态注入 Bearer Token,HTTP 401 时刷新被拒 Token 并仅重试一次,取消归属工具请求。详见会员 MCP 联网搜索。
CLI 成功提示与账号命令
两种渲染器激活成功后返回对话,追加摘要并保留本次浏览器链接:登录成功与邮箱、确认套餐与 Code 可用状态、所选模型与 /upgrade 和 /usage 引导、常用 /usage /upgrade /status /logout 命令。移除启动区重复的 /usage 提示,并从当前 Config 同步模型显示。只展示确认的 Plus/Pro,确认前不猜套餐。遵守隐藏提示和读屏设置,省略默认会员标题空行,保留自定义副标题。OpenTUI 保留完整提交元数据/接收结果和规范历史元数据。
会员输入框下不再单独展示 Try 常用命令提示行;常用命令保留在登录成功摘要中,命令执行行为保持不变。Usage 是已有 CLI 本地统计,不是服务端剩余额度。交互升级命令打开统一套餐页,禁止或打开失败时保留可复制 URL。交互退出命令限主响应空闲时执行;本地退出成功后取消后台 agent/侧问,清除账号套餐状态,保留当前模型、供应商和设置,不弹框、不自动切换。保留其他供应商 API Key 和配置;本地清理失败不能清空当前运行时。显式 /auth 每次都打开对应网页。
账号命令可用性
仅当本地凭据属于当前 OAuth 环境,且当前模型连接使用 qwen-subscription 时,提供内置 /logout 和 /upgrade。API Key 连接和已退出的订阅选择不符合条件。访问令牌过期但仍有刷新令牌时,在刷新被拒绝前仍视为已登录。可用性检查不发起 OAuth 或网络请求。daemon 通过可选 signedIn 返回账号状态;旧响应缺少该字段时不启用账号命令。
CLI 监听模型和凭据文件变化;其他进程移除凭据时也清理缓存套餐,保留模型选择。Web Shell 和原生 VS Code 检查当前工作区或活跃会话连接,并在执行命令前重新确认账号状态,宿主覆盖命令也需先通过检查。模型或会话变化会取消过期的异步操作,包括模型 ID 相同但 provider 不同的情况。同名自定义命令保留自身行为。回归使用隔离凭据和拦截的浏览器入口覆盖这些转换。
显式登录、工作区默认值与退出
每次显式选择 Qwen 登录都重新发起设备授权,访问 /authorize,即使本地凭证仍有效。本地 OAuth 凭证不能证明浏览器仍处于登录状态。设备授权期间保留原账号的 token、revision 和模型目录。取消、拒绝、过期或兑换失败时保留原会话。退出登录或发起更新的登录会使较早的尝试失效。兑换成功后原子保存新的 token 对和 revision,清除旧目录,并拒绝旧账号迟到的目录响应。CLI 及 Desktop、VS Code 共用的进程级 daemon 流程都必须等待本次授权完成,才能确认会员状态或激活模型。普通启动仍自动恢复已保存凭证,不发起授权。成功摘要在模型与常用命令之间保留本次实际授权链接,不再生成 /authorize/success 链接。本次客户端修复不修改网页及已有路由;登录回跳、购买顺序及授权页的成功卡片仍由网页负责。
显式登录优先选 Max,目录没有 Max 时取第一项。在受信任的项目内登录时,模型、认证类型和端点写入该项目设置,供应商目录可以位于任意配置层级。从用户主目录启动交互式 CLI 时,选择保存到用户设置,重启后仍可恢复。daemon 的项目激活接口要求项目设置可用。Desktop 无工作区时,所选模型用于发起登录的会话或草稿。其他活跃会话继续使用各自的运行时模型,新建项目会话按生效设置取默认。CLI /auth 菜单初始高亮 Qwen 会员账号。Desktop 在授权第二步展示账号、套餐、已激活模型和手动链接。
退出清除账号凭证及账号/套餐状态,保留模型和供应商选择,不切换其他供应商、不打开认证弹窗。凭证失效后,可选列表隐藏订阅模型,包括其他 session 退出的场景;通过 API Key 接入的同名模型仍可选择。底层目录与当前模型的路由身份保留,即使当前模型已不在可选列表中;重新登录后恢复订阅选项。无凭证的订阅请求与过期订阅选项统一提示“登录凭证已失效,请运行 /auth 重新登录。”,不附加连接错误包装,也不直接展示 session_changed。订阅入口中文保留 Agent。
交互式 CLI 已配置订阅但凭据缺失或过期时,重启后直接进入输入界面。用户可运行 /auth 重新登录。启动时已保存的订阅模型不可用则提示用 /model 重选。完全未配置供应商的首次启动仍打开供应商向导。
验证覆盖新旧凭证、两套 CLI 渲染器、原生 VS Code 和桌面端、登录后新工作区/新会话、退出后请求及切换其他供应商、浏览器打开失败和中英文文案。补充已有 E2E 报告,本轮不新增 Markdown 文件。
开发与验证
CLI 开发执行 npm run dev,构建后的 CLI 无需 DEV 即可使用订阅。GUI daemon 使用 Core oauth-config.ts 的固定生产配置,不再要求开发环境变量。构建/打包后用 node packages/vscode-ide-companion/scripts/copy-bundled-cli.js 同步 VS Code;桌面包在开发启动或构建安装包前执行 npm run build:runtime。已有 daemon 需重启加载代码。验证 DEV 未设置、false、true,以及 VS Code 正式模式激活和带鉴权的 daemon 能力查询。保留 daemon 鉴权、工作区信任与归属、会员校验、网关限制和显式搜索设置。
定向覆盖授权期限、无重新授权的恢复、Retry-After、轮换/撤销/清理、完整列表与下线模型、激活生命周期/归属、两种渲染器、默认供应商、本地化桌面导航、侧栏桥接、序列化思考参数、流式请求和其他供应商。使用可丢弃凭证与本地 HTTP fixture,不退出开发者真实账号;测试计划/结果放在忽略的 .qwen/e2e-tests/。交付前构建、类型检查、打包并审查完整 diff。
2026-10-29 已记录真实 Pro Token 的 SDK 流式/非流式冒烟,返回 HTTP 200、OK 和 usage,仅证明 SDK 对话链路。原生宿主完整 OAuth、浏览器/购买生效、agent/工具流程、额度/错误契约、逐模型思考支持及长预算执行仍需验收;本地模拟和构建不证明部署或生产可用。