yingclaw 2.5.20 → 2.5.25

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/lib/vscode.js ADDED
@@ -0,0 +1,256 @@
1
+ const fs = require('fs');
2
+ const os = require('os');
3
+ const path = require('path');
4
+ const { buildClaudeEnv, resolveFastModel, PROVIDERS, CLEAR_CLAUDE_ENV_KEYS } = require('./config');
5
+ const { isDesktopChatModel } = require('./gateway');
6
+
7
+ const CLAUDE_CODE_SETTINGS_SCHEMA = 'https://json.schemastore.org/claude-code-settings.json';
8
+ const VSCODE_CLAUDE_OPEN_URI = 'vscode://anthropic.claude-code/open';
9
+ const VSCODE_MODEL_SETTINGS_KEYS = ['model', 'availableModels'];
10
+
11
+ function readJsonFile(file) {
12
+ try {
13
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
14
+ } catch {
15
+ return {};
16
+ }
17
+ }
18
+
19
+ function writeJsonFile(file, value) {
20
+ fs.mkdirSync(path.dirname(file), { recursive: true });
21
+ fs.writeFileSync(file, JSON.stringify(value, null, 2) + '\n');
22
+ }
23
+
24
+ function getClaudeCodeSettingsPath(options = {}) {
25
+ const homeDir = options.homeDir || os.homedir();
26
+ return options.settingsFile || path.join(homeDir, '.claude', 'settings.json');
27
+ }
28
+
29
+ function getVsCodeUserSettingsPath(options = {}) {
30
+ if (options.vsCodeSettingsFile) return options.vsCodeSettingsFile;
31
+
32
+ const platform = options.platform || process.platform;
33
+ const homeDir = options.homeDir || os.homedir();
34
+
35
+ if (platform === 'darwin') {
36
+ return path.join(homeDir, 'Library', 'Application Support', 'Code', 'User', 'settings.json');
37
+ }
38
+ if (platform === 'win32') {
39
+ const appData = options.appData || process.env.APPDATA || path.join(homeDir, 'AppData', 'Roaming');
40
+ return path.win32.join(appData, 'Code', 'User', 'settings.json');
41
+ }
42
+ return path.join(homeDir, '.config', 'Code', 'User', 'settings.json');
43
+ }
44
+
45
+ function buildClaudeCodeSettingsPatch(config) {
46
+ const env = buildVsCodeClaudeEnv(config);
47
+ const availableModels = buildVsCodeAvailableModels(config);
48
+ const model = config.vscodeModel || config.model;
49
+ return {
50
+ $schema: CLAUDE_CODE_SETTINGS_SCHEMA,
51
+ model: availableModels.includes(model) ? model : availableModels[0],
52
+ availableModels,
53
+ env,
54
+ };
55
+ }
56
+
57
+ function buildVsCodeClaudeEnv(config) {
58
+ const { provider, model, fastModel, vscodeModel, vscodeFastModel } = config;
59
+ const selectedModel = vscodeModel || model;
60
+ const resolvedFastModel = vscodeFastModel || fastModel || resolveFastModel(PROVIDERS[provider], selectedModel);
61
+ const claudeEnv = buildClaudeEnv({ ...config, model: selectedModel, fastModel: resolvedFastModel });
62
+ const env = {
63
+ ANTHROPIC_BASE_URL: claudeEnv.ANTHROPIC_BASE_URL,
64
+ ANTHROPIC_AUTH_TOKEN: claudeEnv.ANTHROPIC_AUTH_TOKEN,
65
+ CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY: '1',
66
+ CLAUDE_CODE_SUBAGENT_MODEL: resolvedFastModel,
67
+ CLAUDE_CODE_EFFORT_LEVEL: 'max',
68
+ };
69
+ if (resolvedFastModel && resolvedFastModel !== selectedModel) {
70
+ env.ANTHROPIC_CUSTOM_MODEL_OPTION = resolvedFastModel;
71
+ env.ANTHROPIC_CUSTOM_MODEL_OPTION_NAME = resolvedFastModel;
72
+ env.ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION = 'Custom fast model';
73
+ }
74
+ return env;
75
+ }
76
+
77
+ function buildVsCodeAvailableModels({ model, fastModel, availableModels, vscodeModel, vscodeFastModel }) {
78
+ const providerModels = Array.isArray(availableModels) && availableModels.length > 0
79
+ ? availableModels
80
+ : [];
81
+ const models = [vscodeModel || model, vscodeFastModel || fastModel, model, fastModel, ...providerModels].filter(Boolean);
82
+ const chatModels = models.filter(isDesktopChatModel);
83
+ return [...new Set(chatModels.length > 0 ? chatModels : [model, fastModel].filter(Boolean))];
84
+ }
85
+
86
+ function buildVsCodeModelSelectionIds(config) {
87
+ return buildVsCodeAvailableModels(config);
88
+ }
89
+
90
+ function writeClaudeCodeSettings(config, options = {}) {
91
+ const file = getClaudeCodeSettingsPath(options);
92
+ const current = readJsonFile(file);
93
+ const patch = buildClaudeCodeSettingsPatch(config);
94
+ const nextEnv = { ...(current.env && typeof current.env === 'object' ? current.env : {}) };
95
+ for (const key of CLEAR_CLAUDE_ENV_KEYS) {
96
+ delete nextEnv[key];
97
+ }
98
+ Object.assign(nextEnv, patch.env);
99
+
100
+ const next = {
101
+ ...current,
102
+ $schema: current.$schema || patch.$schema,
103
+ model: patch.model,
104
+ availableModels: patch.availableModels,
105
+ env: nextEnv,
106
+ };
107
+ writeJsonFile(file, next);
108
+ try {
109
+ fs.chmodSync(file, 0o600);
110
+ } catch {}
111
+ return { result: 'updated', file, env: patch.env };
112
+ }
113
+
114
+ function writeVsCodeExtensionSettings(options = {}) {
115
+ const file = getVsCodeUserSettingsPath(options);
116
+ const current = readJsonFile(file);
117
+ const next = {
118
+ ...current,
119
+ 'claudeCode.disableLoginPrompt': true,
120
+ };
121
+ if (options.useTerminal === true || options.useTerminal === false) {
122
+ next['claudeCode.useTerminal'] = options.useTerminal;
123
+ }
124
+ writeJsonFile(file, next);
125
+ return { result: 'updated', file };
126
+ }
127
+
128
+ function writeVsCodeIntegration(config, options = {}) {
129
+ const claudeSettings = writeClaudeCodeSettings(config, options);
130
+ const vscodeSettings = writeVsCodeExtensionSettings(options);
131
+ return {
132
+ result: 'updated',
133
+ files: [claudeSettings.file, vscodeSettings.file],
134
+ claudeSettings,
135
+ vscodeSettings,
136
+ };
137
+ }
138
+
139
+ function clearClaudeCodeSettingsEnv(options = {}) {
140
+ const file = getClaudeCodeSettingsPath(options);
141
+ if (!fs.existsSync(file)) return { result: 'missing', file };
142
+
143
+ const current = readJsonFile(file);
144
+ const nextEnv = { ...(current.env && typeof current.env === 'object' ? current.env : {}) };
145
+ let changed = false;
146
+
147
+ for (const key of CLEAR_CLAUDE_ENV_KEYS) {
148
+ if (Object.prototype.hasOwnProperty.call(nextEnv, key)) {
149
+ delete nextEnv[key];
150
+ changed = true;
151
+ }
152
+ }
153
+ for (const key of VSCODE_MODEL_SETTINGS_KEYS) {
154
+ if (Object.prototype.hasOwnProperty.call(current, key)) {
155
+ changed = true;
156
+ }
157
+ }
158
+
159
+ if (!changed) return { result: 'missing', file };
160
+
161
+ const next = { ...current };
162
+ for (const key of VSCODE_MODEL_SETTINGS_KEYS) {
163
+ delete next[key];
164
+ }
165
+ if (Object.keys(nextEnv).length > 0) {
166
+ next.env = nextEnv;
167
+ } else {
168
+ delete next.env;
169
+ }
170
+ writeJsonFile(file, next);
171
+ return { result: 'updated', file };
172
+ }
173
+
174
+ function clearVsCodeExtensionSettings(options = {}) {
175
+ const file = getVsCodeUserSettingsPath(options);
176
+ if (!fs.existsSync(file)) return { result: 'missing', file };
177
+
178
+ const current = readJsonFile(file);
179
+ const next = { ...current };
180
+ let changed = false;
181
+ for (const key of ['claudeCode.disableLoginPrompt', 'claudeCode.useTerminal']) {
182
+ if (Object.prototype.hasOwnProperty.call(next, key)) {
183
+ delete next[key];
184
+ changed = true;
185
+ }
186
+ }
187
+ if (!changed) return { result: 'missing', file };
188
+
189
+ writeJsonFile(file, next);
190
+ return { result: 'updated', file };
191
+ }
192
+
193
+ function clearVsCodeIntegration(options = {}) {
194
+ const claudeSettings = clearClaudeCodeSettingsEnv(options);
195
+ const vscodeSettings = clearVsCodeExtensionSettings(options);
196
+ const files = [claudeSettings, vscodeSettings]
197
+ .filter(result => result.result === 'updated')
198
+ .map(result => result.file);
199
+
200
+ return {
201
+ result: files.length > 0 ? 'updated' : 'missing',
202
+ files,
203
+ claudeSettings,
204
+ vscodeSettings,
205
+ };
206
+ }
207
+
208
+ function checkClaudeCodeSettingsEnv(config, options = {}) {
209
+ const file = getClaudeCodeSettingsPath(options);
210
+ const current = readJsonFile(file);
211
+ const env = current.env && typeof current.env === 'object' ? current.env : {};
212
+ const expected = buildVsCodeClaudeEnv(config);
213
+ const missing = Object.entries(expected)
214
+ .filter(([key, value]) => env[key] !== value)
215
+ .map(([key]) => key);
216
+ const expectedModels = buildVsCodeAvailableModels(config);
217
+ const expectedModel = expectedModels.includes(config.model) ? config.model : expectedModels[0];
218
+ if (current.model !== expectedModel) missing.push('model');
219
+ if (!Array.isArray(current.availableModels) || current.availableModels.join(',') !== expectedModels.join(',')) {
220
+ missing.push('availableModels');
221
+ }
222
+ return {
223
+ file,
224
+ configured: missing.length === 0,
225
+ missing,
226
+ };
227
+ }
228
+
229
+ function buildVsCodeOpenCommand(platform = process.platform) {
230
+ if (platform === 'darwin') {
231
+ return { command: 'open', args: [VSCODE_CLAUDE_OPEN_URI] };
232
+ }
233
+ if (platform === 'win32') {
234
+ return { command: 'cmd', args: ['/c', 'start', '', VSCODE_CLAUDE_OPEN_URI] };
235
+ }
236
+ return { command: 'xdg-open', args: [VSCODE_CLAUDE_OPEN_URI] };
237
+ }
238
+
239
+ module.exports = {
240
+ CLAUDE_CODE_SETTINGS_SCHEMA,
241
+ VSCODE_CLAUDE_OPEN_URI,
242
+ buildClaudeCodeSettingsPatch,
243
+ buildVsCodeAvailableModels,
244
+ buildVsCodeClaudeEnv,
245
+ buildVsCodeModelSelectionIds,
246
+ buildVsCodeOpenCommand,
247
+ checkClaudeCodeSettingsEnv,
248
+ clearClaudeCodeSettingsEnv,
249
+ clearVsCodeExtensionSettings,
250
+ clearVsCodeIntegration,
251
+ getClaudeCodeSettingsPath,
252
+ getVsCodeUserSettingsPath,
253
+ writeClaudeCodeSettings,
254
+ writeVsCodeExtensionSettings,
255
+ writeVsCodeIntegration,
256
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "yingclaw",
3
- "version": "2.5.20",
4
- "description": "Claude Code × 国产大模型一键接入:DeepSeek、KimiQwen、MiniMax、GLM、MiMo",
3
+ "version": "2.5.25",
4
+ "description": "Claude Code × 国产大模型一键接入:DeepSeek、Kimi、火山方舟、Qwen、MiniMax、GLM、MiMo、自定义接口",
5
5
  "main": "index.js",
6
6
  "bin": {
7
7
  "claw": "bin/cli.js"