xonecode 0.5.1 → 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-BB3SamhR.css → index-Boak51UP.css} +1 -1
- package/apps/web/dist/assets/index-Cg28x6nG.js +477 -0
- package/apps/web/dist/assets/{php-D_2--9WK.js → php-Cu6F_QCJ.js} +1 -1
- package/apps/web/dist/assets/{ruby-DSHSDbk1.js → ruby-BiqQPoC6.js} +1 -1
- package/apps/web/dist/index.html +2 -2
- package/dist/agent/{cloudstudioClient.js → cloudstudio/cloudstudioClient.js} +10 -0
- package/dist/agent/cloudstudio/cloudstudioClient.js.map +1 -0
- package/dist/agent/{cloudstudioMcp.js → cloudstudio/cloudstudioMcp.js} +5 -5
- package/dist/agent/cloudstudio/cloudstudioMcp.js.map +1 -0
- package/dist/agent/{descarga.js → cloudstudio/descarga.js} +17 -7
- package/dist/agent/cloudstudio/descarga.js.map +1 -0
- package/dist/agent/cloudstudio/manifiesto.js.map +1 -0
- package/dist/agent/cloudstudio/ramaActiva.js +11 -0
- package/dist/agent/cloudstudio/ramaActiva.js.map +1 -0
- package/dist/agent/{subida.js → cloudstudio/subida.js} +16 -7
- package/dist/agent/cloudstudio/subida.js.map +1 -0
- package/dist/agent/{zip.js → cloudstudio/zip.js} +1 -1
- package/dist/agent/cloudstudio/zip.js.map +1 -0
- package/dist/agent/{authEnDisco.js → config/authEnDisco.js} +3 -3
- package/dist/agent/config/authEnDisco.js.map +1 -0
- package/dist/agent/{catalogoModelos.js → config/catalogoModelos.js} +47 -1
- package/dist/agent/config/catalogoModelos.js.map +1 -0
- package/dist/agent/{configEnDisco.js → config/configEnDisco.js} +6 -6
- package/dist/agent/config/configEnDisco.js.map +1 -0
- package/dist/agent/{crearProyecto.js → config/crearProyecto.js} +2 -2
- package/dist/agent/config/crearProyecto.js.map +1 -0
- package/dist/agent/config/entorno.js.map +1 -0
- package/dist/agent/config/gemini.js.map +1 -0
- package/dist/agent/config/modelos.js +235 -0
- package/dist/agent/config/modelos.js.map +1 -0
- package/dist/agent/{modelosDeMotor.js → config/modelosDeMotor.js} +1 -1
- package/dist/agent/config/modelosDeMotor.js.map +1 -0
- package/dist/agent/config/mudanzaEnDisco.js +121 -0
- package/dist/agent/config/mudanzaEnDisco.js.map +1 -0
- package/dist/agent/{persona.js → config/persona.js} +1 -1
- package/dist/agent/config/persona.js.map +1 -0
- package/dist/agent/config/selectorEnMaquina.js +45 -0
- package/dist/agent/config/selectorEnMaquina.js.map +1 -0
- package/dist/agent/{settingsEnDisco.js → config/settingsEnDisco.js} +37 -2
- package/dist/agent/config/settingsEnDisco.js.map +1 -0
- package/dist/agent/{versionEnDisco.js → config/versionEnDisco.js} +8 -4
- package/dist/agent/config/versionEnDisco.js.map +1 -0
- package/dist/agent/dispositivos/arranqueDeEmulador.js +146 -0
- package/dist/agent/dispositivos/arranqueDeEmulador.js.map +1 -0
- package/dist/agent/{dispositivosEnMaquina.js → dispositivos/dispositivosEnMaquina.js} +93 -6
- package/dist/agent/dispositivos/dispositivosEnMaquina.js.map +1 -0
- package/dist/agent/dispositivos/hotswap.js.map +1 -0
- package/dist/agent/dispositivos/instalacionEnMaquina.js.map +1 -0
- package/dist/agent/dispositivos/juezVisual.js +152 -0
- package/dist/agent/dispositivos/juezVisual.js.map +1 -0
- package/dist/agent/{lanzamientoEnMaquina.js → dispositivos/lanzamientoEnMaquina.js} +1 -1
- package/dist/agent/dispositivos/lanzamientoEnMaquina.js.map +1 -0
- package/dist/agent/{paqueteDelProyecto.js → dispositivos/paqueteDelProyecto.js} +5 -5
- package/dist/agent/dispositivos/paqueteDelProyecto.js.map +1 -0
- package/dist/agent/dispositivos/procesosEnMaquina.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/{arbolDeProyecto.js → grafo/arbolDeProyecto.js} +2 -2
- package/dist/agent/grafo/arbolDeProyecto.js.map +1 -0
- package/dist/agent/{artefactosEnDisco.js → grafo/artefactosEnDisco.js} +2 -2
- package/dist/agent/grafo/artefactosEnDisco.js.map +1 -0
- package/dist/agent/{busquedaRegex.js → grafo/busquedaRegex.js} +41 -1
- package/dist/agent/grafo/busquedaRegex.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/excluirTools.js +82 -0
- package/dist/agent/grafo/excluirTools.js.map +1 -0
- package/dist/agent/{memoriaDeProyecto.js → grafo/memoriaDeProyecto.js} +1 -1
- package/dist/agent/grafo/memoriaDeProyecto.js.map +1 -0
- package/dist/agent/grafo/navegacionXone.js +231 -0
- package/dist/agent/grafo/navegacionXone.js.map +1 -0
- package/dist/agent/{perfiles.js → grafo/perfiles.js} +96 -10
- package/dist/agent/grafo/perfiles.js.map +1 -0
- package/dist/agent/{proyecto.js → grafo/proyecto.js} +274 -24
- package/dist/agent/grafo/proyecto.js.map +1 -0
- package/dist/agent/grafo/skills.js +425 -0
- package/dist/agent/grafo/skills.js.map +1 -0
- package/dist/agent/grafo/xoneAgent.js +566 -0
- package/dist/agent/grafo/xoneAgent.js.map +1 -0
- 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 +36 -0
- package/dist/agent/navegacion/indiceEnDisco.js.map +1 -0
- package/dist/agent/navegacion/modeloDeProyecto.js +228 -0
- package/dist/agent/navegacion/modeloDeProyecto.js.map +1 -0
- package/dist/agent/raizDelPaquete.js +56 -0
- package/dist/agent/raizDelPaquete.js.map +1 -0
- package/dist/agent/{checkpointer.js → sesiones/checkpointer.js} +1 -1
- package/dist/agent/sesiones/checkpointer.js.map +1 -0
- package/dist/agent/sesiones/git.js.map +1 -0
- package/dist/agent/{gitSync.js → sesiones/gitSync.js} +3 -3
- package/dist/agent/sesiones/gitSync.js.map +1 -0
- package/dist/agent/{sesionGit.js → sesiones/sesionGit.js} +2 -2
- package/dist/agent/sesiones/sesionGit.js.map +1 -0
- package/dist/agent/subagentes/agentesEnDisco.js +818 -0
- package/dist/agent/subagentes/agentesEnDisco.js.map +1 -0
- package/dist/agent/subagentes/consumoExterno.js.map +1 -0
- package/dist/agent/subagentes/escrituraDeCodex.js.map +1 -0
- package/dist/agent/{escrituraDeOpencode.js → subagentes/escrituraDeOpencode.js} +1 -1
- package/dist/agent/subagentes/escrituraDeOpencode.js.map +1 -0
- package/dist/agent/{escrituraExterna.js → subagentes/escrituraExterna.js} +59 -6
- package/dist/agent/subagentes/escrituraExterna.js.map +1 -0
- package/dist/agent/subagentes/pluginDeSkills.js +99 -0
- package/dist/agent/subagentes/pluginDeSkills.js.map +1 -0
- package/dist/agent/subagentes/subagenteCodex.js.map +1 -0
- package/dist/agent/{subagenteExterno.js → subagentes/subagenteExterno.js} +48 -0
- package/dist/agent/subagentes/subagenteExterno.js.map +1 -0
- package/dist/agent/{subagenteOpencode.js → subagentes/subagenteOpencode.js} +53 -1
- package/dist/agent/subagentes/subagenteOpencode.js.map +1 -0
- package/dist/agent/{aumentador.js → tareas/aumentador.js} +2 -2
- package/dist/agent/tareas/aumentador.js.map +1 -0
- package/dist/agent/{juezDeTarea.js → tareas/juezDeTarea.js} +6 -6
- package/dist/agent/tareas/juezDeTarea.js.map +1 -0
- package/dist/agent/{tareasEnDisco.js → tareas/tareasEnDisco.js} +53 -4
- package/dist/agent/tareas/tareasEnDisco.js.map +1 -0
- package/dist/agent/{diagnosticoDeTools.js → turno/diagnosticoDeTools.js} +5 -1
- package/dist/agent/turno/diagnosticoDeTools.js.map +1 -0
- package/dist/agent/{guionizado.js → turno/guionizado.js} +1 -1
- package/dist/agent/turno/guionizado.js.map +1 -0
- package/dist/agent/turno/informeDeTraza.js +245 -0
- package/dist/agent/turno/informeDeTraza.js.map +1 -0
- package/dist/agent/turno/inspectorDePrompt.js +205 -0
- package/dist/agent/turno/inspectorDePrompt.js.map +1 -0
- package/dist/agent/{instantanea.js → turno/instantanea.js} +7 -2
- package/dist/agent/turno/instantanea.js.map +1 -0
- package/dist/agent/{interrupts.js → turno/interrupts.js} +2 -2
- package/dist/agent/turno/interrupts.js.map +1 -0
- package/dist/agent/turno/mensajes.js.map +1 -0
- package/dist/agent/turno/normalizar.js.map +1 -0
- package/dist/agent/{puente.js → turno/puente.js} +71 -4
- package/dist/agent/turno/puente.js.map +1 -0
- package/dist/agent/turno/resumenDeContexto.js +260 -0
- package/dist/agent/turno/resumenDeContexto.js.map +1 -0
- package/dist/agent/{resumenDeTool.js → turno/resumenDeTool.js} +33 -0
- package/dist/agent/turno/resumenDeTool.js.map +1 -0
- package/dist/agent/turno/rubrica.js +91 -0
- package/dist/agent/turno/rubrica.js.map +1 -0
- package/dist/agent/turno/textoDeTool.js.map +1 -0
- package/dist/agent/{turnoReal.js → turno/turnoReal.js} +210 -25
- package/dist/agent/turno/turnoReal.js.map +1 -0
- package/dist/agent/turno/verificador.js.map +1 -0
- package/dist/cli/config.js +1 -1
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/consola.js +72 -9
- package/dist/cli/consola.js.map +1 -1
- package/dist/cli/describe.js +2 -2
- package/dist/cli/describe.js.map +1 -1
- package/dist/cli/doctor.js +1 -1
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/fuentesDeDisco.js +29 -0
- package/dist/cli/fuentesDeDisco.js.map +1 -0
- package/dist/cli/main.js +87 -31
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/run.js +40 -10
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/traza.js +48 -0
- package/dist/cli/traza.js.map +1 -0
- package/dist/cli/tui/correrTui.js +4 -4
- package/dist/cli/tui/correrTui.js.map +1 -1
- package/dist/cli/verify.js +1 -1
- package/dist/cli/verify.js.map +1 -1
- package/dist/core/actos.js +1 -1
- package/dist/core/adjuntos.js +2 -2
- package/dist/core/agentes.js +247 -7
- package/dist/core/agentes.js.map +1 -1
- package/dist/core/artefactos.js +4 -4
- package/dist/core/config.js +1 -1
- package/dist/core/contextos.js +12 -1
- package/dist/core/contextos.js.map +1 -1
- package/dist/core/descargas.js +1 -1
- package/dist/core/dispositivos.js +53 -3
- package/dist/core/dispositivos.js.map +1 -1
- package/dist/core/esfuerzo.js +141 -0
- package/dist/core/esfuerzo.js.map +1 -0
- package/dist/core/esqueleto.js +1 -1
- 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 +48 -3
- 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/navegacion.js +134 -0
- package/dist/core/navegacion.js.map +1 -0
- package/dist/core/notify.js +5 -0
- package/dist/core/notify.js.map +1 -1
- package/dist/core/planDeSubida.js +1 -1
- 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 +56 -7
- package/dist/core/settings.js.map +1 -1
- package/dist/core/shellDeAgente.js +144 -0
- package/dist/core/shellDeAgente.js.map +1 -0
- package/dist/core/skills.js +158 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/topeAgotado.js +69 -0
- package/dist/core/topeAgotado.js.map +1 -0
- package/dist/core/zipDeSkill.js +107 -0
- package/dist/core/zipDeSkill.js.map +1 -0
- package/dist/web/servidor/arranque.js +853 -54
- package/dist/web/servidor/arranque.js.map +1 -1
- package/dist/web/servidor/corredorDeTareas.js +3 -3
- package/dist/web/servidor/corredorDeTareas.js.map +1 -1
- package/dist/web/servidor/sesiones.js +34 -6
- package/dist/web/servidor/sesiones.js.map +1 -1
- package/dist/web/servidor/transporte.js +1 -1
- package/dist/web/servidor/transporte.js.map +1 -1
- package/dist/web/servidor/vestibulo.js +62 -13
- package/dist/web/servidor/vestibulo.js.map +1 -1
- package/package.json +7 -4
- package/skills/archify/SKILL.md +25 -2
- package/skills/artifacts-builder/SKILL.md +23 -0
- package/skills/xone-hotswap/SKILL.md +96 -0
- package/skills/xone-hotswap/scripts/xone-arrancar-android +202 -0
- package/skills/xone-hotswap/scripts/xone-arrancar-ios +85 -0
- package/skills/xone-hotswap/scripts/xone-captura-android +93 -0
- package/skills/xone-hotswap/scripts/xone-desplegar-android +439 -0
- package/skills/xone-hotswap/scripts/xone-hotswap +201 -0
- package/skills/xone-hotswap/scripts/xone-log-android +102 -0
- package/skills/xone-hotswap/scripts/xone-reiniciar-android +132 -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-CFYAoHdw.js +0 -477
- package/dist/agent/agentesEnDisco.js +0 -539
- package/dist/agent/agentesEnDisco.js.map +0 -1
- package/dist/agent/arbolDeProyecto.js.map +0 -1
- package/dist/agent/artefactosEnDisco.js.map +0 -1
- package/dist/agent/aumentador.js.map +0 -1
- package/dist/agent/authEnDisco.js.map +0 -1
- package/dist/agent/busquedaRegex.js.map +0 -1
- package/dist/agent/catalogoModelos.js.map +0 -1
- package/dist/agent/checkpointer.js.map +0 -1
- package/dist/agent/cloudstudioClient.js.map +0 -1
- package/dist/agent/cloudstudioMcp.js.map +0 -1
- package/dist/agent/configEnDisco.js.map +0 -1
- package/dist/agent/consumoExterno.js.map +0 -1
- package/dist/agent/crearProyecto.js.map +0 -1
- package/dist/agent/descarga.js.map +0 -1
- package/dist/agent/diagnosticoDeTools.js.map +0 -1
- package/dist/agent/dispositivosEnMaquina.js.map +0 -1
- package/dist/agent/entorno.js.map +0 -1
- package/dist/agent/escrituraDeCodex.js.map +0 -1
- package/dist/agent/escrituraDeOpencode.js.map +0 -1
- package/dist/agent/escrituraExterna.js.map +0 -1
- package/dist/agent/gemini.js.map +0 -1
- package/dist/agent/git.js.map +0 -1
- package/dist/agent/gitSync.js.map +0 -1
- package/dist/agent/guionizado.js.map +0 -1
- package/dist/agent/hotswap.js.map +0 -1
- package/dist/agent/instalacionEnMaquina.js.map +0 -1
- package/dist/agent/instantanea.js.map +0 -1
- package/dist/agent/interrupts.js.map +0 -1
- package/dist/agent/juezDeTarea.js.map +0 -1
- package/dist/agent/lanzamientoEnMaquina.js.map +0 -1
- package/dist/agent/manifiesto.js.map +0 -1
- package/dist/agent/memoriaDeProyecto.js.map +0 -1
- package/dist/agent/mensajes.js.map +0 -1
- package/dist/agent/modelos.js +0 -130
- package/dist/agent/modelos.js.map +0 -1
- package/dist/agent/modelosDeMotor.js.map +0 -1
- package/dist/agent/normalizar.js.map +0 -1
- package/dist/agent/paqueteDelProyecto.js.map +0 -1
- package/dist/agent/perfiles.js.map +0 -1
- package/dist/agent/persona.js.map +0 -1
- package/dist/agent/procesosEnMaquina.js.map +0 -1
- package/dist/agent/proyecto.js.map +0 -1
- package/dist/agent/puente.js.map +0 -1
- package/dist/agent/resumenDeContexto.js +0 -30
- package/dist/agent/resumenDeContexto.js.map +0 -1
- package/dist/agent/resumenDeTool.js.map +0 -1
- package/dist/agent/sesionGit.js.map +0 -1
- package/dist/agent/settingsEnDisco.js.map +0 -1
- package/dist/agent/skills.js +0 -65
- package/dist/agent/skills.js.map +0 -1
- package/dist/agent/subagenteCodex.js.map +0 -1
- package/dist/agent/subagenteExterno.js.map +0 -1
- package/dist/agent/subagenteOpencode.js.map +0 -1
- package/dist/agent/subida.js.map +0 -1
- package/dist/agent/tareasEnDisco.js.map +0 -1
- package/dist/agent/textoDeTool.js.map +0 -1
- package/dist/agent/turnoReal.js.map +0 -1
- package/dist/agent/verificador.js.map +0 -1
- package/dist/agent/versionEnDisco.js.map +0 -1
- package/dist/agent/xoneAgent.js +0 -347
- package/dist/agent/xoneAgent.js.map +0 -1
- package/dist/agent/zip.js.map +0 -1
- /package/dist/agent/{manifiesto.js → cloudstudio/manifiesto.js} +0 -0
- /package/dist/agent/{entorno.js → config/entorno.js} +0 -0
- /package/dist/agent/{gemini.js → config/gemini.js} +0 -0
- /package/dist/agent/{hotswap.js → dispositivos/hotswap.js} +0 -0
- /package/dist/agent/{instalacionEnMaquina.js → dispositivos/instalacionEnMaquina.js} +0 -0
- /package/dist/agent/{procesosEnMaquina.js → dispositivos/procesosEnMaquina.js} +0 -0
- /package/dist/agent/{git.js → sesiones/git.js} +0 -0
- /package/dist/agent/{consumoExterno.js → subagentes/consumoExterno.js} +0 -0
- /package/dist/agent/{escrituraDeCodex.js → subagentes/escrituraDeCodex.js} +0 -0
- /package/dist/agent/{subagenteCodex.js → subagentes/subagenteCodex.js} +0 -0
- /package/dist/agent/{mensajes.js → turno/mensajes.js} +0 -0
- /package/dist/agent/{normalizar.js → turno/normalizar.js} +0 -0
- /package/dist/agent/{textoDeTool.js → turno/textoDeTool.js} +0 -0
- /package/dist/agent/{verificador.js → turno/verificador.js} +0 -0
|
@@ -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"}
|
package/dist/core/esqueleto.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* inventada no da error — da un bug mudo, y un esqueleto recién creado que no
|
|
8
8
|
* arranca sería la peor primera impresión posible.
|
|
9
9
|
*
|
|
10
|
-
* La escritura en disco vive en `agent/crearProyecto.ts`: aquí solo se DECIDE
|
|
10
|
+
* La escritura en disco vive en `agent/config/crearProyecto.ts`: aquí solo se DECIDE
|
|
11
11
|
* qué ficheros hay y qué llevan dentro, que es exactamente lo que se puede
|
|
12
12
|
* probar sin conexión, sin simulador y sin clave (el invariante de `npm test`).
|
|
13
13
|
*/
|
|
@@ -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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* La carta de presentación del proyecto, pegada al turno.
|
|
3
|
+
*
|
|
4
|
+
* **Existe por una medida, y la medida es de hoy** (19-09-2026): en seis turnos reales sobre un
|
|
5
|
+
* proyecto de verdad, cada especialista repetía las MISMAS búsquedas —`grep` ×42 en un solo
|
|
6
|
+
* turno, con `xnTituloHeaderC` ×7 y `xnHeader` ×3— y el orquestador se llevaba entre el 38 % y
|
|
7
|
+
* el 50 % del gasto averiguando. No por delegar mal: porque **nadie hace el descubrimiento una
|
|
8
|
+
* sola vez**. El prompt del orquestador ya PIDE lo contrario («No pidas al siguiente
|
|
9
|
+
* especialista redescubrir esos hechos») y no basta — una instrucción no es una garantía.
|
|
10
|
+
*
|
|
11
|
+
* Así que los hechos baratos se ponen delante en vez de pedirse: el inventario cuesta cientos
|
|
12
|
+
* de tokens donde abrir los `.xne` cuesta decenas de miles (`xone_navegacion`).
|
|
13
|
+
*
|
|
14
|
+
* **Es el patrón de `conAdjuntos` y de `inventarioDelProyecto`**: montar no basta, hay que
|
|
15
|
+
* DECIR lo que hay. Aquí ni siquiera hay nada montado — el índice existe detrás de una tool
|
|
16
|
+
* que el agente tiene que acordarse de llamar, y un turno que no la llama trabaja a ciegas.
|
|
17
|
+
*
|
|
18
|
+
* **Y se calcula al MANDAR el turno, no al abrir la sesión.** Eso no es un detalle de
|
|
19
|
+
* cableado: `xone_navegacion` no cachea a propósito porque «un índice viejo que dice que un
|
|
20
|
+
* campo existe cuando el agente acaba de borrarlo es peor que no tener índice». Congelar esta
|
|
21
|
+
* foto en el prompt de sistema reintroduciría justo eso. Rehacerla por turno cuesta decenas de
|
|
22
|
+
* milisegundos y no puede quedarse vieja dentro del turno que la usa.
|
|
23
|
+
*
|
|
24
|
+
* Puro y en `core/`: quién lee el disco es de `agent/`.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Del índice a los hechos. PURA: el índice entra ya construido.
|
|
28
|
+
*
|
|
29
|
+
* Separada de quien lo construye por el motivo de siempre —poder probar la traducción sin
|
|
30
|
+
* disco— y porque el índice es la AUTORIDAD: aquí solo se elige qué poquito de él se adelanta.
|
|
31
|
+
* Lo que se elige son las cuatro cosas que un turno cualquiera pregunta primero, y ninguna
|
|
32
|
+
* lleva rutas: solo NOMBRES, así que esto no puede filtrar una ruta de la máquina por el cable.
|
|
33
|
+
*/
|
|
34
|
+
export function hechosDeIndice(indice) {
|
|
35
|
+
const app = indice.app();
|
|
36
|
+
return {
|
|
37
|
+
entrada: app.entrada,
|
|
38
|
+
login: app.login,
|
|
39
|
+
estilos: app.estilos,
|
|
40
|
+
colecciones: indice.inventario().map((d) => d.nombre),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Cuántos nombres de colección caben antes de contar el resto.
|
|
45
|
+
*
|
|
46
|
+
* Un proyecto real medido tiene 98 colecciones y eso son unos cientos de tokens: barato al
|
|
47
|
+
* lado de los 18.000 que cuesta enterarse leyendo. El tope existe para que un proyecto mucho
|
|
48
|
+
* mayor no se coma la ventana, y **lo que no cabe se CUENTA** en vez de recortarse en
|
|
49
|
+
* silencio: una lista truncada sin decirlo se lee como la lista entera, y entonces el agente
|
|
50
|
+
* concluye que una colección no existe.
|
|
51
|
+
*/
|
|
52
|
+
export const TOPE_DE_COLECCIONES = 150;
|
|
53
|
+
/** ¿Hay algo que contar? Sin esto no se pinta el bloque: un control sin dato detrás. */
|
|
54
|
+
function hayAlgo(h) {
|
|
55
|
+
return (h.colecciones.length > 0 || h.entrada.length > 0 || h.login.length > 0 || h.estilos.length > 0);
|
|
56
|
+
}
|
|
57
|
+
/** Una lista, o la marca de que no consta. Vacío NO es «no hay»: es que no se pudo leer. */
|
|
58
|
+
function lista(valores) {
|
|
59
|
+
return valores.length === 0 ? "no consta" : valores.join(", ");
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* La petición del turno con los hechos del proyecto detrás.
|
|
63
|
+
*
|
|
64
|
+
* Sin hechos —no hay índice, o el proyecto no se pudo leer— devuelve la petición TAL CUAL.
|
|
65
|
+
* Nombrar un inventario que no se tiene sería la mentira con forma de dato de siempre.
|
|
66
|
+
*/
|
|
67
|
+
export function conHechosDelProyecto(peticion, hechos) {
|
|
68
|
+
if (hechos === undefined || !hayAlgo(hechos))
|
|
69
|
+
return peticion;
|
|
70
|
+
const visibles = hechos.colecciones.slice(0, TOPE_DE_COLECCIONES);
|
|
71
|
+
const ocultas = hechos.colecciones.length - visibles.length;
|
|
72
|
+
return [
|
|
73
|
+
peticion,
|
|
74
|
+
"",
|
|
75
|
+
`ESTE PROYECTO, medido ahora mismo (${hechos.colecciones.length} colecciones). No vuelvas a`,
|
|
76
|
+
"averiguar lo que ya está aquí, y pásalo en el `HANDOFF DE ANÁLISIS` cuando delegues:",
|
|
77
|
+
`- Entrada: ${lista(hechos.entrada)}`,
|
|
78
|
+
`- Login: ${lista(hechos.login)}`,
|
|
79
|
+
`- Estilos: ${lista(hechos.estilos)}`,
|
|
80
|
+
`- Colecciones: ${visibles.join(", ")}`,
|
|
81
|
+
...(ocultas > 0 ? [` (y ${ocultas} más que no caben aquí: pídelas con \`xone_navegacion\`)`] : []),
|
|
82
|
+
"Esto es una FOTO del arranque del turno y solo dice QUÉ hay, no cómo es cada cosa. Para los",
|
|
83
|
+
"campos de una colección, dónde se declara algo o quién la referencia, usa `xone_navegacion`:",
|
|
84
|
+
"es la autoridad y está al día, esta lista no lo estará si el turno crea o borra algo.",
|
|
85
|
+
].join("\n");
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=hechosDelProyecto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hechosDelProyecto.js","sourceRoot":"","sources":["../../src/core/hechosDelProyecto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAuBH;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,MAA0B;IACvD,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC;IACzB,OAAO;QACL,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,WAAW,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;KACtD,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEvC,wFAAwF;AACxF,SAAS,OAAO,CAAC,CAAoB;IACnC,OAAO,CACL,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAC/F,CAAC;AACJ,CAAC;AAED,4FAA4F;AAC5F,SAAS,KAAK,CAAC,OAA0B;IACvC,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAgB,EAChB,MAAqC;IAErC,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC9D,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC5D,OAAO;QACL,QAAQ;QACR,EAAE;QACF,sCAAsC,MAAM,CAAC,WAAW,CAAC,MAAM,6BAA6B;QAC5F,sFAAsF;QACtF,cAAc,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;QACrC,YAAY,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACjC,cAAc,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;QACrC,kBAAkB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACvC,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,OAAO,0DAA0D,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACnG,6FAA6F;QAC7F,8FAA8F;QAC9F,uFAAuF;KACxF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* El `code` con el que estos hallazgos entran en el bucle.
|
|
3
|
+
*
|
|
4
|
+
* Uno solo y no uno por mensaje: el `code` de un hallazgo del simulador es un identificador
|
|
5
|
+
* ESTABLE de familia (`REF_JS_COLL_MISSING`) y el texto va en `mensaje`. Aquí la familia es
|
|
6
|
+
* «lo que el aparato dijo al arrancar la app», y el mensaje es el que distingue.
|
|
7
|
+
*/
|
|
8
|
+
export const ETIQUETA_DE_ARRANQUE = "DISPOSITIVO_ARRANQUE";
|
|
9
|
+
/**
|
|
10
|
+
* El prefijo de `adb logcat -v threadtime`: `MM-DD HH:MM:SS.mmm PID TID N `, donde `N` es
|
|
11
|
+
* el NIVEL.
|
|
12
|
+
*
|
|
13
|
+
* La fecha, el pid y el tid se van. El nivel se captura: lo pone quien escribió la línea, así
|
|
14
|
+
* que es la única clasificación de importancia que no es una opinión nuestra.
|
|
15
|
+
*/
|
|
16
|
+
const PREFIJO = /^\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+\s+\d+\s+\d+\s+([VDIWEF])\s+/;
|
|
17
|
+
/**
|
|
18
|
+
* Del nivel de logcat a la severidad del harness.
|
|
19
|
+
*
|
|
20
|
+
* `F` (fatal) y `E` son errores; `W` es aviso; `V`, `D` e `I` son información. **No se
|
|
21
|
+
* DESCARTA nada** —es la condición que gobierna este módulo— pero solo los errores entran en
|
|
22
|
+
* la huella, exactamente como en `turnoReal.ts#conVerificacion`: «un aviso que va y viene no
|
|
23
|
+
* dice nada de si el error se está arreglando».
|
|
24
|
+
*
|
|
25
|
+
* Y eso no es cosmética: MEDIDO contra el aparato, dos arranques seguidos de la misma app dan
|
|
26
|
+
* líneas `I` y `D` distintas —`Choreographer: Skipped 75 frames` contra `Skipped 33`,
|
|
27
|
+
* `Compiler allocated 5250KB`, ciclos del replicador que solo salen a veces—. Con ellas
|
|
28
|
+
* dentro, la huella cambiaba entre dos vueltas idénticas y la guarda de «no progreso» no
|
|
29
|
+
* habría cortado nunca.
|
|
30
|
+
*/
|
|
31
|
+
const SEVERIDAD_DE_NIVEL = {
|
|
32
|
+
F: "error",
|
|
33
|
+
E: "error",
|
|
34
|
+
W: "warning",
|
|
35
|
+
I: "info",
|
|
36
|
+
D: "info",
|
|
37
|
+
V: "info",
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* El cuerpo de una traza de Java, que NO lleva nivel en cada línea.
|
|
41
|
+
*
|
|
42
|
+
* Se arrastra con la severidad de la línea que la encabeza: partir una excepción en un error
|
|
43
|
+
* y cuatro huérfanas dejaría fuera de la huella justo la parte que la identifica.
|
|
44
|
+
*/
|
|
45
|
+
const CUERPO_DE_TRAZA = /^\s*(at [\w$.]+\(|Caused by:|\.{3} \d+ more)/;
|
|
46
|
+
/** La cabecera que pone `xone-log-android`, que no es una línea del log. */
|
|
47
|
+
const CABECERA = /^---/;
|
|
48
|
+
/**
|
|
49
|
+
* Lo que es de ANDROID y no de la app.
|
|
50
|
+
*
|
|
51
|
+
* Es una clave de ORDENACIÓN, nunca un descarte (ver la cabecera del módulo). Son las
|
|
52
|
+
* etiquetas que salieron en la medida real sin tener nada que ver con el proyecto: el
|
|
53
|
+
* cargador de clases, Firebase sin configurar, el renderizador, el gesto de «atrás», los
|
|
54
|
+
* avisos de reflexión del propio Android y el Chromium del WebView.
|
|
55
|
+
*/
|
|
56
|
+
const DE_LA_PLATAFORMA = /\b(ziparchive|FirebaseApp|DynamiteModule|ProviderInstaller|HWUI|WindowOnBackDispatcher|chromium|ActivityThread|ApkAssets|OpenGLRenderer)\b|Accessing hidden (method|field)|Cleared Reference was only reachable/;
|
|
57
|
+
export function hallazgosDeLog(texto) {
|
|
58
|
+
const cuenta = new Map();
|
|
59
|
+
/** El nivel de la última línea con nivel, para las continuaciones de una traza. */
|
|
60
|
+
let nivelArrastrado = "I";
|
|
61
|
+
for (const linea of texto.split(/\r?\n/)) {
|
|
62
|
+
const l = linea.trimEnd();
|
|
63
|
+
if (l.trim() === "" || CABECERA.test(l))
|
|
64
|
+
continue;
|
|
65
|
+
const con = PREFIJO.exec(l);
|
|
66
|
+
if (con !== null)
|
|
67
|
+
nivelArrastrado = con[1];
|
|
68
|
+
else if (!CUERPO_DE_TRAZA.test(l))
|
|
69
|
+
nivelArrastrado = "I";
|
|
70
|
+
const mensaje = l.replace(PREFIJO, "").trim();
|
|
71
|
+
if (mensaje === "")
|
|
72
|
+
continue;
|
|
73
|
+
const previo = cuenta.get(mensaje);
|
|
74
|
+
if (previo === undefined) {
|
|
75
|
+
const deLaApp = !DE_LA_PLATAFORMA.test(mensaje);
|
|
76
|
+
cuenta.set(mensaje, {
|
|
77
|
+
mensaje,
|
|
78
|
+
veces: 1,
|
|
79
|
+
deLaApp,
|
|
80
|
+
/**
|
|
81
|
+
* **Lo de la plataforma nunca es ERROR, aunque el log diga `E`.** Un
|
|
82
|
+
* `E chromium: Seed missing signature` es un error de verdad — de Android, no de la
|
|
83
|
+
* app— y nadie lo arregla desde un `.xne`. Como error dejaría el bucle sin poder
|
|
84
|
+
* cerrar jamás. Se ve, con su severidad rebajada; no bloquea.
|
|
85
|
+
*/
|
|
86
|
+
severidad: deLaApp
|
|
87
|
+
? SEVERIDAD_DE_NIVEL[nivelArrastrado]
|
|
88
|
+
: SEVERIDAD_DE_NIVEL[nivelArrastrado] === "error"
|
|
89
|
+
? "warning"
|
|
90
|
+
: SEVERIDAD_DE_NIVEL[nivelArrastrado],
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
previo.veces += 1;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Los de la app delante; dentro de cada grupo, los que más se repiten primero. El orden es
|
|
98
|
+
// ESTABLE (`Map` conserva la inserción y `sort` de V8 es estable), así que dos lecturas del
|
|
99
|
+
// mismo log dan la misma lista — que es media huella.
|
|
100
|
+
const peso = { error: 0, warning: 1, info: 2 };
|
|
101
|
+
const hallazgos = [...cuenta.values()].sort((a, b) => {
|
|
102
|
+
if (peso[a.severidad] !== peso[b.severidad])
|
|
103
|
+
return peso[a.severidad] - peso[b.severidad];
|
|
104
|
+
if (a.deLaApp !== b.deLaApp)
|
|
105
|
+
return a.deLaApp ? -1 : 1;
|
|
106
|
+
return b.veces - a.veces;
|
|
107
|
+
});
|
|
108
|
+
const plataforma = hallazgos.filter((h) => !h.deLaApp).length;
|
|
109
|
+
return {
|
|
110
|
+
hallazgos,
|
|
111
|
+
plataforma,
|
|
112
|
+
/**
|
|
113
|
+
* **Solo lo de la app es ERROR.** Un `Accessing hidden method` de Android entraría en la
|
|
114
|
+
* huella como error, y entonces el bucle se declararía rojo por algo que nadie puede
|
|
115
|
+
* arreglar desde un `.xne` — y no cerraría nunca. Va como `warning`: se ve, no bloquea.
|
|
116
|
+
*
|
|
117
|
+
* Sin `fichero` ni `linea`, y eso es honestidad: el log no los dice. Un fichero adivinado
|
|
118
|
+
* mandaría al agente a abrir el que no es.
|
|
119
|
+
*/
|
|
120
|
+
aHallazgosDelTurno: () => hallazgos.map((h) => ({
|
|
121
|
+
code: ETIQUETA_DE_ARRANQUE,
|
|
122
|
+
severidad: h.severidad,
|
|
123
|
+
mensaje: h.veces === 1 ? h.mensaje : `${h.mensaje} (×${h.veces})`,
|
|
124
|
+
})),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* La huella de una lectura, con el MISMO formato que la de `conVerificacion`
|
|
129
|
+
* (`code|fichero|linea`), para que las dos sean intercambiables en la misma guarda.
|
|
130
|
+
*
|
|
131
|
+
* Solo los de la app: un aviso de la plataforma que va y viene no dice nada de si el error se
|
|
132
|
+
* está arreglando — la misma razón por la que allí la huella son los ERRORES y no todos los
|
|
133
|
+
* hallazgos. El `mensaje` entra en la huella porque aquí el `code` es uno solo: sin él, dos
|
|
134
|
+
* excepciones distintas darían la misma huella y el bucle se creería atascado.
|
|
135
|
+
*/
|
|
136
|
+
export function huellaDeHallazgos(hallazgos) {
|
|
137
|
+
return hallazgos
|
|
138
|
+
.filter((h) => h.severidad === "error")
|
|
139
|
+
.map((h) => `${ETIQUETA_DE_ARRANQUE}|${h.mensaje}|`)
|
|
140
|
+
.sort()
|
|
141
|
+
.join("\n");
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=logDeDispositivo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logDeDispositivo.js","sourceRoot":"","sources":["../../src/core/logDeDispositivo.ts"],"names":[],"mappings":"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"}
|