diff --git a/surfsense_backend/app/agents/researcher/nodes.py b/surfsense_backend/app/agents/researcher/nodes.py index 5f153d6c9..288c7a447 100644 --- a/surfsense_backend/app/agents/researcher/nodes.py +++ b/surfsense_backend/app/agents/researcher/nodes.py @@ -369,6 +369,30 @@ async def fetch_documents_by_ids( except Exception: title += f" ({start_time})" + elif doc_type == "AIRTABLE_CONNECTOR": + # Extract Airtable-specific metadata + base_name = metadata.get("base_name", "Unknown Base") + table_name = metadata.get("table_name", "Unknown Table") + record_id = metadata.get("record_id", "Unknown Record") + created_time = metadata.get("created_time", "") + + title = f"Airtable: {base_name} - {table_name}" + if record_id: + title += f" (Record: {record_id[:8]}...)" + if created_time: + # Format the created time for display + try: + if "T" in created_time: + from datetime import datetime + + created_dt = datetime.fromisoformat( + created_time.replace("Z", "+00:00") + ) + formatted_time = created_dt.strftime("%Y-%m-%d %H:%M") + title += f" - {formatted_time}" + except Exception: + pass + description = ( doc.content[:100] + "..." if len(doc.content) > 100 @@ -456,6 +480,11 @@ async def fetch_documents_by_ids( "EXTENSION": "Browser Extension (Selected)", "CRAWLED_URL": "Web Pages (Selected)", "FILE": "Files (Selected)", + "GOOGLE_CALENDAR_CONNECTOR": "Google Calendar (Selected)", + "GOOGLE_GMAIL_CONNECTOR": "Google Gmail (Selected)", + "CONFLUENCE_CONNECTOR": "Confluence (Selected)", + "CLICKUP_CONNECTOR": "ClickUp (Selected)", + "AIRTABLE_CONNECTOR": "Airtable (Selected)", } source_object = { @@ -1061,6 +1090,32 @@ async def fetch_relevant_documents( ) } ) + elif connector == "AIRTABLE_CONNECTOR": + ( + source_object, + airtable_chunks, + ) = await connector_service.search_airtable( + user_query=reformulated_query, + user_id=user_id, + search_space_id=search_space_id, + top_k=top_k, + search_mode=search_mode, + ) + + # Add to sources and raw documents + if source_object: + all_sources.append(source_object) + all_raw_documents.extend(airtable_chunks) + + # Stream found document count + if streaming_service and writer: + writer( + { + "yield_value": streaming_service.format_terminal_info_delta( + f"🗃️ Found {len(airtable_chunks)} Airtable records related to your query" + ) + } + ) elif connector == "GOOGLE_GMAIL_CONNECTOR": ( source_object, diff --git a/surfsense_backend/app/agents/researcher/qna_agent/prompts.py b/surfsense_backend/app/agents/researcher/qna_agent/prompts.py index cd64d563f..27c169bc2 100644 --- a/surfsense_backend/app/agents/researcher/qna_agent/prompts.py +++ b/surfsense_backend/app/agents/researcher/qna_agent/prompts.py @@ -21,6 +21,7 @@ You are SurfSense, an advanced AI research assistant that provides detailed, wel - GOOGLE_CALENDAR_CONNECTOR: "Google Calendar events, meetings, and schedules" (personal calendar and time management) - GOOGLE_GMAIL_CONNECTOR: "Google Gmail emails and conversations" (personal emails and communications) - DISCORD_CONNECTOR: "Discord server conversations and shared content" (personal community communications) +- AIRTABLE_CONNECTOR: "Airtable records, tables, and database content" (personal data management and organization) - TAVILY_API: "Tavily search API results" (personalized search results) - LINKUP_API: "Linkup search API results" (personalized search results) diff --git a/surfsense_backend/app/agents/researcher/sub_section_writer/prompts.py b/surfsense_backend/app/agents/researcher/sub_section_writer/prompts.py index 07aec91ea..f5771a13e 100644 --- a/surfsense_backend/app/agents/researcher/sub_section_writer/prompts.py +++ b/surfsense_backend/app/agents/researcher/sub_section_writer/prompts.py @@ -21,6 +21,7 @@ You are SurfSense, an advanced AI research assistant that synthesizes informatio - GOOGLE_CALENDAR_CONNECTOR: "Google Calendar events, meetings, and schedules" (personal calendar and time management) - GOOGLE_GMAIL_CONNECTOR: "Google Gmail emails and conversations" (personal emails and communications) - DISCORD_CONNECTOR: "Discord server messages and channels" (personal community interactions) +- AIRTABLE_CONNECTOR: "Airtable records, tables, and database content" (personal data management and organization) - TAVILY_API: "Tavily search API results" (personalized search results) - LINKUP_API: "Linkup search API results" (personalized search results) diff --git a/surfsense_backend/app/agents/researcher/utils.py b/surfsense_backend/app/agents/researcher/utils.py index 53a08bf61..1171c691d 100644 --- a/surfsense_backend/app/agents/researcher/utils.py +++ b/surfsense_backend/app/agents/researcher/utils.py @@ -48,6 +48,7 @@ def get_connector_emoji(connector_name: str) -> str: "TAVILY_API": "🔍", "LINKUP_API": "🔗", "GOOGLE_CALENDAR_CONNECTOR": "📅", + "AIRTABLE_CONNECTOR": "🗃️", } return connector_emojis.get(connector_name, "🔎") @@ -69,6 +70,7 @@ def get_connector_friendly_name(connector_name: str) -> str: "DISCORD_CONNECTOR": "Discord", "TAVILY_API": "Tavily Search", "LINKUP_API": "Linkup Search", + "AIRTABLE_CONNECTOR": "Airtable", } return connector_friendly_names.get(connector_name, connector_name)