Merge pull request #295 from CREDO23/feature/airtable-connector

[Feature]  Add Airtable connector
This commit is contained in:
Rohan Verma 2025-09-03 12:49:14 -07:00 committed by GitHub
commit 662212d4e2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 1629 additions and 3 deletions

View file

@ -1,5 +1,7 @@
import asyncio
import json
import logging
import traceback
from typing import Any
from langchain_core.messages import HumanMessage, SystemMessage
@ -369,6 +371,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 +482,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 +1092,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,
@ -1141,6 +1198,7 @@ async def fetch_relevant_documents(
)
except Exception as e:
logging.error("Error in search_airtable: %s", traceback.format_exc())
error_message = f"Error searching connector {connector}: {e!s}"
print(error_message)

View file

@ -35,6 +35,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)
</knowledge_sources>

View file

@ -35,6 +35,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)
</knowledge_sources>

View file

@ -49,6 +49,7 @@ def get_connector_emoji(connector_name: str) -> str:
"TAVILY_API": "🔍",
"LINKUP_API": "🔗",
"GOOGLE_CALENDAR_CONNECTOR": "📅",
"AIRTABLE_CONNECTOR": "🗃️",
}
return connector_emojis.get(connector_name, "🔎")
@ -70,6 +71,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)