qwen-opencode-provider 1.0.1 → 1.0.3

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/index.js +41 -309
  3. package/package.json +3 -11
package/README.md CHANGED
@@ -39,7 +39,7 @@ cp opencode-qwen-plugin/package.json ~/.config/opencode/
39
39
  Thêm vào `opencode.json`:
40
40
  ```json
41
41
  {
42
- "plugin": ["opencode-qwen-plugin"]
42
+ "plugin": ["qwen-opencode-provider"]
43
43
  }
44
44
  ```
45
45
 
package/index.js CHANGED
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * OpenCode Qwen API Plugin
3
3
  *
4
- * This plugin adds Qwen AI provider to OpenCode and provides custom tools
5
- * for validating tokens and listing models.
4
+ * This plugin automatically adds Qwen AI provider to OpenCode config.
6
5
  *
7
6
  * Provider ID: qwen
8
7
  * Base URL: https://qwen.aikit.club/v1
@@ -63,7 +62,6 @@ function addQwenProvider() {
63
62
  let config = readConfig();
64
63
 
65
64
  if (!config) {
66
- // new Create config with Qwen provider
67
65
  config = {
68
66
  $schema: "https://opencode.ai/config.json",
69
67
  provider: {
@@ -77,121 +75,37 @@ function addQwenProvider() {
77
75
  }
78
76
  },
79
77
  models: {
80
- // Chat Completions
81
- "qwen-max": {
82
- name: "Qwen Max",
83
- description: "Latest Qwen Max model with best performance"
84
- },
85
- "qwen-max-latest": {
86
- name: "Qwen Max Latest",
87
- description: "Latest version of Qwen Max"
88
- },
89
- "qwen2.5-max": {
90
- name: "Qwen2.5 Max",
91
- description: "Qwen2.5 series with vision, reasoning and web search"
92
- },
93
- "qwen2.5-plus": {
94
- name: "Qwen2.5 Plus",
95
- description: "Balanced performance with vision support"
96
- },
97
- "qwen2.5-turbo": {
98
- name: "Qwen2.5 Turbo",
99
- description: "Fast responses with vision support"
100
- },
101
- "qwen2.5-14b-instruct-1m": {
102
- name: "Qwen2.5 14B Instruct 1M",
103
- description: "14B parameters with 1M context window"
104
- },
105
- "qwen2.5-72b-instruct": {
106
- name: "Qwen2.5 72B Instruct",
107
- description: "72B parameters for complex tasks"
108
- },
109
- "qwen2.5-coder-32b-instruct": {
110
- name: "Qwen2.5 Coder 32B",
111
- description: "Specialized code generation model"
112
- },
113
- "qwen2.5-omni-7b": {
114
- name: "Qwen2.5 Omni 7B",
115
- description: "Multimodal model with text, image, audio support"
116
- },
117
- "qwen2.5-vl-32b-instruct": {
118
- name: "Qwen2.5 VL 32B",
119
- description: "Vision-language model"
120
- },
121
- // Qwen3 Series
122
- "qwen3-next-80b-a3b": {
123
- name: "Qwen3 Next 80B A3B",
124
- description: "Next generation with 80B parameters"
125
- },
126
- "qwen3-235b-a22b-2507": {
127
- name: "Qwen3 235B A22B",
128
- description: "Large model with 235B parameters"
129
- },
130
- "qwen3-30b-a3b-2507": {
131
- name: "Qwen3 30B A3B",
132
- description: "Compact high-performance model"
133
- },
134
- "qwen3-coder": {
135
- name: "Qwen3 Coder",
136
- description: "Code generation with tool calling"
137
- },
138
- "qwen3-coder-flash": {
139
- name: "Qwen3 Coder Flash",
140
- description: "Fast code generation"
141
- },
142
- "qwen3-max": {
143
- name: "Qwen3 Max",
144
- description: "Best Qwen3 performance"
145
- },
146
- "qwen3-omni-flash": {
147
- name: "Qwen3 Omni Flash",
148
- description: "Fast multimodal model"
149
- },
150
- "qwen3-vl-235b-a22b": {
151
- name: "Qwen3 VL 235B A22B",
152
- description: "Large vision-language model"
153
- },
154
- "qwen3-vl-32b": {
155
- name: "Qwen3 VL 32B",
156
- description: "Vision-language model 32B"
157
- },
158
- "qwen3-vl-30b-a3b": {
159
- name: "Qwen3 VL 30B A3B",
160
- description: "Compact vision-language model"
161
- },
162
- // Reasoning Models
163
- "qvq-max": {
164
- name: "QVQ Max",
165
- description: "Vision reasoning model"
166
- },
167
- "qwq-32b": {
168
- name: "QWQ 32B",
169
- description: "Reasoning model with thinking"
170
- },
171
- "qwen-deep-research": {
172
- name: "Qwen Deep Research",
173
- description: "Research-focused model with web search"
174
- },
175
- // Development Models
176
- "qwen-web-dev": {
177
- name: "Qwen Web Dev",
178
- description: "Web development specialized model"
179
- },
180
- "qwen-full-stack": {
181
- name: "Qwen Full Stack",
182
- description: "Full-stack application development"
183
- },
184
- // Image Generation
185
- "qwen-cogview": {
186
- name: "Qwen CogView",
187
- description: "Image generation model"
188
- }
78
+ "qwen-max": { name: "Qwen Max" },
79
+ "qwen-max-latest": { name: "Qwen Max Latest" },
80
+ "qwen2.5-max": { name: "Qwen2.5 Max" },
81
+ "qwen2.5-plus": { name: "Qwen2.5 Plus" },
82
+ "qwen2.5-turbo": { name: "Qwen2.5 Turbo" },
83
+ "qwen2.5-14b-instruct-1m": { name: "Qwen2.5 14B Instruct 1M" },
84
+ "qwen2.5-72b-instruct": { name: "Qwen2.5 72B Instruct" },
85
+ "qwen2.5-coder-32b-instruct": { name: "Qwen2.5 Coder 32B" },
86
+ "qwen2.5-omni-7b": { name: "Qwen2.5 Omni 7B" },
87
+ "qwen2.5-vl-32b-instruct": { name: "Qwen2.5 VL 32B" },
88
+ "qwen3-next-80b-a3b": { name: "Qwen3 Next 80B A3B" },
89
+ "qwen3-235b-a22b-2507": { name: "Qwen3 235B A22B" },
90
+ "qwen3-30b-a3b-2507": { name: "Qwen3 30B A3B" },
91
+ "qwen3-coder": { name: "Qwen3 Coder" },
92
+ "qwen3-coder-flash": { name: "Qwen3 Coder Flash" },
93
+ "qwen3-max": { name: "Qwen3 Max" },
94
+ "qwen3-omni-flash": { name: "Qwen3 Omni Flash" },
95
+ "qwen3-vl-235b-a22b": { name: "Qwen3 VL 235B A22B" },
96
+ "qwen3-vl-32b": { name: "Qwen3 VL 32B" },
97
+ "qwen3-vl-30b-a3b": { name: "Qwen3 VL 30B A3B" },
98
+ "qvq-max": { name: "QVQ Max" },
99
+ "qwq-32b": { name: "QWQ 32B" },
100
+ "qwen-deep-research": { name: "Qwen Deep Research" },
101
+ "qwen-web-dev": { name: "Qwen Web Dev" },
102
+ "qwen-full-stack": { name: "Qwen Full Stack" },
103
+ "qwen-cogview": { name: "Qwen CogView" }
189
104
  }
190
105
  }
191
106
  }
192
107
  };
193
108
  } else {
194
- // Add Qwen provider to existing config
195
109
  if (!config.provider) {
196
110
  config.provider = {};
197
111
  }
@@ -245,212 +159,30 @@ function addQwenProvider() {
245
159
  /**
246
160
  * OpenCode Plugin
247
161
  */
248
- export const QwenPlugin = async ({ project, client, $, directory, worktree }) => {
162
+ export const QwenPlugin = async ({ client }) => {
249
163
  // Automatically add Qwen provider on first load
250
164
  try {
251
165
  const configPath = getConfigPath();
252
166
  if (!existsSync(dirname(configPath))) {
253
- // Config directory doesn't exist yet, skip
254
- } else {
255
- const config = readConfig();
256
- if (!isQwenProviderConfigured(config)) {
257
- addQwenProvider();
258
- await client.app.log({
259
- body: {
260
- service: "qwen-plugin",
261
- level: "info",
262
- message: "Qwen provider added to OpenCode config",
263
- }
264
- });
265
- }
167
+ return {};
266
168
  }
267
- } catch (error) {
268
- // Silently fail - provider can be added manually
269
- }
270
-
271
- return {
272
- // Custom tools for Qwen API
273
- tool: {
274
- /**
275
- * Validate Qwen API token
276
- */
277
- "qwen-validate-token": {
278
- description: "Validate a Qwen API access token",
279
- args: {
280
- token: {
281
- type: "string",
282
- description: "The Qwen access token to validate",
283
- required: true
284
- }
285
- },
286
- async execute(args, context) {
287
- const { directory, worktree } = context;
288
-
289
- try {
290
- const response = await fetch(`${QWEN_BASE_URL}/validate?token=${args.token}`, {
291
- method: "GET",
292
- headers: {
293
- "Content-Type": "application/json"
294
- }
295
- });
296
-
297
- const data = await response.json();
298
-
299
- if (data.valid) {
300
- return `✅ Token is valid!\nUser ID: ${data.user_id || 'N/A'}\nExpires: ${data.expires_at || 'N/A'}`;
301
- } else {
302
- return `❌ Token is invalid or expired`;
303
- }
304
- } catch (error) {
305
- return `Error validating token: ${error.message}`;
306
- }
307
- }
308
- },
309
-
310
- /**
311
- * List available Qwen models
312
- */
313
- "qwen-list-models": {
314
- description: "List all available Qwen models",
315
- args: {
316
- apiKey: {
317
- type: "string",
318
- description: "Qwen API key (Bearer token)",
319
- required: true
320
- }
321
- },
322
- async execute(args, context) {
323
- try {
324
- const response = await fetch(`${QWEN_BASE_URL}/models`, {
325
- method: "GET",
326
- headers: {
327
- "Authorization": `Bearer ${args.apiKey}`,
328
- "Content-Type": "application/json"
329
- }
330
- });
331
-
332
- const data = await response.json();
333
-
334
- if (data.data && Array.isArray(data.data)) {
335
- const models = data.data.map(m => `• ${m.id} - ${m.description || 'No description'}`).join('\n');
336
- return `Available Qwen Models:\n\n${models}`;
337
- } else {
338
- return `Error: Could not fetch models - ${JSON.stringify(data)}`;
339
- }
340
- } catch (error) {
341
- return `Error listing models: ${error.message}`;
342
- }
343
- }
344
- },
345
-
346
- /**
347
- * Get Qwen API setup instructions
348
- */
349
- "qwen-setup": {
350
- description: "Get instructions for setting up Qwen API in OpenCode",
351
- args: {},
352
- async execute(args, context) {
353
- return `
354
- ╔══════════════════════════════════════════════════════════════════╗
355
- ║ QWEN API SETUP GUIDE ║
356
- ╠══════════════════════════════════════════════════════════════════╣
357
- ║ ║
358
- ║ 1. GET YOUR TOKEN: ║
359
- ║ • Visit https://chat.qwen.ai ║
360
- ║ • Login and open Developer Console (F12) ║
361
- ║ • Run: localStorage.getItem('token') ║
362
- ║ • Or use the provided JavaScript bookmarklet ║
363
- ║ ║
364
- ║ 2. ADD TO OPENCODE: ║
365
- ║ Run: /connect ║
366
- ║ Search: qwen ║
367
- ║ Enter your token ║
368
- ║ ║
369
- ║ 3. SELECT MODEL: ║
370
- ║ Run: /models ║
371
- ║ Select a Qwen model ║
372
- ║ ║
373
- ║ AVAILABLE MODELS: ║
374
- ║ • qwen2.5-max - Best overall performance ║
375
- ║ • qwen2.5-turbo - Fast responses ║
376
- ║ • qwen2.5-plus - Balanced ║
377
- ║ • qwen3-coder - Code generation ║
378
- ║ • qwen3-max - Latest Qwen3 ║
379
- ║ • qwen-deep-research - Research tasks ║
380
- ║ • qwen-web-dev - Web development ║
381
- ║ • qwen-full-stack - Full-stack apps ║
382
- ║ ║
383
- ║ FEATURES: ║
384
- ║ ✅ Vision (image analysis) ║
385
- ║ ✅ Web Search ║
386
- ║ ✅ Thinking Mode ║
387
- ║ ✅ Image Generation ║
388
- ║ ✅ Code Generation ║
389
- ║ ║
390
- ╚══════════════════════════════════════════════════════════════════╝
391
- `;
392
- }
393
- },
394
-
395
- /**
396
- * Test Qwen API connection
397
- */
398
- "qwen-test": {
399
- description: "Test Qwen API connection with a simple prompt",
400
- args: {
401
- apiKey: {
402
- type: "string",
403
- description: "Qwen API key",
404
- required: true
405
- },
406
- message: {
407
- type: "string",
408
- description: "Test message (default: 'Hello')",
409
- required: false
410
- }
411
- },
412
- async execute(args, context) {
413
- const message = args.message || "Hello, how are you?";
414
-
415
- try {
416
- const response = await fetch(`${QWEN_BASE_URL}/chat/completions`, {
417
- method: "POST",
418
- headers: {
419
- "Authorization": `Bearer ${args.apiKey}`,
420
- "Content-Type": "application/json"
421
- },
422
- body: JSON.stringify({
423
- model: "qwen2.5-turbo",
424
- messages: [{ role: "user", content: message }],
425
- stream: false
426
- })
427
- });
428
-
429
- const data = await response.json();
430
-
431
- if (data.choices && data.choices[0]) {
432
- return `✅ Connection successful!\n\nModel: ${data.model}\nResponse: ${data.choices[0].message.content}`;
433
- } else {
434
- return `❌ Error: ${JSON.stringify(data)}`;
435
- }
436
- } catch (error) {
437
- return `❌ Connection failed: ${error.message}`;
438
- }
439
- }
440
- }
441
- },
442
-
443
- // Event hooks
444
- "session.created": async ({ session }) => {
445
- await client.app.log({
169
+
170
+ const config = readConfig();
171
+ if (!isQwenProviderConfigured(config)) {
172
+ addQwenProvider();
173
+ await client?.app?.log?.({
446
174
  body: {
447
175
  service: "qwen-plugin",
448
- level: "debug",
449
- message: `New session created: ${session.id}`,
176
+ level: "info",
177
+ message: "Qwen provider added to OpenCode config",
450
178
  }
451
179
  });
452
180
  }
453
- };
181
+ } catch (error) {
182
+ // Silently fail - provider can be added manually
183
+ }
184
+
185
+ return {};
454
186
  };
455
187
 
456
188
  export default QwenPlugin;
package/package.json CHANGED
@@ -1,19 +1,11 @@
1
1
  {
2
2
  "name": "qwen-opencode-provider",
3
- "version": "1.0.1",
4
- "description": "OpenCode plugin for Qwen API - adds provider and 28+ models with custom tools",
3
+ "version": "1.0.3",
4
+ "description": "OpenCode plugin for Qwen API - auto adds provider with 28+ models",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
- "keywords": ["opencode", "plugin", "qwen", "ai", "alibaba", "qwen-api", "chatgpt"],
7
+ "keywords": ["opencode", "plugin", "qwen", "ai", "alibaba"],
8
8
  "author": "",
9
9
  "license": "MIT",
10
- "repository": {
11
- "type": "git",
12
- "url": "https://github.com/tanu1337/qwen-api"
13
- },
14
- "homepage": "https://github.com/tanu1337/qwen-api#readme",
15
- "bugs": {
16
- "url": "https://github.com/tanu1337/qwen-api/issues"
17
- },
18
10
  "dependencies": {}
19
11
  }