yymaxapi 1.0.86 → 1.0.88
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/yymaxapi.js +37 -108
- package/package.json +1 -1
package/bin/yymaxapi.js
CHANGED
|
@@ -56,6 +56,20 @@ function safeExec(cmd, options = {}) {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
function shouldSuppressProcessWarning(warning) {
|
|
60
|
+
const message = typeof warning === 'string' ? warning : String(warning?.message || '');
|
|
61
|
+
return message.includes("Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0'");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!process.__yymaxapiWarningFilterInstalled && typeof process.emitWarning === 'function') {
|
|
65
|
+
const originalEmitWarning = process.emitWarning.bind(process);
|
|
66
|
+
process.emitWarning = function patchedEmitWarning(warning, ...args) {
|
|
67
|
+
if (shouldSuppressProcessWarning(warning)) return;
|
|
68
|
+
return originalEmitWarning(warning, ...args);
|
|
69
|
+
};
|
|
70
|
+
process.__yymaxapiWarningFilterInstalled = true;
|
|
71
|
+
}
|
|
72
|
+
|
|
59
73
|
// ============ 预设 (由 build.js 从 provider config 生成) ============
|
|
60
74
|
const DEFAULT_ENDPOINTS = [
|
|
61
75
|
{
|
|
@@ -493,41 +507,8 @@ async function validateApiKey(nodeUrl, apiKey) {
|
|
|
493
507
|
try {
|
|
494
508
|
const res = await httpGetJson(verifyUrl, { Authorization: `Bearer ${apiKey}` });
|
|
495
509
|
if (res.status === 200 && res.data) {
|
|
496
|
-
spinner.succeed('API Key
|
|
497
|
-
|
|
498
|
-
// 基本信息
|
|
499
|
-
if (d.service_type) console.log(chalk.gray(` 服务类型: ${d.service_type}`));
|
|
500
|
-
if (d.billing_mode) console.log(chalk.gray(` 计费模式: ${d.billing_mode}`));
|
|
501
|
-
if (d.status && d.status !== 'active') console.log(chalk.yellow(` ⚠ 状态: ${d.status}`));
|
|
502
|
-
// 配额信息
|
|
503
|
-
if (d.total_quota !== undefined || d.remaining_quota !== undefined) {
|
|
504
|
-
const total = d.total_quota || 0;
|
|
505
|
-
const remaining = d.remaining_quota !== undefined ? d.remaining_quota : total;
|
|
506
|
-
const used = total - remaining;
|
|
507
|
-
const pct = total > 0 ? Math.round((used / total) * 100) : 0;
|
|
508
|
-
const barLen = 20;
|
|
509
|
-
const filled = Math.round(barLen * pct / 100);
|
|
510
|
-
const bar = chalk.green('█'.repeat(filled)) + chalk.gray('░'.repeat(barLen - filled));
|
|
511
|
-
console.log(chalk.gray(` 总配额: ${total}`) + (d.max_requests ? chalk.gray(` | 最大请求: ${d.max_requests}`) : ''));
|
|
512
|
-
console.log(chalk.gray(` 已用/剩余: ${used} / ${remaining}`));
|
|
513
|
-
console.log(` [${bar}] ${pct}%`);
|
|
514
|
-
}
|
|
515
|
-
// 每日配额
|
|
516
|
-
if (d.daily_quota !== undefined || d.daily_remaining !== undefined) {
|
|
517
|
-
const dTotal = d.daily_quota || 0;
|
|
518
|
-
const dRemain = d.daily_remaining !== undefined ? d.daily_remaining : dTotal;
|
|
519
|
-
const dUsed = d.daily_used !== undefined ? d.daily_used : (dTotal - dRemain);
|
|
520
|
-
console.log(chalk.gray(` 今日配额: ${dTotal} | 已用: ${dUsed} | 剩余: ${dRemain}`));
|
|
521
|
-
}
|
|
522
|
-
// 有效期
|
|
523
|
-
if (d.activated_at) console.log(chalk.gray(` 激活时间: ${new Date(d.activated_at).toLocaleDateString()}`));
|
|
524
|
-
if (d.expires_at) {
|
|
525
|
-
const exp = new Date(d.expires_at);
|
|
526
|
-
const daysLeft = Math.ceil((exp - Date.now()) / 86400000);
|
|
527
|
-
const expColor = daysLeft <= 7 ? chalk.red : daysLeft <= 30 ? chalk.yellow : chalk.gray;
|
|
528
|
-
console.log(expColor(` 有效期至: ${exp.toLocaleDateString()} (${daysLeft > 0 ? `剩余 ${daysLeft} 天` : '已过期'})`));
|
|
529
|
-
}
|
|
530
|
-
return { valid: true, data: d };
|
|
510
|
+
spinner.succeed('API Key 可用');
|
|
511
|
+
return { valid: true, data: res.data };
|
|
531
512
|
} else {
|
|
532
513
|
spinner.fail('API Key 验证失败');
|
|
533
514
|
console.log(chalk.red(` HTTP ${res.status}`));
|
|
@@ -2368,13 +2349,10 @@ function applyManagedYunyiOpenClawLayout(config, options = {}) {
|
|
|
2368
2349
|
|
|
2369
2350
|
function printYunyiOpenClawSwitchHint(result = {}) {
|
|
2370
2351
|
if (!result?.applied) return;
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
}
|
|
2376
|
-
console.log(chalk.gray(' GPT 入口是 yunyi-gpt'));
|
|
2377
|
-
console.log(chalk.yellow(' 提示: 当前 OpenClaw Web 顶部模型下拉跨 provider 切换可能报错,建议通过左侧会话/agent 切换 Claude 和 GPT'));
|
|
2352
|
+
const summary = result.preservedMain && result.claudeAgentId === YYMAXAPI_OPENCLAW_ALT_CLAUDE_AGENT_ID
|
|
2353
|
+
? 'OpenClaw: main 已保留, Claude=yunyi-claude, GPT=yunyi-gpt'
|
|
2354
|
+
: 'OpenClaw: main=yunyi-claude, GPT=yunyi-gpt';
|
|
2355
|
+
console.log(chalk.cyan(` ${summary}`));
|
|
2378
2356
|
}
|
|
2379
2357
|
|
|
2380
2358
|
function pruneProvidersByPrefix(config, prefixBase, keepProviders = []) {
|
|
@@ -3948,17 +3926,13 @@ async function presetClaude(paths, args = {}) {
|
|
|
3948
3926
|
updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER, apiKey);
|
|
3949
3927
|
updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_GPT_PROVIDER, apiKey);
|
|
3950
3928
|
}
|
|
3951
|
-
|
|
3929
|
+
syncExternalTools('claude', baseUrl, apiKey, { claudeModelId: modelId, opencodeDefaultModelKey: `yunyi-claude/${modelId}` });
|
|
3952
3930
|
writeSpinner.succeed('配置写入完成');
|
|
3953
3931
|
|
|
3954
3932
|
console.log(chalk.green('\n✅ Claude 节点配置完成!'));
|
|
3955
|
-
|
|
3956
|
-
console.log(chalk.cyan(` ${providerName}${tag}: ${buildFullUrl(selectedEndpoint.url, 'claude')}`));
|
|
3957
|
-
console.log(chalk.gray(` 模型: ${modelName}`));
|
|
3958
|
-
console.log(chalk.gray(' API Key: 已设置'));
|
|
3959
|
-
if (extSynced.length > 0) console.log(chalk.gray(` 同步: ${extSynced.join(', ')}`));
|
|
3933
|
+
console.log(chalk.cyan(` Claude: ${modelName}`));
|
|
3960
3934
|
if (repairResult.renamedProviders.length > 0) {
|
|
3961
|
-
console.log(chalk.
|
|
3935
|
+
console.log(chalk.cyan(` 已修复 provider 冲突: ${repairResult.renamedProviders.map(item => `${item.from}→${item.to}`).join(', ')}`));
|
|
3962
3936
|
}
|
|
3963
3937
|
printYunyiOpenClawSwitchHint(yunyiLayoutResult);
|
|
3964
3938
|
|
|
@@ -4135,17 +4109,13 @@ async function presetCodex(paths, args = {}) {
|
|
|
4135
4109
|
updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_CLAUDE_PROVIDER, apiKey);
|
|
4136
4110
|
updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_GPT_PROVIDER, apiKey);
|
|
4137
4111
|
}
|
|
4138
|
-
|
|
4112
|
+
syncExternalTools('codex', baseUrl, apiKey, { modelId });
|
|
4139
4113
|
writeSpinner2.succeed('配置写入完成');
|
|
4140
4114
|
|
|
4141
4115
|
console.log(chalk.green('\n✅ Codex 节点配置完成!'));
|
|
4142
|
-
|
|
4143
|
-
console.log(chalk.cyan(` ${providerName}${tag}: ${baseUrl}`));
|
|
4144
|
-
console.log(chalk.gray(` 模型: ${modelName}`));
|
|
4145
|
-
console.log(chalk.gray(' API Key: 已设置'));
|
|
4146
|
-
if (extSynced2.length > 0) console.log(chalk.gray(` 同步: ${extSynced2.join(', ')}`));
|
|
4116
|
+
console.log(chalk.cyan(` Codex: ${modelName}`));
|
|
4147
4117
|
if (repairResult.renamedProviders.length > 0) {
|
|
4148
|
-
console.log(chalk.
|
|
4118
|
+
console.log(chalk.cyan(` 已修复 provider 冲突: ${repairResult.renamedProviders.map(item => `${item.from}→${item.to}`).join(', ')}`));
|
|
4149
4119
|
}
|
|
4150
4120
|
printYunyiOpenClawSwitchHint(yunyiLayoutResult);
|
|
4151
4121
|
|
|
@@ -4330,22 +4300,15 @@ async function autoActivate(paths, args = {}) {
|
|
|
4330
4300
|
writeConfigWithSync(paths, config);
|
|
4331
4301
|
updateAuthProfilesWithSync(paths, claudeProviderName, apiKey);
|
|
4332
4302
|
updateAuthProfilesWithSync(paths, codexProviderName, apiKey);
|
|
4333
|
-
const extSynced = [];
|
|
4334
4303
|
const opencodeDefaultModelKey = isClaudePrimary ? `yunyi-claude/${claudeModelId}` : `yunyi-codex/${codexModelId}`;
|
|
4335
|
-
try {
|
|
4336
|
-
try {
|
|
4304
|
+
try { syncExternalTools('claude', claudeBaseUrl, apiKey, { codexBaseUrl, claudeModelId, opencodeDefaultModelKey }); } catch { /* ignore */ }
|
|
4305
|
+
try { syncExternalTools('codex', codexBaseUrl, apiKey, { modelId: codexModelId }); } catch { /* ignore */ }
|
|
4337
4306
|
writeSpinner.succeed('配置写入完成');
|
|
4338
4307
|
|
|
4339
4308
|
// ---- 输出结果 ----
|
|
4340
|
-
const primaryLabel = isClaudePrimary ? 'Claude' : 'GPT';
|
|
4341
4309
|
const selectedModel = isClaudePrimary ? claudeModel : codexModel;
|
|
4342
4310
|
console.log(chalk.green('\n✅ 配置完成!'));
|
|
4343
|
-
console.log(chalk.cyan(` 外部工具默认: ${selectedModel.name}
|
|
4344
|
-
console.log(chalk.gray(` 节点: ${selectedEndpoint.url} (${selectedEndpoint.name})`));
|
|
4345
|
-
console.log(chalk.gray(' API Key: 已设置'));
|
|
4346
|
-
if (extSynced.length > 0) console.log(chalk.gray(` 同步: ${extSynced.join(', ')}`));
|
|
4347
|
-
console.log(chalk.gray(' 若遇 certificate 报错,请新开终端或执行 source ~/.zshrc 后重试(已放宽 TLS 校验)'));
|
|
4348
|
-
console.log(chalk.gray(` 使用 OpenCode 时可在界面中切换 ${getOpencodeSwitchHint()};Codex 仅支持 GPT`));
|
|
4311
|
+
console.log(chalk.cyan(` 外部工具默认: ${selectedModel.name}`));
|
|
4349
4312
|
printYunyiOpenClawSwitchHint(yunyiLayoutResult);
|
|
4350
4313
|
|
|
4351
4314
|
const gwPort = config.gateway?.port || 18789;
|
|
@@ -4790,12 +4753,8 @@ async function yycodeQuickSetup(paths) {
|
|
|
4790
4753
|
|
|
4791
4754
|
// ---- 结果 ----
|
|
4792
4755
|
console.log(chalk.green('\n✅ 配置完成!'));
|
|
4793
|
-
console.log(chalk.cyan(` Claude Code: ${
|
|
4794
|
-
console.log(chalk.
|
|
4795
|
-
console.log(chalk.cyan(` Codex CLI: ${codexBaseUrl}`));
|
|
4796
|
-
console.log(chalk.gray(` 模型: ${codexModel.name}`));
|
|
4797
|
-
console.log(chalk.gray(' API Key: 已设置'));
|
|
4798
|
-
console.log(chalk.gray(' 同步: Claude Code settings, Opencode config, Codex CLI config'));
|
|
4756
|
+
console.log(chalk.cyan(` Claude Code: ${claudeModel.name}`));
|
|
4757
|
+
console.log(chalk.cyan(` Codex CLI: ${codexModel.name}`));
|
|
4799
4758
|
printYunyiOpenClawSwitchHint(yunyiLayoutResult);
|
|
4800
4759
|
console.log('');
|
|
4801
4760
|
}
|
|
@@ -5072,9 +5031,7 @@ async function selectNode(paths, type) {
|
|
|
5072
5031
|
if (managedGptKey) updateAuthProfilesWithSync(paths, YYMAXAPI_OPENCLAW_GPT_PROVIDER, managedGptKey);
|
|
5073
5032
|
|
|
5074
5033
|
console.log(chalk.green(`\n✅ ${typeLabel} 节点配置完成!`));
|
|
5075
|
-
console.log(chalk.cyan(`
|
|
5076
|
-
console.log(chalk.gray(` 模型: ${modelConfig.name} (主模型)`));
|
|
5077
|
-
console.log(chalk.gray(` API Key: ${oldApiKey ? '已设置' : '未设置'}`));
|
|
5034
|
+
console.log(chalk.cyan(` ${typeLabel}: ${modelConfig.name}`));
|
|
5078
5035
|
printYunyiOpenClawSwitchHint(yunyiLayoutResult);
|
|
5079
5036
|
}
|
|
5080
5037
|
|
|
@@ -5129,9 +5086,7 @@ async function activate(paths, type) {
|
|
|
5129
5086
|
writeAuthStore(paths.authProfiles, authStore);
|
|
5130
5087
|
|
|
5131
5088
|
console.log(chalk.green(`\n✅ 已激活 ${typeLabel}`));
|
|
5132
|
-
console.log(chalk.cyan(`
|
|
5133
|
-
console.log(chalk.gray(` 模型: ${modelConfig.name}`));
|
|
5134
|
-
console.log(chalk.gray(` API Key: 已设置`));
|
|
5089
|
+
console.log(chalk.cyan(` ${typeLabel}: ${modelConfig.name}`));
|
|
5135
5090
|
printYunyiOpenClawSwitchHint(yunyiLayoutResult);
|
|
5136
5091
|
}
|
|
5137
5092
|
|
|
@@ -5438,16 +5393,11 @@ async function testConnection(paths, args = {}) {
|
|
|
5438
5393
|
// 获取 Gateway 配置
|
|
5439
5394
|
const gatewayPort = config.gateway?.port || 18789;
|
|
5440
5395
|
|
|
5441
|
-
console.log(chalk.
|
|
5396
|
+
console.log(chalk.cyan(`当前测试: ${typeLabel}`));
|
|
5442
5397
|
if (testTarget.agentId) {
|
|
5443
|
-
console.log(chalk.
|
|
5444
|
-
}
|
|
5445
|
-
if (testTarget.agentId && testTarget.defaultPrimary && testTarget.defaultPrimary !== primary) {
|
|
5446
|
-
console.log(chalk.gray(`默认主入口: ${testTarget.defaultPrimary}`));
|
|
5398
|
+
console.log(chalk.cyan(`测试入口: ${testTarget.agentId}${testTarget.agentName ? ` (${testTarget.agentName})` : ''}`));
|
|
5447
5399
|
}
|
|
5448
|
-
console.log(chalk.
|
|
5449
|
-
console.log(chalk.gray(`模型: ${primary}`));
|
|
5450
|
-
console.log(chalk.gray(`Gateway: http://127.0.0.1:${gatewayPort}\n`));
|
|
5400
|
+
console.log(chalk.cyan(`模型: ${primary}\n`));
|
|
5451
5401
|
// 获取 Gateway token
|
|
5452
5402
|
const gatewayToken = config.gateway?.auth?.token;
|
|
5453
5403
|
if (!gatewayToken) {
|
|
@@ -5574,17 +5524,6 @@ async function testConnection(paths, args = {}) {
|
|
|
5574
5524
|
console.log(chalk.cyan(` Provider: ${cliResult.provider}`));
|
|
5575
5525
|
console.log(chalk.cyan(` Model: ${cliResult.model}`));
|
|
5576
5526
|
}
|
|
5577
|
-
if (cliResult.message) {
|
|
5578
|
-
const reply = sanitizeModelReply(cliResult.message, {
|
|
5579
|
-
provider: cliResult.provider,
|
|
5580
|
-
model: cliResult.model,
|
|
5581
|
-
modelKey: primary
|
|
5582
|
-
});
|
|
5583
|
-
console.log(chalk.yellow(` 模型回复: ${reply}`));
|
|
5584
|
-
}
|
|
5585
|
-
if (!isFallback) {
|
|
5586
|
-
console.log(chalk.gray(' 将继续验证 Web 鉴权端点(避免"CLI 正常但网页 401")...'));
|
|
5587
|
-
}
|
|
5588
5527
|
}
|
|
5589
5528
|
}
|
|
5590
5529
|
|
|
@@ -5615,7 +5554,6 @@ async function testConnection(paths, args = {}) {
|
|
|
5615
5554
|
const primaryApi = config.models?.providers?.[primaryProvider]?.api || '';
|
|
5616
5555
|
const isAnthropic = primaryApi.startsWith('anthropic');
|
|
5617
5556
|
const testEndpoint = isAnthropic ? '/v1/messages' : '/v1/chat/completions';
|
|
5618
|
-
console.log(chalk.gray(` 端点: http://127.0.0.1:${gatewayPort}${testEndpoint}`));
|
|
5619
5557
|
const startTime = Date.now();
|
|
5620
5558
|
let result = await testGatewayApi(gatewayPort, gatewayToken, primary, testEndpoint);
|
|
5621
5559
|
const latency = Date.now() - startTime;
|
|
@@ -5623,26 +5561,17 @@ async function testConnection(paths, args = {}) {
|
|
|
5623
5561
|
// 回退:如果首选端点返回 404/405,尝试另一个
|
|
5624
5562
|
if (!result.success && result.reachable && [404, 405].includes(result.status)) {
|
|
5625
5563
|
const fallbackEndpoint = isAnthropic ? '/v1/chat/completions' : '/v1/responses';
|
|
5626
|
-
console.log(chalk.gray(` ${testEndpoint} 不支持,回退测试 ${fallbackEndpoint}...`));
|
|
5627
5564
|
result = await testGatewayApi(gatewayPort, gatewayToken, primary, fallbackEndpoint);
|
|
5628
5565
|
}
|
|
5629
5566
|
|
|
5630
5567
|
// CLI 对话已成功 + Gateway 可达(404/405)= Dashboard 通过 WebSocket 工作,视为通过
|
|
5631
5568
|
if (!result.success && cliPassed && result.reachable && [404, 405].includes(result.status)) {
|
|
5632
5569
|
console.log(chalk.green(`\n✅ Gateway 测试通过`));
|
|
5633
|
-
console.log(chalk.cyan(` CLI 对话正常,Gateway 可达`));
|
|
5634
|
-
console.log(chalk.gray(` 注: Gateway Dashboard 通过 WebSocket 通信,REST 端点返回 405 属正常现象`));
|
|
5635
5570
|
console.log(chalk.green(`\n🌐 Web Dashboard 访问地址:`));
|
|
5636
5571
|
console.log(chalk.cyan(` http://127.0.0.1:${gatewayPort}/#token=${gatewayToken}`));
|
|
5637
5572
|
} else if (result.success) {
|
|
5638
|
-
console.log(chalk.green(`\n✅ Gateway
|
|
5573
|
+
console.log(chalk.green(`\n✅ Gateway 测试通过`));
|
|
5639
5574
|
console.log(chalk.cyan(` 响应时间: ${latency}ms`));
|
|
5640
|
-
const reply = sanitizeModelReply(result.message, {
|
|
5641
|
-
provider: providerName,
|
|
5642
|
-
model: primary.includes('/') ? primary.split('/')[1] : '',
|
|
5643
|
-
modelKey: primary
|
|
5644
|
-
});
|
|
5645
|
-
console.log(chalk.yellow(` 模型回复: ${reply}`));
|
|
5646
5575
|
console.log(chalk.green(`\n🌐 Web Dashboard 访问地址:`));
|
|
5647
5576
|
console.log(chalk.cyan(` http://127.0.0.1:${gatewayPort}/#token=${gatewayToken}`));
|
|
5648
5577
|
} else {
|