17 KiB
基于 GoodBuddy 的后端基础设计
状态:B1 已实现、验收部分完成,2026-10-05;B2 至 B6 待实现。原始设计日期为 2026-10-04。 本文是技术设计的基础服务实施分册,维护客户端适配依据、接口和实施顺序。 产品范围由 PRD维护,业务状态由功能逻辑维护,已验证事实见实施进度。
1. 设计结论
GoodBuddy 承担模型选择、对话、工具执行、知识检索入口和文档日常操作。ShareServer 独立运行, 负责模型请求转发、组织身份与授权、共享目录和服务端文档存储。ONLYOFFICE 是独立编辑服务。 不把 Electron、客户端 SQLite、Agent Runtime 或客户端源码引入服务端构建。
基础功能优先利用客户端已有调用路径:先完成正常的模型网关接入,再增加组织与设备身份, 随后实现组织模型导入和真实资源发布。知识检索、文档编辑各自按实际用户动作验收。 完整组织服务仍以 PostgreSQL 为目标;本地网关阶段继续单进程文件存储,不先建设消息系统、联邦或通用任务平台。
2. 客户端依据与差距
下表链接指向相邻 goodbuddy 仓库,要求两个仓库位于同一级目录。只引用契约,不建立源码依赖。
| 客户端实现 | 已核对行为 | 后端设计影响 |
|---|---|---|
| 模型配置 schema | profile 含 baseUrl、modelName、显式 protocol、认证方式及能力设置;模型 ID 最长 128 字符 |
开放模型 ID 按客户端限制保存;目录携带协议,不能只返回显示名称 |
| OpenAI 地址拼接 | 在 Base URL 后追加 chat/completions 或 responses;不自动增加 /v1 |
接入信息必须给出包含 /v1 的完整 Base URL |
| 模型 Runtime | 连接测试发非流式生成请求;对话走 SSE,包含工具、工具结果和用量字段 | 获取模型成功不能代替连接测试;必须验收 JSON、SSE 与工具往返 |
| 配置存储、凭据加密 | Main 保管模型 Key,Renderer 只看到是否已配置 | Desktop 保存网关访问 Key,上游 Key 留在 ShareServer |
| 模型选择 | 会话、项目、全局逐层解析模型 profile | 导入组织模型不覆盖个人模型,也不自动更换已有会话选择 |
| 设备共享服务 | 单服务 URL,稳定设备 ID,HTTP 注册、列表、发布和撤销;没有认证或心跳 | 现有 ID 不能当作用户身份;注册记录不能标为在线 |
| 发布契约 | 仅名称、描述、类型、来源模式和权限声明,没有实际资源 ID | 不能从目录记录直接派发执行或检索请求 |
| 能力目录 | 可枚举本机 Skill、MCP 等配置 | 后续发布选择器可复用枚举;枚举结果不自动授权共享 |
| 知识服务 | retrieve、retrieveMany 是现有检索入口 |
提供端经授权后直接调用知识服务,不用 Agent 提示词代替检索协议 |
| 外部知识契约 | 当前提供者是 Dify、FastGPT、RAGFlow | ShareServer 共享知识需要新增适配,不能假设现有外部连接已支持 |
| Office 功能文档 | Office 编辑尚在设计;文件解析与外部打开已有实现 | 服务端 callback 和客户端文档 Tab 都要实现,不能把解析当作编辑 |
GoodBuddy 目前没有自动获取网关模型并创建 profile 的通用流程。现有设备共享页面也不会自动 启用模型连接。设备共享应用仍默认关闭,名称保留“设备共享(技术预览)”。
模型协议分别验收:本期只支持 openai-chat-completions。Responses、Anthropic、图像生成和
Embedding 均不因为上游声称“OpenAI 兼容”而自动支持。现有网关也没有这些转发端点。
远程 Agent 使用模型时,发请求的 Host 必须能访问网关;桌面本机的 127.0.0.1 地址不能直接用于该场景。
3. 服务划分与存储
| 服务 | 第一项可用行为 | 数据归属 |
|---|---|---|
| 模型网关 | 保存上游、开放模型、验证访问 Key、转发并记录调用 | 上游配置及凭据、映射、访问 Key 摘要、调用元数据 |
| 身份与组织 | 管理员初始化、成员登录、加入组织 | 用户、组织、成员关系、会话 |
| 设备与目录 | 认证设备登记、撤销、发布者和资源绑定 | 设备归属、发布记录、动作授权;设备连接状态单独管理 |
| 客户端配置 | 显式获取并导入组织模型,回报应用结果 | 组织配置版本与每设备接收/应用结果 |
| 知识共享 | 对指定发布条目检索并返回引用 | 服务端保存发布元数据;远程模式的正文仍在提供设备 |
| 文档服务 | 上传、读取、编辑后保存、按归属删除或转交 | 主文档、归属、版本、回收记录;编辑会话单独保存 |
继续沿用 Hono 路由、业务 Store 和根 shared/ DTO。业务增长后按上述职责拆文件,不预先建立
空模块树或通用插件框架。HTTP 边界校验输入与输出投影,控制台只使用 API,不直接访问存储。
现有 sharing.json 与 gateway.json 保留。网关新增秘密使用服务端加密密文,组织阶段再将
用户、组织、设备和授权纳入 PostgreSQL 事务。迁移要保留现有 ID 和撤销事实;没有身份的旧目录
只能作为未绑定记录,不能按设备名称自动认领。迁移命令、备份和重复执行行为随数据库实现交付。
4. B1:正常模型网关接入
这一实施单元完成本地可用路径,不依赖组织数据库。支持一个 ShareServer 实例、多个上游和 多个模型映射;使用本机管理入口,GoodBuddy 可手工配置网关。组织分组、费用结算、自动切换上游另行实现。
4.1 上游与凭据
新建上游输入 name、baseUrl、protocol=openai-chat-completions、authentication=api-key|none、
enabled。使用 API Key 时输入真实密钥。更新通过 credentialAction=keep|replace|clear 区分
保留、替换和清除,空输入不解释为清除。响应只返回 credentialConfigured,不返回密钥或密文。
使用 Node 标准加密实现 AES-256-GCM;主密钥来自部署配置或数据目录外的秘密文件,首次配置
命令为 npm run gateway:init-key -- <文件路径>,父目录须已存在,拒绝覆盖已有文件。
通过 SHARESERVER_MASTER_KEY_FILE 指定文件,或用 SHARESERVER_MASTER_KEY 提供 64 位十六进制值,不能同时设置。
密文带随机 nonce 与认证标签,以稳定上游 ID 为 AAD,随上游记录原子保存,避免独立文件半提交。
缺少或错误的主密钥应报告凭据不可用,不能生成新密钥覆盖既有密文。备份说明要求单独保管主密钥。
主密钥不进入 Web、普通数据备份和日志;HTTP 请求正文不记录密钥。
现有环境变量引用是已持久化的数据,需要继续可读、可调用;编辑时可以显式替换为托管凭据。 移除产品界面的前缀导入和变量名输入,环境文件加载仅保留为开发测试方式,不自动扫描 GoodBuddy 配置。
Base URL 接受 HTTP/HTTPS,保留合法服务路径,拒绝内嵌凭据、query 和 fragment,去掉尾斜杠。 可信内网 HTTP 上游已属于支持范围。访问 Key 经非加密 HTTP 传输的部署限制在接入说明中说明,对外部署使用 HTTPS;不为此加入额外网络发现流程。
4.2 模型与转发
发现模型调用上游 /models,发现失败不删除已保存配置,也不阻止手动填写模型 ID。
用户选择模型并指定对外 ID 后才创建映射。新对外 ID 最长 128 字符,首字符为 ASCII 字母或数字,
其余允许字母、数字、下划线、点、冒号、斜杠、连字符;显示名称单独保存。现有更长别名保留调用,
在导入 GoodBuddy 前要求管理员显式改名,不静默截断已有标识。
每个对外 ID 明确绑定一个上游和远端模型。转发只替换模型名与上游认证,不执行工具,不自动重试 有可能已经执行的请求。工具参数、工具结果和用量按 Chat Completions 协议传递;取消传播至上游。 保留现有超时、输出大小边界和终态审计。上游缺失用量记录为未知,不显示为零消耗。
4.3 网关访问与管理边界
客户端访问 Key 与上游 API Key 分开。服务端生成随机访问 Key,只在创建成功时返回完整值, 持久化 SHA-256 摘要、ID、名称、创建/撤销时间和允许的模型记录 UUID;别名改名不改变授权,列表不返回原值。可撤销后重新创建, 不提供读取旧 Key。初期 Key 代表一个调用配置,审计可关联 Key ID,但不能把备注名解释为已认证用户。
/v1/models 与 /v1/chat/completions 使用 Bearer Key;未知或撤销的 Key 返回 401,
无权调用该模型返回 403。列表只返回该 Key 允许且可用的模型。停用或撤销阻止后续请求,
已开始的流按原请求结束或由调用方取消;本期不承诺撤销自动追回已输出内容。
本机管理接口不能仅依靠 Origin 检查授权。B1 默认管理请求限直连回环来源,校验实际连接地址,
拒绝携带 Forwarded、X-Forwarded-* 或 X-Real-IP 的管理请求,并检查 Origin。
Vite 在代理 /api 前也检查原始 socket,只允许回环。除健康和就绪 GET 外,非回环 API 请求
仅能访问已带 Key 的推理接口;无认证旧目录 API 也保持
本机访问。容器/反向代理管理需要 B2 登录接入,不能将代理地址当作管理员。Web 网关测试仍通过
网关转发逻辑,由本机管理入口调用,不在浏览器长期保存管理秘密或把豁免开放给推理接口。
4.4 已实现接口
下表记录 B1 已实现接口,字段、错误及资源限制以技术设计第 4.2 节为准。前缀导入接口已移除,旧环境引用仅保留存储兼容。
| 路径 | 已实现行为 |
|---|---|
GET /api/v1/gateway/config |
上游与模型公开投影、调用元数据、部署指定 gatewayBaseUrl;不携带任何密文或完整 Key |
POST /api/v1/gateway/upstreams、PUT /api/v1/gateway/upstreams/:id |
接收地址、协议、认证方式和凭据操作,替代新表单的 apiKeyEnv |
POST /api/v1/gateway/upstreams/:id/discover |
真实模型发现,保留手工映射入口 |
POST /api/v1/gateway/models、PUT /api/v1/gateway/models/:id |
保存对外 ID、显示名、远端模型和启停 |
GET/POST /api/v1/gateway/access-keys |
列表或创建模型访问 Key |
POST /api/v1/gateway/access-keys/:id/revoke |
撤销 Key,重复撤销返回同一撤销事实 |
POST /api/v1/gateway/test |
本机管理端非流式测试;复用真实转发及审计,不接受自定义上游 URL |
GET /api/v1/gateway/v1/models |
Bearer 认证后的 OpenAI 模型列表 |
POST /api/v1/gateway/v1/chat/completions |
Bearer 认证、模型授权、JSON/SSE 转发 |
Key 无效返回 401,其余错误沿用 {error:{code,message},requestId},请求 ID 与调用
审计关联。不能把上游含密钥的错误正文原样返回;保留可定位的上游状态和错误类别。
4.5 GoodBuddy 使用与验收
管理员保存上游并开放模型后,在网关接入区取得 Base URL、协议和对外模型 ID,创建访问 Key。 GoodBuddy 在现有模型连接页面手动新增配置:
Base URL: http://127.0.0.1:8787/api/v1/gateway/v1
Protocol: openai-chat-completions
Model: 管理员开放的模型 ID
API Key: ShareServer 签发的访问 Key
该操作不依赖设备共享开关,不读取供应商 Key,不修改个人已有 profile。异机调用用客户端可达 的 ShareServer 地址;界面显示配置的公开地址,不能把 Vite 端口或请求中的任意 Host 当作权威地址。
以下为完整验收清单,尚未全部通过。2026-10-05 已完成自动化检查和部分真实 API 验证, 包括发现、JSON/SSE、工具选择及本地执行、重启持久化与撤销拒绝;工具结果未回传上游, 未验证 GoodBuddy Desktop;浏览器仅核对页面快照,交互与视觉验收未完成。详细证据和剩余项目见实施进度。
验收依次检查:
- 从空目录经 Web 保存真实上游,发现或手动添加模型;刷新、重启仍保留配置,密钥不回显。
- GoodBuddy 现有模型连接测试成功,真实会话收到流式回答,审计可以关联模型和访问 Key。
- 用无副作用工具完成一次真实工具调用与结果回传;停止生成时上游请求被取消。
- 错误 Key、撤销 Key、未授权模型和停用上游均拒绝新调用,错误不伪装成空成功响应。
- 上游超时、SSE 中断、凭据缺失、主密钥错误均给出准确状态;检查持久化及日志不含明文秘密或对话正文。
- 验证 HTTP 内网上游及管理接口来源限制。单元测试不能替代上述桌面与真实服务验证。
这组验证只覆盖本机模型 Runtime。OpenCode、Continue、Harness 和远程 Agent 另行记录结果, 不从同一个 profile 推断全部 Runtime 可用。真实模型验证记录调用次数,不将配置下发标记为已实现。
5. 后续基础服务实施顺序
| 单元 | 交付内容 | 前置条件与完成标准 |
|---|---|---|
| B2 身份与组织 | PostgreSQL 迁移、首个管理员、登录退出、单组织成员、设备绑定与撤销;Web 使用会话,Desktop 凭据在 Main 保存 | 从可信本机管理扩展到组织部署;两个不同成员不能改动对方设备或私人资源;退出或撤销后新请求被拒 |
| B3 组织模型导入 | 认证目录、用户显式导入、组织模型来源标记、配置版本与应用回报 | 依赖 B2;客户端创建独立 profile,保留个人配置;离线为待接收,收到后保存成功才为已应用 |
| B4 真实资源发布 | 从本机能力/知识库选择资源,登记稳定来源 ID、所有者、提供设备及独立动作权限 | 依赖 B2;客户端增加资源绑定和提供端通道;无心跳不显示在线,旧手工目录不自动成为可调用资源 |
| B5 共享知识检索 | 消费者选共享库,服务端授权并路由,提供端调用 retrieveMany,返回有界引用 |
依赖 B4;两台 GoodBuddy 真实检索,撤销及提供端离线有准确失败;正文读取、下载各自另验收 |
| B6 服务端文档 | 主文档上传、读取、个人删除、转交组织、回收;再接 ONLYOFFICE 编辑保存与 GoodBuddy 文档入口 | 归属功能依赖 B2;保存后重开及重启可见,转交后个人删除权失效,管理员元数据可见不赋予正文权限 |
Office 私有 DOCX 试验仍可按技术设计第 10.1 节独立验证部署与保存。该试验没有用户归属, 不能替代 B6。后续服务端主存文档保存不要求 Desktop 回写确认;显式本地/SSH 来源模式另走既有源文件契约。
B3 先实现主动获取和显式导入,不以推送、离线队列或回滚系统为第一步。组织配置关联服务端稳定 模型 ID,个人 profile 不由组织配置覆盖。组织撤销后网关直接拒绝访问,客户端缓存不能维持授权。
B4 的提供端连接必须单独实现。已有 Agent 执行通道没有发布身份、共享授权和知识正文协议,不能 直接暴露为共享 API。远程知识模式不上传整个库;服务器副本模式须实际完成文件与索引写入才可标为可检索。
6. 文档与实施记录
2026-10-04 设计轮只完成设计与源码核对,不更改两仓运行代码、不读取 .env*、不调用上游模型。
现有模拟接口仍留在服务端源码但已退出控制台路由,后续清理应单独验证调用方,不作为基础服务使用。
2026-10-05 按 B1 代码同步技术设计第 4.2 节、逻辑规则、UI 设计、运行文档和实施进度,
将实现状态与部分验收结果分开记录。B2 至 B6 和 B1 剩余验收继续按上述顺序推进。
跨产品网络与 Office 契约继续引用 GoodBuddy 原文;其总体架构仍有“没有真实 Desktop 集成”的旧描述, 应在后续 GoodBuddy 文档同步时改为“已有元数据接线,完整共享网络待实现”。本轮不修改相邻仓库。