feat(ui): preserve email connector grant + scope consent under Path 2 (incl. Outlook CTA)#1775
Conversation
Conditionally mounts the gaia_agent_email /v1/email/* router inside create_app when the wheel is installed, mirroring the pattern already used in gaia.api.openai_server. An absent wheel logs a clean info message; a broken installed wheel propagates loudly per the no-silent-fallback rule. Adds integration tests that cover the mounted health/version/triage surface and the absent-wheel skip path.
…correct assertions The #1768 integration test hung in the TestClient lifespan (the UI server's startup tasks) and carried three wrong assertions that were never reached: - use a non-lifespan TestClient (email routes are self-contained; the heavy startup can hang in a bare env, see #1297) - health returns {status: ok}, not an 'ok' key - absent-wheel paths fall through to the SPA catch-all (HTML 200), so assert the email router does not serve them rather than expecting 404 - patch find_spec targeted (no fragile module reload)
…tor (#1770) Tests verify: - installed:email REQUIRED_CONNECTORS exposes full Google+Microsoft scope sets independent of chat-agent activation (resolved from the class, not session) - AGENT_NOT_GRANTED raises for both google/microsoft when no grant exists (403, not 500) — regression-guard against generic-500 regression - CONNECTION_MISSING_SCOPES fires when OAuth token lacks calendar.events while mail scopes are present; triage/send mail-only scopes pass grant check - resolve_send_backend raises HTTP 503 (actionable) when no mailbox connected - Legacy builtin:email → installed:email grant migration is correct and idempotent
…or (#1770) EmailConnectCta now detects which provider the connectors error references (google / microsoft / both) and renders matching connect button(s) — resolving the UI gap where Outlook users saw a Google-only prompt. ConnectorsSection gains Microsoft Graph scope URI labels so the consent list is human-readable. MessageBubble threads `content` to EmailConnectCta for provider detection.
…nd detectProvider (#1770)
…nown connectorId Narrow the connectorId override to the valid google/microsoft values and fall back to content detection otherwise, removing the unchecked cast that could silently hide both buttons (no-silent-fallback convention). Addresses a review advisory.
Real-world (macOS) — live Google OAuth consent ✅Verified on macOS via the Agent UI's in-app connector setup (no env vars — client creds entered in Settings → Connectors → Google, stored in the OS keyring):
Cross-platform (Linux + Windows) OAuth runs next as a coordinated pass. The three negative-scope cases remain covered by the 22 Python tests. |
SummaryClean, well-scoped frontend change that makes the email Connect CTA provider-aware (Google and Microsoft) and adds a thorough Python regression suite for the email connector's grant/scope consent under Path 2. I traced the detection logic against the real The single most important thing: the test suite is almost entirely mock-based (it patches Issues Found🟢 Minor — CTA loses its "reopen sign-in" affordance (
|
…ct send-backend name in tests
- EmailConnectCta: button stays enabled after opening OAuth (disabled={busy}),
labelled 'Reopen <provider> sign-in', so a user who closes the OAuth tab can
reopen it instead of having to re-send the message.
- tests: rename resolve_send_backend -> get_send_backend in docstrings/test name
to match the real api_routes.get_send_backend symbol.
|
Thanks — addressed in 7998aae:
For the record on the no-action items:
Also retargeted this PR to |
Closes #1770. Part of the Path-2 email-in-Agent-UI epic #1767.
Why this matters
Under Path 2 email is consumed as a backend REST surface, not an activated chat agent — but it still needs write-level OAuth scopes (
gmail.modify+gmail.send+calendar.events/Mail.ReadWrite+Mail.Send+Calendars.ReadWrite). Before: consent was driven by email being a granted/activated chat agent, and the Connect CTA only offered Google (Outlook users had no path). If the user connected a mailbox without grantinginstalled:email, write calls failed at call time. After: the Connectors panel surfaces email's requirement from the registry independent of chat activation, the CTA drives consent for both Google and Microsoft, and every insufficient/absent-scope state returns an actionable error + the Connect/Reconnect CTA — never a silent success or generic 500.Evidence
22 Python regression tests —
tests/test_ui_email_scope_consent.py(all pass) covering every AC:installed:emailREQUIRED_CONNECTORSindependent of chat activationAGENT_NOT_GRANTED(Google + Microsoft)calendar.events→CONNECTION_MISSING_SCOPES; triage/draft/send still workbuiltin:email→installed:emailgrant migration (regression-guard [Bug]: Agent UI — connected Google account can't be used by Email Triage agent (per-agent grant missing in UI, then token 401) #1592)20 Vitest —
EmailConnectCta.test.ts(all pass): provider-aware dual-button CTA (detectProvider, Microsoft auth-required paths).npm run buildclean (2086 modules).Real-world (in progress)
Live Gmail + Outlook consent (showing the requested email scopes) is being captured on macOS with the test accounts; cross-platform (Linux/Windows) follows. Posted as a follow-up.
Test plan
python -m pytest tests/test_ui_email_scope_consent.py -v→ 22 passedcd src/gaia/apps/webui && npm test -- EmailConnectCta && npm run build