@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.
- package/lib/cjs/chat/api/conversation.js +46 -4
- package/lib/cjs/mediaProcessing/index.js +18 -90
- package/lib/cjs/prompt/index.js +76 -14
- package/lib/cjs/types/chat/api/conversation.d.ts +28 -1
- package/lib/cjs/types/chat/api/conversation.d.ts.map +1 -1
- package/lib/cjs/types/mediaProcessing/index.d.ts.map +1 -1
- package/lib/cjs/types/prompt/index.d.ts +43 -1
- package/lib/cjs/types/prompt/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -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
|
-
|
|
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
|
|
14
|
-
const
|
|
15
|
-
const
|
|
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
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
const result = yield (0, index_1.sendPrompt)(AUDIO_TRANSCRIPTION_PROMPT, 'PRO', undefined, {
|
|
46
|
+
buffer: fileBuffer,
|
|
47
|
+
mimetype,
|
|
49
48
|
});
|
|
50
|
-
|
|
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,
|
|
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
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
114
|
+
yield (0, index_2.query)('UPDATE [CHAT MESSAGE] SET [FILE TEXT] = ? WHERE [ID] = ?', [fileText, idMessage]);
|
|
187
115
|
}
|
|
188
116
|
catch (error) {
|
|
189
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
179
|
+
(0, index_3.err)(null, null, error, null);
|
|
252
180
|
}
|
|
253
181
|
return { processed, errors };
|
|
254
182
|
});
|
package/lib/cjs/prompt/index.js
CHANGED
|
@@ -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
|
-
|
|
15
|
-
|
|
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,
|
|
20
|
-
location: 'europe-west8',
|
|
51
|
+
project: process.env.PROJECT_ID,
|
|
52
|
+
location: 'europe-west8',
|
|
21
53
|
});
|
|
22
|
-
// Selecciona el modelo de Gemini
|
|
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-
|
|
59
|
+
modelGemini = 'gemini-3-pro-preview';
|
|
28
60
|
else
|
|
29
61
|
modelGemini = 'gemini-2.5-flash';
|
|
30
|
-
// Configura el modelo generativo
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
70
|
+
systemInstruction: systemPrompt
|
|
71
|
+
? {
|
|
72
|
+
role: 'system',
|
|
73
|
+
parts: [{ text: systemPrompt }],
|
|
74
|
+
}
|
|
75
|
+
: undefined,
|
|
42
76
|
});
|
|
43
|
-
|
|
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;
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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"}
|