yingclaw 2.5.7 → 2.5.12
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 +4 -3
- package/lib/autostart.js +50 -0
- package/lib/config.js +1 -1
- package/lib/desktop.js +29 -1
- package/lib/gateway.js +31 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -62,7 +62,7 @@ claw gateway
|
|
|
62
62
|
| 阿里云百炼 | qwen3-max | qwen3.5-plus |
|
|
63
63
|
| MiniMax | MiniMax-M2.7 | MiniMax-M2.7-Turbo |
|
|
64
64
|
| 智谱 GLM | GLM-4.7 | GLM-5-Turbo |
|
|
65
|
-
| 小米 MiMo | mimo-v2.5-pro | mimo-v2
|
|
65
|
+
| 小米 MiMo | mimo-v2.5-pro | mimo-v2.5 |
|
|
66
66
|
| 自定义接口 | 自动获取或手动输入 | — |
|
|
67
67
|
|
|
68
68
|
DeepSeek 的 `[1m]` 后缀是真实 API 模型 ID,表示 100 万 token 上下文窗口([官方说明](https://api-docs.deepseek.com/zh-cn/quick_start/agent_integrations/claude_code))。
|
|
@@ -93,9 +93,9 @@ claw setup # 兼容旧命令:config + code
|
|
|
93
93
|
|
|
94
94
|
| 平台 | 终端接入 | 桌面接入 |
|
|
95
95
|
|------|---------|---------|
|
|
96
|
-
| macOS | ✅ 写入 `~/.zshrc` | ✅
|
|
96
|
+
| macOS | ✅ 写入 `~/.zshrc` | ✅ 自动启动本机 Gateway 并重启 Claude Desktop |
|
|
97
97
|
| Linux / WSL | ✅ 写入 `~/.zshrc` / `~/.bashrc` | — |
|
|
98
|
-
| Windows | ✅ 写入用户级环境变量(需重开终端) | ✅ 写入 `%APPDATA%\Claude-3p
|
|
98
|
+
| Windows | ✅ 写入用户级环境变量(需重开终端) | ✅ 写入 `%APPDATA%\Claude-3p\`,并写入登录启动脚本 |
|
|
99
99
|
|
|
100
100
|
## 原理
|
|
101
101
|
|
|
@@ -115,6 +115,7 @@ CLAUDE_CODE_EFFORT_LEVEL
|
|
|
115
115
|
- macOS / Windows:写入 `Claude-3p/configLibrary/` 中的 yingclaw entry
|
|
116
116
|
- Claude Desktop 访问 `http://127.0.0.1:18080/yingclaw`
|
|
117
117
|
- Gateway 再转发到当前保存的 Anthropic 兼容接口
|
|
118
|
+
- macOS 使用 LaunchAgent 登录启动 Gateway,Windows 使用 Startup 目录脚本登录启动 Gateway
|
|
118
119
|
- 终端接入仍直接使用 `ANTHROPIC_*` 环境变量,不受桌面 Gateway 影响
|
|
119
120
|
|
|
120
121
|
使用 `inferenceProvider=gateway`、`inferenceGatewayAuthScheme=bearer`,将 Gateway Base URL 指向 yingclaw 本机 Gateway。高级用户可用 `claw desktop --direct` 保留旧式直连写入,但新版 Claude Desktop 可能拒绝非 Claude 模型名。
|
package/lib/autostart.js
CHANGED
|
@@ -4,6 +4,7 @@ const path = require('path');
|
|
|
4
4
|
const { spawnSync } = require('child_process');
|
|
5
5
|
|
|
6
6
|
const GATEWAY_LAUNCH_AGENT_LABEL = 'com.yingclaw.gateway';
|
|
7
|
+
const WINDOWS_GATEWAY_STARTUP_SCRIPT = 'yingclaw-gateway.cmd';
|
|
7
8
|
|
|
8
9
|
function xmlEscape(value) {
|
|
9
10
|
return String(value)
|
|
@@ -19,6 +20,12 @@ function getMacLaunchAgentPath(options = {}) {
|
|
|
19
20
|
return path.join(homeDir, 'Library', 'LaunchAgents', `${GATEWAY_LAUNCH_AGENT_LABEL}.plist`);
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
function getWindowsStartupScriptPath(options = {}) {
|
|
24
|
+
const homeDir = options.homeDir || os.homedir();
|
|
25
|
+
const appData = options.appData || process.env.APPDATA || path.join(homeDir, 'AppData', 'Roaming');
|
|
26
|
+
return path.join(appData, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup', WINDOWS_GATEWAY_STARTUP_SCRIPT);
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
function buildMacLaunchAgentPlist(options = {}) {
|
|
23
30
|
const nodePath = options.nodePath || process.execPath;
|
|
24
31
|
const cliPath = options.cliPath || path.join(__dirname, '..', 'bin', 'cli.js');
|
|
@@ -54,6 +61,19 @@ function buildMacLaunchAgentPlist(options = {}) {
|
|
|
54
61
|
`;
|
|
55
62
|
}
|
|
56
63
|
|
|
64
|
+
function buildWindowsGatewayStartupScript(options = {}) {
|
|
65
|
+
const nodePath = options.nodePath || process.execPath;
|
|
66
|
+
const cliPath = options.cliPath || path.join(__dirname, '..', 'bin', 'cli.js');
|
|
67
|
+
const workingDirectory = options.workingDirectory || path.join(__dirname, '..');
|
|
68
|
+
|
|
69
|
+
return [
|
|
70
|
+
'@echo off',
|
|
71
|
+
`cd /d "${workingDirectory}"`,
|
|
72
|
+
`start "" /min "${nodePath}" "${cliPath}" gateway`,
|
|
73
|
+
'',
|
|
74
|
+
].join('\r\n');
|
|
75
|
+
}
|
|
76
|
+
|
|
57
77
|
function runLaunchctl(runner, args, options = {}) {
|
|
58
78
|
const result = runner('launchctl', args, { encoding: 'utf8', stdio: 'pipe' });
|
|
59
79
|
if (result.status !== 0 && !options.optional) {
|
|
@@ -92,8 +112,24 @@ function waitForLaunchAgentUnload(runner, service, options = {}) {
|
|
|
92
112
|
} while (true);
|
|
93
113
|
}
|
|
94
114
|
|
|
115
|
+
function isWindowsPortListening(runner, port) {
|
|
116
|
+
const result = runner('powershell.exe', [
|
|
117
|
+
'-NoProfile',
|
|
118
|
+
'-Command',
|
|
119
|
+
`if (Get-NetTCPConnection -LocalAddress 127.0.0.1 -LocalPort ${Number(port)} -State Listen -ErrorAction SilentlyContinue) { 'LISTEN' }`,
|
|
120
|
+
], { encoding: 'utf8', stdio: 'pipe', windowsHide: true });
|
|
121
|
+
return result.status === 0 && /LISTEN/i.test(`${result.stdout || ''}\n${result.stderr || ''}`);
|
|
122
|
+
}
|
|
123
|
+
|
|
95
124
|
function installGatewayAutostart(options = {}) {
|
|
96
125
|
const platform = options.platform || process.platform;
|
|
126
|
+
if (platform === 'win32') {
|
|
127
|
+
const file = options.file || getWindowsStartupScriptPath(options);
|
|
128
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
129
|
+
fs.writeFileSync(file, buildWindowsGatewayStartupScript(options), 'utf8');
|
|
130
|
+
return { result: 'installed', file };
|
|
131
|
+
}
|
|
132
|
+
|
|
97
133
|
if (platform !== 'darwin') {
|
|
98
134
|
return { result: 'unsupported', file: null };
|
|
99
135
|
}
|
|
@@ -133,6 +169,18 @@ function installGatewayAutostart(options = {}) {
|
|
|
133
169
|
|
|
134
170
|
function getGatewayAutostartStatus(options = {}) {
|
|
135
171
|
const platform = options.platform || process.platform;
|
|
172
|
+
if (platform === 'win32') {
|
|
173
|
+
const file = options.file || getWindowsStartupScriptPath(options);
|
|
174
|
+
const runner = options.runner || spawnSync;
|
|
175
|
+
const port = options.port || 18080;
|
|
176
|
+
return {
|
|
177
|
+
supported: true,
|
|
178
|
+
installed: fs.existsSync(file),
|
|
179
|
+
running: isWindowsPortListening(runner, port),
|
|
180
|
+
file,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
136
184
|
if (platform !== 'darwin') {
|
|
137
185
|
return { supported: false, installed: false, running: false, file: null };
|
|
138
186
|
}
|
|
@@ -162,7 +210,9 @@ function getGatewayAutostartStatus(options = {}) {
|
|
|
162
210
|
module.exports = {
|
|
163
211
|
GATEWAY_LAUNCH_AGENT_LABEL,
|
|
164
212
|
buildMacLaunchAgentPlist,
|
|
213
|
+
buildWindowsGatewayStartupScript,
|
|
165
214
|
getGatewayAutostartStatus,
|
|
166
215
|
getMacLaunchAgentPath,
|
|
216
|
+
getWindowsStartupScriptPath,
|
|
167
217
|
installGatewayAutostart,
|
|
168
218
|
};
|
package/lib/config.js
CHANGED
|
@@ -75,7 +75,7 @@ const PROVIDERS = {
|
|
|
75
75
|
name: '小米 MiMo',
|
|
76
76
|
baseUrl: 'https://api.xiaomimimo.com/anthropic',
|
|
77
77
|
modelsUrl: 'https://api.xiaomimimo.com/v1/models',
|
|
78
|
-
fastModel: 'mimo-v2
|
|
78
|
+
fastModel: 'mimo-v2.5',
|
|
79
79
|
models: [
|
|
80
80
|
{ name: 'MiMo V2.5 Pro(旗舰)', value: 'mimo-v2.5-pro' },
|
|
81
81
|
{ name: 'MiMo V2.5(均衡)', value: 'mimo-v2.5' },
|
package/lib/desktop.js
CHANGED
|
@@ -22,6 +22,12 @@ const DESKTOP_GATEWAY_KEYS = [
|
|
|
22
22
|
'disableDeploymentModeChooser',
|
|
23
23
|
'deploymentOrganizationUuid',
|
|
24
24
|
];
|
|
25
|
+
const MAC_POLICY_KEYS = [
|
|
26
|
+
...DESKTOP_GATEWAY_KEYS,
|
|
27
|
+
'inferenceGatewayHeaders',
|
|
28
|
+
'isClaudeCodeForDesktopEnabled',
|
|
29
|
+
'coworkEgressAllowedHosts',
|
|
30
|
+
];
|
|
25
31
|
|
|
26
32
|
function buildRuntimeEnterpriseConfig(entry) {
|
|
27
33
|
return {
|
|
@@ -109,6 +115,13 @@ function buildClaudeDesktopMacDefaultsCommands(entry) {
|
|
|
109
115
|
];
|
|
110
116
|
}
|
|
111
117
|
|
|
118
|
+
function buildClaudeDesktopMacDefaultsDeleteCommands() {
|
|
119
|
+
return MAC_POLICY_KEYS.map((key) => ({
|
|
120
|
+
command: 'defaults',
|
|
121
|
+
args: ['delete', MAC_POLICY_BUNDLE, key],
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
|
|
112
125
|
function writeClaudeDesktopMacDefaults(entry) {
|
|
113
126
|
for (const { command, args } of buildClaudeDesktopMacDefaultsCommands(entry)) {
|
|
114
127
|
const result = spawnSync(command, args, { encoding: 'utf8' });
|
|
@@ -118,6 +131,13 @@ function writeClaudeDesktopMacDefaults(entry) {
|
|
|
118
131
|
}
|
|
119
132
|
}
|
|
120
133
|
|
|
134
|
+
function clearClaudeDesktopMacDefaults(options = {}) {
|
|
135
|
+
const runner = options.runner || spawnSync;
|
|
136
|
+
for (const { command, args } of buildClaudeDesktopMacDefaultsDeleteCommands()) {
|
|
137
|
+
runner(command, args, { encoding: 'utf8', stdio: 'pipe' });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
121
141
|
function buildClaudeDesktopEnterpriseConfig(config, options = {}) {
|
|
122
142
|
const gatewayConfig = ensureDesktopGatewayConfig(config, options);
|
|
123
143
|
const models = serializeGatewayModels(gatewayConfig);
|
|
@@ -282,9 +302,16 @@ function clearClaudeDesktopConfig(options = {}) {
|
|
|
282
302
|
|
|
283
303
|
// Clear configLibrary regardless of whether the main config file exists
|
|
284
304
|
const libResult = clearClaudeDesktopConfigLibrary({ ...options, dataDir });
|
|
305
|
+
const shouldClearPlatformPolicy = (options.platform || process.platform) === 'darwin'
|
|
306
|
+
&& !options.dataDir
|
|
307
|
+
&& !options.configFile
|
|
308
|
+
&& options.writePlatformPolicy !== false;
|
|
309
|
+
if (shouldClearPlatformPolicy) {
|
|
310
|
+
clearClaudeDesktopMacDefaults(options);
|
|
311
|
+
}
|
|
285
312
|
|
|
286
313
|
if (!file || !fs.existsSync(file)) {
|
|
287
|
-
return { result: libResult.result === 'updated' ? 'updated' : 'missing', file, dataDir };
|
|
314
|
+
return { result: libResult.result === 'updated' || shouldClearPlatformPolicy ? 'updated' : 'missing', file, dataDir };
|
|
288
315
|
}
|
|
289
316
|
|
|
290
317
|
const current = readJsonFile(file);
|
|
@@ -383,6 +410,7 @@ module.exports = {
|
|
|
383
410
|
buildClaudeDesktopEnterpriseConfig,
|
|
384
411
|
buildClaudeDesktopDirectEnterpriseConfig,
|
|
385
412
|
buildClaudeDesktopMacDefaultsCommands,
|
|
413
|
+
buildClaudeDesktopMacDefaultsDeleteCommands,
|
|
386
414
|
buildClaudeDesktopOpenCommands,
|
|
387
415
|
clearClaudeDesktopConfig,
|
|
388
416
|
getClaudeDesktopConfigLibraryDir,
|
package/lib/gateway.js
CHANGED
|
@@ -7,6 +7,16 @@ const YINGCLAW_GATEWAY_PREFIX = '/yingclaw';
|
|
|
7
7
|
const DESKTOP_ROUTE_SPECS = [
|
|
8
8
|
{ id: 'claude-sonnet-4-6', displayName: 'Sonnet', upstreamKey: 'model' },
|
|
9
9
|
{ id: 'claude-haiku-4-5', displayName: 'Haiku', upstreamKey: 'fastModel' },
|
|
10
|
+
{ id: 'claude-opus-4-7', displayName: 'Opus' },
|
|
11
|
+
{ id: 'claude-sonnet-4-5', displayName: 'Sonnet' },
|
|
12
|
+
{ id: 'claude-haiku-4-0', displayName: 'Haiku' },
|
|
13
|
+
{ id: 'claude-opus-4-1', displayName: 'Opus' },
|
|
14
|
+
{ id: 'claude-sonnet-4-0', displayName: 'Sonnet' },
|
|
15
|
+
{ id: 'claude-haiku-3-5', displayName: 'Haiku' },
|
|
16
|
+
{ id: 'claude-opus-3-0', displayName: 'Opus' },
|
|
17
|
+
{ id: 'claude-sonnet-3-7', displayName: 'Sonnet' },
|
|
18
|
+
{ id: 'claude-sonnet-3-5', displayName: 'Sonnet' },
|
|
19
|
+
{ id: 'claude-haiku-3-0', displayName: 'Haiku' },
|
|
10
20
|
];
|
|
11
21
|
const ONE_M_CONTEXT_SUFFIX = ' [1M]';
|
|
12
22
|
|
|
@@ -48,21 +58,28 @@ function desktopRouteLabel(routeId) {
|
|
|
48
58
|
return is1m ? `${label} 1M` : label;
|
|
49
59
|
}
|
|
50
60
|
|
|
61
|
+
function isDesktopChatModel(model) {
|
|
62
|
+
return !/(^|[-_])(tts|voice|voiceclone|voicedesign|speech|audio|image|video|embedding|embed|rerank|moderation)([-_]|$)/i
|
|
63
|
+
.test(String(model || ''));
|
|
64
|
+
}
|
|
65
|
+
|
|
51
66
|
function buildDesktopGatewayRoutes(config) {
|
|
52
67
|
const fastModel = config.fastModel || config.model;
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
68
|
+
const configuredModels = [config.model, fastModel];
|
|
69
|
+
const providerModels = Array.isArray(config.availableModels) ? config.availableModels : [];
|
|
70
|
+
const upstreamModels = [...new Set([...configuredModels, ...providerModels].filter(Boolean))]
|
|
71
|
+
.filter(isDesktopChatModel);
|
|
72
|
+
|
|
73
|
+
return upstreamModels.slice(0, DESKTOP_ROUTE_SPECS.length).map((upstreamModel, index) => {
|
|
74
|
+
const spec = DESKTOP_ROUTE_SPECS[index];
|
|
75
|
+
const supports1m = modelSupports1m(upstreamModel);
|
|
76
|
+
return {
|
|
77
|
+
id: desktopRouteId(spec.id, supports1m),
|
|
78
|
+
displayName: spec.displayName,
|
|
79
|
+
upstreamModel,
|
|
80
|
+
supports1m,
|
|
81
|
+
};
|
|
82
|
+
});
|
|
66
83
|
}
|
|
67
84
|
|
|
68
85
|
function buildDesktopGatewayMappingRows(config) {
|
|
@@ -262,6 +279,7 @@ module.exports = {
|
|
|
262
279
|
createGatewayKey,
|
|
263
280
|
ensureDesktopGatewayConfig,
|
|
264
281
|
modelSupports1m,
|
|
282
|
+
isDesktopChatModel,
|
|
265
283
|
stripOneMContextSuffix,
|
|
266
284
|
desktopRouteId,
|
|
267
285
|
desktopRouteLabel,
|