fix(memory-workspace): show all native Composio memory-sync sources (not Gmail-only) (#2685)

This commit is contained in:
YellowSnnowmann
2026-05-27 15:54:10 +05:30
committed by GitHub
parent b94545bd8c
commit fae16082d3
4 changed files with 21 additions and 16 deletions
@@ -21,7 +21,7 @@
* "Connected sources" panel with one section, one Sync button, one
* stats block per identity. Sync only appears when:
* 1. the connection is currently ACTIVE/CONNECTED, AND
* 2. the toolkit is in the syncable allow-list (today: gmail).
* 2. the toolkit is in the syncable allow-list passed by the parent.
*/
import { useCallback, useEffect, useMemo, useState } from 'react';
@@ -54,11 +54,17 @@ interface MemoryWorkspaceProps {
* adding chunks to the memory tree.
*
* Source of truth: providers under
* `src/openhuman/composio/providers/<toolkit>/` that call
* `ingest_page_into_memory_tree`. Today that's gmail. Add a slug here
* when a new provider lands a memory-tree ingest path.
* `src/openhuman/memory_sync/composio/providers/<toolkit>/` that
* persist items via `store_skill_sync` into the memory tree.
*/
const SYNCABLE_TOOLKITS: ReadonlySet<string> = new Set(['gmail']);
const SYNCABLE_TOOLKITS: ReadonlySet<string> = new Set([
'clickup',
'github',
'gmail',
'linear',
'notion',
'slack',
]);
export function MemoryWorkspace({ onToast }: MemoryWorkspaceProps) {
const { t } = useT();
@@ -235,24 +235,23 @@ describe('MemoryWorkspace (graph view)', () => {
});
});
it('hides toolkits without a memory-tree ingest provider entirely', async () => {
it('shows sync rows for provider-backed toolkits and hides non-syncable ones', async () => {
listConnections.mockResolvedValue({
connections: [
{ id: 'conn-gmail', toolkit: 'gmail', status: 'ACTIVE', accountEmail: 'a@x' },
{ id: 'conn-slack', toolkit: 'slack', status: 'ACTIVE', workspace: 'acme' },
{ id: 'conn-notion', toolkit: 'notion', status: 'ACTIVE' },
{ id: 'conn-discord', toolkit: 'discord', status: 'ACTIVE' },
],
});
renderWithProviders(<MemoryWorkspace />);
// Gmail row exists with a working Sync button.
// Provider-backed toolkits should render actionable Sync rows
expect(await screen.findByTestId('memory-source-sync-gmail')).toBeInTheDocument();
// Non-syncable toolkits are filtered out completely — neither
// the row nor the Sync button render. Cleaner than a "no sync
// yet" placeholder for an action the user can't take.
expect(screen.queryByTestId('memory-source-row-slack')).toBeNull();
expect(screen.queryByTestId('memory-source-row-notion')).toBeNull();
expect(screen.queryByTestId('memory-source-sync-slack')).toBeNull();
expect(screen.queryByTestId('memory-source-sync-notion')).toBeNull();
expect(screen.getByTestId('memory-source-sync-slack')).toBeInTheDocument();
expect(screen.getByTestId('memory-source-sync-notion')).toBeInTheDocument();
// Non-syncable toolkits stay hidden.
expect(screen.queryByTestId('memory-source-row-discord')).toBeNull();
expect(screen.queryByTestId('memory-source-sync-discord')).toBeNull();
});
it('toggling to Contacts mode re-fetches the graph with mode=contacts', async () => {
@@ -149,8 +149,8 @@ pub fn capability_matrix() -> Vec<ComposioCapability> {
///
/// This is consulted by the meta-tool layer alongside any registered
/// provider's [`ComposioProvider::curated_tools`]. It lets toolkits
/// without a full native provider (e.g. `github`, which has no sync
/// logic yet) still benefit from curated whitelisting.
/// without a full native provider still benefit from curated
/// whitelisting.
///
/// Lookup key is the lowercased prefix returned by
/// [`toolkit_from_slug`] applied to the action slug — e.g.