From 342c5428720cf967114f9667030e9e5bbfa4efdb Mon Sep 17 00:00:00 2001 From: Guillermo Arrieta Medina Date: Wed, 4 Feb 2026 16:35:28 -0600 Subject: [PATCH] =?UTF-8?q?inicio=20de=20funcion=20de=20generaci=C3=B3n=20?= =?UTF-8?q?de=20asignatura?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- supabase/config.toml | 11 ++++++ supabase/functions/_shared/openai-service.ts | 39 +++++++++++++++---- supabase/functions/ai-generate-subject/.npmrc | 3 ++ .../functions/ai-generate-subject/deno.json | 3 ++ .../functions/ai-generate-subject/index.ts | 25 ++++++++++++ 5 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 supabase/functions/ai-generate-subject/.npmrc create mode 100644 supabase/functions/ai-generate-subject/deno.json create mode 100644 supabase/functions/ai-generate-subject/index.ts diff --git a/supabase/config.toml b/supabase/config.toml index d81e000..5f119d7 100644 --- a/supabase/config.toml +++ b/supabase/config.toml @@ -26,3 +26,14 @@ entrypoint = "./functions/create-chat-conversation/index.ts" # Specifies static files to be bundled with the function. Supports glob patterns. # For example, if you want to serve static HTML pages in your function: # static_files = [ "./functions/create-chat-conversation/*.html" ] + +[functions.ai-generate-subject] +enabled = true +verify_jwt = true +import_map = "./functions/ai-generate-subject/deno.json" +# Uncomment to specify a custom file path to the entrypoint. +# Supported file extensions are: .ts, .js, .mjs, .jsx, .tsx +entrypoint = "./functions/ai-generate-subject/index.ts" +# Specifies static files to be bundled with the function. Supports glob patterns. +# For example, if you want to serve static HTML pages in your function: +# static_files = [ "./functions/ai-generate-subject/*.html" ] diff --git a/supabase/functions/_shared/openai-service.ts b/supabase/functions/_shared/openai-service.ts index 0f46ff6..543c2a0 100644 --- a/supabase/functions/_shared/openai-service.ts +++ b/supabase/functions/_shared/openai-service.ts @@ -91,6 +91,30 @@ export class OpenAIService { const uploadedToStorage = await this.uploadFilesToStorage(files ?? []); const openaiFileIds = await this.uploadFilesToOpenAI(files ?? []); + const newOptions = { ...options }; + + // Attach file references to the request as an extra user message + if (openaiFileIds.length > 0) { + const fileParts: OpenAITypes.OpenAI.Responses.ResponseInputFile[] = + openaiFileIds.map((id) => ({ + type: "input_file", + file_id: id, + })); + + const arr = Array.isArray(options.input) ? options.input : []; + arr.push({ + role: "user", + content: [ + ...fileParts, + { + type: "input_text", + text: "Usa estos archivos como referencia", + }, + ], + }); + newOptions.input = arr; + } + // Narrow to non-streaming response const openaiRaw = (await this.openai.responses.create( newOptions as OpenAITypes.OpenAI.Responses.ResponseCreateParamsNonStreaming, @@ -98,12 +122,11 @@ export class OpenAIService { const { model, id: responseId } = openaiRaw; const usage = openaiRaw?.usage ?? null; - const conversationId = - ( - openaiRaw as OpenAITypes.OpenAI.Responses.Response & { - conversation_id?: string | null; - } - ).conversation_id ?? null; + const conversationId = ( + openaiRaw as OpenAITypes.OpenAI.Responses.Response & { + conversation_id?: string | null; + } + ).conversation_id ?? null; // Try to read structured JSON output let output: TOutput | undefined = undefined; @@ -148,8 +171,8 @@ export class OpenAIService { const code = message.includes("Supabase upload failed") ? "StorageUploadFailed" : message.includes("OpenAI file upload failed") - ? "OpenAIFileUploadFailed" - : "OpenAIRequestFailed"; + ? "OpenAIFileUploadFailed" + : "OpenAIRequestFailed"; return { ok: false, code, message, cause: err }; } diff --git a/supabase/functions/ai-generate-subject/.npmrc b/supabase/functions/ai-generate-subject/.npmrc new file mode 100644 index 0000000..48c6388 --- /dev/null +++ b/supabase/functions/ai-generate-subject/.npmrc @@ -0,0 +1,3 @@ +# Configuration for private npm package dependencies +# For more information on using private registries with Edge Functions, see: +# https://supabase.com/docs/guides/functions/import-maps#importing-from-private-registries diff --git a/supabase/functions/ai-generate-subject/deno.json b/supabase/functions/ai-generate-subject/deno.json new file mode 100644 index 0000000..f6ca845 --- /dev/null +++ b/supabase/functions/ai-generate-subject/deno.json @@ -0,0 +1,3 @@ +{ + "imports": {} +} diff --git a/supabase/functions/ai-generate-subject/index.ts b/supabase/functions/ai-generate-subject/index.ts new file mode 100644 index 0000000..8cb545f --- /dev/null +++ b/supabase/functions/ai-generate-subject/index.ts @@ -0,0 +1,25 @@ +import "jsr:@supabase/functions-js/edge-runtime.d.ts"; +import { corsHeaders } from "../_shared/cors.ts"; + +console.log("Hello from Functions!"); + +Deno.serve(async (req) => { + const url = new URL(req.url); + const functionName = url.pathname.split("/").pop(); + console.log( + `[${new Date().toISOString()}][${functionName}]: Request received`, + ); + + if (req.method === "OPTIONS") { + return new Response(null, { status: 204, headers: corsHeaders }); + } + const { name } = await req.json(); + const data = { + message: `Hello ${name}!`, + }; + + return new Response( + JSON.stringify(data), + { headers: { "Content-Type": "application/json" } }, + ); +});