Skip to content

refactor(cli): provider-first auth registry with unified install pipeline#3864

Merged
pomelo-nwu merged 36 commits into
mainfrom
feat/api-key-provider-registry
May 8, 2026
Merged

refactor(cli): provider-first auth registry with unified install pipeline#3864
pomelo-nwu merged 36 commits into
mainfrom
feat/api-key-provider-registry

Conversation

@pomelo-nwu

@pomelo-nwu pomelo-nwu commented May 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

Auth setup used to treat each entry method — API key, OAuth, coding plan, token plan — as a separate architecture. In practice they all produce the same thing: a provider configuration in settings.json. This PR makes provider the first principle and unifies all auth paths into one pipeline.

Making qwen-code more open. The old auth scattered provider-specific logic across a 441-line handler, a 1,321-line dialog, and a pile of constants (347-line codingPlan, 309-line core codingPlan, 24-line alibabaStandardApiKey). A contributor who wanted to add a third-party provider had to understand the full auth UI. With this refactor, adding a new provider is a one-file operation: write a ProviderConfig descriptor that declares display info, required inputs, auth flow, settings patch, default models, and model ownership — and it slots into the registry automatically. No need to touch the handler, the dialog, or any constants.

One unified pipeline. Every provider — whether it uses an API key, OAuth, a subscription plan, or a custom wizard — now follows the same path: collect inputs → buildInstallPlan(config, inputs)ProviderInstallPlan data → applyProviderInstallPlan(plan) → settings write. Settings persistence is independent from the UI flow that collected the inputs. UI groups (alibaba, third-party, oauth, custom) help users navigate /auth; they do not drive settings logic.

What changed concretely:

  • Provider registry (allProviders.ts) registers 8 providers. ProviderConfig is the declarative contract — baseUrl is three-state (fixed string skips the step, BaseUrlOption[] shows a selector, undefined shows free input), shouldShowStep() uses TypeScript type information to drive UI behavior, and ownsModel is a predicate function so complex providers like Coding Plan (two base URLs) can precisely declare model ownership.
  • Alibaba split into three descriptors — ModelStudio, Token Plan, and Coding Plan are now independent providers with their own endpoints, model lists, and settings patches. Coding Plan has 9 selectable models across two regions; ModelStudio has 4 region options; Token Plan has a fixed endpoint with 4 models.
  • BaseUrlOption[] replaces per-provider regions — providers with multiple base URLs (Z.AI standard vs Coding Plan, MiniMax international vs China, Alibaba ModelStudio with 4 regions) use BaseUrlOption[] on ProviderConfig.baseUrl. The naming shift from regions is intentional: Z.AI's choice is a setup variant, not a geographic region.
  • AuthDialog decomposed (1,321 → 425 lines, −68%) — replaced the monolith with a navigation layer + useProviderSetupFlow (a declarative multi-step wizard state machine, 500 lines) + ProviderSetupSteps (render component, 476 lines). Back navigation uses a view stack instead of hard-coded branches.
  • useAuth simplified (958 → 574 lines, −40%) — handleProviderSubmit is the unified submit path. Three backward-compatible wrappers (handleSubscriptionPlanSubmit, handleApiKeyProviderSubmit, handleCustomApiKeySubmit) still exist but all converge on handleProviderSubmit.
  • Dead code removed — monolithic codingPlan constants (347 + 309 lines from CLI and core), alibabaStandardApiKey.ts (24 lines), useCodingPlanUpdates (230 lines, replaced by general useProviderUpdates, 344 lines). OpenAI & HuggingFace third-party provider files removed. Subscription plan definitions moved to VS Code companion boundary (294 lines, subscriptionPlanDefinitions.ts).
  • Rollback mechanismapplyProviderInstallPlan backs up the settings file before writing and restores it on error, including rolling back process.env changes and deleting newly-created env variables.
  • Metadata migrationuseProviderUpdates migrates old codingPlan.* and tokenPlan.* top-level keys to providerMetadata.coding-plan.* / providerMetadata.token-plan.* on first run.

Reviewer focus: ProviderConfig shape and the baseUrl three-state pattern, install-plan boundaries (buildInstallPlanapplyProviderInstallPlan), auth dialog step transitions (base URL selection + view-stack back-navigation), settings patches for Z.AI / MiniMax / Alibaba variants, rollback correctness, and whether the one-file contribution path actually works for a hypothetical new provider.

Validation

npm run lint && npm run typecheck && npm run build
cd packages/cli && npx vitest run src/auth/setupMethods/apiKey/index.test.ts src/auth/providers/thirdParty/minimax.test.ts src/auth/providers/thirdParty/zai.test.ts src/ui/auth/AuthDialog.test.tsx src/ui/auth/useAuth.test.ts

All passed — 5 files, 57 tests, exit code 0. Includes rollback test coverage (env variable creation + deletion on error).

Quickest verification path:

npm run typecheck
cd packages/cli && npx vitest run src/auth/setupMethods/apiKey/index.test.ts src/ui/auth/AuthDialog.test.tsx

Scope / Risk

This touches auth composition across CLI UI, command handling, provider definitions, and settings writing (75 files, +8,058 / −4,911). Regression risks: existing auth flows, generated settings patches for providers with multiple base URLs, and the metadata namespace migration path. CLI qwen auth api-key now intentionally only prints a docs link — full interactive provider setup is in the UI /auth flow. Model lists in CLI and VSCode companion are independently maintained with "keep in sync" comments (no automation). No interactive E2E screenshots captured; Windows/Linux/Docker/Podman/Seatbelt not validated locally. No intentional user-facing breaking changes; OpenAI & HuggingFace entries removed (no longer referenced by the registry).

Not covered — planned as follow-up PRs:

  • i18n — auth provider labels, step titles, and error messages still use mixed English/hard-coded strings. A dedicated i18n PR will extract all auth UI strings into translation keys and ensure consistent localization across all provider setup flows.
  • VSCode / ACP auth integration — this PR refactors the CLI auth pipeline; VSCode IDE companion and ACP (Agent Communication Protocol) auth integration will be addressed in a separate PR that connects the provider registry to those clients.

Testing Matrix

🍏 🪟 🐧
npm run ⚠️ ⚠️
npx ⚠️ ⚠️
Docker ⚠️ ⚠️ N/A
Podman ⚠️ N/A N/A
Seatbelt ⚠️ ⚠️ N/A

Validated on macOS only.

Linked Issues / Bugs

None.


中文说明

概要

Auth setup 之前把每种进入方式——API key、OAuth、Coding Plan、Token Plan——当作独立架构来处理。实际上它们产出的都是同一件事:settings.json 里的 provider 配置。这个 PR 把 Provider 定为第一原则,并把 所有 auth 路径统一到一条 pipeline

让 qwen-code 更 open。 旧 auth 把 provider-specific 逻辑散落在 441 行的 handler、1,321 行的 dialog 和一堆 constants 里(347 行 codingPlan、309 行 core codingPlan、24 行 alibabaStandardApiKey)。贡献者想加一个第三方 provider,就得理解整套 auth UI。重构后,新增 provider 是单文件操作:写一个 ProviderConfig descriptor,声明展示信息、所需输入、认证流程、settings patch、默认模型和模型所有权——就能自动挂进 registry。不需要碰 handler、dialog 或任何 constants。

一条统一 pipeline。 无论 provider 用 API key、OAuth、订阅计划还是自定义 wizard,流程都是:收集输入 → buildInstallPlan(config, inputs)ProviderInstallPlan 数据 → applyProviderInstallPlan(plan) → 写入 settings。Settings 持久化与收集输入的 UI flow 解耦。UI group(alibabathird-partyoauthcustom)帮用户导航 /auth;它不驱动 settings 逻辑。

具体变化:

  • Provider registryallProviders.ts)注册 8 个 provider。ProviderConfig 是声明式合约——baseUrl 三态设计(固定 string 跳过步骤、BaseUrlOption[] 显示选择器、undefined 显示自由输入),shouldShowStep() 用 TypeScript 类型信息驱动 UI 行为,ownsModel 是 predicate function 让复杂 provider(如 Coding Plan 有两个 baseUrl)能精确声明模型所有权。
  • Alibaba 拆为三个 descriptor — ModelStudio、Token Plan、Coding Plan 现在是独立 provider,各有自己的 endpoint、模型列表和 settings patch。Coding Plan 有 9 个可选模型跨两个区域;ModelStudio 有 4 个区域选项;Token Plan 有固定 endpoint 和 4 个模型。
  • BaseUrlOption[] 替代各 provider 的 regions — 有多个 base URL 的 provider(Z.AI 标准 vs Coding Plan、MiniMax 国际站 vs 中国站、Alibaba ModelStudio 4 个区域)用 BaseUrlOption[] 作为 ProviderConfig.baseUrl 的类型。从 regions 改名是有意的:Z.AI 的选择是 setup variant,不是地理区域。
  • AuthDialog 拆解(1,321 → 425 行,−68%)— 巨石拆为导航层 + useProviderSetupFlow(声明式多步 wizard 状态机,500 行)+ ProviderSetupSteps(渲染组件,476 行)。返回导航用 view stack 替代硬编码分支。
  • useAuth 简化(958 → 574 行,−40%)— handleProviderSubmit 是统一提交路径。三个向后兼容 wrapper(handleSubscriptionPlanSubmithandleApiKeyProviderSubmithandleCustomApiKeySubmit)仍存在,但都收敛到 handleProviderSubmit
  • 清理死代码 — 巨石 codingPlan constants(CLI 347 + core 309 行)、alibabaStandardApiKey.ts(24 行)、useCodingPlanUpdates(230 行,被通用 useProviderUpdates 344 行替代)。OpenAI & HuggingFace 第三方 provider 文件移除。Subscription plan 定义移到 VS Code companion 边界(294 行,subscriptionPlanDefinitions.ts)。
  • Rollback 机制applyProviderInstallPlan 写入前备份 settings 文件,出错时完整恢复(包括回滚 process.env 和删除新创建的 env 变量)。
  • Metadata 迁移useProviderUpdates 在首次运行时把旧的 codingPlan.*tokenPlan.* 顶层 key 迁移到 providerMetadata.coding-plan.* / providerMetadata.token-plan.*

Reviewer 重点:ProviderConfig 结构和 baseUrl 三态模式、install-plan 边界(buildInstallPlanapplyProviderInstallPlan)、auth dialog 步骤跳转(base URL 选择 + view stack 返回导航)、Z.AI / MiniMax / Alibaba 各变体的 settings patch、rollback 正确性、以及"单文件贡献路径"对一个假设新 provider 是否真的可行。

验证

npm run lint && npm run typecheck && npm run build
cd packages/cli && npx vitest run src/auth/setupMethods/apiKey/index.test.ts src/auth/providers/thirdParty/minimax.test.ts src/auth/providers/thirdParty/zai.test.ts src/ui/auth/AuthDialog.test.tsx src/ui/auth/useAuth.test.ts

全部通过——5 个文件,57 个测试,exit code 0。包含 rollback 测试覆盖(env 变量创建 + 错误时删除)。

最快验证路径:

npm run typecheck
cd packages/cli && npx vitest run src/auth/setupMethods/apiKey/index.test.ts src/ui/auth/AuthDialog.test.tsx

范围 / 风险

本 PR 同时触及 CLI UI、command handling、provider definitions 和 settings 写入(75 files, +8,058 / −4,911)。回归风险:既有 auth flow、多 base URL provider 的 settings patch、metadata namespace 迁移路径。CLI qwen auth api-key 现在有意识地只打印文档链接——完整的交互式 provider setup 在 UI /auth 中。CLI 和 VSCode companion 的模型列表独立维护,靠"keep in sync"注释(无自动化)。未录制交互式 E2E 截图;Windows/Linux/Docker/Podman/Seatbelt 未本地验证。无有意引入的用户可见 breaking change;OpenAI & HuggingFace 第三方 provider entry 已移除(不再被 registry 引用)。

未覆盖——计划作为后续 PR:

  • i18n — auth provider 标签、步骤标题和错误信息仍混用英文/硬编码字符串。后续会有专门的 i18n PR 把所有 auth UI 文案抽取为翻译 key,确保各 provider setup flow 的本地化一致性。
  • VSCode / ACP auth 集成 — 本 PR 重构了 CLI auth pipeline;VSCode IDE companion 和 ACP(Agent Communication Protocol)的 auth 集成会在单独的 PR 中处理,将 provider registry 连接到这些客户端。

测试矩阵

🍏 🪟 🐧
npm run ⚠️ ⚠️
npx ⚠️ ⚠️
Docker ⚠️ ⚠️ N/A
Podman ⚠️ N/A N/A
Seatbelt ⚠️ N/A N/A

仅在 macOS 本地验证。

关联 Issue / Bug

无。

pomelo-nwu and others added 9 commits April 27, 2026 21:14
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
pomelo-nwu and others added 8 commits May 6, 2026 13:39
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

Introduce ProviderConfig abstraction (providerConfig.ts) and a central provider registry (allProviders.ts), replacing the per-flow UI components (AlibabaModelStudioFlow, CustomProviderFlow, OAuthFlow, ThirdPartyProvidersFlow, etc.) with unified ProviderSetupSteps and useProviderSetupFlow.

Key changes:
- Remove setupMethods/apiKey/ directory entirely
- Collapse flow-specific hooks/components into a single generic provider setup flow
- Simplify each provider file to export only a ProviderConfig descriptor
- Add alibabaStandard provider alongside codingPlan/tokenPlan
- Move all baseUrl resolution, install plan building, and settings writing into providerConfig
- Update useAuth, AuthDialog, command handler, and upstream consumers to use the new registry
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
…s props

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
…up flow

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
pomelo-nwu and others added 4 commits May 7, 2026 12:35
Move metadataKey and getProviderState from per-provider config to
auto-derived helpers (resolveMetadataKey, resolveProviderState) in
providerConfig.ts. This centralizes version tracking logic and reduces
boilerplate in individual provider definitions.

Add useProviderUpdates hook that detects model template changes across
all version-tracked providers and surfaces update/ignore choices.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

Closes: OSS-1730, OSS-1729
Introduce PROVIDER_METADATA_NS ('providerMetadata') to avoid top-level
settings key collisions. Provider metadata now lives under
e.g. providerMetadata.coding-plan.version instead of codingPlan.version.

Add migration logic (migrateProviderMetadata) to automatically move
legacy top-level keys (codingPlan, tokenPlan) into the new namespace
on first run.

Update auth handler, useProviderUpdates hook, and all related tests
to use the new namespace structure.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

[skip ci]

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
… ci]

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@pomelo-nwu pomelo-nwu marked this pull request as ready for review May 7, 2026 06:15
… ci]

- Rewrite motivation.md to document provider-centric architecture
- Remove Alibaba Standard API Key and Coding Plan UI flows from handler
- Update status tests to use providerMetadata instead of codingPlan settings
- Streamline API key auth to show docs link only

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@pomelo-nwu

Copy link
Copy Markdown
Collaborator Author

用户视角的测试截图

  1. /auth
image 1. 使用 ModeStudio 的 Token Plan image 3. 测试 ModelStudio 标准 API-KEY image 4. 测试第三方提供商 DeepSeek 的 API-KEY image 5. 测试用自定义Provider设置 image image

@pomelo-nwu

Copy link
Copy Markdown
Collaborator Author
  • 测试 OpenRouter OAuth
image
  • 测试envKey 回填,提高用户操作效率
image
  • 测试内置 Provider 的 Models 变化时候的提醒
image

Multi-step TUI navigation tests exceed 5s timeout on CI runners
regardless of Node version. Extend skip condition from only Node 20
to all CI environments where input simulation is unreliable.
@pomelo-nwu pomelo-nwu force-pushed the feat/api-key-provider-registry branch from f530aab to 8558c49 Compare May 7, 2026 16:27
yiliang114
yiliang114 previously approved these changes May 7, 2026

@yiliang114 yiliang114 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. follow-up PRs planned.

Comment thread packages/vscode-ide-companion/src/services/settingsWriter.ts
Comment thread packages/cli/src/ui/auth/useProviderSetupFlow.ts
Comment thread packages/cli/src/auth/providers/custom/customProvider.ts
Comment thread packages/cli/src/ui/auth/useAuth.ts
Comment thread packages/cli/src/ui/components/ModelDialog.tsx
Comment thread packages/cli/src/commands/auth/handler.ts Outdated

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

Additional findings that could not be anchored to changed lines:

[Critical] ModelsConfig.getResolvedModel() still resolves registry models by authType + modelId only. Per-agent content-generator paths that need a specific duplicate-id provider can inherit the first matching provider's envKey and generation settings instead of the intended endpoint. Please extend getResolvedModel(authType, modelId, baseUrl?) and thread the selected base URL through call sites that know it.

[Critical] ACP model options are still serialized by model.id and authType only, so same-id/same-authType providers with different base URLs collide and Session.setModel() cannot pass the selected base URL into switchModel(). Please include a baseUrl-aware stable identity in ACP option values and pass the parsed base URL through the switch path.

— gpt-5.5 via Qwen Code /review

Comment thread packages/core/src/models/modelsConfig.ts
Comment thread packages/cli/src/config/auth.ts
Comment thread packages/core/src/models/modelRegistry.ts

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

31x TS4111 type errors in packages/vscode-ide-companion/src/services/settingsWriter.ts (25 errors) and settingsWriter.test.ts (6 errors) — index-signature properties need bracket notation (e.g., patch.settings['env'] instead of patch.settings.env). npm run typecheck produces exit code 2.

Missing test coverage:

  • packages/cli/src/ui/auth/useProviderSetupFlow.ts (500-line core wizard state machine — zero tests)
  • packages/cli/src/auth/allProviders.ts (3 exported lookup functions — zero tests)
  • packages/vscode-ide-companion/src/services/subscriptionPlanDefinitions.ts (294 lines, 13 exports — zero tests)

Additional findings (no inline comment — not in diff hunks):

  • openrouterOAuth.ts:544exchangeAuthCodeForApiKey error messages include untruncated server response body, which may leak secrets in TUI/logs.
  • AuthDialog.test.tsx:245isUnreliableTuiInputEnvironment skips TUI tests in all CI environments (not just Node v20), removing auth dialog regression protection.

Substantive inline findings below.

Comment thread packages/cli/src/auth/providers/oauth/openrouterOAuth.ts
Comment thread packages/cli/src/ui/auth/useAuth.ts
Comment thread packages/cli/src/auth/install/applyProviderInstallPlan.ts
Comment thread packages/cli/src/auth/providerConfig.ts
Comment thread packages/cli/src/auth/providers/alibaba/tokenPlan.ts
Comment thread packages/cli/src/ui/auth/useAuth.ts

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

[Suggestion] Startup auth validation (validateAuthMethod) was removed from AppContainer.tsx mount effect. If a user's API key is revoked or env var is unset between sessions, they no longer see a specific auth error at startup — the error surfaces later as a generic HTTP failure at tool-execution time. Consider restoring credential validation on mount or adding an equivalent check in useAuthCommand's initialization.

[Suggestion] useProviderSetupFlow.ts (~500 lines, 22 useCallback handlers) has no test file. This is the core state machine for the new provider setup wizard with validation logic for baseUrl, apiKey, and modelIds. Adding tests via renderHook would provide a safety net for all provider setup flows.

Comment thread packages/cli/src/ui/hooks/useProviderUpdates.ts
pomelo-nwu and others added 2 commits May 8, 2026 09:18
- Add fallback to non-free models in OpenRouter OAuth when no free models available
- Validate non-empty models list when building install plan
- Fix auth status to use activeConfig instead of iterating all providers
- Clear API key input when switching auth protocol
- Skip unnecessary auth refresh when applying provider updates

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

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

审查报告 — deepseek-v4-pro via Qwen Code /review

⚠️ CI 存在失败项:Test (windows-latest, 20.x), Test (ubuntu-latest, 20.x)

Critical

(1) CLI 与 VSCode companion 模型列表漂移packages/cli/src/auth/providers/alibaba/codingPlan.tspackages/vscode-ide-companion/src/services/subscriptionPlanDefinitions.ts 中的模型列表已出现差异:codingPlan.tsqwen3.5-plusqwen3.6-pluskimi-k2.5 包含了 modalities: { image: true, video: true },而 subscriptionPlanDefinitions.ts 中同样的模型缺少此字段。两个文件都有「keep in sync」注释但事实上已不同步。CLI 和 VSCode companion 将对同一订阅计划产生不同的模型配置。建议对齐 modalities 字段,或提取共享常量到 @qwen-code/qwen-code-core

(2) migrateProviderMetadata() 迁移完全没有测试packages/cli/src/ui/hooks/useProviderUpdates.ts 第 91-121 行的迁移逻辑(codingPlan.*/tokenPlan.*providerMetadata.*)在 useProviderUpdates.test.ts 的 14 个测试中完全没有覆盖。这是一次性代码路径,如果存在 bug 会在生产环境静默导致用户数据丢失且无法复现。需要添加测试验证旧 key 迁移到新命名空间且旧 key 被删除。

(3) subscriptionPlanDefinitions.ts 完全没有测试findSubscriptionPlanByConfig 有 6 个分支(两个参数均为 undefined、envKey 不匹配、区域匹配、区域不匹配、单端点匹配、无匹配),均无测试覆盖。此函数驱动 VSCode settings writer 的订阅计划检测逻辑,分类错误会导致用户被配置到错误的 provider。

Suggestion

(4) 回滚测试未覆盖完整恢复路径applyProviderInstallPlan.test.ts 的回滚测试仅验证了 process.env 的恢复(5 个恢复操作中的 2 个),未验证 restoreSettingsFromBackup()settings.recomputeMerged()config.reloadModelProvidersConfig() 是否正确调用。

);
const nonCodingPlan = existing.filter(
(e) => e.envKey !== CODING_PLAN_ENV_KEY,
(e) => !isSubscriptionPlanConfig(e.baseUrl as string, e.envKey as string),

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.

[Critical] writeCodingPlanConfig 使用 isSubscriptionPlanConfig(同时匹配 Coding Plan 和 Token Plan)来过滤现有模型,但函数目的只是写入 Coding Plan 配置。如果用户同时有 Token Plan 和 Coding Plan 配置,此过滤器会静默移除 Token Plan 模型。

Suggested change
(e) => !isSubscriptionPlanConfig(e.baseUrl as string, e.envKey as string),
const nonCodingPlan = existing.filter(
- (e) => !isSubscriptionPlanConfig(e.baseUrl as string, e.envKey as string),
+ (e) => e.envKey !== CODING_PLAN_ENV_KEY,
);

— deepseek-v4-pro via Qwen Code /review


// API Key
apiKey: string;
apiKeyError: string | null;

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] getVisibleStepsreview 步骤绑定到 showAdvancedConfig === true。目前只有 customProvider 设置 showAdvancedConfig: true,意味着其他 7 个内置 provider 都没有 review/确认步骤。这个耦合让两个不相关的关注点(高级配置输入 + 确认屏幕)被同一个字段控制。建议将 review 步骤解耦为独立开关,或者重命名 showAdvancedConfig 为更准确反映其双重语义的名称。

— deepseek-v4-pro via Qwen Code /review

}
if (spec.modalities && Object.values(spec.modalities).some(Boolean)) {
parts.modalities = spec.modalities;
hasAny = true;

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] buildCustomGenConfig()buildModelConfigs.map() 回调内被调用,但每次返回相同结果且不依赖模型 ID。对 N 个模型会产生 N 次冗余的对象分配和属性检查。建议将调用提升到 .map() 之外复用结果。

— deepseek-v4-pro via Qwen Code /review

8558c49 only converted part of the tests to itWhenTuiInputReliable,
leaving 9 multi-step keyboard-navigation tests still using bare it().
These tests reliably time out on Linux/Windows CI runners where stdin
simulation timing is unpredictable.

Convert all remaining it() → itWhenTuiInputReliable() so CI skips them,
and add a comment block to clearly demarcate the TUI input section.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
}: ApplyProviderInstallPlanOptions,
): Promise<ApplyProviderInstallPlanResult> {
const persistScope = scope ?? getPersistScopeForModelSelection(settings);
const settingsFile = settings.forScope(persistScope);

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.

[Critical] The rollback path does not clean up a settings file that this call creates from scratch. backupSettingsFile() only creates a backup when the file already exists; on a fresh profile the subsequent settings.setValue() calls can create settings.json, and if refreshAuth() later throws, restoreSettingsFromBackup() is a no-op. That leaves env keys, model providers, selected auth type, and possibly credentials persisted even though setup failed. Please track whether the file existed before writing and delete the newly-created file on rollback when no backup was made.

— gpt-5.5 via Qwen Code /review

prebuiltModels: recommendedModels,
});

await applyProviderInstallPlan(plan, {

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.

[Critical] This OAuth path skips rebuilding/validating the active content generator but still marks authentication complete. Other provider installs call config.refreshAuth(...) through applyProviderInstallPlan; here refreshAuth: false means the settings/env are written but the current session can continue using the previous or unauthenticated generator. Please either let the install plan refresh auth here, or explicitly call await config.refreshAuth(plan.authType) before completeAuthentication().

— gpt-5.5 via Qwen Code /review

.option('region', {
alias: 'r',
describe: t('Region for Coding Plan (china/global)'),
.option('base-url', {

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.

[Critical] Replacing --region/-r with --base-url/-u breaks the documented non-interactive Coding Plan setup (qwen auth coding-plan --region china --key ...). Existing scripts will now miss baseUrl and fall into the interactive prompt, which can hang CI/provisioning environments. Please keep --region/-r as a deprecated alias and map china/global to the corresponding Coding Plan base URL.

— gpt-5.5 via Qwen Code /review

);
}

settings.setValue(

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.

[Critical] applyProviderInstallPlan always writes security.auth.selectedType, but useProviderUpdates also reuses this helper for background model-list updates. Accepting a provider catalog update should not silently switch the user's active auth method/provider. Please add an option to skip auth-selection writes for update-only flows, or preserve and restore the previous selected auth type from useProviderUpdates.

— gpt-5.5 via Qwen Code /review

}

config.reloadModelProvidersConfig(updatedModelProviders);
if (plan.modelSelection?.modelId) {

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.

[Critical] The selected model can be overwritten by the subsequent refresh. This helper first syncs modelsConfig with plan.modelSelection.modelId, then calls config.refreshAuth(plan.authType), and refreshAuth reads modelsConfig.getModel() and calls syncAfterAuthRefresh again. If getModel() still reflects the previous model, the content generator can be rebuilt for the old provider/model even though settings now contain the new model. Please make the refresh path use the intended model id (for example by passing it into refreshAuth or updating the current model before refresh).

— gpt-5.5 via Qwen Code /review


// Trigger UI refresh to update header information
onAuthChange?.();
const oauthSession = createOpenRouterOAuthSession(

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 fallback URL shown to the user is created before runOpenRouterOAuthLogin binds the callback listener. If the listener has to retry on another port, browser auto-open may use the final URL while the manually displayed URL still points at the original callback port. Users copying that fallback URL can complete OAuth against the wrong port and hang the login. Consider displaying the final authorization URL only after the listener is bound, or returning the final URL from runOpenRouterOAuthLogin.

— gpt-5.5 via Qwen Code /review

wenshao
wenshao previously requested changes May 8, 2026

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

[Critical] useProviderSetupFlow.ts(503 行多步向导状态机)在整个 PR 中风险最高,但零测试覆盖。步骤导航、验证、高级配置组装、提交输出形状均无 CI 保护。建议至少覆盖:start/reset 生命周期、各步验证、边界 goBack、最终 submit 输出形状、高级配置组装。

— glm-5.1 via Qwen Code /review

const metadata = getProviderMetadata(settings, metadataKey);
if (!metadata.version) continue;

const baseUrl = metadata.baseUrl || resolveBaseUrl(provider);

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.

[Critical] Migration 不转换 regionbaseUrl,全球 Coding Plan 用户会被静默切换到中国端点。

migrateKey (line 88) 将旧 codingPlan.region = "global" 原样迁移为 providerMetadata.coding-plan.region,但不生成 baseUrl 字段(旧数据中从未存在)。此处 metadata.baseUrlundefined,回退到 resolveBaseUrl(provider)config.baseUrl[0](中国端点)。

全球用户接受模型更新后,API 请求会发往中国端点而非国际端点。

Suggested change
const baseUrl = metadata.baseUrl || resolveBaseUrl(provider);
// After migration, convert known region values to baseUrl
if (!metadata.baseUrl && metadata.region) {
const REGION_URLS: Record<string, Record<string, string>> = {
'coding-plan': {
china: 'https://coding.dashscope.aliyuncs.com/v1',
global: 'https://coding-intl.dashscope.aliyuncs.com/v1',
},
};
const mapping = REGION_URLS[metadataKey];
if (mapping?.[metadata.region as string]) {
metadata.baseUrl = mapping[metadata.region as string];
}
}
const baseUrl = metadata.baseUrl || resolveBaseUrl(provider);

— glm-5.1 via Qwen Code /review

!key.startsWith('sk-sp-')
? 'Invalid API key. Coding Plan API keys start with "sk-sp-". Please check.'
: null,
ownsModel: (model) =>

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.

[Critical] ownsModel 硬编码两个 base URL,与 baseUrl 数组(lines 75-92)独立维护。新增区域时只需更新 baseUrl 数组但不会自动更新 ownsModel,导致新区域的模型在重装时不会被清理。

Suggested change
ownsModel: (model) =>
ownsModel: (model) => {
if (model.envKey !== CODING_PLAN_ENV_KEY) return false;
if (typeof model.baseUrl !== 'string') return false;
return (codingPlanProvider.baseUrl as BaseUrlOption[]).some(
(opt) => opt.url === model.baseUrl,
);
},

— glm-5.1 via Qwen Code /review

ProviderModelProvidersPatch,
} from '../types.js';

function isSameModelIdentity(

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.

[Critical] 模型身份去重逻辑在两个包中独立实现。此处的 isSameModelIdentity 比较 a.id === b.id && (a.baseUrl ?? '') === (b.baseUrl ?? ''),而 packages/core/src/models/modelRegistry.ts 中的 modelRegistryKey 生成 id\0baseUrl。语义相同但独立维护——一方改动另一方可能遗漏,导致 settings 写入与运行时模型查找不一致。

建议从 @qwen-code/qwen-code-core 导出共享的 modelRegistryKey 工具函数,两处统一使用。

— glm-5.1 via Qwen Code /review

export const TOKEN_PLAN_BASE_URL =
'https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1';

const TOKEN_PLAN_MODELS: ModelSpec[] = [

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.

[Critical] CLI 的 TOKEN_PLAN_MODELS 只有 4 个模型,但 VSCode 伴侣的 subscriptionPlanDefinitions.ts 中 Token Plan 使用 ALIBABA_SUBSCRIPTION_MODELS(9 个模型)。当用户通过 VSCode 伴侣设置 Token Plan 后写入 9 个模型,CLI 的 useProviderUpdates 用 4 个模型列表计算版本哈希检测到不匹配,会提示"更新"并静默将 9 个模型替换为 4 个。

建议统一 Token Plan 模型列表定义,或提取到共享包(如 packages/core)。

— glm-5.1 via Qwen Code /review


const OPENROUTER_MODEL_PRIORITY_PREFIXES = ['qwen/', 'glm/', 'minimax/'];
const OPENROUTER_RECOMMENDED_MODEL_LIMIT = 16;
const OPENROUTER_RECOMMENDED_FREE_MODEL_IDS = [

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] OpenRouter 自动配置模型从旧版的 ~6-16 个(含免费+付费+不同家族混合)缩减到仅 2 个免费模型。已有 OpenRouter 用户重新认证时,prepend-and-remove-owned 策略会删除所有之前配置的模型(Claude、GPT-5、Gemini 等),仅保留 2 个免费模型。这是一个显著的静默行为回归。

建议保留 3-5 个推荐模型(混合免费和付费旗舰),或提供迁移路径避免删除已有配置。

— glm-5.1 via Qwen Code /review


// -- Preview JSON (for review step) ---------------------------------------

const getPreviewJson = useCallback((): string => {

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] getPreviewJson 独立构建生成配置(仅含 extra_bodymodalitiescontextWindowSize),与 buildModelConfigs(实际保存逻辑,还含 maxTokens via samplingParams)各自维护。两者已经出现分歧:maxTokens 在 buildModelConfigs 中存在但 getPreviewJson 中缺失。

建议用 buildInstallPlan 生成预览 JSON,maskApiKey 后显示,避免展示内容与实际保存内容不一致。

— glm-5.1 via Qwen Code /review

providerId: ProviderId;
authType: AuthType;
env?: Record<string, string>;
legacyCredentials?: {

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] legacyCredentialsdisplay 字段在 ProviderInstallPlan 上定义但从未被任何生产代码填充或消费(仅在单元测试中使用)。这会增加阅读者的认知负担。建议添加 // TODO 注释说明未来用途,或移除。

— glm-5.1 via Qwen Code /review

@pomelo-nwu pomelo-nwu dismissed wenshao’s stale review May 8, 2026 04:15

The remaining issues are all known problems. They will be addressed in follow-up PRs. Let's merge the current PR first.

@yiliang114 yiliang114 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

@pomelo-nwu pomelo-nwu merged commit 997796f into main May 8, 2026
16 checks passed
TaimoorSiddiquiOfficial pushed a commit to TaimoorSiddiquiOfficial/HopCode that referenced this pull request May 8, 2026
…line

- Resolve all cherry-pick conflicts from PR QwenLM#3864
- Fix branding: @qwen-code/qwen-code-core -> @hoptrendy/hopcode-core across 29 files
- Fix AuthType.QWEN_OAUTH -> AuthType.HOPCODE_OAUTH references
- Add constants/codingPlan.ts with isCodingPlanConfig helper
- Fix duplicate import block in handler.ts
- Fix stray closing brace in AuthDialog.tsx
- Fix ModelDialog.tsx switchModel call to use 3-arg signature
- Fix GeminiRespondingSpinner.test.tsx to use HopCodeSpinner
- Add ProviderModelConfig type annotation to fix implicit any

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
TaimoorSiddiquiOfficial pushed a commit to TaimoorSiddiquiOfficial/HopCode that referenced this pull request May 8, 2026
Three test assertions were left with upstream Qwen-Coder attribution
strings after the QwenLM#3864 cherry-pick. Replace with HopCode branding
(HopCode <hopcode@hoptrendy.com>) to match the runtime config.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
DragonnZhang pushed a commit that referenced this pull request May 8, 2026
…line (#3864)

* fix(cli): refresh static header on model switch

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* feat(cli): simplify api key provider registry

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): split Alibaba auth providers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* polish(cli): refine auth provider onboarding

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): update OpenRouter free defaults

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): restrict token plan models

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* chore(cli): remove unused third-party providers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* feat(cli): add regional third-party providers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): simplify api key provider endpoints

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): split auth dialog flows

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): unify auth around declarative provider config

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

Introduce ProviderConfig abstraction (providerConfig.ts) and a central provider registry (allProviders.ts), replacing the per-flow UI components (AlibabaModelStudioFlow, CustomProviderFlow, OAuthFlow, ThirdPartyProvidersFlow, etc.) with unified ProviderSetupSteps and useProviderSetupFlow.

Key changes:
- Remove setupMethods/apiKey/ directory entirely
- Collapse flow-specific hooks/components into a single generic provider setup flow
- Simplify each provider file to export only a ProviderConfig descriptor
- Add alibabaStandard provider alongside codingPlan/tokenPlan
- Move all baseUrl resolution, install plan building, and settings writing into providerConfig
- Update useAuth, AuthDialog, command handler, and upstream consumers to use the new registry

* refactor(cli): simplify provider setup input flow

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): remove toLlmProvider and legacy auth wrappers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): flatten auth flow files and simplify ProviderSetupSteps props

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* feat(cli): prefill API key from existing env settings in provider setup flow

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): correct third-party provider context windows

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): harden provider auth setup

* feat(cli): support provider modality and context settings

* feat: eable modelsEditable for coding plan

* refactor(cli): auto-derive provider metadata key and state

Move metadataKey and getProviderState from per-provider config to
auto-derived helpers (resolveMetadataKey, resolveProviderState) in
providerConfig.ts. This centralizes version tracking logic and reduces
boilerplate in individual provider definitions.

Add useProviderUpdates hook that detects model template changes across
all version-tracked providers and surfaces update/ignore choices.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

Closes: OSS-1730, OSS-1729

* refactor(cli): namespace provider metadata under providerMetadata key

Introduce PROVIDER_METADATA_NS ('providerMetadata') to avoid top-level
settings key collisions. Provider metadata now lives under
e.g. providerMetadata.coding-plan.version instead of codingPlan.version.

Add migration logic (migrateProviderMetadata) to automatically move
legacy top-level keys (codingPlan, tokenPlan) into the new namespace
on first run.

Update auth handler, useProviderUpdates hook, and all related tests
to use the new namespace structure.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

[skip ci]

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): polish ProviderUpdatePrompt styling and test coverage [skip ci]

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(auth): simplify auth flows around provider abstraction [skip ci]

- Rewrite motivation.md to document provider-centric architecture
- Remove Alibaba Standard API Key and Coding Plan UI flows from handler
- Update status tests to use providerMetadata instead of codingPlan settings
- Streamline API key auth to show docs link only

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(auth): update provider models and refine auth infrastructure

- Bump model versions (qwen3.6-plus, glm-5.1) and add deepseek-v4-pro/flash
  with modalities to Alibaba Standard provider
- Reorder DeepSeek models, add thinking+image/video modalities to v4-pro,
  fix v4-flash context window
- Enhance auth tests with provider metadata setValue assertions
- Switch env key generation from hash-based to URL-based with
  trailing-slash normalization
- Remove deprecated codingPlan section from settings schema

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(i18n): add missing zh-TW translations for token plan and subscription providers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(auth): improve provider install error recovery and AuthDialog state init

- Restore settings from backup on provider install plan failure
- Fix AuthDialog mainIndex state to null (was 0), preventing stale selection
- Remove ownsModel from customProvider; fall back to id-based filtering
- Change provider migration log from console.error to console.log
- Add sync reminder comments between CLI and VSCode subscription models
- Expand handleApiKeyAuth JSDoc explaining its role as lightweight fallback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(auth): i18n for step labels, lazy preview JSON, and accurate header label

- Wrap getStepLabel() strings and PROTOCOL_ITEMS in t() for i18n
- Only compute previewJson when on the review step
- Return matched provider's own label in getAuthDisplayType instead
  of hardcoding CODING_PLAN for all managed providers

* fix(auth): address round-3 review blockers

- Fix CI: add missing useProviderUpdates mock in AppContainer.test.tsx
  that caused TypeError breaking React effects (title/height tests)
- Fix half-rollback: snapshot settings + modelProviders before install,
  restore in-memory state (not just disk) on refreshAuth failure
- Fix .orig backup reuse: always create fresh backup (overwrite stale),
  cleanup on success, unlink after restore to prevent data loss
- Fix cross-package key consistency: VS Code settingsWriter now writes
  to providerMetadata namespace matching CLI's new structure
- Fix validateApiKey: remove baseUrl guard so sk-sp- prefix check
  applies to both China and Global Coding Plan endpoints

* fix(cli): stabilize AuthDialog tests for slower CI environments

Increase vi.waitFor timeouts from default 1000ms to 5000ms and replace
unreliable fixed-delay waits with proper render-completion assertions,
preventing flaky failures on Linux/Windows CI runners with Node 22/24.

* fix(core): use id+baseUrl composite key for model identity

Custom provider installs previously used model id alone to determine
ownership, causing the second install to remove the first backend's
model entry when both expose the same model id (e.g. gpt-4o) with
different baseUrls. Use id+baseUrl as the composite identity key
throughout the model registry, ModelDialog, and modelsConfig to
prevent cross-provider model collisions.

* fix(cli): update ModelDialog tests for composite-key model identity

Add missing getModelsConfig and getActiveRuntimeModelSnapshot mocks,
and update switchModel assertion to expect the new { baseUrl } options
object introduced in 4c4ebb8.

* fix(cli): skip flaky TUI input tests on all CI environments

Multi-step TUI navigation tests exceed 5s timeout on CI runners
regardless of Node version. Extend skip condition from only Node 20
to all CI environments where input simulation is unreliable.

* fix(cli): improve auth/provider edge cases and UX

- Add fallback to non-free models in OpenRouter OAuth when no free models available
- Validate non-empty models list when building install plan
- Fix auth status to use activeConfig instead of iterating all providers
- Clear API key input when switching auth protocol
- Skip unnecessary auth refresh when applying provider updates

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(cli): update tests for empty model validation and skip auth refresh

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): skip remaining flaky TUI input AuthDialog tests on CI

8558c49 only converted part of the tests to itWhenTuiInputReliable,
leaving 9 multi-step keyboard-navigation tests still using bare it().
These tests reliably time out on Linux/Windows CI runners where stdin
simulation timing is unpredictable.

Convert all remaining it() → itWhenTuiInputReliable() so CI skips them,
and add a comment block to clearly demarcate the TUI input section.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
B-A-M-N pushed a commit to B-A-M-N/qwen-code that referenced this pull request May 8, 2026
…line (QwenLM#3864)

* fix(cli): refresh static header on model switch

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* feat(cli): simplify api key provider registry

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): split Alibaba auth providers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* polish(cli): refine auth provider onboarding

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): update OpenRouter free defaults

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): restrict token plan models

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* chore(cli): remove unused third-party providers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* feat(cli): add regional third-party providers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): simplify api key provider endpoints

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): split auth dialog flows

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): unify auth around declarative provider config

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

Introduce ProviderConfig abstraction (providerConfig.ts) and a central provider registry (allProviders.ts), replacing the per-flow UI components (AlibabaModelStudioFlow, CustomProviderFlow, OAuthFlow, ThirdPartyProvidersFlow, etc.) with unified ProviderSetupSteps and useProviderSetupFlow.

Key changes:
- Remove setupMethods/apiKey/ directory entirely
- Collapse flow-specific hooks/components into a single generic provider setup flow
- Simplify each provider file to export only a ProviderConfig descriptor
- Add alibabaStandard provider alongside codingPlan/tokenPlan
- Move all baseUrl resolution, install plan building, and settings writing into providerConfig
- Update useAuth, AuthDialog, command handler, and upstream consumers to use the new registry

* refactor(cli): simplify provider setup input flow

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): remove toLlmProvider and legacy auth wrappers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): flatten auth flow files and simplify ProviderSetupSteps props

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* feat(cli): prefill API key from existing env settings in provider setup flow

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): correct third-party provider context windows

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): harden provider auth setup

* feat(cli): support provider modality and context settings

* feat: eable modelsEditable for coding plan

* refactor(cli): auto-derive provider metadata key and state

Move metadataKey and getProviderState from per-provider config to
auto-derived helpers (resolveMetadataKey, resolveProviderState) in
providerConfig.ts. This centralizes version tracking logic and reduces
boilerplate in individual provider definitions.

Add useProviderUpdates hook that detects model template changes across
all version-tracked providers and surfaces update/ignore choices.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

Closes: OSS-1730, OSS-1729

* refactor(cli): namespace provider metadata under providerMetadata key

Introduce PROVIDER_METADATA_NS ('providerMetadata') to avoid top-level
settings key collisions. Provider metadata now lives under
e.g. providerMetadata.coding-plan.version instead of codingPlan.version.

Add migration logic (migrateProviderMetadata) to automatically move
legacy top-level keys (codingPlan, tokenPlan) into the new namespace
on first run.

Update auth handler, useProviderUpdates hook, and all related tests
to use the new namespace structure.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

[skip ci]

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): polish ProviderUpdatePrompt styling and test coverage [skip ci]

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(auth): simplify auth flows around provider abstraction [skip ci]

- Rewrite motivation.md to document provider-centric architecture
- Remove Alibaba Standard API Key and Coding Plan UI flows from handler
- Update status tests to use providerMetadata instead of codingPlan settings
- Streamline API key auth to show docs link only

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(auth): update provider models and refine auth infrastructure

- Bump model versions (qwen3.6-plus, glm-5.1) and add deepseek-v4-pro/flash
  with modalities to Alibaba Standard provider
- Reorder DeepSeek models, add thinking+image/video modalities to v4-pro,
  fix v4-flash context window
- Enhance auth tests with provider metadata setValue assertions
- Switch env key generation from hash-based to URL-based with
  trailing-slash normalization
- Remove deprecated codingPlan section from settings schema

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(i18n): add missing zh-TW translations for token plan and subscription providers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(auth): improve provider install error recovery and AuthDialog state init

- Restore settings from backup on provider install plan failure
- Fix AuthDialog mainIndex state to null (was 0), preventing stale selection
- Remove ownsModel from customProvider; fall back to id-based filtering
- Change provider migration log from console.error to console.log
- Add sync reminder comments between CLI and VSCode subscription models
- Expand handleApiKeyAuth JSDoc explaining its role as lightweight fallback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(auth): i18n for step labels, lazy preview JSON, and accurate header label

- Wrap getStepLabel() strings and PROTOCOL_ITEMS in t() for i18n
- Only compute previewJson when on the review step
- Return matched provider's own label in getAuthDisplayType instead
  of hardcoding CODING_PLAN for all managed providers

* fix(auth): address round-3 review blockers

- Fix CI: add missing useProviderUpdates mock in AppContainer.test.tsx
  that caused TypeError breaking React effects (title/height tests)
- Fix half-rollback: snapshot settings + modelProviders before install,
  restore in-memory state (not just disk) on refreshAuth failure
- Fix .orig backup reuse: always create fresh backup (overwrite stale),
  cleanup on success, unlink after restore to prevent data loss
- Fix cross-package key consistency: VS Code settingsWriter now writes
  to providerMetadata namespace matching CLI's new structure
- Fix validateApiKey: remove baseUrl guard so sk-sp- prefix check
  applies to both China and Global Coding Plan endpoints

* fix(cli): stabilize AuthDialog tests for slower CI environments

Increase vi.waitFor timeouts from default 1000ms to 5000ms and replace
unreliable fixed-delay waits with proper render-completion assertions,
preventing flaky failures on Linux/Windows CI runners with Node 22/24.

* fix(core): use id+baseUrl composite key for model identity

Custom provider installs previously used model id alone to determine
ownership, causing the second install to remove the first backend's
model entry when both expose the same model id (e.g. gpt-4o) with
different baseUrls. Use id+baseUrl as the composite identity key
throughout the model registry, ModelDialog, and modelsConfig to
prevent cross-provider model collisions.

* fix(cli): update ModelDialog tests for composite-key model identity

Add missing getModelsConfig and getActiveRuntimeModelSnapshot mocks,
and update switchModel assertion to expect the new { baseUrl } options
object introduced in 4c4ebb8.

* fix(cli): skip flaky TUI input tests on all CI environments

Multi-step TUI navigation tests exceed 5s timeout on CI runners
regardless of Node version. Extend skip condition from only Node 20
to all CI environments where input simulation is unreliable.

* fix(cli): improve auth/provider edge cases and UX

- Add fallback to non-free models in OpenRouter OAuth when no free models available
- Validate non-empty models list when building install plan
- Fix auth status to use activeConfig instead of iterating all providers
- Clear API key input when switching auth protocol
- Skip unnecessary auth refresh when applying provider updates

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(cli): update tests for empty model validation and skip auth refresh

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): skip remaining flaky TUI input AuthDialog tests on CI

8558c49 only converted part of the tests to itWhenTuiInputReliable,
leaving 9 multi-step keyboard-navigation tests still using bare it().
These tests reliably time out on Linux/Windows CI runners where stdin
simulation timing is unpredictable.

Convert all remaining it() → itWhenTuiInputReliable() so CI skips them,
and add a comment block to clearly demarcate the TUI input section.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
pomelo-nwu added a commit that referenced this pull request May 11, 2026
…/auth TUI dialog (#3959)

The `qwen auth` CLI subcommand (with subcommands like qwen-oauth,
coding-plan, api-key, openrouter, status) has been superseded by the
richer /auth TUI dialog introduced in the provider-first auth registry
(#3864). Running `qwen auth` now prints a deprecation notice pointing
users to the /auth TUI dialog (interactive), env vars (CI/headless),
or /doctor (status check).

Changes:
- Replace auth.ts with a stub that prints a removal notice and exits
- Delete handler.ts (734 lines), interactiveSelector.ts, and their
  tests (interactiveSelector.test.ts, openrouter.test.ts, status.test.ts)
- Update /auth slash command to handle non-interactive/ACP modes gracefully
- Enrich /doctor auth check with provider-aware diagnostics using
  findProviderByCredentials
- Mark `auth` as a subcommand that handles its own exit in config.ts

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
wenshao pushed a commit that referenced this pull request May 17, 2026
…/auth TUI dialog (#3959)

The `qwen auth` CLI subcommand (with subcommands like qwen-oauth,
coding-plan, api-key, openrouter, status) has been superseded by the
richer /auth TUI dialog introduced in the provider-first auth registry
(#3864). Running `qwen auth` now prints a deprecation notice pointing
users to the /auth TUI dialog (interactive), env vars (CI/headless),
or /doctor (status check).

Changes:
- Replace auth.ts with a stub that prints a removal notice and exits
- Delete handler.ts (734 lines), interactiveSelector.ts, and their
  tests (interactiveSelector.test.ts, openrouter.test.ts, status.test.ts)
- Update /auth slash command to handle non-interactive/ACP modes gracefully
- Enrich /doctor auth check with provider-aware diagnostics using
  findProviderByCredentials
- Mark `auth` as a subcommand that handles its own exit in config.ts

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
xaelistic pushed a commit to xaelistic/qwen-code that referenced this pull request Jun 7, 2026
xaelistic pushed a commit to xaelistic/qwen-code that referenced this pull request Jun 7, 2026
…line (QwenLM#3864)

* fix(cli): refresh static header on model switch

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* feat(cli): simplify api key provider registry

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): split Alibaba auth providers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* polish(cli): refine auth provider onboarding

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): update OpenRouter free defaults

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): restrict token plan models

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* chore(cli): remove unused third-party providers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* feat(cli): add regional third-party providers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): simplify api key provider endpoints

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): split auth dialog flows

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): unify auth around declarative provider config

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

Introduce ProviderConfig abstraction (providerConfig.ts) and a central provider registry (allProviders.ts), replacing the per-flow UI components (AlibabaModelStudioFlow, CustomProviderFlow, OAuthFlow, ThirdPartyProvidersFlow, etc.) with unified ProviderSetupSteps and useProviderSetupFlow.

Key changes:
- Remove setupMethods/apiKey/ directory entirely
- Collapse flow-specific hooks/components into a single generic provider setup flow
- Simplify each provider file to export only a ProviderConfig descriptor
- Add alibabaStandard provider alongside codingPlan/tokenPlan
- Move all baseUrl resolution, install plan building, and settings writing into providerConfig
- Update useAuth, AuthDialog, command handler, and upstream consumers to use the new registry

* refactor(cli): simplify provider setup input flow

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): remove toLlmProvider and legacy auth wrappers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(cli): flatten auth flow files and simplify ProviderSetupSteps props

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* feat(cli): prefill API key from existing env settings in provider setup flow

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): correct third-party provider context windows

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): harden provider auth setup

* feat(cli): support provider modality and context settings

* feat: eable modelsEditable for coding plan

* refactor(cli): auto-derive provider metadata key and state

Move metadataKey and getProviderState from per-provider config to
auto-derived helpers (resolveMetadataKey, resolveProviderState) in
providerConfig.ts. This centralizes version tracking logic and reduces
boilerplate in individual provider definitions.

Add useProviderUpdates hook that detects model template changes across
all version-tracked providers and surfaces update/ignore choices.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

Closes: OSS-1730, OSS-1729

* refactor(cli): namespace provider metadata under providerMetadata key

Introduce PROVIDER_METADATA_NS ('providerMetadata') to avoid top-level
settings key collisions. Provider metadata now lives under
e.g. providerMetadata.coding-plan.version instead of codingPlan.version.

Add migration logic (migrateProviderMetadata) to automatically move
legacy top-level keys (codingPlan, tokenPlan) into the new namespace
on first run.

Update auth handler, useProviderUpdates hook, and all related tests
to use the new namespace structure.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

[skip ci]

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): polish ProviderUpdatePrompt styling and test coverage [skip ci]

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(auth): simplify auth flows around provider abstraction [skip ci]

- Rewrite motivation.md to document provider-centric architecture
- Remove Alibaba Standard API Key and Coding Plan UI flows from handler
- Update status tests to use providerMetadata instead of codingPlan settings
- Streamline API key auth to show docs link only

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(auth): update provider models and refine auth infrastructure

- Bump model versions (qwen3.6-plus, glm-5.1) and add deepseek-v4-pro/flash
  with modalities to Alibaba Standard provider
- Reorder DeepSeek models, add thinking+image/video modalities to v4-pro,
  fix v4-flash context window
- Enhance auth tests with provider metadata setValue assertions
- Switch env key generation from hash-based to URL-based with
  trailing-slash normalization
- Remove deprecated codingPlan section from settings schema

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(i18n): add missing zh-TW translations for token plan and subscription providers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(auth): improve provider install error recovery and AuthDialog state init

- Restore settings from backup on provider install plan failure
- Fix AuthDialog mainIndex state to null (was 0), preventing stale selection
- Remove ownsModel from customProvider; fall back to id-based filtering
- Change provider migration log from console.error to console.log
- Add sync reminder comments between CLI and VSCode subscription models
- Expand handleApiKeyAuth JSDoc explaining its role as lightweight fallback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(auth): i18n for step labels, lazy preview JSON, and accurate header label

- Wrap getStepLabel() strings and PROTOCOL_ITEMS in t() for i18n
- Only compute previewJson when on the review step
- Return matched provider's own label in getAuthDisplayType instead
  of hardcoding CODING_PLAN for all managed providers

* fix(auth): address round-3 review blockers

- Fix CI: add missing useProviderUpdates mock in AppContainer.test.tsx
  that caused TypeError breaking React effects (title/height tests)
- Fix half-rollback: snapshot settings + modelProviders before install,
  restore in-memory state (not just disk) on refreshAuth failure
- Fix .orig backup reuse: always create fresh backup (overwrite stale),
  cleanup on success, unlink after restore to prevent data loss
- Fix cross-package key consistency: VS Code settingsWriter now writes
  to providerMetadata namespace matching CLI's new structure
- Fix validateApiKey: remove baseUrl guard so sk-sp- prefix check
  applies to both China and Global Coding Plan endpoints

* fix(cli): stabilize AuthDialog tests for slower CI environments

Increase vi.waitFor timeouts from default 1000ms to 5000ms and replace
unreliable fixed-delay waits with proper render-completion assertions,
preventing flaky failures on Linux/Windows CI runners with Node 22/24.

* fix(core): use id+baseUrl composite key for model identity

Custom provider installs previously used model id alone to determine
ownership, causing the second install to remove the first backend's
model entry when both expose the same model id (e.g. gpt-4o) with
different baseUrls. Use id+baseUrl as the composite identity key
throughout the model registry, ModelDialog, and modelsConfig to
prevent cross-provider model collisions.

* fix(cli): update ModelDialog tests for composite-key model identity

Add missing getModelsConfig and getActiveRuntimeModelSnapshot mocks,
and update switchModel assertion to expect the new { baseUrl } options
object introduced in 4a3eaa705.

* fix(cli): skip flaky TUI input tests on all CI environments

Multi-step TUI navigation tests exceed 5s timeout on CI runners
regardless of Node version. Extend skip condition from only Node 20
to all CI environments where input simulation is unreliable.

* fix(cli): improve auth/provider edge cases and UX

- Add fallback to non-free models in OpenRouter OAuth when no free models available
- Validate non-empty models list when building install plan
- Fix auth status to use activeConfig instead of iterating all providers
- Clear API key input when switching auth protocol
- Skip unnecessary auth refresh when applying provider updates

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(cli): update tests for empty model validation and skip auth refresh

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): skip remaining flaky TUI input AuthDialog tests on CI

8f4b82dbf only converted part of the tests to itWhenTuiInputReliable,
leaving 9 multi-step keyboard-navigation tests still using bare it().
These tests reliably time out on Linux/Windows CI runners where stdin
simulation timing is unpredictable.

Convert all remaining it() → itWhenTuiInputReliable() so CI skips them,
and add a comment block to clearly demarcate the TUI input section.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
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.

3 participants