@oevortex/opencode-qwen-auth 0.1.0 → 0.1.2

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/package.json CHANGED
@@ -1,10 +1,15 @@
1
1
  {
2
2
  "name": "@oevortex/opencode-qwen-auth",
3
- "module": "index.ts",
4
- "version": "0.1.0",
3
+ "main": "./dist/index.cjs",
4
+ "module": "./dist/index.js",
5
+ "types": "./dist/index.d.ts",
6
+ "version": "0.1.2",
5
7
  "scripts": {
8
+ "build": "tsup index.ts --format cjs,esm --dts --clean",
9
+ "dev": "tsup index.ts --format cjs,esm --watch --dts",
6
10
  "test": "bun test",
7
- "test:unit": "bun test src/**/*.test.ts"
11
+ "test:unit": "bun test src/**/*.test.ts",
12
+ "prepare": "npm run build"
8
13
  },
9
14
  "description": "Opencode plugin providing Qwen Code OAuth authentication for Qwen/Alibaba Cloud models",
10
15
  "author": "",
@@ -20,15 +25,18 @@
20
25
  ],
21
26
  "repository": "",
22
27
  "files": [
23
- "index.ts",
24
- "src"
28
+ "dist",
29
+ "README.md",
30
+ "LICENSE"
25
31
  ],
26
32
  "license": "MIT",
27
33
  "type": "module",
28
34
  "devDependencies": {
29
35
  "@opencode-ai/sdk": "^1.0.182",
30
36
  "@types/bun": "latest",
31
- "@types/node": "^22.0.0"
37
+ "@types/node": "^22.0.0",
38
+ "tsup": "^8.0.0",
39
+ "typescript": "^5.0.0"
32
40
  },
33
41
  "peerDependencies": {
34
42
  "typescript": "^5.9.3"
package/index.ts DELETED
@@ -1,82 +0,0 @@
1
- /**
2
- * OpenCode Qwen Auth Plugin
3
- *
4
- * Provides OAuth authentication for Qwen/Alibaba Cloud DashScope API
5
- * allowing OpenCode to use Qwen models with your existing credentials.
6
- *
7
- * @module opencode-qwen-auth
8
- */
9
-
10
- // Main plugin export
11
- export { QwenOAuthPlugin, QwenOAuthPlugin as default } from "./src/plugin";
12
-
13
- // OAuth utilities
14
- export {
15
- QwenOAuthManager,
16
- getQwenCachedCredentialPath,
17
- hasQwenCredentials,
18
- } from "./src/qwen/oauth";
19
-
20
- // Thinking block parser
21
- export {
22
- ThinkingBlockParser,
23
- parseThinkingBlocks,
24
- stripThinkingBlocks,
25
- extractThinkingContent,
26
- hasThinkingBlocks,
27
- } from "./src/qwen/thinking-parser";
28
-
29
- // Auth utilities
30
- export {
31
- isOAuthAuth,
32
- accessTokenExpired,
33
- parseRefreshParts,
34
- formatRefreshParts,
35
- createAuthDetails,
36
- } from "./src/plugin/auth";
37
-
38
- // Token utilities
39
- export {
40
- refreshAccessToken,
41
- ensureValidToken,
42
- needsTokenRefresh,
43
- } from "./src/plugin/token";
44
-
45
- // Models configuration
46
- export {
47
- QWEN_CODE_MODELS,
48
- MODEL_ALIASES,
49
- DEFAULT_MODEL,
50
- getModelInfo,
51
- resolveModelId,
52
- getAllModelIds,
53
- isValidModel,
54
- generateProviderConfig,
55
- } from "./src/models";
56
-
57
- // Types
58
- export type {
59
- QwenOAuthCredentials,
60
- QwenTokenResponse,
61
- QwenModelInfo,
62
- ChatMessage,
63
- ChatCompletionRequest,
64
- ChatCompletionResponse,
65
- Tool,
66
- ToolCall,
67
- ToolChoice,
68
- AuthDetails,
69
- OAuthAuthDetails,
70
- PluginContext,
71
- PluginResult,
72
- TokenExchangeResult,
73
- } from "./src/types";
74
-
75
- // Constants
76
- export {
77
- QWEN_PROVIDER_ID,
78
- QWEN_OAUTH_BASE_URL,
79
- QWEN_DEFAULT_BASE_URL,
80
- QWEN_INTL_BASE_URL,
81
- QWEN_PORTAL_BASE_URL,
82
- } from "./src/constants";
package/src/constants.ts DELETED
@@ -1,43 +0,0 @@
1
- // Qwen OAuth Configuration
2
- export const QWEN_OAUTH_BASE_URL = "https://chat.qwen.ai";
3
- export const QWEN_OAUTH_TOKEN_ENDPOINT = `${QWEN_OAUTH_BASE_URL}/api/v1/oauth2/token`;
4
- export const QWEN_OAUTH_CLIENT_ID = "f0304373b74a44d2b584a3fb70ca9e56";
5
-
6
- // Credential storage
7
- export const QWEN_DIR = ".qwen";
8
- export const QWEN_CREDENTIAL_FILENAME = "oauth_creds.json";
9
-
10
- // Default API Base URLs
11
- export const QWEN_DEFAULT_BASE_URL =
12
- "https://dashscope.aliyuncs.com/compatible-mode/v1";
13
- export const QWEN_INTL_BASE_URL =
14
- "https://dashscope-intl.aliyuncs.com/compatible-mode/v1";
15
- export const QWEN_PORTAL_BASE_URL = "https://portal.qwen.ai/v1";
16
-
17
- // Token refresh buffer (30 seconds in milliseconds)
18
- export const TOKEN_REFRESH_BUFFER_MS = 30 * 1000;
19
-
20
- // HTTP Status codes
21
- export const HTTP_OK = 200;
22
- export const HTTP_UNAUTHORIZED = 401;
23
-
24
- // Provider ID for OpenCode
25
- export const QWEN_PROVIDER_ID = "qwencode";
26
-
27
- // OAuth callback configuration
28
- export const QWEN_CALLBACK_PORT = 36743;
29
- export const QWEN_REDIRECT_URI = `http://localhost:${QWEN_CALLBACK_PORT}/oauth-callback`;
30
-
31
- // User Agent
32
- export const QWEN_USER_AGENT = "qwen-code/1.0.0";
33
-
34
- // Rate limit configuration
35
- export const RATE_LIMIT_BACKOFF_BASE_MS = 1000;
36
- export const RATE_LIMIT_BACKOFF_MAX_MS = 60 * 60 * 1000;
37
- export const RATE_LIMIT_MAX_RETRIES = 5;
38
-
39
- // Request timeout (in milliseconds)
40
- export const REQUEST_TIMEOUT_MS = 720 * 1000;
41
-
42
- // Console log environment variable
43
- export const ENV_CONSOLE_LOG = "OPENCODE_QWEN_CONSOLE_LOG";
package/src/global.d.ts DELETED
@@ -1,257 +0,0 @@
1
- /**
2
- * Global type declarations for Node.js modules
3
- * These help TypeScript resolve Node.js built-in modules
4
- */
5
-
6
- /// <reference types="node" />
7
-
8
- declare module "readline" {
9
- import { EventEmitter } from "events";
10
-
11
- interface ReadLineOptions {
12
- input: NodeJS.ReadableStream;
13
- output?: NodeJS.WritableStream;
14
- terminal?: boolean;
15
- historySize?: number;
16
- prompt?: string;
17
- crlfDelay?: number;
18
- removeHistoryDuplicates?: boolean;
19
- escapeCodeTimeout?: number;
20
- }
21
-
22
- interface Interface extends EventEmitter {
23
- question(query: string, callback: (answer: string) => void): void;
24
- close(): void;
25
- pause(): this;
26
- resume(): this;
27
- setPrompt(prompt: string): void;
28
- prompt(preserveCursor?: boolean): void;
29
- write(
30
- data: string | Buffer,
31
- key?: { ctrl?: boolean; meta?: boolean; shift?: boolean; name: string },
32
- ): void;
33
- }
34
-
35
- function createInterface(options: ReadLineOptions): Interface;
36
- }
37
-
38
- declare module "node:readline" {
39
- export * from "readline";
40
- }
41
-
42
- declare module "node:process" {
43
- export const stdin: NodeJS.ReadableStream;
44
- export const stdout: NodeJS.WritableStream;
45
- export const stderr: NodeJS.WritableStream;
46
- export const env: NodeJS.ProcessEnv;
47
- export const platform: NodeJS.Platform;
48
- export function cwd(): string;
49
- export function exit(code?: number): never;
50
- }
51
-
52
- declare module "node:os" {
53
- export function homedir(): string;
54
- export function tmpdir(): string;
55
- export function hostname(): string;
56
- export function platform(): NodeJS.Platform;
57
- export function type(): string;
58
- export function release(): string;
59
- export function arch(): string;
60
- export function cpus(): Array<{
61
- model: string;
62
- speed: number;
63
- times: object;
64
- }>;
65
- export function totalmem(): number;
66
- export function freemem(): number;
67
- export function networkInterfaces(): NodeJS.Dict<
68
- Array<{
69
- address: string;
70
- netmask: string;
71
- family: string;
72
- mac: string;
73
- internal: boolean;
74
- }>
75
- >;
76
- }
77
-
78
- declare module "node:path" {
79
- export function join(...paths: string[]): string;
80
- export function resolve(...paths: string[]): string;
81
- export function dirname(path: string): string;
82
- export function basename(path: string, ext?: string): string;
83
- export function extname(path: string): string;
84
- export function normalize(path: string): string;
85
- export function isAbsolute(path: string): boolean;
86
- export function relative(from: string, to: string): string;
87
- export function parse(path: string): {
88
- root: string;
89
- dir: string;
90
- base: string;
91
- ext: string;
92
- name: string;
93
- };
94
- export const sep: string;
95
- export const delimiter: string;
96
- }
97
-
98
- declare module "node:fs" {
99
- export function readFileSync(path: string, encoding: BufferEncoding): string;
100
- export function readFileSync(path: string): Buffer;
101
- export function writeFileSync(
102
- path: string,
103
- data: string | Buffer,
104
- options?:
105
- | { encoding?: BufferEncoding; mode?: number; flag?: string }
106
- | BufferEncoding,
107
- ): void;
108
- export function existsSync(path: string): boolean;
109
- export function mkdirSync(
110
- path: string,
111
- options?: { recursive?: boolean; mode?: number },
112
- ): string | undefined;
113
- export function readdirSync(path: string): string[];
114
- export function statSync(path: string): {
115
- isFile(): boolean;
116
- isDirectory(): boolean;
117
- size: number;
118
- mtime: Date;
119
- };
120
- export function unlinkSync(path: string): void;
121
- export function rmdirSync(
122
- path: string,
123
- options?: { recursive?: boolean },
124
- ): void;
125
- export function copyFileSync(src: string, dest: string): void;
126
- export function renameSync(oldPath: string, newPath: string): void;
127
- }
128
-
129
- declare module "node:http" {
130
- import { EventEmitter } from "events";
131
- import { Duplex } from "stream";
132
-
133
- export interface IncomingMessage extends Duplex {
134
- url?: string;
135
- method?: string;
136
- headers: { [key: string]: string | string[] | undefined };
137
- httpVersion: string;
138
- statusCode?: number;
139
- statusMessage?: string;
140
- }
141
-
142
- export interface ServerResponse extends Duplex {
143
- statusCode: number;
144
- statusMessage: string;
145
- writeHead(
146
- statusCode: number,
147
- headers?: { [key: string]: string | string[] },
148
- ): this;
149
- setHeader(name: string, value: string | string[]): this;
150
- getHeader(name: string): string | string[] | undefined;
151
- removeHeader(name: string): void;
152
- write(chunk: any, encoding?: BufferEncoding): boolean;
153
- end(data?: any, encoding?: BufferEncoding): this;
154
- }
155
-
156
- export interface Server extends EventEmitter {
157
- listen(port: number, hostname?: string, callback?: () => void): this;
158
- listen(port: number, callback?: () => void): this;
159
- close(callback?: (err?: Error) => void): this;
160
- address():
161
- | { address: string; family: string; port: number }
162
- | string
163
- | null;
164
- on(event: string, listener: (...args: any[]) => void): this;
165
- on(event: "error", listener: (err: Error) => void): this;
166
- on(event: "listening", listener: () => void): this;
167
- on(event: "close", listener: () => void): this;
168
- }
169
-
170
- export function createServer(
171
- requestListener?: (req: IncomingMessage, res: ServerResponse) => void,
172
- ): Server;
173
- }
174
-
175
- declare module "open" {
176
- interface Options {
177
- wait?: boolean;
178
- background?: boolean;
179
- newInstance?: boolean;
180
- allowNonzeroExitCode?: boolean;
181
- app?: { name: string; arguments?: string[] } | string;
182
- }
183
-
184
- function open(
185
- target: string,
186
- options?: Options,
187
- ): Promise<import("child_process").ChildProcess>;
188
- export default open;
189
- }
190
-
191
- declare var process: NodeJS.Process;
192
-
193
- declare namespace NodeJS {
194
- interface Dict<T> {
195
- [key: string]: T | undefined;
196
- }
197
-
198
- interface ProcessEnv {
199
- [key: string]: string | undefined;
200
- }
201
-
202
- interface Process {
203
- stdin: ReadableStream;
204
- stdout: WritableStream;
205
- stderr: WritableStream;
206
- env: ProcessEnv;
207
- platform: Platform;
208
- cwd(): string;
209
- exit(code?: number): never;
210
- }
211
-
212
- interface ReadableStream {
213
- read(size?: number): string | Buffer | null;
214
- on(event: string, listener: (...args: any[]) => void): this;
215
- pipe<T extends WritableStream>(destination: T): T;
216
- }
217
-
218
- interface WritableStream {
219
- write(chunk: any): boolean;
220
- end(): void;
221
- on(event: string, listener: (...args: any[]) => void): this;
222
- }
223
-
224
- interface ErrnoException extends Error {
225
- errno?: number;
226
- code?: string;
227
- path?: string;
228
- syscall?: string;
229
- stack?: string;
230
- }
231
-
232
- type Platform =
233
- | "aix"
234
- | "android"
235
- | "darwin"
236
- | "freebsd"
237
- | "haiku"
238
- | "linux"
239
- | "openbsd"
240
- | "sunos"
241
- | "win32"
242
- | "cygwin"
243
- | "netbsd";
244
- }
245
-
246
- type BufferEncoding =
247
- | "ascii"
248
- | "utf8"
249
- | "utf-8"
250
- | "utf16le"
251
- | "ucs2"
252
- | "ucs-2"
253
- | "base64"
254
- | "base64url"
255
- | "latin1"
256
- | "binary"
257
- | "hex";
package/src/models.ts DELETED
@@ -1,148 +0,0 @@
1
- /**
2
- * Qwen Code Models Configuration
3
- * Defines available models and their specifications for the OpenCode plugin
4
- */
5
-
6
- import type { QwenModelInfo } from "./types";
7
-
8
- /**
9
- * Available Qwen Code models accessible through OAuth authentication.
10
- * All models are free when using OAuth.
11
- */
12
- export const QWEN_CODE_MODELS: Record<string, QwenModelInfo> = {
13
- // Primary models
14
- "qwen3-coder-plus": {
15
- id: "qwen3-coder-plus",
16
- name: "Qwen3 Coder Plus",
17
- context_window: 1000000,
18
- max_output: 65536,
19
- input_price: 0.0,
20
- output_price: 0.0,
21
- supports_native_tools: true,
22
- supports_thinking: true,
23
- },
24
- "qwen3-coder-flash": {
25
- id: "qwen3-coder-flash",
26
- name: "Qwen3 Coder Flash",
27
- context_window: 1000000,
28
- max_output: 65536,
29
- input_price: 0.0,
30
- output_price: 0.0,
31
- supports_native_tools: true,
32
- supports_thinking: true,
33
- },
34
- };
35
-
36
- /**
37
- * Model aliases mapping friendly names to actual model IDs.
38
- */
39
- export const MODEL_ALIASES: Record<string, string> = {
40
- "qwen-coder-plus": "qwen3-coder-plus",
41
- "qwen-coder-flash": "qwen3-coder-flash",
42
- };
43
-
44
- /**
45
- * Default model to use when none specified.
46
- */
47
- export const DEFAULT_MODEL = "qwen3-coder-plus";
48
-
49
- /**
50
- * Get model info by ID or alias.
51
- *
52
- * @param modelIdOrAlias - Model ID or alias name
53
- * @returns Model info or undefined if not found
54
- */
55
- export function getModelInfo(modelIdOrAlias: string): QwenModelInfo | undefined {
56
- // Check if it's a direct model ID
57
- if (modelIdOrAlias in QWEN_CODE_MODELS) {
58
- return QWEN_CODE_MODELS[modelIdOrAlias];
59
- }
60
-
61
- // Check if it's an alias
62
- const resolvedId = MODEL_ALIASES[modelIdOrAlias];
63
- if (resolvedId && resolvedId in QWEN_CODE_MODELS) {
64
- return QWEN_CODE_MODELS[resolvedId];
65
- }
66
-
67
- return undefined;
68
- }
69
-
70
- /**
71
- * Resolve model alias to actual model ID.
72
- *
73
- * @param modelIdOrAlias - Model ID or alias name
74
- * @returns Resolved model ID or the original string if not found
75
- */
76
- export function resolveModelId(modelIdOrAlias: string): string {
77
- return MODEL_ALIASES[modelIdOrAlias] || modelIdOrAlias;
78
- }
79
-
80
- /**
81
- * Get all available model IDs (including aliases).
82
- */
83
- export function getAllModelIds(): string[] {
84
- return [
85
- ...Object.keys(QWEN_CODE_MODELS),
86
- ...Object.keys(MODEL_ALIASES),
87
- ];
88
- }
89
-
90
- /**
91
- * Check if a model ID or alias is valid.
92
- */
93
- export function isValidModel(modelIdOrAlias: string): boolean {
94
- return getModelInfo(modelIdOrAlias) !== undefined;
95
- }
96
-
97
- /**
98
- * Generate OpenCode provider configuration for Qwen Code models.
99
- * Use this to configure models in opencode.json.
100
- */
101
- export function generateProviderConfig(): Record<string, unknown> {
102
- const models: Record<string, unknown> = {};
103
-
104
- // Add primary models
105
- for (const [id, info] of Object.entries(QWEN_CODE_MODELS)) {
106
- models[id] = {
107
- id: info.id,
108
- name: info.name,
109
- limit: {
110
- context: info.context_window,
111
- output: info.max_output,
112
- },
113
- cost: {
114
- input: info.input_price,
115
- output: info.output_price,
116
- },
117
- };
118
- }
119
-
120
- // Add aliases
121
- for (const [alias, targetId] of Object.entries(MODEL_ALIASES)) {
122
- const targetInfo = QWEN_CODE_MODELS[targetId];
123
- if (targetInfo) {
124
- models[alias] = {
125
- id: targetInfo.id,
126
- name: `${targetInfo.name} (Alias)`,
127
- limit: {
128
- context: targetInfo.context_window,
129
- output: targetInfo.max_output,
130
- },
131
- cost: {
132
- input: targetInfo.input_price,
133
- output: targetInfo.output_price,
134
- },
135
- };
136
- }
137
- }
138
-
139
- return {
140
- qwencode: {
141
- npm: "@ai-sdk/openai-compatible",
142
- options: {
143
- baseURL: "https://portal.qwen.ai/v1",
144
- },
145
- models,
146
- },
147
- };
148
- }