Skip to content

feat(memory): clear source memory on disconnect#2528

Open
YOMXXX wants to merge 5 commits into
tinyhumansai:mainfrom
YOMXXX:feat/2515-disconnect-memory-cleanup
Open

feat(memory): clear source memory on disconnect#2528
YOMXXX wants to merge 5 commits into
tinyhumansai:mainfrom
YOMXXX:feat/2515-disconnect-memory-cleanup

Conversation

@YOMXXX
Copy link
Copy Markdown
Contributor

@YOMXXX YOMXXX commented May 23, 2026

Summary

  • Add source-scoped memory cleanup helpers that delete matching memory-tree chunks plus dependent score/entity/embedding/reembed rows and best-effort content files.
  • Thread opt-in clearMemory / clear_memory through channel and Composio disconnect flows, returning memory_chunks_deleted counts.
  • Add disconnect UI checkboxes for channel and Composio flows with irreversible-action copy and focused tests.
  • Address review feedback: safe content-file cleanup, local cleanup/event/cache completion even if memory deletion errors, Composio Notion/Drive cleanup targets, Korean translations, and checkbox reset on failed disconnect retry.

Related Issue

Closes #2515

Type of Change

  • Feature
  • Bug fix
  • N/A: Refactor
  • N/A: Documentation
  • Tests
  • N/A: Chore

How Tested

  • pnpm --filter openhuman-app test:unit src/services/api/__tests__/channelConnectionsApi.test.ts src/lib/composio/composioApi.test.ts src/components/composio/ComposioConnectModal.test.tsx src/components/channels/__tests__/TelegramConfig.test.tsx
  • pnpm --filter openhuman-app test:unit src/components/channels/__tests__/DiscordConfig.test.tsx
  • pnpm --filter openhuman-app exec vitest run --coverage --config test/vitest.config.ts src/components/channels/__tests__/DiscordConfig.test.tsx src/components/channels/__tests__/TelegramConfig.test.tsx src/components/composio/ComposioConnectModal.test.tsx src/services/api/__tests__/channelConnectionsApi.test.ts src/lib/composio/composioApi.test.ts
  • GGML_NATIVE=OFF cargo test --manifest-path Cargo.toml clear_memory --lib
  • GGML_NATIVE=OFF cargo test --manifest-path Cargo.toml cleanup_targets --lib
  • GGML_NATIVE=OFF cargo test --manifest-path Cargo.toml composio::ops --lib
  • GGML_NATIVE=OFF cargo test --manifest-path Cargo.toml delete_chunks_by_source --lib
  • GGML_NATIVE=OFF cargo test --manifest-path Cargo.toml memory::tree::store --lib
  • pnpm i18n:check
  • pnpm typecheck
  • GGML_NATIVE=OFF cargo check --manifest-path Cargo.toml
  • pnpm lint (passes with existing warnings)
  • pnpm format:check
  • git diff --check
  • GGML_NATIVE=OFF pnpm rust:check
  • GGML_NATIVE=OFF git push (pre-push hook passed)

Screenshots / Recordings

Not applicable.

Checklist

  • I have linked the relevant issue.
  • I have added or updated tests for the change.
  • I have updated documentation where needed, or this change does not need docs.
  • I have run the commands listed above and reported any blockers.
  • Diff coverage for changed lines is expected to meet the 80% gate; CI remains authoritative.

AI Authorship Checklist

Summary by CodeRabbit

  • New Features

    • Add an "also delete memory" checkbox when disconnecting Discord, Telegram, and Composio accounts so users can optionally remove locally stored memory chunks.
    • Checkbox state resets after disconnect or when dismissing disconnect errors.
  • Localization

    • Added translations for the new disconnect/clear-memory label and hint in English, Spanish, French, German, Korean, Portuguese, Russian, Arabic, Bengali, Hindi, Indonesian, Italian, and Simplified Chinese.

Review Change Stack

@YOMXXX YOMXXX requested a review from a team May 23, 2026 10:33
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 23, 2026

📝 Walkthrough

Walkthrough

Adds an opt-in "also delete memory" checkbox in disconnect UIs (Discord, Telegram, Composio), wires the flag through frontend APIs to new RPC parameters, and removes matching memory-tree chunks via new store deletion APIs; responses surface deleted-chunk counts and tests cover success/error flows.

Changes

Memory deletion on channel/Composio disconnect

Layer / File(s) Summary
Memory store deletion foundation
src/openhuman/memory/tree/store.rs, src/openhuman/memory/tree/store_tests.rs
delete_chunks_by_source and delete_chunks_by_source_prefix remove chunk rows (and related side tables) in a transaction, return deleted counts, and perform safe filesystem cleanup; tests validate DB and file behavior.
Channels RPC: disconnect with memory clearing
src/openhuman/channels/controllers/ops.rs, src/openhuman/channels/controllers/ops_tests.rs, src/openhuman/channels/controllers/schemas.rs, src/openhuman/channels/controllers/schemas_tests.rs
disconnect_channel accepts a clear_memory flag, deletes chat-source chunks when enabled, includes memory_chunks_deleted in responses, and schema/tests updated.
Frontend API: channel disconnect
app/src/services/api/channelConnectionsApi.ts, app/src/services/api/__tests__/channelConnectionsApi.test.ts
disconnectChannel gains optional options.{clearMemory} and forwards clearMemory to the openhuman.channels_disconnect RPC; unit test asserts RPC params.
Frontend UI: Discord and Telegram disconnect
app/src/components/channels/DiscordConfig.tsx, app/src/components/channels/TelegramConfig.tsx, app/src/components/channels/__tests__/TelegramConfig.test.tsx, app/src/components/channels/__tests__/DiscordConfig.test.tsx
Components add per-auth-mode clearMemoryOnDisconnect state, render a checkbox when connected, pass flag to API on disconnect, and reset checkbox after attempt; tests verify the flag is sent.
Composio RPC: delete with memory clearing
src/openhuman/composio/ops.rs, src/openhuman/composio/ops_test.rs
composio_delete_connection adds clear_memory param, resolves toolkit, derives toolkit-specific memory targets (Gmail/Notion/Drive/Slack), deletes matching chunks (exact + prefix), accumulates memory_chunks_deleted, and reports per-target failures.
Composio support: schema & types
src/openhuman/composio/schemas.rs, src/openhuman/composio/types.rs, src/openhuman/composio/providers/profile.rs
Controller schema and types accept clear_memory and expose memory_chunks_deleted; adds normalize_connection_identifier helper used in target derivation.
Frontend API: composio deleteConnection
app/src/lib/composio/composioApi.ts, app/src/lib/composio/composioApi.test.ts, app/src/lib/composio/types.ts
deleteConnection accepts options.{clearMemory}, forwards clear_memory when present, and unpacks memory_chunks_deleted from RPC response; tests added.
Frontend UI: Composio disconnect
app/src/components/composio/ComposioConnectModal.tsx, app/src/components/composio/ComposioConnectModal.test.tsx
Modal tracks clearMemoryOnDisconnect, renders checkbox in connected phase, forwards option to deleteConnection, resets on success/error; tests verify both success call and error-dismiss reset.
Internationalization
app/src/lib/i18n/chunks/*, app/src/lib/i18n/{en,ko}.ts
Adds accounts.disconnectClearMemory and accounts.disconnectClearMemoryHint keys across language chunks and consolidated maps for UI label and permanence hint.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • graycyrus

"🐰 With whiskers twitching, memory is freed
When sources disconnect, no chunk repeats its creed
A checkbox offers choice, checked with care
Delete the traces, or let the learning stay there ✨"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 69.81% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat(memory): clear source memory on disconnect' accurately summarizes the main feature: adding opt-in memory cleanup when disconnecting channels or Composio integrations.
Linked Issues check ✅ Passed The PR fully implements all coding requirements from issue #2515: delete_chunks_by_source() helper, clear_memory parameters in disconnect_channel and composio_delete_connection RPCs, UI checkboxes with translations, comprehensive test coverage, and memory chunk deletion with safe file cleanup.
Out of Scope Changes check ✅ Passed All changes are within scope: core memory deletion APIs, RPC parameter additions, UI checkbox implementations, internationalization for all supported languages, and test coverage align directly with issue #2515 requirements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added feature Net-new user-facing capability or product behavior. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/. labels May 23, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/components/composio/ComposioConnectModal.tsx (1)

507-522: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Reset clearMemoryOnDisconnect on error recovery.

If deleteConnection fails, the checkbox state persists when the user dismisses the error (line 787) and returns to the 'connected' phase. On retry, the checkbox will still appear checked, which may confuse users who expected the form to reset.

🔄 Proposed fix

Add the state reset in the error handler:

     } catch (err) {
       const msg = err instanceof Error ? err.message : String(err);
       setPhase('error');
       setError(`${t('composio.connect.disconnectFailed')}: ${msg}`);
+      setClearMemoryOnDisconnect(false);
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/components/composio/ComposioConnectModal.tsx` around lines 507 - 522,
The error handler in handleDisconnect does not reset the clearMemoryOnDisconnect
checkbox state when deleteConnection fails, so after dismissing the error the
checkbox remains checked; update the catch block in handleDisconnect to reset
the checkbox by calling setClearMemoryOnDisconnect(false) (in addition to
setting phase and error) and ensure any recovery path that sets phase back to
'connected' also clears this state; reference functions/vars: handleDisconnect,
deleteConnection, setClearMemoryOnDisconnect, setPhase, setError, onChanged.
🧹 Nitpick comments (1)
app/src/components/composio/ComposioConnectModal.test.tsx (1)

226-243: 💤 Low value

Consider testing state reset behavior (optional).

The test verifies the API parameter is passed correctly, but doesn't verify that clearMemoryOnDisconnect is reset to false after a successful disconnect. While the current coverage is sufficient for the primary requirement, adding assertions for state reset would catch regressions if that logic changes.

Optional test enhancement

You could extend this test or add a separate one to verify the checkbox becomes unchecked after disconnect completes:

await waitFor(() => {
  expect(composioApi.deleteConnection).toHaveBeenCalledWith('ca_xyz', { clearMemory: true });
});

// Verify checkbox resets (if modal remains open in a different state)
// or that subsequent disconnect calls would default to clearMemory: false
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/components/composio/ComposioConnectModal.test.tsx` around lines 226 -
243, Extend the test for ComposioConnectModal to assert that the component's
clearMemoryOnDisconnect state resets after a successful disconnect: after the
existing waitFor that checks composioApi.deleteConnection was called with
('ca_xyz', { clearMemory: true }), add a follow-up assertion that the "also
delete memory" checkbox (or the clearMemoryOnDisconnect state) is
false/unchecked, or trigger a second disconnect and assert
composioApi.deleteConnection is called with clearMemory: false; reference
ComposioConnectModal, the clearMemoryOnDisconnect state/checkbox label "also
delete memory", and composioApi.deleteConnection to locate where to add the
assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/lib/i18n/ko.ts`:
- Around line 345-347: Replace the English values for the locale keys
accounts.disconnectClearMemory and accounts.disconnectClearMemoryHint with
Korean text: set accounts.disconnectClearMemory to a concise label like "이 소스의
메모리도 삭제" and set accounts.disconnectClearMemoryHint to a descriptive hint like
"이 연결과 연관된 로컬 메모리 조각을 영구적으로 삭제합니다." Ensure you update the string values for
those exact keys in the ko.ts translations so the disconnect UI shows Korean
text.

In `@src/openhuman/composio/ops.rs`:
- Around line 521-524: The match branch for toolkit currently only returns
sources for "slack" and "gmail" (using gmail_memory_sources_for_connection) and
falls back to Vec::new(), causing clear_memory to be a no-op for other Composio
memory-backed toolkits; update the default branch so it derives or queries
actual memory source IDs for any toolkit instead of returning an empty Vec (for
example by adding a helper like memory_sources_for_toolkit(toolkit,
connection_id) or calling the Composio API to list sources for the
connection_id), ensure the helper returns tuples of (SourceKind, source_id)
consistent with the Slack/Gmail branches, and wire that in where clear_memory
uses the match so memory_chunks_deleted reflects actual deletions.
- Around line 436-444: The loop calling
memory_tree_store::delete_chunks_by_source currently uses ? which returns early
and skips identity-facet cleanup, cache invalidation, and publishing
ComposioConnectionDeleted; change it to capture or log errors instead of
returning: replace the ? with code that pushes any error (with context including
source_id) into a local Vec<Error> or logs it, and continue the loop to ensure
identity-facet cleanup and cache invalidation still run and
ComposioConnectionDeleted is published; after all cleanup steps complete, if the
Vec is non-empty return or aggregate the errors into a single Err so callers
still see failures while local cleanup always runs.

In `@src/openhuman/memory/tree/store.rs`:
- Around line 822-833: remove_chunk_content_files currently appends DB-sourced
content_paths directly to config.memory_tree_content_root and can be exploited
for path traversal; instead, for each rel in content_paths (and in function
remove_chunk_content_files) resolve the candidate path safely by joining rel
components with the root via Path/PathBuf, then canonicalize both the root
(config.memory_tree_content_root()) and the candidate and verify the
canonicalized candidate starts_with the canonicalized root; if it does not, skip
removing and log a warning mentioning the redacted rel; only call
std::fs::remove_file for candidates that pass this containment check and handle
NotFound as before.

---

Outside diff comments:
In `@app/src/components/composio/ComposioConnectModal.tsx`:
- Around line 507-522: The error handler in handleDisconnect does not reset the
clearMemoryOnDisconnect checkbox state when deleteConnection fails, so after
dismissing the error the checkbox remains checked; update the catch block in
handleDisconnect to reset the checkbox by calling
setClearMemoryOnDisconnect(false) (in addition to setting phase and error) and
ensure any recovery path that sets phase back to 'connected' also clears this
state; reference functions/vars: handleDisconnect, deleteConnection,
setClearMemoryOnDisconnect, setPhase, setError, onChanged.

---

Nitpick comments:
In `@app/src/components/composio/ComposioConnectModal.test.tsx`:
- Around line 226-243: Extend the test for ComposioConnectModal to assert that
the component's clearMemoryOnDisconnect state resets after a successful
disconnect: after the existing waitFor that checks composioApi.deleteConnection
was called with ('ca_xyz', { clearMemory: true }), add a follow-up assertion
that the "also delete memory" checkbox (or the clearMemoryOnDisconnect state) is
false/unchecked, or trigger a second disconnect and assert
composioApi.deleteConnection is called with clearMemory: false; reference
ComposioConnectModal, the clearMemoryOnDisconnect state/checkbox label "also
delete memory", and composioApi.deleteConnection to locate where to add the
assertion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 313e1116-213d-4c44-a6b8-e5aac8a5f882

📥 Commits

Reviewing files that changed from the base of the PR and between 7745d58 and 9e182dc.

📒 Files selected for processing (36)
  • app/src/components/channels/DiscordConfig.tsx
  • app/src/components/channels/TelegramConfig.tsx
  • app/src/components/channels/__tests__/TelegramConfig.test.tsx
  • app/src/components/composio/ComposioConnectModal.test.tsx
  • app/src/components/composio/ComposioConnectModal.tsx
  • app/src/lib/composio/composioApi.test.ts
  • app/src/lib/composio/composioApi.ts
  • app/src/lib/composio/types.ts
  • app/src/lib/i18n/chunks/ar-1.ts
  • app/src/lib/i18n/chunks/bn-1.ts
  • app/src/lib/i18n/chunks/de-1.ts
  • app/src/lib/i18n/chunks/en-1.ts
  • app/src/lib/i18n/chunks/es-1.ts
  • app/src/lib/i18n/chunks/fr-1.ts
  • app/src/lib/i18n/chunks/hi-1.ts
  • app/src/lib/i18n/chunks/id-1.ts
  • app/src/lib/i18n/chunks/it-1.ts
  • app/src/lib/i18n/chunks/ko-1.ts
  • app/src/lib/i18n/chunks/pt-1.ts
  • app/src/lib/i18n/chunks/ru-1.ts
  • app/src/lib/i18n/chunks/zh-CN-1.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/ko.ts
  • app/src/services/api/__tests__/channelConnectionsApi.test.ts
  • app/src/services/api/channelConnectionsApi.ts
  • src/openhuman/channels/controllers/ops.rs
  • src/openhuman/channels/controllers/ops_tests.rs
  • src/openhuman/channels/controllers/schemas.rs
  • src/openhuman/channels/controllers/schemas_tests.rs
  • src/openhuman/composio/ops.rs
  • src/openhuman/composio/ops_test.rs
  • src/openhuman/composio/providers/profile.rs
  • src/openhuman/composio/schemas.rs
  • src/openhuman/composio/types.rs
  • src/openhuman/memory/tree/store.rs
  • src/openhuman/memory/tree/store_tests.rs

Comment thread app/src/lib/i18n/ko.ts Outdated
Comment thread src/openhuman/composio/ops.rs Outdated
Comment thread src/openhuman/composio/ops.rs Outdated
Comment thread src/openhuman/memory/tree/store.rs
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/openhuman/composio/ops_test.rs (1)

470-564: ⚡ Quick win

Consider adding error/failure case tests for memory cleanup.

The new memory cleanup tests cover happy paths well, but per the PR objectives ("Error handling: if clear_memory=true and deletion fails...surface an actionable error"), error scenarios should also be tested. Consider adding tests for:

  • Memory cleanup failure when clear_memory=true (e.g., simulating store errors during chunk deletion)
  • Partial cleanup failures (some targets succeed, others fail)
  • Error message format when cleanup fails
Suggested test scenario
#[tokio::test]
async fn composio_delete_connection_reports_memory_cleanup_failures() {
    // Set up config with invalid/broken memory store path
    // or seed chunks that trigger deletion errors
    // Call composio_delete_connection(&config, "c1", true)
    // Assert that the error message surfaces actionable detail
    // about the memory cleanup failure (not just connection deletion)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/composio/ops_test.rs` around lines 470 - 564, Add a test named
composio_delete_connection_reports_memory_cleanup_failures that calls
composio_delete_connection(&config, "c1", true) but arranges the memory store to
fail (for example create a temp workspace, seed chunks via
memory_tree_store::upsert_chunks or SyncState::save, then make the workspace
path unreadable/removed or use a MemoryClient pointing at a
corrupted/nonexistent dir so deletions error); assert the returned Result is Err
and the error string includes actionable details mentioning memory cleanup and
the failing target(s) (referencing composio_delete_connection,
composio_memory_targets_for_connection, MemoryCleanupTarget,
memory_tree_store::upsert_chunks/list_chunks, SyncState and MemoryClient to
locate relevant setup/seed code).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/openhuman/composio/ops.rs`:
- Around line 605-649: The helper notion_memory_targets_for_connection currently
swallows errors from MemoryClient::from_workspace_dir and SyncState::load and
returns a best-effort Vec, causing callers to miss hard failures; change
notion_memory_targets_for_connection to return a
Result<Vec<MemoryCleanupTarget>, E> (propagate the error returned by
MemoryClient::from_workspace_dir and SyncState::load back to the caller instead
of tracing::warn and continuing), only treat the specific benign "no sync state
yet" SyncState::load error as a no-op, and keep dedupe_memory_targets(targets)
on the success path so callers (e.g., the delete/clear flow) can surface and
handle failures rather than silently leaving Notion page-scoped targets behind.

In `@src/openhuman/memory/tree/store.rs`:
- Around line 855-876: The code currently canonicalizes root.join(rel_path) into
path and then calls std::fs::remove_file(&path), which removes the canonical
target (following symlinks); instead, keep the original entry and only use the
canonicalized path for the containment check: compute original_path =
root.join(rel_path), canonicalize(&original_path) for the NotFound/containment
checks, and after confirming it starts_with(&canonical_root) call
std::fs::remove_file(&original_path) (not &path); update the log/error handling
to reference original_path/rel as needed and preserve the existing warnings.

---

Nitpick comments:
In `@src/openhuman/composio/ops_test.rs`:
- Around line 470-564: Add a test named
composio_delete_connection_reports_memory_cleanup_failures that calls
composio_delete_connection(&config, "c1", true) but arranges the memory store to
fail (for example create a temp workspace, seed chunks via
memory_tree_store::upsert_chunks or SyncState::save, then make the workspace
path unreadable/removed or use a MemoryClient pointing at a
corrupted/nonexistent dir so deletions error); assert the returned Result is Err
and the error string includes actionable details mentioning memory cleanup and
the failing target(s) (referencing composio_delete_connection,
composio_memory_targets_for_connection, MemoryCleanupTarget,
memory_tree_store::upsert_chunks/list_chunks, SyncState and MemoryClient to
locate relevant setup/seed code).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c572c3ff-e807-4daa-85fe-1f13cac6e552

📥 Commits

Reviewing files that changed from the base of the PR and between 9e182dc and 92178af.

📒 Files selected for processing (8)
  • app/src/components/composio/ComposioConnectModal.test.tsx
  • app/src/components/composio/ComposioConnectModal.tsx
  • app/src/lib/i18n/chunks/ko-1.ts
  • app/src/lib/i18n/ko.ts
  • src/openhuman/composio/ops.rs
  • src/openhuman/composio/ops_test.rs
  • src/openhuman/memory/tree/store.rs
  • src/openhuman/memory/tree/store_tests.rs
✅ Files skipped from review due to trivial changes (1)
  • app/src/lib/i18n/chunks/ko-1.ts

Comment thread src/openhuman/composio/ops.rs
Comment thread src/openhuman/memory/tree/store.rs
@sanil-23
Copy link
Copy Markdown
Contributor

placeholder

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/openhuman/memory/tree/store.rs (1)

719-726: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reject empty prefixes before deleting.

starts_with("") matches every source_id, so an accidentally empty source_id_prefix will delete all chunks and ingest-gate rows for that SourceKind. This helper is public and sits on a destructive path, so it should fail closed.

🔧 Suggested fix
 pub fn delete_chunks_by_source_prefix(
     config: &Config,
     source_kind: SourceKind,
     source_id_prefix: &str,
 ) -> Result<usize> {
+    if source_id_prefix.is_empty() {
+        anyhow::bail!("source_id_prefix must not be empty");
+    }
     delete_chunks_by_source_filter(config, source_kind, |candidate| {
         candidate.starts_with(source_id_prefix)
     })
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/memory/tree/store.rs` around lines 719 - 726, The public helper
delete_chunks_by_source_prefix currently allows an empty source_id_prefix (since
starts_with("") matches everything); modify delete_chunks_by_source_prefix to
validate source_id_prefix is non-empty and return a failing Result (Err) when
it's empty instead of calling delete_chunks_by_source_filter, so accidental
empty prefixes cannot delete all rows; reference the function
delete_chunks_by_source_prefix and propagate a clear error message via the crate
Result type before invoking delete_chunks_by_source_filter.
🧹 Nitpick comments (1)
src/openhuman/memory/tree/store.rs (1)

707-724: ⚡ Quick win

Push exact-source deletes into SQL.

The exact path currently scans every row for the source_kind in both mem_tree_chunks and mem_tree_ingested_sources, then filters source_id in Rust. That bypasses the existing (source_kind, source_id) index/PK on a user-facing disconnect path. Splitting exact and prefix handling would keep the Rust-side filter only where it is actually needed.

Also applies to: 739-743, 788-793

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/memory/tree/store.rs` around lines 707 - 724, The current
delete_chunks_by_source implementation scans rows and filters source_id in Rust,
bypassing the (source_kind, source_id) index; change it so
delete_chunks_by_source performs direct SQL deletes (DELETE ... WHERE
source_kind = ? AND source_id = ?) against mem_tree_chunks and
mem_tree_ingested_sources to use the PK/index, and reserve
delete_chunks_by_source_filter/delete_chunks_by_source_prefix for true prefix
logic only (keep the Rust-side predicate there). Update the paths that currently
call delete_chunks_by_source_filter for exact matches (e.g., callers around
delete_chunks_by_source, delete_chunks_by_source_prefix, and any code affecting
mem_tree_ingested_sources) to call the new exact-SQL deletion code so
exact-source deletes hit the DB index. Ensure the SQL deletes return the
affected-row counts to match the current Result<usize> behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/openhuman/memory/tree/store.rs`:
- Around line 719-726: The public helper delete_chunks_by_source_prefix
currently allows an empty source_id_prefix (since starts_with("") matches
everything); modify delete_chunks_by_source_prefix to validate source_id_prefix
is non-empty and return a failing Result (Err) when it's empty instead of
calling delete_chunks_by_source_filter, so accidental empty prefixes cannot
delete all rows; reference the function delete_chunks_by_source_prefix and
propagate a clear error message via the crate Result type before invoking
delete_chunks_by_source_filter.

---

Nitpick comments:
In `@src/openhuman/memory/tree/store.rs`:
- Around line 707-724: The current delete_chunks_by_source implementation scans
rows and filters source_id in Rust, bypassing the (source_kind, source_id)
index; change it so delete_chunks_by_source performs direct SQL deletes (DELETE
... WHERE source_kind = ? AND source_id = ?) against mem_tree_chunks and
mem_tree_ingested_sources to use the PK/index, and reserve
delete_chunks_by_source_filter/delete_chunks_by_source_prefix for true prefix
logic only (keep the Rust-side predicate there). Update the paths that currently
call delete_chunks_by_source_filter for exact matches (e.g., callers around
delete_chunks_by_source, delete_chunks_by_source_prefix, and any code affecting
mem_tree_ingested_sources) to call the new exact-SQL deletion code so
exact-source deletes hit the DB index. Ensure the SQL deletes return the
affected-row counts to match the current Result<usize> behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6403beb9-05b8-4cc6-a131-a93c2b56fb80

📥 Commits

Reviewing files that changed from the base of the PR and between 92178af and 6e1eaa2.

📒 Files selected for processing (5)
  • app/src/components/channels/__tests__/DiscordConfig.test.tsx
  • src/openhuman/composio/ops.rs
  • src/openhuman/composio/ops_test.rs
  • src/openhuman/memory/tree/store.rs
  • src/openhuman/memory/tree/store_tests.rs

@YOMXXX
Copy link
Copy Markdown
Contributor Author

YOMXXX commented May 23, 2026

@graycyrus @senamakel Ready for review.

Latest state for #2528 (feat(memory): clear source memory on disconnect):

  • all required checks are green
  • no unresolved review threads
  • CodeRabbit has no actionable comments on the latest head

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Net-new user-facing capability or product behavior. memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Offer memory deletion when disconnecting a channel or Composio integration

2 participants