chore: ran linting

This commit is contained in:
Anish Sarkar 2026-03-21 13:20:13 +05:30
parent 772150eb66
commit de8841fb86
110 changed files with 2673 additions and 1918 deletions

View file

@ -283,9 +283,7 @@ class ComposioService:
timeout=timeout,
)
status = getattr(account, "status", "UNKNOWN")
logger.info(
f"Composio account {connected_account_id} is now {status}"
)
logger.info(f"Composio account {connected_account_id} is now {status}")
return status
except Exception as e:
logger.error(

View file

@ -67,7 +67,10 @@ class ConfluenceKBSyncService:
content_hash = unique_hash
user_llm = await get_user_long_context_llm(
self.db_session, user_id, search_space_id, disable_streaming=True,
self.db_session,
user_id,
search_space_id,
disable_streaming=True,
)
doc_metadata_for_summary = {
@ -116,17 +119,26 @@ class ConfluenceKBSyncService:
logger.info(
"KB sync after create succeeded: doc_id=%s, page=%s",
document.id, page_title,
document.id,
page_title,
)
return {"status": "success"}
except Exception as e:
error_str = str(e).lower()
if "duplicate key value violates unique constraint" in error_str or "uniqueviolationerror" in error_str:
if (
"duplicate key value violates unique constraint" in error_str
or "uniqueviolationerror" in error_str
):
await self.db_session.rollback()
return {"status": "error", "message": "Duplicate document detected"}
logger.error("KB sync after create failed for page %s: %s", page_title, e, exc_info=True)
logger.error(
"KB sync after create failed for page %s: %s",
page_title,
e,
exc_info=True,
)
await self.db_session.rollback()
return {"status": "error", "message": str(e)}
@ -215,11 +227,14 @@ class ConfluenceKBSyncService:
logger.info(
"KB sync successful for document %s (%s)",
document_id, page_title,
document_id,
page_title,
)
return {"status": "success"}
except Exception as e:
logger.error("KB sync failed for document %s: %s", document_id, e, exc_info=True)
logger.error(
"KB sync failed for document %s: %s", document_id, e, exc_info=True
)
await self.db_session.rollback()
return {"status": "error", "message": str(e)}

View file

@ -83,7 +83,7 @@ class ConfluenceToolMetadataService:
async def _check_account_health(self, connector: SearchSourceConnector) -> bool:
"""Check if the Confluence connector auth is still valid.
Returns True if auth is expired/invalid, False if healthy.
"""
try:
@ -112,7 +112,7 @@ class ConfluenceToolMetadataService:
async def get_creation_context(self, search_space_id: int, user_id: str) -> dict:
"""Return context needed to create a new Confluence page.
Fetches all connected accounts, and for the first healthy one fetches spaces.
"""
connectors = await self._get_all_confluence_connectors(search_space_id, user_id)
@ -126,10 +126,12 @@ class ConfluenceToolMetadataService:
for connector in connectors:
auth_expired = await self._check_account_health(connector)
workspace = ConfluenceWorkspace.from_connector(connector)
accounts.append({
**workspace.to_dict(),
"auth_expired": auth_expired,
})
accounts.append(
{
**workspace.to_dict(),
"auth_expired": auth_expired,
}
)
if not auth_expired and not fetched_context:
try:
@ -146,7 +148,8 @@ class ConfluenceToolMetadataService:
except Exception as e:
logger.warning(
"Failed to fetch Confluence spaces for connector %s: %s",
connector.id, e,
connector.id,
e,
)
return {
@ -158,7 +161,7 @@ class ConfluenceToolMetadataService:
self, search_space_id: int, user_id: str, page_ref: str
) -> dict:
"""Return context needed to update an indexed Confluence page.
Resolves the page from KB, then fetches current content and version from API.
"""
document = await self._resolve_page(search_space_id, user_id, page_ref)
@ -191,7 +194,11 @@ class ConfluenceToolMetadataService:
await client.close()
except Exception as e:
error_str = str(e).lower()
if "401" in error_str or "403" in error_str or "authentication" in error_str:
if (
"401" in error_str
or "403" in error_str
or "authentication" in error_str
):
return {
"error": f"Failed to fetch Confluence page: {e!s}",
"auth_expired": True,
@ -207,7 +214,9 @@ class ConfluenceToolMetadataService:
body_storage = storage.get("value", "")
version_obj = page_data.get("version", {})
version_number = version_obj.get("number", 1) if isinstance(version_obj, dict) else 1
version_number = (
version_obj.get("number", 1) if isinstance(version_obj, dict) else 1
)
return {
"account": {**workspace.to_dict(), "auth_expired": False},
@ -263,9 +272,7 @@ class ConfluenceToolMetadataService:
Document.document_type == DocumentType.CONFLUENCE_CONNECTOR,
SearchSourceConnector.user_id == user_id,
or_(
func.lower(
Document.document_metadata.op("->>")("page_title")
)
func.lower(Document.document_metadata.op("->>")("page_title"))
== ref_lower,
func.lower(Document.title) == ref_lower,
),

View file

@ -183,10 +183,12 @@ class GmailToolMetadataService:
and_(
SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_([
SearchSourceConnectorType.GOOGLE_GMAIL_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GMAIL_CONNECTOR,
]),
SearchSourceConnector.connector_type.in_(
[
SearchSourceConnectorType.GOOGLE_GMAIL_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GMAIL_CONNECTOR,
]
),
)
)
.order_by(SearchSourceConnector.last_indexed_at.desc())
@ -223,9 +225,7 @@ class GmailToolMetadataService:
service = build("gmail", "v1", credentials=creds)
profile = await asyncio.get_event_loop().run_in_executor(
None,
lambda: service.users()
.getProfile(userId="me")
.execute(),
lambda: service.users().getProfile(userId="me").execute(),
)
acc_dict["email"] = profile.get("emailAddress", "")
except Exception:
@ -306,10 +306,12 @@ class GmailToolMetadataService:
draft = await asyncio.get_event_loop().run_in_executor(
None,
lambda: service.users()
.drafts()
.get(userId="me", id=draft_id, format="full")
.execute(),
lambda: (
service.users()
.drafts()
.get(userId="me", id=draft_id, format="full")
.execute()
),
)
payload = draft.get("message", {}).get("payload", {})
@ -422,15 +424,15 @@ class GmailToolMetadataService:
.filter(
and_(
Document.search_space_id == search_space_id,
Document.document_type.in_([
DocumentType.GOOGLE_GMAIL_CONNECTOR,
DocumentType.COMPOSIO_GMAIL_CONNECTOR,
]),
Document.document_type.in_(
[
DocumentType.GOOGLE_GMAIL_CONNECTOR,
DocumentType.COMPOSIO_GMAIL_CONNECTOR,
]
),
SearchSourceConnector.user_id == user_id,
or_(
func.lower(
cast(Document.document_metadata["subject"], String)
)
func.lower(cast(Document.document_metadata["subject"], String))
== func.lower(email_ref),
func.lower(Document.title) == func.lower(email_ref),
),

View file

@ -8,7 +8,12 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from sqlalchemy.orm.attributes import flag_modified
from app.db import Document, DocumentType, SearchSourceConnector, SearchSourceConnectorType
from app.db import (
Document,
DocumentType,
SearchSourceConnector,
SearchSourceConnectorType,
)
from app.services.llm_service import get_user_long_context_llm
from app.utils.document_converters import (
create_document_chunks,
@ -107,7 +112,9 @@ class GoogleCalendarKBSyncService:
)
else:
logger.warning("No LLM configured -- using fallback summary")
summary_content = f"Google Calendar Event: {event_summary}\n\n{indexable_content}"
summary_content = (
f"Google Calendar Event: {event_summary}\n\n{indexable_content}"
)
summary_embedding = embed_text(summary_content)
chunks = await create_document_chunks(indexable_content)
@ -201,12 +208,16 @@ class GoogleCalendarKBSyncService:
None, lambda: build("calendar", "v3", credentials=creds)
)
calendar_id = (document.document_metadata or {}).get("calendar_id", "primary")
calendar_id = (document.document_metadata or {}).get(
"calendar_id", "primary"
)
live_event = await loop.run_in_executor(
None,
lambda: service.events()
.get(calendarId=calendar_id, eventId=event_id)
.execute(),
lambda: (
service.events()
.get(calendarId=calendar_id, eventId=event_id)
.execute()
),
)
event_summary = live_event.get("summary", "")
@ -220,7 +231,10 @@ class GoogleCalendarKBSyncService:
end_time = end_data.get("dateTime", end_data.get("date", ""))
attendees = [
{"email": a.get("email", ""), "responseStatus": a.get("responseStatus", "")}
{
"email": a.get("email", ""),
"responseStatus": a.get("responseStatus", ""),
}
for a in live_event.get("attendees", [])
]
@ -252,7 +266,9 @@ class GoogleCalendarKBSyncService:
indexable_content, user_llm, doc_metadata_for_summary
)
else:
summary_content = f"Google Calendar Event: {event_summary}\n\n{indexable_content}"
summary_content = (
f"Google Calendar Event: {event_summary}\n\n{indexable_content}"
)
summary_embedding = embed_text(summary_content)
chunks = await create_document_chunks(indexable_content)
@ -313,7 +329,10 @@ class GoogleCalendarKBSyncService:
if not connector:
raise ValueError(f"Connector {connector_id} not found")
if connector.connector_type == SearchSourceConnectorType.COMPOSIO_GOOGLE_CALENDAR_CONNECTOR:
if (
connector.connector_type
== SearchSourceConnectorType.COMPOSIO_GOOGLE_CALENDAR_CONNECTOR
):
cca_id = connector.config.get("composio_connected_account_id")
if cca_id:
return build_composio_credentials(cca_id)
@ -328,11 +347,17 @@ class GoogleCalendarKBSyncService:
if token_encrypted and app_config.SECRET_KEY:
token_encryption = TokenEncryption(app_config.SECRET_KEY)
if config_data.get("token"):
config_data["token"] = token_encryption.decrypt_token(config_data["token"])
config_data["token"] = token_encryption.decrypt_token(
config_data["token"]
)
if config_data.get("refresh_token"):
config_data["refresh_token"] = token_encryption.decrypt_token(config_data["refresh_token"])
config_data["refresh_token"] = token_encryption.decrypt_token(
config_data["refresh_token"]
)
if config_data.get("client_secret"):
config_data["client_secret"] = token_encryption.decrypt_token(config_data["client_secret"])
config_data["client_secret"] = token_encryption.decrypt_token(
config_data["client_secret"]
)
exp = config_data.get("expiry", "")
if exp:

View file

@ -37,7 +37,9 @@ class GoogleCalendarAccount:
name: str
@classmethod
def from_connector(cls, connector: SearchSourceConnector) -> "GoogleCalendarAccount":
def from_connector(
cls, connector: SearchSourceConnector
) -> "GoogleCalendarAccount":
return cls(id=connector.id, name=connector.name)
def to_dict(self) -> dict:
@ -93,7 +95,10 @@ class GoogleCalendarToolMetadataService:
self._db_session = db_session
async def _build_credentials(self, connector: SearchSourceConnector) -> Credentials:
if connector.connector_type == SearchSourceConnectorType.COMPOSIO_GOOGLE_CALENDAR_CONNECTOR:
if (
connector.connector_type
== SearchSourceConnectorType.COMPOSIO_GOOGLE_CALENDAR_CONNECTOR
):
cca_id = connector.config.get("composio_connected_account_id")
if cca_id:
return build_composio_credentials(cca_id)
@ -108,11 +113,17 @@ class GoogleCalendarToolMetadataService:
if token_encrypted and app_config.SECRET_KEY:
token_encryption = TokenEncryption(app_config.SECRET_KEY)
if config_data.get("token"):
config_data["token"] = token_encryption.decrypt_token(config_data["token"])
config_data["token"] = token_encryption.decrypt_token(
config_data["token"]
)
if config_data.get("refresh_token"):
config_data["refresh_token"] = token_encryption.decrypt_token(config_data["refresh_token"])
config_data["refresh_token"] = token_encryption.decrypt_token(
config_data["refresh_token"]
)
if config_data.get("client_secret"):
config_data["client_secret"] = token_encryption.decrypt_token(config_data["client_secret"])
config_data["client_secret"] = token_encryption.decrypt_token(
config_data["client_secret"]
)
exp = config_data.get("expiry", "")
if exp:
@ -149,10 +160,12 @@ class GoogleCalendarToolMetadataService:
loop = asyncio.get_event_loop()
await loop.run_in_executor(
None,
lambda: build("calendar", "v3", credentials=creds)
.calendarList()
.list(maxResults=1)
.execute(),
lambda: (
build("calendar", "v3", credentials=creds)
.calendarList()
.list(maxResults=1)
.execute()
),
)
return False
except Exception as e:
@ -252,11 +265,13 @@ class GoogleCalendarToolMetadataService:
None, lambda: service.calendarList().list().execute()
)
for cal in cal_list.get("items", []):
calendars.append({
"id": cal.get("id", ""),
"summary": cal.get("summary", ""),
"primary": cal.get("primary", False),
})
calendars.append(
{
"id": cal.get("id", ""),
"summary": cal.get("summary", ""),
"primary": cal.get("primary", False),
}
)
tz_setting = await loop.run_in_executor(
None,
@ -314,23 +329,34 @@ class GoogleCalendarToolMetadataService:
calendar_id = event.calendar_id or "primary"
live_event = await loop.run_in_executor(
None,
lambda: service.events()
.get(calendarId=calendar_id, eventId=event.event_id)
.execute(),
lambda: (
service.events()
.get(calendarId=calendar_id, eventId=event.event_id)
.execute()
),
)
event_dict["summary"] = live_event.get("summary", event_dict["summary"])
event_dict["description"] = live_event.get("description", event_dict["description"])
event_dict["description"] = live_event.get(
"description", event_dict["description"]
)
event_dict["location"] = live_event.get("location", event_dict["location"])
start_data = live_event.get("start", {})
event_dict["start"] = start_data.get("dateTime", start_data.get("date", event_dict["start"]))
event_dict["start"] = start_data.get(
"dateTime", start_data.get("date", event_dict["start"])
)
end_data = live_event.get("end", {})
event_dict["end"] = end_data.get("dateTime", end_data.get("date", event_dict["end"]))
event_dict["end"] = end_data.get(
"dateTime", end_data.get("date", event_dict["end"])
)
event_dict["attendees"] = [
{"email": a.get("email", ""), "responseStatus": a.get("responseStatus", "")}
{
"email": a.get("email", ""),
"responseStatus": a.get("responseStatus", ""),
}
for a in live_event.get("attendees", [])
]
except Exception:

View file

@ -56,7 +56,9 @@ class GoogleDriveKBSyncService:
indexable_content = (content or "").strip()
if not indexable_content:
indexable_content = f"Google Drive file: {file_name} (type: {mime_type})"
indexable_content = (
f"Google Drive file: {file_name} (type: {mime_type})"
)
content_hash = generate_content_hash(indexable_content, search_space_id)
@ -93,7 +95,9 @@ class GoogleDriveKBSyncService:
)
else:
logger.warning("No LLM configured — using fallback summary")
summary_content = f"Google Drive File: {file_name}\n\n{indexable_content}"
summary_content = (
f"Google Drive File: {file_name}\n\n{indexable_content}"
)
summary_embedding = embed_text(summary_content)
chunks = await create_document_chunks(indexable_content)

View file

@ -133,10 +133,12 @@ class GoogleDriveToolMetadataService:
and_(
SearchSourceConnector.id == document.connector_id,
SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_([
SearchSourceConnectorType.GOOGLE_DRIVE_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GOOGLE_DRIVE_CONNECTOR,
]),
SearchSourceConnector.connector_type.in_(
[
SearchSourceConnectorType.GOOGLE_DRIVE_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GOOGLE_DRIVE_CONNECTOR,
]
),
)
)
)
@ -168,10 +170,12 @@ class GoogleDriveToolMetadataService:
and_(
SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.user_id == user_id,
SearchSourceConnector.connector_type.in_([
SearchSourceConnectorType.GOOGLE_DRIVE_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GOOGLE_DRIVE_CONNECTOR,
]),
SearchSourceConnector.connector_type.in_(
[
SearchSourceConnectorType.GOOGLE_DRIVE_CONNECTOR,
SearchSourceConnectorType.COMPOSIO_GOOGLE_DRIVE_CONNECTOR,
]
),
)
)
.order_by(SearchSourceConnector.last_indexed_at.desc())

View file

@ -53,7 +53,8 @@ class JiraKBSyncService:
if existing:
logger.info(
"Document for Jira issue %s already exists (doc_id=%s), skipping",
issue_identifier, existing.id,
issue_identifier,
existing.id,
)
return {"status": "success"}
@ -61,7 +62,9 @@ class JiraKBSyncService:
if not indexable_content:
indexable_content = f"Jira Issue {issue_identifier}: {issue_title}"
issue_content = f"# {issue_identifier}: {issue_title}\n\n{indexable_content}"
issue_content = (
f"# {issue_identifier}: {issue_title}\n\n{indexable_content}"
)
content_hash = generate_content_hash(issue_content, search_space_id)
@ -73,7 +76,10 @@ class JiraKBSyncService:
content_hash = unique_hash
user_llm = await get_user_long_context_llm(
self.db_session, user_id, search_space_id, disable_streaming=True,
self.db_session,
user_id,
search_space_id,
disable_streaming=True,
)
doc_metadata_for_summary = {
@ -88,7 +94,9 @@ class JiraKBSyncService:
issue_content, user_llm, doc_metadata_for_summary
)
else:
summary_content = f"Jira Issue {issue_identifier}: {issue_title}\n\n{issue_content}"
summary_content = (
f"Jira Issue {issue_identifier}: {issue_title}\n\n{issue_content}"
)
summary_embedding = embed_text(summary_content)
chunks = await create_document_chunks(issue_content)
@ -122,17 +130,26 @@ class JiraKBSyncService:
logger.info(
"KB sync after create succeeded: doc_id=%s, issue=%s",
document.id, issue_identifier,
document.id,
issue_identifier,
)
return {"status": "success"}
except Exception as e:
error_str = str(e).lower()
if "duplicate key value violates unique constraint" in error_str or "uniqueviolationerror" in error_str:
if (
"duplicate key value violates unique constraint" in error_str
or "uniqueviolationerror" in error_str
):
await self.db_session.rollback()
return {"status": "error", "message": "Duplicate document detected"}
logger.error("KB sync after create failed for issue %s: %s", issue_identifier, e, exc_info=True)
logger.error(
"KB sync after create failed for issue %s: %s",
issue_identifier,
e,
exc_info=True,
)
await self.db_session.rollback()
return {"status": "error", "message": str(e)}
@ -189,14 +206,18 @@ class JiraKBSyncService:
issue_content, user_llm, doc_meta
)
else:
summary_content = f"Jira Issue {issue_identifier}: {issue_title}\n\n{issue_content}"
summary_content = (
f"Jira Issue {issue_identifier}: {issue_title}\n\n{issue_content}"
)
summary_embedding = embed_text(summary_content)
chunks = await create_document_chunks(issue_content)
document.title = f"{issue_identifier}: {issue_title}"
document.content = summary_content
document.content_hash = generate_content_hash(issue_content, search_space_id)
document.content_hash = generate_content_hash(
issue_content, search_space_id
)
document.embedding = summary_embedding
from sqlalchemy.orm.attributes import flag_modified
@ -219,11 +240,15 @@ class JiraKBSyncService:
logger.info(
"KB sync successful for document %s (%s: %s)",
document_id, issue_identifier, issue_title,
document_id,
issue_identifier,
issue_title,
)
return {"status": "success"}
except Exception as e:
logger.error("KB sync failed for document %s: %s", document_id, e, exc_info=True)
logger.error(
"KB sync failed for document %s: %s", document_id, e, exc_info=True
)
await self.db_session.rollback()
return {"status": "error", "message": str(e)}

View file

@ -87,7 +87,7 @@ class JiraToolMetadataService:
async def _check_account_health(self, connector: SearchSourceConnector) -> bool:
"""Check if the Jira connector auth is still valid.
Returns True if auth is expired/invalid, False if healthy.
"""
try:
@ -98,9 +98,7 @@ class JiraToolMetadataService:
await asyncio.to_thread(jira_client.get_myself)
return False
except Exception as e:
logger.warning(
"Jira connector %s health check failed: %s", connector.id, e
)
logger.warning("Jira connector %s health check failed: %s", connector.id, e)
try:
connector.config = {**connector.config, "auth_expired": True}
flag_modified(connector, "config")
@ -116,7 +114,7 @@ class JiraToolMetadataService:
async def get_creation_context(self, search_space_id: int, user_id: str) -> dict:
"""Return context needed to create a new Jira issue.
Fetches all connected Jira accounts, and for the first healthy one
fetches projects, issue types, and priorities.
"""
@ -165,7 +163,8 @@ class JiraToolMetadataService:
except Exception as e:
logger.warning(
"Failed to fetch Jira context for connector %s: %s",
connector.id, e,
connector.id,
e,
)
return {
@ -179,7 +178,7 @@ class JiraToolMetadataService:
self, search_space_id: int, user_id: str, issue_ref: str
) -> dict:
"""Return context needed to update an indexed Jira issue.
Resolves the issue from the KB, then fetches current details from the Jira API.
"""
document = await self._resolve_issue(search_space_id, user_id, issue_ref)
@ -209,13 +208,15 @@ class JiraToolMetadataService:
session=self._db_session, connector_id=connector.id
)
jira_client = await jira_history._get_jira_client()
issue_data = await asyncio.to_thread(
jira_client.get_issue, issue.issue_id
)
issue_data = await asyncio.to_thread(jira_client.get_issue, issue.issue_id)
formatted = jira_client.format_issue(issue_data)
except Exception as e:
error_str = str(e).lower()
if "401" in error_str or "403" in error_str or "authentication" in error_str:
if (
"401" in error_str
or "403" in error_str
or "authentication" in error_str
):
return {
"error": f"Failed to fetch Jira issue: {e!s}",
"auth_expired": True,

View file

@ -66,7 +66,9 @@ class LinearKBSyncService:
if not indexable_content:
indexable_content = f"Linear Issue {issue_identifier}: {issue_title}"
issue_content = f"# {issue_identifier}: {issue_title}\n\n{indexable_content}"
issue_content = (
f"# {issue_identifier}: {issue_title}\n\n{indexable_content}"
)
content_hash = generate_content_hash(issue_content, search_space_id)

View file

@ -190,7 +190,11 @@ class LinearToolMetadataService:
issue_api = await self._fetch_issue_context(linear_client, issue.id)
except Exception as e:
error_str = str(e).lower()
if "401" in error_str or "authentication" in error_str or "re-authenticate" in error_str:
if (
"401" in error_str
or "authentication" in error_str
or "re-authenticate" in error_str
):
return {
"error": f"Failed to fetch Linear issue context: {e!s}",
"auth_expired": True,

View file

@ -102,7 +102,10 @@ class NotionToolMetadataService:
)
db_connector = result.scalar_one_or_none()
if db_connector and not db_connector.config.get("auth_expired"):
db_connector.config = {**db_connector.config, "auth_expired": True}
db_connector.config = {
**db_connector.config,
"auth_expired": True,
}
flag_modified(db_connector, "config")
await self._db_session.commit()
await self._db_session.refresh(db_connector)