@hotmanxp/opencode-qwen-login-plugin 1.1.0 → 1.2.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.
package/dist/cli.js CHANGED
File without changes
@@ -0,0 +1,188 @@
1
+ /**
2
+ * 配置合并测试 - 集成测试
3
+ *
4
+ * 测试 saveToOpencodeConfig 函数的合并行为
5
+ */
6
+ import { describe, it, beforeEach, afterEach } from 'node:test';
7
+ import { writeFile, mkdir, rm, readFile } from 'node:fs/promises';
8
+ import { join } from 'node:path';
9
+ import assert from 'node:assert';
10
+ import { saveToOpencodeConfig } from './qwen-oauth.js';
11
+ describe('saveToOpencodeConfig - 配置合并', () => {
12
+ let testConfigDir;
13
+ let testConfigPath;
14
+ let originalHOME;
15
+ beforeEach(async () => {
16
+ originalHOME = process.env.HOME;
17
+ testConfigDir = await mkdtemp('opencode-config-test-');
18
+ testConfigPath = join(testConfigDir, '.config', 'opencode');
19
+ await mkdir(testConfigPath, { recursive: true });
20
+ process.env.HOME = testConfigDir;
21
+ });
22
+ afterEach(async () => {
23
+ process.env.HOME = originalHOME;
24
+ await rm(testConfigDir, { recursive: true, force: true }).catch(() => { });
25
+ });
26
+ it('应该保留现有的 plugin 数组', async () => {
27
+ // 创建初始配置
28
+ const initialConfig = {
29
+ plugin: ['oh-my-opencode', 'another-plugin'],
30
+ agent: {
31
+ build: {
32
+ max_steps: 10
33
+ }
34
+ }
35
+ };
36
+ const configPath = join(testConfigPath, 'opencode.json');
37
+ await writeFile(configPath, JSON.stringify(initialConfig, null, 2));
38
+ // 调用 saveToOpencodeConfig
39
+ await saveToOpencodeConfig({
40
+ apiKey: 'Bearer test-token',
41
+ baseURL: 'https://portal.qwen.ai/v1',
42
+ headers: {
43
+ 'user-agent': 'QwenCode/test'
44
+ }
45
+ });
46
+ // 读取更新后的配置
47
+ const updatedConfig = JSON.parse(await readFile(configPath, 'utf-8'));
48
+ // 验证 plugin 数组被保留
49
+ assert.ok(updatedConfig.plugin.includes('oh-my-opencode'), 'Should contain oh-my-opencode');
50
+ assert.ok(updatedConfig.plugin.includes('another-plugin'), 'Should contain another-plugin');
51
+ // 验证 agent 配置被保留
52
+ assert.ok(updatedConfig.agent, 'Should have agent config');
53
+ assert.ok(updatedConfig.agent.build, 'Should have build agent');
54
+ assert.strictEqual(updatedConfig.agent.build.max_steps, 10);
55
+ // 验证 qwen provider 被添加
56
+ assert.ok(updatedConfig.provider, 'Should have provider config');
57
+ assert.ok(updatedConfig.provider.qwen, 'Should have qwen provider');
58
+ });
59
+ it('应该保留现有的其他 provider', async () => {
60
+ // 创建初始配置,包含其他 provider
61
+ const initialConfig = {
62
+ provider: {
63
+ anthropic: {
64
+ options: {
65
+ apiKey: 'sk-ant-xxx'
66
+ }
67
+ },
68
+ openai: {
69
+ options: {
70
+ apiKey: 'sk-openai-xxx'
71
+ }
72
+ }
73
+ },
74
+ model: 'anthropic/claude-sonnet-4-20250514'
75
+ };
76
+ const configPath = join(testConfigPath, 'opencode.json');
77
+ await writeFile(configPath, JSON.stringify(initialConfig, null, 2));
78
+ // 调用 saveToOpencodeConfig
79
+ await saveToOpencodeConfig({
80
+ apiKey: 'Bearer test-token',
81
+ baseURL: 'https://portal.qwen.ai/v1',
82
+ headers: {}
83
+ });
84
+ // 读取更新后的配置
85
+ const updatedConfig = JSON.parse(await readFile(configPath, 'utf-8'));
86
+ // 验证其他 provider 被保留
87
+ assert.ok(updatedConfig.provider.anthropic, "should be defined");
88
+ assert.strictEqual(updatedConfig.provider.anthropic.options.apiKey, 'sk-ant-xxx');
89
+ assert.ok(updatedConfig.provider.openai, "should be defined");
90
+ assert.strictEqual(updatedConfig.provider.openai.options.apiKey, 'sk-openai-xxx');
91
+ // 验证 qwen provider 被添加
92
+ assert.ok(updatedConfig.provider.qwen, "should be defined");
93
+ assert.strictEqual(updatedConfig.provider.qwen.options.apiKey, 'Bearer test-token');
94
+ });
95
+ it('不应该覆盖现有的 model 配置', async () => {
96
+ // 创建初始配置,包含自定义 model
97
+ const initialConfig = {
98
+ provider: {
99
+ anthropic: {
100
+ options: {
101
+ apiKey: 'sk-ant-xxx'
102
+ }
103
+ }
104
+ },
105
+ model: 'anthropic/claude-sonnet-4-20250514'
106
+ };
107
+ const configPath = join(testConfigPath, 'opencode.json');
108
+ await writeFile(configPath, JSON.stringify(initialConfig, null, 2));
109
+ // 调用 saveToOpencodeConfig
110
+ await saveToOpencodeConfig({
111
+ apiKey: 'Bearer test-token',
112
+ baseURL: 'https://portal.qwen.ai/v1',
113
+ headers: {}
114
+ });
115
+ // 读取更新后的配置
116
+ const updatedConfig = JSON.parse(await readFile(configPath, 'utf-8'));
117
+ // 验证原有 model 被保留(不覆盖)
118
+ assert.strictEqual(updatedConfig.model, 'anthropic/claude-sonnet-4-20250514');
119
+ });
120
+ it('不应该设置默认 model', async () => {
121
+ // 创建初始配置,没有 model
122
+ const initialConfig = {
123
+ plugin: ['test-plugin']
124
+ };
125
+ const configPath = join(testConfigPath, 'opencode.json');
126
+ await writeFile(configPath, JSON.stringify(initialConfig, null, 2));
127
+ // 调用 saveToOpencodeConfig
128
+ await saveToOpencodeConfig({
129
+ apiKey: 'Bearer test-token',
130
+ baseURL: 'https://portal.qwen.ai/v1',
131
+ headers: {}
132
+ });
133
+ // 读取更新后的配置
134
+ const updatedConfig = JSON.parse(await readFile(configPath, 'utf-8'));
135
+ // 验证不设置默认 model(让用户自己配置)
136
+ assert.strictEqual(updatedConfig.model, undefined, 'Should not set default model');
137
+ // 验证 plugin 被保留
138
+ assert.ok(updatedConfig.plugin.includes('test-plugin'), 'Should include test-plugin');
139
+ });
140
+ it('应该保留其他顶层配置', async () => {
141
+ // 创建初始配置,包含各种配置
142
+ const initialConfig = {
143
+ $schema: 'https://opencode.ai/config.json',
144
+ agent: {
145
+ build: { max_steps: 10 },
146
+ plan: { read_only: true }
147
+ },
148
+ mode: {
149
+ default: 'build'
150
+ },
151
+ instructions: ['./instructions.md'],
152
+ plugin: ['plugin-a', 'plugin-b'],
153
+ provider: {
154
+ anthropic: { options: { apiKey: 'sk-ant' } }
155
+ }
156
+ };
157
+ const configPath = join(testConfigPath, 'opencode.json');
158
+ await writeFile(configPath, JSON.stringify(initialConfig, null, 2));
159
+ // 调用 saveToOpencodeConfig
160
+ await saveToOpencodeConfig({
161
+ apiKey: 'Bearer test-token',
162
+ baseURL: 'https://portal.qwen.ai/v1',
163
+ headers: {}
164
+ });
165
+ // 读取更新后的配置
166
+ const updatedConfig = JSON.parse(await readFile(configPath, 'utf-8'));
167
+ // 验证所有配置都被保留
168
+ assert.strictEqual(updatedConfig.$schema, 'https://opencode.ai/config.json');
169
+ assert.strictEqual(updatedConfig.agent.build.max_steps, 10);
170
+ assert.strictEqual(updatedConfig.agent.plan.read_only, true);
171
+ assert.strictEqual(updatedConfig.mode.default, 'build');
172
+ assert.ok(updatedConfig.instructions.includes('./instructions.md'), "should include");
173
+ assert.ok(updatedConfig.plugin.includes('plugin-a'), "should include");
174
+ assert.ok(updatedConfig.plugin.includes('plugin-b'), "should include");
175
+ assert.strictEqual(updatedConfig.provider.anthropic.options.apiKey, 'sk-ant');
176
+ // 验证 qwen 被添加
177
+ assert.ok(updatedConfig.provider.qwen, "should be defined");
178
+ });
179
+ });
180
+ // 辅助函数
181
+ async function mkdtemp(template) {
182
+ const fs = await import('node:fs/promises');
183
+ const path = await import('node:path');
184
+ const os = await import('node:os');
185
+ const dir = path.join(os.tmpdir(), `${template}${Date.now()}-${Math.random().toString(36).slice(2)}`);
186
+ await fs.mkdir(dir, { recursive: true });
187
+ return dir;
188
+ }
package/dist/index.js CHANGED
@@ -48,8 +48,8 @@ async function plugin(pluginInput) {
48
48
  temperature: true,
49
49
  interleaved: true,
50
50
  limit: {
51
- context: 256000,
52
- output: 8192
51
+ context: 1048576,
52
+ output: 131072
53
53
  }
54
54
  },
55
55
  "qwen-plus": {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,8BAA8B,EAAE,oBAAoB,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAE3H;;GAEG;AACH,KAAK,UAAU,MAAM,CAAC,WAAgB;IACpC,gBAAgB;IAChB,IAAI,CAAC;QACH,MAAM,8BAA8B,EAAE,CAAA;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,gBAAgB;IAClB,CAAC;IAED,OAAO;QACL,iBAAiB;QACjB,MAAM,EAAE,KAAK,EAAE,MAAW,EAAE,EAAE;YAC5B,IAAI,CAAC;gBACH,iBAAiB;gBACjB,MAAM,KAAK,GAAG,MAAM,oBAAoB,EAAE,CAAA;gBAE1C,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,OAAM;gBACR,CAAC;gBAED,mBAAmB;gBACnB,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzB,OAAM;gBACR,CAAC;gBAED,eAAe;gBACf,MAAM,SAAS,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAA;gBAE9C,oCAAoC;gBACpC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;oBACrB,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAA;gBACtB,CAAC;gBAED,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG;oBACrB,IAAI,EAAE,aAAa;oBACnB,GAAG,EAAE,2BAA2B;oBAChC,GAAG,EAAE,EAAE;oBACP,MAAM,EAAE;wBACN,aAAa,EAAE;4BACb,IAAI,EAAE,kBAAkB;4BACxB,SAAS,EAAE,IAAI;4BACf,SAAS,EAAE,KAAK;4BAChB,UAAU,EAAE,IAAI;4BAChB,WAAW,EAAE,IAAI;4BACjB,WAAW,EAAE,IAAI;4BACjB,KAAK,EAAE;gCACL,OAAO,EAAE,MAAM;gCACf,MAAM,EAAE,IAAI;6BACb;yBACF;wBACD,WAAW,EAAE;4BACX,IAAI,EAAE,WAAW;4BACjB,SAAS,EAAE,IAAI;4BACf,SAAS,EAAE,KAAK;4BAChB,UAAU,EAAE,IAAI;4BAChB,WAAW,EAAE,IAAI;4BACjB,WAAW,EAAE,IAAI;4BACjB,KAAK,EAAE;gCACL,OAAO,EAAE,MAAM;gCACf,MAAM,EAAE,IAAI;6BACb;yBACF;qBACF;oBACD,OAAO,EAAE;wBACP,MAAM,EAAE,SAAS,CAAC,MAAM;wBACxB,OAAO,EAAE,SAAS,CAAC,OAAO;wBAC1B,OAAO,EAAE,SAAS,CAAC,OAAO;qBAC3B;iBACF,CAAA;YAEH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO;YACT,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC;AAED,UAAU;AACV,eAAe,MAAM,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,8BAA8B,EAAE,oBAAoB,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAE3H;;GAEG;AACH,KAAK,UAAU,MAAM,CAAC,WAAgB;IACpC,gBAAgB;IAChB,IAAI,CAAC;QACH,MAAM,8BAA8B,EAAE,CAAA;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,gBAAgB;IAClB,CAAC;IAED,OAAO;QACL,iBAAiB;QACjB,MAAM,EAAE,KAAK,EAAE,MAAW,EAAE,EAAE;YAC5B,IAAI,CAAC;gBACH,iBAAiB;gBACjB,MAAM,KAAK,GAAG,MAAM,oBAAoB,EAAE,CAAA;gBAE1C,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,OAAM;gBACR,CAAC;gBAED,mBAAmB;gBACnB,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzB,OAAM;gBACR,CAAC;gBAED,eAAe;gBACf,MAAM,SAAS,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAA;gBAE9C,oCAAoC;gBACpC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;oBACrB,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAA;gBACtB,CAAC;gBAED,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG;oBACrB,IAAI,EAAE,aAAa;oBACnB,GAAG,EAAE,2BAA2B;oBAChC,GAAG,EAAE,EAAE;oBACP,MAAM,EAAE;wBACN,aAAa,EAAE;4BACb,IAAI,EAAE,kBAAkB;4BACxB,SAAS,EAAE,IAAI;4BACf,SAAS,EAAE,KAAK;4BAChB,UAAU,EAAE,IAAI;4BAChB,WAAW,EAAE,IAAI;4BACjB,WAAW,EAAE,IAAI;4BACjB,KAAK,EAAE;gCACL,OAAO,EAAE,OAAO;gCAChB,MAAM,EAAE,MAAM;6BACf;yBACF;wBACD,WAAW,EAAE;4BACX,IAAI,EAAE,WAAW;4BACjB,SAAS,EAAE,IAAI;4BACf,SAAS,EAAE,KAAK;4BAChB,UAAU,EAAE,IAAI;4BAChB,WAAW,EAAE,IAAI;4BACjB,WAAW,EAAE,IAAI;4BACjB,KAAK,EAAE;gCACL,OAAO,EAAE,MAAM;gCACf,MAAM,EAAE,IAAI;6BACb;yBACF;qBACF;oBACD,OAAO,EAAE;wBACP,MAAM,EAAE,SAAS,CAAC,MAAM;wBACxB,OAAO,EAAE,SAAS,CAAC,OAAO;wBAC1B,OAAO,EAAE,SAAS,CAAC,OAAO;qBAC3B;iBACF,CAAA;YAEH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO;YACT,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC;AAED,UAAU;AACV,eAAe,MAAM,CAAA"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Qwen Login Plugin - 通义千问认证插件
3
+ *
4
+ * 为 opencode 提供 Qwen 模型认证支持
5
+ * 自动从 qwen-code OAuth 配置导入认证信息
6
+ */
7
+ /**
8
+ * Qwen 认证插件主函数
9
+ */
10
+ declare function plugin(pluginInput: any): Promise<{
11
+ config: (config: any) => Promise<void>;
12
+ }>;
13
+ export default plugin;
14
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;GAEG;AACH,iBAAe,MAAM,CAAC,WAAW,EAAE,GAAG;qBAUX,GAAG;GAgE7B;AAGD,eAAe,MAAM,CAAA"}
package/dist/plugin.js ADDED
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Qwen Login Plugin - 通义千问认证插件
3
+ *
4
+ * 为 opencode 提供 Qwen 模型认证支持
5
+ * 自动从 qwen-code OAuth 配置导入认证信息
6
+ */
7
+ import { configureOpencodeFromQwenOAuth, readOAuthCredentials, isTokenValid, getApiConfigFromOAuth } from "./qwen-oauth.js";
8
+ /**
9
+ * Qwen 认证插件主函数
10
+ */
11
+ async function plugin(pluginInput) {
12
+ // 插件加载时立即写入配置文件
13
+ try {
14
+ await configureOpencodeFromQwenOAuth();
15
+ }
16
+ catch (error) {
17
+ // 静默失败,使用其他认证方式
18
+ }
19
+ return {
20
+ // 配置钩子 - 修改运行时配置
21
+ config: async (config) => {
22
+ try {
23
+ // 1. 读取 OAuth 凭证
24
+ const creds = await readOAuthCredentials();
25
+ if (!creds) {
26
+ return;
27
+ }
28
+ // 2. 检查 token 是否有效
29
+ if (!isTokenValid(creds)) {
30
+ return;
31
+ }
32
+ // 3. 生成 API 配置
33
+ const apiConfig = getApiConfigFromOAuth(creds);
34
+ // 4. 按照 opencode provider schema 配置
35
+ if (!config.provider) {
36
+ config.provider = {};
37
+ }
38
+ config.provider.qwen = {
39
+ name: "Qwen (通义千问)",
40
+ npm: "@ai-sdk/openai-compatible",
41
+ env: [],
42
+ models: {
43
+ "coder-model": {
44
+ name: "Qwen Coder Model",
45
+ tool_call: true,
46
+ reasoning: false,
47
+ attachment: true,
48
+ temperature: true,
49
+ interleaved: true,
50
+ limit: {
51
+ context: 256000,
52
+ output: 8192
53
+ }
54
+ },
55
+ "qwen-plus": {
56
+ name: "Qwen Plus",
57
+ tool_call: true,
58
+ reasoning: false,
59
+ attachment: true,
60
+ temperature: true,
61
+ interleaved: true,
62
+ limit: {
63
+ context: 131072,
64
+ output: 8192
65
+ }
66
+ }
67
+ },
68
+ options: {
69
+ apiKey: apiConfig.apiKey,
70
+ baseURL: apiConfig.baseURL,
71
+ headers: apiConfig.headers
72
+ }
73
+ };
74
+ }
75
+ catch (error) {
76
+ // 静默失败
77
+ }
78
+ }
79
+ };
80
+ }
81
+ // 只导出默认函数
82
+ export default plugin;
83
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,8BAA8B,EAAE,oBAAoB,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAE3H;;GAEG;AACH,KAAK,UAAU,MAAM,CAAC,WAAgB;IACpC,gBAAgB;IAChB,IAAI,CAAC;QACH,MAAM,8BAA8B,EAAE,CAAA;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,gBAAgB;IAClB,CAAC;IAED,OAAO;QACL,iBAAiB;QACjB,MAAM,EAAE,KAAK,EAAE,MAAW,EAAE,EAAE;YAC5B,IAAI,CAAC;gBACH,iBAAiB;gBACjB,MAAM,KAAK,GAAG,MAAM,oBAAoB,EAAE,CAAA;gBAE1C,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,OAAM;gBACR,CAAC;gBAED,mBAAmB;gBACnB,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzB,OAAM;gBACR,CAAC;gBAED,eAAe;gBACf,MAAM,SAAS,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAA;gBAE9C,oCAAoC;gBACpC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;oBACrB,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAA;gBACtB,CAAC;gBAED,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG;oBACrB,IAAI,EAAE,aAAa;oBACnB,GAAG,EAAE,2BAA2B;oBAChC,GAAG,EAAE,EAAE;oBACP,MAAM,EAAE;wBACN,aAAa,EAAE;4BACb,IAAI,EAAE,kBAAkB;4BACxB,SAAS,EAAE,IAAI;4BACf,SAAS,EAAE,KAAK;4BAChB,UAAU,EAAE,IAAI;4BAChB,WAAW,EAAE,IAAI;4BACjB,WAAW,EAAE,IAAI;4BACjB,KAAK,EAAE;gCACL,OAAO,EAAE,MAAM;gCACf,MAAM,EAAE,IAAI;6BACb;yBACF;wBACD,WAAW,EAAE;4BACX,IAAI,EAAE,WAAW;4BACjB,SAAS,EAAE,IAAI;4BACf,SAAS,EAAE,KAAK;4BAChB,UAAU,EAAE,IAAI;4BAChB,WAAW,EAAE,IAAI;4BACjB,WAAW,EAAE,IAAI;4BACjB,KAAK,EAAE;gCACL,OAAO,EAAE,MAAM;gCACf,MAAM,EAAE,IAAI;6BACb;yBACF;qBACF;oBACD,OAAO,EAAE;wBACP,MAAM,EAAE,SAAS,CAAC,MAAM;wBACxB,OAAO,EAAE,SAAS,CAAC,OAAO;wBAC1B,OAAO,EAAE,SAAS,CAAC,OAAO;qBAC3B;iBACF,CAAA;YAEH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO;YACT,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC;AAED,UAAU;AACV,eAAe,MAAM,CAAA"}
@@ -202,8 +202,8 @@ async function saveConfigToFile(configPath, config, targetType) {
202
202
  temperature: true,
203
203
  interleaved: true,
204
204
  limit: {
205
- context: 256000,
206
- output: 8192
205
+ context: 1048576,
206
+ output: 131072
207
207
  }
208
208
  },
209
209
  "qwen-plus": {
@@ -1 +1 @@
1
- {"version":3,"file":"qwen-oauth.js","sourceRoot":"","sources":["../src/qwen-oauth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"qwen-oauth.js","sourceRoot":"","sources":["../src/qwen-oauth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Qwen Login Plugin - 单元测试
3
+ *
4
+ * 测试配置合并、OAuth 读取等功能
5
+ */
6
+ import { describe, it, beforeEach, afterEach } from 'node:test';
7
+ import { writeFile, mkdir, rm } from 'node:fs/promises';
8
+ import { join } from 'node:path';
9
+ import { tmpdir } from 'node:os';
10
+ import assert from 'node:assert';
11
+ import { readOAuthCredentials, isTokenValid, getApiConfigFromOAuth, buildBaseUrl, buildDefaultHeaders } from './qwen-oauth.js';
12
+ // 测试用的临时目录
13
+ let testDir;
14
+ let testQwenDir;
15
+ describe('Qwen Login Plugin', () => {
16
+ beforeEach(async () => {
17
+ // 创建临时测试目录
18
+ testDir = await mkdtemp('qwen-login-plugin-test-');
19
+ testQwenDir = join(testDir, '.qwen');
20
+ await mkdir(testQwenDir, { recursive: true });
21
+ });
22
+ afterEach(async () => {
23
+ // 清理临时目录
24
+ await rm(testDir, { recursive: true, force: true }).catch(() => { });
25
+ });
26
+ describe('buildBaseUrl', () => {
27
+ it('应该从 resource_url 构建正确的 endpoint', () => {
28
+ assert.strictEqual(buildBaseUrl('portal.qwen.ai'), 'https://portal.qwen.ai/v1');
29
+ });
30
+ it('应该在没有 resource_url 时使用默认值', () => {
31
+ assert.strictEqual(buildBaseUrl(''), 'https://dashscope.aliyuncs.com/compatible-mode/v1');
32
+ assert.strictEqual(buildBaseUrl(undefined), 'https://dashscope.aliyuncs.com/compatible-mode/v1');
33
+ });
34
+ });
35
+ describe('buildDefaultHeaders', () => {
36
+ it('应该生成完整的请求头', () => {
37
+ const headers = buildDefaultHeaders('test-token-123');
38
+ assert.ok(headers.authorization, 'Should have authorization header');
39
+ assert.strictEqual(headers.authorization, 'Bearer test-token-123');
40
+ assert.ok(headers['user-agent'], 'Should have user-agent header');
41
+ assert.match(headers['user-agent'], /QwenCode\/.*\(.*;.*\)/);
42
+ assert.ok(headers['x-dashscope-authtype'], 'Should have x-dashscope-authtype header');
43
+ assert.strictEqual(headers['x-dashscope-authtype'], 'qwen-oauth');
44
+ assert.ok(headers['content-type'], 'Should have content-type header');
45
+ assert.strictEqual(headers['content-type'], 'application/json');
46
+ assert.ok(headers['accept'], 'Should have accept header');
47
+ assert.strictEqual(headers['accept'], 'application/json');
48
+ });
49
+ it('应该包含所有 stainless 相关 headers', () => {
50
+ const headers = buildDefaultHeaders('test-token');
51
+ assert.strictEqual(headers['x-stainless-lang'], 'js');
52
+ assert.strictEqual(headers['x-stainless-package-version'], '4.104.0');
53
+ assert.strictEqual(headers['x-stainless-os'], 'MacOS');
54
+ assert.strictEqual(headers['x-stainless-runtime'], 'node');
55
+ });
56
+ });
57
+ describe('isTokenValid', () => {
58
+ it('应该返回 true 当 token 未过期', () => {
59
+ const futureDate = Date.now() + 1000 * 60 * 60 * 24; // 1 天后
60
+ assert.strictEqual(isTokenValid({ expiry_date: futureDate }), true);
61
+ });
62
+ it('应该返回 false 当 token 已过期', () => {
63
+ const pastDate = Date.now() - 1000 * 60 * 60; // 1 小时前
64
+ assert.strictEqual(isTokenValid({ expiry_date: pastDate }), false);
65
+ });
66
+ });
67
+ describe('readOAuthCredentials', () => {
68
+ it('应该成功读取 OAuth 凭证', async () => {
69
+ // 模拟 OAuth 凭证文件
70
+ const mockCreds = {
71
+ access_token: 'test-access-token',
72
+ token_type: 'Bearer',
73
+ refresh_token: 'test-refresh-token',
74
+ resource_url: 'portal.qwen.ai',
75
+ expiry_date: Date.now() + 1000000
76
+ };
77
+ await writeFile(join(testQwenDir, 'oauth_creds.json'), JSON.stringify(mockCreds));
78
+ // 临时修改 home 目录
79
+ const originalHome = process.env.HOME;
80
+ process.env.HOME = testDir;
81
+ try {
82
+ const creds = await readOAuthCredentials();
83
+ assert.deepStrictEqual(creds, mockCreds);
84
+ }
85
+ finally {
86
+ process.env.HOME = originalHome;
87
+ }
88
+ });
89
+ it('应该在文件不存在时返回 null', async () => {
90
+ const originalHome = process.env.HOME;
91
+ process.env.HOME = testDir;
92
+ try {
93
+ const creds = await readOAuthCredentials();
94
+ assert.strictEqual(creds, null);
95
+ }
96
+ finally {
97
+ process.env.HOME = originalHome;
98
+ }
99
+ });
100
+ });
101
+ describe('getApiConfigFromOAuth', () => {
102
+ it('应该从 OAuth 凭证生成正确的 API 配置', () => {
103
+ const mockCreds = {
104
+ access_token: 'test-token',
105
+ token_type: 'Bearer',
106
+ refresh_token: 'test-refresh',
107
+ resource_url: 'portal.qwen.ai',
108
+ expiry_date: Date.now() + 1000000
109
+ };
110
+ const config = getApiConfigFromOAuth(mockCreds);
111
+ assert.strictEqual(config.apiKey, 'Bearer test-token');
112
+ assert.strictEqual(config.baseURL, 'https://portal.qwen.ai/v1');
113
+ assert.ok(config.headers);
114
+ assert.strictEqual(config.headers?.authorization, 'Bearer test-token');
115
+ });
116
+ });
117
+ });
118
+ // 辅助函数
119
+ async function mkdtemp(template) {
120
+ const dir = join(tmpdir(), `${template}${Date.now()}-${Math.random().toString(36).slice(2)}`);
121
+ await mkdir(dir, { recursive: true });
122
+ return dir;
123
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmanxp/opencode-qwen-login-plugin",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "通义千问认证插件 - 从 qwen-code OAuth 自动配置 opencode",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",