diff --git a/supabase/functions/create-chat-conversation/plan/crear.ts b/supabase/functions/create-chat-conversation/plan/crear.ts index bfbd398..74673a0 100644 --- a/supabase/functions/create-chat-conversation/plan/crear.ts +++ b/supabase/functions/create-chat-conversation/plan/crear.ts @@ -1,34 +1,90 @@ // ./plan_mensajes_ia/index.ts -import { getSupabaseServiceClient } from "../_shared/supabase.ts"; +import type { OpenAI } from "openai"; -export async function handlePlanMensajesResponse(response: any) { - const supabase = getSupabaseServiceClient(); - const { mensaje_id, is_structured } = response.metadata; +import type { Json } from "../../_shared/database.types.ts"; +import { ResponseMetadata } from "../../_shared/utils.ts"; +import { supabase } from "../../openai-webhook-responses/supabase.ts"; - // Extraer el texto de la respuesta (usando tu lógica de filtrado de output) - const outputText = response.output_text || ""; // Ajustar según cómo venga el objeto - const respuestaJSON = JSON.parse(outputText || "{}"); - const is_refusal = !!respuestaJSON.is_refusal || respuestaJSON["is-refusal"] === true; - - let recommendations = []; - if (is_structured) { - recommendations = Object.entries(respuestaJSON) - .filter(([k]) => k !== "ai-message" && k !== "is-refusal") - .map(([campo, valor]) => ({ - campo_afectado: campo, - texto_mejora: valor, - aplicada: false, - })); +function extractOutputText(response: OpenAI.Responses.Response): string { + const direct = (response as unknown as { output_text?: unknown }).output_text; + if (typeof direct === "string") return direct; + + const output = (response as unknown as { output?: unknown }).output; + if (!Array.isArray(output)) return ""; + + // Fallback similar al usado en index.ts + try { + return output + .filter((item) => (item as { type?: unknown })?.type === "message") + .flatMap((item) => (item as { content?: unknown })?.content ?? []) + .filter((c) => (c as { type?: unknown })?.type === "output_text") + .map((c) => String((c as { text?: unknown })?.text ?? "")) + .join(""); + } catch { + return ""; + } +} + +export async function handlePlanMensajesResponse( + response: OpenAI.Responses.Response, +): Promise { + const metadata = response.metadata as any; + const mensajeId = metadata?.mensaje_id; +console.log("ya entre aqui"); + + const isStructured = metadata?.is_structured === "true" || metadata?.is_structured === true; + if (!mensajeId) { + console.warn("No se recibió mensaje_id en la metadata del webhook"); + return; } - await supabase - .from("plan_mensajes_ia") - .update({ - respuesta: respuestaJSON["ai-message"] || "", - propuesta: { recommendations }, - is_refusal, - estado: "COMPLETADO", - }) - .eq("id", mensaje_id); + try { + const outputText = extractOutputText(response); + if (!outputText) { + throw new Error("La respuesta de OpenAI está vacía"); + } + + let respuestaJSON: any; + try { + respuestaJSON = JSON.parse(outputText); + } catch (e) { + throw new Error(`Error parseando JSON de OpenAI: ${e.message}`); + } + + const is_refusal = !!respuestaJSON.is_refusal || respuestaJSON["is-refusal"] === true; + + let recommendations = []; + if (isStructured && !is_refusal) { + recommendations = Object.entries(respuestaJSON) + .filter(([k]) => k !== "ai-message" && k !== "is-refusal" && k !== "is_refusal") + .map(([campo, valor]) => ({ + campo_afectado: campo, + texto_mejora: valor, + aplicada: false, + })); + } + + const { error } = await supabase + .from("plan_mensajes_ia") + .update({ + respuesta: respuestaJSON["ai-message"] || "", + propuesta: { recommendations }, + is_refusal, + estado: "COMPLETADO", + }) + .eq("id", mensajeId); + + if (error) { + throw error; + } + + } catch (e) { + console.error("Error procesando handlePlanMensajesResponse:", { mensajeId, e }); + // Opcional: Marcar el mensaje como fallido en la tabla si tienes ese estado + await supabase + .from("plan_mensajes_ia") + .update({ estado: "ERROR" }) + .eq("id", mensajeId); + } } \ No newline at end of file diff --git a/supabase/functions/openai-webhook-responses/index.ts b/supabase/functions/openai-webhook-responses/index.ts index 6ed7d7d..9a43c11 100644 --- a/supabase/functions/openai-webhook-responses/index.ts +++ b/supabase/functions/openai-webhook-responses/index.ts @@ -8,7 +8,8 @@ import OpenAI from "openai"; import { ResponseMetadata } from "../_shared/utils.ts"; import { handlePlanesEstudioResponse } from "./planes_estudio/index.ts"; import { handleAsignaturasResponse } from "./asignaturas/index.ts"; -import { handlePlanMensajesResponse } from "./planes_estudio/crear.ts"; +import { handlePlanMensajesResponse } from "../create-chat-conversation/plan/crear.ts"; + console.log("Starting OpenAI webhook responses function"); @@ -36,9 +37,7 @@ async function handleCompletedResponse( case "asignaturas": await handleAsignaturasResponse(response); break; - case "plan_mensajes_ia": // <-- Nueva tabla añadida - console.log("entre aqui"); - + case "plan_mensajes_ia": await handlePlanMensajesResponse(response); break; default: diff --git a/supabase/functions/openai-webhook-responses/planes_estudio/crear.ts b/supabase/functions/openai-webhook-responses/planes_estudio/crear.ts index 966607f..6f133bf 100644 --- a/supabase/functions/openai-webhook-responses/planes_estudio/crear.ts +++ b/supabase/functions/openai-webhook-responses/planes_estudio/crear.ts @@ -106,66 +106,3 @@ export async function handleCrearPlanEstudio( return; } } - -export async function handlePlanMensajesResponse( - response: OpenAI.Responses.Response, -): Promise { - const metadata = response.metadata as any; - const mensajeId = metadata?.mensaje_id; -console.log("ya entre aqui"); - - const isStructured = metadata?.is_structured === "true" || metadata?.is_structured === true; - if (!mensajeId) { - console.warn("No se recibió mensaje_id en la metadata del webhook"); - return; - } - - try { - const outputText = extractOutputText(response); - if (!outputText) { - throw new Error("La respuesta de OpenAI está vacía"); - } - - let respuestaJSON: any; - try { - respuestaJSON = JSON.parse(outputText); - } catch (e) { - throw new Error(`Error parseando JSON de OpenAI: ${e.message}`); - } - - const is_refusal = !!respuestaJSON.is_refusal || respuestaJSON["is-refusal"] === true; - - let recommendations = []; - if (isStructured && !is_refusal) { - recommendations = Object.entries(respuestaJSON) - .filter(([k]) => k !== "ai-message" && k !== "is-refusal" && k !== "is_refusal") - .map(([campo, valor]) => ({ - campo_afectado: campo, - texto_mejora: valor, - aplicada: false, - })); - } - - const { error } = await supabase - .from("plan_mensajes_ia") - .update({ - respuesta: respuestaJSON["ai-message"] || "", - propuesta: { recommendations }, - is_refusal, - estado: "COMPLETADO", - }) - .eq("id", mensajeId); - - if (error) { - throw error; - } - - } catch (e) { - console.error("Error procesando handlePlanMensajesResponse:", { mensajeId, e }); - // Opcional: Marcar el mensaje como fallido en la tabla si tienes ese estado - await supabase - .from("plan_mensajes_ia") - .update({ estado: "ERROR" }) - .eq("id", mensajeId); - } -} \ No newline at end of file