import { HttpError } from "./errors.ts"; export function pickSchemaFields( definicion: any, campos: string[], ) { if (!definicion || definicion.type !== "object" || !definicion.properties) { return definicion; } const extra = { properties: { "ai-message": { type: "string", description: "Mensaje breve para el usuario final confirmando qué se mejoró y qué se hizo.", examples: [ "Listo: mejoré la redacción del perfil de ingreso y propuse un tema de investigación alineado al plan.", ], }, "is-refusal": { type: "boolean", description: "Indica si el plan fue rechazado por el modelo. En caso de ser true, se espera un mensaje de rechazo en `ai-message`.", }, }, }; const out = structuredClone(definicion); // Si piden campos, filtramos propiedades/required a esos campos const entries = Object.entries(out.properties).filter(([k]) => campos.includes(k) ); out.properties = Object.fromEntries(entries); if (Array.isArray(out.required)) { out.required = out.required.filter((k: string) => campos.includes(k)); } // Siempre agregamos ai-message out.properties = { ...out.properties, ...extra.properties }; out.required = Array.isArray(out.required) ? [...new Set([...out.required, ...Object.keys(extra.properties)])] : Object.keys(extra.properties); return out; } export function pickSchemaAsignaturaFields( definicion: any, campos: string[], ) { // Si no hay definición válida, devolvemos un objeto vacío seguro if (!definicion || definicion.type !== "object" || !definicion.properties) { return { type: "object", properties: {}, required: [], additionalProperties: false }; } // Clonamos para no mutar el original const out = structuredClone(definicion); // 1. Filtrar las propiedades: solo las que el usuario pidió en 'campos' const entries = Object.entries(out.properties).filter(([k]) => campos.includes(k) ); out.properties = Object.fromEntries(entries); // 2. Filtrar los requeridos: solo si están en el nuevo set de propiedades if (Array.isArray(out.required)) { out.required = out.required.filter((k: string) => campos.includes(k)); } else { out.required = []; } // 3. Limpieza de OpenAI: Forzar additionalProperties a false out.additionalProperties = false; return out; } export function safePlanForPrompt(plan: any) { const copy = structuredClone(plan); if (copy?.estructuras_plan) delete copy.estructuras_plan; return copy; } export function assertUuid(v: string, name: string) { // validación ligera if (!v || typeof v !== "string" || v.length < 10) { throw new HttpError(400, "bad_input", `Invalid ${name}`); } }