1+ import os
2+ import json
3+ from typing import List , Optional , Dict , Any
4+ from pathlib import Path
5+ from hyperspell import Hyperspell
6+
7+ # Get environment variables
8+ HYPERSPELL_API_KEY = os .getenv ('HYPERSPELL_API_KEY' )
9+ default_user_id = os .getenv ('HYPERSPELL_USER_ID' )
10+
11+
12+ def hyperspell_search (query : str , sources : Optional [str ] = None , answer : bool = False , user_id : Optional [str ] = None ) -> str :
13+ """
14+ Search across your HyperSpell knowledge base (documents, integrations like Notion, Gmail, etc.).
15+
16+ Args:
17+ query: The search query to find relevant information
18+ sources: Comma-separated list of sources to search (e.g., "collections,notion,gmail").
19+ If None, searches all available sources.
20+ answer: If True, returns a direct answer to the query instead of just documents
21+ user_id: Optional user ID to use for this request. Defaults to HYPERSPELL_USER_ID env var.
22+
23+ Returns:
24+ JSON string containing search results or answer
25+ """
26+ try :
27+ # Create client for this request
28+ client = Hyperspell (api_key = HYPERSPELL_API_KEY , user_id = user_id or default_user_id )
29+ # Parse sources if provided
30+ sources_list = sources .split (',' ) if sources else None
31+
32+ # Build options based on sources
33+ options = {}
34+ if sources_list and 'collections' in sources_list :
35+ options ['collections' ] = {}
36+
37+ response = client .query .search (
38+ query = query ,
39+ sources = sources_list or ["collections" ],
40+ answer = answer ,
41+ options = options
42+ )
43+
44+ if answer :
45+ return json .dumps ({
46+ "answer" : response .answer ,
47+ "sources_used" : [doc .source for doc in response .documents ],
48+ "document_count" : len (response .documents )
49+ })
50+ else :
51+ return json .dumps ({
52+ "documents" : [
53+ {
54+ "title" : getattr (doc , 'filename' , getattr (doc , 'title' , 'No title' )),
55+ "content" : getattr (doc , 'summary' , 'No content available' )[:500 ] + "..." if len (getattr (doc , 'summary' , '' )) > 500 else getattr (doc , 'summary' , 'No content available' ),
56+ "source" : doc .source ,
57+ "score" : getattr (doc , 'score' , 0 ),
58+ "resource_id" : doc .resource_id ,
59+ "content_type" : getattr (doc , 'content_type' , None )
60+ }
61+ for doc in response .documents
62+ ],
63+ "total_results" : len (response .documents )
64+ })
65+
66+ except Exception as e :
67+ return json .dumps ({"error" : f"Error searching HyperSpell: { str (e )} " })
68+
69+
70+ def hyperspell_add_document (text : str , title : Optional [str ] = None , collection : Optional [str ] = None , user_id : Optional [str ] = None ) -> str :
71+ """
72+ Add a text document to your HyperSpell knowledge base.
73+
74+ Args:
75+ text: The full text content to add
76+ title: Optional title for the document
77+ collection: Optional collection name to organize the document
78+ user_id: Optional user ID to use for this request. Defaults to HYPERSPELL_USER_ID env var.
79+
80+ Returns:
81+ JSON string with the document ID and status
82+ """
83+ try :
84+ # Create client for this request
85+ client = Hyperspell (api_key = HYPERSPELL_API_KEY , user_id = user_id or default_user_id )
86+ response = client .documents .add (
87+ text = text ,
88+ title = title ,
89+ collection = collection
90+ )
91+
92+ return json .dumps ({
93+ "document_id" : response .id ,
94+ "resource_id" : response .resource_id ,
95+ "status" : response .status ,
96+ "collection" : collection
97+ })
98+
99+ except Exception as e :
100+ return json .dumps ({"error" : f"Error adding document to HyperSpell: { str (e )} " })
101+
102+
103+ def hyperspell_upload_file (file_path : str , collection : Optional [str ] = None , user_id : Optional [str ] = None ) -> str :
104+ """
105+ Upload a file (PDF, Word doc, spreadsheet, etc.) to your HyperSpell knowledge base.
106+
107+ Args:
108+ file_path: Path to the file to upload
109+ collection: Optional collection name to organize the document
110+ user_id: Optional user ID to use for this request. Defaults to HYPERSPELL_USER_ID env var.
111+
112+ Returns:
113+ JSON string with the document ID and status
114+ """
115+ try :
116+ # Create client for this request
117+ client = Hyperspell (api_key = HYPERSPELL_API_KEY , user_id = user_id or default_user_id )
118+ # Convert to Path object for proper MIME type detection
119+ file_path_obj = Path (file_path )
120+
121+ if not file_path_obj .exists ():
122+ return json .dumps ({"error" : f"File not found: { file_path } " })
123+
124+ response = client .documents .upload (
125+ file = file_path_obj , # Use Path object directly
126+ collection = collection
127+ )
128+
129+ return json .dumps ({
130+ "document_id" : response .id ,
131+ "resource_id" : response .resource_id ,
132+ "status" : response .status ,
133+ "filename" : file_path_obj .name ,
134+ "collection" : collection
135+ })
136+
137+ except Exception as e :
138+ return json .dumps ({"error" : f"Error uploading file to HyperSpell: { str (e )} " })
0 commit comments