Skip to content

Commit 5a44a58

Browse files
authored
Merge pull request MODSetter#339 from MODSetter/dev
[Feature] Add Luma connector
2 parents 4a2b066 + 9bd4699 commit 5a44a58

File tree

27 files changed

+1769
-4
lines changed

27 files changed

+1769
-4
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
# SurfSense
13-
While tools like NotebookLM and Perplexity are impressive and highly effective for conducting research on any topic/query, SurfSense elevates this capability by integrating with your personal knowledge base. It is a highly customizable AI research agent, connected to external sources such as Search Engines (Tavily, LinkUp), Slack, Linear, Jira, ClickUp, Confluence, Gmail, Notion, YouTube, GitHub, Discord, Airtable, Google Calendar and more to come.
13+
While tools like NotebookLM and Perplexity are impressive and highly effective for conducting research on any topic/query, SurfSense elevates this capability by integrating with your personal knowledge base. It is a highly customizable AI research agent, connected to external sources such as Search Engines (Tavily, LinkUp), Slack, Linear, Jira, ClickUp, Confluence, Gmail, Notion, YouTube, GitHub, Discord, Airtable, Google Calendar, Luma and more to come.
1414

1515
<div align="center">
1616
<a href="https://trendshift.io/repositories/13606" target="_blank"><img src="https://trendshift.io/api/badge/repositories/13606" alt="MODSetter%2FSurfSense | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
@@ -74,6 +74,7 @@ Open source and easy to deploy locally.
7474
- Discord
7575
- Airtable
7676
- Google Calendar
77+
- Luma
7778
- and more to come.....
7879

7980
## 📄 **Supported File Extensions**
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""Add Luma connector enums
2+
3+
Revision ID: 21
4+
Revises: 20
5+
Create Date: 2025-09-27 20:00:00.000000
6+
7+
"""
8+
9+
from collections.abc import Sequence
10+
11+
from alembic import op
12+
13+
# revision identifiers, used by Alembic.
14+
revision: str = "21"
15+
down_revision: str | None = "20"
16+
branch_labels: str | Sequence[str] | None = None
17+
depends_on: str | Sequence[str] | None = None
18+
19+
20+
def upgrade() -> None:
21+
"""Safely add 'LUMA_CONNECTOR' to enum types if missing."""
22+
23+
# Add to searchsourceconnectortype enum
24+
op.execute(
25+
"""
26+
DO $$
27+
BEGIN
28+
IF NOT EXISTS (
29+
SELECT 1 FROM pg_type t
30+
JOIN pg_enum e ON t.oid = e.enumtypid
31+
WHERE t.typname = 'searchsourceconnectortype' AND e.enumlabel = 'LUMA_CONNECTOR'
32+
) THEN
33+
ALTER TYPE searchsourceconnectortype ADD VALUE 'LUMA_CONNECTOR';
34+
END IF;
35+
END
36+
$$;
37+
"""
38+
)
39+
40+
# Add to documenttype enum
41+
op.execute(
42+
"""
43+
DO $$
44+
BEGIN
45+
IF NOT EXISTS (
46+
SELECT 1 FROM pg_type t
47+
JOIN pg_enum e ON t.oid = e.enumtypid
48+
WHERE t.typname = 'documenttype' AND e.enumlabel = 'LUMA_CONNECTOR'
49+
) THEN
50+
ALTER TYPE documenttype ADD VALUE 'LUMA_CONNECTOR';
51+
END IF;
52+
END
53+
$$;
54+
"""
55+
)
56+
57+
58+
def downgrade() -> None:
59+
"""Remove 'LUMA_CONNECTOR' from enum types."""
60+
pass

surfsense_backend/app/agents/researcher/nodes.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,42 @@ async def fetch_documents_by_ids(
413413
else:
414414
url = ""
415415

416+
elif doc_type == "LUMA_CONNECTOR":
417+
# Extract Luma-specific metadata
418+
event_id = metadata.get("event_id", "")
419+
event_name = metadata.get("event_name", "Untitled Event")
420+
event_url = metadata.get("event_url", "")
421+
start_time = metadata.get("start_time", "")
422+
location_name = metadata.get("location_name", "")
423+
meeting_url = metadata.get("meeting_url", "")
424+
425+
title = f"Luma: {event_name}"
426+
if start_time:
427+
# Format the start time for display
428+
try:
429+
if "T" in start_time:
430+
from datetime import datetime
431+
432+
start_dt = datetime.fromisoformat(
433+
start_time.replace("Z", "+00:00")
434+
)
435+
formatted_time = start_dt.strftime("%Y-%m-%d %H:%M")
436+
title += f" ({formatted_time})"
437+
except Exception:
438+
pass
439+
440+
description = (
441+
doc.content[:100] + "..."
442+
if len(doc.content) > 100
443+
else doc.content
444+
)
445+
if location_name:
446+
description += f" | Venue: {location_name}"
447+
elif meeting_url:
448+
description += " | Online Event"
449+
450+
url = event_url if event_url else ""
451+
416452
elif doc_type == "EXTENSION":
417453
# Extract Extension-specific metadata
418454
webpage_title = metadata.get("VisitedWebPageTitle", doc.title)
@@ -487,6 +523,7 @@ async def fetch_documents_by_ids(
487523
"CONFLUENCE_CONNECTOR": "Confluence (Selected)",
488524
"CLICKUP_CONNECTOR": "ClickUp (Selected)",
489525
"AIRTABLE_CONNECTOR": "Airtable (Selected)",
526+
"LUMA_CONNECTOR": "Luma Events (Selected)",
490527
}
491528

492529
source_object = {
@@ -1197,6 +1234,33 @@ async def fetch_relevant_documents(
11971234
}
11981235
)
11991236

1237+
elif connector == "LUMA_CONNECTOR":
1238+
(
1239+
source_object,
1240+
luma_chunks,
1241+
) = await connector_service.search_luma(
1242+
user_query=reformulated_query,
1243+
user_id=user_id,
1244+
search_space_id=search_space_id,
1245+
top_k=top_k,
1246+
search_mode=search_mode,
1247+
)
1248+
1249+
# Add to sources and raw documents
1250+
if source_object:
1251+
all_sources.append(source_object)
1252+
all_raw_documents.extend(luma_chunks)
1253+
1254+
# Stream found document count
1255+
if streaming_service and writer:
1256+
writer(
1257+
{
1258+
"yield_value": streaming_service.format_terminal_info_delta(
1259+
f"🎯 Found {len(luma_chunks)} Luma events related to your query"
1260+
)
1261+
}
1262+
)
1263+
12001264
except Exception as e:
12011265
logging.error("Error in search_airtable: %s", traceback.format_exc())
12021266
error_message = f"Error searching connector {connector}: {e!s}"

surfsense_backend/app/agents/researcher/qna_agent/prompts.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def get_qna_citation_system_prompt(chat_history: str | None = None):
3838
- AIRTABLE_CONNECTOR: "Airtable records, tables, and database content" (personal data management and organization)
3939
- TAVILY_API: "Tavily search API results" (personalized search results)
4040
- LINKUP_API: "Linkup search API results" (personalized search results)
41+
- LUMA_CONNECTOR: "Luma events"
4142
</knowledge_sources>
4243
4344
<instructions>

surfsense_backend/app/agents/researcher/sub_section_writer/prompts.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def get_citation_system_prompt(chat_history: str | None = None):
3838
- AIRTABLE_CONNECTOR: "Airtable records, tables, and database content" (personal data management and organization)
3939
- TAVILY_API: "Tavily search API results" (personalized search results)
4040
- LINKUP_API: "Linkup search API results" (personalized search results)
41+
- LUMA_CONNECTOR: "Luma events"
4142
</knowledge_sources>
4243
<instructions>
4344
1. Review the chat history to understand the conversation context and any previous topics discussed.

surfsense_backend/app/agents/researcher/utils.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def get_connector_emoji(connector_name: str) -> str:
5050
"LINKUP_API": "🔗",
5151
"GOOGLE_CALENDAR_CONNECTOR": "📅",
5252
"AIRTABLE_CONNECTOR": "🗃️",
53+
"LUMA_CONNECTOR": "✨",
5354
}
5455
return connector_emojis.get(connector_name, "🔎")
5556

@@ -72,6 +73,7 @@ def get_connector_friendly_name(connector_name: str) -> str:
7273
"TAVILY_API": "Tavily Search",
7374
"LINKUP_API": "Linkup Search",
7475
"AIRTABLE_CONNECTOR": "Airtable",
76+
"LUMA_CONNECTOR": "Luma",
7577
}
7678
return connector_friendly_names.get(connector_name, connector_name)
7779

0 commit comments

Comments
 (0)