PrivateGPT Workbench 的“单一事实来源“体系:从 ui/docs/SOURCE_OF_TRUTH.md 读懂单文件 UI 的实现契约

发布时间:2026/9/7 9:27:29
PrivateGPT Workbench 的“单一事实来源“体系:从 ui/docs/SOURCE_OF_TRUTH.md 读懂单文件 UI 的实现契约 PrivateGPT Workbench 的单一事实来源体系从 ui/docs/SOURCE_OF_TRUTH.md 读懂单文件 UI 的实现契约【免费下载链接】privateGPTComplete API layer for private AI applications on local models: RAG, skills, tools, MCP, text-to-sql, and more. Works with any OpenAI-compatible inference server.项目地址: https://gitcode.com/GitHub_Trending/pr/privateGPT本文以 ui/docs/SOURCE_OF_TRUTH.md 为主体系统讲解 PrivateGPT 工作台Workbench演示 UI 的文档治理体系运行时实现的唯一归属、人类与 Agent 的入口分层、Fern 生成的 OpenAPI 契约位置以及十余条只有读源码才能验证的关键实现笔记。读完本文你既能掌握如何维护一套人与 AI Agent 共用的 UI 文档结构也能对照 ui/index.html 的 7974 行单文件实现理解默认集合Collection、有状态引导Onboarding、外观变量、推理强度Reasoning Effort与 Code Execution 会话连续性等核心机制在代码中的真实落点。一、文档体系总览ui/ 目录的单一事实来源SOURCE_OF_TRUTH.md 开宗明义This document defines where the authoritative guidance forui/lives.本文档定义ui/的权威指引存在于何处。它不是产品文档也不是样式指南而是一份文档治理清单规定哪个文件是唯一运行时实现、哪类内容应该写在哪个文件里、API 契约以哪里为准。ui/README.md 中的目录地图与之一一对应路径角色ui/index.html唯一的运行时实现文件Workbench 演示 UI 的全部 HTML/CSS/JSui/README.md顶层导航与目录地图ui/AGENTS.mdCodex / OpenAI 风格 Agent 的工作流说明ui/CLAUDE.mdClaude Code 的工作流说明ui/docs/PRD.md产品行为与信息架构约 999 行ui/docs/STYLE_GUIDE.md视觉与交互方向约 599 行ui/docs/SOURCE_OF_TRUTH.md权威路径、API 契约与文档归属本文主题ui/references/*供样式指南使用的非运行时视觉参考图这种单文件运行时 分门别类的文档组织方式使得运行时逻辑保持在一个文件内便于审查README 明确要求Keep the app implementation inindex.htmlunless a separate refactor is explicitly requested而所有设计决策外置到docs/避免规则散落在实现旁边。二、人类与 Agent 的入口分层SOURCE_OF_TRUTH.md 将入口分为两类运行时实现仅 ui/index.html 一个文件人类与 Agent 入口ui/README.md顶层导航、ui/AGENTS.mdCodex 风格 Agent、ui/CLAUDE.mdClaude Code。从源码结构看两个 Agent 入口文件的分工非常一致。ui/AGENTS.md 要求 Agent 在修改行为、UI 或 API 接线前按序阅读五个文件ui/README.mdui/docs/SOURCE_OF_TRUTH.mdui/docs/PRD.mdui/docs/STYLE_GUIDE.mdui/index.html并给出两条硬性规则把SOURCE_OF_TRUTH.md视为 API 契约路径与文档归属的权威指针当实现与文档不一致时fix the disagreement in the same change在同一次变更中修复分歧。ui/CLAUDE.md 内容更精简但同样要求先读上述共享文档并强调Use the shared docs above as the source of truth instead of duplicating product or design rules here——即不在这类入口文件里重复产品或设计规则。这形成了清晰的文档金字塔入口文件只做指针规则下沉到 PRD 与样式指南事实核对以本文件和源码为准。三、API 契约以 Fern 生成的 OpenAPI 为唯一来源SOURCE_OF_TRUTH.md 对 API 契约给出了明确且排他的规定Workbench should follow the Fern-generated OpenAPI schema at:../../fern/openapi/openapi.json相对仓库根目录即 fern/openapi/openapi.json。Do not maintain a duplicated UI-local OpenAPI snapshot.不要维护一份 UI 本地的 OpenAPI 副本。该约束在仓库中可以得到验证fern/openapi/openapi.json 确实定义了 Workbench 实际调用的核心路径包括/v1/messages流式对话、/v1/files按scope_id隔离的文件上传/列表和/v1/files/{file_id}/content按scope_id下载文件内容。在 ui/index.html 中可以逐一找到这些路径的调用方流式对话apiStreamFetch(/v1/messages, ...)ui/index.html以及外观生成时复用同一端点的apiFetch(/v1/messages, ...)ui/index.html会话文件列表/v1/files?scope_id{chat.id}ui/index.html会话文件下载/v1/files/{file_id}/content?scope_id{chat.id}ui/index.html。此外UI 还调用了/v1/models加载模型ui/index.html、/v1/artifacts/list与/v1/artifacts/ingest知识库文档ui/index.html、/v1/skills技能ui/index.html等端点。由于仓库规定不保留 UI 本地的 OpenAPI 快照阅读这份演示 UI 时接口字段的第一手依据始终是 fern/openapi/openapi.json而不是 UI 代码中的内联类型——这正是单一事实来源原则在 API 层的具体化。四、工作规则内容归属与同步更新SOURCE_OF_TRUTH.md 的 Working Rules 一节用五条规则划定了文档归属边界产品需求 →ui/docs/PRD.md视觉规则 →ui/docs/STYLE_GUIDE.mdAgent 专属工作流规则 →ui/AGENTS.md与ui/CLAUDE.md参考图片 →ui/references/运行时代码 →ui/index.html并附上一条关键纪律If a change affects behavior, visuals, persistence, security posture, or API request/response handling, update the relevant docs in the same change.若变更影响行为、视觉、持久化、安全姿态或 API 请求/响应处理必须在同一次变更中更新相关文档。ui/README.md 的 Working Rules 与之互为镜像Keep docs and implementation aligned whenever behavior, visuals, persistence, or API wiring changes。对以 Agent 协作为主的仓库这条规则实际上把文档腐化预防到了提交粒度。五、关键实现笔记上状态模型与行为机制SOURCE_OF_TRUTH.md 的 Key Implementation Notes 自称是those things not obvious from readingindex.html单看 ui/index.html 不易察觉、但未来的维护者与 Agent 必须知道的事项。以下逐条对照源码验证5.1 集合Collection存于 Settings 而非 Documents 面板文档指出集合不是放在文档面板而是state.context.documents.defaultCollection是所有文档与聊天操作共用的唯一全局集合名。源码印证状态初始化时默认值为pgpt_collectionui/index.html设置面板输入框#defaultCollection与之双向同步ui/index.html聊天副标题ui/index.html、技能过滤上下文skill_filter.collectionui/index.html以及引导流程ui/index.html都直接回退读取该字段——single global collection name的描述与调用链完全吻合。5.2 有状态的 Onboardingstate.onboarding控制首跑引导浮层当前步骤与最近一次活体校验结果都写在其中浮层的显示条件只有一个——state.onboarding.completed ! true。源码中的渲染逻辑正是如此const isOpen state.onboarding?.completed ! trueui/index.html步骤由state.onboarding?.step决定ui/index.html校验结果缓存在state.onboarding.lastCheckui/index.html。5.3 外观覆盖是运行时变量state.uiAppearance通过applyAppearance()同时驱动文案、功能可见性与 CSS 自定义属性。源码中applyAppearance()位于 ui/index.html调用paintAppearance()将state.uiAppearance || DEFAULT_APPEARANCE写入 DOM功能开关统一走featureEnabled(key)其语义是state.uiAppearance?.features?.[key] ! falseui/index.html即默认开启、显式关闭。品牌名、欢迎标题等文案同理回退到DEFAULT_APPEARANCEui/index.html。Settings 与 Onboarding 写入的是同一结构这与文档Settings and onboarding write into the same structure一致。5.4 外观生成复用聊天 API文档称主题简报theme brief走POST /v1/messages解析为 JSON 后回写到外观表单中用户可手工编辑的字段。源码验证引导/外观生成流程调用apiFetch(/v1/messages, ...)ui/index.html且状态合并逻辑把用户已有的uiAppearance含palette、features与生成结果做深合并ui/index.html保证生成不覆盖手工配置——这正是written back into the same appearance form fields的实现方式。5.5 自定义工具执行被收敛到单条助手气泡文档说明初始响应、工具结果与后续回答都渲染在同一个助手消息气泡内hidden: true的消息只承载 API 历史、永不渲染。消息渲染的核心函数是blocksToHtml()ui/index.html请求构建侧的sanitizeMessages()负责把隐藏消息从渲染流中剥离。这一设计让多轮工具调用在界面上呈现为一次连贯的助手发言而非碎片化的多条气泡。六、关键实现笔记中交互与渲染细节6.1 自定义模型选择器模型选择器不是原生select而是由#modelSelectBtn#modelDropdown两个自定义元素构成由renderModelSelect()ui/index.html填充。选择器内部同时承载模型列表与推理强度选项选择一个模型或强度时就地更新现有弹窗 DOM保留搜索与滚动位置仅由触发按钮、Esc 或外部点击关闭——这一行为约束避免了重新渲染导致的输入丢失。6.2 推理强度与 thinking 请求字段每个聊天把推理强度存在chat.settings.reasoningEffort取值为null、low、medium、high、max或xhigh默认nullNone。源码中初始化即为reasoningEffort: nullui/index.html对旧数据还会做缺省补全ui/index.html。请求构建时该值被转换为const reasoningEffort state.enableThinking ! false ? chat.settings.reasoningEffort || null : null; // ... body { model: state.selectedModel, messages: sanitizeMessages(chat.messages), tools, tool_context, mcp_servers, stream: true, max_tokens: 4096, thinking: { enabled: Boolean(reasoningEffort), type: reasoningEffort } };ui/index.html。文档提到effort options are enabled from the selected modelscapabilities.effortresponse——源码中当当前选中强度不在模型能力列表内时会被重置为nullui/index.html这正是对模型capabilities.effort响应的消费。6.3 Composer 加号菜单与附件复用既有上传路径Composer 的操作被收敛到一个加号按钮菜单先列出 Add files随后是既有的聊天工具/上下文控件不存在独立的 Build 模式或 Build 按钮。附件行为按 Code Execution 状态分叉——开启时会发送到当前 code-execution 会话否则摄取进已配置的 Documents 集合。源码分叉点在 ui/index.htmlif (chat?.settings?.enabledCodeExecution) await uploadToSession(files)。6.4 Hash 导航syncHash()/restoreFromHash()让 URL 与当前视图保持同步格式为#context/{tab}、#chat/{id}、#settings、#apiDebugger。源码实现ui/index.html与文档完全一致syncHash()依据runtime.view与state.activeChatId拼出 hash 后用history.replaceState静默更新restoreFromHash()在页面加载时按前缀解析且只接受白名单内的 context tabCONTEXT_TAB_IDS包含documents、databases、web、mcp、skills、customTools、codeExecution与已存在的 chat id——防止脏 hash 破坏视图状态。6.5 滚动渐隐、开关样式与浮动面板磨砂滚动渐隐.chat-list-wrap与.messages使用mask-image配合--fade-top-stop/--fade-bot-stop两个自定义属性由updateMessagesFade()ui/index.html与updateChatListFade()ui/index.html在滚动时更新距顶部/底部 6px 之内时渐隐宽度归零否则为 28px消息区或 22px会话列表。开关所有input[typecheckbox]都被样式化为无原生外观的自定义 CSS 药丸开关。浮动面板磨砂.modal-card、.menu-panel、.model-dropdown覆写共享的 glass 组采用近实心深色背景rgba(10,12,22,0.82–0.94)、blur(72px) saturate(1.4)与上浅下深的to bottom渐变用于保证可读性与视觉落定感。这三条属于纯表现层契约读 ui/index.html 的样式段固然能看到但为什么可读性、统一开关手感只有这份实现笔记给出了意图。七、关键实现笔记下Code Execution 的端到端契约Code Execution 是这份实现笔记中篇幅最大的一组条目涉及工具声明、渲染、会话连续性与文件 I/O 四个层面逐条对照源码7.1 工具声明与后端展开Tools 菜单中的 Code Execution 开关在请求的tools数组里发送一个简写声明if (chat.settings.enabledCodeExecution) { tools.push({ name: code_execution, type: code_execution_v1 }); }ui/index.html。后端会把该声明展开为bash、text_editorview / str_replace / create / insert、present_files与present_server等具体工具。开关状态按聊天粒度持久化在chat.settings.enabledCodeExecutionui/index.html、ui/index.html。7.2 渲染isCodeExecTool 白名单与块配对渲染侧的关键函数isCodeExecTool(name)ui/index.html维护白名单bash、view、str_replace、create、insert、present_files、present_server。blocksToHtml()在遇到这些工具的tool_use/server_tool_use块时ui/index.html把相邻的 tool_use tool_result 配对合并为一个.code-exec-blockdetails 元素呈现终端输出、带行号的文件视图、diff 高亮与退出码徽章对应样式集中在 ui/index.html 的.code-exec-block样式族中。白名单同时驱动是否配对与逐工具如何渲染两个决策避免把无关工具误并入代码执行样式。7.3 会话连续性container 字段文档强调thecontainerfield must be set whenever code execution tools are active。请求构建代码印证ui/index.htmlif (chat.settings.enabledCodeExecution) { body.container chat.id; }即把chat.id作为container放进ChatBody后端据此在整个聊天的所有消息间复用同一个沙箱会话。从源码结构看这解释了为何 Code Execution 的文件与进程状态可以跨消息保持——会话身份由聊天 id 承载而非每次请求新建。7.4 文件上传直接进入会话工作区开启 Code Execution 后 Composer 工具栏出现Files按钮选择的文件以 multipart/form-data 直接上传到POST /v1/files?scope_id{chat.id}ui/index.html落入会话工作区可被模型的 bash/文件工具访问随后通过GET /v1/files?scope_id{chat.id}列出ui/index.html、DELETE /v1/files/{file_id}?scope_id{chat.id}删除ui/index.html。这与 fern/openapi/openapi.json 中/v1/files端点按scope_id隔离的设计一致。7.5 文件下载与服务链接下载present_files结果中的local_resource块被渲染为.code-exec-download锚点指向GET /v1/files/{file_id}/content?scope_id{chat.id}ui/index.htmlfile_id与mime_type取自local_resource块 schema服务链接present_server结果中的resource_link块被渲染为.code-exec-server-link锚点地球图标 服务名 隧道 URL新标签页打开uri、name、description取自resource_link块 schematool_use 摘要显示service_name:port及可选initial_path深链。八、验证方式与维护闭环维护这套单文件 UI 有一个明确的最低验证动作记录在 ui/README.md由 ui/AGENTS.md 转引为 Agent 必做步骤对 ui/index.html 的改动必须验证内联脚本可解析node -e const fsrequire(fs); const htmlfs.readFileSync(./ui/index.html,utf8); const mhtml.match(/script([\s\S]*)\/script/); if(!m) throw new Error(script tag not found); new Function(m[1]); console.log(script ok)该命令提取最后一个script块并尝试构造函数以做语法级校验是单文件运行时架构下最轻量的回归防线。再结合 SOURCE_OF_TRUTH 的同步更新规则行为/视觉/持久化/安全/API 处理变更必须同改文档与 Agent 入口的发现实现与文档分歧须同次修复要求ui/形成了一条完整闭环文档定义权威位置 → 入口文件只做指针 → 源码是最终事实 → 脚本解析校验兜底。九、小结这份 SOURCE_OF_TRUTH 的工程价值ui/docs/SOURCE_OF_TRUTH.md 的价值不在于它描述的某个功能而在于它示范了一套可复用的人机协作型 UI 文档治理范式归属清晰每条内容只有一个权威落点API 契约指回 fern/openapi/openapi.json 而非 UI 本地快照入口分层人读 READMEAgent 读 AGENTS/CLAUDE两者共享同一组 docs 作为唯一事实源实现笔记前置隐性知识defaultCollection的全局性、container chat.id的强制约束、thinking: { enabled, type }的请求形态、hidden: true消息不渲染等约定若不写成文档维护者尤其是新接入的编码 Agent极易从 ui/index.html 的局部代码中得出错误结论。对希望在自己的仓库中引入单文件演示 UI 多 Agent 协作模式的团队这套README → SOURCE_OF_TRUTH → PRD / STYLE_GUIDE → references的分层与同变更同步文档纪律是比任何单条规则都更值得借鉴的部分。【免费下载链接】privateGPTComplete API layer for private AI applications on local models: RAG, skills, tools, MCP, text-to-sql, and more. Works with any OpenAI-compatible inference server.项目地址: https://gitcode.com/GitHub_Trending/pr/privateGPT创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考