[Bug] Agent custom user tools are permanently removed during cold start while the installed-plugin catalog is loading

这个报错通常发生在自托管 LobeChat 中、Agent Profile 绑定了自定义用户工具(User Tools / Integrated Skills)之后,冷启动时已安装插件目录(installed-plugin catalog)的异步加载尚未完成,而 stale-plugin 清理逻辑在

快速结论:这个报错通常发生在自托管 LobeChat 中、Agent Profile 绑定了自定义用户工具(User Tools / Integrated Skills)之后,冷启动时已安装插件目录(installed-plugin catalog)的异步加载尚未完成,而 stale-plugin 清理逻辑在 500ms 防抖后误把有效绑定判定为“过期”,并把它从 Agent 的 plugins 字段中持久化删除。优先确认 loadingInstallPlugins 是否在清理执行时仍为 true,以及清理逻辑是否等待了已安装插件目录加载完成。

适用环境:Issue 已确认:LobeChat 自托管 Docker 部署、版本 2.2.13、Windows 桌面浏览器、Edge。触发路径涉及 src/features/ProfileEditor/AgentTool.tsx 与 src/features/ProfileEditor/staleProfilePlugins.ts。涉及的工具/插件元数据需为异步加载。

最快修复方案:暂无确认的一步修复方案(Issue 中报告者基于上游 commit 70a1e6aa70942b89479608b4651e71eb1660ef10 做了本地 hotfix 并称冷启动回归测试通过,但该修复未被确认为官方合并方案)。可优先尝试的最小改动思路是:在 AgentTool.tsx 中读取 loadingInstallPlugins,传入 resolveStalePluginCleanup,在该目录加载期间返回 null(不清理、不写入),并把该加载状态加入清理 effect 的依赖数组。

注意事项:上述修复思路来自 Issue 报告者与维护者分析,尚未在官方发布版本中确认验证;不要把它当作已发布的补丁版本依据。清理逻辑务必保持“失败关闭”(fail closed),即在目录未加载完成时不得写入修改后的 plugins 列表。改动前建议先备份 Agent 配置。

问题场景

在自托管 Docker 部署的 LobeChat 2.2.13 中,用户为某个 Agent Profile 在 User Tools / Integrated Skills 区域绑定了一个自定义用户工具/插件。该工具在刚配置完成后可正常显示并可调用。完全关闭浏览器后重新打开该 Agent Profile,绑定的工具会短暂出现随后消失;并且这不是单纯的渲染问题——前端会把清理后的列表持久化写回,覆盖 Agent 在 PostgreSQL 中的 plugins 值(在复现场景中变成了空 JSON 数组 [])。自定义插件本身仍已安装、manifest 有效,重新绑定又能正常使用,直到下一次浏览器冷启动再次复现。

报错原文

[Bug] Agent custom user tools are permanently removed during cold start while the installed-plugin catalog is loading

原因分析

维护者确认了报告者的分析。问题出在 AgentTool.tsx 的 stale-plugin 清理 effect:它从多个来源(builtin tools、installedPluginList、connector catalog、builtin/market/user skills、custom connectors)构建 validIdentifiers,然后在 500ms 防抖后执行 resolveStalePluginCleanup。该函数以 canEditContent、isAccessResolved、canEditResource、isConnectorsInit 作为门槛,但没有对“已安装插件目录是否加载完成”做任何门槛判断,StalePluginCleanupInput 接口也缺少对应字段。

因此当已安装插件的 SWR 请求在 500ms 时仍未返回时,installedPluginList 为空,validIdentifiers 不包含任何自定义插件标识符,清理逻辑便把这笔有效绑定误判为过期,通过 updateAgentConfigById 将裁剪后的 plugins 数组持久化写回。这是一个与 #17715(该 PR 新增了 canEditResource / isAccessResolved / isConnectorsInit 门槛以防止工作区幻影保存)不同的独立缺口,未覆盖已安装插件目录自身的加载状态。当已安装插件目录加载耗时超过 stale-plugin 清理延时(500ms)时,竞态更易复现。

环境排查

  • LobeChat 版本:确认是否为 2.2.13 或包含相同代码路径的版本。
  • 部署方式:自托管 Docker。
  • 操作系统与浏览器:Windows + Edge(其他环境未在 Issue 中确认)。
  • 代码路径:确认 src/features/ProfileEditor/AgentTool.tsx 中清理 effect 的构建与防抖逻辑。
  • 代码路径:确认 src/features/ProfileEditor/staleProfilePlugins.ts 中 resolveStalePluginCleanup 的门槛判断,以及 StalePluginCleanupInput 是否包含已安装插件目录的加载状态字段。
  • 数据侧:检查受影响 Agent 记录中 plugins 字段的持久化值,核对是否在冷启动后被改写(例如变为 [])。
  • 触发条件:绑定的工具/插件元数据是否为异步加载。
  • 测试覆盖:检查 staleProfilePlugins.test.ts 是否已有“已安装插件目录仍在加载”的用例(现状是只有 connector-init 与权限门槛的用例)。

解决步骤

  1. 先确认复现路径:绑定自定义工具 → 完全关闭浏览器 → 重新打开同一 Agent Profile → 观察工具短暂出现后消失,并检查 Agent 记录中 plugins 是否被改写。
  2. 在 AgentTool.tsx 中读取 loadingInstallPlugins。若该目录加载状态在清理执行时仍为 true,则说明命中了该竞态条件。
  3. 将 loadingInstallPlugins 传递进 resolveStalePluginCleanup,新增为一项门槛。
  4. 当已安装插件目录仍在加载时,让 resolveStalePluginCleanup 返回 null,即不做清理、也不触发任何写入。
  5. 把该加载状态加入清理 effect 的依赖数组,使目录加载完成后清理逻辑能够重新评估。
  6. 补充回归测试:构造“已安装插件目录仍在加载且 validIdentifiers 暂时不完整”时 Agent 已绑定自定义工具的场景,期望结果是不清理、不持久化写入。
  7. 若你只想尽快恢复业务,可先重新绑定被删掉的自定义工具(这是临时缓解,冷启动后仍会复现,除非应用了上述修复)。

验证方法

应用修复后,按相同步骤复现:安装一个异步加载元数据的自定义工具,绑定到 Agent Profile 的 User Tools / Integrated Skills,确认可正常显示与调用;完全关闭浏览器;重新打开浏览器并立即打开该 Agent Profile。预期结果是工具稳定保留、不会短暂出现后消失,且 Agent 记录中的 plugins 数组保持不变(不再被改写为空数组或去掉该自定义工具)。同时确认新增的冷启动回归测试通过。

参考来源

lobehub/lobe-chat #18856

lobehub/lobe-chat #17715(相关 stale-plugin 清理改动)

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 28973

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注