opencode-qwen-cli-auth 2.2.9 → 2.3.0

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.
@@ -1,12 +1,24 @@
1
1
  /**
2
- * Constants for Qwen OAuth Plugin
2
+ * @fileoverview Constants for Qwen OAuth Plugin
3
+ * Centralized configuration for OAuth endpoints, headers, error codes, and other constants
4
+ * @license MIT
3
5
  */
4
- /** Plugin identifier */
6
+
7
+ /** Plugin identifier for logging and debugging */
5
8
  export const PLUGIN_NAME = "qwen-oauth-plugin";
6
- /** Provider ID for opencode configuration (used in model references like qwen-code/coder-model) */
9
+
10
+ /**
11
+ * Provider ID for opencode configuration
12
+ * Used in model references like qwen-code/coder-model
13
+ */
7
14
  export const PROVIDER_ID = "qwen-code";
8
- /** Dummy API key (actual auth via OAuth) */
15
+
16
+ /**
17
+ * Dummy API key placeholder
18
+ * Actual authentication is handled via OAuth flow, not API key
19
+ */
9
20
  export const DUMMY_API_KEY = "qwen-oauth";
21
+
10
22
  /**
11
23
  * Default Qwen DashScope base URL (fallback if resource_url is missing)
12
24
  * Note: This plugin is for OAuth authentication only. For API key authentication,
@@ -15,27 +27,43 @@ export const DUMMY_API_KEY = "qwen-oauth";
15
27
  * IMPORTANT: OAuth endpoints use /api/v1, DashScope OpenAI-compatible uses /compatible-mode/v1
16
28
  * - OAuth endpoints: /api/v1/oauth2/ (for authentication)
17
29
  * - Chat API: /v1/ (for completions)
30
+ *
31
+ * @constant {string}
18
32
  */
19
33
  // NOTE:
20
34
  // qwen-code (official CLI) defaults to DashScope OpenAI-compatible endpoint when
21
35
  // `resource_url` is missing. This is required for the free OAuth flow to behave
22
36
  // the same as the CLI.
23
37
  export const DEFAULT_QWEN_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1";
24
- /** Qwen OAuth endpoints and configuration */
38
+
39
+ /**
40
+ * Qwen OAuth endpoints and configuration
41
+ * Source: Qwen Code CLI (https://github.com/QwenLM/qwen-code)
42
+ * @namespace
43
+ */
25
44
  export const QWEN_OAUTH = {
45
+ /** OAuth 2.0 Device Code endpoint */
26
46
  DEVICE_CODE_URL: "https://chat.qwen.ai/api/v1/oauth2/device/code",
47
+ /** OAuth 2.0 Token endpoint */
27
48
  TOKEN_URL: "https://chat.qwen.ai/api/v1/oauth2/token",
28
49
  /**
29
50
  * Qwen OAuth Client ID
30
- * Source: Qwen Code CLI (https://github.com/QwenLM/qwen-code)
31
51
  * This is a public client ID used for OAuth Device Authorization Grant flow (RFC 8628)
52
+ * @constant {string}
32
53
  */
33
54
  CLIENT_ID: "f0304373b74a44d2b584a3fb70ca9e56",
55
+ /** OAuth scopes requested: openid, profile, email, and model completion access */
34
56
  SCOPE: "openid profile email model.completion",
57
+ /** OAuth 2.0 Device Code grant type (RFC 8628) */
35
58
  GRANT_TYPE_DEVICE: "urn:ietf:params:oauth:grant-type:device_code",
59
+ /** OAuth 2.0 Refresh Token grant type */
36
60
  GRANT_TYPE_REFRESH: "refresh_token",
37
61
  };
38
- /** HTTP Status Codes */
62
+
63
+ /**
64
+ * HTTP Status Codes for error handling
65
+ * @namespace
66
+ */
39
67
  export const HTTP_STATUS = {
40
68
  OK: 200,
41
69
  BAD_REQUEST: 400,
@@ -43,21 +71,37 @@ export const HTTP_STATUS = {
43
71
  FORBIDDEN: 403,
44
72
  TOO_MANY_REQUESTS: 429,
45
73
  };
74
+
46
75
  /**
47
- * DashScope headers
76
+ * DashScope headers for OAuth authentication
48
77
  * Note: OAuth requires X-DashScope-AuthType to indicate qwen-oauth authentication
78
+ * @namespace
49
79
  */
50
80
  export const PORTAL_HEADERS = {
81
+ /** Header name for auth type specification */
51
82
  AUTH_TYPE: "X-DashScope-AuthType",
83
+ /** Header value for qwen-oauth authentication */
52
84
  AUTH_TYPE_VALUE: "qwen-oauth",
53
85
  };
54
- /** Device flow polling configuration */
86
+
87
+ /**
88
+ * Device flow polling configuration
89
+ * Controls backoff strategy for OAuth token polling
90
+ * @namespace
91
+ */
55
92
  export const DEVICE_FLOW = {
93
+ /** Initial polling interval in milliseconds */
56
94
  INITIAL_POLL_INTERVAL: 2000, // 2 seconds
95
+ /** Maximum polling interval in milliseconds */
57
96
  MAX_POLL_INTERVAL: 10000, // 10 seconds
97
+ /** Backoff multiplier for exponential backoff */
58
98
  BACKOFF_MULTIPLIER: 1.5,
59
99
  };
60
- /** Error messages */
100
+
101
+ /**
102
+ * Error messages for user-facing errors
103
+ * @namespace
104
+ */
61
105
  export const ERROR_MESSAGES = {
62
106
  TOKEN_REFRESH_FAILED: "Failed to refresh token, authentication required",
63
107
  DEVICE_AUTH_TIMEOUT: "Device authorization timed out",
@@ -65,14 +109,27 @@ export const ERROR_MESSAGES = {
65
109
  REQUEST_PARSE_ERROR: "Error parsing request",
66
110
  NO_RESOURCE_URL: "No resource_url in token response, using default",
67
111
  };
68
- /** OAuth error codes */
112
+
113
+ /**
114
+ * OAuth error codes from RFC 8628 Device Flow
115
+ * @namespace
116
+ */
69
117
  export const OAUTH_ERRORS = {
118
+ /** User has not yet authorized the device code */
70
119
  AUTHORIZATION_PENDING: "authorization_pending",
120
+ /** Server requests slower polling (slow_down error) */
71
121
  SLOW_DOWN: "slow_down",
122
+ /** User denied the authorization request */
72
123
  ACCESS_DENIED: "access_denied",
124
+ /** Device code has expired */
73
125
  EXPIRED_TOKEN: "expired_token",
74
126
  };
75
- /** Log stages for request logging */
127
+
128
+ /**
129
+ * Log stages for request logging
130
+ * Used for debugging and tracing request lifecycle
131
+ * @namespace
132
+ */
76
133
  export const LOG_STAGES = {
77
134
  BEFORE_TRANSFORM: "before-transform",
78
135
  AFTER_TRANSFORM: "after-transform",
@@ -81,29 +138,53 @@ export const LOG_STAGES = {
81
138
  DEVICE_CODE_REQUEST: "device-code-request",
82
139
  TOKEN_POLL: "token-poll",
83
140
  };
84
- /** Platform-specific browser opener commands */
141
+
142
+ /**
143
+ * Platform-specific browser opener commands
144
+ * Used for opening OAuth verification URL in default browser
145
+ * @namespace
146
+ */
85
147
  export const PLATFORM_OPENERS = {
86
148
  darwin: "open",
87
149
  win32: "start",
88
150
  linux: "xdg-open",
89
151
  };
90
- /** OAuth authorization labels */
152
+
153
+ /**
154
+ * OAuth authorization labels for UI display
155
+ * @namespace
156
+ */
91
157
  export const AUTH_LABELS = {
158
+ /** Label shown in OpenCode auth provider selection */
92
159
  OAUTH: "Qwen Code (qwen.ai OAuth)",
160
+ /** Instructions shown to user during OAuth flow */
93
161
  INSTRUCTIONS: "Visit the URL shown in your browser to complete authentication.",
94
162
  };
95
- /** OAuth verification URI parameters */
163
+
164
+ /**
165
+ * OAuth verification URI parameters
166
+ * Used to construct complete verification URL with client identification
167
+ * @namespace
168
+ */
96
169
  export const VERIFICATION_URI = {
97
170
  /** Query parameter key for client identification */
98
171
  CLIENT_PARAM_KEY: "client=",
99
172
  /** Full query parameter for Qwen Code client */
100
173
  CLIENT_PARAM_VALUE: "client=qwen-code",
101
174
  };
102
- /** Token refresh buffer (refresh 30 seconds before expiry) */
175
+
176
+ /**
177
+ * Token refresh buffer in milliseconds
178
+ * Tokens are refreshed 30 seconds before expiry to avoid race conditions
179
+ * @constant {number}
180
+ */
103
181
  export const TOKEN_REFRESH_BUFFER_MS = 30 * 1000; // 30 seconds
104
- /** Stream processing configuration */
182
+
183
+ /**
184
+ * Stream processing configuration
185
+ * @namespace
186
+ */
105
187
  export const STREAM_CONFIG = {
106
188
  /** Maximum buffer size for SSE pass-through mode (1MB) */
107
189
  MAX_BUFFER_SIZE: 1024 * 1024,
108
190
  };
109
- //# sourceMappingURL=constants.js.map
@@ -1,10 +1,34 @@
1
+ /**
2
+ * @fileoverview Logging utilities for Qwen OAuth Plugin
3
+ * Provides configurable logging for debugging and request tracing
4
+ * @license MIT
5
+ */
6
+
1
7
  import { writeFileSync, mkdirSync, existsSync } from "node:fs";
2
8
  import { join } from "node:path";
3
9
  import { homedir } from "node:os";
4
- // Logging configuration
10
+
11
+ /**
12
+ * Flag to enable request logging to file
13
+ * Controlled by ENABLE_PLUGIN_REQUEST_LOGGING environment variable
14
+ * @constant {boolean}
15
+ */
5
16
  export const LOGGING_ENABLED = process.env.ENABLE_PLUGIN_REQUEST_LOGGING === "1";
17
+
18
+ /**
19
+ * Flag to enable debug logging to console
20
+ * Controlled by DEBUG_QWEN_PLUGIN or ENABLE_PLUGIN_REQUEST_LOGGING environment variables
21
+ * @constant {boolean}
22
+ */
6
23
  export const DEBUG_ENABLED = process.env.DEBUG_QWEN_PLUGIN === "1" || LOGGING_ENABLED;
24
+
25
+ /**
26
+ * Directory path for log files
27
+ * Logs are stored in ~/.opencode/logs/qwen-plugin/
28
+ * @constant {string}
29
+ */
7
30
  const LOG_DIR = join(homedir(), ".opencode", "logs", "qwen-plugin");
31
+
8
32
  // Log startup message about logging state
9
33
  if (LOGGING_ENABLED) {
10
34
  console.log("[qwen-oauth-plugin] Request logging ENABLED - logs will be saved to:", LOG_DIR);
@@ -12,23 +36,34 @@ if (LOGGING_ENABLED) {
12
36
  if (DEBUG_ENABLED && !LOGGING_ENABLED) {
13
37
  console.log("[qwen-oauth-plugin] Debug logging ENABLED");
14
38
  }
39
+
40
+ /**
41
+ * Request counter for generating unique request IDs in logs
42
+ * @type {number}
43
+ */
15
44
  let requestCounter = 0;
45
+
16
46
  /**
17
47
  * Log request data to file (only when LOGGING_ENABLED is true)
18
- * @param stage - The stage of the request (e.g., "before-transform", "after-transform")
19
- * @param data - The data to log
48
+ * Creates JSON files with request/response data for debugging
49
+ * @param {string} stage - The stage of the request (e.g., "before-transform", "after-transform", "response")
50
+ * @param {Object} data - The data to log (request/response objects, metadata, etc.)
51
+ * @returns {void}
20
52
  */
21
53
  export function logRequest(stage, data) {
22
54
  // Only log if explicitly enabled via environment variable
23
55
  if (!LOGGING_ENABLED)
24
56
  return;
57
+
25
58
  // Ensure log directory exists on first log
26
59
  if (!existsSync(LOG_DIR)) {
27
60
  mkdirSync(LOG_DIR, { recursive: true });
28
61
  }
62
+
29
63
  const timestamp = new Date().toISOString();
30
64
  const requestId = ++requestCounter;
31
65
  const filename = join(LOG_DIR, `request-${requestId}-${stage}.json`);
66
+
32
67
  try {
33
68
  writeFileSync(filename, JSON.stringify({
34
69
  timestamp,
@@ -43,10 +78,13 @@ export function logRequest(stage, data) {
43
78
  console.error("[qwen-oauth-plugin] Failed to write log:", error.message);
44
79
  }
45
80
  }
81
+
46
82
  /**
47
83
  * Log debug information (only when DEBUG_ENABLED is true)
48
- * @param message - Debug message
49
- * @param data - Optional data to log
84
+ * Used for detailed debugging during development
85
+ * @param {string} message - Debug message describing the context
86
+ * @param {*} [data] - Optional data to log (objects, values, etc.)
87
+ * @returns {void}
50
88
  */
51
89
  export function logDebug(message, data) {
52
90
  if (!DEBUG_ENABLED)
@@ -58,10 +96,13 @@ export function logDebug(message, data) {
58
96
  console.log(`[qwen-oauth-plugin] ${message}`);
59
97
  }
60
98
  }
99
+
61
100
  /**
62
101
  * Log error (always enabled for important issues)
63
- * @param message - Error message
64
- * @param data - Optional data to log
102
+ * Used for critical errors that need attention
103
+ * @param {string} message - Error message describing what went wrong
104
+ * @param {*} [data] - Optional data to log (error objects, context, etc.)
105
+ * @returns {void}
65
106
  */
66
107
  export function logError(message, data) {
67
108
  if (data !== undefined) {
@@ -71,10 +112,13 @@ export function logError(message, data) {
71
112
  console.error(`[qwen-oauth-plugin] ${message}`);
72
113
  }
73
114
  }
115
+
74
116
  /**
75
117
  * Log warning (always enabled for important issues)
76
- * @param message - Warning message
77
- * @param data - Optional data to log
118
+ * Used for non-critical issues that may need attention
119
+ * @param {string} message - Warning message describing the issue
120
+ * @param {*} [data] - Optional data to log (context, values, etc.)
121
+ * @returns {void}
78
122
  */
79
123
  export function logWarn(message, data) {
80
124
  if (data !== undefined) {
@@ -84,10 +128,13 @@ export function logWarn(message, data) {
84
128
  console.warn(`[qwen-oauth-plugin] ${message}`);
85
129
  }
86
130
  }
131
+
87
132
  /**
88
133
  * Log info message (always enabled)
89
- * @param message - Info message
90
- * @param data - Optional data to log
134
+ * Used for general informational messages
135
+ * @param {string} message - Info message describing the event
136
+ * @param {*} [data] - Optional data to log (context, values, etc.)
137
+ * @returns {void}
91
138
  */
92
139
  export function logInfo(message, data) {
93
140
  if (data !== undefined) {
@@ -97,4 +144,3 @@ export function logInfo(message, data) {
97
144
  console.log(`[qwen-oauth-plugin] ${message}`);
98
145
  }
99
146
  }
100
- //# sourceMappingURL=logger.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-qwen-cli-auth",
3
- "version": "2.2.9",
3
+ "version": "2.3.0",
4
4
  "description": "Qwen OAuth authentication plugin for opencode - use your Qwen account instead of API keys",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",