opencode-qwencode-oauth
v1.0.5
Published
Qwen OAuth authentication plugin for OpenCode with multi-account rotation and API translation
Downloads
1,511
Maintainers
Readme
OpenCode Qwen Auth Plugin
Qwen OAuth authentication plugin for OpenCode with multi-account rotation, proactive token refresh, and automatic API translation.
Features
- Device Flow OAuth - PKCE-secured authentication, works in headless/CI environments
- Multi-Account Support - Store and rotate between multiple Qwen accounts
- Hybrid Account Rotation - Smart selection using health scores, token bucket, and LRU
- Proactive Token Refresh - Automatically refresh tokens before expiry
- Rate Limit Handling - Detects 429 responses, rotates accounts, respects retry-after
- API Translation - Bridges OpenAI Responses API ↔ Chat Completions API
- Streaming Support - Full SSE transformation for real-time responses
- Cross-Platform - Works on macOS, Linux, and Windows
Installation
Let an LLM Do It
Paste this into any LLM agent (Claude Code, OpenCode, Cursor, etc.):
Install the opencode-qwencode-oauth plugin by following: https://raw.githubusercontent.com/mseptiaan/opencode-qwencode-oauth/main/README.mdQuick Install (Recommended)
Add to your opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-qwencode-oauth"],
"provider": {
"qwen": {
"npm": "@ai-sdk/openai",
"options": {
"baseURL": "https://portal.qwen.ai/v1",
"compatibility": "strict"
},
"models": {
"coder-model": {
"id": "coder-model",
"name": "Qwen Coder",
"limit": {
"context": 1048576,
"output": 65536
},
"modalities": {
"input": [
"text",
"image"
],
"output": [
"text"
]
},
"attachment": true
}
}
}
}
}Quick Start
Start OpenCode in your project directory:
opencodeAuthenticate with Qwen:
/connectSelect Qwen OAuth and follow the device flow instructions.
Start coding with Qwen models:
/model qwen/coder-model
Configuration
No configuration required. The plugin works out of the box with sensible defaults.
Configuration is loaded in layers with later sources taking precedence:
- Built-in defaults
- User config (
~/.config/opencode/qwen.json) - Project config (
.opencode/qwen.json) - Environment variables
Available Options
| Option | Default | Description |
| ------ | ------- | ----------- |
| rotation_strategy | "hybrid" | Account rotation strategy (hybrid, round-robin, sequential) |
| proactive_refresh | true | Refresh tokens before they expire |
| refresh_window_seconds | 300 | Seconds before expiry to trigger a proactive refresh |
| max_rate_limit_wait_seconds | 300 | Max time to wait when all accounts are rate-limited (0 = unlimited) |
| quiet_mode | false | Suppress informational log output |
| pid_offset_enabled | false | Distribute load by process PID when running parallel sessions |
| health_score | (see below) | Fine-tune health score parameters |
| token_bucket | (see below) | Fine-tune token bucket parameters |
Environment Variables
| Variable | Config Key |
| -------- | ---------- |
| QWEN_OAUTH_CLIENT_ID | client_id |
| QWEN_OAUTH_BASE_URL | oauth_base_url |
| QWEN_API_BASE_URL | base_url |
| QWEN_ROTATION_STRATEGY | rotation_strategy |
| QWEN_PROACTIVE_REFRESH | proactive_refresh |
| QWEN_REFRESH_WINDOW_SECONDS | refresh_window_seconds |
| QWEN_MAX_RATE_LIMIT_WAIT_SECONDS | max_rate_limit_wait_seconds |
| QWEN_QUIET_MODE | quiet_mode |
| QWEN_PID_OFFSET_ENABLED | pid_offset_enabled |
Models
Available via OAuth
| Model | Context Window | Features |
| ----- | -------------- | -------- |
| coder-model | 1M tokens | Text + image input, streaming |
Multi-Account Rotation
Add multiple accounts for higher throughput:
- Run
/connectand complete the first login - Run
/connectagain to add additional accounts - The plugin automatically rotates between accounts
Rotation Strategies
- hybrid (default): Smart selection combining health scores, token bucket rate limiting, and LRU. Accounts recover health passively over time.
- round-robin: Cycles through accounts on each request.
- sequential: Uses one account until rate limited, then switches.
Hybrid Strategy Details
The hybrid strategy uses a weighted scoring algorithm:
- Health Score (0-100): Tracks account wellness. Success rewards (+1), rate limits penalize (-10), failures penalize more (-20). Accounts passively recover +2 points/hour when rested.
- Token Bucket: Client-side rate limiting (50 tokens max, regenerates 6/minute) to prevent hitting server 429s.
- LRU Freshness: Prefers accounts that haven't been used recently.
Score formula:
Score = (healthScore × 2) + ((tokens / maxTokens) × 100 × 5) + (min(secondsSinceUsed, 3600) × 0.1)Maximum possible component values (total max ≈ 1060 points):
| Component | Max Points | Influence | | --------- | ---------- | --------- | | Health score | 200 pts | ~19% | | Token balance | 500 pts | ~47% | | Freshness (LRU) | 360 pts | ~34% |
Accounts with a health score below min_usable (default: 50) or with an exhausted token bucket are excluded from selection.
Enable pid_offset_enabled: true when running multiple parallel sessions (e.g., oh-my-opencode) to distribute load across accounts.
Customising Health Score
{
"health_score": {
"initial": 70,
"success_reward": 1,
"rate_limit_penalty": -10,
"failure_penalty": -20,
"recovery_rate_per_hour": 2,
"min_usable": 50
}
}Customising Token Bucket
{
"token_bucket": {
"max_tokens": 50,
"regeneration_rate_per_minute": 6
}
}How It Works
This plugin bridges OpenCode's Responses API format with Qwen's Chat Completions API:
OpenCode → [Responses API] → Plugin → [Chat Completions] → Qwen
↓
OpenCode ← [Responses API] ← Plugin ← [Chat Completions] ← QwenRequest Transformation
| Responses API | Chat Completions API |
| ------------- | -------------------- |
| input | messages |
| input_text | text content type |
| input_image | image_url content type |
| instructions | System message |
| max_output_tokens | max_tokens |
| text.format | response_format |
Response Transformation (Streaming)
Converts SSE events from Chat Completions to Responses API format:
response.createdresponse.output_item.addedresponse.content_part.addedresponse.output_text.deltaresponse.completed
Storage Locations
| Data | Linux / macOS | Windows |
| ---- | ------------- | ------- |
| User config | ~/.config/opencode/qwen.json | %APPDATA%\opencode\qwen.json |
| Project config | .opencode/qwen.json | .opencode/qwen.json |
| Account tokens | ~/.config/opencode/qwen-auth-accounts.json | %APPDATA%\opencode\qwen-auth-accounts.json |
| Tracker state | ~/.config/opencode/qwen-auth-tracker-state.json | %APPDATA%\opencode\qwen-auth-tracker-state.json |
XDG_CONFIG_HOME is respected on Linux/macOS.
Security Note: All token and state files are stored with restricted permissions (0600). Ensure appropriate filesystem security.
Troubleshooting
Authentication Issues
"invalid_grant" error
- Your refresh token has expired or been revoked. The account is automatically excluded from rotation. Run
/connectto re-authenticate.
Device code expired
- Complete the browser login within 5 minutes of starting
/connect.
Rate Limiting
Frequent 429 errors
- Add more accounts with
/connect. - Increase
max_rate_limit_wait_secondsin config. - The hybrid strategy's token bucket provides client-side protection before hitting server limits.
Debug Logging
Set QWEN_DEBUG=1 to enable verbose debug output to stderr (and optionally a log file).
Reset Plugin State
To start fresh, delete the accounts and tracker state files:
rm ~/.config/opencode/qwen-auth-accounts.json
rm ~/.config/opencode/qwen-auth-tracker-state.jsonDevelopment
This project uses Bun for development.
Prerequisites
- Bun 1.0+
- Node.js 20+ (for npm compatibility)
Getting Started
# Install dependencies
bun install
# Build
bun run build
# Run tests (135 tests)
bun test
# Run tests in watch mode
bun test --watch
# Run with coverage
bun test --coverage
# Lint
bun run lint
# Auto-fix lint issues
bun run lint:fix
# Type-check
bun run typecheck
# Run e2e test (requires authenticated Qwen account)
bun run test:e2e
# Link for local testing
bun linkUsing npm
npm install
npm run build
npm testKnown Limitations
- Audio input (
input_audio) is not supported by Qwen and is converted to placeholder text.
License
MIT License. See LICENSE for details.
Intended Use
- Personal / internal development only
- Respect internal quotas and data handling policies
- Not for production services or bypassing intended limits
Warning
By using this plugin, you acknowledge:
- Terms of Service risk — This approach may violate ToS of AI model providers
- Account risk — Providers may suspend or ban accounts
- No guarantees — APIs may change without notice
- Assumption of risk — You assume all legal, financial, and technical risks
Disclaimer
- Not affiliated with QWEN and Alibaba. This is an independent open-source project.
- "QWEN" and "Alibaba" are trademarks of Alibaba company.
