mihomo-cli 2.6.0 → 2.6.1

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/CHANGELOG.md CHANGED
@@ -1,11 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.6.1] - 2026-05-03
4
+
5
+ ### 修复
6
+
7
+ - **启动前配置校验** - 自动检测并修复 proxy-group 中引用不存在的节点/分组,避免内核启动失败
8
+ - 写入配置后使用 `mihomo -t` 做内核级校验,提前发现配置错误
9
+
10
+ ### 改进
11
+
12
+ - 移除已废弃的 `global-client-fingerprint` 配置项,消除内核启动时的 warning
13
+
14
+ ---
15
+
3
16
  ## [2.6.0] - 2026-05-03
4
17
 
5
18
  ### 改进
6
19
 
7
20
  - **统一使用 mixed-port**:用 `mixed-port: 7890` 替代原来的 `port: 7890` + `socks-port: 7891`,单端口同时支持 HTTP 和 SOCKS5
8
- - **BASE_CONFIG 优化**:新增 `unified-delay`、`tcp-concurrent`、`global-client-fingerprint`、`geo-auto-update`、`profile.store-selected`,不再依赖订阅自带这些配置
21
+ - **BASE_CONFIG 优化**:新增 `unified-delay`、`tcp-concurrent`、`geo-auto-update`、`profile.store-selected`,不再依赖订阅自带这些配置
9
22
  - **自动启用 sniffer**:检测到 `fake-ip` 模式时自动注入 sniffer 配置(嗅探 HTTP/TLS/QUIC),确保域名规则正常工作;订阅自带 sniffer 时不覆盖
10
23
 
11
24
  ---
package/dist/index.js CHANGED
@@ -2707,7 +2707,6 @@ var BASE_CONFIG = {
2707
2707
  "external-controller": "127.0.0.1:9090",
2708
2708
  "unified-delay": true,
2709
2709
  "tcp-concurrent": true,
2710
- "global-client-fingerprint": "chrome",
2711
2710
  "geo-auto-update": true,
2712
2711
  "geo-update-interval": 24,
2713
2712
  "geodata-mode": true,
@@ -3113,6 +3112,40 @@ function excludeOverwriteProxiesFromIncludeAll(config, overwriteFiles) {
3113
3112
  }
3114
3113
  }
3115
3114
  }
3115
+ var BUILTIN_PROXY_NAMES = /* @__PURE__ */ new Set(["DIRECT", "REJECT", "REJECT-DROP", "PASS", "COMPATIBLE"]);
3116
+ function validateProxyGroupDependencies(config) {
3117
+ const warnings = [];
3118
+ const proxies = config.proxies || [];
3119
+ const groups = config["proxy-groups"] || [];
3120
+ if (groups.length === 0) return warnings;
3121
+ const validNames = new Set(BUILTIN_PROXY_NAMES);
3122
+ for (const p of proxies) validNames.add(p.name);
3123
+ for (const g of groups) validNames.add(g.name);
3124
+ const removedGroups = /* @__PURE__ */ new Set();
3125
+ let changed = true;
3126
+ while (changed) {
3127
+ changed = false;
3128
+ for (const group of groups) {
3129
+ if (removedGroups.has(group.name)) continue;
3130
+ if (!Array.isArray(group.proxies)) continue;
3131
+ const invalid = group.proxies.filter((name) => !validNames.has(name));
3132
+ if (invalid.length === 0) continue;
3133
+ group.proxies = group.proxies.filter((name) => validNames.has(name));
3134
+ warnings.push(`proxy-group "${group.name}": \u79FB\u9664\u4E86\u4E0D\u5B58\u5728\u7684\u5F15\u7528 ${invalid.map((n) => `"${n}"`).join(", ")}`);
3135
+ const hasOtherSource = group.use || group["include-all"] || group["include-all-proxies"];
3136
+ if (group.proxies.length === 0 && !hasOtherSource) {
3137
+ removedGroups.add(group.name);
3138
+ validNames.delete(group.name);
3139
+ warnings.push(`proxy-group "${group.name}": \u5DF2\u79FB\u9664\uFF08\u65E0\u53EF\u7528\u8282\u70B9\uFF09`);
3140
+ changed = true;
3141
+ }
3142
+ }
3143
+ }
3144
+ if (removedGroups.size > 0) {
3145
+ config["proxy-groups"] = groups.filter((g) => !removedGroups.has(g.name));
3146
+ }
3147
+ return warnings;
3148
+ }
3116
3149
  function buildConfig(subRawContent, mode) {
3117
3150
  const subscriptionConfig = parseYamlOrJson(subRawContent, "\u8BA2\u9605\u5185\u5BB9");
3118
3151
  if (!subscriptionConfig) {
@@ -3166,7 +3199,22 @@ function buildConfig(subRawContent, mode) {
3166
3199
  "skip-domain": ["+.push.apple.com"]
3167
3200
  };
3168
3201
  }
3169
- return { config: merged, subscriptionConfig, overwriteFiles, systemConfig };
3202
+ const warnings = validateProxyGroupDependencies(merged);
3203
+ return { config: merged, subscriptionConfig, overwriteFiles, systemConfig, warnings };
3204
+ }
3205
+ function checkConfig() {
3206
+ if (!hasKernel() || !hasConfig()) return { ok: true, errors: [] };
3207
+ try {
3208
+ execSync(`"${PATHS.mihomoBinary}" -t -f "${PATHS.configFile}" 2>&1`, { encoding: "utf8" });
3209
+ return { ok: true, errors: [] };
3210
+ } catch (e) {
3211
+ const output = e.stdout || e.message || "";
3212
+ const errors = output.split("\n").filter((line) => line.includes("level=error") || line.includes("level=fatal")).map((line) => {
3213
+ const match = line.match(/msg="(.+)"/);
3214
+ return match ? match[1] : line;
3215
+ });
3216
+ return { ok: false, errors };
3217
+ }
3170
3218
  }
3171
3219
  function writeMihomoConfig(configObj) {
3172
3220
  ensureDirs();
@@ -4444,8 +4492,20 @@ function prepareConfigForStart(mode, subName = "default") {
4444
4492
  throw new Error(`\u672A\u627E\u5230\u8BA2\u9605\u914D\u7F6E "${subName}"\uFF0C\u8BF7\u5148\u6DFB\u52A0\u8BA2\u9605`);
4445
4493
  }
4446
4494
  const buildResult = buildConfig(rawContent, mode);
4495
+ if (buildResult.warnings.length > 0) {
4496
+ for (const warning of buildResult.warnings) {
4497
+ console.log(`${colors.yellow("\u81EA\u52A8\u4FEE\u590D:")} ${warning}`);
4498
+ }
4499
+ console.log("");
4500
+ }
4447
4501
  writeMihomoConfig(buildResult.config);
4448
4502
  writeDebugConfig(buildResult);
4503
+ const configCheck = checkConfig();
4504
+ if (!configCheck.ok) {
4505
+ const errorDetail = configCheck.errors.length > 0 ? configCheck.errors.join("\n ") : "\u672A\u77E5\u9519\u8BEF";
4506
+ throw new Error(`\u914D\u7F6E\u6821\u9A8C\u5931\u8D25:
4507
+ ${errorDetail}`);
4508
+ }
4449
4509
  const proxies = buildResult.config.proxies;
4450
4510
  const proxyGroups = buildResult.config["proxy-groups"];
4451
4511
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mihomo-cli",
3
- "version": "2.6.0",
3
+ "version": "2.6.1",
4
4
  "type": "module",
5
5
  "description": "A terminal-based mihomo (Clash.Meta) client for macOS",
6
6
  "bin": {