@runnerpro/backend 1.17.2 → 1.17.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23,7 +23,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
23
23
  return (mod && mod.__esModule) ? mod : { "default": mod };
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.sendMessage = exports.updateSenderView = exports.conversationRoute = void 0;
26
+ exports.editConversationMessage = exports.sendMessage = exports.updateSenderView = exports.conversationRoute = void 0;
27
27
  const fs_1 = __importDefault(require("fs"));
28
28
  const path_1 = __importDefault(require("path"));
29
29
  const util_1 = require("util");
@@ -129,25 +129,67 @@ const deleteConversationMessage = (req, res, { isClient }) => __awaiter(void 0,
129
129
  // - Se elimina la sugerencia
130
130
  // - Se elimina el mensaje programado
131
131
  // TODO: Comprobar que el cliente/entrenador puede editar/eliminar el mensaje (no se haya contestado ya y que no haya pasado el tiempo de cortesía)
132
+ /**
133
+ * Edita un mensaje de chat existente
134
+ *
135
+ * @param req - Request con params y body
136
+ * @param req.params.id - ID del mensaje a editar
137
+ * @param req.body.text - Nuevo texto del mensaje
138
+ * @param req.body.idWorkout - ID del workout a linkear (opcional, solo entrenadores). Si se envía null, se quita el workout linkeado
139
+ * @param res - Response
140
+ * @param params.isClient - Si el sender es cliente (true) o entrenador (false)
141
+ * @returns Promise<void> - Envía { status: 'ok' } en la respuesta
142
+ *
143
+ * @example
144
+ * ```typescript
145
+ * // Editar solo el texto
146
+ * PUT /chat/conversation/123
147
+ * { "text": "Texto corregido" }
148
+ *
149
+ * // Editar texto y agregar workout
150
+ * PUT /chat/conversation/123
151
+ * { "text": "Texto corregido", "idWorkout": "workout456" }
152
+ *
153
+ * // Quitar workout linkeado
154
+ * PUT /chat/conversation/123
155
+ * { "text": "Texto corregido", "idWorkout": null }
156
+ * ```
157
+ */
132
158
  const editConversationMessage = (req, res, { isClient }) => __awaiter(void 0, void 0, void 0, function* () {
133
159
  const { id } = req.params;
134
- const { text } = req.body;
160
+ const { text, idWorkout: idWorkoutBody } = req.body;
135
161
  if (!(yield canEditOrDeleteMessage({ idMessage: id, isClient, userid: req.session.userid })))
136
162
  return res.send({ status: 'ok' });
137
- const [message] = yield (0, index_1.query)('SELECT [ID CLIENTE] FROM [CHAT MESSAGE] WHERE [ID] = ?', [id]);
163
+ const [message] = yield (0, index_1.query)('SELECT [ID CLIENTE], [ID WORKOUT] FROM [CHAT MESSAGE] WHERE [ID] = ?', [id]);
138
164
  // Devuelve el texto en el otro idioma si el cliente no habla español y el idioma del cliente
139
165
  const { textSpanish, textPreferredLanguage } = yield getPreferredLanguageForChat({
140
166
  text,
141
167
  idCliente: message.idCliente,
142
168
  isClient,
143
169
  });
144
- yield (0, index_1.query)('UPDATE [CHAT MESSAGE] SET [TEXT] = ?, [TEXT PREFERRED LANGUAGE] = ?, [EDITADO] = TRUE WHERE [ID] = ?', [
170
+ // Linkeo de workout desde la edición (solo para entrenadores)
171
+ let idWorkout = message.idWorkout; // Mantener el workout existente por defecto
172
+ if (idWorkoutBody && !isClient) {
173
+ // Validar que el workout existe y pertenece al cliente
174
+ const [workout] = yield (0, index_1.query)('SELECT [ID] FROM [WORKOUT] WHERE [ID] = ? AND [ID CLIENTE] = ?', [idWorkoutBody, message.idCliente]);
175
+ if (workout) {
176
+ idWorkout = idWorkoutBody;
177
+ }
178
+ // Si el workout no existe o no pertenece al cliente, se mantiene el idWorkout actual (o null)
179
+ }
180
+ else if (idWorkoutBody === null && !isClient) {
181
+ // Permitir quitar el workout si se envía explícitamente null
182
+ idWorkout = null;
183
+ }
184
+ yield (0, index_1.query)('UPDATE [CHAT MESSAGE] SET [TEXT] = ?, [TEXT PREFERRED LANGUAGE] = ?, [ID WORKOUT] = ?, [EDITADO] = TRUE WHERE [ID] = ?', [
145
185
  textSpanish,
146
186
  textPreferredLanguage,
187
+ idWorkout,
147
188
  id,
148
189
  ]);
149
190
  res.send({ status: 'ok' });
150
191
  });
192
+ exports.editConversationMessage = editConversationMessage;
151
193
  const canEditOrDeleteMessage = ({ idMessage, isClient, userid }) => __awaiter(void 0, void 0, void 0, function* () {
152
194
  const [message] = yield (0, index_1.query)('SELECT [ID], "ID CLIENTE", "ID SENDER" FROM [CHAT MESSAGE] WHERE [ID] = ? AND (? = FALSE OR [ID CLIENTE] = ?)', [
153
195
  idMessage,
@@ -10,9 +10,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.reprocessRecentMedia = exports.processMediaFile = exports.describeImage = exports.transcribeAudio = void 0;
13
- const vertexai_1 = require("@google-cloud/vertexai");
14
- const index_1 = require("../db/index");
15
- const index_2 = require("../err/index");
13
+ const index_1 = require("../prompt/index");
14
+ const index_2 = require("../db/index");
15
+ const index_3 = require("../err/index");
16
16
  // ✅ PROMPTS PARA PROCESAMIENTO DE ARCHIVOS MULTIMEDIA
17
17
  const AUDIO_TRANSCRIPTION_PROMPT = `Transcribe el audio de forma literal y completa en español.
18
18
  Si el audio está en otro idioma, tradúcelo al español.
@@ -41,51 +41,15 @@ Si la imagen no está relacionada con deporte/fitness, descríbela brevemente.`;
41
41
  * ```
42
42
  */
43
43
  const transcribeAudio = (fileBuffer, mimetype) => __awaiter(void 0, void 0, void 0, function* () {
44
- var _a, _b, _c, _d;
45
44
  try {
46
- const vertex_ai = new vertexai_1.VertexAI({
47
- project: process.env.PROJECT_ID,
48
- location: 'europe-west8',
45
+ const result = yield (0, index_1.sendPrompt)(AUDIO_TRANSCRIPTION_PROMPT, 'PRO', undefined, {
46
+ buffer: fileBuffer,
47
+ mimetype,
49
48
  });
50
- // Usamos gemini-2.5-flash para balance entre velocidad y precisión
51
- const generativeModel = vertex_ai.preview.getGenerativeModel({
52
- model: 'gemini-2.5-flash',
53
- generationConfig: {
54
- temperature: 0.1, // Baja temperatura para transcripción precisa
55
- topP: 0.8,
56
- topK: 20,
57
- },
58
- });
59
- const base64Audio = fileBuffer.toString('base64');
60
- // @ts-ignore - Vertex AI types son complejos para contenido multimodal
61
- const resp = yield generativeModel.generateContent({
62
- contents: [
63
- {
64
- role: 'user',
65
- parts: [
66
- {
67
- inlineData: {
68
- mimeType: mimetype,
69
- data: base64Audio,
70
- },
71
- },
72
- {
73
- text: AUDIO_TRANSCRIPTION_PROMPT,
74
- },
75
- ],
76
- },
77
- ],
78
- });
79
- const candidate = (_a = resp.response.candidates) === null || _a === void 0 ? void 0 : _a[0];
80
- if (!candidate)
81
- return '[Error al procesar audio]';
82
- const parts = (_b = candidate.content) === null || _b === void 0 ? void 0 : _b.parts;
83
- if (!parts || parts.length === 0)
84
- return '[Error al procesar audio]';
85
- return ((_d = (_c = parts[0]) === null || _c === void 0 ? void 0 : _c.text) === null || _d === void 0 ? void 0 : _d.trim()) || '[Audio vacío]';
49
+ return result || '[Audio vacío]';
86
50
  }
87
51
  catch (error) {
88
- (0, index_2.err)(null, null, error, null);
52
+ (0, index_3.err)(null, null, error, null);
89
53
  return '[Error al transcribir audio]';
90
54
  }
91
55
  });
@@ -105,51 +69,15 @@ exports.transcribeAudio = transcribeAudio;
105
69
  * ```
106
70
  */
107
71
  const describeImage = (fileBuffer, mimetype) => __awaiter(void 0, void 0, void 0, function* () {
108
- var _e, _f, _g, _h;
109
72
  try {
110
- const vertex_ai = new vertexai_1.VertexAI({
111
- project: process.env.PROJECT_ID,
112
- location: 'europe-west8',
113
- });
114
- // ⭐ Usamos gemini-2.5-flash para balance entre velocidad y precisión
115
- const generativeModel = vertex_ai.preview.getGenerativeModel({
116
- model: 'gemini-2.5-flash',
117
- generationConfig: {
118
- temperature: 0.3,
119
- topP: 0.8,
120
- topK: 20,
121
- },
122
- });
123
- const base64Image = fileBuffer.toString('base64');
124
- // @ts-ignore - Vertex AI types son complejos para contenido multimodal
125
- const resp = yield generativeModel.generateContent({
126
- contents: [
127
- {
128
- role: 'user',
129
- parts: [
130
- {
131
- inlineData: {
132
- mimeType: mimetype,
133
- data: base64Image,
134
- },
135
- },
136
- {
137
- text: IMAGE_DESCRIPTION_PROMPT,
138
- },
139
- ],
140
- },
141
- ],
73
+ const result = yield (0, index_1.sendPrompt)(IMAGE_DESCRIPTION_PROMPT, 'PRO', undefined, {
74
+ buffer: fileBuffer,
75
+ mimetype,
142
76
  });
143
- const candidate = (_e = resp.response.candidates) === null || _e === void 0 ? void 0 : _e[0];
144
- if (!candidate)
145
- return '[Error al procesar imagen]';
146
- const parts = (_f = candidate.content) === null || _f === void 0 ? void 0 : _f.parts;
147
- if (!parts || parts.length === 0)
148
- return '[Error al procesar imagen]';
149
- return ((_h = (_g = parts[0]) === null || _g === void 0 ? void 0 : _g.text) === null || _h === void 0 ? void 0 : _h.trim()) || '[Imagen no analizable]';
77
+ return result || '[Imagen no analizable]';
150
78
  }
151
79
  catch (error) {
152
- (0, index_2.err)(null, null, error, null);
80
+ (0, index_3.err)(null, null, error, null);
153
81
  return '[Error al describir imagen]';
154
82
  }
155
83
  });
@@ -183,10 +111,10 @@ const processMediaFile = (idMessage, fileBuffer, mimetype) => __awaiter(void 0,
183
111
  return;
184
112
  }
185
113
  // ✅ Guardar el resultado en la base de datos
186
- yield (0, index_1.query)('UPDATE [CHAT MESSAGE] SET [FILE TEXT] = ? WHERE [ID] = ?', [fileText, idMessage]);
114
+ yield (0, index_2.query)('UPDATE [CHAT MESSAGE] SET [FILE TEXT] = ? WHERE [ID] = ?', [fileText, idMessage]);
187
115
  }
188
116
  catch (error) {
189
- (0, index_2.err)(null, null, error, null);
117
+ (0, index_3.err)(null, null, error, null);
190
118
  }
191
119
  });
192
120
  exports.processMediaFile = processMediaFile;
@@ -208,7 +136,7 @@ const reprocessRecentMedia = (bucket) => __awaiter(void 0, void 0, void 0, funct
208
136
  let errors = 0;
209
137
  try {
210
138
  // ✅ Buscar mensajes de los últimos 2 días con MIMETYPE de audio/imagen y sin FILE TEXT
211
- const messages = yield (0, index_1.query)(`SELECT "ID", "MIMETYPE" FROM "CHAT MESSAGE"
139
+ const messages = yield (0, index_2.query)(`SELECT "ID", "MIMETYPE" FROM "CHAT MESSAGE"
212
140
  WHERE "DATE" >= NOW() - INTERVAL '2 days'
213
141
  AND "FILE TEXT" IS NULL
214
142
  AND ("MIMETYPE" LIKE 'audio/%' OR "MIMETYPE" LIKE 'image/%')
@@ -235,7 +163,7 @@ const reprocessRecentMedia = (bucket) => __awaiter(void 0, void 0, void 0, funct
235
163
  fileText = yield describeImage(fileBuffer, message.mimetype);
236
164
  }
237
165
  // ⭐ Guardar en BD
238
- yield (0, index_1.query)('UPDATE [CHAT MESSAGE] SET [FILE TEXT] = ? WHERE [ID] = ?', [fileText, message.id]);
166
+ yield (0, index_2.query)('UPDATE [CHAT MESSAGE] SET [FILE TEXT] = ? WHERE [ID] = ?', [fileText, message.id]);
239
167
  // eslint-disable-next-line no-console
240
168
  console.log(`[reprocessRecentMedia] ✅ Procesado mensaje ${message.id}: ${fileText.substring(0, 50)}...`);
241
169
  processed++;
@@ -248,7 +176,7 @@ const reprocessRecentMedia = (bucket) => __awaiter(void 0, void 0, void 0, funct
248
176
  }
249
177
  }
250
178
  catch (error) {
251
- (0, index_2.err)(null, null, error, null);
179
+ (0, index_3.err)(null, null, error, null);
252
180
  }
253
181
  return { processed, errors };
254
182
  });
@@ -11,36 +11,98 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.sendPrompt = void 0;
13
13
  const vertexai_1 = require("@google-cloud/vertexai");
14
- function sendPrompt(prompt, model = 'FLASH', systemPrompt = undefined) {
15
- var _a, _b, _c;
14
+ /**
15
+ * Envía un prompt a Gemini (Vertex AI) y retorna la respuesta
16
+ * Soporta contenido multimodal (texto + audio/imagen)
17
+ *
18
+ * @param prompt - Texto del prompt a enviar
19
+ * @param model - Modelo a usar: 'LITE', 'FLASH' (default), 'PRO'
20
+ * @param systemPrompt - Instrucciones de sistema opcionales
21
+ * @param media - Contenido multimedia opcional (audio o imagen)
22
+ * @returns Promise<string> - Respuesta generada por la IA
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * // Solo texto
27
+ * const response = await sendPrompt('Traduce esto al inglés: Hola mundo');
28
+ *
29
+ * // Con imagen
30
+ * const description = await sendPrompt(
31
+ * 'Describe esta imagen',
32
+ * 'FLASH',
33
+ * undefined,
34
+ * { buffer: imageBuffer, mimetype: 'image/jpeg' }
35
+ * );
36
+ *
37
+ * // Con audio
38
+ * const transcription = await sendPrompt(
39
+ * 'Transcribe este audio en español',
40
+ * 'FLASH',
41
+ * undefined,
42
+ * { buffer: audioBuffer, mimetype: 'audio/mpeg' }
43
+ * );
44
+ * ```
45
+ */
46
+ function sendPrompt(prompt, model = 'FLASH', systemPrompt = undefined, media = undefined) {
47
+ var _a, _b, _c, _d;
16
48
  return __awaiter(this, void 0, void 0, function* () {
17
49
  // Inicializa el cliente de Vertex AI
18
50
  const vertex_ai = new vertexai_1.VertexAI({
19
- project: process.env.PROJECT_ID, // Reemplaza con tu ID de proyecto de Google Cloud
20
- location: 'europe-west8', // Reemplaza con tu región
51
+ project: process.env.PROJECT_ID,
52
+ location: 'europe-west8',
21
53
  });
22
- // Selecciona el modelo de Gemini más rápido
54
+ // Selecciona el modelo de Gemini
23
55
  let modelGemini;
24
56
  if (model === 'LITE')
25
57
  modelGemini = 'gemini-2.5-flash-lite';
26
58
  else if (model === 'PRO')
27
- modelGemini = 'gemini-2.5-pro';
59
+ modelGemini = 'gemini-3-pro-preview';
28
60
  else
29
61
  modelGemini = 'gemini-2.5-flash';
30
- // Configura el modelo generativo con parámetros optimizados para velocidad
62
+ // Configura el modelo generativo
31
63
  const generativeModel = vertex_ai.preview.getGenerativeModel({
32
64
  model: modelGemini,
33
65
  generationConfig: {
34
- temperature: 0.3,
66
+ temperature: media ? 0.1 : 0.3, // Menor temperatura para transcripciones
35
67
  topP: 0.8,
36
68
  topK: 20,
37
69
  },
38
- systemInstruction: systemPrompt ? {
39
- role: 'system',
40
- parts: [{ text: systemPrompt }],
41
- } : undefined,
70
+ systemInstruction: systemPrompt
71
+ ? {
72
+ role: 'system',
73
+ parts: [{ text: systemPrompt }],
74
+ }
75
+ : undefined,
42
76
  });
43
- const resp = yield generativeModel.generateContent(prompt);
77
+ // Construir contenido según si hay media o no
78
+ let content;
79
+ if (media) {
80
+ // Contenido multimodal (audio/imagen + texto)
81
+ content = {
82
+ contents: [
83
+ {
84
+ role: 'user',
85
+ parts: [
86
+ {
87
+ inlineData: {
88
+ mimeType: media.mimetype,
89
+ data: media.buffer.toString('base64'),
90
+ },
91
+ },
92
+ {
93
+ text: prompt,
94
+ },
95
+ ],
96
+ },
97
+ ],
98
+ };
99
+ }
100
+ else {
101
+ // Solo texto
102
+ content = prompt;
103
+ }
104
+ // @ts-ignore - Vertex AI types son complejos para contenido multimodal
105
+ const resp = yield generativeModel.generateContent(content);
44
106
  // Early return si no hay candidates
45
107
  const candidate = (_a = resp.response.candidates) === null || _a === void 0 ? void 0 : _a[0];
46
108
  if (!candidate)
@@ -50,7 +112,7 @@ function sendPrompt(prompt, model = 'FLASH', systemPrompt = undefined) {
50
112
  if (!parts || parts.length === 0)
51
113
  return '';
52
114
  // Return del texto si existe
53
- return ((_c = parts[0]) === null || _c === void 0 ? void 0 : _c.text) || '';
115
+ return ((_d = (_c = parts[0]) === null || _c === void 0 ? void 0 : _c.text) === null || _d === void 0 ? void 0 : _d.trim()) || '';
54
116
  });
55
117
  }
56
118
  exports.sendPrompt = sendPrompt;
@@ -1,4 +1,31 @@
1
1
  declare const conversationRoute: ({ router, ...params }: any) => void;
2
+ /**
3
+ * Edita un mensaje de chat existente
4
+ *
5
+ * @param req - Request con params y body
6
+ * @param req.params.id - ID del mensaje a editar
7
+ * @param req.body.text - Nuevo texto del mensaje
8
+ * @param req.body.idWorkout - ID del workout a linkear (opcional, solo entrenadores). Si se envía null, se quita el workout linkeado
9
+ * @param res - Response
10
+ * @param params.isClient - Si el sender es cliente (true) o entrenador (false)
11
+ * @returns Promise<void> - Envía { status: 'ok' } en la respuesta
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // Editar solo el texto
16
+ * PUT /chat/conversation/123
17
+ * { "text": "Texto corregido" }
18
+ *
19
+ * // Editar texto y agregar workout
20
+ * PUT /chat/conversation/123
21
+ * { "text": "Texto corregido", "idWorkout": "workout456" }
22
+ *
23
+ * // Quitar workout linkeado
24
+ * PUT /chat/conversation/123
25
+ * { "text": "Texto corregido", "idWorkout": null }
26
+ * ```
27
+ */
28
+ declare const editConversationMessage: (req: any, res: any, { isClient }: any) => Promise<any>;
2
29
  /**
3
30
  * Envía un mensaje de chat entre entrenador y cliente
4
31
  *
@@ -31,5 +58,5 @@ declare const updateSenderView: ({ userid, idCliente, idMessage }: {
31
58
  idCliente: any;
32
59
  idMessage: any;
33
60
  }) => Promise<void>;
34
- export { conversationRoute, updateSenderView, sendMessage };
61
+ export { conversationRoute, updateSenderView, sendMessage, editConversationMessage };
35
62
  //# sourceMappingURL=conversation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../../../src/chat/api/conversation.ts"],"names":[],"mappings":"AAmBA,QAAA,MAAM,iBAAiB,0BAA2B,GAAG,SA0BpD,CAAC;AAmMF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,QAAA,MAAM,WAAW,0EAAuE,GAAG,kBAkE1F,CAAC;AAEF,QAAA,MAAM,gBAAgB;;;;mBAqBrB,CAAC;AA8RF,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../../../src/chat/api/conversation.ts"],"names":[],"mappings":"AAmBA,QAAA,MAAM,iBAAiB,0BAA2B,GAAG,SA0BpD,CAAC;AA0EF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,QAAA,MAAM,uBAAuB,qCAAkC,GAAG,iBAqCjE,CAAC;AAmGF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,QAAA,MAAM,WAAW,0EAAuE,GAAG,kBAkE1F,CAAC;AAEF,QAAA,MAAM,gBAAgB;;;;mBAqBrB,CAAC;AA8RF,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/index.ts"],"names":[],"mappings":";AAqBA;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,eAAe,eAAsB,MAAM,YAAY,MAAM,KAAG,QAAQ,MAAM,CAkDnF,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,aAAa,eAAsB,MAAM,YAAY,MAAM,KAAG,QAAQ,MAAM,CAkDjF,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,QAAA,MAAM,gBAAgB,cAAqB,MAAM,cAAc,MAAM,YAAY,MAAM,KAAG,QAAQ,IAAI,CAkBrG,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,oBAAoB,WAAkB,GAAG;eAAwB,MAAM;YAAU,MAAM;EAwD5F,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/index.ts"],"names":[],"mappings":";AAqBA;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,eAAe,eAAsB,MAAM,YAAY,MAAM,KAAG,QAAQ,MAAM,CAWnF,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,aAAa,eAAsB,MAAM,YAAY,MAAM,KAAG,QAAQ,MAAM,CAWjF,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,QAAA,MAAM,gBAAgB,cAAqB,MAAM,cAAc,MAAM,YAAY,MAAM,KAAG,QAAQ,IAAI,CAkBrG,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,oBAAoB,WAAkB,GAAG;eAAwB,MAAM;YAAU,MAAM;EAwD5F,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,CAAC"}
@@ -1,3 +1,45 @@
1
- declare function sendPrompt(prompt: string, model?: string, systemPrompt?: string | undefined): Promise<string>;
1
+ /// <reference types="node" />
2
+ /**
3
+ * Contenido multimedia opcional para enviar junto con el prompt
4
+ */
5
+ interface MediaContent {
6
+ /** Buffer del archivo (audio o imagen) */
7
+ buffer: Buffer;
8
+ /** Tipo MIME del archivo (ej: 'audio/mpeg', 'image/jpeg') */
9
+ mimetype: string;
10
+ }
11
+ /**
12
+ * Envía un prompt a Gemini (Vertex AI) y retorna la respuesta
13
+ * Soporta contenido multimodal (texto + audio/imagen)
14
+ *
15
+ * @param prompt - Texto del prompt a enviar
16
+ * @param model - Modelo a usar: 'LITE', 'FLASH' (default), 'PRO'
17
+ * @param systemPrompt - Instrucciones de sistema opcionales
18
+ * @param media - Contenido multimedia opcional (audio o imagen)
19
+ * @returns Promise<string> - Respuesta generada por la IA
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // Solo texto
24
+ * const response = await sendPrompt('Traduce esto al inglés: Hola mundo');
25
+ *
26
+ * // Con imagen
27
+ * const description = await sendPrompt(
28
+ * 'Describe esta imagen',
29
+ * 'FLASH',
30
+ * undefined,
31
+ * { buffer: imageBuffer, mimetype: 'image/jpeg' }
32
+ * );
33
+ *
34
+ * // Con audio
35
+ * const transcription = await sendPrompt(
36
+ * 'Transcribe este audio en español',
37
+ * 'FLASH',
38
+ * undefined,
39
+ * { buffer: audioBuffer, mimetype: 'audio/mpeg' }
40
+ * );
41
+ * ```
42
+ */
43
+ declare function sendPrompt(prompt: string, model?: string, systemPrompt?: string | undefined, media?: MediaContent | undefined): Promise<string>;
2
44
  export { sendPrompt };
3
45
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/prompt/index.ts"],"names":[],"mappings":"AAEA,iBAAe,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAAgB,EAAE,YAAY,GAAE,MAAM,GAAG,SAAqB,mBAuC9G;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/prompt/index.ts"],"names":[],"mappings":";AAEA;;GAEG;AACH,UAAU,YAAY;IACpB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,iBAAe,UAAU,CACvB,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAgB,EACvB,YAAY,GAAE,MAAM,GAAG,SAAqB,EAC5C,KAAK,GAAE,YAAY,GAAG,SAAqB,mBAsE5C;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runnerpro/backend",
3
- "version": "1.17.2",
3
+ "version": "1.17.4",
4
4
  "description": "A collection of common backend functions",
5
5
  "exports": {
6
6
  ".": "./lib/cjs/index.js"