fix: never rewrite rules to a smart group that does not exist (#2036)

The generated Smart override creates the "Smart Group" conditionally but
rewrites rules unconditionally, so the rules can end up pointing at a
group that was never added.

Two reachable cases:

  - The group is only created when `config.proxies` is a non-empty array.
    A subscription that ships only `proxy-providers` (which the app
    explicitly accepts) skips creation, yet every non-builtin rule target
    is still replaced with the literal string 'Smart Group'.

  - When the profile already contains a `type: smart` group under a
    different name, `smartGroupExists` becomes true so nothing is
    created, and the existing group is never renamed - but the rules are
    still rewritten to 'Smart Group'.

In both cases the generated config.yaml references a missing proxy
group, so the core refuses to start ("proxy Smart Group not found") and
the app is left with no working core.

Track the name of the smart group that actually exists - the existing
group's own name, or 'Smart Group' when one was created - and use it for
the replacement. When neither applies, skip rule rewriting entirely and
leave the profile's own targets untouched.

Closes #885

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
MOMO0302-02
2026-08-21 03:04:47 -07:00
committed by GitHub
parent f9c841a6f6
commit 7caecd6474

View File

@@ -184,11 +184,15 @@ function main(config) {
console.log('[Smart Override] No url-test or load-balance groups found, executing original logic')
// 查找现有的 Smart 代理组并更新
// smartGroupName 记录「实际存在且可被规则引用」的组名:命中已有组时是它自己的名字,
// 新建时才是 'Smart Group'。规则替换必须用这个名字,否则会指向不存在的组。
let smartGroupExists = false
let smartGroupName = ''
for (let i = 0; i < config['proxy-groups'].length; i++) {
const group = config['proxy-groups'][i]
if (group && group.type === 'smart') {
smartGroupExists = true
smartGroupName = group.name
console.log('[Smart Override] Found existing smart group:', group.name)
if (!group['policy-priority']) {
@@ -221,6 +225,7 @@ function main(config) {
proxies: proxyNames
}
config['proxy-groups'].unshift(smartGroup)
smartGroupName = 'Smart Group'
console.log('[Smart Override] Created smart group at first position with proxies:', proxyNames)
} else {
console.log('[Smart Override] No valid proxies found, skipping smart group creation')
@@ -230,7 +235,11 @@ function main(config) {
}
// 处理规则替换
if (config.rules && Array.isArray(config.rules)) {
// 只有在确实存在可引用的 smart 组时才改写规则。否则(订阅只有 proxy-providers、
// 没有顶层 proxies因而没能建组会把规则目标指向一个不存在的组内核直接启动失败。
if (!smartGroupName) {
console.log('[Smart Override] No usable smart group, skipping rule replacement')
} else if (config.rules && Array.isArray(config.rules)) {
console.log('[Smart Override] Processing rules, original count:', config.rules.length)
// 收集所有代理组名称
@@ -296,9 +305,9 @@ function main(config) {
!ruleParams.has(targetValue))
if (shouldReplace) {
parts[targetIndex] = 'Smart Group'
parts[targetIndex] = smartGroupName
replacedCount++
console.log('[Smart Override] Replaced rule target:', targetValue, '→ Smart Group')
console.log('[Smart Override] Replaced rule target:', targetValue, '→', smartGroupName)
return parts.join(',')
}
}
@@ -322,16 +331,16 @@ function main(config) {
!ruleParams.has(targetValue))
if (shouldReplace) {
rule[targetField] = 'Smart Group'
rule[targetField] = smartGroupName
replacedCount++
console.log('[Smart Override] Replaced rule target:', targetValue, '→ Smart Group')
console.log('[Smart Override] Replaced rule target:', targetValue, '→', smartGroupName)
}
}
}
return rule
})
console.log('[Smart Override] Rules processed, replaced', replacedCount, 'non-DIRECT rules with Smart Group')
console.log('[Smart Override] Rules processed, replaced', replacedCount, 'non-DIRECT rules with', smartGroupName)
} else {
console.log('[Smart Override] No rules found or rules is not an array')
}