mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
fix(gmail): remove inbox-only sync restriction to enable sent-mail re… (#1902)
This commit is contained in:
@@ -36,6 +36,20 @@ use crate::openhuman::composio::providers::{
|
||||
const ACTION_GET_PROFILE: &str = "GMAIL_GET_PROFILE";
|
||||
const ACTION_FETCH_EMAILS: &str = "GMAIL_FETCH_EMAILS";
|
||||
|
||||
/// Base Gmail search query used on every sync pass.
|
||||
///
|
||||
/// Excludes spam and trash but intentionally does NOT restrict to `in:inbox` —
|
||||
/// that restriction (issue #1713) prevented sent emails from ever being ingested.
|
||||
/// Exported `pub(super)` so `tests.rs` can assert against the canonical value
|
||||
/// rather than a duplicated literal.
|
||||
pub(super) const BASE_QUERY: &str = "-in:spam -in:trash";
|
||||
|
||||
/// Gmail search query strings that retrieve sent mail.
|
||||
///
|
||||
/// Any of these can be passed as the `query` parameter to `GMAIL_FETCH_EMAILS`
|
||||
/// to fetch outbound messages. Exported `pub(super)` for use in regression tests.
|
||||
pub(super) const SENT_QUERIES: &[&str] = &["from:me", "label:SENT", "in:sent"];
|
||||
|
||||
/// Page size per API call. Kept moderate so each call is fast and we
|
||||
/// get frequent checkpoints for the daily budget.
|
||||
const PAGE_SIZE: u32 = 25;
|
||||
@@ -283,7 +297,14 @@ impl ComposioProvider for GmailProvider {
|
||||
// so same-day re-ticks do not re-fetch a whole day's
|
||||
// window every time. Fall back to the day filter only when
|
||||
// the cursor cannot be parsed as a timestamp.
|
||||
let mut query = "in:inbox -in:spam -in:trash".to_string();
|
||||
//
|
||||
// NOTE: We intentionally do NOT restrict to `in:inbox` here.
|
||||
// The original query `in:inbox -in:spam -in:trash` meant sent
|
||||
// emails (label:SENT) were never fetched and therefore the
|
||||
// agent could not answer questions about outbound mail (issue #1713).
|
||||
// Removing `in:inbox` lets Gmail return both inbox and sent
|
||||
// messages while still excluding spam and trash.
|
||||
let mut query = BASE_QUERY.to_string();
|
||||
if let Some(ref cursor) = state.cursor {
|
||||
if let Some(epoch_filter) = sync::cursor_to_gmail_after_epoch_filter(cursor) {
|
||||
query.push_str(&format!(" after:{epoch_filter}"));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//! Unit tests for the Gmail provider.
|
||||
|
||||
use super::provider::{BASE_QUERY, SENT_QUERIES};
|
||||
use super::sync::{
|
||||
cursor_to_gmail_after_epoch_filter, cursor_to_gmail_after_filter, extract_messages,
|
||||
extract_page_token, now_ms, parse_cursor_to_epoch_secs,
|
||||
@@ -238,3 +239,63 @@ fn extract_messages_handles_deep_nesting() {
|
||||
// live `ComposioClient` (HTTP) plus the global `MemoryClient` singleton.
|
||||
// Those go through the integration test suite. Here we just lock in
|
||||
// the provider's identity surface and helpers.
|
||||
|
||||
// ── Regression tests for issue #1713: sent-mail retrieval ───────────────────
|
||||
//
|
||||
// Before the fix the sync query was `in:inbox -in:spam -in:trash`, which meant
|
||||
// sent emails (label:SENT) were never fetched or ingested into the memory tree.
|
||||
// The fix removes `in:inbox` so both inbox and sent mail are fetched.
|
||||
|
||||
/// Guard: the provider source must NOT contain the `in:inbox` restriction.
|
||||
/// If this test fails, someone reintroduced the inbox-only query that caused
|
||||
/// issue #1713.
|
||||
#[test]
|
||||
fn provider_source_does_not_restrict_to_inbox() {
|
||||
let source = include_str!("provider.rs");
|
||||
// The old restriction started with `"in:inbox`. The double-quote is part
|
||||
// of the Rust string literal, so this catches the exact regression pattern.
|
||||
assert!(
|
||||
!source.contains("\"in:inbox"),
|
||||
"provider.rs sync query must NOT start with 'in:inbox' — this \
|
||||
restriction prevents sent emails from being ingested (issue #1713). \
|
||||
Use '-in:spam -in:trash' to allow both inbox and sent mail."
|
||||
);
|
||||
}
|
||||
|
||||
/// The base sync query must exclude spam and trash but NOT restrict to inbox.
|
||||
/// Asserts against the canonical `BASE_QUERY` constant from provider.rs so
|
||||
/// any change to the production value is caught immediately.
|
||||
#[test]
|
||||
fn sync_base_query_excludes_spam_and_trash_without_inbox_restriction() {
|
||||
assert!(
|
||||
BASE_QUERY.contains("-in:spam"),
|
||||
"BASE_QUERY must exclude spam (got: {BASE_QUERY:?})"
|
||||
);
|
||||
assert!(
|
||||
BASE_QUERY.contains("-in:trash"),
|
||||
"BASE_QUERY must exclude trash (got: {BASE_QUERY:?})"
|
||||
);
|
||||
assert!(
|
||||
!BASE_QUERY.contains("in:inbox"),
|
||||
"BASE_QUERY must NOT restrict to inbox — omitting this allows sent \
|
||||
mail to be fetched and ingested (issue #1713). Got: {BASE_QUERY:?}"
|
||||
);
|
||||
}
|
||||
|
||||
/// Sent-mail query strings must be non-empty and must not restrict to inbox.
|
||||
/// Iterates `SENT_QUERIES` from provider.rs — the canonical list of query
|
||||
/// strings a user or agent can pass to GMAIL_FETCH_EMAILS for sent mail.
|
||||
#[test]
|
||||
fn sent_mail_query_strings_are_well_formed() {
|
||||
assert!(!SENT_QUERIES.is_empty(), "SENT_QUERIES must not be empty");
|
||||
for q in SENT_QUERIES {
|
||||
assert!(
|
||||
!q.is_empty(),
|
||||
"sent-mail query must not be empty, got empty string in SENT_QUERIES"
|
||||
);
|
||||
assert!(
|
||||
!q.starts_with("in:inbox"),
|
||||
"sent-mail query '{q}' must not restrict to inbox"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,7 +499,10 @@ impl Tool for ComposioTool {
|
||||
fn description(&self) -> &str {
|
||||
"Execute actions on 1000+ apps via Composio (Gmail, Notion, GitHub, Slack, etc.). \
|
||||
Use action='list' to see available actions, action='execute' with action_name/tool_slug, params, and optional connected_account_id, \
|
||||
or action='connect' with app/auth_config_id to get OAuth URL."
|
||||
or action='connect' with app/auth_config_id to get OAuth URL. \
|
||||
For Gmail: GMAIL_FETCH_EMAILS supports standard Gmail search syntax in the 'query' param — \
|
||||
use query='from:me' or query='label:SENT' to retrieve sent emails, query='label:INBOX' for inbox, \
|
||||
query='is:unread' for unread mail, etc. Sent mail is synced and searchable."
|
||||
}
|
||||
|
||||
fn parameters_schema(&self) -> serde_json::Value {
|
||||
|
||||
Reference in New Issue
Block a user