import "https://deno.land/x/xhr@0.1.0/mod.ts"; import { serve } from "https://deno.land/std@0.168.0/http/server.ts"; import { createClient } from "https://esm.sh/@supabase/supabase-js@2.38.1"; const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', }; const OPENAI_API_KEY = Deno.env.get('OPENAI_API_KEY'); const SUPABASE_URL = Deno.env.get('SUPABASE_URL') || "https://ffwcnetryatmpcnjkegg.supabase.co"; const SUPABASE_SERVICE_ROLE_KEY = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') || ""; serve(async (req) => { // Handle CORS preflight requests if (req.method === 'OPTIONS') { return new Response(null, { headers: corsHeaders }); } try { const { uploadId, userId, filePath, fileType } = await req.json(); // Create Supabase client with service role key to bypass RLS const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, { auth: { persistSession: false, }, }); // Fetch the file content from Supabase Storage const { data: fileData, error: fileError } = await supabase .storage .from('documents') .download(filePath); if (fileError) { console.error('Error downloading file:', fileError); return new Response( JSON.stringify({ error: 'Error downloading file' }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ); } // Convert file content to text const text = await fileData.text(); // Extract tasks using OpenAI const tasks = await extractTasksWithOpenAI(text, uploadId, userId); // Save extracted tasks to the database for (const task of tasks) { const { error: taskError } = await supabase .from('tasks') .insert(task); if (taskError) { console.error('Error inserting task:', taskError); } } // Update upload status to 'Completed' const { error: updateError } = await supabase .from('uploads') .update({ status: 'Completed' }) .eq('id', uploadId); if (updateError) { console.error('Error updating upload status:', updateError); return new Response( JSON.stringify({ error: 'Error updating upload status' }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ); } return new Response( JSON.stringify({ success: true, tasksExtracted: tasks.length }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ); } catch (error) { console.error('Error processing document:', error); return new Response( JSON.stringify({ error: error.message }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ); } }); async function extractTasksWithOpenAI(text: string, uploadId: string, userId: string) { try { // Call OpenAI API to extract tasks const response = await fetch('https://api.openai.com/v1/chat/completions', { method: 'POST', headers: { 'Authorization': `Bearer ${OPENAI_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ model: 'gpt-4o-mini', messages: [ { role: 'system', content: ` You are a specialized task extractor for IT security and compliance policy documents. Your job is to identify specific actionable tasks from policy documents. For each task, extract the following information: 1. Task name (short, clear description of what needs to be done) 2. Description (more detailed explanation) 3. Priority (High, Medium, Low) 4. Due date (if mentioned) Format your response as a valid JSON array of task objects with these properties: [ { "task_name": "string", "description": "string", "priority": "string", "due_date": "ISO date string or null" } ] If no due date is mentioned for a task, return null for that field. Only return the JSON array, nothing else. ` }, { role: 'user', content: text } ] }), }); const data = await response.json(); const extractedTasksJson = data.choices[0].message.content; // Parse the extracted tasks const extractedTasks = JSON.parse(extractedTasksJson); // Format tasks for database insertion return extractedTasks.map((task: any) => ({ upload_id: uploadId, user_id: userId, task_name: task.task_name, description: task.description, priority: task.priority, due_date: task.due_date, status: 'Open' })); } catch (error) { console.error('Error extracting tasks with OpenAI:', error); throw new Error('Failed to extract tasks from document'); } }