From 5859bfad2e4bc109ed383903daa3b90714fa0337 Mon Sep 17 00:00:00 2001 From: RyanVan <150385913+Ryson-32@users.noreply.github.com> Date: Wed, 24 Jun 2026 18:31:51 +0800 Subject: [PATCH 1/2] fix: narrow custom proxy group defaults --- .../core/src/generator/proxy-groups.test.ts | 71 ++++++++++++++++--- packages/core/src/generator/proxy-groups.ts | 7 +- .../actions/custom-actions.test.ts | 2 +- .../config-store/actions/custom-actions.ts | 2 +- 4 files changed, 65 insertions(+), 17 deletions(-) diff --git a/packages/core/src/generator/proxy-groups.test.ts b/packages/core/src/generator/proxy-groups.test.ts index cd7f7db..07a881a 100644 --- a/packages/core/src/generator/proxy-groups.test.ts +++ b/packages/core/src/generator/proxy-groups.test.ts @@ -141,7 +141,55 @@ describe("proxy group generator", () => { }); }); - it("keeps filtered-node custom groups node-scoped while exposing them as policy members", () => { + it("defaults ordinary custom groups to node-only members without adding them to node select", () => { + const groups = generateProxyGroups({ + nodes: [node("Node A"), node("Node B")], + enabledModules: ["select", "auto"], + ruleProviderBaseUrl: "https://rules.example.com", + testUrl: "https://probe.example.com/204", + testInterval: 120, + customProxyGroups: [ + customGroup("one", "select"), + customGroup("two", "select"), + customGroup("direct", "direct-first"), + customGroup("reject", "reject-first"), + ], + }); + + expect(groups.find((group) => group.name === "🚀 节点选择")?.proxies).toEqual([ + "⚡ 自动选择", + "DIRECT", + "REJECT", + "Node A", + "Node B", + ]); + expect(groups.find((group) => group.name === "Custom one")?.proxies).toEqual([ + "DIRECT", + "REJECT", + "Node A", + "Node B", + ]); + expect(groups.find((group) => group.name === "Custom two")?.proxies).toEqual([ + "DIRECT", + "REJECT", + "Node A", + "Node B", + ]); + expect(groups.find((group) => group.name === "Custom direct")?.proxies).toEqual([ + "DIRECT", + "REJECT", + "Node A", + "Node B", + ]); + expect(groups.find((group) => group.name === "Custom reject")?.proxies).toEqual([ + "REJECT", + "DIRECT", + "Node A", + "Node B", + ]); + }); + + it("keeps filtered-node custom groups node-scoped while exposing them as non-select policy members", () => { const groups = generateProxyGroups({ nodes: [node("Node A"), node("Node B"), node("Filtered")], proxyProviderNames: ["remote"], @@ -152,7 +200,7 @@ describe("proxy group generator", () => { customProxyGroups: [ { id: "filtered", - name: "Filtered", + name: "Filtered Group", emoji: "", memberSource: "filtered-nodes", includeInGroupMembers: true, @@ -163,25 +211,26 @@ describe("proxy group generator", () => { ], }); - expect(groups[0]?.name).toBe("Filtered"); - expect(groups.find((group) => group.name === "Filtered")?.proxies).toEqual([ + expect(groups[0]?.name).toBe("Filtered Group"); + expect(groups.find((group) => group.name === "Filtered Group")?.proxies).toEqual([ "DIRECT", "REJECT", "Node A", "Filtered", ]); - expect(groups.find((group) => group.name === "Filtered")).not.toHaveProperty("use"); - expect(groups.find((group) => group.name === "Filtered")?.proxies).not.toContain("Custom normal"); - expect(groups.find((group) => group.name === "Filtered")?.proxies).not.toContain("🚀 节点选择"); - expect(groups.find((group) => group.name === "Custom normal")?.proxies).toContain("Filtered"); + expect(groups.find((group) => group.name === "Filtered Group")).not.toHaveProperty("use"); + expect(groups.find((group) => group.name === "Filtered Group")?.proxies).not.toContain("Custom normal"); + expect(groups.find((group) => group.name === "Filtered Group")?.proxies).not.toContain("🚀 节点选择"); + expect(groups.find((group) => group.name === "Custom normal")?.proxies).not.toContain("Filtered Group"); + expect(groups.find((group) => group.name === "Custom normal")?.proxies).not.toContain("🚀 节点选择"); expect(groups.find((group) => group.name === "Custom normal")?.proxies).not.toContain("Custom normal"); expect(groups.find((group) => group.name === "Custom normal")).toMatchObject({ use: ["remote"] }); - expect(groups.find((group) => group.name === "🚀 节点选择")?.proxies).toContain("Filtered"); - expect(groups.find((group) => group.name === "🚀 节点选择")?.proxies).toContain("Custom normal"); + expect(groups.find((group) => group.name === "🚀 节点选择")?.proxies).not.toContain("Filtered Group"); + expect(groups.find((group) => group.name === "🚀 节点选择")?.proxies).not.toContain("Custom normal"); expect(groups.find((group) => group.name === "🏠 私有网络")?.proxies?.slice(0, 5)).toEqual([ "DIRECT", "REJECT", - "Filtered", + "Filtered Group", "Custom normal", "🚀 节点选择", ]); diff --git a/packages/core/src/generator/proxy-groups.ts b/packages/core/src/generator/proxy-groups.ts index edc7c2f..63d56d5 100644 --- a/packages/core/src/generator/proxy-groups.ts +++ b/packages/core/src/generator/proxy-groups.ts @@ -197,7 +197,7 @@ export function generateProxyGroups(options: GenerateOptions): ProxyGroup[] { "DIRECT", "REJECT" ); - const customBaseProxies = moduleBaseProxies; + const customBaseProxies = fallbackTargets("DIRECT", "REJECT", ...filteredNodeNames); const availableMemberProxyNames = fallbackTargets( "DIRECT", "REJECT", @@ -252,7 +252,6 @@ export function generateProxyGroups(options: GenerateOptions): ProxyGroup[] { autoTarget, "DIRECT", "REJECT", - ...customGroupNames, ...nodeNames ); groups.push({ @@ -408,7 +407,7 @@ export function generateProxyGroups(options: GenerateOptions): ProxyGroup[] { name: customGroup.name, type: "select", proxies: resolveCustom( - fallbackTargets("DIRECT", "REJECT", selectTarget, autoTarget, ...filteredNodeNames).filter( + fallbackTargets("DIRECT", "REJECT", ...filteredNodeNames).filter( (target) => target !== customGroup.name ) ), @@ -420,7 +419,7 @@ export function generateProxyGroups(options: GenerateOptions): ProxyGroup[] { name: customGroup.name, type: "select", proxies: resolveCustom( - fallbackTargets("REJECT", "DIRECT", selectTarget).filter( + fallbackTargets("REJECT", "DIRECT", ...filteredNodeNames).filter( (target) => target !== customGroup.name ) ), diff --git a/packages/ui/src/store/config-store/actions/custom-actions.test.ts b/packages/ui/src/store/config-store/actions/custom-actions.test.ts index 0658668..0404386 100644 --- a/packages/ui/src/store/config-store/actions/custom-actions.test.ts +++ b/packages/ui/src/store/config-store/actions/custom-actions.test.ts @@ -85,7 +85,7 @@ describe("custom config-store actions", () => { const groupId = getState().customProxyGroups[0].id; expect(groupId).toBe("custom-group-1767225600000"); expect(getState().customProxyGroups[0]).toEqual( - expect.objectContaining({ includeInGroupMembers: true }) + expect.objectContaining({ includeInGroupMembers: false }) ); actions.updateCustomProxyGroup(groupId, { diff --git a/packages/ui/src/store/config-store/actions/custom-actions.ts b/packages/ui/src/store/config-store/actions/custom-actions.ts index 4a3cc8b..a92dd87 100644 --- a/packages/ui/src/store/config-store/actions/custom-actions.ts +++ b/packages/ui/src/store/config-store/actions/custom-actions.ts @@ -140,7 +140,7 @@ export function createCustomActions( ...(typeof group.description === "string" ? { description: group.description.trim() } : {}), ...(group.memberSource === "filtered-nodes" ? { memberSource: "filtered-nodes" as const } : {}), includeInGroupMembers: - typeof group.includeInGroupMembers === "boolean" ? group.includeInGroupMembers : true, + typeof group.includeInGroupMembers === "boolean" ? group.includeInGroupMembers : false, groupType: group.groupType, ...(group.groupType === "load-balance" && group.strategy ? { strategy: group.strategy } : {}), ...(group.advanced ? { advanced: normalizeProxyGroupAdvancedConfig(group.advanced) } : {}), From c06bf1b099c5658cc140d71323f8125938a3ca43 Mon Sep 17 00:00:00 2001 From: RyanVan <150385913+Ryson-32@users.noreply.github.com> Date: Wed, 24 Jun 2026 18:51:37 +0800 Subject: [PATCH 2/2] chore: bump public version to v2.5.1 --- README-CN.md | 2 +- README.md | 2 +- docs/release-notes.md | 40 +++++++++++++++++----------------------- local/package.json | 2 +- package-lock.json | 6 +++--- package.json | 2 +- 6 files changed, 24 insertions(+), 30 deletions(-) diff --git a/README-CN.md b/README-CN.md index 6497d91..421d12d 100644 --- a/README-CN.md +++ b/README-CN.md @@ -4,7 +4,7 @@

SubBoost

平台:Linux + Docker - 版本 2.5.0 + 版本 2.5.1 在线入口 文档 GHCR 镜像 diff --git a/README.md b/README.md index 54eeac5..27a159c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@

SubBoost

Platform: Linux + Docker - Version 2.5.0 + Version 2.5.1 Online app Documentation GHCR image diff --git a/docs/release-notes.md b/docs/release-notes.md index a15cf83..7c045e0 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,49 +1,43 @@ -# SubBoost v2.5.0 +# SubBoost v2.5.1 ## 中文 ### 更新重点 -SubBoost v2.5.0 主要改善代理组编辑、自部署更新和订阅生成稳定性。建议 v2.4.0 用户升级。 +SubBoost v2.5.1 是一个修复版本,主要修复自定义代理组的默认成员逻辑,并提升自部署安装、更新时的版本来源稳定性。建议 v2.5.0 用户升级。 ### 主要变化 -- **移除筛选代理组**,相关功能转移到分流代理组高级模式和自定义分流组。 -- 分流代理组高级模式支持按来源、地区、关键词和排除条件整理节点。 -- 订阅生成更稳,规则顺序、代理组输出和常见 Mihomo 字段处理减少了意外变化。 -- 节点导入兼容性更好,覆盖更多常见节点链接和 Mihomo YAML 配置。 -- 自部署安装和更新流程更可靠,`subboost update`、状态检查和失败提示都有改进。 -- Dashboard 下载订阅 YAML 的行为更接近直接访问订阅链接,文件名和响应头更稳定。 -- 首次安装后的管理员初始化、登录和数据库连接更稳,减少安装完成后进不去后台的情况。 -- 安全和发布检查加强,降低公开包、安装资产和更新流程出错的风险。 +- 修复新建自定义代理组时默认成员过宽的问题,避免默认生成出“节点选择”和自定义组互相引用的循环配置。 +- `🚀 节点选择` 默认不再自动包含自定义代理组,减少代理组套娃导致配置异常或预览卡顿的风险。 +- 新建普通自定义代理组默认只包含 `DIRECT`、`REJECT` 和真实节点,保留高级模式里的手动配置能力。 +- 改进自部署安装和 `subboost update` 的版本来源处理,稳定版安装资产会默认固定到对应 release 版本。 +- 改进自部署管理脚本的更新来源,减少从指定版本更新时意外跟随其它发布通道的风险。 ### 升级说明 - 建议升级前备份 `/opt/subboost/.env` 和数据库,方便需要时回滚。 -- 已安装 v2.4.0 的自部署实例可以继续使用 `subboost update` 更新。 +- 已安装 v2.5.0 的自部署实例可以继续使用 `subboost update` 更新。 - 普通订阅转换、模板和规则功能不需要手动改环境变量。 -- 如果你在 v2.4.0 使用过筛选代理组,请升级后到自定义代理组或分流代理组高级模式里重新配置。 +- 已经手动配置过的高级代理组不会被自动改写;本次主要改变新建和默认生成行为。 ## English ### Highlights -SubBoost v2.5.0 mainly improves proxy group editing, self-hosted updates, and subscription generation stability. v2.4.0 users are encouraged to upgrade. +SubBoost v2.5.1 is a patch release that fixes default custom proxy group membership and improves version-source stability for self-hosted install and update flows. v2.5.0 users are encouraged to upgrade. ### Main Changes -- Removed filtered proxy groups. Related features have moved to proxy group advanced mode and custom proxy groups. -- Proxy group advanced mode supports organizing nodes by source, region, keyword, and exclusion rules. -- Made subscription generation more stable, reducing unexpected changes in rule order, proxy group output, and common Mihomo fields. -- Improved node import compatibility for more common node links and Mihomo YAML configurations. -- Made self-hosted install and update flows more reliable, including `subboost update`, status checks, and failure messages. -- Dashboard YAML downloads now behave more like direct subscription links, with steadier filenames and response headers. -- Improved first-install admin setup, login, and database connection reliability to reduce post-install access issues. -- Strengthened safety and release checks to reduce the risk of problems in public packages, install assets, and updates. +- Fixed overly broad default members for newly created custom proxy groups, preventing default configurations where node selection and custom groups reference each other in a loop. +- `🚀 节点选择` no longer automatically includes custom proxy groups by default, reducing the risk of nested proxy group loops causing invalid output or preview slowdowns. +- Newly created normal custom proxy groups now default to `DIRECT`, `REJECT`, and real nodes only, while manual advanced configuration remains available. +- Improved self-hosted install and `subboost update` version-source handling so stable release assets stay pinned to the matching release version by default. +- Improved the self-hosted manager update source to reduce the risk of a pinned-version update unexpectedly following another release channel. ### Upgrade Notes - Back up `/opt/subboost/.env` and the database before upgrading so rollback is easier if needed. -- Existing v2.4.0 self-hosted installations can continue to update with `subboost update`. +- Existing v2.5.0 self-hosted installations can continue to update with `subboost update`. - Normal subscription conversion, templates, and rules do not require manual environment-variable changes. -- If you used filtered proxy groups in v2.4.0, reconfigure them after upgrading through custom proxy groups or proxy group advanced mode. +- Manually configured advanced proxy groups are not rewritten automatically; this release mainly changes new and default generated behavior. diff --git a/local/package.json b/local/package.json index a57f440..86c48f8 100644 --- a/local/package.json +++ b/local/package.json @@ -1,6 +1,6 @@ { "name": "@subboost/local", - "version": "2.5.0", + "version": "2.5.1", "license": "AGPL-3.0-only", "private": true, "type": "module", diff --git a/package-lock.json b/package-lock.json index 3340d5f..ec0d0d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "subboost", - "version": "2.5.0", + "version": "2.5.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "subboost", - "version": "2.5.0", + "version": "2.5.1", "license": "AGPL-3.0-only", "workspaces": [ "packages/*", @@ -67,7 +67,7 @@ }, "local": { "name": "@subboost/local", - "version": "2.5.0", + "version": "2.5.1", "license": "AGPL-3.0-only", "dependencies": { "@prisma/adapter-pg": "^7.8.0", diff --git a/package.json b/package.json index def6930..795f5dc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "subboost", - "version": "2.5.0", + "version": "2.5.1", "license": "AGPL-3.0-only", "private": true, "engines": {