Files
goodbuddy/docs/features/knowledge-base/external-knowledge-logic-design.md
T
mesalogo 1c22e1a06d fix: keep browser overlays and knowledge controls usable
Native browser pages could cover application dialogs and overlapping menus
or notifications. Suspend only the viewport while covered and restore the
same active page afterward, including nested dialogs and terminal prompts.

Keep knowledge source controls at their full height, constrain long library
cards and titles, and update automatic names when switching remote targets
without overwriting edited or saved names. Restore packaged release-note
loading now that the history exceeds its previous size limit.

Add focused regressions and real Electron UI evidence. Clean up temporary
Harness fixture directories at test completion instead of accumulating them.

Release note: 修复内嵌浏览器遮挡弹窗和浮层、知识库来源选项被压缩及长名称显示异常;切换远端知识库时自动名称正确更新,并恢复更新说明显示。
2026-09-13 19:46:37 +08:00

175 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 外部知识库逻辑设计
## 文档信息
| 项目 | 内容 |
| --- | --- |
| 状态 | 当前实现规则;三家短答案、Dify 完整 App 与当前 UI 自动回归已通过,远程待验收 |
| 版本 | 0.2 |
| 日期 | 2026-09-13 |
| 关联需求 | [外部知识库接入 PRD](./external-knowledge-prd.md) |
| 关联场景 | [外部知识库 User Stories](./external-knowledge-user-stories.md) |
| 技术契约 | [技术设计](./external-knowledge-technical-design.md) |
## 1. 不变量
| 稳定 ID | 规则 | 对应需求 |
| --- | --- | --- |
| `EK-I-01` 单一知识库身份 | 本地与外部都以 GoodBuddy `knowledgeBaseId` 参与聊天范围与工具授权,实例和远端 ID 不扩大选中范围 | `EK-FR-10`、`EK-FR-11` |
| `EK-I-02` 外部绑定只读 | 添加、配置和移除仅修改本机记录;请求限于目录、详情、检索 | `EK-FR-15` |
| `EK-I-03` 凭据边界 | 新密钥在输入表单和保存 IPC 中短暂存在;加密后只在 Main 解密使用,摘要与引用不返回密钥 | `EK-FR-02`、`EK-FR-11` |
| `EK-I-04` 本地定义界面 | Provider 只返回数据,控件和配置由本地共享契约及组件定义 | `EK-FR-09` |
| `EK-I-05` 无静默切换 | 请求使用保存的实例、目标和配置;失败不更换实例、公共云地址或其他知识库 | `EK-FR-14`、`EK-FR-16` |
| `EK-I-06` 零结果与失败分离 | 合法成功响应无片段是零命中;请求或响应失败保留失败信息 | `EK-FR-14` |
| `EK-I-07` 外部证据不可信 | 标准化片段按已有知识证据边界进入 Runtime,不改变工具权限 | `EK-FR-12` |
| `EK-I-08` 配置不跨类型复用 | Provider 配置必须与实例一致,类型切换不迁移同名字段 | `EK-FR-06`、`EK-FR-09` |
## 2. 对象关系
一个实例可以有零个或多个绑定;一个绑定对应一个 GoodBuddy 知识库和一个远端目标。
同一实例与远端 ID 的组合唯一,不同实例可以使用相同 ID。本地知识库没有外部绑定。
类型由绑定关系推导,旧本地知识库不需要改成另一套对象。
GoodBuddy 显示名称与 `remoteName` 分开保存。刷新详情仅更新当前视图,不自动改写本地
名称或持久化远端名称;重新保存绑定时才写入当前表单使用的远端名称。
## 3. 实例状态与连接测试
| 状态维度 | 当前值与行为 |
| --- | --- |
| 启停 | `enabled` 为 false 时 Main 拒绝目录和检索,并取消当前实例请求 |
| 凭据 | `configured`、`missing`、`unavailable`;列表尝试解密判断可用性 |
| 最近探测 | `untested`、`catalog-ready`、`healthy`、`list-restricted`、`auth-failed`、`unreachable`、`failed`;其中 `healthy` 在类型中保留,当前操作没有写入它 |
实例先保存为 `untested`,不要求保存前完成网络或认证测试。保存、替换或清除凭据后
重置探测状态。保存后的“测试连接”只尝试目录读取:成功写入 `catalog-ready`;403
写入 `list-restricted`;401 写入 `auth-failed`;网络或超时写入 `unreachable`;其他错误
写入 `failed`。时间和错误码随本次结果保存。
探测结果是最近一次观察,不是 Main 的永久禁用条件。Main 请求检查实例是否存在、启用
和凭据能否解密;即使最近为 `auth-failed` 或 `failed`,仍可重新请求。UI 会据该状态
显示不可用并禁用聊天勾选,用户可编辑或重新测试实例。
绑定创建另做目标检索验证,成功零命中可保存。保存实例不代表目录可用,目录成功也不
代表绑定检索或整个产品验收通过。
## 4. 目录与手工 ID
目录每页最多 100 项,UI 当前请求 30 项,页码上限 500;当前没有“总目录最多 500 项”
的累计限制。Dify/RAGFlow 由远端分页,搜索过滤当前页;FastGPT 按 `parentId` 读取
当前父级,在返回结果内搜索和分页。文件夹只能进入浏览,不能作为目录绑定目标。
目录加载、空结果、搜索无结果和失败分别展示;失败提供重试,用户可主动切换手工 ID。
已经绑定的目录项禁用。手工 ID 不依赖详情接口一定可用,但保存前仍必须通过实际检索。
详情失败不阻断基础检索,例如旧 Dify 的详情 405。
Renderer 丢弃已失效的目录、详情和测试响应,不把切换前的结果写回当前表单。它没有
通过 IPC 取消已发出的目录请求,Main 请求仍受超时和服务生命周期管理。
## 5. 创建与编辑
新建绑定时,用户尚未编辑的显示名称跟随当前目录选择更新;更换实例或手工输入另一个
目标 ID 时清除旧自动名称。用户手动填写过名称后保留该草稿。编辑或重新绑定已有库时,
始终保留已保存的本地名称,除非用户主动修改;此修正不自动重命名已有知识库。
流程为选择 `local | dify | fastgpt | ragflow`,外部类型再选择实例、目录项或手工 ID、
显示名称、配置与测试查询。表单测试成功后允许保存;服务保存前再次执行同一查询验证,
检查实例、绑定和唯一性是否在等待期间改变,再写入数据库。
| 表单变化 | 当前失效规则 |
| --- | --- |
| Provider 类型 | 重新挂载绑定表单,清空旧类型状态 |
| 实例 | 清空目标、详情、目录位置和搜索,恢复该 Provider 默认配置,清除测试结果 |
| 远端目标、测试查询、通用或 Provider 参数 | 清除测试结果,需要重新测试 |
| 显示名称 | 保留测试结果 |
| 已保存实例摘要变化 | 旧测试结果不再视为有效 |
| 更换现有绑定实例或远端目标 | 需要重新测试和重新绑定确认 |
成功新建后仅把新库加入当前对话选择,不重新启用已取消的其他知识库。当前表单保存期间
禁用字段和操作;generation 检查用于避免旧响应更新 UI,不构成可取消的保存事务。
## 6. 配置与优先级
当前配置的精确字段、数值范围和默认值由[技术设计第 3 节](./external-knowledge-technical-design.md#3-共享契约)
对应的共享 Schema 定义。恢复默认只重置本地表单,保存成功后才影响该绑定后续请求。
Dify `useDatasetDefaults=true` 时省略整个覆盖对象,使用远端当时配置;远端管理员修改
默认值会影响后续结果。关闭后按完整覆盖对象发送,不与远端默认逐字段合并。
FastGPT 使用本地保存的模式、Token 预算、相似度和重排开关,不开放查询优化。
RAGFlow 图谱与知识编译分别保存且默认关闭。图谱完成时间有效才允许开启图谱;非空
知识编译模板组 ID 才允许开启知识编译。服务在发送启用请求前重新读详情确认;仅配置
GraphRAG 或请求返回 200 都不能替代对应能力证据。证据不足时 UI 仍允许关闭已保存的开关。
当前没有自动版本识别、Adapter 版本矩阵或配置迁移状态。共享契约拒绝未知输入与
Provider 错配,不能据此承诺所有部署版本均支持每个显式参数。
## 7. 绑定可用性
绑定只持久化配置和 `lastVerifiedAt`,没有独立 `binding_status`、最后成功检索时间或
远端缺失状态字段。详情与列表当前按实例推导:
| 条件 | UI 状态 |
| --- | --- |
| 实例不存在 | `temporarily-unavailable` |
| 实例停用 | `instance-disabled` |
| 凭据未配置、无法解密或最近认证失败 | `credential-error` |
| 最近探测失败或不可达 | `temporarily-unavailable` |
| 其余且绑定有验证时间 | `ready` |
| 其余且无验证时间 | `untested` |
聊天选择器保留已选 ID,但不可用行禁用勾选。检索时的 401、404、超时等通过本次失败
报告,不自动写成持久 `remote-missing/config-invalid` 状态。`ready` 表示当前可尝试使用,
不保证下一次请求成功。
## 8. 多库检索与失败
请求使用已冻结的 GoodBuddy ID 集合,`retrieveMany` 去重后并行检索各库。本地与外部
共享入口,外部库不触发本地 Embedding。预算按各库结果的 rank 轮转分配,先各库第 1 条、
再各库第 2 条,同 rank 按输入库顺序处理;不先耗尽整个库,也不比较 Provider 原始分数。
当前没有每库最低字符配额。精确预算见
[技术设计第 7 节](./external-knowledge-technical-design.md#7-检索编排)。
成功零命中返回空 results 且无 failure。单库错误返回 `diagnostics.failure`,其他库
仍可返回结果;上层据此区分部分失败与全部失败。MCP 在有失败且没有任何片段时返回
工具错误,即使另有成功零命中的库;预检索则保留降级诊断。用户取消或服务关闭会向上
传播取消,不把整次取消解释为成功零命中。
客户端错误码包括 `NETWORK/TIMEOUT/CANCELLED/AUTH/FORBIDDEN/NOT_FOUND/RATE_LIMITED/`
`INCOMPATIBLE/INVALID_RESPONSE/SERVER`,均以 `EXTERNAL_KB_` 为前缀。服务另报告凭据
不可用、停用、配置变化、配置错配、能力不可用、重复绑定和实例被引用。远端错误正文
不直接成为 UI 错误;部分本地校验错误仍是 Zod、TypeError 或 RangeError,不能承诺
所有失败都已有独立本地化诊断。
## 9. 删除与引用
停用和清除凭据保留绑定,UI 清除凭据需要确认。有绑定的实例不能直接删除;管理界面
列出受影响知识库并确认后,依次移除本地库再删实例。若中途失败,已成功移除的本地
记录保持删除,刷新列表后显示当前状态。任何一步均不发送远端内容删除请求。
历史引用保存当时的片段与外部定位,移除实例或绑定后仍能阅读。当前不重新读取远端
片段,不打开来源 URL,不查询实例是否已删除;因此没有自动“连接已移除”标签。
App 与 Main 引用处理共用 `knowledgeReferenceKey`,键包含远端库、文档和片段 ID、
定位及正文,避免外部结果缺少本地 ID 时被错误合并。弹窗只显示优先选中的一个定位。
早期 Dify 历史引用保存和重载检查使用测试会话;后续完整 App 已从实际输入区生成真实
短答案并点击引用验证。两轮证据分别保留,不把测试会话当成模型回答。
## 10. 需求追踪与完整性
| 需求 | 规则 | 场景 |
| --- | --- | --- |
| `EK-FR-01` 至 `EK-FR-05` | 实例状态、保存后测试、目录与手工 ID | `EK-US-A1`、`EK-US-A2`、`EK-US-B1`、`EK-US-B2` |
| `EK-FR-06` 至 `EK-FR-10` | 对象关系、创建编辑、配置与优先级 | `EK-US-B3`、`EK-US-B4`、`EK-US-D1`、`EK-US-D3` |
| `EK-FR-11` 至 `EK-FR-14` | 范围、可用性、结果与失败、引用 | `EK-US-C1` 至 `EK-US-C4`、`EK-US-D2`、`EK-US-D4` |
| `EK-FR-15`、`EK-FR-16` | 只读生命周期、凭据与请求边界 | `EK-US-A3`、`EK-US-C2` |
三家真实 Provider 的生产服务、本机 HTTP MCP、生产 IPC `always` 短答案,以及 Dify
`auto` 与完整 App 输入区回答、引用已有证据,详见[实施进度](./progress.md)。`auto` 本轮
使用进程内工具调用,不覆盖远程 ACP。FastGPT/RAGFlow 完整桌面、复杂问答和远程
forced-preflight 仍待完成;远程已确认网络可达,但已有 SSH 凭据在验证程序内无法解密。
后续 Portal 与控件修正后的聚焦测试、全量回归及相关检查已通过,精确结果由实施进度维护。
原场景中的保存前分项测试、按地址
传输确认、取消交互、版本能力状态和完整诊断尚不等同当前实现,不能把对应 User Story
全部标为通过。是否调整这些验收要求由功能 owner 确认,本轮不增加新的状态框架。