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
103 changes: 86 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,32 @@
- 🧠 **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`
- 🌐 **Multi-endpoint support** - Automatically routes to portal.qwen.ai or DashScope based on your token

## 🆕 What's New in v1.4.0

### 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.

### DashScope Headers Support

When using DashScope endpoints, the plugin automatically injects the required headers:
- `X-DashScope-CacheControl: enable`
- `X-DashScope-UserAgent: opencode-qwencode-auth/1.4.0`
- `X-DashScope-AuthType: qwen-oauth`

### Fixed: Loader Return Format

Fixed a critical bug where the loader was returning `baseUrl` instead of `baseURL` (capital letters), which caused `ERR_INVALID_URL` errors.

## 📋 Prerequisites

Expand All @@ -30,13 +56,26 @@

### 1. Install the plugin

**From npm (recommended):**
```bash
cd ~/.config/opencode && npm install opencode-qwencode-auth
```

**Or with bun:**
```bash
cd ~/.opencode && npm install opencode-qwencode-auth
cd ~/.config/opencode && bun add opencode-qwencode-auth
```

**From GitHub (latest unreleased changes):**
```bash
cd ~/.config/opencode && npm install ishan-parihar/opencode-qwencode-auth
# or with bun
cd ~/.config/opencode && bun add ishan-parihar/opencode-qwencode-auth
```

### 2. Enable the plugin

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

```json
{
Expand Down Expand Up @@ -76,21 +115,18 @@ Select **"Qwen Code (qwen.ai OAuth)"**
| `qwen3-coder-plus` | 1M tokens | 64K tokens | Complex coding tasks |
| `qwen3-coder-flash` | 1M tokens | 64K tokens | Fast coding responses |

### General Purpose Models
### Alias Models

| Model | Context | Max Output | Reasoning | Best For |
|-------|---------|------------|-----------|----------|
| `qwen3-max` | 256K tokens | 64K tokens | No | Flagship model, complex reasoning and tool use |
| `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 |
| Model | Context | Max Output | Description |
|-------|---------|------------|-------------|
| `coder-model` | 1M tokens | 64K tokens | Auto-routed coding model |
| `vision-model` | 128K tokens | 32K tokens | Vision-language model (qwen3-vl-plus) |

### Using a specific model

```bash
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 vision-model
```

## ⚙️ How It Works
Expand All @@ -105,7 +141,20 @@ opencode --provider qwen-code --model qwen-plus-latest
1. **Device Flow (RFC 8628)**: Opens your browser to `chat.qwen.ai` for authentication
2. **Automatic Polling**: Detects authorization completion automatically
3. **Token Storage**: Saves credentials to `~/.qwen/oauth_creds.json`
4. **Auto-refresh**: Renews tokens 30 seconds before expiration
4. **Dynamic URL Resolution**: Uses `resource_url` from token to determine API endpoint
5. **Auto-refresh**: Renews tokens 60 seconds before expiration

## 📊 API Endpoints

The plugin supports multiple API endpoints:

| Endpoint | URL | Headers | Region |
|----------|-----|---------|--------|
| Portal | `https://portal.qwen.ai/v1` | Standard Bearer | International |
| DashScope | `https://dashscope.aliyuncs.com/compatible-mode/v1` | DashScope-specific | China |
| DashScope Intl | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | DashScope-specific | International |

The correct endpoint is automatically selected based on your OAuth token's `resource_url` field.

## 📊 Usage Limits

Expand All @@ -118,6 +167,18 @@ opencode --provider qwen-code --model qwen-plus-latest

## 🔧 Troubleshooting

### ERR_INVALID_URL error

This was a bug in versions before 1.4.0. Update to the latest version:

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

### "Incorrect API key provided" error

This happens when the wrong API endpoint is used. The v1.4.0 update fixes this by automatically detecting the correct endpoint from your token's `resource_url`.

### Token expired

The plugin automatically renews tokens. If issues persist:
Expand All @@ -143,6 +204,15 @@ The `qwen-code` provider is added via plugin. In the `opencode auth login` comma
- Try using `qwen3-coder-flash` for faster, lighter requests
- Consider [DashScope API](https://dashscope.aliyun.com) for higher limits

### Debug Mode

Enable debug logging to see technical details:

```bash
export OPENCODE_QWEN_DEBUG=1
opencode
```

## 🛠️ Development

```bash
Expand All @@ -159,7 +229,7 @@ bun run typecheck

### Local testing

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

```json
{
Expand All @@ -172,21 +242,20 @@ Edit `~/.opencode/package.json`:
Then reinstall:

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

## 📁 Project Structure

```
src/
├── constants.ts # OAuth endpoints, models config
├── constants.ts # OAuth endpoints, API URLs, models config
├── types.ts # TypeScript interfaces
├── index.ts # Main plugin entry point
├── qwen/
│ └── oauth.ts # OAuth Device Flow + PKCE
└── plugin/
├── auth.ts # Credentials management
└── utils.ts # Helper utilities
└── auth.ts # Credentials management + URL resolution
```

## 🔗 Related Projects
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "opencode-qwencode-auth",
"version": "1.3.0",
"version": "1.4.0",
"description": "Qwen OAuth authentication plugin for OpenCode - Access Qwen AI models (Coder, Vision) with your qwen.ai account",
"module": "index.ts",
"type": "module",
Expand All @@ -20,7 +20,9 @@
"authentication",
"ai",
"llm",
"opencode-plugins"
"opencode-plugins",
"dashscope",
"portal-qwen"
],
"author": "Gustavo Dias <me@gustavodias.dev>",
"license": "MIT",
Expand Down
29 changes: 21 additions & 8 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,38 @@ export const QWEN_OAUTH_CONFIG = {
} as const;

// Qwen API Configuration
// O resource_url das credenciais é usado para determinar a URL base
// The resource_url from credentials is used to determine the base URL
export const QWEN_API_CONFIG = {
// Default base URL (pode ser sobrescrito pelo resource_url das credenciais)
defaultBaseUrl: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
// Portal URL (usado quando resource_url = "portal.qwen.ai")
// DashScope (Chinese region)
dashscopeBaseUrl: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
// DashScope International
dashscopeIntlBaseUrl: 'https://dashscope-intl.aliyuncs.com/compatible-mode/v1',
// Portal URL (used when resource_url = "portal.qwen.ai")
portalBaseUrl: 'https://portal.qwen.ai/v1',
// Default fallback
baseUrl: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
// Endpoint de chat completions
chatEndpoint: '/chat/completions',
// Endpoint de models
modelsEndpoint: '/models',
// Usado pelo OpenCode para configurar o provider
baseUrl: 'https://portal.qwen.ai/v1',
} as const;

// DashScope-specific headers required for OAuth tokens
// These are needed when using DashScope endpoints with OAuth tokens
export const DASHSCOPE_HEADERS = {
cacheControl: 'X-DashScope-CacheControl',
userAgent: 'X-DashScope-UserAgent',
authType: 'X-DashScope-AuthType',
} as const;

// User agent string for DashScope
export const QWEN_USER_AGENT = 'opencode-qwencode-auth/1.4.0';

// OAuth callback port (para futuro Device Flow no plugin)
export const CALLBACK_PORT = 14561;

// Available Qwen models through OAuth (portal.qwen.ai)
// Testados e confirmados funcionando via token OAuth
// Available Qwen models through OAuth
// Supports both portal.qwen.ai and DashScope endpoints
export const QWEN_MODELS = {
// --- Coding Models ---
'qwen3-coder-plus': {
Expand Down
Loading