opencode-qwen-oauth 1.1.0 → 2.0.1
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 +59 -1
- package/dist/browser.d.ts +5 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +71 -8
- package/dist/browser.js.map +1 -1
- package/dist/config.d.ts +23 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +25 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +37 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +79 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +102 -35
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +9 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +46 -4
- package/dist/logger.js.map +1 -1
- package/dist/mutex.d.ts +30 -0
- package/dist/mutex.d.ts.map +1 -0
- package/dist/mutex.js +90 -0
- package/dist/mutex.js.map +1 -0
- package/dist/oauth.d.ts +12 -0
- package/dist/oauth.d.ts.map +1 -1
- package/dist/oauth.js +220 -49
- package/dist/oauth.js.map +1 -1
- package/dist/retry.d.ts +18 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +74 -0
- package/dist/retry.js.map +1 -0
- package/dist/validation.d.ts +39 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +125 -0
- package/dist/validation.js.map +1 -0
- package/package.json +5 -4
package/dist/retry.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry logic with exponential backoff for network requests
|
|
3
|
+
*/
|
|
4
|
+
import { NetworkError, isRecoverableError } from "./errors.js";
|
|
5
|
+
import { debugLog } from "./logger.js";
|
|
6
|
+
const defaultOptions = {
|
|
7
|
+
maxRetries: 3,
|
|
8
|
+
baseDelay: 1000,
|
|
9
|
+
maxDelay: 30000,
|
|
10
|
+
timeout: 30000,
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Retry a function with exponential backoff
|
|
14
|
+
*/
|
|
15
|
+
export async function retryWithBackoff(fn, options = {}) {
|
|
16
|
+
const opts = { ...defaultOptions, ...options };
|
|
17
|
+
let lastError;
|
|
18
|
+
for (let attempt = 0; attempt < opts.maxRetries; attempt++) {
|
|
19
|
+
try {
|
|
20
|
+
debugLog(`Attempt ${attempt + 1}/${opts.maxRetries}`);
|
|
21
|
+
// Add timeout wrapper
|
|
22
|
+
const result = await Promise.race([
|
|
23
|
+
fn(),
|
|
24
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("Request timeout")), opts.timeout)),
|
|
25
|
+
]);
|
|
26
|
+
debugLog(`Attempt ${attempt + 1} succeeded`);
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
31
|
+
// Don't retry if error is not recoverable
|
|
32
|
+
if (!isRecoverableError(error)) {
|
|
33
|
+
debugLog(`Non-recoverable error, not retrying: ${lastError.message}`);
|
|
34
|
+
throw lastError;
|
|
35
|
+
}
|
|
36
|
+
// Don't retry on last attempt
|
|
37
|
+
if (attempt === opts.maxRetries - 1) {
|
|
38
|
+
debugLog(`Max retries (${opts.maxRetries}) reached`);
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
// Calculate delay with exponential backoff and jitter
|
|
42
|
+
const exponentialDelay = opts.baseDelay * Math.pow(2, attempt);
|
|
43
|
+
const jitter = Math.random() * 0.1 * exponentialDelay; // 10% jitter
|
|
44
|
+
const delay = Math.min(exponentialDelay + jitter, opts.maxDelay);
|
|
45
|
+
debugLog(`Retrying in ${Math.round(delay)}ms...`, {
|
|
46
|
+
attempt: attempt + 1,
|
|
47
|
+
error: lastError.message,
|
|
48
|
+
});
|
|
49
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
throw new NetworkError(`Failed after ${opts.maxRetries} retries: ${lastError?.message}`);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Retry fetch with exponential backoff
|
|
56
|
+
*/
|
|
57
|
+
export async function fetchWithRetry(url, init, options = {}) {
|
|
58
|
+
return retryWithBackoff(async () => {
|
|
59
|
+
const response = await fetch(url, init);
|
|
60
|
+
// Throw on HTTP errors for retry logic
|
|
61
|
+
if (!response.ok) {
|
|
62
|
+
// Check for rate limiting
|
|
63
|
+
if (response.status === 429) {
|
|
64
|
+
const retryAfter = response.headers.get("Retry-After");
|
|
65
|
+
const waitTime = retryAfter ? parseInt(retryAfter) * 1000 : 60000;
|
|
66
|
+
throw new NetworkError(`Rate limited (429)`, `Rate limit exceeded. Please wait ${Math.ceil(waitTime / 1000)} seconds.`);
|
|
67
|
+
}
|
|
68
|
+
// Other HTTP errors
|
|
69
|
+
throw new NetworkError(`HTTP ${response.status}: ${response.statusText}`);
|
|
70
|
+
}
|
|
71
|
+
return response;
|
|
72
|
+
}, options);
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input validation and security utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Validate URL is HTTPS and from qwen.ai domain
|
|
6
|
+
*/
|
|
7
|
+
export declare function validateQwenUrl(url: string): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Validate device code format
|
|
10
|
+
*/
|
|
11
|
+
export declare function validateDeviceCode(code: string): void;
|
|
12
|
+
/**
|
|
13
|
+
* Validate user code format
|
|
14
|
+
*/
|
|
15
|
+
export declare function validateUserCode(code: string): void;
|
|
16
|
+
/**
|
|
17
|
+
* Validate access token format
|
|
18
|
+
*/
|
|
19
|
+
export declare function validateToken(token: string): void;
|
|
20
|
+
/**
|
|
21
|
+
* Validate expires_in value
|
|
22
|
+
*/
|
|
23
|
+
export declare function validateExpiresIn(expiresIn: number): void;
|
|
24
|
+
/**
|
|
25
|
+
* Validate interval for polling
|
|
26
|
+
*/
|
|
27
|
+
export declare function validateInterval(interval: number): void;
|
|
28
|
+
/**
|
|
29
|
+
* Sanitize log data by removing sensitive fields
|
|
30
|
+
*/
|
|
31
|
+
export declare function sanitizeLogData(data: any): any;
|
|
32
|
+
/**
|
|
33
|
+
* Validate OAuth error response
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateOAuthError(error: any): {
|
|
36
|
+
error: string;
|
|
37
|
+
error_description?: string;
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAYpD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAOrD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAQnD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAOjD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAQzD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAQvD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,CA8B9C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,GAAG,GAAG;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAWA"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input validation and security utilities
|
|
3
|
+
*/
|
|
4
|
+
import { ValidationError } from "./errors.js";
|
|
5
|
+
/**
|
|
6
|
+
* Validate URL is HTTPS and from qwen.ai domain
|
|
7
|
+
*/
|
|
8
|
+
export function validateQwenUrl(url) {
|
|
9
|
+
try {
|
|
10
|
+
const parsed = new URL(url);
|
|
11
|
+
return (parsed.protocol === "https:" &&
|
|
12
|
+
(parsed.hostname === "chat.qwen.ai" ||
|
|
13
|
+
parsed.hostname === "portal.qwen.ai" ||
|
|
14
|
+
parsed.hostname.endsWith(".qwen.ai")));
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Validate device code format
|
|
22
|
+
*/
|
|
23
|
+
export function validateDeviceCode(code) {
|
|
24
|
+
if (!code || typeof code !== "string") {
|
|
25
|
+
throw new ValidationError("Device code must be a non-empty string", "device_code");
|
|
26
|
+
}
|
|
27
|
+
if (code.length < 10 || code.length > 100) {
|
|
28
|
+
throw new ValidationError("Device code has invalid length", "device_code");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Validate user code format
|
|
33
|
+
*/
|
|
34
|
+
export function validateUserCode(code) {
|
|
35
|
+
if (!code || typeof code !== "string") {
|
|
36
|
+
throw new ValidationError("User code must be a non-empty string", "user_code");
|
|
37
|
+
}
|
|
38
|
+
// User codes are typically short alphanumeric codes
|
|
39
|
+
if (!/^[A-Z0-9-]{4,12}$/i.test(code)) {
|
|
40
|
+
throw new ValidationError("User code has invalid format", "user_code");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Validate access token format
|
|
45
|
+
*/
|
|
46
|
+
export function validateToken(token) {
|
|
47
|
+
if (!token || typeof token !== "string") {
|
|
48
|
+
throw new ValidationError("Token must be a non-empty string", "token");
|
|
49
|
+
}
|
|
50
|
+
if (token.length < 20) {
|
|
51
|
+
throw new ValidationError("Token is too short", "token");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Validate expires_in value
|
|
56
|
+
*/
|
|
57
|
+
export function validateExpiresIn(expiresIn) {
|
|
58
|
+
if (!Number.isInteger(expiresIn) || expiresIn <= 0) {
|
|
59
|
+
throw new ValidationError("expires_in must be a positive integer", "expires_in");
|
|
60
|
+
}
|
|
61
|
+
// Sanity check: shouldn't be more than 1 year
|
|
62
|
+
if (expiresIn > 365 * 24 * 60 * 60) {
|
|
63
|
+
throw new ValidationError("expires_in value is unreasonably large", "expires_in");
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Validate interval for polling
|
|
68
|
+
*/
|
|
69
|
+
export function validateInterval(interval) {
|
|
70
|
+
if (!Number.isInteger(interval) || interval <= 0) {
|
|
71
|
+
throw new ValidationError("Interval must be a positive integer", "interval");
|
|
72
|
+
}
|
|
73
|
+
// Minimum 1 second, maximum 60 seconds
|
|
74
|
+
if (interval < 1 || interval > 60) {
|
|
75
|
+
throw new ValidationError("Interval must be between 1 and 60 seconds", "interval");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Sanitize log data by removing sensitive fields
|
|
80
|
+
*/
|
|
81
|
+
export function sanitizeLogData(data) {
|
|
82
|
+
if (!data || typeof data !== "object") {
|
|
83
|
+
return data;
|
|
84
|
+
}
|
|
85
|
+
const sensitiveFields = [
|
|
86
|
+
"access_token",
|
|
87
|
+
"refresh_token",
|
|
88
|
+
"api_key",
|
|
89
|
+
"apiKey",
|
|
90
|
+
"secret",
|
|
91
|
+
"password",
|
|
92
|
+
"verifier",
|
|
93
|
+
"device_code",
|
|
94
|
+
];
|
|
95
|
+
const sanitized = Array.isArray(data) ? [] : {};
|
|
96
|
+
for (const [key, value] of Object.entries(data)) {
|
|
97
|
+
const lowerKey = key.toLowerCase();
|
|
98
|
+
if (sensitiveFields.some((field) => lowerKey.includes(field))) {
|
|
99
|
+
sanitized[key] = "[REDACTED]";
|
|
100
|
+
}
|
|
101
|
+
else if (value && typeof value === "object") {
|
|
102
|
+
sanitized[key] = sanitizeLogData(value);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
sanitized[key] = value;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return sanitized;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Validate OAuth error response
|
|
112
|
+
*/
|
|
113
|
+
export function validateOAuthError(error) {
|
|
114
|
+
if (!error || typeof error !== "object") {
|
|
115
|
+
throw new ValidationError("Invalid OAuth error response");
|
|
116
|
+
}
|
|
117
|
+
if (!error.error || typeof error.error !== "string") {
|
|
118
|
+
throw new ValidationError("OAuth error must have an error field");
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
error: error.error,
|
|
122
|
+
error_description: error.error_description,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-qwen-oauth",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Qwen OAuth authentication plugin for OpenCode - authenticate with Qwen.ai using OAuth device flow",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"bin": {
|
|
9
|
-
"opencode-qwen-oauth": "
|
|
9
|
+
"opencode-qwen-oauth": "bin/install.js"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"build": "tsc -p tsconfig.json",
|
|
19
19
|
"dev": "tsc -p tsconfig.json --watch",
|
|
20
20
|
"prepublishOnly": "npm run build",
|
|
21
|
-
"test": "
|
|
21
|
+
"test": "bun test",
|
|
22
|
+
"test:watch": "bun test --watch"
|
|
22
23
|
},
|
|
23
24
|
"keywords": [
|
|
24
25
|
"opencode",
|
|
@@ -33,7 +34,7 @@
|
|
|
33
34
|
"license": "MIT",
|
|
34
35
|
"repository": {
|
|
35
36
|
"type": "git",
|
|
36
|
-
"url": "https://github.com/yourusername/opencode-qwen-oauth.git"
|
|
37
|
+
"url": "git+https://github.com/yourusername/opencode-qwen-oauth.git"
|
|
37
38
|
},
|
|
38
39
|
"bugs": {
|
|
39
40
|
"url": "https://github.com/yourusername/opencode-qwen-oauth/issues"
|