Skip to content

fix(auth): support modern Qwen CLI v0.18+ API-key authentication - #46851

Open
liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:fix/qwen-cli-v018-auth-fallback
Open

liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:fix/qwen-cli-v018-auth-fallback

Conversation

@liuhao1024

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds support for modern Qwen CLI v0.18+ API-key authentication. When the legacy oauth_creds.json file is absent, Hermes now falls back to reading the API key from ~/.qwen/settings.json (where Qwen CLI v0.18+ stores credentials). Also updates error messages to remove references to the deprecated qwen auth qwen-oauth command.

Related Issue

Fixes #46771

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • hermes_cli/auth.py: Add _try_read_qwen_settings_api_key() helper that reads API key from ~/.qwen/settings.json; modify _read_qwen_cli_tokens() to fall back to settings.json when oauth_creds.json is missing; modify resolve_qwen_runtime_credentials() to skip OAuth refresh for API-key auth (no expiry, no refresh token); update 4 error messages to remove deprecated qwen auth qwen-oauth references
  • hermes_cli/model_setup_flows.py: Update guidance message from deprecated command to modern DASHSCOPE_API_KEY setup
  • hermes_cli/status.py: Update status display message for not-logged-in state
  • tests/hermes_cli/test_auth_qwen_provider.py: Add 10 new tests covering settings.json fallback (nested auth, top-level key, DASHSCOPE_API_KEY, missing file, no key, invalid JSON), fallback integration, refresh skip, and auth status

How to Test

  1. Run pytest tests/hermes_cli/test_auth_qwen_provider.py -v — all 41 tests pass
  2. Manual: create ~/.qwen/settings.json with {"security": {"auth": {"apiKey": "test-key"}}} and verify hermes auth status shows Qwen as logged in
  3. Verify that when both oauth_creds.json and settings.json are absent, the error message says "Set DASHSCOPE_API_KEY" instead of "Run 'qwen auth qwen-oauth'"

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — N/A (auth file paths are platform-independent via Path.home())
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Code Intelligence

  • Analyzed: hermes_cli/auth.py _read_qwen_cli_tokens, _try_read_qwen_settings_api_key, resolve_qwen_runtime_credentials
  • Blast radius: LOW — changes are isolated to Qwen OAuth provider path; other providers unaffected
  • Related patterns: External CLI auth storage migration fallback (other providers like google-gemini-cli, xai-oauth use similar patterns)

Qwen CLI v0.18+ removed the 'qwen auth qwen-oauth' command and stores
credentials in ~/.qwen/settings.json with DASHSCOPE_API_KEY instead of
the legacy ~/.qwen/oauth_creds.json OAuth flow.

- Add _try_read_qwen_settings_api_key() to read API key from settings.json
- Fall back to settings.json when oauth_creds.json is missing
- Skip OAuth refresh logic for API-key auth (no expiry, no refresh token)
- Update error messages to remove references to deprecated CLI command
- Add 10 new tests for settings.json fallback and API-key auth flow

Fixes NousResearch#46771
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard area/auth Authentication, OAuth, credential pools provider/qwen Qwen / Alibaba Cloud (OAuth) labels Jun 15, 2026

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

Thanks for adding coverage for the modern Qwen CLI credential file. The compatibility gap is real on current main: hermes_cli/auth.py:2220-2227 only accepts oauth_creds.json.

Problems

  • hermes_cli/auth.py:2167 sets should_refresh = bool(force_refresh) even for qwen-settings-json; therefore force_refresh=True still invokes OAuth refresh at line 2171, contrary to the new no-refresh contract. The added test at tests/hermes_cli/test_auth_qwen_provider.py:562-582 covers only refresh_if_expiring=True.
  • The new parser recognizes selectedType=openai (hermes_cli/auth.py:1970) but returns it through qwen-oauth with the Portal base URL (hermes_cli/auth.py:2180-2183). Current main defines that endpoint as https://portal.qwen.ai/v1 (hermes_cli/auth.py:96), while the documented DASHSCOPE_API_KEY path is the distinct Alibaba/DashScope provider (website/docs/integrations/providers.md:430-431).

Suggested changes

  • Suppress refresh when the source is settings.json even if force_refresh=True, with a direct regression test.
  • Preserve the API-key route's provider and endpoint explicitly, and test final provider/base-URL resolution rather than only credential parsing.

Automated hermes-sweeper review.

Comment thread hermes_cli/auth.py
# API-key auth (from settings.json) has no expiry or refresh token —
# skip OAuth refresh logic entirely.
is_api_key_auth = tokens.get("source") == "qwen-settings-json"
should_refresh = bool(force_refresh)

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.

force_refresh=True still makes this API-key credential enter _refresh_qwen_cli_tokens() at line 2171. Gate this initialization on not is_api_key_auth too, and add a force-refresh regression test.

@teknium1 teknium1 added sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists provider/qwen Qwen / Alibaba Cloud (OAuth) sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Hermes appears incompatible with modern Qwen CLI authentication.

3 participants