yingclaw 2.4.5 → 2.5.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/README.md +1 -1
- package/bin/cli.js +7 -123
- package/lib/config.js +4 -67
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -72,7 +72,6 @@ claw config # 配置 API 连接
|
|
|
72
72
|
claw code # 接入 Claude Code 终端
|
|
73
73
|
claw desktop # 接入 Claude 桌面应用
|
|
74
74
|
claw switch # 快速切换厂商或模型
|
|
75
|
-
claw prompt # 配置系统提示词(按模型独立保存)
|
|
76
75
|
claw status # 查看当前配置,验证 Key 是否有效
|
|
77
76
|
claw update # 检查并升级到最新版本
|
|
78
77
|
|
|
@@ -82,6 +81,7 @@ claw reset # 清除所有 yingclaw 配置
|
|
|
82
81
|
|
|
83
82
|
claw install-claude # 安装 Claude Code
|
|
84
83
|
claw setup # 兼容旧命令:config + code
|
|
84
|
+
|
|
85
85
|
```
|
|
86
86
|
|
|
87
87
|
## 平台支持
|
package/bin/cli.js
CHANGED
|
@@ -5,8 +5,6 @@ const { select, input, confirm } = require('@inquirer/prompts');
|
|
|
5
5
|
const {
|
|
6
6
|
loadConfig,
|
|
7
7
|
saveConfig,
|
|
8
|
-
getSystemPrompt,
|
|
9
|
-
setSystemPrompt,
|
|
10
8
|
writeEnvToZshrc,
|
|
11
9
|
clearClaudeCodeEnv,
|
|
12
10
|
fetchModels,
|
|
@@ -237,14 +235,6 @@ async function showStatus() {
|
|
|
237
235
|
env: process.env,
|
|
238
236
|
});
|
|
239
237
|
|
|
240
|
-
const systemPromptText = getSystemPrompt(config);
|
|
241
|
-
if (systemPromptText) {
|
|
242
|
-
const preview = systemPromptText.length > 60 ? systemPromptText.slice(0, 60) + '…' : systemPromptText;
|
|
243
|
-
view.lines.push({ label: '系统提示词', value: preview });
|
|
244
|
-
} else {
|
|
245
|
-
view.lines.push({ label: '系统提示词', value: '未配置' });
|
|
246
|
-
}
|
|
247
|
-
|
|
248
238
|
const lines = view.lines.map(({ label, value }) => {
|
|
249
239
|
const coloredValue = label === '厂商'
|
|
250
240
|
? chalk.white.bold(value)
|
|
@@ -364,7 +354,7 @@ async function runConfigFlow({ writeCodeEnv = false } = {}) {
|
|
|
364
354
|
cfg = customConfig || { provider: providerKey, model, fastModel, apiKey, baseUrl: provider.baseUrl, availableModels };
|
|
365
355
|
saveConfig(cfg);
|
|
366
356
|
if (writeCodeEnv) {
|
|
367
|
-
({ file } = writeEnvToZshrc(cfg.baseUrl, cfg.apiKey, cfg.model, cfg.fastModel
|
|
357
|
+
({ file } = writeEnvToZshrc(cfg.baseUrl, cfg.apiKey, cfg.model, cfg.fastModel));
|
|
368
358
|
}
|
|
369
359
|
spinner.succeed(chalk.green(writeCodeEnv ? 'API 连接已保存,Claude Code 终端已接入' : 'API 连接已保存'));
|
|
370
360
|
} catch (e) {
|
|
@@ -492,7 +482,7 @@ program
|
|
|
492
482
|
const spinner = ora('写入 Claude Code 终端环境变量...').start();
|
|
493
483
|
let file;
|
|
494
484
|
try {
|
|
495
|
-
({ file } = writeEnvToZshrc(config.baseUrl, config.apiKey, config.model, config.fastModel
|
|
485
|
+
({ file } = writeEnvToZshrc(config.baseUrl, config.apiKey, config.model, config.fastModel));
|
|
496
486
|
spinner.succeed(chalk.green(`Claude Code 终端已接入 → ${file}`));
|
|
497
487
|
} catch (e) {
|
|
498
488
|
spinner.fail(chalk.red(`写入失败: ${e.message}`));
|
|
@@ -643,105 +633,6 @@ program
|
|
|
643
633
|
await offerDesktopSync(chalk, ora, newConfig);
|
|
644
634
|
});
|
|
645
635
|
|
|
646
|
-
program
|
|
647
|
-
.command('prompt')
|
|
648
|
-
.description('配置系统提示词')
|
|
649
|
-
.action(async () => {
|
|
650
|
-
const chalk = (await import('chalk')).default;
|
|
651
|
-
const ora = (await import('ora')).default;
|
|
652
|
-
const boxen = (await import('boxen')).default;
|
|
653
|
-
|
|
654
|
-
console.log(await getBanner());
|
|
655
|
-
|
|
656
|
-
const config = loadConfig();
|
|
657
|
-
if (!config) {
|
|
658
|
-
console.log(chalk.red('\n未配置 API 连接,请先运行: claw config\n'));
|
|
659
|
-
return;
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
const provider = PROVIDERS[config.provider];
|
|
663
|
-
const providerName = config.providerName || provider?.name || config.provider;
|
|
664
|
-
const currentPrompt = getSystemPrompt(config);
|
|
665
|
-
|
|
666
|
-
console.log(chalk.dim(` 当前模型:${providerName} · ${config.model}\n`));
|
|
667
|
-
|
|
668
|
-
if (currentPrompt) {
|
|
669
|
-
const preview = currentPrompt.length > 300 ? currentPrompt.slice(0, 300) + '\n...' : currentPrompt;
|
|
670
|
-
console.log(boxen(
|
|
671
|
-
chalk.bold('当前系统提示词\n\n') + chalk.dim(preview),
|
|
672
|
-
{ padding: { top: 0, bottom: 0, left: 2, right: 2 }, borderStyle: 'round', borderColor: 'cyan', margin: { top: 1, bottom: 1 } }
|
|
673
|
-
));
|
|
674
|
-
} else {
|
|
675
|
-
console.log(chalk.dim(' 当前模型未配置系统提示词\n'));
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
const action = await select({ loop: false,
|
|
679
|
-
message: chalk.cyan('操作'),
|
|
680
|
-
choices: [
|
|
681
|
-
{ name: currentPrompt ? '✏️ 编辑系统提示词' : '✏️ 设置系统提示词', value: 'edit' },
|
|
682
|
-
...(currentPrompt ? [{ name: '🗑 清除当前模型提示词', value: 'clear' }] : []),
|
|
683
|
-
{ name: chalk.dim('↩ 返回'), value: '__BACK__' },
|
|
684
|
-
],
|
|
685
|
-
});
|
|
686
|
-
|
|
687
|
-
if (action === '__BACK__') return;
|
|
688
|
-
|
|
689
|
-
if (action === 'clear') {
|
|
690
|
-
const yes = await confirm({ message: '确定清除该模型的系统提示词?', default: false });
|
|
691
|
-
if (!yes) { console.log(chalk.dim('已取消')); return; }
|
|
692
|
-
const spinner = ora('清除中...').start();
|
|
693
|
-
setSystemPrompt(config, null);
|
|
694
|
-
saveConfig(config);
|
|
695
|
-
try {
|
|
696
|
-
writeEnvToZshrc(config.baseUrl, config.apiKey, config.model, config.fastModel, {});
|
|
697
|
-
} catch {}
|
|
698
|
-
spinner.succeed(chalk.green('系统提示词已清除'));
|
|
699
|
-
return;
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
if (currentPrompt) {
|
|
703
|
-
console.log(chalk.dim(' 直接输入新内容覆盖,留空并回车取消'));
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
const newPrompt = await input({
|
|
707
|
-
message: chalk.cyan('系统提示词'),
|
|
708
|
-
default: currentPrompt || undefined,
|
|
709
|
-
validate: () => true,
|
|
710
|
-
});
|
|
711
|
-
|
|
712
|
-
if (!newPrompt || !newPrompt.trim()) {
|
|
713
|
-
console.log(chalk.dim('内容为空,已取消'));
|
|
714
|
-
return;
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
const spinner = ora('保存中...').start();
|
|
718
|
-
setSystemPrompt(config, newPrompt);
|
|
719
|
-
saveConfig(config);
|
|
720
|
-
|
|
721
|
-
// 无论是否已有 clawai 块,都同步写入 shell RC / PowerShell Profile
|
|
722
|
-
let rcFile;
|
|
723
|
-
try {
|
|
724
|
-
({ file: rcFile } = writeEnvToZshrc(config.baseUrl, config.apiKey, config.model, config.fastModel, { systemPrompt: getSystemPrompt(config) }));
|
|
725
|
-
} catch {}
|
|
726
|
-
|
|
727
|
-
spinner.succeed(chalk.green('系统提示词已保存'));
|
|
728
|
-
|
|
729
|
-
if (process.platform === 'win32') {
|
|
730
|
-
console.log(boxen(
|
|
731
|
-
chalk.dim('• 通过菜单"启动 Claude Code"立即生效\n') +
|
|
732
|
-
chalk.dim('• 直接运行 claude 需重新打开 PowerShell 后生效\n') +
|
|
733
|
-
chalk.dim(' (已写入 PowerShell Profile,新窗口自动加载)'),
|
|
734
|
-
{ padding: { top: 0, bottom: 0, left: 2, right: 2 }, borderStyle: 'round', borderColor: 'green', margin: { top: 1, bottom: 1 } }
|
|
735
|
-
));
|
|
736
|
-
} else {
|
|
737
|
-
console.log(boxen(
|
|
738
|
-
chalk.dim('• 通过菜单"启动 Claude Code"立即生效\n') +
|
|
739
|
-
chalk.dim('• 终端直接运行 claude 需先执行:') + chalk.cyan(`source ${rcFile || '~/.zshrc'}`),
|
|
740
|
-
{ padding: { top: 0, bottom: 0, left: 2, right: 2 }, borderStyle: 'round', borderColor: 'green', margin: { top: 1, bottom: 1 } }
|
|
741
|
-
));
|
|
742
|
-
}
|
|
743
|
-
});
|
|
744
|
-
|
|
745
636
|
program
|
|
746
637
|
.command('status')
|
|
747
638
|
.description('查看当前配置和 Key 有效性')
|
|
@@ -1174,7 +1065,6 @@ async function runMenu() {
|
|
|
1174
1065
|
{ name: '📦 安装 Claude Code', value: 'install' },
|
|
1175
1066
|
{ name: config ? '🔑 重新配置 API 连接' : '🔑 配置 API 连接', value: 'config' },
|
|
1176
1067
|
{ name: '🔄 切换厂商或模型', value: 'switch', disabled: disabledHint },
|
|
1177
|
-
{ name: getSystemPrompt(config) ? '📝 系统提示词(已配置)' : '📝 配置系统提示词', value: 'prompt', disabled: !config && '需先配置 API 连接' },
|
|
1178
1068
|
{ name: '💻 接入 Claude Code 终端', value: 'code', disabled: disabledHint },
|
|
1179
1069
|
{ name: '🖥 接入 Claude 桌面应用', value: 'desktop', disabled: disabledHint },
|
|
1180
1070
|
{ name: '📊 查看当前配置', value: 'status', disabled: !config && '需先配置 API 连接' },
|
|
@@ -1201,17 +1091,12 @@ async function runMenu() {
|
|
|
1201
1091
|
if (resolvedAction === 'launch') {
|
|
1202
1092
|
const cfg = loadConfig();
|
|
1203
1093
|
if (!cfg || getConfigValidationMessage(cfg)) continue;
|
|
1204
|
-
const systemPromptText = getSystemPrompt(cfg);
|
|
1205
|
-
const launchArgs = systemPromptText ? ['--append-system-prompt', systemPromptText] : [];
|
|
1206
|
-
if (systemPromptText) {
|
|
1207
|
-
const preview = systemPromptText.length > 40 ? systemPromptText.slice(0, 40) + '…' : systemPromptText;
|
|
1208
|
-
console.log(chalk.dim(` 系统提示词已启用:${preview}`));
|
|
1209
|
-
}
|
|
1210
1094
|
await new Promise((resolve) => {
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
:
|
|
1095
|
+
const child = spawn('claude', [], {
|
|
1096
|
+
stdio: 'inherit',
|
|
1097
|
+
env: { ...process.env, ...buildClaudeEnv(cfg) },
|
|
1098
|
+
shell: process.platform === 'win32',
|
|
1099
|
+
});
|
|
1215
1100
|
child.on('error', () => {
|
|
1216
1101
|
console.log(chalk.yellow('\nClaude Code 未找到,请先选择"安装 Claude Code"'));
|
|
1217
1102
|
resolve();
|
|
@@ -1227,7 +1112,6 @@ async function runMenu() {
|
|
|
1227
1112
|
code: 'code',
|
|
1228
1113
|
'code-reset': 'code-reset',
|
|
1229
1114
|
switch: 'switch',
|
|
1230
|
-
prompt: 'prompt',
|
|
1231
1115
|
desktop: 'desktop',
|
|
1232
1116
|
'desktop-reset': 'desktop-reset',
|
|
1233
1117
|
status: 'status',
|
package/lib/config.js
CHANGED
|
@@ -128,26 +128,6 @@ function normalizeAnthropicBaseUrl(baseUrl) {
|
|
|
128
128
|
return url.toString().replace(/\/+$/, '');
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
function systemPromptKey(config) {
|
|
132
|
-
return `${config.provider}::${config.model}`;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function getSystemPrompt(config) {
|
|
136
|
-
if (!config?.systemPrompts) return null;
|
|
137
|
-
return config.systemPrompts[systemPromptKey(config)] || null;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function setSystemPrompt(config, prompt) {
|
|
141
|
-
const key = systemPromptKey(config);
|
|
142
|
-
if (!config.systemPrompts) config.systemPrompts = {};
|
|
143
|
-
if (prompt && prompt.trim()) {
|
|
144
|
-
config.systemPrompts[key] = prompt.trim();
|
|
145
|
-
} else {
|
|
146
|
-
delete config.systemPrompts[key];
|
|
147
|
-
if (Object.keys(config.systemPrompts).length === 0) delete config.systemPrompts;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
131
|
function buildModelUrlCandidates(baseUrl) {
|
|
152
132
|
let url;
|
|
153
133
|
try { url = new URL(normalizeAnthropicBaseUrl(baseUrl)); } catch { return []; }
|
|
@@ -344,10 +324,10 @@ function shellQuote(value) {
|
|
|
344
324
|
}
|
|
345
325
|
|
|
346
326
|
// 构造完整的 clawai 环境变量块
|
|
347
|
-
function buildEnvBlock(baseUrl, apiKey, model, fastModel
|
|
327
|
+
function buildEnvBlock(baseUrl, apiKey, model, fastModel) {
|
|
348
328
|
const provider = providerKeyFromBaseUrl(baseUrl);
|
|
349
329
|
const env = buildClaudeEnv({ provider, baseUrl, apiKey, model, fastModel });
|
|
350
|
-
|
|
330
|
+
return [
|
|
351
331
|
'',
|
|
352
332
|
'# clawai-start',
|
|
353
333
|
`export ANTHROPIC_BASE_URL=${shellQuote(env.ANTHROPIC_BASE_URL)}`,
|
|
@@ -359,47 +339,9 @@ function buildEnvBlock(baseUrl, apiKey, model, fastModel, systemPrompt) {
|
|
|
359
339
|
`export ANTHROPIC_DEFAULT_HAIKU_MODEL=${shellQuote(env.ANTHROPIC_DEFAULT_HAIKU_MODEL)}`,
|
|
360
340
|
`export CLAUDE_CODE_SUBAGENT_MODEL=${shellQuote(env.CLAUDE_CODE_SUBAGENT_MODEL)}`,
|
|
361
341
|
`export CLAUDE_CODE_EFFORT_LEVEL=${shellQuote(env.CLAUDE_CODE_EFFORT_LEVEL)}`,
|
|
362
|
-
];
|
|
363
|
-
|
|
364
|
-
if (systemPrompt && systemPrompt.trim()) {
|
|
365
|
-
lines.push(`_claw_system_prompt=${shellQuote(systemPrompt.trim())}`);
|
|
366
|
-
lines.push(`claude() { command claude --append-system-prompt "$_claw_system_prompt" "$@"; }`);
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
lines.push('# clawai-end', '');
|
|
370
|
-
return lines.join('\n');
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
function buildPsBlock(systemPrompt) {
|
|
374
|
-
const escaped = systemPrompt.replace(/'/g, "''");
|
|
375
|
-
return [
|
|
376
|
-
'',
|
|
377
|
-
'# clawai-start',
|
|
378
|
-
`$_claw_system_prompt = '${escaped}'`,
|
|
379
|
-
`function claude { $claudePath = (Get-Command -Name claude.cmd -ErrorAction SilentlyContinue)?.Source; if (-not $claudePath) { $claudePath = 'claude' }; & $claudePath --append-system-prompt $_claw_system_prompt @args }`,
|
|
380
342
|
'# clawai-end',
|
|
381
343
|
'',
|
|
382
|
-
].join('\
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
function writePowerShellProfile(systemPrompt, options = {}) {
|
|
386
|
-
const homeDir = options.homeDir || os.homedir();
|
|
387
|
-
const profilePaths = [
|
|
388
|
-
path.join(homeDir, 'Documents', 'WindowsPowerShell', 'Microsoft.PowerShell_profile.ps1'),
|
|
389
|
-
path.join(homeDir, 'Documents', 'PowerShell', 'Microsoft.PowerShell_profile.ps1'),
|
|
390
|
-
];
|
|
391
|
-
const written = [];
|
|
392
|
-
for (const profilePath of profilePaths) {
|
|
393
|
-
try {
|
|
394
|
-
fs.mkdirSync(path.dirname(profilePath), { recursive: true });
|
|
395
|
-
const current = fs.existsSync(profilePath) ? fs.readFileSync(profilePath, 'utf8') : '';
|
|
396
|
-
const cleaned = current.replace(/\r?\n?# clawai-start[\s\S]*?# clawai-end\r?\n?/g, '');
|
|
397
|
-
const next = (systemPrompt && systemPrompt.trim()) ? cleaned + buildPsBlock(systemPrompt) : cleaned;
|
|
398
|
-
fs.writeFileSync(profilePath, next, 'utf8');
|
|
399
|
-
written.push(profilePath);
|
|
400
|
-
} catch {}
|
|
401
|
-
}
|
|
402
|
-
return written;
|
|
344
|
+
].join('\n');
|
|
403
345
|
}
|
|
404
346
|
|
|
405
347
|
// 写入或更新 shell 配置文件中的环境变量块
|
|
@@ -409,7 +351,6 @@ function writeEnvToZshrc(baseUrl, apiKey, model, fastModel, options = {}) {
|
|
|
409
351
|
const provider = providerKeyFromBaseUrl(baseUrl);
|
|
410
352
|
const env = buildClaudeEnv({ provider, baseUrl, apiKey, model, fastModel });
|
|
411
353
|
runWindowsEnvCommands(buildWindowsSetEnvCommands(env), options.runner || spawnSync);
|
|
412
|
-
writePowerShellProfile(options.systemPrompt, options);
|
|
413
354
|
return { result: 'updated', file: WINDOWS_ENV_LABEL };
|
|
414
355
|
}
|
|
415
356
|
|
|
@@ -423,7 +364,7 @@ function writeEnvToZshrc(baseUrl, apiKey, model, fastModel, options = {}) {
|
|
|
423
364
|
rcFile = path.join(os.homedir(), '.zshrc');
|
|
424
365
|
}
|
|
425
366
|
|
|
426
|
-
const block = buildEnvBlock(baseUrl, apiKey, model, fastModel
|
|
367
|
+
const block = buildEnvBlock(baseUrl, apiKey, model, fastModel);
|
|
427
368
|
const current = fs.existsSync(rcFile) ? fs.readFileSync(rcFile, 'utf8') : '';
|
|
428
369
|
|
|
429
370
|
// 兼容旧版(# clawai 单行块)和新版(# clawai-start...# clawai-end 多行块)
|
|
@@ -483,11 +424,7 @@ function resetConfig(options = {}) {
|
|
|
483
424
|
module.exports = {
|
|
484
425
|
loadConfig,
|
|
485
426
|
saveConfig,
|
|
486
|
-
getSystemPrompt,
|
|
487
|
-
setSystemPrompt,
|
|
488
427
|
writeEnvToZshrc,
|
|
489
|
-
writePowerShellProfile,
|
|
490
|
-
buildPsBlock,
|
|
491
428
|
buildWindowsSetEnvCommands,
|
|
492
429
|
buildWindowsClearEnvCommands,
|
|
493
430
|
clearClaudeCodeEnv,
|