xonecode 0.6.0 → 0.8.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/apps/web/dist/assets/{index-rqecK6s2.css → index-Boak51UP.css} +1 -1
- package/apps/web/dist/assets/index-Cg28x6nG.js +477 -0
- package/apps/web/dist/assets/{php-BBij3Lhc.js → php-Cu6F_QCJ.js} +1 -1
- package/apps/web/dist/assets/{ruby-Dq2YEaLo.js → ruby-BiqQPoC6.js} +1 -1
- package/apps/web/dist/index.html +2 -2
- package/dist/agent/cloudstudio/cloudstudioClient.js +10 -0
- package/dist/agent/cloudstudio/cloudstudioClient.js.map +1 -1
- package/dist/agent/cloudstudio/descarga.js +14 -4
- package/dist/agent/cloudstudio/descarga.js.map +1 -1
- package/dist/agent/cloudstudio/ramaActiva.js +11 -0
- package/dist/agent/cloudstudio/ramaActiva.js.map +1 -0
- package/dist/agent/cloudstudio/subida.js +13 -4
- package/dist/agent/cloudstudio/subida.js.map +1 -1
- package/dist/agent/config/catalogoModelos.js +45 -0
- package/dist/agent/config/catalogoModelos.js.map +1 -1
- package/dist/agent/config/modelos.js +103 -12
- package/dist/agent/config/modelos.js.map +1 -1
- package/dist/agent/config/mudanzaEnDisco.js +121 -0
- package/dist/agent/config/mudanzaEnDisco.js.map +1 -0
- package/dist/agent/config/selectorEnMaquina.js +45 -0
- package/dist/agent/config/selectorEnMaquina.js.map +1 -0
- package/dist/agent/config/settingsEnDisco.js +35 -0
- package/dist/agent/config/settingsEnDisco.js.map +1 -1
- package/dist/agent/dispositivos/juezVisual.js +152 -0
- package/dist/agent/dispositivos/juezVisual.js.map +1 -0
- package/dist/agent/dispositivos/sensorDeArranque.js +154 -0
- package/dist/agent/dispositivos/sensorDeArranque.js.map +1 -0
- package/dist/agent/exportarPdf.js +140 -0
- package/dist/agent/exportarPdf.js.map +1 -0
- package/dist/agent/grafo/criticaVisual.js +115 -0
- package/dist/agent/grafo/criticaVisual.js.map +1 -0
- package/dist/agent/grafo/navegacionXone.js +37 -4
- package/dist/agent/grafo/navegacionXone.js.map +1 -1
- package/dist/agent/grafo/perfiles.js +52 -9
- package/dist/agent/grafo/perfiles.js.map +1 -1
- package/dist/agent/grafo/proyecto.js +74 -7
- package/dist/agent/grafo/proyecto.js.map +1 -1
- package/dist/agent/grafo/skills.js +32 -0
- package/dist/agent/grafo/skills.js.map +1 -1
- package/dist/agent/grafo/xoneAgent.js +103 -13
- package/dist/agent/grafo/xoneAgent.js.map +1 -1
- package/dist/agent/navegacion/estilosEnDisco.js +110 -0
- package/dist/agent/navegacion/estilosEnDisco.js.map +1 -0
- package/dist/agent/navegacion/hechosEnDisco.js +26 -0
- package/dist/agent/navegacion/hechosEnDisco.js.map +1 -0
- package/dist/agent/navegacion/indiceEnDisco.js +15 -0
- package/dist/agent/navegacion/indiceEnDisco.js.map +1 -1
- package/dist/agent/subagentes/agentesEnDisco.js +85 -24
- package/dist/agent/subagentes/agentesEnDisco.js.map +1 -1
- package/dist/agent/subagentes/escrituraExterna.js +53 -0
- package/dist/agent/subagentes/escrituraExterna.js.map +1 -1
- package/dist/agent/subagentes/pluginDeSkills.js +99 -0
- package/dist/agent/subagentes/pluginDeSkills.js.map +1 -0
- package/dist/agent/subagentes/subagenteExterno.js +48 -0
- package/dist/agent/subagentes/subagenteExterno.js.map +1 -1
- package/dist/agent/subagentes/subagenteOpencode.js +53 -1
- package/dist/agent/subagentes/subagenteOpencode.js.map +1 -1
- package/dist/agent/tareas/juezDeTarea.js +1 -1
- package/dist/agent/tareas/juezDeTarea.js.map +1 -1
- package/dist/agent/tareas/tareasEnDisco.js +49 -0
- package/dist/agent/tareas/tareasEnDisco.js.map +1 -1
- package/dist/agent/turno/diagnosticoDeTools.js +5 -1
- package/dist/agent/turno/diagnosticoDeTools.js.map +1 -1
- package/dist/agent/turno/informeDeTraza.js +27 -4
- package/dist/agent/turno/informeDeTraza.js.map +1 -1
- package/dist/agent/turno/puente.js +24 -1
- package/dist/agent/turno/puente.js.map +1 -1
- package/dist/agent/turno/resumenDeContexto.js +88 -4
- package/dist/agent/turno/resumenDeContexto.js.map +1 -1
- package/dist/agent/turno/resumenDeTool.js +18 -0
- package/dist/agent/turno/resumenDeTool.js.map +1 -1
- package/dist/agent/turno/rubrica.js +91 -0
- package/dist/agent/turno/rubrica.js.map +1 -0
- package/dist/agent/turno/turnoReal.js +172 -11
- package/dist/agent/turno/turnoReal.js.map +1 -1
- package/dist/cli/consola.js +63 -0
- package/dist/cli/consola.js.map +1 -1
- package/dist/cli/main.js +51 -4
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/run.js +8 -0
- package/dist/cli/run.js.map +1 -1
- package/dist/core/agentes.js +111 -9
- package/dist/core/agentes.js.map +1 -1
- package/dist/core/esfuerzo.js +141 -0
- package/dist/core/esfuerzo.js.map +1 -0
- package/dist/core/estilos.js +78 -0
- package/dist/core/estilos.js.map +1 -0
- package/dist/core/exportacion.js +140 -0
- package/dist/core/exportacion.js.map +1 -0
- package/dist/core/hechosDelProyecto.js +87 -0
- package/dist/core/hechosDelProyecto.js.map +1 -0
- package/dist/core/logDeDispositivo.js +143 -0
- package/dist/core/logDeDispositivo.js.map +1 -0
- package/dist/core/modelos.js +32 -0
- package/dist/core/modelos.js.map +1 -1
- package/dist/core/mudanzaDeWorkspace.js +93 -0
- package/dist/core/mudanzaDeWorkspace.js.map +1 -0
- package/dist/core/planes.js +70 -0
- package/dist/core/planes.js.map +1 -0
- package/dist/core/ports.js +4 -0
- package/dist/core/ports.js.map +1 -1
- package/dist/core/rubrica.js +90 -0
- package/dist/core/rubrica.js.map +1 -0
- package/dist/core/selectorDeCarpeta.js +87 -0
- package/dist/core/selectorDeCarpeta.js.map +1 -0
- package/dist/core/settings.js +54 -5
- package/dist/core/settings.js.map +1 -1
- package/dist/core/shellDeAgente.js +45 -0
- package/dist/core/shellDeAgente.js.map +1 -1
- package/dist/core/topeAgotado.js +69 -0
- package/dist/core/topeAgotado.js.map +1 -0
- package/dist/web/servidor/arranque.js +324 -9
- package/dist/web/servidor/arranque.js.map +1 -1
- package/dist/web/servidor/sesiones.js +30 -2
- package/dist/web/servidor/sesiones.js.map +1 -1
- package/dist/web/servidor/transporte.js.map +1 -1
- package/dist/web/servidor/vestibulo.js +55 -6
- package/dist/web/servidor/vestibulo.js.map +1 -1
- package/package.json +2 -1
- package/skills/xone-hotswap/SKILL.md +31 -9
- package/skills/xone-hotswap/scripts/xone-arrancar-android +202 -0
- package/skills/xone-hotswap/scripts/xone-captura-android +93 -0
- package/skills/xone-hotswap/scripts/xone-desplegar-android +28 -0
- package/skills/xone-hotswap/scripts/xone-hotswap +39 -9
- package/skills/xone-hotswap/scripts/xone-reiniciar-android +28 -0
- package/skills/xone-plan-builder/SKILL.md +22 -4
- package/skills/xone-spec-builder/SKILL.md +37 -7
- package/apps/web/dist/assets/index-DBZTodio.js +0 -477
package/dist/core/agentes.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* editando un `.md` convertiría el invariante en una preferencia; es el mismo principio por
|
|
16
16
|
* el que los avisos de honestidad son código y no prompt (`core/bitacora.ts`).
|
|
17
17
|
*/
|
|
18
|
+
import { esEsfuerzo } from "./esfuerzo.js";
|
|
18
19
|
export const MOTORES = ["modelo", "claude-code", "codex", "opencode"];
|
|
19
20
|
/**
|
|
20
21
|
* Las reglas del dominio, iguales para todos y NO editables desde el fichero.
|
|
@@ -62,19 +63,37 @@ export const REGLAS_XONE = [
|
|
|
62
63
|
* «Error loading initial config»), no rompe solo la función donde está. Así que un descuido
|
|
63
64
|
* que en un navegador sería un aviso, aquí es una app que no abre.
|
|
64
65
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* motor es cambiar un error por otro.
|
|
66
|
+
* Tres se midieron el 18-09-2026 sobre un proyecto real: una llamada sin `;` (Rhino no
|
|
67
|
+
* aplica ASI donde un navegador sí), una coma sobrante en un objeto, y **una `var` declarada
|
|
68
|
+
* dos veces en la misma función** — esta última la introdujo el propio agente «arreglando» la
|
|
69
|
+
* primera, y por eso está escrita: arreglar sin conocer el motor es cambiar un error por otro.
|
|
70
70
|
*
|
|
71
|
-
* **
|
|
72
|
-
*
|
|
73
|
-
*
|
|
71
|
+
* **El resto es la matriz del 19-09-2026, y está medida EJECUTANDO en el aparato** —emulador
|
|
72
|
+
* con `com.xone.android.framework` 5.0.2.2dev, por el canal hotswap (`runScript`)—, no
|
|
73
|
+
* deducida de la versión. Decía «(ES5)» a secas, y eso era impreciso en las DOS direcciones:
|
|
74
|
+
* de menos, porque acepta media docena de cosas de ES2015; y de más, porque lo que no acepta
|
|
75
|
+
* lo rechaza **al PARSEAR**, o sea que el script entero queda mudo — ni error, ni traza.
|
|
76
|
+
*
|
|
77
|
+
* **Va la lista ENTERA y no solo las frecuentes**, aunque alargue unas líneas que el propio
|
|
78
|
+
* comentario de arriba quiere cortas. El motivo es que una lista incompleta es peor que
|
|
79
|
+
* ninguna: el modelo se fía de ella, y lo omitido no falla ruidosamente sino en silencio y
|
|
80
|
+
* para toda la app. Y la mitad de «SÍ puedes» no es relleno — sin ella, un modelo al que se
|
|
81
|
+
* le dice «ES5» evita `let` y las arrow functions, que funcionan, y peor: «arregla» código
|
|
82
|
+
* bueno, que es exactamente el fallo que ya introdujo una vez.
|
|
83
|
+
*
|
|
84
|
+
* **Lo que sigue sin decir, a propósito**: que no se pueda usar `let`. Estaba escrito así
|
|
85
|
+
* desde el 18-09 por prudencia —el proyecto donde se midió lo usa y arranca— y la medida del
|
|
86
|
+
* 19 lo confirma: `let`, `const`, arrow functions, destructuring y `for...of` los acepta.
|
|
74
87
|
*/
|
|
75
|
-
"- El motor JS en Android es Rhino
|
|
88
|
+
"- El motor JS en Android es Rhino 1.7.13: un error de sintaxis en un fichero incluido para",
|
|
76
89
|
" la app ENTERA al arrancar. Termina cada sentencia con `;` (no se aplica ASI), sin comas",
|
|
77
90
|
" sobrantes, y no declares dos veces la misma `var` en una función.",
|
|
91
|
+
"- SÍ acepta: let, const, arrow functions, destructuring, for...of, { m(){} }.",
|
|
92
|
+
"- NO acepta, y el script queda MUDO (falla al parsear, sin dar error): template literals",
|
|
93
|
+
" `${}`, class, spread y rest (...), parámetros por defecto (a=1), function*, async/await,",
|
|
94
|
+
" **, ?., ??, propiedad abreviada ({ a }) y clave computada ({ [k]: v }).",
|
|
95
|
+
"- Existen pero valen undefined: Map, Set, WeakMap, Array.prototype.includes. Sí están",
|
|
96
|
+
" Object.assign/keys, Array.isArray/find/forEach, String.includes/startsWith/trim, JSON.",
|
|
78
97
|
].join("\n");
|
|
79
98
|
/**
|
|
80
99
|
* El prompt completo de un subagente: sus reglas, su descripción y sus instrucciones.
|
|
@@ -227,6 +246,82 @@ export function nombreSugerido(nombre) {
|
|
|
227
246
|
.replace(/^-+|-+$/g, "");
|
|
228
247
|
return slug !== "" && motivoDeNombreInaceptable(slug) === undefined ? slug : undefined;
|
|
229
248
|
}
|
|
249
|
+
/**
|
|
250
|
+
* Un agente ya cargado: el fichero, más de QUIÉN es.
|
|
251
|
+
*
|
|
252
|
+
* `semilla` no sale del `.md` —no hay forma de escribirlo ahí, y está bien: sería un campo
|
|
253
|
+
* que el usuario podría mentir— sino de comparar lo que hay en disco con lo que sembramos
|
|
254
|
+
* nosotros (`agentesEnDisco.ts#marcarSemilla`). Por eso vive en un tipo aparte de `Agente`,
|
|
255
|
+
* que es lo que `leerAgente` devuelve de un fichero.
|
|
256
|
+
*
|
|
257
|
+
* TRES estados y no un booleano, porque la pantalla hace tres cosas distintas con ellos y
|
|
258
|
+
* un `{deSerie, modificado}` admitiría la combinación imposible «no es de serie pero está
|
|
259
|
+
* modificado»:
|
|
260
|
+
*
|
|
261
|
+
* | valor | qué es | qué se puede hacer con él |
|
|
262
|
+
* |---|---|---|
|
|
263
|
+
* | ausente | un subagente del usuario | borrarlo |
|
|
264
|
+
* | `"intacta"` | de serie, tal como lo entregamos | nada: no hay nada que restaurar |
|
|
265
|
+
* | `"modificada"` | de serie, con el prompt afinado | restaurar el de serie (pisa lo suyo) |
|
|
266
|
+
*
|
|
267
|
+
* Y un de serie NO se borra: ver `restaurarAgente`. Borrarlo no devolvía el de serie —la
|
|
268
|
+
* marca recuerda que se entregó y no se resiembra—, así que era perderlo para siempre.
|
|
269
|
+
*/
|
|
270
|
+
/**
|
|
271
|
+
* La ficha con la que el ORQUESTADOR conoce a un especialista: su descripción más lo que
|
|
272
|
+
* SABE HACER y lo que DEVUELVE.
|
|
273
|
+
*
|
|
274
|
+
* **Por qué hace falta, medido en la librería.** deepagents arma la lista de especialistas con
|
|
275
|
+
* `- ${name}: ${description}` y nada más
|
|
276
|
+
* (`getTaskToolDescription`/`subagentDescriptions.push`), bajo un encabezado que promete
|
|
277
|
+
* «Available agent types **and the tools they have access to**» — una promesa que su cuerpo no
|
|
278
|
+
* cumple. O sea que lo único que el orquestador sabe de su equipo es una frase en prosa: no
|
|
279
|
+
* sabe quién escribe, quién alcanza la máquina ni qué devuelve cada uno. Y con eso no se puede
|
|
280
|
+
* ENGRANAR nada: componer un pipeline exige conocer las capacidades y qué entra y sale de cada
|
|
281
|
+
* pieza.
|
|
282
|
+
*
|
|
283
|
+
* **Se DERIVA de lo que el `.md` ya declara**, nunca se escribe a mano. Así un subagente del
|
|
284
|
+
* usuario trae su ficha solo y no hay una segunda lista que se quede vieja — que es el fallo
|
|
285
|
+
* que este repo ya tiene anotado para la regla de los diagramas, la única escrita a pelo.
|
|
286
|
+
*
|
|
287
|
+
* Y la frase del usuario va DELANTE y entera: es lo que él quiso decir, y esto solo la
|
|
288
|
+
* completa con lo que el código sabe y él no tiene por qué repetir.
|
|
289
|
+
*/
|
|
290
|
+
export function fichaDeAgente(agente) {
|
|
291
|
+
const capacidades = [];
|
|
292
|
+
/**
|
|
293
|
+
* **Quien EJECUTA es su propio caso, y confundirlo con «escribe» miente dos veces.**
|
|
294
|
+
* `montajeDeFicheros` le da `TOOLS_CON_EJECUCION`, que no lleva `write_file` ni `edit_file`
|
|
295
|
+
* —así que con las tools de fichero no escribe nada—, y **no recibe `permissions`** (la
|
|
296
|
+
* librería lanza al combinarlos con un backend ejecutable), así que lo que su shell toque no
|
|
297
|
+
* pasa por ninguna aprobación. Derivarlo de `soloLectura: false` decía lo contrario en las
|
|
298
|
+
* dos mitades, y la segunda en la dirección peligrosa: prometía una barrera que no existe.
|
|
299
|
+
*/
|
|
300
|
+
if (agente.ejecucion === true) {
|
|
301
|
+
capacidades.push("ejecuta comandos en esta máquina, así que alcanza el disco sin pasar por la aprobación", "no edita ficheros con las tools de fichero: no las tiene");
|
|
302
|
+
}
|
|
303
|
+
else if (agente.soloLectura) {
|
|
304
|
+
capacidades.push("solo LEE el proyecto");
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
capacidades.push("ESCRIBE ficheros del proyecto, y cada escritura pasa por aprobación");
|
|
308
|
+
}
|
|
309
|
+
if (agente.motor !== "modelo")
|
|
310
|
+
capacidades.push(`corre en ${agente.motor}`);
|
|
311
|
+
/**
|
|
312
|
+
* Qué DEVUELVE, que es la mitad que falta para encadenar. Derivado de lo mismo: quien solo
|
|
313
|
+
* lee devuelve hechos; quien escribe devuelve cambios; quien ejecuta devuelve lo que MIDIÓ,
|
|
314
|
+
* que no es lo mismo que lo que cree.
|
|
315
|
+
*/
|
|
316
|
+
const devuelve = agente.ejecucion === true
|
|
317
|
+
? "devuelve lo que midió en la máquina"
|
|
318
|
+
: agente.soloLectura
|
|
319
|
+
? "devuelve hechos y análisis, sin tocar nada"
|
|
320
|
+
: "devuelve los ficheros que cambió";
|
|
321
|
+
const frase = agente.descripcion.trim();
|
|
322
|
+
const conPunto = /[.!?]$/.test(frase) ? frase : `${frase}.`;
|
|
323
|
+
return `${conPunto} [${capacidades.join("; ")}; ${devuelve}]`;
|
|
324
|
+
}
|
|
230
325
|
function esMotor(v) {
|
|
231
326
|
return MOTORES.includes(v);
|
|
232
327
|
}
|
|
@@ -329,6 +424,12 @@ export function leerAgente(nombre, contenido, origen) {
|
|
|
329
424
|
// cuando es cierto: un `ejecucion: false` en todos los `.md` sería ruido que además
|
|
330
425
|
// invita a cambiarlo a mano sin saber lo que abre.
|
|
331
426
|
...((campos["ejecucion"] ?? "").trim() === "true" ? { ejecucion: true } : {}),
|
|
427
|
+
// Contra el vocabulario y no contra `string`: lo que se escriba aquí acaba siendo un
|
|
428
|
+
// parámetro de una API, así que un `esfuerzo: mucho` se DESCARTA en silencio —el
|
|
429
|
+
// subagente corre sin él— en vez de viajar y dar un 400 a mitad de turno.
|
|
430
|
+
...(esEsfuerzo((campos["esfuerzo"] ?? "").trim())
|
|
431
|
+
? { esfuerzo: (campos["esfuerzo"] ?? "").trim() }
|
|
432
|
+
: {}),
|
|
332
433
|
skills: leerLista(campos["skills"]),
|
|
333
434
|
instrucciones,
|
|
334
435
|
origen,
|
|
@@ -356,6 +457,7 @@ export function escribirAgente(agente) {
|
|
|
356
457
|
`descripcion: ${agente.descripcion}`,
|
|
357
458
|
`motor: ${agente.motor}`,
|
|
358
459
|
...(agente.modelo === undefined ? [] : [`modelo: ${agente.modelo}`]),
|
|
460
|
+
...(agente.esfuerzo === undefined ? [] : [`esfuerzo: ${agente.esfuerzo}`]),
|
|
359
461
|
`soloLectura: ${agente.soloLectura}`,
|
|
360
462
|
...(agente.ejecucion === true ? ["ejecucion: true"] : []),
|
|
361
463
|
`skills: [${agente.skills.join(", ")}]`,
|
package/dist/core/agentes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentes.js","sourceRoot":"","sources":["../../src/core/agentes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"agentes.js","sourceRoot":"","sources":["../../src/core/agentes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAiB,MAAM,eAAe,CAAC;AAK1D,MAAM,CAAC,MAAM,OAAO,GAAqB,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,CAAU,CAAC;AAkFjG;;;;;;GAMG;AACH;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,2CAA2C;IAC3C,8FAA8F;IAC9F,iFAAiF;IACjF,6FAA6F;IAC7F,0CAA0C;IAC1C,gEAAgE;CACjE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,iCAAiC;IACjC,qFAAqF;IACrF,wFAAwF;IACxF,uFAAuF;IACvF,iEAAiE;IACjE;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,4FAA4F;IAC5F,2FAA2F;IAC3F,qEAAqE;IACrE,+EAA+E;IAC/E,0FAA0F;IAC1F,4FAA4F;IAC5F,2EAA2E;IAC3E,uFAAuF;IACvF,0FAA0F;CAC3F,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,MAAuB;IACpE,OAAO;QACL,WAAW;QACX,EAAE;QACF,iBAAiB;QACjB,EAAE;QACF,MAAM,CAAC,WAAW;QAClB,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC;QAChF,EAAE;QACF,qFAAqF;QACrF,wFAAwF;QACxF,+EAA+E;QAC/E;;;;;;;;;;;;;WAaG;QACH,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;YACpD,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,kDAAkD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpF,kFAAkF;QAClF,uFAAuF;QACvF,yEAAyE;QACzE,MAAM,CAAC,WAAW;YAChB,CAAC,CAAC,oBAAoB;YACtB,CAAC,CAAC,+GAA+G;QACnH;;;;;;;;;;;;WAYG;QACH;;;;;;;;;;;;WAYG;QACH,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,QAAQ;YAC3B,CAAC,CAAC;gBACE,iFAAiF;oBAC/E,yFAAyF;oBACzF,qFAAqF;oBACrF,0FAA0F;oBAC1F,2FAA2F;oBAC3F,yFAAyF;oBACzF,0FAA0F;oBAC1F,8CAA8C;aACjD;YACH,CAAC,CAAC;gBACE,mFAAmF;oBACjF,sFAAsF;oBACtF,4EAA4E;aAC/E,CAAC;KACP;SACE,IAAI,CAAC,IAAI,CAAC;QACX,uFAAuF;QACvF,wFAAwF;QACxF,2DAA2D;SAC1D,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AAChC,CAAC;AAQD,6FAA6F;AAC7F,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,WAAgC;IAC7E,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACtD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;KACzD,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,gBAAgB,GAAG,0BAA0B,CAAC;AAEpD;;;;;;;;GAQG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAc;IACtD,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,sBAAsB,CAAC;IACxD,IAAI,MAAM,KAAK,MAAM,CAAC,IAAI,EAAE;QAAE,OAAO,yCAAyC,CAAC;IAC/E,IAAI,MAAM,KAAK,MAAM,CAAC,WAAW,EAAE;QAAE,OAAO,mDAAmD,CAAC;IAChG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACnC,OAAO,+GAA+G,CAAC;IACzH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,IAAI,GAAG,MAAM;SAChB,SAAS,CAAC,KAAK,CAAC;SAChB,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC3B,OAAO,IAAI,KAAK,EAAE,IAAI,yBAAyB,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACzF,CAAC;AASD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC;;;;;;;OAOG;IACH,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;QAC9B,WAAW,CAAC,IAAI,CACd,wFAAwF,EACxF,0DAA0D,CAC3D,CAAC;IACJ,CAAC;SAAM,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QAC9B,WAAW,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAC3C,CAAC;SAAM,CAAC;QACN,WAAW,CAAC,IAAI,CAAC,qEAAqE,CAAC,CAAC;IAC1F,CAAC;IACD,IAAI,MAAM,CAAC,KAAK,KAAK,QAAQ;QAAE,WAAW,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IAE5E;;;;OAIG;IACH,MAAM,QAAQ,GACZ,MAAM,CAAC,SAAS,KAAK,IAAI;QACvB,CAAC,CAAC,qCAAqC;QACvC,CAAC,CAAC,MAAM,CAAC,WAAW;YAClB,CAAC,CAAC,4CAA4C;YAC9C,CAAC,CAAC,kCAAkC,CAAC;IAE3C,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC;IAC5D,OAAO,GAAG,QAAQ,KAAK,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,QAAQ,GAAG,CAAC;AAChE,CAAC;AAYD,SAAS,OAAO,CAAC,CAAS;IACxB,OAAQ,OAA6B,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,eAAe,CAAC,KAAa;IACpC,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,KAAK,IAAI,CAAC;YAAE,SAAS;QACzB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3C,IAAI,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1C,IACE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;YACnE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,EACnE,CAAC;YACD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QACD,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;IACxB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,4FAA4F;AAC5F,SAAS,SAAS,CAAC,KAAyB;IAC1C,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAClE,OAAO,MAAM;SACV,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;SAChD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CACxB,MAAc,EACd,SAAiB,EACjB,MAAwB;IAExB,MAAM,CAAC,GAAG,6CAA6C,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACxE,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,+DAA+D,EAAE,CAAC;IAElG,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC;IACtC,MAAM,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAEjC,MAAM,WAAW,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACzD,kFAAkF;IAClF,yFAAyF;IACzF,wEAAwE;IACxE,IAAI,WAAW,KAAK,EAAE;QAAE,OAAO,EAAE,KAAK,EAAE,wEAAwE,EAAE,CAAC;IAEnH,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;IACxD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,WAAW,UAAU,6BAA6B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;IAC3F,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAE/C,qEAAqE;IACrE,MAAM,WAAW,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,MAAM,CAAC;IACpE;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,OAAO;QACL,MAAM,EAAE;YACN,MAAM;YACN,WAAW;YACX,KAAK,EAAE,UAAU;YACjB,GAAG,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;YACpC,oFAAoF;YACpF,kFAAkF;YAClF,uEAAuE;YACvE,WAAW;YACX,sFAAsF;YACtF,oFAAoF;YACpF,mDAAmD;YACnD,GAAG,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7E,qFAAqF;YACrF,iFAAiF;YACjF,0EAA0E;YAC1E,GAAG,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC/C,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAc,EAAE;gBAC7D,CAAC,CAAC,EAAE,CAAC;YACP,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACnC,aAAa;YACb,MAAM;SACP;KACF,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAmB,MAAoB,EAAE,QAAsB;IAC5F,MAAM,SAAS,GAAG,IAAI,GAAG,EAAa,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACnD,KAAK,MAAM,CAAC,IAAI,QAAQ;QAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAClF,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,MAAM,GAAG;QACb,gBAAgB,MAAM,CAAC,WAAW,EAAE;QACpC,UAAU,MAAM,CAAC,KAAK,EAAE;QACxB,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACpE,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC1E,gBAAgB,MAAM,CAAC,WAAW,EAAE;QACpC,GAAG,CAAC,MAAM,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,YAAY,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;KACxC,CAAC;IACF,OAAO,QAAQ,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,MAAM,CAAC,aAAa,EAAE,CAAC;AACnE,CAAC"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cuánto tiene que PENSAR un modelo antes de contestar, y qué modelos admiten que se les
|
|
3
|
+
* pida.
|
|
4
|
+
*
|
|
5
|
+
* Es la tercera tabla de esta familia, detrás de `contextos.ts#TOPES` y de
|
|
6
|
+
* `modelos.ts#pideThinkingAdaptativo`, y existe por el mismo motivo que ellas: el
|
|
7
|
+
* parámetro no significa lo mismo en todos, lo que no se reconoce hay que OMITIRLO, y
|
|
8
|
+
* pedirlo a ciegas no da una respuesta peor — da un 400.
|
|
9
|
+
*
|
|
10
|
+
* **La unidad es el MODELO, nunca el proveedor**, y eso está medido: dentro de NVIDIA,
|
|
11
|
+
* `nvidia/nemotron-3-super-120b-a12b` acepta siete niveles y `openai/gpt-oss-20b` acepta
|
|
12
|
+
* tres, contra el mismo host y con la misma clave. Una tabla por proveedor habría sido
|
|
13
|
+
* falsa el primer día.
|
|
14
|
+
*
|
|
15
|
+
* **Y los niveles son una LISTA por modelo, no tres fijos.** La razón es DeepSeek: publica
|
|
16
|
+
* —y su API acepta— siete valores, pero los COLAPSA (`minimal`→low, `medium`→high,
|
|
17
|
+
* `xhigh`→high, `ultra`→max), así que ahí solo hay tres niveles de verdad. Ofrecer
|
|
18
|
+
* low/medium/high en un desplegable contra ese modelo sería dar dos opciones que hacen
|
|
19
|
+
* exactamente lo mismo sin decirlo, que es la misma clase de mentira que un contador a
|
|
20
|
+
* cero que nadie ha medido.
|
|
21
|
+
*
|
|
22
|
+
* **Lo desconocido devuelve `undefined`**: ni se ofrece control ni se manda parámetro. Es
|
|
23
|
+
* el mismo lado conservador de `pideThinkingAdaptativo`, y aquí es literal — un nivel
|
|
24
|
+
* mandado a quien no lo admite se contesta con un error duro, comprobado en los tres
|
|
25
|
+
* proveedores que se pudieron medir.
|
|
26
|
+
*/
|
|
27
|
+
export const ESFUERZOS = ["low", "medium", "high", "xhigh", "max"];
|
|
28
|
+
export function esEsfuerzo(valor) {
|
|
29
|
+
return ESFUERZOS.includes(valor);
|
|
30
|
+
}
|
|
31
|
+
/** Los tres de siempre, que es lo que admite la mayoría. */
|
|
32
|
+
const TRES = ["low", "medium", "high"];
|
|
33
|
+
/** Los cinco de Anthropic desde Opus 4.7. */
|
|
34
|
+
const CINCO = ["low", "medium", "high", "xhigh", "max"];
|
|
35
|
+
/**
|
|
36
|
+
* Qué acepta cada familia, emparejado por PREFIJO del id, y el primero que casa gana —
|
|
37
|
+
* igual que en `contextos.ts`, así que lo específico va antes que lo general.
|
|
38
|
+
*
|
|
39
|
+
* De dónde sale cada fila, porque en este repo la procedencia es un dato:
|
|
40
|
+
*
|
|
41
|
+
* - **anthropic**: LEÍDO de la documentación de la casa (no hubo clave con la que medir).
|
|
42
|
+
* `output_config.effort` es GA y su omisión ya es `high`. Los cinco niveles existen desde
|
|
43
|
+
* Opus 4.7; Opus 4.6 y Sonnet 4.6 no tienen `xhigh`; Opus 4.5 solo tiene tres; y **Haiku
|
|
44
|
+
* 4.5, Sonnet 4.5 y todo lo anterior dan ERROR**, así que no tienen fila. Esa frontera es
|
|
45
|
+
* la hermana de la de `pideThinkingAdaptativo`: ahí la pregunta era qué acepta `thinking`
|
|
46
|
+
* y aquí qué acepta `effort`, y las dos parten la misma generación.
|
|
47
|
+
* - **gemini**: MEDIDO contra la API real. `thinkingLevel` solo existe de la generación 3 en
|
|
48
|
+
* adelante: `gemini-2.5-flash` contesta «Thinking level is not supported for this model» y
|
|
49
|
+
* `gemma-4-31b-it` lo mismo. Los tres alias `*-latest` van ENUMERADOS porque apuntan a 3.x
|
|
50
|
+
* y el prefijo `gemini-3` no los casaría — se comprobó uno a uno que los tres lo aceptan.
|
|
51
|
+
* Y el catálogo vivo NO sirve para decidir esto: `GET /v1beta/models/<id>` devuelve
|
|
52
|
+
* `"thinking": true` también para `gemini-2.5-flash`, que es justo el que falla; ese campo
|
|
53
|
+
* dice «sabe pensar», no «acepta niveles».
|
|
54
|
+
* - **deepseek**: MEDIDO que el enum se valida (un valor inventado da 422) y LEÍDO de su
|
|
55
|
+
* documentación que lo colapsa. Por eso la fila tiene TRES valores que no son los tres de
|
|
56
|
+
* siempre: `low`, `high` y `max` son los únicos distintos. Lo que NO se pudo medir es que
|
|
57
|
+
* los niveles cambien el resultado — con un problema fácil y dos pasadas la señal quedó
|
|
58
|
+
* por debajo de la varianza —, y eso es «no medido», que no es lo mismo que «no hace nada».
|
|
59
|
+
* - **nvidia**: MEDIDO con el truco del valor inválido, que devuelve el enum en el propio
|
|
60
|
+
* error. Son dos filas y no una porque los dos modelos probados no coinciden.
|
|
61
|
+
*
|
|
62
|
+
* **Lo que NO tiene fila, y por qué**: `openai`, `groq` y `xai` no se pudieron medir —no
|
|
63
|
+
* había credencial— y sus reglas por modelo no se parecen entre sí, así que se quedan
|
|
64
|
+
* fuera hasta que alguien las mida. Un proveedor PERSONALIZADO tampoco puede tenerla: su
|
|
65
|
+
* modelo lo elige quien dio de alta el endpoint. En los tres casos el resultado es el
|
|
66
|
+
* mismo y es el correcto: sin control y sin parámetro.
|
|
67
|
+
*/
|
|
68
|
+
const TABLA = {
|
|
69
|
+
anthropic: [
|
|
70
|
+
["claude-fable", CINCO],
|
|
71
|
+
["claude-mythos", CINCO],
|
|
72
|
+
["claude-opus-5", CINCO],
|
|
73
|
+
["claude-sonnet-5", CINCO],
|
|
74
|
+
["claude-opus-4-8", CINCO],
|
|
75
|
+
["claude-opus-4-7", CINCO],
|
|
76
|
+
// 4.6 es la generación donde `effort` ya existe pero `xhigh` todavía no.
|
|
77
|
+
["claude-opus-4-6", ["low", "medium", "high", "max"]],
|
|
78
|
+
["claude-sonnet-4-6", ["low", "medium", "high", "max"]],
|
|
79
|
+
["claude-opus-4-5", TRES],
|
|
80
|
+
// Y nada más: Haiku 4.5, Sonnet 4.5 y lo anterior devuelven error si se les pide.
|
|
81
|
+
],
|
|
82
|
+
gemini: [
|
|
83
|
+
["gemini-3", TRES],
|
|
84
|
+
["gemini-flash-latest", TRES],
|
|
85
|
+
["gemini-flash-lite-latest", TRES],
|
|
86
|
+
["gemini-pro-latest", TRES],
|
|
87
|
+
],
|
|
88
|
+
deepseek: [["deepseek", ["low", "high", "max"]]],
|
|
89
|
+
nvidia: [
|
|
90
|
+
["openai/gpt-oss", TRES],
|
|
91
|
+
["nvidia/nemotron-3", CINCO],
|
|
92
|
+
],
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Los niveles de esfuerzo que admite un modelo, o `undefined` si no admite ninguno —que es
|
|
96
|
+
* también lo que se devuelve cuando no se sabe, porque no saberlo y no poder son lo mismo
|
|
97
|
+
* para quien tiene que decidir si manda el parámetro.
|
|
98
|
+
*
|
|
99
|
+
* **Ollama va por las capacidades vivas y no por la tabla**, y esa asimetría es el hallazgo
|
|
100
|
+
* que la justifica: sus modelos los elige el usuario y no hay prefijo que los describa, pero
|
|
101
|
+
* el servidor contesta por cada uno. Sin capacidades —porque aún no se preguntó— no se
|
|
102
|
+
* afirma nada, que es distinto de afirmar que no puede.
|
|
103
|
+
*/
|
|
104
|
+
export function nivelesDeEsfuerzo(proveedor, modelo, vivas) {
|
|
105
|
+
if (proveedor === "ollama" || proveedor === "ollama-cloud") {
|
|
106
|
+
return vivas?.piensa === true ? NIVELES_DE_OLLAMA : undefined;
|
|
107
|
+
}
|
|
108
|
+
return TABLA[proveedor]?.find(([prefijo]) => modelo.startsWith(prefijo))?.[1];
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Lo que el servidor de Ollama valida, y está medido en su propio mensaje de error: un
|
|
112
|
+
* `think: "banana"` contesta `must be "high", "medium", "low", "max", true, or false`.
|
|
113
|
+
*
|
|
114
|
+
* O sea que Ollama SÍ tiene niveles; que el tipo de `@langchain/ollama` los declare como un
|
|
115
|
+
* `boolean` es una limitación del cliente y no del servidor, y el cliente pasa el valor tal
|
|
116
|
+
* cual al request.
|
|
117
|
+
*
|
|
118
|
+
* **Y aquí hay un límite declarado que no se puede cerrar desde esta tabla**: que el
|
|
119
|
+
* servidor acepte el nivel no significa que el modelo lo honre. Medido: en `granite4.2:3b`
|
|
120
|
+
* solo `low` cambia algo y `medium`/`high`/`max` son idénticos entre sí; en
|
|
121
|
+
* `glm-5.3-flash:cloud` —que es el modelo POR OMISIÓN de este repo— `high` se comporta como
|
|
122
|
+
* apagado y solo `medium` piensa. No es monótono y no lo podemos arreglar: lo pone el
|
|
123
|
+
* template de cada modelo. Quien pinte esto tiene que DECIRLO.
|
|
124
|
+
*/
|
|
125
|
+
export const NIVELES_DE_OLLAMA = ["low", "medium", "high", "max"];
|
|
126
|
+
/**
|
|
127
|
+
* El nivel que se va a usar de verdad, dado lo que el usuario eligió y lo que el modelo
|
|
128
|
+
* admite.
|
|
129
|
+
*
|
|
130
|
+
* Existe porque elegir y aplicar están separados en el tiempo: el esfuerzo se fija una vez
|
|
131
|
+
* y el modelo se cambia después, así que un `xhigh` elegido con Opus 5 sigue puesto cuando
|
|
132
|
+
* alguien se pasa a Gemini, que no lo tiene. Ahí NO se manda el parámetro y NO se sustituye
|
|
133
|
+
* por el más parecido: bajar `xhigh` a `high` por nuestra cuenta sería decidir en nombre de
|
|
134
|
+
* alguien, y en este harness eso se paga en tokens que no pidió.
|
|
135
|
+
*/
|
|
136
|
+
export function esfuerzoAplicable(elegido, proveedor, modelo, vivas) {
|
|
137
|
+
if (elegido === undefined)
|
|
138
|
+
return undefined;
|
|
139
|
+
return nivelesDeEsfuerzo(proveedor, modelo, vivas)?.includes(elegido) === true ? elegido : undefined;
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=esfuerzo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"esfuerzo.js","sourceRoot":"","sources":["../../src/core/esfuerzo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAaH,MAAM,CAAC,MAAM,SAAS,GAAwB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAU,CAAC;AAEjG,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAQ,SAA+B,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED,4DAA4D;AAC5D,MAAM,IAAI,GAAwB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC5D,6CAA6C;AAC7C,MAAM,KAAK,GAAwB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,KAAK,GAAuF;IAChG,SAAS,EAAE;QACT,CAAC,cAAc,EAAE,KAAK,CAAC;QACvB,CAAC,eAAe,EAAE,KAAK,CAAC;QACxB,CAAC,eAAe,EAAE,KAAK,CAAC;QACxB,CAAC,iBAAiB,EAAE,KAAK,CAAC;QAC1B,CAAC,iBAAiB,EAAE,KAAK,CAAC;QAC1B,CAAC,iBAAiB,EAAE,KAAK,CAAC;QAC1B,yEAAyE;QACzE,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QACrD,CAAC,mBAAmB,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC,iBAAiB,EAAE,IAAI,CAAC;QACzB,kFAAkF;KACnF;IACD,MAAM,EAAE;QACN,CAAC,UAAU,EAAE,IAAI,CAAC;QAClB,CAAC,qBAAqB,EAAE,IAAI,CAAC;QAC7B,CAAC,0BAA0B,EAAE,IAAI,CAAC;QAClC,CAAC,mBAAmB,EAAE,IAAI,CAAC;KAC5B;IACD,QAAQ,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IAChD,MAAM,EAAE;QACN,CAAC,gBAAgB,EAAE,IAAI,CAAC;QACxB,CAAC,mBAAmB,EAAE,KAAK,CAAC;KAC7B;CACF,CAAC;AAoBF;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC/B,SAAoB,EACpB,MAAc,EACd,KAAwB;IAExB,IAAI,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,cAAc,EAAE,CAAC;QAC3D,OAAO,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC;IAChE,CAAC;IACD,OAAO,KAAK,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAwB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAEvF;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAA6B,EAC7B,SAAoB,EACpB,MAAc,EACd,KAAwB;IAExB,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC5C,OAAO,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AACvG,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Qué estilo le toca de verdad a un control, y de dónde sale.
|
|
3
|
+
*
|
|
4
|
+
* ## La medida que lo motiva
|
|
5
|
+
*
|
|
6
|
+
* Diez pasadas reales del mismo encargo visual («el título sale cortado»), 19-09-2026. En OCHO
|
|
7
|
+
* de ellas `xone_navegacion` es la PRIMERA tool del turno —el modelo sí empieza por donde se le
|
|
8
|
+
* dice— y luego deja de servirle: la usa una o dos veces y el resto del turno son **20-46
|
|
9
|
+
* lecturas y 30-42 `grep`**, de los cuales ~22 de cada 30 son **la misma clase con variantes**
|
|
10
|
+
* (`xnTituloHeaderC`, `.xnTituloHeader`, `xnHeader`, `xnLightTitle`, `font42`…). Más cinco
|
|
11
|
+
* ficheros CSS, varios `.xne` AJENOS buscando ejemplos, y nueve documentos de skill.
|
|
12
|
+
*
|
|
13
|
+
* El índice actual contesta sobre el MODELO `.xne` —colecciones, campos, referencias— y el
|
|
14
|
+
* trabajo de un arreglo visual vive en la capa de ESTILOS, que no tenía índice. Esto lo cierra.
|
|
15
|
+
*
|
|
16
|
+
* ## Lo que NO se rederiva
|
|
17
|
+
*
|
|
18
|
+
* La cascada de XOne la resuelve `xone-linter`, no este módulo: `Stylesheet.lookup` está
|
|
19
|
+
* anotado como fiel a `FindStylesheetByClassName` (`CXoneApplication.mm:6146-6166`), con la
|
|
20
|
+
* sutileza de que **un fichero posterior que redirige por `extends` gana al atributo DIRECTO de
|
|
21
|
+
* uno anterior** —resolución intercalada por fichero, no dos pasadas globales—, y
|
|
22
|
+
* `selectorsFor` implementa el orden de prioridad (`prop.clase:tipo` → `prop.clase` →
|
|
23
|
+
* `.clase` → `prop:tipo` → `prop`) con sus dos banderas. Reescribir eso aquí sería un segundo
|
|
24
|
+
* sitio donde decidir lo mismo, que es justo el argumento por el que `xone_navegacion` usa la
|
|
25
|
+
* librería en vez de reimplementar `CrossReferenceRule`.
|
|
26
|
+
*
|
|
27
|
+
* Aquí vive lo que se ENSEÑA y con qué topes. Puro: sin disco y sin librería.
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Topes de lo que se enseña.
|
|
31
|
+
*
|
|
32
|
+
* Existen porque esto viaja al contexto del modelo entero y una hoja grande tiene decenas de
|
|
33
|
+
* atributos por selector. **Lo que no cabe se CUENTA**, como en todas partes aquí: una lista
|
|
34
|
+
* recortada en silencio se lee como la lista entera, y sobre eso se concluye de más.
|
|
35
|
+
*/
|
|
36
|
+
export const LIMITES_ESTILOS = { atributos: 30, selectores: 12, declaraciones: 12 };
|
|
37
|
+
/** La marca de que un valor no viene de la hoja sino del XML del propio control. */
|
|
38
|
+
export const DEL_XML = "el XML del prop (gana a la hoja)";
|
|
39
|
+
function recortar(lista, tope, pinta) {
|
|
40
|
+
const cabe = lista.slice(0, tope).map(pinta);
|
|
41
|
+
const fuera = lista.length - cabe.length;
|
|
42
|
+
return fuera > 0 ? [...cabe, ` … y ${fuera} más`] : cabe;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* La respuesta, en el formato que el turno necesitaba.
|
|
46
|
+
*
|
|
47
|
+
* Las cuatro preguntas que los greps estaban haciendo a mano —qué se aplica, de qué selector,
|
|
48
|
+
* qué selectores compiten y en qué fichero están— en una sola llamada. El orden no es
|
|
49
|
+
* cosmético: primero lo que se aplica, que es lo que se preguntó; los selectores y los ficheros
|
|
50
|
+
* van después, porque son el CAMINO y solo hacen falta si hay que cambiar algo.
|
|
51
|
+
*/
|
|
52
|
+
export function pintarEstiloDeProp(e) {
|
|
53
|
+
const cabecera = `${e.coll}.${e.prop}` +
|
|
54
|
+
(e.tipo === undefined ? "" : ` type=${e.tipo}`) +
|
|
55
|
+
(e.clase === undefined ? "" : ` class="${e.clase}"`);
|
|
56
|
+
const nada = e.deLaHoja.length === 0 && e.delXml.length === 0;
|
|
57
|
+
return [
|
|
58
|
+
cabecera,
|
|
59
|
+
"",
|
|
60
|
+
"LO QUE ACABA APLICÁNDOSE",
|
|
61
|
+
...(nada
|
|
62
|
+
? [" (nada: ni la hoja ni el XML le ponen ningún atributo)"]
|
|
63
|
+
: recortar([...e.delXml, ...e.deLaHoja], LIMITES_ESTILOS.atributos, (a) => ` ${a.atributo.padEnd(18)} ${a.valor.padEnd(14)} ← ${a.de}`)),
|
|
64
|
+
"",
|
|
65
|
+
"SELECTORES QUE APLICAN, de más a menos prioridad",
|
|
66
|
+
...(e.selectores.length === 0
|
|
67
|
+
? [" (ninguno: el prop no tiene clase y la hoja no declara reglas de tipo)"]
|
|
68
|
+
: recortar(e.selectores, LIMITES_ESTILOS.selectores, (s) => ` ${s}`)),
|
|
69
|
+
...(e.declaradoEn.length === 0
|
|
70
|
+
? []
|
|
71
|
+
: [
|
|
72
|
+
"",
|
|
73
|
+
"DÓNDE SE DECLARAN",
|
|
74
|
+
...recortar(e.declaradoEn, LIMITES_ESTILOS.declaraciones, (d) => ` ${d.selector.padEnd(28)} ${d.fichero}`),
|
|
75
|
+
]),
|
|
76
|
+
].join("\n");
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=estilos.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"estilos.js","sourceRoot":"","sources":["../../src/core/estilos.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AA0BH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAW,CAAC;AAE7F,oFAAoF;AACpF,MAAM,CAAC,MAAM,OAAO,GAAG,kCAAkC,CAAC;AAE1D,SAAS,QAAQ,CAAI,KAAmB,EAAE,IAAY,EAAE,KAAuB;IAC7E,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACzC,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAe;IAChD,MAAM,QAAQ,GACZ,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE;QACrB,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;QAChD,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;IAExD,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;IAC9D,OAAO;QACL,QAAQ;QACR,EAAE;QACF,0BAA0B;QAC1B,GAAG,CAAC,IAAI;YACN,CAAC,CAAC,CAAC,yDAAyD,CAAC;YAC7D,CAAC,CAAC,QAAQ,CACN,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,EAC5B,eAAe,CAAC,SAAS,EACzB,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CACpE,CAAC;QACN,EAAE;QACF,kDAAkD;QAClD,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;YAC3B,CAAC,CAAC,CAAC,yEAAyE,CAAC;YAC7E,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,EAAE,eAAe,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACxE,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;YAC5B,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC;gBACE,EAAE;gBACF,mBAAmB;gBACnB,GAAG,QAAQ,CACT,CAAC,CAAC,WAAW,EACb,eAAe,CAAC,aAAa,EAC7B,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CACjD;aACF,CAAC;KACP,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exportar un documento del proyecto a PDF: las reglas PURAS.
|
|
3
|
+
*
|
|
4
|
+
* **Por qué el harness y no el agente.** Producir un PDF es lo que las skills `pdf`/`docx`
|
|
5
|
+
* de Claude Code hacen ejecutando scripts, y a un motor externo no se le concede shell
|
|
6
|
+
* —`Bash` está denegada, y abrirla dejaría a ese hijo reescribir el proyecto sin diff ni
|
|
7
|
+
* aprobación—. Medido además sobre la máquina real: esas skills asumen el sandbox donde sus
|
|
8
|
+
* dependencias vienen puestas (`reportlab`, `pypdf`, `docx` de npm, `pandoc`), y ahí no
|
|
9
|
+
* estaba ninguna, así que conceder la shell no habría dado el PDF. Lo que sí hay en cualquier
|
|
10
|
+
* máquina que use la consola web es un navegador, y un navegador imprime — así que la
|
|
11
|
+
* conversión la hace el harness con un comando FIJO, y la shell del hijo sigue cerrada.
|
|
12
|
+
*
|
|
13
|
+
* Aquí solo está lo que se puede decidir sin tocar disco. Lanzar el navegador es de
|
|
14
|
+
* `agent/exportarPdf.ts`.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Lo que se sabe convertir. Lista CERRADA: lo que no está no se intenta.
|
|
18
|
+
*
|
|
19
|
+
* `.md` porque es lo que el agente escribe cuando se le pide documentación, y `.html` porque
|
|
20
|
+
* es lo que produce la skill de artefactos. Un `.xne` o un `.js` no entran: imprimir código
|
|
21
|
+
* fuente a PDF no es una necesidad que nadie haya tenido, y ofrecerlo sería un botón que
|
|
22
|
+
* nadie pulsa sobre cada fichero del árbol.
|
|
23
|
+
*/
|
|
24
|
+
export const EXTENSIONES_EXPORTABLES = [".md", ".html", ".htm"];
|
|
25
|
+
/** ¿Hace falta convertir Markdown antes, o el fichero ya es HTML? */
|
|
26
|
+
export function esMarkdown(ruta) {
|
|
27
|
+
return ruta.toLowerCase().endsWith(".md");
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Por qué no se puede exportar esa ruta, o AUSENTE si vale.
|
|
31
|
+
*
|
|
32
|
+
* No comprueba que exista ni que se pueda leer: de eso ya hay una barrera
|
|
33
|
+
* (`motivoDeRutaInaceptable` y el `realpath` de `leerFicheroDeProyecto`), y duplicarla aquí
|
|
34
|
+
* sería un segundo sitio donde decidir sobre una ruta.
|
|
35
|
+
*/
|
|
36
|
+
export function motivoDeExportacionInaceptable(ruta) {
|
|
37
|
+
const bajo = ruta.toLowerCase();
|
|
38
|
+
if (!EXTENSIONES_EXPORTABLES.some((e) => bajo.endsWith(e))) {
|
|
39
|
+
return `solo se exportan ${EXTENSIONES_EXPORTABLES.join(", ")} — «${ruta}» no es ninguno`;
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Dónde queda el PDF: al lado del original y con su mismo nombre.
|
|
45
|
+
*
|
|
46
|
+
* **El destino lo DERIVA el código, nunca se recibe.** Es lo que impide que quien pide la
|
|
47
|
+
* exportación elija dónde escribir: con un destino por parámetro, esta función sería una
|
|
48
|
+
* forma de escribir cualquier fichero del proyecto sin pasar por ninguna aprobación.
|
|
49
|
+
*/
|
|
50
|
+
export function rutaDePdf(ruta) {
|
|
51
|
+
const punto = ruta.lastIndexOf(".");
|
|
52
|
+
return `${punto <= 0 ? ruta : ruta.slice(0, punto)}.pdf`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* El documento listo para imprimir: el cuerpo HTML dentro de una hoja de estilos de PÁGINA.
|
|
56
|
+
*
|
|
57
|
+
* Los estilos no son decoración, son lo que hace legible un PDF de doce páginas y se
|
|
58
|
+
* comprobaron imprimiendo uno de verdad: `@page` con márgenes, `break-inside: avoid` en
|
|
59
|
+
* tablas y bloques de código —sin eso una tabla se parte por la mitad entre dos hojas— y
|
|
60
|
+
* `break-after: avoid` en los encabezados, para que un título no se quede solo al pie.
|
|
61
|
+
*
|
|
62
|
+
* El título va ESCAPADO: sale de un nombre de fichero del proyecto, y un `<` ahí dentro
|
|
63
|
+
* rompería la cabecera del documento.
|
|
64
|
+
*/
|
|
65
|
+
export function documentoImprimible(cuerpo, titulo) {
|
|
66
|
+
return `<!doctype html>
|
|
67
|
+
<html lang="es">
|
|
68
|
+
<head>
|
|
69
|
+
<meta charset="utf-8">
|
|
70
|
+
${POLITICA_SIN_SCRIPTS}
|
|
71
|
+
<title>${escaparHtml(titulo)}</title>
|
|
72
|
+
<style>
|
|
73
|
+
@page { size: A4; margin: 18mm 16mm 20mm; }
|
|
74
|
+
body { font: 10.5pt/1.55 -apple-system, "Segoe UI", Helvetica, Arial, sans-serif; color: #1a1a1a; }
|
|
75
|
+
h1 { font-size: 22pt; border-bottom: 2px solid #0b5fff; padding-bottom: .3em; }
|
|
76
|
+
h2 { font-size: 15pt; margin-top: 1.6em; border-bottom: 1px solid #d7dbe0; padding-bottom: .2em; }
|
|
77
|
+
h3 { font-size: 12pt; margin-top: 1.2em; }
|
|
78
|
+
h1, h2, h3, h4 { break-after: avoid; break-inside: avoid; }
|
|
79
|
+
table { border-collapse: collapse; width: 100%; margin: .8em 0; font-size: 9pt; break-inside: avoid; }
|
|
80
|
+
th, td { border: 1px solid #c9ced6; padding: 5px 7px; text-align: left; vertical-align: top; }
|
|
81
|
+
th { background: #eef2f7; }
|
|
82
|
+
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .88em;
|
|
83
|
+
background: #f3f5f8; padding: 1px 4px; border-radius: 3px; }
|
|
84
|
+
pre { background: #f7f8fa; border: 1px solid #e2e6ec; border-radius: 5px; padding: 10px;
|
|
85
|
+
overflow-x: auto; break-inside: avoid; }
|
|
86
|
+
pre code { background: none; padding: 0; }
|
|
87
|
+
blockquote { border-left: 3px solid #0b5fff; margin: 1em 0; padding: .2em 1em; background: #f5f8ff; }
|
|
88
|
+
img { max-width: 100%; }
|
|
89
|
+
hr { border: 0; border-top: 1px solid #d7dbe0; margin: 1.6em 0; }
|
|
90
|
+
a { color: #0b5fff; text-decoration: none; }
|
|
91
|
+
</style>
|
|
92
|
+
</head>
|
|
93
|
+
<body>${cuerpo}</body>
|
|
94
|
+
</html>
|
|
95
|
+
`;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* La política que impide que imprimir ejecute nada.
|
|
99
|
+
*
|
|
100
|
+
* **Y es una CSP y no un flag del navegador, porque los flags NO lo hacen.** Medido contra
|
|
101
|
+
* el Chrome instalado con un documento que reescribe su propio texto desde un `<script>`:
|
|
102
|
+
* con `--disable-javascript`, con `--blink-settings=scriptEnabled=false` y sin nada, el
|
|
103
|
+
* script se ejecutó en los tres casos; y encima el segundo hace que `--print-to-pdf` no
|
|
104
|
+
* escriba el fichero, en silencio y con código de salida 0. Con esta CSP el script no corre.
|
|
105
|
+
*
|
|
106
|
+
* `default-src 'none'` corta además las peticiones de RED: un documento del proyecto podría
|
|
107
|
+
* llevar un `<img src="https://…">` que se lleve fuera el hecho de que se está imprimiendo.
|
|
108
|
+
* Lo que se deja es lo que un PDF necesita: imágenes locales o embebidas, estilos en línea
|
|
109
|
+
* —los nuestros— y tipografías locales.
|
|
110
|
+
*/
|
|
111
|
+
export const POLITICA_SIN_SCRIPTS = `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; ` +
|
|
112
|
+
`img-src 'self' data: file:; style-src 'unsafe-inline' 'self'; font-src 'self' data:">`;
|
|
113
|
+
/**
|
|
114
|
+
* El mismo blindaje para un documento que YA es HTML y no pasa por nuestra plantilla.
|
|
115
|
+
*
|
|
116
|
+
* Se inserta lo antes posible: dentro de su `<head>` si lo tiene, dentro de su `<html>` si
|
|
117
|
+
* no, y al principio si no hay ninguno de los dos. **Inyectarla siempre TENSA y nunca
|
|
118
|
+
* afloja**: cuando un documento trae su propia CSP, el navegador exige que TODAS las
|
|
119
|
+
* políticas permitan cada carga, así que añadir la nuestra no puede ampliar lo que el
|
|
120
|
+
* documento ya se permitía.
|
|
121
|
+
*
|
|
122
|
+
* **Límite declarado**: esto es una transformación de TEXTO, no un parser. Un documento
|
|
123
|
+
* con un `<head` dentro de un comentario o de una cadena puede recibir la meta en un sitio
|
|
124
|
+
* raro; el peor caso es que no aplique, que es exactamente donde estábamos antes.
|
|
125
|
+
*/
|
|
126
|
+
export function conPoliticaSinScripts(html) {
|
|
127
|
+
const tras = (patron) => {
|
|
128
|
+
const m = patron.exec(html);
|
|
129
|
+
return m === null ? undefined : `${html.slice(0, m.index + m[0].length)}${POLITICA_SIN_SCRIPTS}${html.slice(m.index + m[0].length)}`;
|
|
130
|
+
};
|
|
131
|
+
return tras(/<head\b[^>]*>/i) ?? tras(/<html\b[^>]*>/i) ?? `${POLITICA_SIN_SCRIPTS}${html}`;
|
|
132
|
+
}
|
|
133
|
+
function escaparHtml(texto) {
|
|
134
|
+
return texto
|
|
135
|
+
.replace(/&/g, "&")
|
|
136
|
+
.replace(/</g, "<")
|
|
137
|
+
.replace(/>/g, ">")
|
|
138
|
+
.replace(/"/g, """);
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=exportacion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exportacion.js","sourceRoot":"","sources":["../../src/core/exportacion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAU,CAAC;AAEzE,qEAAqE;AACrE,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,8BAA8B,CAAC,IAAY;IACzD,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAChC,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,OAAO,oBAAoB,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,iBAAiB,CAAC;IAC5F,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACpC,OAAO,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAc,EAAE,MAAc;IAChE,OAAO;;;;EAIP,oBAAoB;SACb,WAAW,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;QAsBpB,MAAM;;CAEb,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAC/B,0EAA0E;IAC1E,uFAAuF,CAAC;AAE1F;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,MAAM,IAAI,GAAG,CAAC,MAAc,EAAsB,EAAE;QAClD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,oBAAoB,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACvI,CAAC,CAAC;IACF,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,GAAG,oBAAoB,GAAG,IAAI,EAAE,CAAC;AAC9F,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC"}
|