opencode-qwen-cli-auth 1.0.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.
Files changed (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +162 -0
  3. package/dist/index.d.ts +21 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +167 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/lib/auth/auth.d.ts +65 -0
  8. package/dist/lib/auth/auth.d.ts.map +1 -0
  9. package/dist/lib/auth/auth.js +419 -0
  10. package/dist/lib/auth/auth.js.map +1 -0
  11. package/dist/lib/auth/browser.d.ts +16 -0
  12. package/dist/lib/auth/browser.d.ts.map +1 -0
  13. package/dist/lib/auth/browser.js +37 -0
  14. package/dist/lib/auth/browser.js.map +1 -0
  15. package/dist/lib/config.d.ts +28 -0
  16. package/dist/lib/config.d.ts.map +1 -0
  17. package/dist/lib/config.js +63 -0
  18. package/dist/lib/config.js.map +1 -0
  19. package/dist/lib/constants.d.ts +105 -0
  20. package/dist/lib/constants.d.ts.map +1 -0
  21. package/dist/lib/constants.js +105 -0
  22. package/dist/lib/constants.js.map +1 -0
  23. package/dist/lib/logger.d.ts +33 -0
  24. package/dist/lib/logger.d.ts.map +1 -0
  25. package/dist/lib/logger.js +100 -0
  26. package/dist/lib/logger.js.map +1 -0
  27. package/dist/lib/prompts/fallback/opencode-qwen-prompt.txt +109 -0
  28. package/dist/lib/prompts/opencode-qwen.d.ts +14 -0
  29. package/dist/lib/prompts/opencode-qwen.d.ts.map +1 -0
  30. package/dist/lib/prompts/opencode-qwen.js +121 -0
  31. package/dist/lib/prompts/opencode-qwen.js.map +1 -0
  32. package/dist/lib/prompts/qwen-code.d.ts +25 -0
  33. package/dist/lib/prompts/qwen-code.d.ts.map +1 -0
  34. package/dist/lib/prompts/qwen-code.js +307 -0
  35. package/dist/lib/prompts/qwen-code.js.map +1 -0
  36. package/dist/lib/prompts/qwen-opencode-bridge.d.ts +15 -0
  37. package/dist/lib/prompts/qwen-opencode-bridge.d.ts.map +1 -0
  38. package/dist/lib/prompts/qwen-opencode-bridge.js +81 -0
  39. package/dist/lib/prompts/qwen-opencode-bridge.js.map +1 -0
  40. package/dist/lib/request/fetch-helpers.d.ts +19 -0
  41. package/dist/lib/request/fetch-helpers.d.ts.map +1 -0
  42. package/dist/lib/request/fetch-helpers.js +50 -0
  43. package/dist/lib/request/fetch-helpers.js.map +1 -0
  44. package/dist/lib/request/header-utils.d.ts +38 -0
  45. package/dist/lib/request/header-utils.d.ts.map +1 -0
  46. package/dist/lib/request/header-utils.js +75 -0
  47. package/dist/lib/request/header-utils.js.map +1 -0
  48. package/dist/lib/request/openai-chunk-builder.d.ts +68 -0
  49. package/dist/lib/request/openai-chunk-builder.d.ts.map +1 -0
  50. package/dist/lib/request/openai-chunk-builder.js +110 -0
  51. package/dist/lib/request/openai-chunk-builder.js.map +1 -0
  52. package/dist/lib/request/payload-analyzer.d.ts +34 -0
  53. package/dist/lib/request/payload-analyzer.d.ts.map +1 -0
  54. package/dist/lib/request/payload-analyzer.js +114 -0
  55. package/dist/lib/request/payload-analyzer.js.map +1 -0
  56. package/dist/lib/request/request-transformer.d.ts +39 -0
  57. package/dist/lib/request/request-transformer.d.ts.map +1 -0
  58. package/dist/lib/request/request-transformer.js +108 -0
  59. package/dist/lib/request/request-transformer.js.map +1 -0
  60. package/dist/lib/request/response-handler.d.ts +15 -0
  61. package/dist/lib/request/response-handler.d.ts.map +1 -0
  62. package/dist/lib/request/response-handler.js +90 -0
  63. package/dist/lib/request/response-handler.js.map +1 -0
  64. package/dist/lib/request/sse-parser.d.ts +36 -0
  65. package/dist/lib/request/sse-parser.d.ts.map +1 -0
  66. package/dist/lib/request/sse-parser.js +85 -0
  67. package/dist/lib/request/sse-parser.js.map +1 -0
  68. package/dist/lib/request/stream-normalizer.d.ts +18 -0
  69. package/dist/lib/request/stream-normalizer.d.ts.map +1 -0
  70. package/dist/lib/request/stream-normalizer.js +140 -0
  71. package/dist/lib/request/stream-normalizer.js.map +1 -0
  72. package/dist/lib/types.d.ts +180 -0
  73. package/dist/lib/types.d.ts.map +1 -0
  74. package/dist/lib/types.js +2 -0
  75. package/dist/lib/types.js.map +1 -0
  76. package/package.json +67 -0
@@ -0,0 +1,419 @@
1
+ import { generatePKCE } from "@openauthjs/openauth/pkce";
2
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync } from "fs";
3
+ import { QWEN_OAUTH, DEFAULT_QWEN_BASE_URL, TOKEN_REFRESH_BUFFER_MS, VERIFICATION_URI } from "../constants.js";
4
+ import { getTokenPath, getConfigDir } from "../config.js";
5
+ import { logError, logWarn, logInfo, LOGGING_ENABLED } from "../logger.js";
6
+ // So lan retry toi da khi refresh token that bai
7
+ const MAX_REFRESH_RETRIES = 2;
8
+ const REFRESH_RETRY_DELAY_MS = 1000;
9
+ /**
10
+ * Normalize and validate resource_url from OAuth response
11
+ * @param resourceUrl - Resource URL from token response
12
+ * @returns Normalized URL or undefined if invalid
13
+ */
14
+ function normalizeResourceUrl(resourceUrl) {
15
+ if (!resourceUrl)
16
+ return undefined;
17
+ try {
18
+ // Qwen returns resource_url without protocol (e.g., "portal.qwen.ai")
19
+ // Normalize it by adding https:// if missing
20
+ let normalizedUrl = resourceUrl;
21
+ if (!normalizedUrl.startsWith("http://") && !normalizedUrl.startsWith("https://")) {
22
+ normalizedUrl = `https://${normalizedUrl}`;
23
+ }
24
+ // Validate the normalized URL
25
+ new URL(normalizedUrl);
26
+ if (LOGGING_ENABLED) {
27
+ logInfo("Valid resource_url found and normalized:", normalizedUrl);
28
+ }
29
+ return normalizedUrl;
30
+ }
31
+ catch (error) {
32
+ logWarn("invalid resource_url:", { original: resourceUrl, error });
33
+ return undefined;
34
+ }
35
+ }
36
+ /**
37
+ * Validate token response fields
38
+ * @param json - Token response JSON
39
+ * @param context - Context for logging (e.g., "token response" or "refresh response")
40
+ * @returns True if valid, false otherwise
41
+ */
42
+ function validateTokenResponse(json, context) {
43
+ // Check required fields
44
+ if (!json.access_token || !json.refresh_token || typeof json.expires_in !== "number") {
45
+ logError(`${context} missing fields:`, json);
46
+ return false;
47
+ }
48
+ // Validate expires_in is positive
49
+ if (json.expires_in <= 0) {
50
+ logError(`invalid expires_in value in ${context}:`, json.expires_in);
51
+ return false;
52
+ }
53
+ return true;
54
+ }
55
+ /**
56
+ * Request device authorization code
57
+ * @param pkce - PKCE challenge/verifier pair
58
+ * @returns Device authorization response with user code and verification URL
59
+ */
60
+ export async function requestDeviceCode(pkce) {
61
+ try {
62
+ const res = await fetch(QWEN_OAUTH.DEVICE_CODE_URL, {
63
+ method: "POST",
64
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
65
+ body: new URLSearchParams({
66
+ client_id: QWEN_OAUTH.CLIENT_ID,
67
+ scope: QWEN_OAUTH.SCOPE,
68
+ code_challenge: pkce.challenge,
69
+ code_challenge_method: "S256",
70
+ }),
71
+ });
72
+ if (!res.ok) {
73
+ const text = await res.text().catch(() => "");
74
+ logError("device code request failed:", { status: res.status, text });
75
+ return null;
76
+ }
77
+ const json = await res.json();
78
+ if (LOGGING_ENABLED) {
79
+ logInfo("Device code response received:", json);
80
+ }
81
+ if (!json.device_code || !json.user_code || !json.verification_uri) {
82
+ logError("device code response missing fields:", json);
83
+ return null;
84
+ }
85
+ // Ensure verification_uri_complete includes the client parameter
86
+ // Qwen's OAuth server requires client=qwen-code for proper authentication
87
+ if (!json.verification_uri_complete || !json.verification_uri_complete.includes(VERIFICATION_URI.CLIENT_PARAM_KEY)) {
88
+ const baseUrl = json.verification_uri_complete || json.verification_uri;
89
+ const separator = baseUrl.includes('?') ? '&' : '?';
90
+ json.verification_uri_complete = `${baseUrl}${separator}${VERIFICATION_URI.CLIENT_PARAM_VALUE}`;
91
+ if (LOGGING_ENABLED) {
92
+ logInfo("Fixed verification_uri_complete:", json.verification_uri_complete);
93
+ }
94
+ }
95
+ return json;
96
+ }
97
+ catch (error) {
98
+ logError("device code request error:", error);
99
+ return null;
100
+ }
101
+ }
102
+ /**
103
+ * Poll for token using device code
104
+ * @param deviceCode - Device code from authorization response
105
+ * @param verifier - PKCE verifier
106
+ * @param interval - Polling interval in seconds (from device response)
107
+ * @returns Token result or null if still pending
108
+ */
109
+ export async function pollForToken(deviceCode, verifier, interval = 2) {
110
+ try {
111
+ const res = await fetch(QWEN_OAUTH.TOKEN_URL, {
112
+ method: "POST",
113
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
114
+ body: new URLSearchParams({
115
+ grant_type: QWEN_OAUTH.GRANT_TYPE_DEVICE,
116
+ client_id: QWEN_OAUTH.CLIENT_ID,
117
+ device_code: deviceCode,
118
+ code_verifier: verifier,
119
+ }),
120
+ });
121
+ if (!res.ok) {
122
+ const json = await res.json().catch(() => ({}));
123
+ const error = json.error;
124
+ // Handle expected errors
125
+ if (error === "authorization_pending") {
126
+ return { type: "pending" };
127
+ }
128
+ if (error === "slow_down") {
129
+ return { type: "slow_down" };
130
+ }
131
+ if (error === "expired_token") {
132
+ return { type: "expired" };
133
+ }
134
+ if (error === "access_denied") {
135
+ return { type: "denied" };
136
+ }
137
+ logError("token poll failed:", { status: res.status, json });
138
+ return { type: "failed" };
139
+ }
140
+ const json = await res.json();
141
+ if (LOGGING_ENABLED) {
142
+ // Log the full token response for debugging
143
+ logInfo("Token response received:", {
144
+ has_access_token: !!json.access_token,
145
+ has_refresh_token: !!json.refresh_token,
146
+ expires_in: json.expires_in,
147
+ resource_url: json.resource_url,
148
+ all_fields: Object.keys(json),
149
+ });
150
+ }
151
+ // Validate token response fields
152
+ if (!validateTokenResponse(json, "token response")) {
153
+ return { type: "failed" };
154
+ }
155
+ // Validate and normalize resource_url if present
156
+ json.resource_url = normalizeResourceUrl(json.resource_url);
157
+ if (!json.resource_url) {
158
+ logWarn("No valid resource_url in token response, will use default DashScope endpoint");
159
+ }
160
+ // At this point, validation ensures these fields exist
161
+ return {
162
+ type: "success",
163
+ access: json.access_token,
164
+ refresh: json.refresh_token,
165
+ expires: Date.now() + json.expires_in * 1000,
166
+ resourceUrl: json.resource_url, // Dynamic API base URL
167
+ };
168
+ }
169
+ catch (error) {
170
+ logError("token poll error:", error);
171
+ return { type: "failed" };
172
+ }
173
+ }
174
+ /**
175
+ * Refresh access token using refresh token (1 lan duy nhat, khong retry)
176
+ * @param refreshToken - Refresh token
177
+ * @returns Token result
178
+ */
179
+ async function refreshAccessTokenOnce(refreshToken) {
180
+ try {
181
+ const res = await fetch(QWEN_OAUTH.TOKEN_URL, {
182
+ method: "POST",
183
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
184
+ body: new URLSearchParams({
185
+ grant_type: QWEN_OAUTH.GRANT_TYPE_REFRESH,
186
+ client_id: QWEN_OAUTH.CLIENT_ID,
187
+ refresh_token: refreshToken,
188
+ }),
189
+ });
190
+ if (!res.ok) {
191
+ const text = await res.text().catch(() => "");
192
+ logError("token refresh failed:", { status: res.status, text });
193
+ return { type: "failed", status: res.status };
194
+ }
195
+ const json = await res.json();
196
+ if (LOGGING_ENABLED) {
197
+ logInfo("Token refresh response received:", {
198
+ has_access_token: !!json.access_token,
199
+ has_refresh_token: !!json.refresh_token,
200
+ expires_in: json.expires_in,
201
+ resource_url: json.resource_url,
202
+ all_fields: Object.keys(json),
203
+ });
204
+ }
205
+ // Validate token response fields
206
+ if (!validateTokenResponse(json, "refresh response")) {
207
+ return { type: "failed" };
208
+ }
209
+ // Validate and normalize resource_url if present
210
+ json.resource_url = normalizeResourceUrl(json.resource_url);
211
+ if (!json.resource_url) {
212
+ logWarn("No valid resource_url in refresh response, will use default DashScope endpoint");
213
+ }
214
+ return {
215
+ type: "success",
216
+ access: json.access_token,
217
+ refresh: json.refresh_token,
218
+ expires: Date.now() + json.expires_in * 1000,
219
+ resourceUrl: json.resource_url,
220
+ };
221
+ }
222
+ catch (error) {
223
+ logError("token refresh error:", error);
224
+ return { type: "failed" };
225
+ }
226
+ }
227
+ /**
228
+ * Refresh access token voi retry logic
229
+ * Retry toi da MAX_REFRESH_RETRIES lan voi delay giua cac lan
230
+ * @param refreshToken - Refresh token
231
+ * @returns Token result
232
+ */
233
+ export async function refreshAccessToken(refreshToken) {
234
+ for (let attempt = 0; attempt <= MAX_REFRESH_RETRIES; attempt++) {
235
+ const result = await refreshAccessTokenOnce(refreshToken);
236
+ if (result.type === "success") {
237
+ return result;
238
+ }
239
+ // Neu loi 401/403 thi refresh token da bi revoke, khong can retry
240
+ if (result.status === 401 || result.status === 403) {
241
+ logError("Refresh token bi reject (" + result.status + "), can dang nhap lai");
242
+ return { type: "failed" };
243
+ }
244
+ // Con retry thi cho delay roi thu lai
245
+ if (attempt < MAX_REFRESH_RETRIES) {
246
+ if (LOGGING_ENABLED) {
247
+ logInfo(`Token refresh that bai, thu lai lan ${attempt + 2}/${MAX_REFRESH_RETRIES + 1}...`);
248
+ }
249
+ await new Promise(resolve => setTimeout(resolve, REFRESH_RETRY_DELAY_MS));
250
+ }
251
+ }
252
+ logError("Token refresh that bai sau " + (MAX_REFRESH_RETRIES + 1) + " lan thu");
253
+ return { type: "failed" };
254
+ }
255
+ /**
256
+ * Generate PKCE challenge and verifier
257
+ * @returns PKCE pair
258
+ */
259
+ export async function createPKCE() {
260
+ const { challenge, verifier } = await generatePKCE();
261
+ return { challenge, verifier };
262
+ }
263
+ /**
264
+ * Load stored token from disk
265
+ * @returns Stored token data or null if not found
266
+ */
267
+ export function loadStoredToken() {
268
+ const tokenPath = getTokenPath();
269
+ if (!existsSync(tokenPath)) {
270
+ return null;
271
+ }
272
+ try {
273
+ const content = readFileSync(tokenPath, "utf-8");
274
+ const data = JSON.parse(content);
275
+ // Validate required fields
276
+ if (!data.access_token || !data.refresh_token || typeof data.expires !== "number") {
277
+ logWarn("Invalid token data, re-authentication required");
278
+ return null;
279
+ }
280
+ return data;
281
+ }
282
+ catch (error) {
283
+ logError("Failed to load token:", error);
284
+ return null;
285
+ }
286
+ }
287
+ /**
288
+ * Xoa token luu tren disk khi token khong con hop le
289
+ */
290
+ export function clearStoredToken() {
291
+ const tokenPath = getTokenPath();
292
+ if (existsSync(tokenPath)) {
293
+ try {
294
+ unlinkSync(tokenPath);
295
+ logWarn("Da xoa token cu, can dang nhap lai");
296
+ }
297
+ catch (error) {
298
+ logError("Khong the xoa token file:", error);
299
+ }
300
+ }
301
+ }
302
+ /**
303
+ * Save token to disk
304
+ * @param tokenResult - Token result from OAuth flow
305
+ */
306
+ export function saveToken(tokenResult) {
307
+ if (tokenResult.type !== "success") {
308
+ throw new Error("Cannot save non-success token result");
309
+ }
310
+ const configDir = getConfigDir();
311
+ // Ensure directory exists
312
+ if (!existsSync(configDir)) {
313
+ mkdirSync(configDir, { recursive: true, mode: 0o700 });
314
+ }
315
+ const tokenData = {
316
+ access_token: tokenResult.access,
317
+ refresh_token: tokenResult.refresh,
318
+ expires: tokenResult.expires,
319
+ resource_url: tokenResult.resourceUrl,
320
+ };
321
+ const tokenPath = getTokenPath();
322
+ try {
323
+ writeFileSync(tokenPath, JSON.stringify(tokenData, null, 2), {
324
+ encoding: "utf-8",
325
+ mode: 0o600, // Secure permissions
326
+ });
327
+ }
328
+ catch (error) {
329
+ logError("Failed to save token:", error);
330
+ throw error;
331
+ }
332
+ }
333
+ /**
334
+ * Check if token is expired (with 5 minute buffer)
335
+ * @param expiresAt - Expiration timestamp in milliseconds
336
+ * @returns True if token is expired or will expire soon
337
+ */
338
+ export function isTokenExpired(expiresAt) {
339
+ return Date.now() >= expiresAt - TOKEN_REFRESH_BUFFER_MS;
340
+ }
341
+ /**
342
+ * Get valid access token, refreshing if necessary
343
+ * Khi refresh that bai, xoa token cu de user biet can dang nhap lai
344
+ * @returns Access token and resource URL, or null if authentication required
345
+ */
346
+ export async function getValidToken() {
347
+ const stored = loadStoredToken();
348
+ if (!stored) {
349
+ return null; // Khong co token, can dang nhap
350
+ }
351
+ // Token con hieu luc
352
+ if (!isTokenExpired(stored.expires)) {
353
+ return {
354
+ accessToken: stored.access_token,
355
+ resourceUrl: stored.resource_url,
356
+ };
357
+ }
358
+ // Token het han, thu refresh (co retry ben trong)
359
+ if (LOGGING_ENABLED) {
360
+ logInfo("Token expired, refreshing...");
361
+ }
362
+ const refreshResult = await refreshAccessToken(stored.refresh_token);
363
+ if (refreshResult.type !== "success") {
364
+ logError("Token refresh failed, re-authentication required");
365
+ // Xoa token cu de tranh loop loi
366
+ clearStoredToken();
367
+ return null;
368
+ }
369
+ // Luu token moi
370
+ saveToken(refreshResult);
371
+ return {
372
+ accessToken: refreshResult.access,
373
+ resourceUrl: refreshResult.resourceUrl,
374
+ };
375
+ }
376
+ /**
377
+ * Get Portal API base URL from token or use default
378
+ * @param resourceUrl - Resource URL from token (optional)
379
+ * @returns Portal API base URL
380
+ *
381
+ * IMPORTANT: Portal API uses /v1 path (not /api/v1)
382
+ * - OAuth endpoints: /api/v1/oauth2/ (for authentication)
383
+ * - Chat API: /v1/ (for completions)
384
+ */
385
+ export function getApiBaseUrl(resourceUrl) {
386
+ if (resourceUrl) {
387
+ // Validate URL format
388
+ try {
389
+ const url = new URL(resourceUrl);
390
+ if (!url.protocol.startsWith('http')) {
391
+ logWarn('Invalid resource_url protocol, using default Portal API URL');
392
+ return DEFAULT_QWEN_BASE_URL;
393
+ }
394
+ // Construct the Portal API endpoint from resource_url
395
+ // Qwen returns "portal.qwen.ai" which should become "https://portal.qwen.ai/v1"
396
+ // Remove trailing slash if present
397
+ let baseUrl = resourceUrl.replace(/\/$/, "");
398
+ // Add /v1 suffix if not already present
399
+ const suffix = '/v1';
400
+ if (!baseUrl.endsWith(suffix)) {
401
+ baseUrl = `${baseUrl}${suffix}`;
402
+ }
403
+ if (LOGGING_ENABLED) {
404
+ logInfo('Constructed Portal API base URL from resource_url:', baseUrl);
405
+ }
406
+ return baseUrl;
407
+ }
408
+ catch (error) {
409
+ logWarn('Invalid resource_url format, using default Portal API URL:', error);
410
+ return DEFAULT_QWEN_BASE_URL;
411
+ }
412
+ }
413
+ // Fall back to default Portal API URL
414
+ if (LOGGING_ENABLED) {
415
+ logInfo('No resource_url provided, using default Portal API URL');
416
+ }
417
+ return DEFAULT_QWEN_BASE_URL;
418
+ }
419
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../lib/auth/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Browser utilities for OAuth flow
3
+ * Handles platform-specific browser opening
4
+ */
5
+ /**
6
+ * Gets the platform-specific command to open a URL in the default browser
7
+ * @returns Browser opener command for the current platform
8
+ */
9
+ export declare function getBrowserOpener(): string;
10
+ /**
11
+ * Opens a URL in the default browser
12
+ * Silently fails if browser cannot be opened (user can copy URL manually)
13
+ * @param url - URL to open
14
+ */
15
+ export declare function openBrowserUrl(url: string): void;
16
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../../lib/auth/browser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAKzC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAUhD"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Browser utilities for OAuth flow
3
+ * Handles platform-specific browser opening
4
+ */
5
+ import { spawn } from "node:child_process";
6
+ import { PLATFORM_OPENERS } from "../constants.js";
7
+ /**
8
+ * Gets the platform-specific command to open a URL in the default browser
9
+ * @returns Browser opener command for the current platform
10
+ */
11
+ export function getBrowserOpener() {
12
+ const platform = process.platform;
13
+ if (platform === "darwin")
14
+ return PLATFORM_OPENERS.darwin;
15
+ if (platform === "win32")
16
+ return PLATFORM_OPENERS.win32;
17
+ return PLATFORM_OPENERS.linux;
18
+ }
19
+ /**
20
+ * Opens a URL in the default browser
21
+ * Silently fails if browser cannot be opened (user can copy URL manually)
22
+ * @param url - URL to open
23
+ */
24
+ export function openBrowserUrl(url) {
25
+ try {
26
+ const opener = getBrowserOpener();
27
+ spawn(opener, [url], {
28
+ stdio: "ignore",
29
+ shell: process.platform === "win32",
30
+ });
31
+ }
32
+ catch (error) {
33
+ // Log canh bao de ho tro debug, user van co the mo URL thu cong
34
+ console.warn("[qwen-oauth-plugin] Khong the mo trinh duyet:", error?.message || error);
35
+ }
36
+ }
37
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../../lib/auth/browser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,gBAAgB,CAAC,MAAM,CAAC;IAC1D,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,gBAAgB,CAAC,KAAK,CAAC;IACxD,OAAO,gBAAgB,CAAC,KAAK,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACzC,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;QAClC,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE;YACpB,KAAK,EAAE,QAAQ;YACf,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;SACnC,CAAC,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,mEAAmE;IACpE,CAAC;AACF,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { PluginConfig } from "./types.js";
2
+ /**
3
+ * Get plugin configuration directory
4
+ */
5
+ export declare function getConfigDir(): string;
6
+ /**
7
+ * Get plugin configuration file path
8
+ */
9
+ export declare function getConfigPath(): string;
10
+ /**
11
+ * Load plugin configuration from ~/.opencode/qwen/auth-config.json
12
+ * Returns default config if file doesn't exist
13
+ */
14
+ export declare function loadPluginConfig(): PluginConfig;
15
+ /**
16
+ * Get QWEN_MODE setting
17
+ * Priority: QWEN_MODE env var > config file > default (true)
18
+ */
19
+ export declare function getQwenMode(config: PluginConfig): boolean;
20
+ /**
21
+ * Get token storage path
22
+ */
23
+ export declare function getTokenPath(): string;
24
+ /**
25
+ * Get cache directory for prompts
26
+ */
27
+ export declare function getCacheDir(): string;
28
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../lib/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,YAAY,CAc/C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAMzD;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAEpC"}
@@ -0,0 +1,63 @@
1
+ import { homedir } from "os";
2
+ import { join } from "path";
3
+ import { readFileSync, existsSync } from "fs";
4
+ /**
5
+ * Get plugin configuration directory
6
+ */
7
+ export function getConfigDir() {
8
+ return join(homedir(), ".opencode", "qwen");
9
+ }
10
+ /**
11
+ * Get plugin configuration file path
12
+ */
13
+ export function getConfigPath() {
14
+ return join(getConfigDir(), "auth-config.json");
15
+ }
16
+ /**
17
+ * Load plugin configuration from ~/.opencode/qwen/auth-config.json
18
+ * Returns default config if file doesn't exist
19
+ */
20
+ export function loadPluginConfig() {
21
+ const configPath = getConfigPath();
22
+ if (!existsSync(configPath)) {
23
+ return { qwenMode: true }; // Default to QWEN_MODE enabled
24
+ }
25
+ try {
26
+ const content = readFileSync(configPath, "utf-8");
27
+ return JSON.parse(content);
28
+ }
29
+ catch (error) {
30
+ console.warn(`[qwen-oauth-plugin] Failed to load config from ${configPath}:`, error);
31
+ return { qwenMode: true };
32
+ }
33
+ }
34
+ /**
35
+ * Get QWEN_MODE setting
36
+ * Priority: QWEN_MODE env var > config file > default (true)
37
+ */
38
+ export function getQwenMode(config) {
39
+ const envValue = process.env.QWEN_MODE;
40
+ if (envValue !== undefined) {
41
+ return envValue === "1" || envValue.toLowerCase() === "true";
42
+ }
43
+ // Ep kieu boolean chac chan, tranh string "false" bi truthy
44
+ const val = config.qwenMode;
45
+ if (val === undefined || val === null) return true; // mac dinh bat
46
+ if (typeof val === "string") {
47
+ return val === "1" || val.toLowerCase() === "true";
48
+ }
49
+ return !!val;
50
+ }
51
+ /**
52
+ * Get token storage path
53
+ */
54
+ export function getTokenPath() {
55
+ return join(getConfigDir(), "oauth_token.json");
56
+ }
57
+ /**
58
+ * Get cache directory for prompts
59
+ */
60
+ export function getCacheDir() {
61
+ return join(homedir(), ".opencode", "cache");
62
+ }
63
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAG9C;;GAEG;AACH,MAAM,UAAU,YAAY;IAC3B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa;IAC5B,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,kBAAkB,CAAC,CAAC;AACjD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC/B,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IAEnC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,+BAA+B;IAC3D,CAAC;IAED,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAiB,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,kDAAkD,UAAU,GAAG,EAAE,KAAK,CAAC,CAAC;QACrF,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;AACF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,MAAoB;IAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;IACvC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,QAAQ,KAAK,GAAG,IAAI,QAAQ,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC;IAC9D,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC3B,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,kBAAkB,CAAC,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW;IAC1B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;AAC9C,CAAC"}