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.
- package/README.md +160 -160
- package/bin/cli.js +328 -328
- package/package.json +53 -53
- package/src/index.js +323 -323
- package/src/tools/claude.js +198 -198
- package/src/tools/cline.js +103 -103
- package/src/tools/codex.js +154 -154
- package/src/tools/continue.js +158 -158
- package/src/tools/cursor.js +99 -99
- package/src/tools/droid.js +262 -261
- package/src/tools/openclaw.js +292 -292
- package/src/tools/opencode.js +216 -216
package/src/tools/claude.js
CHANGED
|
@@ -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;
|
package/src/tools/cline.js
CHANGED
|
@@ -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;
|