duojie-helper 0.2.21 → 0.2.22

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.
@@ -1,198 +1,198 @@
1
- import fs from 'fs-extra';
2
- import path from 'path';
3
- import os from 'os';
4
- import { API_CONFIG, getModels } from '../index.js';
5
-
6
- /**
7
- * 获取 Claude Code 配置路径
8
- */
9
- function getClaudeConfigPaths() {
10
- const home = os.homedir();
11
- return {
12
- // Claude Code 配置目录
13
- configDir: path.join(home, '.claude'),
14
- // 主配置文件 (环境变量)
15
- settingsFile: path.join(home, '.claude', 'settings.json'),
16
- // 登录状态文件
17
- claudeJson: path.join(home, '.claude.json'),
18
- };
19
- }
20
-
21
- /**
22
- * 配置 Claude Code
23
- * 使用官方推荐的 settings.json env 方式配置
24
- */
25
- export async function configureClaudeCode(apiKey) {
26
- const paths = getClaudeConfigPaths();
27
-
28
- try {
29
- // 确保目录存在
30
- await fs.ensureDir(paths.configDir);
31
-
32
- // 1. 读取现有 settings.json(如果存在)
33
- let settings = {};
34
- if (await fs.pathExists(paths.settingsFile)) {
35
- try {
36
- const content = await fs.readFile(paths.settingsFile, 'utf-8');
37
- settings = JSON.parse(content);
38
- } catch {
39
- settings = {};
40
- }
41
- }
42
-
43
- // 2. 清理旧的 Duojie 配置(如果有)
44
- // 保留用户其他配置,只更新 env 中的 Duojie 相关项
45
- if (!settings.env) {
46
- settings.env = {};
47
- }
48
-
49
- // 3. 获取可用的 Claude 模型
50
- const models = getModels();
51
- const claudeModels = models.claude || [];
52
-
53
- // 查找各类型模型(优先查找最新 kiro 版本)
54
- let sonnetModel = null;
55
- let opusModel = null;
56
-
57
- // 优先级:opus-4-6-kiro > opus-4-6 > opus+kiro > opus > 第一个opus
58
- const opusKiro46 = claudeModels.find(m => m.id.includes('opus-4-6') && m.id.includes('kiro'));
59
- const opus46 = claudeModels.find(m => m.id.includes('opus-4-6'));
60
- const opusKiro = claudeModels.find(m => m.id.includes('opus') && m.id.includes('kiro'));
61
- const opusAny = claudeModels.find(m => m.id.includes('opus'));
62
- opusModel = opusKiro46?.id || opus46?.id || opusKiro?.id || opusAny?.id || null;
63
-
64
- // sonnet 模型
65
- sonnetModel = claudeModels.find(m => m.id.includes('sonnet'))?.id || null;
66
-
67
- // 4. 设置 Duojie API 环境变量
68
- settings.env.ANTHROPIC_API_KEY = apiKey;
69
- settings.env.ANTHROPIC_BASE_URL = API_CONFIG.baseUrl;
70
- settings.env.API_TIMEOUT_MS = "300000";
71
- settings.env.ANTHROPIC_MAX_TOKENS = "16384";
72
-
73
- // 配置各类型模型(不配置 haiku/fast 模型)
74
- if (sonnetModel) {
75
- settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL = sonnetModel;
76
- }
77
- if (opusModel) {
78
- settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL = opusModel;
79
- }
80
-
81
- // 优先将默认主模型设为 gpt-5.2(如存在),否则回退到 opus/sonnet/首个 claude
82
- const gpt52 = (models.gpt || []).find(m => m.id === 'gpt-5.2')?.id || null;
83
- const defaultModel = gpt52 || opusModel || sonnetModel || claudeModels[0]?.id;
84
- if (defaultModel) {
85
- settings.model = defaultModel;
86
- }
87
-
88
- // 标记为 Duojie 配置
89
- settings._duojie = {
90
- configured: true,
91
- configuredAt: new Date().toISOString(),
92
- models: {
93
- default: defaultModel,
94
- sonnet: sonnetModel,
95
- opus: opusModel,
96
- },
97
- };
98
-
99
- // 5. 写入 settings.json
100
- await fs.writeJson(paths.settingsFile, settings, { spaces: 2 });
101
-
102
- // 6. 创建/更新 .claude.json(跳过登录流程)
103
- let claudeJson = {};
104
- if (await fs.pathExists(paths.claudeJson)) {
105
- try {
106
- claudeJson = await fs.readJson(paths.claudeJson);
107
- } catch {
108
- claudeJson = {};
109
- }
110
- }
111
-
112
- claudeJson.hasCompletedOnboarding = true;
113
- await fs.writeJson(paths.claudeJson, claudeJson, { spaces: 2 });
114
-
115
- // 统计配置的模型数量
116
- const configuredModels = [sonnetModel, opusModel].filter(Boolean).length;
117
-
118
- return {
119
- success: true,
120
- message: `已配置 ${configuredModels} 个模型 → ${paths.settingsFile}`,
121
- configPath: paths.settingsFile,
122
- };
123
- } catch (error) {
124
- return {
125
- success: false,
126
- message: `配置失败: ${error.message}`,
127
- };
128
- }
129
- }
130
-
131
- /**
132
- * 检查 Claude Code 配置状态
133
- */
134
- configureClaudeCode.checkStatus = async function() {
135
- const paths = getClaudeConfigPaths();
136
-
137
- if (await fs.pathExists(paths.settingsFile)) {
138
- try {
139
- const settings = await fs.readJson(paths.settingsFile);
140
-
141
- // 检查是否有 Duojie 配置
142
- if (settings._duojie?.configured ||
143
- settings.env?.ANTHROPIC_BASE_URL?.includes('duojie')) {
144
- return {
145
- configured: true,
146
- message: '已配置 Duojie API',
147
- };
148
- } else if (settings.env?.ANTHROPIC_API_KEY || settings.env?.ANTHROPIC_AUTH_TOKEN) {
149
- return {
150
- configured: true,
151
- message: '已配置(非 Duojie)',
152
- };
153
- }
154
- } catch {
155
- // ignore
156
- }
157
- }
158
-
159
- return { configured: false };
160
- };
161
-
162
- /**
163
- * 撤销 Claude Code 配置
164
- */
165
- configureClaudeCode.revoke = async function() {
166
- const paths = getClaudeConfigPaths();
167
-
168
- if (await fs.pathExists(paths.settingsFile)) {
169
- try {
170
- const settings = await fs.readJson(paths.settingsFile);
171
-
172
- // 只删除 Duojie 相关的环境变量
173
- if (settings.env) {
174
- delete settings.env.ANTHROPIC_API_KEY;
175
- delete settings.env.ANTHROPIC_AUTH_TOKEN;
176
- delete settings.env.ANTHROPIC_BASE_URL;
177
- delete settings.env.API_TIMEOUT_MS;
178
- delete settings.env.ANTHROPIC_MAX_TOKENS;
179
- delete settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL;
180
- delete settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL;
181
-
182
- // 如果 env 为空,删除整个 env
183
- if (Object.keys(settings.env).length === 0) {
184
- delete settings.env;
185
- }
186
- }
187
-
188
- delete settings.model;
189
- delete settings._duojie;
190
-
191
- await fs.writeJson(paths.settingsFile, settings, { spaces: 2 });
192
- } catch {
193
- // ignore
194
- }
195
- }
196
- };
197
-
198
- export default configureClaudeCode;
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ import { API_CONFIG, getModels } from '../index.js';
5
+
6
+ /**
7
+ * 获取 Claude Code 配置路径
8
+ */
9
+ function getClaudeConfigPaths() {
10
+ const home = os.homedir();
11
+ return {
12
+ // Claude Code 配置目录
13
+ configDir: path.join(home, '.claude'),
14
+ // 主配置文件 (环境变量)
15
+ settingsFile: path.join(home, '.claude', 'settings.json'),
16
+ // 登录状态文件
17
+ claudeJson: path.join(home, '.claude.json'),
18
+ };
19
+ }
20
+
21
+ /**
22
+ * 配置 Claude Code
23
+ * 使用官方推荐的 settings.json env 方式配置
24
+ */
25
+ export async function configureClaudeCode(apiKey) {
26
+ const paths = getClaudeConfigPaths();
27
+
28
+ try {
29
+ // 确保目录存在
30
+ await fs.ensureDir(paths.configDir);
31
+
32
+ // 1. 读取现有 settings.json(如果存在)
33
+ let settings = {};
34
+ if (await fs.pathExists(paths.settingsFile)) {
35
+ try {
36
+ const content = await fs.readFile(paths.settingsFile, 'utf-8');
37
+ settings = JSON.parse(content);
38
+ } catch {
39
+ settings = {};
40
+ }
41
+ }
42
+
43
+ // 2. 清理旧的 Duojie 配置(如果有)
44
+ // 保留用户其他配置,只更新 env 中的 Duojie 相关项
45
+ if (!settings.env) {
46
+ settings.env = {};
47
+ }
48
+
49
+ // 3. 获取可用的 Claude 模型
50
+ const models = getModels();
51
+ const claudeModels = models.claude || [];
52
+
53
+ // 查找各类型模型(优先查找最新 kiro 版本)
54
+ let sonnetModel = null;
55
+ let opusModel = null;
56
+
57
+ // 优先级:opus-4-6-kiro > opus-4-6 > opus+kiro > opus > 第一个opus
58
+ const opusKiro46 = claudeModels.find(m => m.id.includes('opus-4-6') && m.id.includes('kiro'));
59
+ const opus46 = claudeModels.find(m => m.id.includes('opus-4-6'));
60
+ const opusKiro = claudeModels.find(m => m.id.includes('opus') && m.id.includes('kiro'));
61
+ const opusAny = claudeModels.find(m => m.id.includes('opus'));
62
+ opusModel = opusKiro46?.id || opus46?.id || opusKiro?.id || opusAny?.id || null;
63
+
64
+ // sonnet 模型
65
+ sonnetModel = claudeModels.find(m => m.id.includes('sonnet'))?.id || null;
66
+
67
+ // 4. 设置 Duojie API 环境变量
68
+ settings.env.ANTHROPIC_API_KEY = apiKey;
69
+ settings.env.ANTHROPIC_BASE_URL = API_CONFIG.baseUrl;
70
+ settings.env.API_TIMEOUT_MS = "300000";
71
+ settings.env.ANTHROPIC_MAX_TOKENS = "16384";
72
+
73
+ // 配置各类型模型(不配置 haiku/fast 模型)
74
+ if (sonnetModel) {
75
+ settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL = sonnetModel;
76
+ }
77
+ if (opusModel) {
78
+ settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL = opusModel;
79
+ }
80
+
81
+ // 优先将默认主模型设为 gpt-5.2(如存在),否则回退到 opus/sonnet/首个 claude
82
+ const gpt52 = (models.gpt || []).find(m => m.id === 'gpt-5.2')?.id || null;
83
+ const defaultModel = gpt52 || opusModel || sonnetModel || claudeModels[0]?.id;
84
+ if (defaultModel) {
85
+ settings.model = defaultModel;
86
+ }
87
+
88
+ // 标记为 Duojie 配置
89
+ settings._duojie = {
90
+ configured: true,
91
+ configuredAt: new Date().toISOString(),
92
+ models: {
93
+ default: defaultModel,
94
+ sonnet: sonnetModel,
95
+ opus: opusModel,
96
+ },
97
+ };
98
+
99
+ // 5. 写入 settings.json
100
+ await fs.writeJson(paths.settingsFile, settings, { spaces: 2 });
101
+
102
+ // 6. 创建/更新 .claude.json(跳过登录流程)
103
+ let claudeJson = {};
104
+ if (await fs.pathExists(paths.claudeJson)) {
105
+ try {
106
+ claudeJson = await fs.readJson(paths.claudeJson);
107
+ } catch {
108
+ claudeJson = {};
109
+ }
110
+ }
111
+
112
+ claudeJson.hasCompletedOnboarding = true;
113
+ await fs.writeJson(paths.claudeJson, claudeJson, { spaces: 2 });
114
+
115
+ // 统计配置的模型数量
116
+ const configuredModels = [sonnetModel, opusModel].filter(Boolean).length;
117
+
118
+ return {
119
+ success: true,
120
+ message: `已配置 ${configuredModels} 个模型 → ${paths.settingsFile}`,
121
+ configPath: paths.settingsFile,
122
+ };
123
+ } catch (error) {
124
+ return {
125
+ success: false,
126
+ message: `配置失败: ${error.message}`,
127
+ };
128
+ }
129
+ }
130
+
131
+ /**
132
+ * 检查 Claude Code 配置状态
133
+ */
134
+ configureClaudeCode.checkStatus = async function() {
135
+ const paths = getClaudeConfigPaths();
136
+
137
+ if (await fs.pathExists(paths.settingsFile)) {
138
+ try {
139
+ const settings = await fs.readJson(paths.settingsFile);
140
+
141
+ // 检查是否有 Duojie 配置
142
+ if (settings._duojie?.configured ||
143
+ settings.env?.ANTHROPIC_BASE_URL?.includes('duojie')) {
144
+ return {
145
+ configured: true,
146
+ message: '已配置 Duojie API',
147
+ };
148
+ } else if (settings.env?.ANTHROPIC_API_KEY || settings.env?.ANTHROPIC_AUTH_TOKEN) {
149
+ return {
150
+ configured: true,
151
+ message: '已配置(非 Duojie)',
152
+ };
153
+ }
154
+ } catch {
155
+ // ignore
156
+ }
157
+ }
158
+
159
+ return { configured: false };
160
+ };
161
+
162
+ /**
163
+ * 撤销 Claude Code 配置
164
+ */
165
+ configureClaudeCode.revoke = async function() {
166
+ const paths = getClaudeConfigPaths();
167
+
168
+ if (await fs.pathExists(paths.settingsFile)) {
169
+ try {
170
+ const settings = await fs.readJson(paths.settingsFile);
171
+
172
+ // 只删除 Duojie 相关的环境变量
173
+ if (settings.env) {
174
+ delete settings.env.ANTHROPIC_API_KEY;
175
+ delete settings.env.ANTHROPIC_AUTH_TOKEN;
176
+ delete settings.env.ANTHROPIC_BASE_URL;
177
+ delete settings.env.API_TIMEOUT_MS;
178
+ delete settings.env.ANTHROPIC_MAX_TOKENS;
179
+ delete settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL;
180
+ delete settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL;
181
+
182
+ // 如果 env 为空,删除整个 env
183
+ if (Object.keys(settings.env).length === 0) {
184
+ delete settings.env;
185
+ }
186
+ }
187
+
188
+ delete settings.model;
189
+ delete settings._duojie;
190
+
191
+ await fs.writeJson(paths.settingsFile, settings, { spaces: 2 });
192
+ } catch {
193
+ // ignore
194
+ }
195
+ }
196
+ };
197
+
198
+ export default configureClaudeCode;
@@ -1,103 +1,103 @@
1
- import fs from 'fs-extra';
2
- import path from 'path';
3
- import os from 'os';
4
- import chalk from 'chalk';
5
- import { API_CONFIG } from '../index.js';
6
-
7
- /**
8
- * 获取 Cline 配置路径 (VS Code 插件)
9
- */
10
- function getClineConfigPaths() {
11
- const home = os.homedir();
12
- const platform = os.platform();
13
-
14
- let vscodeDir;
15
- if (platform === 'win32') {
16
- vscodeDir = path.join(process.env.APPDATA || home, 'Code', 'User');
17
- } else if (platform === 'darwin') {
18
- vscodeDir = path.join(home, 'Library', 'Application Support', 'Code', 'User');
19
- } else {
20
- vscodeDir = path.join(home, '.config', 'Code', 'User');
21
- }
22
-
23
- return {
24
- configDir: vscodeDir,
25
- settingsFile: path.join(vscodeDir, 'settings.json'),
26
- // Cline 全局存储
27
- globalStorageDir: path.join(vscodeDir, 'globalStorage', 'saoudrizwan.claude-dev'),
28
- };
29
- }
30
-
31
- /**
32
- * 配置 Cline
33
- * Cline 需要通过 UI 手动配置,这里输出配置信息
34
- */
35
- export async function configureCline(apiKey) {
36
- const baseUrl = API_CONFIG.baseUrl;
37
-
38
- // 生成配置说明
39
- const instructions = `
40
- ${chalk.yellow('Cline 需要在 VS Code 中手动配置:')}
41
-
42
- ${chalk.cyan('步骤 1:')} 打开 VS Code,点击左侧 Cline 图标
43
- ${chalk.cyan('步骤 2:')} 点击设置图标 (⚙️)
44
- ${chalk.cyan('步骤 3:')} 选择 "Use your own API Key"
45
- ${chalk.cyan('步骤 4:')} 填入以下配置:
46
-
47
- ${chalk.green('API Provider:')} OpenAI Compatible
48
- ${chalk.green('Base URL:')} ${baseUrl}
49
- ${chalk.green('API Key:')} ${apiKey}
50
- ${chalk.green('Model:')} 选择 "Enter model ID" 并输入模型名称
51
- 例如: gpt-5.2 或 claude-sonnet-4-6
52
-
53
- ${chalk.cyan('步骤 5:')} 可选配置:
54
- • ${chalk.green('Max Tokens:')} 16384 (推荐)
55
- • Context Window Size: 200000
56
- • 取消勾选 "Support Images"(如果模型不支持)
57
-
58
- ${chalk.gray('提示: 配置完成后即可在 Cline 中使用 Duojie API')}
59
- `;
60
-
61
- return {
62
- success: true,
63
- manual: true,
64
- message: '需要手动配置',
65
- instructions: instructions,
66
- configInfo: {
67
- provider: 'OpenAI Compatible',
68
- baseUrl: baseUrl,
69
- apiKey: apiKey,
70
- }
71
- };
72
- }
73
-
74
- /**
75
- * 检查 Cline 配置状态
76
- */
77
- configureCline.checkStatus = async function() {
78
- const paths = getClineConfigPaths();
79
-
80
- // Cline 配置存储在插件的 globalStorage 中,不在 settings.json
81
- // 这里只能检测插件是否安装
82
- if (await fs.pathExists(paths.globalStorageDir)) {
83
- return {
84
- configured: true,
85
- message: 'Cline 插件已安装(配置状态需在 VS Code 中查看)',
86
- };
87
- }
88
-
89
- return {
90
- configured: false,
91
- message: 'Cline 插件未安装或未使用过',
92
- };
93
- };
94
-
95
- /**
96
- * 撤销 Cline 配置
97
- */
98
- configureCline.revoke = async function() {
99
- // Cline 配置在插件内部,无法通过文件操作撤销
100
- console.log(chalk.yellow('Cline 配置需要在 VS Code 的 Cline 插件设置中手动清除'));
101
- };
102
-
103
- export default configureCline;
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ import chalk from 'chalk';
5
+ import { API_CONFIG } from '../index.js';
6
+
7
+ /**
8
+ * 获取 Cline 配置路径 (VS Code 插件)
9
+ */
10
+ function getClineConfigPaths() {
11
+ const home = os.homedir();
12
+ const platform = os.platform();
13
+
14
+ let vscodeDir;
15
+ if (platform === 'win32') {
16
+ vscodeDir = path.join(process.env.APPDATA || home, 'Code', 'User');
17
+ } else if (platform === 'darwin') {
18
+ vscodeDir = path.join(home, 'Library', 'Application Support', 'Code', 'User');
19
+ } else {
20
+ vscodeDir = path.join(home, '.config', 'Code', 'User');
21
+ }
22
+
23
+ return {
24
+ configDir: vscodeDir,
25
+ settingsFile: path.join(vscodeDir, 'settings.json'),
26
+ // Cline 全局存储
27
+ globalStorageDir: path.join(vscodeDir, 'globalStorage', 'saoudrizwan.claude-dev'),
28
+ };
29
+ }
30
+
31
+ /**
32
+ * 配置 Cline
33
+ * Cline 需要通过 UI 手动配置,这里输出配置信息
34
+ */
35
+ export async function configureCline(apiKey) {
36
+ const baseUrl = API_CONFIG.baseUrl;
37
+
38
+ // 生成配置说明
39
+ const instructions = `
40
+ ${chalk.yellow('Cline 需要在 VS Code 中手动配置:')}
41
+
42
+ ${chalk.cyan('步骤 1:')} 打开 VS Code,点击左侧 Cline 图标
43
+ ${chalk.cyan('步骤 2:')} 点击设置图标 (⚙️)
44
+ ${chalk.cyan('步骤 3:')} 选择 "Use your own API Key"
45
+ ${chalk.cyan('步骤 4:')} 填入以下配置:
46
+
47
+ ${chalk.green('API Provider:')} OpenAI Compatible
48
+ ${chalk.green('Base URL:')} ${baseUrl}
49
+ ${chalk.green('API Key:')} ${apiKey}
50
+ ${chalk.green('Model:')} 选择 "Enter model ID" 并输入模型名称
51
+ 例如: gpt-5.2 或 claude-sonnet-4-6
52
+
53
+ ${chalk.cyan('步骤 5:')} 可选配置:
54
+ • ${chalk.green('Max Tokens:')} 16384 (推荐)
55
+ • Context Window Size: 200000
56
+ • 取消勾选 "Support Images"(如果模型不支持)
57
+
58
+ ${chalk.gray('提示: 配置完成后即可在 Cline 中使用 Duojie API')}
59
+ `;
60
+
61
+ return {
62
+ success: true,
63
+ manual: true,
64
+ message: '需要手动配置',
65
+ instructions: instructions,
66
+ configInfo: {
67
+ provider: 'OpenAI Compatible',
68
+ baseUrl: baseUrl,
69
+ apiKey: apiKey,
70
+ }
71
+ };
72
+ }
73
+
74
+ /**
75
+ * 检查 Cline 配置状态
76
+ */
77
+ configureCline.checkStatus = async function() {
78
+ const paths = getClineConfigPaths();
79
+
80
+ // Cline 配置存储在插件的 globalStorage 中,不在 settings.json
81
+ // 这里只能检测插件是否安装
82
+ if (await fs.pathExists(paths.globalStorageDir)) {
83
+ return {
84
+ configured: true,
85
+ message: 'Cline 插件已安装(配置状态需在 VS Code 中查看)',
86
+ };
87
+ }
88
+
89
+ return {
90
+ configured: false,
91
+ message: 'Cline 插件未安装或未使用过',
92
+ };
93
+ };
94
+
95
+ /**
96
+ * 撤销 Cline 配置
97
+ */
98
+ configureCline.revoke = async function() {
99
+ // Cline 配置在插件内部,无法通过文件操作撤销
100
+ console.log(chalk.yellow('Cline 配置需要在 VS Code 的 Cline 插件设置中手动清除'));
101
+ };
102
+
103
+ export default configureCline;