qwen-opencode-provider 1.0.4 → 1.0.6
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 -24
- package/index.js +63 -118
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
# OpenCode Qwen Plugin
|
|
2
2
|
|
|
3
|
-
OpenCode plugin for Qwen AI - auto
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Auto-configure**: Automatically adds Qwen provider to OpenCode
|
|
8
|
-
- **28+ Models**: All Qwen models pre-configured
|
|
9
|
-
- **Native auth**: Uses OpenCode's built-in auth system (`/connect`)
|
|
3
|
+
OpenCode plugin for Qwen AI - auto-registers provider with 28+ models.
|
|
10
4
|
|
|
11
5
|
## Installation
|
|
12
6
|
|
|
@@ -19,22 +13,35 @@ Add to `opencode.json`:
|
|
|
19
13
|
|
|
20
14
|
## Usage
|
|
21
15
|
|
|
22
|
-
###
|
|
16
|
+
### Connect
|
|
17
|
+
|
|
23
18
|
```bash
|
|
24
19
|
/connect
|
|
20
|
+
# Select: Other
|
|
21
|
+
# Enter: qwen
|
|
22
|
+
# Enter your Qwen token
|
|
25
23
|
```
|
|
26
|
-
Search for "qwen" and enter your Qwen access token.
|
|
27
24
|
|
|
28
|
-
###
|
|
25
|
+
### Get Token
|
|
26
|
+
|
|
29
27
|
1. Visit https://chat.qwen.ai and login
|
|
30
28
|
2. Open Developer Console (F12)
|
|
31
29
|
3. Run: `localStorage.getItem('token')`
|
|
32
30
|
|
|
33
|
-
###
|
|
31
|
+
### Select Model
|
|
32
|
+
|
|
34
33
|
```bash
|
|
35
34
|
/models
|
|
35
|
+
# Choose any Qwen model
|
|
36
36
|
```
|
|
37
|
-
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- 👁️ Vision (image analysis)
|
|
41
|
+
- 🌐 Web Search
|
|
42
|
+
- 🧠 Thinking Mode
|
|
43
|
+
- 🎨 Image Generation
|
|
44
|
+
- 👨💻 Code Generation
|
|
38
45
|
|
|
39
46
|
## Supported Models
|
|
40
47
|
|
|
@@ -52,15 +59,3 @@ Choose any Qwen model.
|
|
|
52
59
|
| qwen-web-dev | Web development |
|
|
53
60
|
| qwen-full-stack | Full-stack apps |
|
|
54
61
|
| qwen-cogview | Image generation |
|
|
55
|
-
|
|
56
|
-
## API Features
|
|
57
|
-
|
|
58
|
-
- 👁️ Vision (image analysis)
|
|
59
|
-
- 🌐 Web Search
|
|
60
|
-
- 🧠 Thinking Mode
|
|
61
|
-
- 🎨 Image Generation
|
|
62
|
-
- 👨💻 Code Generation
|
|
63
|
-
|
|
64
|
-
## License
|
|
65
|
-
|
|
66
|
-
MIT
|
package/index.js
CHANGED
|
@@ -1,132 +1,77 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* OpenCode Qwen API Plugin
|
|
3
3
|
*
|
|
4
|
-
* Automatically
|
|
5
|
-
*
|
|
4
|
+
* Automatically registers Qwen provider with OpenCode.
|
|
5
|
+
* No manual config needed - just add plugin to opencode.json!
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* 1. Add to opencode.json: { "plugin": ["qwen-opencode-provider"] }
|
|
9
|
+
* 2. Run /connect -> Select "Other" -> Enter "qwen"
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
|
-
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
12
|
-
import { join } from 'path';
|
|
13
|
-
import { homedir } from 'os';
|
|
14
|
-
|
|
15
|
-
const QWEN_BASE_URL = 'https://qwen.aikit.club/v1';
|
|
16
12
|
const QWEN_PROVIDER_ID = 'qwen';
|
|
17
13
|
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"qwen2.5-14b-instruct-1m": { name: "Qwen2.5 14B Instruct 1M", description: "1M context" },
|
|
25
|
-
"qwen2.5-72b-instruct": { name: "Qwen2.5 72B Instruct", description: "72B parameters" },
|
|
26
|
-
"qwen2.5-coder-32b-instruct": { name: "Qwen2.5 Coder 32B", description: "Code generation" },
|
|
27
|
-
"qwen2.5-omni-7b": { name: "Qwen2.5 Omni 7B", description: "Multimodal" },
|
|
28
|
-
"qwen2.5-vl-32b-instruct": { name: "Qwen2.5 VL 32B", description: "Vision-language" },
|
|
29
|
-
"qwen3-next-80b-a3b": { name: "Qwen3 Next 80B A3B", description: "Next gen" },
|
|
30
|
-
"qwen3-235b-a22b-2507": { name: "Qwen3 235B A22B", description: "Large model" },
|
|
31
|
-
"qwen3-30b-a3b-2507": { name: "Qwen3 30B A3B", description: "Compact high-perf" },
|
|
32
|
-
"qwen3-coder": { name: "Qwen3 Coder", description: "Code + tool calling" },
|
|
33
|
-
"qwen3-coder-flash": { name: "Qwen3 Coder Flash", description: "Fast code" },
|
|
34
|
-
"qwen3-max": { name: "Qwen3 Max", description: "Best Qwen3" },
|
|
35
|
-
"qwen3-omni-flash": { name: "Qwen3 Omni Flash", description: "Fast multimodal" },
|
|
36
|
-
"qwen3-vl-235b-a22b": { name: "Qwen3 VL 235B", description: "Large vision" },
|
|
37
|
-
"qwen3-vl-32b": { name: "Qwen3 VL 32B", description: "Vision 32B" },
|
|
38
|
-
"qwen3-vl-30b-a3b": { name: "Qwen3 VL 30B A3B", description: "Compact vision" },
|
|
39
|
-
"qvq-max": { name: "QVQ Max", description: "Vision reasoning" },
|
|
40
|
-
"qwq-32b": { name: "QWQ 32B", description: "Reasoning with thinking" },
|
|
41
|
-
"qwen-deep-research": { name: "Qwen Deep Research", description: "Research + web search" },
|
|
42
|
-
"qwen-web-dev": { name: "Qwen Web Dev", description: "Web development" },
|
|
43
|
-
"qwen-full-stack": { name: "Qwen Full Stack", description: "Full-stack apps" },
|
|
44
|
-
"qwen-cogview": { name: "Qwen CogView", description: "Image generation" }
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
function getConfigPath() {
|
|
48
|
-
return join(homedir(), '.config', 'opencode', 'opencode.json');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function readConfig() {
|
|
52
|
-
const configPath = getConfigPath();
|
|
53
|
-
if (!existsSync(configPath)) return null;
|
|
54
|
-
try {
|
|
55
|
-
return JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
56
|
-
} catch {
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function writeConfig(config) {
|
|
62
|
-
writeFileSync(getConfigPath(), JSON.stringify(config, null, 2));
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function isQwenProviderConfigured(config) {
|
|
66
|
-
return config?.provider?.[QWEN_PROVIDER_ID] !== undefined;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function addQwenProvider() {
|
|
70
|
-
let config = readConfig();
|
|
71
|
-
|
|
72
|
-
const qwenConfig = {
|
|
73
|
-
npm: "@ai-sdk/openai-compatible",
|
|
74
|
-
name: "Qwen AI",
|
|
75
|
-
options: {
|
|
76
|
-
baseURL: QWEN_BASE_URL,
|
|
77
|
-
headers: {
|
|
78
|
-
"Authorization": "Bearer ${QWEN_API_KEY}"
|
|
14
|
+
export const QwenPlugin = async (ctx) => {
|
|
15
|
+
return {
|
|
16
|
+
config: async (config) => {
|
|
17
|
+
// Auto-add Qwen provider to config
|
|
18
|
+
if (!config.provider) {
|
|
19
|
+
config.provider = {};
|
|
79
20
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
21
|
+
|
|
22
|
+
if (!config.provider[QWEN_PROVIDER_ID]) {
|
|
23
|
+
config.provider[QWEN_PROVIDER_ID] = {
|
|
24
|
+
npm: '@ai-sdk/openai-compatible',
|
|
25
|
+
name: 'Qwen AI',
|
|
26
|
+
options: {
|
|
27
|
+
baseURL: 'https://qwen.aikit.club/v1'
|
|
28
|
+
},
|
|
29
|
+
models: {
|
|
30
|
+
'qwen-max': { name: 'Qwen Max' },
|
|
31
|
+
'qwen-max-latest': { name: 'Qwen Max Latest' },
|
|
32
|
+
'qwen2.5-max': { name: 'Qwen2.5 Max' },
|
|
33
|
+
'qwen2.5-plus': { name: 'Qwen2.5 Plus' },
|
|
34
|
+
'qwen2.5-turbo': { name: 'Qwen2.5 Turbo' },
|
|
35
|
+
'qwen2.5-14b-instruct-1m': { name: 'Qwen2.5 14B Instruct 1M' },
|
|
36
|
+
'qwen2.5-72b-instruct': { name: 'Qwen2.5 72B Instruct' },
|
|
37
|
+
'qwen2.5-coder-32b-instruct': { name: 'Qwen2.5 Coder 32B' },
|
|
38
|
+
'qwen2.5-omni-7b': { name: 'Qwen2.5 Omni 7B' },
|
|
39
|
+
'qwen2.5-vl-32b-instruct': { name: 'Qwen2.5 VL 32B' },
|
|
40
|
+
'qwen3-next-80b-a3b': { name: 'Qwen3 Next 80B A3B' },
|
|
41
|
+
'qwen3-235b-a22b-2507': { name: 'Qwen3 235B A22B' },
|
|
42
|
+
'qwen3-30b-a3b-2507': { name: 'Qwen3 30B A3B' },
|
|
43
|
+
'qwen3-coder': { name: 'Qwen3 Coder' },
|
|
44
|
+
'qwen3-coder-flash': { name: 'Qwen3 Coder Flash' },
|
|
45
|
+
'qwen3-max': { name: 'Qwen3 Max' },
|
|
46
|
+
'qwen3-omni-flash': { name: 'Qwen3 Omni Flash' },
|
|
47
|
+
'qwen3-vl-235b-a22b': { name: 'Qwen3 VL 235B' },
|
|
48
|
+
'qwen3-vl-32b': { name: 'Qwen3 VL 32B' },
|
|
49
|
+
'qwen3-vl-30b-a3b': { name: 'Qwen3 VL 30B A3B' },
|
|
50
|
+
'qvq-max': { name: 'QVQ Max' },
|
|
51
|
+
'qwq-32b': { name: 'QWQ 32B' },
|
|
52
|
+
'qwen-deep-research': { name: 'Qwen Deep Research' },
|
|
53
|
+
'qwen-web-dev': { name: 'Qwen Web Dev' },
|
|
54
|
+
'qwen-full-stack': { name: 'Qwen Full Stack' },
|
|
55
|
+
'qwen-cogview': { name: 'Qwen CogView' }
|
|
56
|
+
}
|
|
57
|
+
};
|
|
89
58
|
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const config = readConfig();
|
|
105
|
-
if (!isQwenProviderConfigured(config)) {
|
|
106
|
-
addQwenProvider();
|
|
107
|
-
await client.app.log({
|
|
108
|
-
body: {
|
|
109
|
-
service: "qwen-plugin",
|
|
110
|
-
level: "info",
|
|
111
|
-
message: "Qwen provider added to OpenCode config"
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
} catch (error) {
|
|
116
|
-
// Silent fail
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return {
|
|
120
|
-
"installation.updated": async ({ installation }) {
|
|
121
|
-
try {
|
|
122
|
-
const config = readConfig();
|
|
123
|
-
if (config?.provider?.[QWEN_PROVIDER_ID]) {
|
|
124
|
-
config.provider[QWEN_PROVIDER_ID].models = QWEN_MODELS;
|
|
125
|
-
writeConfig(config);
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
auth: {
|
|
62
|
+
provider: QWEN_PROVIDER_ID,
|
|
63
|
+
loader: async (auth, provider) => {
|
|
64
|
+
// Load and return the API key
|
|
65
|
+
return {
|
|
66
|
+
apiKey: auth?.apiKey || ''
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
methods: [
|
|
70
|
+
{
|
|
71
|
+
type: 'api',
|
|
72
|
+
label: 'API Key'
|
|
126
73
|
}
|
|
127
|
-
|
|
128
|
-
// Silent fail
|
|
129
|
-
}
|
|
74
|
+
]
|
|
130
75
|
}
|
|
131
76
|
};
|
|
132
77
|
};
|