chore: ran linting

This commit is contained in:
Anish Sarkar 2026-03-22 00:43:53 +05:30
parent 44f59bfb61
commit 2bc6a0c3bc
24 changed files with 166 additions and 160 deletions

View file

@ -144,7 +144,7 @@ def create_create_gmail_draft_tool(
from app.db import SearchSourceConnector, SearchSourceConnectorType from app.db import SearchSourceConnector, SearchSourceConnectorType
_GMAIL_TYPES = [ _gmail_types = [
SearchSourceConnectorType.GOOGLE_GMAIL_CONNECTOR, SearchSourceConnectorType.GOOGLE_GMAIL_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GMAIL_CONNECTOR, SearchSourceConnectorType.COMPOSIO_GMAIL_CONNECTOR,
] ]
@ -155,7 +155,7 @@ def create_create_gmail_draft_tool(
SearchSourceConnector.id == final_connector_id, SearchSourceConnector.id == final_connector_id,
SearchSourceConnector.search_space_id == search_space_id, SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.user_id == user_id, SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_(_GMAIL_TYPES), SearchSourceConnector.connector_type.in_(_gmail_types),
) )
) )
connector = result.scalars().first() connector = result.scalars().first()
@ -170,7 +170,7 @@ def create_create_gmail_draft_tool(
select(SearchSourceConnector).filter( select(SearchSourceConnector).filter(
SearchSourceConnector.search_space_id == search_space_id, SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.user_id == user_id, SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_(_GMAIL_TYPES), SearchSourceConnector.connector_type.in_(_gmail_types),
) )
) )
connector = result.scalars().first() connector = result.scalars().first()

View file

@ -145,7 +145,7 @@ def create_send_gmail_email_tool(
from app.db import SearchSourceConnector, SearchSourceConnectorType from app.db import SearchSourceConnector, SearchSourceConnectorType
_GMAIL_TYPES = [ _gmail_types = [
SearchSourceConnectorType.GOOGLE_GMAIL_CONNECTOR, SearchSourceConnectorType.GOOGLE_GMAIL_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GMAIL_CONNECTOR, SearchSourceConnectorType.COMPOSIO_GMAIL_CONNECTOR,
] ]
@ -156,7 +156,7 @@ def create_send_gmail_email_tool(
SearchSourceConnector.id == final_connector_id, SearchSourceConnector.id == final_connector_id,
SearchSourceConnector.search_space_id == search_space_id, SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.user_id == user_id, SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_(_GMAIL_TYPES), SearchSourceConnector.connector_type.in_(_gmail_types),
) )
) )
connector = result.scalars().first() connector = result.scalars().first()
@ -171,7 +171,7 @@ def create_send_gmail_email_tool(
select(SearchSourceConnector).filter( select(SearchSourceConnector).filter(
SearchSourceConnector.search_space_id == search_space_id, SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.user_id == user_id, SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_(_GMAIL_TYPES), SearchSourceConnector.connector_type.in_(_gmail_types),
) )
) )
connector = result.scalars().first() connector = result.scalars().first()

View file

@ -162,7 +162,7 @@ def create_trash_gmail_email_tool(
from app.db import SearchSourceConnector, SearchSourceConnectorType from app.db import SearchSourceConnector, SearchSourceConnectorType
_GMAIL_TYPES = [ _gmail_types = [
SearchSourceConnectorType.GOOGLE_GMAIL_CONNECTOR, SearchSourceConnectorType.GOOGLE_GMAIL_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GMAIL_CONNECTOR, SearchSourceConnectorType.COMPOSIO_GMAIL_CONNECTOR,
] ]
@ -172,7 +172,7 @@ def create_trash_gmail_email_tool(
SearchSourceConnector.id == final_connector_id, SearchSourceConnector.id == final_connector_id,
SearchSourceConnector.search_space_id == search_space_id, SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.user_id == user_id, SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_(_GMAIL_TYPES), SearchSourceConnector.connector_type.in_(_gmail_types),
) )
) )
connector = result.scalars().first() connector = result.scalars().first()

View file

@ -192,7 +192,7 @@ def create_update_gmail_draft_tool(
from app.db import SearchSourceConnector, SearchSourceConnectorType from app.db import SearchSourceConnector, SearchSourceConnectorType
_GMAIL_TYPES = [ _gmail_types = [
SearchSourceConnectorType.GOOGLE_GMAIL_CONNECTOR, SearchSourceConnectorType.GOOGLE_GMAIL_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GMAIL_CONNECTOR, SearchSourceConnectorType.COMPOSIO_GMAIL_CONNECTOR,
] ]
@ -202,7 +202,7 @@ def create_update_gmail_draft_tool(
SearchSourceConnector.id == final_connector_id, SearchSourceConnector.id == final_connector_id,
SearchSourceConnector.search_space_id == search_space_id, SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.user_id == user_id, SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_(_GMAIL_TYPES), SearchSourceConnector.connector_type.in_(_gmail_types),
) )
) )
connector = result.scalars().first() connector = result.scalars().first()
@ -419,7 +419,9 @@ async def _find_draft_id_by_message(gmail_service: Any, message_id: str) -> str
response = await asyncio.get_event_loop().run_in_executor( response = await asyncio.get_event_loop().run_in_executor(
None, None,
lambda: gmail_service.users().drafts().list(**kwargs).execute(), lambda kwargs=kwargs: (
gmail_service.users().drafts().list(**kwargs).execute()
),
) )
for draft in response.get("drafts", []): for draft in response.get("drafts", []):

View file

@ -155,7 +155,7 @@ def create_create_calendar_event_tool(
from app.db import SearchSourceConnector, SearchSourceConnectorType from app.db import SearchSourceConnector, SearchSourceConnectorType
_CALENDAR_TYPES = [ _calendar_types = [
SearchSourceConnectorType.GOOGLE_CALENDAR_CONNECTOR, SearchSourceConnectorType.GOOGLE_CALENDAR_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GOOGLE_CALENDAR_CONNECTOR, SearchSourceConnectorType.COMPOSIO_GOOGLE_CALENDAR_CONNECTOR,
] ]
@ -166,7 +166,7 @@ def create_create_calendar_event_tool(
SearchSourceConnector.id == final_connector_id, SearchSourceConnector.id == final_connector_id,
SearchSourceConnector.search_space_id == search_space_id, SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.user_id == user_id, SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_(_CALENDAR_TYPES), SearchSourceConnector.connector_type.in_(_calendar_types),
) )
) )
connector = result.scalars().first() connector = result.scalars().first()
@ -181,7 +181,7 @@ def create_create_calendar_event_tool(
select(SearchSourceConnector).filter( select(SearchSourceConnector).filter(
SearchSourceConnector.search_space_id == search_space_id, SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.user_id == user_id, SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_(_CALENDAR_TYPES), SearchSourceConnector.connector_type.in_(_calendar_types),
) )
) )
connector = result.scalars().first() connector = result.scalars().first()

View file

@ -161,7 +161,7 @@ def create_delete_calendar_event_tool(
from app.db import SearchSourceConnector, SearchSourceConnectorType from app.db import SearchSourceConnector, SearchSourceConnectorType
_CALENDAR_TYPES = [ _calendar_types = [
SearchSourceConnectorType.GOOGLE_CALENDAR_CONNECTOR, SearchSourceConnectorType.GOOGLE_CALENDAR_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GOOGLE_CALENDAR_CONNECTOR, SearchSourceConnectorType.COMPOSIO_GOOGLE_CALENDAR_CONNECTOR,
] ]
@ -171,7 +171,7 @@ def create_delete_calendar_event_tool(
SearchSourceConnector.id == final_connector_id, SearchSourceConnector.id == final_connector_id,
SearchSourceConnector.search_space_id == search_space_id, SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.user_id == user_id, SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_(_CALENDAR_TYPES), SearchSourceConnector.connector_type.in_(_calendar_types),
) )
) )
connector = result.scalars().first() connector = result.scalars().first()

View file

@ -178,7 +178,7 @@ def create_update_calendar_event_tool(
from app.db import SearchSourceConnector, SearchSourceConnectorType from app.db import SearchSourceConnector, SearchSourceConnectorType
_CALENDAR_TYPES = [ _calendar_types = [
SearchSourceConnectorType.GOOGLE_CALENDAR_CONNECTOR, SearchSourceConnectorType.GOOGLE_CALENDAR_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GOOGLE_CALENDAR_CONNECTOR, SearchSourceConnectorType.COMPOSIO_GOOGLE_CALENDAR_CONNECTOR,
] ]
@ -188,7 +188,7 @@ def create_update_calendar_event_tool(
SearchSourceConnector.id == final_connector_id, SearchSourceConnector.id == final_connector_id,
SearchSourceConnector.search_space_id == search_space_id, SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.user_id == user_id, SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_(_CALENDAR_TYPES), SearchSourceConnector.connector_type.in_(_calendar_types),
) )
) )
connector = result.scalars().first() connector = result.scalars().first()

View file

@ -166,7 +166,7 @@ def create_create_google_drive_file_tool(
from app.db import SearchSourceConnector, SearchSourceConnectorType from app.db import SearchSourceConnector, SearchSourceConnectorType
_DRIVE_TYPES = [ _drive_types = [
SearchSourceConnectorType.GOOGLE_DRIVE_CONNECTOR, SearchSourceConnectorType.GOOGLE_DRIVE_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GOOGLE_DRIVE_CONNECTOR, SearchSourceConnectorType.COMPOSIO_GOOGLE_DRIVE_CONNECTOR,
] ]
@ -177,7 +177,7 @@ def create_create_google_drive_file_tool(
SearchSourceConnector.id == final_connector_id, SearchSourceConnector.id == final_connector_id,
SearchSourceConnector.search_space_id == search_space_id, SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.user_id == user_id, SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_(_DRIVE_TYPES), SearchSourceConnector.connector_type.in_(_drive_types),
) )
) )
connector = result.scalars().first() connector = result.scalars().first()
@ -192,7 +192,7 @@ def create_create_google_drive_file_tool(
select(SearchSourceConnector).filter( select(SearchSourceConnector).filter(
SearchSourceConnector.search_space_id == search_space_id, SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.user_id == user_id, SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_(_DRIVE_TYPES), SearchSourceConnector.connector_type.in_(_drive_types),
) )
) )
connector = result.scalars().first() connector = result.scalars().first()

View file

@ -162,7 +162,7 @@ def create_delete_google_drive_file_tool(
from app.db import SearchSourceConnector, SearchSourceConnectorType from app.db import SearchSourceConnector, SearchSourceConnectorType
_DRIVE_TYPES = [ _drive_types = [
SearchSourceConnectorType.GOOGLE_DRIVE_CONNECTOR, SearchSourceConnectorType.GOOGLE_DRIVE_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GOOGLE_DRIVE_CONNECTOR, SearchSourceConnectorType.COMPOSIO_GOOGLE_DRIVE_CONNECTOR,
] ]
@ -172,7 +172,7 @@ def create_delete_google_drive_file_tool(
SearchSourceConnector.id == final_connector_id, SearchSourceConnector.id == final_connector_id,
SearchSourceConnector.search_space_id == search_space_id, SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.user_id == user_id, SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_(_DRIVE_TYPES), SearchSourceConnector.connector_type.in_(_drive_types),
) )
) )
connector = result.scalars().first() connector = result.scalars().first()

View file

@ -9,6 +9,7 @@ This module provides:
""" """
import asyncio import asyncio
import contextlib
import json import json
import re import re
import time import time
@ -89,10 +90,8 @@ async def _browse_recent_documents(
doc_type_enums = [] doc_type_enums = []
for dt in type_list: for dt in type_list:
if isinstance(dt, str): if isinstance(dt, str):
try: with contextlib.suppress(KeyError):
doc_type_enums.append(DocumentType[dt]) doc_type_enums.append(DocumentType[dt])
except KeyError:
pass
else: else:
doc_type_enums.append(dt) doc_type_enums.append(dt)
if not doc_type_enums: if not doc_type_enums:

View file

@ -59,11 +59,12 @@ class GoogleCalendarConnector:
""" """
has_standard_refresh = bool(self._credentials.refresh_token) has_standard_refresh = bool(self._credentials.refresh_token)
if has_standard_refresh: if has_standard_refresh and not all(
if not all([self._credentials.client_id, self._credentials.client_secret]): [self._credentials.client_id, self._credentials.client_secret]
raise ValueError( ):
"Google OAuth credentials (client_id, client_secret) must be set" raise ValueError(
) "Google OAuth credentials (client_id, client_secret) must be set"
)
if self._credentials and not self._credentials.expired: if self._credentials and not self._credentials.expired:
return self._credentials return self._credentials

View file

@ -3,6 +3,7 @@
import io import io
from typing import Any from typing import Any
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build from googleapiclient.discovery import build
from googleapiclient.errors import HttpError from googleapiclient.errors import HttpError
from googleapiclient.http import MediaIoBaseUpload from googleapiclient.http import MediaIoBaseUpload

View file

@ -88,11 +88,12 @@ class GoogleGmailConnector:
""" """
has_standard_refresh = bool(self._credentials.refresh_token) has_standard_refresh = bool(self._credentials.refresh_token)
if has_standard_refresh: if has_standard_refresh and not all(
if not all([self._credentials.client_id, self._credentials.client_secret]): [self._credentials.client_id, self._credentials.client_secret]
raise ValueError( ):
"Google OAuth credentials (client_id, client_secret) must be set" raise ValueError(
) "Google OAuth credentials (client_id, client_secret) must be set"
)
if self._credentials and not self._credentials.expired: if self._credentials and not self._credentials.expired:
return self._credentials return self._credentials

View file

@ -1,4 +1,5 @@
import asyncio import asyncio
import contextlib
import time import time
from datetime import datetime from datetime import datetime
@ -225,10 +226,8 @@ class ChucksHybridSearchRetriever:
doc_type_enums = [] doc_type_enums = []
for dt in type_list: for dt in type_list:
if isinstance(dt, str): if isinstance(dt, str):
try: with contextlib.suppress(KeyError):
doc_type_enums.append(DocumentType[dt]) doc_type_enums.append(DocumentType[dt])
except KeyError:
pass
else: else:
doc_type_enums.append(dt) doc_type_enums.append(dt)
if not doc_type_enums: if not doc_type_enums:

View file

@ -1,3 +1,4 @@
import contextlib
import time import time
from datetime import datetime from datetime import datetime
@ -205,10 +206,8 @@ class DocumentHybridSearchRetriever:
doc_type_enums = [] doc_type_enums = []
for dt in type_list: for dt in type_list:
if isinstance(dt, str): if isinstance(dt, str):
try: with contextlib.suppress(KeyError):
doc_type_enums.append(DocumentType[dt]) doc_type_enums.append(DocumentType[dt])
except KeyError:
pass
else: else:
doc_type_enums.append(dt) doc_type_enums.append(dt)
if not doc_type_enums: if not doc_type_enums:

View file

@ -225,7 +225,9 @@ class GmailToolMetadataService:
service = build("gmail", "v1", credentials=creds) service = build("gmail", "v1", credentials=creds)
profile = await asyncio.get_event_loop().run_in_executor( profile = await asyncio.get_event_loop().run_in_executor(
None, None,
lambda: service.users().getProfile(userId="me").execute(), lambda service=service: (
service.users().getProfile(userId="me").execute()
),
) )
acc_dict["email"] = profile.get("emailAddress", "") acc_dict["email"] = profile.get("emailAddress", "")
except Exception: except Exception:
@ -334,7 +336,9 @@ class GmailToolMetadataService:
kwargs["pageToken"] = page_token kwargs["pageToken"] = page_token
response = await asyncio.get_event_loop().run_in_executor( response = await asyncio.get_event_loop().run_in_executor(
None, None,
lambda: service.users().drafts().list(**kwargs).execute(), lambda kwargs=kwargs: (
service.users().drafts().list(**kwargs).execute()
),
) )
for draft in response.get("drafts", []): for draft in response.get("drafts", []):
if draft.get("message", {}).get("id") == message_id: if draft.get("message", {}).get("id") == message_id:

View file

@ -16,15 +16,6 @@ from sqlalchemy.ext.asyncio import AsyncSession
from app.connectors.google_calendar_connector import GoogleCalendarConnector from app.connectors.google_calendar_connector import GoogleCalendarConnector
from app.db import Document, DocumentStatus, DocumentType, SearchSourceConnectorType from app.db import Document, DocumentStatus, DocumentType, SearchSourceConnectorType
from app.utils.google_credentials import (
COMPOSIO_GOOGLE_CONNECTOR_TYPES,
build_composio_credentials,
)
ACCEPTED_CALENDAR_CONNECTOR_TYPES = {
SearchSourceConnectorType.GOOGLE_CALENDAR_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GOOGLE_CALENDAR_CONNECTOR,
}
from app.services.llm_service import get_user_long_context_llm from app.services.llm_service import get_user_long_context_llm
from app.services.task_logging_service import TaskLoggingService from app.services.task_logging_service import TaskLoggingService
from app.utils.document_converters import ( from app.utils.document_converters import (
@ -34,6 +25,10 @@ from app.utils.document_converters import (
generate_document_summary, generate_document_summary,
generate_unique_identifier_hash, generate_unique_identifier_hash,
) )
from app.utils.google_credentials import (
COMPOSIO_GOOGLE_CONNECTOR_TYPES,
build_composio_credentials,
)
from .base import ( from .base import (
check_document_by_unique_identifier, check_document_by_unique_identifier,
@ -46,6 +41,11 @@ from .base import (
update_connector_last_indexed, update_connector_last_indexed,
) )
ACCEPTED_CALENDAR_CONNECTOR_TYPES = {
SearchSourceConnectorType.GOOGLE_CALENDAR_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GOOGLE_CALENDAR_CONNECTOR,
}
# Type hint for heartbeat callback # Type hint for heartbeat callback
HeartbeatCallbackType = Callable[[int], Awaitable[None]] HeartbeatCallbackType = Callable[[int], Awaitable[None]]

View file

@ -21,15 +21,6 @@ from app.db import (
DocumentType, DocumentType,
SearchSourceConnectorType, SearchSourceConnectorType,
) )
from app.utils.google_credentials import (
COMPOSIO_GOOGLE_CONNECTOR_TYPES,
build_composio_credentials,
)
ACCEPTED_GMAIL_CONNECTOR_TYPES = {
SearchSourceConnectorType.GOOGLE_GMAIL_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GMAIL_CONNECTOR,
}
from app.services.llm_service import get_user_long_context_llm from app.services.llm_service import get_user_long_context_llm
from app.services.task_logging_service import TaskLoggingService from app.services.task_logging_service import TaskLoggingService
from app.utils.document_converters import ( from app.utils.document_converters import (
@ -39,6 +30,10 @@ from app.utils.document_converters import (
generate_document_summary, generate_document_summary,
generate_unique_identifier_hash, generate_unique_identifier_hash,
) )
from app.utils.google_credentials import (
COMPOSIO_GOOGLE_CONNECTOR_TYPES,
build_composio_credentials,
)
from .base import ( from .base import (
calculate_date_range, calculate_date_range,
@ -51,6 +46,11 @@ from .base import (
update_connector_last_indexed, update_connector_last_indexed,
) )
ACCEPTED_GMAIL_CONNECTOR_TYPES = {
SearchSourceConnectorType.GOOGLE_GMAIL_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GMAIL_CONNECTOR,
}
# Type hint for heartbeat callback # Type hint for heartbeat callback
HeartbeatCallbackType = Callable[[int], Awaitable[None]] HeartbeatCallbackType = Callable[[int], Awaitable[None]]

View file

@ -23,7 +23,7 @@ async def test_search_google_drive_includes_legacy_composio_docs(
async with patched_session_factory() as session: async with patched_session_factory() as session:
service = ConnectorService(session, search_space_id=space_id) service = ConnectorService(session, search_space_id=space_id)
result_object, raw_docs = await service.search_google_drive( _, raw_docs = await service.search_google_drive(
user_query="quarterly budget", user_query="quarterly budget",
search_space_id=space_id, search_space_id=space_id,
top_k=10, top_k=10,
@ -55,7 +55,7 @@ async def test_search_files_does_not_include_google_types(
async with patched_session_factory() as session: async with patched_session_factory() as session:
service = ConnectorService(session, search_space_id=space_id) service = ConnectorService(session, search_space_id=space_id)
result_object, raw_docs = await service.search_files( _, raw_docs = await service.search_files(
user_query="quarterly budget", user_query="quarterly budget",
search_space_id=space_id, search_space_id=space_id,
top_k=10, top_k=10,

View file

@ -15,11 +15,11 @@ pytestmark = pytest.mark.unit
@patch("app.services.composio_service.ComposioService") @patch("app.services.composio_service.ComposioService")
def test_returns_credentials_with_token_and_expiry(MockComposioService): def test_returns_credentials_with_token_and_expiry(mock_composio_service):
"""build_composio_credentials returns a Credentials object with the Composio access token.""" """build_composio_credentials returns a Credentials object with the Composio access token."""
mock_service = MagicMock() mock_service = MagicMock()
mock_service.get_access_token.return_value = "fake-access-token" mock_service.get_access_token.return_value = "fake-access-token"
MockComposioService.return_value = mock_service mock_composio_service.return_value = mock_service
from app.utils.google_credentials import build_composio_credentials from app.utils.google_credentials import build_composio_credentials
@ -32,14 +32,14 @@ def test_returns_credentials_with_token_and_expiry(MockComposioService):
@patch("app.services.composio_service.ComposioService") @patch("app.services.composio_service.ComposioService")
def test_refresh_handler_fetches_fresh_token(MockComposioService): def test_refresh_handler_fetches_fresh_token(mock_composio_service):
"""The refresh_handler on the returned Credentials fetches a new token from Composio.""" """The refresh_handler on the returned Credentials fetches a new token from Composio."""
mock_service = MagicMock() mock_service = MagicMock()
mock_service.get_access_token.side_effect = [ mock_service.get_access_token.side_effect = [
"initial-token", "initial-token",
"refreshed-token", "refreshed-token",
] ]
MockComposioService.return_value = mock_service mock_composio_service.return_value = mock_service
from app.utils.google_credentials import build_composio_credentials from app.utils.google_credentials import build_composio_credentials

View file

@ -208,7 +208,7 @@ async def test_drive_client_uses_prebuilt_composio_credentials(mock_build):
credentials=creds, credentials=creds,
) )
files, next_token, error = await client.list_files() files, _next_token, error = await client.list_files()
assert error is None assert error is None
assert files == [] assert files == []

View file

@ -204,8 +204,8 @@ export function LayoutShell({
onChatArchive={onChatArchive} onChatArchive={onChatArchive}
onViewAllSharedChats={onViewAllSharedChats} onViewAllSharedChats={onViewAllSharedChats}
onViewAllPrivateChats={onViewAllPrivateChats} onViewAllPrivateChats={onViewAllPrivateChats}
isSharedChatsPanelOpen={activeSlideoutPanel === "shared"} isSharedChatsPanelOpen={activeSlideoutPanel === "shared"}
isPrivateChatsPanelOpen={activeSlideoutPanel === "private"} isPrivateChatsPanelOpen={activeSlideoutPanel === "private"}
user={user} user={user}
onSettings={onSettings} onSettings={onSettings}
onManageMembers={onManageMembers} onManageMembers={onManageMembers}
@ -217,92 +217,92 @@ export function LayoutShell({
isLoadingChats={isLoadingChats} isLoadingChats={isLoadingChats}
/> />
<main className={cn("flex-1", isChatPage ? "overflow-hidden" : "overflow-auto")}> <main className={cn("flex-1", isChatPage ? "overflow-hidden" : "overflow-auto")}>
{children} {children}
</main> </main>
{/* Mobile unified slide-out panel */} {/* Mobile unified slide-out panel */}
<SidebarSlideOutPanel <SidebarSlideOutPanel
open={anySlideOutOpen} open={anySlideOutOpen}
onOpenChange={closeSlideout} onOpenChange={closeSlideout}
ariaLabel={panelAriaLabel} ariaLabel={panelAriaLabel}
> >
<AnimatePresence mode="popLayout" initial={false}> <AnimatePresence mode="popLayout" initial={false}>
{activeSlideoutPanel === "inbox" && inbox && ( {activeSlideoutPanel === "inbox" && inbox && (
<motion.div <motion.div
key="inbox" key="inbox"
className="h-full flex flex-col" className="h-full flex flex-col"
initial={{ opacity: 0 }} initial={{ opacity: 0 }}
animate={{ opacity: 1 }} animate={{ opacity: 1 }}
exit={{ opacity: 0 }} exit={{ opacity: 0 }}
transition={{ duration: 0.15 }} transition={{ duration: 0.15 }}
> >
<InboxSidebarContent <InboxSidebarContent
onOpenChange={(open) => closeSlideout(open)} onOpenChange={(open) => closeSlideout(open)}
comments={inbox.comments} comments={inbox.comments}
status={inbox.status} status={inbox.status}
totalUnreadCount={inbox.totalUnreadCount} totalUnreadCount={inbox.totalUnreadCount}
onCloseMobileSidebar={() => setMobileMenuOpen(false)} onCloseMobileSidebar={() => setMobileMenuOpen(false)}
/> />
</motion.div> </motion.div>
)} )}
{activeSlideoutPanel === "announcements" && ( {activeSlideoutPanel === "announcements" && (
<motion.div <motion.div
key="announcements" key="announcements"
className="h-full flex flex-col" className="h-full flex flex-col"
initial={{ opacity: 0 }} initial={{ opacity: 0 }}
animate={{ opacity: 1 }} animate={{ opacity: 1 }}
exit={{ opacity: 0 }} exit={{ opacity: 0 }}
transition={{ duration: 0.15 }} transition={{ duration: 0.15 }}
> >
<AnnouncementsSidebarContent <AnnouncementsSidebarContent
onOpenChange={(open) => closeSlideout(open)} onOpenChange={(open) => closeSlideout(open)}
onCloseMobileSidebar={() => setMobileMenuOpen(false)} onCloseMobileSidebar={() => setMobileMenuOpen(false)}
/> />
</motion.div> </motion.div>
)} )}
{activeSlideoutPanel === "shared" && allSharedChatsPanel && ( {activeSlideoutPanel === "shared" && allSharedChatsPanel && (
<motion.div <motion.div
key="shared" key="shared"
className="h-full flex flex-col" className="h-full flex flex-col"
initial={{ opacity: 0 }} initial={{ opacity: 0 }}
animate={{ opacity: 1 }} animate={{ opacity: 1 }}
exit={{ opacity: 0 }} exit={{ opacity: 0 }}
transition={{ duration: 0.15 }} transition={{ duration: 0.15 }}
> >
<AllSharedChatsSidebarContent <AllSharedChatsSidebarContent
onOpenChange={(open) => closeSlideout(open)} onOpenChange={(open) => closeSlideout(open)}
searchSpaceId={allSharedChatsPanel.searchSpaceId} searchSpaceId={allSharedChatsPanel.searchSpaceId}
onCloseMobileSidebar={() => setMobileMenuOpen(false)} onCloseMobileSidebar={() => setMobileMenuOpen(false)}
/> />
</motion.div> </motion.div>
)} )}
{activeSlideoutPanel === "private" && allPrivateChatsPanel && ( {activeSlideoutPanel === "private" && allPrivateChatsPanel && (
<motion.div <motion.div
key="private" key="private"
className="h-full flex flex-col" className="h-full flex flex-col"
initial={{ opacity: 0 }} initial={{ opacity: 0 }}
animate={{ opacity: 1 }} animate={{ opacity: 1 }}
exit={{ opacity: 0 }} exit={{ opacity: 0 }}
transition={{ duration: 0.15 }} transition={{ duration: 0.15 }}
> >
<AllPrivateChatsSidebarContent <AllPrivateChatsSidebarContent
onOpenChange={(open) => closeSlideout(open)} onOpenChange={(open) => closeSlideout(open)}
searchSpaceId={allPrivateChatsPanel.searchSpaceId} searchSpaceId={allPrivateChatsPanel.searchSpaceId}
onCloseMobileSidebar={() => setMobileMenuOpen(false)} onCloseMobileSidebar={() => setMobileMenuOpen(false)}
/> />
</motion.div> </motion.div>
)} )}
</AnimatePresence> </AnimatePresence>
</SidebarSlideOutPanel> </SidebarSlideOutPanel>
{/* Mobile Documents Sidebar - separate (not part of slide-out group) */} {/* Mobile Documents Sidebar - separate (not part of slide-out group) */}
{documentsPanel && ( {documentsPanel && (
<DocumentsSidebar <DocumentsSidebar
open={documentsPanel.open} open={documentsPanel.open}
onOpenChange={documentsPanel.onOpenChange} onOpenChange={documentsPanel.onOpenChange}
/> />
)} )}
</div> </div>
</TooltipProvider> </TooltipProvider>
</SidebarProvider> </SidebarProvider>
@ -402,9 +402,7 @@ export function LayoutShell({
exit={{ opacity: 0 }} exit={{ opacity: 0 }}
transition={{ duration: 0.15 }} transition={{ duration: 0.15 }}
> >
<AnnouncementsSidebarContent <AnnouncementsSidebarContent onOpenChange={(open) => closeSlideout(open)} />
onOpenChange={(open) => closeSlideout(open)}
/>
</motion.div> </motion.div>
)} )}
{activeSlideoutPanel === "shared" && allSharedChatsPanel && ( {activeSlideoutPanel === "shared" && allSharedChatsPanel && (

View file

@ -24,6 +24,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { getDocumentTypeLabel } from "@/app/dashboard/[search_space_id]/documents/(manage)/components/DocumentTypeIcon"; import { getDocumentTypeLabel } from "@/app/dashboard/[search_space_id]/documents/(manage)/components/DocumentTypeIcon";
import { setTargetCommentIdAtom } from "@/atoms/chat/current-thread.atom"; import { setTargetCommentIdAtom } from "@/atoms/chat/current-thread.atom";
import { convertRenderedToDisplay } from "@/components/chat-comments/comment-item/comment-item"; import { convertRenderedToDisplay } from "@/components/chat-comments/comment-item/comment-item";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/animated-tabs";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
@ -43,7 +44,6 @@ import {
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
import { Spinner } from "@/components/ui/spinner"; import { Spinner } from "@/components/ui/spinner";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/animated-tabs";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { getConnectorIcon } from "@/contracts/enums/connectorIcons"; import { getConnectorIcon } from "@/contracts/enums/connectorIcons";
import { import {

View file

@ -88,7 +88,9 @@ function HeroCarouselCard({
return ( return (
<> <>
<div className="overflow-hidden rounded-2xl border border-neutral-200/60 bg-white shadow-xl sm:rounded-3xl dark:border-neutral-700/60 dark:bg-neutral-900"> <div className="flex items-center gap-3 border-b border-neutral-200/60 px-4 py-3 sm:px-6 sm:py-4 dark:border-neutral-700/60"> <div className="overflow-hidden rounded-2xl border border-neutral-200/60 bg-white shadow-xl sm:rounded-3xl dark:border-neutral-700/60 dark:bg-neutral-900">
{" "}
<div className="flex items-center gap-3 border-b border-neutral-200/60 px-4 py-3 sm:px-6 sm:py-4 dark:border-neutral-700/60">
<div className="min-w-0"> <div className="min-w-0">
<h3 className="truncate text-base font-semibold text-neutral-900 sm:text-xl dark:text-white"> <h3 className="truncate text-base font-semibold text-neutral-900 sm:text-xl dark:text-white">
{title} {title}