Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [1.5.0] - 2026-03-09

### 🚨 Critical Fixes

- **Fixed rate limiting issue (#4)** - Added official Qwen Code headers to prevent aggressive rate limiting
- Added `QWEN_OFFICIAL_HEADERS` constant with required identification headers
- Headers include `X-DashScope-CacheControl`, `X-DashScope-AuthType`, `X-DashScope-UserAgent`
- Requests now recognized as legitimate Qwen Code client
- Full 2,000 requests/day quota now available

- **Added session and prompt tracking** - Prevents false-positive abuse detection
- Unique `sessionId` per plugin lifetime
- Unique `promptId` per request via `crypto.randomUUID()`
- `X-Metadata` header with tracking information

### ✨ New Features

- **Dynamic API endpoint resolution** - Automatic region detection based on OAuth token
- `portal.qwen.ai` β†’ `https://portal.qwen.ai/v1` (International)
- `dashscope` β†’ `https://dashscope.aliyuncs.com/compatible-mode/v1` (China)
- `dashscope-intl` β†’ `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` (International)
- Added `loadCredentials()` function to read `resource_url` from credentials file
- Added `resolveBaseUrl()` function for intelligent URL resolution

- **Added qwen3.5-plus model support** - Latest flagship hybrid model
- 1M token context window
- 64K token max output
- Reasoning capabilities enabled
- Vision support included

- **Vision model capabilities** - Proper modalities configuration
- Dynamic `modalities.input` based on model capabilities
- Vision models now correctly advertise `['text', 'image']` input
- Non-vision models remain `['text']` only

### πŸ”§ Technical Improvements

- **Enhanced loader hook** - Returns complete configuration with headers
- Headers injected at loader level for all requests
- Metadata object for backend quota recognition
- Session-based tracking for usage patterns

- **Enhanced config hook** - Consistent header configuration
- Headers set in provider options
- Dynamic modalities based on model capabilities
- Better type safety for vision features

- **Improved auth module** - Better credentials management
- Added `loadCredentials()` for reading from file
- Better error handling in credential loading
- Support for multi-region tokens

### πŸ“š Documentation

- Updated README with new features section
- Added troubleshooting section for rate limiting
- Updated model table with `qwen3.5-plus`
- Added vision model documentation
- Enhanced installation instructions

### πŸ”„ Changes from Previous Versions

#### Compared to 1.4.0 (PR #7 by @ishan-parihar)

This version includes all features from PR #7 plus:
- Complete official headers (not just DashScope-specific)
- Session and prompt tracking for quota recognition
- `qwen3.5-plus` model support
- Vision capabilities in modalities
- Direct fix for Issue #4 (rate limiting)

---

## [1.4.0] - 2026-02-27

### Added
- Dynamic API endpoint resolution (PR #7)
- DashScope headers support (PR #7)
- `loadCredentials()` and `resolveBaseUrl()` functions (PR #7)

### Fixed
- `ERR_INVALID_URL` error - loader now returns `baseURL` correctly (PR #7)
- "Incorrect API key provided" error for portal.qwen.ai tokens (PR #7)

---

## [1.3.0] - 2026-02-10

### Added
- OAuth Device Flow authentication
- Support for qwen3-coder-plus, qwen3-coder-flash models
- Automatic token refresh
- Compatibility with qwen-code credentials

### Known Issues
- Rate limiting reported by users (Issue #4)
- Missing official headers for quota recognition

---

## [1.2.0] - 2026-01-15

### Added
- Initial release
- Basic OAuth authentication
- Model configuration for Qwen providers
61 changes: 52 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,49 @@

## ✨ Features

- πŸš€ **Qwen 3.5 Plus Support** - Use the latest flagship hybrid model
- πŸ” **OAuth Device Flow** - Secure browser-based authentication (RFC 8628)
- ⚑ **Automatic Polling** - No need to press Enter after authorizing
- πŸ†“ **2,000 req/day free** - Generous free tier with no credit card
- 🧠 **1M context window** - Models with 1 million token context
- πŸ”„ **Auto-refresh** - Tokens renewed automatically before expiration
- πŸ”— **qwen-code compatible** - Reuses credentials from `~/.qwen/oauth_creds.json`
- 🌐 **Dynamic Routing** - Automatic resolution of API base URL based on region
- 🏎️ **KV Cache Support** - Official DashScope headers for high performance
- 🎯 **Rate Limit Fix** - Official headers prevent aggressive rate limiting (Fixes #4)
- πŸ” **Session Tracking** - Unique session/prompt IDs for proper quota recognition

## πŸ†• What's New in v1.5.0

### Rate Limiting Fix (Issue #4)

**Problem:** Users were experiencing aggressive rate limiting (2,000 req/day quota exhausted quickly).

**Solution:** Added official Qwen Code headers that properly identify the client:
- `X-DashScope-CacheControl: enable` - Enables KV cache optimization
- `X-DashScope-AuthType: qwen-oauth` - Marks as OAuth authentication
- `X-DashScope-UserAgent` - Identifies as official Qwen Code client
- `X-Metadata` - Session and prompt tracking for quota recognition

**Result:** Full daily quota now available without premature rate limiting.

### Dynamic API Endpoint Resolution

The plugin now automatically detects and uses the correct API endpoint based on the `resource_url` returned by the OAuth server:

| resource_url | API Endpoint | Region |
|-------------|--------------|--------|
| `portal.qwen.ai` | `https://portal.qwen.ai/v1` | International |
| `dashscope` | `https://dashscope.aliyuncs.com/compatible-mode/v1` | China |
| `dashscope-intl` | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | International |

This means the plugin works correctly regardless of which region your Qwen account is associated with.

### Latest Model Support

- βœ… **qwen3.5-plus** - Latest flagship hybrid model with reasoning + vision
- βœ… **Vision capabilities** - Models with vision now correctly support image input
- βœ… **Dynamic modalities** - Input modalities adapt based on model capabilities

## πŸ“‹ Prerequisites

Expand All @@ -31,12 +68,12 @@
### 1. Install the plugin

```bash
cd ~/.opencode && npm install opencode-qwencode-auth
cd ~/.config/opencode && npm install opencode-qwencode-auth
```

### 2. Enable the plugin

Edit `~/.opencode/opencode.jsonc`:
Edit `~/.config/opencode/opencode.jsonc`:

```json
{
Expand Down Expand Up @@ -71,26 +108,28 @@ Select **"Qwen Code (qwen.ai OAuth)"**

### Coding Models

| Model | Context | Max Output | Best For |
| Model | Context | Max Output | Features |
|-------|---------|------------|----------|
| `qwen3-coder-plus` | 1M tokens | 64K tokens | Complex coding tasks |
| `qwen3.5-plus` | 1M tokens | 64K tokens | Latest Flagship, Hybrid, Vision, Reasoning |
| `qwen3-coder-plus` | 1M tokens | 64K tokens | Stable Qwen 3.0 Coding model |
| `qwen3-coder-flash` | 1M tokens | 64K tokens | Fast coding responses |
| `coder-model` | 1M tokens | 64K tokens | Official alias (Auto-routes to Qwen 3.5 Plus) |

### General Purpose Models

| Model | Context | Max Output | Reasoning | Best For |
|-------|---------|------------|-----------|----------|
| `qwen3-max` | 256K tokens | 64K tokens | No | Flagship model, complex reasoning and tool use |
| `vision-model` | 128K tokens | 32K tokens | No | Official Vision alias (Qwen VL Plus) |
| `qwen-plus-latest` | 128K tokens | 16K tokens | Yes | Balanced quality-speed with thinking mode |
| `qwen3-235b-a22b` | 128K tokens | 32K tokens | Yes | Largest open-weight MoE with thinking mode |
| `qwen-flash` | 1M tokens | 8K tokens | No | Ultra-fast, low-cost simple tasks |

### Using a specific model

```bash
opencode --provider qwen-code --model qwen3.5-plus
opencode --provider qwen-code --model qwen3-coder-plus
opencode --provider qwen-code --model qwen3-max
opencode --provider qwen-code --model qwen-plus-latest
opencode --provider qwen-code --model coder-model
```

## βš™οΈ How It Works
Expand Down Expand Up @@ -139,6 +178,10 @@ The `qwen-code` provider is added via plugin. In the `opencode auth login` comma

### Rate limit exceeded (429 errors)

**As of v1.5.0, this should no longer occur!** The plugin now sends official Qwen Code headers that properly identify your client and prevent aggressive rate limiting.

If you still experience rate limiting:
- Ensure you're using v1.5.0 or later: `npm update opencode-qwencode-auth`
- Wait until midnight UTC for quota reset
- Try using `qwen3-coder-flash` for faster, lighter requests
- Consider [DashScope API](https://dashscope.aliyun.com) for higher limits
Expand All @@ -159,7 +202,7 @@ bun run typecheck

### Local testing

Edit `~/.opencode/package.json`:
Edit `~/.config/opencode/package.json`:

```json
{
Expand All @@ -172,7 +215,7 @@ Edit `~/.opencode/package.json`:
Then reinstall:

```bash
cd ~/.opencode && npm install
cd ~/.config/opencode && npm install
```

## πŸ“ Project Structure
Expand Down
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "opencode-qwencode-auth",
"version": "1.3.0",
"description": "Qwen OAuth authentication plugin for OpenCode - Access Qwen AI models (Coder, Vision) with your qwen.ai account",
"version": "1.5.0",
"description": "Qwen OAuth authentication plugin for OpenCode - Access Qwen AI models (Coder, Vision) with your qwen.ai account - Fixes rate limiting (Issue #4)",
"module": "index.ts",
"type": "module",
"scripts": {
Expand All @@ -15,12 +15,15 @@
"qwen-code",
"qwen3-coder",
"qwen3-vl-plus",
"qwen3.5-plus",
"vision-model",
"oauth",
"authentication",
"ai",
"llm",
"opencode-plugins"
"opencode-plugins",
"rate-limit-fix",
"dashscope"
],
"author": "Gustavo Dias <me@gustavodias.dev>",
"license": "MIT",
Expand Down
25 changes: 22 additions & 3 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,24 @@ export const CALLBACK_PORT = 14561;
// Testados e confirmados funcionando via token OAuth
export const QWEN_MODELS = {
// --- Coding Models ---
'qwen3.5-plus': {
id: 'qwen3.5-plus',
name: 'Qwen 3.5 Plus',
contextWindow: 1048576, // 1M tokens
maxOutput: 65536, // 64K tokens
description: 'Latest and most capable Qwen 3.5 coding model with 1M context window',
reasoning: true,
capabilities: { vision: true },
cost: { input: 0, output: 0 }, // Free via OAuth
},
'qwen3-coder-plus': {
id: 'qwen3-coder-plus',
name: 'Qwen3 Coder Plus',
contextWindow: 1048576, // 1M tokens
maxOutput: 65536, // 64K tokens
description: 'Most capable Qwen coding model with 1M context window',
description: 'Most capable Qwen 3.0 coding model with 1M context window',
reasoning: false,
cost: { input: 0, output: 0 }, // Free via OAuth
cost: { input: 0, output: 0 },
},
'qwen3-coder-flash': {
id: 'qwen3-coder-flash',
Expand All @@ -62,8 +72,9 @@ export const QWEN_MODELS = {
name: 'Qwen Coder (auto)',
contextWindow: 1048576,
maxOutput: 65536,
description: 'Auto-routed coding model (maps to qwen3-coder-plus)',
description: 'Auto-routed coding model (Maps to Qwen 3.5 Plus - Hybrid & Vision)',
reasoning: false,
capabilities: { vision: true },
cost: { input: 0, output: 0 },
},
// --- Vision Model ---
Expand All @@ -77,3 +88,11 @@ export const QWEN_MODELS = {
cost: { input: 0, output: 0 },
},
} as const;

// Official Qwen Code CLI Headers for performance and quota recognition
export const QWEN_OFFICIAL_HEADERS = {
'X-DashScope-CacheControl': 'enable',
'X-DashScope-AuthType': 'qwen-oauth',
'X-DashScope-UserAgent': 'QwenCode/0.12.0 (Linux; x64)',
'User-Agent': 'QwenCode/0.12.0 (Linux; x64)'
} as const;
Loading