Skip to content

fix(acp): hide discontinued OAuth model for other auth types - #7522

Merged
wenshao merged 2 commits into
QwenLM:mainfrom
hogeheer499-commits:agent/qwen-code-7433
Jul 23, 2026
Merged

fix(acp): hide discontinued OAuth model for other auth types#7522
wenshao merged 2 commits into
QwenLM:mainfrom
hogeheer499-commits:agent/qwen-code-7433

Conversation

@hogeheer499-commits

Copy link
Copy Markdown
Contributor

What this PR does

ACP sessions now omit the discontinued built-in Qwen OAuth model from model selectors when another authentication type is active. Existing Qwen OAuth sessions keep their current model and selector entry. Session creation, model configuration, and daemon session context use the same filtered options.

Why it's needed

The global model registry includes a built-in OAuth model even for users who configured only a local or custom OpenAI-compatible provider. Raw ACP responses consequently advertised that unrelated model first, allowing clients to present it as the preferred choice. The interactive model picker already filters the same discontinued entry; this brings the ACP surface in line with that behavior.

Reviewer Test Plan

How to verify

Create an ACP session with an authenticated OpenAI-compatible provider and a non-OAuth model selected. Confirm that the current model is unchanged, the discontinued OAuth model is absent from both model selectors, and the daemon session context matches. Then create a Qwen OAuth session and confirm its active model remains available. The regression tests exercise both cases and preserve the structured authentication error for a direct request to the hidden route.

Evidence (Before & After)

Before, the reproduced raw ACP response for an OpenAI-compatible session reported qwen3.6-27b(openai) as current but placed coder-model(qwen-oauth) first in both available model lists. After, the same built CLI reports only the configured OpenAI-compatible models; the current model remains qwen3.6-27b(openai). The separate incorrect-current-model label reported by an external SDK was not reproduced on current main.

Tested on

OS Status
🍏 macOS ⚠️
🪟 Windows ⚠️
🐧 Linux

Environment (optional)

Built CLI with a local deterministic OpenAI-compatible test configuration; no external model request was required.

Risk & Scope

  • Main risk or tradeoff: A user on another authentication type can no longer select the discontinued OAuth route from the advertised ACP list; direct requests still return the existing structured authentication error.
  • Not validated / out of scope: The external SDK's incorrect current-model label was not reproducible on current main. Interactive model selection and registry contents are unchanged.
  • Breaking changes / migration notes: None. Active Qwen OAuth sessions retain the built-in model.

Linked Issues

Addresses the reproducible ACP model-list portion of #7433.

中文说明

本 PR 的改动

当会话当前使用其他认证类型时,ACP 模型选择器不再展示已停用的内置 Qwen OAuth 模型。已有的 Qwen OAuth 会话仍保留当前模型及其选择项。会话创建、模型配置和守护进程会话上下文现在使用同一组过滤后的选项。

为什么需要此改动

即使用户只配置了本地或自定义的 OpenAI 兼容提供商,全局模型注册表仍会包含一个内置 OAuth 模型。因此,原始 ACP 响应会把这个无关模型放在第一位,客户端可能将其显示为首选项。交互式模型选择器已经过滤了同一个已停用条目;本改动让 ACP 接口与该行为保持一致。

审阅者测试计划

验证方法

使用已认证的 OpenAI 兼容提供商并选择非 OAuth 模型来创建 ACP 会话。确认当前模型不变、两个模型选择器都不包含已停用的 OAuth 模型,并且守护进程会话上下文与其一致。然后创建 Qwen OAuth 会话,确认其当前模型仍可选择。回归测试覆盖这两种情况,同时保留直接请求隐藏路由时的结构化认证错误。

证据(修改前后)

修改前,在 OpenAI 兼容会话中复现的原始 ACP 响应将 qwen3.6-27b(openai) 正确报告为当前模型,但在两个可用模型列表中都把 coder-model(qwen-oauth) 放在第一位。修改后,同一个构建后的 CLI 只报告已配置的 OpenAI 兼容模型,当前模型仍为 qwen3.6-27b(openai)。外部 SDK 报告的另一项“当前模型标签错误”在当前 main 分支上未能复现。

测试平台

系统 状态
macOS ⚠️
Windows ⚠️
Linux

环境(可选)

使用本地确定性的 OpenAI 兼容测试配置运行构建后的 CLI;无需向外部模型发起请求。

风险与范围

  • 主要风险或取舍:使用其他认证类型的用户无法再从 ACP 公布的列表中选择已停用的 OAuth 路由;直接请求仍会返回原有的结构化认证错误。
  • 未验证或超出范围:外部 SDK 的“当前模型标签错误”在当前 main 分支上无法复现。交互式模型选择和模型注册表内容均未更改。
  • 破坏性变更或迁移说明:无。已有的 Qwen OAuth 会话仍保留内置模型。

关联 Issue

本 PR 处理 #7433 中可复现的 ACP 模型列表问题。

@hogeheer499-commits

Copy link
Copy Markdown
Contributor Author

E2E verification report (Linux)

I reproduced the issue against the built CLI with the reporter's provider shape and a deterministic local API key. On current main, raw session/new output already reported qwen3.6-27b(openai) as currentModelId, but both the available-model list and model config options began with the unrelated coder-model(qwen-oauth) entry.

With this change, the same JSON-RPC ACP handshake reports:

  • current: qwen3.6-27b(openai)
  • available: qwen3.6-27b(openai), deepseek-v4-flash(openai)
  • model config options: the same two OpenAI-compatible models

An independent Qwen OAuth scenario retains coder-model(qwen-oauth). A direct request for that hidden route from a non-OAuth session still returns the existing structured authentication-required error.

Checks completed:

  • ACP agent suite: 301/301 passed
  • focused built-CLI integration test: passed
  • ESLint on all changed source and test files: passed
  • full monorepo build: passed
  • full monorepo typecheck: passed

The external SDK's separate incorrect-current-model label was not reproducible on current main, so this PR intentionally claims only the model-list portion that was reproduced end to end.

@hogeheer499-commits
hogeheer499-commits marked this pull request as ready for review July 23, 2026 01:57
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template looks good ✓

Problem: observed bug with a clear reproduction in #7433 — a user running local OpenAI-compatible models via ACP sees coder-model(qwen-oauth) injected first in the model list and reported as currentModel, despite having no OAuth configuration. The E2E verification comment confirms the reproduction on current main.

Direction: aligned. The interactive model picker already filters the discontinued OAuth entry; this brings the ACP surface in line with that behavior. CHANGELOG has several analogous fixes for model picker filtering on other surfaces (Bedrock, availableModels enforcement).

Size: not applicable — no core paths touched. 17 production lines, 127 test lines.

Approach: the scope feels right. A single buildSelectableModelOptions method filters at the two ACP call sites, existing OAuth sessions are preserved, and the integration test is updated to request the hidden route directly rather than discovering it in the list. No unrelated changes.

Moving on to code review. 🔍

中文说明

感谢贡献!

模板完整 ✓

问题:已观测到的 bug,#7433 中有清晰复现——用户通过 ACP 使用本地 OpenAI 兼容模型时,coder-model(qwen-oauth) 被插入模型列表首位并被报告为 currentModel,尽管用户没有 OAuth 配置。E2E 验证评论确认了在当前 main 上的复现。

方向:对齐。交互式模型选择器已经过滤了已停用的 OAuth 条目;本改动让 ACP 接口与该行为保持一致。CHANGELOG 中有多个类似的模型选择器过滤修复(Bedrock、availableModels 强制执行)。

规模:不适用——未触及核心路径。17 行生产代码,127 行测试代码。

方案:范围合理。一个 buildSelectableModelOptions 方法在两个 ACP 调用点进行过滤,保留已有 OAuth 会话,集成测试更新为直接请求隐藏路由而非从列表中发现。无无关改动。

进入代码审查 🔍

Qwen Code · qwen3.8-max-preview

Reviewed at acceaa06b3fd64f6f325c7eb9df186384233f39e · re-run with @qwen-code /triage

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Code Review

The implementation is clean and minimal. A single buildSelectableModelOptions private method wraps buildAcpModelOptions with a filter that excludes AuthType.QWEN_OAUTH models when the session's current auth type is not OAuth. Both ACP call sites (buildAvailableModels and buildConfigOptions) now go through this method, so session creation, model config options, and the daemon session context all use the same filtered list.

The filter logic is correct: model.authType !== AuthType.QWEN_OAUTH || currentAuthType === AuthType.QWEN_OAUTH — keeps all non-OAuth models unconditionally, and keeps OAuth models only for OAuth sessions. The two remaining unfiltered buildAcpModelOptions / getAllConfiguredModels call sites (buildWorkspaceProvidersStatus and buildProvidersPreflightCell) are status/monitoring endpoints that should show all configured providers — correctly left unchanged.

The integration test is updated to directly request coder-model(qwen-oauth) via session/set_config_option rather than discovering it in the model list, verifying the structured auth error path still works. The unit tests cover both cases (non-OAuth hides, OAuth keeps) and verify all three surfaces (session models, config options, daemon context).

No critical blockers. No AGENTS.md violations. 301/301 unit tests pass, build and typecheck clean, ESLint clean on all changed files.

Real-Scenario Testing

Spawned the ACP server with a deterministic OpenAI-compatible test configuration (two models, selectedType: openai), sent initialize + session/new, and inspected the model list.

Before (main branch)

=== BEFORE (main branch — bug reproduces) ===
=== ACP Session Model List ===
currentModelId: qwen3.6-27b(openai)
availableModels: [
  'coder-model(qwen-oauth)',
  'qwen3.6-27b(openai)',
  'deepseek-v4-flash(openai)'
]
configOptions.model.currentValue: qwen3.6-27b(openai)
configOptions.model.options: [
  'coder-model(qwen-oauth)',
  'qwen3.6-27b(openai)',
  'deepseek-v4-flash(openai)'
]
RESULT: OAuth model PRESENT in list (bug)

After (this PR)

=== AFTER (PR #7522 — fix applied) ===
=== ACP Session Model List ===
currentModelId: qwen3.6-27b(openai)
availableModels: [ 'qwen3.6-27b(openai)', 'deepseek-v4-flash(openai)' ]
configOptions.model.currentValue: qwen3.6-27b(openai)
configOptions.model.options: [ 'qwen3.6-27b(openai)', 'deepseek-v4-flash(openai)' ]
RESULT: OAuth model ABSENT from list (fixed)

The discontinued coder-model(qwen-oauth) is gone from both availableModels and configOptions.model.options. The current model remains qwen3.6-27b(openai) — unchanged, as expected.

中文说明

代码审查

实现简洁且最小化。一个 buildSelectableModelOptions 私有方法包装了 buildAcpModelOptions,在会话当前认证类型不是 OAuth 时过滤掉 AuthType.QWEN_OAUTH 模型。两个 ACP 调用点(buildAvailableModelsbuildConfigOptions)都通过此方法,因此会话创建、模型配置选项和守护进程会话上下文都使用同一组过滤后的列表。

过滤逻辑正确:model.authType !== AuthType.QWEN_OAUTH || currentAuthType === AuthType.QWEN_OAUTH——无条件保留所有非 OAuth 模型,仅在 OAuth 会话中保留 OAuth 模型。剩余两个未过滤的调用点(buildWorkspaceProvidersStatusbuildProvidersPreflightCell)是状态/监控端点,应显示所有已配置的提供商——正确地未做更改。

集成测试更新为直接通过 session/set_config_option 请求 coder-model(qwen-oauth),而非从模型列表中发现它,验证了结构化认证错误路径仍然有效。单元测试覆盖两种情况(非 OAuth 隐藏、OAuth 保留),并验证三个表面(会话模型、配置选项、守护进程上下文)。

无关键阻塞项。无 AGENTS.md 违规。301/301 单元测试通过,构建和类型检查通过,ESLint 对所有改动文件通过。

真实场景测试

使用确定性 OpenAI 兼容测试配置(两个模型,selectedType: openai)启动 ACP 服务器,发送 initialize + session/new,检查模型列表。

修改前:coder-model(qwen-oauth) 出现在 availableModelsconfigOptions.model.options 的首位(bug 复现)。

修改后:coder-model(qwen-oauth) 从两个列表中消失。当前模型仍为 qwen3.6-27b(openai)——未变,符合预期。

Qwen Code · qwen3.8-max-preview

Reviewed at acceaa06b3fd64f6f325c7eb9df186384233f39e · re-run with @qwen-code /triage

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Confidence: 5/5 — clean fix for a real, reproduced bug; minimal diff, thorough tests, before/after confirms the fix.

This is exactly the kind of PR you want to see: a real user hit a real bug (#7433), the fix is 15 lines of production code that mirrors what the interactive model picker already does, and the tests cover both the happy path and the edge case (OAuth sessions keep their model, direct requests for the hidden route still get a structured error). The before/after reproduction confirms the fix works end-to-end. Nothing to cut, nothing missing, nothing unrelated in the diff.

中文说明

置信度:5/5 — 对已复现的真实 bug 的干净修复;最小化 diff,充分的测试,before/after 确认修复有效。

这正是理想的 PR:真实用户遇到了真实 bug(#7433),修复仅 15 行生产代码,与交互式模型选择器已有的行为保持一致,测试覆盖了正常路径和边界情况(OAuth 会话保留其模型,直接请求隐藏路由仍返回结构化错误)。before/after 复现确认修复端到端有效。无需删减,无遗漏,diff 中无无关改动。

Qwen Code · qwen3.8-max-preview

Reviewed at acceaa06b3fd64f6f325c7eb9df186384233f39e · re-run with @qwen-code /triage

@qwen-code-ci-bot qwen-code-ci-bot 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.

LGTM, looks ready to ship. ✅

@qwen-code-ci-bot qwen-code-ci-bot 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

@gwinthis gwinthis 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.

Review: APPROVE (C=0)

Summary

Clean fix (+132/-12) hiding the discontinued qwen-oauth model from non-OAuth sessions while keeping it visible for existing qwen-oauth sessions. The auth error path stays structured even when requesting a discontinued route directly.

Design

  • Non-OAuth sessions (e.g., openai auth): discontinued model hidden from selector, not advertised
  • Existing qwen-oauth sessions: model still visible and usable
  • Auth error path: requesting discontinued route directly still returns structured error (tested in integration test)

Test Coverage

Parameterized tests cover both auth types:

  • openai auth: only qwen3.6-27b(openai) visible, discontinued model hidden
  • qwen-oauth auth: both coder-model(qwen-oauth) and qwen3.6-27b(openai) visible

Integration test verifies the auth-required error path stays structured when requesting the discontinued route.

Pattern

Graceful deprecation by auth context: When deprecating a model tied to a specific auth type, hide it from sessions using other auth types (prevents confusion) but keep it for sessions already using that auth type (prevents breakage). The error path for direct requests stays structured regardless.

中文说明

评审:APPROVE (C=0)

概要

干净修复(+132/-12):对非 OAuth 会话隐藏已废弃的 qwen-oauth 模型,对现有 qwen-oauth 会话保持可见。

模式

按认证上下文优雅废弃: 废弃与特定认证类型绑定的模型时,对其他认证类型的会话隐藏(防混淆),对该类型会话保留(防中断)。直接请求的错误路径保持结构化。

— qwen3.7-max via Qwen Code /review

@wenshao
wenshao added this pull request to the merge queue Jul 23, 2026
Merged via the queue into QwenLM:main with commit 442a697 Jul 23, 2026
72 checks passed
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.

4 participants