Skip to content

fix(cli): hide unconfigured discontinued OAuth model - #5167

Merged
wenshao merged 1 commit into
QwenLM:mainfrom
he-yufeng:fix/hide-unconfigured-qwen-oauth
Jun 16, 2026
Merged

wenshao merged 1 commit into
QwenLM:mainfrom
he-yufeng:fix/hide-unconfigured-qwen-oauth

Conversation

@he-yufeng

Copy link
Copy Markdown
Contributor

What this PR does

The interactive /model picker now hides the discontinued built-in Qwen OAuth model when the current session uses another authentication provider. Existing Qwen OAuth sessions still see the discontinued entry, so their migration warning remains available.

Why it's needed

getAllConfiguredModels() includes the built-in Qwen OAuth registry entry even when a user has no OAuth configuration. That made API-key and OpenAI-compatible users see an unusable discontinued model as the first picker option. Filtering only the dialog's non-runtime registry entries removes the misleading option without changing the global registry or runtime compatibility.

Reviewer Test Plan

How to verify

Open /model while authenticated through an OpenAI-compatible provider and confirm no qwen-oauth row is shown. Open it in an existing Qwen OAuth session and confirm the discontinued row and warning remain visible.

Evidence (Before & After)

Before: non-OAuth users see [qwen-oauth] coder-model (Discontinued) as the first row. After: the row is omitted unless Qwen OAuth is the active auth type. Focused component tests cover both sides.

Tested on

OS Status
🍏 macOS N/A
🪟 Windows ✅ tested
🐧 Linux N/A

Environment (optional)

Node.js 24; repository dependencies installed locally.

Risk & Scope

  • Main risk or tradeoff: existing Qwen OAuth sessions must still see the migration warning; this remains covered.
  • Not validated / out of scope: no live OAuth login was attempted.
  • Breaking changes / migration notes: none.

Linked Issues

Fixes #5160

中文说明

本 PR 做了什么

交互式 /model 选择器现在会在当前会话使用其它认证提供商时隐藏已经停用的内置 Qwen OAuth 模型。已有 Qwen OAuth 会话仍能看到停用条目,因此迁移提示不会丢失。

为什么需要修改

getAllConfiguredModels() 即使在用户没有配置 OAuth 时也会包含内置 Qwen OAuth 注册项,导致 API Key 和 OpenAI 兼容提供商用户把一个不可用的停用模型看作第一个选项。本次只过滤选择器中的非运行时注册项,不改变全局模型注册和现有运行时兼容行为。

Reviewer Test Plan

验证方式

使用 OpenAI 兼容提供商认证后打开 /model,确认不再显示 qwen-oauth 行;在已有 Qwen OAuth 会话中打开,确认停用条目和警告仍然可见。

修改前后证据

修改前,非 OAuth 用户会把 [qwen-oauth] coder-model (Discontinued) 看到为第一行;修改后,只有当前认证类型为 Qwen OAuth 时才显示该行。聚焦组件测试覆盖了两侧行为。

已测试环境

Windows,Node.js 24;本地安装仓库依赖。聚焦测试、lint、完整 build 和全工作区 typecheck 均通过。

风险与范围

  • 主要风险:已有 Qwen OAuth 会话仍需看到迁移警告,测试已覆盖。
  • 未验证 / 范围外:未尝试真实 OAuth 登录。
  • 破坏性变更:无。

关联 Issue

Fixes #5160

@DragonnZhang DragonnZhang left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Clean fix: discontinued QWEN_OAUTH models are now hidden from the model dialog when the user is on a different auth type, rather than being shown and then blocking selection. The filter m.authType !== AuthType.QWEN_OAUTH || authType === AuthType.QWEN_OAUTH correctly shows QWEN_OAUTH models only when the user is already on that auth type. authType added to useMemo dependencies. Old "blocks switching" test removed (replaced with "hides" test). No high-confidence issues found.

Downgraded from Approve to Comment: CI pending.

— claude-opus-4-6 via Qwen Code /review

expect(props.showNumbers).toBe(true);
});

it('hides discontinued qwen-oauth models for other auth types', () => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The new test covers the "hide" side (non-OAuth user doesn't see QWEN_OAUTH model) but lacks the complementary "show" test — verifying that a QWEN_OAUTH user still sees the discontinued entry. The PR description explicitly promises this behavior ("Existing Qwen OAuth sessions still see the discontinued entry"), but it's untested.

A regression in the filter logic that accidentally hides QWEN_OAUTH models from QWEN_OAUTH users (breaking the migration warning flow) would go undetected.

Consider adding a complementary test:

it('shows discontinued qwen-oauth models for QWEN_OAUTH auth type', () => {
  renderComponent(
    {},
    {
      getAuthType: vi.fn(() => AuthType.QWEN_OAUTH),
      getAllConfiguredModels: vi.fn(() => [
        {
          id: DEFAULT_QWEN_MODEL,
          label: DEFAULT_QWEN_MODEL,
          authType: AuthType.QWEN_OAUTH,
        },
        {
          id: 'gpt-4',
          label: 'GPT-4',
          authType: AuthType.USE_OPENAI,
        },
      ]),
    },
  );

  const items = mockedSelect.mock.calls[0][0].items;
  const oauthItem = items.find(
    (item: { value: string }) =>
      item.value === `${AuthType.QWEN_OAUTH}::${DEFAULT_QWEN_MODEL}`,
  );
  expect(oauthItem).toBeDefined();
});

— qwen3.7-max via Qwen Code /review

@doudouOUC doudouOUC left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No issues found. LGTM! ✅ — qwen3.7-max via Qwen Code /review

@wenshao

wenshao commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

✅ Maintainer verification — built and tested locally

I verified this PR by building it from source and driving the real interactive TUI under tmux (not just the unit tests), reproducing issue #5160 end-to-end and confirming the fix.

Setup

  • Source: PR head 68b3bc5 (fix/hide-unconfigured-qwen-oauth), fresh npm ci + npm run bundle → dist/cli.js (v0.18.0).
  • Env: Linux, Node v22. Isolated config via QWEN_HOME; placeholder API key / cached credentials only — no real keys, no network calls.
  • A/B method: same config fixture each time; only ModelDialog.tsx was toggled between the pre-fix version (parent commit 8608028c) and the PR version, rebuilding the bundle between runs.

1. OpenAI-compatible auth — the bug in #5160 (Before → After)

Fixture: security.auth.selectedType = "openai" + one modelProviders.openai entry (gpt-4), no OAuth configured. Opened /model:

Before (pre-fix): the discontinued OAuth model is the first selectable row — exactly the reported bug.

│ Select Model                                          │
│ › 1. [qwen-oauth] coder-model (Discontinued)          │
│      Discontinued — switch to Coding Plan or API Key  │
│   2. [openai] GPT-4 (gpt-4)                            │
│ Enter to select, ↑↓ to navigate, Esc to close         │

After (this PR): the qwen-oauth row is gone; only the configured provider remains. ✅

│ Select Model                                          │
│ › 1. [openai] GPT-4 (gpt-4)                            │
│ Enter to select, ↑↓ to navigate, Esc to close         │

2. Existing Qwen OAuth session — migration warning preserved (regression guard)

Fixture: selectedType = "qwen-oauth" + a cached oauth_creds.json (far-future expiry). The session starts as Qwen OAuth | coder-model. Opened /model:

The discontinued registry row is still shown (alongside the runtime model from cached creds), so the migration notice is intact for users who actually have an OAuth session. ✅

│ Select Model                                          │
│ › 1. [qwen-oauth] coder-model (Runtime)               │
│      Runtime model                                    │
│   2. [qwen-oauth] coder-model (Discontinued)          │
│      Discontinued — switch to Coding Plan or API Key  │
│ Enter to select, ↑↓ to navigate, Esc to close         │

This matches the PR's intent: the entry is filtered only when the active auth type is not qwen-oauth.

3. Automated checks (on PR head)

  • ModelDialog.test.tsx: 15/15 pass, including the new hides discontinued qwen-oauth models for other auth types. The retained blocks qwen-oauth model selection with an error message (discontinued) still passes, so selection in an OAuth session remains guarded.
  • tsc --noEmit on packages/cli: clean.

Notes / scope

  • The change is presentation-only in the dialog: it filters non-runtime registry entries and adds authType to the useMemo deps so the list re-computes after an in-session /auth switch. The global model registry and runtime compatibility are untouched, which keeps the blast radius minimal.
  • Runtime OAuth models (from cached tokens) are intentionally not filtered — confirmed in scenario 2 — so existing sessions keep working until the server rejects them.

Verdict: Behavior matches the PR description and resolves #5160 in the real TUI, with the OAuth-session path preserved. LGTM. 👍

🇨🇳 中文版(点击展开)

✅ 维护者验证 —— 本地构建并实测

我从源码构建了本 PR,并在 tmux 中驱动真实的交互式 TUI(不仅仅跑单测)进行验证,端到端复现了 issue #5160 并确认修复生效。

环境

  • 源码: PR head 68b3bc5(fix/hide-unconfigured-qwen-oauth),全新 npm ci + npm run bundle → dist/cli.js(v0.18.0)。
  • 环境: Linux,Node v22。通过 QWEN_HOME 隔离配置;仅使用占位 API Key / 本地缓存凭据 —— 无真实密钥、无网络调用。
  • A/B 方法: 每次使用相同的配置 fixture,仅在「修复前版本」(父提交 8608028c)与「PR 版本」之间切换 ModelDialog.tsx,并在两次运行之间重新打包。

1. OpenAI 兼容认证 —— #5160 的 bug(修复前 → 修复后)

Fixture:security.auth.selectedType = "openai" + 一个 modelProviders.openai 条目(gpt-4),未配置任何 OAuth。打开 /model:

修复前: 已停用的 OAuth 模型是第一个可选项 —— 正是所报告的 bug。

│ Select Model                                          │
│ › 1. [qwen-oauth] coder-model (Discontinued)          │
│      Discontinued — switch to Coding Plan or API Key  │
│   2. [openai] GPT-4 (gpt-4)                            │
│ Enter to select, ↑↓ to navigate, Esc to close         │

修复后(本 PR): qwen-oauth 行消失,只剩已配置的 provider。✅

│ Select Model                                          │
│ › 1. [openai] GPT-4 (gpt-4)                            │
│ Enter to select, ↑↓ to navigate, Esc to close         │

2. 已有的 Qwen OAuth 会话 —— 迁移提示得以保留(回归保护)

Fixture:selectedType = "qwen-oauth" + 一份缓存的 oauth_creds.json(设很久以后过期)。会话以 Qwen OAuth | coder-model 启动。打开 /model:

已停用的注册项仍然显示(与来自缓存凭据的 runtime 模型并列),因此对真正拥有 OAuth 会话的用户而言,迁移提示完好无损。✅

│ Select Model                                          │
│ › 1. [qwen-oauth] coder-model (Runtime)               │
│      Runtime model                                    │
│   2. [qwen-oauth] coder-model (Discontinued)          │
│      Discontinued — switch to Coding Plan or API Key  │
│ Enter to select, ↑↓ to navigate, Esc to close         │

这与 PR 的意图一致:仅当当前认证类型不是 qwen-oauth 时才过滤该条目。

3. 自动化检查(基于 PR head)

  • ModelDialog.test.tsx:15/15 通过,包含新增的 hides discontinued qwen-oauth models for other auth types。保留的 blocks qwen-oauth model selection with an error message (discontinued) 仍然通过,因此 OAuth 会话中选择该项仍被拦截。
  • 对 packages/cli 执行 tsc --noEmit:无报错。

说明 / 范围

  • 本改动仅作用于对话框的展示层:过滤非 runtime 的注册项,并把 authType 加入 useMemo 依赖,使列表在会话内 /auth 切换后重新计算。全局模型注册表与 runtime 兼容性均未改动,影响面最小。
  • runtime OAuth 模型(来自缓存 token)有意不被过滤 —— 已在场景 2 中确认 —— 因此已有会话在服务端拒绝之前仍可继续使用。

结论: 行为与 PR 描述一致,在真实 TUI 中解决了 #5160,同时保留了 OAuth 会话路径。可以合并。👍

Verification performed locally in an isolated environment; placeholder credentials only.

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.

bug(cli): /model lists discontinued qwen-oauth coder-model even when OAuth is not configured

4 participants