Repository navigation
feat(memory): file the brain by connector, not by file type - #7085
Conversation
A Composio memory source took its toolkit slug only lowercased, so `google_drive` stayed `google_drive` while Composio names the toolkit `googledrive`: the source never matched its own connections, and its items would file under a brain source no connection uses. normalize_target() now runs the slug through canonicalize_toolkit_slug() (now pub(crate)), and source_id_for_toolkit() compares canonical slugs on both sides, so a source saved before this still finds its connections.
A brain source is the unit memory erases when the user disconnects an app or removes a source, so it has to name where a document came from. Local files were filed by format (source:pdf, source:markdown, HTML in source:web next to links), so no node matched anything a user removes. brain_source() now maps by connector: every local file and upload to `files`, links and feeds to `web`, GitHub (the reader and the Composio toolkit alike) to `github`, and any other Composio toolkit to its canonical slug. memory_brain_ingest files under `files` when no source is named. `files` is BrainSource::Other until the tinymemory pin carries BrainSource::Files (same node).
The migration to the connector-keyed brain re-stores every document of the old per-type nodes under its new source. legacy_brain_node() is the one rule it applies, as a pure function: per-format nodes (pdf, markdown, docx, xlsx, pptx, code, other) to `files`; `web` to `files` for a file (a file kind, or a file path, which uploads kept although they carried the Link kind `web` implies) and to `web` for links and feeds; any other node to its canonical Composio slug, so connectors keep their node.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (3)
💤 Files with no reviewable changes (2)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review. 📝 WalkthroughWalkthroughMemory documents now use connector-based source assignments. Local files and uploads use the ChangesMemory source filing and labels
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~20 minutes Change: Feature Suggested reviewers: Merge Risk: ⚪ Minimal · up to No actionable merge-blocking issue is established in the supplied changes. The new ingestion test’s listing and search checks use a mock backend that exposes accepted writes synchronously. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to Documents now share connector-based groups, and toolkit aliases resolve to one identity. Existing source and connection deletion filters remain narrowly scoped. Compatibility with older records and cleanup during concurrent background writes is not fully established. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
A rabbit files a note away, Comment |
Tiny Sweeper reviewTiny Sweeper completed its review; deterministic results follow. State: Reviewing pending checks Review snapshot
Completeness: Complete What changedThe pull request refiles brain documents by connector rather than by file format. `brain_source` now keys on the source kind: GitHub, web, or a Composio toolkit's canonical slug, while local files and text of every format are filed under a single `files` source instead of per-format nodes like `pdf`/`markdown`. `canonicalize_toolkit_slug` is promoted to `pub(crate)` and applied when normalizing Composio targets, matching configured sources, and deriving source ids, so legacy aliases like `google_drive` are treated as the same toolkit as `googledrive` and duplicates are rejected. The UI adds a translated `files` brain source label across 17 locales. This revision also adds a poll-until-queryable helper for e2e reads of writes. Features
Tests
Findings
Previously reported and still active
Resolved this pass
Pending checks: Rust E2E (mock backend), Build Playwright E2E Artifact, E2E (Playwright / web lane), Desktop E2E (full suite, 3 OS) Before merge
How this fits togetherflowchart LR
n0["german"]:::impacted
n1["missingKeys"]:::impacted
n2["simplifiedChinese"]:::impacted
n1 -->|uses| n0
n1 -->|uses| n2
classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Agent review detailscritique
security
tests
commits
description
e2e
Evidence and run details
|
There was a problem hiding this comment.
tinysweeper found nothing blocking. Approving.
$0.0264 · 391,406 in / 16,400 out · 59,653 cached (15%) · gpt-5.6-luna, glm-5.3-flash
critique: $0.0129 · 170,731 in / 6,808 out · 45,469 cached (27%) · gpt-5.6-luna, glm-5.3-flash
security: $0.0130 · 167,810 in / 4,684 out · 11,240 cached (7%) · gpt-5.6-luna
tests: $0.0001 · 12,232 in / 533 out · 1,536 cached (13%) · glm-5.3-flash
description: $0.0001 · 12,880 in / 248 out · 1,408 cached (11%) · glm-5.3-flash
e2e: $0.0001 · 15,874 in / 131 out · 0 cached (0%) · glm-5.3-flash
brain_ingest_files_a_pdf_by_path only runs with the documents feature, so the focused memory:: run missed it; it now expects the files source and checks the node the document landed at.
A source saved as google_drive before targets were canonicalized and a new googledrive one name the same toolkit, but apply_add compared the stored target literally and added the second. It now canonicalizes the saved Composio target before comparing.
There was a problem hiding this comment.
tinysweeper found nothing blocking. Approving.
$0.0077 · 118,980 in / 5,446 out · 8,490 cached (7%) · gpt-5.6-luna, glm-5.3-flash
critique: $0.0027 · 23,728 in / 1,242 out · 2,031 cached (9%) · gpt-5.6-luna
security: $0.0045 · 38,290 in / 1,372 out · 1,787 cached (5%) · gpt-5.6-luna
tests: $0.0001 · 13,234 in / 238 out · 1,536 cached (12%) · glm-5.3-flash
description: $0.0001 · 13,988 in / 93 out · 1,408 cached (10%) · glm-5.3-flash
e2e: $0.0001 · 16,933 in / 871 out · 1,728 cached (10%) · glm-5.3-flash
End to end through the running core: memory_brain_ingest with a file path and with text, neither naming a source, files both under files, memory_brain_sources lists that one source with both documents, and a search of it finds them.
There was a problem hiding this comment.
tinysweeper found nothing blocking. Approving.
$0.0078 · 169,214 in / 9,618 out · 14,680 cached (9%) · gpt-5.6-luna, glm-5.3-flash
critique: $0.0047 · 65,182 in / 3,794 out · 9,136 cached (14%) · gpt-5.6-luna, glm-5.3-flash
security: $0.0025 · 29,376 in / 2,074 out · 5,352 cached (18%) · gpt-5.6-luna
tests: $0.0001 · 13,933 in / 773 out · 64 cached (0%) · glm-5.3-flash
description: $0.0001 · 14,687 in / 227 out · 64 cached (0%) · glm-5.3-flash
e2e: $0.0001 · 17,569 in / 772 out · 64 cached (0%) · glm-5.3-flash
… to end Over JSON-RPC through the running core: a document at an old per-format node (source:pdf) stays listed beside files, searchable and forgettable until the migration re-files it; a Composio source added as Google_Drive is stored as googledrive, and adding googledrive again is refused.
There was a problem hiding this comment.
tinysweeper found nothing blocking. Approving.
$0.0096 · 221,152 in / 11,671 out · 19,050 cached (9%) · gpt-5.6-luna, glm-5.3-flash
critique: $0.0029 · 40,896 in / 2,228 out · 4,056 cached (10%) · gpt-5.6-luna, glm-5.3-flash
security: $0.0060 · 70,834 in / 4,792 out · 12,050 cached (17%) · gpt-5.6-luna
tests: $0.0003 · 30,437 in / 1,389 out · 1,536 cached (5%) · glm-5.3-flash
description: $0.0001 · 15,504 in / 458 out · 1,408 cached (9%) · glm-5.3-flash
e2e: $0.0001 · 18,030 in / 582 out · 0 cached (0%) · glm-5.3-flash
legacy_brain_node() had no caller here: it is the migration's rule, and it belongs with the job that re-files old documents and the end-to-end test that proves it, so it leaves this change. The alias end-to-end test stays, as an_aliased_toolkit_is_one_memory_source.
There was a problem hiding this comment.
tinysweeper found nothing blocking. Approving.
$0.0123 · 300,352 in / 15,937 out · 31,021 cached (10%) · gpt-5.6-luna, glm-5.3-flash
critique: $0.0067 · 132,308 in / 7,358 out · 15,259 cached (12%) · gpt-5.6-luna, glm-5.3-flash
security: $0.0049 · 92,680 in / 3,787 out · 10,962 cached (12%) · gpt-5.6-luna
tests: $0.0001 · 13,234 in / 673 out · 1,536 cached (12%) · glm-5.3-flash
description: $0.0001 · 13,988 in / 749 out · 1,408 cached (10%) · glm-5.3-flash
e2e: $0.0001 · 16,561 in / 1,348 out · 1,728 cached (10%) · glm-5.3-flash
…d to end A document stored at source:pdf before the brain was filed by connector stays listed beside files, is found by an unscoped brain search, and can be forgotten by its source, over JSON-RPC through the running core.
There was a problem hiding this comment.
tinysweeper found nothing blocking. Approving.
$0.0038 · 163,706 in / 10,137 out · 18,039 cached (11%) · gpt-5.6-luna, glm-5.3-flash
critique: $0.0013 · 57,246 in / 3,811 out · 7,893 cached (14%) · gpt-5.6-luna, glm-5.3-flash
security: $0.0020 · 46,261 in / 3,101 out · 8,482 cached (18%) · gpt-5.6-luna
tests: $0.0001 · 13,847 in / 367 out · 64 cached (0%) · glm-5.3-flash
description: $0.0001 · 14,459 in / 297 out · 1,408 cached (10%) · glm-5.3-flash
e2e: $0.0001 · 17,179 in / 293 out · 64 cached (0%) · glm-5.3-flash
The fixture's backend answers a read of a fresh write at once, but the brain e2e cases now wait (bounded, ten seconds) for the listing and the search to show what was ingested, so they hold on a backend that indexes after it answers.
There was a problem hiding this comment.
tinysweeper found nothing blocking. Approving.
$0.0045 · 123,268 in / 6,136 out · 7,892 cached (6%) · gpt-5.6-luna, glm-5.3-flash
critique: $0.0026 · 20,359 in / 1,850 out · 2,540 cached (12%) · gpt-5.6-luna, glm-5.3-flash
security: $0.0012 · 24,242 in / 1,176 out · 5,352 cached (22%) · gpt-5.6-luna
tests: $0.0001 · 14,338 in / 337 out · 0 cached (0%) · glm-5.3-flash
description: $0.0001 · 14,950 in / 450 out · 0 cached (0%) · glm-5.3-flash
e2e: $0.0001 · 17,669 in / 343 out · 0 cached (0%) · glm-5.3-flash
fix(memory): forget a disconnected app's items within its own source (stacked on #7085)
Summary
source:files.source:web.source:github.source:gmail,source:googledrive).google_drive→googledrive), and a source saved before this still matches its connections.filessource in all 16 locales.Problem
source:pdf, a markdown file insource:markdown, an HTML file insource:webnext to fetched links. No node matched anything the user can actually remove.google_drivesource never matched Composio'sgoogledriveconnections, and its items would have filed under a source no connection uses.Solution
memory::brain::brain_source(kind, target)maps by connector.memory_brain_ingestdefaults tofiles.filesisBrainSource::Other("files")until the tinymemory pin carriesBrainSource::Files(File the brain by connector: source:files, and collections below a source tinymemory#214). It is the same node, so nothing moves at that bump.normalize_target()andsource_id_for_toolkit()usecanonicalize_toolkit_slug(), nowpub(crate), so the canonical slug is defined in one place.Submission Checklist
synced_items_are_filed_by_their_connectorcovers every kind, the GitHub reader and toolkit sharing a source, and the alias slug.normalize_targetcovers the alias, andsource_id_for_toolkitcovers an alias saved before this change.source:files, and end to end over JSON-RPC:local_files_and_text_file_under_the_files_sourceandan_aliased_toolkit_is_one_memory_source.brainSourceLabel.pnpm test:coveragelocally; CI's diff-cover is the gate.Impact
Filessource.memory_brain_ingest,_searchand_forgetstill accept every old source id.Related
BrainSource::Files, collections, subtree forget/build): not required by this PR.AI Authored PR Metadata (required for Codex/Linear PRs)
Linear Issue
Commit & Branch
feat/brain-by-connector4171b6ab25Validation Run
pnpm --filter openhuman-app format:check:prettier --checkon the changed frontend files passes;cargo fmt --all -- --checkpasses.pnpm typecheck: pass.cargo test -p openhuman --lib -- memory:: integrations::composio: 520 passed.vitest run --config test/vitest.config.ts src/components/memory: 148 passed.cargo clippy -p openhuman --all-targets -- -D warningsandpnpm rust:layoutpass.pnpm i18n:checkpass.Validation Blocked
command:pnpm i18n:english:checkerror:2 unexpected English strings inja(chat.subagents.ofTotal,chat.todos.ofTotal="{complete} / {total}").impact:pre-existing onmain, not touched by this PR.Behavior Changes
Files(and connected apps) instead ofPDFandMarkdownfor new documents.Parity Contract
composio.Duplicate / Superseded PR Handling
Summary by CodeRabbit