據(jù)遷移指南:從 OpenClaw 與 Hermes Agent 工作區(qū)導(dǎo)入記憶(migrate 命名空間))
OpenHuman 記憶數(shù)據(jù)遷移指南從 OpenClaw 與 Hermes Agent 工作區(qū)導(dǎo)入記憶migrate 命名空間【免費(fèi)下載鏈接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.項(xiàng)目地址: https://gitcode.com/GitHub_Trending/op/openhuman導(dǎo)讀本文講解 OpenHuman 內(nèi)置的記憶遷移助手src/openhuman/config/migration_helpers/如何把其他 AI 助手OpenClaw、Hermes Agent工作區(qū)中積累的長期記憶通過migrate.openclaw/migrate.hermes兩個 RPC 控制器導(dǎo)入當(dāng)前 OpenHuman 工作區(qū)的記憶后端。讀完本文你將掌握源工作區(qū)的路徑解析規(guī)則、OpenClaw SQLite 與 Markdown 記憶的讀取方式、Hermes 固定文件映射、dry-run 演練模式、冪等重跑與沖突重命名策略、遷移前的自動備份機(jī)制以及通過 CLI / JSON-RPC 安全執(zhí)行遷移的完整流程。模塊定位用戶記憶數(shù)據(jù)遷移而非配置 schema 升級在 OpenHuman 的代碼庫中存在兩個名字相近但職責(zé)完全不同的模塊理解二者的區(qū)別是使用本模塊的前提src/openhuman/config/migration_helpers/單數(shù) migration_helpers本文主角用戶主動觸發(fā)的 RPC 服務(wù)負(fù)責(zé)把其他廠商 AI 助手工作區(qū)里的用戶記憶數(shù)據(jù)brain.db、MEMORY.md等導(dǎo)入當(dāng)前工作區(qū)對應(yīng)migrate命名空間下的兩個控制器src/openhuman/config/migrations/復(fù)數(shù) migrations自動運(yùn)行的 schema 版本遷移器由Config::schema_version門控在Config::load_or_init時執(zhí)行負(fù)責(zé)持久化config.toml與會話轉(zhuǎn)錄數(shù)據(jù)的版本升級與用戶記憶無關(guān)。從 migrations/README.md 的模塊文檔可以看到同樣的對照說明migrations復(fù)數(shù)是每次工作區(qū)首次啟動新構(gòu)建時觸發(fā)一次的自動 schema-version runner而migration_helpers單數(shù)是用戶觸發(fā)的、從舊 OpenClaw 工作區(qū)導(dǎo)入記憶的 RPC。模塊結(jié)構(gòu)與公共 APImigration_helpers是一個典型的core 邏輯 ops 適配 schemas 注冊三層結(jié)構(gòu)目錄下共 8 個文件文件職責(zé)mod.rs僅做導(dǎo)出聲明core/ops/schemaspub use core::*與pub use ops::*將ops別名導(dǎo)出為rpc并對外暴露all_migration_controller_schemas/all_migration_registered_controllers這對注冊函數(shù)core.rs核心邏輯MigrationStats、MigrationReport、私有SourceEntry類型migrate_openclaw_memory/migrate_hermes_memory兩個核心函數(shù)SQLite Markdown 源讀取器、工作區(qū)路徑解析、key/分類歸一化、備份與沖突重命名輔助函數(shù)ops.rsJSON-RPC / CLI 適配層被mod.rs重新導(dǎo)出為rpc別名migrate_openclaw/migrate_hermes包裝核心函數(shù)將anyhow::Error映射為String返回RpcOutcomeMigrationReport并附帶migration completed日志schemas.rs控制器 schema 與處理器定義MigrateOpenClawParams/MigrateHermesParams參數(shù)結(jié)構(gòu)、all_controller_schemas、all_registered_controllers、schemas(function)以及兩個handle_migrate_*處理器core_tests.rs/ops_tests.rs/schemas_tests.rs三組單元測試覆蓋歸一化、路徑解析、dry-run、apply、缺失源、自遷移拒絕等場景公共導(dǎo)出面mod.rs 重新導(dǎo)出類型MigrationReport、MigrationStats核心函數(shù)migrate_openclaw_memory(config, source_workspace, dry_run) - ResultMigrationReport、migrate_hermes_memory(...)RPC 函數(shù)經(jīng)ops/ 別名rpcmigrate_openclaw(...) - ResultRpcOutcomeMigrationReport, String、migrate_hermes(...)控制器注冊導(dǎo)出all_migration_controller_schemas、all_migration_registered_controllers。其中SourceEntry與core.rs內(nèi)部輔助函數(shù)保持私有不構(gòu)成公共 API。RPC 控制器migrate 命名空間兩個控制器通過all_registered_controllers注冊位于migrate命名空間參見 schemas.rs方法描述輸入輸出migrate.openclaw將 OpenClaw 記憶遷移到當(dāng)前工作區(qū)source_workspace?: String、dry_run?: boolreport: MigrationReportmigrate.hermes將 Hermes Agent 記憶遷移到當(dāng)前工作區(qū)source_workspace?: String、dry_run?: boolreport: MigrationReport兩個輸入字段均可選schema 中required: false。dry_run省略時默認(rèn)值為true——handle_migrate_openclaw/handle_migrate_hermes使用payload.dry_run.unwrap_or(true)見 schemas.rs。這意味著在 RPC 邊界上不帶dry_run參數(shù)調(diào)用只會生成遷移計(jì)劃而不會真正寫入只有顯式傳dry_run: false才會實(shí)際執(zhí)行遷移。這是本模塊最重要的安全默認(rèn)值。處理器內(nèi)部通過config_rpc::load_config_with_timeout()加載配置再委托給migration_helpers::rpc::*執(zhí)行。若傳入未知函數(shù)名schemas()會返回一個namespace: migrate、function: unknown的占位 schema輸出為error字段。一個完整的 JSON-RPC 調(diào)用示例先演練、再實(shí)遷// 1. 演練模式只生成遷移計(jì)劃報(bào)告 {jsonrpc: 2.0, method: migrate.openclaw, params: {dry_run: true}, id: 1} // 2. 顯式指定源路徑并實(shí)際執(zhí)行 {jsonrpc: 2.0, method: migrate.openclaw, params: {source_workspace: /home/user/.openclaw/workspace, dry_run: false}, id: 2} // 3. 遷移 Hermes 記憶 {jsonrpc: 2.0, method: migrate.hermes, params: {dry_run: false}, id: 3}返回的RpcOutcomeMigrationReport經(jīng)into_cli_compatible_json()轉(zhuǎn)為 CLI 兼容 JSON包含migration completed日志與MigrationReport主體??刂破鞯娜肿詀ll_migration_registered_controllers()在 src/core/all.rs 中以DomainGroup::Config分組注冊進(jìn)全局控制器注冊表因此兩個方法同時通過 CLI 與 JSON-RPC 暴露schema 注冊由all_migration_controller_schemas()提供。源工作區(qū)路徑解析規(guī)則遷移的第一步是確定源工作區(qū)路徑。core.rs中resolve_openclaw_workspace與resolve_hermes_workspace的實(shí)現(xiàn)遵循顯式覆蓋優(yōu)先否則回退到廠商默認(rèn)的規(guī)則廠商顯式source_workspace默認(rèn)路徑未提供時OpenClaw原樣使用~/.openclaw/workspace經(jīng)directories::UserDirs獲取主目錄Hermes原樣使用Windows 下優(yōu)先%LOCALAPPDATA%\hermes否則~/.hermes路徑解析的源碼證據(jù)見 core.rs其中 Hermes 的 Windows 分支用#[cfg(windows)]std::env::var_os(LOCALAPPDATA)檢測環(huán)境變量對應(yīng)測試見 core_tests.rs。若解析出的源工作區(qū)不存在核心函數(shù)直接bail!返回錯誤如OpenClaw workspace not found at {}. Provide a valid source workspace.。ops.rs層測試migrate_openclaw_returns_error_for_missing_source_workspace驗(yàn)證了缺失源必須作為Err浮出水面確保 JSON-RPC 調(diào)用方能拿到失敗原因。自遷移防護(hù)無論哪個廠商的遷移函數(shù)在讀取任何數(shù)據(jù)之前都會先做自遷移檢查若解析出的源工作區(qū)與當(dāng)前 OpenHuman 工作區(qū)config.workspace_dir是同一路徑則直接拒絕執(zhí)行。paths_equal先嘗試canonicalize()規(guī)范化比較失敗時退回直接路徑比較見 core.rs。測試migrate_hermes_refuses_self_migration驗(yàn)證錯誤信息必須包含self-migration字樣。這一防護(hù)的意義在于把當(dāng)前工作區(qū)當(dāng)作源遷移到自己身上毫無意義反而可能觸發(fā)備份覆蓋或沖突重命名因此模塊選擇在最前面攔截。數(shù)據(jù)源讀取OpenClawOpenClaw 的記憶數(shù)據(jù)來自兩類文件collect_source_entries會把二者合并后統(tǒng)一去重1. SQLitememory/brain.db讀取邏輯位于read_openclaw_sqlite_entriescore.rs具有顯著的schema 容錯設(shè)計(jì)數(shù)據(jù)庫以只讀方式打開OpenFlags::SQLITE_OPEN_READ_ONLY絕不修改源數(shù)據(jù)先查sqlite_master確認(rèn)存在名為memories的表不存在則靜默返回空列表通過PRAGMA table_info(memories)讀取真實(shí)列名再從候選名列表中按大小寫不敏感匹配挑選列key 列候選key/id/name缺失時回退為CAST(rowid AS TEXT)content 列候選content/value/text/memory若連一個 content 類列都找不到直接報(bào)錯no content-like column was detected因?yàn)闊o法判斷內(nèi)容就沒有導(dǎo)入價(jià)值category 列候選category/kind/type缺失時回退為常量core逐行讀取時key 讀取失敗回退為openclaw_sqlite_{idx}content 為空的記錄被跳過category 經(jīng)parse_category歸一化。由于采用動態(tài)列檢測而非硬編碼 schemaOpenClaw 不同版本的memories表結(jié)構(gòu)變化不會導(dǎo)致遷移中斷——這是模塊對第三方數(shù)據(jù)格式兼容性的核心設(shè)計(jì)。2. MarkdownMEMORY.md與memory/*.mdread_openclaw_markdown_entriescore.rs處理 Markdown 記憶工作區(qū)根目錄的MEMORY.md若存在且非空導(dǎo)入為 keyopenclaw_memory_md、分類Corememory/目錄下所有*.md文件以文件名去掉擴(kuò)展名作為 key經(jīng)normalize_key歸一化分類統(tǒng)一為Core空文件跳過??諆?nèi)容檢查貫穿所有讀取路徑確保不會把空白文件當(dāng)作有效記憶導(dǎo)入。數(shù)據(jù)源讀取HermesHermes Agent 的遷移采用固定文件映射見hermes_file_mappingscore.rs源文件導(dǎo)入 key目標(biāo)分類MEMORY.mdhermes_memoryMemoryCategory::CoreUSER.mdhermes_user_profileMemoryCategory::Custom(user_profile)SOUL.mdhermes_personaMemoryCategory::Custom(persona)三個文件各自獨(dú)立可選缺失的文件會以 warning 形式記錄如USER.md not found in ...空文件同樣被跳過并告警但不會中斷其他文件的導(dǎo)入。測試migrate_hermes_skips_missing_optional_files驗(yàn)證了部分文件存在時的行為migrate_hermes_apply_imports_markdown_entries則覆蓋了完整三文件映射——包括SOUL.md→Custom(persona)這條曾被評審點(diǎn)名的分支。歸一化、分類映射與去重key 歸一化normalize_key從源讀取的 key 會經(jīng)過normalize_key處理core.rs非字母數(shù)字字符除-與_一律替換為_再修剪首尾的_若結(jié)果為空白回退為openclaw_{idx}。例如測試用例中的hello/world會變?yōu)閔ello_world。對于 SQLite 讀取時 key 缺失的行同樣在行號索引基礎(chǔ)上回退生成openclaw_sqlite_{idx}。分類映射parse_categorySQLite 中的 category 字符串按小寫匹配映射到MemoryCategory枚舉源分類字符串目標(biāo)MemoryCategorycoreCoredailyDailyconversationConversationpersonalCustom(personal)projectCustom(project)episodeCustom(episode)其他Custom(原字符串)即已知枚舉走標(biāo)準(zhǔn)分類未知字符串兜底為自定義分類不會因?yàn)樵磾?shù)據(jù)出現(xiàn)新分類而失敗。精確去重collect_source_entries在合并 SQLite 與 Markdown 來源后用key content category三元組簽名做HashSet去重core.rs保證重復(fù)運(yùn)行遷移時結(jié)果確定這是冪等性的第一層保障。目標(biāo)端寫入策略備份、跳過與沖突重命名1. 遷移前自動備份非 dry-run 模式下backup_target_memorycore.rs會把目標(biāo)工作區(qū)現(xiàn)有的記憶產(chǎn)物復(fù)制到workspace_dir/memory_backup/MEMORY.md→memory_backup/MEMORY.mdmemory/brain.db→memory_backup/brain.dbmemory/目錄下所有*.md→memory_backup/memory/*.md。若目標(biāo)工作區(qū)本來就沒有任何記憶文件則不創(chuàng)建備份目錄并返回None成功創(chuàng)建備份后報(bào)告會追加一條Backup created: pathwarning。fs::copy的失敗以.ok()寬容處理不阻斷遷移主流程。2. 寫入與沖突處理寫入通過target_memory_backend獲取目標(biāo)記憶后端后對每個條目執(zhí)行如下邏輯見migrate_openclaw_memory與migrate_hermes_memory的寫入循環(huán)memory.get(, key) 查詢已有條目 ├─ 不存在 → 直接 storeimported 1 ├─ 存在且內(nèi)容相同 → skipped_unchanged 1跳過 └─ 存在但內(nèi)容不同 → next_available_key 生成 key_1、key_2…… renamed_conflicts 1以新 key storenext_available_keycore.rs從key_1開始遞增探測空閑 key確保沖突條目不覆蓋已有記憶、也不相互覆蓋。所有條目寫入時使用空命名空間memory.store(, key, ...)與目標(biāo)記憶后端的默認(rèn)命名空間一致。3. 冪等性總結(jié)源端精確重復(fù)條目去重HashSet簽名目標(biāo)端內(nèi)容未變的條目跳過skipped_unchanged沖突端內(nèi)容沖突條目重命名renamed_conflicts。三者疊加使得重復(fù)執(zhí)行同一遷移是安全且確定性的第二次運(yùn)行時大部分條目落入skipped_unchanged。報(bào)告結(jié)構(gòu)MigrationReport 與 MigrationStats無論 dry-run 還是 apply遷移都會返回MigrationReportcore.rspub struct MigrationReport { pub source_workspace: PathBuf, // 源工作區(qū) pub target_workspace: PathBuf, // 目標(biāo)工作區(qū)config.workspace_dir pub dry_run: bool, // 是否為演練模式 pub stats: MigrationStats, // 遷移統(tǒng)計(jì) pub warnings: VecString, // 警告列表 }MigrationStats六個計(jì)數(shù)core.rs字段含義from_sqlite從 SQLite 讀取的條目數(shù)from_markdown從 Markdown 讀取的條目數(shù)imported實(shí)際寫入目標(biāo)后端的條目數(shù)skipped_unchanged因內(nèi)容未變而跳過的條目數(shù)renamed_conflicts因內(nèi)容沖突而重命名的條目數(shù)當(dāng)源工作區(qū)沒有任何可導(dǎo)入記憶時entries.is_empty()函數(shù)不會報(bào)錯而是返回一份空統(tǒng)計(jì)報(bào)告并附上提示性 warnings如No importable memory found in ...與Checked for: memory/brain.db, MEMORY.md, memory/*.md。ops_tests.rs中migrate_openclaw_dry_run_on_empty_source_returns_report明確驗(yàn)證了這一空源返回報(bào)告而非報(bào)錯的行為。目標(biāo)記憶后端綁定與空驅(qū)動拒絕target_memory_backendcore.rs是 apply 路徑的關(guān)鍵防護(hù)點(diǎn)。它通過memory::binding::for_config解析當(dāng)前配置綁定的記憶驅(qū)動再經(jīng)由agent::experience::ops::DriverMemory::for_config構(gòu)造寫入后端DriverMemory包裝的是未加守衛(wèi)的驅(qū)動不會受capture_max_chars截?cái)嘤绊懸虼碎L記憶正文可完整導(dǎo)入。若綁定的驅(qū)動是null driverDriverClass::Null模塊會拒絕導(dǎo)入并精確說明原因而不是靜默丟棄寫入配置了[subsystems.memory] driver null——memory is disabled by configuration配置的驅(qū)動綁定失敗并回退到 null——報(bào)告被拒的驅(qū)動與其原因配置了可持有數(shù)據(jù)的驅(qū)動但當(dāng)前構(gòu)建未編譯入對應(yīng) memory 模塊modulesfeature 關(guān)閉module_provider代之以 null provider——報(bào)告this build has no memory module compiled in。錯誤信息統(tǒng)一以refusing to import memory into the null driver — ... Nothing was imported; the source workspace is untouched.收尾明確承諾源工作區(qū)未被觸碰。這一防護(hù)的理由在源碼注釋中闡述得很清楚如果遷移報(bào)告顯示已導(dǎo)入 N 條而實(shí)際一條都沒寫入用戶可能據(jù)此刪除源工作區(qū)造成無法挽回的數(shù)據(jù)丟失。對應(yīng)測試apply_refuses_and_names_the_build_when_no_memory_module_is_compiled_in#[cfg(not(feature modules))]還斷言了源文件在拒絕后保持字節(jié)級一致。關(guān)鍵回歸記錄#1440ops_tests.rs中的migrate_openclaw_apply_imports_markdown_entries_into_target_workspace#[cfg(feature modules)]記錄了一次重要回歸此前 apply 路徑dry_run false在統(tǒng)一命名空間記憶核心下會于create_memory_for_migration處直接中斷hard-disable導(dǎo)致導(dǎo)入無法真正執(zhí)行該禁用被移除后apply 路徑必須能實(shí)際把 OpenClaw 源工作區(qū)的 Markdown 條目寫入目標(biāo)。測試用偽造的 OpenClaw 工作區(qū)僅含MEMORY.md與memory/sprint.md無需brain.db驗(yàn)證imported 1。Hermes 側(cè)同樣有對應(yīng)的 apply 測試覆蓋三個文件的完整導(dǎo)入imported 3、from_markdown 3。使用建議與注意事項(xiàng)始終先 dry-run 再 apply由于 RPC 邊界上dry_run默認(rèn)true未顯式傳參的調(diào)用只生成計(jì)劃。建議先運(yùn)行一次不帶dry_run: false的調(diào)用查看MigrationStats確認(rèn)來源與數(shù)量無誤后再顯式傳入dry_run: false執(zhí)行。遷移前確認(rèn)目標(biāo)記憶后端可用若配置為 null 驅(qū)動或構(gòu)建未啟用modulesfeatureapply 會被拒絕且源不受影響——這是保護(hù)而非故障請按錯誤信息給出的原因調(diào)整配置或重新構(gòu)建。遷移后核對memory_backup/apply 模式會自動在workspace_dir/memory_backup/生成目標(biāo)記憶的備份核對無誤前不建議刪除源工作區(qū)。冪等可重跑重復(fù)執(zhí)行遷移會跳過未變條目、重命名沖突條目報(bào)告中的skipped_unchanged/renamed_conflicts計(jì)數(shù)可用于確認(rèn)收斂。Windows 路徑注意Hermes 默認(rèn)源路徑在 Windows 上是%LOCALAPPDATA%\hermes與其他平臺的~/.hermes不同顯式傳source_workspace可覆蓋一切默認(rèn)值??偨Y(jié)OpenHuman 的migration_helpers模塊為從其他 AI 助手切換到 OpenHuman提供了完整、安全的記憶遷移通道schema 容錯的 SQLite 讀取兼容 OpenClaw 不同版本固定文件映射覆蓋 Hermes 的MEMORY.md/USER.md/SOUL.mddry-run 默認(rèn)值 自遷移拒絕 null 驅(qū)動拒絕 自動備份 冪等寫入五重保障確保任何一步都不會造成數(shù)據(jù)丟失。通過migrate.openclaw與migrate.hermes兩個 RPC 控制器CLI 與 JSON-RPC 調(diào)用方都能以統(tǒng)一方式完成演練 → 備份 → 導(dǎo)入 → 報(bào)告的完整遷移閉環(huán)?!久赓M(fèi)下載鏈接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.項(xiàng)目地址: https://gitcode.com/GitHub_Trending/op/openhuman創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考