Skip to content

Commit e2b3be7

Browse files
committed
完善claude,codex的vscode自动配置(windows,linux,mac)
1 parent d808598 commit e2b3be7

File tree

4 files changed

+137
-28
lines changed

4 files changed

+137
-28
lines changed

src-tauri/src/commands.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,12 @@ pub async fn get_current_codex_auth() -> Result<Option<codex_config::CodexAuth>,
8585
/// 配置 VSCode Claude 扩展
8686
#[tauri::command]
8787
pub async fn configure_vscode_claude(base_url: String, api_key: String) -> Result<String, String> {
88-
if api_key.trim().is_empty() {
89-
return Err("API 密钥不能为空".to_string());
90-
}
88+
// 如果 api_key 为空,使用默认值 "key"
89+
let api_key = if api_key.trim().is_empty() {
90+
"key".to_string()
91+
} else {
92+
api_key.trim().to_string()
93+
};
9194

9295
// VSCode Claude 扩展只需要 API Key,base_url 不做检查
9396
vscode::configure_vscode_claude(api_key, base_url)

src-tauri/src/vscode.rs

Lines changed: 112 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,80 @@ use serde_json::{json, Value};
33
use std::fs;
44
use crate::config::{get_claude_config_dir, get_claude_settings_path, write_json_file};
55

6+
/// 移除 JSON/JSONC 中的注释(简单实现)
7+
/// 处理单行注释 // 和多行注释 /* */
8+
fn strip_json_comments(content: &str) -> String {
9+
let mut result = String::new();
10+
let mut chars = content.chars().peekable();
11+
let mut in_string = false;
12+
let mut escape_next = false;
13+
14+
while let Some(ch) = chars.next() {
15+
if escape_next {
16+
result.push(ch);
17+
escape_next = false;
18+
continue;
19+
}
20+
21+
if ch == '\\' && in_string {
22+
result.push(ch);
23+
escape_next = true;
24+
continue;
25+
}
26+
27+
if ch == '"' {
28+
in_string = !in_string;
29+
result.push(ch);
30+
continue;
31+
}
32+
33+
if in_string {
34+
result.push(ch);
35+
continue;
36+
}
37+
38+
// 处理注释(仅在非字符串中)
39+
if ch == '/' {
40+
if let Some(&next_ch) = chars.peek() {
41+
if next_ch == '/' {
42+
// 单行注释,跳到行尾
43+
chars.next(); // 消费第二个 /
44+
for c in chars.by_ref() {
45+
if c == '\n' {
46+
result.push('\n');
47+
break;
48+
}
49+
}
50+
continue;
51+
} else if next_ch == '*' {
52+
// 多行注释,跳到 */
53+
chars.next(); // 消费 *
54+
let mut found_end = false;
55+
while let Some(c) = chars.next() {
56+
if c == '*' {
57+
if let Some(&n) = chars.peek() {
58+
if n == '/' {
59+
chars.next(); // 消费 /
60+
found_end = true;
61+
break;
62+
}
63+
}
64+
}
65+
}
66+
if found_end {
67+
result.push(' '); // 用空格替代注释
68+
}
69+
continue;
70+
}
71+
}
72+
}
73+
74+
result.push(ch);
75+
}
76+
77+
result
78+
}
79+
680
/// 枚举可能的 VS Code 发行版配置目录名称
781
fn vscode_product_dirs() -> Vec<&'static str> {
882
vec![
@@ -97,14 +171,46 @@ pub fn configure_vscode_claude(api_key: String, _base_url: String) -> Result<Str
97171
/// 配置 VSCode Codex 扩展(配置 ChatGPT 扩展)
98172
/// 功能:在 VSCode settings.json 中写入 ChatGPT 扩展配置
99173
pub fn configure_vscode_codex(base_url: String, api_key: String) -> Result<String, String> {
100-
let settings_path = find_existing_settings()
101-
.ok_or_else(|| "未找到 VSCode settings.json 文件。请确保已安装 VSCode 并至少打开过一次。".to_string())?;
174+
// 查找或创建 settings.json 路径
175+
let settings_path = if let Some(path) = find_existing_settings() {
176+
path
177+
} else {
178+
// 如果找不到现有配置,使用第一个候选路径(通常是 Code Stable)
179+
let candidates = candidate_settings_paths();
180+
if candidates.is_empty() {
181+
return Err("无法确定 VSCode 配置目录路径。".to_string());
182+
}
183+
let path = candidates[0].clone();
102184

103-
// 读取现有设置(支持 JSONC 格式的简单处理)
104-
let content = fs::read_to_string(&settings_path)
105-
.map_err(|e| format!("读取 VSCode 设置失败: {}", e))?;
185+
// 确保父目录存在
186+
if let Some(parent) = path.parent() {
187+
fs::create_dir_all(parent)
188+
.map_err(|e| format!("创建 VSCode 配置目录失败: {}", e))?;
189+
}
106190

107-
let mut settings: Value = serde_json::from_str(&content).unwrap_or(json!({}));
191+
log::info!("VSCode settings.json 不存在,将创建新文件: {:?}", path);
192+
path
193+
};
194+
195+
// 读取现有设置(如果文件存在),否则使用空对象
196+
let mut settings: Value = if settings_path.exists() {
197+
let content = fs::read_to_string(&settings_path)
198+
.map_err(|e| format!("读取 VSCode 设置失败: {}", e))?;
199+
200+
// 移除注释后再解析(处理 JSONC 格式)
201+
let cleaned_content = strip_json_comments(&content);
202+
203+
match serde_json::from_str(&cleaned_content) {
204+
Ok(v) => v,
205+
Err(e) => {
206+
log::warn!("解析 VSCode settings.json 失败,将使用空配置: {}", e);
207+
log::warn!("原始内容长度: {}, 清理后长度: {}", content.len(), cleaned_content.len());
208+
json!({})
209+
}
210+
}
211+
} else {
212+
json!({})
213+
};
108214

109215
// 更新 ChatGPT 扩展配置
110216
if let Some(obj) = settings.as_object_mut() {

src/components/ClaudeConfigPanel.vue

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@
9595
</label>
9696
<input
9797
v-model="vscodeConfig.apiKey"
98-
type="password"
98+
type="text"
9999
class="w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition-all duration-200"
100-
placeholder="输入您的 API 密钥"
100+
placeholder="key(可随意填写,默认即可)"
101101
/>
102102
</div>
103103

@@ -124,6 +124,10 @@
124124
<span class="text-blue-500 mt-0.5">•</span>
125125
<span>写入内容:<code class="bg-blue-100 px-1.5 py-0.5 rounded font-mono">{"primaryApiKey": "您的密钥"}</code></span>
126126
</li>
127+
<li class="flex items-start gap-2">
128+
<span class="text-blue-500 mt-0.5">•</span>
129+
<span><strong>API 密钥可随意编写</strong>(例如默认的 "key",仅限vscode配置,客户端配置的密钥必须是真实密钥),如果出错,可以尝试输入您的真实密钥</span>
130+
</li>
127131
<li class="flex items-start gap-2">
128132
<span class="text-blue-500 mt-0.5">•</span>
129133
<span>配置后需要重新加载 VSCode 窗口(Ctrl+Shift+P → Reload Window)</span>
@@ -173,7 +177,7 @@ const clientConfig = ref({
173177
});
174178
175179
const vscodeConfig = ref({
176-
apiKey: ''
180+
apiKey: 'key'
177181
});
178182
179183
const isLoading = ref({
@@ -210,21 +214,19 @@ const handleClientConfigure = async () => {
210214
};
211215
212216
const handleVSCodeConfigure = async () => {
213-
if (!vscodeConfig.value.apiKey.trim()) {
214-
emit('error', '请输入 API 密钥');
215-
return;
216-
}
217+
// 如果 apiKey 为空,使用默认值 'key'
218+
const apiKey = vscodeConfig.value.apiKey.trim() || 'key';
217219
218220
isLoading.value.vscode = true;
219221
220222
try {
221223
const result = await invoke('configure_vscode_claude', {
222224
baseUrl: '', // baseUrl 在后端不使用,传空字符串
223-
apiKey: vscodeConfig.value.apiKey.trim(),
225+
apiKey: apiKey,
224226
});
225227
226228
emit('success', result);
227-
vscodeConfig.value.apiKey = '';
229+
vscodeConfig.value.apiKey = 'key';
228230
} catch (error) {
229231
emit('error', error);
230232
} finally {

src/components/CodexConfigPanel.vue

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,16 @@
131131
<div class="mb-8">
132132
<label class="block text-sm font-semibold text-gray-700 mb-3">
133133
API 密钥
134+
<span class="text-xs font-normal text-gray-500 ml-2">(保持默认值即可,实际密钥从环境变量 key88 读取)</span>
134135
</label>
135136
<input
136137
v-model="vscodeConfig.apiKey"
137-
type="password"
138-
class="w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:ring-2 focus:ring-green-500 focus:border-transparent outline-none transition-all duration-200"
139-
placeholder="输入您的 API 密钥"
138+
type="text"
139+
readonly
140+
class="w-full px-4 py-3 border-2 border-gray-200 rounded-xl bg-gray-50 cursor-not-allowed outline-none"
141+
placeholder="apikey"
140142
/>
143+
<p class="text-xs text-gray-500 mt-2">💡 此字段无需修改,API 认证通过环境变量 key88 完成</p>
141144
</div>
142145

143146
<button
@@ -217,7 +220,7 @@ const clientConfig = ref({
217220
218221
const vscodeConfig = ref({
219222
baseUrl: 'https://88code.org/openai/v1',
220-
apiKey: ''
223+
apiKey: 'apikey'
221224
});
222225
223226
const isLoading = ref({
@@ -254,11 +257,6 @@ const handleClientConfigure = async () => {
254257
};
255258
256259
const handleVSCodeConfigure = async () => {
257-
if (!vscodeConfig.value.apiKey.trim()) {
258-
emit('error', '请输入 API 密钥');
259-
return;
260-
}
261-
262260
if (!vscodeConfig.value.baseUrl.trim()) {
263261
emit('error', '请输入 Base URL');
264262
return;
@@ -273,7 +271,7 @@ const handleVSCodeConfigure = async () => {
273271
});
274272
275273
emit('success', result);
276-
vscodeConfig.value.apiKey = '';
274+
// apiKey 保持默认值不清空
277275
} catch (error) {
278276
emit('error', error);
279277
} finally {

0 commit comments

Comments
 (0)