duojie-helper 0.2.21 → 0.2.23

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/bin/cli.js CHANGED
@@ -1,328 +1,328 @@
1
- #!/usr/bin/env node
2
-
3
- import { Command } from 'commander';
4
- import inquirer from 'inquirer';
5
- import chalk from 'chalk';
6
- import ora from 'ora';
7
- import { createRequire } from 'module';
8
- import { configureAll, configureTool, listTools, showStatus, revokeKey, fetchModels, getModels } from '../src/index.js';
9
-
10
- const require = createRequire(import.meta.url);
11
- const pkg = require('../package.json');
12
-
13
- const program = new Command();
14
-
15
- program
16
- .name('duojie')
17
- .description('🎮 Duojie API 一键配置助手 - 支持主流 AI 编程工具')
18
- .version(pkg.version);
19
-
20
- // 默认命令 - 交互式配置
21
- program
22
- .command('init', { isDefault: true })
23
- .description('交互式配置向导')
24
- .action(async () => {
25
- console.log(chalk.cyan(`
26
- ╔═══════════════════════════════════════════════════════════╗
27
- ║ ║
28
- ║ 🎮 Duojie API 配置助手 ║
29
- ║ ║
30
- ║ 一键配置你的 AI 编程工具 ║
31
- ║ 支持: Claude Code, OpenClaw, Cursor, Cline 等 ║
32
- ║ ║
33
- ║ 提示: 按 Ctrl+C 可随时退出 ║
34
- ║ ║
35
- ╚═══════════════════════════════════════════════════════════╝
36
- `));
37
-
38
- let apiKey = null;
39
- let tools = null;
40
- let step = 1;
41
-
42
- try {
43
- while (step > 0) {
44
- if (step === 1) {
45
- // 步骤 1: 输入 API Key
46
- const result = await inquirer.prompt([
47
- {
48
- type: 'input',
49
- name: 'apiKey',
50
- message: '请输入你的 Duojie API Key (Ctrl+C 退出):',
51
- filter: (input) => input.trim(),
52
- validate: (input) => {
53
- if (!input || input.length < 10) {
54
- return 'API Key 不能为空且长度至少 10 位';
55
- }
56
- return true;
57
- }
58
- }
59
- ]);
60
-
61
- apiKey = result.apiKey.trim();
62
-
63
- // 验证 API Key 并获取模型列表
64
- const modelSpinner = ora('正在验证 API Key 并获取模型列表...').start();
65
- const models = await fetchModels(apiKey);
66
-
67
- const totalModels = (models.claude?.length || 0) +
68
- (models.gpt?.length || 0) +
69
- (models.gemini?.length || 0) +
70
- (models.other?.length || 0);
71
-
72
- if (totalModels === 0) {
73
- modelSpinner.fail('API Key 无效或无法获取模型列表');
74
- continue; // 重新输入
75
- }
76
-
77
- modelSpinner.succeed(`验证成功!可用模型: ${totalModels} 个`);
78
- step = 2;
79
- }
80
-
81
- else if (step === 2) {
82
- // 步骤 2: 选择要配置的工具
83
- console.log(chalk.gray('\n 提示: 按 Ctrl+C 返回上一步\n'));
84
-
85
- try {
86
- const result = await inquirer.prompt([
87
- {
88
- type: 'checkbox',
89
- name: 'tools',
90
- message: '选择要配置的工具 (空格选择,回车确认):',
91
- loop: false,
92
- choices: [
93
- { name: '🤖 Claude Code - 自动配置', value: 'claude' },
94
- { name: '🏭 Droid - 自动配置', value: 'droid' },
95
- { name: '🦞 OpenClaw / Moltbot - 自动配置', value: 'openclaw' },
96
- { name: '🖥️ OpenCode - 自动配置', value: 'opencode' },
97
- { name: '💻 Continue - 自动配置', value: 'continue' },
98
- { name: '🤖 Codex CLI - 自动配置', value: 'codex' },
99
- new inquirer.Separator('── 以下需要手动配置 ──'),
100
- { name: '📝 Cursor - 输出配置信息', value: 'cursor' },
101
- { name: '🔌 Cline (VS Code) - 输出配置信息', value: 'cline' },
102
- ],
103
- validate: (input) => {
104
- if (input.length === 0) {
105
- return '请至少选择一个工具 (使用空格键选择)';
106
- }
107
- return true;
108
- }
109
- }
110
- ]);
111
-
112
- tools = result.tools;
113
- step = 3;
114
- } catch (err) {
115
- if (err.message?.includes('User force closed')) {
116
- step = 1; // 返回上一步
117
- console.log(chalk.yellow('\n↩ 返回上一步...\n'));
118
- continue;
119
- }
120
- throw err;
121
- }
122
- }
123
-
124
- else if (step === 3) {
125
- // 步骤 3: 执行配置
126
- const spinner = ora('正在配置...').start();
127
-
128
- const results = await configureAll(apiKey, tools);
129
-
130
- spinner.succeed('配置完成!');
131
-
132
- // 显示结果
133
- console.log('\n' + chalk.green('✅ 配置结果:'));
134
- console.log(chalk.gray('─'.repeat(60)));
135
-
136
- const autoConfigured = [];
137
- const manualRequired = [];
138
-
139
- for (const result of results) {
140
- if (result.success) {
141
- if (result.manual) {
142
- manualRequired.push(result);
143
- } else {
144
- autoConfigured.push(result);
145
- console.log(chalk.green(` ✓ ${result.tool}: ${result.message}`));
146
- }
147
- } else {
148
- console.log(chalk.red(` ✗ ${result.tool}: ${result.message}`));
149
- }
150
- }
151
-
152
- console.log(chalk.gray('─'.repeat(60)));
153
-
154
- // 显示需要手动配置的工具
155
- if (manualRequired.length > 0) {
156
- console.log(chalk.yellow('\n📋 以下工具需要手动配置:\n'));
157
-
158
- for (const result of manualRequired) {
159
- console.log(chalk.cyan(`\n━━━ ${result.tool} ━━━`));
160
- if (result.instructions) {
161
- console.log(result.instructions);
162
- }
163
- }
164
- }
165
-
166
- console.log(chalk.cyan('\n🎉 配置完成!\n'));
167
-
168
- // 显示后续步骤
169
- if (autoConfigured.length > 0) {
170
- console.log(chalk.yellow('📋 后续步骤:'));
171
- if (tools.includes('claude')) {
172
- console.log(chalk.gray(' • Claude Code: 重新打开终端窗口'));
173
- }
174
- if (tools.includes('droid')) {
175
- console.log(chalk.gray(' • Droid: 重启 Factory'));
176
- }
177
- if (tools.includes('openclaw')) {
178
- console.log(chalk.gray(' • OpenClaw: 运行 openclaw gateway restart'));
179
- }
180
- if (tools.includes('opencode')) {
181
- console.log(chalk.gray(' • OpenCode: 重启 OpenCode'));
182
- }
183
- if (tools.includes('continue')) {
184
- console.log(chalk.gray(' • Continue: 重启 VS Code/JetBrains'));
185
- }
186
- if (tools.includes('codex')) {
187
- console.log(chalk.gray(' • Codex CLI: 已写入 ~/.codex/config.toml(无需设置 DUOJIE_API_KEY)'));
188
- }
189
- console.log('');
190
- }
191
-
192
- step = 0; // 完成,退出循环
193
- }
194
- }
195
-
196
- } catch (error) {
197
- if (error.message?.includes('User force closed')) {
198
- console.log(chalk.yellow('\n\n👋 已退出配置向导\n'));
199
- process.exit(0);
200
- }
201
- console.error(chalk.red('\n❌ 配置失败:'), error.message);
202
- process.exit(1);
203
- }
204
- });
205
-
206
- // 配置单个工具
207
- program
208
- .command('config <tool>')
209
- .description('配置单个工具 (claude/droid/openclaw/opencode/cursor/cline/codex/continue)')
210
- .option('-k, --key <apiKey>', 'API Key')
211
- .action(async (tool, options) => {
212
- try {
213
- let apiKey = options.key;
214
-
215
- if (!apiKey) {
216
- const answer = await inquirer.prompt([
217
- {
218
- type: 'input',
219
- name: 'apiKey',
220
- message: '请输入你的 Duojie API Key:',
221
- filter: (input) => input.trim(),
222
- }
223
- ]);
224
- apiKey = answer.apiKey;
225
- } else {
226
- apiKey = apiKey.trim();
227
- }
228
-
229
- // 获取模型列表
230
- const spinner = ora('正在验证 API Key...').start();
231
- await fetchModels(apiKey);
232
- spinner.succeed('验证成功');
233
-
234
- const configSpinner = ora(`正在配置 ${tool}...`).start();
235
- const result = await configureTool(tool, apiKey);
236
-
237
- if (result.success) {
238
- configSpinner.succeed(result.message);
239
-
240
- // 如果需要手动配置,显示说明
241
- if (result.manual && result.instructions) {
242
- console.log(chalk.yellow('\n📋 手动配置说明:\n'));
243
- console.log(result.instructions);
244
- }
245
- } else {
246
- configSpinner.fail(result.message);
247
- }
248
- } catch (error) {
249
- console.error(chalk.red('配置失败:'), error.message);
250
- process.exit(1);
251
- }
252
- });
253
-
254
- // 查看状态
255
- program
256
- .command('status')
257
- .description('查看当前配置状态')
258
- .action(async () => {
259
- await showStatus();
260
- });
261
-
262
- // 列出支持的工具
263
- program
264
- .command('list')
265
- .description('列出支持的工具')
266
- .action(() => {
267
- listTools();
268
- });
269
-
270
- // 撤销配置
271
- program
272
- .command('revoke [tool]')
273
- .description('撤销配置 (不指定工具则撤销全部)')
274
- .action(async (tool) => {
275
- const { confirm } = await inquirer.prompt([
276
- {
277
- type: 'confirm',
278
- name: 'confirm',
279
- message: tool
280
- ? `确定要撤销 ${tool} 的配置吗?`
281
- : '确定要撤销所有工具的配置吗?',
282
- default: false
283
- }
284
- ]);
285
-
286
- if (confirm) {
287
- await revokeKey(tool);
288
- }
289
- });
290
-
291
- // 帮助信息
292
- program
293
- .command('help')
294
- .description('显示帮助信息')
295
- .action(() => {
296
- console.log(chalk.cyan(`
297
- 🎮 Duojie API 配置助手
298
-
299
- 使用方法:
300
- npx duojie-helper # 交互式配置向导
301
- npx duojie-helper init # 同上
302
- npx duojie-helper config <tool> -k <key> # 配置单个工具
303
- npx duojie-helper status # 查看配置状态
304
- npx duojie-helper list # 列出支持的工具
305
- npx duojie-helper revoke # 撤销配置
306
-
307
- 支持的工具 (自动配置):
308
- • claude - Claude Code (Anthropic 官方 CLI)
309
- • droid - Droid (Factory 的 AI 编程工具)
310
- • openclaw - OpenClaw / Moltbot
311
- • opencode - OpenCode (终端 AI 编码助手)
312
- • continue - Continue (VS Code/JetBrains)
313
- • codex - OpenAI Codex CLI
314
-
315
- 支持的工具 (输出配置信息):
316
- • cursor - Cursor 编辑器 (需手动在 UI 配置)
317
- • cline - Cline VS Code 插件 (需手动在 UI 配置)
318
-
319
- 示例:
320
- npx duojie-helper # 交互式配置
321
- npx duojie-helper config claude -k sk-xxx # 只配置 Claude Code
322
- npx duojie-helper config opencode # 配置 OpenCode
323
-
324
- 获取 API Key: https://api.duojie.games
325
- `));
326
- });
327
-
328
- program.parse();
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+ import inquirer from 'inquirer';
5
+ import chalk from 'chalk';
6
+ import ora from 'ora';
7
+ import { createRequire } from 'module';
8
+ import { configureAll, configureTool, listTools, showStatus, revokeKey, fetchModels, getModels } from '../src/index.js';
9
+
10
+ const require = createRequire(import.meta.url);
11
+ const pkg = require('../package.json');
12
+
13
+ const program = new Command();
14
+
15
+ program
16
+ .name('duojie')
17
+ .description('🎮 Duojie API 一键配置助手 - 支持主流 AI 编程工具')
18
+ .version(pkg.version);
19
+
20
+ // 默认命令 - 交互式配置
21
+ program
22
+ .command('init', { isDefault: true })
23
+ .description('交互式配置向导')
24
+ .action(async () => {
25
+ console.log(chalk.cyan(`
26
+ ╔═══════════════════════════════════════════════════════════╗
27
+ ║ ║
28
+ ║ 🎮 Duojie API 配置助手 ║
29
+ ║ ║
30
+ ║ 一键配置你的 AI 编程工具 ║
31
+ ║ 支持: Claude Code, OpenClaw, Cursor, Cline 等 ║
32
+ ║ ║
33
+ ║ 提示: 按 Ctrl+C 可随时退出 ║
34
+ ║ ║
35
+ ╚═══════════════════════════════════════════════════════════╝
36
+ `));
37
+
38
+ let apiKey = null;
39
+ let tools = null;
40
+ let step = 1;
41
+
42
+ try {
43
+ while (step > 0) {
44
+ if (step === 1) {
45
+ // 步骤 1: 输入 API Key
46
+ const result = await inquirer.prompt([
47
+ {
48
+ type: 'input',
49
+ name: 'apiKey',
50
+ message: '请输入你的 Duojie API Key (Ctrl+C 退出):',
51
+ filter: (input) => input.trim(),
52
+ validate: (input) => {
53
+ if (!input || input.length < 10) {
54
+ return 'API Key 不能为空且长度至少 10 位';
55
+ }
56
+ return true;
57
+ }
58
+ }
59
+ ]);
60
+
61
+ apiKey = result.apiKey.trim();
62
+
63
+ // 验证 API Key 并获取模型列表
64
+ const modelSpinner = ora('正在验证 API Key 并获取模型列表...').start();
65
+ const models = await fetchModels(apiKey);
66
+
67
+ const totalModels = (models.claude?.length || 0) +
68
+ (models.gpt?.length || 0) +
69
+ (models.gemini?.length || 0) +
70
+ (models.other?.length || 0);
71
+
72
+ if (totalModels === 0) {
73
+ modelSpinner.fail('API Key 无效或无法获取模型列表');
74
+ continue; // 重新输入
75
+ }
76
+
77
+ modelSpinner.succeed(`验证成功!可用模型: ${totalModels} 个`);
78
+ step = 2;
79
+ }
80
+
81
+ else if (step === 2) {
82
+ // 步骤 2: 选择要配置的工具
83
+ console.log(chalk.gray('\n 提示: 按 Ctrl+C 返回上一步\n'));
84
+
85
+ try {
86
+ const result = await inquirer.prompt([
87
+ {
88
+ type: 'checkbox',
89
+ name: 'tools',
90
+ message: '选择要配置的工具 (空格选择,回车确认):',
91
+ loop: false,
92
+ choices: [
93
+ { name: '🤖 Claude Code - 自动配置', value: 'claude' },
94
+ { name: '🏭 Droid - 自动配置', value: 'droid' },
95
+ { name: '🦞 OpenClaw / Moltbot - 自动配置', value: 'openclaw' },
96
+ { name: '🖥️ OpenCode - 自动配置', value: 'opencode' },
97
+ { name: '💻 Continue - 自动配置', value: 'continue' },
98
+ { name: '🤖 Codex CLI - 自动配置', value: 'codex' },
99
+ new inquirer.Separator('── 以下需要手动配置 ──'),
100
+ { name: '📝 Cursor - 输出配置信息', value: 'cursor' },
101
+ { name: '🔌 Cline (VS Code) - 输出配置信息', value: 'cline' },
102
+ ],
103
+ validate: (input) => {
104
+ if (input.length === 0) {
105
+ return '请至少选择一个工具 (使用空格键选择)';
106
+ }
107
+ return true;
108
+ }
109
+ }
110
+ ]);
111
+
112
+ tools = result.tools;
113
+ step = 3;
114
+ } catch (err) {
115
+ if (err.message?.includes('User force closed')) {
116
+ step = 1; // 返回上一步
117
+ console.log(chalk.yellow('\n↩ 返回上一步...\n'));
118
+ continue;
119
+ }
120
+ throw err;
121
+ }
122
+ }
123
+
124
+ else if (step === 3) {
125
+ // 步骤 3: 执行配置
126
+ const spinner = ora('正在配置...').start();
127
+
128
+ const results = await configureAll(apiKey, tools);
129
+
130
+ spinner.succeed('配置完成!');
131
+
132
+ // 显示结果
133
+ console.log('\n' + chalk.green('✅ 配置结果:'));
134
+ console.log(chalk.gray('─'.repeat(60)));
135
+
136
+ const autoConfigured = [];
137
+ const manualRequired = [];
138
+
139
+ for (const result of results) {
140
+ if (result.success) {
141
+ if (result.manual) {
142
+ manualRequired.push(result);
143
+ } else {
144
+ autoConfigured.push(result);
145
+ console.log(chalk.green(` ✓ ${result.tool}: ${result.message}`));
146
+ }
147
+ } else {
148
+ console.log(chalk.red(` ✗ ${result.tool}: ${result.message}`));
149
+ }
150
+ }
151
+
152
+ console.log(chalk.gray('─'.repeat(60)));
153
+
154
+ // 显示需要手动配置的工具
155
+ if (manualRequired.length > 0) {
156
+ console.log(chalk.yellow('\n📋 以下工具需要手动配置:\n'));
157
+
158
+ for (const result of manualRequired) {
159
+ console.log(chalk.cyan(`\n━━━ ${result.tool} ━━━`));
160
+ if (result.instructions) {
161
+ console.log(result.instructions);
162
+ }
163
+ }
164
+ }
165
+
166
+ console.log(chalk.cyan('\n🎉 配置完成!\n'));
167
+
168
+ // 显示后续步骤
169
+ if (autoConfigured.length > 0) {
170
+ console.log(chalk.yellow('📋 后续步骤:'));
171
+ if (tools.includes('claude')) {
172
+ console.log(chalk.gray(' • Claude Code: 重新打开终端窗口'));
173
+ }
174
+ if (tools.includes('droid')) {
175
+ console.log(chalk.gray(' • Droid: 重启 Factory'));
176
+ }
177
+ if (tools.includes('openclaw')) {
178
+ console.log(chalk.gray(' • OpenClaw: 运行 openclaw gateway restart'));
179
+ }
180
+ if (tools.includes('opencode')) {
181
+ console.log(chalk.gray(' • OpenCode: 重启 OpenCode'));
182
+ }
183
+ if (tools.includes('continue')) {
184
+ console.log(chalk.gray(' • Continue: 重启 VS Code/JetBrains'));
185
+ }
186
+ if (tools.includes('codex')) {
187
+ console.log(chalk.gray(' • Codex CLI: 已写入 ~/.codex/config.toml(无需设置 DUOJIE_API_KEY)'));
188
+ }
189
+ console.log('');
190
+ }
191
+
192
+ step = 0; // 完成,退出循环
193
+ }
194
+ }
195
+
196
+ } catch (error) {
197
+ if (error.message?.includes('User force closed')) {
198
+ console.log(chalk.yellow('\n\n👋 已退出配置向导\n'));
199
+ process.exit(0);
200
+ }
201
+ console.error(chalk.red('\n❌ 配置失败:'), error.message);
202
+ process.exit(1);
203
+ }
204
+ });
205
+
206
+ // 配置单个工具
207
+ program
208
+ .command('config <tool>')
209
+ .description('配置单个工具 (claude/droid/openclaw/opencode/cursor/cline/codex/continue)')
210
+ .option('-k, --key <apiKey>', 'API Key')
211
+ .action(async (tool, options) => {
212
+ try {
213
+ let apiKey = options.key;
214
+
215
+ if (!apiKey) {
216
+ const answer = await inquirer.prompt([
217
+ {
218
+ type: 'input',
219
+ name: 'apiKey',
220
+ message: '请输入你的 Duojie API Key:',
221
+ filter: (input) => input.trim(),
222
+ }
223
+ ]);
224
+ apiKey = answer.apiKey;
225
+ } else {
226
+ apiKey = apiKey.trim();
227
+ }
228
+
229
+ // 获取模型列表
230
+ const spinner = ora('正在验证 API Key...').start();
231
+ await fetchModels(apiKey);
232
+ spinner.succeed('验证成功');
233
+
234
+ const configSpinner = ora(`正在配置 ${tool}...`).start();
235
+ const result = await configureTool(tool, apiKey);
236
+
237
+ if (result.success) {
238
+ configSpinner.succeed(result.message);
239
+
240
+ // 如果需要手动配置,显示说明
241
+ if (result.manual && result.instructions) {
242
+ console.log(chalk.yellow('\n📋 手动配置说明:\n'));
243
+ console.log(result.instructions);
244
+ }
245
+ } else {
246
+ configSpinner.fail(result.message);
247
+ }
248
+ } catch (error) {
249
+ console.error(chalk.red('配置失败:'), error.message);
250
+ process.exit(1);
251
+ }
252
+ });
253
+
254
+ // 查看状态
255
+ program
256
+ .command('status')
257
+ .description('查看当前配置状态')
258
+ .action(async () => {
259
+ await showStatus();
260
+ });
261
+
262
+ // 列出支持的工具
263
+ program
264
+ .command('list')
265
+ .description('列出支持的工具')
266
+ .action(() => {
267
+ listTools();
268
+ });
269
+
270
+ // 撤销配置
271
+ program
272
+ .command('revoke [tool]')
273
+ .description('撤销配置 (不指定工具则撤销全部)')
274
+ .action(async (tool) => {
275
+ const { confirm } = await inquirer.prompt([
276
+ {
277
+ type: 'confirm',
278
+ name: 'confirm',
279
+ message: tool
280
+ ? `确定要撤销 ${tool} 的配置吗?`
281
+ : '确定要撤销所有工具的配置吗?',
282
+ default: false
283
+ }
284
+ ]);
285
+
286
+ if (confirm) {
287
+ await revokeKey(tool);
288
+ }
289
+ });
290
+
291
+ // 帮助信息
292
+ program
293
+ .command('help')
294
+ .description('显示帮助信息')
295
+ .action(() => {
296
+ console.log(chalk.cyan(`
297
+ 🎮 Duojie API 配置助手
298
+
299
+ 使用方法:
300
+ npx duojie-helper # 交互式配置向导
301
+ npx duojie-helper init # 同上
302
+ npx duojie-helper config <tool> -k <key> # 配置单个工具
303
+ npx duojie-helper status # 查看配置状态
304
+ npx duojie-helper list # 列出支持的工具
305
+ npx duojie-helper revoke # 撤销配置
306
+
307
+ 支持的工具 (自动配置):
308
+ • claude - Claude Code (Anthropic 官方 CLI)
309
+ • droid - Droid (Factory 的 AI 编程工具)
310
+ • openclaw - OpenClaw / Moltbot
311
+ • opencode - OpenCode (终端 AI 编码助手)
312
+ • continue - Continue (VS Code/JetBrains)
313
+ • codex - OpenAI Codex CLI
314
+
315
+ 支持的工具 (输出配置信息):
316
+ • cursor - Cursor 编辑器 (需手动在 UI 配置)
317
+ • cline - Cline VS Code 插件 (需手动在 UI 配置)
318
+
319
+ 示例:
320
+ npx duojie-helper # 交互式配置
321
+ npx duojie-helper config claude -k sk-xxx # 只配置 Claude Code
322
+ npx duojie-helper config opencode # 配置 OpenCode
323
+
324
+ 获取 API Key: https://api.duojie.games
325
+ `));
326
+ });
327
+
328
+ program.parse();