Spaces:
Running
Running
import { toast } from "@/components/ui/sonner"; | |
import { storage, STORAGE_KEYS } from "@/lib/storage"; | |
// Define types matching our API | |
export interface SourceMetadata { | |
source?: string; | |
ruling_date?: string; | |
[key: string]: string | undefined; | |
} | |
export interface RetrievedSource { | |
content_snippet: string; | |
metadata?: SourceMetadata; | |
} | |
export interface QueryResponse { | |
answer: string; | |
retrieved_sources?: RetrievedSource[]; | |
} | |
export interface TitleResponse { | |
title: string; | |
} | |
export interface Message { | |
role: "user" | "assistant" | "system"; | |
content: string; | |
} | |
export interface QueryRequest { | |
query: string; | |
chat_history?: Message[]; | |
filters?: Record<string, any>; | |
regenerate?: boolean; | |
} | |
// Add a delay function for better UX when showing loading states | |
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); | |
export const apiService = { | |
async getApiUrl(): Promise<string> { | |
const storedUrl = storage.get<string>(STORAGE_KEYS.API_ENDPOINT); | |
if (storedUrl) { | |
return storedUrl; | |
} else { | |
// Set default if not found | |
return null; | |
} | |
}, | |
async queryRulings(request: QueryRequest): Promise<QueryResponse> { | |
try { | |
// Add a slight delay to make loading states more visible for demo purposes | |
await delay(1000); | |
const API_URL = await this.getApiUrl(); | |
if (!API_URL) { | |
return { | |
answer: "<think>The user hasn't configured an API endpoint yet. I should provide a helpful response.</think>\n\nIt looks like you haven't configured the API endpoint yet. Please go to Settings and enter your API URL to connect to your data source." | |
}; | |
} | |
const response = await fetch(`${API_URL}/query`, { | |
method: "POST", | |
headers: { | |
"Content-Type": "application/json", | |
}, | |
body: JSON.stringify(request), | |
}); | |
if (!response.ok) { | |
const errorData = await response.json().catch(() => ({})); | |
const errorMessage = errorData.detail || `Error: ${response.status} ${response.statusText}`; | |
toast.error(errorMessage); | |
throw new Error(errorMessage); | |
} | |
const result = await response.json(); | |
// Store sources in storage for later use on sources page | |
if (result.retrieved_sources && result.retrieved_sources.length > 0) { | |
// Get existing sources or initialize empty array | |
const existingSources = storage.get<RetrievedSource[]>(STORAGE_KEYS.SOURCES) || []; | |
// Merge new sources, avoid duplicates based on content | |
const updatedSources = [...existingSources]; | |
result.retrieved_sources.forEach((source: RetrievedSource) => { | |
const exists = existingSources.some( | |
existing => existing.content_snippet === source.content_snippet | |
); | |
if (!exists) { | |
updatedSources.push(source); | |
} | |
}); | |
// Store updated sources | |
storage.set(STORAGE_KEYS.SOURCES, updatedSources); | |
} | |
return result; | |
} catch (error) { | |
console.error("Failed to query AI:", error); | |
const errorMessage = error instanceof Error ? error.message : "Failed to get a response"; | |
toast.error(errorMessage); | |
throw error; | |
} | |
}, | |
async generateTitle(query: string): Promise<TitleResponse> { | |
try { | |
const API_URL = await this.getApiUrl(); | |
// If no API URL is configured, return a generic title | |
if (!API_URL) { | |
return { title: query.slice(0, 30) + (query.length > 30 ? '...' : '') }; | |
} | |
const response = await fetch(`${API_URL}/generate-title`, { | |
method: "POST", | |
headers: { | |
"Content-Type": "application/json", | |
}, | |
body: JSON.stringify({ query }), | |
}); | |
if (!response.ok) { | |
const errorData = await response.json().catch(() => ({})); | |
const errorMessage = errorData.detail || `Error: ${response.status} ${response.statusText}`; | |
throw new Error(errorMessage); | |
} | |
return await response.json(); | |
} catch (error) { | |
console.error("Failed to generate title:", error); | |
// Return a default title instead of throwing | |
return { title: "New Chat" }; | |
} | |
} | |
}; | |