paperclip-plugin-autopilot-ops 0.1.44 → 0.1.45

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/dist/manifest.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/manifest.ts
2
2
  var PLUGIN_ID = "alephoo.autopilot-ops";
3
- var PLUGIN_VERSION = "0.1.44";
3
+ var PLUGIN_VERSION = "0.1.45";
4
4
  var DB_NAMESPACE_SLUG = "autopilot_ops";
5
5
  var PAGE_ROUTE = "autopilot";
6
6
  var TOOL_NAMES = {
package/dist/ui/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
 
9
9
  // src/manifest.ts
10
10
  var PLUGIN_ID = "alephoo.autopilot-ops";
11
- var PLUGIN_VERSION = "0.1.44";
11
+ var PLUGIN_VERSION = "0.1.45";
12
12
  var DB_NAMESPACE_SLUG = "autopilot_ops";
13
13
  var PAGE_ROUTE = "autopilot";
14
14
  var TOOL_NAMES = {
package/dist/worker.js CHANGED
@@ -39932,7 +39932,7 @@ function startWorkerRpcHost(options) {
39932
39932
 
39933
39933
  // src/manifest.ts
39934
39934
  var PLUGIN_ID = "alephoo.autopilot-ops";
39935
- var PLUGIN_VERSION = "0.1.44";
39935
+ var PLUGIN_VERSION = "0.1.45";
39936
39936
  var DB_NAMESPACE_SLUG = "autopilot_ops";
39937
39937
  var PAGE_ROUTE = "autopilot";
39938
39938
  var TOOL_NAMES = {
@@ -47003,6 +47003,21 @@ var MAX_LARGO_LECTURA = 900;
47003
47003
  var MAX_LARGO_PERIODO = 60;
47004
47004
  var MAX_LARGO_DESCRIPCION = 160;
47005
47005
  var MAX_LARGO_CONTEXTO = 120;
47006
+ var MAX_LARGO_TITULO = 60;
47007
+ var MAX_PRIMERA_ORACION = 160;
47008
+ var MESES_RE = "(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|setiembre|octubre|noviembre|diciembre) \\d{4}";
47009
+ var PERIODO_RE = new RegExp(`^(${MESES_RE}( a ${MESES_RE})?|al \\d{2}/\\d{2}/\\d{4})$`, "i");
47010
+ function primeraOracion(texto10) {
47011
+ const re = /\.\s+(?=[A-ZÁÉÍÓÚÑ¿¡«(])/g;
47012
+ let m;
47013
+ while (m = re.exec(texto10)) {
47014
+ const ultima = texto10.slice(0, m.index).split(/\s/).pop() ?? "";
47015
+ if (/^(dr|dra|sr|sra|lic|ing|aprox|etc|nro|art|av|[a-záéíóúñ])$/i.test(ultima) || m.index < 20) continue;
47016
+ return texto10.slice(0, m.index + 1);
47017
+ }
47018
+ return texto10;
47019
+ }
47020
+ var sinApertura = (c) => JSON.stringify(Object.fromEntries(Object.entries(c.parametros).filter(([k]) => k !== "por").sort(([a], [b]) => a.localeCompare(b))));
47006
47021
  function marcaDelSistemaEn(texto10) {
47007
47022
  const m = /\bAlephoo\b|\b[Ii][Dd] \d+\b/.exec(texto10);
47008
47023
  return m ? m[0] : null;
@@ -47059,6 +47074,7 @@ function validarWidgets(entrada) {
47059
47074
  return { x: texto9(po.x, 40, `${ref}.puntos[${j}].x`, problemas, true) ?? "", y: numero2(po.y, `${ref}.puntos[${j}].y`, problemas) };
47060
47075
  });
47061
47076
  if (unidad === "%" && !ES_VARIACION.test(titulo)) serie2.forEach((p, j) => controlarPorcentaje(p.y, `${ref}.puntos[${j}].y`, problemas));
47077
+ if (!unidad) problemas.push(`${ref}.unidad: una curva lleva su unidad (\xABturnos\xBB, \xAB$\xBB, \xAB%\xBB)`);
47062
47078
  const { calculo, origen } = leerCalculo(o.calculo, ref, problemas);
47063
47079
  salida.push({ tipo, titulo, unidad, puntos: serie2, ancho: a, ...calculo ? { calculo } : {}, origen });
47064
47080
  break;
@@ -47085,7 +47101,10 @@ function validarWidgets(entrada) {
47085
47101
  break;
47086
47102
  }
47087
47103
  case "texto": {
47088
- salida.push({ tipo, titulo: texto9(o.titulo, 120, `${ref}.titulo`, problemas), texto: texto9(o.texto, 4e3, `${ref}.texto`, problemas, true) ?? "", ancho: a });
47104
+ const lectura = (texto9(o.texto, 4e3, `${ref}.texto`, problemas, true) ?? "").replace(/\*\*/g, "");
47105
+ const primera = primeraOracion(lectura.split(/\n{2,}/)[0]?.trim() ?? "");
47106
+ if (primera.length > MAX_PRIMERA_ORACION) problemas.push(`${ref}.texto: la primera oraci\xF3n tiene ${primera.length} caracteres: hasta ${MAX_PRIMERA_ORACION} (una acci\xF3n para la direcci\xF3n con un n\xFAmero; lo que la sostiene, despu\xE9s)`);
47107
+ salida.push({ tipo, titulo: texto9(o.titulo, 120, `${ref}.titulo`, problemas), texto: lectura, ancho: a });
47089
47108
  break;
47090
47109
  }
47091
47110
  }
@@ -47116,6 +47135,15 @@ function validarWidgets(entrada) {
47116
47135
  const marca = nombres.map(marcaDelSistemaEn).find(Boolean);
47117
47136
  if (marca) problemas.push(`widgets[${k}]: \xAB${marca}\xBB no es un dato de la instituci\xF3n (un usuario o la marca del sistema): sac\xE1 esa fila o agrupala en \xABSin asignar\xBB`);
47118
47137
  }
47138
+ for (const [k, w] of salida.entries()) {
47139
+ if (w.tipo !== "barras" || !w.calculo || w.unidad && /%|promedio|tasa/i.test(w.unidad)) continue;
47140
+ const metrica = w.calculo.metricas[0]?.id;
47141
+ const ind = salida.find((x) => x.tipo === "indicador" && typeof x.valor === "number" && !!x.calculo && x.calculo.metricas[0]?.id === metrica && sinApertura(x.calculo) === sinApertura(w.calculo));
47142
+ if (!ind) continue;
47143
+ const suma = w.series.reduce((a, s) => a + s.valor, 0);
47144
+ const valor = ind.valor;
47145
+ if (Math.abs(suma - valor) > Math.max(0.5, Math.abs(valor) * 5e-3)) problemas.push(`widgets[${k}]: las barras suman ${Math.round(suma * 100) / 100} y el indicador \xAB${ind.etiqueta}\xBB (mismo c\xE1lculo) dice ${valor}: agreg\xE1 la barra que falta (\xABSin \u2026\xBB u \xABOtros\xBB) o us\xE1 el mismo per\xEDodo`);
47146
+ }
47119
47147
  const textos = salida.filter((w) => w.tipo === "texto");
47120
47148
  if (textos.length > MAX_TEXTOS) problemas.push(`un solo widget de texto (\xABLectura\xBB): lo que cambi\xF3 va en una frase al final de ella, el resto en el comentario de la tarea`);
47121
47149
  for (const t6 of textos) if (t6.texto.length > MAX_LARGO_LECTURA) problemas.push(`la Lectura tiene ${t6.texto.length} caracteres: hasta ${MAX_LARGO_LECTURA} (2 o 3 p\xE1rrafos breves; el primero, qu\xE9 conviene hacer)`);
@@ -47171,6 +47199,12 @@ async function publicarTablero(ctx, input2) {
47171
47199
  if (typeof input2.periodo === "string" && input2.periodo.trim().length > MAX_LARGO_PERIODO) {
47172
47200
  throw new OpsError("tablero_invalido", `periodo: hasta ${MAX_LARGO_PERIODO} caracteres (p. ej. \xABoctubre 2025 a septiembre 2026\xBB); las aclaraciones van en la descripci\xF3n`);
47173
47201
  }
47202
+ if (typeof input2.periodo === "string" && input2.periodo.trim() && !PERIODO_RE.test(input2.periodo.trim())) {
47203
+ throw new OpsError("tablero_invalido", `periodo: \xAB${input2.periodo.trim()}\xBB no tiene la forma de siempre: \xABseptiembre 2026\xBB, \xABoctubre 2025 a septiembre 2026\xBB o \xABal 24/10/2026\xBB (lo dem\xE1s va en la descripci\xF3n)`);
47204
+ }
47205
+ if (titulo.length > MAX_LARGO_TITULO) {
47206
+ throw new OpsError("tablero_invalido", `titulo: hasta ${MAX_LARGO_TITULO} caracteres (entra en dos renglones de la tarjeta); el detalle va en la descripci\xF3n`);
47207
+ }
47174
47208
  const widgets = validarWidgets(input2.widgets);
47175
47209
  const fuentes = arr(input2.fuentes).filter((f) => typeof f === "string" && f.trim()).map((f) => String(f).trim().slice(0, 120)).slice(0, 12);
47176
47210
  const limpio = (v, max) => typeof v === "string" && v.trim() ? v.trim().slice(0, max) : null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paperclip-plugin-autopilot-ops",
3
- "version": "0.1.44",
3
+ "version": "0.1.45",
4
4
  "type": "module",
5
5
  "description": "Autopilot Care · operación autónoma gobernada para instituciones de salud: workflows determinísticos, validaciones, registro de negocio, políticas (observa/propone/ejecuta/corte) y tablero del director, como plugin de Paperclip.",
6
6
  "files": [