Repository navigation
灵桥 Linkora v0.6.0
修复「启动卡在步骤 4/8」——服务起不来的真凶
本地部署时日志停在「步骤 4/8: 初始化规则引擎… 完成」永不继续、Web 端口从不上线。根因是 embedding.offline=True(用本地缓存、不联网的常见配置)恰好命中「同步直载」分支,把主线程整个卡在读取模型权重上(实测 >50 秒,进程存活但 CPU 0.4%)。离线本该只决定"是否联网",与"是否阻塞启动"无关。现在改为后台加载:启动秒回,模型就绪情况照旧可在后台查询(约 10 秒),Web 不再被模型加载阻塞。
首页「决策追踪」不再停在旧消息
管理后台首页的决策追踪此前取的是最旧两条而非最新——后端按时间正序返回,前端组件却直接取前 N 条。现在排序下沉到组件内部统一处理,最新消息始终在最上方;「意图 & 路由」页同步受益。
关闭鉴权 + 无凭据时不再裸奔写接口
调试时关掉 web.auth_enabled 且未配置凭据,此前即使服务绑定了对外地址,所有写操作(改配置、删数据)与配置导出仍会完全无认证放行。现在这种情况直接拒绝(fail-closed 返回 503);仅本机 / 私网使用时维持原有放行行为,不影响本地免鉴权调试与内网反代部署。
管理后台口令从明文升级为 PBKDF2 哈希
config.yaml 里的 web.auth_password 此前存明文。项目本已内置 PBKDF2 支持但存量配置从未迁移,现提供迁移工具一键升级。登录行为完全不变(校验函数对明文与哈希双兼容),备份先行、明文全程不落盘不打印。
消除 82 处「静默吞噬错误的宽异常」并加门禁防回潮
项目内 640 处 except Exception 中,有 85 处既不记日志也不重新抛出——异常被彻底吞掉,排障时完全看不到线索(本次「启动卡死」被另一条噪音告警淹没就是实例)。现在这 85 处全部补上带完整堆栈的日志,行为不变;并新增 AST 门禁把宽异常总数锁定为「只减不增」,防止回潮。
说明:项目中大量宽异常是正确的防御性容错(配置解析失败即回退默认值、日志格式化失败绝不能崩),本版本刻意未做机械收窄——强行收窄反而会把可容错变成会崩。
性能:每次回复最多省 400 次数据库查询
「意图 & 路由」的少样本推荐原先对每条候选回复单独查一次"前一条用户消息",候选多时每次回复产生最多 400 次查询。现改为一次批量取回 + 二分定位,N+1 降为单次查询,返回值完全不变。
可靠性与数据库
- 数据库索引自愈:2026-10-05 的生产事故(轮询器持续报 database is locked)真凶是某分库的
idx_conversations_updated索引损坏(49 行 missing from index),导致每次写入退化为全表扫描重建索引、写锁长期被占。启动时自动检测并重建损坏索引(幂等、不动数据),上线后该错误归零。 - 孤儿图片回收补 busy_timeout:撞写锁时立即失败会让孤儿图片静默漏回收,现改为等待而非立即失败。
- 历史导入接口修复:
/api/history/import原先调用一个不存在的脚本(必然失败),现改为进程内执行,与其它导入路径同源。 - 消息列表读路径不再写库:GET 请求原先会在关键路径内顺手回填图片路径(与业务写抢锁、阻塞响应),现改为请求返回后后台异步回填。
工程门禁
- ruff 覆盖范围从 38% 扩到全量:此前只扫
src/,web/、tests/、scripts/、main.py全在门外(web/routers/image.py的真实崩溃就是这么漏的)。现已全部纳入且当前零违规。 - CI 补并发控制与超时:连续推送不再叠加完整 CI 作业;任一 job 挂死不会永久占用 runner。
- 依赖一致性门禁首次真正在 CI 生效:本次即拦下一次自动合并带来的 10 项版本漂移。
依赖与安全
- 升级
urllib3至 2.8.0,消除 3 条 Dependabot 告警(2 高危:分块解码无界内存耗尽、HTTPS 代理 TLS 配置被忽略;1 中危:分块解压死循环)。此前requirements.lock已是安全版本但 CI 实际消费的是uv.lock里的漏洞版本,两份锁文件现已对齐。 - 清理
config.yaml.example的出厂口令与失效文档,过期审计报告归档并标注状态。