diff options
Diffstat (limited to 'makima/frontend/src/lib')
| -rw-r--r-- | makima/frontend/src/lib/listenApi.ts | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/makima/frontend/src/lib/listenApi.ts b/makima/frontend/src/lib/listenApi.ts new file mode 100644 index 0000000..187ebe0 --- /dev/null +++ b/makima/frontend/src/lib/listenApi.ts @@ -0,0 +1,168 @@ +import { API_BASE } from './api'; +import { supabase } from './supabase'; + +// ============================================================================= +// Authentication helper (same pattern as api.ts) +// ============================================================================= + +/** Storage key for API key */ +const API_KEY_STORAGE_KEY = "makima_api_key"; + +/** Get stored API key from localStorage */ +function getStoredApiKey(): string | null { + if (typeof window === "undefined") return null; + return localStorage.getItem(API_KEY_STORAGE_KEY); +} + +/** Get auth headers for API requests */ +async function getAuthHeaders(): Promise<HeadersInit> { + const headers: HeadersInit = { + "Content-Type": "application/json", + }; + + // Try Supabase session first + if (supabase) { + const { data: { session } } = await supabase.auth.getSession(); + if (session?.access_token) { + headers["Authorization"] = `Bearer ${session.access_token}`; + return headers; + } + } + + // Fall back to API key if available + const apiKey = getStoredApiKey(); + if (apiKey) { + headers["X-Makima-API-Key"] = apiKey; + } + + return headers; +} + +// ============================================================================= +// Transcript Analysis Types +// ============================================================================= + +export interface TranscriptAnalysisResult { + requirements: Array<{ + text: string; + speaker: string; + timestamp: number; + confidence: number; + category?: string; + }>; + decisions: Array<{ + text: string; + speaker: string; + timestamp: number; + confidence: number; + context?: string; + }>; + actionItems: Array<{ + text: string; + speaker: string; + timestamp: number; + assignee?: string; + priority?: string; + }>; + keyTopics: string[]; + suggestedContractName?: string; + suggestedDescription?: string; + speakerSummary: Array<{ + speaker: string; + wordCount: number; + speakingTimeSeconds: number; + contributionPercentage: number; + }>; +} + +export interface AnalyzeResponse { + fileId: string; + analysis: TranscriptAnalysisResult; +} + +export interface CreateContractResponse { + contractId: string; + contractName: string; + filesCreated: Array<{ id: string; name: string; fileType: string }>; + tasksCreated: Array<{ id: string; name: string }>; +} + +export interface CreateContractOptions { + name?: string; + description?: string; + includeRequirements?: boolean; + includeDecisions?: boolean; + includeActionItems?: boolean; +} + +// ============================================================================= +// Listen API Functions +// ============================================================================= + +/** + * Analyze a transcript file to extract requirements, decisions, and action items. + */ +export async function analyzeTranscript(fileId: string): Promise<AnalyzeResponse> { + const response = await fetch(`${API_BASE}/api/v1/listen/analyze`, { + method: 'POST', + headers: await getAuthHeaders(), + body: JSON.stringify({ fileId }), + }); + + if (!response.ok) { + const error = await response.json().catch(() => ({ message: 'Failed to analyze transcript' })); + throw new Error(error.message || 'Failed to analyze transcript'); + } + + return response.json(); +} + +/** + * Create a contract from a transcript analysis. + */ +export async function createContractFromTranscript( + fileId: string, + options?: CreateContractOptions +): Promise<CreateContractResponse> { + const response = await fetch(`${API_BASE}/api/v1/listen/create-contract`, { + method: 'POST', + headers: await getAuthHeaders(), + body: JSON.stringify({ + fileId, + ...options, + }), + }); + + if (!response.ok) { + const error = await response.json().catch(() => ({ message: 'Failed to create contract' })); + throw new Error(error.message || 'Failed to create contract'); + } + + return response.json(); +} + +/** + * Update an existing contract with transcript analysis. + */ +export async function updateContractFromTranscript( + fileId: string, + contractId: string, + options?: Omit<CreateContractOptions, 'name'> +): Promise<CreateContractResponse> { + const response = await fetch(`${API_BASE}/api/v1/listen/update-contract`, { + method: 'POST', + headers: await getAuthHeaders(), + body: JSON.stringify({ + fileId, + contractId, + ...options, + }), + }); + + if (!response.ok) { + const error = await response.json().catch(() => ({ message: 'Failed to update contract' })); + throw new Error(error.message || 'Failed to update contract'); + } + + return response.json(); +} |
