@runnerpro/backend 1.35.0 → 1.35.1

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.
@@ -123,7 +123,8 @@ const reconocer = (params) => __awaiter(void 0, void 0, void 0, function* () {
123
123
  });
124
124
  /**
125
125
  * Cadena completa sobre un audio ya medido: guarda de silencio → motores → guarda de densidad →
126
- * corrección → una línea de log por audio (motor, duración, dB, confianza, caracteres, latencia).
126
+ * corrección → una línea de log por audio (motor, duración, dB, confianza, caracteres, latencia y
127
+ * en qué acabó la corrección).
127
128
  *
128
129
  * @param params - Audio original, WAV opcional, medidas y contexto
129
130
  * @returns Transcripción o marcador
@@ -172,11 +173,14 @@ const transcribirMedido = (params) => __awaiter(void 0, void 0, void 0, function
172
173
  registrar({ motor, resultado: 'densidad imposible', chars: text.length });
173
174
  return MARCADOR_NO_TRANSCRITO;
174
175
  }
175
- const { texto, sustituciones } = yield (0, correccionTranscripcion_1.corregirTranscripcion)(text, params.contexto);
176
+ const { texto, sustituciones, estado } = yield (0, correccionTranscripcion_1.corregirTranscripcion)(text, params.contexto);
176
177
  registrar({
177
178
  motor,
178
179
  conf: confidence,
179
180
  chars: texto.length,
181
+ // ⭐ `correccion` separa «el modelo no vio nada que corregir» de «no contestó»: con solo el
182
+ // contador, un LITE caído se leería igual que un audio limpio (0/0) y no se notaría nunca
183
+ correccion: estado,
180
184
  sustituciones: `${sustituciones.filter((sustitucion) => sustitucion.aceptada).length}/${sustituciones.length}`,
181
185
  });
182
186
  return recortado && wav ? `${texto} (Solo se transcribieron los primeros ${Math.round(TRANSCRIPTION_MAX_SECONDS / 60)} minutos.)` : texto;
@@ -243,7 +243,7 @@ Devuelve SOLO la transcripción corregida, sin comentarios.`;
243
243
  * Pide al modelo LITE una propuesta de corrección; si no llega a tiempo, devuelve null
244
244
  *
245
245
  * @param prompt - Prompt de corrección
246
- * @returns Texto propuesto, o null
246
+ * @returns Texto propuesto (null si no llegó nada) y si fue por agotarse el tiempo
247
247
  */
248
248
  const pedirPropuesta = (prompt) => __awaiter(void 0, void 0, void 0, function* () {
249
249
  const llamada = (0, index_1.generateText)({
@@ -252,8 +252,8 @@ const pedirPropuesta = (prompt) => __awaiter(void 0, void 0, void 0, function* (
252
252
  // ⭐ Sin registro en LLM CACHE: una transcripción no vale como clave y engorda la tabla
253
253
  log: false,
254
254
  providerOptions: { openai: { reasoningEffort: 'low' } },
255
- }).then((resultado) => ((resultado === null || resultado === void 0 ? void 0 : resultado.text) || '').trim());
256
- const timeout = new Promise((resolve) => setTimeout(() => resolve(null), CORRECCION_TIMEOUT_MS));
255
+ }).then((resultado) => ({ propuesta: ((resultado === null || resultado === void 0 ? void 0 : resultado.text) || '').trim(), agotado: false }));
256
+ const timeout = new Promise((resolve) => setTimeout(() => resolve({ propuesta: null, agotado: true }), CORRECCION_TIMEOUT_MS));
257
257
  return Promise.race([llamada, timeout]);
258
258
  });
259
259
  /**
@@ -263,22 +263,30 @@ const pedirPropuesta = (prompt) => __awaiter(void 0, void 0, void 0, function* (
263
263
  *
264
264
  * @param texto - Transcripción tal como sale del reconocedor
265
265
  * @param contexto - Nombres y últimos mensajes del chat
266
- * @returns Texto corregido y la lista de sustituciones propuestas con su veredicto
266
+ * @returns Texto corregido, las sustituciones propuestas con su veredicto y en qué acabó la capa
267
267
  *
268
268
  * @example
269
269
  * ```typescript
270
- * const { texto, sustituciones } = await corregirTranscripcion('Hoy he hecho Farley con el garam', { nombres: ['Ana', 'Rubén'] });
271
- * // texto: 'Hoy he hecho fartlek con el Garmin'
270
+ * const { texto, estado } = await corregirTranscripcion('Hoy he hecho Farley con el garam', { nombres: ['Ana', 'Rubén'] });
271
+ * // texto: 'Hoy he hecho fartlek con el Garmin', estado: 'aplicada'
272
272
  * ```
273
273
  */
274
274
  const corregirTranscripcion = (texto, contexto) => __awaiter(void 0, void 0, void 0, function* () {
275
- const sinCambios = { texto, sustituciones: [] };
275
+ const sinCorregir = (estado) => ({ texto, sustituciones: [], estado });
276
276
  if (!texto || texto.length < CORRECCION_MIN_CARACTERES || process.env.TRANSCRIPCION_CORRECCION === 'off')
277
- return sinCambios;
277
+ return sinCorregir('omitida');
278
278
  try {
279
- const propuesta = yield pedirPropuesta(promptCorreccion(texto, contexto || {}));
280
- if (!propuesta || normalizar(propuesta) === normalizar(texto))
281
- return sinCambios;
279
+ const { propuesta, agotado } = yield pedirPropuesta(promptCorreccion(texto, contexto || {}));
280
+ // ⚠️ El timeout se avisa: es la única forma de enterarse de que el LITE dejó de contestar
281
+ if (agotado) {
282
+ // eslint-disable-next-line no-console
283
+ console.error(`[corregirTranscripcion] El modelo no contestó en ${CORRECCION_TIMEOUT_MS} ms: se guarda sin corregir`);
284
+ return sinCorregir('timeout');
285
+ }
286
+ if (!propuesta)
287
+ return sinCorregir('sin propuesta');
288
+ if (normalizar(propuesta) === normalizar(texto))
289
+ return sinCorregir('sin cambios');
282
290
  const nombres = ((contexto === null || contexto === void 0 ? void 0 : contexto.nombres) || []).filter(Boolean);
283
291
  const canonicas = new Map();
284
292
  for (const entrada of [...GLOSARIO_RUNNING, ...nombres]) {
@@ -302,12 +310,16 @@ const corregirTranscripcion = (texto, contexto) => __awaiter(void 0, void 0, voi
302
310
  if (aceptada)
303
311
  aceptadas.push(tramo);
304
312
  }
305
- return { texto: aceptadas.length ? aplicar(texto, aceptadas, canonicas) : texto, sustituciones };
313
+ return {
314
+ texto: aceptadas.length ? aplicar(texto, aceptadas, canonicas) : texto,
315
+ sustituciones,
316
+ estado: aceptadas.length ? 'aplicada' : 'rechazada',
317
+ };
306
318
  }
307
319
  catch (error) {
308
320
  // eslint-disable-next-line no-console
309
321
  console.error('[corregirTranscripcion] Se guarda sin corregir:', (error === null || error === void 0 ? void 0 : error.message) || error);
310
- return sinCambios;
322
+ return sinCorregir('error');
311
323
  }
312
324
  });
313
325
  exports.corregirTranscripcion = corregirTranscripcion;
@@ -1 +1 @@
1
- {"version":3,"file":"audio.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/audio.ts"],"names":[],"mappings":";AAKA,OAAO,EAA2C,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAG3G,QAAA,MAAM,yBAAyB,MAAM,CAAC;AAItC,QAAA,MAAM,0BAA0B,KAAK,CAAC;AAKtC,QAAA,MAAM,gBAAgB,gCAAgC,CAAC;AACvD,QAAA,MAAM,sBAAsB,0BAA0B,CAAC;AACvD,QAAA,MAAM,gBAAgB,sCAAsC,CAAC;AAC7D,QAAA,MAAM,gBAAgB,UAA+D,CAAC;AAMtF;;;;;;GAMG;AACH,QAAA,MAAM,eAAe,eAAgB,MAAM,aAAa,MAAM,KAAG,QAAQ;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAuBtG,CAAC;AAgJL;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,QAAA,MAAM,eAAe,eAAsB,MAAM,YAAY,MAAM,aAAa,MAAM,aAAa,qBAAqB,GAAG,IAAI,KAAG,QAAQ,MAAM,CAG/I,CAAC;AAEF;;;;;;;GAOG;AACH,QAAA,MAAM,gBAAgB,cAAqB,MAAM,aAAa,qBAAqB,GAAG,IAAI,KAAG,QAAQ,MAAM,CAK1G,CAAC;AAEF,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAChB,yBAAyB,EACzB,0BAA0B,GAC3B,CAAC;AACF,YAAY,EAAE,qBAAqB,EAAE,CAAC"}
1
+ {"version":3,"file":"audio.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/audio.ts"],"names":[],"mappings":";AAKA,OAAO,EAA2C,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAG3G,QAAA,MAAM,yBAAyB,MAAM,CAAC;AAItC,QAAA,MAAM,0BAA0B,KAAK,CAAC;AAKtC,QAAA,MAAM,gBAAgB,gCAAgC,CAAC;AACvD,QAAA,MAAM,sBAAsB,0BAA0B,CAAC;AACvD,QAAA,MAAM,gBAAgB,sCAAsC,CAAC;AAC7D,QAAA,MAAM,gBAAgB,UAA+D,CAAC;AAMtF;;;;;;GAMG;AACH,QAAA,MAAM,eAAe,eAAgB,MAAM,aAAa,MAAM,KAAG,QAAQ;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAuBtG,CAAC;AAoJL;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,QAAA,MAAM,eAAe,eAAsB,MAAM,YAAY,MAAM,aAAa,MAAM,aAAa,qBAAqB,GAAG,IAAI,KAAG,QAAQ,MAAM,CAG/I,CAAC;AAEF;;;;;;;GAOG;AACH,QAAA,MAAM,gBAAgB,cAAqB,MAAM,aAAa,qBAAqB,GAAG,IAAI,KAAG,QAAQ,MAAM,CAK1G,CAAC;AAEF,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAChB,yBAAyB,EACzB,0BAA0B,GAC3B,CAAC;AACF,YAAY,EAAE,qBAAqB,EAAE,CAAC"}
@@ -18,6 +18,20 @@ type Sustitucion = {
18
18
  a: string;
19
19
  aceptada: boolean;
20
20
  };
21
+ /**
22
+ * En qué acabó la capa de corrección. Va en la línea de log de cada audio para poder distinguir
23
+ * «el modelo no vio nada que corregir» de «el modelo no llegó a tiempo»: sin esto, una caída
24
+ * silenciosa del LITE dejaría la corrección apagada de hecho y el log seguiría diciendo 0/0.
25
+ *
26
+ * - `omitida`: texto demasiado corto o TRANSCRIPCION_CORRECCION=off; no se llamó al modelo
27
+ * - `timeout`: el modelo no contestó en CORRECCION_TIMEOUT_MS
28
+ * - `error`: la llamada falló
29
+ * - `sin propuesta`: contestó vacío
30
+ * - `sin cambios`: propuso exactamente el mismo texto
31
+ * - `rechazada`: propuso cambios y el filtro determinista los tumbó todos
32
+ * - `aplicada`: al menos una sustitución pasó el filtro
33
+ */
34
+ type EstadoCorreccion = 'omitida' | 'timeout' | 'error' | 'sin propuesta' | 'sin cambios' | 'rechazada' | 'aplicada';
21
35
  /**
22
36
  * Normaliza para comparar: minúsculas, sin acentos, solo letras, dígitos y espacios
23
37
  *
@@ -32,18 +46,19 @@ declare const normalizar: (texto: string) => string;
32
46
  *
33
47
  * @param texto - Transcripción tal como sale del reconocedor
34
48
  * @param contexto - Nombres y últimos mensajes del chat
35
- * @returns Texto corregido y la lista de sustituciones propuestas con su veredicto
49
+ * @returns Texto corregido, las sustituciones propuestas con su veredicto y en qué acabó la capa
36
50
  *
37
51
  * @example
38
52
  * ```typescript
39
- * const { texto, sustituciones } = await corregirTranscripcion('Hoy he hecho Farley con el garam', { nombres: ['Ana', 'Rubén'] });
40
- * // texto: 'Hoy he hecho fartlek con el Garmin'
53
+ * const { texto, estado } = await corregirTranscripcion('Hoy he hecho Farley con el garam', { nombres: ['Ana', 'Rubén'] });
54
+ * // texto: 'Hoy he hecho fartlek con el Garmin', estado: 'aplicada'
41
55
  * ```
42
56
  */
43
57
  declare const corregirTranscripcion: (texto: string, contexto?: ContextoTranscripcion | null) => Promise<{
44
58
  texto: string;
45
59
  sustituciones: Sustitucion[];
60
+ estado: EstadoCorreccion;
46
61
  }>;
47
62
  export { corregirTranscripcion, GLOSARIO_RUNNING, normalizar };
48
- export type { ContextoTranscripcion, MensajePrevio, Sustitucion };
63
+ export type { ContextoTranscripcion, EstadoCorreccion, MensajePrevio, Sustitucion };
49
64
  //# sourceMappingURL=correccionTranscripcion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"correccionTranscripcion.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/correccionTranscripcion.ts"],"names":[],"mappings":"AAWA,QAAA,MAAM,gBAAgB,EAAE,MAAM,EAqD7B,CAAC;AAWF,KAAK,aAAa,GAAG;IAAE,KAAK,EAAE,SAAS,GAAG,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,KAAK,qBAAqB,GAAG;IAC3B,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,+FAA+F;IAC/F,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,iEAAiE;IACjE,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;CAC3B,CAAC;AAEF,KAAK,WAAW,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC;AAIhE;;;;;GAKG;AACH,QAAA,MAAM,UAAU,UAAW,MAAM,KAAG,MAOzB,CAAC;AAiKZ;;;;;;;;;;;;;;GAcG;AACH,QAAA,MAAM,qBAAqB,UAAiB,MAAM,aAAa,qBAAqB,GAAG,IAAI;WAAoB,MAAM;mBAAiB,WAAW,EAAE;EAqClJ,CAAC;AAEF,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC;AAC/D,YAAY,EAAE,qBAAqB,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"correccionTranscripcion.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/correccionTranscripcion.ts"],"names":[],"mappings":"AAWA,QAAA,MAAM,gBAAgB,EAAE,MAAM,EAqD7B,CAAC;AAWF,KAAK,aAAa,GAAG;IAAE,KAAK,EAAE,SAAS,GAAG,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,KAAK,qBAAqB,GAAG;IAC3B,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,+FAA+F;IAC/F,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,iEAAiE;IACjE,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;CAC3B,CAAC;AAEF,KAAK,WAAW,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC;AAEhE;;;;;;;;;;;;GAYG;AACH,KAAK,gBAAgB,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,eAAe,GAAG,aAAa,GAAG,WAAW,GAAG,UAAU,CAAC;AAIrH;;;;;GAKG;AACH,QAAA,MAAM,UAAU,UAAW,MAAM,KAAG,MAOzB,CAAC;AAmKZ;;;;;;;;;;;;;;GAcG;AACH,QAAA,MAAM,qBAAqB,UAClB,MAAM,aACF,qBAAqB,GAAG,IAAI;WACrB,MAAM;mBAAiB,WAAW,EAAE;YAAU,gBAAgB;EAgDjF,CAAC;AAEF,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC;AAC/D,YAAY,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runnerpro/backend",
3
- "version": "1.35.0",
3
+ "version": "1.35.1",
4
4
  "description": "A collection of common backend functions",
5
5
  "exports": {
6
6
  ".": "./lib/cjs/index.js"