Feat/openrouter auth (#3576)

* feat(cli): add OpenRouter auth flow

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

* feat(cli): add OpenRouter model management UI

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

* fix(cli): align OpenRouter OAuth fallback session

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

* refactor(cli): unify OpenRouter model setup flow

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

* feat(auth): update OAuth description with provider examples and i18n support

- Updated OAuth option description to include provider examples (OpenRouter, ModelScope)
- Added internationalization support for new description text
- Updated all language files (en, zh, de, fr, ja, pt, ru) with translations

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

* docs: simplify OpenRouter design docs

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

* test(auth): fix OpenRouter OAuth mock typing

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

* test(auth): sync AuthDialog tests with new three-option main menu layout

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

Update assertions that referenced removed 'Qwen OAuth' and 'OpenRouter' options in the main/API-key views to match the refactored OAUTH / CODING_PLAN / API_KEY structure.

* fix(i18n): add missing zh-TW translation for browser-based auth key

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

zh-TW.js was generated from main's en.js which had already removed this key, but the PR re-adds it in en.js. Sync zh-TW with the new translation.

* feat(cli): Improve custom auth wizard with step indicators and cleaner advanced config (#3607)

* feat(cli): Add custom API key auth wizard with 6-step setup flow

Replace the documentation-only

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>"Custom API Key" screen with an
in-terminal wizard: Protocol select → Base URL input → API Key input →
Model ID input → JSON review → Save.

- Add 5 new ViewLevels and render functions in AuthDialog
- Implement utility functions: generateCustomApiKeyEnvKey (normalization),
  normalizeCustomModelIds (split/trim/dedupe), maskApiKey (display)
- Implement handleCustomApiKeySubmit in useAuth with backup, env key
  generation, modelProviders merge, auth refresh, and user feedback
- Wire handler through UIActionsContext and AppContainer
- Add 18 unit tests for utilities, 4 wizard flow integration tests

* feat(cli): Improve custom auth wizard with step indicators and cleaner advanced config

- Add step indicators (Step 1/6 · Protocol) to each wizard screen
- Remove redundant Protocol/Endpoint context from each step for focus
- Redesign advanced config: add descriptions to thinking/modality toggles
- Remove max tokens option; keep only thinking and modality settings
- Add ↑↓ arrow navigation with Space toggle and Enter to continue
- Generation config flows through review JSON and final submit

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

* test: Fix Windows CI failures in fileUtils and AuthDialog tests

- fileUtils.test.ts: Mock node:child_process execFile to prevent
  pdftotext spawn that times out on Windows (ENOENT, 5s timeout)
- AuthDialog.test.tsx: Add char-by-char typeText() helper to work
  around Node 24.x + ink TextInput compatibility issue on Windows

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

* fix(cli): Reset advanced wizard state and use JSON.stringify for settings preview

- Reset advancedThinkingEnabled, advancedModalityEnabled, and
  focusedConfigIndex when re-entering custom wizard to prevent
  state leakage between configurations
- Replace hand-rolled JSON string concatenation with
  JSON.stringify for settings.json preview to properly escape
  special characters in model IDs and base URLs

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

---------

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

* fix(cli): harden OpenRouter OAuth callback handling

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

* test(cli): stabilize OpenRouter state mismatch test

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

* test(cli): stabilize custom auth wizard navigation

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

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
pomelo 2026-04-27 14:47:44 +08:00 committed by GitHub
parent 96bc874197
commit 7fe853a782
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
45 changed files with 5666 additions and 129 deletions

View file

@ -0,0 +1,89 @@
# OpenRouter Auth and Model Management Design
This document captures the design intent behind the OpenRouter auth flow and the
model management changes introduced with it. It intentionally focuses on the
product and architectural choices, not implementation history.
## Goals
- Let users authenticate with OpenRouter from both CLI and `/auth`.
- Reuse the existing OpenAI-compatible provider path instead of adding a new auth
type for OpenRouter.
- Make the first-run experience usable without asking users to manage hundreds of
models immediately.
- Keep a clear path toward richer model management via `/manage-models`.
## OpenRouter Auth
OpenRouter is integrated as an OpenAI-compatible provider:
- auth type: `AuthType.USE_OPENAI`
- provider settings: `modelProviders.openai`
- API key env var: `OPENROUTER_API_KEY`
- base URL: `https://openrouter.ai/api/v1`
This avoids introducing an OpenRouter-specific `AuthType` when the runtime model
provider path is already OpenAI-compatible. It keeps auth status, model
resolution, provider selection, and settings schema aligned with the existing
provider abstraction.
The user-facing flows are:
- `qwen auth openrouter --key <key>` for automation or direct API-key setup.
- `qwen auth openrouter` for browser-based OAuth.
- `/auth` → API Key → OpenRouter for the TUI flow.
Browser OAuth uses OpenRouter's PKCE flow and writes the exchanged API key into
settings before refreshing auth as `AuthType.USE_OPENAI`.
## Model Management
OpenRouter exposes a large dynamic model catalog. Writing every discovered model
into `modelProviders.openai` would make `/model` noisy and would turn a long-term
settings field into a cache of a remote catalog.
The key design split is:
- **Catalog**: the full set of models discovered from a source such as
OpenRouter.
- **Enabled set**: the smaller set of models that should appear in `/model` and
be persisted in user settings.
For the initial OpenRouter flow, auth should finish with a useful default enabled
set instead of interrupting the user with a large picker. The recommended set
should be small, stable, and biased toward models that let users try the product
successfully, including free models when available.
`/model` remains a fast model switcher. It should not become the place where
users browse and curate a full provider catalog.
## `/manage-models`
Richer model management belongs in a separate `/manage-models` entry point. That
flow should let users:
- browse discovered models;
- search by id, display name, provider prefix, and derived tags such as `free` or
`vision`;
- see which models are currently enabled;
- enable or disable models in batches.
The source dimension must remain part of this design. OpenRouter is only the
first dynamic catalog source; future sources such as ModelScope and ModelStudio
should fit the same shape. UI complexity can be reduced, but the underlying
source abstraction should stay available as the extension point.
## Current Boundary
This change should do the minimum needed to make OpenRouter auth and model setup
pleasant:
- OAuth or key-based auth configures OpenRouter through the existing
OpenAI-compatible provider path.
- The initial enabled model set is curated instead of dumping the full catalog
into settings.
- Full catalog storage, browsing, filtering, and batch management are deferred to
`/manage-models`.
The design principle is simple: authentication should get users to a working
state quickly, while model curation should live in a dedicated management flow.