@runnerpro/backend 1.22.8 → 1.23.0
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 +5 -4
- package/lib/cjs/index.js +5 -1
- package/lib/cjs/mediaProcessing/audio.js +216 -0
- package/lib/cjs/mediaProcessing/documents.js +225 -0
- package/lib/cjs/mediaProcessing/ffmpegUtils.js +107 -0
- package/lib/cjs/mediaProcessing/image.js +59 -0
- package/lib/cjs/mediaProcessing/index.js +145 -132
- package/lib/cjs/mediaProcessing/video.js +149 -0
- package/lib/cjs/prompt/ai.js +29 -1
- package/lib/cjs/types/chat/api/conversation.d.ts.map +1 -1
- package/lib/cjs/types/index.d.ts +2 -2
- package/lib/cjs/types/index.d.ts.map +1 -1
- package/lib/cjs/types/mediaProcessing/audio.d.ts +63 -0
- package/lib/cjs/types/mediaProcessing/audio.d.ts.map +1 -0
- package/lib/cjs/types/mediaProcessing/documents.d.ts +79 -0
- package/lib/cjs/types/mediaProcessing/documents.d.ts.map +1 -0
- package/lib/cjs/types/mediaProcessing/ffmpegUtils.d.ts +31 -0
- package/lib/cjs/types/mediaProcessing/ffmpegUtils.d.ts.map +1 -0
- package/lib/cjs/types/mediaProcessing/image.d.ts +20 -0
- package/lib/cjs/types/mediaProcessing/image.d.ts.map +1 -0
- package/lib/cjs/types/mediaProcessing/index.d.ts +41 -28
- package/lib/cjs/types/mediaProcessing/index.d.ts.map +1 -1
- package/lib/cjs/types/mediaProcessing/video.d.ts +21 -0
- package/lib/cjs/types/mediaProcessing/video.d.ts.map +1 -0
- package/lib/cjs/types/prompt/ai.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
declare const AUDIO_ENCODING_MAP: Record<string, string>;
|
|
3
|
+
declare const SYNC_MAX_SECONDS = 55;
|
|
4
|
+
/**
|
|
5
|
+
* Transcribe con un modelo multimodal de Google. Es la red que recoge lo que Speech-to-Text
|
|
6
|
+
* no reconoce y, sobre todo, los audios de más de 60s, que el modo síncrono no admite.
|
|
7
|
+
*
|
|
8
|
+
* @param wavBuffer - Buffer WAV mono 16 kHz
|
|
9
|
+
* @returns Promise<string | null> - Transcripción, o null si no hay voz
|
|
10
|
+
*/
|
|
11
|
+
declare const transcribeWithModel: (wavBuffer: Buffer) => Promise<string | null>;
|
|
12
|
+
/**
|
|
13
|
+
* Convierte cualquier audio al formato que espera Speech-to-Text (WAV PCM mono 16 kHz)
|
|
14
|
+
*
|
|
15
|
+
* @param fileBuffer - Buffer del audio original
|
|
16
|
+
* @param filename - Nombre original del archivo
|
|
17
|
+
* @returns WAV mono 16 kHz y la duración original en segundos
|
|
18
|
+
*/
|
|
19
|
+
declare const convertToWav16k: (fileBuffer: Buffer, filename?: string) => Promise<{
|
|
20
|
+
wav: Buffer;
|
|
21
|
+
duration: number;
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* Transcribe una nota de voz.
|
|
25
|
+
*
|
|
26
|
+
* El audio se normaliza a WAV mono 16 kHz y luego se elige motor por duración:
|
|
27
|
+
* - hasta 55s → Speech-to-Text, que es barato y preciso.
|
|
28
|
+
* - más de 55s → modelo multimodal, porque `recognize` no admite audios más largos y
|
|
29
|
+
* `longRunningRecognize` exige subir el archivo a GCS antes.
|
|
30
|
+
* - si Speech-to-Text no reconoce nada, se reintenta con el modelo antes de darlo por perdido.
|
|
31
|
+
*
|
|
32
|
+
* ⚠️ El orden importa y no es intercambiable. Medido sobre notas de voz reales de producción
|
|
33
|
+
* que hoy acaban en '[Audio sin contenido reconocible]':
|
|
34
|
+
* - mandar el AAC crudo declarando 'MP3' (lo que se hacía): 0 de 14 recuperadas.
|
|
35
|
+
* - convertir a WAV y declarar LINEAR16: 13 de 14 (la que falla es de 81s).
|
|
36
|
+
* - modelo multimodal: 14 de 14.
|
|
37
|
+
* Y a la inversa, convertir a WAV SIN respetar el límite de 55s rompe los audios largos que hoy
|
|
38
|
+
* sí funcionan (4 de 4 medidos): con LINEAR16 la API deduce la duración exacta y los rechaza,
|
|
39
|
+
* mientras que con un códec comprimido declarado se saltaba esa comprobación.
|
|
40
|
+
*
|
|
41
|
+
* @param fileBuffer - Buffer del archivo de audio
|
|
42
|
+
* @param mimetype - Tipo MIME del archivo (ej: 'audio/aac', 'audio/x-m4a')
|
|
43
|
+
* @param filename - Nombre original del archivo
|
|
44
|
+
* @returns Promise<string> - Transcripción del audio
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const transcription = await transcribeAudio(audioBuffer, 'audio/aac', 'audio.aac');
|
|
49
|
+
* // Resultado: "Hola, quería comentarte que hoy me duele un poco la rodilla..."
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
declare const transcribeAudio: (fileBuffer: Buffer, mimetype: string, filename?: string) => Promise<string>;
|
|
53
|
+
/**
|
|
54
|
+
* Transcribe un WAV que ya viene en el formato que espera Speech-to-Text
|
|
55
|
+
* (PCM 16 bits, mono, 16 kHz) y dura menos de 55 segundos. Lo usa el análisis de vídeo,
|
|
56
|
+
* que extrae la pista así y ya la recorta.
|
|
57
|
+
*
|
|
58
|
+
* @param wavBuffer - Buffer WAV mono 16 kHz de menos de 55 segundos
|
|
59
|
+
* @returns Promise<string> - Transcripción del audio
|
|
60
|
+
*/
|
|
61
|
+
declare const transcribeWav16k: (wavBuffer: Buffer) => Promise<string>;
|
|
62
|
+
export { transcribeAudio, transcribeWav16k, transcribeWithModel, convertToWav16k, AUDIO_ENCODING_MAP, SYNC_MAX_SECONDS };
|
|
63
|
+
//# sourceMappingURL=audio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/audio.ts"],"names":[],"mappings":";AAUA,QAAA,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAa9C,CAAC;AAIF,QAAA,MAAM,gBAAgB,KAAK,CAAC;AAoD5B;;;;;;GAMG;AACH,QAAA,MAAM,mBAAmB,cAAqB,MAAM,KAAG,QAAQ,MAAM,GAAG,IAAI,CA4B3E,CAAC;AAEF;;;;;;GAMG;AACH,QAAA,MAAM,eAAe,eAAgB,MAAM,aAAa,MAAM,KAAG,QAAQ;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAuBtG,CAAC;AAEL;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,QAAA,MAAM,eAAe,eAAsB,MAAM,YAAY,MAAM,aAAa,MAAM,KAAG,QAAQ,MAAM,CA4BtG,CAAC;AAEF;;;;;;;GAOG;AACH,QAAA,MAAM,gBAAgB,cAAqB,MAAM,KAAG,QAAQ,MAAM,CAGjE,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,eAAe,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
declare const MAX_MODEL_FILE_BYTES: number;
|
|
3
|
+
/**
|
|
4
|
+
* Formatea un tamaño en bytes de forma legible en español (1024 → "1 KB")
|
|
5
|
+
*
|
|
6
|
+
* @param bytes - Tamaño en bytes
|
|
7
|
+
* @returns Tamaño legible con unidad
|
|
8
|
+
*/
|
|
9
|
+
declare const formatBytes: (bytes: number) => string;
|
|
10
|
+
/**
|
|
11
|
+
* Heurística para saber si un buffer es texto plano legible.
|
|
12
|
+
* Útil cuando el cliente manda un .gpx o un .csv como 'application/octet-stream'.
|
|
13
|
+
*
|
|
14
|
+
* @param fileBuffer - Buffer del archivo
|
|
15
|
+
* @returns true si los primeros KB parecen texto UTF-8
|
|
16
|
+
*/
|
|
17
|
+
declare const looksLikeText: (fileBuffer: Buffer) => boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Decodifica un buffer de texto respetando su BOM.
|
|
20
|
+
*
|
|
21
|
+
* Importa porque los .txt y .csv guardados como "Unicode" desde el Bloc de notas o Excel vienen
|
|
22
|
+
* en UTF-16: leerlos como UTF-8 intercala bytes nulos, y Postgres rechaza el carácter nulo en una
|
|
23
|
+
* columna text, así que el UPDATE de FILE TEXT fallaría (en silencio, porque query() se traga el
|
|
24
|
+
* error) y el adjunto se quedaría sin texto para siempre.
|
|
25
|
+
*
|
|
26
|
+
* @param fileBuffer - Buffer del archivo
|
|
27
|
+
* @returns Contenido decodificado
|
|
28
|
+
*/
|
|
29
|
+
declare const decodeTextBuffer: (fileBuffer: Buffer) => string;
|
|
30
|
+
/**
|
|
31
|
+
* Genera un resumen de un PDF mandándoselo entero al modelo, que lo lee de forma nativa
|
|
32
|
+
*
|
|
33
|
+
* @param fileBuffer - Buffer del PDF
|
|
34
|
+
* @param filename - Nombre original del archivo (ayuda al modelo a contextualizar)
|
|
35
|
+
* @returns Promise<string> - Resumen del documento
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const summary = await describePdf(pdfBuffer, 'informe-traumatologo.pdf');
|
|
40
|
+
* // Resultado: "Informe de traumatología del 12/03 con diagnóstico de fascitis plantar..."
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
declare const describePdf: (fileBuffer: Buffer, filename?: string) => Promise<string>;
|
|
44
|
+
/**
|
|
45
|
+
* Extrae el contenido de un archivo de texto (txt, csv, gpx, json, xml...).
|
|
46
|
+
* Los archivos cortos se guardan literales; los largos se resumen con el modelo.
|
|
47
|
+
*
|
|
48
|
+
* @param fileBuffer - Buffer del archivo
|
|
49
|
+
* @param filename - Nombre original del archivo
|
|
50
|
+
* @returns Promise<string> - Contenido literal o resumen
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const content = await describeTextFile(gpxBuffer, 'ruta-domingo.gpx');
|
|
55
|
+
* // Resultado: "Traza GPS de una carrera de 12,4 km con 340 m de desnivel..."
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
declare const describeTextFile: (fileBuffer: Buffer, filename?: string) => Promise<string>;
|
|
59
|
+
/**
|
|
60
|
+
* Ficha determinista para los archivos cuyo contenido no se puede extraer
|
|
61
|
+
* (comprimidos, binarios propietarios, ofimática antigua...).
|
|
62
|
+
*
|
|
63
|
+
* No llama a ningún modelo: su valor es que FILE TEXT nunca se quede a NULL, de forma
|
|
64
|
+
* que el entrenador sabe que hay un adjunto y de qué tipo, en vez de quedarse bloqueado.
|
|
65
|
+
*
|
|
66
|
+
* @param mimetype - Tipo MIME del archivo
|
|
67
|
+
* @param filename - Nombre original del archivo
|
|
68
|
+
* @param size - Tamaño en bytes
|
|
69
|
+
* @returns Ficha del archivo en español
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* describeOpaqueFile('application/zip', 'fotos.zip', 2515000);
|
|
74
|
+
* // "[Archivo adjunto: fotos.zip (archivo comprimido ZIP, 2,4 MB). No se puede leer su contenido automáticamente.]"
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
declare const describeOpaqueFile: (mimetype: string, filename?: string, size?: number) => string;
|
|
78
|
+
export { describePdf, describeTextFile, describeOpaqueFile, decodeTextBuffer, looksLikeText, formatBytes, MAX_MODEL_FILE_BYTES };
|
|
79
|
+
//# sourceMappingURL=documents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/documents.ts"],"names":[],"mappings":";AAIA,QAAA,MAAM,oBAAoB,QAAmB,CAAC;AAsC9C;;;;;GAKG;AACH,QAAA,MAAM,WAAW,UAAW,MAAM,KAAG,MAUpC,CAAC;AAEF;;;;;;GAMG;AACH,QAAA,MAAM,aAAa,eAAgB,MAAM,KAAG,OAW3C,CAAC;AAEF;;;;;;;;;;GAUG;AACH,QAAA,MAAM,gBAAgB,eAAgB,MAAM,KAAG,MAgB9C,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,WAAW,eAAsB,MAAM,aAAa,MAAM,KAAG,QAAQ,MAAM,CAqBhF,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,gBAAgB,eAAsB,MAAM,aAAa,MAAM,KAAG,QAAQ,MAAM,CA+BrF,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,kBAAkB,aAAc,MAAM,aAAa,MAAM,SAAS,MAAM,KAAG,MAIhF,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import ffmpeg from 'fluent-ffmpeg';
|
|
2
|
+
declare const FFMPEG_TIMEOUT_MS = 120000;
|
|
3
|
+
declare const SPEECH_SAMPLE_RATE = 16000;
|
|
4
|
+
/**
|
|
5
|
+
* Ejecuta un comando de ffmpeg como promesa, matándolo si se pasa del tiempo máximo
|
|
6
|
+
*
|
|
7
|
+
* @param command - Comando de fluent-ffmpeg ya configurado
|
|
8
|
+
* @param label - Etiqueta para el mensaje de error
|
|
9
|
+
*/
|
|
10
|
+
declare const runFfmpeg: (command: any, label: string) => Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Lee duración y pistas disponibles de un archivo multimedia con ffprobe
|
|
13
|
+
*
|
|
14
|
+
* @param inputPath - Ruta del archivo en disco
|
|
15
|
+
* @returns Duración en segundos y si tiene pista de vídeo y de audio
|
|
16
|
+
*/
|
|
17
|
+
declare const probeMedia: (inputPath: string) => Promise<{
|
|
18
|
+
duration: number;
|
|
19
|
+
hasAudio: boolean;
|
|
20
|
+
hasVideo: boolean;
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* Crea un directorio temporal, ejecuta el trabajo y lo borra pase lo que pase.
|
|
24
|
+
* En Cloud Run el temporal vive en RAM, así que dejarlo sin borrar cuesta memoria.
|
|
25
|
+
*
|
|
26
|
+
* @param work - Función que recibe la ruta del directorio temporal
|
|
27
|
+
* @returns Lo que devuelva `work`
|
|
28
|
+
*/
|
|
29
|
+
declare const withTempDir: <T>(work: (dir: string) => Promise<T>) => Promise<T>;
|
|
30
|
+
export { ffmpeg, runFfmpeg, probeMedia, withTempDir, FFMPEG_TIMEOUT_MS, SPEECH_SAMPLE_RATE };
|
|
31
|
+
//# sourceMappingURL=ffmpegUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ffmpegUtils.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/ffmpegUtils.ts"],"names":[],"mappings":"AAGA,OAAO,MAAM,MAAM,eAAe,CAAC;AASnC,QAAA,MAAM,iBAAiB,SAAS,CAAC;AAGjC,QAAA,MAAM,kBAAkB,QAAQ,CAAC;AAEjC;;;;;GAKG;AACH,QAAA,MAAM,SAAS,YAAa,GAAG,SAAS,MAAM,KAAG,QAAQ,IAAI,CAqBzD,CAAC;AAEL;;;;;GAKG;AACH,QAAA,MAAM,UAAU,cAAe,MAAM,KAAG,QAAQ;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAetG,CAAC;AAEL;;;;;;GAMG;AAEH,QAAA,MAAM,WAAW,kBAAyB,MAAM,8BAW/C,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
declare const IMAGE_DESCRIPTION_PROMPT = "Describe esta imagen de forma directa y completa en un solo p\u00E1rrafo continuo, sin introducciones ni listas.\nSi la imagen es de contenido deportivo (captura de Garmin/Strava/reloj deportivo, foto de lesi\u00F3n/dolor, gr\u00E1fica de entrenamiento, selfie deportivo, foto de equipamiento, datos de entrenamiento, etc.), incluye el tipo de imagen, los datos relevantes si es una captura (ritmo, distancia, frecuencia card\u00EDaca, zonas, etc.), y cualquier contexto \u00FAtil para entender el estado del atleta o su entrenamiento.\nSi la imagen NO es deportiva, describe su contenido de forma general pero \u00FAtil para entender el contexto de la conversaci\u00F3n.\nDevuelve \u00DANICAMENTE la descripci\u00F3n en espa\u00F1ol, sin comentarios adicionales ni formato de lista. M\u00E1ximo 300 palabras.";
|
|
3
|
+
/**
|
|
4
|
+
* Genera una descripción de una imagen usando el modelo de visión (Vercel AI SDK)
|
|
5
|
+
* Contextualizada para una aplicación de fitness/entrenamiento
|
|
6
|
+
*
|
|
7
|
+
* @param fileBuffer - Buffer del archivo de imagen
|
|
8
|
+
* @param mimetype - Tipo MIME del archivo (ej: 'image/jpeg', 'image/png')
|
|
9
|
+
* @param promptOverride - Prompt alternativo (ej: para fotogramas extraídos de un vídeo)
|
|
10
|
+
* @returns Promise<string> - Descripción de la imagen
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const description = await describeImage(imageBuffer, 'image/jpeg');
|
|
15
|
+
* // Resultado: "Captura de Garmin Connect mostrando un entrenamiento de 10km..."
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
declare const describeImage: (fileBuffer: Buffer, mimetype: string, promptOverride?: string) => Promise<string>;
|
|
19
|
+
export { describeImage, IMAGE_DESCRIPTION_PROMPT };
|
|
20
|
+
//# sourceMappingURL=image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/image.ts"],"names":[],"mappings":";AAIA,QAAA,MAAM,wBAAwB,8yBAGuF,CAAC;AAEtH;;;;;;;;;;;;;;GAcG;AACH,QAAA,MAAM,aAAa,eAAsB,MAAM,YAAY,MAAM,mBAAmB,MAAM,KAAG,QAAQ,MAAM,CAqB1G,CAAC;AAEF,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,CAAC"}
|
|
@@ -1,54 +1,67 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
import { transcribeAudio } from './audio';
|
|
3
|
+
import { describeImage } from './image';
|
|
4
|
+
import { describeVideo } from './video';
|
|
5
|
+
import { describePdf, describeTextFile, describeOpaqueFile } from './documents';
|
|
6
|
+
declare const FILE_KIND: {
|
|
7
|
+
readonly AUDIO: "AUDIO";
|
|
8
|
+
readonly IMAGE: "IMAGE";
|
|
9
|
+
readonly VIDEO: "VIDEO";
|
|
10
|
+
readonly PDF: "PDF";
|
|
11
|
+
readonly TEXT: "TEXT";
|
|
12
|
+
readonly OPAQUE: "OPAQUE";
|
|
13
|
+
};
|
|
14
|
+
type FileKind = (typeof FILE_KIND)[keyof typeof FILE_KIND];
|
|
2
15
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
16
|
+
* Decide qué extractor le toca a un archivo a partir de su MIME type, su nombre
|
|
17
|
+
* y, como último recurso, el contenido del propio buffer.
|
|
5
18
|
*
|
|
6
|
-
* @param
|
|
7
|
-
* @param
|
|
8
|
-
* @
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```typescript
|
|
12
|
-
* const transcription = await transcribeAudio(audioBuffer, 'audio/mpeg');
|
|
13
|
-
* // Resultado: "Hola, quería comentarte que hoy me duele un poco la rodilla..."
|
|
14
|
-
* ```
|
|
19
|
+
* @param mimetype - Tipo MIME declarado por el cliente
|
|
20
|
+
* @param filename - Nombre original del archivo
|
|
21
|
+
* @param fileBuffer - Buffer del archivo
|
|
22
|
+
* @returns Tipo de tratamiento a aplicar
|
|
15
23
|
*/
|
|
16
|
-
declare const
|
|
24
|
+
declare const classifyFile: (mimetype: string, filename: string | undefined, fileBuffer: Buffer) => FileKind;
|
|
17
25
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
26
|
+
* Analiza cualquier adjunto y devuelve su representación en texto.
|
|
27
|
+
*
|
|
28
|
+
* Nunca devuelve vacío: los tipos cuyo contenido no se puede extraer (comprimidos,
|
|
29
|
+
* binarios propietarios, ofimática antigua) reciben una ficha con nombre, tipo y tamaño.
|
|
30
|
+
* Esto importa porque el entrenador se salta la respuesta si un adjunto no tiene texto,
|
|
31
|
+
* y un archivo no soportado no debe distinguirse de uno que aún no se ha procesado.
|
|
20
32
|
*
|
|
21
|
-
* @param fileBuffer - Buffer del archivo
|
|
22
|
-
* @param mimetype - Tipo MIME del archivo
|
|
23
|
-
* @
|
|
33
|
+
* @param fileBuffer - Buffer del archivo
|
|
34
|
+
* @param mimetype - Tipo MIME del archivo
|
|
35
|
+
* @param filename - Nombre original del archivo
|
|
36
|
+
* @returns Promise<string> - Transcripción, descripción, resumen o ficha del archivo
|
|
24
37
|
*
|
|
25
38
|
* @example
|
|
26
39
|
* ```typescript
|
|
27
|
-
*
|
|
28
|
-
* //
|
|
40
|
+
* await analyzeFile(pdfBuffer, 'application/pdf', 'analitica.pdf');
|
|
41
|
+
* // "Analítica de sangre del 3 de junio con ferritina de 28 ng/ml..."
|
|
29
42
|
* ```
|
|
30
43
|
*/
|
|
31
|
-
declare const
|
|
44
|
+
declare const analyzeFile: (fileBuffer: Buffer, mimetype: string, filename?: string) => Promise<string>;
|
|
32
45
|
/**
|
|
33
|
-
* Procesa un
|
|
34
|
-
*
|
|
35
|
-
* - Imagen: usa Gemini (Vertex AI)
|
|
46
|
+
* Procesa un adjunto de chat y guarda su texto en la base de datos.
|
|
47
|
+
* Pensado para llamarse sin await (fire-and-forget) desde el envío del archivo.
|
|
36
48
|
*
|
|
37
49
|
* @param idMessage - ID del mensaje en CHAT MESSAGE
|
|
38
50
|
* @param fileBuffer - Buffer del archivo
|
|
39
51
|
* @param mimetype - Tipo MIME del archivo
|
|
52
|
+
* @param filename - Nombre original del archivo
|
|
40
53
|
* @returns Promise<void>
|
|
41
54
|
*
|
|
42
55
|
* @example
|
|
43
56
|
* ```typescript
|
|
44
57
|
* // No usar await para ejecutar en background
|
|
45
|
-
* processMediaFile(123, fileBuffer, '
|
|
58
|
+
* processMediaFile(123, fileBuffer, 'application/pdf', 'informe.pdf');
|
|
46
59
|
* ```
|
|
47
60
|
*/
|
|
48
|
-
declare const processMediaFile: (idMessage: number, fileBuffer: Buffer, mimetype: string) => Promise<void>;
|
|
61
|
+
declare const processMediaFile: (idMessage: number, fileBuffer: Buffer, mimetype: string, filename?: string) => Promise<void>;
|
|
49
62
|
/**
|
|
50
|
-
* Reprocesa
|
|
51
|
-
* Útil para
|
|
63
|
+
* Reprocesa los adjuntos recientes (últimos 2 días) que no tienen FILE TEXT,
|
|
64
|
+
* sea cual sea su tipo. Útil para rellenar mensajes anteriores al deploy.
|
|
52
65
|
*
|
|
53
66
|
* @param bucket - Instancia del bucket de Google Cloud Storage
|
|
54
67
|
* @returns Promise<{ processed: number; errors: number }> - Estadísticas del reprocesamiento
|
|
@@ -63,5 +76,5 @@ declare const reprocessRecentMedia: (bucket: any) => Promise<{
|
|
|
63
76
|
processed: number;
|
|
64
77
|
errors: number;
|
|
65
78
|
}>;
|
|
66
|
-
export { transcribeAudio, describeImage, processMediaFile, reprocessRecentMedia };
|
|
79
|
+
export { transcribeAudio, describeImage, describeVideo, describePdf, describeTextFile, describeOpaqueFile, classifyFile, analyzeFile, processMediaFile, reprocessRecentMedia, FILE_KIND, };
|
|
67
80
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/index.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,kBAAkB,EAAuC,MAAM,aAAa,CAAC;AAGrH,QAAA,MAAM,SAAS;;;;;;;CAOL,CAAC;AAEX,KAAK,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAiC3D;;;;;;;;GAQG;AACH,QAAA,MAAM,YAAY,aAAc,MAAM,YAAY,MAAM,GAAG,SAAS,cAAc,MAAM,KAAG,QA0B1F,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,QAAA,MAAM,WAAW,eAAsB,MAAM,YAAY,MAAM,aAAa,MAAM,KAAG,QAAQ,MAAM,CA8BlG,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,gBAAgB,cAAqB,MAAM,cAAc,MAAM,YAAY,MAAM,aAAa,MAAM,KAAG,QAAQ,IAAI,CASxH,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,oBAAoB,WAAkB,GAAG;eAAwB,MAAM;YAAU,MAAM;EAmD5F,CAAC;AAEF,OAAO,EACL,eAAe,EACf,aAAa,EACb,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,SAAS,GACV,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/**
|
|
3
|
+
* Analiza un vídeo descomponiéndolo en lo que sí sabemos leer: un fotograma
|
|
4
|
+
* representativo (descrito por el modelo de visión) y su pista de audio
|
|
5
|
+
* (transcrita con Speech-to-Text). Ambas partes son opcionales: un vídeo mudo
|
|
6
|
+
* devuelve solo la descripción visual, y uno sin imagen solo la transcripción.
|
|
7
|
+
*
|
|
8
|
+
* @param fileBuffer - Buffer del vídeo
|
|
9
|
+
* @param mimetype - Tipo MIME del archivo (ej: 'video/mp4')
|
|
10
|
+
* @param filename - Nombre original del archivo
|
|
11
|
+
* @returns Promise<string> - Descripción combinada del vídeo
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const description = await describeVideo(videoBuffer, 'video/mp4', 'tecnica.mp4');
|
|
16
|
+
* // "Vídeo de 12 s. Imagen: corredor de perfil sobre cinta... Audio: mira cómo apoyo el talón..."
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
declare const describeVideo: (fileBuffer: Buffer, mimetype: string, filename?: string) => Promise<string>;
|
|
20
|
+
export { describeVideo };
|
|
21
|
+
//# sourceMappingURL=video.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/video.ts"],"names":[],"mappings":";AAsEA;;;;;;;;;;;;;;;;GAgBG;AACH,QAAA,MAAM,aAAa,eAAsB,MAAM,YAAY,MAAM,aAAa,MAAM,KAAG,QAAQ,MAAM,CAyDpG,CAAC;AAEF,OAAO,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../../../src/prompt/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,IAAI,sBAAsB,EAAE,YAAY,IAAI,oBAAoB,EAAE,MAAM,IAAI,CAAC;AAEpG,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAwKhE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,iBAAe,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAoD/H;
|
|
1
|
+
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../../../src/prompt/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,IAAI,sBAAsB,EAAE,YAAY,IAAI,oBAAoB,EAAE,MAAM,IAAI,CAAC;AAEpG,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAwKhE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,iBAAe,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAoD/H;AAkFD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,iBAAe,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CA4C5H;AA+ED;;;;;;;;;;;;;;;;;GAiBG;AACH,iBAAe,mBAAmB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,CAAC,CAAC;IAAC,SAAS,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAgB5H;AAED,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,mBAAmB,EAAE,CAAC"}
|