opencode-qwen-auth 0.1.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.
Files changed (67) hide show
  1. package/LICENSE +203 -0
  2. package/README.md +252 -0
  3. package/dist/index.d.ts +5 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +3 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/src/constants.d.ts +7 -0
  8. package/dist/src/constants.d.ts.map +1 -0
  9. package/dist/src/constants.js +12 -0
  10. package/dist/src/constants.js.map +1 -0
  11. package/dist/src/plugin/account.d.ts +40 -0
  12. package/dist/src/plugin/account.d.ts.map +1 -0
  13. package/dist/src/plugin/account.js +237 -0
  14. package/dist/src/plugin/account.js.map +1 -0
  15. package/dist/src/plugin/auth.d.ts +5 -0
  16. package/dist/src/plugin/auth.d.ts.map +1 -0
  17. package/dist/src/plugin/auth.js +16 -0
  18. package/dist/src/plugin/auth.js.map +1 -0
  19. package/dist/src/plugin/config/index.d.ts +4 -0
  20. package/dist/src/plugin/config/index.d.ts.map +1 -0
  21. package/dist/src/plugin/config/index.js +3 -0
  22. package/dist/src/plugin/config/index.js.map +1 -0
  23. package/dist/src/plugin/config/loader.d.ts +3 -0
  24. package/dist/src/plugin/config/loader.d.ts.map +1 -0
  25. package/dist/src/plugin/config/loader.js +69 -0
  26. package/dist/src/plugin/config/loader.js.map +1 -0
  27. package/dist/src/plugin/config/schema.d.ts +31 -0
  28. package/dist/src/plugin/config/schema.d.ts.map +1 -0
  29. package/dist/src/plugin/config/schema.js +15 -0
  30. package/dist/src/plugin/config/schema.js.map +1 -0
  31. package/dist/src/plugin/logger.d.ts +12 -0
  32. package/dist/src/plugin/logger.d.ts.map +1 -0
  33. package/dist/src/plugin/logger.js +74 -0
  34. package/dist/src/plugin/logger.js.map +1 -0
  35. package/dist/src/plugin/token.d.ts +8 -0
  36. package/dist/src/plugin/token.d.ts.map +1 -0
  37. package/dist/src/plugin/token.js +29 -0
  38. package/dist/src/plugin/token.js.map +1 -0
  39. package/dist/src/plugin/types.d.ts +96 -0
  40. package/dist/src/plugin/types.d.ts.map +1 -0
  41. package/dist/src/plugin/types.js +2 -0
  42. package/dist/src/plugin/types.js.map +1 -0
  43. package/dist/src/plugin.d.ts +11 -0
  44. package/dist/src/plugin.d.ts.map +1 -0
  45. package/dist/src/plugin.js +439 -0
  46. package/dist/src/plugin.js.map +1 -0
  47. package/dist/src/qwen/oauth.d.ts +29 -0
  48. package/dist/src/qwen/oauth.d.ts.map +1 -0
  49. package/dist/src/qwen/oauth.js +151 -0
  50. package/dist/src/qwen/oauth.js.map +1 -0
  51. package/dist/src/transform/index.d.ts +4 -0
  52. package/dist/src/transform/index.d.ts.map +1 -0
  53. package/dist/src/transform/index.js +4 -0
  54. package/dist/src/transform/index.js.map +1 -0
  55. package/dist/src/transform/request.d.ts +4 -0
  56. package/dist/src/transform/request.d.ts.map +1 -0
  57. package/dist/src/transform/request.js +106 -0
  58. package/dist/src/transform/request.js.map +1 -0
  59. package/dist/src/transform/response.d.ts +10 -0
  60. package/dist/src/transform/response.d.ts.map +1 -0
  61. package/dist/src/transform/response.js +52 -0
  62. package/dist/src/transform/response.js.map +1 -0
  63. package/dist/src/transform/sse.d.ts +10 -0
  64. package/dist/src/transform/sse.d.ts.map +1 -0
  65. package/dist/src/transform/sse.js +230 -0
  66. package/dist/src/transform/sse.js.map +1 -0
  67. package/package.json +78 -0
@@ -0,0 +1,96 @@
1
+ import type { PluginInput } from "@opencode-ai/plugin";
2
+ export interface OAuthAuthDetails {
3
+ type: "oauth";
4
+ refresh: string;
5
+ access?: string;
6
+ expires?: number;
7
+ resourceUrl?: string;
8
+ }
9
+ export interface NonOAuthAuthDetails {
10
+ type: string;
11
+ [key: string]: unknown;
12
+ }
13
+ export type AuthDetails = OAuthAuthDetails | NonOAuthAuthDetails;
14
+ export type GetAuth = () => Promise<AuthDetails>;
15
+ export interface ProviderModelCost {
16
+ input: number;
17
+ output: number;
18
+ cache: {
19
+ read: number;
20
+ write: number;
21
+ };
22
+ experimentalOver200K?: {
23
+ input: number;
24
+ output: number;
25
+ cache: {
26
+ read: number;
27
+ write: number;
28
+ };
29
+ };
30
+ }
31
+ export interface ProviderModel {
32
+ cost?: ProviderModelCost;
33
+ [key: string]: unknown;
34
+ }
35
+ export interface Provider {
36
+ models?: Record<string, ProviderModel>;
37
+ }
38
+ export interface LoaderResult {
39
+ apiKey: string;
40
+ fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
41
+ }
42
+ export type PluginClient = PluginInput["client"];
43
+ export interface PluginContext {
44
+ client: PluginClient;
45
+ directory: string;
46
+ }
47
+ export type AuthPrompt = {
48
+ type: "text";
49
+ key: string;
50
+ message: string;
51
+ placeholder?: string;
52
+ validate?: (value: string) => string | undefined;
53
+ condition?: (inputs: Record<string, string>) => boolean;
54
+ } | {
55
+ type: "select";
56
+ key: string;
57
+ message: string;
58
+ options: Array<{
59
+ label: string;
60
+ value: string;
61
+ hint?: string;
62
+ }>;
63
+ condition?: (inputs: Record<string, string>) => boolean;
64
+ };
65
+ export type OAuthAuthorizationResult = {
66
+ url: string;
67
+ instructions: string;
68
+ } & ({
69
+ method: "auto";
70
+ callback: () => Promise<Record<string, unknown>>;
71
+ } | {
72
+ method: "code";
73
+ callback: (code: string) => Promise<Record<string, unknown>>;
74
+ });
75
+ export interface AuthMethod {
76
+ provider?: string;
77
+ label: string;
78
+ type: "oauth" | "api";
79
+ prompts?: AuthPrompt[];
80
+ authorize?: (inputs?: Record<string, string>) => Promise<OAuthAuthorizationResult>;
81
+ }
82
+ export interface PluginEventPayload {
83
+ event: {
84
+ type: string;
85
+ properties?: unknown;
86
+ };
87
+ }
88
+ export interface PluginResult {
89
+ auth: {
90
+ provider: string;
91
+ loader: (getAuth: GetAuth, provider: Provider) => Promise<LoaderResult | Record<string, unknown>>;
92
+ methods: AuthMethod[];
93
+ };
94
+ event?: (payload: PluginEventPayload) => void;
95
+ }
96
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/plugin/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/plugin/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import type { Plugin } from "@opencode-ai/plugin";
2
+ declare function sanitizeMalformedUrl(url: string): string;
3
+ declare function applyResourceUrl(input: RequestInfo | URL, baseUrl?: string): {
4
+ url: string;
5
+ };
6
+ export declare const createQwenOAuthPlugin: (providerId: string) => Plugin;
7
+ export declare const QwenCLIOAuthPlugin: Plugin;
8
+ export declare const QwenOAuthPlugin: Plugin;
9
+ export { sanitizeMalformedUrl, applyResourceUrl };
10
+ export default QwenOAuthPlugin;
11
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAqFlD,iBAAS,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAcjD;AAED,iBAAS,gBAAgB,CACvB,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,OAAO,CAAC,EAAE,MAAM,GACf;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAgDjB;AA8ED,eAAO,MAAM,qBAAqB,GAC/B,YAAY,MAAM,KAAG,MAyWrB,CAAC;AAEJ,eAAO,MAAM,kBAAkB,QAAgC,CAAC;AAChE,eAAO,MAAM,eAAe,QAAqB,CAAC;AAElD,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,CAAC;AAElD,eAAe,eAAe,CAAC"}
@@ -0,0 +1,439 @@
1
+ import { QWEN_DEFAULT_SCOPES, QWEN_OAUTH_BASE_URL } from "./constants";
2
+ import { getMinRateLimitWait, loadAccounts, markRateLimited, recordFailure, recordSuccess, saveAccounts, selectAccount, updateAccount, upsertAccount, } from "./plugin/account";
3
+ import { accessTokenExpired, isOAuthAuth } from "./plugin/auth";
4
+ import { loadConfig } from "./plugin/config";
5
+ import { createLogger, initDebugFromEnv, setLoggerQuietMode, } from "./plugin/logger";
6
+ import { refreshAccessToken } from "./plugin/token";
7
+ import { authorizeQwenDevice, pollQwenDeviceToken, } from "./qwen/oauth";
8
+ import { transformResponsesToChatCompletions } from "./transform/request";
9
+ import { createTransformContext, transformChatCompletionsToResponses, } from "./transform/response";
10
+ import { createSSETransformContext, createSSETransformStream, } from "./transform/sse";
11
+ const logger = createLogger("plugin");
12
+ function normalizeUrl(value, fallback) {
13
+ if (typeof value !== "string") {
14
+ return fallback;
15
+ }
16
+ const trimmed = value.trim();
17
+ if (!trimmed)
18
+ return fallback;
19
+ if (trimmed.startsWith("http://") || trimmed.startsWith("https://")) {
20
+ return trimmed;
21
+ }
22
+ return `https://${trimmed}`;
23
+ }
24
+ function buildOAuthOptions(config) {
25
+ return {
26
+ clientId: config.client_id,
27
+ oauthBaseUrl: normalizeUrl(config.oauth_base_url, QWEN_OAUTH_BASE_URL),
28
+ scopes: QWEN_DEFAULT_SCOPES,
29
+ };
30
+ }
31
+ function ensureStorage(auth) {
32
+ return {
33
+ version: 1,
34
+ accounts: [
35
+ {
36
+ refreshToken: auth.refresh,
37
+ accessToken: auth.access,
38
+ expires: auth.expires,
39
+ resourceUrl: auth.resourceUrl,
40
+ addedAt: Date.now(),
41
+ lastUsed: Date.now(),
42
+ },
43
+ ],
44
+ activeIndex: 0,
45
+ };
46
+ }
47
+ function sanitizeMalformedUrl(url) {
48
+ let result = url.trim();
49
+ // Strip leading sentinel prefix (undefined/null) only at start
50
+ // OpenCode may pass "undefined/chat/completions" when provider has no baseUrl
51
+ result = result.replace(/^(undefined|null)(?=\/|$)/, "");
52
+ // Prevent protocol-relative URL after stripping (e.g., "undefined//path" -> "//path" is dangerous)
53
+ // Collapse multiple leading slashes to single slash
54
+ if (result.startsWith("//")) {
55
+ result = `/${result.replace(/^\/+/, "")}`;
56
+ }
57
+ return result;
58
+ }
59
+ function applyResourceUrl(input, baseUrl) {
60
+ let rawUrl;
61
+ if (typeof input === "string") {
62
+ rawUrl = input;
63
+ }
64
+ else if (input instanceof URL) {
65
+ rawUrl = input.toString();
66
+ }
67
+ else {
68
+ rawUrl = input.url;
69
+ }
70
+ // Sanitize malformed URLs from OpenCode (e.g., "undefined/chat/completions")
71
+ rawUrl = sanitizeMalformedUrl(rawUrl);
72
+ // If sanitization resulted in empty string, treat as root path
73
+ if (!rawUrl) {
74
+ rawUrl = "/";
75
+ }
76
+ let originalUrl;
77
+ try {
78
+ originalUrl = new URL(rawUrl);
79
+ }
80
+ catch {
81
+ if (!baseUrl) {
82
+ throw new Error(`Qwen OAuth requires a base URL for ${rawUrl}`);
83
+ }
84
+ originalUrl = new URL(rawUrl, baseUrl);
85
+ }
86
+ if (!baseUrl) {
87
+ return { url: originalUrl.toString() };
88
+ }
89
+ const base = new URL(baseUrl);
90
+ const basePath = base.pathname.replace(/\/$/, "");
91
+ const originalPath = originalUrl.pathname;
92
+ let combinedPath = originalPath;
93
+ if (originalPath.startsWith(basePath)) {
94
+ combinedPath = `${basePath}${originalPath.slice(basePath.length)}`;
95
+ }
96
+ else {
97
+ combinedPath = `${basePath}${originalPath.startsWith("/") ? "" : "/"}${originalPath}`;
98
+ }
99
+ base.pathname = combinedPath;
100
+ base.search = originalUrl.search;
101
+ base.hash = originalUrl.hash;
102
+ return { url: base.toString() };
103
+ }
104
+ function extractRetryAfterMs(response) {
105
+ const retryAfterMs = response.headers.get("retry-after-ms");
106
+ if (retryAfterMs) {
107
+ const value = Number.parseInt(retryAfterMs, 10);
108
+ if (!Number.isNaN(value) && value > 0) {
109
+ return value;
110
+ }
111
+ }
112
+ const retryAfter = response.headers.get("retry-after");
113
+ if (retryAfter) {
114
+ const value = Number.parseInt(retryAfter, 10);
115
+ if (!Number.isNaN(value) && value > 0) {
116
+ return value * 1000;
117
+ }
118
+ }
119
+ return null;
120
+ }
121
+ const BACKOFF_TIERS = {
122
+ QUOTA_EXHAUSTED: [60_000, 300_000, 1800_000],
123
+ RATE_LIMIT_EXCEEDED: [30_000, 60_000],
124
+ SERVER_ERROR: [20_000, 40_000],
125
+ UNKNOWN: [60_000],
126
+ };
127
+ function parseRateLimitReason(response) {
128
+ const errorHeader = response.headers.get("x-error-code");
129
+ if (errorHeader) {
130
+ const upper = errorHeader.toUpperCase();
131
+ if (upper.includes("QUOTA"))
132
+ return "QUOTA_EXHAUSTED";
133
+ if (upper.includes("RATE"))
134
+ return "RATE_LIMIT_EXCEEDED";
135
+ if (upper.includes("SERVER") || upper.includes("CAPACITY"))
136
+ return "SERVER_ERROR";
137
+ }
138
+ if (response.status >= 500)
139
+ return "SERVER_ERROR";
140
+ return "UNKNOWN";
141
+ }
142
+ function getBackoffMs(reason, consecutiveFailures) {
143
+ const tier = BACKOFF_TIERS[reason];
144
+ return tier[Math.min(consecutiveFailures, tier.length - 1)];
145
+ }
146
+ function sleep(ms) {
147
+ return new Promise((resolve) => setTimeout(resolve, ms));
148
+ }
149
+ async function ensureAuthInStorage(storage, auth) {
150
+ const now = Date.now();
151
+ const baseStorage = storage ?? ensureStorage(auth);
152
+ const updated = upsertAccount(baseStorage, {
153
+ refreshToken: auth.refresh,
154
+ accessToken: auth.access,
155
+ expires: auth.expires,
156
+ resourceUrl: auth.resourceUrl,
157
+ addedAt: now,
158
+ lastUsed: now,
159
+ });
160
+ await saveAccounts(updated);
161
+ return updated;
162
+ }
163
+ export const createQwenOAuthPlugin = (providerId) => async ({ client, directory }) => {
164
+ const config = loadConfig(directory);
165
+ setLoggerQuietMode(config.quiet_mode);
166
+ initDebugFromEnv();
167
+ logger.debug("Plugin initialized", { providerId, directory });
168
+ const oauthOptions = buildOAuthOptions(config);
169
+ return {
170
+ auth: {
171
+ provider: providerId,
172
+ async loader(getAuth, provider) {
173
+ const auth = (await getAuth());
174
+ if (!isOAuthAuth(auth)) {
175
+ return {};
176
+ }
177
+ let accountStorage = await ensureAuthInStorage(await loadAccounts(), auth);
178
+ if (provider.models) {
179
+ for (const model of Object.values(provider.models)) {
180
+ if (model) {
181
+ model.cost = {
182
+ input: 0,
183
+ output: 0,
184
+ cache: { read: 0, write: 0 },
185
+ };
186
+ }
187
+ }
188
+ }
189
+ return {
190
+ apiKey: "",
191
+ fetch: async (input, init) => {
192
+ let attempts = 0;
193
+ while (true) {
194
+ const now = Date.now();
195
+ const selection = selectAccount(accountStorage, config.rotation_strategy, now);
196
+ if (!selection) {
197
+ const waitMs = getMinRateLimitWait(accountStorage, now);
198
+ if (!waitMs) {
199
+ throw new Error("No available Qwen OAuth accounts. Re-authenticate to continue.");
200
+ }
201
+ const maxWaitMs = (config.max_rate_limit_wait_seconds ?? 0) * 1000;
202
+ if (maxWaitMs > 0 && waitMs > maxWaitMs) {
203
+ throw new Error("All Qwen OAuth accounts are rate-limited. Try again later.");
204
+ }
205
+ await sleep(waitMs);
206
+ continue;
207
+ }
208
+ accountStorage = selection.storage;
209
+ const account = selection.account;
210
+ const accountIndex = selection.index;
211
+ const authRecord = {
212
+ type: "oauth",
213
+ refresh: account.refreshToken,
214
+ access: account.accessToken,
215
+ expires: account.expires,
216
+ resourceUrl: account.resourceUrl,
217
+ };
218
+ const refreshBuffer = config.proactive_refresh
219
+ ? config.refresh_window_seconds
220
+ : 0;
221
+ if (!authRecord.access ||
222
+ accessTokenExpired(authRecord, refreshBuffer)) {
223
+ logger.debug("Token refresh needed", {
224
+ accountIndex,
225
+ hasAccess: !!authRecord.access,
226
+ proactive: config.proactive_refresh,
227
+ });
228
+ try {
229
+ const refreshed = await refreshAccessToken(authRecord, oauthOptions, client, providerId);
230
+ if (!refreshed) {
231
+ throw new Error("Token refresh failed");
232
+ }
233
+ logger.debug("Token refreshed successfully", {
234
+ accountIndex,
235
+ });
236
+ accountStorage = updateAccount(accountStorage, accountIndex, {
237
+ refreshToken: refreshed.refresh,
238
+ accessToken: refreshed.access,
239
+ expires: refreshed.expires,
240
+ resourceUrl: refreshed.resourceUrl ?? account.resourceUrl,
241
+ lastUsed: now,
242
+ });
243
+ await saveAccounts(accountStorage);
244
+ }
245
+ catch (error) {
246
+ const refreshError = error;
247
+ logger.debug("Token refresh failed", {
248
+ accountIndex,
249
+ code: refreshError.code,
250
+ });
251
+ if (refreshError.code === "invalid_grant") {
252
+ accountStorage = updateAccount(accountStorage, accountIndex, { rateLimitResetAt: Date.now() + 60_000 });
253
+ await saveAccounts(accountStorage);
254
+ }
255
+ attempts += 1;
256
+ if (attempts >= accountStorage.accounts.length) {
257
+ throw error;
258
+ }
259
+ continue;
260
+ }
261
+ }
262
+ const latestAuth = (await getAuth());
263
+ if (!isOAuthAuth(latestAuth)) {
264
+ return fetch(input, init);
265
+ }
266
+ const activeAuth = latestAuth.access ? latestAuth : authRecord;
267
+ // Get URL from input - OpenCode already constructs full URLs
268
+ let rawUrl;
269
+ if (typeof input === "string") {
270
+ rawUrl = input;
271
+ }
272
+ else if (input instanceof URL) {
273
+ rawUrl = input.toString();
274
+ }
275
+ else {
276
+ rawUrl = input.url;
277
+ }
278
+ // Sanitize malformed URLs (e.g., "undefined/path")
279
+ rawUrl = sanitizeMalformedUrl(rawUrl);
280
+ let requestInit = init ??
281
+ (input instanceof Request
282
+ ? {
283
+ method: input.method,
284
+ headers: input.headers,
285
+ body: input.body,
286
+ signal: input.signal,
287
+ }
288
+ : undefined);
289
+ if (!requestInit && !(input instanceof Request)) {
290
+ requestInit = {};
291
+ }
292
+ if (requestInit && !requestInit.headers) {
293
+ requestInit.headers = {};
294
+ }
295
+ const headers = new Headers(requestInit?.headers);
296
+ if (activeAuth.access) {
297
+ headers.set("Authorization", `Bearer ${activeAuth.access}`);
298
+ }
299
+ const needsResponsesTransform = rawUrl.endsWith("/responses");
300
+ const finalUrl = rawUrl.replace(/\/responses$/, "/chat/completions");
301
+ const finalInit = { ...requestInit };
302
+ if (needsResponsesTransform && requestInit?.body) {
303
+ try {
304
+ const bodyStr = typeof requestInit.body === "string"
305
+ ? requestInit.body
306
+ : await new Response(requestInit.body).text();
307
+ const body = JSON.parse(bodyStr);
308
+ const transformed = transformResponsesToChatCompletions(body);
309
+ finalInit.body = JSON.stringify(transformed);
310
+ logger.verbose("Transformed request body", {
311
+ messagesCount: transformed.messages?.length,
312
+ hasTools: !!transformed.tools,
313
+ });
314
+ }
315
+ catch {
316
+ logger.debug("Body parse failed, using original");
317
+ }
318
+ }
319
+ logger.debug("Sending request", {
320
+ url: finalUrl,
321
+ method: finalInit.method ?? "POST",
322
+ needsTransform: needsResponsesTransform,
323
+ });
324
+ const response = await fetch(finalUrl, {
325
+ ...finalInit,
326
+ headers,
327
+ });
328
+ logger.debug("Response received", {
329
+ status: response.status,
330
+ contentType: response.headers.get("content-type"),
331
+ });
332
+ // Transform streaming response from Chat Completions to Responses API format
333
+ if (needsResponsesTransform &&
334
+ response.ok &&
335
+ response.body &&
336
+ response.headers
337
+ .get("content-type")
338
+ ?.includes("text/event-stream")) {
339
+ const sseCtx = createSSETransformContext(logger);
340
+ const transformStream = createSSETransformStream(sseCtx);
341
+ const transformedBody = response.body.pipeThrough(transformStream);
342
+ return new Response(transformedBody, {
343
+ status: response.status,
344
+ statusText: response.statusText,
345
+ headers: response.headers,
346
+ });
347
+ }
348
+ if (needsResponsesTransform &&
349
+ response.ok &&
350
+ !response.headers
351
+ .get("content-type")
352
+ ?.includes("text/event-stream")) {
353
+ logger.debug("Transforming non-streaming response");
354
+ const chatBody = await response.json();
355
+ const ctx = createTransformContext();
356
+ const responsesBody = transformChatCompletionsToResponses(chatBody, ctx);
357
+ return new Response(JSON.stringify(responsesBody), {
358
+ status: response.status,
359
+ statusText: response.statusText,
360
+ headers: new Headers({
361
+ "content-type": "application/json",
362
+ }),
363
+ });
364
+ }
365
+ if (response.status === 429 || response.status >= 500) {
366
+ const reason = parseRateLimitReason(response);
367
+ const headerMs = extractRetryAfterMs(response);
368
+ const tieredMs = getBackoffMs(reason, attempts);
369
+ const retryAfterMs = headerMs ?? tieredMs;
370
+ logger.debug("Rate limited or server error", {
371
+ status: response.status,
372
+ reason,
373
+ accountIndex,
374
+ retryAfterMs,
375
+ attempts,
376
+ totalAccounts: accountStorage.accounts.length,
377
+ });
378
+ accountStorage = markRateLimited(accountStorage, accountIndex, retryAfterMs);
379
+ accountStorage = recordFailure(accountStorage, accountIndex);
380
+ await saveAccounts(accountStorage);
381
+ attempts += 1;
382
+ if (attempts >= accountStorage.accounts.length) {
383
+ const waitMs = getMinRateLimitWait(accountStorage, Date.now());
384
+ if (waitMs) {
385
+ logger.debug("All accounts rate limited, waiting", {
386
+ waitMs,
387
+ });
388
+ await sleep(waitMs);
389
+ attempts = 0;
390
+ continue;
391
+ }
392
+ return response;
393
+ }
394
+ continue;
395
+ }
396
+ accountStorage = recordSuccess(accountStorage, accountIndex);
397
+ await saveAccounts(accountStorage);
398
+ return response;
399
+ }
400
+ },
401
+ };
402
+ },
403
+ methods: [
404
+ {
405
+ label: "Qwen OAuth",
406
+ type: "oauth",
407
+ authorize: async () => {
408
+ const device = await authorizeQwenDevice(oauthOptions);
409
+ const url = device.verificationUriComplete ?? device.verificationUri;
410
+ const instructions = `Open ${device.verificationUri} and enter code ${device.userCode}`;
411
+ return {
412
+ url,
413
+ method: "auto",
414
+ instructions,
415
+ callback: async () => {
416
+ const result = await pollQwenDeviceToken(oauthOptions, device.deviceCode, device.intervalSeconds, device.expiresAt, device.codeVerifier);
417
+ if (result.type === "success") {
418
+ return {
419
+ type: "success",
420
+ refresh: result.refresh,
421
+ access: result.access,
422
+ expires: result.expires,
423
+ resourceUrl: result.resourceUrl,
424
+ };
425
+ }
426
+ return { type: "failed", error: result.error };
427
+ },
428
+ };
429
+ },
430
+ },
431
+ ],
432
+ },
433
+ };
434
+ };
435
+ export const QwenCLIOAuthPlugin = createQwenOAuthPlugin("qwen");
436
+ export const QwenOAuthPlugin = QwenCLIOAuthPlugin;
437
+ export { sanitizeMalformedUrl, applyResourceUrl };
438
+ export default QwenOAuthPlugin;
439
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ export interface QwenOAuthOptions {
2
+ clientId: string;
3
+ oauthBaseUrl: string;
4
+ scopes?: string[];
5
+ }
6
+ export interface QwenDeviceAuthorization {
7
+ deviceCode: string;
8
+ userCode: string;
9
+ verificationUri: string;
10
+ verificationUriComplete?: string;
11
+ expiresAt: number;
12
+ intervalSeconds: number;
13
+ codeVerifier: string;
14
+ }
15
+ export type QwenTokenResult = {
16
+ type: "success";
17
+ access: string;
18
+ refresh: string;
19
+ expires: number;
20
+ resourceUrl?: string;
21
+ } | {
22
+ type: "failed";
23
+ error: string;
24
+ code?: string;
25
+ };
26
+ export declare function authorizeQwenDevice(options: QwenOAuthOptions): Promise<QwenDeviceAuthorization>;
27
+ export declare function pollQwenDeviceToken(options: QwenOAuthOptions, deviceCode: string, intervalSeconds: number, expiresAt: number, codeVerifier: string): Promise<QwenTokenResult>;
28
+ export declare function refreshQwenToken(options: QwenOAuthOptions, refreshToken: string): Promise<QwenTokenResult>;
29
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../src/qwen/oauth.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB;AAwBD,MAAM,MAAM,eAAe,GACvB;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GACD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAsCN,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,uBAAuB,CAAC,CAqClC;AAMD,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,gBAAgB,EACzB,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,eAAe,CAAC,CA8D1B;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,gBAAgB,EACzB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,eAAe,CAAC,CAmC1B"}