feat(composio): provider folder modules + user profile persistence#523
feat(composio): provider folder modules + user profile persistence#523senamakel merged 6 commits intotinyhumansai:mainfrom
Conversation
- Introduced a new `profile` module to handle the persistence of user profile data from various providers into the local `user_profile` facet table. - Enhanced the `composio_get_user_profile` and `fetch_user_profile` functions to call `persist_provider_profile`, ensuring that profile fields like display name, email, and avatar are stored locally for quick access. - Added debug logging to track the number of facets written during the persistence process, improving observability of profile updates. - This change aims to enhance user experience by reducing the need for repeated upstream API calls for frequently accessed profile information.
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 5 minutes and 59 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughThe PR introduces profile persistence for Composio providers by creating a new profile module that writes fetched provider identity fields into the local user_profile facet table, while refactoring Gmail and Notion provider helpers into dedicated sync modules with extracted test files. Changes
Sequence Diagram(s)sequenceDiagram
participant CP as ComposioProvider
participant API as Composio API
participant Profile as profile module
participant DB as user_profile table
CP->>API: fetch ProviderUserProfile
API-->>CP: ProviderUserProfile
CP->>Profile: persist_provider_profile(profile)
Profile->>Profile: extract identity fields<br/>(email, display_name, etc.)
Profile->>DB: upsert facets<br/>(context facet type)
DB-->>Profile: facets_written count
Profile-->>CP: facets_written
CP->>CP: emit debug log<br/>(toolkit, facets_written)
CP-->>CP: return RpcOutcome/result
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
src/openhuman/composio/providers/gmail/tests.rs (1)
42-50: Strengthen the epoch-millis test with an exact expected date.At Lines 46-50, checking only for
'/'can pass even with an incorrect conversion result.✅ Proposed test hardening
#[test] fn cursor_to_filter_from_epoch_millis() { - // 2026-04-01 00:00:00 UTC in millis - let millis = "1774915200000"; - let filter = cursor_to_gmail_after_filter(millis); - assert!(filter.is_some()); - // Should produce a YYYY/MM/DD date. - let f = filter.unwrap(); - assert!(f.contains('/'), "Expected date with slashes, got {f}"); + // 1970-01-02 00:00:00 UTC in millis + assert_eq!( + cursor_to_gmail_after_filter("86400000"), + Some("1970/01/02".to_string()) + ); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/openhuman/composio/providers/gmail/tests.rs` around lines 42 - 50, The test cursor_to_filter_from_epoch_millis currently only checks for a '/' in the output which is too weak; update the test (and keep using cursor_to_gmail_after_filter and the same millis "1774915200000") to assert the exact expected date string (e.g. "2026/04/01") appears in the filter (or equals it if the function returns only the date) instead of just asserting f.contains('/'), so replace the loose assertion with a precise equality or substring check against "2026/04/01".src/openhuman/composio/providers/profile.rs (1)
82-87: Usedebug!for the persistence success log.This runs on normal fetch/connect paths and reads like development diagnostics, so
info!will get noisy quickly.As per coding guidelines, "Use log/tracing at debug or trace level for development-oriented diagnostics in Rust."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/openhuman/composio/providers/profile.rs` around lines 82 - 87, The persistence success log currently uses tracing::info! which is too noisy for normal fetch/connect flows; change the call to tracing::debug! (keeping the same structured fields toolkit = %toolkit, facets_written = written and the message "[composio:profile] persisted provider profile facets") so the message is emitted at debug level instead of info in the branch that checks written > 0.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/openhuman/composio/providers/gmail/sync.rs`:
- Around line 44-59: The cursor_to_gmail_after_filter function is vulnerable to
leading/trailing whitespace causing parse failures; fix it by trimming the input
at the start (e.g., let s = cursor.trim()) and use that trimmed string for all
subsequent parse attempts (millis parse, NaiveDate::parse_from_str,
DateTime::parse_from_rfc3339) so whitespace does not silently bypass the filter
while preserving the existing return values and formats.
In `@src/openhuman/composio/providers/profile.rs`:
- Around line 58-69: The provider writes use profile::profile_upsert with a
fixed PROVIDER_CONFIDENCE (0.95) for provider-authoritative facets (keys built
from facet_id/key), but the unified store
(src/openhuman/memory/store/unified/profile.rs) only replaces values when new
confidence is greater, so equal-confidence refreshes leave stale values; change
the provider write to use an overwrite path for provider-authoritative facets by
invoking the upsert variant that forces replace-on-equal (or add a parameter to
profile::profile_upsert to allow replace_on_equal) when writing
FacetType::Context for provider data (the code that constructs facet_id/key and
calls profile::profile_upsert), ensuring same-source refreshes replace
equal-confidence values rather than only incrementing evidence_count.
---
Nitpick comments:
In `@src/openhuman/composio/providers/gmail/tests.rs`:
- Around line 42-50: The test cursor_to_filter_from_epoch_millis currently only
checks for a '/' in the output which is too weak; update the test (and keep
using cursor_to_gmail_after_filter and the same millis "1774915200000") to
assert the exact expected date string (e.g. "2026/04/01") appears in the filter
(or equals it if the function returns only the date) instead of just asserting
f.contains('/'), so replace the loose assertion with a precise equality or
substring check against "2026/04/01".
In `@src/openhuman/composio/providers/profile.rs`:
- Around line 82-87: The persistence success log currently uses tracing::info!
which is too noisy for normal fetch/connect flows; change the call to
tracing::debug! (keeping the same structured fields toolkit = %toolkit,
facets_written = written and the message "[composio:profile] persisted provider
profile facets") so the message is emitted at debug level instead of info in the
branch that checks written > 0.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 44e39af3-9e7c-4363-a6e3-27404121f8db
📒 Files selected for processing (10)
src/openhuman/composio/ops.rssrc/openhuman/composio/providers/gmail/mod.rssrc/openhuman/composio/providers/gmail/sync.rssrc/openhuman/composio/providers/gmail/tests.rssrc/openhuman/composio/providers/mod.rssrc/openhuman/composio/providers/notion/mod.rssrc/openhuman/composio/providers/notion/sync.rssrc/openhuman/composio/providers/notion/tests.rssrc/openhuman/composio/providers/profile.rssrc/openhuman/memory/store/client.rs
…ion, log level
- Trim whitespace in cursor_to_gmail_after_filter before parsing so
leading/trailing spaces don't silently bypass the date filter.
- Change profile_upsert condition from `>` to `>=` so equal-confidence
provider refreshes replace stale values instead of only bumping
evidence_count.
- Tighten epoch millis test to assert exact date "2026/03/31" instead
of loose contains('/') check.
- Lower profile persistence log from info to debug to reduce noise in
normal connect/sync flows.
Summary
providers/gmail/,providers/notion/) withmod.rs(struct + trait impl),sync.rs(helpers), andtests.rs— following the project convention for new features living in folder modules.providers/profile.rs):ProviderUserProfiledata (display name, email, username, avatar) is now persisted into the localuser_profilefacet table on OAuth connection and RPC profile fetch. Previously this data was fetched, logged, and discarded.profile_conn()getter toMemoryClient(pub(crate)) to expose the SQLite connection for direct profile-facet writes without going through the ingestion queue.Key design decisions
FacetType::Contextwith confidence 0.95 (provider-sourced data is authoritative, not inferred from conversation)composio:{toolkit}:{field}convention (e.g.composio:gmail:email)profile_upsertconflict resolutionFiles changed (10)
providers/gmail.rs→providers/gmail/{mod,sync,tests}.rsproviders/notion.rs→providers/notion/{mod,sync,tests}.rsproviders/profile.rsproviders/mod.rspub mod profile;+ wired intoon_connection_createdcomposio/ops.rsget_user_profilenow persists as side-effectmemory/store/client.rspub(crate) fn profile_conn()Test plan
cargo checkpasses cleancargo test --lib -- openhuman::composio::providers— 36 tests pass (including 3 new profile tests)Summary by CodeRabbit
New Features
Refactor