AionUi 反馈数据库诊断(Feedback DB Diagnostics):面向隐私安全的对话/模型/团队故障快照设计
2026/9/19 18:47:01 网站建设 项目流程

AionUi 反馈数据库诊断(Feedback DB Diagnostics):面向隐私安全的对话/模型/团队故障快照设计

【免费下载链接】AionUi免费、本地、开源的 24/7 全天候 Cowork 应用,以及适用于 Gemini CLI、Claude Code、Codex、OpenCode、Qwen Code、Goose CLI、Auggie 等的 OpenClaw | 🌟 喜欢就点star吧项目地址: https://gitcode.com/iOfficeAI/AionUi

导读

用户反馈(User Feedback)是 AionUi 桌面端排查问题的重要通道,但传统上仅凭 Sentry 事件中的模块、描述、日志与截图,往往不足以还原一次对话失败时的最终落库状态:turns 是否失败、消息处于什么状态、选了哪个 Provider/Model、ACP 会话配置如何、团队 backlog 里积压了什么。本文基于 docs/prds/settings/feedback-db-diagnostics.md 这份 PRD,完整讲解 AionUi 如何在反馈报告中附加一份小型、隐私安全的数据库快照db-diagnostics.json/db-diagnostics.json.gz),包括 AionUi 与 aionCore 的职责边界、五个诊断 Profile 的输出白名单与红线清单、前端路由/模块上下文的采集链路,以及配套的单测与 E2E 验证。读完你不仅能理解该机制的设计取舍,还能掌握其在 submitFeedbackReport.ts 等源码中的真实实现细节。

背景:为什么日志和截图不够用

PRD 开篇点明了动机:Sentry 中的用户反馈已经包含type=user-feedback、所选模块、描述、日志和截图,但真实反馈样本表明,对于对话 / 模型 / 团队类问题这些信息常常不足:

  • 日志能说明某个 turn 失败了,却不一定能展示最终持久化的会话状态
  • 无法确知消息的状态字段、用户实际选中的Provider/Model
  • 缺少ACP 会话配置(mode/model/effort 等非机密配置项)与团队 backlog(任务/信箱计数)的快照。

因此 PRD 提出:反馈报告需要附带一个诊断附件——由 aionCore 生成、经过严格脱敏的数据库快照。它的红线非常明确:不得上传 SQLite 数据库文件本身、不得执行任意 SQL、不得包含 prompt、消息内容、Provider API Key 或原始错误消息

职责边界:AionUi 只做编排,aionCore 掌握全部诊断逻辑

这是本 PRD 最重要的架构约束,它把「谁来采集、谁来生成」划分得泾渭分明:

归属职责
AionUi(渲染进程)捕获route_at_openroute_at_submit;发送用户选择的模块;从反馈入口显式发送安全 ID(conversation_idprovider_idteam_idagent_idmcp_server_id等);调用 aionCore 的GET /api/system/diagnostics/feedback-report;将返回的 JSON 在支持 gzip 时附为db-diagnostics.json.gz,否则附为db-diagnostics.json
aionCore(主进程侧后端)路由/模块/Profile 解析;路由派生 Profile、模块派生 Profile 与显式 Profile 的并集(union);SQL 选择;用户隔离;脱敏与字段白名单;响应 Schema

两个硬性约束值得注意:

  1. AionUi 主进程不得读取 SQLite,也不得暴露feedback:collect-db-diagnosticsIPC——采集逻辑完全收敛在 aionCore 的 HTTP 接口之后,前端只做「传参 → 收 JSON → 打包附件」。
  2. 诊断路径必须走HTTP 而非 IPC,这既隔离了数据库访问权限,也保证了 Web 构建下(无window.electronAPI)依然能工作。

前端实现对照

在渲染进程中,反馈模态框(FeedbackReportModal.tsx)提交时构造collectDbDiagnostics输入,交给 submitFeedbackReport.ts 的collectDbDiagnosticsAttachment

  • 使用httpRequest('GET', ...)请求诊断接口,并对400/401/403/404/500/502/503/504静默处理,避免诊断失败打断主反馈提交流程;
  • buildFeedbackDiagnosticsPath(第 178-192 行)通过URLSearchParamsroute_at_openroute_at_submitselected_moduleprofiles(逗号拼接的显式 Profile)以及conversation_idprovider_idagent_idteam_idmcp_server_id拼进查询串;
  • encodeDiagnosticsAttachmentPayload(第 201-226 行)先TextEncoder序列化 JSON,再检测CompressionStream是否可用:可用则经CompressionStream('gzip')压缩,产出db-diagnostics.json.gzapplication/gzip);不可用或压缩异常则回退为db-diagnostics.jsonapplication/json)。

采集状态会被记录进随附日志(collected / empty / failed / skipped / unavailable),失败时反馈照常提交,只是附件缺失——诊断是尽力而为的增强,不是提交的硬依赖。

Profile 解析:路由上下文优先于用户所选模块

PRD 给出了一个关键设计决策:路由上下文比所选模块更可信,因为用户可能选错模块;但所选模块仍是有价值的用户意图。因此 aionCore 必须取以下来源的并集

  • 提交时的路由(route_at_submit
  • 打开时的路由(route_at_open
  • 所选模块(selected_module
  • 显式 Profile 提示(profiles
  • 恒定的global-summary

PRD 给出示例:若反馈在#/conversations/conv-1页面打开、用户却选了system-settings,则附件应至少包含conversation-sessionmodel-authmcp-toolsglobal-summary四个 Profile——即「路由说这是对话问题、用户觉得是设置问题」,两者都要覆盖。

前端的路由捕获与 ID 推导

前端侧的路由采集在 routeContext.ts:

  • captureFeedbackRoute()优先取window.location.hash,否则回退到pathname + search + hash
  • feedbackDiagnosticsContextFromRoute(route)用正则/^#?\/(conversation|team)\/([^/?#]+)/从路由直接推导teamIdconversationId(已做decodeURIComponent与空值防御)。

这两个能力被 FeedbackContext.tsx 的openFeedback组装:打开模态框瞬间捕获routeAtOpen并推导路由 ID,与调用方传入的diagnosticsContext合并(调用方字段覆盖路由推导值),最终在提交时由模态框补上routeAtSubmitselectedModule。此外,标题栏反馈按钮还会通过 resolveFeedbackModule.ts 的ROUTE_MODULE_MAP(如/conversationconversation-session/teamagent-team/settings/modelmodel-auth/settings/toolsmcp-tools)按当前页面预选模块,该映射对应用户可见的 FEEDBACK_MODULES 模块列表,并有 feedback-route-module.e2e.ts 覆盖各路由的预选行为。

五个诊断 Profile 详解

PRD 为 aionCore 定义了五个 Profile,每个都明确了「详细键(detailed key)」、适用场景、允许输出禁止输出清单。下面按原文完整展开并结合实现说明。

conversation-session(会话)

  • 详细键conversation_id
  • 适用场景(Sentry 中真实见到的问题):
    • Provider 认证失败(日志出现UserLlmProviderAuthFailed);
    • OpenCode 模式/模型确认超时;
    • 回合以空输出或隐藏输出结束;
    • 图片/文件输入类投诉(需要消息元数据与附件计数)。
  • 允许输出
    • 当前会话的 id/title/type/status/source/model provider id/model id/timestamps/name 长度;
    • 同一用户作用域内、被报告会话附近的近期会话(当前为24 小时窗口、上限 20 行),含标题、id、状态、model/provider id、消息计数与最近错误码;
    • 按 type/status/hidden 聚合的消息计数;
    • 近期消息元数据:id、msg id、type、status、position、内容字节长度、文本长度、附件/图片/工具调用计数;
    • 近期错误元数据:错误码、归属、是否可重试、解决类型/目标、是否建议反馈;
    • ACP 会话元数据:agent id/source/status、session id 是否存在、运行时当前 mode/model、非机密配置选择值(mode/model/effort);
    • agent 元数据计数:可用 mode/model/command/配置项数量、最近检查状态/错误码;
    • assistant 快照元数据与数组计数。
  • 禁止输出:原始messages.content、prompts、原始session_configrules_content、Provider API Key、原始错误消息。

model-auth(模型认证)

  • 详细键provider_id,或由conversation_id推导。
  • 允许输出
    • provider id/platform/name/enabled;
    • api_key_configured布尔值(只回答「有没有配」,绝不回显 Key);
    • base URL 的主机部分(不含路径/查询串);
    • 模型总数、被禁用模型数、不健康模型数;
    • 能力(capability)计数与时间戳。
  • 禁止输出api_key_encrypted、完整 URL、URL 查询字符串、bearer token、Bedrock 配置。

agent-team(Agent 团队)

  • 详细键team_id,或由conversation_id推导。
  • 允许输出
    • team id、name 长度、工作区模式、会话模式、agent 数量、lead agent id、agents 版本、时间戳;
    • 按状态统计的任务计数;
    • 按类型/已读状态统计的信箱计数。
  • 禁止输出:工作区绝对路径、任务 subject/description、信箱内容、信箱摘要。

mcp-tools(MCP 工具)

  • 详细键mcp_server_id
  • 允许输出
    • server id/name/enabled/builtin/传输类型(transport type);
    • 工具数量;
    • 最近测试状态与最近连接时间戳;
    • 传输配置字节长度与原始 JSON 字节长度(只报长度,不报内容)。
  • 禁止输出:原始传输配置、原始 JSON、headers、env 值、token。

global-summary(全局摘要)

始终作为低成本上下文附带,输出仅包含当前用户的聚合计数:

  • 当前用户的会话数;
  • 当前用户会话的消息数;
  • Provider 数量;
  • Agent 数量;
  • 活跃 MCP server 数量。

隐私要求:保留诊断价值,剔除凭据风险

PRD 明确响应必须在保留诊断价值的同时,排除真正构成隐私/凭据风险的少数类别:

  • 不输出原始数据库文件;
  • 不执行任意前端 SQL;
  • 不输出providers.api_key_encrypted
  • 不输出users.password_hashusers.jwt_secretusers.email
  • 不输出 OAuth 或远程 agent token;
  • 不输出原始 prompt/消息内容;
  • 不输出原始错误消息;
  • 不输出带 userinfo/查询串的完整 URL。

一个容易被误解的点:会话标题(conversation titles)是允许输出的,因为需要它来将数据库快照与截图、Sentry 反馈相互关联;标题不会单独按sk-...tokenbearer之类的字符串形态做二次脱敏(也就是说,若用户把密钥写进了标题,标题本身不会被额外清洗——这是文档明确写出的取舍)。

aionCore 的响应必须包含一个privacy块作为自证声明:

{ "raw_content_included": false, "api_keys_included": false }

测试则必须断言:具有代表性的 Provider API Key、加密的 Provider Key、原始 prompt 文本与原始错误消息,不会出现在序列化后的诊断响应中。

测试与验证:从单测到 E2E

仓库为这套链路提供了多层次的验证:

  • submitFeedbackReport.test.ts 的单测会 stubfetch,断言请求路径包含/api/system/diagnostics/feedback-report?route_at_openroute_at_submitselected_moduleconversation_id等查询参数且方法为GET,并断言附件文件名匹配/^db-diagnostics\.json(?:\.gz)?$/、contentType 匹配^application\/(?:gzip|json)$;当fetch抛错(如db locked)时,反馈仍正常提交且附件为空。
  • feedback-route-module.e2e.ts 覆盖标题栏反馈按钮按路由预选模块的行为(如/scheduled预选scheduled-task/settings/model预选model-auth/settings兜底system-settings)。
  • FeedbackReportModal.dom.test.tsx 等 DOM 测试覆盖模态框的模块选择、截图预填、路由上下文透传等交互细节。

总结

AionUi 的 Feedback DB Diagnostics 是一份「小而安全」的故障快照设计:AionUi 渲染进程只负责捕获路由与显式 ID、调用 aionCore 的GET /api/system/diagnostics/feedback-report并把 JSON 打包为(gzip 优先的)db-diagnostics.json附件;所有 SQL、Profile 并集、用户隔离、脱敏与字段白名单全部收敛在 aionCore 侧。五个 Profile(conversation-sessionmodel-authagent-teammcp-toolsglobal-summary)各自明确了 detailed key、允许输出的诊断字段与绝对禁止的凭据/内容字段,最终以privacy块自证raw_content_included: falseapi_keys_included: false。它既显著提升了对话/模型/团队类问题的可诊断性,又严守了「不上传 DB 文件、不执行任意 SQL、不泄露密钥与消息内容」的隐私底线——这一边界在 submitFeedbackReport.ts 与配套测试中有完整、可复核的实现支撑。

【免费下载链接】AionUi免费、本地、开源的 24/7 全天候 Cowork 应用,以及适用于 Gemini CLI、Claude Code、Codex、OpenCode、Qwen Code、Goose CLI、Auggie 等的 OpenClaw | 🌟 喜欢就点star吧项目地址: https://gitcode.com/iOfficeAI/AionUi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询