yingclaw 2.1.8 → 2.2.0
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 +38 -9
- package/lib/desktop.js +21 -10
- package/lib/panel.js +7 -3
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -79,13 +79,20 @@ function getConfigValidationMessage(config) {
|
|
|
79
79
|
return validation.valid ? null : validation.message;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
let _claudeInstalledCache;
|
|
82
83
|
function isClaudeInstalled() {
|
|
84
|
+
if (_claudeInstalledCache !== undefined) return _claudeInstalledCache;
|
|
83
85
|
try {
|
|
84
86
|
execSync('claude --version', { stdio: 'pipe' });
|
|
85
|
-
|
|
87
|
+
_claudeInstalledCache = true;
|
|
86
88
|
} catch {
|
|
87
|
-
|
|
89
|
+
_claudeInstalledCache = false;
|
|
88
90
|
}
|
|
91
|
+
return _claudeInstalledCache;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function invalidateClaudeInstalledCache() {
|
|
95
|
+
_claudeInstalledCache = undefined;
|
|
89
96
|
}
|
|
90
97
|
|
|
91
98
|
function isValidUrl(value) {
|
|
@@ -131,7 +138,7 @@ async function offerDesktopSync(chalk, ora, config) {
|
|
|
131
138
|
spinner.fail(chalk.red(`桌面配置同步失败: ${e.message}`));
|
|
132
139
|
return;
|
|
133
140
|
}
|
|
134
|
-
if (process.platform === 'darwin') {
|
|
141
|
+
if (process.platform === 'darwin' || process.platform === 'win32') {
|
|
135
142
|
const shouldOpen = await confirm({ message: '是否重启 Claude 桌面应用使新配置生效?', default: true });
|
|
136
143
|
if (shouldOpen) {
|
|
137
144
|
const openSpinner = ora('正在重启 Claude 桌面应用...').start();
|
|
@@ -139,7 +146,13 @@ async function offerDesktopSync(chalk, ora, config) {
|
|
|
139
146
|
await openClaudeDesktop();
|
|
140
147
|
openSpinner.succeed(chalk.green('Claude 桌面应用已重启'));
|
|
141
148
|
} catch (e) {
|
|
142
|
-
openSpinner.fail(chalk.red(
|
|
149
|
+
openSpinner.fail(chalk.red(`自动重启失败: ${e.message}`));
|
|
150
|
+
if (process.platform === 'win32') {
|
|
151
|
+
console.log(chalk.yellow('\n请手动操作(仅关闭窗口不够,进程还在系统托盘):'));
|
|
152
|
+
console.log(chalk.dim(' 1. 任务栏右下角找 Claude 图标 → 右键 → 退出'));
|
|
153
|
+
console.log(chalk.dim(' 2. 或在任务管理器中结束所有 Claude.exe 进程'));
|
|
154
|
+
console.log(chalk.dim(' 3. 然后重新打开 Claude'));
|
|
155
|
+
}
|
|
143
156
|
}
|
|
144
157
|
}
|
|
145
158
|
}
|
|
@@ -334,6 +347,7 @@ async function runConfigFlow({ writeCodeEnv = false } = {}) {
|
|
|
334
347
|
} else if (step === 'apikey') {
|
|
335
348
|
const k = await input({
|
|
336
349
|
message: chalk.cyan(`${provider.name} API Key(输入 b 返回上一步)`),
|
|
350
|
+
default: apiKey || undefined,
|
|
337
351
|
transformer: (v) => v && v !== 'b' ? chalk.dim('•'.repeat(v.length)) : v,
|
|
338
352
|
validate: (v) => v.trim().length > 0 ? true : 'API Key 不能为空',
|
|
339
353
|
});
|
|
@@ -397,6 +411,8 @@ async function runConfigFlow({ writeCodeEnv = false } = {}) {
|
|
|
397
411
|
nextStep,
|
|
398
412
|
{ padding: { top: 0, bottom: 0, left: 2, right: 2 }, borderStyle: 'round', borderColor: 'green', margin: { top: 1, bottom: 1 } }
|
|
399
413
|
));
|
|
414
|
+
|
|
415
|
+
await offerDesktopSync(chalk, ora, cfg);
|
|
400
416
|
}
|
|
401
417
|
|
|
402
418
|
program
|
|
@@ -614,6 +630,8 @@ program
|
|
|
614
630
|
validate: (v) => v.trim().length > 0 ? true : 'API Key 不能为空',
|
|
615
631
|
});
|
|
616
632
|
apiKey = apiKey.trim();
|
|
633
|
+
} else {
|
|
634
|
+
console.log(chalk.yellow('⚠ 沿用旧 Key 通常无法访问新厂商,模型列表可能拉取失败'));
|
|
617
635
|
}
|
|
618
636
|
}
|
|
619
637
|
|
|
@@ -706,16 +724,23 @@ program
|
|
|
706
724
|
{ padding: { top: 0, bottom: 0, left: 2, right: 2 }, borderStyle: 'round', borderColor: 'cyan', margin: { top: 1, bottom: 1 } }
|
|
707
725
|
));
|
|
708
726
|
|
|
709
|
-
if (process.platform === 'darwin') {
|
|
710
|
-
const shouldOpen = await confirm({ message: '
|
|
727
|
+
if (process.platform === 'darwin' || process.platform === 'win32') {
|
|
728
|
+
const shouldOpen = await confirm({ message: '是否现在重启 Claude 桌面应用?', default: true });
|
|
711
729
|
if (shouldOpen) {
|
|
712
|
-
const openSpinner = ora('
|
|
730
|
+
const openSpinner = ora('正在重启 Claude 桌面应用...').start();
|
|
713
731
|
try {
|
|
714
732
|
await openClaudeDesktop();
|
|
715
733
|
openSpinner.succeed(chalk.green('Claude 桌面应用已重新打开(旧实例已退出,新配置生效)'));
|
|
716
734
|
} catch (e) {
|
|
717
|
-
openSpinner.fail(chalk.red(
|
|
718
|
-
|
|
735
|
+
openSpinner.fail(chalk.red(`自动重启失败: ${e.message}`));
|
|
736
|
+
if (process.platform === 'win32') {
|
|
737
|
+
console.log(chalk.yellow('\n请手动操作(仅关闭窗口不够,进程还在系统托盘):'));
|
|
738
|
+
console.log(chalk.dim(' 1. 任务栏右下角找 Claude 图标 → 右键 → 退出'));
|
|
739
|
+
console.log(chalk.dim(' 2. 或在任务管理器中结束所有 Claude.exe 进程'));
|
|
740
|
+
console.log(chalk.dim(' 3. 然后重新打开 Claude'));
|
|
741
|
+
} else {
|
|
742
|
+
console.log(chalk.dim(getDesktopOpenHint()));
|
|
743
|
+
}
|
|
719
744
|
}
|
|
720
745
|
}
|
|
721
746
|
} else {
|
|
@@ -1087,6 +1112,10 @@ async function runMenu() {
|
|
|
1087
1112
|
lastCheckResult = undefined;
|
|
1088
1113
|
lastCheckedHash = null;
|
|
1089
1114
|
}
|
|
1115
|
+
// 安装 Claude 后刷新检测缓存
|
|
1116
|
+
if (resolvedAction === 'install') {
|
|
1117
|
+
invalidateClaudeInstalledCache();
|
|
1118
|
+
}
|
|
1090
1119
|
|
|
1091
1120
|
console.log();
|
|
1092
1121
|
const next = await select({ loop: false,
|
package/lib/desktop.js
CHANGED
|
@@ -232,15 +232,26 @@ function isDesktopConfigured(options = {}) {
|
|
|
232
232
|
}
|
|
233
233
|
|
|
234
234
|
function buildClaudeDesktopOpenCommands(platform = process.platform) {
|
|
235
|
-
if (platform !== 'darwin') return null;
|
|
236
235
|
// 必须先完全退出 Claude,新配置只在启动时读取一次
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
236
|
+
if (platform === 'darwin') {
|
|
237
|
+
return [
|
|
238
|
+
{ command: 'osascript', args: ['-e', 'tell application "Claude" to quit'], optional: true, waitAfter: 800 },
|
|
239
|
+
{ command: 'pkill', args: ['-TERM', '-x', 'Claude'], optional: true, waitAfter: 500 },
|
|
240
|
+
{ command: 'pkill', args: ['-KILL', '-x', 'Claude'], optional: true, waitAfter: 800 },
|
|
241
|
+
{ command: 'open', args: ['-a', 'Claude'], waitAfter: 600 },
|
|
242
|
+
{ command: 'osascript', args: ['-e', 'tell application "Claude" to activate'], optional: true },
|
|
243
|
+
];
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (platform === 'win32') {
|
|
247
|
+
// taskkill /T 也连带杀掉子进程;start "" 找已注册的 Claude.exe
|
|
248
|
+
return [
|
|
249
|
+
{ command: 'taskkill', args: ['/IM', 'Claude.exe', '/F', '/T'], optional: true, waitAfter: 1200, shell: true },
|
|
250
|
+
{ command: 'cmd', args: ['/c', 'start', '""', '/B', 'claude:'], optional: true, waitAfter: 600, shell: true },
|
|
251
|
+
];
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return null;
|
|
244
255
|
}
|
|
245
256
|
|
|
246
257
|
async function sleep(ms) {
|
|
@@ -257,8 +268,8 @@ async function openClaudeDesktop(options = {}) {
|
|
|
257
268
|
const timeoutMs = options.timeoutMs || 5000;
|
|
258
269
|
|
|
259
270
|
const trace = [];
|
|
260
|
-
for (const { command, args, optional, waitAfter } of commands) {
|
|
261
|
-
const result = runner(command, args, { stdio: 'pipe', encoding: 'utf8', windowsHide: true, timeout: timeoutMs });
|
|
271
|
+
for (const { command, args, optional, waitAfter, shell } of commands) {
|
|
272
|
+
const result = runner(command, args, { stdio: 'pipe', encoding: 'utf8', windowsHide: true, timeout: timeoutMs, shell });
|
|
262
273
|
const stderr = (result.stderr || '').toString().trim();
|
|
263
274
|
trace.push({ command, args, status: result.status, stderr });
|
|
264
275
|
|
package/lib/panel.js
CHANGED
|
@@ -23,8 +23,12 @@ function buildStatusView(config, options = {}) {
|
|
|
23
23
|
const envActive = isEnvActive(config, env);
|
|
24
24
|
const warnings = [];
|
|
25
25
|
|
|
26
|
-
if (config.provider === 'deepseek' &&
|
|
27
|
-
|
|
26
|
+
if (config.provider === 'deepseek' && (
|
|
27
|
+
config.model === 'deepseek-v4-pro' ||
|
|
28
|
+
config.model === 'deepseek-v4-flash' ||
|
|
29
|
+
config.fastModel === 'deepseek-v4-flash'
|
|
30
|
+
)) {
|
|
31
|
+
warnings.push('检测到旧 DeepSeek 模型名,建议运行 claw switch 更新到 [1m] 长上下文版本');
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
return {
|
|
@@ -63,7 +67,7 @@ function buildMenuStatusLines(view, options = {}) {
|
|
|
63
67
|
lines.push(`主模型 ${view.mainModel} · 快速模型 ${view.fastModel}`);
|
|
64
68
|
|
|
65
69
|
if (view.warnings.some((warning) => warning.includes('旧 DeepSeek 模型名'))) {
|
|
66
|
-
lines.push('
|
|
70
|
+
lines.push('旧模型名:选择下方"切换厂商或模型"更新到 [1m]');
|
|
67
71
|
}
|
|
68
72
|
|
|
69
73
|
return lines;
|