yymaxapi 1.0.118 → 1.0.120
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
CHANGED
|
@@ -16,7 +16,7 @@ npx yymaxapi@latest
|
|
|
16
16
|
npx yymaxapi@latest speed-test
|
|
17
17
|
```
|
|
18
18
|
或在具体配置命令后追加 `--speed-test`,按测速结果手动选点。
|
|
19
|
-
如需直接切换到其他云翼域名,可在预设/一键激活命令后追加 `--endpoint-url https://yunyi.
|
|
19
|
+
如需直接切换到其他云翼域名,可在预设/一键激活命令后追加 `--endpoint-url https://yunyi.yun`,也兼容 `--base-url https://你的域名/claude` 这种写法。
|
|
20
20
|
|
|
21
21
|
**方式二:一键配置 Claude**
|
|
22
22
|
```bash
|
package/bin/yymaxapi.js
CHANGED
|
@@ -1646,12 +1646,18 @@ function invalidateGatewayEnvCache() {
|
|
|
1646
1646
|
function isWslAvailable() {
|
|
1647
1647
|
if (process.platform !== 'win32') return false;
|
|
1648
1648
|
if (_wslAvailCache !== null) return _wslAvailCache;
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1649
|
+
const probes = [
|
|
1650
|
+
'wsl -- echo ok',
|
|
1651
|
+
'wsl -u root -- echo ok'
|
|
1652
|
+
];
|
|
1653
|
+
for (const cmd of probes) {
|
|
1654
|
+
const result = safeExec(cmd, { timeout: 5000 });
|
|
1655
|
+
if (result.ok && String(result.output || result.stdout || '').includes('ok')) {
|
|
1656
|
+
_wslAvailCache = true;
|
|
1657
|
+
return _wslAvailCache;
|
|
1658
|
+
}
|
|
1654
1659
|
}
|
|
1660
|
+
_wslAvailCache = false;
|
|
1655
1661
|
return _wslAvailCache;
|
|
1656
1662
|
}
|
|
1657
1663
|
|
|
@@ -3840,7 +3846,7 @@ function scoreHermesWslCandidate(candidate) {
|
|
|
3840
3846
|
}
|
|
3841
3847
|
|
|
3842
3848
|
function getHermesWslMirrorInfo(options = {}) {
|
|
3843
|
-
if (process.platform !== 'win32'
|
|
3849
|
+
if (process.platform !== 'win32') {
|
|
3844
3850
|
return {
|
|
3845
3851
|
dataDir: null,
|
|
3846
3852
|
sourceConfigPath: null,
|
|
@@ -3886,7 +3892,8 @@ function getHermesWslMirrorInfo(options = {}) {
|
|
|
3886
3892
|
sourceConfigPath,
|
|
3887
3893
|
configPath: candidate.configPath,
|
|
3888
3894
|
envPath: candidate.envPath,
|
|
3889
|
-
target: candidate.target
|
|
3895
|
+
target: candidate.target,
|
|
3896
|
+
commandPath: selected?.commandPath || probeHermesWslCommand(candidate.target)
|
|
3890
3897
|
};
|
|
3891
3898
|
}
|
|
3892
3899
|
|
|
@@ -4109,6 +4116,36 @@ function readHermesCliConfig() {
|
|
|
4109
4116
|
};
|
|
4110
4117
|
}
|
|
4111
4118
|
|
|
4119
|
+
function buildHermesCliConfigFromRaw(configRaw, envRaw, configPath = '', envPath = '') {
|
|
4120
|
+
const parsed = parseSimpleYamlConfig(configRaw);
|
|
4121
|
+
const envEntries = parseEnvFile(envRaw);
|
|
4122
|
+
const modelConfig = parsed?.model && typeof parsed.model === 'object' ? parsed.model : {};
|
|
4123
|
+
const modelId = String(modelConfig.default || '').trim() || getDefaultClaudeModel().id;
|
|
4124
|
+
const provider = String(modelConfig.provider || '').trim().toLowerCase();
|
|
4125
|
+
const type = resolveHermesModelType(modelId, provider);
|
|
4126
|
+
const apiKey = type === 'codex'
|
|
4127
|
+
? (envEntries.OPENAI_API_KEY || '')
|
|
4128
|
+
: (envEntries.ANTHROPIC_API_KEY || envEntries.ANTHROPIC_TOKEN || '');
|
|
4129
|
+
|
|
4130
|
+
return {
|
|
4131
|
+
configPath,
|
|
4132
|
+
envPath,
|
|
4133
|
+
configured: !!configRaw || !!envRaw,
|
|
4134
|
+
modelId,
|
|
4135
|
+
provider,
|
|
4136
|
+
type,
|
|
4137
|
+
baseUrl: String(modelConfig.base_url || '').trim(),
|
|
4138
|
+
apiKey
|
|
4139
|
+
};
|
|
4140
|
+
}
|
|
4141
|
+
|
|
4142
|
+
function readHermesWslCliConfig(wslMirror = getHermesWslMirrorInfo()) {
|
|
4143
|
+
const configPath = wslMirror.sourceConfigPath || wslMirror.configPath;
|
|
4144
|
+
const configRaw = readWslTextFile(configPath, wslMirror.target);
|
|
4145
|
+
const envRaw = readWslTextFile(wslMirror.envPath, wslMirror.target);
|
|
4146
|
+
return buildHermesCliConfigFromRaw(configRaw, envRaw, configPath, wslMirror.envPath);
|
|
4147
|
+
}
|
|
4148
|
+
|
|
4112
4149
|
function getOpencodeConfigPath() {
|
|
4113
4150
|
const home = os.homedir();
|
|
4114
4151
|
return process.platform === 'win32'
|
|
@@ -4368,6 +4405,9 @@ function testCodexCliConnection() {
|
|
|
4368
4405
|
|
|
4369
4406
|
function testHermesCliConnection() {
|
|
4370
4407
|
const cliBinary = resolveCommandBinary('hermes');
|
|
4408
|
+
if (!cliBinary && process.platform === 'win32') {
|
|
4409
|
+
return testHermesWslCliConnection();
|
|
4410
|
+
}
|
|
4371
4411
|
if (!cliBinary) return { name: 'Hermes CLI', status: 'skipped', detail: '未安装 hermes 命令' };
|
|
4372
4412
|
|
|
4373
4413
|
const config = readHermesCliConfig();
|
|
@@ -4413,6 +4453,40 @@ function testHermesCliConnection() {
|
|
|
4413
4453
|
};
|
|
4414
4454
|
}
|
|
4415
4455
|
|
|
4456
|
+
function testHermesWslCliConnection() {
|
|
4457
|
+
const wslMirror = getHermesWslMirrorInfo();
|
|
4458
|
+
const commandPath = wslMirror.commandPath || probeHermesWslCommand(wslMirror.target || {});
|
|
4459
|
+
if (!commandPath) return { name: 'Hermes CLI (WSL)', status: 'skipped', detail: '未检测到 WSL 内 hermes 命令' };
|
|
4460
|
+
|
|
4461
|
+
const config = readHermesWslCliConfig(wslMirror);
|
|
4462
|
+
if (!config.configured) return { name: 'Hermes CLI (WSL)', status: 'skipped', detail: '未检测到 WSL ~/.hermes/config.yaml 或 ~/.hermes/.env' };
|
|
4463
|
+
if (!config.apiKey) return { name: 'Hermes CLI (WSL)', status: 'failed', detail: 'Hermes 配置缺少 API Key' };
|
|
4464
|
+
|
|
4465
|
+
const providerArg = config.provider === 'anthropic' ? ' --provider anthropic' : '';
|
|
4466
|
+
const command = [
|
|
4467
|
+
`export HERMES_HOME=${shellQuote(wslMirror.dataDir)}`,
|
|
4468
|
+
'export NODE_TLS_REJECT_UNAUTHORIZED=0',
|
|
4469
|
+
'export NODE_NO_WARNINGS=1',
|
|
4470
|
+
'set -a',
|
|
4471
|
+
`[ -f "$HERMES_HOME/.env" ] && . "$HERMES_HOME/.env"`,
|
|
4472
|
+
'set +a',
|
|
4473
|
+
`${shellQuote(commandPath)} chat -Q -q ${shellQuote('请只回复 OK')}${providerArg}`
|
|
4474
|
+
].join('; ');
|
|
4475
|
+
const result = runWslCommand(command, { timeout: 120000, maxBuffer: 1024 * 1024 }, { ...(wslMirror.target || {}), login: true });
|
|
4476
|
+
const combined = cleanCliTestOutput(`${result.output || ''}\n${result.stdout || ''}\n${result.stderr || ''}`);
|
|
4477
|
+
const reply = extractHermesCliReply(combined);
|
|
4478
|
+
|
|
4479
|
+
if (result.ok && /^OK$/i.test(reply) && !looksLikeCliTestError(combined)) {
|
|
4480
|
+
return { name: 'Hermes CLI (WSL)', status: 'success', detail: 'OK' };
|
|
4481
|
+
}
|
|
4482
|
+
|
|
4483
|
+
return {
|
|
4484
|
+
name: 'Hermes CLI (WSL)',
|
|
4485
|
+
status: 'failed',
|
|
4486
|
+
detail: reply || summarizeCliTestOutput(combined) || result.error || '命令执行失败'
|
|
4487
|
+
};
|
|
4488
|
+
}
|
|
4489
|
+
|
|
4416
4490
|
async function testAdditionalCliConnections(args = {}, options = {}) {
|
|
4417
4491
|
if (args['no-app-test'] || args.noAppTest) return;
|
|
4418
4492
|
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
```json5
|
|
14
14
|
{
|
|
15
15
|
"endpoints": [
|
|
16
|
-
{ "name": "默认主节点", "url": "https://yunyi.
|
|
17
|
-
{ "name": "CF国外节点1", "url": "https://cdn2.yunyi.
|
|
16
|
+
{ "name": "默认主节点", "url": "https://yunyi.yun" },
|
|
17
|
+
{ "name": "CF国外节点1", "url": "https://cdn2.yunyi.yun" }
|
|
18
18
|
],
|
|
19
19
|
"fallbackEndpoints": [
|
|
20
20
|
{ "name": "备用节点1", "url": "http://47.99.42.193" },
|
|
@@ -75,7 +75,7 @@ npx yymaxapi@latest
|
|
|
75
75
|
```json
|
|
76
76
|
{
|
|
77
77
|
"provider": "anthropic",
|
|
78
|
-
"base_url": "https://yunyi.
|
|
78
|
+
"base_url": "https://yunyi.yun/claude",
|
|
79
79
|
"api": "anthropic-messages",
|
|
80
80
|
"api_key": "<你的云翼 API Key>",
|
|
81
81
|
"model": {
|
|
@@ -90,7 +90,7 @@ npx yymaxapi@latest
|
|
|
90
90
|
```json
|
|
91
91
|
{
|
|
92
92
|
"provider": "openai",
|
|
93
|
-
"base_url": "https://yunyi.
|
|
93
|
+
"base_url": "https://yunyi.yun/codex",
|
|
94
94
|
"api": "openai-completions",
|
|
95
95
|
"api_key": "<你的云翼 API Key>",
|
|
96
96
|
"model": {
|
|
@@ -121,7 +121,7 @@ npx yymaxapi@latest
|
|
|
121
121
|
```json
|
|
122
122
|
{
|
|
123
123
|
"provider": "anthropic",
|
|
124
|
-
"base_url": "https://yunyi.
|
|
124
|
+
"base_url": "https://yunyi.yun/claude",
|
|
125
125
|
"api": "anthropic-messages",
|
|
126
126
|
"api_key": "<你的云翼 API Key>",
|
|
127
127
|
"model": {
|
|
@@ -136,7 +136,7 @@ npx yymaxapi@latest
|
|
|
136
136
|
```json
|
|
137
137
|
{
|
|
138
138
|
"provider": "openai",
|
|
139
|
-
"base_url": "https://yunyi.
|
|
139
|
+
"base_url": "https://yunyi.yun/codex",
|
|
140
140
|
"api": "openai-completions",
|
|
141
141
|
"api_key": "<你的云翼 API Key>",
|
|
142
142
|
"model": {
|
|
@@ -152,10 +152,10 @@ npx yymaxapi@latest
|
|
|
152
152
|
|
|
153
153
|
```json
|
|
154
154
|
{
|
|
155
|
-
"apiBaseUrl": "https://yunyi.
|
|
155
|
+
"apiBaseUrl": "https://yunyi.yun/claude",
|
|
156
156
|
"env": {
|
|
157
157
|
"ANTHROPIC_API_KEY": "<你的云翼 API Key>",
|
|
158
|
-
"ANTHROPIC_BASE_URL": "https://yunyi.
|
|
158
|
+
"ANTHROPIC_BASE_URL": "https://yunyi.yun/claude"
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
```
|