feat: Import OpenClaw memory, history and settings#903
feat: Import OpenClaw memory, history and settings#903nickpismenkov merged 4 commits intostagingfrom
Conversation
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
zmanian
left a comment
There was a problem hiding this comment.
Review: Import OpenClaw memory, history, and settings
Good feature -- clean reader design, solid test coverage (6 test files with real SQLite fixtures), proper feature gating. Two blocking issues:
Blocking
1. [Security] API keys stored as plain String with Debug derive
src/import/openclaw/reader.rs -- OpenClawLlmConfig and OpenClawEmbeddingsConfig store api_key: Option<String> and derive Debug. Any debug log or panic backtrace leaks keys in cleartext. The keys are wrapped in SecretString later in extract_credentials, but the intermediate structs are exposed.
Fix: Use SecretString for the api_key fields and implement Debug manually with redaction, or at minimum remove the Debug derive and add a manual impl.
2. [Database Safety] No transaction wrapping for multi-step import
src/import/openclaw/mod.rs -- import() performs settings, credentials, workspace, chunk, and conversation writes as individual calls. Per CLAUDE.md: "Multi-step database operations MUST be wrapped in a transaction." A crash mid-import leaves partial state with no way to detect or recover. Especially problematic for conversations where the conversation is created, then messages are added one by one.
Fix: Wrap each conversation + its messages in a transaction at minimum. Ideally wrap the entire import.
Non-blocking
super::imports insettings.rstests -- usecrate::import::openclaw::reader::per project style- Dead code:
credentials.rs::import_credentials()is defined but never called (logic inlined in mod.rs) - No idempotency: Re-running import creates duplicate conversations (no check for
openclaw_conversation_idalready imported) - Dead
#[cfg(not(feature = "import"))]fallbacks: The entire module is feature-gated, so the not-feature stubs are unreachable - Dry-run undercounts: Messages within conversations are not counted in dry-run mode
- Dependencies:
json5brings pest (4 transitive crates),rusqlite bundledcompiles SQLite from source. Both behind feature gate so normal builds unaffected. Acceptable. list_agent_dbsnondeterministic order: Filesystem iteration order makes test assertions fragile. Sort by name.
Looks good
- Feature gating keeps deps out of default builds
- No
.unwrap()/.expect()in production code - Credentials wrapped in SecretString before reaching SecretsStore
- Reader is read-only (never modifies source data)
- Tests are substantive -- real SQLite fixtures, error paths, edge cases, UTF-8, idempotency
tempfileused correctly in all tests- Dry-run separation is clean
zmanian
left a comment
There was a problem hiding this comment.
Follow-up Review (post review-fixes commits)
The two blocking issues from my previous review have been addressed:
-
API keys as SecretString -- Fixed.
OpenClawLlmConfigandOpenClawEmbeddingsConfignow useSecretStringforapi_keyfields with manualDebugimpls that redact values. Tests verify redaction. Good. -
Transaction safety -- Partially addressed. The Database trait doesn't expose transaction control, so full wrapping isn't possible without trait changes. The current approach (read-all-first, then write in grouped phases) is a reasonable mitigation. The
import_conversation_atomicfunction validates messages before creating the conversation, which helps. The code comments honestly document the limitation. Acceptable for now.
Remaining issues (non-blocking, should be tracked)
3. Dead import_conversation function -- The old non-atomic import_conversation in history.rs is marked #[allow(dead_code)] and deprecated. It should just be deleted rather than kept around. No callers remain.
4. unwrap_or("unknown") in list_agent_dbs (reader.rs:212) -- This is on file_stem().and_then(|s| s.to_str()).unwrap_or("unknown"). While unlikely to cause issues in practice, this silently processes a file whose name couldn't be decoded as UTF-8. Consider logging a warning or skipping the file instead of silently renaming it to "unknown".
5. #[allow(dead_code)] on LLM code -- The merge commit adds #[allow(dead_code)] to UnsupportedParam, strip_unsupported_completion_params, and strip_unsupported_tool_params in src/llm/provider.rs. These were added in a separate PR (#809) and should already be wired up. The allow(dead_code) annotations suggest a merge conflict resolution that lost the integration wiring. This needs investigation -- if the code from #809 that actually calls these functions was dropped during the merge into this branch, those providers will silently send unsupported parameters again.
6. No idempotency for conversations -- Re-importing creates duplicate conversations. The openclaw_conversation_id is stored in metadata but never checked before creating. The import_conversation_atomic doc comments acknowledge this as a known limitation. Fine for v1 but should be tracked.
7. Emojis in CLI output -- cli/import.rs uses emoji in println! output. Per project convention (CLAUDE.md emoji policy), these should be removed or replaced with plain text markers.
8. unwrap_or_else in cli/import.rs -- Lines 70 and 74 use unwrap_or_else for HOME and user_id respectively. The HOME one is fine (fallback to "."). The user_id one is fine (defaulting to "default"). These are acceptable CLI-level defaults.
Verdict
The review fixes are solid. The security issue is properly resolved, the transaction safety has a documented pragmatic mitigation, dead code was cleaned up (except the old import_conversation), and super::super:: was fixed. The #[allow(dead_code)] on the LLM provider code from the merge is the most concerning item -- please verify the unsupported-param filtering from #809 is still wired up in the providers after the merge.
No blocking issues remain. The items above can be addressed in follow-up work.
1. Remove dead import_conversation() function - replaced by import_conversation_atomic() 2. Improve non-UTF-8 filename handling in list_agent_dbs() - log warning instead of silent 'unknown' 3. Remove emojis from CLI output per project style guide Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
c0f5da5 to
4d6fbba
Compare
|
@zmanian sorry, I accidentally merged main into the branch, now it should be fixed, please check again. thanks! |
zmanian
left a comment
There was a problem hiding this comment.
Re-review after fix commits (6739426, c3646db, 4d6fbba)
The new commits address the issues flagged in my previous two reviews. Here is the status of each:
Previously flagged items -- now resolved
-
Dead
import_conversationfunction -- Deleted in 4d6fbba. Onlyimport_conversation_atomicremains. Good. -
unwrap_or("unknown")inlist_agent_dbs-- Replaced withmatchthat logs atracing::warn!and skips the file. Correct behavior. -
Emojis in CLI output -- The two main ones were fixed:
"Import Complete"(was checkmark emoji) and"[DRY RUN] No data was written."(was warning emoji). Good. -
#[allow(dead_code)]on LLM provider code -- Resolved by the merge from staging (c3646db), which brought in the wiring from PR #809. Thestrip_unsupported_completion_paramsandstrip_unsupported_tool_paramsfunctions are now properly called fromrig_adapter.rs. No dead code annotations remain. -
Dry-run message counting -- Fixed in 6739426. The dry-run path now iterates conversations and sums
conv.messages.len(). -
super::super::imports -- No longer present. Remainingsuper::usage is single-level within the same package (sibling module refs likeuse super::reader::OpenClawConfig), which is acceptable.
Minor remaining items (non-blocking, can be follow-up)
-
Remaining emoji on line 76 of
cli/import.rs:println!("magnifying glass OpenClaw Import")still has a magnifying glass emoji. The other two were fixed but this one was missed. -
Unreachable
#[cfg(not(feature = "import"))]inreader.rs:187: The entireopenclawmodule is gated behind#[cfg(feature = "import")]insrc/import/mod.rs, so the#[cfg(not(feature = "import"))]block insidereader.rs::read_config()is dead code -- it can never compile. Harmless but should be cleaned up. -
No conversation import idempotency: Re-importing still creates duplicate conversations. The code documents this limitation clearly with a TODO in
import_conversation_atomic. Fine for v1. -
credentials.rsis test-only: The module contains only tests (the production logic is inlined inmod.rs). Consider renaming or documenting this to avoid confusion, or moving the tests elsewhere.
Verdict
All blocking and significant non-blocking issues from the previous reviews have been addressed. The remaining items are cosmetic. Approving.
zmanian
left a comment
There was a problem hiding this comment.
Re-review after fix commits (6739426, c3646db, 4d6fbba)
The new commits address the issues flagged in my previous two reviews. Here is the status of each:
Previously flagged items -- now resolved
-
Dead import_conversation function -- Deleted in 4d6fbba. Only import_conversation_atomic remains. Good.
-
unwrap_or(unknown) in list_agent_dbs -- Replaced with match that logs a tracing::warn! and skips the file. Correct behavior.
-
Emojis in CLI output -- The two main ones were fixed: Import Complete (was checkmark emoji) and [DRY RUN] No data was written (was warning emoji). Good.
-
allow(dead_code) on LLM provider code -- Resolved by the merge from staging (c3646db), which brought in the wiring from PR #809. The strip_unsupported_completion_params and strip_unsupported_tool_params functions are now properly called from rig_adapter.rs. No dead code annotations remain.
-
Dry-run message counting -- Fixed in 6739426. The dry-run path now iterates conversations and sums conv.messages.len().
-
super::super:: imports -- No longer present. Remaining super:: usage is single-level within the same package (sibling module refs like use super::reader::OpenClawConfig), which is acceptable.
Minor remaining items (non-blocking, can be follow-up)
-
Remaining emoji on line 76 of cli/import.rs: The magnifying glass emoji in the OpenClaw Import header was not removed along with the other two.
-
Unreachable cfg(not(feature = import)) in reader.rs:187: The entire openclaw module is gated behind cfg(feature = import) in src/import/mod.rs, so the cfg(not(feature = import)) block inside reader.rs::read_config() is dead code -- it can never compile. Harmless but should be cleaned up.
-
No conversation import idempotency: Re-importing still creates duplicate conversations. The code documents this limitation clearly with a TODO in import_conversation_atomic. Fine for v1.
-
credentials.rs is test-only: The module contains only tests (the production logic is inlined in mod.rs). Consider renaming or documenting this to avoid confusion, or moving the tests elsewhere.
Verdict
All blocking and significant non-blocking issues from the previous reviews have been addressed. The remaining items are cosmetic. Approving.
…e3 symbol conflicts The `import` feature (added in #903) brings in `rusqlite[bundled]` which conflicts with `libsql-ffi` — both bundle SQLite C code, causing duplicate symbol linker errors. Use explicit features matching the test matrix instead of `--all-features`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(ci): use explicit features in WASM WIT compat test to avoid sqlite3 symbol conflicts The `import` feature (added in #903) brings in `rusqlite[bundled]` which conflicts with `libsql-ffi` — both bundle SQLite C code, causing duplicate symbol linker errors. Use explicit features matching the test matrix instead of `--all-features`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: replace rusqlite with libsql in import module to fix sqlite3 symbol conflict The `import` feature used `rusqlite[bundled]` which bundled its own SQLite C code, conflicting with `libsql-ffi` (also bundles SQLite). This caused duplicate `sqlite3_*` symbol linker errors when both features were enabled via `--all-features`. Replace `rusqlite` with `libsql` (already a dependency) in the import reader. The `import` feature now implies `libsql`. This eliminates the duplicate symbol conflict and allows `--all-features` to compile cleanly. Also restores `--all-features` in the WASM WIT compat CI test (now safe) and converts all import test helpers from rusqlite to libsql. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style: apply cargo fmt formatting fixes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: Import OpenClaw memory, history and settings * review fixes * fix: address remaining code quality issues 1. Remove dead import_conversation() function - replaced by import_conversation_atomic() 2. Improve non-UTF-8 filename handling in list_agent_dbs() - log warning instead of silent 'unknown' 3. Remove emojis from CLI output per project style guide Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
* fix(ci): use explicit features in WASM WIT compat test to avoid sqlite3 symbol conflicts The `import` feature (added in nearai#903) brings in `rusqlite[bundled]` which conflicts with `libsql-ffi` — both bundle SQLite C code, causing duplicate symbol linker errors. Use explicit features matching the test matrix instead of `--all-features`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: replace rusqlite with libsql in import module to fix sqlite3 symbol conflict The `import` feature used `rusqlite[bundled]` which bundled its own SQLite C code, conflicting with `libsql-ffi` (also bundles SQLite). This caused duplicate `sqlite3_*` symbol linker errors when both features were enabled via `--all-features`. Replace `rusqlite` with `libsql` (already a dependency) in the import reader. The `import` feature now implies `libsql`. This eliminates the duplicate symbol conflict and allows `--all-features` to compile cleanly. Also restores `--all-features` in the WASM WIT compat CI test (now safe) and converts all import test helpers from rusqlite to libsql. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style: apply cargo fmt formatting fixes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: Import OpenClaw memory, history and settings * review fixes * fix: address remaining code quality issues 1. Remove dead import_conversation() function - replaced by import_conversation_atomic() 2. Improve non-UTF-8 filename handling in list_agent_dbs() - log warning instead of silent 'unknown' 3. Remove emojis from CLI output per project style guide Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
* fix(ci): use explicit features in WASM WIT compat test to avoid sqlite3 symbol conflicts The `import` feature (added in nearai#903) brings in `rusqlite[bundled]` which conflicts with `libsql-ffi` — both bundle SQLite C code, causing duplicate symbol linker errors. Use explicit features matching the test matrix instead of `--all-features`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: replace rusqlite with libsql in import module to fix sqlite3 symbol conflict The `import` feature used `rusqlite[bundled]` which bundled its own SQLite C code, conflicting with `libsql-ffi` (also bundles SQLite). This caused duplicate `sqlite3_*` symbol linker errors when both features were enabled via `--all-features`. Replace `rusqlite` with `libsql` (already a dependency) in the import reader. The `import` feature now implies `libsql`. This eliminates the duplicate symbol conflict and allows `--all-features` to compile cleanly. Also restores `--all-features` in the WASM WIT compat CI test (now safe) and converts all import test helpers from rusqlite to libsql. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style: apply cargo fmt formatting fixes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Change Type
Linked Issue
Validation
cargo fmtcargo clippy --all --benches --tests --examples --all-featuresSecurity Impact
Database Impact
Blast Radius
Rollback Plan
Review track: