@hung319/opencode-qwen 1.1.4 → 1.1.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 CHANGED
@@ -26,7 +26,7 @@ Or add to your `opencode.json` with specific version:
26
26
 
27
27
  ```json
28
28
  {
29
- "plugin": ["@hung319/opencode-qwen@1.1.3"]
29
+ "plugin": ["@hung319/opencode-qwen@1.1.5"]
30
30
  }
31
31
  ```
32
32
 
package/dist/plugin.js CHANGED
@@ -395,8 +395,11 @@ export const createQwenPlugin = (id) => async ({ client, directory }) => {
395
395
  break;
396
396
  }
397
397
  try {
398
- const validation = await validateToken(token);
399
- const email = await promptEmail();
398
+ // Add timeout to prevent hanging during validation
399
+ const validationPromise = validateToken(token);
400
+ const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('Token validation timed out')), 15000));
401
+ const validation = await Promise.race([validationPromise, timeoutPromise]);
402
+ const email = validation.email || await promptEmail();
400
403
  accounts.push({ apiKey: token, email });
401
404
  const isFirstAccount = accounts.length === 1;
402
405
  const am = await AccountManager.loadFromDisk(config.account_selection_strategy);
@@ -437,7 +440,12 @@ export const createQwenPlugin = (id) => async ({ client, directory }) => {
437
440
  callback: async () => ({ type: 'failed' })
438
441
  });
439
442
  }
440
- break;
443
+ // Allow user to try another token instead of breaking completely
444
+ const addAnother = await promptAddAnotherAccount(accounts.length);
445
+ if (!addAnother) {
446
+ break;
447
+ }
448
+ continue; // Continue to ask for another token
441
449
  }
442
450
  }
443
451
  const primary = accounts[0];
@@ -3,34 +3,20 @@ export async function validateToken(apiKey) {
3
3
  // First validate using header-based auth
4
4
  // Use a minimal fetch that only checks if the token is valid
5
5
  try {
6
- const controller = new AbortController();
7
- const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout
8
- const response = await fetch(`${QWEN_CONSTANTS.BASE_URL}/models`, {
6
+ // Only try the validation endpoint first to get user info, as it's more efficient
7
+ const validateController = new AbortController();
8
+ const validateTimeoutId = setTimeout(() => validateController.abort(), 10000); // 10 second timeout
9
+ const validateResponse = await fetch(QWEN_CONSTANTS.VALIDATE_URL, {
10
+ method: 'POST',
9
11
  headers: {
10
- Authorization: `Bearer ${apiKey}`,
12
+ 'Content-Type': 'application/json',
11
13
  'User-Agent': QWEN_CONSTANTS.USER_AGENT
12
14
  },
13
- signal: controller.signal
15
+ body: JSON.stringify({ token: apiKey }),
16
+ signal: validateController.signal
14
17
  });
15
- clearTimeout(timeoutId);
16
- if (!response.ok) {
17
- // Try validation endpoint with token in request body as fallback
18
- const validateController = new AbortController();
19
- const validateTimeoutId = setTimeout(() => validateController.abort(), 10000); // 10 second timeout
20
- const validateResponse = await fetch(QWEN_CONSTANTS.VALIDATE_URL, {
21
- method: 'POST',
22
- headers: {
23
- 'Content-Type': 'application/json',
24
- 'User-Agent': QWEN_CONSTANTS.USER_AGENT
25
- },
26
- body: JSON.stringify({ token: apiKey }),
27
- signal: validateController.signal
28
- });
29
- clearTimeout(validateTimeoutId);
30
- if (!validateResponse.ok) {
31
- const errorText = await validateResponse.text().catch(() => '');
32
- throw new Error(`Token validation failed: ${validateResponse.status} - ${errorText}`);
33
- }
18
+ clearTimeout(validateTimeoutId);
19
+ if (validateResponse.ok) {
34
20
  // Extract email from the validation response
35
21
  const validationData = await validateResponse.json();
36
22
  const email = validationData.email || 'qwen-token-user';
@@ -41,35 +27,27 @@ export async function validateToken(apiKey) {
41
27
  };
42
28
  }
43
29
  else {
44
- // If the models endpoint worked, try to get user info from validation endpoint anyway
45
- const validateController = new AbortController();
46
- const validateTimeoutId = setTimeout(() => validateController.abort(), 10000); // 10 second timeout
47
- const validateResponse = await fetch(QWEN_CONSTANTS.VALIDATE_URL, {
48
- method: 'POST',
30
+ // If validation endpoint failed, try models endpoint as fallback
31
+ const modelsController = new AbortController();
32
+ const modelsTimeoutId = setTimeout(() => modelsController.abort(), 10000); // 10 second timeout
33
+ const modelsResponse = await fetch(`${QWEN_CONSTANTS.BASE_URL}/models`, {
49
34
  headers: {
50
- 'Content-Type': 'application/json',
35
+ Authorization: `Bearer ${apiKey}`,
51
36
  'User-Agent': QWEN_CONSTANTS.USER_AGENT
52
37
  },
53
- body: JSON.stringify({ token: apiKey }),
54
- signal: validateController.signal
38
+ signal: modelsController.signal
55
39
  });
56
- clearTimeout(validateTimeoutId);
57
- if (validateResponse.ok) {
58
- // Extract email from the validation response
59
- const validationData = await validateResponse.json();
60
- const email = validationData.email || 'qwen-token-user';
40
+ clearTimeout(modelsTimeoutId);
41
+ if (modelsResponse.ok) {
61
42
  return {
62
43
  apiKey,
63
- email,
44
+ email: 'qwen-token-user', // Fallback to default email if models endpoint was used
64
45
  authMethod: 'token'
65
46
  };
66
47
  }
67
48
  else {
68
- return {
69
- apiKey,
70
- email: 'qwen-token-user',
71
- authMethod: 'token'
72
- };
49
+ const errorText = await modelsResponse.text().catch(() => '');
50
+ throw new Error(`Token validation failed: ${modelsResponse.status} - ${errorText}`);
73
51
  }
74
52
  }
75
53
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hung319/opencode-qwen",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "OpenCode plugin for Qwen API providing access to Qwen AI models with auto-config and token management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",