diff --git a/deno.json b/deno.json index c46e55a..60f816d 100644 --- a/deno.json +++ b/deno.json @@ -1,8 +1,12 @@ { - "allowScripts": ["npm:deno@2.6.4", "npm:supabase-js@1.0.4", "npm:supabase@2.72.6"], + "allowScripts": [ + "npm:deno@2.6.4", + "npm:supabase-js@1.0.4", + "npm:supabase@2.72.6" + ], "imports": { "@openai/openai": "jsr:@openai/openai@^6.16.0", - "@zod/zod": "jsr:@zod/zod@^4.3.5" + "@zod/zod": "jsr:@zod/zod@^4.3.5", "@david/dax": "jsr:@david/dax@^0.44.2" } } diff --git a/supabase/functions/_shared/cors.ts b/supabase/functions/_shared/cors.ts index 455c898..5da4b63 100644 --- a/supabase/functions/_shared/cors.ts +++ b/supabase/functions/_shared/cors.ts @@ -1,5 +1,5 @@ export const corsHeaders = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": - "authorization, x-client-info, apikey, content-type", + "authorization, x-client-info, apikey, content-type, x-supabase-client-platform", }; diff --git a/supabase/functions/ai-generate-plan/index.ts b/supabase/functions/ai-generate-plan/index.ts index 374a5f3..0f3185b 100644 --- a/supabase/functions/ai-generate-plan/index.ts +++ b/supabase/functions/ai-generate-plan/index.ts @@ -168,8 +168,15 @@ Deno.serve(async (req: Request): Promise => { const userPrompt = `Genera un borrador completo del PLAN DE ESTUDIOS con base en lo siguiente: - - Descripción del enfoque: ${payload.iaConfig.descripcionEnfoque} - - Notas adicionales: ${payload.iaConfig.notasAdicionales ?? "Ninguna"}`; + - Nombre de la institución: Universidad La Salle México + - Nombre del plan: ${payload.datosBasicos.nombrePlan} + - Nivel: ${payload.datosBasicos.nivel} + - Tipo de ciclo: ${payload.datosBasicos.tipoCiclo} + - Número de ciclos: ${payload.datosBasicos.numCiclos} + - Descripción del enfoque académico (sobre el contenido de la respuesta generada): ${payload.iaConfig.descripcionEnfoqueAcademico} + - Notas adicionales (sobre el formato de la respuesta generada): ${ + payload.iaConfig.instruccionesAdicionalesIA ?? "Ninguna" + }`; // Ensure the JSON schema is an object as required by OpenAI types const schemaDef: Record = typeof estructuraPlan?.definicion === "object" && @@ -313,8 +320,10 @@ Deno.serve(async (req: Request): Promise => { repositoriosIds: payload.iaConfig?.repositoriosIds ?? null, }, iaConfig: { - descripcionEnfoque: payload.iaConfig?.descripcionEnfoque ?? null, - notasAdicionales: payload.iaConfig?.notasAdicionales ?? null, + descripcionEnfoqueAcademico: + payload.iaConfig?.descripcionEnfoqueAcademico ?? null, + instruccionesAdicionalesIA: + payload.iaConfig?.instruccionesAdicionalesIA ?? null, usarMCP: Boolean(payload.iaConfig?.usarMCP), }, } as unknown as Json, diff --git a/supabase/functions/ai-generate-plan/types.ts b/supabase/functions/ai-generate-plan/types.ts index 08b016a..9e8e9d1 100644 --- a/supabase/functions/ai-generate-plan/types.ts +++ b/supabase/functions/ai-generate-plan/types.ts @@ -9,8 +9,8 @@ export type AIGeneratePlanInput = { estructuraPlanId: string; }; iaConfig: { - descripcionEnfoque: string; - notasAdicionales?: string; + descripcionEnfoqueAcademico: string; + instruccionesAdicionalesIA?: string; archivosReferencia?: Array; repositoriosIds?: Array; usarMCP?: boolean; diff --git a/supabase/functions/create-chat-conversation/index.ts b/supabase/functions/create-chat-conversation/index.ts index cadbed2..ee7b7dd 100644 --- a/supabase/functions/create-chat-conversation/index.ts +++ b/supabase/functions/create-chat-conversation/index.ts @@ -1,7 +1,6 @@ // Setup type definitions for built-in Supabase Runtime APIs import "@supabase/functions-js/edge-runtime.d.ts"; import { createClient } from "https://esm.sh/@supabase/supabase-js@2"; - type WebhookPayload = { type: "INSERT" | "UPDATE" | "DELETE"; table: string; @@ -9,28 +8,23 @@ type WebhookPayload = { record: Record | null; old_record: Record | null; }; - const SUPABASE_URL = Deno.env.get("SUPABASE_URL") ?? ""; -const SUPABASE_SERVICE_ROLE_KEY = - Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""; +const SUPABASE_SERVICE_ROLE_KEY = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? + ""; const OPENAI_API_KEY = Deno.env.get("OPENAI_API_KEY") ?? ""; -const OPENAI_BASE_URL = - Deno.env.get("OPENAI_BASE_URL") ?? "https://api.openai.com/v1"; - +const OPENAI_BASE_URL = Deno.env.get("OPENAI_BASE_URL") ?? + "https://api.openai.com/v1"; const ALLOWED_SCHEMA = "public"; const ALLOWED_TABLES = new Set(["planes_estudio", "asignaturas"]); - const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, { auth: { persistSession: false }, }); - function jsonResponse(status: number, body: Record) { return new Response(JSON.stringify(body), { status, headers: { "Content-Type": "application/json" }, }); } - async function createConversationId(metadata: Record) { const response = await fetch(`${OPENAI_BASE_URL}/conversations`, { method: "POST", @@ -40,61 +34,47 @@ async function createConversationId(metadata: Record) { }, body: JSON.stringify({ metadata }), }); - if (!response.ok) { const errorText = await response.text(); throw new Error(`OpenAI error: ${response.status} ${errorText}`); } - const data = await response.json(); const conversationId = data?.id as string | undefined; - if (!conversationId) { throw new Error("OpenAI response missing conversation id"); } - return conversationId; } - Deno.serve(async (req) => { if (req.method !== "POST") { return jsonResponse(405, { error: "Method not allowed" }); } - if (!SUPABASE_URL || !SUPABASE_SERVICE_ROLE_KEY) { return jsonResponse(500, { error: "Supabase env vars missing" }); } - if (!OPENAI_API_KEY) { return jsonResponse(500, { error: "OPENAI_API_KEY missing" }); } - let payload: WebhookPayload; try { payload = await req.json(); } catch { return jsonResponse(400, { error: "Invalid JSON body" }); } - const { type, table, schema, record } = payload; - if (schema !== ALLOWED_SCHEMA || !ALLOWED_TABLES.has(table)) { return jsonResponse(400, { error: "Table not allowed" }); } - if (type !== "INSERT") { return jsonResponse(200, { status: "ignored", reason: "event_type" }); } - if (!record || typeof record !== "object") { return jsonResponse(400, { error: "Missing record" }); } - const recordId = record["id"] as string | number | undefined; if (!recordId) { return jsonResponse(400, { error: "Record id missing" }); } - const existingConversationId = record["conversation_id"] as | string | null @@ -105,7 +85,6 @@ Deno.serve(async (req) => { conversation_id: existingConversationId, }); } - let conversationId: string; try { conversationId = await createConversationId({ @@ -115,16 +94,13 @@ Deno.serve(async (req) => { } catch (error) { return jsonResponse(502, { error: (error as Error).message }); } - const { error } = await supabase .from(table) .update({ conversation_id: conversationId }) .eq("id", recordId); - if (error) { return jsonResponse(500, { error: error.message }); } - return jsonResponse(200, { status: "updated", table,