qwen-opencode-provider 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -43
- package/index.js +105 -61
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenCode Qwen Plugin
|
|
2
2
|
|
|
3
|
-
OpenCode plugin for Qwen AI - auto-
|
|
3
|
+
OpenCode plugin for Qwen AI - auto-registers provider with 28+ models.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -11,40 +11,9 @@ Add to `opencode.json`:
|
|
|
11
11
|
}
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## Usage
|
|
15
15
|
|
|
16
|
-
###
|
|
17
|
-
|
|
18
|
-
Add this to your `opencode.json`:
|
|
19
|
-
|
|
20
|
-
```json
|
|
21
|
-
{
|
|
22
|
-
"$schema": "https://opencode.ai/config.json",
|
|
23
|
-
"plugin": ["qwen-opencode-provider"],
|
|
24
|
-
"provider": {
|
|
25
|
-
"qwen": {
|
|
26
|
-
"npm": "@ai-sdk/openai-compatible",
|
|
27
|
-
"name": "Qwen AI",
|
|
28
|
-
"options": {
|
|
29
|
-
"baseURL": "https://qwen.aikit.club/v1"
|
|
30
|
-
},
|
|
31
|
-
"models": {
|
|
32
|
-
"qwen-max": { "name": "Qwen Max" },
|
|
33
|
-
"qwen2.5-max": { "name": "Qwen2.5 Max" },
|
|
34
|
-
"qwen2.5-plus": { "name": "Qwen2.5 Plus" },
|
|
35
|
-
"qwen2.5-turbo": { "name": "Qwen2.5 Turbo" },
|
|
36
|
-
"qwen2.5-coder-32b-instruct": { "name": "Qwen2.5 Coder 32B" },
|
|
37
|
-
"qwen3-coder": { "name": "Qwen3 Coder" },
|
|
38
|
-
"qwen3-max": { "name": "Qwen3 Max" },
|
|
39
|
-
"qwq-32b": { "name": "QWQ 32B" },
|
|
40
|
-
"qwen-deep-research": { "name": "Qwen Deep Research" }
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### Step 2: Connect
|
|
16
|
+
### Connect
|
|
48
17
|
|
|
49
18
|
```bash
|
|
50
19
|
/connect
|
|
@@ -53,12 +22,27 @@ Add this to your `opencode.json`:
|
|
|
53
22
|
# Enter your Qwen token
|
|
54
23
|
```
|
|
55
24
|
|
|
56
|
-
###
|
|
25
|
+
### Get Token
|
|
57
26
|
|
|
58
27
|
1. Visit https://chat.qwen.ai and login
|
|
59
28
|
2. Open Developer Console (F12)
|
|
60
29
|
3. Run: `localStorage.getItem('token')`
|
|
61
30
|
|
|
31
|
+
### Select Model
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
/models
|
|
35
|
+
# Choose any Qwen model
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- 👁️ Vision (image analysis)
|
|
41
|
+
- 🌐 Web Search
|
|
42
|
+
- 🧠 Thinking Mode
|
|
43
|
+
- 🎨 Image Generation
|
|
44
|
+
- 👨💻 Code Generation
|
|
45
|
+
|
|
62
46
|
## Supported Models
|
|
63
47
|
|
|
64
48
|
| Model | Description |
|
|
@@ -75,11 +59,3 @@ Add this to your `opencode.json`:
|
|
|
75
59
|
| qwen-web-dev | Web development |
|
|
76
60
|
| qwen-full-stack | Full-stack apps |
|
|
77
61
|
| qwen-cogview | Image generation |
|
|
78
|
-
|
|
79
|
-
## Features
|
|
80
|
-
|
|
81
|
-
- 👁️ Vision (image analysis)
|
|
82
|
-
- 🌐 Web Search
|
|
83
|
-
- 🧠 Thinking Mode
|
|
84
|
-
- 🎨 Image Generation
|
|
85
|
-
- 👨💻 Code Generation
|
package/index.js
CHANGED
|
@@ -1,80 +1,124 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* OpenCode Qwen API Plugin
|
|
3
3
|
*
|
|
4
|
-
* Automatically
|
|
5
|
-
* No
|
|
4
|
+
* Automatically registers Qwen provider with OpenCode.
|
|
5
|
+
* No manual config needed - just add plugin to opencode.json!
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
8
|
* 1. Add to opencode.json: { "plugin": ["qwen-opencode-provider"] }
|
|
9
|
-
* 2.
|
|
10
|
-
* 3. Run /connect and select "Other" -> "qwen"
|
|
11
|
-
*
|
|
12
|
-
* Provider config for opencode.json:
|
|
13
|
-
* {
|
|
14
|
-
* "provider": {
|
|
15
|
-
* "qwen": {
|
|
16
|
-
* "npm": "@ai-sdk/openai-compatible",
|
|
17
|
-
* "name": "Qwen AI",
|
|
18
|
-
* "options": {
|
|
19
|
-
* "baseURL": "https://qwen.aikit.club/v1"
|
|
20
|
-
* },
|
|
21
|
-
* "models": {
|
|
22
|
-
* "qwen-max": { "name": "Qwen Max" },
|
|
23
|
-
* "qwen2.5-max": { "name": "Qwen2.5 Max" },
|
|
24
|
-
* ...
|
|
25
|
-
* }
|
|
26
|
-
* }
|
|
27
|
-
* }
|
|
28
|
-
* }
|
|
9
|
+
* 2. Run /connect -> Select "Other" -> Enter "qwen"
|
|
29
10
|
*/
|
|
30
11
|
|
|
31
12
|
const QWEN_PROVIDER_ID = 'qwen';
|
|
32
13
|
|
|
33
14
|
const QWEN_MODELS = {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
15
|
+
'qwen-max': { name: 'Qwen Max' },
|
|
16
|
+
'qwen-max-latest': { name: 'Qwen Max Latest' },
|
|
17
|
+
'qwen2.5-max': { name: 'Qwen2.5 Max' },
|
|
18
|
+
'qwen2.5-plus': { name: 'Qwen2.5 Plus' },
|
|
19
|
+
'qwen2.5-turbo': { name: 'Qwen2.5 Turbo' },
|
|
20
|
+
'qwen2.5-14b-instruct-1m': { name: 'Qwen2.5 14B Instruct 1M' },
|
|
21
|
+
'qwen2.5-72b-instruct': { name: 'Qwen2.5 72B Instruct' },
|
|
22
|
+
'qwen2.5-coder-32b-instruct': { name: 'Qwen2.5 Coder 32B' },
|
|
23
|
+
'qwen2.5-omni-7b': { name: 'Qwen2.5 Omni 7B' },
|
|
24
|
+
'qwen2.5-vl-32b-instruct': { name: 'Qwen2.5 VL 32B' },
|
|
25
|
+
'qwen3-next-80b-a3b': { name: 'Qwen3 Next 80B A3B' },
|
|
26
|
+
'qwen3-235b-a22b-2507': { name: 'Qwen3 235B A22B' },
|
|
27
|
+
'qwen3-30b-a3b-2507': { name: 'Qwen3 30B A3B' },
|
|
28
|
+
'qwen3-coder': { name: 'Qwen3 Coder' },
|
|
29
|
+
'qwen3-coder-flash': { name: 'Qwen3 Coder Flash' },
|
|
30
|
+
'qwen3-max': { name: 'Qwen3 Max' },
|
|
31
|
+
'qwen3-omni-flash': { name: 'Qwen3 Omni Flash' },
|
|
32
|
+
'qwen3-vl-235b-a22b': { name: 'Qwen3 VL 235B' },
|
|
33
|
+
'qwen3-vl-32b': { name: 'Qwen3 VL 32B' },
|
|
34
|
+
'qwen3-vl-30b-a3b': { name: 'Qwen3 VL 30B A3B' },
|
|
35
|
+
'qvq-max': { name: 'QVQ Max' },
|
|
36
|
+
'qwq-32b': { name: 'QWQ 32B' },
|
|
37
|
+
'qwen-deep-research': { name: 'Qwen Deep Research' },
|
|
38
|
+
'qwen-web-dev': { name: 'Qwen Web Dev' },
|
|
39
|
+
'qwen-full-stack': { name: 'Qwen Full Stack' },
|
|
40
|
+
'qwen-cogview': { name: 'Qwen CogView' }
|
|
60
41
|
};
|
|
61
42
|
|
|
62
|
-
|
|
43
|
+
function getProviderConfig(apiKey = null) {
|
|
44
|
+
const options = {
|
|
45
|
+
baseURL: 'https://qwen.aikit.club/v1',
|
|
46
|
+
headers: {
|
|
47
|
+
'Authorization': `Bearer ${apiKey || ''}`
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
if (apiKey) {
|
|
52
|
+
options.apiKey = apiKey;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
npm: '@ai-sdk/openai-compatible',
|
|
57
|
+
name: 'Qwen AI',
|
|
58
|
+
options,
|
|
59
|
+
models: QWEN_MODELS
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const QwenPlugin = async (ctx) => {
|
|
64
|
+
let cachedApiKey = null;
|
|
65
|
+
|
|
63
66
|
return {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
67
|
+
config: async (config) => {
|
|
68
|
+
if (!config.provider) {
|
|
69
|
+
config.provider = {};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!config.provider[QWEN_PROVIDER_ID]) {
|
|
73
|
+
config.provider[QWEN_PROVIDER_ID] = getProviderConfig(cachedApiKey);
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
'installation.updated': async ({ installation }) => {
|
|
78
|
+
// Try to get API key from auth config
|
|
79
|
+
if (installation?.auth?.[QWEN_PROVIDER_ID]?.apiKey) {
|
|
80
|
+
cachedApiKey = installation.auth[QWEN_PROVIDER_ID].apiKey;
|
|
81
|
+
|
|
82
|
+
// Update config with API key
|
|
83
|
+
try {
|
|
84
|
+
const configPath = ctx.project?.id
|
|
85
|
+
? `${ctx.directory}/opencode.json`
|
|
86
|
+
: `${process.env.HOME}/.config/opencode/opencode.json`;
|
|
87
|
+
|
|
88
|
+
const { exists } = await import('fs');
|
|
89
|
+
if (exists(configPath)) {
|
|
90
|
+
const { readFile, writeFile } = await import('fs/promises');
|
|
91
|
+
try {
|
|
92
|
+
const configContent = await readFile(configPath, 'utf-8');
|
|
93
|
+
const config = JSON.parse(configContent);
|
|
94
|
+
|
|
95
|
+
if (config.provider && config.provider[QWEN_PROVIDER_ID]) {
|
|
96
|
+
config.provider[QWEN_PROVIDER_ID].options.apiKey = cachedApiKey;
|
|
97
|
+
await writeFile(configPath, JSON.stringify(config, null, 2));
|
|
98
|
+
}
|
|
99
|
+
} catch (e) {
|
|
100
|
+
// Ignore config read/write errors
|
|
101
|
+
}
|
|
73
102
|
}
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
|
|
103
|
+
} catch (e) {
|
|
104
|
+
// Ignore errors
|
|
105
|
+
}
|
|
77
106
|
}
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
auth: {
|
|
110
|
+
provider: QWEN_PROVIDER_ID,
|
|
111
|
+
loader: async (auth, provider) => {
|
|
112
|
+
const apiKey = auth?.apiKey || cachedApiKey || '';
|
|
113
|
+
cachedApiKey = apiKey;
|
|
114
|
+
return { apiKey };
|
|
115
|
+
},
|
|
116
|
+
methods: [
|
|
117
|
+
{
|
|
118
|
+
type: 'api',
|
|
119
|
+
label: 'API Key'
|
|
120
|
+
}
|
|
121
|
+
]
|
|
78
122
|
}
|
|
79
123
|
};
|
|
80
124
|
};
|