ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

DeepChat 数据导入实战:agent.db 加密架构、SQLite Schema 与跨平台迁移指南

DeepChat 数据导入实战:agent.db 加密架构、SQLite Schema 与跨平台迁移指南 DeepChat 数据导入实战agent.db 加密架构、SQLite Schema 与跨平台迁移指南【免费下载链接】deepchatDeepChat - A smart assistant that connects powerful AI to your personal world项目地址: https://gitcode.com/GitHub_Trending/dee/deepchatDeepChat 将提供商配置、会话、消息等核心数据持久化在本地的agent.dbSQLCipher 可加密 SQLite中。本篇基于仓库.agents/skills/deepchat-data-import技能包系统讲解第三方工具如何安全地定位、解锁、读取并迁移 DeepChat 本地数据从磁盘上的文件布局、safeStorage 密码解包决策树到new_sessions/deepchat_messages等核心表结构再到可直接落地的只读导出、一致性校验与秘密脱敏实践。读完本篇你将能够设计并实现一个合规、可复现、面向 DeepChat 真实数据形态的导入器。概述把 SQLite 当作一份可文档化的内部契约DeepChat 的本地数据存储以 SQLite 为核心但其 Schema 属于内部但可文档化的契约写入导入器时应以读取当前真实 Schema为第一原则优先使用只读快照并且绝不要向正在运行的用户配置文件写入任何内容。技能包给出的标准工作流见 SKILL.md如下识别数据源在线运行的 DeepChat 配置目录、拷贝出来的配置目录、同步备份包、导出的agent.db或旧版chat.db。定位数据阅读>electron userData/app_db/agent.db electron userData/app_db/agent.db-wal electron userData/app_db/agent.db-shm其中agent.db-walWrite-Ahead Log与agent.db-shmShared Memory是 SQLite WAL 模式的侧车文件。拷贝运行中的数据库时三者必须一起拷贝否则近期事务可能从副本中消失。旧版数据库如果存在为electron userData/app_db/chat.db加密元数据不在 SQLite 内部而是独立的 ElectronStore JSON 文件electron userData/database-security.json其关键结构如下与仓库 databaseSecurity.ts 中DatabaseSecurityMetadata类型一致{ metadata: { version: 1, enabled: true, cipher: sqlcipher, passwordStorage: safeStorage, wrappedPassword: base64-electron-safeStorage-blob, safeStorageBackend: basic_text, lastMigrationAt: 1770000000000, lastMigrationDirection: enable } }passwordStorage的取值空间为safeStorage、manual、none三种当enabled为false时agent.db就是普通明文 SQLite可直接打开。默认 userData 路径Electron 默认依据打包产品名DeepChat推导配置目录除非运行时通过app.getPath(userData)覆盖macOS: ~/Library/Application Support/DeepChat Windows: %APPDATA%\DeepChat Linux: ~/.config/DeepChat这些只是默认值——便携版、开发构建、测试环境或用户手动覆盖都可能指向其他位置导入器不应硬编码路径。同步备份布局与快照规则DeepChat 同步备份包中当前版本以database/agent.db作为主数据库负载部分兼容性备份还可能包含database/chat.db或旧版 JSON 设置。当agent.db与chat.db同时存在时优先读取agent.db。快照规则数据完整性红线DeepChat 正在运行agent.db、agent.db-wal、agent.db-shm必须一并拷贝。DeepChat 已退出单独拷agent.db通常足够但连同侧车一起拷也无害。高完整性导入对源库建立只读连接用 SQLite backup API 落一份临时文件再从临时文件导入。不要删除用户配置中的*.migration-tmp、*.migration-rollback、agent.db-wal、agent.db-shm——这些生命周期决策由 DeepChat 自己负责。仍留在 agent.db 之外的 JSON 文件多数敏感配置已迁入 SQLite但userData下可能仍残留少量轻量/兼容 JSONapp-settings.jsoncustom_prompts.jsonsystem_prompts.jsonmcp-settings.json导入当前版本数据时应优先读取 SQLite 中的 provider、MCP、应用设置、提示词与知识配置表JSON 文件仅作为旧版回退。SQLite 访问与加密打开 agent.db 前的决策树agent.db可能被 SQLCipher 加密也可能只是普通 SQLite。打开前必须按 sqlite-access.md 的决策树依次判断定位database-security.json。文件不存在或metadata.enabled ! true→ 按普通 SQLite 打开agent.db。metadata.enabled true→ 使用 DeepChat 的 SQLite 密码经 SQLCipher 打开。metadata.passwordStorage safeStorage且存在wrappedPassword→ 优先尝试 Electron safeStorage 辅助解包。safeStorage 不可用、解密失败、或导入运行时不是 Electron →询问用户 SQLite 密码并在读取前验证。旧版chat.db通常不加密若用户明确提供了加密数据库则走同一套 SQLCipher 流程。打开明文 SQLite尽量使用只读连接打开后用以下两条语句自检SELECT name FROM sqlite_master LIMIT 1; PRAGMA quick_check;如果导入器对agent.db报file is not a database、SQLITE_NOTADB或SQLITE_CORRUPT先检查database-security.json再下损坏的结论——这很可能是加密库被当明文打开的表现。打开加密 SQLiteSQLCipher 兼容参数DeepChat 使用better-sqlite3-multiple-ciphers在施加密钥前先配置 SQLCipher 兼容参数db.pragma(ciphersqlcipher) db.pragma(legacy4) db.key(Buffer.from(password, utf8))随后同样用SELECT name FROM sqlite_master LIMIT 1;与PRAGMA quick_check;验证。对其他 SQLCipher 绑定选择与该绑定legacy4等价的 SQLCipher 4 兼容设置库支持时优先使用参数化或原生的 key API。仓库中数据库打开与密钥处理逻辑集中在 connectionConfig.ts 与 baseTable.ts可作为理解 DeepChat 自身打开路径的参照。Electron 导入器利用 safeStorage 解包基于 Electron 的第三方导入器最有可能直接用上 DeepChat 的 wrapped password手动读取元数据 JSON再尝试safeStorage.decryptStringimport { app, safeStorage } from electron import fs from node:fs import path from node:path async function readDeepChatPassword(deepChatUserData: string): Promisestring | null { await app.whenReady() const metadataPath path.join(deepChatUserData, database-security.json) const raw JSON.parse(fs.readFileSync(metadataPath, utf8)) as { metadata?: { enabled?: boolean passwordStorage?: string wrappedPassword?: string } } const metadata raw.metadata if (!metadata?.enabled) return undefined if (metadata.passwordStorage ! safeStorage || !metadata.wrappedPassword) return null if (!safeStorage.isEncryptionAvailable()) return null try { return safeStorage.decryptString(Buffer.from(metadata.wrappedPassword, base64)) } catch { return null } }返回null时回退到密码询问。safeStorage 的 blob 与用户 OS 安全上下文及 Electron 底层实现绑定跨应用、跨机器解密不是稳定的公共契约。仓库侧databaseSecurity.ts 正是在safeStorage.isEncryptionAvailable()为真时写入passwordStorage: safeStorage与wrappedPassword否则降级为manual模式并写入safeStorageBackend——这正是决策树第 4/5 步的源码依据。Tauri 导入器与原生平台Tauri 无法直接调用 Electron safeStorage推荐流程定位agent.db与database-security.json。未加密 → 用普通 SQLite crate/插件打开。已加密 →询问用户 SQLite 密码。经支持 SQLCipher 的绑定打开标准 SQLite 驱动打不开加密的agent.db。可选仅为了 safeStorage 解包派生一个小的 Electron helper通过本地、用户同意的通道回传密码。Tauri/OS keyring API 只应用于保存导入器自己的记住的密码不要假设它们能解包 DeepChat 的 Electron safeStorage blob。原生macOS/Windows/Linux场景未加密库用平台标准 SQLite 只读打开加密库用支持 SQLCipher 的库并询问密码除非特意内置 Electron helper。平台差异说明macOSElectron safeStorage 依赖 Keychain 支撑的 OS 加密原生 Keychain 访问受应用权限约束不应视为稳定的 DeepChat 导入 API。WindowssafeStorage 通常依赖当前用户的 OS 保护原生 DPAPI 实验对部分 blob 可能有效但 blob 格式与 Electron 行为属实现细节优先手工密码回退。LinuxsafeStorage 可能走 libsecret、KWallet 或更弱的后端即safeStorageBackend字段桌面 secret service 不可用时DeepChat 会以 manual 模式存元数据导入器必须询问密码。验证错误速查密码错误通常表现为file is not a database、SQLITE_NOTADB或读取sqlite_master失败。WAL 文件缺失会让拷贝的在线数据库丢失近期行——重新拷贝侧车或请用户关闭 DeepChat。不要从导入器执行 rekey 或迁移操作。DeepChat 自身的迁移流程会通过附加临时数据库拷贝且只在验证通过后更新元数据。Schema 参考agent.db 表结构与字段契约读库前先理解 schema-reference.md 中的表关系。用户库可能由更新版本创建始终以sqlite_master的实际结果为准。版本表schema_versions已应用的迁移版本MAX(version)表示该库迁移到的版本。config_migrations配置存储迁移记录包含 SQLite 配置迁移标记。提供商与配置表providers提供商主行关键列列含义id提供商 idname显示名api_type提供商 API 适配器类型api_key敏感 API 密钥默认必须脱敏base_url配置的端点enabled1 表示启用custom1 表示自定义提供商capability_provider_id能力查询所用目录提供商可空sort_order/last_used_at/created_at/updated_at排序与时间戳provider_jsonLLM_PROVIDER其余字段的 JSON不含模型数组与启用/禁用模型列表重建提供商对象的方式是解析provider_json再覆盖标量列{ ...JSON.parse(row.provider_json || {}), id: row.id, name: row.name, apiType: row.api_type, apiKey: row.api_key, baseUrl: row.base_url, enable: row.enabled 1, custom: row.custom 1, capabilityProviderId: row.capability_provider_id }provider_models提供商/自定义模型目录行主键(provider_id, model_id, source)source取provider或custommodel_json是MODEL_META的 JSON需叠加model_id、provider_id、name、group_name、isCustom。model_status按模型的启用状态status_key为主键含provider_id、model_id、enabled、updated_at。model_configs按模型的生成配置cache_key为主键DeepChat 配置辅助函数使用provider_id、model_id、source为反规范化查找字段config_json保存 temperature、context length、reasoning、search、image/video generation、TTS 等配置。mcp_servers / mcp_settings / agent_settings / app_settingsmcp_servers按name的 MCP 服务器配置含config_json、sort_order与时间戳。mcp_settingsMCP 行为的 JSON 键值设置。agent_settingsAgent 行为的 JSON 键值设置。app_settings应用 JSON 键值设置带sensitive标记当前敏感配置提示词、知识配置、hooks、远程控制、类 API 设置等可能存放在这里。注意mcp_servers.config_json、MCP 环境变量值与app_settings.value_json都可能包含秘密。当前会话与消息表当前主线会话模型拆分为薄注册表 Agent 专属数据两层。new_sessions每个可见会话或子 Agent 会话一行。关键列id会话 id。agent_idAgent 实现 idDeepChat 聊天会话通常用 DeepChat agent idACP 会话用 ACP 导向的 id。title侧边栏标题。project_dir项目/工作区路径可空。is_pinned、is_draft整型布尔。active_skills、disabled_agent_tools兼容保留的 JSON 数组。subagent_enabled整型布尔。session_kindregular或subagent。parent_session_id、subagent_meta_json子 Agent 关系数据。created_at、updated_atepoch 毫秒。关联表new_projects项目路径、名称、可选图标、最后访问时间、new_session_active_skills结构化技能行、new_session_disabled_agent_tools结构化禁用工具行。deepchat_sessionsDeepChat 专属会话配置id与new_sessions.id对应。关键列provider_id、model_id选中模型permission_modedefault或full_accesssystem_prompt、temperature、context_length、max_tokens、timeout_msthinking_budget、reasoning_effort、reasoning_visibility、verbosityforce_interleaved_thinking_compat可空整型布尔image_generation_options_json、video_generation_options_json可空 JSONsummary_text、summary_cursor_order_seq、summary_updated_at压缩摘要状态。deepchat_messages会话消息时间线。关键列id消息 id。session_id会话 id。order_seq会话内单调排序升序排列即对话顺序。roleuser或assistant。contentJSON 字符串作为回退/物化内容。statuspending、sent或error。is_context_edge整型布尔。metadataJSON 字符串。created_at、updated_atepoch 毫秒。基础查询SELECT * FROM deepchat_messages WHERE session_id ? ORDER BY order_seq ASC;结构化用户消息表当前行优先缺失时回退deepchat_messages.contentdeepchat_user_messagesmessage_id、text、search_enabled、think_enabled。deepchat_user_message_filesmessage_id、ordinal、name、path、mime_type、size、metadata_json。deepchat_user_message_linksmessage_id、ordinal、url。物化的用户内容 JSON 形状{ text: user text, files: [], links: [], search: false, think: false }结构化助手块助手消息优先读deepchat_assistant_blocks对 pending 或最近流式输出的消息尤其重要。列message_id、block_index联合主键、block_type、status、text_content、tool_call_id、tool_name、tool_params、tool_response、action_type、image_mime_type、reasoning_start_at、reasoning_end_at、extra_json含 block id、时间戳、图片数据、工具调用附加信息与推理耗时、updated_at。按(message_id, block_index)排序无结构化块时解析deepchat_messages.content作为回退的助手块数组。事件、搜索、追踪与用量表适合更丰富的导入基础聊天历史可忽略deepchat_tape_entries每会话的追加式重建/事件事实。deepchat_pending_inputs排队或 steer 模式下的 pending 输入负载。deepchat_search_documents及 FTS 影子表派生的搜索索引。deepchat_message_search_results与消息关联的网页/搜索结果。deepchat_message_traces提供商请求追踪高度敏感。deepchat_usage_stats按消息、提供商、模型、日期的 token/成本用量。旧版兼容表当前版本保留旧版表用于兼容与导入。conversations旧版会话元数据。业务 id 是conv_idid是自增行 id。重要列含title、provider_id、model_id、生成设置、搜索设置、context_chain、active_skills、父级 fork 字段、created_at、updated_at。messages旧版消息时间线。msg_id为业务 idconversation_id引用conversations.conv_idparent_id为树/变体父级role取user、assistant、system或function还有content、order_seq、metadata、token_count、status、is_context_edge、is_variant。message_attachments按message_id、type与序列化content的旧版附件。当前导入优先new_sessions与deepchat_*表仅当agent.db缺失、导入旧备份或用户明确要旧版数据时才走旧版表或chat.db。导入配方从只读导出到写回与一致性校验import-recipes.md 给出了可直接照做的完整流程。最小只读导出定位并快照agent.db。按sqlite-access.md的流程打开。从providers、provider_models、model_status、model_configs读取提供商配置。读取会话SELECT ns.*, ds.* FROM new_sessions ns LEFT JOIN deepchat_sessions ds ON ds.id ns.id WHERE ns.session_kind regular ORDER BY ns.updated_at DESC, ns.id DESC;按会话读消息SELECT * FROM deepchat_messages WHERE session_id ? ORDER BY order_seq ASC, id ASC;用deepchat_user_messages、deepchat_user_message_files、deepchat_user_message_links水合用户消息。用deepchat_assistant_blocks水合助手消息缺失时回退解析deepchat_messages.content。导出为目标应用格式默认脱敏所有秘密除非用户明确选择包含。提供商配置导入向其他工具导入提供商时保留provider id、name、API 类型、base URL、enabled 与 custom 标记API 密钥与 OAuth token仅在用户明确同意时迁移用于模型能力查询的capability_provider_id来自provider_models且按source拆分的模型行来自model_status的启用/禁用状态来自model_configs.config_json的模型配置。不要只依赖provider_json——DeepChat 有意把常用标量字段放入独立列以支持查询与迁移。会话与消息导入的目标形状{ session: { id: session-id, title: Session title, agentId: deepchat, projectDir: /path/to/project, providerId: openai, modelId: gpt-4.1, createdAt: 1770000000000, updatedAt: 1770000000000 }, messages: [ { id: message-id, orderSeq: 1, role: user, status: sent, content: { text: hello, files: [], links: [], search: false, think: false }, metadata: {}, createdAt: 1770000000000, updatedAt: 1770000000000 } ] }助手消息尽量保留助手块数组而非拍平成文本——工具调用、工具响应、推理块、图片数据、动作提示与错误块都可能以助手块表示。处理部分或旧行结构化用户行缺失 → 解析deepchat_messages.content。结构化助手块缺失 → 解析deepchat_messages.content。new_sessions缺失但conversations存在 → 走旧版导入路径。agent.db缺失但chat.db存在 → 将chat.db作为旧版数据打开。列缺失 → 检查schema_versions使用最接近的回退而不是让整个导入失败。写回 DeepChat谨慎区避免第三方对用户在线 DeepChat 数据库直接写入。必须生成数据时优先产出 DeepChat 能通过自身代码导入的导出文件或备份包。若在 DeepChat 内部实现使用 Presenter/表辅助函数而非裸 SQL。若为受控迁移测试写拷贝库每个会话一个事务保持表组一致new_sessions、deepchat_sessions、deepchat_messages、结构化用户/助手表可选 search、trace、usage、pending input、tape 行。即使结构化表已填充也要保持deepchat_messages.content兼容因为它始终是回退路径。rekey 后不要手工更新database-security.json使用 DeepChat 的迁移流程。秘密处理清单默认脱敏或要求显式选择包含providers.api_keyproviders.provider_json中的 OAuth tokenMCP 服务器env与自定义 headersapp_settings中sensitive 1的行deepchat_message_traces.headers_json与body_json用户消息文件中的文件路径聊天内容、系统提示词、摘要与项目路径一致性校验从拷贝库导入后运行PRAGMA quick_check; SELECT COUNT(*) FROM new_sessions; SELECT COUNT(*) FROM deepchat_sessions; SELECT COUNT(*) FROM deepchat_messages; SELECT m.session_id FROM deepchat_messages m LEFT JOIN new_sessions s ON s.id m.session_id WHERE s.id IS NULL LIMIT 20;加密库在任何导入工作前先验证密码SELECT name FROM sqlite_master LIMIT 1;安全规则与源码路径索引技能包强调的硬性安全规则详见 SKILL.md读取本地数据前取得用户明确同意提供商密钥、OAuth token、MCP env 变量、提示词文本、消息追踪与聊天内容均可能敏感绝不以读写方式从第三方工具打开在用的agent.db应拷贝agent.db、agent.db-wal、agent.db-shm或经 DeepChat 自身使用 SQLite backup APIDeepChat 运行中要么请用户退出要么先做 WAL 感知快照SQLCipher 密码优先参数化 key API不把密码拼进 SQL日志、遥测、预览与生成的示例输出默认脱敏Schema 变化时先查schema_versions、sqlite_master与表类再假设列可用。以下仓库路径是回答版本敏感问题与维护该技能时的当前事实源数据库连接与密钥配置connectionConfig.ts、databaseConnection.ts数据库安全元数据enabled / passwordStorage / wrappedPassword / safeStorageBackenddatabaseSecurity.ts表基类与 Schema 目录baseTable.ts、schemaCatalog.ts旧版chat.db迁移服务legacyChatImportService.ts注意SKILL.md 中列出的src/main/presenter/...路径为技能编写时的命名当前仓库对应实现已组织在src/main/data/等目录下编写导入器时应以上述实际路径与运行时sqlite_master的真实结果为准。遵循先定位、再判定加密、后核对 Schema、最后按配方提取的完整流程即可构建出安全、准确、可维护的 DeepChat 数据导入与迁移工具。【免费下载链接】deepchatDeepChat - A smart assistant that connects powerful AI to your personal world项目地址: https://gitcode.com/GitHub_Trending/dee/deepchat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表