BBSMC Logo
模组整合包光影资源包软件汉化插件数据包地图
登录
模组插件数据包光影资源包整合包软件汉化地图
登录
设置
发芽启动器(FayaLaunch)

发芽启动器(FayaLaunch)

一个功能丰富的启动器,集多种功能与一身,一个工具便是多个工具。对新手,上手快,与PCL2一样,10分钟玩上整合包;对老手,有着齐全的工具。含全新的tailscale联机(P2P),对海外环境友好,一个完全免费,可以自动修复游戏崩溃的AI助手,还支持下载与启动服务端,插件。

72025 days ago
发芽启动器(FayaLaunch)

发芽启动器(FayaLaunch)

一个功能丰富的启动器,集多种功能与一身,一个工具便是多个工具。对新手,上手快,与PCL2一样,10分钟玩上整合包;对老手,有着齐全的工具。含全新的tailscale联机(P2P),对海外环境友好,一个完全免费,可以自动修复游戏崩溃的AI助手,还支持下载与启动服务端,插件。

72
0

基本信息

我的世界Java版本

平台

Windows
BBSMC 创作者激励广告

创作者

发芽的挪威张班
发芽的挪威张班 Member

详情信息

许可证 MIT
发布于 2026-08-28
更新于 2026-09-05
简介更新日志版本百科反馈讨论

基础功能已经全部正常。

by 发芽的挪威张班 on 2026 Sep 05
下载

2026-09-05 · 发芽启动器 v1.1.4 — 下载/搜索/整合包/联机/更新 全面修复与打包

改动文件:main.py、gen_wxs3.py、build_msi_102.py;版本号 1.1.3 → 1.1.4


一、资源下载 / 搜索

  1. 国内镜像优先:Modrinth API 与文件 CDN 走 MCIM 镜像,多镜像按本机实测延迟/失败率自动排序、失败回退官方;forge/neoforge 加载器安装器加 BMCLAPI /maven 镜像。
  2. 自适应并发 _AdaptiveGate(4~48,AIMD:全成功 +4、失败率 ≥25% 减半、≥10% -2),整合包文件镜像优先。
  3. 缓存写盘节流(threading.Timer,最小间隔 2s)修 GIL 饿死导致的界面冻结;缓存条目兼容 dict/tuple 双形态,修 curseforge_files 的 KeyError: 0 崩溃。
  4. 中英同搜 CN_FEATURE_MAP(~85 词条)合并结果、保持相关性排序、图标重绘防抖、结果上限 80。
  5. 版本列表加载全链路不再抛异常拖垮资源详情页。

二、整合包 / 前置模组

  1. fileSize 字段修正(旧读 size 恒 0 → 显示 0MB、多一次探测);整合包强制 Modrinth 源;sha1 + zip 校验;失败日志落盘。
  2. 加载器识别 _mrpack_loader_from_deps:fabric 用 fabric-loader、quilt 用 quilt_loader(旧只找 fabric/quilt → fabric 整合包被当无加载器、继承原版 → 一个模组都不加载)。_mrpack_loader_version_id 探测真实安装目录名让 inheritsFrom 指对。修复 Better Minecraft 等 fabric 包零模组加载。
  3. 前置识别/下载全部改走镜像:修 api.modrinth.com 被墙时「自动补装前置」整体静默失效(_mr_fetch_api / 新增 _mr_download_dep)。
  4. 新增源站无关前置解析:读 jar 内嵌 fabric.mod.json / mods.toml(_mod_jar_meta),CurseForge-only 模组的强制前置也能识别并按 Modrinth 精确 slug 补装,查不到的显式列出。

三、红石联机 / 急速启动 / 皮肤

  1. 红石联机不再写死 25565:_rs_open 探测本机真实 MC 端口(_srv_scan_ports + _mc_ping),探测不到弹框手填;内核要求端口确有 Java 服务端监听,poll 现能报「隧道被拒」。
  2. 急速启动:natives 首次解压持久化 .natives.ok 标记,跳过每次启动的重复解压扫描。
  3. 皮肤同步:_skins_sync_to_game 里 CSL 自动安装移入独立 try,落位成功即返回 True(不再被 CSL 异常误判失败)。

四、自动更新(重写)

  1. 修根因:_fetch_update_info 首行 _http_get_json 对 HTML 页抛 JSONDecodeError 未捕获 → 启动检查静默失败、弹窗永不出现。现三级容错(自托管 JSON → BBSMC 接口 → HTML 兜底)。
  2. 检测改走 BBSMC Modrinth 兼容接口 api.<host>/v2/project/<slug>/version(无盾,取最新版号+zip直链+sha1+changelog),比抓 HTML 稳。
  3. 更新器 _apply_update_mode 兼容两种包:BBSMC 免安装(顶层 FayaLauncher/、无 manifest)与 build_update(扁平 + manifest 白名单);_find_update_root 定位根;旧 manifest 读取提前到覆盖前修清理逻辑;排除 versions/config/auth 等玩家数据绝不删。
  4. 下载后校验 is_zipfile + sha1/sha256;BBSMC cdn 直链带 JS 防下载盾(纯 HTTP 只拿到 55 字节验证页)→ 优雅降级为引导浏览器下载 + 提示 update_source.txt;源码运行态不自更新。

五、Bug 检索(pyflakes 全量 + 人工复查)

  • 修 3 处 self.after(0, lambda: ... str(e) ...):except 的 e 在块结束被删、延迟回调触发 NameError(红石安装 / 更新 / 检查更新);改默认参快照 lambda _e=str(e)。
  • 修服务端模组同步「版本不一致跳过」引用未定义 loader_key → 改从 .faya_meta 读 loader。
  • 更新下载去掉 known_size(避免 175MB 触发 Range 多线程、撞盾直接失败而绕过盾检测)。

六、验证

  • 语法编译通过;pyflakes 无 undefined-name / referenced-before-assignment。
  • 冒烟 test_smoke.py:143 通过 / 0 失败(此前基线 142/1,皮肤同步项已修复)。
  • 自动更新自测(临时脚本,已删):真实 BBSMC 解析 → latest=1.1.3 + url + sha1 + changelog;免安装包覆盖 exe / 新增 _internal / 保留玩家存档 / 包内 versions 不落地 / 临时目录清理;manifest 包按白名单清理旧产品文件。全过。
  • 打包:build_msi_102 产出 dist\发芽启动器-1.1.4.msi(≈147.7MB)+ 发芽启动器-1.1.4-win64.zip(≈166.99MB,1239 文件,顶层 FayaLauncher/,与更新器免安装包识别一致)。

七、备注

  • 需重启启动器生效。
  • 现本地已 1.1.4、BBSMC 上最新仍为 1.1.3,故 1.1.4 用户暂不弹更新;把 1.1.4 发布到 BBSMC 后,1.1.3 老用户即可被检测到并提示更新。

bug修复

by 发芽的挪威张班 on 2026 Aug 29
下载

修复了版本下载无法重命名,模组错乱的恶性bug

修复了大量bug,并更新了不少使用功能

by 发芽的挪威张班 on 2026 Aug 29
下载

开发日志

2026-08-28 · 发芽启动器 v1.1.0 — 僵尸代码清理与功能接入

改动文件:D:\AI\P\fy\main.py(17811 行 → 17131 行,净减 680 行)


一、接上的功能(原「代码完整、只差入口」)

  1. 多账号管理入口
  • 设置页「离线玩家名 → 保存」按钮后新增 👥 多账号管理 按钮,打开 _acct_show_dialog 弹窗(添加 / 切换 / 删除离线账号)。
  • 同时删除多账号的第二套重复定义(L9351 区):它与第一套同名且覆盖后者,导致弹窗里 self._acct_add() 命中需要 name 参数的版本而抛 TypeError。保留 L9141 完整版(含弹窗输入与列表 UI 重建),该隐患随删除消除。
  1. 微软正版皮肤上传
  • 皮肤页「📦 安装 CSL」后新增 ⬆ 上传到正版账号 按钮 → _ms_change_skin → _ms_upload_skin(Mojang API PUT multipart)。
  • 未登录正版账号时内部已有提示,不会出错。
  1. 首次运行欢迎引导(后台自动)
  • __init__ 中 self.after(1200, self._show_first_setup),仅在 launcher_config.json 不存在时弹窗,老用户静默。
  1. AI 助手首用引导(后台自动)
  • AI 页构建末尾调用 _check_first_run(),ai_config.json 不存在时给出模型源 / Key 配置提示。
  1. 加载器自修复(后台自动)
  • 启动流程 _launch_flow 中,在 load_version_json 之前调用 _repair_loader_shell + _rebuild_forge_shell,fabric / quilt / forge 版本 json 缺加载器参数时自动从官方 meta 源重建(顺序不能颠倒,否则读到的是损坏 json)。

二、删除的代码(共 696 行)

类别 内容
拖放安装(已证实不可用) _enable_drag_drop(WndProc 子类化钩子,70 行)、_on_drop_files、_poll_queue 里 _drop_pending 投递块、__init__ 的初始化与提示日志
历史兼容壳(对齐 0.2.11 命名) 15 个纯转发方法:_net_e4mc_worker _net_srv_worker _net_srv_java _net_srv_copy _net_room_detect_servers _net_room_mods_list _on_net_room _on_net_ts _on_ai_test_result _make_default_skin_png _skins_ensure_defaults _skins_set_active _skins_refresh_lib _ts_copy_ip _ts_down _net_room_check_dialog(转发目标均存活,零风险)
重复实现(有活替代品) _ai_test_conn + _ai_test_conn_worker、_gen_error_report、_ai_open_skills、_ai_clear_chat、_ai_open_memory、_ai_show_signup、_save_mem_mode、_nav_hover、_ai_net_task、_hall_post/_hall_fetch、_net_room_stop、_tc_room_code_display、_tc_backend、_osx_only_lib、_save_client_id、_show_cid_help、_make_readonly_text、_ai_is_rate_limited、多账号第二套定义
开发者模式旧入口 _dev_lock_click(「关于页标题连点 5 次」版本,从未绑定控件)
死类 CardView(约 144 行,全项目从未实例化)

保留说明:拖放的识别/安装核心 _drop_identify、_on_drop_pack、_drop_install_legacy、_drop_install_modrinth 是「导入整合包」按钮的共用链路,已保留,导入功能不受影响。开发者模式现唯一入口为关于页标题鼠标中键(_dev_unlock_dialog)。


三、验证结果

  • 语法编译:通过
  • 方法清单差分对比(删除前 604 项 → 删除后 550 项):新增 0 项,消失项与计划完全一致,无误删
  • 冒烟测试 test_smoke.py:143 通过 / 0 失败

四、遗留备注

  • 冒烟测试「CF 翻页」项存在偶发失败:同一份代码连续运行 4 次,首次报 142/1、后 3 次 143/0。与本次改动无关(改动前基线也是 143/0),推测是 _MR_CACHE 缓存状态在用例间共享导致,建议后续单独排查。
  • 开发者模式入口目前是隐藏的(关于页标题鼠标中键),如需显式入口可在设置页加按钮。
  • 项目根目录仍有大量开发期残留脚本(recon*.py、main_rebuild.py、main_bad/main_recovered/main_restored.py、ui_refine.py、kanban-work/ 等),非产品代码,可另行清理。

2026-08-28(2)· 修复 Forge 1.20.1 启动崩溃(线上事故)

事故现象:下载 1.20.1 Forge 版本(版本目录 D:\发芽启动器\versions\AI测试)后无法启动。

一、已修复:启动器自身缺陷(根因 1)

问题:MinecraftLauncher._resolve_libraries() 对继承型版本(整合包/Forge)会沿继承链把原版 jar 加入 classpath,最终混入 versions\1.20.1\1.20.1.jar。

后果:Forge 1.20.1 的 Minecraft 类实际由 libraries\net\minecraftforge\forge\1.20.1-47.0.50\forge-1.20.1-47.0.50-client.jar 提供(FML 的 MinecraftLocator 将其加载为 minecraft 模块)。原版 jar 同时存在时会被 ModLauncher 转成模块 _1._20._1,两个模块导出同名包,启动即中止:

java.lang.module.ResolutionException: Modules _1._20._1 and minecraft
export package net.minecraft.util.profiling.jfr.event to module customskinloader

补充:Forge json 的 -DignoreList=…,AI测试.jar 本意是跳过版本自身 jar,但启动器实际混入的是继承来的 1.20.1.jar,名字对不上导致 ignoreList 失效。

修复:_resolve_libraries() 中,当 mainClass 含 bootstraplauncher(Forge 47+)且存在对应的 forge-<mc>-<ver>-client.jar 时,跳过原版 jar(Forge client jar 由 FML 自行加载)。client jar 不存在时仍走原逻辑兜底,不影响其他版本。

验证:classpath 已不含 1.20.1.jar;移走 mods 后游戏正常启动(资源/纹理/声音引擎全部就绪)。冒烟测试 143 通过 / 0 失败。

二、未修复(非启动器缺陷,需决策)

  1. CustomSkinLoader 与 Forge 1.20.1 不兼容
  • 启动器为「离线显示皮肤」自动安装的 CustomSkinLoader_Universal-15.0.1.jar,其运行时释放的 CustomSkinLoader-Common.jar 内含 net/minecraft/client/renderer/IImageBuffer.class,被转成 customskinloader 模块后导出 net.minecraft.client.renderer,与 minecraft 模块冲突。
  • 已验证:单独保留 CSL、移走匠魂仍必崩,即 CSL 自身即可搞崩 Forge 1.20.1。
  • 已验证无效的规避手段:把 customskinloader 追加进 -DignoreList(Common jar 为 CSL 运行时释放,不受启动时 ignoreList 控制)。
  1. 匠魂缺少前置模组
  • TConstruct-1.20.1-3.11.2.166.jar 依赖 mantle(要求 >=1.11.97),当前 mods 目录未安装,Forge 会因强制依赖缺失拒绝启动。

三、建议后续动作

  • CSL:启动器在 Forge 1.20.1+ 场景应不再自动安装 CSL,并在启动前检测已装 CSL 时提示/自动禁用(待确认方案后再实施)。
  • 模组依赖:可增加启动前依赖检测,提示缺失的强制前置并提供一键补装。

2026-08-28(3)· CSL 与 Forge 47+ 冲突防护(落实上节遗留方案)

改动文件:D:\AI\P\fy\main.py

一、改动内容

  1. 新增 _is_forge_module_launch(vi, data=None)
  • 判断版本是否为 Forge 47+ 模块化启动(mainClass 含 bootstraplauncher)。
  • 该场景下 Minecraft 类由 forge-<mc>-<ver>-client.jar 提供,CSL 与 minecraft 模块导出同名包 net.minecraft.client.renderer,混用必崩(对应上节根因 2 的 CSL 部分)。
  • 可复用 _launch_flow 已加载的 data,避免重复读 json。
  1. _skins_ensure_csl(gd, vi=None) 增加 Forge 47+ 守卫
  • 自动安装 CSL 前先判定 _is_forge_module_launch,命中则直接 return False 跳过自动安装。
  • 仅拦截「皮肤同步触发的后台自动安装」;用户手动点「📦 安装 CSL」仍可强制安装,不拦截。
  1. 新增 _forge_csl_guard(vi)(启动前自动禁用已装 CSL)
  • 在 _launch_flow 皮肤同步前调用;命中 Forge 47+ 时扫描游戏目录 mods/,把 customskinloader*.jar 改名 <name>.jar.disabled(可手动恢复),并写日志 warn + toast 提示。
  • 解决「CSL 自身即可搞崩 Forge 1.20.1」的遗留问题(对应上节根因 2)。
  1. _launch_flow 插入防护调用
  • 皮肤同步(3.6)前新增 3.5 步 self._forge_csl_guard(vi)。

二、验证

  • 语法编译:python -m py_compile main.py 通过
  • IDE 静态检查:0 错误 / 0 警告

三、遗留

  • 模组强制依赖检测(如匠魂缺 mantle)仍未实施,留待后续。

2026-08-28(4)· 错误报告正则诊断(AI 更好分析 / 玩家更易看懂)

需求:错误报告加正则匹配,让 AI 分析更简单,玩家页更容易看懂。改动文件:D:\AI\P\fy\main.py(仅 main.py)

一、新增:崩溃诊断规则库(模块级,位于 version_has_loader 之后)

ERROR_PATTERNS(16 类,按顺序匹配,越具体越靠前)每类含 name(机器标识)/ title(玩家可读标题)/ pat(正则)/ cause(通俗原因)/ fix(可执行建议):

name 玩家看到的标题 典型命中
module_conflict 模组模块冲突(Forge 模块化启动) java.lang.module.ResolutionException、Modules X and Y export package
mod_missing_dep 模组缺少前置依赖 Missing or unsupported mandatory dependencies、Mod X requires Y
mod_duplicate 模组重复安装 DuplicateModsFoundException、Found duplicate mod
mod_load_fail 模组加载失败 ModLoadingException、Failed to load mod
mixin_fail 模组注入失败(Mixin 错误) MixinApplyError、Mixin apply for ... failed
java_version Java 版本不匹配 UnsupportedClassVersionError、class file version 61.0
jvm_crash Java 虚拟机崩溃 EXCEPTION_ACCESS_VIOLATION、SIGSEGV、hs_err_pid
out_of_memory 内存不足 OutOfMemoryError、Could not reserve enough space for object heap
opengl 显卡 / OpenGL 错误 GLException、Pixel format not accelerated、GLFW error
natives_missing 本地库(natives)缺失 no xxx in java.library.path、Failed to locate library
java_not_found Java 未找到或无法启动 CreateProcess error=2、Could not find or load main class
auth_fail 登录验证失败 Invalid session、ForbiddenOperationException
download_fail 游戏文件下载 / 校验失败 Failed to download、SHA-1 mismatch
mod_incompatible 模组与游戏版本不匹配 NoSuchMethodError、NoClassDefFoundError
port_in_use 端口被占用(联机失败) Address already in use
runtime_error 游戏内部错误(空指针等) NullPointerException 等

配套三个函数:

  • extract_error_evidence(log_text, pat) — 抽关键日志:命中处上下文窗口(前 2 后 14)+ Caused by 根因链(≤6 条),去重、单行截 300 字符、上限 24 行;无命中时退化为「尾部含错误关键词的行」,过滤掉 INFO 噪声。
  • diagnose_crash(log_text, exit_code) — 返回 {name,title,cause,fix,match,evidence};未命中时 name='unknown' 并按退出码给兜底标题(1=启动失败、-1=被强制结束、0=异常退出、其他=带退出码)。
  • format_diagnosis(diag) — 格式化为纯文本段(类型 / 通俗原因 / 建议操作 / 关键日志片段),弹窗、报告正文、AI 输入三处复用。

统一忽略大小写:规则定义后统一 re.compile(pat, re.I) 重编译。实测 MC / Forge 日志大小写不固定(如 missing or unsupported mandatory dependencies),不加 re.I 会漏判。

二、接入点(4 处)

  1. _show_error_report(玩家页弹窗)
  • 标题由「游戏异常退出(退出码 1)」改为分类标题(如「模组缺少前置依赖」);
  • 顶部两行新增:🔍 通俗原因(灰色)、🛠 建议操作(绿色),自动换行;
  • 正文由「原始日志尾部 4000 字符」改为 format_diagnosis(结构化摘要 + 去噪关键片段);
  • 窗口 560x360 → 620x500;原始提示(含退出码)降级显示在版本/日志信息区。
  1. _build_error_report_content(导出报告正文)
  • 在【AI 诊断】之前新增【错误分类】(启动器自动识别)整段,_last_diag 缺失时回读 game-latest.log 重新诊断。
  1. _ai_auto_analyze(AI 请求)
  • user 消息在日志前插入三行结构化摘要(启动器自动识别 / 可能原因 / 建议操作);
  • 日志正文改为「去噪关键片段 + --- 原始日志片段 --- + 原文前 4000 字符」,上限 8000(原 5000);
  • 提示语改为「请结合上面的自动识别结果分析日志」。
  1. game_exit 分支(崩溃触发)
  • 读 game-latest.log → diagnose_crash(log, code) → 结果缓存到 self._last_diag,供弹窗 / 导出 / AI 三处复用同一份结论;
  • 弹窗标题、AI 分析标题、崩溃历史 error_type 统一用分类标题;
  • 崩溃历史新增 error_kind(机器标识,便于日后统计)与 exit_code 字段(详情面板为 JSON 全量展示,无需改 UI)。

三、验证

  • 语法编译:python -m py_compile main.py 通过;IDE 静态检查 0 错误 / 0 警告。
  • 规则库自测(临时脚本,已删除):9 条典型日志用例(模块冲突 / 缺依赖 / Java 版本 / 内存 / OpenGL / 模组重复 / Mixin / natives / 无匹配)全部命中预期类别,退出码兜底 4 种(0 / 1 / -1 / 3221225477)标题正确。
    • 过程中发现并修复:规则未加 re.I 导致「缺少前置依赖」被「模组加载失败」抢先命中(顺序在前但大小写不匹配),已统一重编译为忽略大小写。

四、备注

  • 规则表是数据驱动的,后续新增错误类型只需往 ERROR_PATTERNS 追加一条,无需改其他代码。
  • 匹配采用「首个命中」而非打分,因此新增规则时要注意顺序:更具体的错误必须排在泛化规则(如 mod_load_fail、runtime_error)之前。

2026-08-28(5)· AI 自动修复新增 fix_mixin 专用工具(解决"没有 mixin 工具")

现象:用 AI 助手修复「模组注入失败」(Mixin 错误)的版本时,模型回复"没有 mixin 工具"——AGENT_TOOLS 工具列表里确实没有任何 Mixin 相关工具,弱模型只会找名字带 "mixin" 的工具,无法完成修复。改动文件:D:\AI\P\fy\main.py(仅 main.py)

一、新增工具 fix_mixin

  1. 工具定义(AGENT_TOOLS):位于 get_mods 之后。描述明确指引:"遇到 MixinApplyError / Mixin apply failed / Mixin transformation of ... failed / InvalidMixinException 等注入类错误时务必用此工具,不要手动猜测模组"。参数:log(必填,崩溃日志/错误报告文本)、version(可选,版本 ID,默认当前选中版本)。

  2. 实现 _tool_fix_mixin(args)(模块级,位于 _tool_get_mods 之后):

  • 解析:正则提取 Mixin apply for mod X failed、from mod X(InvalidMixinException 格式)命中的模组 id(去重、清理特殊字符);另提取 Mixin transformation of <类> failed 的目标类作为参考信息。
  • 定位 mods 目录:优先用版本 json 的 game_dir / mc_dir(经 _APP_REF.versions),兜底 LAUNCHER_DIR\versions\<vid>\game\mods 与 \mods;vid 为空时用当前选中版本。
  • 匹配并禁用:按模组 id 与 jar 文件名做忽略大小写 / 忽略连字符匹配,把命中 jar 重命名为 .disabled;同一文件去重,避免重复禁用。
  • 返回:禁用成功的文件列表、点名但未匹配的模组 id、Mixin 注入目标类、mods 目录路径;完全无法解析时给出明确提示(不是让模型自己猜)。
  1. 注册:AGENT_TOOL_IMPL 加 "fix_mixin": _tool_fix_mixin;AGENT_TOOL_LEVEL 加 "fix_mixin": 1(高级权限,会修改 mods 目录;普通模式弹窗确认,高级模式全自动)。

二、_ai_auto_fix 提示词引导(错误报告弹窗的「AI 自动修复」)

  • system prompt 追加:"遇到 Mixin 注入失败(MixinApplyError / Mixin apply failed / Mixin transformation of ... failed / InvalidMixinException)时,必须调用 fix_mixin 工具(log 传崩溃报告文本,version 传版本 ID),由它自动定位并禁用问题模组,不要自行猜测模组。"
  • user 消息开头带上当前版本 ID:当前修复的版本 ID:<vid>,让模型调用 fix_mixin 时能填对 version 参数。
  • _on_ai_fix_confirm 调用 _ai_auto_fix 时补传 vid=self.selected or ""。

普通 AI 对话(_ai_agent_run)与子代理同样加载 AGENT_TOOLS,因此用户直接说"修复模组注入失败"时模型也能看到并调用 fix_mixin,无需改其他链路。

三、验证

  • 语法编译:python -m py_compile main.py 通过;IDE 静态检查 0 错误 / 0 警告。
  • _tool_fix_mixin 自测(临时脚本,已删除;在 D:\发芽启动器\versions\__mixin_test__ 造真实目录与假 jar):
    1. 命中 Mixin apply for mod create failed → 正确匹配 create-0.5.1-fabric.jar 并禁用(改名 .disabled)✓
    2. 点名 unknownmod(mods 目录无该 jar)→ 明确报告未匹配 + 给出 mods 目录 ✓
    3. 非 Mixin 日志(OutOfMemoryError)→ 提示"未能从日志解析出 Mixin 相关模组",不会误禁用 ✓
    4. 缺 log 参数 → 提示缺参 ✓
    5. 重复点名同一模组 → 去重,只禁用一次 ✓

四、备注

  • 工具按高级权限处理是刻意的:禁用模组会改动玩家 mods 目录,普通模式必须弹窗确认。
  • 若日志点名的 mod id 与 jar 文件名差异过大(极端情况)会落入「未匹配」分支并提示 mods 目录,AI 可结合 get_mods / rename_file 手动兜底。

2026-08-28(6)· 前置模组补全:新增一键按钮 + 修复下载后自动补装

反馈:① 版本管理页找不到「一键补全前置模组」按钮;② 下载新模组时不会自动下载前置模组。改动文件:D:\AI\P\fy\main.py(仅 main.py)

一、新增依赖解析基础方法(_mr_deps_of_version 之前)

方法 作用
_mr_sha1_of_file(path) 计算文件 sha1,供 Modrinth version_file 反查模组身份
_mr_resolve_dep_file(pid, version_id, mc, loader) 把依赖项目解析成可下载文件 {project_id, slug, title, url, filename, sha1, size};锁定版本时直接取,否则按 (MC 版本, 加载器) 取最新兼容版;只取 primary 文件(避开 javadoc / sources)
_mr_deps_by_sha1(sha1, mc, loader) 用 /version_file/<sha1>?algorithm=sha1 反查该文件的 required 依赖。与下载来源无关:从 CurseForge 下载的模组只要文件被 Modrinth 收录,同样能查出前置
_mr_wait_file_ready(dest, timeout=90) 等下载线程把主文件写完整(大小连续两次稳定且非空),避免并发算出半截 sha1

_mr_deps_of_version 同步重构为复用 _mr_resolve_dep_file(去重 + 支持环境筛选)。

二、修复「下载后自动补装前置」(_mr_auto_deps_after_download)

原实现三个问题,逐一修复:

  1. 只认 Modrinth version id → 从 CurseForge 来源下载的模组,其 id 查 Modrinth /version/<id> 必然 404,依赖查不到。修复:改为优先用下载完成后的文件 sha1 反查,反查不到再退回 version_id 查询。对两种来源都有效。
  2. 与下载线程并发:原实现与 _mr_download_worker 同时 start,补装时主文件可能还没落盘。修复:先用 _mr_wait_file_ready 等待落盘完成。
  3. 全程静默:成功只写日志,用户感知不到,会以为功能没生效。修复:补装成功给 toast「✅ 已自动补装 N 个前置模组:…」,失败也给提示并引导点「补全前置模组」重试。

三、新增「一键补全前置模组」

  • 入口 1:版本管理页按钮网格新增 🔗 补全前置模组(第 8 项,网格 3 列 → 4 行;无模组加载器时随 mods/mods_folder 一起隐藏)。
  • 入口 2:模组管理页搜索行,紧邻「🔍 校验兼容性」右侧。
  • 实现 _mods_deps_complete() → 后台线程 _mods_deps_worker(vi, jars):
    1. 逐个对已启用 jar 算 sha1 → 反查 Modrinth 项目 id,收集各自的 required 依赖;
    2. BFS 展开依赖(前置的前置也补,深度上限 3、总数上限 20,防失控);
    3. 每个依赖先按 (MC 版本, 加载器) 解析出文件,再按 project_id 与文件名双重判重,已装则跳过;
    4. 汇总弹窗:已补装 / 已存在无需安装 / 未成功 / 无法识别(未被 Modrinth 收录)/ 前置齐全。
  • 新增队列消息 mods_deps 与 _on_mods_deps_msg(主线程弹窗),照 mods_compat 的既有模式接入。

四、过程中发现并修复的真实缺陷

_mr_resolve_dep_file 按环境过滤查询时,参数直接拼成 ?game_versions=["1.18.2"]&loaders=["forge"]——方括号与双引号未编码,Modrinth 返回 HTTP 400,异常被 except 吞掉后静默返回 None,导致「依赖未锁版本时」这条路径 100% 失效。修复:改用 urllib.parse.urlencode 编码;并加兜底——过滤结果为空时退回不过滤取最新版本,避免筛选过严而完全失败。

五、验证

  • 语法编译:python -m py_compile main.py 通过;IDE 静态检查 0 错误 / 0 警告。
  • 自测(临时脚本,已删除;真实 API + mock 网络混合):
    1. sha1 计算正确 ✓
    2. _mr_resolve_dep_file(Flywheel + 1.18.2/forge)→ 命中 flywheel-forge-1.18.2-0.6.8.a.jar,且正确排除 javadoc/sources ✓(此项修复前返回 None)
    3. _mr_deps_by_sha1(create forge 1.18.2 样本 sha1)→ 反查出 Flywheel ✓
    4. _mods_deps_worker 完整流程(mock 网络与下载)→ 正确补装缺失前置、文件落到 mods 目录、汇总文本正确 ✓
    5. 二次运行(前置齐全)→ 不重复下载、提示「🎉 前置齐全,无需补装」✓

六、遗留

  • 依赖识别依赖 Modrinth 收录:极少数仅发布于 CurseForge 的模组无法识别(汇总里会归入「无法识别」并提示手动确认)。
  • 启动前的强制依赖检测(mod_missing_dep 类崩溃 → 自动提示补装)仍未做,可复用本节方法实现。

2026-08-28(7)· 补全前置模组的下载进度接入「下载管理」页

需求:一键补全前置模组时,能在下载管理页看到每个前置的下载进度。

改动文件:D:\AI\P\fy\main.py(仅 main.py)

一、机制说明(既有基础设施)

下载管理页(dlmgr)渲染 _dl_tasks(tid → {name, text, pct}),由主线程方法 _dl_task_start / _dl_task_update / _dl_task_done 维护。模组下载走的 mr_progress_show/hide 消息还附带模组下载页的内联进度条(_mr_show_progress),对「补全前置」不适用(用户不在下载页,且 frame 不属于模组管理页)。

二、实现

  1. 新增 _mr_dep_progress_cb(tid, name)(_mr_auto_deps_after_download 之前)
  • _simple_download 进度回调适配器:接收 (done_bytes, total_bytes),节流 0.25s,换算成「🔗 <文件名>:x.x / x.x MB | xx%」+ pct,发 dl_dep_progress 队列消息。
  1. 新增 3 个队列消息分支(mr_progress_show 之后,只操作下载管理任务、不碰内联进度条):
  • dl_dep_start(tid, name) → _dl_task_start
  • dl_dep_progress(tid, pct, text) → _dl_task_update
  • dl_dep_done(tid, final_text) → _dl_task_update(100%, final) + _dl_task_done(移入下载管理历史)
  1. 两条补装链路都接入:
  • 一键补全(_mods_deps_worker):每个前置下载前 tid = self._mr_new_tid() + 发 dl_dep_start(名称「🔗 补装前置:<文件名>」),下载带 progress_cb 与 known_size(省一次探测),结束发 dl_dep_done(✅ 已就位 / ❌ 下载失败)。
  • 下载页自动补装(_mr_auto_deps_after_download):同样处理,名称「🔗 自动补装前置:<文件名>」。
  1. tid 唯一性:复用 _mr_new_tid()(mr: 前缀自增,预登记 _dl_stats),与模组下载共用序号,互不冲突。

三、验证

  • 语法编译:python -m py_compile main.py 通过;IDE 静态检查 0 错误 / 0 警告。
  • 自测(临时脚本,已删除;mock 网络 + 模拟下载回调):
    1. 完整流程产生 dl_dep_start → dl_dep_progress×3 → dl_dep_done,tid 唯一同源 ✓
    2. 进度数值递增(0% → 50% → 100%),文字含文件名与百分比 ✓
    3. 回调节流生效(0.25s 内连续调用只发 1 条)✓
    4. 下载失败同样发 dl_dep_done 且文案为失败 ✓

四、备注

  • 刻意不走 mr_progress_show/hide:其附带的内联进度条只属于模组下载页,补全前置场景下会错位显示,故新增独立消息类型,只刷新下载管理任务列表与历史。
  • 下载完成的任务会进入下载管理「历史记录」(保留 30 条),失败也能看到留痕。

2026-08-28(8)· 修复「默认(内置 Key)」预设仍显示 API Key 栏且无法编辑

反馈:默认模型页面不应该有 API Key 栏,但显示了;里面有无效 key,且无法编辑/删除。

一、根因

原 _ai_apply_preset 对内置预设的处理是「填入占位文字 + 设为 readonly」:

self._ai_key_entry.insert(0, "(内置 Key,无需填写)")
self._ai_key_entry.configure(state="readonly")

Key 输入框带 show="●",占位文字被遮成一串黑点——视觉上就是一个「已存在的 Key」,而且 readonly 导致无法编辑、无法删除。这正是用户描述的「里面有无效 key,还无法编辑删除 key」。

连带 3 个问题:

  1. 占位文字被落盘:_ai_save_cfg 无条件 cfg["key"] = self._ai_key_entry.get().strip(),切换/保存内置预设时把占位文字(或残留的旧自填 key)写进 ai_config.json,下次启动又被插回输入框。
  2. pack_forget() 后 pack() 打乱布局:_ai_custom_row(Base URL 行)在「自定义模型」预设下恢复时,没有 before 锚点,会被追加到卡片末尾(跑到 MCP/技能按钮行之后)。
  3. 内置预设无法测连接:_ai_test_from_settings 直接读 Key 框(内置时为空),会误报「请先填写 Base URL 与 API Key」。

二、修复(仅 main.py)

  1. 内置预设整行隐藏 API Key(用户诉求)
  • 设置页把 Key 行 / 模型名行 / 按钮行分别存为 self._ai_key_row、self._ai_model_row、self._ai_row3;
  • _ai_apply_preset:内置预设 → 清空 Key 框 + self._ai_key_row.pack_forget();其它预设 → 带锚点恢复 pack(fill="x", pady=3, before=self._ai_model_row)。
  1. 布局顺序修复
  • _ai_custom_row 恢复时改用 pack(fill="x", pady=3, before=self._ai_row3),不再追加到末尾。
  1. 占位文字不再落盘
  • _ai_save_cfg:内置预设(或值为占位文字)时 _pk = "",cfg["key"] 与 keys[预设名] 都不写入;非内置预设照常落盘并绑定供应商。
  1. 启动清理脏数据
  • 设置页恢复配置时,若 cfg["key"] 是旧版写入的占位文字,直接清空并回写 cfg。
  1. 测试连接支持内置预设
  • _ai_test_from_settings:内置预设用 preset["key"] 测试,不再误报未填 Key。

三、验证

  • 语法编译:python -m py_compile main.py 通过;IDE 静态检查 0 错误 / 0 警告。
  • 自测(临时脚本,已删除;用桩件替代 tk 组件,验证纯逻辑)18 项全过:
    • 内置预设:Key 行隐藏 ✓ / Key 内容清空(清掉残留旧 key)✓ / Base URL 行隐藏 ✓ / 回填内置模型名 ✓
    • 落盘:内置预设不落盘占位文字 ✓ / 不绑 keys ✓;DeepSeek 正常落盘并绑定 ✓
    • 切换:内置 → DeepSeek → 内置,Key 行正确隐藏/恢复,不残留上一家 key ✓
    • 布局:Key 行恢复锚定在模型行之前 ✓ / 自定义 Base URL 行锚定在按钮行之前 ✓
    • 落盘文件无占位文字 ✓

四、备注

  • 内置预设隐藏 Key 行后,用户切到「千问 / DeepSeek / 智谱」等任意自带 Base URL 的预设即可恢复 Key 行并填自己的 Key;选「自定义模型」会同时恢复 Key 行与 Base URL 行。

2026-08-28(9)· AI 助手上下文窗口:按模型自适应 + 75% 水位自动压缩

需求:① 上下文窗口长度根据模型自行调整;② 历史会话压缩;③ 上下文达到窗口 75% 时自动压缩。

改动文件:D:\AI\P\fy\main.py(仅 main.py)

一、模型上下文窗口表(AI_CTX_WINDOWS)

补全常见模型窗口(按模型名子串匹配,越靠前优先;未收录默认 128K):

模型 窗口
deepseek 1M
qwen 256K
gemini / bard / gemma 1M
claude / command 200K
glm / chatglm / gpt- / o1 / o3 / grok / kimi / moonshot / sense / hunyuan / doubao / ernie / wenxin / spark / xfyun / xinghuo / llama / internlm / yi- / mistral 家族 128K

_ai_ctx_window(model) 根据当前模型名自动返回对应窗口——即「长度根据模型自行调整」。

二、新增 token 占用统计(模块级)

  • _ai_messages_tokens(messages):累加每条消息的估算 token(_est_tokens + 每条 16 token 固定开销;content 为数组/对象时按序列化文本估算,兼容多模态/工具结果)。
  • _ai_ctx_usage(messages, model):返回 (已用 tokens, 窗口大小, 占用比例 0~1)。

三、75% 水位自动压缩(_ai_maybe_compress 改造)

原实现按「条数 ≥40」触发,与上下文窗口无关。改造为按 token 水位:

  1. 计算 system(内置提示词) + 全部历史 的估算 token;
  2. ratio >= 75%(窗口的 75%)→ 触发压缩;或条数 ≥60 兜底触发(小窗口模型条数涨得快,固定开销也占窗口);
  3. 至少 20 条历史才压缩(保留最近 10 条原文 + ≥10 条早期可压),避免无谓的 AI 摘要调用;
  4. 触发后后台 _ai_compress_worker 把早期对话压成中文摘要(保留用户偏好/决策/进度/关键事实/待办),历史替换为 [摘要, ...最近10条原文];
  5. 返回是否已触发,供调用方判断;_ai_compressing 防止重复触发。

四、发送前检查(_ai_ask)

组装请求前调用 _ai_maybe_compress()——历史水位达到 75% 时在发送前启动后台压缩,而不是等回复后才压缩。压缩完成前本次请求由 _ai_trim_history(60% 预算硬截断)兜底,保证永不超窗。回复后 _on_ai_reply 仍会再检查一次,为下一轮准备。

五、阈值对齐

  • _ai_maybe_compress 触发要求历史 ≥20 条;
  • _ai_compress_worker 的早期消息下限从 20 调整为 10(与新触发条件匹配,避免触发后 worker 又因 old 太少直接返回而无限重复触发)。

六、验证

  • 语法编译:python -m py_compile main.py 通过;IDE 静态检查 0 错误 / 0 警告。
  • 自测(临时脚本,已删除)25 项全过:
    • 12 组模型名 → 窗口识别全部正确(含新增 gemini/llama/mistral/spark 等)✓
    • _ai_ctx_usage 计算正确,content 数组也计入 ✓
    • 历史 <20 条不触发 ✓;小窗口 + 长历史水位 >75% 触发压缩且启动后台线程 ✓;压缩中不重复触发 ✓
    • 条数 ≥60 兜底触发 ✓;水位低且条数未超不触发 ✓

七、备注

  • 压缩是「AI 摘要式」(保留最近 10 条原文 + 早期摘要),不是简单丢弃;摘要会随下次请求进入上下文,可支撑接力续聊。
  • 75% 阈值隐含为输出/工具结果预留 25% 空间;硬截断(60%)作为压缩完成前的安全网,两层保证不超窗。

2026-08-28(10)· 上下文水位指示:发送按钮旁的空心圆

需求:把上下文水位以空心圆 ⚪ 形式做到 AI 助手发送按钮旁边。

改动文件:D:\AI\P\fy\main.py(仅 main.py)

一、实现

  1. 空心圆指示器(AI 页输入行,发送按钮与语音按钮之间)
  • tk.Canvas 30×30 绘制:灰色整圈(空心圆外观)+ 彩色水位弧(从 12 点方向顺时针,弧长 = system+历史 估算 token / 模型窗口)+ 中心百分比数字。
  • 颜色分区:<50% 绿 #7BC47F、50–75% 灰(COL_SUB)、75–90% 黄 #E0A83A(即将压缩)、≥90% 红 #E05A5A。
  • 百分比与弧长在超窗时封顶 100%(自测中发现并修复:超窗曾显示 291%)。
  1. _ai_update_ctx_ring():计算当前水位(_ai_ctx_usage(system+历史, 模型))并重绘;模型名优先取设置页输入框,未构建时回退 ai_config.json 的 model。缓存 _ai_ctx_ratio / _ai_ctx_used / _ai_ctx_window_size 供提示用。

  2. 悬停详情(_ai_ctx_tip):鼠标悬停显示 Toplevel 提示——「上下文水位:xx% / 约 x.xK / 128.0K tokens(模型窗口)/ 达到 75% 自动压缩历史对话」。

  3. 新增 _fmt_tokens():token 数人性化(1234567 → 1.2M、12345 → 12.3K)。

  4. 刷新时机:AI 回复后、历史压缩完成后、新建会话后、加载历史会话后,以及 AI 页构建完成时(初始 0%)。

二、验证

  • 语法编译:python -m py_compile main.py 通过;IDE 静态检查 0 错误 / 0 警告。
  • 自测(临时脚本,已删除;Canvas 用桩件记录绘制调用)16 项全过:
    • _fmt_tokens 边界(0 / 999 / 12.3K / 1.2M / None)✓
    • 空历史:system 占用被如实反映(极小水位弧)、显示 0% ✓
    • 低水位弧长与比例精确一致、颜色正确 ✓
    • 中水位黄 / 超 90% 红 / 超窗时百分比与弧长封顶 100% ✓(过程中发现并修复超窗显示 291% 的小缺陷)

三、备注

  • 指示器与 75% 自动压缩共用同一套水位计算(_ai_ctx_usage),显示值与实际触发阈值一致;黄色阶段即「接近压缩阈值」的预告。

2026-08-28(11)· 修复「内置 Key 不生效」(key 文件注释污染)

现象:选择「默认(内置 Key)」预设对话报 401,内置 Key 完全不可用。

一、根因(两层叠加)

  1. key 文件注释污染(主因):千问内置 key 文件 mm_eer 的内容是「3 行 # 使用说明注释 + 1 行逗号分隔的 3 个 key」,而注入逻辑直接 read().strip() 把整坨文字当成 key:

    QWEN_BUILTIN_KEY = "# 千问(阿里百炼)内置 API Key —— 打包时注入…\nsk-ws-…,…"

于是默认预设(优先千问)变成「千问 base + 注释污染的 key」→ Authorization: Bearer # 千问(阿里百炼)… → 401。 2. 兜底换 key 不换 base(次因):_ai_chat_once 发现 key 含非 ASCII(中文注释)会换成 AI_BUILTIN_KEY(智谱 key),但 base_url 仍是千问的 → 智谱 key 调千问 API → 照样 401。兜底反而掩盖了真正病因。

二、修复(仅 main.py)

新增模块级 _read_key_file(path):读 key 文件时跳过 # 注释行与空行,剩余行拼接为逗号分隔的 key 串(多 key 轮询语义不变)。GLM(ai_key.txt)与千问(mm_eer)两处注入统一改用它——今后 key 文件里写使用说明不会再污染 key。

三、验证

  • 语法编译通过;IDE 静态检查 0 错误。
  • 端到端实测(临时诊断脚本,已删除;仅打印 key 前 8 位不泄露):
    • 修复后 QWEN_BUILTIN_KEY = 351 字符干净 3-key 串(head sk-ws-H.,不再是注释文字)✓
    • 默认预设 = 千问 base + qwen-turbo + 干净 key ✓
    • 真实调用 API 返回 "OK",内置 Key 生效 ✓
  • 附带发现:用户 ai_config.json 里残留旧版占位文字 key(13 字符),启动加载时的清理逻辑(见 2026-08-28(8)节)会自动清空,无需手动处理。

四、备注

  • key 文件今后仍可写 # 注释说明(方便维护),解析层已免疫;但key 本身不要带引号/空格。
  • _ai_chat_once 的「非 ASCII key → 换内置 key」兜底保留(防御占位文字类脏数据),但根治在源头解析。

2026-08-29(1)· 模组管理:前置下载提速 + 进度可见 + 筛选按钮 + 更新检查提速

反馈:① 前置下载太慢且看不到进度;② 从版本管理页直接点「补全前置模组」误报"该版本没有模组 jar 文件",必须先打开模组管理页;③ 模组列表上方需要 全部/禁用/启用/可更新 四个筛选按钮;④ 优化模组更新检查速度。

改动文件:D:\AI\P\fy\main.py(仅 main.py)

一、修复「版本管理页直接补全前置」误报(Bug)

根因:_mods_deps_complete 读的是 self._mods_entries,而该列表只在打开模组管理页时由 _refresh_mods_list() 填充。从版本管理页直接点按钮时它还是空的 → 误判"没有已启用的模组 .jar"。

修复:新增 _mods_scan_jars(vi),直接读 version_mods_dir(vi) 目录返回 [(文件名, 完整路径)](自动排除 .jar.disabled)。_mods_deps_complete 改用它,两个入口行为一致。

二、前置下载提速(串行 → 并发)

原 _mods_deps_worker 是逐项串行:识别 1 次网络 + 解析 2 次网络 + 1 次下载,全部排队。改造为分层并发:

  1. 并发识别(_mods_identify + 8 线程池):N 个模组的 sha1 反查同时进行,不再串行等待。
  2. 并发解析(8 线程池):本层所有前置的下载信息(_mr_resolve_dep_file)同时解析。
  3. 并发下载(4 线程池):每个前置一个独立下载任务,各自持有 tid 与进度回调。
  4. 依赖仍按层展开(前置的前置),层数上限 3、总数上限 20,防失控。

另加 sha1 缓存(_mr_sha1_of_file):按 (路径, 修改时间, 大小) 缓存,更新检查/依赖检查反复调用不再重复哈希大文件;缓存在 App.__init__ 预初始化(避免属性缺失时 getattr 走 tkinter __getattr__)。

实测提速:mock 两个各耗时 0.35s 的下载,串行约 0.7s,并发实测 0.36s。

三、进度可见(页面内实时状态)

  • 模组管理页筛选行右侧新增状态标签 self._mods_status_lbl,后台通过队列消息 mods_status 实时更新:🔗 正在识别 N 个模组… → 🔗 正在解析 N 个前置的下载信息… → ⬇ 正在下载 N 个前置模组… → ⬇ 正在下载前置 1/2… → ✅ 前置补全完成:新增 2 个
  • 每个前置仍是下载管理页的独立任务(进度条 + MB + 百分比)+ 完成后进入历史。

四、筛选按钮(全部 / 已启用 / 已禁用 / 可更新)

  • 搜索行下方新增筛选行,4 个圆角按钮,当前模式高亮(强调色)。
  • _apply_mods_filter 支持 self._mods_filter_mode(all/enabled/disabled/updatable),与搜索关键词叠加生效。
  • 卡片状态位在可更新时显示 [可更新 → 新版本号](强调色),与 [正常]/[已禁用] 区分。

五、模组更新检查提速

新增 _mods_check_updates / _mods_updates_worker / _mods_one_update:

  • 并发 8 线程,每个模组:sha1 反查 Modrinth → 取当前 version_id → 按 (MC 版本, 加载器) 查该项目最新版本 → id 不同即判定可更新(记录 当前版本 / 最新版本 / url / 文件名)。
  • 结果缓存 self._mods_updates,_mods_updates_done 标记:同一版本重复点「可更新」直接复用结果,不重复请求;切换版本/刷新列表时重置。
  • 依赖 sha1 缓存,避免重复哈希大文件。

六、验证

  • 语法编译:python -m py_compile main.py 通过;IDE 静态检查 0 错误 / 0 警告。
  • 自测(临时脚本)19 项全过:
    • 4 种筛选模式 + 关键词叠加 ✓
    • _mods_scan_jars 正确排除 .disabled ✓
    • sha1 缓存命中 / 内容变化后重算 ✓
    • 并发补装:2 个前置均落盘、耗时 0.36s(串行需 0.7s)✓、进度消息序列完整 ✓
    • 更新检查:识别可更新并记录版本号 ✓、未收录模组不误报 ✓

七、遗留

  • 「可更新」目前只做检测与标记,一键更新沿用右键菜单的「更新(下载页)」入口;如需直接一键下载替换可后续补。

2026-08-29(2)· 修复「内置 Key 又失效」:跨源 401(base 与 key 不配套)

现象:上一轮修复后主对话可用,但「AI 自动修复」等路径仍报 401「API Key 无效或已过期」。

一、诊断(先排除 key 本身)

逐个实测:千问 3 个 key 全部可用(3/3)、智谱 key 可用、默认预设连续调用 5 次全部成功。→ key 没失效,是调用路径用错了 key。

二、根因:base 与 key 跨源

_ai_sub_agent(子代理)与 _ai_auto_fix(AI 自动修复)是这么取凭据的:

base = cfg.get("base") or ...                        # 千问 base(内置预设保存的)
key  = cfg.get("key")  or globals()["AI_BUILTIN_KEY"]  # cfg["key"] 为空 → 智谱 key

内置预设的 key 不落盘(上一轮修复),于是 cfg["key"] 为空 → 回退成智谱 key,而 base 仍是千问 → 拿智谱 key 请求千问 → 401。

对照实验直接证实了这点:

组合 结果
千问 base + 千问 key(修复后) ✅ 成功
千问 base + 智谱 key(旧逻辑) ❌ 401「API Key 无效或已过期」

正常对话走 _ai_ask(用 preset["key"])所以没问题,只有这两条路径踩坑——表现就是"对话能用,一点自动修复就说 key 失效"。

三、修复(仅 main.py)

新增统一凭据解析 _ai_resolve_creds() → 返回 (base, key, model):

  • 内置预设:整套使用预设值(preset["base"]/["key"]/["model"]),保证 base 与 key 同源;
  • 其它预设:用设置页输入框的值;
  • UI 尚未构建时回退 ai_config.json 的保存值。

6 处调用点全部改为使用它:_ai_ask、子代理 _ai_sub_agent、_ai_auto_fix、崩溃自动分析、_ai_maybe_compress、设置页测试连接。key 与 base 从此只有一处解析逻辑,不会再出现跨源组合。

四、验证

  • 语法编译通过;IDE 静态检查 0 错误 / 0 警告。
  • 自测(临时脚本,已删除)10 项全过:
    • 内置预设返回千问 base + 千问 key(同源),不再是智谱 key ✓
    • 端到端实测:AI 自动修复路径调用成功 ✓
    • 对照:旧组合(千问 base + 智谱 key)确实 401 ✓(证实病因)
    • 非内置预设用自填 key ✓;UI 未构建时正确回退 cfg ✓

五、备注

  • 临时脚本 d:/AI/P/fy/_mods_opt_test.py(上一轮遗留)已一并清理。
  • 后续新增任何调用 AI 的地方,都应走 _ai_resolve_creds(),不要自己拼 base/key。

2026-08-29(3)· AI 技能体系扩充 + 崩溃修复手册自动注入

反馈:AI 助手需要更多 skill,知识库的修复方法要更详细,现在根本修不好一个 bug。

一、为什么之前修不好(根因)

  1. 技能只有 1 个:仅《崩溃诊断知识库》(41 条索引表),且每条"修复要点"只有一句话(如"更新显卡驱动"、"删除损坏的 launcher 配置文件")——AI 拿到也不知道具体改哪个文件、怎么改。
  2. 工具描述与实物不符:get_skill 描述声称有"崩溃修复、数据包制作、配置调优、整合包制作、搜索"5 类技能,实际只有 1 个,AI 尝试加载其余的必然失败。
  3. 依赖 AI 主动加载:崩溃流程写在 system prompt 里让 AI 自己 get_skill,弱模型经常不调用。
  4. 自动修复完全没提技能:_ai_auto_fix 的 prompt 里只字未提技能/知识库。
  5. 诊断结果没喂给 AI:ERROR_PATTERNS(16 类正则诊断)的结果只在弹窗显示,没进入 AI 上下文。

二、新增《崩溃修复手册》(详细操作版)

按 diagnose_crash() 的 16 个类别逐一成节,每节结构统一:

  • 判定:该类错误的日志特征
  • 根因:为什么会这样(讲清原理,不是只给结论)
  • 步骤:3-5 条可执行操作(读哪个日志、看哪一行、改哪个文件、用哪个工具、命令怎么写)
  • 验证:如何确认修好了
  • 坑:常见误区(如本机可能有两个 mods 目录)

含 16 类:module_conflict / mod_missing_dep / mod_duplicate / mod_load_fail / mixin_fail /java_version / jvm_crash / out_of_memory / opengl / natives_missing / java_not_found /auth_fail / download_fail / mod_incompatible / port_in_use / runtime_error,另加「通用排查流程」与「兜底流程」两节。

其中 mixin_fail 一节明确要求优先调用 fix_mixin 工具(上次新增的自动定位+禁用能力)。

三、另补 2 个实用技能

  • 《模组与依赖管理》:先确认 mods 目录(隔离 vs 共享)、禁用=改名 .disabled、download_mod 一步安装、前置补全入口、二分法排查冲突、同类优化模组不共存。
  • 《性能优化》:客户端优化按性价比排序、内存分配对照表(物理内存 → 建议值)、服务器优化、如何判断瓶颈在客户端还是服务端。

内置技能从 1 个 → 4 个(崩溃诊断知识库、崩溃修复手册、模组与依赖管理、性能优化)。

四、关键改进:知识自动注入,不再靠 AI 主动取

新增模块级 skill_section(kind):按 ## <kind> 标题从手册中截取对应整节。

  • _ai_auto_analyze(崩溃自动分析):diagnose_crash 得到类别后,把该类别整节手册塞进 user prompt 的「详细修复手册」块。
  • _ai_auto_fix(AI 自动修复):同样先对报告文本分类,注入对应手册章节,并在 system prompt 里写明"严格按手册执行,不要自由发挥"、缺失时再 get_skill 兜底。

即:AI 还没开口,正确的操作手册已经摆在它面前——不再依赖它记得去调工具。

五、配套修正

  • get_skill 描述改为真实可用的 4 个技能名 + 提示可用 list_skills 查看。
  • system prompt【修崩溃流程】改写:告知手册已自动注入、不要重复 get_skill、并强调"get_mods 返回的才是实际 mods 目录"这类具体坑。

六、验证

  • 语法编译:python -m py_compile main.py 通过;IDE 静态检查 0 错误 / 0 警告。
  • 自测(临时脚本,已删除;用临时目录避免动用户真实 skills)16 项全过:
    • 4 个内置技能全部写入 ✓
    • 16 个崩溃类别 100% 有对应手册章节,无遗漏 ✓
    • 章节够详细(≥200 字符)且含操作步骤 ✓
    • 章节提取准确(标题正确、不串节、未收录类别返回空、不误命中兜底节)✓
    • get_skill 能加载手册全文与模糊匹配 ✓

七、备注

  • 新技能在启动器启动时写入 D:\发芽启动器\skills,需重启一次生效。
  • 用户可在该目录自行增改 .md 技能文件;_ensure_builtin_skills 只覆盖内置 4 个(内容变化时才重写),用户自建技能不会被删。

2026-08-29(4)· AI 工具支持任意磁盘版本 + 去除崩溃后自动修复弹窗

反馈:① AI 修不了 G 盘的版本,说"找不到版本";② 去除崩溃 AI 自动修复(崩溃弹窗上已有入口,重复打扰)。

一、AI 只认启动器目录的版本(Bug 根因)

get_versions / get_game_log / get_mods 三个工具全部硬编码 LAUNCHER_DIR:

  • get_versions 只列 D:\发芽启动器\versions
  • get_game_log 只找 D:\发芽启动器\logs\<vid>.log
  • get_mods 只在 D:\发芽启动器\versions\<vid> 下找 mods

而启动器本体支持全盘扫描版本,G 盘的版本明明在 self.versions 里,AI 却看不见。

修复:新增 _ai_find_version(vid)(在已扫描的全部版本里按 id 查找,大小写/空格容错)与 _ai_version_names():

  • get_versions → 列出全部已扫描版本 + 所在路径(含其他磁盘),并在工具描述里写明"不确定版本名时先调这个";
  • get_game_log → 优先版本自身 logs/latest.log(game_dir → 版本目录 → mc_dir 逐级尝试);
  • get_mods → 用 version_mods_dir(vi) 取实际 mods 目录,同时列出启用/禁用数量与目录路径;
  • 版本不存在时的失败提示会附上可用版本列表,让 AI 能自我纠正(而不是瞎猜版本名)。

过程中发现并修复的语义缺陷:最初 _ai_find_version 在"指定版本不存在"时会悄悄回退到当前选中版本——AI 会拿着另一个版本的日志/模组去修用户指定的版本,修错对象。已改为:vid 为空才回退选中版本;vid 非空且不存在时明确报"未找到版本「X」+ 可用版本列表"。同理,get_game_log 在版本不存在时不再用全局 game-latest.log 冒充该版本日志(那是上次启动的任意版本的日志)。

二、去除崩溃后自动弹出的「AI 自动修复」询问

原行为:崩溃 → 错误报告弹窗 + 自动 AI 分析 → 分析完成后再弹一次 askyesno 问"是否接受 AI 自动修复" → 自动改动 mods 目录。

改动:删除该自动弹窗(_on_ai_fix_confirm 调用与方法一并移除)。崩溃报告弹窗上的「🤖 发送 AI 分析」入口保留;_ai_auto_fix 能力本身保留(供 AI 助手页/后续手动入口调用),但不再自动弹窗、不再未经确认就动玩家的 mods 目录。

三、验证

  • 语法编译:python -m py_compile main.py 通过;IDE 静态检查 0 错误 / 0 警告。
  • 自测(临时脚本,已删除;用临时目录模拟 G 盘版本)16 项全过:
    • get_versions 能看到启动器目录之外的版本并列出路径 ✓
    • get_game_log 读到 G 盘版本自身日志并报出文件路径 ✓
    • get_mods 列出启用/禁用模组与实际 mods 目录 ✓
    • 版本名大小写/空格容错 ✓
    • 不存在的版本:mods 与日志均给出"未找到 + 可用版本列表"(不再误回退/误用全局日志)✓
    • 未传版本时回退当前选中版本 ✓
    • _on_ai_fix_confirm 已移除、分析完成后不再触发自动修复 ✓、_ai_auto_fix 能力保留 ✓

四、备注

  • AI 工具修复的对象范围与启动器一致了:版本选择页扫描到哪,AI 就能修到哪。
  • 需重启启动器生效。

2026-08-29(5)· 崩溃后不再自动分析;主动分析后直接自动修复

澄清需求(更正上一轮的理解):要取消的是「自动分析」而非「自动修复」——崩溃后不要自动发起 AI 分析;但用户在弹窗点了「发送 AI 分析」,分析完成后就应直接自动修复。

一、行为变更

场景 旧行为 新行为
游戏崩溃(game_exit) 弹错误报告 + 自动发起 AI 分析 + 分析完弹窗问是否修复 只弹错误报告,是否分析由用户决定
弹窗点「发送 AI 分析」 受「自动分析」开关限制;分析完弹窗问是否修复 按钮改名 「🤖 AI 分析并修复」,不受开关限制(用户明确意图);分析完成直接自动修复,无二次弹窗
下载失败(dl_fail) 自动分析(受开关控制) 不变,仍受开关控制

二、实现

  1. game_exit:删除 _ai_auto_analyze(...) 自动调用(_show_error_report、崩溃历史保留)。
  2. _ai_auto_analyze(..., auto_fix=False) 新增参数:
  • auto_fix=True(用户主动):跳过「自动分析」开关检查,并置 self._ai_analyze_auto_fix = True;
  • auto_fix=False(下载失败等自动场景):行为不变,受开关控制,标志置 False。
  1. _on_ai_analyze_result:末尾读取 _ai_analyze_auto_fix 标志,True 则直接 self._ai_auto_fix(reply, vid=当前选中) 并消费标志(不弹窗确认——普通模式下危险工具仍有确认弹窗兜底)。
  2. 弹窗按钮文字 →「🤖 AI 分析并修复」,调用带 auto_fix=True。
  3. 设置页开关文字更新:「下载失败时 AI 自动诊断(崩溃需在弹窗点「AI 分析并修复」)」。
  4. App.__init__ 预初始化 _ai_analyze_auto_fix = False。

三、过程中修复的连带问题

改 _ai_auto_analyze 开头时,函数剩余部分(原 try 块内 12 空格缩进)出现悬挂;同时发现该函数的凭据解析仍是旧代码(注释不同导致上轮 replace_all 漏掉,未走 _ai_resolve_creds())。已一并修复:补 try: 恢复结构 + 凭据解析统一走 _ai_resolve_creds()。

四、验证

  • 语法编译通过;IDE 静态检查 0 错误 / 0 警告。
  • 自测(临时脚本,已删除)12 项全过:
    • 开关关 + 自动场景 → 不发起 ✓;开关开 + 自动场景 → 发起但不标记修复 ✓
    • 用户主动(auto_fix=True)→ 不受开关限制、标记自动修复 ✓
    • 分析完成:标志 True → 调用 _ai_auto_fix(正确的 reply/vid)并消费标志 ✓;标志 False → 不修复 ✓
    • 静态检查:game_exit 不再调 _ai_auto_analyze、仍弹错误报告 ✓;按钮文案与 auto_fix=True ✓;开关文字已更新 ✓

五、备注

  • 修复动作会改 mods 目录(如 fix_mixin 改名禁用),普通模式下工具执行前仍有用户确认弹窗(_confirm_tool_exec),安全兜底不变。
  • 需重启启动器生效。

一个过渡版本

by 发芽的挪威张班 on 2026 Aug 29
下载

新增了一些功能

FayaLaunch

by 发芽的挪威张班 on 2026 Aug 27
下载

发芽启动器 · 全新系统安装与使用说明

版本:1.1.0 | 适用:Windows 11(也兼容 Windows 10)


一、快速开始(3 步用起来)

第 1 步:安装

双击 发芽启动器-1.1.0.msi,一路「下一步」即可完成安装。

  • ✅ 无需安装任何依赖:Python、Java、运行库统统不用装,安装包全部自带
  • ✅ 安装完成后,桌面会出现「发芽启动器」快捷方式,双击打开

如果之前装过旧版本,直接覆盖安装即可,配置和游戏版本都会保留。

第 2 步:启动游戏

  1. 打开启动器,在「启动游戏」页点击「扫描版本」,会自动全盘扫描所有磁盘中的我的世界版本,可以无缝游玩上次玩的版本,支持PCL2,HMCL等主流启动器
  2. 选择你想玩的 Minecraft 版本(如 1.20.1)
  3. 点击「▶ 启动游戏」

🎁 首次启动会自动下载 Java:如果你的电脑没有 Java,启动器会从清华镜像自动下载合适的 Java 运行时(PCL2 同款机制),无需手动配置。首次启动游戏还需要下载游戏文件(几百 MB,取决于网络),耐心等待即可。

第 3 步:开始玩

启动成功后会弹出游戏窗口。首次进游戏建议先调好视频设置(低 → 高 逐步提升,避免卡顿)。


二、左侧导航栏功能总览

启动器左侧导航栏从上到下依次是:

导航项 功能
▶ 启动游戏 版本扫描、版本选择、启动/停止游戏、实时日志
⬇ 下载 下载游戏版本、模组、光影、整合包、资源包、数据包、服务端、插件
📊 下载管理 查看所有下载任务的进度、速度、剩余时间
🌐 联机 局域网/跨网联机、房间列表、一键开服
🤖 AI 助手 内置 AI 助手(问答、修崩溃、装模组、写配置)
🎨 皮肤 皮肤管理(下载、预览、应用)
⚙ 设置 登录方式、AI 模型、内存分配、语音识别等
🎛 个性化 界面主题颜色、按钮动效等外观定制
ℹ 关于 版本信息、致谢

三、各功能详细介绍

🎮 启动游戏

  • 版本扫描:自动扫描电脑上所有已安装的 Minecraft 版本(包括其他启动器装的)
  • 启动/停止:一键启动或强制停止游戏
  • 实时日志:启动日志实时显示,游戏出问题可以直接复制给 AI 助手分析

版本选择列表的标识(颜色说明):

标识 含义
🔴 红色版本名 基础版本(父版本):被其他版本依赖的底座版本。例如「1.20.1」原版是被「1.20.1-Forge」依赖的底座。鼠标悬停可看到它被哪些版本依赖;有删除保护,不能单独删除(删了依赖它的版本会崩)这是官方标准,PCL也有,只是把父版本藏起来了。
🔵 蓝色版本名 服务端版本:从「下载 → 服务端」下载的版本。悬停提示"这是服务端";选中它后点「启动」就是离线开服,不需要本地客户端
黑色版本名 普通客户端版本

💡 隔离文件夹 game:每个版本在 发芽启动器\versions\<版本名>\ 下有独立的 game\ 子目录,存档、mods、配置都隔离在这个文件夹里,互不影响。也就是说:

  • 不同版本之间存档/模组完全独立,不会串数据
  • 想备份某个版本的存档,直接备份 versions\<版本名>\game\saves 即可
  • 整合包风格版本(版本根目录自带 mods/config 的)游戏数据直接放版本根,不额外建 game 子目录

⬇ 下载中心

下载中心有 8 个分类子页,全部支持搜索、按版本/加载器筛选:

子页 说明
版本 下载任意 Minecraft 版本(含远古版本),自动配好 Java
服务端 下载Vanilla / Spigot /Paper / Forge / NeoForge / Fabric / Quilt 服务端,一键开服
模组 从 Modrinth / CurseForge 搜索下载模组,自动补装缺失的前置模组
光影 光影包(shader)下载,配 Iris/Optifine 使用
整合包 从 Modrinth 下载整合包,一键导入
资源包 材质/资源包下载
数据包 数据包下载(机械动力等玩法增强)
插件 服务端插件下载(Paper/Spigot 等)

特色:

  • 下载失败自动重试(带退避),进度清晰
  • 使用高速多线程下载引擎
  • 模组下载自动检测并补装依赖(如 Iris 自动装 Sodium)
  • 多个下载任务并发互不干扰,各自独立进度条

📊 下载管理

  • 所有下载任务的实时进度(百分比、剩余时间、总大小)
  • 历史记录(最近 30 条)

🌐 联机

两种组网方式:

  1. Tailscale 组网(推荐,跨网稳定)
  • 点「📥 安装」→「🔑 登录」(用微软/Google/GitHub 账号)→ 获得虚拟 IP
  • 朋友也装 Tailscale 后,输入你的虚拟 IP 即可联机,像在同一局域网一样
  1. 陶瓦联机(国内低延迟)
  • 基于 EasyTier 的去中心化组网,免注册
  • 创建房间 → 生成邀请码 → 朋友填码加入
  • ⚠️ 注意:陶瓦依赖 EasyTier 公共节点,官方节点目前失效(全网问题,非本启动器缺陷),因此当前陶瓦卡片标注「无可用节点」——跨网联机在不自行配置的情况下止咳药使用 Tailscale

其他功能:

  • 房间列表:发现局域网内开放的服务器房间,一键加入
  • 一键开服:下载官方服务端并启动离线服(可选 原版/Forge/Fabric 等)
  • AI 联机诊断:联机连不上时让 AI 帮你分析原因

🤖 AI 助手

内置 AI 助手(开箱即用,无需配置),能帮你:

  • 修崩溃:崩溃时自动读日志 → 匹配内置 41 条崩溃诊断知识库 → 给出根因和修复步骤
  • 装模组/整合包:直接说"帮我找 1.20.1 的机械动力",AI 搜索并下载
  • 写配置:改启动参数、优化内存、调视频设置
  • 解答问题:Minecraft 机制、版本兼容、模组用法等
  • 日常事务:查资料、下载文件、整理信息、写脚本

模型选择(设置 → AI 助手):

  • 「默认(免费模型)」:开箱即用
  • 「千问(阿里百炼)」/「DeepSeek」/「智谱 GLM」/「Kimi」等:用自己的 API Key
  • AI 助手页支持多轮对话、停止生成、清空会话

🎨 皮肤

  • 从皮肤站搜索下载皮肤
  • 本地预览、一键应用
  • ⚠️ 说明:离线模式(未登录正版账号)下,皮肤只在自己视角显示;要让别人看到你的皮肤,需要正版账号或安装 CSL 模组

⚙ 设置

设置项 说明
登录方式 离线模式(免账号)/ 正版登录(微软账号)
AI 助手 模型源、API Key(支持多 Key 逗号分隔轮询)、模型列表获取
内存分配 游戏可用内存(默认自动 = 物理内存一半,可手动调整)
CurseForge 填写 API Key 走官方源(不填用公益镜像)
语音识别 下载/管理语音识别模型,AI 页可语音提问

🎛 个性化

  • 界面主题:浅色/深色配色自定义,保存即生效(无需重启)
  • 按钮悬停动效、圆角卡片风格

四、常见问题(FAQ)

**Q1:全新系统需要先装 Java 吗?**不需要。启动器首次启动游戏时自动下载合适的 Java。

**Q2:需要装 Python 吗?**不需要。安装包自带完整 Python 运行时。

**Q3:断网能用吗?**能启动已下载的版本;下载类功能(版本/模组/Java)需要网络。

**Q4:老版本(1.7.10/1.8)怎么玩?**下载对应版本 + 对应 Forge 即可。启动器会自动为老版本匹配 Java 8(新版 Java 跑不了老版本,这是 Minecraft 本身限制)。

**Q5:和网易版冲突吗?**不冲突,完全独立。建议玩启动器版时先关闭网易版,避免资源竞争。

**Q6:游戏崩溃了怎么办?**把崩溃信息发给 AI 助手("帮我看看游戏为什么崩了"),它会读日志、匹配诊断知识库、给出修复步骤。


五、系统要求

项目 要求
操作系统 Windows 10 / 11(64 位)
内存 建议 8GB 以上(游戏 + 启动器)
硬盘 至少 2GB 空闲(游戏本体另需 1-10GB)
网络 首次下载游戏/Java/模组需联网

发芽启动器 —— 免费、无捆绑、开箱即用的 Minecraft 启动器

还有一个彩蛋:)

BBSMC Logo

中国最活跃的 Minecraft 中文资源社区

QQ 群:1078515449

资源

模组整合包光影资源包地图

社区

汉化软件插件数据包

帮助

服务条款隐私政策社区规则开源代码
设置

"Minecraft"以及"我的世界"为美国微软公司的商标,本站与微软公司没有从属关系。 本站与 Modrinth 无从属关系,网站遵循 LGPL 协议开源。

© 2019-2026 青岛柒兮网络科技有限公司 | 鲁B2-20210590 | 鲁ICP备2021009459号-12 | 公安备案 鲁公网安备37021002001586号