Files
genesis-2/supabase/functions/create-chat-conversation/asignatura/crear.ts
T

100 lines
3.1 KiB
TypeScript

// ./plan_mensajes_ia/index.ts
import type { OpenAI } from "openai";
import type { Json } from "../../_shared/database.types.ts";
import { ResponseMetadata } from "../../_shared/utils.ts";
import { supabase } from "../../openai-webhook-responses/supabase.ts";
function extractOutputText(response: OpenAI.Responses.Response): string {
const direct = (response as any).output_text;
if (typeof direct === "string") return direct;
const output = (response as any).output;
if (!Array.isArray(output)) return "";
try {
return output
.filter((item) => item?.type === "message")
.flatMap((item) => item?.content ?? [])
.filter((c) => c?.type === "output_text")
.map((c) => String(c?.text ?? ""))
.join("");
} catch {
return "";
}
}
export async function handleAsignaturaMensajesResponse(
response: OpenAI.Responses.Response,
): Promise<void> {
const metadata = response.metadata as any;
const mensajeId = metadata?.mensaje_id;
console.log("Procesando Webhook para Asignatura. Mensaje ID:", mensajeId);
const isStructured = metadata?.is_structured === "true" || metadata?.is_structured === true;
if (!mensajeId) {
console.warn("No se recibió mensaje_id en la metadata del webhook de asignatura");
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}`);
}
// Normalización de campos de la IA
const aiMessage = respuestaJSON["ai-message"] || respuestaJSON["ai_message"] || "";
const is_refusal = !!respuestaJSON.is_refusal || respuestaJSON["is-refusal"] === true;
let recommendations: any[] = [];
// Si es estructurado y no es un rechazo de la IA, generamos las recomendaciones
if (isStructured && !is_refusal) {
recommendations = Object.entries(respuestaJSON)
.filter(([k]) => !["ai-message", "ai_message", "is-refusal", "is_refusal"].includes(k))
.map(([campo, valor]) => ({
campo_afectado: campo,
texto_mejora: valor,
aplicada: false,
}));
}
// --- CAMBIO CLAVE: TABLA 'asignatura_mensajes_ia' ---
const { error } = await supabase
.from("asignatura_mensajes_ia")
.update({
respuesta: aiMessage,
// Guardamos la propuesta completa para mantener historial
propuesta: {
respuesta: aiMessage,
recommendations
},
is_refusal,
estado: "COMPLETADO",
})
.eq("id", mensajeId);
if (error) throw error;
console.log(`Mensaje de asignatura ${mensajeId} actualizado con éxito.`);
} catch (e) {
console.error("Error en handleAsignaturaMensajesResponse:", { mensajeId, error: e.message });
// Marcamos como error en la tabla correcta para que el front deje de mostrar el spinner
await supabase
.from("asignatura_mensajes_ia")
.update({ estado: "ERROR" })
.eq("id", mensajeId);
}
}